[CalendarServer-changes] [8417] CalendarServer/trunk/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Thu Dec 8 12:32:31 PST 2011


Revision: 8417
          http://trac.macosforge.org/projects/calendarserver/changeset/8417
Author:   cdaboo at apple.com
Date:     2011-12-08 12:32:30 -0800 (Thu, 08 Dec 2011)
Log Message:
-----------
Fix attribute error in iSchedule deadlock code. Had to tweak memcache and lock timeout stuff to get a usable test for this fix.

Modified Paths:
--------------
    CalendarServer/trunk/twistedcaldav/directory/test/test_proxyprincipaldb.py
    CalendarServer/trunk/twistedcaldav/memcacher.py
    CalendarServer/trunk/twistedcaldav/method/put_common.py
    CalendarServer/trunk/twistedcaldav/scheduling/processing.py
    CalendarServer/trunk/twistedcaldav/scheduling/scheduler.py
    CalendarServer/trunk/twistedcaldav/stdconfig.py
    CalendarServer/trunk/twistedcaldav/storebridge.py
    CalendarServer/trunk/twistedcaldav/test/test_schedule.py
    CalendarServer/trunk/twistedcaldav/test/util.py

Modified: CalendarServer/trunk/twistedcaldav/directory/test/test_proxyprincipaldb.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/test/test_proxyprincipaldb.py	2011-12-08 15:48:47 UTC (rev 8416)
+++ CalendarServer/trunk/twistedcaldav/directory/test/test_proxyprincipaldb.py	2011-12-08 20:32:30 UTC (rev 8417)
@@ -240,6 +240,8 @@
             self.assertEqual(membershipsD, set())
             self.assertEqual(membershipsE, set(("A",)))
 
+            yield db.clean()
+
     @inlineCallbacks
     def test_cachingDBRemove(self):
     
@@ -281,6 +283,8 @@
             self.assertEqual(membershipsC, set("X",))
             self.assertEqual(membershipsD, set())
 
+            yield db.clean()
+
     @inlineCallbacks
     def test_cachingDBRemoveSpecial(self):
     
@@ -314,6 +318,8 @@
             self.assertEqual(membershipsC, set("X",))
             self.assertEqual(membershipsD, set())
 
+            yield db.clean()
+
     @inlineCallbacks
     def test_cachingDBRemovePrincipal(self):
     
@@ -355,6 +361,8 @@
             self.assertEqual(membershipsC, set(("A", "X",)))
             self.assertEqual(membershipsD, set(("A",),))
 
+            yield db.clean()
+
     @inlineCallbacks
     def test_cachingDBInsertUncached(self):
     
@@ -384,6 +392,8 @@
             self.assertEqual(membershipsDD, set())
             self.assertEqual(membershipsEE, set(("AA",)))
 
+            yield db.clean()
+
 class ProxyPrincipalDBPostgreSQL (twistedcaldav.test.util.TestCase):
     """
     Directory service provisioned principals.

Modified: CalendarServer/trunk/twistedcaldav/memcacher.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/memcacher.py	2011-12-08 15:48:47 UTC (rev 8416)
+++ CalendarServer/trunk/twistedcaldav/memcacher.py	2011-12-08 20:32:30 UTC (rev 8417)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2008-2010 Apple Inc. All rights reserved.
+# Copyright (c) 2008-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.
@@ -36,6 +36,7 @@
     keyNormalizeTranslateTable = string.maketrans("".join([chr(i) for i in range(33)]) + chr(0x7F), "_"*33 + "_")
 
     allowTestCache = False
+    memoryCacheInstance = None
 
     class memoryCacher():
         """
@@ -204,7 +205,9 @@
 
         elif config.ProcessType == "Single" or self._noInvalidation or self.allowTestCache:
             # NB no need to pickle the memory cacher as it handles python types natively
-            self._memcacheProtocol = Memcacher.memoryCacher()
+            if Memcacher.memoryCacheInstance is None:
+                Memcacher.memoryCacheInstance = Memcacher.memoryCacher()
+            self._memcacheProtocol = Memcacher.memoryCacheInstance
             self._pickle = False
 
         else:

Modified: CalendarServer/trunk/twistedcaldav/method/put_common.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/put_common.py	2011-12-08 15:48:47 UTC (rev 8416)
+++ CalendarServer/trunk/twistedcaldav/method/put_common.py	2011-12-08 20:32:30 UTC (rev 8417)
@@ -66,7 +66,12 @@
             if internal_request:
                 self.lock = None
             else:
-                self.lock = MemcacheLock("ImplicitUIDLock", uid, timeout=60.0, expire_time=5*60)
+                self.lock = MemcacheLock(
+                    "ImplicitUIDLock",
+                    uid,
+                    timeout=config.Scheduling.Options.UIDLockTimeoutSeconds,
+                    expire_time=config.Scheduling.Options.UIDLockExpirySeconds
+                )
             self.reserved = False
             self.index = index
             self.uid = uid

Modified: CalendarServer/trunk/twistedcaldav/scheduling/processing.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/processing.py	2011-12-08 15:48:47 UTC (rev 8416)
+++ CalendarServer/trunk/twistedcaldav/scheduling/processing.py	2011-12-08 20:32:30 UTC (rev 8417)
@@ -239,7 +239,12 @@
         if config.Scheduling.Options.AttendeeRefreshBatch:
             
             # Need to lock whilst manipulating the batch list
-            lock = MemcacheLock("BatchRefreshUIDLock", self.uid, timeout=60.0, expire_time=60.0)
+            lock = MemcacheLock(
+                "BatchRefreshUIDLock",
+                self.uid,
+                timeout=config.Scheduling.Options.UIDLockTimeoutSeconds,
+                expire_time=config.Scheduling.Options.UIDLockExpirySeconds,
+            )
             try:
                 yield lock.acquire()
             except MemcacheLockTimeoutError:
@@ -311,7 +316,12 @@
         # We need to get the UID lock for implicit processing whilst we send the auto-reply
         # as the Organizer processing will attempt to write out data to other attendees to
         # refresh them. To prevent a race we need a lock.
-        uidlock = MemcacheLock("ImplicitUIDLock", self.uid, timeout=60.0, expire_time=5*60)
+        uidlock = MemcacheLock(
+            "ImplicitUIDLock",
+            self.uid,
+            timeout=config.Scheduling.Options.UIDLockTimeoutSeconds,
+            expire_time=config.Scheduling.Options.UIDLockExpirySeconds,
+        )
 
         try:
             yield uidlock.acquire()
@@ -347,7 +357,12 @@
 
         # Need to lock whilst manipulating the batch list
         log.debug("ImplicitProcessing - batch refresh for UID: '%s'" % (self.uid,))
-        lock = MemcacheLock("BatchRefreshUIDLock", self.uid, timeout=60.0, expire_time=60.0)
+        lock = MemcacheLock(
+            "BatchRefreshUIDLock",
+            self.uid,
+            timeout=config.Scheduling.Options.UIDLockTimeoutSeconds,
+            expire_time=config.Scheduling.Options.UIDLockExpirySeconds,
+        )
         try:
             yield lock.acquire()
         except MemcacheLockTimeoutError:
@@ -598,7 +613,12 @@
         # We need to get the UID lock for implicit processing whilst we send the auto-reply
         # as the Organizer processing will attempt to write out data to other attendees to
         # refresh them. To prevent a race we need a lock.
-        lock = MemcacheLock("ImplicitUIDLock", calendar.resourceUID(), timeout=60.0, expire_time=5*60)
+        lock = MemcacheLock(
+            "ImplicitUIDLock",
+            calendar.resourceUID(),
+            timeout=config.Scheduling.Options.UIDLockTimeoutSeconds,
+            expire_time=config.Scheduling.Options.UIDLockExpirySeconds,
+        )
 
         # Note that this lock also protects the request, as this request is
         # being re-used by potentially multiple transactions and should not be

Modified: CalendarServer/trunk/twistedcaldav/scheduling/scheduler.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/scheduler.py	2011-12-08 15:48:47 UTC (rev 8416)
+++ CalendarServer/trunk/twistedcaldav/scheduling/scheduler.py	2011-12-08 20:32:30 UTC (rev 8417)
@@ -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.
@@ -110,17 +110,19 @@
 
         # We might trigger an implicit scheduling operation here that will require consistency
         # of data for all events with the same UID. So detect this and use a lock
-        lock = None
         if self.calendar.resourceType() != "VFREEBUSY":
             uid = self.calendar.resourceUID()
-            lock = MemcacheLock("ImplicitUIDLock", uid, timeout=60.0, expire_time=5*60)
+            lock = MemcacheLock(
+                "ImplicitUIDLock",
+                uid,
+                timeout=config.Scheduling.Options.UIDLockTimeoutSeconds,
+                expire_time=config.Scheduling.Options.UIDLockExpirySeconds,
+            )
 
-        # Implicit lock
-        if lock:
             try:
                 yield lock.acquire()
             except MemcacheLockTimeoutError:
-                raise HTTPError(StatusResponse(responsecode.CONFLICT, "Resource: %s currently in use on the server." % (self.uri,)))
+                raise HTTPError(StatusResponse(responsecode.CONFLICT, "UID: %s currently in use on the server." % (uid,)))
             else:
                 # Release lock after commit or abort
                 transaction.postCommit(lock.clean)

Modified: CalendarServer/trunk/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/stdconfig.py	2011-12-08 15:48:47 UTC (rev 8416)
+++ CalendarServer/trunk/twistedcaldav/stdconfig.py	2011-12-08 20:32:30 UTC (rev 8417)
@@ -620,10 +620,12 @@
             "AllowLocationAsOrganizer"            : False, # Allow locations to be Organizers
             "AllowResourceAsOrganizer"            : False, # Allow resources to be Organizers
             "AllowUserAutoAccept"                 : False, # Allow auto-accept for users
-            "LimitFreeBusyAttendees"              : 30,    # Maximum number of attendees to request freebusy for
-            "AttendeeRefreshBatch"                :  5,    # Number of attendees to do batched refreshes: 0 - no batching
-            "AttendeeRefreshBatchDelaySeconds"    :  5,    # Time after an iTIP REPLY for first batched attendee refresh
-            "AttendeeRefreshBatchIntervalSeconds" :  5,    # Time between attendee batch refreshes 
+            "LimitFreeBusyAttendees"              :  30,    # Maximum number of attendees to request freebusy for
+            "AttendeeRefreshBatch"                :   5,    # Number of attendees to do batched refreshes: 0 - no batching
+            "AttendeeRefreshBatchDelaySeconds"    :   5,    # Time after an iTIP REPLY for first batched attendee refresh
+            "AttendeeRefreshBatchIntervalSeconds" :   5,    # Time between attendee batch refreshes
+            "UIDLockTimeoutSeconds"               :  60,    # Time for implicit UID lock timeout
+            "UIDLockExpirySeconds"                : 300,    # Expiration time for UID lock
         }
     },
 

Modified: CalendarServer/trunk/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/storebridge.py	2011-12-08 15:48:47 UTC (rev 8416)
+++ CalendarServer/trunk/twistedcaldav/storebridge.py	2011-12-08 20:32:30 UTC (rev 8417)
@@ -1952,7 +1952,10 @@
             )
             if do_implicit_action:
                 lock = MemcacheLock(
-                    "ImplicitUIDLock", calendar.resourceUID(), timeout=60.0, expire_time=5*60
+                    "ImplicitUIDLock",
+                    calendar.resourceUID(),
+                    timeout=config.Scheduling.Options.UIDLockTimeoutSeconds,
+                    expire_time=config.Scheduling.Options.UIDLockExpirySeconds,
                 )
 
         try:

Modified: CalendarServer/trunk/twistedcaldav/test/test_schedule.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_schedule.py	2011-12-08 15:48:47 UTC (rev 8416)
+++ CalendarServer/trunk/twistedcaldav/test/test_schedule.py	2011-12-08 20:32:30 UTC (rev 8417)
@@ -25,6 +25,9 @@
 from twisted.internet.defer import inlineCallbacks
 
 from twistedcaldav import caldavxml, customxml
+from twistedcaldav.config import config
+from twistedcaldav.memcachelock import MemcacheLock
+from twistedcaldav.schedule import IScheduleInboxResource
 from twistedcaldav.test.util import HomeTestCase, TestCase
 
 class Properties (HomeTestCase):
@@ -306,3 +309,52 @@
         self.assertEqual(result, customxml.ScheduleDefaultTasksURL)
 
         request._newStoreTransaction.commit()
+
+class iSchedulePOST (TestCase):
+
+    def setUp(self):
+        super(iSchedulePOST, self).setUp()
+        self.createStockDirectoryService()
+        self.setupCalendars()
+        self.site.resource.putChild("ischedule", IScheduleInboxResource(self.site.resource, self._newStore))
+
+    @inlineCallbacks
+    def test_deadlock(self):
+        """
+        Make calendar
+        """
+        
+        request = SimpleRequest(
+            self.site,
+            "POST",
+            "/ischedule",
+            headers=http_headers.Headers(rawHeaders={
+                "Originator": ("mailto:wsanchez at example.com",),
+                "Recipient": ("mailto:cdaboo at example.com",),
+            }),
+            content="""BEGIN:VCALENDAR
+CALSCALE:GREGORIAN
+PRODID:-//Example Inc.//Example Calendar//EN
+VERSION:2.0
+BEGIN:VEVENT
+DTSTAMP:20051222T205953Z
+CREATED:20060101T150000Z
+DTSTART:20060101T100000Z
+DURATION:PT1H
+SUMMARY:event 1
+UID:deadlocked
+ORGANIZER:mailto:wsanchez at example.com
+ATTENDEE;PARTSTAT=ACCEPTED:mailto:wsanchez at example.com
+ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION:mailto:cdaboo at example.com
+END:VEVENT
+END:VCALENDAR
+""".replace("\n", "\r\n")
+        )
+
+        # Lock the UID here to force a deadlock - but adjust the timeout so the test does not wait too long
+        self.patch(config.Scheduling.Options, "UIDLockTimeoutSeconds", 1)
+        lock = MemcacheLock("ImplicitUIDLock", "deadlocked", timeout=60, expire_time=60)
+        yield lock.acquire()
+        
+        response = (yield self.send(request))
+        self.assertEqual(response.code, responsecode.CONFLICT)

Modified: CalendarServer/trunk/twistedcaldav/test/util.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/util.py	2011-12-08 15:48:47 UTC (rev 8416)
+++ CalendarServer/trunk/twistedcaldav/test/util.py	2011-12-08 20:32:30 UTC (rev 8417)
@@ -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.
@@ -116,19 +116,19 @@
         """
 
         # Need a data store
-        _newStore = self.createDataStore()
+        self._newStore = self.createDataStore()
 
         self.calendarCollection = DirectoryCalendarHomeProvisioningResource(
             self.directoryService,
             "/calendars/",
-            _newStore
+            self._newStore
         )
         self.site.resource.putChild("calendars", self.calendarCollection)
 
         self.addressbookCollection = DirectoryAddressBookHomeProvisioningResource(
             self.directoryService,
             "/addressbooks/",
-            _newStore
+            self._newStore
         )
         self.site.resource.putChild("addressbooks", self.addressbookCollection)
 
@@ -160,6 +160,7 @@
         config.Memcached.Pools.Default.ServerEnabled = False
         ClientFactory.allowTestCache = True
         memcacher.Memcacher.allowTestCache = True
+        memcacher.Memcacher.memoryCacheInstance = None
 
         config.DirectoryAddressBook.Enabled = False
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20111208/3d5bc6e9/attachment-0001.html>


More information about the calendarserver-changes mailing list