diff --git a/neo/client/Storage.py b/neo/client/Storage.py index be1c3dd3f0101f821e7435da7f43674bf20cade2..cce637ce3ba1a90a816ebc1e8a244fe595c65429 100644 --- a/neo/client/Storage.py +++ b/neo/client/Storage.py @@ -100,19 +100,21 @@ class Storage(BaseStorage.BaseStorage, data = data, version = version, transaction = transaction) except NEOStorageConflictError: - if app.conflict_serial <= app.tid: + conflict_serial = app.getConflictSerial() + tid = app.getTID() + if conflict_serial <= tid: # Try to resolve conflict only if conflicting serial is older # than the current transaction ID new_data = self.tryToResolveConflict(oid, - app.conflict_serial, + conflict_serial, serial, data) if new_data is not None: # Try again after conflict resolution - self.store(oid, app.conflict_serial, + self.store(oid, conflict_serial, new_data, version, transaction) return ConflictResolution.ResolvedSerial raise POSException.ConflictError(oid=oid, - serials=(app.tid, + serials=(tid, serial),data=data) def _clear_temp(self): diff --git a/neo/client/app.py b/neo/client/app.py index 502e40be82df1f4625527be176f84fad70b5efc8..51e4c62f022ad9a8169cf73b152c9f5fc69319cf 100644 --- a/neo/client/app.py +++ b/neo/client/app.py @@ -212,8 +212,8 @@ class Application(object): self.txn = None self.txn_data_dict = {} self.txn_object_stored = 0 - self.txn_voted = 0 - self.txn_finished = 0 + self.txn_voted = False + self.txn_finished = False # Internal attribute distinct between thread self.local_var = local() # Lock definition : @@ -554,12 +554,12 @@ class Application(object): conn.addPacket(p) conn.expectMessage(msg_id) self.dispatcher.register(conn, msg_id, self.getQueue()) - self.txn_voted = 0 + self.txn_voted = False finally: conn.unlock() self._waitMessage(conn, msg_id) - if self.txn_voted != 1: + if not self.isTransactionVoted(): raise NEOStorageError('tpc_vote failed') def _clear_txn(self): @@ -567,8 +567,8 @@ class Application(object): self.tid = None self.txn = None self.txn_data_dict.clear() - self.txn_voted = 0 - self.txn_finished = 0 + self.txn_voted = False + self.txn_finished = False def tpc_abort(self, transaction): """Abort current transaction.""" @@ -651,7 +651,7 @@ class Application(object): # Wait for answer self._waitMessage(conn, msg_id) - if self.txn_finished != 1: + if not self.isTransactionFinished(): raise NEOStorageError('tpc_finish failed') # Update cache @@ -1000,3 +1000,24 @@ class Application(object): def isNodeReady(self): return self.local_var.node_ready + def setTID(self, value): + self.tid = value + + def getTID(self): + return self.tid + + def getConflictSerial(self): + return self.conflict_serial + + def setTransactionFinished(self): + self.txn_finished = True + + def isTransactionFinished(self): + return self.txn_finished + + def setTransactionVoted(self): + self.txn_voted = True + + def isTransactionVoted(self): + return self.txn_voted + diff --git a/neo/client/handler.py b/neo/client/handler.py index 60821d18274610ec5e8d1818cc50b9f90b4f6cb0..5bc240dad0154d45e2fa1f1bca37db4fa8111d85 100644 --- a/neo/client/handler.py +++ b/neo/client/handler.py @@ -401,7 +401,7 @@ class ClientAnswerEventHandler(BaseClientEventHandler): def handleAnswerNewTID(self, conn, packet, tid): app = self.app - app.tid = tid + app.setTID(tid) def handleAnswerNewOIDs(self, conn, packet, oid_list): app = self.app @@ -410,11 +410,8 @@ class ClientAnswerEventHandler(BaseClientEventHandler): def handleNotifyTransactionFinished(self, conn, packet, tid): app = self.app - if tid != app.tid: - app.txn_finished = -1 - else: - app.txn_finished = 1 - + if tid == app.getTID(): + app.setTransactionFinished() # Storage node handler def handleAnswerObject(self, conn, packet, oid, start_serial, end_serial, compression, @@ -432,7 +429,7 @@ class ClientAnswerEventHandler(BaseClientEventHandler): def handleAnswerStoreTransaction(self, conn, packet, tid): app = self.app - app.txn_voted = 1 + app.setTransactionVoted() def handleAnswerTransactionInformation(self, conn, packet, tid, user, desc, ext, oid_list): diff --git a/neo/client/tests/testClientHandler.py b/neo/client/tests/testClientHandler.py index 568c5ed14e05c127f3f3bf6b021a957d953e85a3..95536a96e867e61a97604f68fa478e4861892fe1 100644 --- a/neo/client/tests/testClientHandler.py +++ b/neo/client/tests/testClientHandler.py @@ -830,26 +830,24 @@ class ClientEventHandlerTest(unittest.TestCase): self.assertEqual(state, test_cell_list[0][2]) def test_AnswerNewTID(self): - class App: - tid = None - app = App() + app = Mock({'setTID': None}) dispatcher = self.getDispatcher() client_handler = ClientAnswerEventHandler(app, dispatcher) conn = self.getConnection() test_tid = 1 client_handler.handleAnswerNewTID(conn, None, test_tid) - self.assertEquals(app.tid, test_tid) + setTID_call_list = app.mockGetNamedCalls('setTID') + self.assertEquals(len(setTID_call_list), 1) + self.assertEquals(setTID_call_list[0].getParam(0), test_tid) def test_NotifyTransactionFinished(self): - class App: - tid = 1 - txn_finished = None - app = App() + test_tid = 1 + app = Mock({'getTID': test_tid, 'setTransactionFinished': None}) dispatcher = self.getDispatcher() client_handler = ClientAnswerEventHandler(app, dispatcher) conn = self.getConnection() - client_handler.handleNotifyTransactionFinished(conn, None, 1) - self.assertEquals(app.txn_finished, 1) + client_handler.handleNotifyTransactionFinished(conn, None, test_tid) + self.assertEquals(len(app.mockGetNamedCalls('setTransactionFinished')), 1) # TODO: decide what to do when non-current transaction is notified as finished, and test that behaviour def test_InvalidateObjects(self): @@ -949,16 +947,13 @@ class ClientEventHandlerTest(unittest.TestCase): self.assertEqual(app.txn_object_stored, (test_oid, test_serial)) def test_AnswerStoreTransaction(self): - class App: - tid = 10 - txn_voted = 0 - app = App() + test_tid = 10 + app = Mock({'getTID': test_tid, 'setTransactionVoted': None}) dispatcher = self.getDispatcher() client_handler = ClientAnswerEventHandler(app, dispatcher) conn = self.getConnection() - test_tid = 10 client_handler.handleAnswerStoreTransaction(conn, None, test_tid) - self.assertEquals(app.txn_voted, 1) + self.assertEquals(len(app.mockGetNamedCalls('setTransactionVoted')), 1) # TODO: test handleAnswerObject with test_tid not matching app.tid (not handled in program) def test_AnswerTransactionInformation(self):