def checkZEOInvalidation(self): addr = self._storage._addr storage2 = ClientStorage(addr, wait=1, min_disconnect_poll=0.1) try: oid = self._storage.new_oid() ob = MinPO('first') revid1 = self._dostore(oid, data=ob) data, serial = storage2.load(oid, '') self.assertEqual(zodb_unpickle(data), MinPO('first')) self.assertEqual(serial, revid1) revid2 = self._dostore(oid, data=MinPO('second'), revid=revid1) # Now, storage 2 should eventually get the new data. It # will take some time, although hopefully not much. # We'll poll till we get it and whine if we time out: for n in range(30): time.sleep(.1) data, serial = storage2.load(oid, '') if (serial == revid2 and zodb_unpickle(data) == MinPO('second')): break else: raise AssertionError('Invalidation message was not sent!') finally: storage2.close()
def checkTwoObjectUndoAgain(self): eq = self.assertEqual p31, p32, p33, p51, p52, p53 = map( zodb_pickle, map(MinPO, (31, 32, 33, 51, 52, 53))) # Like the above, but the first revision of the objects are stored in # different transactions. oid1 = self._storage.new_oid() oid2 = self._storage.new_oid() revid1 = self._dostore(oid1, data=p31, already_pickled=1) revid2 = self._dostore(oid2, data=p51, already_pickled=1) # Update those same two objects t = Transaction() self._storage.tpc_begin(t) self._transaction_begin() self._transaction_store(oid1, revid1, p32, '', t) self._transaction_store(oid2, revid2, p52, '', t) # Finish the transaction self._transaction_vote(t) self._storage.tpc_finish(t) revid1 = self._transaction_newserial(oid1) revid2 = self._transaction_newserial(oid2) eq(revid1, revid2) # Now attempt to undo the transaction containing two objects info = self._storage.undoInfo() self._undo(info[0]["id"], [oid1, oid2]) data, revid1 = self._storage.load(oid1, '') eq(zodb_unpickle(data), MinPO(31)) data, revid2 = self._storage.load(oid2, '') eq(zodb_unpickle(data), MinPO(51)) # Like the above, but this time, the second transaction contains only # one object. t = Transaction() self._storage.tpc_begin(t) self._transaction_begin() self._transaction_store(oid1, revid1, p33, '', t) self._transaction_store(oid2, revid2, p53, '', t) # Finish the transaction self._transaction_vote(t) self._storage.tpc_finish(t) revid1 = self._transaction_newserial(oid1) revid2 = self._transaction_newserial(oid2) eq(revid1, revid2) # Update in different transactions revid1 = self._dostore(oid1, revid=revid1, data=MinPO(34)) revid2 = self._dostore(oid2, revid=revid2, data=MinPO(54)) # Now attempt to undo the transaction containing two objects info = self._storage.undoInfo() tid = info[1]['id'] t = Transaction() oids = self._begin_undos_vote(t, tid) self._storage.tpc_finish(t) eq(len(oids), 1) self.assertTrue(oid1 in oids) self.assertTrue(not oid2 in oids) data, revid1 = self._storage.load(oid1, '') eq(zodb_unpickle(data), MinPO(33)) data, revid2 = self._storage.load(oid2, '') eq(zodb_unpickle(data), MinPO(54)) self._iterate()
def checkRecoverUndoInVersion(self): oid = self._storage.new_oid() version = "aVersion" revid_a = self._dostore(oid, data=MinPO(91)) revid_b = self._dostore(oid, revid=revid_a, version=version, data=MinPO(92)) revid_c = self._dostore(oid, revid=revid_b, version=version, data=MinPO(93)) self._undo(self._storage.undoInfo()[0]['id'], [oid]) self._commitVersion(version, '') self._undo(self._storage.undoInfo()[0]['id'], [oid]) # now copy the records to a new storage self._dst.copyTransactionsFrom(self._storage) self.compare(self._storage, self._dst) # The last two transactions were applied directly rather than # copied. So we can't use compare() to verify that they new # transactions are applied correctly. (The new transactions # will have different timestamps for each storage.) self._abortVersion(version) self.assert_(self._storage.versionEmpty(version)) self._undo(self._storage.undoInfo()[0]['id'], [oid]) self.assert_(not self._storage.versionEmpty(version)) # check the data is what we expect it to be data, revid = self._storage.load(oid, version) self.assertEqual(zodb_unpickle(data), MinPO(92)) data, revid = self._storage.load(oid, '') self.assertEqual(zodb_unpickle(data), MinPO(91)) # and swap the storages tmp = self._storage self._storage = self._dst self._abortVersion(version) self.assert_(self._storage.versionEmpty(version)) self._undo(self._storage.undoInfo()[0]['id'], [oid]) self.assert_(not self._storage.versionEmpty(version)) # check the data is what we expect it to be data, revid = self._storage.load(oid, version) self.assertEqual(zodb_unpickle(data), MinPO(92)) data, revid = self._storage.load(oid, '') self.assertEqual(zodb_unpickle(data), MinPO(91)) # swap them back self._storage = tmp # Now remove _dst and copy all the transactions a second time. # This time we will be able to confirm via compare(). self._dst.close() self._dst.cleanup() self._dst = self.new_dest() self._dst.copyTransactionsFrom(self._storage) self.compare(self._storage, self._dst)
def checkSimpleTransactionalUndo(self): eq = self.assertEqual oid = self._storage.new_oid() revid = self._dostore(oid, data=MinPO(23)) revid = self._dostore(oid, revid=revid, data=MinPO(24)) revid = self._dostore(oid, revid=revid, data=MinPO(25)) info = self._storage.undoInfo() # Now start an undo transaction self._undo(info[0]["id"], [oid], note="undo1") data, revid = load_current(self._storage, oid) eq(zodb_unpickle(data), MinPO(24)) # Do another one info = self._storage.undoInfo() self._undo(info[2]["id"], [oid], note="undo2") data, revid = load_current(self._storage, oid) eq(zodb_unpickle(data), MinPO(23)) # Try to undo the first record info = self._storage.undoInfo() self._undo(info[4]["id"], [oid], note="undo3") # This should fail since we've undone the object's creation self.assertRaises(KeyError, load_current, self._storage, oid) # And now let's try to redo the object's creation info = self._storage.undoInfo() self._undo(info[0]["id"], [oid]) data, revid = load_current(self._storage, oid) eq(zodb_unpickle(data), MinPO(23)) self._iterate()
def checkSimpleTransactionalUndo(self): eq = self.assertEqual oid = self._storage.new_oid() revid = self._dostore(oid, data=MinPO(23)) revid = self._dostore(oid, revid=revid, data=MinPO(24)) revid = self._dostore(oid, revid=revid, data=MinPO(25)) info = self._storage.undoInfo() # Now start an undo transaction self._undo(info[0]["id"], [oid], note="undo1") data, revid = load_current(self._storage, oid) eq(zodb_unpickle(data), MinPO(24)) # Do another one info = self._storage.undoInfo() self._undo(info[2]["id"], [oid], note="undo2") data, revid = load_current(self._storage, oid) eq(zodb_unpickle(data), MinPO(23)) # Try to undo the first record info = self._storage.undoInfo() self._undo(info[4]["id"], [oid], note="undo3") # This should fail since we've undone the object's creation self.assertRaises(KeyError, load_current, self._storage, oid) # And now let's try to redo the object's creation info = self._storage.undoInfo() self._undo(info[0]["id"], [oid]) data, revid = load_current(self._storage, oid) eq(zodb_unpickle(data), MinPO(23)) self._iterate()
def checkUndoInVersion(self): def check_objects(nonversiondata, versiondata): data, revid = self._storage.load(oid, version) self.assertEqual(zodb_unpickle(data), MinPO(versiondata)) data, revid = self._storage.load(oid, '') self.assertEqual(zodb_unpickle(data), MinPO(nonversiondata)) oid = self._storage.new_oid() version = 'one' revid_a = self._dostore(oid, data=MinPO(91)) revid_b = self._dostore(oid, revid=revid_a, data=MinPO(92), version=version) revid_c = self._dostore(oid, revid=revid_b, data=MinPO(93), version=version) info = self._storage.undoInfo() self._undo(info[0]['id'], oid) data, revid = self._storage.load(oid, '') assert revid == revid_a assert zodb_unpickle(data) == MinPO(91) data, revid = self._storage.load(oid, version) assert revid > revid_b and revid > revid_c assert zodb_unpickle(data) == MinPO(92) # Now commit the version... t = Transaction() self._storage.tpc_begin(t) oids = self._storage.commitVersion(version, '', t) self._storage.tpc_vote(t) self._storage.tpc_finish(t) assert len(oids) == 1 assert oids[0] == oid check_objects(92, 92) # ...and undo the commit info = self._storage.undoInfo() self._undo(info[0]['id'], oid) check_objects(91, 92) # Now abort the version t = Transaction() self._storage.tpc_begin(t) oids = self._storage.abortVersion(version, t) self._storage.tpc_vote(t) self._storage.tpc_finish(t) assert len(oids) == 1 assert oids[0] == oid check_objects(91, 91) # Now undo the abort info=self._storage.undoInfo() self._undo(info[0]['id'], oid) # And the object should be back in versions 'one' and '' check_objects(91, 92)
def checkUndoCreationBranch2(self): eq = self.assertEqual oid = self._storage.new_oid() revid = self._dostore(oid, data=MinPO(11)) revid = self._dostore(oid, revid=revid, data=MinPO(12)) # Undo the last transaction info = self._storage.undoInfo() tid = info[0]['id'] t = Transaction() self._storage.tpc_begin(t) oids = self._storage.transactionalUndo(tid, t) self._storage.tpc_vote(t) self._storage.tpc_finish(t) eq(len(oids), 1) eq(oids[0], oid) data, revid = self._storage.load(oid, '') eq(zodb_unpickle(data), MinPO(11)) # Now from here, we can either redo the last undo, or undo the object # creation. Let's redo the last undo info = self._storage.undoInfo() tid = info[0]['id'] t = Transaction() self._storage.tpc_begin(t) oids = self._storage.transactionalUndo(tid, t) self._storage.tpc_vote(t) self._storage.tpc_finish(t) eq(len(oids), 1) eq(oids[0], oid) data, revid = self._storage.load(oid, '') eq(zodb_unpickle(data), MinPO(12)) self._iterate()
def checkTwoObjectUndoAgain(self): eq = self.assertEqual p31, p32, p33, p51, p52, p53 = map( zodb_pickle, map(MinPO, (31, 32, 33, 51, 52, 53))) # Like the above, but the first revision of the objects are stored in # different transactions. oid1 = self._storage.new_oid() oid2 = self._storage.new_oid() revid1 = self._dostore(oid1, data=p31, already_pickled=1) revid2 = self._dostore(oid2, data=p51, already_pickled=1) # Update those same two objects t = Transaction() self._storage.tpc_begin(t) self._transaction_begin() self._transaction_store(oid1, revid1, p32, '', t) self._transaction_store(oid2, revid2, p52, '', t) # Finish the transaction self._transaction_vote(t) self._storage.tpc_finish(t) revid1 = self._transaction_newserial(oid1) revid2 = self._transaction_newserial(oid2) eq(revid1, revid2) # Now attempt to undo the transaction containing two objects info = self._storage.undoInfo() self._undo(info[0]["id"], [oid1, oid2]) data, revid1 = self._storage.load(oid1, '') eq(zodb_unpickle(data), MinPO(31)) data, revid2 = self._storage.load(oid2, '') eq(zodb_unpickle(data), MinPO(51)) # Like the above, but this time, the second transaction contains only # one object. t = Transaction() self._storage.tpc_begin(t) self._transaction_begin() self._transaction_store(oid1, revid1, p33, '', t) self._transaction_store(oid2, revid2, p53, '', t) # Finish the transaction self._transaction_vote(t) self._storage.tpc_finish(t) revid1 = self._transaction_newserial(oid1) revid2 = self._transaction_newserial(oid2) eq(revid1, revid2) # Update in different transactions revid1 = self._dostore(oid1, revid=revid1, data=MinPO(34)) revid2 = self._dostore(oid2, revid=revid2, data=MinPO(54)) # Now attempt to undo the transaction containing two objects info = self._storage.undoInfo() tid = info[1]['id'] t = Transaction() oids = self._begin_undos_vote(t, tid) self._storage.tpc_finish(t) eq(len(oids), 1) self.failUnless(oid1 in oids) self.failUnless(not oid2 in oids) data, revid1 = self._storage.load(oid1, '') eq(zodb_unpickle(data), MinPO(33)) data, revid2 = self._storage.load(oid2, '') eq(zodb_unpickle(data), MinPO(54)) self._iterate()
def checkVerificationInvalidationPersists(self): # This tests a subtle invalidation bug from ZODB 3.3: # invalidations processed as part of ZEO cache verification acted # kinda OK wrt the in-memory cache structures, but had no effect # on the cache file. So opening the file cache again could # incorrectly believe that a previously invalidated object was # still current. This takes some effort to set up. # First, using a persistent cache ('test'), create an object # MinPO(13). We used to see this again at the end of this test, # despite that we modify it, and despite that it gets invalidated # in 'test', before the end. self._storage = self.openClientStorage('test') oid = self._storage.new_oid() obj = MinPO(13) self._dostore(oid, data=obj) self._storage.close() # Now modify obj via a temp connection. `test` won't learn about # this until we open a connection using `test` again. self._storage = self.openClientStorage() pickle, rev = self._storage.load(oid, '') newobj = zodb_unpickle(pickle) self.assertEqual(newobj, obj) newobj.value = 42 # .value *should* be 42 forever after now, not 13 self._dostore(oid, data=newobj, revid=rev) self._storage.close() # Open 'test' again. `oid` in this cache should be (and is) # invalidated during cache verification. The bug was that it # got invalidated (kinda) in memory, but not in the cache file. self._storage = self.openClientStorage('test') # The invalidation happened already. Now create and store a new # object before closing this storage: this is so `test` believes # it's seen transactions beyond the one that invalidated `oid`, so # that the *next* time we open `test` it doesn't process another # invalidation for `oid`. It's also important that we not try to # load `oid` now: because it's been (kinda) invalidated in the # cache's memory structures, loading it now would fetch the # current revision from the server, thus hiding the bug. obj2 = MinPO(666) oid2 = self._storage.new_oid() self._dostore(oid2, data=obj2) self._storage.close() # Finally, open `test` again and load `oid`. `test` believes # it's beyond the transaction that modified `oid`, so its view # of whether it has an up-to-date `oid` comes solely from the disk # file, unaffected by cache verification. self._storage = self.openClientStorage('test') pickle, rev = self._storage.load(oid, '') newobj_copy = zodb_unpickle(pickle) # This used to fail, with # AssertionError: MinPO(13) != MinPO(42) # That is, `test` retained a stale revision of the object on disk. self.assertEqual(newobj_copy, newobj) self._storage.close()
def checkVerificationInvalidationPersists(self): # This tests a subtle invalidation bug from ZODB 3.3: # invalidations processed as part of ZEO cache verification acted # kinda OK wrt the in-memory cache structures, but had no effect # on the cache file. So opening the file cache again could # incorrectly believe that a previously invalidated object was # still current. This takes some effort to set up. # First, using a persistent cache ('test'), create an object # MinPO(13). We used to see this again at the end of this test, # despite that we modify it, and despite that it gets invalidated # in 'test', before the end. self._storage = self.openClientStorage('test') oid = self._storage.new_oid() obj = MinPO(13) self._dostore(oid, data=obj) self._storage.close() # Now modify obj via a temp connection. `test` won't learn about # this until we open a connection using `test` again. self._storage = self.openClientStorage() pickle, rev = self._storage.load(oid, '') newobj = zodb_unpickle(pickle) self.assertEqual(newobj, obj) newobj.value = 42 # .value *should* be 42 forever after now, not 13 self._dostore(oid, data=newobj, revid=rev) self._storage.close() # Open 'test' again. `oid` in this cache should be (and is) # invalidated during cache verification. The bug was that it # got invalidated (kinda) in memory, but not in the cache file. self._storage = self.openClientStorage('test') # The invalidation happened already. Now create and store a new # object before closing this storage: this is so `test` believes # it's seen transactions beyond the one that invalidated `oid`, so # that the *next* time we open `test` it doesn't process another # invalidation for `oid`. It's also important that we not try to # load `oid` now: because it's been (kinda) invalidated in the # cache's memory structures, loading it now would fetch the # current revision from the server, thus hiding the bug. obj2 = MinPO(666) oid2 = self._storage.new_oid() self._dostore(oid2, data=obj2) self._storage.close() # Finally, open `test` again and load `oid`. `test` believes # it's beyond the transaction that modified `oid`, so its view # of whether it has an up-to-date `oid` comes solely from the disk # file, unaffected by cache verification. self._storage = self.openClientStorage('test') pickle, rev = self._storage.load(oid, '') newobj_copy = zodb_unpickle(pickle) # This used to fail, with # AssertionError: MinPO(13) != MinPO(42) # That is, `test` retained a stale revision of the object on disk. self.assertEqual(newobj_copy, newobj) self._storage.close()
def checkNotUndoable(self): eq = self.assertEqual # Set things up so we've got a transaction that can't be undone oid = self._storage.new_oid() revid_a = self._dostore(oid, data=MinPO(51)) revid_b = self._dostore(oid, revid=revid_a, data=MinPO(52)) revid_c = self._dostore(oid, revid=revid_b, data=MinPO(53)) # Start the undo info = self._storage.undoInfo() tid = info[1]['id'] t = Transaction() self._storage.tpc_begin(t) self.assertRaises(POSException.UndoError, self._storage.undo, tid, t) self._storage.tpc_abort(t) # Now have more fun: object1 and object2 are in the same transaction, # which we'll try to undo to, but one of them has since modified in # different transaction, so the undo should fail. oid1 = oid revid1 = revid_c oid2 = self._storage.new_oid() revid2 = ZERO p81, p82, p91, p92 = map(zodb_pickle, map(MinPO, (81, 82, 91, 92))) t = Transaction() self._storage.tpc_begin(t) self._transaction_begin() self._transaction_store(oid1, revid1, p81, '', t) self._transaction_store(oid2, revid2, p91, '', t) self._transaction_vote(t) self._storage.tpc_finish(t) revid1 = self._transaction_newserial(oid1) revid2 = self._transaction_newserial(oid2) eq(revid1, revid2) # Make sure the objects have the expected values data, revid_11 = self._storage.load(oid1, '') eq(zodb_unpickle(data), MinPO(81)) data, revid_22 = self._storage.load(oid2, '') eq(zodb_unpickle(data), MinPO(91)) eq(revid_11, revid1) eq(revid_22, revid2) # Now modify oid2 revid2 = self._dostore(oid2, revid=revid2, data=MinPO(92)) self.assertNotEqual(revid1, revid2) self.assertNotEqual(revid2, revid_22) info = self._storage.undoInfo() tid = info[1]['id'] t = Transaction() self._storage.tpc_begin(t) self.assertRaises(POSException.UndoError, self._storage.undo, tid, t) self._storage.tpc_abort(t) self._iterate()
def checkRecoverUndoInVersion(self): oid = self._storage.new_oid() version = "aVersion" revid_a = self._dostore(oid, data=MinPO(91)) revid_b = self._dostore(oid, revid=revid_a, version=version, data=MinPO(92)) revid_c = self._dostore(oid, revid=revid_b, version=version, data=MinPO(93)) self._undo(self._storage.undoInfo()[0]['id'], [oid]) self._commitVersion(version, '') self._undo(self._storage.undoInfo()[0]['id'], [oid]) # now copy the records to a new storage self._dst.copyTransactionsFrom(self._storage) self.compare(self._storage, self._dst) # The last two transactions were applied directly rather than # copied. So we can't use compare() to verify that they new # transactions are applied correctly. (The new transactions # will have different timestamps for each storage.) self._abortVersion(version) self.assert_(self._storage.versionEmpty(version)) self._undo(self._storage.undoInfo()[0]['id'], [oid]) self.assert_(not self._storage.versionEmpty(version)) # check the data is what we expect it to be data, revid = self._storage.load(oid, version) self.assertEqual(zodb_unpickle(data), MinPO(92)) data, revid = self._storage.load(oid, '') self.assertEqual(zodb_unpickle(data), MinPO(91)) # and swap the storages tmp = self._storage self._storage = self._dst self._abortVersion(version) self.assert_(self._storage.versionEmpty(version)) self._undo(self._storage.undoInfo()[0]['id'], [oid]) self.assert_(not self._storage.versionEmpty(version)) # check the data is what we expect it to be data, revid = self._storage.load(oid, version) self.assertEqual(zodb_unpickle(data), MinPO(92)) data, revid = self._storage.load(oid, '') self.assertEqual(zodb_unpickle(data), MinPO(91)) # swap them back self._storage = tmp # Now remove _dst and copy all the transactions a second time. # This time we will be able to confirm via compare(). self._dst.close() self._dst.cleanup() self._dst = self.new_dest() self._dst.copyTransactionsFrom(self._storage) self.compare(self._storage, self._dst)
def checkNotUndoable(self): eq = self.assertEqual # Set things up so we've got a transaction that can't be undone oid = self._storage.new_oid() revid_a = self._dostore(oid, data=MinPO(51)) revid_b = self._dostore(oid, revid=revid_a, data=MinPO(52)) revid_c = self._dostore(oid, revid=revid_b, data=MinPO(53)) # Start the undo info = self._storage.undoInfo() tid = info[1]['id'] t = Transaction() self._storage.tpc_begin(t) self.assertRaises(POSException.UndoError, self._storage.undo, tid, t) self._storage.tpc_abort(t) # Now have more fun: object1 and object2 are in the same transaction, # which we'll try to undo to, but one of them has since modified in # different transaction, so the undo should fail. oid1 = oid revid1 = revid_c oid2 = self._storage.new_oid() revid2 = ZERO p81, p82, p91, p92 = map(zodb_pickle, map(MinPO, (81, 82, 91, 92))) t = Transaction() self._storage.tpc_begin(t) self._transaction_begin() self._transaction_store(oid1, revid1, p81, '', t) self._transaction_store(oid2, revid2, p91, '', t) self._transaction_vote(t) self._storage.tpc_finish(t) revid1 = self._transaction_newserial(oid1) revid2 = self._transaction_newserial(oid2) eq(revid1, revid2) # Make sure the objects have the expected values data, revid_11 = self._storage.load(oid1, '') eq(zodb_unpickle(data), MinPO(81)) data, revid_22 = self._storage.load(oid2, '') eq(zodb_unpickle(data), MinPO(91)) eq(revid_11, revid1) eq(revid_22, revid2) # Now modify oid2 revid2 = self._dostore(oid2, revid=revid2, data=MinPO(92)) self.assertNotEqual(revid1, revid2) self.assertNotEqual(revid2, revid_22) info = self._storage.undoInfo() tid = info[1]['id'] t = Transaction() self._storage.tpc_begin(t) self.assertRaises(POSException.UndoError, self._storage.undo, tid, t) self._storage.tpc_abort(t) self._iterate()
def checkCommitToNonVersion(self): eq = self.assertEqual oid, version = self._setup_version() data, revid = self._storage.load(oid, version) eq(zodb_unpickle(data), MinPO(54)) data, revid = self._storage.load(oid, '') eq(zodb_unpickle(data), MinPO(51)) self._commitVersion(version, '') data, revid = self._storage.load(oid, '') eq(zodb_unpickle(data), MinPO(54))
def checkCommitToOtherVersion(self): eq = self.assertEqual oid1, version1 = self._setup_version('one') data, revid1 = self._storage.load(oid1, version1) eq(zodb_unpickle(data), MinPO(54)) oid2, version2 = self._setup_version('two') data, revid2 = self._storage.load(oid2, version2) eq(zodb_unpickle(data), MinPO(54)) # make sure we see the non-version data when appropriate data, revid2 = self._storage.load(oid1, version2) eq(zodb_unpickle(data), MinPO(51)) data, revid2 = self._storage.load(oid2, version1) eq(zodb_unpickle(data), MinPO(51)) data, revid2 = self._storage.load(oid1, '') eq(zodb_unpickle(data), MinPO(51)) # Okay, now let's commit object1 to version2 oids = self._commitVersion(version1, version2) eq(len(oids), 1) eq(oids[0], oid1) data, revid = self._storage.load(oid1, version2) eq(zodb_unpickle(data), MinPO(54)) data, revid = self._storage.load(oid2, version2) eq(zodb_unpickle(data), MinPO(54)) # an object can only exist in one version, so a load from # version1 should now give the non-version data data, revid2 = self._storage.load(oid1, version1) eq(zodb_unpickle(data), MinPO(51)) # as should a version that has never been used data, revid2 = self._storage.load(oid1, 'bela lugosi') eq(zodb_unpickle(data), MinPO(51))
def checkTwoObjectUndo(self): eq = self.assertEqual # Convenience p31, p32, p51, p52 = map(zodb_pickle, map(MinPO, (31, 32, 51, 52))) oid1 = self._storage.new_oid() oid2 = self._storage.new_oid() revid1 = revid2 = ZERO # Store two objects in the same transaction t = Transaction() self._storage.tpc_begin(t) self._transaction_begin() self._transaction_store(oid1, revid1, p31, '', t) self._transaction_store(oid2, revid2, p51, '', t) # Finish the transaction self._transaction_vote(t) revid1 = self._transaction_newserial(oid1) revid2 = self._transaction_newserial(oid2) self._storage.tpc_finish(t) eq(revid1, revid2) # Update those same two objects t = Transaction() self._storage.tpc_begin(t) self._transaction_begin() self._transaction_store(oid1, revid1, p32, '', t) self._transaction_store(oid2, revid2, p52, '', t) # Finish the transaction self._transaction_vote(t) revid1 = self._transaction_newserial(oid1) revid2 = self._transaction_newserial(oid2) self._storage.tpc_finish(t) eq(revid1, revid2) # Make sure the objects have the current value data, revid1 = self._storage.load(oid1, '') eq(zodb_unpickle(data), MinPO(32)) data, revid2 = self._storage.load(oid2, '') eq(zodb_unpickle(data), MinPO(52)) # Now attempt to undo the transaction containing two objects info = self._storage.undoInfo() tid = info[0]['id'] t = Transaction() self._storage.tpc_begin(t) oids = self._storage.transactionalUndo(tid, t) self._storage.tpc_vote(t) self._storage.tpc_finish(t) eq(len(oids), 2) self.failUnless(oid1 in oids) self.failUnless(oid2 in oids) data, revid1 = self._storage.load(oid1, '') eq(zodb_unpickle(data), MinPO(31)) data, revid2 = self._storage.load(oid2, '') eq(zodb_unpickle(data), MinPO(51)) self._iterate()
def checkStoreAndLoad(self): eq = self.assertEqual oid = self._storage.new_oid() self._dostore(oid=oid, data=MinPO(7)) data, revid = utils.load_current(self._storage, oid) value = zodb_unpickle(data) eq(value, MinPO(7)) # Now do a bunch of updates to an object for i in range(13, 22): revid = self._dostore(oid, revid=revid, data=MinPO(i)) # Now get the latest revision of the object data, revid = utils.load_current(self._storage, oid) eq(zodb_unpickle(data), MinPO(21))
def checkStoreAndLoad(self): eq = self.assertEqual oid = self._storage.new_oid() self._dostore(oid=oid, data=MinPO(7)) data, revid = self._storage.load(oid, "") value = zodb_unpickle(data) eq(value, MinPO(7)) # Now do a bunch of updates to an object for i in range(13, 22): revid = self._dostore(oid, revid=revid, data=MinPO(i)) # Now get the latest revision of the object data, revid = self._storage.load(oid, "") eq(zodb_unpickle(data), MinPO(21))
def checkUndoInvalidation(self): oid = self._storage.new_oid() revid = self._dostore(oid, data=MinPO(23)) revid = self._dostore(oid, revid=revid, data=MinPO(24)) revid = self._dostore(oid, revid=revid, data=MinPO(25)) info = self._storage.undoInfo() if not info: # Preserved this comment, but don't understand it: # "Perhaps we have an old storage implementation that # does do the negative nonsense." info = self._storage.undoInfo(0, 20) tid = info[0]['id'] # Now start an undo transaction t = TransactionMetaData() t.note(u'undo1') oids = self._begin_undos_vote(t, tid) # Make sure this doesn't load invalid data into the cache self._storage.load(oid, '') self._storage.tpc_finish(t) [uoid] = oids assert uoid == oid data, revid = self._storage.load(oid, '') obj = zodb_unpickle(data) assert obj == MinPO(24)
def checkUndoInvalidation(self): oid = self._storage.new_oid() revid = self._dostore(oid, data=MinPO(23)) revid = self._dostore(oid, revid=revid, data=MinPO(24)) revid = self._dostore(oid, revid=revid, data=MinPO(25)) info = self._storage.undoInfo() if not info: # Preserved this comment, but don't understand it: # "Perhaps we have an old storage implementation that # does do the negative nonsense." info = self._storage.undoInfo(0, 20) tid = info[0]['id'] # Now start an undo transaction t = Transaction() t.note('undo1') self._storage.tpc_begin(t) tid, oids = self._storage.undo(tid, t) # Make sure this doesn't load invalid data into the cache self._storage.load(oid, '') self._storage.tpc_vote(t) self._storage.tpc_finish(t) assert len(oids) == 1 assert oids[0] == oid data, revid = self._storage.load(oid, '') obj = zodb_unpickle(data) assert obj == MinPO(24)
def checkResolveConflictBetweenConnections(self): # Verify that conflict resolution works between storage instances # bound to connections. obj = ConflictResolution.PCounter() obj.inc() oid = self._storage.new_oid() revid1 = self._dostoreNP(oid, data=zodb_pickle(obj)) storage1 = self._storage.bind_connection(None) storage1.load(oid, '') storage2 = self._storage.bind_connection(None) storage2.load(oid, '') obj.inc() obj.inc() # The effect of committing two transactions with the same # pickle is to commit two different transactions relative to # revid1 that add two to _value. root_storage = self._storage try: self._storage = storage1 revid2 = self._dostoreNP(oid, revid=revid1, data=zodb_pickle(obj)) self._storage = storage2 revid3 = self._dostoreNP(oid, revid=revid1, data=zodb_pickle(obj)) data, serialno = self._storage.load(oid, '') inst = zodb_unpickle(data) self.assertEqual(inst._value, 5) finally: self._storage = root_storage
def checkAbortVersionErrors(self): eq = self.assertEqual oid, version = self._setup_version() # Now abort a bogus version t = Transaction() self._storage.tpc_begin(t) #JF# The spec is silent on what happens if you abort or commit #JF# a non-existent version. FileStorage consideres this a noop. #JF# We can change the spec, but until we do .... #JF# self.assertRaises(POSException.VersionError, #JF# self._storage.abortVersion, #JF# 'bogus', t) # And try to abort the empty version if (hasattr(self._storage, 'supportsTransactionalUndo') and self._storage.supportsTransactionalUndo()): # XXX FileStorage used to be broken on this one self.assertRaises(POSException.VersionError, self._storage.abortVersion, '', t) # But now we really try to abort the version oids = self._storage.abortVersion(version, t) self._storage.tpc_vote(t) self._storage.tpc_finish(t) eq(len(oids), 1) eq(oids[0], oid) data, revid = self._storage.load(oid, '') eq(zodb_unpickle(data), MinPO(51))
def checkTransactionalUndoAfterPack(self): eq = self.assertEqual # Add a few object revisions oid = self._storage.new_oid() revid1 = self._dostore(oid, data=MinPO(51)) packtime = time.time() snooze() # time.time() now distinct from packtime revid2 = self._dostore(oid, revid=revid1, data=MinPO(52)) self._dostore(oid, revid=revid2, data=MinPO(53)) # Now get the undo log info = self._storage.undoInfo() eq(len(info), 3) tid = info[0]['id'] # Now pack just the initial revision of the object. We need the # second revision otherwise we won't be able to undo the third # revision! self._storage.pack(packtime, referencesf) # Make some basic assertions about the undo information now info2 = self._storage.undoInfo() eq(len(info2), 2) # And now attempt to undo the last transaction t = Transaction() self._storage.tpc_begin(t) tid, oids = self._storage.undo(tid, t) self._storage.tpc_vote(t) self._storage.tpc_finish(t) eq(len(oids), 1) eq(oids[0], oid) data, revid = self._storage.load(oid, '') # The object must now be at the second state eq(zodb_unpickle(data), MinPO(52)) self._iterate()
def checkLoadBeforeConsecutiveTids(self): eq = self.assertEqual oid = self._storage.new_oid() def helper(tid, revid, x): data = zodb_pickle(MinPO(x)) t = transaction.Transaction() try: self._storage.tpc_begin(t, p64(tid)) r1 = self._storage.store(oid, revid, data, '', t) # Finish the transaction r2 = self._storage.tpc_vote(t) newrevid = handle_serials(oid, r1, r2) self._storage.tpc_finish(t) except: self._storage.tpc_abort(t) raise return newrevid revid1 = helper(1, None, 1) revid2 = helper(2, revid1, 2) revid3 = helper(3, revid2, 3) data, start_tid, end_tid = self._storage.loadBefore(oid, p64(2)) eq(zodb_unpickle(data), MinPO(1)) eq(u64(start_tid), 1) eq(u64(end_tid), 2)
def checkResolveConflictBetweenConnections(self): # Verify that conflict resolution works between storage instances # bound to connections. obj = ConflictResolution.PCounter() obj.inc() oid = self._storage.new_oid() revid1 = self._dostoreNP(oid, data=zodb_pickle(obj)) storage1 = self._storage.new_instance() storage1.load(oid, '') storage2 = self._storage.new_instance() storage2.load(oid, '') obj.inc() obj.inc() # The effect of committing two transactions with the same # pickle is to commit two different transactions relative to # revid1 that add two to _value. root_storage = self._storage try: self._storage = storage1 _revid2 = self._dostoreNP(oid, revid=revid1, data=zodb_pickle(obj)) self._storage = storage2 _revid3 = self._dostoreNP(oid, revid=revid1, data=zodb_pickle(obj)) data, _serialno = self._storage.load(oid, '') inst = zodb_unpickle(data) self.assertEqual(inst._value, 5) finally: storage1.close() storage2.close() self._storage = root_storage
def checkTransactionalUndoAfterPack(self): eq = self.assertEqual # Add a few object revisions oid = self._storage.new_oid() revid1 = self._dostore(oid, data=MinPO(51)) packtime = time.time() snooze() # time.time() now distinct from packtime revid2 = self._dostore(oid, revid=revid1, data=MinPO(52)) self._dostore(oid, revid=revid2, data=MinPO(53)) # Now get the undo log info = self._storage.undoInfo() eq(len(info), 3) tid = info[0]['id'] # Now pack just the initial revision of the object. We need the # second revision otherwise we won't be able to undo the third # revision! self._storage.pack(packtime, referencesf) # Make some basic assertions about the undo information now info2 = self._storage.undoInfo() eq(len(info2), 2) # And now attempt to undo the last transaction t = Transaction() self._storage.tpc_begin(t) tid, oids = self._storage.undo(tid, t) self._storage.tpc_vote(t) self._storage.tpc_finish(t) eq(len(oids), 1) eq(oids[0], oid) data, revid = self._storage.load(oid, '') # The object must now be at the second state eq(zodb_unpickle(data), MinPO(52)) self._iterate()
def checkRSResolve(self): # ZODB.tests.ConflictResolution.ConflictResolvingStorage has a checkResolve # with a different signature (as of 4.4.0) that we were unintentionally(?) # shadowing, hence the weird name. obj = PCounter() obj.inc() oid = self._storage.new_oid() revid1 = self._dostoreNP(oid, data=zodb_pickle(obj)) obj.inc() obj.inc() # The effect of committing two transactions with the same # pickle is to commit two different transactions relative to # revid1 that add two to _value. # open s1 at this point of time. s1 = self._storage.new_instance() # start a load transaction in s1 s1.poll_invalidations() # commit a change not visible to s1 _revid2 = self._dostoreNP(oid, revid=revid1, data=zodb_pickle(obj)) # commit a conflicting change using s1 main_storage = self._storage self._storage = s1 try: # we can resolve this conflict because s1 has an open # transaction that can read the old state of the object. _revid3 = self._dostoreNP(oid, revid=revid1, data=zodb_pickle(obj)) s1.release() finally: self._storage = main_storage # If we don't restart our load connection, # we will still read the old state. data, _serialno = self._storage.load(oid, '') inst = zodb_unpickle(data) self.assertEqual(inst._value, 3) self._storage.poll_invalidations() data, _serialno = self._storage.load(oid, '') inst = zodb_unpickle(data) self.assertEqual(inst._value, 5)
def checkUndoCreationBranch2(self): eq = self.assertEqual oid = self._storage.new_oid() revid = self._dostore(oid, data=MinPO(11)) revid = self._dostore(oid, revid=revid, data=MinPO(12)) # Undo the last transaction info = self._storage.undoInfo() self._undo(info[0]['id'], [oid]) data, revid = load_current(self._storage, oid) eq(zodb_unpickle(data), MinPO(11)) # Now from here, we can either redo the last undo, or undo the object # creation. Let's redo the last undo info = self._storage.undoInfo() self._undo(info[0]['id'], [oid]) data, revid = load_current(self._storage, oid) eq(zodb_unpickle(data), MinPO(12)) self._iterate()
def checkUndoCreationBranch2(self): eq = self.assertEqual oid = self._storage.new_oid() revid = self._dostore(oid, data=MinPO(11)) revid = self._dostore(oid, revid=revid, data=MinPO(12)) # Undo the last transaction info = self._storage.undoInfo() self._undo(info[0]['id'], [oid]) data, revid = load_current(self._storage, oid) eq(zodb_unpickle(data), MinPO(11)) # Now from here, we can either redo the last undo, or undo the object # creation. Let's redo the last undo info = self._storage.undoInfo() self._undo(info[0]['id'], [oid]) data, revid = load_current(self._storage, oid) eq(zodb_unpickle(data), MinPO(12)) self._iterate()
def checkTwoObjectUndo(self): eq = self.assertEqual # Convenience p31, p32, p51, p52 = map(zodb_pickle, map(MinPO, (31, 32, 51, 52))) oid1 = self._storage.new_oid() oid2 = self._storage.new_oid() revid1 = revid2 = ZERO # Store two objects in the same transaction t = Transaction() self._storage.tpc_begin(t) self._transaction_begin() self._transaction_store(oid1, revid1, p31, '', t) self._transaction_store(oid2, revid2, p51, '', t) # Finish the transaction self._transaction_vote(t) revid1 = self._transaction_newserial(oid1) revid2 = self._transaction_newserial(oid2) self._storage.tpc_finish(t) eq(revid1, revid2) # Update those same two objects t = Transaction() self._storage.tpc_begin(t) self._transaction_begin() self._transaction_store(oid1, revid1, p32, '', t) self._transaction_store(oid2, revid2, p52, '', t) # Finish the transaction self._transaction_vote(t) revid1 = self._transaction_newserial(oid1) revid2 = self._transaction_newserial(oid2) self._storage.tpc_finish(t) eq(revid1, revid2) # Make sure the objects have the current value data, revid1 = self._storage.load(oid1, '') eq(zodb_unpickle(data), MinPO(32)) data, revid2 = self._storage.load(oid2, '') eq(zodb_unpickle(data), MinPO(52)) # Now attempt to undo the transaction containing two objects info = self._storage.undoInfo() self._undo(info[0]['id'], [oid1, oid2]) data, revid1 = self._storage.load(oid1, '') eq(zodb_unpickle(data), MinPO(31)) data, revid2 = self._storage.load(oid2, '') eq(zodb_unpickle(data), MinPO(51)) self._iterate()
def checkTwoObjectUndoAgain(self): eq = self.assertEqual p31, p32, p33, p51, p52, p53 = map( zodb_pickle, map(MinPO, (31, 32, 33, 51, 52, 53))) # Like the above, but the first revision of the objects are stored in # different transactions. oid1 = self._storage.new_oid() oid2 = self._storage.new_oid() revid1 = self._dostore(oid1, data=p31, already_pickled=1) revid2 = self._dostore(oid2, data=p51, already_pickled=1) # Update those same two objects t = TransactionMetaData() self._storage.tpc_begin(t) self._storage.store(oid1, revid1, p32, '', t) self._storage.store(oid2, revid2, p52, '', t) # Finish the transaction self._storage.tpc_vote(t) self._storage.tpc_finish(t) # Now attempt to undo the transaction containing two objects info = self._storage.undoInfo() self._undo(info[0]["id"], [oid1, oid2]) data, revid1 = load_current(self._storage, oid1) eq(zodb_unpickle(data), MinPO(31)) data, revid2 = load_current(self._storage, oid2) eq(zodb_unpickle(data), MinPO(51)) # Like the above, but this time, the second transaction contains only # one object. t = TransactionMetaData() self._storage.tpc_begin(t) self._storage.store(oid1, revid1, p33, '', t) self._storage.store(oid2, revid2, p53, '', t) # Finish the transaction self._storage.tpc_vote(t) tid = self._storage.tpc_finish(t) # Update in different transactions revid1 = self._dostore(oid1, revid=tid, data=MinPO(34)) revid2 = self._dostore(oid2, revid=tid, data=MinPO(54)) # Now attempt to undo the transaction containing two objects info = self._storage.undoInfo() self.undo(info[1]['id']) data, revid1 = load_current(self._storage, oid1) eq(zodb_unpickle(data), MinPO(33)) data, revid2 = load_current(self._storage, oid2) eq(zodb_unpickle(data), MinPO(54)) self._iterate()
def checkAbortVersionSerialno(self): oid = self._storage.new_oid() revid1 = self._dostore(oid, data=MinPO(12)) revid2 = self._dostore(oid, revid=revid1, data=MinPO(13), version="version") data, tid, ver = self._storage.loadEx(oid, "version") self.assertEqual(revid2, tid) self.assertEqual(zodb_unpickle(data), MinPO(13)) oids = self._abortVersion("version") self.assertEqual([oid], oids) data, revid3 = self._storage.load(oid, "") # use repr() to avoid getting binary data in a traceback on error self.assertNotEqual(revid1, revid3) self.assertNotEqual(revid2, revid3) data, tid, ver = self._storage.loadEx(oid, "") self.assertEqual(revid3, tid) self.assertEqual(zodb_unpickle(data), MinPO(12)) self.assertEqual(tid, self._storage.lastTransaction())
def checkLoadBeforeVersion(self): eq = self.assertEqual oid = self._storage.new_oid() revid1 = self._dostore(oid, data=1) revid2 = self._dostore(oid, data=2, revid=revid1, version="kobe") revid3 = self._dostore(oid, data=3, revid=revid2, version="kobe") data, start_tid, end_tid = self._storage.loadBefore(oid, revid3) eq(zodb_unpickle(data), MinPO(1)) eq(start_tid, revid1) eq(end_tid, None)
def checkLoadSerial(self): oid = self._storage.new_oid() revid = ZERO revisions = {} for i in range(31, 38): revid = self._dostore(oid, revid=revid, data=MinPO(i)) revisions[revid] = MinPO(i) # Now make sure all the revisions have the correct value for revid, value in revisions.items(): data = self._storage.loadSerial(oid, revid) self.assertEqual(zodb_unpickle(data), value)
def checkLoadSerial(self): oid = self._storage.new_oid() revid = ZERO revisions = {} for i in range(31, 38): revid = self._dostore(oid, revid=revid, data=MinPO(i)) revisions[revid] = MinPO(i) # Now make sure all the revisions have the correct value for revid, value in revisions.items(): data = self._storage.loadSerial(oid, revid) self.assertEqual(zodb_unpickle(data), value)
def checkZEOInvalidation(self): addr = self._storage._addr storage2 = ClientStorage(addr, wait=1, min_disconnect_poll=0.1) try: oid = self._storage.new_oid() ob = MinPO('first') revid1 = self._dostore(oid, data=ob) data, serial = storage2.load(oid, '') self.assertEqual(zodb_unpickle(data), MinPO('first')) self.assertEqual(serial, revid1) revid2 = self._dostore(oid, data=MinPO('second'), revid=revid1) for n in range(3): # Let the server and client talk for a moment. # Is there a better way to do this? asyncore.poll(0.1) data, serial = storage2.load(oid, '') self.assertEqual(zodb_unpickle(data), MinPO('second'), 'Invalidation message was not sent!') self.assertEqual(serial, revid2) finally: storage2.close()
def checkZEOInvalidation(self): addr = self._storage._addr storage2 = ClientStorage(addr, wait=1, min_disconnect_poll=0.1) try: oid = self._storage.new_oid() ob = MinPO('first') revid1 = self._dostore(oid, data=ob) data, serial = storage2.load(oid, '') self.assertEqual(zodb_unpickle(data), MinPO('first')) self.assertEqual(serial, revid1) revid2 = self._dostore(oid, data=MinPO('second'), revid=revid1) for n in range(3): # Let the server and client talk for a moment. # Is there a better way to do this? asyncore.poll(0.1) data, serial = storage2.load(oid, '') self.assertEqual(zodb_unpickle(data), MinPO('second'), 'Invalidation message was not sent!') self.assertEqual(serial, revid2) finally: storage2.close()
def checkModifyAfterAbortVersion(self): eq = self.assertEqual oid, version = self._setup_version() self._abortVersion(version) data, revid = self._storage.load(oid, '') # And modify it a few times revid = self._dostore(oid, revid=revid, data=MinPO(52)) revid = self._dostore(oid, revid=revid, data=MinPO(53)) revid = self._dostore(oid, revid=revid, data=MinPO(54)) data, newrevid = self._storage.load(oid, '') eq(newrevid, revid) eq(zodb_unpickle(data), MinPO(54))
def checkVersionedLoadErrors(self): oid = self._storage.new_oid() version = 'test-version' revid = self._dostore(oid, data=MinPO(11)) revid = self._dostore(oid, revid=revid, data=MinPO(12), version=version) # Try to load a bogus oid self.assertRaises(KeyError, self._storage.load, self._storage.new_oid(), '') data, revid = self._storage.load(oid, 'bogus') self.assertEqual(zodb_unpickle(data), MinPO(11))
def iter_verify(self, txniter, revids, val0): eq = self.assertEqual oid = self._oid val = val0 for reciter, revid in itertools.izip(txniter, revids + [None]): eq(reciter.tid, revid) for rec in reciter: eq(rec.oid, oid) eq(rec.tid, revid) eq(zodb_unpickle(rec.data), MinPO(val)) val = val + 1 eq(val, val0 + len(revids))
def iter_verify(self, txniter, revids, val0): eq = self.assertEqual oid = self._oid val = val0 for reciter, revid in zip(txniter, revids + [None]): eq(reciter.tid, revid) for rec in reciter: eq(rec.oid, oid) eq(rec.tid, revid) eq(zodb_unpickle(rec.data), MinPO(val)) val = val + 1 eq(val, val0 + len(revids))
def checkCommitVersionErrors(self): eq = self.assertEqual oid1, version1 = self._setup_version('one') data, revid1 = self._storage.load(oid1, version1) eq(zodb_unpickle(data), MinPO(54)) t = Transaction() self._storage.tpc_begin(t) try: self.assertRaises(POSException.VersionCommitError, self._storage.commitVersion, 'one', 'one', t) finally: self._storage.tpc_abort(t)
def checkLoad_was_checkLoadEx(self): oid = self._storage.new_oid() self._dostore(oid, data=42) data, tid = load_current(self._storage, oid) self.assertEqual(zodb_unpickle(data), MinPO(42)) match = False for txn in self._storage.iterator(): for rec in txn: if rec.oid == oid and rec.tid == tid: self.assertEqual(txn.tid, tid) match = True if not match: self.fail("Could not find transaction with matching id")
def checkTwoObjectUndoAtOnce(self): # Convenience eq = self.assertEqual unless = self.failUnless p30, p31, p32, p50, p51, p52 = map( zodb_pickle, map(MinPO, (30, 31, 32, 50, 51, 52))) oid1 = self._storage.new_oid() oid2 = self._storage.new_oid() revid1 = revid2 = ZERO # Store two objects in the same transaction d = self._multi_obj_transaction([ (oid1, revid1, p30), (oid2, revid2, p50), ]) eq(d[oid1], d[oid2]) # Update those same two objects d = self._multi_obj_transaction([ (oid1, d[oid1], p31), (oid2, d[oid2], p51), ]) eq(d[oid1], d[oid2]) # Update those same two objects d = self._multi_obj_transaction([ (oid1, d[oid1], p32), (oid2, d[oid2], p52), ]) eq(d[oid1], d[oid2]) revid1 = self._transaction_newserial(oid1) revid2 = self._transaction_newserial(oid2) eq(revid1, revid2) # Make sure the objects have the current value data, revid1 = self._storage.load(oid1, '') eq(zodb_unpickle(data), MinPO(32)) data, revid2 = self._storage.load(oid2, '') eq(zodb_unpickle(data), MinPO(52)) # Now attempt to undo the transaction containing two objects info = self._storage.undoInfo() tid = info[0]['id'] tid1 = info[1]['id'] t = Transaction() oids = self._begin_undos_vote(t, tid, tid1) self._storage.tpc_finish(t) # We get the finalization stuff called an extra time: eq(len(oids), 4) unless(oid1 in oids) unless(oid2 in oids) data, revid1 = self._storage.load(oid1, '') eq(zodb_unpickle(data), MinPO(30)) data, revid2 = self._storage.load(oid2, '') eq(zodb_unpickle(data), MinPO(50)) # Now try to undo the one we just did to undo, whew info = self._storage.undoInfo() self._undo(info[0]['id'], [oid1, oid2]) data, revid1 = self._storage.load(oid1, '') eq(zodb_unpickle(data), MinPO(32)) data, revid2 = self._storage.load(oid2, '') eq(zodb_unpickle(data), MinPO(52)) self._iterate()
def checkLoadBeforeEdges(self): # Check the edges cases for a non-current load. oid = self._storage.new_oid() self.assertRaises(KeyError, self._storage.loadBefore, oid, p64(0)) revid1 = self._dostore(oid, data=MinPO(1)) self.assertEqual(self._storage.loadBefore(oid, p64(0)), None) self.assertEqual(self._storage.loadBefore(oid, revid1), None) cur = p64(u64(revid1) + 1) data, start, end = self._storage.loadBefore(oid, cur) self.assertEqual(zodb_unpickle(data), MinPO(1)) self.assertEqual(start, revid1) self.assertEqual(end, None) revid2 = self._dostore(oid, revid=revid1, data=MinPO(2)) data, start, end = self._storage.loadBefore(oid, cur) self.assertEqual(zodb_unpickle(data), MinPO(1)) self.assertEqual(start, revid1) self.assertEqual(end, revid2)
def checkLoad_was_checkLoadEx(self): oid = self._storage.new_oid() self._dostore(oid, data=42) data, tid = self._storage.load(oid, "") self.assertEqual(zodb_unpickle(data), MinPO(42)) match = False for txn in self._storage.iterator(): for rec in txn: if rec.oid == oid and rec.tid == tid: self.assertEqual(txn.tid, tid) match = True if not match: self.fail("Could not find transaction with matching id")
def checkTwoObjectUndo(self): eq = self.assertEqual # Convenience p31, p32, p51, p52 = map(zodb_pickle, map(MinPO, (31, 32, 51, 52))) oid1 = self._storage.new_oid() oid2 = self._storage.new_oid() revid1 = revid2 = ZERO # Store two objects in the same transaction t = TransactionMetaData() self._storage.tpc_begin(t) self._storage.store(oid1, revid1, p31, '', t) self._storage.store(oid2, revid2, p51, '', t) # Finish the transaction self._storage.tpc_vote(t) tid = self._storage.tpc_finish(t) # Update those same two objects t = TransactionMetaData() self._storage.tpc_begin(t) self._storage.store(oid1, tid, p32, '', t) self._storage.store(oid2, tid, p52, '', t) # Finish the transaction self._storage.tpc_vote(t) self._storage.tpc_finish(t) # Make sure the objects have the current value data, revid1 = load_current(self._storage, oid1) eq(zodb_unpickle(data), MinPO(32)) data, revid2 = load_current(self._storage, oid2) eq(zodb_unpickle(data), MinPO(52)) # Now attempt to undo the transaction containing two objects info = self._storage.undoInfo() self._undo(info[0]['id'], [oid1, oid2]) data, revid1 = load_current(self._storage, oid1) eq(zodb_unpickle(data), MinPO(31)) data, revid2 = load_current(self._storage, oid2) eq(zodb_unpickle(data), MinPO(51)) self._iterate()
def checkCommitVersionInvalidation(self): oid = self._storage.new_oid() revid = self._dostore(oid, data=MinPO(1)) revid = self._dostore(oid, revid=revid, data=MinPO(2)) revid = self._dostore(oid, revid=revid, data=MinPO(3), version="foo") t = Transaction() self._storage.tpc_begin(t) self._storage.commitVersion("foo", "bar", t) self._storage.load(oid, "") self._storage.tpc_vote(t) self._storage.tpc_finish(t) data, revid = self._storage.load(oid, "bar") obj = zodb_unpickle(data) assert obj == MinPO(3), obj
def checkVersionedStoreAndLoad(self): eq = self.assertEqual # Store a couple of non-version revisions of the object oid = self._storage.new_oid() revid = self._dostore(oid, data=MinPO(11)) revid = self._dostore(oid, revid=revid, data=MinPO(12)) # And now store some new revisions in a version version = 'test-version' revid = self._dostore(oid, revid=revid, data=MinPO(13), version=version) revid = self._dostore(oid, revid=revid, data=MinPO(14), version=version) revid = self._dostore(oid, revid=revid, data=MinPO(15), version=version) # Now read back the object in both the non-version and version and # make sure the values jive. data, revid = self._storage.load(oid, '') eq(zodb_unpickle(data), MinPO(12)) data, vrevid = self._storage.load(oid, version) eq(zodb_unpickle(data), MinPO(15)) if hasattr(self._storage, 'getSerial'): s = self._storage.getSerial(oid) eq(s, max(revid, vrevid))
def checkSerialIsNoneForInitialRevision(self): eq = self.assertEqual oid = self._storage.new_oid() txn = TransactionMetaData() self._storage.tpc_begin(txn) # Use None for serial. Don't use _dostore() here because that coerces # serial=None to serial=ZERO. self._storage.store(oid, None, zodb_pickle(MinPO(11)), '', txn) self._storage.tpc_vote(txn) newrevid = self._storage.tpc_finish(txn) data, revid = utils.load_current(self._storage, oid) value = zodb_unpickle(data) eq(value, MinPO(11)) eq(revid, newrevid)
def checkLoadBeforeOld(self): # Look for a very old revision. With the BaseStorage implementation # this should require multple history() calls. oid = self._storage.new_oid() revs = [] revid = None for i in range(50): revid = self._dostore(oid, revid, data=MinPO(i)) revs.append(revid) data, start, end = self._storage.loadBefore(oid, revs[12]) self.assertEqual(zodb_unpickle(data), MinPO(11)) self.assertEqual(start, revs[11]) self.assertEqual(end, revs[12])
def checkLoadBeforeEdges(self): # Check the edges cases for a non-current load. oid = self._storage.new_oid() self.assertRaises(KeyError, self._storage.loadBefore, oid, p64(0)) revid1 = self._dostore(oid, data=MinPO(1)) self.assertEqual(self._storage.loadBefore(oid, p64(0)), None) self.assertEqual(self._storage.loadBefore(oid, revid1), None) cur = p64(u64(revid1) + 1) data, start, end = self._storage.loadBefore(oid, cur) self.assertEqual(zodb_unpickle(data), MinPO(1)) self.assertEqual(start, revid1) self.assertEqual(end, None) revid2 = self._dostore(oid, revid=revid1, data=MinPO(2)) data, start, end = self._storage.loadBefore(oid, cur) self.assertEqual(zodb_unpickle(data), MinPO(1)) self.assertEqual(start, revid1) self.assertEqual(end, revid2)
def checkLoadBeforeOld(self): # Look for a very old revision. With the BaseStorage implementation # this should require multple history() calls. oid = self._storage.new_oid() revs = [] revid = None for i in range(50): revid = self._dostore(oid, revid, data=MinPO(i)) revs.append(revid) data, start, end = self._storage.loadBefore(oid, revs[12]) self.assertEqual(zodb_unpickle(data), MinPO(11)) self.assertEqual(start, revs[11]) self.assertEqual(end, revs[12])
def checkAbortVersion(self): eq = self.assertEqual oid, version = self._setup_version() # Not sure I can write a test for getSerial() in the # presence of aborted versions, because FileStorage and # Berkeley storage give a different answer. I think Berkeley # is right and FS is wrong. oids = self._abortVersion(version) eq(len(oids), 1) eq(oids[0], oid) data, revid = self._storage.load(oid, '') eq(zodb_unpickle(data), MinPO(51))