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

Guido van Rossum guido@python.org
Thu, 12 Sep 2002 00:30:20 -0400


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

Modified Files:
	ClientStorage.py 
Log Message:
First part of changes to fall back to a read-only connection when a
read-write connection is not available.  This refactors
ClientStorage.notifyConnected() into two functions, testConnection()
and notifyConnected().  testConnection creates the RPC stub and calls
the register() method; it returns the stub plus a flag indicating
whether this connection was preferred or sub-optimal.  If the
register() method raises ReadOnlyError, and the new option
read_only_fallback was true on the ClientStorage constructor, it is
retried with its read_only argument set to 1, and the stub is returned
with the sub-optimal flag.  notifyConnected() now receives the stub
returned by testConnection(), and starts the verification as before.

XXX The read_only_fallback  feature is not yet tested.

XXX More work is needed; when a suboptimal connection is used, the
ConnectThread must stay around trying to get a preferred connection,
and then it must switch connections on the ClientStorage (how???).



=== ZODB3/ZEO/ClientStorage.py 1.57 => 1.58 ===
--- ZODB3/ZEO/ClientStorage.py:1.57	Wed Sep 11 13:36:39 2002
+++ ZODB3/ZEO/ClientStorage.py	Thu Sep 12 00:30:19 2002
@@ -74,12 +74,13 @@
     def __init__(self, addr, storage='1', cache_size=20000000,
                  name='', client=None, var=None,
                  min_disconnect_poll=5, max_disconnect_poll=300,
-                 wait=0, read_only=0):
+                 wait=0, read_only=0, read_only_fallback=0):
 
         self._addr = addr # For tests
         self._server = disconnected_stub
         self._is_read_only = read_only
         self._storage = storage
+        self._read_only_fallback = read_only_fallback
 
         self._info = {'length': 0, 'size': 0, 'name': 'ZEO Client',
                       'supportsUndo':0, 'supportsVersions': 0,
@@ -175,21 +176,41 @@
         """Handle any pending invalidation messages."""
         self._server._update()
 
-    def notifyConnected(self, conn):
-        log2(INFO, "Connected to storage via %s" % repr(conn))
-
-        # check the protocol version here?
+    def testConnection(self, conn):
+        """Return a pair (stub, preferred).
 
+        Where:
+        - stub is an RPC stub
+        - preferred is: 1 if the connection is an optimal match,
+                        0 if it is a suboptimal but acceptable match
+        It can also raise DisconnectedError or ReadOnlyError.
+
+        This is called by ConnectionManager to decide which connection
+        to use in case there are multiple, and some are read-only and
+        others are read-write.
+        """
+        log2(INFO, "Testing connection %r" % conn)
+        # XXX Check the protocol version here?
         stub = ServerStub.StorageServer(conn)
-
+        try:
+            stub.register(str(self._storage), self._is_read_only)
+            return (stub, 1)
+        except POSException.ReadOnlyError:
+            if not self._read_only_fallback:
+                raise
+            stub.register(str(self._storage), read_only=1)
+            return (stub, 0)
+
+    def notifyConnected(self, stub):
+        """Start using the given RPC stub.
+
+        This is called by ConnectionManager after it has decided which
+        connection should be used.
+        """
         self._oids = []
-
-        stub.register(str(self._storage), self._is_read_only)
         self._info.update(stub.get_info())
         self.verify_cache(stub)
 
-        # Don't make the server available to clients until after
-        # validating the cache
         # XXX The stub should be saved here and set in end() below.
         self._server = stub