def testClientDisconectsAfterBegin(self): client_uuid1, node1 = self.makeNode(NodeTypes.CLIENT) tm = TransactionManager(None) tid1 = self.getNextTID() tid2 = self.getNextTID() tm.begin(node1, 0, tid1) self.assertEqual(1, len(list(tm.clientLost(node1)))) self.assertNotIn(tid1, tm)
def testClientDisconectsAfterBegin(self): client_uuid1, node1 = self.makeNode(NodeTypes.CLIENT) tm = TransactionManager(lambda tid, txn: None) tid1 = self.getNextTID() tid2 = self.getNextTID() tm.begin(node1, tid1) tm.clientLost(node1) self.assertTrue(tid1 not in tm)
def test_storageLost(self): client1 = Mock({'__hash__': 1}) client2 = Mock({'__hash__': 2}) client3 = Mock({'__hash__': 3}) storage_1_uuid = self.getStorageUUID() storage_2_uuid = self.getStorageUUID() oid_list = [ self.makeOID(1), ] tm = TransactionManager(lambda tid, txn: None) # Transaction 1: 2 storage nodes involved, one will die and the other # already answered node lock msg_id_1 = 1 ttid1 = tm.begin(client1) tid1 = tm.prepare(ttid1, 1, oid_list, [storage_1_uuid, storage_2_uuid], msg_id_1) tm.lock(ttid1, storage_2_uuid) t1 = tm[ttid1] self.assertFalse(t1.locked()) # Storage 1 dies: # t1 is over self.assertTrue(t1.storageLost(storage_1_uuid)) self.assertEqual(t1.getUUIDList(), [storage_2_uuid]) del tm[ttid1] # Transaction 2: 2 storage nodes involved, one will die msg_id_2 = 2 ttid2 = tm.begin(client2) tid2 = tm.prepare(ttid2, 1, oid_list, [storage_1_uuid, storage_2_uuid], msg_id_2) t2 = tm[ttid2] self.assertFalse(t2.locked()) # Storage 1 dies: # t2 still waits for storage 2 self.assertFalse(t2.storageLost(storage_1_uuid)) self.assertEqual(t2.getUUIDList(), [storage_2_uuid]) self.assertTrue(t2.lock(storage_2_uuid)) del tm[ttid2] # Transaction 3: 1 storage node involved, which won't die msg_id_3 = 3 ttid3 = tm.begin(client3) tid3 = tm.prepare(ttid3, 1, oid_list, [ storage_2_uuid, ], msg_id_3) t3 = tm[ttid3] self.assertFalse(t3.locked()) # Storage 1 dies: # t3 doesn't care self.assertFalse(t3.storageLost(storage_1_uuid)) self.assertEqual(t3.getUUIDList(), [storage_2_uuid]) self.assertTrue(t3.lock(storage_2_uuid)) del tm[ttid3]
def test_storageLost(self): client1 = Mock({'__hash__': 1}) client2 = Mock({'__hash__': 2}) client3 = Mock({'__hash__': 3}) storage_1_uuid = self.getStorageUUID() storage_2_uuid = self.getStorageUUID() oid_list = [self.makeOID(1), ] tm = TransactionManager(lambda tid, txn: None) # Transaction 1: 2 storage nodes involved, one will die and the other # already answered node lock msg_id_1 = 1 ttid1 = tm.begin(client1) tid1 = tm.prepare(ttid1, 1, oid_list, [storage_1_uuid, storage_2_uuid], msg_id_1) tm.lock(ttid1, storage_2_uuid) t1 = tm[ttid1] self.assertFalse(t1.locked()) # Storage 1 dies: # t1 is over self.assertTrue(t1.storageLost(storage_1_uuid)) self.assertEqual(t1.getUUIDList(), [storage_2_uuid]) del tm[ttid1] # Transaction 2: 2 storage nodes involved, one will die msg_id_2 = 2 ttid2 = tm.begin(client2) tid2 = tm.prepare(ttid2, 1, oid_list, [storage_1_uuid, storage_2_uuid], msg_id_2) t2 = tm[ttid2] self.assertFalse(t2.locked()) # Storage 1 dies: # t2 still waits for storage 2 self.assertFalse(t2.storageLost(storage_1_uuid)) self.assertEqual(t2.getUUIDList(), [storage_2_uuid]) self.assertTrue(t2.lock(storage_2_uuid)) del tm[ttid2] # Transaction 3: 1 storage node involved, which won't die msg_id_3 = 3 ttid3 = tm.begin(client3) tid3 = tm.prepare(ttid3, 1, oid_list, [storage_2_uuid, ], msg_id_3) t3 = tm[ttid3] self.assertFalse(t3.locked()) # Storage 1 dies: # t3 doesn't care self.assertFalse(t3.storageLost(storage_1_uuid)) self.assertEqual(t3.getUUIDList(), [storage_2_uuid]) self.assertTrue(t3.lock(storage_2_uuid)) del tm[ttid3]
def testUnlockPending(self): callback = Mock() uuid1, node1 = self.makeNode(NodeTypes.CLIENT) uuid2, node2 = self.makeNode(NodeTypes.CLIENT) storage_uuid = self.getStorageUUID() tm = TransactionManager(callback) ttid1 = tm.begin(node1) ttid2 = tm.begin(node2) tid1 = tm.prepare(ttid1, 1, [], [storage_uuid], 0) tid2 = tm.prepare(ttid2, 1, [], [storage_uuid], 0) tm.lock(ttid2, storage_uuid) # txn 2 is still blocked by txn 1 self.assertEqual(len(callback.getNamedCalls('__call__')), 0) tm.lock(ttid1, storage_uuid) # both transactions are unlocked when txn 1 is fully locked self.assertEqual(len(callback.getNamedCalls('__call__')), 2)
def testTransactionLock(self): """ Transaction lock is present to ensure invalidation TIDs are sent in strictly increasing order. Note: this implementation might change later, to allow more paralelism. """ client_uuid, client = self.makeNode(NodeTypes.CLIENT) tm = TransactionManager(lambda tid, txn: None) # With a requested TID, lock spans from begin to remove ttid1 = self.getNextTID() ttid2 = self.getNextTID() tid1 = tm.begin(client, ttid1) self.assertEqual(tid1, ttid1) del tm[ttid1] # Without a requested TID, lock spans from prepare to remove only ttid3 = tm.begin(client) ttid4 = tm.begin(client) # Doesn't raise node = Mock({'getUUID': client_uuid, '__hash__': 0}) tid4 = tm.prepare(ttid4, 1, [], [], 0) del tm[ttid4] tm.prepare(ttid3, 1, [], [], 0)
def testManager(self): # test data node = Mock({'__hash__': 1}) msg_id = 1 oid_list = (oid1, oid2) = self.makeOID(1), self.makeOID(2) uuid_list = uuid1, uuid2 = self.getStorageUUID(), self.getStorageUUID() client_uuid = self.getClientUUID() # create transaction manager callback = Mock() txnman = TransactionManager(on_commit=callback) self.assertFalse(txnman.hasPending()) self.assertEqual(txnman.registerForNotification(uuid1), []) # begin the transaction ttid = txnman.begin(node) self.assertTrue(ttid is not None) self.assertEqual(len(txnman.registerForNotification(uuid1)), 1) self.assertTrue(txnman.hasPending()) # prepare the transaction tid = txnman.prepare(ttid, 1, oid_list, uuid_list, msg_id) self.assertTrue(txnman.hasPending()) self.assertEqual(txnman.registerForNotification(uuid1), [ttid]) txn = txnman[ttid] self.assertEqual(txn.getTID(), tid) self.assertEqual(txn.getUUIDList(), list(uuid_list)) self.assertEqual(txn.getOIDList(), list(oid_list)) # lock nodes txnman.lock(ttid, uuid1) self.assertEqual(len(callback.getNamedCalls('__call__')), 0) txnman.lock(ttid, uuid2) self.assertEqual(len(callback.getNamedCalls('__call__')), 1) self.assertEqual(txnman.registerForNotification(uuid1), [])