[Zodb-checkins] CVS: ZODB3/ZEO/tests - ConnectionTests.py:1.4.2.6
testZEO.py:1.54.2.8
Tim Peters
tim.one at comcast.net
Mon Aug 4 19:14:08 EDT 2003
Update of /cvs-repository/ZODB3/ZEO/tests
In directory cvs.zope.org:/tmp/cvs-serv24603/ZEO/tests
Modified Files:
Tag: ZODB3-3_1-branch
ConnectionTests.py testZEO.py
Log Message:
Side-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.
NOTE: The Berkeley tests are all hosed on Windows in this branch now,
but that was true before this patch.
=== ZODB3/ZEO/tests/ConnectionTests.py 1.4.2.5 => 1.4.2.6 ===
--- ZODB3/ZEO/tests/ConnectionTests.py:1.4.2.5 Wed Jun 11 19:11:32 2003
+++ ZODB3/ZEO/tests/ConnectionTests.py Mon Aug 4 18:14:00 2003
@@ -26,16 +26,17 @@
from ZEO.ClientStorage import ClientStorage, ClientDisconnected
from ZEO.Exceptions import Disconnected
from ZEO.zrpc.marshal import Marshaller
+from ZEO.zrpc.error import DisconnectedError
from ZEO.tests.InvalidationTests import InvalidationTests
from ZODB.Transaction import get_transaction, Transaction
-from ZODB.POSException import ReadOnlyError
+from ZODB.POSException import ReadOnlyError, ConflictError
from ZODB.tests import StorageTestBase
from ZODB.tests.MinPO import MinPO
from ZODB.tests.StorageTestBase import zodb_pickle, zodb_unpickle
class DummyDB:
- def invalidate(self, *args):
+ def invalidate(self, *args, **kws):
pass
class ConnectionTests(StorageTestBase.StorageTestBase,
@@ -577,3 +578,103 @@
storage.tpc_begin(txn)
storage.tpc_abort(txn)
+ def checkTimeoutAfterVote(self):
+ raises = self.assertRaises
+ unless = self.failUnless
+ self.shutdownServer()
+ self.startServer(transaction_timeout=1)
+ self._storage = storage = self.openClientStorage()
+ # Assert that the zeo cache is empty
+ unless(not storage._cache._index)
+ # Create the object
+ oid = storage.new_oid()
+ obj = MinPO(7)
+ ZERO = '\0'*8
+ # Now do a store, sleeping before the finish so as to cause a timeout
+ t = Transaction()
+ storage.tpc_begin(t)
+ revid1 = storage.store(oid, ZERO, zodb_pickle(obj), '', t)
+ storage.tpc_vote(t)
+ # Now sleep long enough for the storage to time out
+ time.sleep(3)
+ storage.sync()
+ unless(not storage.is_connected())
+ storage._wait()
+ unless(storage.is_connected())
+ # We expect finish to fail
+ raises(ClientDisconnected, storage.tpc_finish, t)
+ # The cache should still be empty
+ unless(not storage._cache._index)
+ # Load should fail since the object should not be in either the cache
+ # or the server.
+ raises(KeyError, storage.load, oid, '')
+
+ def checkTimeoutProvokingConflicts(self):
+ eq = self.assertEqual
+ raises = self.assertRaises
+ unless = self.failUnless
+ self.shutdownServer()
+ self.startServer(transaction_timeout=1)
+ self._storage = storage = self.openClientStorage()
+ # Assert that the zeo cache is empty
+ unless(not storage._cache._index)
+ # Create the object
+ oid = storage.new_oid()
+ obj = MinPO(7)
+ ZERO = '\0'*8
+ # We need to successfully commit an object now so we have something to
+ # conflict about.
+ t = Transaction()
+ storage.tpc_begin(t)
+ revid1a = storage.store(oid, ZERO, zodb_pickle(obj), '', t)
+ revid1b = storage.tpc_vote(t)
+ revid1 = StorageTestBase.handle_serials(oid, revid1a, revid1b)
+ storage.tpc_finish(t)
+ # Now do a store, sleeping before the finish so as to cause a timeout
+ obj.value = 8
+ t = Transaction()
+ storage.tpc_begin(t)
+ revid2a = storage.store(oid, revid1, zodb_pickle(obj), '', t)
+ revid2b = storage.tpc_vote(t)
+ revid2 = StorageTestBase.handle_serials(oid, revid2a, revid2b)
+ # Now sleep long enough for the storage to time out
+ time.sleep(3)
+ storage.sync()
+ unless(not storage.is_connected())
+ storage._wait()
+ unless(storage.is_connected())
+ # We expect finish to fail
+ raises(ClientDisconnected, storage.tpc_finish, t)
+ # Now we think we've committed the second transaction, but we really
+ # haven't. A third one should produce a POSKeyError on the server,
+ # which manifests as a ConflictError on the client.
+ obj.value = 9
+ t = Transaction()
+ storage.tpc_begin(t)
+ storage.store(oid, revid2, zodb_pickle(obj), '', t)
+ raises(ConflictError, storage.tpc_vote, t)
+ # Even aborting won't help
+ storage.tpc_abort(t)
+ storage.tpc_finish(t)
+ # Try again
+ obj.value = 10
+ t = Transaction()
+ storage.tpc_begin(t)
+ storage.store(oid, revid2, zodb_pickle(obj), '', t)
+ # Even aborting won't help
+ raises(ConflictError, storage.tpc_vote, t)
+ # Abort this one and try a transaction that should succeed
+ storage.tpc_abort(t)
+ storage.tpc_finish(t)
+ # Now do a store, sleeping before the finish so as to cause a timeout
+ obj.value = 11
+ t = Transaction()
+ storage.tpc_begin(t)
+ revid2a = storage.store(oid, revid1, zodb_pickle(obj), '', t)
+ revid2b = storage.tpc_vote(t)
+ revid2 = StorageTestBase.handle_serials(oid, revid2a, revid2b)
+ storage.tpc_finish(t)
+ # Now load the object and verify that it has a value of 11
+ data, revid = storage.load(oid, '')
+ eq(zodb_unpickle(data), MinPO(11))
+ eq(revid, revid2)
=== ZODB3/ZEO/tests/testZEO.py 1.54.2.7 => 1.54.2.8 ===
--- ZODB3/ZEO/tests/testZEO.py:1.54.2.7 Mon Jul 28 13:53:11 2003
+++ ZODB3/ZEO/tests/testZEO.py Mon Aug 4 18:14:00 2003
@@ -142,6 +142,11 @@
if hasattr(ZODB, "__version__"):
ReadOnlyStorage.ReadOnlyStorage.checkWriteMethods(self)
+ def checkSortKey(self):
+ key = '%s:%s' % (self._storage._storage, self._storage._server_addr)
+ self.assertEqual(self._storage.sortKey(), key)
+
+
class UnixTests(GenericTests):
"""Add Unix-specific scaffolding to the generic test suite."""
More information about the Zodb-checkins
mailing list