Commit 2120a7a2 authored by Julien Muchembled's avatar Julien Muchembled Committed by Kirill Smelkov

[ZODB3] Allow serial to be returned as late as tpc_finish

----

kirr: This is likely to be ZODB3-backport of https://github.com/zopefoundation/ZODB/pull/69
Taken from https://lab.nexedi.com/nexedi/neoppod/blob/v1.12-52-gfb746e6b/ZODB3.patch
parent d9d5b50a
...@@ -776,6 +776,10 @@ class IStorage(Interface): ...@@ -776,6 +776,10 @@ class IStorage(Interface):
called while the storage transaction lock is held. It takes called while the storage transaction lock is held. It takes
the new transaction id generated by the transaction. the new transaction id generated by the transaction.
The return value can be either None or a serial giving new
serial for objects whose ids were passed to previous store calls
in the same transaction, and for which no serial was returned
from either store or tpc_vote for objects passed to store.
""" """
def tpc_vote(transaction): def tpc_vote(transaction):
...@@ -794,8 +798,6 @@ class IStorage(Interface): ...@@ -794,8 +798,6 @@ class IStorage(Interface):
The return value can be either None or a sequence of object-id The return value can be either None or a sequence of object-id
and serial pairs giving new serials for objects who's ids were and serial pairs giving new serials for objects who's ids were
passed to previous store calls in the same transaction. passed to previous store calls in the same transaction.
After the tpc_vote call, new serials must have been returned,
either from tpc_vote or store for objects passed to store.
A serial returned in a sequence of oid/serial pairs, may be A serial returned in a sequence of oid/serial pairs, may be
the special value ZODB.ConflictResolution.ResolvedSerial to the special value ZODB.ConflictResolution.ResolvedSerial to
......
...@@ -72,8 +72,10 @@ class BasicStorage: ...@@ -72,8 +72,10 @@ class BasicStorage:
r1 = self._storage.store(oid, None, zodb_pickle(MinPO(11)), r1 = self._storage.store(oid, None, zodb_pickle(MinPO(11)),
'', txn) '', txn)
r2 = self._storage.tpc_vote(txn) r2 = self._storage.tpc_vote(txn)
self._storage.tpc_finish(txn) serial = self._storage.tpc_finish(txn)
newrevid = handle_serials(oid, r1, r2) newrevid = handle_serials(oid, r1, r2)
if newrevid is None and serial is not None:
newrevid = serial
data, revid = self._storage.load(oid, '') data, revid = self._storage.load(oid, '')
value = zodb_unpickle(data) value = zodb_unpickle(data)
eq(value, MinPO(11)) eq(value, MinPO(11))
......
...@@ -155,10 +155,12 @@ class StorageClientThread(TestThread): ...@@ -155,10 +155,12 @@ class StorageClientThread(TestThread):
r2 = self.storage.tpc_vote(t) r2 = self.storage.tpc_vote(t)
self.pause() self.pause()
self.storage.tpc_finish(t) serial = self.storage.tpc_finish(t)
self.pause() self.pause()
revid = handle_serials(oid, r1, r2) revid = handle_serials(oid, r1, r2)
if serial is not None and revid is None:
revid = serial
self.oids[oid] = revid self.oids[oid] = revid
class ExtStorageClientThread(StorageClientThread): class ExtStorageClientThread(StorageClientThread):
......
...@@ -150,10 +150,12 @@ class RevisionStorage: ...@@ -150,10 +150,12 @@ class RevisionStorage:
# Finish the transaction # Finish the transaction
r2 = self._storage.tpc_vote(t) r2 = self._storage.tpc_vote(t)
newrevid = handle_serials(oid, r1, r2) newrevid = handle_serials(oid, r1, r2)
self._storage.tpc_finish(t) serial = self._storage.tpc_finish(t)
except: except:
self._storage.tpc_abort(t) self._storage.tpc_abort(t)
raise raise
if serial is not None and newrevid is None:
newrevid = serial
return newrevid return newrevid
revid1 = helper(1, None, 1) revid1 = helper(1, None, 1)
revid2 = helper(2, revid1, 2) revid2 = helper(2, revid1, 2)
......
...@@ -134,7 +134,7 @@ def handle_serials(oid, *args): ...@@ -134,7 +134,7 @@ def handle_serials(oid, *args):
A helper for function _handle_all_serials(). A helper for function _handle_all_serials().
""" """
return handle_all_serials(oid, *args)[oid] return handle_all_serials(oid, *args).get(oid)
def import_helper(name): def import_helper(name):
__import__(name) __import__(name)
...@@ -191,7 +191,9 @@ class StorageTestBase(ZODB.tests.util.TestCase): ...@@ -191,7 +191,9 @@ class StorageTestBase(ZODB.tests.util.TestCase):
# Finish the transaction # Finish the transaction
r2 = self._storage.tpc_vote(t) r2 = self._storage.tpc_vote(t)
revid = handle_serials(oid, r1, r2) revid = handle_serials(oid, r1, r2)
self._storage.tpc_finish(t) serial = self._storage.tpc_finish(t)
if serial is not None and revid is None:
revid = serial
except: except:
self._storage.tpc_abort(t) self._storage.tpc_abort(t)
raise raise
...@@ -211,8 +213,8 @@ class StorageTestBase(ZODB.tests.util.TestCase): ...@@ -211,8 +213,8 @@ class StorageTestBase(ZODB.tests.util.TestCase):
self._storage.tpc_begin(t) self._storage.tpc_begin(t)
undo_result = self._storage.undo(tid, t) undo_result = self._storage.undo(tid, t)
vote_result = self._storage.tpc_vote(t) vote_result = self._storage.tpc_vote(t)
self._storage.tpc_finish(t) serial = self._storage.tpc_finish(t)
if expected_oids is not None: if expected_oids is not None and serial is None:
oids = undo_result and undo_result[1] or [] oids = undo_result and undo_result[1] or []
oids.extend(oid for (oid, _) in vote_result or ()) oids.extend(oid for (oid, _) in vote_result or ())
self.assertEqual(len(oids), len(expected_oids), repr(oids)) self.assertEqual(len(oids), len(expected_oids), repr(oids))
......
...@@ -76,6 +76,12 @@ class TransactionalUndoStorage: ...@@ -76,6 +76,12 @@ class TransactionalUndoStorage:
def _transaction_newserial(self, oid): def _transaction_newserial(self, oid):
return self.__serials[oid] return self.__serials[oid]
def _transaction_finish(self, t, oid_list):
tid = self._storage.tpc_finish(t)
if tid is not None:
for oid in oid_list:
self.__serials[oid] = tid
def _multi_obj_transaction(self, objs): def _multi_obj_transaction(self, objs):
newrevs = {} newrevs = {}
t = Transaction() t = Transaction()
...@@ -85,7 +91,7 @@ class TransactionalUndoStorage: ...@@ -85,7 +91,7 @@ class TransactionalUndoStorage:
self._transaction_store(oid, rev, data, '', t) self._transaction_store(oid, rev, data, '', t)
newrevs[oid] = None newrevs[oid] = None
self._transaction_vote(t) self._transaction_vote(t)
self._storage.tpc_finish(t) self._transaction_finish(t, [x[0] for x in objs])
for oid in newrevs.keys(): for oid in newrevs.keys():
newrevs[oid] = self._transaction_newserial(oid) newrevs[oid] = self._transaction_newserial(oid)
return newrevs return newrevs
...@@ -218,9 +224,9 @@ class TransactionalUndoStorage: ...@@ -218,9 +224,9 @@ class TransactionalUndoStorage:
self._transaction_store(oid2, revid2, p51, '', t) self._transaction_store(oid2, revid2, p51, '', t)
# Finish the transaction # Finish the transaction
self._transaction_vote(t) self._transaction_vote(t)
self._transaction_finish(t, [oid1, oid2])
revid1 = self._transaction_newserial(oid1) revid1 = self._transaction_newserial(oid1)
revid2 = self._transaction_newserial(oid2) revid2 = self._transaction_newserial(oid2)
self._storage.tpc_finish(t)
eq(revid1, revid2) eq(revid1, revid2)
# Update those same two objects # Update those same two objects
t = Transaction() t = Transaction()
...@@ -230,9 +236,9 @@ class TransactionalUndoStorage: ...@@ -230,9 +236,9 @@ class TransactionalUndoStorage:
self._transaction_store(oid2, revid2, p52, '', t) self._transaction_store(oid2, revid2, p52, '', t)
# Finish the transaction # Finish the transaction
self._transaction_vote(t) self._transaction_vote(t)
self._transaction_finish(t, [oid1, oid2])
revid1 = self._transaction_newserial(oid1) revid1 = self._transaction_newserial(oid1)
revid2 = self._transaction_newserial(oid2) revid2 = self._transaction_newserial(oid2)
self._storage.tpc_finish(t)
eq(revid1, revid2) eq(revid1, revid2)
# Make sure the objects have the current value # Make sure the objects have the current value
data, revid1 = self._storage.load(oid1, '') data, revid1 = self._storage.load(oid1, '')
...@@ -288,11 +294,12 @@ class TransactionalUndoStorage: ...@@ -288,11 +294,12 @@ class TransactionalUndoStorage:
tid1 = info[1]['id'] tid1 = info[1]['id']
t = Transaction() t = Transaction()
oids = self._begin_undos_vote(t, tid, tid1) oids = self._begin_undos_vote(t, tid, tid1)
self._storage.tpc_finish(t) serial = self._storage.tpc_finish(t)
# We get the finalization stuff called an extra time: # We get the finalization stuff called an extra time:
eq(len(oids), 4) if serial is None:
unless(oid1 in oids) eq(len(oids), 4)
unless(oid2 in oids) unless(oid1 in oids)
unless(oid2 in oids)
data, revid1 = self._storage.load(oid1, '') data, revid1 = self._storage.load(oid1, '')
eq(zodb_unpickle(data), MinPO(30)) eq(zodb_unpickle(data), MinPO(30))
data, revid2 = self._storage.load(oid2, '') data, revid2 = self._storage.load(oid2, '')
...@@ -326,7 +333,7 @@ class TransactionalUndoStorage: ...@@ -326,7 +333,7 @@ class TransactionalUndoStorage:
self._transaction_store(oid2, revid2, p52, '', t) self._transaction_store(oid2, revid2, p52, '', t)
# Finish the transaction # Finish the transaction
self._transaction_vote(t) self._transaction_vote(t)
self._storage.tpc_finish(t) self._transaction_finish(t, [oid1, oid2])
revid1 = self._transaction_newserial(oid1) revid1 = self._transaction_newserial(oid1)
revid2 = self._transaction_newserial(oid2) revid2 = self._transaction_newserial(oid2)
eq(revid1, revid2) eq(revid1, revid2)
...@@ -346,7 +353,7 @@ class TransactionalUndoStorage: ...@@ -346,7 +353,7 @@ class TransactionalUndoStorage:
self._transaction_store(oid2, revid2, p53, '', t) self._transaction_store(oid2, revid2, p53, '', t)
# Finish the transaction # Finish the transaction
self._transaction_vote(t) self._transaction_vote(t)
self._storage.tpc_finish(t) self._transaction_finish(t, [oid1, oid2])
revid1 = self._transaction_newserial(oid1) revid1 = self._transaction_newserial(oid1)
revid2 = self._transaction_newserial(oid2) revid2 = self._transaction_newserial(oid2)
eq(revid1, revid2) eq(revid1, revid2)
...@@ -358,10 +365,11 @@ class TransactionalUndoStorage: ...@@ -358,10 +365,11 @@ class TransactionalUndoStorage:
tid = info[1]['id'] tid = info[1]['id']
t = Transaction() t = Transaction()
oids = self._begin_undos_vote(t, tid) oids = self._begin_undos_vote(t, tid)
self._storage.tpc_finish(t) serial = self._storage.tpc_finish(t)
eq(len(oids), 1) if serial is None:
self.failUnless(oid1 in oids) eq(len(oids), 1)
self.failUnless(not oid2 in oids) self.failUnless(oid1 in oids)
self.failUnless(not oid2 in oids)
data, revid1 = self._storage.load(oid1, '') data, revid1 = self._storage.load(oid1, '')
eq(zodb_unpickle(data), MinPO(33)) eq(zodb_unpickle(data), MinPO(33))
data, revid2 = self._storage.load(oid2, '') data, revid2 = self._storage.load(oid2, '')
...@@ -397,7 +405,7 @@ class TransactionalUndoStorage: ...@@ -397,7 +405,7 @@ class TransactionalUndoStorage:
self._transaction_store(oid1, revid1, p81, '', t) self._transaction_store(oid1, revid1, p81, '', t)
self._transaction_store(oid2, revid2, p91, '', t) self._transaction_store(oid2, revid2, p91, '', t)
self._transaction_vote(t) self._transaction_vote(t)
self._storage.tpc_finish(t) self._transaction_finish(t, [oid1, oid2])
revid1 = self._transaction_newserial(oid1) revid1 = self._transaction_newserial(oid1)
revid2 = self._transaction_newserial(oid2) revid2 = self._transaction_newserial(oid2)
eq(revid1, revid2) eq(revid1, revid2)
...@@ -683,9 +691,9 @@ class TransactionalUndoStorage: ...@@ -683,9 +691,9 @@ class TransactionalUndoStorage:
tid = p64(i + 1) tid = p64(i + 1)
eq(txn.tid, tid) eq(txn.tid, tid)
L1 = [(rec.oid, rec.tid, rec.data_txn) for rec in txn] L1 = {(rec.oid, rec.tid, rec.data_txn) for rec in txn}
L2 = [(oid, revid, None) for _tid, oid, revid in orig L2 = {(oid, revid, None) for _tid, oid, revid in orig
if _tid == tid] if _tid == tid}
eq(L1, L2) eq(L1, L2)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment