[CalendarServer-changes] [6405] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Wed Oct 6 13:31:13 PDT 2010


Revision: 6405
          http://trac.macosforge.org/projects/calendarserver/changeset/6405
Author:   cdaboo at apple.com
Date:     2010-10-06 13:31:12 -0700 (Wed, 06 Oct 2010)
Log Message:
-----------
Handle depth:infinity sync with sharing.

Modified Paths:
--------------
    CalendarServer/trunk/twext/web2/dav/resource.py
    CalendarServer/trunk/twistedcaldav/method/report_sync_collection.py
    CalendarServer/trunk/twistedcaldav/resource.py
    CalendarServer/trunk/twistedcaldav/storebridge.py
    CalendarServer/trunk/txdav/common/datastore/sql.py
    CalendarServer/trunk/txdav/common/datastore/sql_legacy.py

Modified: CalendarServer/trunk/twext/web2/dav/resource.py
===================================================================
--- CalendarServer/trunk/twext/web2/dav/resource.py	2010-10-06 20:25:51 UTC (rev 6404)
+++ CalendarServer/trunk/twext/web2/dav/resource.py	2010-10-06 20:31:12 UTC (rev 6405)
@@ -719,6 +719,7 @@
         # First find all depth 1 children
         names1= []
         namesDeep = []
+        collections1 = []
         if names:
             for name in names:
                 (names1 if name.rstrip("/").find("/") == -1 else namesDeep).append(name.rstrip("/"))
@@ -730,10 +731,12 @@
         basepath = request.urlForResource(self)
         childnames = list(self.listChildren())
         for childname in childnames:
-            if names1 and childname not in names1:
-                continue
             childpath = joinURL(basepath, urllib.quote(childname))
             child = (yield request.locateChildResource(self, childname))
+            if child.isCollection():
+                collections1.append((child, childpath + "/"))
+            if names and childname not in names1:
+                continue
             if child is None:
                 children.append((None, childpath + "/"))
             else:
@@ -756,7 +759,6 @@
 
         # Now determine whether each ace satisfies privileges
         #print aclmap
-        allowed_collections = []
         for items in aclmap.itervalues():
             checked = (yield self.checkACLPrivilege(
                 request, items[0], items[1], privileges, inherited_aces
@@ -765,8 +767,6 @@
                 for resource, url in items[2]:
                     if okcallback:
                         okcallback(resource, url)
-                    if resource.isCollection():
-                        allowed_collections.append((resource, url))
             else:
                 if badcallback:
                     for resource, url in items[2]:
@@ -779,15 +779,15 @@
                 collection, name = name.split("/", 1)
                 child_collections.setdefault(collection, []).append(name)
 
-            for collection, url in allowed_collections:
-                collection_name = collection.name()
+            for collection, url in collections1:
+                collection_name = url.split("/")[-2]
                 if collection_name in child_collections:
                     collection_inherited_aces = (
                         yield collection.inheritedACEsforChildren(request)
                     )
                     yield collection.findChildrenFaster(
                         depth, request, okcallback, badcallback,
-                        child_collections[collection_name], privileges,
+                        child_collections[collection_name] if names else None, privileges,
                         inherited_aces=collection_inherited_aces
                     )
                 

Modified: CalendarServer/trunk/twistedcaldav/method/report_sync_collection.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/report_sync_collection.py	2010-10-06 20:25:51 UTC (rev 6404)
+++ CalendarServer/trunk/twistedcaldav/method/report_sync_collection.py	2010-10-06 20:31:12 UTC (rev 6405)
@@ -106,7 +106,7 @@
     # the child resource loop and supply those to the checkPrivileges on each child.
     filteredaces = (yield self.inheritedACEsforChildren(request))
 
-    changed, removed, newtoken = self.whatchanged(sync_collection.sync_token, depth)
+    changed, removed, notallowed, newtoken = self.whatchanged(sync_collection.sync_token, depth)
 
     # Now determine which valid resources are readable and which are not
     ok_resources = []
@@ -146,6 +146,10 @@
         href = davxml.HRef.fromString(joinURL(request.uri, name))
         responses.append(davxml.StatusResponse(davxml.HRef.fromString(href), davxml.Status.fromResponseCode(responsecode.NOT_FOUND)))
     
+    for name in notallowed:
+        href = davxml.HRef.fromString(joinURL(request.uri, name))
+        responses.append(davxml.StatusResponse(davxml.HRef.fromString(href), davxml.Status.fromResponseCode(responsecode.NOT_ALLOWED)))
+    
     if not hasattr(request, "extendedLogItems"):
         request.extendedLogItems = {}
     request.extendedLogItems["responses"] = len(responses)

Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py	2010-10-06 20:25:51 UTC (rev 6404)
+++ CalendarServer/trunk/twistedcaldav/resource.py	2010-10-06 20:31:12 UTC (rev 6405)
@@ -1342,11 +1342,11 @@
             revision = 0
 
         try:
-            changed, removed = self._indexWhatChanged(revision, depth)
+            changed, removed, notallowed = self._indexWhatChanged(revision, depth)
         except SyncTokenValidException:
             raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (dav_namespace, "valid-sync-token")))
 
-        return changed, removed, current_token
+        return changed, removed, notallowed, current_token
 
     def _indexWhatChanged(self, revision, depth):
         # Now handled directly by newstore
@@ -2189,14 +2189,17 @@
             result.append(davxml.Report(SyncCollection(),))
         return result
 
-    def _indexWhatChanged(self, revision, depth):
-        # The newstore implementation supports this directly
-        return self._newStoreHome.resourceNamesSinceToken(revision, depth)
+    def _mergeSyncTokens(self, hometoken, notificationtoken):
+        """
+        Merge two sync tokens, choosing the higher revision number of the two, but keeping
+        the home resource-id intact.
+        """
+        homekey, homerev = hometoken.split("#", 1)
+        notrev = notificationtoken.split("#", 1)[1]
+        if int(notrev) > int(homerev):
+            hometoken = "%s#%s" % (homekey, notrev,)
+        return hometoken
 
-    def getSyncToken(self):
-        # The newstore implementation supports this directly
-        return self._newStoreHome.syncToken()
-
     def canShare(self):
         raise NotImplementedError
 
@@ -2522,6 +2525,47 @@
 
         return davxml.ACL(*aces)
 
+    def getSyncToken(self):
+        # The newstore implementation supports this directly
+        caltoken = self._newStoreHome.syncToken()
+
+        if config.Sharing.Enabled and config.Sharing.Calendars.Enabled:
+            notificationtoken = self.getChild("notification").getSyncToken()
+            
+            # Merge tokens
+            caltoken = self._mergeSyncTokens(caltoken, notificationtoken)
+            
+        return caltoken
+
+    def _indexWhatChanged(self, revision, depth):
+        # The newstore implementation supports this directly
+        changed, deleted = self._newStoreHome.resourceNamesSinceToken(revision, depth)
+        notallowed = []
+
+        # Need to insert some addition items on first sync
+        if revision == 0:
+            changed.append("outbox/")
+
+            if config.FreeBusyURL.Enabled:
+                changed.append("freebusy")
+    
+            if config.Sharing.Enabled and config.Sharing.Calendars.Enabled:
+                changed.append("notification/")
+        
+            # Dropbox is never synchronized
+            if config.EnableDropBox:
+                notallowed.append("dropbox/")
+    
+        # Add in notification changes
+        if config.Sharing.Enabled and config.Sharing.Calendars.Enabled:
+            noti_changed, noti_deleted, noti_notallowed = self.getChild("notification")._indexWhatChanged(revision, depth)
+
+            changed.extend([joinURL("notification", name) for name in noti_changed])
+            deleted.extend([joinURL("notification", name) for name in noti_deleted])
+            notallowed.extend([joinURL("notification", name) for name in noti_notallowed])
+
+        return changed, deleted, notallowed
+
 class AddressBookHomeResource (CommonHomeResource):
     """
     Address book home collection resource.
@@ -2576,6 +2620,41 @@
         return similar
 
 
+    def getSyncToken(self):
+        # The newstore implementation supports this directly
+        adbktoken = self._newStoreHome.syncToken()
+
+        if config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled and not config.Sharing.Calendars.Enabled:
+            notifcationtoken = self.getChild("notification").getSyncToken()
+            
+            # Merge tokens
+            adbkkey, adbkrev = adbktoken.split("#", 1)
+            notrev = notifcationtoken.split("#", 1)[1]
+            if int(notrev) > int(adbkrev):
+                adbktoken = "%s#%s" % (adbkkey, notrev,)
+            
+        return adbktoken
+
+    def _indexWhatChanged(self, revision, depth):
+        # The newstore implementation supports this directly
+        changed, deleted = self._newStoreHome.resourceNamesSinceToken(revision, depth)
+        notallowed = []
+
+        # Need to insert some addition items on first sync
+        if revision == 0:
+            if config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled and not config.Sharing.Calendars.Enabled:
+                changed.append("notification/")
+        
+        # Add in notification changes
+        if config.Sharing.Enabled and config.Sharing.AddressBooks.Enabled and not config.Sharing.Calendars.Enabled:
+            noti_changed, noti_deleted, noti_notallowed = self.getChild("notification")._indexWhatChanged(revision, depth)
+
+            changed.extend([joinURL("notification", name) for name in noti_changed])
+            deleted.extend([joinURL("notification", name) for name in noti_deleted])
+            notallowed.extend([joinURL("notification", name) for name in noti_notallowed])
+
+        return changed, deleted, notallowed
+
 class GlobalAddressBookResource (ReadOnlyResourceMixIn, CalDAVResource):
     """
     Global address book. All we care about is making sure permissions are setup.

Modified: CalendarServer/trunk/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/storebridge.py	2010-10-06 20:25:51 UTC (rev 6404)
+++ CalendarServer/trunk/twistedcaldav/storebridge.py	2010-10-06 20:31:12 UTC (rev 6405)
@@ -243,7 +243,7 @@
 
     def _indexWhatChanged(self, revision, depth):
         # The newstore implementation supports this directly
-        return self._newStoreCalendar.resourceNamesSinceToken(revision)
+        return self._newStoreCalendar.resourceNamesSinceToken(revision) + ([],)
 
     @classmethod
     def transform(cls, self, calendar, home):
@@ -1279,7 +1279,7 @@
 
     def _indexWhatChanged(self, revision, depth):
         # The newstore implementation supports this directly
-        return self._newStoreAddressBook.resourceNamesSinceToken(revision)
+        return self._newStoreAddressBook.resourceNamesSinceToken(revision) + ([],)
 
     @classmethod
     def transform(cls, self, addressbook, home):
@@ -1852,6 +1852,9 @@
         self._initializeWithNotifications(notifications, home)
 
 
+    def name(self):
+        return "notification"
+
     def listChildren(self):
         l = []
         for notification in self._newStoreNotifications.notificationObjects():
@@ -1865,7 +1868,7 @@
         return self._newStoreNotifications.syncToken()
 
     def _indexWhatChanged(self, revision, depth):
-        return self._newStoreNotifications.resourceNamesSinceToken(revision)
+        return self._newStoreNotifications.resourceNamesSinceToken(revision) + ([],)
 
     def addNotification(self, request, uid, xmltype, xmldata):
 

Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py	2010-10-06 20:25:51 UTC (rev 6404)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py	2010-10-06 20:31:12 UTC (rev 6405)
@@ -299,6 +299,7 @@
         self._resourceID = resourceID
         self._shares = None
         self._children = {}
+        self._sharedChildren = {}
         self._notifier = notifier
 
         # Needed for REVISION/BIND table join
@@ -350,15 +351,44 @@
 
         @return: an iterable of C{str}s.
         """
+        return self._listChildren(owned=True)
+
+    def listSharedChildren(self):
+        """
+        Retrieve the names of the children in this home.
+
+        @return: an iterable of C{str}s.
+        """
+        return self._listChildren(owned=False)
+
+    def _listChildren(self, owned):
+        """
+        Retrieve the names of the children in this home.
+
+        @return: an iterable of C{str}s.
+        """
         # FIXME: not specified on the interface or exercised by the tests, but
         # required by clients of the implementation!
-        rows = self._txn.execSQL(
-            "select %(column_RESOURCE_NAME)s from %(name)s where "
-            "%(column_HOME_RESOURCE_ID)s = %%s "
-            "and %(column_BIND_MODE)s = %%s " % self._bindTable,
-            # Right now, we only show owned calendars.
-            [self._resourceID, _BIND_MODE_OWN]
-        )
+        if owned:
+            rows = self._txn.execSQL("""
+                select %(column_RESOURCE_NAME)s from %(name)s
+                where
+                  %(column_HOME_RESOURCE_ID)s = %%s and
+                  %(column_BIND_MODE)s = %%s
+                """ % self._bindTable,
+                [self._resourceID, _BIND_MODE_OWN]
+            )
+        else:
+            rows = self._txn.execSQL("""
+                select %(column_RESOURCE_NAME)s from %(name)s
+                where
+                  %(column_HOME_RESOURCE_ID)s = %%s and
+                  %(column_BIND_MODE)s != %%s and
+                  %(column_RESOURCE_NAME)s is not null
+                """ % self._bindTable,
+                [self._resourceID, _BIND_MODE_OWN]
+            )
+
         names = [row[0] for row in rows]
         return names
 
@@ -373,12 +403,65 @@
         @return: an L{ICalendar} or C{None} if no such child
             exists.
         """
-        data = self._txn.execSQL(
-            "select %(column_RESOURCE_ID)s from %(name)s where "
-            "%(column_RESOURCE_NAME)s = %%s and %(column_HOME_RESOURCE_ID)s = %%s "
-            "and %(column_BIND_MODE)s = %%s" % self._bindTable,
-            [name, self._resourceID, _BIND_MODE_OWN]
-        )
+        return self._childWithName(name, owned=True)
+
+    @memoized('name', '_sharedChildren')
+    def sharedChildWithName(self, name):
+        """
+        Retrieve the shared child with the given C{name} contained in this
+        home. Return a child object with this home and the name.
+
+        IMPORTANT: take care when using this. Shared calendars should normally
+        be accessed through the owner home collection, not the sharee home collection.
+        The only reason for access through sharee home is to do some housekeeping
+        for maintaining the revisions database to show shared calendars appearing and
+        disappearing in the sharee home.
+
+        @param name: a string.
+        @return: an L{ICalendar} or C{None} if no such child
+            exists.
+        """
+        return self._childWithName(name, owned=False)
+
+    def _childWithName(self, name, owned):
+        """
+        Retrieve the child with the given C{name} contained in this
+        home.
+
+        @param name: a string.
+        @return: an L{ICalendar} or C{None} if no such child
+            exists.
+        """
+        
+        if owned:
+            data = self._txn.execSQL("""
+                select %(column_RESOURCE_ID)s from %(name)s
+                where
+                  %(column_RESOURCE_NAME)s = %%s and
+                  %(column_HOME_RESOURCE_ID)s = %%s and
+                  %(column_BIND_MODE)s = %%s
+                """ % self._bindTable,
+                [
+                    name,
+                    self._resourceID,
+                    _BIND_MODE_OWN
+                ]
+            )
+        else:
+            data = self._txn.execSQL("""
+                select %(column_RESOURCE_ID)s from %(name)s
+                where
+                  %(column_RESOURCE_NAME)s = %%s and
+                  %(column_HOME_RESOURCE_ID)s = %%s and
+                  %(column_BIND_MODE)s != %%s
+                """ % self._bindTable,
+                [
+                    name,
+                    self._resourceID,
+                    _BIND_MODE_OWN
+                ]
+            )
+
         if not data:
             return None
         resourceID = data[0][0]
@@ -389,7 +472,6 @@
             notifier = None
         return self._childClass(self, name, resourceID, notifier)
 
-
     def createChildWithName(self, name):
         if name.startswith("."):
             raise HomeChildNameNotAllowedError(name)
@@ -456,33 +538,46 @@
     def syncToken(self):
         revision = self._txn.execSQL(
             """
-            select max(%(column_REVISION)s) from %(name)s
-            where %(column_HOME_RESOURCE_ID)s = %%s
-            """ % self._revisionsTable,
-            [self._resourceID,]
+            select max(%(REV:column_REVISION)s) from %(REV:name)s
+            where %(REV:column_RESOURCE_ID)s in (
+              select %(BIND:column_RESOURCE_ID)s from %(BIND:name)s 
+              where %(BIND:column_HOME_RESOURCE_ID)s = %%s
+            ) or (
+              %(REV:column_HOME_RESOURCE_ID)s = %%s and
+              %(REV:column_RESOURCE_ID)s is null
+            )
+            """ % self._revisionBindJoinTable,
+            [self._resourceID, self._resourceID,]
         )[0][0]
         return "%s#%s" % (self._resourceID, revision)
 
     def resourceNamesSinceToken(self, token, depth):
+
         results = [
             (
                 path if path else (collection if collection else ""),
                 name if name else "",
-                deleted
+                wasdeleted
             )
-            for path, collection, name, deleted in
+            for path, collection, name, wasdeleted in
             self._txn.execSQL("""
                 select %(BIND:column_RESOURCE_NAME)s, %(REV:column_COLLECTION_NAME)s, %(REV:column_RESOURCE_NAME)s, %(REV:column_DELETED)s
                 from %(REV:name)s
-                left outer join %(BIND:name)s on (%(REV:name)s.%(REV:column_RESOURCE_ID)s = %(BIND:name)s.%(BIND:column_RESOURCE_ID)s)
-                where %(REV:column_REVISION)s > %%s and %(REV:name)s.%(REV:column_HOME_RESOURCE_ID)s = %%s
+                left outer join %(BIND:name)s on (
+                  %(BIND:name)s.%(BIND:column_HOME_RESOURCE_ID)s = %%s and
+                  %(REV:name)s.%(REV:column_RESOURCE_ID)s = %(BIND:name)s.%(BIND:column_RESOURCE_ID)s
+                )
+                where 
+                  %(REV:column_REVISION)s > %%s and 
+                  %(REV:name)s.%(REV:column_HOME_RESOURCE_ID)s = %%s
                 """ % self._revisionBindJoinTable,
-                [token, self._resourceID],
+                [self._resourceID, token, self._resourceID],
             )
         ]
         
         deleted = []
         deleted_collections = set()
+        changed_collections = set()
         for path, name, wasdeleted in results:
             if wasdeleted:
                 if token:
@@ -494,7 +589,51 @@
         for path, name, wasdeleted in results:
             if path not in deleted_collections:
                 changed.append("%s/%s" % (path, name,))
+                if not name:
+                    changed_collections.add(path)
         
+        # Now deal with shared collections
+        shares = self.listSharedChildren()
+        for sharename in shares:
+            sharetoken = 0 if sharename in changed_collections else token
+            shareID = self._txn.execSQL("""
+                select %(column_RESOURCE_ID)s from %(name)s
+                where
+                  %(column_RESOURCE_NAME)s = %%s and
+                  %(column_HOME_RESOURCE_ID)s = %%s and
+                  %(column_BIND_MODE)s != %%s
+                """ % self._bindTable,
+                [
+                    sharename,
+                    self._resourceID,
+                    _BIND_MODE_OWN
+                ]
+            )[0][0]
+            results = [
+                (
+                    sharename,
+                    name if name else "",
+                    wasdeleted
+                )
+                for name, wasdeleted in
+                self._txn.execSQL("""
+                    select %(column_RESOURCE_NAME)s, %(column_DELETED)s
+                    from %(name)s
+                    where %(column_REVISION)s > %%s and %(column_RESOURCE_ID)s = %%s
+                    """ % self._revisionsTable,
+                    [sharetoken, shareID],
+                ) if name
+            ]
+
+            for path, name, wasdeleted in results:
+                if wasdeleted:
+                    if sharetoken:
+                        deleted.append("%s/%s" % (path, name,))
+            
+            for path, name, wasdeleted in results:
+                changed.append("%s/%s" % (path, name,))
+        
+        
         changed.sort()
         deleted.sort()
         return changed, deleted,
@@ -712,11 +851,20 @@
     def syncToken(self):
         revision = self._txn.execSQL(
             """
-            select %(column_REVISION)s from %(name)s
-            where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
+            select max(%(column_REVISION)s) from %(name)s
+            where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is not null
             """ % self._revisionsTable,
             [self._resourceID,]
         )[0][0]
+        if revision is None:
+            revision = self._txn.execSQL(
+                """
+                select %(column_REVISION)s from %(name)s
+                where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
+                """ % self._revisionsTable,
+                [self._resourceID,]
+            )[0][0]
+            
         return "%s#%s" % (self._resourceID, revision,)
 
     def objectResourcesSinceToken(self, token):
@@ -796,7 +944,8 @@
             [self._home._resourceID, self._resourceID,]
         )
         
-        # Then adjust collection entry to deleted state
+        # Then adjust collection entry to deleted state (do this for all entries with this collection's
+        # resource-id so that we deal with direct shares which are not normally removed thorugh an unshare
         self._txn.execSQL("""
             update %(name)s
             set (%(column_RESOURCE_ID)s, %(column_REVISION)s, %(column_DELETED)s)
@@ -830,13 +979,6 @@
                 """ % self._revisionsTable,
                 [nextrevision, self._resourceID, name]
             )
-            self._txn.execSQL("""
-                update %(name)s
-                set (%(column_REVISION)s) = (%%s)
-                where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
-                """ % self._revisionsTable,
-                [nextrevision, self._resourceID,]
-            )
         elif action == "update":
             self._txn.execSQL("""
                 update %(name)s
@@ -845,13 +987,6 @@
                 """ % self._revisionsTable,
                 [nextrevision, self._resourceID, name]
             )
-            self._txn.execSQL("""
-                update %(name)s
-                set (%(column_REVISION)s) = (%%s)
-                where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
-                """ % self._revisionsTable,
-                [nextrevision, self._resourceID,]
-            )
         elif action == "insert":
             # Note that an "insert" may happen for a resource that previously existed and then
             # was deleted. In that case an entry in the REVISIONS table still exists so we have to
@@ -880,13 +1015,6 @@
                     """ % self._revisionsTable,
                     [self._home._resourceID, self._resourceID, name, nextrevision]
                 )
-            self._txn.execSQL("""
-                update %(name)s
-                set (%(column_REVISION)s) = (%%s)
-                where %(column_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
-                """ % self._revisionsTable,
-                [nextrevision, self._resourceID,]
-            )
 
     @cached
     def properties(self):
@@ -1153,11 +1281,20 @@
     def syncToken(self):
         revision = self._txn.execSQL(
             """
-            select %(column_REVISION)s from %(name)s
-            where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
+            select max(%(column_REVISION)s) from %(name)s
+            where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is not null
             """ % self._revisionsTable,
             [self._resourceID,]
         )[0][0]
+        if revision is None:
+            revision = self._txn.execSQL(
+                """
+                select %(column_REVISION)s from %(name)s
+                where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
+                """ % self._revisionsTable,
+                [self._resourceID,]
+            )[0][0]
+
         return "%s#%s" % (self._resourceID, revision,)
 
     def objectResourcesSinceToken(self, token):
@@ -1230,13 +1367,6 @@
                 """ % self._revisionsTable,
                 [nextrevision, self._resourceID, name]
             )
-            self._txn.execSQL("""
-                update %(name)s
-                set (%(column_REVISION)s) = (%%s)
-                where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
-                """ % self._revisionsTable,
-                [nextrevision, self._resourceID]
-            )
         elif action == "update":
             self._txn.execSQL("""
                 update %(name)s
@@ -1245,13 +1375,6 @@
                 """ % self._revisionsTable,
                 [nextrevision, self._resourceID, name]
             )
-            self._txn.execSQL("""
-                update %(name)s
-                set (%(column_REVISION)s) = (%%s)
-                where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
-                """ % self._revisionsTable,
-                [nextrevision, self._resourceID]
-            )
         elif action == "insert":
             # Note that an "insert" may happen for a resource that previously existed and then
             # was deleted. In that case an entry in the REVISIONS table still exists so we have to
@@ -1280,13 +1403,6 @@
                     """ % self._revisionsTable,
                     [self._resourceID, name, nextrevision]
                 )
-            self._txn.execSQL("""
-                update %(name)s
-                set (%(column_REVISION)s) = (%%s)
-                where %(column_HOME_RESOURCE_ID)s = %%s and %(column_RESOURCE_NAME)s is null
-                """ % self._revisionsTable,
-                [nextrevision, self._resourceID]
-            )
 
     @cached
     def properties(self):

Modified: CalendarServer/trunk/txdav/common/datastore/sql_legacy.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql_legacy.py	2010-10-06 20:25:51 UTC (rev 6404)
+++ CalendarServer/trunk/txdav/common/datastore/sql_legacy.py	2010-10-06 20:31:12 UTC (rev 6405)
@@ -539,8 +539,16 @@
                     True,
                     record.summary,
                 ])
+            
+        shareeCollection = self._home.sharedChildWithName(record.localname)
+        shareeCollection._initSyncToken()
 
     def removeRecordForLocalName(self, localname):
+        
+        record = self.recordForLocalName(localname)
+        shareeCollection = self._home.sharedChildWithName(record.localname)
+        shareeCollection._deletedSyncToken()
+        
         self._txn.execSQL(
             """
             update %(name)s
@@ -553,6 +561,11 @@
 
 
     def removeRecordForShareUID(self, shareUID):
+
+        record = self.recordForShareUID(shareUID)
+        shareeCollection = self._home.sharedChildWithName(record.localname)
+        shareeCollection._deletedSyncToken()
+        
         if not shareUID.startswith("Direct"):
             self._txn.execSQL(
                 """
@@ -578,8 +591,8 @@
                 """ % self._bindTable,
                 [homeID, resourceID,]
             )
-            
 
+
 class SQLLegacyCalendarShares(SQLLegacyShares):
     """
     Emulator for the implicit interface specified by
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20101006/cc637e1a/attachment-0001.html>


More information about the calendarserver-changes mailing list