[Zope-Checkins] CVS: ZODB3/ZEO - ClientStorage.py:1.108

Tim Peters tim.one at comcast.net
Wed Aug 6 12:51:58 EDT 2003


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

Modified Files:
	ClientStorage.py 
Log Message:
Forward-porting critical ZEO client fixes from ZODB3-3_1-boston-branch.

+ If a storage times out between the vote and the finish, the ZEO cache
  could get populated with objects that don't make it to the storage
  server.

  A new flag self._midtxn_disconnect gets reset in tpc_begin() and set
  in notifyDisconnected().  If tpc_finish() discovers this flag set, it
  raises a ClientDisconnected error before calling tpc_finish() on the
  server.

+ In tpc_finish() we re-order the calls so that the server's tpc_finish()
  is called (and must succeed) before we update the ZEO client cache.

+ The storage name is now prepended to the sort key, to ensure a
  unique global sort order if storages are named uniquely.

+ Added new tests for the above (checkTimeoutAfterVote,
  checkTimeoutProvokingConflicts, checkSortKey).


=== ZODB3/ZEO/ClientStorage.py 1.107 => 1.108 ===
--- ZODB3/ZEO/ClientStorage.py:1.107	Wed Jul  9 12:25:13 2003
+++ ZODB3/ZEO/ClientStorage.py	Wed Aug  6 11:51:23 2003
@@ -232,6 +232,11 @@
         self._username = username
         self._password = password
         self._realm = realm
+
+        # Flag tracking disconnections in the middle of a transaction.  This
+        # is reset in tpc_begin() and set in notifyDisconnected().
+        self._midtxn_disconnect = 0
+
         # _server_addr is used by sortKey()
         self._server_addr = None
         self._tfile = None
@@ -514,7 +519,7 @@
         if self._server_addr is None:
             raise ClientDisconnected
         else:
-            return self._server_addr
+            return '%s:%s' % (self._storage, self._server_addr)
 
     def verify_cache(self, server):
         """Internal routine called to verify the cache.
@@ -583,6 +588,7 @@
         self._connection = None
         self._ready.clear()
         self._server = disconnected_stub
+        self._midtxn_disconnect = 1
 
     def __len__(self):
         """Return the size of the storage."""
@@ -821,6 +827,7 @@
         if self._is_read_only:
             raise POSException.ReadOnlyError()
         self._tpc_cond.acquire()
+        self._midtxn_disconnect = 0
         while self._transaction is not None:
             # It is allowable for a client to call two tpc_begins in a
             # row with the same transaction, and the second of these
@@ -891,6 +898,12 @@
             return
         self._load_lock.acquire()
         try:
+            if self._midtxn_disconnect:
+                raise ClientDisconnected(
+                       'Calling tpc_finish() on a disconnected transaction')
+
+            tid = self._server.tpc_finish(self._serial)
+
             self._lock.acquire()  # for atomic processing of invalidations
             try:
                 self._update_cache()
@@ -898,8 +911,6 @@
                     f()
             finally:
                 self._lock.release()
-
-            tid = self._server.tpc_finish(self._serial)
             self._cache.setLastTid(tid)
 
             r = self._check_serials()




More information about the Zope-Checkins mailing list