diff --git a/neo/client/app.py b/neo/client/app.py index 619699e722ef93bd1f6dd05b6882374b265564f0..5f45004a859399ca923022c96778b949c122fe0b 100644 --- a/neo/client/app.py +++ b/neo/client/app.py @@ -584,7 +584,7 @@ class Application(object): # Store object in tmp cache self.local_var.data_dict[oid] = data # Store data on each node - self.local_var.object_stored_counter_dict[oid] = 0 + self.local_var.object_stored_counter_dict[oid] = {} self.local_var.object_serial_dict[oid] = (serial, version) getConnForCell = self.cp.getConnForCell for cell in cell_list: @@ -663,9 +663,9 @@ class Application(object): break # Check for never-stored objects, and update result for all others - for oid, store_count in \ + for oid, store_dict in \ local_var.object_stored_counter_dict.iteritems(): - if store_count == 0: + if not store_dict: raise NEOStorageError('tpc_store failed') elif oid in resolved_oid_set: append((oid, ResolvedSerial)) diff --git a/neo/client/handlers/storage.py b/neo/client/handlers/storage.py index add3680e99f2431719f00f8c697c2fd91e3519a4..7156aa0dfc81b73b4478eb86f5cc7dcc881d8088 100644 --- a/neo/client/handlers/storage.py +++ b/neo/client/handlers/storage.py @@ -69,7 +69,7 @@ class StorageAnswersHandler(AnswerBaseHandler): def answerStoreObject(self, conn, conflicting, oid, serial): local_var = self.app.local_var - object_stored_counter_dict = local_var.object_stored_counter_dict + object_stored_counter_dict = local_var.object_stored_counter_dict[oid] if conflicting: conflict_serial_dict = local_var.conflict_serial_dict pending_serial = conflict_serial_dict.get(oid) @@ -80,18 +80,19 @@ class StorageAnswersHandler(AnswerBaseHandler): 'object (%s) in a single store: %s, %s, %s' % ( dump(oid), dump(pending_serial), dump(resolved_serial), dump(serial)) + if serial in object_stored_counter_dict: + raise NEOStorageError, 'A storage accepted object for ' \ + 'serial %s but another reports a conflict for it.' % ( + dump(serial), ) # If this conflict is not already resolved, mark it for # resolution. if resolved_serial is None: - if object_stored_counter_dict[oid]: - raise NEOStorageError, 'Storage node(s) accepted ' \ - 'object %s, but one (%s) reports a conflict.' % ( - dump(oid), dump(conn.getUUID())) # Note: we might overwrite an entry, but above test protects # against overwriting a different value. conflict_serial_dict[oid] = serial else: - object_stored_counter_dict[oid] += 1 + object_stored_counter_dict[serial] = \ + object_stored_counter_dict.get(serial, 0) + 1 def answerStoreTransaction(self, conn, tid): if tid != self.app.getTID(): diff --git a/neo/tests/client/testClientApp.py b/neo/tests/client/testClientApp.py index 09a735d1593bf133700a7cd754e7317dfa1d4a63..d3cbcb5dc041cb0224eb8047022ee4f9ee2d4f71 100644 --- a/neo/tests/client/testClientApp.py +++ b/neo/tests/client/testClientApp.py @@ -463,7 +463,7 @@ class ClientApplicationTests(NeoTestBase): failing_tryToResolveConflict) self.assertTrue(oid not in app.local_var.data_dict) self.assertEquals(app.local_var.conflict_serial_dict[oid], tid) - self.assertEquals(app.local_var.object_stored_counter_dict[oid], 0) + self.assertEquals(app.local_var.object_stored_counter_dict[oid], {}) self.checkAskStoreObject(conn) def test_store3(self): @@ -496,7 +496,7 @@ class ClientApplicationTests(NeoTestBase): self.checkAskStoreObject(conn) app.local_var.queue.put((conn, packet)) app.waitStoreResponses(resolving_tryToResolveConflict) - self.assertEquals(app.local_var.object_stored_counter_dict[oid], 1) + self.assertEquals(app.local_var.object_stored_counter_dict[oid], {tid: 1}) self.assertEquals(app.local_var.data_dict.get(oid, None), 'DATA') self.assertFalse(oid in app.local_var.conflict_serial_dict) diff --git a/neo/tests/client/testStorageHandler.py b/neo/tests/client/testStorageHandler.py index 6a6f428002547055e293ef398f43d39febcf7472..11a2f8ad626290a69e09c0b4f33067631b12e75f 100644 --- a/neo/tests/client/testStorageHandler.py +++ b/neo/tests/client/testStorageHandler.py @@ -93,15 +93,15 @@ class StorageAnswerHandlerTests(NeoTestBase): tid = self.getNextTID() # conflict local_var = self.app.local_var - local_var.object_stored_counter_dict = {oid: 0} + local_var.object_stored_counter_dict = {oid: {}} local_var.conflict_serial_dict = {} local_var.resolved_conflict_serial_dict = {} self.handler.answerStoreObject(conn, 1, oid, tid) self.assertEqual(local_var.conflict_serial_dict[oid], tid) - self.assertEqual(local_var.object_stored_counter_dict[oid], 0) + self.assertEqual(local_var.object_stored_counter_dict[oid], {}) self.assertFalse(oid in local_var.resolved_conflict_serial_dict) # object was already accepted by another storage, raise - local_var.object_stored_counter_dict = {oid: 1} + local_var.object_stored_counter_dict = {oid: {tid: 1}} local_var.conflict_serial_dict = {} local_var.resolved_conflict_serial_dict = {} self.assertRaises(NEOStorageError, self.handler.answerStoreObject, @@ -114,21 +114,21 @@ class StorageAnswerHandlerTests(NeoTestBase): tid_2 = self.getNextTID() # resolution-pending conflict local_var = self.app.local_var - local_var.object_stored_counter_dict = {oid: 0} + local_var.object_stored_counter_dict = {oid: {}} local_var.conflict_serial_dict = {oid: tid} local_var.resolved_conflict_serial_dict = {} self.handler.answerStoreObject(conn, 1, oid, tid) self.assertEqual(local_var.conflict_serial_dict[oid], tid) self.assertFalse(oid in local_var.resolved_conflict_serial_dict) - self.assertEqual(local_var.object_stored_counter_dict[oid], 0) + self.assertEqual(local_var.object_stored_counter_dict[oid], {}) # object was already accepted by another storage, raise - local_var.object_stored_counter_dict = {oid: 1} + local_var.object_stored_counter_dict = {oid: {tid: 1}} local_var.conflict_serial_dict = {oid: tid} local_var.resolved_conflict_serial_dict = {} self.assertRaises(NEOStorageError, self.handler.answerStoreObject, conn, 1, oid, tid) # detected conflict is different, raise - local_var.object_stored_counter_dict = {oid: 0} + local_var.object_stored_counter_dict = {oid: {}} local_var.conflict_serial_dict = {oid: tid} local_var.resolved_conflict_serial_dict = {} self.assertRaises(NEOStorageError, self.handler.answerStoreObject, @@ -144,15 +144,15 @@ class StorageAnswerHandlerTests(NeoTestBase): # any other storage already answered (with same conflict) and any other # storage accepted the resolved object. local_var = self.app.local_var - local_var.object_stored_counter_dict = {oid: 1} + local_var.object_stored_counter_dict = {oid: {tid_2: 1}} local_var.conflict_serial_dict = {} local_var.resolved_conflict_serial_dict = {oid: tid} self.handler.answerStoreObject(conn, 1, oid, tid) self.assertFalse(oid in local_var.conflict_serial_dict) self.assertEqual(local_var.resolved_conflict_serial_dict[oid], tid) - self.assertEqual(local_var.object_stored_counter_dict[oid], 1) + self.assertEqual(local_var.object_stored_counter_dict[oid], {tid_2: 1}) # detected conflict is different, raise - local_var.object_stored_counter_dict = {oid: 1} + local_var.object_stored_counter_dict = {oid: {tid: 1}} local_var.conflict_serial_dict = {} local_var.resolved_conflict_serial_dict = {oid: tid} self.assertRaises(NEOStorageError, self.handler.answerStoreObject, @@ -164,13 +164,13 @@ class StorageAnswerHandlerTests(NeoTestBase): tid = self.getNextTID() # no conflict local_var = self.app.local_var - local_var.object_stored_counter_dict = {oid: 0} + local_var.object_stored_counter_dict = {oid: {}} local_var.conflict_serial_dict = {} local_var.resolved_conflict_serial_dict = {} self.handler.answerStoreObject(conn, 0, oid, tid) self.assertFalse(oid in local_var.conflict_serial_dict) self.assertFalse(oid in local_var.resolved_conflict_serial_dict) - self.assertEqual(local_var.object_stored_counter_dict[oid], 1) + self.assertEqual(local_var.object_stored_counter_dict[oid], {tid: 1}) def test_answerStoreTransaction(self): conn = self.getConnection()