[Neo-report] r2600 vincent - in /trunk/neo: storage/ tests/storage/

nobody at svn.erp5.org nobody at svn.erp5.org
Mon Jan 10 11:46:49 CET 2011


Author: vincent
Date: Mon Jan 10 11:46:49 2011
New Revision: 2600

Log:
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.

Modified:
    trunk/neo/storage/transactions.py
    trunk/neo/tests/storage/testTransactions.py

Modified: trunk/neo/storage/transactions.py
==============================================================================
--- trunk/neo/storage/transactions.py [iso-8859-1] (original)
+++ trunk/neo/storage/transactions.py [iso-8859-1] Mon Jan 10 11:46:49 2011
@@ -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:

Modified: trunk/neo/tests/storage/testTransactions.py
==============================================================================
--- trunk/neo/tests/storage/testTransactions.py [iso-8859-1] (original)
+++ trunk/neo/tests/storage/testTransactions.py [iso-8859-1] Mon Jan 10 11:46:49 2011
@@ -372,7 +372,9 @@ class TransactionManagerTests(NeoUnitTes
         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(NeoUnitTes
         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(NeoUnitTes
         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()




More information about the Neo-report mailing list