[CalendarServer-changes] [9459] CalendarServer/trunk/txdav

source_changes at macosforge.org source_changes at macosforge.org
Tue Jul 17 13:32:22 PDT 2012


Revision: 9459
          http://trac.macosforge.org/projects/calendarserver/changeset/9459
Author:   sagen at apple.com
Date:     2012-07-17 13:32:21 -0700 (Tue, 17 Jul 2012)
Log Message:
-----------
Send push notifications upon DAV property changes

Modified Paths:
--------------
    CalendarServer/trunk/txdav/base/propertystore/sql.py
    CalendarServer/trunk/txdav/caldav/datastore/test/common.py
    CalendarServer/trunk/txdav/carddav/datastore/test/common.py
    CalendarServer/trunk/txdav/common/datastore/file.py
    CalendarServer/trunk/txdav/common/datastore/sql.py

Modified: CalendarServer/trunk/txdav/base/propertystore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/base/propertystore/sql.py	2012-07-17 00:20:24 UTC (rev 9458)
+++ CalendarServer/trunk/txdav/base/propertystore/sql.py	2012-07-17 20:32:21 UTC (rev 9459)
@@ -73,7 +73,11 @@
 
     @classmethod
     @inlineCallbacks
-    def load(cls, defaultuser, txn, resourceID, created=False):
+    def load(cls, defaultuser, txn, resourceID, created=False, notifyCallback=None):
+        """
+        @param notifyCallback: a callable used to trigger notifications when the
+            property store changes.
+        """
         self = cls.__new__(cls)
         super(PropertyStore, self).__init__(defaultuser)
         self._txn = txn
@@ -81,6 +85,7 @@
         self._cached = {}
         if not created:
             yield self._refresh(txn)
+        self._notifyCallback = notifyCallback
         returnValue(self)
 
 
@@ -196,6 +201,11 @@
                     txn, resourceID=self._resourceID, value=value_str,
                     name=key_str, uid=uid)
             self._cacher.delete(str(self._resourceID))
+
+        # Call the registered notification callback
+        if hasattr(self, "_notifyCallback") and self._notifyCallback is not None:
+            self._notifyCallback()
+
         self._txn.subtransaction(trySetItem)
 
 

Modified: CalendarServer/trunk/txdav/caldav/datastore/test/common.py
===================================================================
--- CalendarServer/trunk/txdav/caldav/datastore/test/common.py	2012-07-17 00:20:24 UTC (rev 9458)
+++ CalendarServer/trunk/txdav/caldav/datastore/test/common.py	2012-07-17 20:32:21 UTC (rev 9459)
@@ -717,8 +717,7 @@
         yield self.commit()
 
         # Make sure notification fired after commit
-        self.assertEquals(self.notifierFactory.history,
-            [("update", "CalDAV|home1")])
+        self.assertTrue(("update", "CalDAV|home1") in self.notifierFactory.history)
 
         # Make sure it's available in a new transaction; i.e. test the commit.
         home = yield self.homeUnderTest()

Modified: CalendarServer/trunk/txdav/carddav/datastore/test/common.py
===================================================================
--- CalendarServer/trunk/txdav/carddav/datastore/test/common.py	2012-07-17 00:20:24 UTC (rev 9458)
+++ CalendarServer/trunk/txdav/carddav/datastore/test/common.py	2012-07-17 20:32:21 UTC (rev 9459)
@@ -329,8 +329,7 @@
         yield self.commit()
 
         # Make sure notification fired after commit
-        self.assertEquals(self.notifierFactory.history,
-            [("update", "CardDAV|home1")])
+        self.assertTrue(("update", "CardDAV|home1") in self.notifierFactory.history)
 
         # Make sure it's available in a new transaction; i.e. test the commit.
         home = yield self.homeUnderTest()

Modified: CalendarServer/trunk/txdav/common/datastore/file.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/file.py	2012-07-17 00:20:24 UTC (rev 9458)
+++ CalendarServer/trunk/txdav/common/datastore/file.py	2012-07-17 20:32:21 UTC (rev 9459)
@@ -208,6 +208,7 @@
         self._notificationHomes = {}
         self._notifierFactory = notifierFactory
         self._notifiedAlready = set()
+        self._bumpedAlready = set()
         self._migrating = migrating
 
         extraInterfaces = []
@@ -267,11 +268,28 @@
 
     def isNotifiedAlready(self, obj):
         return obj in self._notifiedAlready
-    
+
     def notificationAddedForObject(self, obj):
         self._notifiedAlready.add(obj)
 
+    def isBumpedAlready(self, obj):
+        """
+        Indicates whether or not bumpAddedForObject has already been
+        called for the given object, in order to facilitate calling
+        bumpModified only once per object.
+        """
+        return obj in self._bumpedAlready
 
+    def bumpAddedForObject(self, obj):
+        """
+        Records the fact that a bumpModified( ) call has already been
+        done, in order to facilitate calling bumpModified only once per
+        object.
+        """
+        self._bumpedAlready.add(obj)
+
+
+
 class StubResource(object):
     """
     Just enough resource to keep the shared sql DB classes going.

Modified: CalendarServer/trunk/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/trunk/txdav/common/datastore/sql.py	2012-07-17 00:20:24 UTC (rev 9458)
+++ CalendarServer/trunk/txdav/common/datastore/sql.py	2012-07-17 20:32:21 UTC (rev 9459)
@@ -321,6 +321,7 @@
         self._postAbortOperations = []
         self._notifierFactory = notifierFactory
         self._notifiedAlready = set()
+        self._bumpedAlready = set()
         self._label = label
         self._migrating = migrating
         self._primaryHomeType = None
@@ -565,10 +566,26 @@
 
     def isNotifiedAlready(self, obj):
         return obj in self._notifiedAlready
-    
+
     def notificationAddedForObject(self, obj):
         self._notifiedAlready.add(obj)
 
+    def isBumpedAlready(self, obj):
+        """
+        Indicates whether or not bumpAddedForObject has already been
+        called for the given object, in order to facilitate calling
+        bumpModified only once per object.
+        """
+        return obj in self._bumpedAlready
+
+    def bumpAddedForObject(self, obj):
+        """
+        Records the fact that a bumpModified( ) call has already been
+        done, in order to facilitate calling bumpModified only once per
+        object.
+        """
+        self._bumpedAlready.add(obj)
+
     _savepointCounter = 0
 
     def _savepoint(self):
@@ -1338,7 +1355,8 @@
         props = yield PropertyStore.load(
             self.uid(),
             self._txn,
-            self._resourceID
+            self._resourceID,
+            notifyCallback=self.notifyChanged
         )
         self._propertyStore = props
 
@@ -1539,6 +1557,10 @@
         delay the transaction whilst waiting for deadlock detection to kick in.
         """
 
+        if self._txn.isBumpedAlready(self):
+            returnValue(None)
+        self._txn.bumpAddedForObject(self)
+
         # NB if modified is bumped we know that sync token will have changed too, so invalidate the cached value
         self._syncTokenRevision = None
 
@@ -1557,13 +1579,13 @@
 
         except AllRetriesFailed:
             log.debug("CommonHome.bumpModified failed")
-        
+
     @inlineCallbacks
     def notifyChanged(self):
         """
         Trigger a notification of a change
         """
-        
+
         # Update modified if object still exists
         if self._resourceID:
             yield self.bumpModified()
@@ -2914,7 +2936,8 @@
             props = yield PropertyStore.load(
                 self.ownerHome().uid(),
                 self._txn,
-                self._resourceID
+                self._resourceID,
+                notifyCallback=self.notifyChanged
             )
         self.initPropertyStore(props)
         self._properties = props
@@ -3003,12 +3026,16 @@
         delay the transaction whilst waiting for deadlock detection to kick in.
         """
 
+        if self._txn.isBumpedAlready(self):
+            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(_bumpModified, retries=0, failureOK=True))[0][0]
 
@@ -3018,13 +3045,13 @@
                 yield queryCacher.invalidateAfterCommit(self._txn, cacheKey)
         except AllRetriesFailed:
             log.debug("CommonHomeChild.bumpModified failed")
-        
+
     @inlineCallbacks
     def notifyChanged(self):
         """
         Trigger a notification of a change
         """
-        
+
         # Update modified if object still exists
         if self._resourceID:
             yield self.bumpModified()
@@ -3036,7 +3063,6 @@
             self._txn.notificationAddedForObject(self)
 
 
-
 class CommonObjectResource(LoggingMixIn, FancyEqMixin):
     """
     Base class for object resources.
@@ -3507,7 +3533,8 @@
         self._propertyStore = yield PropertyStore.load(
             self._uid,
             self._txn,
-            self._resourceID
+            self._resourceID,
+            notifyCallback=self.notifyChanged
         )
 
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120717/cd834f1c/attachment-0001.html>


More information about the calendarserver-changes mailing list