[Zodb-checkins] CVS: ZODB3/ZEO/zrpc - client.py:1.10

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


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

Modified Files:
	client.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/zrpc/client.py 1.9 => 1.10 ===
--- ZODB3/ZEO/zrpc/client.py:1.9	Thu Sep 12 00:02:18 2002
+++ ZODB3/ZEO/zrpc/client.py	Thu Sep 12 00:30:19 2002
@@ -215,6 +215,7 @@
         self.tmax = tmax
         self.stopped = 0
         self.one_attempt = threading.Event()
+        self.fallback = None
         # A ConnectThread keeps track of whether it has finished a
         # call to attempt_connects().  This allows the
         # ConnectionManager to make an attempt to connect right away,
@@ -293,7 +294,21 @@
         if ok:
             del self.sockets[s] # don't close the newly connected socket
             self.close_sockets()
-        return ok
+            return 1
+        if self.fallback:
+            (c, stub) = self.fallback
+            self.fallback = None
+            try:
+                self.client.notifyConnected(stub)
+            except:
+                log("error in notifyConnected (%r)" % addr,
+                    level=zLOG.ERROR, error=sys.exc_info())
+                c.close()
+                return 0
+            else:
+                self.mgr.connect_done(c)
+                return 1
+        return 0
 
     def try_connect(self, s):
         """Call s.connect_ex(addr); return true iff connection succeeds.
@@ -364,13 +379,25 @@
         # okay.
         c = ManagedConnection(s, addr, self.client, self.mgr)
         try:
-            self.client.notifyConnected(c)
+            (stub, preferred) = self.client.testConnection(c)
         except:
-            log("error connecting to server: %s" % str(addr),
+            log("error in testConnection (%r)" % addr,
                 level=zLOG.ERROR, error=sys.exc_info())
             c.close()
             # Closing the ZRPC connection will eventually close the
             # socket, somewhere in asyncore.
             return 0
-        self.mgr.connect_done(c)
-        return 1
+        if preferred:
+            try:
+                self.client.notifyConnected(stub)
+            except:
+                log("error in notifyConnected (%r)" % addr,
+                    level=zLOG.ERROR, error=sys.exc_info())
+                c.close()
+                return 0
+            else:
+                self.mgr.connect_done(c)
+                return 1
+        if self.fallback is None:
+            self.fallback = (c, stub)
+        return 0