[Zodb-checkins] CVS: ZODB3/ZEO - start.py:1.45.6.2 StorageServer.py:1.74.2.6 ClientStorage.py:1.73.2.5

Jeremy Hylton jeremy@zope.com
Tue, 12 Nov 2002 15:18:10 -0500


Update of /cvs-repository/ZODB3/ZEO
In directory cvs.zope.org:/tmp/cvs-serv20159/ZEO

Modified Files:
      Tag: ZODB3-3_1-branch
	start.py StorageServer.py ClientStorage.py 
Log Message:
Merge the deadlock debug code to the release branch.


=== ZODB3/ZEO/start.py 1.45.6.1 => 1.45.6.2 ===
--- ZODB3/ZEO/start.py:1.45.6.1	Wed Oct 16 17:47:07 2002
+++ ZODB3/ZEO/start.py	Tue Nov 12 15:18:09 2002
@@ -17,6 +17,8 @@
 
 import sys, os, getopt
 import types
+import errno
+import socket
 
 def directory(p, n=1):
     d = p
@@ -288,7 +290,12 @@
 
     try:
         try:
-            asyncore.loop()
+            while 1:
+                try:
+                    asyncore.loop()
+                except (socket.error, OSError), err:
+                    if err[0] != errno.EBADF:
+                        raise
         finally:
             if os.path.isfile(env.zeo_pid):
                 os.unlink(env.zeo_pid)


=== ZODB3/ZEO/StorageServer.py 1.74.2.5 => 1.74.2.6 ===
--- ZODB3/ZEO/StorageServer.py:1.74.2.5	Tue Nov 12 12:59:56 2002
+++ ZODB3/ZEO/StorageServer.py	Tue Nov 12 15:18:09 2002
@@ -392,12 +392,8 @@
                                               " requests from one client.")
 
         # (This doesn't require a lock because we're using asyncore)
-        if self.storage._transaction is None:
-            self.strategy = self.ImmediateCommitStrategyClass(self.storage,
-                                                              self.client)
-        else:
-            self.strategy = self.DelayedCommitStrategyClass(self.storage,
-                                                            self.wait)
+        self.strategy = self.DelayedCommitStrategyClass(self.storage,
+                                                        self.wait)
 
         t = Transaction()
         t.id = id
@@ -474,8 +470,10 @@
                      "Clients waiting: %d." % len(self.storage._waiting))
             return d
         else:
-            self.restart()
-            return None
+            return self.restart()
+
+    def dontwait(self):
+        return self.restart()
 
     def handle_waiting(self):
         while self.storage._waiting:
@@ -510,6 +508,8 @@
         resp = old_strategy.restart(self.strategy)
         if delay is not None:
             delay.reply(resp)
+        else:
+            return resp
 
 # A ZEOStorage instance can use different strategies to commit a
 # transaction.  The current implementation uses different strategies


=== ZODB3/ZEO/ClientStorage.py 1.73.2.4 => 1.73.2.5 ===
--- ZODB3/ZEO/ClientStorage.py:1.73.2.4	Wed Oct 16 17:44:05 2002
+++ ZODB3/ZEO/ClientStorage.py	Tue Nov 12 15:18:09 2002
@@ -28,9 +28,11 @@
 
 import cPickle
 import os
+import socket
 import tempfile
 import threading
 import time
+import types
 
 from ZEO import ClientCache, ServerStub
 from ZEO.TransactionBuffer import TransactionBuffer
@@ -204,6 +206,8 @@
         self._storage = storage
         self._read_only_fallback = read_only_fallback
         self._connection = None
+        # _server_addr is used by sortKey()
+        self._server_addr = None
 
         self._info = {'length': 0, 'size': 0, 'name': 'ZEO Client',
                       'supportsUndo':0, 'supportsVersions': 0,
@@ -339,6 +343,7 @@
             log2(INFO, "Reconnected to storage")
         else:
             log2(INFO, "Connected to storage")
+        self.set_server_addr(conn.get_addr())
         stub = self.StorageServerStubClass(conn)
         self._oids = []
         self._info.update(stub.get_info())
@@ -349,6 +354,33 @@
             self._connection.close()
         self._connection = conn
         self._server = stub
+
+    def set_server_addr(self, addr):
+        # Normalize server address and convert to string
+        if isinstance(addr, types.StringType):
+            self._server_addr = addr
+        else:
+            assert isinstance(addr, types.TupleType)
+            # If the server is on a remote host, we need to guarantee
+            # that all clients used the same name for the server.  If
+            # they don't, the sortKey() may be different for each client.
+            # The best solution seems to be the official name reported
+            # by gethostbyaddr().
+            host = addr[0]
+            try:
+                canonical, aliases, addrs = socket.gethostbyaddr(host)
+            except socket.error, err:
+                log2(BLATHER, "Error resoving host: %s (%s)" % (host, err))
+                canonical = host
+            self._server_addr = str((canonical, addr[1]))
+
+    def sortKey(self):
+        # If the client isn't connected to anything, it can't have a
+        # valid sortKey().  Raise an error to stop the transaction early.
+        if self._server_addr is None:
+            raise ClientDisconnected
+        else:
+            return self._server_addr
 
     def verify_cache(self, server):
         """Internal routine called to verify the cache."""