[Zodb-checkins] CVS: ZODB3/ZEO - ClientStorage.py:1.73.2.4.2.1

Jeremy Hylton jeremy@zope.com
Fri, 1 Nov 2002 14:17:25 -0500


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

Modified Files:
      Tag: ZODB3-deadlock-debug-branch
	ClientStorage.py 
Log Message:
Implement sortKey() for ClientStorage.

The sortKey is the address of the current storage server.  Two
wrinkles of interest: 

- A single client can connect to multiple servers, so its sortKey()
  can change.
- If different clients use different names (e.g. one uses hostname and
  one uses IP address), we could get different sortKeys.  This config
  should be avoided, but the code tries to get a canonical name just
  in case.


=== ZODB3/ZEO/ClientStorage.py 1.73.2.4 => 1.73.2.4.2.1 ===
--- ZODB3/ZEO/ClientStorage.py:1.73.2.4	Wed Oct 16 17:44:05 2002
+++ ZODB3/ZEO/ClientStorage.py	Fri Nov  1 14:17:24 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(INFO, "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."""