[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)