Commit 609ef821 authored by Vincent Pelletier's avatar Vincent Pelletier

Add conflict detection for multiple "undo" in same transaction.

Detect if a client requests multiple undo/store based on wrong revisions.
Also, don't try to acquire lock when we know we have it.

git-svn-id: https://svn.erp5.org/repos/neo/trunk@2600 71dcc9de-d417-0410-9af5-da40c76e7ee4
parent 4d69f401
......@@ -239,16 +239,28 @@ class TransactionManager(object):
self._app.executeQueuedEvents()
# Attemp to acquire lock again.
locking_tid = self._store_lock_dict.get(oid)
if locking_tid == tid:
neo.logging.info('Transaction %s storing %s more than once',
dump(tid), dump(oid))
elif locking_tid is None:
if locking_tid in (None, tid):
# check if this is generated from the latest revision.
history_list = self._app.dm.getObjectHistory(oid)
if history_list and history_list[0][0] != serial:
if locking_tid == tid:
# If previous store was an undo, next store must be based on
# undo target.
_, _, _, _, previous_serial = self._transaction_dict[
tid].getObject(oid)
if previous_serial is None:
# XXX: use some special serial when previous store was not
# an undo ? Maybe it should just not happen.
neo.logging.info('Transaction %s storing %s more than '
'once', dump(tid), dump(oid))
else:
previous_serial = None
if previous_serial is None:
history_list = self._app.dm.getObjectHistory(oid)
if history_list:
previous_serial = history_list[0][0]
if previous_serial is not None and previous_serial != serial:
neo.logging.info('Resolvable conflict on %r:%r', dump(oid),
dump(tid))
raise ConflictError(history_list[0][0])
raise ConflictError(previous_serial)
neo.logging.info('Transaction %s storing %s', dump(tid), dump(oid))
self._store_lock_dict[oid] = tid
elif locking_tid > tid:
......
......@@ -372,7 +372,9 @@ class TransactionManagerTests(NeoUnitTestBase):
self.manager.updateObjectDataForPack(oid, orig_serial, None, None)
self.assertEqual(self.manager.getObjectFromTransaction(locking_serial,
oid), None)
self.manager.abort(locking_serial, even_if_locked=True)
# Object known, but doesn't point at orig_serial, it is not updated
self.manager.register(uuid, locking_serial)
self.manager.storeObject(locking_serial, ram_serial, oid, 0, 512,
'bar', None)
orig_object = self.manager.getObjectFromTransaction(locking_serial,
......@@ -380,7 +382,9 @@ class TransactionManagerTests(NeoUnitTestBase):
self.manager.updateObjectDataForPack(oid, orig_serial, None, None)
self.assertEqual(self.manager.getObjectFromTransaction(locking_serial,
oid), orig_object)
self.manager.abort(locking_serial, even_if_locked=True)
self.manager.register(uuid, locking_serial)
self.manager.storeObject(locking_serial, ram_serial, oid, None, None,
None, other_serial)
orig_object = self.manager.getObjectFromTransaction(locking_serial,
......@@ -388,21 +392,26 @@ class TransactionManagerTests(NeoUnitTestBase):
self.manager.updateObjectDataForPack(oid, orig_serial, None, None)
self.assertEqual(self.manager.getObjectFromTransaction(locking_serial,
oid), orig_object)
self.manager.abort(locking_serial, even_if_locked=True)
# Object known and points at undone data it gets updated
# ...with data_serial: getObjectData must not be called
self.manager.register(uuid, locking_serial)
self.manager.storeObject(locking_serial, ram_serial, oid, None, None,
None, orig_serial)
self.manager.updateObjectDataForPack(oid, orig_serial, new_serial,
None)
self.assertEqual(self.manager.getObjectFromTransaction(locking_serial,
oid), (oid, None, None, None, new_serial))
self.manager.abort(locking_serial, even_if_locked=True)
# with data
self.manager.register(uuid, locking_serial)
self.manager.storeObject(locking_serial, ram_serial, oid, None, None,
None, orig_serial)
self.manager.updateObjectDataForPack(oid, orig_serial, None,
getObjectData)
self.assertEqual(self.manager.getObjectFromTransaction(locking_serial,
oid), (oid, compression, checksum, value, None))
self.manager.abort(locking_serial, even_if_locked=True)
if __name__ == "__main__":
unittest.main()
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