[CalendarServer-changes] [10877] CalendarServer/branches/users/gaya/sharedgroups

source_changes at macosforge.org source_changes at macosforge.org
Fri Mar 8 17:28:52 PST 2013


Revision: 10877
          http://trac.calendarserver.org//changeset/10877
Author:   gaya at apple.com
Date:     2013-03-08 17:28:52 -0800 (Fri, 08 Mar 2013)
Log Message:
-----------
fixes to make revision and created/modified work with owned address book

Modified Paths:
--------------
    CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/test/test_purge.py
    CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/storebridge.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py
    CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql

Modified: CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/test/test_purge.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/test/test_purge.py	2013-03-08 21:17:39 UTC (rev 10876)
+++ CalendarServer/branches/users/gaya/sharedgroups/calendarserver/tools/test/test_purge.py	2013-03-09 01:28:52 UTC (rev 10877)
@@ -842,8 +842,8 @@
         # Share calendars each way
         home2 = (yield txn.calendarHomeWithUID(self.uid2))
         calendar2 = (yield home2.calendarWithName("calendar2"))
-        self.sharedName = yield calendar2.shareWith(home, _BIND_MODE_WRITE)
-        self.sharedName2 = yield calendar.shareWith(home2, _BIND_MODE_WRITE)
+        self.sharedName = (yield calendar2.shareWith(home, _BIND_MODE_WRITE))
+        self.sharedName2 = (yield calendar.shareWith(home2, _BIND_MODE_WRITE))
 
         (yield txn.commit())
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/storebridge.py	2013-03-08 21:17:39 UTC (rev 10876)
+++ CalendarServer/branches/users/gaya/sharedgroups/twistedcaldav/storebridge.py	2013-03-09 01:28:52 UTC (rev 10877)
@@ -2773,11 +2773,9 @@
 
 
     def isAddressBookCollection(self):
-        """
-        Yes, it is a calendar collection.
-        """
         return True
 
+
     createAddressBookCollection = _CommonHomeChildCollectionMixin.createCollection
 
 
@@ -2816,54 +2814,6 @@
         returnValue(storer.returndata if hasattr(storer, "returndata") else None)
 
 
-    @inlineCallbacks
-    def storeRemove(self, request, viaRequest, where):
-        """
-        Delete this collection resource, first deleting each contained
-        object resource.
-
-        This has to emulate the behavior in fileop.delete in that any errors
-        need to be reported back in a multistatus response.
-
-        @param request: The request used to locate child resources.  Note that
-            this is the request which I{triggered} the C{DELETE}, but which may
-            not actually be a C{DELETE} request itself.
-
-        @type request: L{twext.web2.iweb.IRequest}
-
-        @param viaRequest: Indicates if the delete was a direct result of an http_DELETE
-        which for calendars at least will require implicit cancels to be sent.
-
-        @type request: C{bool}
-
-        @param where: the URI at which the resource is being deleted.
-        @type where: C{str}
-
-        @return: an HTTP response suitable for sending to a client (or
-            including in a multi-status).
-
-        @rtype: something adaptable to L{twext.web2.iweb.IResponse}
-        """
-
-        # Not allowed to delete the default address book
-        default = (yield self.isDefaultAddressBook(request))
-        if default:
-            log.err("Cannot DELETE default address book: %s" % (self,))
-            raise HTTPError(ErrorResponse(
-                FORBIDDEN,
-                (carddav_namespace, "default-addressbook-delete-allowed",),
-                "Cannot delete default address book",
-            ))
-
-        response = (
-            yield super(AddressBookCollectionResource, self).storeRemove(
-                request, viaRequest, where
-            )
-        )
-
-        returnValue(response)
-
-
     def http_MOVE(self, request):
         """
         Addressbooks may not be renamed.
@@ -2925,9 +2875,15 @@
         if wasShared:
             yield self.downgradeFromShare(request)
 
-        returnValue((yield super(AddressBookObjectResource, self).storeRemove(request, viaRequest, where)))
+        response = (
+            yield super(AddressBookObjectResource, self).storeRemove(
+                request, viaRequest, where
+            )
+        )
 
+        returnValue(response)
 
+
     @inlineCallbacks
     def http_PUT(self, request):
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py	2013-03-08 21:17:39 UTC (rev 10876)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/carddav/datastore/sql.py	2013-03-09 01:28:52 UTC (rev 10877)
@@ -131,7 +131,7 @@
                     # Cache the data
                     yield queryCacher.setAfterCommit(self._txn, cacheKey, data)
 
-            self._created, self._modified = data
+            #self._created, self._modified = data
             yield self._loadPropertyStore()
 
             # created owned address book
@@ -140,6 +140,7 @@
                 name="addressbook", resourceID=self._resourceID,
                 mode=_BIND_MODE_OWN, status=_BIND_STATUS_ACCEPTED,
             )
+            self._created, self._modified = data
             yield addressbook._loadPropertyStore()
             addressbook.properties()[
                 PropertyName.fromElement(ResourceType)
@@ -280,65 +281,26 @@
         self._bindName = bindName
 
 
-        def getCreated():
-            if self._resourceID == self._home._resourceID:
-                return self._home.created()
-            else:
-                return self._created
-
-
-        def setCreated(newValue):
-            if self._resourceID == self._home._resourceID:
-                self._home._created = newValue
-            else:
-                self._created = newValue
-
-
-        def getModified():
-            if self._resourceID == self._home._resourceID:
-                return self._home.created()
-            else:
-                return self._modified
-
-
-        def setModified(newValue):
-            if self._resourceID == self._home._resourceID:
-                self._home._modified = newValue
-            else:
-                self._modified = newValue
-
-        _created = property(self.getCreated, self.setCreated,)
-        _modified = property(self.getModified, self.setModified,)
-
-
     def getCreated(self):
-        if self._resourceID == self._home._resourceID:
-            return self._home.created()
-        else:
-            return self._created
+        return self.ownerHome()._created
 
 
     def setCreated(self, newValue):
-        if self._resourceID == self._home._resourceID:
-            self._home._created = newValue
-        else:
-            self._created = newValue
+        self.ownerHome()._created = newValue
 
 
     def getModified(self):
-        if self._resourceID == self._home._resourceID:
-            return self._home.created()
-        else:
-            return self._modified
+        return self.ownerHome()._modified
 
 
     def setModified(self, newValue):
-        if self._resourceID == self._home._resourceID:
-            self._home._modified = newValue
-        else:
-            self._modified = newValue
+        self.ownerHome()._modified = newValue
 
 
+    _created = property(getCreated, setCreated,)
+    _modified = property(getModified, setModified,)
+
+
     @property
     def _addressbookHome(self):
         return self._home
@@ -403,12 +365,17 @@
             # allow remove, as a way to reset the address book to an empty state
             for abo in (yield self.objectResources()):
                 yield self.removeObjectResource(abo)
-            self.unshare()
+
+            yield self.unshare()  # storebridge should already have done this
+            yield self._deletedSyncToken()
+
             self.properties()._removeResource()
-            self._loadPropertyStore()
+            yield self._loadPropertyStore()
             self.properties()[
                 PropertyName.fromElement(ResourceType)
             ] = self.resourceType()
+            yield self.notifyChanged()
+            yield self._home.bumpModified()
         else:
             returnValue((yield super(AddressBook, self).remove()))
 
@@ -530,61 +497,19 @@
 
         returnValue(component)
 
-    '''
-    @classproperty
-    def _metadataByIDQuery(cls): #@NoSelf
-        """
-        DAL query to retrieve created/modified dates based on a resource ID.
-        """
-        child = cls._homeChildMetaDataSchema
-        abo = schema.ADDRESSBOOK_OBJECT
-        return Select(
-            cls.metadataColumns(),
-            From=child,
-            Where=child.RESOURCE_ID == Parameter("resourceID"),
-            SetExpression=Union(
-                Select(
-                    [abo.CREATED, abo.MODIFIED],
-                    From=abo,
-                    Where=abo.RESOURCE_ID == Parameter("resourceID"),
-                    ),
-                optype=Union.OPTYPE_ALL,
-            )
-        )
-    '''
 
-
-    @classproperty
-    def _changeABForSharedGroupLastModifiedQuery(cls): #@NoSelf
-        schema = AddressBookObject._objectSchema
-        return Update({schema.MODIFIED: utcNowSQL},
-                      Where=schema.RESOURCE_ID == Parameter("resourceID"),
-                      Return=schema.MODIFIED)
-
-
     @inlineCallbacks
-    def _bumpModified(self, subtxn):
+    def bumpModified(self):
+        # TODO: The next line seems the next line work too.  Why?
+        # returnValue((yield self.ownerHome().bumpModified()))
+        #
+        if self._resourceID == self._home._resourceID:
+            returnValue((yield self._home.bumpModified()))
+        else:
+            returnValue((yield super(AddressBook, self).bumpModified()))
 
-        yield self._lockLastModifiedQuery.on(
-            subtxn, resourceID=self._resourceID
-        )
 
-        # can't call self.ownerGroup() on a subtranaction,
-        # So just try AB schema first, then ABOBject schema 
-        # The following line makes shared groups faster, but a bit of a hack
-        #if hasattr(self, "_ownerGroup") and not (yield self.ownerGroup()):
-        result = yield self._changeLastModifiedQuery.on(
-            subtxn, resourceID=self._resourceID
-        )
 
-        if not result:
-            result = yield self._changeABForSharedGroupLastModifiedQuery.on(
-                subtxn, resourceID=self._resourceID
-            )
-
-        returnValue(result)
-
-
     @classmethod
     @inlineCallbacks
     def loadAllObjects(cls, home):
@@ -841,39 +766,6 @@
         returnValue(result)
 
 
-    @classproperty
-    def _revisionsForHomeID(cls): #@NoSelf
-
-        def columns(rev):
-            return [rev.RESOURCE_ID, Max(rev.REVISION)]
-
-        def _from(rev, bind):
-            return rev.join(bind, rev.RESOURCE_ID == bind.RESOURCE_ID, 'left')
-
-        def where(rev, bind):
-            return ((bind.HOME_RESOURCE_ID == Parameter("homeID")).
-                And((rev.RESOURCE_NAME != None).Or(rev.DELETED == False)))
-
-        addressbookBind = cls._bindSchema
-        aboBind = AddressBookObject._bindSchema
-        rev = cls._revisionsSchema
-        return Select(
-            columns(rev),
-            From=_from(rev, addressbookBind),
-            Where=where(rev, addressbookBind),
-            GroupBy=rev.RESOURCE_ID,
-            SetExpression=Union(
-                Select(
-                    columns(rev),
-                    From=_from(rev, aboBind),
-                    Where=where(rev, aboBind),
-                    GroupBy=rev.RESOURCE_ID
-                    ),
-                optype=Union.OPTYPE_ALL,
-           ),
-        )
-
-
     def shareUID(self):
         """
         @see: L{ICalendar.shareUID}
@@ -1305,8 +1197,8 @@
     def remove(self):
 
         if self.owned():
-            if self._kind == _ABO_KIND_GROUP: # optimization
-                self.unshare()
+            # storebridge should already have done this
+            yield self.unshare()
         else:
             # Can't delete a share here with notification so raise.
             if self._resourceID == self._addressbook._resourceID:
@@ -1984,9 +1876,8 @@
 
 
 
-    @inlineCallbacks
     def notifyChanged(self):
-        returnValue((yield self._addressbook.notifyChanged()))
+        return self._addressbook.notifyChanged()
 
 
     @inlineCallbacks
@@ -2073,15 +1964,17 @@
         """
         Unshares a group, regardless of which "direction" it was shared.
         """
-        if self.owned():
-            # This collection may be shared to others
-            for sharedToHome in [x.viewerHome() for x in (yield self.asShared())]:
-                yield self.unshareWith(sharedToHome)
-        else:
-            # This collection is shared to me
-            ownerAddressBook = self._addressbook.ownerHome().addressbook()
-            ownerGroup = yield ownerAddressBook.objectResourceWithID(self._resourceID)
-            yield ownerGroup.unshareWith(self._home)
+        if self._kind == _ABO_KIND_GROUP:
+            if self.owned():
+                # This collection may be shared to others
+                for sharedToHome in [x.viewerHome() for x in (yield self.asShared())]:
+                    yield self.unshareWith(sharedToHome)
+            else:
+                # This collection is shared to me
+                ownerAddressBook = self._addressbook.ownerHome().addressbook()
+                ownerGroup = yield ownerAddressBook.objectResourceWithID(self._resourceID)
+                if ownerGroup:
+                    yield ownerGroup.unshareWith(self._home)
 
 
     @inlineCallbacks
@@ -2112,7 +2005,7 @@
                 shareeHome._children.pop(self._addressbook.shareeAddressBookName(), None)
 
             # Must send notification to ensure cache invalidation occurs
-            yield self._addressbook.notifyChanged()
+            yield self.notifyChanged()
 
         # delete binds including invites
         deletedBindNameRows = yield self._deleteBindWithResourceIDAndHomeID.on(
@@ -2214,7 +2107,7 @@
             shareeView._name = sharedname[0][0]
 
             # Must send notification to ensure cache invalidation occurs
-            yield self._addressbook.notifyChanged()
+            yield self.notifyChanged()
 
         returnValue(shareeView._name)
 

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py	2013-03-08 21:17:39 UTC (rev 10876)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py	2013-03-09 01:28:52 UTC (rev 10877)
@@ -2117,6 +2117,7 @@
             Where=(bind.HOME_RESOURCE_ID == Parameter("homeResourceID")).And(bind.BIND_STATUS != _BIND_STATUS_ACCEPTED)
         ).on(self._txn, **kwds)
 
+
     @inlineCallbacks
     def ownerHomeWithChildID(self, resourceID):
         """
@@ -3557,7 +3558,7 @@
         yield child.remove()
         self._objects.pop(name, None)
         self._objects.pop(uid, None)
-        if self._objectNames:
+        if self._objectNames and name in self._objectNames:
             self._objectNames.remove(name)
         yield self._deleteRevision(name)
         yield self.notifyChanged()
@@ -3730,13 +3731,6 @@
 
 
     @inlineCallbacks
-    def _bumpModified(self, subtxn):
-        yield self._lockLastModifiedQuery.on(subtxn, resourceID=self._resourceID)
-        result = (yield self._changeLastModifiedQuery.on(subtxn, resourceID=self._resourceID))
-        returnValue(result)
-
-
-    @inlineCallbacks
     def bumpModified(self):
         """
         Bump the MODIFIED value. A possible deadlock could happen here if two or more
@@ -3750,8 +3744,14 @@
             returnValue(None)
         self._txn.bumpAddedForObject(self)
 
+        @inlineCallbacks
+        def _bumpModified(subtxn):
+            yield self._lockLastModifiedQuery.on(subtxn, resourceID=self._resourceID)
+            result = (yield self._changeLastModifiedQuery.on(subtxn, resourceID=self._resourceID))
+            returnValue(result)
+
         try:
-            self._modified = (yield self._txn.subtransaction(self._bumpModified, retries=0, failureOK=True))[0][0]
+            self._modified = (yield self._txn.subtransaction(_bumpModified, retries=0, failureOK=True))[0][0]
 
             queryCacher = self._txn._queryCacher
             if queryCacher is not None:

Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql
===================================================================
--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql	2013-03-08 21:17:39 UTC (rev 10876)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql_schema/current.sql	2013-03-09 01:28:52 UTC (rev 10877)
@@ -494,7 +494,7 @@
 
 create table ADDRESSBOOK_OBJECT_REVISIONS (
   ADDRESSBOOK_HOME_RESOURCE_ID integer      not null references ADDRESSBOOK_HOME,
-  ADDRESSBOOK_RESOURCE_ID      integer, 	-- FIXME, should reference ADDRESSBOOK_HOME
+  ADDRESSBOOK_RESOURCE_ID      integer      references ADDRESSBOOK_HOME,
   ADDRESSBOOK_NAME             varchar(255) default null,
   RESOURCE_NAME                varchar(255),
   REVISION                     integer      default nextval('REVISION_SEQ') not null,
@@ -546,6 +546,7 @@
 create index APN_SUBSCRIPTIONS_RESOURCE_KEY
    on APN_SUBSCRIPTIONS(RESOURCE_KEY);
 
+   
 -----------------
 -- IMIP Tokens --
 -----------------
@@ -563,12 +564,14 @@
 create index IMIP_TOKENS_TOKEN
    on IMIP_TOKENS(TOKEN);
 
+   
 ----------------
 -- Work Items --
 ----------------
 
 create sequence WORKITEM_SEQ;
 
+
 ---------------------------
 -- IMIP Inivitation Work --
 ---------------------------
@@ -581,6 +584,7 @@
   ICALENDAR_TEXT                text         not null
 );
 
+
 -----------------------
 -- IMIP Polling Work --
 -----------------------
@@ -590,6 +594,7 @@
   NOT_BEFORE                    timestamp    default timezone('UTC', CURRENT_TIMESTAMP)
 );
 
+
 ---------------------
 -- IMIP Reply Work --
 ---------------------
@@ -602,6 +607,7 @@
   ICALENDAR_TEXT                text         not null
 );
 
+
 ------------------------
 -- Push Notifications --
 ------------------------
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130308/d4085f59/attachment-0001.html>


More information about the calendarserver-changes mailing list