Exemplo n.º 1
0
 def setUp(self):
     NeoUnitTestBase.setUp(self)
     self.app = Mock()
     # no history
     self.app.dm = Mock({'getObjectHistory': []})
     self.app.pt = Mock({'isAssigned': True, 'getPartitions': 2})
     self.app.em = Mock({'setTimeout': None})
     self.manager = TransactionManager(self.app)
Exemplo n.º 2
0
 def setUp(self):
     NeoUnitTestBase.setUp(self)
     self.app = Mock()
     # no history
     self.app.dm = Mock({'getObjectHistory': []})
     self.app.pt = Mock({'isAssigned': True})
     self.app.em = Mock({'setTimeout': None})
     self.manager = TransactionManager(self.app)
     self.ltid = None
Exemplo n.º 3
0
class TransactionManagerTests(NeoUnitTestBase):
    def setUp(self):
        NeoUnitTestBase.setUp(self)
        self.app = Mock()
        # no history
        self.app.dm = Mock({'getObjectHistory': []})
        self.app.pt = Mock({'isAssigned': True, 'getPartitions': 2})
        self.app.em = Mock({'setTimeout': None})
        self.manager = TransactionManager(self.app)

    def register(self, uuid, ttid):
        self.manager.register(Mock({'getUUID': uuid}), ttid)

    def test_updateObjectDataForPack(self):
        ram_serial = self.getNextTID()
        oid = p64(1)
        orig_serial = self.getNextTID()
        uuid = self.getClientUUID()
        locking_serial = self.getNextTID()
        other_serial = self.getNextTID()
        new_serial = self.getNextTID()
        checksum = "2" * 20
        self.register(uuid, locking_serial)
        # Object not known, nothing happens
        self.assertEqual(
            self.manager.getObjectFromTransaction(locking_serial, oid), None)
        self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum)
        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.register(uuid, locking_serial)
        self.manager.storeObject(locking_serial, ram_serial, oid, 0, "3" * 20,
                                 'bar', None)
        holdData = self.app.dm.mockGetNamedCalls('holdData')
        self.assertEqual(holdData.pop(0).params, ("3" * 20, oid, 'bar', 0))
        orig_object = self.manager.getObjectFromTransaction(
            locking_serial, oid)
        self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum)
        self.assertEqual(
            self.manager.getObjectFromTransaction(locking_serial, oid),
            orig_object)
        self.manager.abort(locking_serial, even_if_locked=True)

        self.register(uuid, locking_serial)
        self.manager.storeObject(locking_serial, ram_serial, oid, None, None,
                                 None, other_serial)
        orig_object = self.manager.getObjectFromTransaction(
            locking_serial, oid)
        self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum)
        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
        self.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,
                                             checksum)
        self.assertEqual(
            self.manager.getObjectFromTransaction(locking_serial, oid),
            (oid, None, new_serial))
        self.manager.abort(locking_serial, even_if_locked=True)

        self.register(uuid, locking_serial)
        self.manager.storeObject(locking_serial, ram_serial, oid, None, None,
                                 None, orig_serial)
        self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum)
        self.assertEqual(holdData.pop(0).params, (checksum, ))
        self.assertEqual(
            self.manager.getObjectFromTransaction(locking_serial, oid),
            (oid, checksum, None))
        self.manager.abort(locking_serial, even_if_locked=True)
        self.assertFalse(holdData)
Exemplo n.º 4
0
class TransactionManagerTests(NeoUnitTestBase):

    def setUp(self):
        NeoUnitTestBase.setUp(self)
        self.app = Mock()
        # no history
        self.app.dm = Mock({'getObjectHistory': []})
        self.app.pt = Mock({'isAssigned': True})
        self.app.em = Mock({'setTimeout': None})
        self.manager = TransactionManager(self.app)
        self.ltid = None

    def _getTransaction(self):
        tid = self.getNextTID(self.ltid)
        oid_list = [self.getOID(1), self.getOID(2)]
        return (tid, ('USER', 'DESC', 'EXT', oid_list))

    def _storeTransactionObjects(self, tid, txn):
        for i, oid in enumerate(txn[3]):
            self.manager.storeObject(tid, None,
                    oid, 1, '%020d' % i, '0' + str(i), None)

    def _getObject(self, value):
        oid = self.getOID(value)
        serial = self.getNextTID()
        return (serial, (oid, 1, '%020d' % value, 'O' + str(value), None))

    def _checkTransactionStored(self, *args):
        calls = self.app.dm.mockGetNamedCalls('storeTransaction')
        self.assertEqual(len(calls), 1)
        calls[0].checkArgs(*args)

    def _checkTransactionFinished(self, *args):
        calls = self.app.dm.mockGetNamedCalls('unlockTransaction')
        self.assertEqual(len(calls), 1)
        calls[0].checkArgs(*args)

    def _checkQueuedEventExecuted(self, number=1):
        calls = self.app.mockGetNamedCalls('executeQueuedEvents')
        self.assertEqual(len(calls), number)

    def assertRegistered(self, ttid):
        self.assertIn(ttid, self.manager._transaction_dict)

    def assertNotRegistered(self, ttid):
        self.assertNotIn(ttid, self.manager._transaction_dict)

    def testSimpleCase(self):
        """ One node, one transaction, not abort """
        data_id_list = random.random(), random.random()
        self.app.dm.mockAddReturnValues(holdData=ReturnValues(*data_id_list))
        uuid = self.getClientUUID()
        ttid = self.getNextTID()
        tid, txn = self._getTransaction()
        serial1, object1 = self._getObject(1)
        serial2, object2 = self._getObject(2)
        self.manager.register(uuid, ttid)
        self.manager.storeObject(ttid, serial1, *object1)
        self.manager.storeObject(ttid, serial2, *object2)
        self.assertRegistered(ttid)
        self.manager.vote(ttid, txn)
        user, desc, ext, oid_list = txn
        call, = self.app.dm.mockGetNamedCalls('storeTransaction')
        call.checkArgs(ttid, [
            (object1[0], data_id_list[0], object1[4]),
            (object2[0], data_id_list[1], object2[4]),
            ], (oid_list, user, desc, ext, False, ttid))
        self.manager.lock(ttid, tid)
        call, = self.app.dm.mockGetNamedCalls('lockTransaction')
        call.checkArgs(tid, ttid)
        self.manager.unlock(ttid)
        self.assertNotRegistered(ttid)
        call, = self.app.dm.mockGetNamedCalls('unlockTransaction')
        call.checkArgs(tid, ttid)

    def testDelayed(self):
        """ Two transactions, the first cause the second to be delayed """
        uuid = self.getClientUUID()
        ttid1 = self.getNextTID()
        ttid2 = self.getNextTID()
        tid1, txn1 = self._getTransaction()
        tid2, txn2 = self._getTransaction()
        serial, obj = self._getObject(1)
        # first transaction lock the object
        self.manager.register(uuid, ttid1)
        self.assertRegistered(ttid1)
        self._storeTransactionObjects(ttid1, txn1)
        self.manager.vote(ttid1, txn1)
        self.manager.lock(ttid1, tid1)
        # the second is delayed
        self.manager.register(uuid, ttid2)
        self.assertRegistered(ttid2)
        self.assertRaises(DelayedError, self.manager.storeObject,
                ttid2, serial, *obj)

    def testUnresolvableConflict(self):
        """ A newer transaction has already modified an object """
        uuid = self.getClientUUID()
        ttid1 = self.getNextTID()
        ttid2 = self.getNextTID()
        tid1, txn1 = self._getTransaction()
        tid2, txn2 = self._getTransaction()
        serial, obj = self._getObject(1)
        # the (later) transaction lock (change) the object
        self.manager.register(uuid, ttid2)
        self.assertRegistered(ttid2)
        self._storeTransactionObjects(ttid2, txn2)
        self.manager.vote(ttid2, txn2)
        self.manager.lock(ttid2, tid2)
        # the previous it's not using the latest version
        self.manager.register(uuid, ttid1)
        self.assertRegistered(ttid1)
        self.assertRaises(ConflictError, self.manager.storeObject,
                ttid1, serial, *obj)

    def testResolvableConflict(self):
        """ Try to store an object with the lastest revision """
        uuid = self.getClientUUID()
        tid, txn = self._getTransaction()
        serial, obj = self._getObject(1)
        next_serial = self.getNextTID(serial)
        # try to store without the last revision
        self.app.dm = Mock({'getLastObjectTID': next_serial})
        self.manager.register(uuid, tid)
        self.assertRaises(ConflictError, self.manager.storeObject,
                tid, serial, *obj)

    def testLockDelayed(self):
        """ Check lock delay """
        uuid1 = self.getClientUUID()
        uuid2 = self.getClientUUID()
        self.assertNotEqual(uuid1, uuid2)
        ttid1 = self.getNextTID()
        ttid2 = self.getNextTID()
        tid1, txn1 = self._getTransaction()
        tid2, txn2 = self._getTransaction()
        serial1, obj1 = self._getObject(1)
        serial2, obj2 = self._getObject(2)
        # first transaction lock objects
        self.manager.register(uuid1, ttid1)
        self.assertRegistered(ttid1)
        self.manager.storeObject(ttid1, serial1, *obj1)
        self.manager.storeObject(ttid1, serial1, *obj2)
        self.manager.vote(ttid1, txn1)
        self.manager.lock(ttid1, tid1)
        # second transaction is delayed
        self.manager.register(uuid2, ttid2)
        self.assertRegistered(ttid2)
        self.assertRaises(DelayedError, self.manager.storeObject,
                ttid2, serial1, *obj1)
        self.assertRaises(DelayedError, self.manager.storeObject,
                ttid2, serial2, *obj2)

    def testLockConflict(self):
        """ Check lock conflict """
        uuid1 = self.getClientUUID()
        uuid2 = self.getClientUUID()
        self.assertNotEqual(uuid1, uuid2)
        ttid1 = self.getNextTID()
        ttid2 = self.getNextTID()
        tid1, txn1 = self._getTransaction()
        tid2, txn2 = self._getTransaction()
        serial1, obj1 = self._getObject(1)
        serial2, obj2 = self._getObject(2)
        # the second transaction lock objects
        self.manager.register(uuid2, ttid2)
        self.manager.storeObject(ttid2, serial1, *obj1)
        self.manager.storeObject(ttid2, serial2, *obj2)
        self.assertRegistered(ttid2)
        self.manager.vote(ttid2, txn2)
        self.manager.lock(ttid2, tid2)
        # the first get a conflict
        self.manager.register(uuid1, ttid1)
        self.assertRegistered(ttid1)
        self.assertRaises(ConflictError, self.manager.storeObject,
                ttid1, serial1, *obj1)
        self.assertRaises(ConflictError, self.manager.storeObject,
                ttid1, serial2, *obj2)

    def testAbortUnlocked(self):
        """ Abort a non-locked transaction """
        uuid = self.getClientUUID()
        tid, txn = self._getTransaction()
        serial, obj = self._getObject(1)
        self.manager.register(uuid, tid)
        self.manager.storeObject(tid, serial, *obj)
        self.assertRegistered(tid)
        self.manager.vote(tid, txn)
        # transaction is not locked
        self.manager.abort(tid)
        self.assertNotRegistered(tid)
        self.assertFalse(self.manager.loadLocked(obj[0]))
        self._checkQueuedEventExecuted()

    def testAbortLockedDoNothing(self):
        """ Try to abort a locked transaction """
        uuid = self.getClientUUID()
        ttid = self.getNextTID()
        tid, txn = self._getTransaction()
        self.manager.register(uuid, ttid)
        self._storeTransactionObjects(ttid, txn)
        self.manager.vote(ttid, txn)
        # lock transaction
        self.manager.lock(ttid, tid)
        self.assertRegistered(ttid)
        self.manager.abort(ttid)
        self.assertRegistered(ttid)
        for oid in txn[-1]:
            self.assertTrue(self.manager.loadLocked(oid))
        self._checkQueuedEventExecuted(number=0)

    def testAbortForNode(self):
        """ Abort transaction for a node """
        uuid1 = self.getClientUUID()
        uuid2 = self.getClientUUID()
        self.assertNotEqual(uuid1, uuid2)
        ttid1 = self.getNextTID()
        ttid2 = self.getNextTID()
        ttid3 = self.getNextTID()
        tid1, txn1 = self._getTransaction()
        tid2, txn2 = self._getTransaction()
        tid3, txn3 = self._getTransaction()
        self.manager.register(uuid1, ttid1)
        self.manager.register(uuid2, ttid2)
        self.manager.register(uuid2, ttid3)
        self.manager.vote(ttid1, txn1)
        # node 2 owns tid2 & tid3 and lock tid2 only
        self._storeTransactionObjects(ttid2, txn2)
        self.manager.vote(ttid2, txn2)
        self.manager.vote(ttid3, txn3)
        self.manager.lock(ttid2, tid2)
        self.assertRegistered(ttid1)
        self.assertRegistered(ttid2)
        self.assertRegistered(ttid3)
        self.manager.abortFor(uuid2)
        # only tid3 is aborted
        self.assertRegistered(ttid1)
        self.assertRegistered(ttid2)
        self.assertNotRegistered(ttid3)
        self._checkQueuedEventExecuted(number=1)

    def testReset(self):
        """ Reset the manager """
        uuid = self.getClientUUID()
        tid, txn = self._getTransaction()
        ttid = self.getNextTID()
        self.manager.register(uuid, ttid)
        self._storeTransactionObjects(ttid, txn)
        self.manager.vote(ttid, txn)
        self.manager.lock(ttid, tid)
        self.assertRegistered(ttid)
        self.manager.reset()
        self.assertNotRegistered(ttid)
        for oid in txn[0]:
            self.assertFalse(self.manager.loadLocked(oid))

    def test_getObjectFromTransaction(self):
        data_id = random.random()
        self.app.dm.mockAddReturnValues(holdData=ReturnValues(data_id))
        uuid = self.getClientUUID()
        tid1, txn1 = self._getTransaction()
        tid2, txn2 = self._getTransaction()
        serial1, obj1 = self._getObject(1)
        serial2, obj2 = self._getObject(2)
        self.manager.register(uuid, tid1)
        self.manager.storeObject(tid1, serial1, *obj1)
        self.assertEqual(self.manager.getObjectFromTransaction(tid2, obj1[0]),
            None)
        self.assertEqual(self.manager.getObjectFromTransaction(tid1, obj2[0]),
            None)
        self.assertEqual(self.manager.getObjectFromTransaction(tid1, obj1[0]),
            (obj1[0], data_id, obj1[4]))

    def test_getLockingTID(self):
        uuid = self.getClientUUID()
        serial1, obj1 = self._getObject(1)
        oid1 = obj1[0]
        tid1, txn1 = self._getTransaction()
        self.assertEqual(self.manager.getLockingTID(oid1), None)
        self.manager.register(uuid, tid1)
        self.manager.storeObject(tid1, serial1, *obj1)
        self.assertEqual(self.manager.getLockingTID(oid1), tid1)

    def test_updateObjectDataForPack(self):
        ram_serial = self.getNextTID()
        oid = self.getOID(1)
        orig_serial = self.getNextTID()
        uuid = self.getClientUUID()
        locking_serial = self.getNextTID()
        other_serial = self.getNextTID()
        new_serial = self.getNextTID()
        checksum = "2" * 20
        self.manager.register(uuid, locking_serial)
        # Object not known, nothing happens
        self.assertEqual(self.manager.getObjectFromTransaction(locking_serial,
            oid), None)
        self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum)
        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, "3" * 20,
            'bar', None)
        holdData = self.app.dm.mockGetNamedCalls('holdData')
        self.assertEqual(holdData.pop(0).params, ("3" * 20, 'bar', 0))
        orig_object = self.manager.getObjectFromTransaction(locking_serial,
            oid)
        self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum)
        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,
            oid)
        self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum)
        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
        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,
            checksum)
        self.assertEqual(self.manager.getObjectFromTransaction(locking_serial,
            oid), (oid, None, new_serial))
        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, orig_serial)
        self.manager.updateObjectDataForPack(oid, orig_serial, None, checksum)
        self.assertEqual(holdData.pop(0).params, (checksum,))
        self.assertEqual(self.manager.getObjectFromTransaction(locking_serial,
            oid), (oid, checksum, None))
        self.manager.abort(locking_serial, even_if_locked=True)
        self.assertFalse(holdData)