[CalendarServer-changes] [6577] CalendarServer/branches/users/glyph/conn-limit/txdav/base/datastore

source_changes at macosforge.org source_changes at macosforge.org
Mon Nov 8 09:14:36 PST 2010


Revision: 6577
          http://trac.macosforge.org/projects/calendarserver/changeset/6577
Author:   glyph at apple.com
Date:     2010-11-08 09:14:33 -0800 (Mon, 08 Nov 2010)
Log Message:
-----------
Make the test pass.

Modified Paths:
--------------
    CalendarServer/branches/users/glyph/conn-limit/txdav/base/datastore/asyncsqlpool.py
    CalendarServer/branches/users/glyph/conn-limit/txdav/base/datastore/test/test_asyncsqlpool.py

Modified: CalendarServer/branches/users/glyph/conn-limit/txdav/base/datastore/asyncsqlpool.py
===================================================================
--- CalendarServer/branches/users/glyph/conn-limit/txdav/base/datastore/asyncsqlpool.py	2010-11-08 17:14:08 UTC (rev 6576)
+++ CalendarServer/branches/users/glyph/conn-limit/txdav/base/datastore/asyncsqlpool.py	2010-11-08 17:14:33 UTC (rev 6577)
@@ -39,6 +39,7 @@
 from txdav.base.datastore.threadutils import ThreadHolder
 from txdav.idav import AlreadyFinishedError
 from twisted.python import log
+from twisted.internet.defer import maybeDeferred
 from twisted.python.components import proxyForInterface
 
 
@@ -204,10 +205,7 @@
         """
         Relay a single command to another transaction.
         """
-        def cb(nothing):
-            return getattr(other, cmd)(*a, **kw)
-        d.addCallback(cb)
-        d.callback(None)
+        maybeDeferred(getattr(other, cmd), *a, **kw).chainDeferred(d)
 
 
     def execSQL(self, *a, **kw):
@@ -281,15 +279,26 @@
     """
     This is a central service that has a threadpool and executes SQL statements
     asynchronously, in a pool.
+
+    @ivar connectionFactory: a 0-or-1-argument callable that returns a DB-API
+        connection.  The optional argument can be used as a label for
+        diagnostic purposes.
+
+    @ivar maxConnections: The connection pool will not attempt to make more
+        than this many concurrent connections to the database.
+
+    @type maxConnections: C{int}
     """
 
     reactor = _reactor
 
-    def __init__(self, connectionFactory):
+    def __init__(self, connectionFactory, maxConnections=10):
         super(ConnectionPool, self).__init__()
         self.free = []
         self.busy = []
+        self.waiting = []
         self.connectionFactory = connectionFactory
+        self.maxConnections = maxConnections
 
 
     def startService(self):
@@ -321,27 +330,46 @@
 
         @return: an L{IAsyncTransaction}
         """
+
+        overload = False
         if self.free:
             basetxn = self.free.pop(0)
-        else:
+        elif len(self.busy) < self.maxConnections:
             basetxn = BaseSqlTxn(
                 connectionFactory=self.connectionFactory,
                 reactor=self.reactor
             )
+        else:
+            basetxn = SpooledTxn()
+            overload = True
         txn = PooledSqlTxn(self, basetxn)
-        self.busy.append(txn)
+        if overload:
+            self.waiting.append(txn)
+        else:
+            self.busy.append(txn)
         return txn
 
 
     def reclaim(self, txn):
         """
-        Shuck the L{PooledSqlTxn} wrapper off, and put the BaseSqlTxn into the
-        free list.
+        Shuck the L{PooledSqlTxn} wrapper off, and recycle the underlying
+        BaseSqlTxn into the free list.
         """
         baseTxn = txn._baseTxn
         baseTxn.reset()
-        self.free.append(baseTxn)
         self.busy.remove(txn)
+        if self.waiting:
+            waiting = self.waiting.pop(0)
+            waiting._baseTxn._unspool(baseTxn)
+            # Note: although commit() may already have been called, we don't
+            # have to handle it specially here.  It only unspools after the
+            # deferred returned by commit() has actually been called, and since
+            # that occurs in a callFromThread, that won't happen until the next
+            # iteration of the mainloop, when the _baseTxn is safely correct.
+            waiting._baseTxn = baseTxn
+            self.busy.append(waiting)
+        else:
+            self.free.append(baseTxn)
 
 
 

Modified: CalendarServer/branches/users/glyph/conn-limit/txdav/base/datastore/test/test_asyncsqlpool.py
===================================================================
--- CalendarServer/branches/users/glyph/conn-limit/txdav/base/datastore/test/test_asyncsqlpool.py	2010-11-08 17:14:08 UTC (rev 6576)
+++ CalendarServer/branches/users/glyph/conn-limit/txdav/base/datastore/test/test_asyncsqlpool.py	2010-11-08 17:14:33 UTC (rev 6577)
@@ -136,7 +136,7 @@
         until an existing connection becomes available.
         """
         cf = ConnectionFactory()
-        cp = ConnectionPool(cf.connect)
+        cp = ConnectionPool(cf.connect, maxConnections=2)
         cp.startService()
         self.addCleanup(cp.stopService)
         a = cp.connection()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20101108/7d6d3d43/attachment.html>


More information about the calendarserver-changes mailing list