[CalendarServer-changes] [9660] CalendarServer/branches/users/glyph/q

source_changes at macosforge.org source_changes at macosforge.org
Sat Aug 11 01:55:32 PDT 2012


Revision: 9660
          http://trac.macosforge.org/projects/calendarserver/changeset/9660
Author:   glyph at apple.com
Date:     2012-08-11 01:55:31 -0700 (Sat, 11 Aug 2012)
Log Message:
-----------
push postCommit/postAbort hooks down into the SQL store.

Modified Paths:
--------------
    CalendarServer/branches/users/glyph/q/twext/enterprise/adbapi2.py
    CalendarServer/branches/users/glyph/q/twext/enterprise/ienterprise.py
    CalendarServer/branches/users/glyph/q/txdav/base/datastore/file.py
    CalendarServer/branches/users/glyph/q/txdav/base/datastore/util.py
    CalendarServer/branches/users/glyph/q/txdav/common/datastore/sql.py
    CalendarServer/branches/users/glyph/q/txdav/idav.py

Property Changed:
----------------
    CalendarServer/branches/users/glyph/q/

Modified: CalendarServer/branches/users/glyph/q/twext/enterprise/adbapi2.py
===================================================================
--- CalendarServer/branches/users/glyph/q/twext/enterprise/adbapi2.py	2012-08-11 08:55:30 UTC (rev 9659)
+++ CalendarServer/branches/users/glyph/q/twext/enterprise/adbapi2.py	2012-08-11 08:55:31 UTC (rev 9660)
@@ -484,7 +484,53 @@
 
 
 
-class _SingleTxn(proxyForInterface(iface=IAsyncTransaction,
+class _HookableOperation(object):
+
+    def __init__(self):
+        self._hooks = []
+
+
+    @inlineCallbacks
+    def runHooks(self, ignored):
+        """
+        Callback for C{commit} and C{abort} Deferreds.
+        """
+        for operation in self._hooks:
+            yield operation()
+        returnValue(ignored)
+
+
+    def addHook(self, operation):
+        """
+        Implement L{IAsyncTransaction.postCommit}.
+        """
+        self._hooks.append(operation)
+
+
+
+class _CommitAndAbortHooks(object):
+    """
+    Shared implementation of post-commit and post-abort hooks.
+    """
+    # FIXME: this functionality needs direct tests, although it's pretty well-
+    # covered by txdav's test suite.
+
+    def __init__(self):
+        self._commit = _HookableOperation()
+        self._abort = _HookableOperation()
+
+
+    def postCommit(self, operation):
+        return self._commit.addHook(operation)
+
+
+    def postAbort(self, operation):
+        return self._abort.addHook(operation)
+
+
+
+class _SingleTxn(_CommitAndAbortHooks,
+                 proxyForInterface(iface=IAsyncTransaction,
                                    originalAttribute='_baseTxn')):
     """
     A L{_SingleTxn} is a single-use wrapper for the longer-lived
@@ -505,6 +551,7 @@
     """
 
     def __init__(self, pool, baseTxn):
+        super(_SingleTxn, self).__init__()
         self._pool           = pool
         self._baseTxn        = baseTxn
         self._completed      = False
@@ -601,9 +648,9 @@
             # We're in the process of executing a block of commands.  Wait until
             # they're done.  (Commit will be repeated in _checkNextBlock.)
             return self._blockedQueue.commit()
-
         self._markComplete()
-        return super(_SingleTxn, self).commit()
+        return (super(_SingleTxn, self).commit()
+                .addCallback(self._commit.runHooks))
 
 
     def abort(self):
@@ -611,6 +658,7 @@
         result = super(_SingleTxn, self).abort()
         if self in self._pool._waiting:
             self._stopWaiting()
+        result.addCallback(self._abort.runHooks)
         return result
 
 
@@ -1432,7 +1480,7 @@
 
 
 
-class _NetTransaction(object):
+class _NetTransaction(_CommitAndAbortHooks):
     """
     A L{_NetTransaction} is an L{AMP}-protocol-based provider of the
     L{IAsyncTransaction} interface.  It sends SQL statements, query results, and
@@ -1446,6 +1494,7 @@
         Initialize a transaction with a L{ConnectionPoolClient} and a unique
         transaction identifier.
         """
+        super(_NetTransaction, self).__init__()
         self._client        = client
         self._transactionID = transactionID
         self._completed     = False
@@ -1503,11 +1552,12 @@
         def done(whatever):
             self._committed = True
             return whatever
-        return self._complete(Commit).addBoth(done)
+        return (self._complete(Commit).addBoth(done)
+                .addCallback(self._commit.runHooks))
 
 
     def abort(self):
-        return self._complete(Abort)
+        return self._complete(Abort).addCallback(self._abort.runHooks)
 
 
     def commandBlock(self):

Modified: CalendarServer/branches/users/glyph/q/twext/enterprise/ienterprise.py
===================================================================
--- CalendarServer/branches/users/glyph/q/twext/enterprise/ienterprise.py	2012-08-11 08:55:30 UTC (rev 9659)
+++ CalendarServer/branches/users/glyph/q/twext/enterprise/ienterprise.py	2012-08-11 08:55:31 UTC (rev 9660)
@@ -103,6 +103,18 @@
         """
 
 
+    def postCommit(operation):
+        """
+        Perform the given operation only after this L{IAsyncTransaction}
+        commits.  These will be invoked before the L{Deferred} returned by
+        L{IAsyncTransaction.commit} fires.
+
+        @param operation: a 0-argument callable that may return a L{Deferred}.
+            If it does, then the subsequent operations added by L{postCommit}
+            will not fire until that L{Deferred} fires.
+        """
+
+
     def abort():
         """
         Roll back changes caused by this transaction.
@@ -112,6 +124,17 @@
         """
 
 
+    def postAbort(operation):
+        """
+        Invoke a callback after abort.
+
+        @see: L{IAsyncTransaction.postCommit}
+
+        @param operation: 0-argument callable, potentially returning a
+            L{Deferred}.
+        """
+
+
     def commandBlock():
         """
         Create an object which will cause the commands executed on it to be

Modified: CalendarServer/branches/users/glyph/q/txdav/base/datastore/file.py
===================================================================
--- CalendarServer/branches/users/glyph/q/txdav/base/datastore/file.py	2012-08-11 08:55:30 UTC (rev 9659)
+++ CalendarServer/branches/users/glyph/q/txdav/base/datastore/file.py	2012-08-11 08:55:31 UTC (rev 9660)
@@ -187,15 +187,19 @@
                         self.log_error("Cannot undo DataStoreTransaction")
                 raise
 
-        for (operation, ignored) in self._postCommitOperations:
+        for operation in self._postCommitOperations:
             operation()
 
-    def postCommit(self, operation, immediately=False):
-        self._postCommitOperations.append((operation, immediately))
 
+    def postCommit(self, operation):
+        self._postCommitOperations.append(operation)
+
+
     def postAbort(self, operation):
         self._postAbortOperations.append(operation)
 
+
+
 class FileMetaDataMixin(object):
     
     implements(IDataStoreObject)

Modified: CalendarServer/branches/users/glyph/q/txdav/base/datastore/util.py
===================================================================
--- CalendarServer/branches/users/glyph/q/txdav/base/datastore/util.py	2012-08-11 08:55:30 UTC (rev 9659)
+++ CalendarServer/branches/users/glyph/q/txdav/base/datastore/util.py	2012-08-11 08:55:31 UTC (rev 9660)
@@ -70,13 +70,19 @@
 
 
     def setAfterCommit(self, transaction, key, value):
-        transaction.postCommit(lambda: self.set(key, value), immediately=True)
+        def setit():
+            # Don't return Deferred; let the postCommit chain continue.
+            self.set(key, value)
+        transaction.postCommit(setit)
 
     def invalidateAfterCommit(self, transaction, key):
         # Invalidate now (so that operations within this transaction see it)
         # and *also* post-commit (because there could be a scheduled setAfterCommit
         # for this key)
-        transaction.postCommit(lambda: self.delete(key), immediately=True)
+        def delit():
+            # Don't return Deferred; let the postCommit chain continue.
+            self.delete(key)
+        transaction.postCommit(delit)
         return self.delete(key)
 
     # Home child objects by name

Modified: CalendarServer/branches/users/glyph/q/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/glyph/q/txdav/common/datastore/sql.py	2012-08-11 08:55:30 UTC (rev 9659)
+++ CalendarServer/branches/users/glyph/q/txdav/common/datastore/sql.py	2012-08-11 08:55:31 UTC (rev 9660)
@@ -350,8 +350,6 @@
         self._calendarHomes = {}
         self._addressbookHomes = {}
         self._notificationHomes = {}
-        self._postCommitOperations = []
-        self._postAbortOperations = []
         self._notifierFactory = notifierFactory
         self._notifiedAlready = set()
         self._bumpedAlready = set()
@@ -606,18 +604,18 @@
         return self._apnSubscriptionsBySubscriberQuery.on(self, subscriberGUID=guid)
 
 
-    def postCommit(self, operation, immediately=False):
+    def postCommit(self, operation):
         """
         Run things after C{commit}.
         """
-        self._postCommitOperations.append((operation, immediately))
+        return self._sqlTxn.postCommit(operation)
 
 
     def postAbort(self, operation):
         """
         Run things after C{abort}.
         """
-        self._postAbortOperations.append(operation)
+        return self._sqlTxn.postAbort(operation)
 
 
     def isNotifiedAlready(self, obj):
@@ -774,30 +772,16 @@
         """
         Commit the transaction and execute any post-commit hooks.
         """
-        @inlineCallbacks
-        def postCommit(ignored):
-            for operation, immediately in self._postCommitOperations:
-                if immediately:
-                    yield operation()
-                else:
-                    operation()
-            returnValue(ignored)
-
         if self._stats:
             self._stats.printReport()
+        return self._sqlTxn.commit()
 
-        return self._sqlTxn.commit().addCallback(postCommit)
 
-
     def abort(self):
         """
         Abort the transaction.
         """
-        def postAbort(ignored):
-            for operation in self._postAbortOperations:
-                operation()
-            return ignored
-        return self._sqlTxn.abort().addCallback(postAbort)
+        return self._sqlTxn.abort()
 
 
     def _oldEventsBase(limited): #@NoSelf

Modified: CalendarServer/branches/users/glyph/q/txdav/idav.py
===================================================================
--- CalendarServer/branches/users/glyph/q/txdav/idav.py	2012-08-11 08:55:30 UTC (rev 9659)
+++ CalendarServer/branches/users/glyph/q/txdav/idav.py	2012-08-11 08:55:31 UTC (rev 9660)
@@ -207,29 +207,15 @@
         """
 
 
-    def postCommit(operation, immediately=False):
+    def postCommit(operation):
         """
-        Registers an operation to be executed after the transaction is
-        committed.
-
-        postCommit can be called multiple times, and operations are executed
-        in the order which they were registered.
-
-        @param operation: a callable.
-        @param immediately: a boolean; True means finish this operation *before* the
-            commit( ) call completes, defaults to False.
+        @see: L{IAsyncTransaction.postCommit}
         """
 
 
     def postAbort(operation):
         """
-        Registers an operation to be executed after the transaction is
-        aborted.
-
-        postAbort can be called multiple times, and operations are executed
-        in the order which they were registered.
-
-        @param operation: a callable.
+        @see: L{IAsyncTransaction.postAbort}
         """
 
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120811/739f0614/attachment-0001.html>


More information about the calendarserver-changes mailing list