[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