[Zodb-checkins] CVS: StandaloneZODB/ZEO - StorageServer.py:1.32.6.3.2.4

Jeremy Hylton jeremy@zope.com
Mon, 6 May 2002 17:22:19 -0400


Update of /cvs-repository/StandaloneZODB/ZEO
In directory cvs.zope.org:/tmp/cvs-serv25680

Modified Files:
      Tag: ZEO2-branch
	StorageServer.py 
Log Message:
Fix more bugs in the distributed commit lock implementation.

If a transaction got into the Delayed strategy and got to the wait()
call after the other transaction was finished, it was added to the
waiting list even though there was no running transaction to unblock
it.  The solution is to check whether the commit lock is held when
wait() is called.  If it isn't, the transaction can transition
immediately to the immediate strategy.

In _handle_waiting(), continue to pop transactions off the waiting
queue until one succeeds in starting.

In restart(), make delay argument optional.  There is no delay if
wait() finds the lock free.

In DelayedCommitStrategy's restart() method, loads is an int not a
list, so call range() not len().




=== StandaloneZODB/ZEO/StorageServer.py 1.32.6.3.2.3 => 1.32.6.3.2.4 ===
     
     def wait(self):
-        d = Delay()
-        self.__storage._waiting.append((d, self))
-        self._log("Transaction block waiting for storage. "
-                  "%d clients waiting." % len(self.__storage._waiting))
-        return d
+        if self.__storage._transaction:
+            d = Delay()
+            self.__storage._waiting.append((d, self))
+            self._log("Transaction block waiting for storage. "
+                      "%d clients waiting." % len(self.__storage._waiting))
+            return d
+        else:
+            self.restart()
 
     def _handle_waiting(self):
-        if self.__storage._waiting:
+        while self.__storage._waiting:
             delay, zeo_storage = self.__storage._waiting.pop(0)
-            try:
-                zeo_storage.restart(delay)
-            except:
-                self._log("Unexpected error handling waiting transaction",
-                          level=zLOG.WARNING, error=sys.exc_info())
-                zeo_storage.close()
+            if self._restart(delay):
+                break
 
-    def restart(self, delay):
+    def _restart(self, delay):
+        # call the restart() method on the appropriate server
+        try:
+            zeo_storage.restart(delay)
+        except:
+            self._log("Unexpected error handling waiting transaction",
+                      level=zLOG.WARNING, error=sys.exc_info())
+            zeo_storage.close()
+            return 0
+        else:
+            return 1
+            
+    def restart(self, delay=None):
         old_strategy = self.strategy
         self.strategy = ImmediateCommitStrategy(self.__storage,
                                                 self.client)
-        delay.reply(old_strategy.restart(self.strategy))
+        resp = old_strategy.restart(self.strategy)
+        if delay is not None:
+            delay.reply(resp)
 
 # A ZEOStorage instance can use different strategies to commit a
 # transaction.  The current implementation uses different strategies
@@ -538,7 +551,7 @@
         # called by the storage when the storage is available
         new_strategy.tpc_begin(self.txn, self.tid, self.status)
         loads, loader = self.log.get_loader()
-        for i in len(loads):
+        for i in range(loads):
             oid, serial, data, version = loader.load()
             new_strategy.store(oid, serial, data, version)
         meth = getattr(new_strategy, self.name)