[Neo-report] r2569 gregory - in /trunk/neo: master/ tests/ tests/master/
nobody at svn.erp5.org
nobody at svn.erp5.org
Thu Dec 23 17:04:25 CET 2010
Author: gregory
Date: Thu Dec 23 17:04:25 2010
New Revision: 2569
Log:
Many fixes for r2564.
- Pop queued transaction from the beginning instead of end
- Restore test for begin with a tid
- Add test to check transactions unlocking mechanism
- Add/fix comments
Modified:
trunk/neo/master/transactions.py
trunk/neo/tests/__init__.py
trunk/neo/tests/master/testClientHandler.py
trunk/neo/tests/master/testTransactions.py
Modified: trunk/neo/master/transactions.py
==============================================================================
--- trunk/neo/master/transactions.py [iso-8859-1] (original)
+++ trunk/neo/master/transactions.py [iso-8859-1] Thu Dec 23 17:04:25 2010
@@ -389,6 +389,7 @@ class TransactionManager(object):
A storage node has been lost, don't expect a reply from it for
current transactions
"""
+ # iterate over a copy because _unlockPending may alter the dict
for tid, txn in self._tid_dict.items():
if txn.forget(uuid):
self._unlockPending()
@@ -396,34 +397,32 @@ class TransactionManager(object):
def _unlockPending(self):
# unlock pending transactions
while self._queue:
- tid = self._queue[0][1]
- # _queue can contain un-prepared transactions
+ uuid, tid = self._queue.pop(0)
txn = self._tid_dict.get(tid, None)
+ # _queue can contain un-prepared transactions
if txn is not None and txn.locked():
- self._queue.pop()
self._on_commit(tid, txn)
else:
+ self._queue.insert(0, (uuid, tid))
break
def abortFor(self, node):
"""
Abort pending transactions initiated by a node
"""
- neo.logging.debug('Abort for %s', node)
- # nothing to do
- if node not in self._node_dict:
- return
- # remove transactions
+ neo.logging.debug('Abort TXN for %s', node)
uuid = node.getUUID()
- remove = self.remove
- for tid in self._node_dict[node].keys():
- remove(uuid, tid)
- # the code below is usefull only during an import
+ # XXX: this loop is usefull only during an import
for nuuid, ntid in list(self._queue):
if nuuid == uuid:
- self._queue.remove((uuid, tid))
- # discard node entry
- del self._node_dict[node]
+ self._queue.remove((uuid, ntid))
+ if node in self._node_dict:
+ # remove transactions
+ remove = self.remove
+ for tid in self._node_dict[node].keys():
+ remove(uuid, tid)
+ # discard node entry
+ del self._node_dict[node]
def log(self):
neo.logging.info('Transactions:')
Modified: trunk/neo/tests/__init__.py
==============================================================================
--- trunk/neo/tests/__init__.py [iso-8859-1] (original)
+++ trunk/neo/tests/__init__.py [iso-8859-1] Thu Dec 23 17:04:25 2010
@@ -375,6 +375,9 @@ class NeoUnitTestBase(NeoTestBase):
def checkAnswerTransactionInformation(self, conn, **kw):
return self.checkAnswerPacket(conn, Packets.AnswerTransactionInformation, **kw)
+ def checkAnswerBeginTransaction(self, conn, **kw):
+ return self.checkAnswerPacket(conn, Packets.AnswerBeginTransaction, **kw)
+
def checkAnswerTids(self, conn, **kw):
return self.checkAnswerPacket(conn, Packets.AnswerTIDs, **kw)
Modified: trunk/neo/tests/master/testClientHandler.py
==============================================================================
--- trunk/neo/tests/master/testClientHandler.py [iso-8859-1] (original)
+++ trunk/neo/tests/master/testClientHandler.py [iso-8859-1] Thu Dec 23 17:04:25 2010
@@ -79,9 +79,16 @@ class MasterClientHandlerTests(NeoUnitTe
calls = tm.mockGetNamedCalls('begin')
self.assertEqual(len(calls), 1)
calls[0].checkArgs(client_uuid, None)
+ self.checkAnswerBeginTransaction(conn)
# Client asks for a TID
+ conn = self.getFakeConnection(client_uuid, self.client_address)
self.app.tm = tm_org
service.askBeginTransaction(conn, tid1)
+ calls = tm.mockGetNamedCalls('begin')
+ self.assertEqual(len(calls), 1)
+ calls[0].checkArgs(client_uuid, None)
+ args = self.checkAnswerBeginTransaction(conn, decode=True)
+ self.assertEqual(args, (tid1, ))
def test_08_askNewOIDs(self):
service = self.service
Modified: trunk/neo/tests/master/testTransactions.py
==============================================================================
--- trunk/neo/tests/master/testTransactions.py [iso-8859-1] (original)
+++ trunk/neo/tests/master/testTransactions.py [iso-8859-1] Thu Dec 23 17:04:25 2010
@@ -35,6 +35,11 @@ class testTransactionManager(NeoUnitTest
def makeUUID(self, i):
return '\0' * 12 + pack('!Q', i)
+ def makeNode(self, i):
+ uuid = self.makeUUID(i)
+ node = Mock({'getUUID': uuid, '__hash__': 0})
+ return uuid, node
+
def testTransaction(self):
# test data
node = Mock({'__repr__': 'Node'})
@@ -108,7 +113,7 @@ class testTransactionManager(NeoUnitTest
self.assertEqual(txnman.getPendingList(), [])
self.assertFalse(txnman.hasPending())
# ...and the lock is available
- txnman.begin(self.getNextTID())
+ txnman.begin(client_uuid, self.getNextTID())
def test_getNextOIDList(self):
txnman = TransactionManager(lambda tid, txn: None)
@@ -226,14 +231,30 @@ class testTransactionManager(NeoUnitTest
def testClientDisconectsAfterBegin(self):
client1_uuid = self.makeUUID(1)
- client2_uuid = self.makeUUID(2)
tm = TransactionManager(lambda tid, txn: None)
tid1 = self.getNextTID()
tid2 = self.getNextTID()
- tm.begin(tid1)
+ tm.begin(client1_uuid, tid1)
node1 = Mock({'getUUID': client1_uuid, '__hash__': 0})
tm.abortFor(node1)
- tm.begin(tid2)
+ self.assertTrue(tid1 not in tm)
+
+ def testUnlockPending(self):
+ callback = Mock()
+ uuid1, node1 = self.makeNode(1)
+ uuid2, node2 = self.makeNode(2)
+ storage_uuid = self.makeUUID(3)
+ tm = TransactionManager(callback)
+ ttid1 = tm.begin(uuid1)
+ ttid2 = tm.begin(uuid2)
+ tid1 = tm.prepare(node1, ttid1, 1, [], [storage_uuid], 0)
+ tid2 = tm.prepare(node2, ttid2, 1, [], [storage_uuid], 0)
+ tm.lock(tid2, storage_uuid)
+ # txn 2 is still blocked by txn 1
+ self.assertEqual(len(callback.getNamedCalls('__call__')), 0)
+ tm.lock(tid1, storage_uuid)
+ # both transactions are unlocked when txn 1 is fully locked
+ self.assertEqual(len(callback.getNamedCalls('__call__')), 2)
if __name__ == '__main__':
unittest.main()
More information about the Neo-report
mailing list