)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1e5f07681b7f74b15b67983bb05d2fec2d63aa61","unresolved":false,"context_lines":[{"line_number":18,"context_line":"1. Related-Change: I91f3d4af52cbc66c9f7ce00726f247b5462e66f9"},{"line_number":19,"context_line":"2. Related-Change: I2310981fd1c4622ff5d1a739cbcc59637ffe3fc3"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"Closes-Bug: 1624176"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"Change-Id: I06fc381a25613585dd18916d50e7ca2c68d406b6"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"7a8ec9b2_5f3a7635","line":21,"updated":"2016-09-20 18:39:40.000000000","message":"nit: closes-bug or related-bug? IDK. but whichever, the bug report should be marked as fixed","commit_id":"73dbbce556830b4ff04329e83d59e5c4ce82120c"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"083228985d824a7f0755af207d7f0615ad251627","unresolved":false,"context_lines":[{"line_number":18,"context_line":"1. Related-Change: I91f3d4af52cbc66c9f7ce00726f247b5462e66f9"},{"line_number":19,"context_line":"2. Related-Change: I2310981fd1c4622ff5d1a739cbcc59637ffe3fc3"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"Closes-Bug: 1624176"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"Change-Id: I06fc381a25613585dd18916d50e7ca2c68d406b6"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"ba5da102_ae86c1d8","line":21,"in_reply_to":"7a8ec9b2_5f3a7635","updated":"2016-11-02 00:07:42.000000000","message":"Done","commit_id":"73dbbce556830b4ff04329e83d59e5c4ce82120c"}],"test/probe/test_object_handoff.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1e5f07681b7f74b15b67983bb05d2fec2d63aa61","unresolved":false,"context_lines":[{"line_number":351,"context_line":"                    node, opart, self.account, container_name,"},{"line_number":352,"context_line":"                    object_name, headers\u003dreq_headers)"},{"line_number":353,"context_line":"            except Exception as e:"},{"line_number":354,"context_line":"                print(\u0027node %r raised %r\u0027 % (node, e))"},{"line_number":355,"context_line":"                continue"},{"line_number":356,"context_line":"            found_frags[headers[\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027]] +\u003d 1"},{"line_number":357,"context_line":"        return found_frags"}],"source_content_type":"text/x-python","patch_set":2,"id":"7a8ec9b2_d36da8cd","line":354,"updated":"2016-09-20 18:39:40.000000000","message":"do we want this print? Exceptions are expected so its not a warning.","commit_id":"73dbbce556830b4ff04329e83d59e5c4ce82120c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"48ed3d477d6800cc01145fcdceac248e762224e8","unresolved":false,"context_lines":[{"line_number":351,"context_line":"                    node, opart, self.account, container_name,"},{"line_number":352,"context_line":"                    object_name, headers\u003dreq_headers)"},{"line_number":353,"context_line":"            except Exception as e:"},{"line_number":354,"context_line":"                print(\u0027node %r raised %r\u0027 % (node, e))"},{"line_number":355,"context_line":"                continue"},{"line_number":356,"context_line":"            found_frags[headers[\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027]] +\u003d 1"},{"line_number":357,"context_line":"        return found_frags"}],"source_content_type":"text/x-python","patch_set":2,"id":"7a8ec9b2_d97026a7","line":354,"in_reply_to":"7a8ec9b2_d36da8cd","updated":"2016-09-21 16:21:34.000000000","message":"conversely, I ended up adding something like:\n\n      print(\u0027node %r has frag %s\u0027 % (node, headers[\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027])\n\nat line 353 to get the full picture.","commit_id":"73dbbce556830b4ff04329e83d59e5c4ce82120c"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"083228985d824a7f0755af207d7f0615ad251627","unresolved":false,"context_lines":[{"line_number":351,"context_line":"                    node, opart, self.account, container_name,"},{"line_number":352,"context_line":"                    object_name, headers\u003dreq_headers)"},{"line_number":353,"context_line":"            except Exception as e:"},{"line_number":354,"context_line":"                print(\u0027node %r raised %r\u0027 % (node, e))"},{"line_number":355,"context_line":"                continue"},{"line_number":356,"context_line":"            found_frags[headers[\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027]] +\u003d 1"},{"line_number":357,"context_line":"        return found_frags"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba5da102_69890375","line":354,"in_reply_to":"7a8ec9b2_d97026a7","updated":"2016-11-02 00:07:42.000000000","message":"you know *honestly* I think I meant to tighten up the expected exceptions","commit_id":"73dbbce556830b4ff04329e83d59e5c4ce82120c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1e5f07681b7f74b15b67983bb05d2fec2d63aa61","unresolved":false,"context_lines":[{"line_number":401,"context_line":"            handoff_frags.append((node, headers, data))"},{"line_number":402,"context_line":""},{"line_number":403,"context_line":"        # bring the first double primary back, and fail the other one"},{"line_number":404,"context_line":"        config_number, node_list \u003d double_disk_primary[0]"},{"line_number":405,"context_line":"        Manager([\u0027object-server\u0027]).start(number\u003dconfig_number)"},{"line_number":406,"context_line":"        config_number, node_list \u003d double_disk_primary[1]"},{"line_number":407,"context_line":"        Manager([\u0027object-server\u0027]).stop(number\u003dconfig_number)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7a8ec9b2_8a2053b2","line":404,"updated":"2016-09-20 18:39:40.000000000","message":"nit: these don\u0027t need to be reassigned - unchanged from line 386","commit_id":"73dbbce556830b4ff04329e83d59e5c4ce82120c"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"083228985d824a7f0755af207d7f0615ad251627","unresolved":false,"context_lines":[{"line_number":401,"context_line":"            handoff_frags.append((node, headers, data))"},{"line_number":402,"context_line":""},{"line_number":403,"context_line":"        # bring the first double primary back, and fail the other one"},{"line_number":404,"context_line":"        config_number, node_list \u003d double_disk_primary[0]"},{"line_number":405,"context_line":"        Manager([\u0027object-server\u0027]).start(number\u003dconfig_number)"},{"line_number":406,"context_line":"        config_number, node_list \u003d double_disk_primary[1]"},{"line_number":407,"context_line":"        Manager([\u0027object-server\u0027]).stop(number\u003dconfig_number)"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba5da102_04b2294c","line":404,"in_reply_to":"7a8ec9b2_8a2053b2","updated":"2016-11-02 00:07:42.000000000","message":"I think this comment is hinting that the re-use of the variable names in the tuple unpacking is not really as helpful as it might be if the variable names were unique.\n\nI\u0027m going with primary0_config_number, primary0_node_list ... etc.","commit_id":"73dbbce556830b4ff04329e83d59e5c4ce82120c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1e5f07681b7f74b15b67983bb05d2fec2d63aa61","unresolved":false,"context_lines":[{"line_number":432,"context_line":"        self.assertEqual(len(found_frags), 4)"},{"line_number":433,"context_line":"        # ... because one index appears twice - we have duplicates!"},{"line_number":434,"context_line":"        self.assertEqual(len(filter("},{"line_number":435,"context_line":"            lambda x: x \u003e 1, found_frags.values())), 1)"},{"line_number":436,"context_line":""},{"line_number":437,"context_line":"        # we can still GET the object"},{"line_number":438,"context_line":"        resp_etag \u003d self.get_object(container_name, object_name)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7a8ec9b2_c4feb904","line":435,"updated":"2016-09-20 18:39:40.000000000","message":"is this last assertion necessary, if we assume that all found_frags are found at least once?\n\nthis felt like a map would help but in the end I\u0027m not sure its a huge improvement...\n\n          # only 4 unique indexes\n        self.assertEqual(len(found_frags), 4)\n        buckets \u003d defaultdict(list)\n        map(lambda x: buckets[x[1]].append(x[0]), found_frags.items())\n        self.assertEqual({1, 2}, set(buckets.keys()))\n        # 3 indexes occur once\n        self.assertEqual(3, len(buckets[1]))\n        # 1 index occurs twice\n        self.assertEqual(1, len(buckets[2]))","commit_id":"73dbbce556830b4ff04329e83d59e5c4ce82120c"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"083228985d824a7f0755af207d7f0615ad251627","unresolved":false,"context_lines":[{"line_number":432,"context_line":"        self.assertEqual(len(found_frags), 4)"},{"line_number":433,"context_line":"        # ... because one index appears twice - we have duplicates!"},{"line_number":434,"context_line":"        self.assertEqual(len(filter("},{"line_number":435,"context_line":"            lambda x: x \u003e 1, found_frags.values())), 1)"},{"line_number":436,"context_line":""},{"line_number":437,"context_line":"        # we can still GET the object"},{"line_number":438,"context_line":"        resp_etag \u003d self.get_object(container_name, object_name)"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba5da102_a4da5d4a","line":435,"in_reply_to":"7a8ec9b2_c4feb904","updated":"2016-11-02 00:07:42.000000000","message":"I think you\u0027re right, it\u0027s just not needed - pigeon hole theorem is a thing and _check_nodes doesn\u0027t return keys with a 0 value\n\nI\u0027m going to rename it frag2count and let the reader assume that _check_nodes won\u0027t return keys with zero values (it\u0027s obvious when you look at it that not-found frag keys won\u0027t exist)","commit_id":"73dbbce556830b4ff04329e83d59e5c4ce82120c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1e5f07681b7f74b15b67983bb05d2fec2d63aa61","unresolved":false,"context_lines":[{"line_number":434,"context_line":"        self.assertEqual(len(filter("},{"line_number":435,"context_line":"            lambda x: x \u003e 1, found_frags.values())), 1)"},{"line_number":436,"context_line":""},{"line_number":437,"context_line":"        # we can still GET the object"},{"line_number":438,"context_line":"        resp_etag \u003d self.get_object(container_name, object_name)"},{"line_number":439,"context_line":"        self.assertEqual(resp_etag, contents.etag)"},{"line_number":440,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7a8ec9b2_04f3410b","line":437,"updated":"2016-09-20 18:39:40.000000000","message":"we\u0027ve got two primaries with one original frag, one primary with frag \"reverted\" from first handoff and both handoffs, so we are guaranteed to get duplicate frags from the reverted primary and first handoff. The second handoff is available to serve a distinct frag when the duplicate is detected.","commit_id":"73dbbce556830b4ff04329e83d59e5c4ce82120c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1e5f07681b7f74b15b67983bb05d2fec2d63aa61","unresolved":false,"context_lines":[{"line_number":435,"context_line":"            lambda x: x \u003e 1, found_frags.values())), 1)"},{"line_number":436,"context_line":""},{"line_number":437,"context_line":"        # we can still GET the object"},{"line_number":438,"context_line":"        resp_etag \u003d self.get_object(container_name, object_name)"},{"line_number":439,"context_line":"        self.assertEqual(resp_etag, contents.etag)"},{"line_number":440,"context_line":""},{"line_number":441,"context_line":"        # fix everything"}],"source_content_type":"text/x-python","patch_set":2,"id":"7a8ec9b2_21b74ff6","line":438,"updated":"2016-09-20 18:39:40.000000000","message":"OK. test fails here when applied to pre-optimistic GETs system:\n\n  2003  git checkout f414c15\n 2004  git checkout review/clay_gerrard/bug/1469094 test/probe/test_object_handoff.py\n 2005  nosetests ./test/probe/test_object_handoff.py -m duplicate -s\n\n  \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\nERROR: test_ec_handoff_duplicate_available (test.probe.test_object_handoff.TestECObjectHandoff)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n  File \"/home/swift/swift/test/probe/test_object_handoff.py\", line 441, in test_ec_handoff_duplicate_available\n    resp_etag \u003d self.get_object(container_name, object_name)\n  File \"/home/swift/swift/test/probe/test_object_handoff.py\", line 254, in get_object\n    resp_chunk_size\u003d64 * 2 ** 10)\n  File \"/home/swift/swiftclient/swiftclient/client.py\", line 1139, in get_object\n    raise ClientException.from_response(resp, \u0027Object GET failed\u0027, body)\nClientException: Object GET failed: http://127.0.0.1:8080/v1/AUTH_test/container-9c559d01-769c-41bd-b1c4-1bff0a8f9ad2/object-3eea7ba2-0051-4151-9e26-9dfa2c6e873f 500 Internal Error  [first 60 chars of response] \u003chtml\u003e\u003ch1\u003eInternal Error\u003c/h1\u003e\u003cp\u003eThe server has either erred\n\n(note line 441 reported here \u003d\u003d line 338, I had hacked in some more test logging)","commit_id":"73dbbce556830b4ff04329e83d59e5c4ce82120c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1e5f07681b7f74b15b67983bb05d2fec2d63aa61","unresolved":false,"context_lines":[{"line_number":437,"context_line":"        # we can still GET the object"},{"line_number":438,"context_line":"        resp_etag \u003d self.get_object(container_name, object_name)"},{"line_number":439,"context_line":"        self.assertEqual(resp_etag, contents.etag)"},{"line_number":440,"context_line":""},{"line_number":441,"context_line":"        # fix everything"},{"line_number":442,"context_line":"        config_number, node_list \u003d double_disk_primary[1]"},{"line_number":443,"context_line":"        Manager([\u0027object-server\u0027]).start(number\u003dconfig_number)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7a8ec9b2_3fa3ea9f","line":440,"updated":"2016-09-20 18:39:40.000000000","message":"we could verify that we don\u0027t get a 500 when the only frags available include a duplicate:\n\n          # unless the second handoff is lost\n        Manager([\u0027object-server\u0027]).stop(\n            number\u003dself.config_number(handoff_frags[1][0]))\n        with self.assertRaises(Exception) as cm:\n            self.get_object(container_name, object_name)\n        self.assertEqual(cm.exception.http_status in (404, 503))\n        Manager([\u0027object-server\u0027]).start(\n            number\u003dself.config_number(handoff_frags[1][0]))","commit_id":"73dbbce556830b4ff04329e83d59e5c4ce82120c"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"083228985d824a7f0755af207d7f0615ad251627","unresolved":false,"context_lines":[{"line_number":437,"context_line":"        # we can still GET the object"},{"line_number":438,"context_line":"        resp_etag \u003d self.get_object(container_name, object_name)"},{"line_number":439,"context_line":"        self.assertEqual(resp_etag, contents.etag)"},{"line_number":440,"context_line":""},{"line_number":441,"context_line":"        # fix everything"},{"line_number":442,"context_line":"        config_number, node_list \u003d double_disk_primary[1]"},{"line_number":443,"context_line":"        Manager([\u0027object-server\u0027]).start(number\u003dconfig_number)"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba5da102_b707ed16","line":440,"in_reply_to":"7a8ec9b2_3fa3ea9f","updated":"2016-11-02 00:07:42.000000000","message":"Done","commit_id":"73dbbce556830b4ff04329e83d59e5c4ce82120c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1e5f07681b7f74b15b67983bb05d2fec2d63aa61","unresolved":false,"context_lines":[{"line_number":452,"context_line":"        self.assertEqual(len(found_frags), 6)"},{"line_number":453,"context_line":"        # ... and no duplicates!!!"},{"line_number":454,"context_line":"        self.assertEqual(len(filter("},{"line_number":455,"context_line":"            lambda x: x \u003e 1, found_frags.values())), 0)"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":"if __name__ \u003d\u003d \u0027__main__\u0027:"},{"line_number":458,"context_line":"    main()"}],"source_content_type":"text/x-python","patch_set":2,"id":"7a8ec9b2_5fc5163b","line":455,"updated":"2016-09-20 18:39:40.000000000","message":"as above, not sure this is needed unless one of the found_frags items could have value 0","commit_id":"73dbbce556830b4ff04329e83d59e5c4ce82120c"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"083228985d824a7f0755af207d7f0615ad251627","unresolved":false,"context_lines":[{"line_number":452,"context_line":"        self.assertEqual(len(found_frags), 6)"},{"line_number":453,"context_line":"        # ... and no duplicates!!!"},{"line_number":454,"context_line":"        self.assertEqual(len(filter("},{"line_number":455,"context_line":"            lambda x: x \u003e 1, found_frags.values())), 0)"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":"if __name__ \u003d\u003d \u0027__main__\u0027:"},{"line_number":458,"context_line":"    main()"}],"source_content_type":"text/x-python","patch_set":2,"id":"ba5da102_9706691b","line":455,"in_reply_to":"7a8ec9b2_5fc5163b","updated":"2016-11-02 00:07:42.000000000","message":"Done","commit_id":"73dbbce556830b4ff04329e83d59e5c4ce82120c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"41d62f7f34d520f559e53c237ed06a863eca17d9","unresolved":false,"context_lines":[{"line_number":438,"context_line":"        resp_etag \u003d self.get_object(container_name, object_name)"},{"line_number":439,"context_line":"        self.assertEqual(resp_etag, contents.etag)"},{"line_number":440,"context_line":""},{"line_number":441,"context_line":"        # ... but we need both handoffs are we get a error"},{"line_number":442,"context_line":"        for handoff_node, hdrs, data in handoff_frags:"},{"line_number":443,"context_line":"            Manager([\u0027object-server\u0027]).stop("},{"line_number":444,"context_line":"                number\u003dself.config_number(handoff_node))"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba5da102_3dad2c9b","line":441,"updated":"2016-11-03 17:35:51.000000000","message":"nit s/are/or/","commit_id":"2f442f9edf0c2895a7ef5a08500c5c87d55bb9cf"}]}
