[Zope3-checkins] CVS: ZODB4/src/zodb/storage/tests - test_autopack.py:1.6
Barry Warsaw
barry@wooz.org
Mon, 27 Jan 2003 11:23:52 -0500
Update of /cvs-repository/ZODB4/src/zodb/storage/tests
In directory cvs.zope.org:/tmp/cvs-serv22645
Modified Files:
test_autopack.py
Log Message:
Refactor actual race condition tests to RaceConditionBase since the
only difference is the pack-thread object they need to create. Added
a second race condition test which checks for an earlier race
condition in the tpc.
=== ZODB4/src/zodb/storage/tests/test_autopack.py 1.5 => 1.6 ===
--- ZODB4/src/zodb/storage/tests/test_autopack.py:1.5 Fri Jan 24 18:20:51 2003
+++ ZODB4/src/zodb/storage/tests/test_autopack.py Mon Jan 27 11:23:48 2003
@@ -264,6 +264,113 @@
# clean up any outstanding transactions
get_transaction().abort()
+ def _getPackThread(self, storage):
+ raise NotImplemented
+
+ def testRaceCondition(self):
+ unless = self.failUnless
+ storage = self._storage
+ db = DB(storage)
+ conn = db.open()
+ root = conn.root()
+ # Start by storing a root reachable object.
+ obj1 = C()
+ obj1.value = 888
+ root.obj1 = obj1
+ txn = get_transaction()
+ txn.note('root -> obj1')
+ txn.commit()
+ # Now, start a transaction, store an object, but don't yet complete
+ # the transaction. This will ensure that the second object has a tid
+ # < packtime, but it won't be root reachable yet.
+ obj2 = C()
+ t = Transaction()
+ storage.tpc_begin(t)
+ obj2sn = storage.store('\0'*7 + '\2', ZERO, zodb_pickle(obj2), '', t)
+ # Now, acquire the condvar lock and start a thread that will do a
+ # pack, up to the _sweep call. Wait for the _mark() call to
+ # complete.
+ now = time.time()
+ while now == time.time():
+ time.sleep(0.5)
+ self._cv.acquire()
+ packthread = self._getPackThread(storage)
+ packthread.start()
+ self._cv.wait()
+ # Now that the _mark() has finished, complete the transaction, which
+ # links the object to root.
+ root.obj2 = obj2
+ rootsn = storage.getSerial(ZERO)
+ rootsn = storage.store(ZERO, rootsn, zodb_pickle(root), '', t)
+ storage.tpc_vote(t)
+ storage.tpc_finish(t)
+ # And notify the pack thread that it can do the sweep and collect
+ self._cv.notify()
+ self._cv.wait()
+ # We're done with the condvar and the thread
+ self._cv.release()
+ packthread.join()
+ # Now make sure that all the interesting objects are still available
+ rootsn = storage.getSerial(ZERO)
+ obj1sn = storage.getSerial('\0'*7 + '\1')
+ obj2sn = storage.getSerial('\0'*7 + '\2')
+ # obj1 revision was written before the second revision of the root
+ unless(obj1sn < rootsn)
+ unless(rootsn == obj2sn)
+ unless(obj1sn < obj2sn)
+
+ def testEarlierRaceCondition(self):
+ unless = self.failUnless
+ storage = self._storage
+ db = DB(storage)
+ conn = db.open()
+ root = conn.root()
+ # Start by storing a root reachable object.
+ obj1 = C()
+ obj1.value = 888
+ root.obj1 = obj1
+ txn = get_transaction()
+ txn.note('root -> obj1')
+ txn.commit()
+ # Now, start a transaction, store an object, but don't yet complete
+ # the transaction. This will ensure that the second object has a tid
+ # < packtime, but it won't be root reachable yet.
+ obj2 = C()
+ t = Transaction()
+ storage.tpc_begin(t)
+ # Now, acquire the condvar lock and start a thread that will do a
+ # pack, up to the _sweep call. Wait for the _mark() call to
+ # complete.
+ now = time.time()
+ while now == time.time():
+ time.sleep(0.5)
+ self._cv.acquire()
+ packthread = self._getPackThread(storage)
+ packthread.start()
+ self._cv.wait()
+ obj2sn = storage.store('\0'*7 + '\2', ZERO, zodb_pickle(obj2), '', t)
+ # Now that the _mark() has finished, complete the transaction, which
+ # links the object to root.
+ root.obj2 = obj2
+ rootsn = storage.getSerial(ZERO)
+ rootsn = storage.store(ZERO, rootsn, zodb_pickle(root), '', t)
+ storage.tpc_vote(t)
+ storage.tpc_finish(t)
+ # And notify the pack thread that it can do the sweep and collect
+ self._cv.notify()
+ self._cv.wait()
+ # We're done with the condvar and the thread
+ self._cv.release()
+ packthread.join()
+ # Now make sure that all the interesting objects are still available
+ rootsn = storage.getSerial(ZERO)
+ obj1sn = storage.getSerial('\0'*7 + '\1')
+ obj2sn = storage.getSerial('\0'*7 + '\2')
+ # obj1 revision was written before the second revision of the root
+ unless(obj1sn < rootsn)
+ unless(rootsn == obj2sn)
+ unless(obj1sn < obj2sn)
+
# Subclass which does ugly things to _dopack so we can actually test the race
@@ -344,57 +451,8 @@
class TestFullClassicPackRaceCondition(RaceConditionBase):
ConcreteStorage = SynchronizedFullStorage
- def testRaceCondition(self):
- unless = self.failUnless
- storage = self._storage
- db = DB(storage)
- conn = db.open()
- root = conn.root()
- # Start by storing a root reachable object.
- obj1 = C()
- obj1.value = 888
- root.obj1 = obj1
- txn = get_transaction()
- txn.note('root -> obj1')
- txn.commit()
- # Now, start a transaction, store an object, but don't yet complete
- # the transaction. This will ensure that the second object has a tid
- # < packtime, but it won't be root reachable yet.
- obj2 = C()
- t = Transaction()
- storage.tpc_begin(t)
- obj2sn = storage.store('\0'*7 + '\2', ZERO, zodb_pickle(obj2), '', t)
- # Now, acquire the condvar lock and start a thread that will do a
- # pack, up to the _sweep call. Wait for the _mark() call to
- # complete.
- now = time.time()
- while now == time.time():
- time.sleep(0.5)
- self._cv.acquire()
- packthread = FullPackThread(storage)
- packthread.start()
- self._cv.wait()
- # Now that the _mark() has finished, complete the transaction, which
- # links the object to root.
- root.obj2 = obj2
- rootsn = storage.getSerial(ZERO)
- rootsn = storage.store(ZERO, rootsn, zodb_pickle(root), '', t)
- storage.tpc_vote(t)
- storage.tpc_finish(t)
- # And notify the pack thread that it can do the sweep and collect
- self._cv.notify()
- self._cv.wait()
- # We're done with the condvar and the thread
- self._cv.release()
- packthread.join()
- # Now make sure that all the interesting objects are still available
- rootsn = storage.getSerial(ZERO)
- obj1sn = storage.getSerial('\0'*7 + '\1')
- obj2sn = storage.getSerial('\0'*7 + '\2')
- # obj1 revision was written before the second revision of the root
- unless(obj1sn < rootsn)
- unless(rootsn == obj2sn)
- unless(obj1sn < obj2sn)
+ def _getPackThread(self, storage):
+ return FullPackThread(storage)
@@ -451,58 +509,8 @@
class TestMinimalClassicPackRaceCondition(RaceConditionBase):
ConcreteStorage = SynchronizedMinimalStorage
- def testRaceCondition(self):
- unless = self.failUnless
- storage = self._storage
- db = DB(storage)
- conn = db.open()
- root = conn.root()
- # Start by storing a root reachable object.
- obj1 = C()
- obj1.value = 888
- root.obj1 = obj1
- txn = get_transaction()
- txn.note('root -> obj1')
- txn.commit()
- # Now, start a transaction, store an object, but don't yet complete
- # the transaction. This will ensure that the second object has a tid
- # < packtime, but it won't be root reachable yet.
- obj2 = C()
- t = Transaction()
- storage.tpc_begin(t)
- obj2sn = storage.store('\0'*7 + '\2', ZERO, zodb_pickle(obj2), '', t)
- # Now, acquire the condvar lock and start a thread that will do a
- # pack, up to the _sweep call. Wait for the _mark() call to
- # complete.
- now = time.time()
- while now == time.time():
- time.sleep(0.5)
- self._cv.acquire()
- packthread = MinimalPackThread(storage)
- packthread.start()
- self._cv.wait()
- # Now that the _mark() has finished, complete the transaction, which
- # links the object to root.
- root.obj2 = obj2
- rootsn = storage.getSerial(ZERO)
- #rootdata = ObjectWriter(root._p_jar).getState(root)
- rootsn = storage.store(ZERO, rootsn, zodb_pickle(root), '', t)
- storage.tpc_vote(t)
- storage.tpc_finish(t)
- # And notify the pack thread that it can do the sweep and collect
- self._cv.notify()
- self._cv.wait()
- # We're done with the condvar and the thread
- self._cv.release()
- packthread.join()
- # Now make sure that all the interesting objects are still available
- rootsn = storage.getSerial(ZERO)
- obj1sn = storage.getSerial('\0'*7 + '\1')
- obj2sn = storage.getSerial('\0'*7 + '\2')
- # obj1 revision was written before the second revision of the root
- unless(obj1sn < rootsn)
- unless(rootsn == obj2sn)
- unless(obj1sn < obj2sn)
+ def _getPackThread(self, storage):
+ return MinimalPackThread(storage)