[CalendarServer-changes] [7252] CalendarServer/branches/users/glyph/subtransactions/twext/enterprise

source_changes at macosforge.org source_changes at macosforge.org
Thu Mar 24 13:36:07 PDT 2011


Revision: 7252
          http://trac.macosforge.org/projects/calendarserver/changeset/7252
Author:   glyph at apple.com
Date:     2011-03-24 13:36:07 -0700 (Thu, 24 Mar 2011)
Log Message:
-----------
test for one command block following another, and (apparently wrong) fix for that

Modified Paths:
--------------
    CalendarServer/branches/users/glyph/subtransactions/twext/enterprise/adbapi2.py
    CalendarServer/branches/users/glyph/subtransactions/twext/enterprise/test/test_adbapi2.py

Modified: CalendarServer/branches/users/glyph/subtransactions/twext/enterprise/adbapi2.py
===================================================================
--- CalendarServer/branches/users/glyph/subtransactions/twext/enterprise/adbapi2.py	2011-03-24 20:35:56 UTC (rev 7251)
+++ CalendarServer/branches/users/glyph/subtransactions/twext/enterprise/adbapi2.py	2011-03-24 20:36:07 UTC (rev 7252)
@@ -1,4 +1,3 @@
-from twext.enterprise.ienterprise import IDerivedParameter
 # -*- test-case-name: twext.enterprise.test.test_adbapi2 -*-
 ##
 # Copyright (c) 2010 Apple Inc. All rights reserved.
@@ -53,7 +52,10 @@
 
 from twext.internet.threadutils import ThreadHolder
 from twisted.internet.defer import succeed
+
 from twext.enterprise.ienterprise import ConnectionError
+from twext.enterprise.ienterprise import IDerivedParameter
+
 from twisted.internet.defer import fail
 from twext.enterprise.ienterprise import (
     AlreadyFinishedError, IAsyncTransaction, POSTGRES_DIALECT
@@ -362,7 +364,7 @@
         self._complete      = False
         self._currentBlock  = None
         self._pendingBlocks = []
-        self._allPending    = []
+        self._stillExecuting    = []
         self._blockedQueue  = None
 
 
@@ -396,10 +398,11 @@
         self._checkComplete()
         if block is None and self._blockedQueue is not None:
             return self._blockedQueue.execSQL(sql, args, raiseOnZeroRowCount)
+        # 'block' should always be _currentBlock at this point.
         d = super(_SingleTxn, self).execSQL(sql, args, raiseOnZeroRowCount)
-        self._allPending.append(d)
+        self._stillExecuting.append(d)
         def itsDone(result):
-            self._allPending.remove(d)
+            self._stillExecuting.remove(d)
             self._checkNextBlock()
             return result
         d.addBoth(itsDone)
@@ -412,7 +415,7 @@
         execute, and execute the next one if there are no outstanding execute
         calls.
         """
-        if self._allPending:
+        if self._stillExecuting:
             return
 
         if self._pendingBlocks and self._currentBlock is None:
@@ -431,8 +434,7 @@
         bq = self._blockedQueue
         self._blockedQueue = None
         bq._unspool(self)
-        # XXX need to check next block, there might have been nothing in the
-        # blocked executing queue.
+        self._checkNextBlock()
 
 
     def commit(self):
@@ -474,14 +476,18 @@
 
     def commandBlock(self):
         """
-        Create an IAsyncTransaction that will wait for all currently spooled
+        Create a L{CommandBlock} which will wait for all currently spooled
         commands to complete before executing its own.
         """
-        self._currentBlock = CommandBlock(self)
-        self._blockedQueue = _WaitingTxn(self._pool)
-        # FIXME: test the case where it's ready immediately.
-        self._checkNextBlock()
-        return self._currentBlock
+        block = CommandBlock(self)
+        if self._currentBlock is None:
+            self._currentBlock = block
+            self._blockedQueue = _WaitingTxn(self._pool)
+            # FIXME: test the case where it's ready immediately.
+            self._checkNextBlock()
+        else:
+            self._pendingBlocks.append(block)
+        return block
 
 
 
@@ -557,8 +563,9 @@
         """
         # FIXME: test the case where end() is called when it's not the current
         # executing block.
+        if self._ended:
+            raise AlreadyFinishedError()
         self._ended = True
-        self._singleTxn._checkNextBlock()
         DeferredList(self._waitingForEnd).chainDeferred(self._endDeferred)
 
 

Modified: CalendarServer/branches/users/glyph/subtransactions/twext/enterprise/test/test_adbapi2.py
===================================================================
--- CalendarServer/branches/users/glyph/subtransactions/twext/enterprise/test/test_adbapi2.py	2011-03-24 20:35:56 UTC (rev 7251)
+++ CalendarServer/branches/users/glyph/subtransactions/twext/enterprise/test/test_adbapi2.py	2011-03-24 20:36:07 UTC (rev 7252)
@@ -27,6 +27,7 @@
 
 from twisted.internet.defer import Deferred
 from twext.enterprise.ienterprise import ConnectionError
+from twext.enterprise.ienterprise import AlreadyFinishedError
 from twext.enterprise.adbapi2 import ConnectionPool
 
 
@@ -918,3 +919,43 @@
         self.assertEquals(len(d), 1)
         self.assertEquals(len(e), 1)
 
+
+    def test_twoCommandBlocks(self, flush=lambda : None):
+        """
+        When execution of one command block is complete, it will proceed to the
+        next queued block, then to regular SQL executed on the transaction.
+        """
+        txn = self.pool.connection()
+        cb1 = txn.commandBlock()
+        cb2 = txn.commandBlock()
+        txn.execSQL("e")
+        cb1.execSQL("a")
+        cb2.execSQL("c")
+        cb1.execSQL("b")
+        cb2.execSQL("d")
+        cb2.end()
+        cb1.end()
+        flush()
+        self.assertEquals(self.factory.connections[0].cursors[0].allExecutions,
+                          [("a", []), ("b", []), ("c", []), ("d", []),
+                           ("e", [])])
+
+
+    def test_twoCommandBlocksLatently(self):
+        """
+        Same as L{test_twoCommandBlocks}, but with slower callbacks.
+        """
+        self.pauseHolders()
+        self.test_twoCommandBlocks(self.flushHolders)
+
+
+    def test_commandBlockEndTwice(self):
+        """
+        L{CommandBlock.end} will raise L{AlreadyFinishedError} when called more
+        than once.
+        """
+        txn = self.pool.connection()
+        block = txn.commandBlock()
+        block.end()
+        self.assertRaises(AlreadyFinishedError, block.end)
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20110324/34b84a1c/attachment.html>


More information about the calendarserver-changes mailing list