[CalendarServer-changes] [2975] CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Wed Sep 10 20:32:19 PDT 2008


Revision: 2975
          http://trac.macosforge.org/projects/calendarserver/changeset/2975
Author:   cdaboo at apple.com
Date:     2008-09-10 20:32:19 -0700 (Wed, 10 Sep 2008)
Log Message:
-----------
Various fixes for auto-accept behavior including serialization of inbox auto-processing
using a memcache deferred lock.

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/ical.py
    CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/itip.py
    CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/scheduling/icaldiff.py
    CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/scheduling/itip.py

Modified: CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/ical.py
===================================================================
--- CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/ical.py	2008-09-11 03:30:02 UTC (rev 2974)
+++ CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/ical.py	2008-09-11 03:32:19 UTC (rev 2975)
@@ -1349,11 +1349,10 @@
 
         assert self.name() == "VCALENDAR", "Not a calendar: %r" % (self,)
 
-        if self.name() == "VCALENDAR":
-            for component in self.subcomponents():
-                if component.name() == "VTIMEZONE":
-                    continue
-                [component.removeProperty(p) for p in tuple(component.properties("ATTENDEE")) if p.value() != attendee]
+        for component in self.subcomponents():
+            if component.name() == "VTIMEZONE":
+                continue
+            [component.removeProperty(p) for p in tuple(component.properties("ATTENDEE")) if p.value() != attendee]
             
     def removeAlarms(self):
         """
@@ -1377,14 +1376,13 @@
 
         assert self.name() == "VCALENDAR", "Not a calendar: %r" % (self,)
 
-        if self.name() == "VCALENDAR":
-            for component in self.subcomponents():
-                if component.name() == "VTIMEZONE":
-                    continue
-                if keep:
-                    [component.removeProperty(p) for p in tuple(component.properties()) if p.name() not in keep]
-                if remove:
-                    [component.removeProperty(p) for p in tuple(component.properties()) if p.name() in remove]
+        for component in self.subcomponents():
+            if component.name() == "VTIMEZONE":
+                continue
+            if keep:
+                [component.removeProperty(p) for p in tuple(component.properties()) if p.name() not in keep]
+            if remove:
+                [component.removeProperty(p) for p in tuple(component.properties()) if p.name() in remove]
                 
     def removeXProperties(self, keep_properties):
         """
@@ -1393,15 +1391,14 @@
 
         assert self.name() == "VCALENDAR", "Not a calendar: %r" % (self,)
 
-        if self.name() == "VCALENDAR":
-            for component in self.subcomponents():
-                if component.name() == "VTIMEZONE":
-                    continue
-                [
-                    component.removeProperty(p)
-                    for p in tuple(component.properties())
-                    if p.name().startswith("X-") and p.name() not in keep_properties
-                ]
+        for component in self.subcomponents():
+            if component.name() == "VTIMEZONE":
+                continue
+            [
+                component.removeProperty(p)
+                for p in tuple(component.properties())
+                if p.name().startswith("X-") and p.name() not in keep_properties
+            ]
             
     def removePropertyParameters(self, property, params):
         """
@@ -1410,18 +1407,34 @@
 
         assert self.name() == "VCALENDAR", "Not a calendar: %r" % (self,)
 
-        if self.name() == "VCALENDAR":
-            for component in self.subcomponents():
-                if component.name() == "VTIMEZONE":
-                    continue
-                props = component.properties(property)
-                for prop in props:
-                    for param in params:
-                        try:
-                            del prop.params()[param]
-                        except KeyError:
-                            pass
-            
+        for component in self.subcomponents():
+            if component.name() == "VTIMEZONE":
+                continue
+            props = component.properties(property)
+            for prop in props:
+                for param in params:
+                    try:
+                        del prop.params()[param]
+                    except KeyError:
+                        pass
+
+    def normalizePropertyValueLists(self, propname):
+        """
+        Convert properties that have a list of values into single properties, to make it easier
+        to do comparisons between two ical objects.
+        """
+        
+        assert self.name() == "VCALENDAR", "Not a calendar: %r" % (self,)
+
+        for component in self.subcomponents():
+            if component.name() == "VTIMEZONE":
+                continue
+            for prop in tuple(component.properties(propname)):
+                if type(prop.value()) is list and len(prop.value()) > 1:
+                    component.removeProperty(prop)
+                    for value in prop.value():
+                        component.addProperty(Property(propname, [value,]))
+        
 ##
 # Dates and date-times
 ##

Modified: CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/itip.py
===================================================================
--- CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/itip.py	2008-09-11 03:30:02 UTC (rev 2974)
+++ CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/itip.py	2008-09-11 03:32:19 UTC (rev 2975)
@@ -35,7 +35,8 @@
 import time
 
 from twisted.python.failure import Failure
-from twisted.internet.defer import inlineCallbacks, returnValue, maybeDeferred
+from twisted.internet.defer import inlineCallbacks, returnValue, maybeDeferred,\
+    succeed
 from twisted.web2.dav import davxml
 from twisted.web2.dav.method.report import NumberOfMatchesWithinLimits
 from twisted.web2.dav.util import joinURL
@@ -46,6 +47,7 @@
 from twistedcaldav.accounting import accountingEnabled, emitAccounting
 from twistedcaldav.log import Logger
 from twistedcaldav.ical import Property
+from twistedcaldav.memcachelock import MemcacheLock, MemcacheLockTimeoutError
 from twistedcaldav.method import report_common
 from twistedcaldav.resource import isCalendarCollectionResource
 
@@ -63,6 +65,7 @@
 
 class iTipProcessor(object):
     
+    @inlineCallbacks
     def handleRequest(self, request, principal, inbox, calendar, child):
         """
         Handle an iTIP response automatically.
@@ -93,7 +96,19 @@
         else:
             self.childname = ""
  
-        return f()
+        # Get a lock on the inbox first
+        _lock = MemcacheLock("iTIPAutoProcess", inbox.fp.path, timeout=60.0, retry_interval=1.0, expire_time=300)
+        
+        try:
+            yield _lock.acquire()
+            yield f()
+            yield _lock.release()
+        except MemcacheLockTimeoutError:
+            raise
+        except Exception, e:
+            log.error(e)
+            yield _lock.clean()
+            raise
 
     @inlineCallbacks
     def processRequest(self):
@@ -567,9 +582,9 @@
     def deleteInboxResource(self, processed_state):
         # Remove the now processed incoming request.
         try:
+            log.info("Deleting new iTIP message %s in Inbox because it has been %s." %
+                (self.childname, processed_state,))
             yield self.deleteResource(self.inbox, self.childname)
-            log.info("Deleted new iTIP message %s in Inbox because it has been %s." %
-                (self.childname, processed_state,))
         except:
             # FIXME: bare except
             log.err("Error while auto-processing iTIP: %s" % (Failure(),))
@@ -585,6 +600,12 @@
         """
         
         delchild = collection.getChild(name)
+        
+        # Sometimes the resource might already be gone...
+        if delchild is None:
+            log.warn("Nothing to delete: %s in %s is missing." % (name, collection))
+            return succeed(None)
+
         index = collection.index()
         index.deleteResource(delchild.fp.basename())
         

Modified: CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/scheduling/icaldiff.py
===================================================================
--- CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/scheduling/icaldiff.py	2008-09-11 03:30:02 UTC (rev 2974)
+++ CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/scheduling/icaldiff.py	2008-09-11 03:32:19 UTC (rev 2975)
@@ -85,11 +85,13 @@
 
         # Do straight comparison without alarms
         self.calendar1 = self.calendar1.duplicate()
+        self.calendar1.attendeesView((attendee,))
+        self.calendar1.normalizePropertyValueLists("EXDATE")
         self.calendar1.removeXProperties(("X-CALENDARSERVER-PRIVATE-COMMENT",))
-        self.calendar1.attendeesView((attendee,))
         iTipGenerator.prepareSchedulingMessage(self.calendar1)
 
         self.calendar2 = self.calendar2.duplicate()
+        self.calendar2.normalizePropertyValueLists("EXDATE")
         self.calendar2.removeXProperties(("X-CALENDARSERVER-PRIVATE-COMMENT",))
         iTipGenerator.prepareSchedulingMessage(self.calendar2)
 
@@ -100,10 +102,12 @@
         
         # Make sure the same VCALENDAR properties match
         if not self._checkVCALENDARProperties():
+            log.debug("attendeeMerge: VCALENDAR properties do not match")
             return False, False
         
         # Make sure the same VTIMEZONE components appear
         if not self._compareVTIMEZONEs():
+            log.debug("attendeeMerge: VTIMEZONEs do not match")
             return False, False
         
         # Compare each component instance from the new calendar with each derived
@@ -186,6 +190,7 @@
         for key in set2 - set1:
             component1 = self.calendar1.deriveInstance(key[2])
             if component1 is None:
+                log.debug("_compareComponents: Could not derive instance: %s" % (key[2],))
                 return False, False
             component2 = map2[key]
             

Modified: CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/scheduling/itip.py
===================================================================
--- CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/scheduling/itip.py	2008-09-11 03:30:02 UTC (rev 2974)
+++ CalendarServer/branches/users/cdaboo/implicitauto-2947/twistedcaldav/scheduling/itip.py	2008-09-11 03:32:19 UTC (rev 2975)
@@ -376,7 +376,7 @@
                 instance = original.overriddenComponent(instance_rid)
                 if instance is None:
                     instance = original.masterComponent()
-            assert instance is not None
+            assert instance is not None, "Need a master component"
 
             # Add some required properties extracted from the original
             comp.addProperty(Property("DTSTAMP", datetime.datetime.now(tz=utc)))
@@ -404,7 +404,7 @@
             # Extract the matching attendee property
             for attendee in attendees:
                 attendeeProp = instance.getAttendeeProperty((attendee,))
-                assert attendeeProp is not None
+                assert attendeeProp is not None, "Must have matching ATTENDEE property"
                 comp.addProperty(attendeeProp)
 
             tzids.update(comp.timezoneIDs())
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080910/4563f982/attachment-0001.html 


More information about the calendarserver-changes mailing list