[CalendarServer-changes] [6745] CalendarServer/branches/users/wsanchez/m2
source_changes at macosforge.org
source_changes at macosforge.org
Mon Jan 17 15:09:53 PST 2011
Revision: 6745
http://trac.macosforge.org/projects/calendarserver/changeset/6745
Author: wsanchez at apple.com
Date: 2011-01-17 15:09:45 -0800 (Mon, 17 Jan 2011)
Log Message:
-----------
twistedcaldav.memcachelock -> twext.internet.memcachelock
Modified Paths:
--------------
CalendarServer/branches/users/wsanchez/m2/twistedcaldav/directory/opendirectorybacker.py
CalendarServer/branches/users/wsanchez/m2/twistedcaldav/ical.py
CalendarServer/branches/users/wsanchez/m2/twistedcaldav/method/put_common.py
CalendarServer/branches/users/wsanchez/m2/twistedcaldav/scheduling/processing.py
CalendarServer/branches/users/wsanchez/m2/twistedcaldav/storebridge.py
CalendarServer/branches/users/wsanchez/m2/twistedcaldav/test/test_collectioncontents.py
Added Paths:
-----------
CalendarServer/branches/users/wsanchez/m2/twext/internet/memcachelock.py
CalendarServer/branches/users/wsanchez/m2/twext/internet/test/test_memcachelock.py
Removed Paths:
-------------
CalendarServer/branches/users/wsanchez/m2/twistedcaldav/memcachelock.py
CalendarServer/branches/users/wsanchez/m2/twistedcaldav/test/test_memcachelock.py
Copied: CalendarServer/branches/users/wsanchez/m2/twext/internet/memcachelock.py (from rev 6744, CalendarServer/branches/users/wsanchez/m2/twistedcaldav/memcachelock.py)
===================================================================
--- CalendarServer/branches/users/wsanchez/m2/twext/internet/memcachelock.py (rev 0)
+++ CalendarServer/branches/users/wsanchez/m2/twext/internet/memcachelock.py 2011-01-17 23:09:45 UTC (rev 6745)
@@ -0,0 +1,118 @@
+##
+# Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from twistedcaldav.memcacher import Memcacher
+from twisted.internet.defer import inlineCallbacks, Deferred, returnValue,\
+ succeed
+from twisted.internet import reactor
+import time
+
+class MemcacheLock(Memcacher):
+
+ def __init__(self, namespace, locktoken, timeout=5.0, retry_interval=0.1, expire_time=0):
+ """
+
+ @param namespace: a unique namespace for this lock's tokens
+ @type namespace: C{str}
+ @param locktoken: the name of the locktoken
+ @type locktoken: C{str}
+ @param timeout: the maximum time in seconds that the lock should block
+ @type timeout: C{float}
+ @param retry_interval: the interval to retry acquiring the lock
+ @type retry_interval: C{float}
+ @param expiryTime: the time in seconds for the lock to expire. Zero: no expiration.
+ @type expiryTime: C{float}
+ """
+
+ super(MemcacheLock, self).__init__(namespace)
+ self._locktoken = locktoken
+ self._timeout = timeout
+ self._retry_interval = retry_interval
+ self._expire_time = expire_time
+ self._hasLock = False
+
+ def _getMemcacheProtocol(self):
+
+ result = super(MemcacheLock, self)._getMemcacheProtocol()
+
+ if isinstance(result, Memcacher.nullCacher):
+ raise AssertionError("No implementation of shared locking without memcached")
+
+ return result
+
+ @inlineCallbacks
+ def acquire(self):
+
+ assert not self._hasLock, "Lock already acquired."
+
+ timeout_at = time.time() + self._timeout
+ waiting = False
+ while True:
+
+ result = (yield self.add(self._locktoken, "1", self._expire_time))
+ if result:
+ self._hasLock = True
+ if waiting:
+ self.log_debug("Got lock after waiting on %s" % (self._locktoken,))
+ break
+
+ if self._timeout and time.time() < timeout_at:
+ waiting = True
+ self.log_debug("Waiting for lock on %s" % (self._locktoken,))
+ pause = Deferred()
+ def _timedDeferred():
+ pause.callback(True)
+ reactor.callLater(self._retry_interval, _timedDeferred)
+ yield pause
+ else:
+ self.log_debug("Timed out lock after waiting on %s" % (self._locktoken,))
+ raise MemcacheLockTimeoutError()
+
+ returnValue(True)
+
+ def release(self):
+
+ assert self._hasLock, "Lock not acquired."
+
+ def _done(result):
+ self._hasLock = False
+ return result
+
+ d = self.delete(self._locktoken)
+ d.addCallback(_done)
+ return d
+
+ def clean(self):
+
+ if self._hasLock:
+ return self.release()
+ else:
+ return succeed(True)
+
+ def locked(self):
+ """
+ Test if the lock is currently being held.
+ """
+
+ def _gotit(value):
+ return value is not None
+
+ d = self.get(self._locktoken)
+ d.addCallback(_gotit)
+ return d
+
+class MemcacheLockTimeoutError(Exception):
+ pass
Copied: CalendarServer/branches/users/wsanchez/m2/twext/internet/test/test_memcachelock.py (from rev 6744, CalendarServer/branches/users/wsanchez/m2/twistedcaldav/test/test_memcachelock.py)
===================================================================
--- CalendarServer/branches/users/wsanchez/m2/twext/internet/test/test_memcachelock.py (rev 0)
+++ CalendarServer/branches/users/wsanchez/m2/twext/internet/test/test_memcachelock.py 2011-01-17 23:09:45 UTC (rev 6745)
@@ -0,0 +1,252 @@
+# Copyright (c) 2007 Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+"""
+Test the memcache client protocol.
+"""
+
+from twext.protocols.memcache import MemCacheProtocol
+
+from twisted.test.proto_helpers import StringTransportWithDisconnection
+from twisted.internet.task import Clock
+from twisted.internet.defer import inlineCallbacks
+
+from twext.internet.memcachelock import MemcacheLock, MemcacheLockTimeoutError
+
+from twistedcaldav.test.util import TestCase
+
+class MemCacheTestCase(TestCase):
+ """
+ Test client protocol class L{MemCacheProtocol}.
+ """
+
+ class FakedMemcacheLock(MemcacheLock):
+
+ def __init__(self, faked, namespace, locktoken, timeout=5.0, retry_interval=0.1, expire_time=0):
+ """
+
+ @param namespace: a unique namespace for this lock's tokens
+ @type namespace: C{str}
+ @param locktoken: the name of the locktoken
+ @type locktoken: C{str}
+ @param timeout: the maximum time in seconds that the lock should block
+ @type timeout: C{float}
+ @param retry_interval: the interval to retry acquiring the lock
+ @type retry_interval: C{float}
+ @param expiryTime: the time in seconds for the lock to expire. Zero: no expiration.
+ @type expiryTime: C{float}
+ """
+
+ super(MemCacheTestCase.FakedMemcacheLock, self).__init__(namespace, locktoken, timeout, retry_interval, expire_time)
+ self.faked = faked
+
+ def _getMemcacheProtocol(self):
+
+ return self.faked
+
+ def setUp(self):
+ """
+ Create a memcache client, connect it to a string protocol, and make it
+ use a deterministic clock.
+ """
+ TestCase.setUp(self)
+ self.proto = MemCacheProtocol()
+ self.clock = Clock()
+ self.proto.callLater = self.clock.callLater
+ self.transport = StringTransportWithDisconnection()
+ self.transport.protocol = self.proto
+ self.proto.makeConnection(self.transport)
+
+
+ def _test(self, d, send, recv, result):
+ """
+ Shortcut method for classic tests.
+
+ @param d: the resulting deferred from the memcache command.
+ @type d: C{Deferred}
+
+ @param send: the expected data to be sent.
+ @type send: C{str}
+
+ @param recv: the data to simulate as reception.
+ @type recv: C{str}
+
+ @param result: the expected result.
+ @type result: C{any}
+ """
+ def cb(res):
+ self.assertEquals(res, result)
+ self.assertEquals(self.transport.value(), send)
+ self.transport.clear()
+ d.addCallback(cb)
+ self.proto.dataReceived(recv)
+ return d
+
+ def test_get(self):
+ """
+ L{MemCacheProtocol.get} should return a L{Deferred} which is
+ called back with the value and the flag associated with the given key
+ if the server returns a successful result.
+ """
+ lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking")
+ return self._test(
+ lock.get("foo"),
+ "get lock:foo-acbd18db4cc2f85cedef654fccc4a4d8\r\n",
+ "VALUE lock:foo-acbd18db4cc2f85cedef654fccc4a4d8 0 3\r\nbar\r\nEND\r\n",
+ "bar"
+ )
+
+ def test_set(self):
+ """
+ L{MemCacheProtocol.get} should return a L{Deferred} which is
+ called back with the value and the flag associated with the given key
+ if the server returns a successful result.
+ """
+ lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking")
+ return self._test(
+ lock.set("foo", "bar"),
+ "set lock:foo-acbd18db4cc2f85cedef654fccc4a4d8 0 0 3\r\nbar\r\n",
+ "STORED\r\n",
+ True
+ )
+
+ @inlineCallbacks
+ def test_acquire(self):
+ """
+ L{MemCacheProtocol.get} should return a L{Deferred} which is
+ called back with the value and the flag associated with the given key
+ if the server returns a successful result.
+ """
+ lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking")
+ yield self._test(
+ lock.acquire(),
+ "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
+ "STORED\r\n",
+ True
+ )
+ self.assertTrue(lock._hasLock)
+
+ @inlineCallbacks
+ def test_acquire_ok_timeout_0(self):
+ """
+ L{MemCacheProtocol.get} should return a L{Deferred} which is
+ called back with the value and the flag associated with the given key
+ if the server returns a successful result.
+ """
+ lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking", timeout=0)
+ yield self._test(
+ lock.acquire(),
+ "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
+ "STORED\r\n",
+ True
+ )
+ self.assertTrue(lock._hasLock)
+
+ @inlineCallbacks
+ def test_acquire_fails_timeout_0(self):
+ """
+ L{MemCacheProtocol.get} should return a L{Deferred} which is
+ called back with the value and the flag associated with the given key
+ if the server returns a successful result.
+ """
+ lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking", timeout=0)
+ try:
+ yield self._test(
+ lock.acquire(),
+ "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
+ "NOT_STORED\r\n",
+ True
+ )
+ except MemcacheLockTimeoutError:
+ pass
+ except Exception, e:
+ self.fail("Unknown exception thrown: %s" % (e,))
+ else:
+ self.fail("No timeout exception thrown")
+ self.assertFalse(lock._hasLock)
+
+ @inlineCallbacks
+ def test_acquire_release(self):
+ """
+ L{MemCacheProtocol.get} should return a L{Deferred} which is
+ called back with the value and the flag associated with the given key
+ if the server returns a successful result.
+ """
+ lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking")
+ yield self._test(
+ lock.acquire(),
+ "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
+ "STORED\r\n",
+ True
+ )
+ self.assertTrue(lock._hasLock)
+ yield self._test(
+ lock.release(),
+ "delete lock:locking-559159aa00cc525bfe5c4b34cf16cccb\r\n",
+ "DELETED\r\n",
+ True
+ )
+ self.assertFalse(lock._hasLock)
+
+ @inlineCallbacks
+ def test_acquire_clean(self):
+ """
+ L{MemCacheProtocol.get} should return a L{Deferred} which is
+ called back with the value and the flag associated with the given key
+ if the server returns a successful result.
+ """
+ lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking")
+ yield self._test(
+ lock.acquire(),
+ "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
+ "STORED\r\n",
+ True
+ )
+ yield self._test(
+ lock.clean(),
+ "delete lock:locking-559159aa00cc525bfe5c4b34cf16cccb\r\n",
+ "DELETED\r\n",
+ True
+ )
+
+ @inlineCallbacks
+ def test_acquire_unicode(self):
+ """
+ L{MemCacheProtocol.get} should return a L{Deferred} which is
+ called back with the value and the flag associated with the given key
+ if the server returns a successful result.
+ """
+ lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", u"locking")
+ yield self._test(
+ lock.acquire(),
+ "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
+ "STORED\r\n",
+ True
+ )
+ self.assertTrue(lock._hasLock)
+
+ @inlineCallbacks
+ def test_acquire_invalid_token1(self):
+ """
+ L{MemCacheProtocol.get} should return a L{Deferred} which is
+ called back with the value and the flag associated with the given key
+ if the server returns a successful result.
+ """
+
+ try:
+ lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", 1)
+ yield lock.acquire()
+ self.fail("AssertionError not raised")
+ except AssertionError:
+ pass
+ except:
+ self.fail("AssertionError not raised")
+
+ try:
+ lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", ("abc",))
+ yield lock.acquire()
+ self.fail("AssertionError not raised")
+ except AssertionError:
+ pass
+ except:
+ self.fail("AssertionError not raised")
Modified: CalendarServer/branches/users/wsanchez/m2/twistedcaldav/directory/opendirectorybacker.py
===================================================================
--- CalendarServer/branches/users/wsanchez/m2/twistedcaldav/directory/opendirectorybacker.py 2011-01-17 22:07:02 UTC (rev 6744)
+++ CalendarServer/branches/users/wsanchez/m2/twistedcaldav/directory/opendirectorybacker.py 2011-01-17 23:09:45 UTC (rev 6745)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2006-2010 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2011 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -52,7 +52,7 @@
from twistedcaldav.config import config
from twistedcaldav.directory.directory import DirectoryService, DirectoryRecord
from twistedcaldav.ical import iCalendarProductID
-from twistedcaldav.memcachelock import MemcacheLock, MemcacheLockTimeoutError
+from twext.intenet.memcachelock import MemcacheLock, MemcacheLockTimeoutError
from twistedcaldav.query import addressbookqueryfilter
from twistedcaldav.vcard import Component, Property
@@ -80,17 +80,17 @@
peopleNode = "/Search/Contacts",
queryUserRecords=True,
userNode = "/Search",
- maxDSQueryRecords = 0, # maximum number of records requested for any ds query
+ maxDSQueryRecords = 0, # maximum number of records requested for any ds query
- queryDSLocal = False, #query in DSLocal -- debug
+ queryDSLocal = False, # query in DSLocal -- debug
dsLocalCacheTimeout = 30,
ignoreSystemRecords = True,
- liveQuery = True, # query directory service as needed
- fakeETag = True, # eTag is not reliable if True
+ liveQuery = True, # query directory service as needed
+ fakeETag = True, # eTag is not reliable if True
cacheQuery = False,
- cacheTimeout=30, # cache timeout
+ cacheTimeout=30, # cache timeout
addDSAttrXProperties=False, # add dsattributes to vcards as "X-" attributes
standardizeSyntheticUIDs = False, # use simple synthetic UIDs --- good for testing
@@ -103,17 +103,21 @@
"""
@queryPeopleRecords: C{True} to query for People records
@queryUserRecords: C{True} to query for User records
- @maxDSQueryRecords: maximum number of (unfiltered) ds records retrieved before raising
- NumberOfMatchesWithinLimits exception or returning results
+ @maxDSQueryRecords: maximum number of (unfiltered) ds records
+ retrieved before raising NumberOfMatchesWithinLimits
+ exception or returning results
@dsLocalCacheTimeout: how log to keep cache of DSLocal records
@liveQuery: C{True} to query the directory as needed
- @fakeETag: C{True} to use a fake eTag; allows ds queries with partial attributes
+ @fakeETag: C{True} to use a fake eTag; allows ds queries with
+ partial attributes
@cacheQuery: C{True} to query the directory and cache results
@cacheTimeout: if caching, the average cache timeout
- @standardizeSyntheticUIDs: C{True} when creating synthetic UID (==f(Node, Type, Record Name)),
- use a standard Node name. This allows testing with the same UID on different hosts
- @allowedAttributes: list of DSAttributes that are used to create VCards
-
+ @standardizeSyntheticUIDs: C{True} when creating synthetic UID
+ (==f(Node, Type, Record Name)), use a standard Node
+ name. This allows testing with the same UID on different
+ hosts
+ @allowedAttributes: list of DSAttributes that are used to
+ create VCards
"""
assert directoryBackedAddressBook is not None
self.directoryBackedAddressBook = directoryBackedAddressBook
Modified: CalendarServer/branches/users/wsanchez/m2/twistedcaldav/ical.py
===================================================================
--- CalendarServer/branches/users/wsanchez/m2/twistedcaldav/ical.py 2011-01-17 22:07:02 UTC (rev 6744)
+++ CalendarServer/branches/users/wsanchez/m2/twistedcaldav/ical.py 2011-01-17 23:09:45 UTC (rev 6745)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2005-2010 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2011 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -60,44 +60,62 @@
"VEVENT",
"VTODO",
"VTIMEZONE",
- #"VJOURNAL",
+ #"VJOURNAL",
"VFREEBUSY",
- #"VAVAILABILITY",
+ #"VAVAILABILITY",
)
# 2445 default values and parameters
# Structure: propname: (<default value>, <parameter defaults dict>)
normalizeProps = {
- "CALSCALE": ("GREGORIAN", {"VALUE": "TEXT"}),
- "METHOD": (None, {"VALUE": "TEXT"}),
- "PRODID": (None, {"VALUE": "TEXT"}),
- "VERSION": (None, {"VALUE": "TEXT"}),
- "ATTACH": (None, {"VALUE": "URI"}),
- "CATEGORIES": (None, {"VALUE": "TEXT"}),
- "CLASS": (None, {"VALUE": "TEXT"}),
- "COMMENT": (None, {"VALUE": "TEXT"}),
- "DESCRIPTION": (None, {"VALUE": "TEXT"}),
- "GEO": (None, {"VALUE": "FLOAT"}),
- "LOCATION": (None, {"VALUE": "TEXT"}),
- "PERCENT-COMPLETE": (None, {"VALUE": "INTEGER"}),
- "PRIORITY": ("0", {"VALUE": "INTEGER"}),
- "RESOURCES": (None, {"VALUE": "TEXT"}),
- "STATUS": (None, {"VALUE": "TEXT"}),
- "SUMMARY": (None, {"VALUE": "TEXT"}),
- "COMPLETED": (None, {"VALUE": "DATE-TIME"}),
- "DTEND": (None, {"VALUE": "DATE-TIME"}),
- "DUE": (None, {"VALUE": "DATE-TIME"}),
- "DTSTART": (None, {"VALUE": "DATE-TIME"}),
- "DURATION": (None, {"VALUE": "DURATION"}),
- "FREEBUSY": (None, {"VALUE": "PERIOD"}),
- "TRANSP": ("OPAQUE", {"VALUE": "TEXT"}),
- "TZID": (None, {"VALUE": "TEXT"}),
- "TZNAME": (None, {"VALUE": "TEXT"}),
- "TZOFFSETFROM": (None, {"VALUE": "UTC-OFFSET"}),
- "TZOFFSETTO": (None, {"VALUE": "UTC-OFFSET"}),
- "TZURL": (None, {"VALUE": "URI"}),
- "ATTENDEE": (None, {
+ "CALSCALE": ("GREGORIAN", {"VALUE": "TEXT" }),
+ "METHOD": (None, {"VALUE": "TEXT" }),
+ "PRODID": (None, {"VALUE": "TEXT" }),
+ "VERSION": (None, {"VALUE": "TEXT" }),
+ "ATTACH": (None, {"VALUE": "URI" }),
+ "CATEGORIES": (None, {"VALUE": "TEXT" }),
+ "CLASS": (None, {"VALUE": "TEXT" }),
+ "COMMENT": (None, {"VALUE": "TEXT" }),
+ "DESCRIPTION": (None, {"VALUE": "TEXT" }),
+ "GEO": (None, {"VALUE": "FLOAT" }),
+ "LOCATION": (None, {"VALUE": "TEXT" }),
+ "PERCENT-COMPLETE": (None, {"VALUE": "INTEGER" }),
+ "PRIORITY": ("0", {"VALUE": "INTEGER" }),
+ "RESOURCES": (None, {"VALUE": "TEXT" }),
+ "STATUS": (None, {"VALUE": "TEXT" }),
+ "SUMMARY": (None, {"VALUE": "TEXT" }),
+ "COMPLETED": (None, {"VALUE": "DATE-TIME" }),
+ "DTEND": (None, {"VALUE": "DATE-TIME" }),
+ "DUE": (None, {"VALUE": "DATE-TIME" }),
+ "DTSTART": (None, {"VALUE": "DATE-TIME" }),
+ "DURATION": (None, {"VALUE": "DURATION" }),
+ "FREEBUSY": (None, {"VALUE": "PERIOD" }),
+ "TRANSP": ("OPAQUE", {"VALUE": "TEXT" }),
+ "TZID": (None, {"VALUE": "TEXT" }),
+ "TZNAME": (None, {"VALUE": "TEXT" }),
+ "TZOFFSETFROM": (None, {"VALUE": "UTC-OFFSET" }),
+ "TZOFFSETTO": (None, {"VALUE": "UTC-OFFSET" }),
+ "TZURL": (None, {"VALUE": "URI" }),
+ "CONTACT": (None, {"VALUE": "TEXT" }),
+ "ORGANIZER": (None, {"VALUE": "CAL-ADDRESS"}),
+ "RECURRENCE-ID": (None, {"VALUE": "DATE-TIME" }),
+ "RELATED-TO": (None, {"VALUE": "TEXT" }),
+ "URL": (None, {"VALUE": "URI" }),
+ "UID": (None, {"VALUE": "TEXT" }),
+ "EXDATE": (None, {"VALUE": "DATE-TIME" }),
+ "EXRULE": (None, {"VALUE": "RECUR" }),
+ "RDATE": (None, {"VALUE": "DATE-TIME" }),
+ "RRULE": (None, {"VALUE": "RECUR" }),
+ "ACTION": (None, {"VALUE": "TEXT" }),
+ "REPEAT": ("0", {"VALUE": "INTEGER" }),
+ "TRIGGER": (None, {"VALUE": "DURATION" }),
+ "CREATED": (None, {"VALUE": "DATE-TIME" }),
+ "DTSTAMP": (None, {"VALUE": "DATE-TIME" }),
+ "LAST-MODIFIED": (None, {"VALUE": "DATE-TIME" }),
+ "SEQUENCE": ("0", {"VALUE": "INTEGER" }),
+ "REQUEST-STATUS": (None, {"VALUE": "TEXT" }),
+ "ATTENDEE": (None, {
"VALUE": "CAL-ADDRESS",
"CUTYPE": "INDIVIDUAL",
"ROLE": "REQ-PARTICIPANT",
@@ -105,24 +123,6 @@
"RSVP": "FALSE",
"SCHEDULE-AGENT": "SERVER",
}),
- "CONTACT": (None, {"VALUE": "TEXT"}),
- "ORGANIZER": (None, {"VALUE": "CAL-ADDRESS"}),
- "RECURRENCE-ID": (None, {"VALUE": "DATE-TIME"}),
- "RELATED-TO": (None, {"VALUE": "TEXT"}),
- "URL": (None, {"VALUE": "URI"}),
- "UID": (None, {"VALUE": "TEXT"}),
- "EXDATE": (None, {"VALUE": "DATE-TIME"}),
- "EXRULE": (None, {"VALUE": "RECUR"}),
- "RDATE": (None, {"VALUE": "DATE-TIME"}),
- "RRULE": (None, {"VALUE": "RECUR"}),
- "ACTION": (None, {"VALUE": "TEXT"}),
- "REPEAT": ("0", {"VALUE": "INTEGER"}),
- "TRIGGER": (None, {"VALUE": "DURATION"}),
- "CREATED": (None, {"VALUE": "DATE-TIME"}),
- "DTSTAMP": (None, {"VALUE": "DATE-TIME"}),
- "LAST-MODIFIED": (None, {"VALUE": "DATE-TIME"}),
- "SEQUENCE": ("0", {"VALUE": "INTEGER"}),
- "REQUEST-STATUS": (None, {"VALUE": "TEXT"}),
}
# transformations to apply to property values
Deleted: CalendarServer/branches/users/wsanchez/m2/twistedcaldav/memcachelock.py
===================================================================
--- CalendarServer/branches/users/wsanchez/m2/twistedcaldav/memcachelock.py 2011-01-17 22:07:02 UTC (rev 6744)
+++ CalendarServer/branches/users/wsanchez/m2/twistedcaldav/memcachelock.py 2011-01-17 23:09:45 UTC (rev 6745)
@@ -1,118 +0,0 @@
-##
-# Copyright (c) 2008-2009 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-from twistedcaldav.memcacher import Memcacher
-from twisted.internet.defer import inlineCallbacks, Deferred, returnValue,\
- succeed
-from twisted.internet import reactor
-import time
-
-class MemcacheLock(Memcacher):
-
- def __init__(self, namespace, locktoken, timeout=5.0, retry_interval=0.1, expire_time=0):
- """
-
- @param namespace: a unique namespace for this lock's tokens
- @type namespace: C{str}
- @param locktoken: the name of the locktoken
- @type locktoken: C{str}
- @param timeout: the maximum time in seconds that the lock should block
- @type timeout: C{float}
- @param retry_interval: the interval to retry acquiring the lock
- @type retry_interval: C{float}
- @param expiryTime: the time in seconds for the lock to expire. Zero: no expiration.
- @type expiryTime: C{float}
- """
-
- super(MemcacheLock, self).__init__(namespace)
- self._locktoken = locktoken
- self._timeout = timeout
- self._retry_interval = retry_interval
- self._expire_time = expire_time
- self._hasLock = False
-
- def _getMemcacheProtocol(self):
-
- result = super(MemcacheLock, self)._getMemcacheProtocol()
-
- if isinstance(result, Memcacher.nullCacher):
- raise AssertionError("No implementation of shared locking without memcached")
-
- return result
-
- @inlineCallbacks
- def acquire(self):
-
- assert not self._hasLock, "Lock already acquired."
-
- timeout_at = time.time() + self._timeout
- waiting = False
- while True:
-
- result = (yield self.add(self._locktoken, "1", self._expire_time))
- if result:
- self._hasLock = True
- if waiting:
- self.log_debug("Got lock after waiting on %s" % (self._locktoken,))
- break
-
- if self._timeout and time.time() < timeout_at:
- waiting = True
- self.log_debug("Waiting for lock on %s" % (self._locktoken,))
- pause = Deferred()
- def _timedDeferred():
- pause.callback(True)
- reactor.callLater(self._retry_interval, _timedDeferred)
- yield pause
- else:
- self.log_debug("Timed out lock after waiting on %s" % (self._locktoken,))
- raise MemcacheLockTimeoutError()
-
- returnValue(True)
-
- def release(self):
-
- assert self._hasLock, "Lock not acquired."
-
- def _done(result):
- self._hasLock = False
- return result
-
- d = self.delete(self._locktoken)
- d.addCallback(_done)
- return d
-
- def clean(self):
-
- if self._hasLock:
- return self.release()
- else:
- return succeed(True)
-
- def locked(self):
- """
- Test if the lock is currently being held.
- """
-
- def _gotit(value):
- return value is not None
-
- d = self.get(self._locktoken)
- d.addCallback(_gotit)
- return d
-
-class MemcacheLockTimeoutError(Exception):
- pass
Modified: CalendarServer/branches/users/wsanchez/m2/twistedcaldav/method/put_common.py
===================================================================
--- CalendarServer/branches/users/wsanchez/m2/twistedcaldav/method/put_common.py 2011-01-17 22:07:02 UTC (rev 6744)
+++ CalendarServer/branches/users/wsanchez/m2/twistedcaldav/method/put_common.py 2011-01-17 23:09:45 UTC (rev 6745)
@@ -1,6 +1,6 @@
# -*- test-case-name: twistedcaldav.test.test_validation -*-
##
-# Copyright (c) 2005-2010 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2011 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -55,9 +55,9 @@
from twistedcaldav.datafilters.peruserdata import PerUserDataFilter
from twistedcaldav.ical import Component, Property
-from twistedcaldav.instance import TooManyInstancesError,\
- InvalidOverriddenInstanceError
-from twistedcaldav.memcachelock import MemcacheLock, MemcacheLockTimeoutError
+from twistedcaldav.instance import TooManyInstancesError
+from twistedcaldav.instance import InvalidOverriddenInstanceError
+from twext.internet.memcachelock import MemcacheLock, MemcacheLockTimeoutError
from twistedcaldav.scheduling.implicit import ImplicitScheduler
log = Logger()
Modified: CalendarServer/branches/users/wsanchez/m2/twistedcaldav/scheduling/processing.py
===================================================================
--- CalendarServer/branches/users/wsanchez/m2/twistedcaldav/scheduling/processing.py 2011-01-17 22:07:02 UTC (rev 6744)
+++ CalendarServer/branches/users/wsanchez/m2/twistedcaldav/scheduling/processing.py 2011-01-17 23:09:45 UTC (rev 6745)
@@ -1,6 +1,6 @@
+##
+# Copyright (c) 2005-2011 Apple Inc. All rights reserved.
#
-# Copyright (c) 2005-2010 Apple Inc. All rights reserved.
-#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -36,7 +36,7 @@
from twistedcaldav.scheduling.cuaddress import normalizeCUAddr
from twistedcaldav.scheduling.itip import iTipProcessing, iTIPRequestStatus
from twistedcaldav.scheduling.utils import getCalendarObjectForPrincipals
-from twistedcaldav.memcachelock import MemcacheLock, MemcacheLockTimeoutError
+from twext.internet.memcachelock import MemcacheLock, MemcacheLockTimeoutError
__all__ = [
"ImplicitProcessor",
Modified: CalendarServer/branches/users/wsanchez/m2/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/users/wsanchez/m2/twistedcaldav/storebridge.py 2011-01-17 22:07:02 UTC (rev 6744)
+++ CalendarServer/branches/users/wsanchez/m2/twistedcaldav/storebridge.py 2011-01-17 23:09:45 UTC (rev 6745)
@@ -1,6 +1,6 @@
# -*- test-case-name: twistedcaldav.test.test_wrapping -*-
##
-# Copyright (c) 2005-2010 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2011 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -22,8 +22,8 @@
from urlparse import urlsplit
-from twisted.internet.defer import succeed, inlineCallbacks, returnValue,\
- maybeDeferred
+from twisted.internet.defer import succeed, maybeDeferred
+from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.internet.protocol import Protocol
from twisted.python.log import err as logDefaultException
from twisted.python.util import FancyEqMixin
@@ -36,8 +36,8 @@
from twext.web2.dav.http import ErrorResponse, ResponseQueue
from twext.web2.dav.noneprops import NonePropertyStore
from twext.web2.dav.resource import TwistedACLInheritable, AccessDeniedError
-from twext.web2.dav.util import parentForURL, allDataFromStream, joinURL, \
- davXMLFromStream
+from twext.web2.dav.util import parentForURL, joinURL
+from twext.web2.dav.util import allDataFromStream, davXMLFromStream
from twext.web2.http import HTTPError, StatusResponse, Response
from twext.web2.http_headers import ETag, MimeType
from twext.web2.responsecode import (
@@ -48,9 +48,9 @@
from twistedcaldav.caldavxml import caldav_namespace
from twistedcaldav.config import config
-from twistedcaldav.memcachelock import MemcacheLock, MemcacheLockTimeoutError
-from twistedcaldav.notifications import NotificationCollectionResource, \
- NotificationResource
+from twext.internet.memcachelock import MemcacheLock, MemcacheLockTimeoutError
+from twistedcaldav.notifications import NotificationCollectionResource
+from twistedcaldav.notifications import NotificationResource
from twistedcaldav.resource import CalDAVResource, GlobalAddressBookResource
from twistedcaldav.schedule import ScheduleInboxResource
from twistedcaldav.scheduling.implicit import ImplicitScheduler
Modified: CalendarServer/branches/users/wsanchez/m2/twistedcaldav/test/test_collectioncontents.py
===================================================================
--- CalendarServer/branches/users/wsanchez/m2/twistedcaldav/test/test_collectioncontents.py 2011-01-17 22:07:02 UTC (rev 6744)
+++ CalendarServer/branches/users/wsanchez/m2/twistedcaldav/test/test_collectioncontents.py 2011-01-17 23:09:45 UTC (rev 6745)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2011 Apple Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
from twext.web2.test.test_server import SimpleRequest
from twistedcaldav.ical import Component
-from twistedcaldav.memcachelock import MemcacheLock
+from twext.internet.memcachelock import MemcacheLock
from twistedcaldav.memcacher import Memcacher
from twistedcaldav.method.put_common import StoreCalendarObjectResource
Deleted: CalendarServer/branches/users/wsanchez/m2/twistedcaldav/test/test_memcachelock.py
===================================================================
--- CalendarServer/branches/users/wsanchez/m2/twistedcaldav/test/test_memcachelock.py 2011-01-17 22:07:02 UTC (rev 6744)
+++ CalendarServer/branches/users/wsanchez/m2/twistedcaldav/test/test_memcachelock.py 2011-01-17 23:09:45 UTC (rev 6745)
@@ -1,252 +0,0 @@
-# Copyright (c) 2007 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-"""
-Test the memcache client protocol.
-"""
-
-from twext.protocols.memcache import MemCacheProtocol
-
-from twisted.test.proto_helpers import StringTransportWithDisconnection
-from twisted.internet.task import Clock
-from twisted.internet.defer import inlineCallbacks
-
-from twistedcaldav.memcachelock import MemcacheLock, MemcacheLockTimeoutError
-
-from twistedcaldav.test.util import TestCase
-
-class MemCacheTestCase(TestCase):
- """
- Test client protocol class L{MemCacheProtocol}.
- """
-
- class FakedMemcacheLock(MemcacheLock):
-
- def __init__(self, faked, namespace, locktoken, timeout=5.0, retry_interval=0.1, expire_time=0):
- """
-
- @param namespace: a unique namespace for this lock's tokens
- @type namespace: C{str}
- @param locktoken: the name of the locktoken
- @type locktoken: C{str}
- @param timeout: the maximum time in seconds that the lock should block
- @type timeout: C{float}
- @param retry_interval: the interval to retry acquiring the lock
- @type retry_interval: C{float}
- @param expiryTime: the time in seconds for the lock to expire. Zero: no expiration.
- @type expiryTime: C{float}
- """
-
- super(MemCacheTestCase.FakedMemcacheLock, self).__init__(namespace, locktoken, timeout, retry_interval, expire_time)
- self.faked = faked
-
- def _getMemcacheProtocol(self):
-
- return self.faked
-
- def setUp(self):
- """
- Create a memcache client, connect it to a string protocol, and make it
- use a deterministic clock.
- """
- TestCase.setUp(self)
- self.proto = MemCacheProtocol()
- self.clock = Clock()
- self.proto.callLater = self.clock.callLater
- self.transport = StringTransportWithDisconnection()
- self.transport.protocol = self.proto
- self.proto.makeConnection(self.transport)
-
-
- def _test(self, d, send, recv, result):
- """
- Shortcut method for classic tests.
-
- @param d: the resulting deferred from the memcache command.
- @type d: C{Deferred}
-
- @param send: the expected data to be sent.
- @type send: C{str}
-
- @param recv: the data to simulate as reception.
- @type recv: C{str}
-
- @param result: the expected result.
- @type result: C{any}
- """
- def cb(res):
- self.assertEquals(res, result)
- self.assertEquals(self.transport.value(), send)
- self.transport.clear()
- d.addCallback(cb)
- self.proto.dataReceived(recv)
- return d
-
- def test_get(self):
- """
- L{MemCacheProtocol.get} should return a L{Deferred} which is
- called back with the value and the flag associated with the given key
- if the server returns a successful result.
- """
- lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking")
- return self._test(
- lock.get("foo"),
- "get lock:foo-acbd18db4cc2f85cedef654fccc4a4d8\r\n",
- "VALUE lock:foo-acbd18db4cc2f85cedef654fccc4a4d8 0 3\r\nbar\r\nEND\r\n",
- "bar"
- )
-
- def test_set(self):
- """
- L{MemCacheProtocol.get} should return a L{Deferred} which is
- called back with the value and the flag associated with the given key
- if the server returns a successful result.
- """
- lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking")
- return self._test(
- lock.set("foo", "bar"),
- "set lock:foo-acbd18db4cc2f85cedef654fccc4a4d8 0 0 3\r\nbar\r\n",
- "STORED\r\n",
- True
- )
-
- @inlineCallbacks
- def test_acquire(self):
- """
- L{MemCacheProtocol.get} should return a L{Deferred} which is
- called back with the value and the flag associated with the given key
- if the server returns a successful result.
- """
- lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking")
- yield self._test(
- lock.acquire(),
- "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
- "STORED\r\n",
- True
- )
- self.assertTrue(lock._hasLock)
-
- @inlineCallbacks
- def test_acquire_ok_timeout_0(self):
- """
- L{MemCacheProtocol.get} should return a L{Deferred} which is
- called back with the value and the flag associated with the given key
- if the server returns a successful result.
- """
- lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking", timeout=0)
- yield self._test(
- lock.acquire(),
- "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
- "STORED\r\n",
- True
- )
- self.assertTrue(lock._hasLock)
-
- @inlineCallbacks
- def test_acquire_fails_timeout_0(self):
- """
- L{MemCacheProtocol.get} should return a L{Deferred} which is
- called back with the value and the flag associated with the given key
- if the server returns a successful result.
- """
- lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking", timeout=0)
- try:
- yield self._test(
- lock.acquire(),
- "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
- "NOT_STORED\r\n",
- True
- )
- except MemcacheLockTimeoutError:
- pass
- except Exception, e:
- self.fail("Unknown exception thrown: %s" % (e,))
- else:
- self.fail("No timeout exception thrown")
- self.assertFalse(lock._hasLock)
-
- @inlineCallbacks
- def test_acquire_release(self):
- """
- L{MemCacheProtocol.get} should return a L{Deferred} which is
- called back with the value and the flag associated with the given key
- if the server returns a successful result.
- """
- lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking")
- yield self._test(
- lock.acquire(),
- "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
- "STORED\r\n",
- True
- )
- self.assertTrue(lock._hasLock)
- yield self._test(
- lock.release(),
- "delete lock:locking-559159aa00cc525bfe5c4b34cf16cccb\r\n",
- "DELETED\r\n",
- True
- )
- self.assertFalse(lock._hasLock)
-
- @inlineCallbacks
- def test_acquire_clean(self):
- """
- L{MemCacheProtocol.get} should return a L{Deferred} which is
- called back with the value and the flag associated with the given key
- if the server returns a successful result.
- """
- lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", "locking")
- yield self._test(
- lock.acquire(),
- "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
- "STORED\r\n",
- True
- )
- yield self._test(
- lock.clean(),
- "delete lock:locking-559159aa00cc525bfe5c4b34cf16cccb\r\n",
- "DELETED\r\n",
- True
- )
-
- @inlineCallbacks
- def test_acquire_unicode(self):
- """
- L{MemCacheProtocol.get} should return a L{Deferred} which is
- called back with the value and the flag associated with the given key
- if the server returns a successful result.
- """
- lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", u"locking")
- yield self._test(
- lock.acquire(),
- "add lock:locking-559159aa00cc525bfe5c4b34cf16cccb 0 0 1\r\n1\r\n",
- "STORED\r\n",
- True
- )
- self.assertTrue(lock._hasLock)
-
- @inlineCallbacks
- def test_acquire_invalid_token1(self):
- """
- L{MemCacheProtocol.get} should return a L{Deferred} which is
- called back with the value and the flag associated with the given key
- if the server returns a successful result.
- """
-
- try:
- lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", 1)
- yield lock.acquire()
- self.fail("AssertionError not raised")
- except AssertionError:
- pass
- except:
- self.fail("AssertionError not raised")
-
- try:
- lock = MemCacheTestCase.FakedMemcacheLock(self.proto, "lock", ("abc",))
- yield lock.acquire()
- self.fail("AssertionError not raised")
- except AssertionError:
- pass
- except:
- self.fail("AssertionError not raised")
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110117/e4cb6103/attachment-0001.html>
More information about the calendarserver-changes
mailing list