[Zodb-checkins] SVN: ZODB/branches/3.3/src/ZEO/zrpc/connection.py Rewrite ZEO protocol negotiation.

Tim Peters tim.one at comcast.net
Thu Mar 31 21:43:41 EST 2005


Log message for revision 29769:
  Rewrite ZEO protocol negotiation.
  
  3.3 should have bumped the ZEO protocol number (new methods were
  added for MVCC support), but didn't.  Untangling this is a mess.
  

Changed:
  U   ZODB/branches/3.3/src/ZEO/zrpc/connection.py

-=-
Modified: ZODB/branches/3.3/src/ZEO/zrpc/connection.py
===================================================================
--- ZODB/branches/3.3/src/ZEO/zrpc/connection.py	2005-04-01 01:23:25 UTC (rev 29768)
+++ ZODB/branches/3.3/src/ZEO/zrpc/connection.py	2005-04-01 02:43:41 UTC (rev 29769)
@@ -87,7 +87,9 @@
 #    own protocol version and the server protocol version, allowing it to
 #    talk to servers using later protocol versions (2.0.2 and higher) as
 #    well:  the effective protocol used will be the lower of the client
-#    and server protocol.
+#    and server protocol.  However, this changed in ZODB 3.3.1 (and
+#    should have changed in ZODB 3.3) because an older server doesn't
+#    support MVCC methods required by 3.3 clients.
 #
 # [Ugly details:  In order to treat the first received message (protocol
 #  handshake) differently than all later messages, both client and server
@@ -174,14 +176,6 @@
     __super_close = smac.SizedMessageAsyncConnection.close
     __super_setSessionKey = smac.SizedMessageAsyncConnection.setSessionKey
 
-    # Protocol variables:
-    #
-    # oldest_protocol_version -- the oldest protocol version we support
-    # protocol_version -- the newest protocol version we support; preferred
-
-    oldest_protocol_version = "Z200"
-    protocol_version = "Z201"
-
     # Protocol history:
     #
     # Z200 -- Original ZEO 2.0 protocol
@@ -193,9 +187,54 @@
     #             getAuthProtocol() and scheme-specific authentication methods
     #             getExtensionMethods().
     #             getInvalidations().
+    #
+    # Z303 -- named after the ZODB release 3.3
+    #         Added methods for MVCC:
+    #             loadBefore()
+    #             loadEx()
+    #         A Z303 client cannot talk to a Z201 server, because the latter
+    #         doesn't support MVCC.  A Z201 client can talk to a Z303 server,
+    #         but because (at least) the type of the root object changed
+    #         from ZODB.PersistentMapping to persistent.mapping, the older
+    #         client can't actually make progress if a Z303 client created,
+    #         or ever modified, the root.
 
+    # Protocol variables:
+    # Our preferred protocol.
+    current_protocol = "Z303"
+
+    # If we're a client, an exhaustive list of the server protocols we
+    # can accept.
+    servers_we_can_talk_to = [current_protocol]
+
+    # If we're a server, an exhaustive list of the client protocols we
+    # can accept.
+    clients_we_can_talk_to = ["Z200", "Z201", current_protocol]
+
+    # This is pretty excruciating.  Details:
+    #
+    # 3.3 server 3.2 client
+    #     server sends Z303 to client
+    #     client computes min(Z303, Z201) == Z201 as the protocol to use
+    #     client sends Z201 to server
+    #     OK, because Z201 is in the server's clients_we_can_talk_to
+    #
+    # 3.2 server 3.3 client
+    #     server sends Z201 to client
+    #     client computes min(Z303, Z201) == Z201 as the protocol to use
+    #     Z201 isn't in the client's servers_we_can_talk_to, so client
+    #         raises exception
+    #
+    # 3.3 server 3.3 client
+    #     server sends Z303 to client
+    #     client computes min(Z303, Z303) == Z303 as the protocol to use
+    #     Z303 is in the client's servers_we_can_talk_to, so client
+    #         sends Z303 to server
+    #     OK, because Z303 is in the server's clients_we_can_talk_to
+
     # Client constructor passes 'C' for tag, server constructor 'S'.  This
-    # is used in log messages.
+    # is used in log messages, and to determine whether we can speak with
+    # our peer.
     def __init__(self, sock, addr, obj, tag):
         self.obj = None
         self.marshal = Marshaller()
@@ -203,6 +242,7 @@
         self.peer_protocol_version = None # set in recv_handshake()
 
         assert tag in "CS"
+        self.tag = tag
         self.logger = logging.getLogger('ZEO.zrpc.Connection(%c)' % tag)
         if isinstance(addr, types.TupleType):
             self.log_label = "(%s:%d) " % addr
@@ -324,7 +364,14 @@
         # Extended by ManagedClientConnection.
         del self.message_input  # uncover normal-case message_input()
         self.peer_protocol_version = proto
-        if self.oldest_protocol_version <= proto <= self.protocol_version:
+
+        if self.tag == 'C':
+            good_protos = self.servers_we_can_talk_to
+        else:
+            assert self.tag == 'S'
+            good_protos = self.clients_we_can_talk_to
+
+        if proto in good_protos:
             self.log("received handshake %r" % proto, level=logging.INFO)
         else:
             self.log("bad handshake %s" % short_repr(proto),
@@ -673,7 +720,7 @@
 
     def handshake(self):
         # Send the server's preferred protocol to the client.
-        self.message_output(self.protocol_version)
+        self.message_output(self.current_protocol)
 
     def close(self):
         self.obj.notifyDisconnected()
@@ -729,7 +776,7 @@
     def recv_handshake(self, proto):
         # The protocol to use is the older of our and the server's preferred
         # protocols.
-        proto = min(proto, self.protocol_version)
+        proto = min(proto, self.current_protocol)
 
         # Restore the normal message_input method, and raise an exception
         # if the protocol version is too old.
@@ -752,6 +799,7 @@
 
     def close_trigger(self):
         # the manager should actually close the trigger
+        # TODO: what is that comment trying to say?  What 'manager'?
         del self.trigger
 
     def set_async(self, map):



More information about the Zodb-checkins mailing list