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

Jeremy Hylton cvs-admin at zope.org
Wed Nov 19 22:22:41 EST 2003


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

Modified Files:
      Tag: ZODB3-mvcc-2-branch
	ClientStorage.py 
Log Message:
Fix bogus tpc_begin() implementation.

Delete a bunch of instance variables:
_serial, _oid, _ts, _ltid

Fix lastTransaction() to use the cache's getLastTid() method.

Never pass a tid argument to tpc_begin() unless the caller passes one.

Details: The old tpc_begin() implementation always passed a non-None
value for the tid argument, even if the caller did not specify a tid.
Since a tid is rare, except in the case of recovered transactions,
ClientStorage usually computed a timestamp to use for the tid.  There
was no need to generate this tid; the client didn't use the value and
the server would generate one if is wasn't passed.  Worse, the tid
could easily be ignored, if it wasn't greater than the last tid
generated by the server; this could happen if the client's clock was
behind the server's or if the client generated its timestamp while
another transaction was committing.

Use the id() of the client's transaction object for the txn id
argument passed as the first argument to tpc_begin() and the last
argument to other transactional methods.

Details: The only purpose of this id is to distinguish between mutiple
threads using a single ClientStorage.  Each thread gets a unique
Transaction instance, so id() is sufficient.


=== ZODB3/ZEO/ClientStorage.py 1.110.2.5 => 1.110.2.6 ===
--- ZODB3/ZEO/ClientStorage.py:1.110.2.5	Wed Nov 12 17:24:26 2003
+++ ZODB3/ZEO/ClientStorage.py	Wed Nov 19 22:22:40 2003
@@ -253,6 +253,7 @@
 
         self._tbuf = self.TransactionBufferClass()
         self._db = None
+        self._ltid = None # the last committed transaction
 
         # _serials: stores (oid, serialno) as returned by server
         # _seriald: _check_serials() moves from _serials to _seriald,
@@ -293,10 +294,6 @@
         # is executing.
         self._lock = threading.Lock()
 
-        t = self._ts = get_timestamp()
-        self._serial = `t`
-        self._oid = '\0\0\0\0\0\0\0\0'
-
         # Decide whether to use non-temporary files
         if client is not None:
             dir = var or os.getcwd()
@@ -669,10 +666,10 @@
             raise POSException.StorageTransactionError(self._transaction,
                                                        trans)
 
-    def abortVersion(self, version, transaction):
+    def abortVersion(self, version, txn):
         """Storage API: clear any changes made by the given version."""
-        self._check_trans(transaction)
-        tid, oids = self._server.abortVersion(version, self._serial)
+        self._check_trans(txn)
+        tid, oids = self._server.abortVersion(version, id(txn))
         # When a version aborts, invalidate the version and
         # non-version data.  The non-version data should still be
         # valid, but older versions of ZODB will change the
@@ -686,11 +683,10 @@
             self._tbuf.invalidate(oid, '')
         return tid, oids
 
-    def commitVersion(self, source, destination, transaction):
+    def commitVersion(self, source, destination, txn):
         """Storage API: commit the source version in the destination."""
-        self._check_trans(transaction)
-        tid, oids = self._server.commitVersion(source, destination,
-                                               self._serial)
+        self._check_trans(txn)
+        tid, oids = self._server.commitVersion(source, destination, id(txn))
         if destination:
             # just invalidate our version data
             for oid in oids:
@@ -860,18 +856,18 @@
                 self._seriald[oid] = s
             return r
 
-    def store(self, oid, serial, data, version, transaction):
+    def store(self, oid, serial, data, version, txn):
         """Storage API: store data for an object."""
-        self._check_trans(transaction)
-        self._server.storea(oid, serial, data, version, self._serial)
+        self._check_trans(txn)
+        self._server.storea(oid, serial, data, version, id(txn))
         self._tbuf.store(oid, version, data)
         return self._check_serials()
 
-    def tpc_vote(self, transaction):
+    def tpc_vote(self, txn):
         """Storage API: vote on a transaction."""
-        if transaction is not self._transaction:
+        if txn is not self._transaction:
             return
-        self._server.vote(self._serial)
+        self._server.vote(id(txn))
         return self._check_serials()
 
     def tpc_begin(self, txn, tid=None, status=' '):
@@ -891,15 +887,8 @@
         self._transaction = txn
         self._tpc_cond.release()
 
-        if tid is None:
-            self._ts = get_timestamp(self._ts)
-            id = `self._ts`
-        else:
-            self._ts = TimeStamp(tid)
-            id = tid
-
         try:
-            self._server.tpc_begin(id, txn.user, txn.description,
+            self._server.tpc_begin(id(txn), txn.user, txn.description,
                                    txn._extension, tid, status)
         except:
             # Client may have disconnected during the tpc_begin().
@@ -907,7 +896,6 @@
                 self.end_transaction()
             raise
 
-        self._serial = id
         self._tbuf.clear()
         self._seriald.clear()
         del self._serials[:]
@@ -916,18 +904,17 @@
         """Internal helper to end a transaction."""
         # the right way to set self._transaction to None
         # calls notify() on _tpc_cond in case there are waiting threads
-        self._ltid = self._serial
         self._tpc_cond.acquire()
         self._transaction = None
         self._tpc_cond.notify()
         self._tpc_cond.release()
 
     def lastTransaction(self):
-        return self._ltid
+        return self._cache.getLastTid()
 
-    def tpc_abort(self, transaction):
+    def tpc_abort(self, txn):
         """Storage API: abort a transaction."""
-        if transaction is not self._transaction:
+        if txn is not self._transaction:
             return
         try:
             # XXX Are there any transactions that should prevent an
@@ -935,7 +922,7 @@
             # all, yet you want to be sure that other abort logic is
             # executed regardless.
             try:
-                self._server.tpc_abort(self._serial)
+                self._server.tpc_abort(id(txn))
             except ClientDisconnected:
                 log2(BLATHER, 'ClientDisconnected in tpc_abort() ignored')
         finally:
@@ -944,9 +931,9 @@
             del self._serials[:]
             self.end_transaction()
 
-    def tpc_finish(self, transaction, f=None):
+    def tpc_finish(self, txn, f=None):
         """Storage API: finish a transaction."""
-        if transaction is not self._transaction:
+        if txn is not self._transaction:
             return
         self._load_lock.acquire()
         try:
@@ -954,7 +941,7 @@
                 raise ClientDisconnected(
                        'Calling tpc_finish() on a disconnected transaction')
 
-            tid = self._server.tpc_finish(self._serial)
+            tid = self._server.tpc_finish(id(txn))
 
             self._lock.acquire()  # for atomic processing of invalidations
             try:
@@ -1008,7 +995,7 @@
                     self._cache.store(oid, version, s, tid, None, data)
         self._tbuf.clear()
 
-    def transactionalUndo(self, trans_id, trans):
+    def transactionalUndo(self, trans_id, txn):
         """Storage API: undo a transaction.
 
         This is executed in a transactional context.  It has no effect
@@ -1017,8 +1004,8 @@
         Zope uses this to implement undo unless it is not supported by
         a storage.
         """
-        self._check_trans(trans)
-        tid, oids = self._server.transactionalUndo(trans_id, self._serial)
+        self._check_trans(txn)
+        tid, oids = self._server.transactionalUndo(trans_id, id(txn))
         for oid in oids:
             self._tbuf.invalidate(oid, '')
         return tid, oids




More information about the Zope-Checkins mailing list