Commit 76a6eef2 authored by Vincent Pelletier's avatar Vincent Pelletier

Ignore TID chronology when detecting & resolving conflicts.

If TID allocation and conflict resolution are serialised at database scope
(=cluster scope in NEO), the question doesn't arises: when we have a TID,
we are the latest TID until we call tpc_finish.
If they are not serialised, it means TID allocation will happen after
conflict resolution, as TID generation must be serialised anyway, and in
such case, the temporary TID we have when detecting conflicts has no
ordering signification, so it is meaningless to check their chronology.

git-svn-id: https://svn.erp5.org/repos/neo/trunk@2533 71dcc9de-d417-0410-9af5-da40c76e7ee4
parent 4e402dda
......@@ -816,28 +816,23 @@ class Application(object):
tid = local_var.tid
resolved = False
if data is not None:
if conflict_serial <= tid:
new_data = tryToResolveConflict(oid, conflict_serial,
serial, data)
if new_data is not None:
neo.logging.info('Conflict resolution succeed for ' \
'%r:%r with %r', dump(oid), dump(serial),
dump(conflict_serial))
# Mark this conflict as resolved
resolved_serial_set.update(conflict_serial_dict.pop(
oid))
# Try to store again
self._store(oid, conflict_serial, new_data)
append(oid)
resolved = True
else:
neo.logging.info('Conflict resolution failed for ' \
'%r:%r with %r', dump(oid), dump(serial),
dump(conflict_serial))
new_data = tryToResolveConflict(oid, conflict_serial,
serial, data)
if new_data is not None:
neo.logging.info('Conflict resolution succeed for ' \
'%r:%r with %r', dump(oid), dump(serial),
dump(conflict_serial))
# Mark this conflict as resolved
resolved_serial_set.update(conflict_serial_dict.pop(
oid))
# Try to store again
self._store(oid, conflict_serial, new_data)
append(oid)
resolved = True
else:
neo.logging.info('Conflict reported for %r:%r with ' \
'later transaction %r , cannot resolve conflict.',
dump(oid), dump(serial), dump(conflict_serial))
neo.logging.info('Conflict resolution failed for ' \
'%r:%r with %r', dump(oid), dump(serial),
dump(conflict_serial))
if not resolved:
# XXX: Is it really required to remove from data_dict ?
del data_dict[oid]
......
......@@ -220,17 +220,11 @@ class TransactionManager(object):
raise ConflictError(history_list[0][0])
neo.logging.info('Transaction %s storing %s', dump(tid), dump(oid))
self._store_lock_dict[oid] = tid
elif locking_tid < tid:
else:
# a previous transaction lock this object, retry later
neo.logging.info('Store delayed for %r:%r by %r', dump(oid),
dump(tid), dump(locking_tid))
raise DelayedError
else:
# If a newer transaction already locks this object,
# do not try to resolve a conflict, so return immediately.
neo.logging.info('Unresolvable conflict on %r:%r with %r',
dump(oid), dump(tid), dump(locking_tid))
raise ConflictError(locking_tid)
def checkCurrentSerial(self, tid, serial, oid):
self.lockObject(tid, serial, oid)
......
......@@ -155,26 +155,6 @@ class TransactionManagerTests(NeoUnitTestBase):
self.assertRaises(DelayedError, self.manager.storeObject,
tid2, serial, *obj)
def testUnresolvableConflict(self):
""" A newer transaction has already modified an object """
uuid = self.getNewUUID()
tid1, txn1 = self._getTransaction()
tid2, txn2 = self._getTransaction()
serial, obj = self._getObject(1)
# the (later) transaction lock (change) the object
self.manager.register(uuid, tid2)
self.manager.storeTransaction(tid2, *txn2)
self.manager.storeObject(tid2, serial, *obj)
self.assertTrue(tid2 in self.manager)
self._storeTransactionObjects(tid2, txn2)
self.manager.lock(tid2, txn2[0])
# the previous it's not using the latest version
self.manager.register(uuid, tid1)
self.manager.storeTransaction(tid1, *txn1)
self.assertTrue(tid1 in self.manager)
self.assertRaises(ConflictError, self.manager.storeObject,
tid1, serial, *obj)
def testResolvableConflict(self):
""" Try to store an object with the lastest revision """
uuid = self.getNewUUID()
......@@ -229,13 +209,13 @@ class TransactionManagerTests(NeoUnitTestBase):
self.manager.storeObject(tid2, serial2, *obj2)
self.assertTrue(tid2 in self.manager)
self.manager.lock(tid2, txn1[0])
# the first get a conflict
# the first get a delay, as nothing is committed yet
self.manager.register(uuid1, tid1)
self.manager.storeTransaction(tid1, *txn1)
self.assertTrue(tid1 in self.manager)
self.assertRaises(ConflictError, self.manager.storeObject,
self.assertRaises(DelayedError, self.manager.storeObject,
tid1, serial1, *obj1)
self.assertRaises(ConflictError, self.manager.storeObject,
self.assertRaises(DelayedError, self.manager.storeObject,
tid1, serial2, *obj2)
def testAbortUnlocked(self):
......
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