)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7616defbc04f817241dbf883df0b173056b244a","unresolved":false,"context_lines":[{"line_number":19,"context_line":"centers which have the same volume of disks, it is likely the fragments"},{"line_number":20,"context_line":"will be stored evenly (about 4 and 5) so we still need to access a"},{"line_number":21,"context_line":"faraway data center to decode the original object. In addition, if one"},{"line_number":22,"context_line":"of the data centers were lost in a disaster, the stored objects will be"},{"line_number":23,"context_line":"lost forever, and we have to cry a lot. To eunsure highly durable"},{"line_number":24,"context_line":"storage, you would think of making *more* parity fragments (e.g."},{"line_number":25,"context_line":"ec_k\u003d6, ec_m\u003d10), unfortunately this causes *significant* performance"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":20,"id":"dada55a8_aed05bf7","line":22,"range":{"start_line":22,"start_character":20,"end_line":22,"end_character":24},"updated":"2016-07-20 12:05:35.000000000","message":"s/were/was/","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7616defbc04f817241dbf883df0b173056b244a","unresolved":false,"context_lines":[{"line_number":55,"context_line":""},{"line_number":56,"context_line":"This patch inclues following changes:"},{"line_number":57,"context_line":"- Add ec_duplication_factor option to storage policy, to configure"},{"line_number":58,"context_line":"  how many times dupplicates of each fragment set will be created"},{"line_number":59,"context_line":"- Change PUT Path to map encoded chunk to each backend node by"},{"line_number":60,"context_line":"  \"ec_duplication_factor\""},{"line_number":61,"context_line":"- Change GET Path to sort primary nodes grouping as subsets, so that"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":20,"id":"dada55a8_eeed33b8","line":58,"range":{"start_line":58,"start_character":16,"end_line":58,"end_character":28},"updated":"2016-07-20 12:05:35.000000000","message":"s/dupplicates/duplicates/","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":78,"context_line":""},{"line_number":79,"context_line":"Additional improvements to Global EC Cluster Support will require"},{"line_number":80,"context_line":"features such as Composite Rings, and more efficient fragment"},{"line_number":81,"context_line":"rebalance/reconstruction."},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"1: http://goo.gl/IYiNPk (Swift Design Spec Repository)"},{"line_number":84,"context_line":"2: http://goo.gl/frgj6w (Slide Share for OpenStack Summit Tokyo)"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":44,"id":"7a3c09a3_eaf89cc5","line":81,"updated":"2017-01-17 02:54:44.000000000","message":"How strong is the guarantee that the ring will place the right duplicates in the right regions?  On my dev/test it sort of \"just worked\"\n\nRegion #1\n\nnode1\t1484618244.81712#0#d.data\nnode1\t1484618244.81712#1#d.data\nnode1\t1484618244.81712#2#d.data\nnode3\t1484618244.81712#3#d.data\nnode3\t1484618244.81712#4#d.data\nnode3\t1484618244.81712#5#d.data\n\nRegion #2\n\nnode2\t1484618244.81712#0#d.data\nnode2\t1484618244.81712#1#d.data\nnode2\t1484618244.81712#4#d.data\nnode2\t1484618244.81712#5#d.data\nnode4\t1484618244.81712#2#d.data\nnode4\t1484618244.81712#3#d.data\n\nIs that expected!?  Cause that\u0027s awesome!?","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"efd89ba3beb38a31d211f39027728d5a93359721","unresolved":false,"context_lines":[{"line_number":78,"context_line":""},{"line_number":79,"context_line":"Additional improvements to Global EC Cluster Support will require"},{"line_number":80,"context_line":"features such as Composite Rings, and more efficient fragment"},{"line_number":81,"context_line":"rebalance/reconstruction."},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"1: http://goo.gl/IYiNPk (Swift Design Spec Repository)"},{"line_number":84,"context_line":"2: http://goo.gl/frgj6w (Slide Share for OpenStack Summit Tokyo)"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":44,"id":"7a3c09a3_effb4bbf","line":81,"in_reply_to":"7a3c09a3_eaf89cc5","updated":"2017-01-17 10:30:20.000000000","message":"I think it\u0027s muck lucky. I don\u0027t think this patch guarantee the right duplication over the regions.","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":17361,"name":"Shashirekha Gundur","email":"shashirekha.j.gundur@intel.com","username":"shashirekha.j.gundur"},"change_message_id":"ac4a0687a58014fa3e007819cb2aa90cb286d173","unresolved":false,"context_lines":[{"line_number":53,"context_line":"On GET:"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"This patch inclues following changes:"},{"line_number":56,"context_line":"- Add ec_duplication_factor option to storage policy, to configure"},{"line_number":57,"context_line":"  how many times duplicates of each fragment set will be created"},{"line_number":58,"context_line":"- Change PUT Path to map encoded chunk to each backend node by"},{"line_number":59,"context_line":"  \"ec_duplication_factor\""},{"line_number":60,"context_line":"- Change GET Path to sort primary nodes grouping as subsets, so that"},{"line_number":61,"context_line":"  each subset will includes unique fragments"},{"line_number":62,"context_line":"- Change Reconstructor to be more aware of possibly duplicate fragments"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":45,"id":"3a461143_c41246b4","line":59,"range":{"start_line":56,"start_character":2,"end_line":59,"end_character":25},"updated":"2017-01-26 17:45:24.000000000","message":"L56-59 describes the PUT path; could be moved to PUT section above?","commit_id":"6f67f06282edee83f5042d96c5ab2bd4d967611a"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"0402581a177e1b238637e9be524a6662e4f84c84","unresolved":false,"context_lines":[{"line_number":53,"context_line":"On GET:"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"This patch inclues following changes:"},{"line_number":56,"context_line":"- Add ec_duplication_factor option to storage policy, to configure"},{"line_number":57,"context_line":"  how many times duplicates of each fragment set will be created"},{"line_number":58,"context_line":"- Change PUT Path to map encoded chunk to each backend node by"},{"line_number":59,"context_line":"  \"ec_duplication_factor\""},{"line_number":60,"context_line":"- Change GET Path to sort primary nodes grouping as subsets, so that"},{"line_number":61,"context_line":"  each subset will includes unique fragments"},{"line_number":62,"context_line":"- Change Reconstructor to be more aware of possibly duplicate fragments"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":45,"id":"3a461143_0e4ed23a","line":59,"range":{"start_line":56,"start_character":2,"end_line":59,"end_character":25},"in_reply_to":"3a461143_c41246b4","updated":"2017-01-30 06:00:52.000000000","message":"Ok, good thought. Probably my mistake.","commit_id":"6f67f06282edee83f5042d96c5ab2bd4d967611a"},{"author":{"_account_id":17361,"name":"Shashirekha Gundur","email":"shashirekha.j.gundur@intel.com","username":"shashirekha.j.gundur"},"change_message_id":"ac4a0687a58014fa3e007819cb2aa90cb286d173","unresolved":false,"context_lines":[{"line_number":64,"context_line":"For example, with this change, a policy could be configured such that"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"swift.conf:"},{"line_number":67,"context_line":"ec_n_data_fragments \u003d 2"},{"line_number":68,"context_line":"ec_n_parity_fragments \u003d 1"},{"line_number":69,"context_line":"ec_duplication_factor \u003d 2"},{"line_number":70,"context_line":"(object ring must have 6 replicas)"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":45,"id":"3a461143_c4c7a610","line":68,"range":{"start_line":67,"start_character":0,"end_line":68,"end_character":25},"updated":"2017-01-26 17:45:24.000000000","message":"maybe modify the params as swift.conf expects, like\nec_n_data_fragments —\u003e ec_num_data_fragments\nec_n_parity_fragments —\u003eec_num_parity_fragments","commit_id":"6f67f06282edee83f5042d96c5ab2bd4d967611a"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"0402581a177e1b238637e9be524a6662e4f84c84","unresolved":false,"context_lines":[{"line_number":64,"context_line":"For example, with this change, a policy could be configured such that"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"swift.conf:"},{"line_number":67,"context_line":"ec_n_data_fragments \u003d 2"},{"line_number":68,"context_line":"ec_n_parity_fragments \u003d 1"},{"line_number":69,"context_line":"ec_duplication_factor \u003d 2"},{"line_number":70,"context_line":"(object ring must have 6 replicas)"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":45,"id":"3a461143_ce3f6a85","line":68,"range":{"start_line":67,"start_character":0,"end_line":68,"end_character":25},"in_reply_to":"3a461143_c4c7a610","updated":"2017-01-30 06:00:52.000000000","message":"good catch, thanks!\n\nWill fix.","commit_id":"6f67f06282edee83f5042d96c5ab2bd4d967611a"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"f19621c2546075b18093736e840a23ea03843566","unresolved":false,"context_lines":[{"line_number":42,"context_line":""},{"line_number":43,"context_line":"The duplicated fragments increase pressure on existing requirements"},{"line_number":44,"context_line":"when decoding objects in service to a read request.  All fragments are"},{"line_number":45,"context_line":"stored with their X-Object-Sysmeta-Frag-Index.  In this change, the"},{"line_number":46,"context_line":"X-Object-Sysmeta-Frag-Index represents the actual fragment index"},{"line_number":47,"context_line":"encoded by PyECLib, there *will* be duplicates.  Anytime we must decode"},{"line_number":48,"context_line":"the original object data, we must only consider the ec_k fragments as"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":56,"id":"fa31d9ce_6bde8740","line":45,"range":{"start_line":45,"start_character":18,"end_line":45,"end_character":45},"updated":"2017-02-13 16:03:31.000000000","message":"nit: s/X-Object-Sysmeta-Frag-Index/X-Object-Sysmeta-Ec-Frag-Index","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"553d8dc2d7136e6b0a934d5989dc9f491f6d6a45","unresolved":false,"context_lines":[{"line_number":42,"context_line":""},{"line_number":43,"context_line":"The duplicated fragments increase pressure on existing requirements"},{"line_number":44,"context_line":"when decoding objects in service to a read request.  All fragments are"},{"line_number":45,"context_line":"stored with their X-Object-Sysmeta-Frag-Index.  In this change, the"},{"line_number":46,"context_line":"X-Object-Sysmeta-Frag-Index represents the actual fragment index"},{"line_number":47,"context_line":"encoded by PyECLib, there *will* be duplicates.  Anytime we must decode"},{"line_number":48,"context_line":"the original object data, we must only consider the ec_k fragments as"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":56,"id":"fa31d9ce_61513536","line":45,"range":{"start_line":45,"start_character":18,"end_line":45,"end_character":45},"in_reply_to":"fa31d9ce_6bde8740","updated":"2017-02-14 01:34:16.000000000","message":"Done","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"f19621c2546075b18093736e840a23ea03843566","unresolved":false,"context_lines":[{"line_number":43,"context_line":"The duplicated fragments increase pressure on existing requirements"},{"line_number":44,"context_line":"when decoding objects in service to a read request.  All fragments are"},{"line_number":45,"context_line":"stored with their X-Object-Sysmeta-Frag-Index.  In this change, the"},{"line_number":46,"context_line":"X-Object-Sysmeta-Frag-Index represents the actual fragment index"},{"line_number":47,"context_line":"encoded by PyECLib, there *will* be duplicates.  Anytime we must decode"},{"line_number":48,"context_line":"the original object data, we must only consider the ec_k fragments as"},{"line_number":49,"context_line":"unique according to their X-Object-Sysmeta-Frag-Index.  On decode no"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":56,"id":"fa31d9ce_6b276764","line":46,"range":{"start_line":46,"start_character":0,"end_line":46,"end_character":27},"updated":"2017-02-13 16:03:31.000000000","message":"ditto as above","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"553d8dc2d7136e6b0a934d5989dc9f491f6d6a45","unresolved":false,"context_lines":[{"line_number":43,"context_line":"The duplicated fragments increase pressure on existing requirements"},{"line_number":44,"context_line":"when decoding objects in service to a read request.  All fragments are"},{"line_number":45,"context_line":"stored with their X-Object-Sysmeta-Frag-Index.  In this change, the"},{"line_number":46,"context_line":"X-Object-Sysmeta-Frag-Index represents the actual fragment index"},{"line_number":47,"context_line":"encoded by PyECLib, there *will* be duplicates.  Anytime we must decode"},{"line_number":48,"context_line":"the original object data, we must only consider the ec_k fragments as"},{"line_number":49,"context_line":"unique according to their X-Object-Sysmeta-Frag-Index.  On decode no"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":56,"id":"fa31d9ce_8142a966","line":46,"range":{"start_line":46,"start_character":0,"end_line":46,"end_character":27},"in_reply_to":"fa31d9ce_6b276764","updated":"2017-02-14 01:34:16.000000000","message":"Done","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"f19621c2546075b18093736e840a23ea03843566","unresolved":false,"context_lines":[{"line_number":46,"context_line":"X-Object-Sysmeta-Frag-Index represents the actual fragment index"},{"line_number":47,"context_line":"encoded by PyECLib, there *will* be duplicates.  Anytime we must decode"},{"line_number":48,"context_line":"the original object data, we must only consider the ec_k fragments as"},{"line_number":49,"context_line":"unique according to their X-Object-Sysmeta-Frag-Index.  On decode no"},{"line_number":50,"context_line":"duplicate X-Object-Sysmeta-Frag-Index may be used when decoding an"},{"line_number":51,"context_line":"object, duplicate X-Object-Sysmeta-Frag-Index should be expected and"},{"line_number":52,"context_line":"avoided if possible."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":56,"id":"fa31d9ce_0beeebeb","line":49,"range":{"start_line":49,"start_character":26,"end_line":49,"end_character":53},"updated":"2017-02-13 16:03:31.000000000","message":"here too","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"553d8dc2d7136e6b0a934d5989dc9f491f6d6a45","unresolved":false,"context_lines":[{"line_number":46,"context_line":"X-Object-Sysmeta-Frag-Index represents the actual fragment index"},{"line_number":47,"context_line":"encoded by PyECLib, there *will* be duplicates.  Anytime we must decode"},{"line_number":48,"context_line":"the original object data, we must only consider the ec_k fragments as"},{"line_number":49,"context_line":"unique according to their X-Object-Sysmeta-Frag-Index.  On decode no"},{"line_number":50,"context_line":"duplicate X-Object-Sysmeta-Frag-Index may be used when decoding an"},{"line_number":51,"context_line":"object, duplicate X-Object-Sysmeta-Frag-Index should be expected and"},{"line_number":52,"context_line":"avoided if possible."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":56,"id":"fa31d9ce_e15d2548","line":49,"range":{"start_line":49,"start_character":26,"end_line":49,"end_character":53},"in_reply_to":"fa31d9ce_0beeebeb","updated":"2017-02-14 01:34:16.000000000","message":"Done","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"f19621c2546075b18093736e840a23ea03843566","unresolved":false,"context_lines":[{"line_number":47,"context_line":"encoded by PyECLib, there *will* be duplicates.  Anytime we must decode"},{"line_number":48,"context_line":"the original object data, we must only consider the ec_k fragments as"},{"line_number":49,"context_line":"unique according to their X-Object-Sysmeta-Frag-Index.  On decode no"},{"line_number":50,"context_line":"duplicate X-Object-Sysmeta-Frag-Index may be used when decoding an"},{"line_number":51,"context_line":"object, duplicate X-Object-Sysmeta-Frag-Index should be expected and"},{"line_number":52,"context_line":"avoided if possible."},{"line_number":53,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":56,"id":"fa31d9ce_8bb81be7","line":50,"range":{"start_line":50,"start_character":10,"end_line":50,"end_character":37},"updated":"2017-02-13 16:03:31.000000000","message":"ditto","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"553d8dc2d7136e6b0a934d5989dc9f491f6d6a45","unresolved":false,"context_lines":[{"line_number":47,"context_line":"encoded by PyECLib, there *will* be duplicates.  Anytime we must decode"},{"line_number":48,"context_line":"the original object data, we must only consider the ec_k fragments as"},{"line_number":49,"context_line":"unique according to their X-Object-Sysmeta-Frag-Index.  On decode no"},{"line_number":50,"context_line":"duplicate X-Object-Sysmeta-Frag-Index may be used when decoding an"},{"line_number":51,"context_line":"object, duplicate X-Object-Sysmeta-Frag-Index should be expected and"},{"line_number":52,"context_line":"avoided if possible."},{"line_number":53,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":56,"id":"fa31d9ce_01579926","line":50,"range":{"start_line":50,"start_character":10,"end_line":50,"end_character":37},"in_reply_to":"fa31d9ce_8bb81be7","updated":"2017-02-14 01:34:16.000000000","message":"Done","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"f19621c2546075b18093736e840a23ea03843566","unresolved":false,"context_lines":[{"line_number":48,"context_line":"the original object data, we must only consider the ec_k fragments as"},{"line_number":49,"context_line":"unique according to their X-Object-Sysmeta-Frag-Index.  On decode no"},{"line_number":50,"context_line":"duplicate X-Object-Sysmeta-Frag-Index may be used when decoding an"},{"line_number":51,"context_line":"object, duplicate X-Object-Sysmeta-Frag-Index should be expected and"},{"line_number":52,"context_line":"avoided if possible."},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"On GET:"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":56,"id":"fa31d9ce_cbca136e","line":51,"range":{"start_line":51,"start_character":18,"end_line":51,"end_character":45},"updated":"2017-02-13 16:03:31.000000000","message":"ditto","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"553d8dc2d7136e6b0a934d5989dc9f491f6d6a45","unresolved":false,"context_lines":[{"line_number":48,"context_line":"the original object data, we must only consider the ec_k fragments as"},{"line_number":49,"context_line":"unique according to their X-Object-Sysmeta-Frag-Index.  On decode no"},{"line_number":50,"context_line":"duplicate X-Object-Sysmeta-Frag-Index may be used when decoding an"},{"line_number":51,"context_line":"object, duplicate X-Object-Sysmeta-Frag-Index should be expected and"},{"line_number":52,"context_line":"avoided if possible."},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"On GET:"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":56,"id":"fa31d9ce_21549d1f","line":51,"range":{"start_line":51,"start_character":18,"end_line":51,"end_character":45},"in_reply_to":"fa31d9ce_cbca136e","updated":"2017-02-14 01:34:16.000000000","message":"Done","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":20508,"name":"Mohit Motiani","email":"mohit.motiani@intel.com","username":"mohit.motiani"},"change_message_id":"0d440ca35ab2594b1da1efc54df64ba451815944","unresolved":false,"context_lines":[{"line_number":9,"context_line":"This patch enables efficent PUT/GET for global distributed cluster[1]."},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Problem:"},{"line_number":12,"context_line":"Erasure coding has the capability to decrease the amout of actual stored"},{"line_number":13,"context_line":"data less then replicated model. For example, ec_k\u003d6, ec_m\u003d3 parameter"},{"line_number":14,"context_line":"can be 1.5x of the original data which is smaller than 3x replicated."},{"line_number":15,"context_line":"However, unlike replication, erasure coding requires availability of at"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":58,"id":"da36d5c6_84456918","line":12,"range":{"start_line":12,"start_character":50,"end_line":12,"end_character":55},"updated":"2017-02-22 15:31:42.000000000","message":"s/amout/amount","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":20508,"name":"Mohit Motiani","email":"mohit.motiani@intel.com","username":"mohit.motiani"},"change_message_id":"0d440ca35ab2594b1da1efc54df64ba451815944","unresolved":false,"context_lines":[{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Problem:"},{"line_number":12,"context_line":"Erasure coding has the capability to decrease the amout of actual stored"},{"line_number":13,"context_line":"data less then replicated model. For example, ec_k\u003d6, ec_m\u003d3 parameter"},{"line_number":14,"context_line":"can be 1.5x of the original data which is smaller than 3x replicated."},{"line_number":15,"context_line":"However, unlike replication, erasure coding requires availability of at"},{"line_number":16,"context_line":"least some ec_k fragments of the total ec_k + ec_m fragments to service"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":58,"id":"da36d5c6_645955fe","line":13,"range":{"start_line":13,"start_character":10,"end_line":13,"end_character":14},"updated":"2017-02-22 15:31:42.000000000","message":"s/then/than","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"c386f23e99c0d3c169c0afefca5f3ecfada59835","unresolved":false,"context_lines":[{"line_number":20,"context_line":"will be stored evenly (about 4 and 5) so we still need to access a"},{"line_number":21,"context_line":"faraway data center to decode the original object. In addition, if one"},{"line_number":22,"context_line":"of the data centers was lost in a disaster, the stored objects will be"},{"line_number":23,"context_line":"lost forever, and we have to cry a lot. To eunsure highly durable"},{"line_number":24,"context_line":"storage, you would think of making *more* parity fragments (e.g."},{"line_number":25,"context_line":"ec_k\u003d6, ec_m\u003d10), unfortunately this causes *significant* performance"},{"line_number":26,"context_line":"degradation due to the cost of mathmatical caluculation for erasure"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":58,"id":"da36d5c6_b58a9ebd","line":23,"updated":"2017-02-22 15:11:50.000000000","message":"\"ensure\"","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4f33c5b54a738ed1d499a2e4a9e3c5a687bb761b","unresolved":false,"context_lines":[{"line_number":20,"context_line":"will be stored evenly (about 4 and 5) so we still need to access a"},{"line_number":21,"context_line":"faraway data center to decode the original object. In addition, if one"},{"line_number":22,"context_line":"of the data centers was lost in a disaster, the stored objects will be"},{"line_number":23,"context_line":"lost forever, and we have to cry a lot. To eunsure highly durable"},{"line_number":24,"context_line":"storage, you would think of making *more* parity fragments (e.g."},{"line_number":25,"context_line":"ec_k\u003d6, ec_m\u003d10), unfortunately this causes *significant* performance"},{"line_number":26,"context_line":"degradation due to the cost of mathmatical caluculation for erasure"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":58,"id":"da36d5c6_84eba9af","line":23,"in_reply_to":"da36d5c6_b58a9ebd","updated":"2017-02-22 15:31:32.000000000","message":"Done in the next patch.","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"c386f23e99c0d3c169c0afefca5f3ecfada59835","unresolved":false,"context_lines":[{"line_number":23,"context_line":"lost forever, and we have to cry a lot. To eunsure highly durable"},{"line_number":24,"context_line":"storage, you would think of making *more* parity fragments (e.g."},{"line_number":25,"context_line":"ec_k\u003d6, ec_m\u003d10), unfortunately this causes *significant* performance"},{"line_number":26,"context_line":"degradation due to the cost of mathmatical caluculation for erasure"},{"line_number":27,"context_line":"coding encode/decode."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"How this resolves the problem:"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":58,"id":"da36d5c6_95bafa6c","line":26,"updated":"2017-02-22 15:11:50.000000000","message":"\"mathematical\"","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":20508,"name":"Mohit Motiani","email":"mohit.motiani@intel.com","username":"mohit.motiani"},"change_message_id":"0d440ca35ab2594b1da1efc54df64ba451815944","unresolved":false,"context_lines":[{"line_number":23,"context_line":"lost forever, and we have to cry a lot. To eunsure highly durable"},{"line_number":24,"context_line":"storage, you would think of making *more* parity fragments (e.g."},{"line_number":25,"context_line":"ec_k\u003d6, ec_m\u003d10), unfortunately this causes *significant* performance"},{"line_number":26,"context_line":"degradation due to the cost of mathmatical caluculation for erasure"},{"line_number":27,"context_line":"coding encode/decode."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"How this resolves the problem:"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":58,"id":"da36d5c6_84e1e900","line":26,"range":{"start_line":26,"start_character":43,"end_line":26,"end_character":55},"updated":"2017-02-22 15:31:42.000000000","message":"s/caluculation/calculation","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4f33c5b54a738ed1d499a2e4a9e3c5a687bb761b","unresolved":false,"context_lines":[{"line_number":23,"context_line":"lost forever, and we have to cry a lot. To eunsure highly durable"},{"line_number":24,"context_line":"storage, you would think of making *more* parity fragments (e.g."},{"line_number":25,"context_line":"ec_k\u003d6, ec_m\u003d10), unfortunately this causes *significant* performance"},{"line_number":26,"context_line":"degradation due to the cost of mathmatical caluculation for erasure"},{"line_number":27,"context_line":"coding encode/decode."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"How this resolves the problem:"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":58,"id":"da36d5c6_24059d79","line":26,"in_reply_to":"da36d5c6_95bafa6c","updated":"2017-02-22 15:31:32.000000000","message":"Done in the next.","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"c386f23e99c0d3c169c0afefca5f3ecfada59835","unresolved":false,"context_lines":[{"line_number":27,"context_line":"coding encode/decode."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"How this resolves the problem:"},{"line_number":30,"context_line":"EC Fragment Duplication extends on the initial solution add *more*"},{"line_number":31,"context_line":"fragments from which to rebuild an object similar to the solution"},{"line_number":32,"context_line":"described above. The difference is making *copies* of encoded fragments."},{"line_number":33,"context_line":"With experimental results[1][2], employing small ec_k and ec_m shows"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":58,"id":"da36d5c6_90f768f4","line":30,"updated":"2017-02-22 15:11:50.000000000","message":"\"to add\"?","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4f33c5b54a738ed1d499a2e4a9e3c5a687bb761b","unresolved":false,"context_lines":[{"line_number":27,"context_line":"coding encode/decode."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"How this resolves the problem:"},{"line_number":30,"context_line":"EC Fragment Duplication extends on the initial solution add *more*"},{"line_number":31,"context_line":"fragments from which to rebuild an object similar to the solution"},{"line_number":32,"context_line":"described above. The difference is making *copies* of encoded fragments."},{"line_number":33,"context_line":"With experimental results[1][2], employing small ec_k and ec_m shows"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":58,"id":"da36d5c6_a4f98d82","line":30,"in_reply_to":"da36d5c6_90f768f4","updated":"2017-02-22 15:31:32.000000000","message":"ditto.","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":20508,"name":"Mohit Motiani","email":"mohit.motiani@intel.com","username":"mohit.motiani"},"change_message_id":"0d440ca35ab2594b1da1efc54df64ba451815944","unresolved":false,"context_lines":[{"line_number":35,"context_line":""},{"line_number":36,"context_line":"On PUT:"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"- Encode incomming object with small ec_k and ec_m  \u003c- faster!"},{"line_number":39,"context_line":"- Make duplicated copies of the encoded fragments. The # of copies"},{"line_number":40,"context_line":"  are determined by \u0027ec_duplication_factor\u0027 in swift.conf"},{"line_number":41,"context_line":"- Store all fragments in Swift Global EC Cluster"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":58,"id":"da36d5c6_a4a42da6","line":38,"range":{"start_line":38,"start_character":9,"end_line":38,"end_character":18},"updated":"2017-02-22 15:31:42.000000000","message":"s/incomming/incoming","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":20508,"name":"Mohit Motiani","email":"mohit.motiani@intel.com","username":"mohit.motiani"},"change_message_id":"0d440ca35ab2594b1da1efc54df64ba451815944","unresolved":false,"context_lines":[{"line_number":36,"context_line":"On PUT:"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"- Encode incomming object with small ec_k and ec_m  \u003c- faster!"},{"line_number":39,"context_line":"- Make duplicated copies of the encoded fragments. The # of copies"},{"line_number":40,"context_line":"  are determined by \u0027ec_duplication_factor\u0027 in swift.conf"},{"line_number":41,"context_line":"- Store all fragments in Swift Global EC Cluster"},{"line_number":42,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":58,"id":"da36d5c6_64b155e1","line":39,"range":{"start_line":39,"start_character":7,"end_line":39,"end_character":17},"updated":"2017-02-22 15:31:42.000000000","message":"s/duplicated/duplicate","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":20508,"name":"Mohit Motiani","email":"mohit.motiani@intel.com","username":"mohit.motiani"},"change_message_id":"0d440ca35ab2594b1da1efc54df64ba451815944","unresolved":false,"context_lines":[{"line_number":53,"context_line":""},{"line_number":54,"context_line":"On GET:"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"This patch inclues following changes:"},{"line_number":57,"context_line":"- Change GET Path to sort primary nodes grouping as subsets, so that"},{"line_number":58,"context_line":"  each subset will includes unique fragments"},{"line_number":59,"context_line":"- Change Reconstructor to be more aware of possibly duplicate fragments"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":58,"id":"da36d5c6_a4d26dfe","line":56,"range":{"start_line":56,"start_character":11,"end_line":56,"end_character":18},"updated":"2017-02-22 15:31:42.000000000","message":"s/inclues/includes","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"c386f23e99c0d3c169c0afefca5f3ecfada59835","unresolved":false,"context_lines":[{"line_number":64,"context_line":"ec_num_data_fragments \u003d 2"},{"line_number":65,"context_line":"ec_num_parity_fragments \u003d 1"},{"line_number":66,"context_line":"ec_duplication_factor \u003d 2"},{"line_number":67,"context_line":"(object ring must have 6 replicas)"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"At Object-Server:"},{"line_number":70,"context_line":"node index (from object ring):  0 1 2 3 4 5 \u003c- keep node index for"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":58,"id":"da36d5c6_d03d60bc","line":67,"updated":"2017-02-22 15:11:50.000000000","message":"The numbers are somewhat unimpressive to me. 6 total over 2 data is the same as 3-time replication and only 25% savings over 4-time replication. Might as well suggest not use EC and use replication for multiply datacenters. And this number 6-from-2 is representative if you _duplicate what\u0027s already encoded_. If we could only duplicate \"some\", randomly, just enough to survive a loss of the half of data for 2 datacenter case...","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"fe193c3c28fdebf41e01ba4a4599e1d67e788fed","unresolved":false,"context_lines":[{"line_number":64,"context_line":"ec_num_data_fragments \u003d 2"},{"line_number":65,"context_line":"ec_num_parity_fragments \u003d 1"},{"line_number":66,"context_line":"ec_duplication_factor \u003d 2"},{"line_number":67,"context_line":"(object ring must have 6 replicas)"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"At Object-Server:"},{"line_number":70,"context_line":"node index (from object ring):  0 1 2 3 4 5 \u003c- keep node index for"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":58,"id":"da36d5c6_07b6db3c","line":67,"in_reply_to":"da36d5c6_c4c68148","updated":"2017-02-22 15:41:50.000000000","message":"Just talked to Clay and the best way to think about it is that EC parameters are enough to protect against a device failure locally and duplication corresponds to number of regions. So I withdraw the consideration for fractional duplication factor.","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"4f33c5b54a738ed1d499a2e4a9e3c5a687bb761b","unresolved":false,"context_lines":[{"line_number":64,"context_line":"ec_num_data_fragments \u003d 2"},{"line_number":65,"context_line":"ec_num_parity_fragments \u003d 1"},{"line_number":66,"context_line":"ec_duplication_factor \u003d 2"},{"line_number":67,"context_line":"(object ring must have 6 replicas)"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":"At Object-Server:"},{"line_number":70,"context_line":"node index (from object ring):  0 1 2 3 4 5 \u003c- keep node index for"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":58,"id":"da36d5c6_c4c68148","line":67,"in_reply_to":"da36d5c6_d03d60bc","updated":"2017-02-22 15:31:32.000000000","message":"correct, the reason i told the ec duplication with the parameters here is to make the mapping below easy.\n\nI think (and at least, our company use case) the parameters should be bigger than the example to make the duplication effective for hardware cost, like ec_num_data_fragments \u003d 10, ec_num_parity_fragments \u003d 4 and duplication_factor \u003d 2 which less spaces than 3 replication.","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"}],"doc/source/overview_erasure_code.rst":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":273,"context_line":""},{"line_number":274,"context_line":"For at least the initial version of EC, it is not recommended that an EC scheme"},{"line_number":275,"context_line":"span beyond a single region, neither performance nor functional validation has"},{"line_number":276,"context_line":"be been done in such a configuration."},{"line_number":277,"context_line":""},{"line_number":278,"context_line":"--------------"},{"line_number":279,"context_line":"Under the Hood"}],"source_content_type":"text/x-rst","patch_set":44,"id":"7a3c09a3_a5ea4daa","line":276,"updated":"2017-01-17 02:54:44.000000000","message":"I think this would be a better place to expand on the motivation for EC duplication factor and why it\u0027s needed","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"381bbaf5157aaf99c818b3bab373a9845047ca56","unresolved":false,"context_lines":[{"line_number":273,"context_line":""},{"line_number":274,"context_line":"For at least the initial version of EC, it is not recommended that an EC scheme"},{"line_number":275,"context_line":"span beyond a single region, neither performance nor functional validation has"},{"line_number":276,"context_line":"be been done in such a configuration."},{"line_number":277,"context_line":""},{"line_number":278,"context_line":"--------------"},{"line_number":279,"context_line":"Under the Hood"}],"source_content_type":"text/x-rst","patch_set":47,"id":"3a461143_8894fa44","line":276,"updated":"2017-02-02 03:14:49.000000000","message":"This paragraph must be expanded to include WIP on ec_duplication and goals/limitations for global ec","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"18f22649c4317c3b5930fc2b2735de04703e6dcc","unresolved":false,"context_lines":[{"line_number":292,"context_line":"\u0027ec_duplication_factor\u0027). This *can* allow for a failure domain to rebuild"},{"line_number":293,"context_line":"an object to full durability even when *more* than 14 fragments are"},{"line_number":294,"context_line":"unavailable."},{"line_number":295,"context_line":""},{"line_number":296,"context_line":"--------------"},{"line_number":297,"context_line":"Under the Hood"},{"line_number":298,"context_line":"--------------"}],"source_content_type":"text/x-rst","patch_set":48,"id":"1a430d35_b88c7580","line":295,"updated":"2017-02-06 01:14:26.000000000","message":"We still needs more clear Note for current cosntraint/known-issue here so it\u0027s WIP right now but it should be addressed soon.","commit_id":"ce6807ab6fd33d30d7844546c6261951772eb822"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":204,"context_line":"        ec_num_data_fragments \u003d 10"},{"line_number":205,"context_line":"        ec_num_parity_fragments \u003d 4"},{"line_number":206,"context_line":"        ec_object_segment_size \u003d 1048576"},{"line_number":207,"context_line":"        ec_duplication_factor \u003d 1"},{"line_number":208,"context_line":""},{"line_number":209,"context_line":"Let\u0027s take a closer look at each configuration parameter:"},{"line_number":210,"context_line":""}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_2881978f","line":207,"updated":"2017-02-08 18:01:12.000000000","message":"is it a good idea to have an experimental option in the documented example? would it be sufficient to have it only in swift.conf.sample?","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":204,"context_line":"        ec_num_data_fragments \u003d 10"},{"line_number":205,"context_line":"        ec_num_parity_fragments \u003d 4"},{"line_number":206,"context_line":"        ec_object_segment_size \u003d 1048576"},{"line_number":207,"context_line":"        ec_duplication_factor \u003d 1"},{"line_number":208,"context_line":""},{"line_number":209,"context_line":"Let\u0027s take a closer look at each configuration parameter:"},{"line_number":210,"context_line":""}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_d92e0242","line":207,"in_reply_to":"1a430d35_2881978f","updated":"2017-02-09 09:36:43.000000000","message":"Good call, done.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":224,"context_line":"  comprised of parity."},{"line_number":225,"context_line":"* ``ec_object_segment_size``: The amount of data that will be buffered up before"},{"line_number":226,"context_line":"  feeding a segment into the encoder/decoder. The default value is 1048576."},{"line_number":227,"context_line":"* ``ec_duplication_factor``: The number of duplicated copies for each fragments."},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"When PyECLib encodes an object, it will break it into N fragments. However, what"},{"line_number":230,"context_line":"is important during configuration, is how many of those are data and how many"}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_7c29a089","line":227,"updated":"2017-02-08 18:01:12.000000000","message":"if this is documented here then it should be marked as \"experimental\" as in swift.conf.sample","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":224,"context_line":"  comprised of parity."},{"line_number":225,"context_line":"* ``ec_object_segment_size``: The amount of data that will be buffered up before"},{"line_number":226,"context_line":"  feeding a segment into the encoder/decoder. The default value is 1048576."},{"line_number":227,"context_line":"* ``ec_duplication_factor``: The number of duplicated copies for each fragments."},{"line_number":228,"context_line":""},{"line_number":229,"context_line":"When PyECLib encodes an object, it will break it into N fragments. However, what"},{"line_number":230,"context_line":"is important during configuration, is how many of those are data and how many"}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_59ea12dc","line":227,"in_reply_to":"1a430d35_7c29a089","updated":"2017-02-09 09:36:43.000000000","message":"Done","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":278,"context_line":"EC Duplication"},{"line_number":279,"context_line":"^^^^^^^^^^^^^^"},{"line_number":280,"context_line":""},{"line_number":281,"context_line":"ec_duplication_factor is an opition to make duplicated copies of fragments"},{"line_number":282,"context_line":"of erasure encoded Swift objects.  The default value is 1 (not duplicated)."},{"line_number":283,"context_line":"If an erasure code storage policy is configured with a non-default"},{"line_number":284,"context_line":"ec_duplication_factor of N \u003e 1, then the policy will create N duplicates of"}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_3c4b985a","line":281,"updated":"2017-02-08 18:01:12.000000000","message":"s/opition/option/","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":278,"context_line":"EC Duplication"},{"line_number":279,"context_line":"^^^^^^^^^^^^^^"},{"line_number":280,"context_line":""},{"line_number":281,"context_line":"ec_duplication_factor is an opition to make duplicated copies of fragments"},{"line_number":282,"context_line":"of erasure encoded Swift objects.  The default value is 1 (not duplicated)."},{"line_number":283,"context_line":"If an erasure code storage policy is configured with a non-default"},{"line_number":284,"context_line":"ec_duplication_factor of N \u003e 1, then the policy will create N duplicates of"}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_d9bc42de","line":281,"in_reply_to":"1a430d35_3c4b985a","updated":"2017-02-09 09:36:43.000000000","message":"Done","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":282,"context_line":"of erasure encoded Swift objects.  The default value is 1 (not duplicated)."},{"line_number":283,"context_line":"If an erasure code storage policy is configured with a non-default"},{"line_number":284,"context_line":"ec_duplication_factor of N \u003e 1, then the policy will create N duplicates of"},{"line_number":285,"context_line":"each fragment that is returned from the configured EC engine.  Duplication"},{"line_number":286,"context_line":"of EC fragments is optimal for EC storage policies which require dispersion"},{"line_number":287,"context_line":"of fragment data across failure domains which are assigned less than 1/2 of"},{"line_number":288,"context_line":"the total fragments.  Empirical testing has shown using duplication is more"}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_3cfc783d","line":285,"range":{"start_line":285,"start_character":5,"end_line":285,"end_character":13},"updated":"2017-02-08 18:01:12.000000000","message":"I think it would be helpful when reading text below to introduce the concept of unique frag here i.e. insert \"unique\" before \"fragment\" here","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":282,"context_line":"of erasure encoded Swift objects.  The default value is 1 (not duplicated)."},{"line_number":283,"context_line":"If an erasure code storage policy is configured with a non-default"},{"line_number":284,"context_line":"ec_duplication_factor of N \u003e 1, then the policy will create N duplicates of"},{"line_number":285,"context_line":"each fragment that is returned from the configured EC engine.  Duplication"},{"line_number":286,"context_line":"of EC fragments is optimal for EC storage policies which require dispersion"},{"line_number":287,"context_line":"of fragment data across failure domains which are assigned less than 1/2 of"},{"line_number":288,"context_line":"the total fragments.  Empirical testing has shown using duplication is more"}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_d9a362b0","line":285,"range":{"start_line":285,"start_character":5,"end_line":285,"end_character":13},"in_reply_to":"1a430d35_3cfc783d","updated":"2017-02-09 09:36:43.000000000","message":"Done","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":285,"context_line":"each fragment that is returned from the configured EC engine.  Duplication"},{"line_number":286,"context_line":"of EC fragments is optimal for EC storage policies which require dispersion"},{"line_number":287,"context_line":"of fragment data across failure domains which are assigned less than 1/2 of"},{"line_number":288,"context_line":"the total fragments.  Empirical testing has shown using duplication is more"},{"line_number":289,"context_line":"efficient in the PUT path than encoding a schema with num_parity \u003e num_data,"},{"line_number":290,"context_line":"and Swift EC supports this schema.  You should evaluate which strategy works"},{"line_number":291,"context_line":"best in your environment."}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_fcd4b0ec","line":288,"updated":"2017-02-08 18:01:12.000000000","message":"sorry, I have a feeling I am being stupid, but I don\u0027t understand the significance of 1/2.\n\nIs \"total fragments\" here ndata + nparity or is it duplication * (ndata + nparity)?\n\nWith 10+4, why are we saying duplication is optimal when a failure domain has \u003c14 frags? Or does this mean a failure domain would have \u003c7 so duplication would be a good thing to use, but then I thought the threshold would be 10 in a domain.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":285,"context_line":"each fragment that is returned from the configured EC engine.  Duplication"},{"line_number":286,"context_line":"of EC fragments is optimal for EC storage policies which require dispersion"},{"line_number":287,"context_line":"of fragment data across failure domains which are assigned less than 1/2 of"},{"line_number":288,"context_line":"the total fragments.  Empirical testing has shown using duplication is more"},{"line_number":289,"context_line":"efficient in the PUT path than encoding a schema with num_parity \u003e num_data,"},{"line_number":290,"context_line":"and Swift EC supports this schema.  You should evaluate which strategy works"},{"line_number":291,"context_line":"best in your environment."}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_b9df76d4","line":288,"in_reply_to":"1a430d35_fcd4b0ec","updated":"2017-02-09 09:36:43.000000000","message":"Good catch, the words looks wrong, I meant using normal erasure code policy *w/o* duplication with 2 regions will cause less assignment of 1/2 of ec_k + ec_m. But current docs is far from the meaning, exactly.\n\nHow about correcting the block like as:\n\nIf an erasure code storage policy is configured with a non-default ec_duplication_factor of N \u003e 1, then the policy will create N duplicates of each unique fragment that is returned from the configured EC engine. Duplication of EC fragments is optimal for EC storage policies which require dispersion of fragment data across failure domains. Without duplication, almost of common ec parameters like 10-4 cause less assignments than 1/(the number of failure domains) of the total unique fragments. And usually, it will be less than the number of data fragments which are required to construct the original data. To guarantee the number of fragmetns in a failure domain, the system requires more parities. On the situation which needs more parity, empirical testing has shown using duplication is more efficient in the PUT path than encoding a schema with num_parity \u003e num_data, and Swift EC supports this schema. You should evaluate which strategy works best in your environment.\n\n\n???\n\nI\u0027ll change here with above, so please feel free to correct that.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":286,"context_line":"of EC fragments is optimal for EC storage policies which require dispersion"},{"line_number":287,"context_line":"of fragment data across failure domains which are assigned less than 1/2 of"},{"line_number":288,"context_line":"the total fragments.  Empirical testing has shown using duplication is more"},{"line_number":289,"context_line":"efficient in the PUT path than encoding a schema with num_parity \u003e num_data,"},{"line_number":290,"context_line":"and Swift EC supports this schema.  You should evaluate which strategy works"},{"line_number":291,"context_line":"best in your environment."},{"line_number":292,"context_line":""}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_b3fa6541","line":289,"updated":"2017-02-08 10:06:42.000000000","message":"I\u0027ve said before the reason I like 10+4x2 better than 10+18 is so you can increase duplication factor into another region (10+4x3) as you grow - there\u0027s no going to 10+32 (nor would you want to, nor does libec support a schema like that [1])\n\n1. Feb  8 04:42:29 saio liberasurecode[23302]: Total number of fragments (k + m) must be less than 32","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":286,"context_line":"of EC fragments is optimal for EC storage policies which require dispersion"},{"line_number":287,"context_line":"of fragment data across failure domains which are assigned less than 1/2 of"},{"line_number":288,"context_line":"the total fragments.  Empirical testing has shown using duplication is more"},{"line_number":289,"context_line":"efficient in the PUT path than encoding a schema with num_parity \u003e num_data,"},{"line_number":290,"context_line":"and Swift EC supports this schema.  You should evaluate which strategy works"},{"line_number":291,"context_line":"best in your environment."},{"line_number":292,"context_line":""}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_a9c2f631","line":289,"in_reply_to":"1a430d35_b3fa6541","updated":"2017-02-09 09:36:43.000000000","message":"Yeah, liberasurecode has the hard-coded constraint.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":291,"context_line":"best in your environment."},{"line_number":292,"context_line":""},{"line_number":293,"context_line":"e.g. 10-4 and duplication factor of 2 will store 28 fragments (i.e."},{"line_number":294,"context_line":"(\u0027ec_num_data_fragments\u0027 + \u0027ec_num_parity_fragments\u0027) *"},{"line_number":295,"context_line":"\u0027ec_duplication_factor\u0027). This *can* allow for a failure domain to rebuild"},{"line_number":296,"context_line":"an object to full durability even when *more* than 14 fragments are"},{"line_number":297,"context_line":"unavailable."}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_ffa662ac","line":294,"updated":"2017-02-08 18:01:12.000000000","message":"nit: use double back-ticks","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f90c30a46d20b933970f063a350dc2d2085389b7","unresolved":false,"context_lines":[{"line_number":291,"context_line":"best in your environment."},{"line_number":292,"context_line":""},{"line_number":293,"context_line":"e.g. 10-4 and duplication factor of 2 will store 28 fragments (i.e."},{"line_number":294,"context_line":"(\u0027ec_num_data_fragments\u0027 + \u0027ec_num_parity_fragments\u0027) *"},{"line_number":295,"context_line":"\u0027ec_duplication_factor\u0027). This *can* allow for a failure domain to rebuild"},{"line_number":296,"context_line":"an object to full durability even when *more* than 14 fragments are"},{"line_number":297,"context_line":"unavailable."}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_adb474d4","line":294,"in_reply_to":"1a430d35_f9365e01","updated":"2017-02-09 18:00:58.000000000","message":"you got it :) double back tick \u003d\u003d ``","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":291,"context_line":"best in your environment."},{"line_number":292,"context_line":""},{"line_number":293,"context_line":"e.g. 10-4 and duplication factor of 2 will store 28 fragments (i.e."},{"line_number":294,"context_line":"(\u0027ec_num_data_fragments\u0027 + \u0027ec_num_parity_fragments\u0027) *"},{"line_number":295,"context_line":"\u0027ec_duplication_factor\u0027). This *can* allow for a failure domain to rebuild"},{"line_number":296,"context_line":"an object to full durability even when *more* than 14 fragments are"},{"line_number":297,"context_line":"unavailable."}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_f9365e01","line":294,"in_reply_to":"1a430d35_ffa662ac","updated":"2017-02-09 09:36:43.000000000","message":"Maybe done if I get correct understanding but not sure the doubled back-ticks is ``?","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":301,"context_line":"    Current EC Duplication is a part work of EC region support so we still"},{"line_number":302,"context_line":"    have some known issues to get complete region supports:"},{"line_number":303,"context_line":""},{"line_number":304,"context_line":"    Known-Issues:"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"    - Unique fragment dispersion"},{"line_number":307,"context_line":""}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_533ea1da","line":304,"updated":"2017-02-08 10:06:42.000000000","message":"This section is great!  I think it renders fine.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":306,"context_line":"    - Unique fragment dispersion"},{"line_number":307,"context_line":""},{"line_number":308,"context_line":"     Currently, Swift \\*doesn\u0027t\\* guarantee the dispersion of unique"},{"line_number":309,"context_line":"     fragments\u0027 locations in the global distributed cluster being robust in"},{"line_number":310,"context_line":"     the disaster recovery case. In the EC fragment duplication, sometimes we"},{"line_number":311,"context_line":"     could get the case we cannot decode the original data with # of"},{"line_number":312,"context_line":"     ec_ndata fragments because the set of fragments may include duplicate"}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_9cc2cce7","line":309,"updated":"2017-02-08 18:01:12.000000000","message":"see line 285, would be useful to have defined the concept of \"unique fragment\"","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":306,"context_line":"    - Unique fragment dispersion"},{"line_number":307,"context_line":""},{"line_number":308,"context_line":"     Currently, Swift \\*doesn\u0027t\\* guarantee the dispersion of unique"},{"line_number":309,"context_line":"     fragments\u0027 locations in the global distributed cluster being robust in"},{"line_number":310,"context_line":"     the disaster recovery case. In the EC fragment duplication, sometimes we"},{"line_number":311,"context_line":"     could get the case we cannot decode the original data with # of"},{"line_number":312,"context_line":"     ec_ndata fragments because the set of fragments may include duplicate"}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_f91d7e73","line":309,"in_reply_to":"1a430d35_9cc2cce7","updated":"2017-02-09 09:36:43.000000000","message":"Done","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":308,"context_line":"     Currently, Swift \\*doesn\u0027t\\* guarantee the dispersion of unique"},{"line_number":309,"context_line":"     fragments\u0027 locations in the global distributed cluster being robust in"},{"line_number":310,"context_line":"     the disaster recovery case. In the EC fragment duplication, sometimes we"},{"line_number":311,"context_line":"     could get the case we cannot decode the original data with # of"},{"line_number":312,"context_line":"     ec_ndata fragments because the set of fragments may include duplicate"},{"line_number":313,"context_line":"     fragments. E.g. the 4-2, and duplication factor \u003d\u003d 2 case, if we have"},{"line_number":314,"context_line":"     fragments"}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_fc611006","line":311,"range":{"start_line":311,"start_character":19,"end_line":311,"end_character":33},"updated":"2017-02-08 18:01:12.000000000","message":"nit s/we/when we/","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":308,"context_line":"     Currently, Swift \\*doesn\u0027t\\* guarantee the dispersion of unique"},{"line_number":309,"context_line":"     fragments\u0027 locations in the global distributed cluster being robust in"},{"line_number":310,"context_line":"     the disaster recovery case. In the EC fragment duplication, sometimes we"},{"line_number":311,"context_line":"     could get the case we cannot decode the original data with # of"},{"line_number":312,"context_line":"     ec_ndata fragments because the set of fragments may include duplicate"},{"line_number":313,"context_line":"     fragments. E.g. the 4-2, and duplication factor \u003d\u003d 2 case, if we have"},{"line_number":314,"context_line":"     fragments"}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_b4b85d2b","line":311,"range":{"start_line":311,"start_character":19,"end_line":311,"end_character":33},"in_reply_to":"1a430d35_fc611006","updated":"2017-02-09 09:36:43.000000000","message":"Done","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":308,"context_line":"     Currently, Swift \\*doesn\u0027t\\* guarantee the dispersion of unique"},{"line_number":309,"context_line":"     fragments\u0027 locations in the global distributed cluster being robust in"},{"line_number":310,"context_line":"     the disaster recovery case. In the EC fragment duplication, sometimes we"},{"line_number":311,"context_line":"     could get the case we cannot decode the original data with # of"},{"line_number":312,"context_line":"     ec_ndata fragments because the set of fragments may include duplicate"},{"line_number":313,"context_line":"     fragments. E.g. the 4-2, and duplication factor \u003d\u003d 2 case, if we have"},{"line_number":314,"context_line":"     fragments"},{"line_number":315,"context_line":"     with index [0, 1, 2, 0] (length \u003d\u003d ec_ndata \u003d 4), the case still needs"},{"line_number":316,"context_line":"     either index 3, 4, or 5 to decode."}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_7f7c32ec","line":313,"range":{"start_line":311,"start_character":64,"end_line":313,"end_character":14},"updated":"2017-02-08 18:01:12.000000000","message":"If I did not already know what this means, I would not understand the text: what is #? which set?\n\nI *think* it is saying:\n\nCurrently, Swift \\*doesn\u0027t\\* guarantee the dispersion of unique fragments\u0027 locations in the global distributed cluster being robust in the disaster recovery case. Whilst the goal is to have duplicates of each unique fragment placed in each region, it is currently possible for duplicates of the same unique fragment to be placed in the same region. Since a set of ``ec_num_data_fragments`` unique fragments is required to reconstruct an object, the suboptimal distribution of duplicates across regions may, in some cases, make it impossible to assemble such a set from a single region.\n\nFor example, if we have a Swift cluster with 2 regions, the fragments may be located like as: ...","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":308,"context_line":"     Currently, Swift \\*doesn\u0027t\\* guarantee the dispersion of unique"},{"line_number":309,"context_line":"     fragments\u0027 locations in the global distributed cluster being robust in"},{"line_number":310,"context_line":"     the disaster recovery case. In the EC fragment duplication, sometimes we"},{"line_number":311,"context_line":"     could get the case we cannot decode the original data with # of"},{"line_number":312,"context_line":"     ec_ndata fragments because the set of fragments may include duplicate"},{"line_number":313,"context_line":"     fragments. E.g. the 4-2, and duplication factor \u003d\u003d 2 case, if we have"},{"line_number":314,"context_line":"     fragments"},{"line_number":315,"context_line":"     with index [0, 1, 2, 0] (length \u003d\u003d ec_ndata \u003d 4), the case still needs"},{"line_number":316,"context_line":"     either index 3, 4, or 5 to decode."}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_0f53dc17","line":313,"range":{"start_line":311,"start_character":64,"end_line":313,"end_character":14},"in_reply_to":"1a430d35_7f7c32ec","updated":"2017-02-09 09:36:43.000000000","message":"Great docs! Thanks I\u0027ll replace this block with that!","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":336,"context_line":"        #5#d.data"},{"line_number":337,"context_line":""},{"line_number":338,"context_line":"     In this case, r1 has only the fragments with index 0, 2, 4 and r2 has"},{"line_number":339,"context_line":"     the rest of indexes but we need 4 unique indexes to decode. To resolve"},{"line_number":340,"context_line":"     the case to tight the index up to each region, the composite ring which"},{"line_number":341,"context_line":"     enables the operator oriented location mapping [1] is under development."},{"line_number":342,"context_line":""},{"line_number":343,"context_line":"     1: https://review.openstack.org/#/c/271920/"}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_3f81ca8f","line":340,"range":{"start_line":339,"start_character":65,"end_line":340,"end_character":50},"updated":"2017-02-08 18:01:12.000000000","message":"this doesn\u0027t make sense gramatically. I think it would be ok to simply say:\n\nTo resolve this case, the composite ring which enables the operator oriented location mapping [1] is under development.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":336,"context_line":"        #5#d.data"},{"line_number":337,"context_line":""},{"line_number":338,"context_line":"     In this case, r1 has only the fragments with index 0, 2, 4 and r2 has"},{"line_number":339,"context_line":"     the rest of indexes but we need 4 unique indexes to decode. To resolve"},{"line_number":340,"context_line":"     the case to tight the index up to each region, the composite ring which"},{"line_number":341,"context_line":"     enables the operator oriented location mapping [1] is under development."},{"line_number":342,"context_line":""},{"line_number":343,"context_line":"     1: https://review.openstack.org/#/c/271920/"}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_6fb2a04d","line":340,"range":{"start_line":339,"start_character":65,"end_line":340,"end_character":50},"in_reply_to":"1a430d35_3f81ca8f","updated":"2017-02-09 09:36:43.000000000","message":"Done","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":344,"context_line":""},{"line_number":345,"context_line":"    - Efficient node iteration for read"},{"line_number":346,"context_line":""},{"line_number":347,"context_line":"     Since EC fragment duplication requires to unique fragment indexes to"},{"line_number":348,"context_line":"     decode the original object, it needs efficient node iteration rather"},{"line_number":349,"context_line":"     than current. Current Swift is iterating the nodes ordered by sorting"},{"line_number":350,"context_line":"     method defined in proxy server config. (i.e. either shuffle, node_timing,"}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_3f58ea55","line":347,"updated":"2017-02-08 18:01:12.000000000","message":"s/requires to/requires a set of/","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":344,"context_line":""},{"line_number":345,"context_line":"    - Efficient node iteration for read"},{"line_number":346,"context_line":""},{"line_number":347,"context_line":"     Since EC fragment duplication requires to unique fragment indexes to"},{"line_number":348,"context_line":"     decode the original object, it needs efficient node iteration rather"},{"line_number":349,"context_line":"     than current. Current Swift is iterating the nodes ordered by sorting"},{"line_number":350,"context_line":"     method defined in proxy server config. (i.e. either shuffle, node_timing,"}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_af8f2873","line":347,"in_reply_to":"1a430d35_3f58ea55","updated":"2017-02-09 09:36:43.000000000","message":"Done","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":356,"context_line":""},{"line_number":357,"context_line":"     The possible solution could be some refactoring work on NodeIter to"},{"line_number":358,"context_line":"     provide suitable nodes even if it\u0027s fragment duplication but it\u0027s still"},{"line_number":359,"context_line":"     under development yet."},{"line_number":360,"context_line":""},{"line_number":361,"context_line":""},{"line_number":362,"context_line":"--------------"}],"source_content_type":"text/x-rst","patch_set":53,"id":"1a430d35_bf113a5f","line":359,"updated":"2017-02-08 18:01:12.000000000","message":"ok. good to know.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":20508,"name":"Mohit Motiani","email":"mohit.motiani@intel.com","username":"mohit.motiani"},"change_message_id":"437c588b6999a8869578b6282578869c0d7d3a6b","unresolved":false,"context_lines":[{"line_number":228,"context_line":"  comprised of parity."},{"line_number":229,"context_line":"* ``ec_object_segment_size``: The amount of data that will be buffered up before"},{"line_number":230,"context_line":"  feeding a segment into the encoder/decoder. The default value is 1048576."},{"line_number":231,"context_line":"* ``ec_duplication_factor``: The number of duplicated copies for each fragments."},{"line_number":232,"context_line":"  This is now experimental support to enable Global Erasure Coding policies with"},{"line_number":233,"context_line":"  multiple regions. Do not change the default except in development/testing. And"},{"line_number":234,"context_line":"  please read the \"EC Duplication\" section below before changing the default"}],"source_content_type":"text/x-rst","patch_set":58,"id":"da36d5c6_5dcb44a5","line":231,"range":{"start_line":231,"start_character":70,"end_line":231,"end_character":79},"updated":"2017-02-22 16:28:27.000000000","message":"s/fragments/fragment","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":20508,"name":"Mohit Motiani","email":"mohit.motiani@intel.com","username":"mohit.motiani"},"change_message_id":"437c588b6999a8869578b6282578869c0d7d3a6b","unresolved":false,"context_lines":[{"line_number":286,"context_line":"EC Duplication"},{"line_number":287,"context_line":"^^^^^^^^^^^^^^"},{"line_number":288,"context_line":""},{"line_number":289,"context_line":"ec_duplication_factor is an option to make duplicated copies of fragments"},{"line_number":290,"context_line":"of erasure encoded Swift objects. The default value is 1 (not duplicated)."},{"line_number":291,"context_line":"If an erasure code storage policy is configured with a non-default"},{"line_number":292,"context_line":"ec_duplication_factor of N \u003e 1, then the policy will create N duplicates of"}],"source_content_type":"text/x-rst","patch_set":58,"id":"da36d5c6_dd5654d1","line":289,"range":{"start_line":289,"start_character":43,"end_line":289,"end_character":53},"updated":"2017-02-22 16:28:27.000000000","message":"s/duplicated/duplicate","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":20508,"name":"Mohit Motiani","email":"mohit.motiani@intel.com","username":"mohit.motiani"},"change_message_id":"437c588b6999a8869578b6282578869c0d7d3a6b","unresolved":false,"context_lines":[{"line_number":296,"context_line":"of common ec parameters like 10-4 cause less assignments than 1/(the number"},{"line_number":297,"context_line":"of failure domains) of the total unique fragments. And usually, it will be less"},{"line_number":298,"context_line":"than the number of data fragments which are required to construct the original"},{"line_number":299,"context_line":"data. To guarantee the number of fragmetns in a failure domain, the system"},{"line_number":300,"context_line":"requires more parities. On the situation which needs more parity, empirical"},{"line_number":301,"context_line":"testing has shown using duplication is more efficient in the PUT path than"},{"line_number":302,"context_line":"encoding a schema with num_parity \u003e num_data, and Swift EC supports this schema."}],"source_content_type":"text/x-rst","patch_set":58,"id":"da36d5c6_7d72c8ae","line":299,"range":{"start_line":299,"start_character":33,"end_line":299,"end_character":42},"updated":"2017-02-22 16:28:27.000000000","message":"s/fragmetns/fragments","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"}],"etc/swift.conf-sample":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":90,"context_line":"# If an erasure code storage policy is configured with a non-default"},{"line_number":91,"context_line":"# ec_duplication_factor of N \u003e 1, then the policy will create N duplicates of"},{"line_number":92,"context_line":"# each fragment that is returned from the configured EC engine.  Duplication"},{"line_number":93,"context_line":"# of EC fragments is optimal for EC storage policies which require dispersion"},{"line_number":94,"context_line":"# of fragment data across failure domains which are assigned less than 1/2 of"},{"line_number":95,"context_line":"# the total fragments.  Empirical testing has shown using duplication is more"},{"line_number":96,"context_line":"# efficient in the PUT path than encoding a schema with num_parity \u003e num_data,"}],"source_content_type":"application/octet-stream","patch_set":43,"id":"ba5201f7_a796ca3b","line":93,"range":{"start_line":93,"start_character":21,"end_line":93,"end_character":28},"updated":"2017-01-12 00:29:56.000000000","message":"\"optimal\" or \"useful\"? Or maybe someone else has a better idea on wording?","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ddab6fb5eac38b4b7d145db57826fcd3948ae2c7","unresolved":false,"context_lines":[{"line_number":90,"context_line":"# If an erasure code storage policy is configured with a non-default"},{"line_number":91,"context_line":"# ec_duplication_factor of N \u003e 1, then the policy will create N duplicates of"},{"line_number":92,"context_line":"# each fragment that is returned from the configured EC engine.  Duplication"},{"line_number":93,"context_line":"# of EC fragments is optimal for EC storage policies which require dispersion"},{"line_number":94,"context_line":"# of fragment data across failure domains which are assigned less than 1/2 of"},{"line_number":95,"context_line":"# the total fragments.  Empirical testing has shown using duplication is more"},{"line_number":96,"context_line":"# efficient in the PUT path than encoding a schema with num_parity \u003e num_data,"}],"source_content_type":"application/octet-stream","patch_set":43,"id":"7a3c09a3_25ab328b","line":93,"range":{"start_line":93,"start_character":21,"end_line":93,"end_character":28},"in_reply_to":"ba5201f7_a796ca3b","updated":"2017-01-13 13:53:40.000000000","message":"I\u0027m not good at English wording, so not sure. but it sounds like optimal could be ok.","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":91,"context_line":"# ec_duplication_factor of N \u003e 1, then the policy will create N duplicates of"},{"line_number":92,"context_line":"# each fragment that is returned from the configured EC engine.  Duplication"},{"line_number":93,"context_line":"# of EC fragments is optimal for EC storage policies which require dispersion"},{"line_number":94,"context_line":"# of fragment data across failure domains which are assigned less than 1/2 of"},{"line_number":95,"context_line":"# the total fragments.  Empirical testing has shown using duplication is more"},{"line_number":96,"context_line":"# efficient in the PUT path than encoding a schema with num_parity \u003e num_data,"},{"line_number":97,"context_line":"# and Swift EC supports this schema.  You should evaluate which strategy works"},{"line_number":98,"context_line":"# best in your environment."}],"source_content_type":"application/octet-stream","patch_set":43,"id":"ba5201f7_07f7968b","line":95,"range":{"start_line":94,"start_character":61,"end_line":95,"end_character":21},"updated":"2017-01-12 00:29:56.000000000","message":"Less than half, or less than num_data_fragments?","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ddab6fb5eac38b4b7d145db57826fcd3948ae2c7","unresolved":false,"context_lines":[{"line_number":91,"context_line":"# ec_duplication_factor of N \u003e 1, then the policy will create N duplicates of"},{"line_number":92,"context_line":"# each fragment that is returned from the configured EC engine.  Duplication"},{"line_number":93,"context_line":"# of EC fragments is optimal for EC storage policies which require dispersion"},{"line_number":94,"context_line":"# of fragment data across failure domains which are assigned less than 1/2 of"},{"line_number":95,"context_line":"# the total fragments.  Empirical testing has shown using duplication is more"},{"line_number":96,"context_line":"# efficient in the PUT path than encoding a schema with num_parity \u003e num_data,"},{"line_number":97,"context_line":"# and Swift EC supports this schema.  You should evaluate which strategy works"},{"line_number":98,"context_line":"# best in your environment."}],"source_content_type":"application/octet-stream","patch_set":43,"id":"7a3c09a3_c5aa6e70","line":95,"range":{"start_line":94,"start_character":61,"end_line":95,"end_character":21},"in_reply_to":"ba5201f7_07f7968b","updated":"2017-01-13 13:53:40.000000000","message":"less than or equal to num_data_fragmetns.","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":100,"context_line":"# e.g. 10-4 and duplication factor of 2 will store 28 fragments.  This *can*"},{"line_number":101,"context_line":"# allow for a failure domain to rebuild an object to full durability even when"},{"line_number":102,"context_line":"# *more* than 14 fragments are unavailable."},{"line_number":103,"context_line":"#ec_duplication_factor \u003d 1"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"# The swift-constraints section sets the basic constraints on data"},{"line_number":106,"context_line":"# saved in the swift cluster. These constraints are automatically"}],"source_content_type":"application/octet-stream","patch_set":43,"id":"ba5201f7_c70e6e8b","line":103,"updated":"2017-01-12 00:29:56.000000000","message":"Does this have to be an integer, or can it be fractional like the ring\u0027s replica_count? Would that even still be useful?","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ddab6fb5eac38b4b7d145db57826fcd3948ae2c7","unresolved":false,"context_lines":[{"line_number":100,"context_line":"# e.g. 10-4 and duplication factor of 2 will store 28 fragments.  This *can*"},{"line_number":101,"context_line":"# allow for a failure domain to rebuild an object to full durability even when"},{"line_number":102,"context_line":"# *more* than 14 fragments are unavailable."},{"line_number":103,"context_line":"#ec_duplication_factor \u003d 1"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"# The swift-constraints section sets the basic constraints on data"},{"line_number":106,"context_line":"# saved in the swift cluster. These constraints are automatically"}],"source_content_type":"application/octet-stream","patch_set":43,"id":"7a3c09a3_05d8f652","line":103,"in_reply_to":"ba5201f7_c70e6e8b","updated":"2017-01-13 13:53:40.000000000","message":"It should be natural number and if someone set a float instance, it should be value error (see swift.common.utils.config_natural_number). AFAIK, erasure coding doesn\u0027t allow floating replica count because total_number of fragments should be fixed ec_k + ec_m. Otherwise, the encoding scheme could be in violence. Therefore, the value should be natural number, IMO.","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":99,"context_line":"#"},{"line_number":100,"context_line":"# e.g. 10-4 and duplication factor of 2 will store 28 fragments.  This *can*"},{"line_number":101,"context_line":"# allow for a failure domain to rebuild an object to full durability even when"},{"line_number":102,"context_line":"# *more* than 14 fragments are unavailable."},{"line_number":103,"context_line":"#ec_duplication_factor \u003d 1"},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"# The swift-constraints section sets the basic constraints on data"}],"source_content_type":"application/octet-stream","patch_set":44,"id":"7a3c09a3_65a8658e","line":102,"updated":"2017-01-17 02:54:44.000000000","message":"at first glance this is a bit wordy for annotations in the config file:\n\n\t# if using multi region set this to # of regions and make your ring with\n\t# \"(k + m) * d\" replicas`\n\nor something else straight to the point - save the verbose prose for the doc tree?","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":17361,"name":"Shashirekha Gundur","email":"shashirekha.j.gundur@intel.com","username":"shashirekha.j.gundur"},"change_message_id":"ac4a0687a58014fa3e007819cb2aa90cb286d173","unresolved":false,"context_lines":[{"line_number":96,"context_line":"# efficient in the PUT path than encoding a schema with num_parity \u003e num_data,"},{"line_number":97,"context_line":"# and Swift EC supports this schema.  You should evaluate which strategy works"},{"line_number":98,"context_line":"# best in your environment."},{"line_number":99,"context_line":"#"},{"line_number":100,"context_line":"# e.g. 10-4 and duplication factor of 2 will store 28 fragments.  This *can*"},{"line_number":101,"context_line":"# allow for a failure domain to rebuild an object to full durability even when"},{"line_number":102,"context_line":"# *more* than 14 fragments are unavailable."}],"source_content_type":"application/octet-stream","patch_set":45,"id":"3a461143_84591e5d","line":99,"updated":"2017-01-26 17:45:24.000000000","message":"may add a brief note about what should be the replica count taking duplication_factor  into account like\n(\u0027ec_num_data_fragments\u0027 + ‘ec_num_parity_fragments’) * ‘ec_duplication_factor\u0027\nhttps://github.com/openstack/swift/blob/master/etc/swift.conf-sample#L64-L67","commit_id":"6f67f06282edee83f5042d96c5ab2bd4d967611a"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"0402581a177e1b238637e9be524a6662e4f84c84","unresolved":false,"context_lines":[{"line_number":96,"context_line":"# efficient in the PUT path than encoding a schema with num_parity \u003e num_data,"},{"line_number":97,"context_line":"# and Swift EC supports this schema.  You should evaluate which strategy works"},{"line_number":98,"context_line":"# best in your environment."},{"line_number":99,"context_line":"#"},{"line_number":100,"context_line":"# e.g. 10-4 and duplication factor of 2 will store 28 fragments.  This *can*"},{"line_number":101,"context_line":"# allow for a failure domain to rebuild an object to full durability even when"},{"line_number":102,"context_line":"# *more* than 14 fragments are unavailable."}],"source_content_type":"application/octet-stream","patch_set":45,"id":"3a461143_6e5116d8","line":99,"in_reply_to":"3a461143_84591e5d","updated":"2017-01-30 06:00:52.000000000","message":"Sure! Good docs!","commit_id":"6f67f06282edee83f5042d96c5ab2bd4d967611a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"381bbaf5157aaf99c818b3bab373a9845047ca56","unresolved":false,"context_lines":[{"line_number":102,"context_line":"# \u0027ec_duplication_factor\u0027). This *can* allow for a failure domain to rebuild"},{"line_number":103,"context_line":"# an object to full durability even when *more* than 14 fragments are"},{"line_number":104,"context_line":"# unavailable."},{"line_number":105,"context_line":"#ec_duplication_factor \u003d 1"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"# The swift-constraints section sets the basic constraints on data"},{"line_number":108,"context_line":"# saved in the swift cluster. These constraints are automatically"}],"source_content_type":"application/octet-stream","patch_set":47,"id":"3a461143_72509e5f","line":105,"updated":"2017-02-02 03:14:49.000000000","message":"The amount of prose in swift.conf-sample is not appropriate IMHO.  We should be trying to eliminate walls-of-text from an example config file and migrate any useful prose into the docs.\n\nIMHO, this change contributes to the existing problem and makes it worse.  We *should* say much less about ec_duplication-factor in this file and much *more* in the documentation.\n\nWe *need* to say here the feature is experimental (lacking compoiste-ring/frag-index placement)","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"2671effc57b1f727998acb5e80e3d54c801ba99f","unresolved":false,"context_lines":[{"line_number":102,"context_line":"# \u0027ec_duplication_factor\u0027). This *can* allow for a failure domain to rebuild"},{"line_number":103,"context_line":"# an object to full durability even when *more* than 14 fragments are"},{"line_number":104,"context_line":"# unavailable."},{"line_number":105,"context_line":"#ec_duplication_factor \u003d 1"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"# The swift-constraints section sets the basic constraints on data"},{"line_number":108,"context_line":"# saved in the swift cluster. These constraints are automatically"}],"source_content_type":"application/octet-stream","patch_set":47,"id":"1a430d35_3d5d0dea","line":105,"in_reply_to":"3a461143_72509e5f","updated":"2017-02-03 10:42:24.000000000","message":"Fair enough. Ok, let\u0027s try to move them to overview_erasure_code.rst","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"14e79b02b1701be869c5bc61940f6419465ddbf1","unresolved":false,"context_lines":[{"line_number":88,"context_line":"# Duplicated EC fragments is proof-of-concept experimental support to enable"},{"line_number":89,"context_line":"# Global Erasure Coding policies with multiple regions acting as independent"},{"line_number":90,"context_line":"# failure domains.  Do not change the default except in development/testing."},{"line_number":91,"context_line":"#ec_duplication_factor \u003d 1"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"# The swift-constraints section sets the basic constraints on data"},{"line_number":94,"context_line":"# saved in the swift cluster. These constraints are automatically"}],"source_content_type":"application/octet-stream","patch_set":60,"id":"da36d5c6_84536016","line":91,"updated":"2017-02-24 06:33:58.000000000","message":"Is there any upgrade path for existing policies? If I update swift.conf\u0027s ec_duplication_factor from 1 to 2, and update the ring to have twice as many replicas, should that Just Work? (+/- a whole lot of reconstructor traffic as those next num_data + num_parity nodes scramble for fragments, of course.)\n\nI know that we can grow replica counts for replicated policies, and soon we\u0027ll be able to grow part_power. It seems like we may want to be able to grow ec_duplication factor, too? Say, if you had a single-region cluster but wanted to bring up a whole new data center?","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"17784a067ebf84c421087547a44f4579982c1887","unresolved":false,"context_lines":[{"line_number":88,"context_line":"# Duplicated EC fragments is proof-of-concept experimental support to enable"},{"line_number":89,"context_line":"# Global Erasure Coding policies with multiple regions acting as independent"},{"line_number":90,"context_line":"# failure domains.  Do not change the default except in development/testing."},{"line_number":91,"context_line":"#ec_duplication_factor \u003d 1"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"# The swift-constraints section sets the basic constraints on data"},{"line_number":94,"context_line":"# saved in the swift cluster. These constraints are automatically"}],"source_content_type":"application/octet-stream","patch_set":60,"id":"da36d5c6_6071ef43","line":91,"in_reply_to":"da36d5c6_84536016","updated":"2017-02-24 14:37:56.000000000","message":"Good thought, i think. At the my first idea, I didn\u0027t expect the use case to grow the # of fragments in the Swift EC Policy which is not supported currently but from the discussion at PTG, I\u0027m realizing it could be. IMO, we need to test/improvement with that case with deep thinking (perhaps some of corner cases could be broken).","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"}],"swift/common/storage_policy.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2ba7bc6218b06841791a14e78044af4ec4fe9962","unresolved":false,"context_lines":[{"line_number":526,"context_line":"        return (\"%s, EC config(ec_type\u003d%s, ec_segment_size\u003d%d, \""},{"line_number":527,"context_line":"                \"ec_ndata\u003d%d, ec_nparity\u003d%d)\") % \\"},{"line_number":528,"context_line":"               (super(ECStoragePolicy, self).__repr__(), self.ec_type,"},{"line_number":529,"context_line":"                self.ec_segment_size, self.ec_ndata, self.ec_nparity)"},{"line_number":530,"context_line":""},{"line_number":531,"context_line":"    @classmethod"},{"line_number":532,"context_line":"    def _config_options_map(cls):"}],"source_content_type":"text/x-python","patch_set":20,"id":"fad55976_00ec4fc6","side":"PARENT","line":529,"updated":"2016-07-15 18:53:07.000000000","message":"ec_duplication_factor is important component of ring, I believe it should be represented in this repr","commit_id":"d309a5d14881fd2943f3cc3ca894bdef1e24540d"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7616defbc04f817241dbf883df0b173056b244a","unresolved":false,"context_lines":[{"line_number":526,"context_line":"        return (\"%s, EC config(ec_type\u003d%s, ec_segment_size\u003d%d, \""},{"line_number":527,"context_line":"                \"ec_ndata\u003d%d, ec_nparity\u003d%d)\") % \\"},{"line_number":528,"context_line":"               (super(ECStoragePolicy, self).__repr__(), self.ec_type,"},{"line_number":529,"context_line":"                self.ec_segment_size, self.ec_ndata, self.ec_nparity)"},{"line_number":530,"context_line":""},{"line_number":531,"context_line":"    @classmethod"},{"line_number":532,"context_line":"    def _config_options_map(cls):"}],"source_content_type":"text/x-python","patch_set":20,"id":"dada55a8_6e3e63db","side":"PARENT","line":529,"in_reply_to":"fad55976_00ec4fc6","updated":"2016-07-20 12:05:35.000000000","message":"Alright, this is addressed at https://review.openstack.org/#/c/343032/1/swift/common/storage_policy.py@543\n\nAnd I think you\u0027re correct. So I will squash up the change to here.","commit_id":"d309a5d14881fd2943f3cc3ca894bdef1e24540d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2ba7bc6218b06841791a14e78044af4ec4fe9962","unresolved":false,"context_lines":[{"line_number":576,"context_line":"            raise PolicyError(\u0027Ring is not loaded\u0027)"},{"line_number":577,"context_line":"        nodes_configured \u003d self.object_ring.replica_count"},{"line_number":578,"context_line":"        policy_configured \u003d \\"},{"line_number":579,"context_line":"            (self.ec_ndata + self.ec_nparity) * self.ec_duplication_factor"},{"line_number":580,"context_line":"        if nodes_configured !\u003d policy_configured:"},{"line_number":581,"context_line":"            raise RingValidationError("},{"line_number":582,"context_line":"                \u0027EC ring for policy %s needs to be configured with \u0027"}],"source_content_type":"text/x-python","patch_set":20,"id":"fad55976_20feb36b","line":579,"updated":"2016-07-15 18:53:07.000000000","message":"perhaps use n_fragments more often, or remove n_fragments?\n\nPerhaps this value \"(ndata + nparity) * duplication_factor\" named \"total_fragments\" - is most obvious?  If only n_fragments is needed in some code (obj.controller or obj.reconstructor) perhaps it is more clear to say (ndata + nparity) explicitly?  I think n_fragments !\u003d total_fragments may be a source of future bugs if we confuse the meaning of these names?","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7616defbc04f817241dbf883df0b173056b244a","unresolved":false,"context_lines":[{"line_number":576,"context_line":"            raise PolicyError(\u0027Ring is not loaded\u0027)"},{"line_number":577,"context_line":"        nodes_configured \u003d self.object_ring.replica_count"},{"line_number":578,"context_line":"        policy_configured \u003d \\"},{"line_number":579,"context_line":"            (self.ec_ndata + self.ec_nparity) * self.ec_duplication_factor"},{"line_number":580,"context_line":"        if nodes_configured !\u003d policy_configured:"},{"line_number":581,"context_line":"            raise RingValidationError("},{"line_number":582,"context_line":"                \u0027EC ring for policy %s needs to be configured with \u0027"}],"source_content_type":"text/x-python","patch_set":20,"id":"dada55a8_42f53355","line":579,"in_reply_to":"fad55976_20feb36b","updated":"2016-07-20 12:05:35.000000000","message":"Gotcha. Probably, *n_unique_fragments* is more obvious than n_fragments? Exactly it make us to confuse like total vs unique_count.\n\nI will change the property name as n_unique_fragments and use in somewhere in storage_policy.","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":603,"context_line":"            considering the number of nodes in the primary list from the ring."},{"line_number":604,"context_line":"            \"\"\""},{"line_number":605,"context_line":""},{"line_number":606,"context_line":"            nodes_configured \u003d len(ring_data._replica2part2dev_id)"},{"line_number":607,"context_line":"            policy_configured \u003d \\"},{"line_number":608,"context_line":"                (self.ec_n_unique_fragments) * self.ec_duplication_factor"},{"line_number":609,"context_line":"            if nodes_configured !\u003d policy_configured:"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_efea6873","line":606,"range":{"start_line":606,"start_character":31,"end_line":606,"end_character":66},"updated":"2017-01-12 00:29:56.000000000","message":"off-topic: we can\u0027t just use ring_data.replica_count here?","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ddab6fb5eac38b4b7d145db57826fcd3948ae2c7","unresolved":false,"context_lines":[{"line_number":603,"context_line":"            considering the number of nodes in the primary list from the ring."},{"line_number":604,"context_line":"            \"\"\""},{"line_number":605,"context_line":""},{"line_number":606,"context_line":"            nodes_configured \u003d len(ring_data._replica2part2dev_id)"},{"line_number":607,"context_line":"            policy_configured \u003d \\"},{"line_number":608,"context_line":"                (self.ec_n_unique_fragments) * self.ec_duplication_factor"},{"line_number":609,"context_line":"            if nodes_configured !\u003d policy_configured:"}],"source_content_type":"text/x-python","patch_set":43,"id":"7a3c09a3_653ffa25","line":606,"range":{"start_line":606,"start_character":31,"end_line":606,"end_character":66},"in_reply_to":"ba5201f7_efea6873","updated":"2017-01-13 13:53:40.000000000","message":"sure. it looks smarter.","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":619,"context_line":"    @property"},{"line_number":620,"context_line":"    def sort_key(self):"},{"line_number":621,"context_line":"        \"\"\""},{"line_number":622,"context_line":"        Sorting key for node_iter. This is according to policy\u0027s own storategy"},{"line_number":623,"context_line":"        which nodes should be chosen prior to other nodes."},{"line_number":624,"context_line":"        Default: No sort."},{"line_number":625,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_6f7cb8b5","line":622,"range":{"start_line":622,"start_character":69,"end_line":622,"end_character":78},"updated":"2017-01-12 00:29:56.000000000","message":"s/storategy/strategy/","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ddab6fb5eac38b4b7d145db57826fcd3948ae2c7","unresolved":false,"context_lines":[{"line_number":619,"context_line":"    @property"},{"line_number":620,"context_line":"    def sort_key(self):"},{"line_number":621,"context_line":"        \"\"\""},{"line_number":622,"context_line":"        Sorting key for node_iter. This is according to policy\u0027s own storategy"},{"line_number":623,"context_line":"        which nodes should be chosen prior to other nodes."},{"line_number":624,"context_line":"        Default: No sort."},{"line_number":625,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":43,"id":"7a3c09a3_250c1294","line":622,"range":{"start_line":622,"start_character":69,"end_line":622,"end_character":78},"in_reply_to":"ba5201f7_6f7cb8b5","updated":"2017-01-13 13:53:40.000000000","message":"Done","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":626,"context_line":"        if self.ec_duplication_factor \u003e 1:"},{"line_number":627,"context_line":"            return lambda node: node[\u0027index\u0027] // self.ec_n_unique_fragments"},{"line_number":628,"context_line":"        else:"},{"line_number":629,"context_line":"            return lambda node: None"},{"line_number":630,"context_line":""},{"line_number":631,"context_line":"    def get_backend_index(self, index):"},{"line_number":632,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_ef14284e","line":629,"updated":"2017-01-12 00:29:56.000000000","message":"Is this just an optimization to avoid needless integer divisions? If we only ever returned\n\n return lambda node: node[\u0027index\u0027] // self.ec_n_unique_fragments\n\nwouldn\u0027t it just always come out 0 in this case?","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ddab6fb5eac38b4b7d145db57826fcd3948ae2c7","unresolved":false,"context_lines":[{"line_number":626,"context_line":"        if self.ec_duplication_factor \u003e 1:"},{"line_number":627,"context_line":"            return lambda node: node[\u0027index\u0027] // self.ec_n_unique_fragments"},{"line_number":628,"context_line":"        else:"},{"line_number":629,"context_line":"            return lambda node: None"},{"line_number":630,"context_line":""},{"line_number":631,"context_line":"    def get_backend_index(self, index):"},{"line_number":632,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":43,"id":"7a3c09a3_c5742eff","line":629,"in_reply_to":"ba5201f7_ef14284e","updated":"2017-01-13 13:53:40.000000000","message":"Ah, good call. it\u0027s simpler than current. Done.","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":633,"context_line":"        Backend index for PyECLib"},{"line_number":634,"context_line":""},{"line_number":635,"context_line":"        :param index: integer of node index"},{"line_number":636,"context_line":"        :retrn: integer of actual fragment index if param is not an integer,"},{"line_number":637,"context_line":"                retrun None instead"},{"line_number":638,"context_line":"        \"\"\""},{"line_number":639,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_725d7b14","line":636,"range":{"start_line":636,"start_character":43,"end_line":636,"end_character":51},"updated":"2017-01-12 00:29:56.000000000","message":"Needs a period. Otherwise it sounds backwards :-P\n\nAlso, s/retrn/return/ and s/retrun/return/","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ddab6fb5eac38b4b7d145db57826fcd3948ae2c7","unresolved":false,"context_lines":[{"line_number":633,"context_line":"        Backend index for PyECLib"},{"line_number":634,"context_line":""},{"line_number":635,"context_line":"        :param index: integer of node index"},{"line_number":636,"context_line":"        :retrn: integer of actual fragment index if param is not an integer,"},{"line_number":637,"context_line":"                retrun None instead"},{"line_number":638,"context_line":"        \"\"\""},{"line_number":639,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":43,"id":"7a3c09a3_e594cae9","line":636,"range":{"start_line":636,"start_character":43,"end_line":636,"end_character":51},"in_reply_to":"ba5201f7_725d7b14","updated":"2017-01-13 13:53:40.000000000","message":"Oops, thanks. Done.","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":644,"context_line":"        if self.ec_duplication_factor \u003e 1:"},{"line_number":645,"context_line":"            return index % self.ec_n_unique_fragments"},{"line_number":646,"context_line":"        else:"},{"line_number":647,"context_line":"            return index"},{"line_number":648,"context_line":""},{"line_number":649,"context_line":""},{"line_number":650,"context_line":"class StoragePolicyCollection(object):"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_d2a2a7fb","line":647,"updated":"2017-01-12 00:29:56.000000000","message":"Again, just an optimization? Or am I missing something more subtle?\n\nIn this case, I\u0027m not sure it actually helps any since we do the \u003e 1 comparison every time. Haven\u0027t profiled it or anything, but it seems like the branching/comparison would be at least as bad as an unnecessary modulo?","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ddab6fb5eac38b4b7d145db57826fcd3948ae2c7","unresolved":false,"context_lines":[{"line_number":644,"context_line":"        if self.ec_duplication_factor \u003e 1:"},{"line_number":645,"context_line":"            return index % self.ec_n_unique_fragments"},{"line_number":646,"context_line":"        else:"},{"line_number":647,"context_line":"            return index"},{"line_number":648,"context_line":""},{"line_number":649,"context_line":""},{"line_number":650,"context_line":"class StoragePolicyCollection(object):"}],"source_content_type":"text/x-python","patch_set":43,"id":"7a3c09a3_45403e57","line":647,"in_reply_to":"ba5201f7_d2a2a7fb","updated":"2017-01-13 13:53:40.000000000","message":"Yeah, maybe the first time I wrote this, that means \"with duplication factor \u003d\u003d 1, nothing changed\" but in the review process (review/changes/refactoring), that can not be track-able anymore and for the new reviewer, exactly it looks odd.\n\nSo that I will remove the if condition here.","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":583,"context_line":"            considering the number of nodes in the primary list from the ring."},{"line_number":584,"context_line":"            \"\"\""},{"line_number":585,"context_line":""},{"line_number":586,"context_line":"            nodes_configured \u003d len(ring_data._replica2part2dev_id)"},{"line_number":587,"context_line":"            if nodes_configured !\u003d (self.ec_ndata + self.ec_nparity):"},{"line_number":588,"context_line":"                raise RingLoadError("},{"line_number":589,"context_line":"                    \u0027EC ring for policy %s needs to be configured with \u0027"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_05f16195","side":"PARENT","line":586,"updated":"2017-01-17 02:54:44.000000000","message":"I think this variable name is not great - but it was here before","commit_id":"436374e66c21b1ea7974d5c10527e72eca47a738"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":486,"context_line":""},{"line_number":487,"context_line":"    @property"},{"line_number":488,"context_line":"    def ec_n_unique_fragments(self):"},{"line_number":489,"context_line":"        return self._ec_ndata + self._ec_nparity"},{"line_number":490,"context_line":""},{"line_number":491,"context_line":"    @property"},{"line_number":492,"context_line":"    def ec_segment_size(self):"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_d9602404","line":489,"updated":"2017-01-17 02:54:44.000000000","message":"I think \"unique\" in this name here pairs well with \"duplication\"\n\nthis is a strong clear name I think compared to something like \"total\"","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":604,"context_line":"            \"\"\""},{"line_number":605,"context_line":""},{"line_number":606,"context_line":"            nodes_configured \u003d len(ring_data._replica2part2dev_id)"},{"line_number":607,"context_line":"            policy_configured \u003d \\"},{"line_number":608,"context_line":"                (self.ec_n_unique_fragments) * self.ec_duplication_factor"},{"line_number":609,"context_line":"            if nodes_configured !\u003d policy_configured:"},{"line_number":610,"context_line":"                raise RingLoadError("}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_25457db2","line":607,"updated":"2017-01-17 02:54:44.000000000","message":"I think this variable name is not good - something about required and replicas?\n\nI think I have come to live with the fact that\n\n1) we don\u0027t have a word that means \"either replicas or number of frags\" when speaking in the context of rings generally about either EC or replicated policies\n\n2) even if we did - we\u0027re not going to rename _replica2part2dev\n\nSo in the context of the ring we will *always* use the term \"replicas\" to mean \"either replicas of number of frags\" and when speaking about replicas in the context of EC policies it will always mean \"number of frags\"","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"efd89ba3beb38a31d211f39027728d5a93359721","unresolved":false,"context_lines":[{"line_number":604,"context_line":"            \"\"\""},{"line_number":605,"context_line":""},{"line_number":606,"context_line":"            nodes_configured \u003d len(ring_data._replica2part2dev_id)"},{"line_number":607,"context_line":"            policy_configured \u003d \\"},{"line_number":608,"context_line":"                (self.ec_n_unique_fragments) * self.ec_duplication_factor"},{"line_number":609,"context_line":"            if nodes_configured !\u003d policy_configured:"},{"line_number":610,"context_line":"                raise RingLoadError("}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_af330361","line":607,"in_reply_to":"7a3c09a3_25457db2","updated":"2017-01-17 10:30:20.000000000","message":"Hmm, good point. And also, this is in the EC Policy world so we can use words like number of frags, right? \n\nsort of \"configured_fragments_count\" and \"required_fragments_count\" could be better to clarify the meaning?","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":639,"context_line":"        except ValueError:"},{"line_number":640,"context_line":"            return None"},{"line_number":641,"context_line":""},{"line_number":642,"context_line":"        return index % self.ec_n_unique_fragments"},{"line_number":643,"context_line":""},{"line_number":644,"context_line":""},{"line_number":645,"context_line":"class StoragePolicyCollection(object):"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_65f5c555","line":642,"updated":"2017-01-17 02:54:44.000000000","message":"I find it surprising that these methods only exist on the ECStoragePolicy and don\u0027t have default/noop implementations on the BaseStoragePolicy\n\nthe implication is of course two-fold\n\n1) They are only used by the ECObjectController\n\n2) There is no shared common interface between StoragePolicies - and they are free to implement only things required by their own ObjectController\n\nThis should not be surprising to me - the ECObjectController already consumes many of the properties defined the ECStoragePolicy that makes it entirely incompatible with the general StoragePolicy interface\n\nHowever; it makes me wonder if there is any abstraction lines that would dictate if a method/helper belongs on the controller or the Policy itself?\n\nI suppose it would have something to do with if the property/method/helper is used (or is expected/assured to be used) in multiple components in the system or *only* in the ECObjectController?","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"efd89ba3beb38a31d211f39027728d5a93359721","unresolved":false,"context_lines":[{"line_number":639,"context_line":"        except ValueError:"},{"line_number":640,"context_line":"            return None"},{"line_number":641,"context_line":""},{"line_number":642,"context_line":"        return index % self.ec_n_unique_fragments"},{"line_number":643,"context_line":""},{"line_number":644,"context_line":""},{"line_number":645,"context_line":"class StoragePolicyCollection(object):"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_f2ddf2e0","line":642,"in_reply_to":"7a3c09a3_65f5c555","updated":"2017-01-17 10:30:20.000000000","message":"In my opinion, get_backend_index is only designed to ECObjectController. That is because only *EC policy* requires the index (both frag_index and node_index) to control some stuffs (e.g. fragment uniqueness, the nodes to reconstruct a missing fragment). And replicated Controller doesn\u0027t care about those indexes, right?\n\nOTOH, considering the abstraction/definition of policy interface, tightening up the properties/methods/helpers as *required* could be useful but... for now, we have only two controllers, i.e. Replicated and EC, and the class definition here seems being a reference which can be used for each controller. That makes me wondering if it\u0027s really needed.","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"381bbaf5157aaf99c818b3bab373a9845047ca56","unresolved":false,"context_lines":[{"line_number":628,"context_line":"            nodes_configured \u003d len(ring_data._replica2part2dev_id)"},{"line_number":629,"context_line":"            policy_configured \u003d \\"},{"line_number":630,"context_line":"                (self.ec_n_unique_fragments) * self.ec_duplication_factor"},{"line_number":631,"context_line":"            if nodes_configured !\u003d policy_configured:"},{"line_number":632,"context_line":"                raise RingLoadError("},{"line_number":633,"context_line":"                    \u0027EC ring for policy %s needs to be configured with \u0027"},{"line_number":634,"context_line":"                    \u0027exactly %d replicas. Got %d.\u0027 % ("}],"source_content_type":"text/x-python","patch_set":47,"id":"3a461143_1b2f72f7","line":631,"updated":"2017-02-02 03:14:49.000000000","message":"these names are bad","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":588,"context_line":"    def quorum(self):"},{"line_number":589,"context_line":"        \"\"\""},{"line_number":590,"context_line":"        Number of successful backend requests needed for the proxy to consider"},{"line_number":591,"context_line":"        the client request successful."},{"line_number":592,"context_line":""},{"line_number":593,"context_line":"        The quorum size for EC policies defines the minimum number"},{"line_number":594,"context_line":"        of data + parity elements required to be able to guarantee"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_d2ad1d9c","line":591,"range":{"start_line":591,"start_character":12,"end_line":591,"end_character":26},"updated":"2017-02-08 18:01:12.000000000","message":"nit: off-topic: be nice to clarify this as PUT requests","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":588,"context_line":"    def quorum(self):"},{"line_number":589,"context_line":"        \"\"\""},{"line_number":590,"context_line":"        Number of successful backend requests needed for the proxy to consider"},{"line_number":591,"context_line":"        the client request successful."},{"line_number":592,"context_line":""},{"line_number":593,"context_line":"        The quorum size for EC policies defines the minimum number"},{"line_number":594,"context_line":"        of data + parity elements required to be able to guarantee"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_2faa5885","line":591,"range":{"start_line":591,"start_character":12,"end_line":591,"end_character":26},"in_reply_to":"1a430d35_d2ad1d9c","updated":"2017-02-09 09:36:43.000000000","message":"Oh, the quorum of storage_policy is only PUT. I though it could be in best_response but it usually use swift.common.utils.quorum_size.\n\nGood call, done.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":604,"context_line":"        for every erasure coding scheme, consult PyECLib for"},{"line_number":605,"context_line":"        min_parity_fragments_needed()"},{"line_number":606,"context_line":"        \"\"\""},{"line_number":607,"context_line":"        return self._ec_quorum_size"},{"line_number":608,"context_line":""},{"line_number":609,"context_line":"    def load_ring(self, swift_dir):"},{"line_number":610,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_062dbefd","line":607,"updated":"2017-02-08 10:06:42.000000000","message":"I think we should increase by the duplication factor\n\nhttps://gist.github.com/clayg/ac96b102c32e0149f8abcb6fe19ecc59","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":604,"context_line":"        for every erasure coding scheme, consult PyECLib for"},{"line_number":605,"context_line":"        min_parity_fragments_needed()"},{"line_number":606,"context_line":"        \"\"\""},{"line_number":607,"context_line":"        return self._ec_quorum_size"},{"line_number":608,"context_line":""},{"line_number":609,"context_line":"    def load_ring(self, swift_dir):"},{"line_number":610,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_5f6a20b4","line":607,"in_reply_to":"1a430d35_062dbefd","updated":"2017-02-09 09:36:43.000000000","message":"We had discussion in irc and I like that idea to employ bigger quorum size for safe durable so the new version will merge the gist change above.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":604,"context_line":"        for every erasure coding scheme, consult PyECLib for"},{"line_number":605,"context_line":"        min_parity_fragments_needed()"},{"line_number":606,"context_line":"        \"\"\""},{"line_number":607,"context_line":"        return self._ec_quorum_size"},{"line_number":608,"context_line":""},{"line_number":609,"context_line":"    def load_ring(self, swift_dir):"},{"line_number":610,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_72a469b9","line":607,"in_reply_to":"1a430d35_062dbefd","updated":"2017-02-08 18:01:12.000000000","message":"makes sense","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":639,"context_line":"            swift_dir, ring_name\u003dself.ring_name,"},{"line_number":640,"context_line":"            validation_hook\u003dvalidate_ring_data)"},{"line_number":641,"context_line":""},{"line_number":642,"context_line":"    def get_backend_index(self, index):"},{"line_number":643,"context_line":"        \"\"\""},{"line_number":644,"context_line":"        Backend index for PyECLib"},{"line_number":645,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_4537a4fe","line":642,"updated":"2017-02-08 18:01:12.000000000","message":"This seems mis-named - elsewhere in this module backend refers to a storage server so one might expect this method to return a backend server/node index.\n\nwhy would this not be called get_fragment_index?","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":639,"context_line":"            swift_dir, ring_name\u003dself.ring_name,"},{"line_number":640,"context_line":"            validation_hook\u003dvalidate_ring_data)"},{"line_number":641,"context_line":""},{"line_number":642,"context_line":"    def get_backend_index(self, index):"},{"line_number":643,"context_line":"        \"\"\""},{"line_number":644,"context_line":"        Backend index for PyECLib"},{"line_number":645,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_c83f29b2","line":642,"range":{"start_line":642,"start_character":32,"end_line":642,"end_character":37},"updated":"2017-02-08 18:01:12.000000000","message":"nit: for clarity this could be named node_index","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":639,"context_line":"            swift_dir, ring_name\u003dself.ring_name,"},{"line_number":640,"context_line":"            validation_hook\u003dvalidate_ring_data)"},{"line_number":641,"context_line":""},{"line_number":642,"context_line":"    def get_backend_index(self, index):"},{"line_number":643,"context_line":"        \"\"\""},{"line_number":644,"context_line":"        Backend index for PyECLib"},{"line_number":645,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_6f7f0015","line":642,"range":{"start_line":642,"start_character":32,"end_line":642,"end_character":37},"in_reply_to":"1a430d35_c83f29b2","updated":"2017-02-09 09:36:43.000000000","message":"Yes, it\u0027s node_index. Done.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":553,"context_line":""},{"line_number":554,"context_line":"    def __repr__(self):"},{"line_number":555,"context_line":"        extra_info \u003d \u0027\u0027"},{"line_number":556,"context_line":"        if self.ec_duplication_factor !\u003d 1:"},{"line_number":557,"context_line":"            extra_info \u003d \u0027, ec_duplication_factor\u003d%d\u0027 % \\"},{"line_number":558,"context_line":"                self.ec_duplication_factor"},{"line_number":559,"context_line":"        return (\"%s, EC config(ec_type\u003d%s, ec_segment_size\u003d%d, \""}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_be669fea","line":556,"range":{"start_line":556,"start_character":38,"end_line":556,"end_character":42},"updated":"2017-02-26 04:44:21.000000000","message":"nit: no test verifies the condition !\u003d1","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"14e79b02b1701be869c5bc61940f6419465ddbf1","unresolved":false,"context_lines":[{"line_number":627,"context_line":""},{"line_number":628,"context_line":"            configured_fragment_count \u003d len(ring_data._replica2part2dev_id)"},{"line_number":629,"context_line":"            required_fragment_count \u003d \\"},{"line_number":630,"context_line":"                (self.ec_n_unique_fragments) * self.ec_duplication_factor"},{"line_number":631,"context_line":"            if configured_fragment_count !\u003d required_fragment_count:"},{"line_number":632,"context_line":"                raise RingLoadError("},{"line_number":633,"context_line":"                    \u0027EC ring for policy %s needs to be configured with \u0027"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_c459d836","line":630,"updated":"2017-02-24 06:33:58.000000000","message":"nit: the parentheses aren\u0027t really needed","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"17784a067ebf84c421087547a44f4579982c1887","unresolved":false,"context_lines":[{"line_number":627,"context_line":""},{"line_number":628,"context_line":"            configured_fragment_count \u003d len(ring_data._replica2part2dev_id)"},{"line_number":629,"context_line":"            required_fragment_count \u003d \\"},{"line_number":630,"context_line":"                (self.ec_n_unique_fragments) * self.ec_duplication_factor"},{"line_number":631,"context_line":"            if configured_fragment_count !\u003d required_fragment_count:"},{"line_number":632,"context_line":"                raise RingLoadError("},{"line_number":633,"context_line":"                    \u0027EC ring for policy %s needs to be configured with \u0027"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_a0d92759","line":630,"in_reply_to":"da36d5c6_c459d836","updated":"2017-02-24 14:37:56.000000000","message":"In follow-up.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"14e79b02b1701be869c5bc61940f6419465ddbf1","unresolved":false,"context_lines":[{"line_number":639,"context_line":"            swift_dir, ring_name\u003dself.ring_name,"},{"line_number":640,"context_line":"            validation_hook\u003dvalidate_ring_data)"},{"line_number":641,"context_line":""},{"line_number":642,"context_line":"    def get_backend_index(self, node_index):"},{"line_number":643,"context_line":"        \"\"\""},{"line_number":644,"context_line":"        Backend index for PyECLib"},{"line_number":645,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_e4441c4b","line":642,"updated":"2017-02-24 06:33:58.000000000","message":"I still kinda want to see an inverse for this here. get_nodes_for_fragment or something?","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"17784a067ebf84c421087547a44f4579982c1887","unresolved":false,"context_lines":[{"line_number":639,"context_line":"            swift_dir, ring_name\u003dself.ring_name,"},{"line_number":640,"context_line":"            validation_hook\u003dvalidate_ring_data)"},{"line_number":641,"context_line":""},{"line_number":642,"context_line":"    def get_backend_index(self, node_index):"},{"line_number":643,"context_line":"        \"\"\""},{"line_number":644,"context_line":"        Backend index for PyECLib"},{"line_number":645,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_60156fe3","line":642,"in_reply_to":"da36d5c6_e4441c4b","updated":"2017-02-24 14:37:56.000000000","message":"Yup, Alistair also calls that, IIRC. In follow-up.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"}],"swift/common/utils.py":[{"author":{"_account_id":11866,"name":"Naoto Nishizono","email":"nishizono.naoto@po.ntt-tx.co.jp","username":"Naoto_Nishizono"},"change_message_id":"6c11620b9c4627a12186a078247de5cedb3c37fc","unresolved":false,"context_lines":[{"line_number":286,"context_line":"        if value \u003c 1:"},{"line_number":287,"context_line":"            raise ValueError()"},{"line_number":288,"context_line":"    except (TypeError, ValueError):"},{"line_number":289,"context_line":"        raise ValueError(\u0027Config option must be an nutural number\u0027)"},{"line_number":290,"context_line":"    return value"},{"line_number":291,"context_line":""},{"line_number":292,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"da85f559_f6b643db","line":289,"updated":"2015-11-10 04:57:29.000000000","message":"typo: nutural -\u003e natural","commit_id":"99b854a47729924cbfb16ec030d681b752504778"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":345,"context_line":""},{"line_number":346,"context_line":"def config_natural_number_value(value):"},{"line_number":347,"context_line":"    try:"},{"line_number":348,"context_line":"        value \u003d int(value)"},{"line_number":349,"context_line":"        if value \u003c 1:"},{"line_number":350,"context_line":"            raise ValueError()"},{"line_number":351,"context_line":"    except (TypeError, ValueError):"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_520157ae","line":348,"updated":"2017-01-12 00:29:56.000000000","message":"So\n\n config_natural_number_value(1.2) \u003d\u003d 1\n\nbut\n\n config_natural_number_value(\u00271.2\u0027)\n\nraises a ValueError? Seems kinda curious, but OK. I suppose the same is true for config_auto_int_value below.","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ddab6fb5eac38b4b7d145db57826fcd3948ae2c7","unresolved":false,"context_lines":[{"line_number":345,"context_line":""},{"line_number":346,"context_line":"def config_natural_number_value(value):"},{"line_number":347,"context_line":"    try:"},{"line_number":348,"context_line":"        value \u003d int(value)"},{"line_number":349,"context_line":"        if value \u003c 1:"},{"line_number":350,"context_line":"            raise ValueError()"},{"line_number":351,"context_line":"    except (TypeError, ValueError):"}],"source_content_type":"text/x-python","patch_set":43,"id":"7a3c09a3_d04cee78","line":348,"in_reply_to":"ba5201f7_520157ae","updated":"2017-01-13 13:53:40.000000000","message":"Ah, that means if set 1.2 at config, it will be ValueError here. I think it is expected because the error message is \"Config option must be an natural number\" and IMO, we should avoid the silence unexpected behavior with unexpected option value, right?\n\n\nI will add unit test \u00271.2\u0027 case. I don\u0027t have clear answer right now about 1.2 (float) case here. Thinking of risk for a  silence bug, I\u0027d bet we should reject that case but it seems to require more complicated code rather than now...","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":350,"context_line":"            raise ValueError()"},{"line_number":351,"context_line":"    except (TypeError, ValueError):"},{"line_number":352,"context_line":"        raise ValueError(\u0027Config option must be an natural number\u0027)"},{"line_number":353,"context_line":"    return value"},{"line_number":354,"context_line":""},{"line_number":355,"context_line":""},{"line_number":356,"context_line":"def config_auto_int_value(value, default):"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_059241f6","line":353,"updated":"2017-01-17 02:54:44.000000000","message":"nice!","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":343,"context_line":"        (isinstance(value, six.string_types) and value.lower() in TRUE_VALUES)"},{"line_number":344,"context_line":""},{"line_number":345,"context_line":""},{"line_number":346,"context_line":"def config_natural_number_value(value):"},{"line_number":347,"context_line":"    try:"},{"line_number":348,"context_line":"        value \u003d int(value)"},{"line_number":349,"context_line":"        if value \u003c 1:"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_e8bdc502","line":346,"updated":"2017-02-08 18:01:12.000000000","message":"nit: there is confusion over the definition of a natural number - some definitions say it includes zero, others not\n\ncould be\n\n  def config_positive_int_value","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":343,"context_line":"        (isinstance(value, six.string_types) and value.lower() in TRUE_VALUES)"},{"line_number":344,"context_line":""},{"line_number":345,"context_line":""},{"line_number":346,"context_line":"def config_natural_number_value(value):"},{"line_number":347,"context_line":"    try:"},{"line_number":348,"context_line":"        value \u003d int(value)"},{"line_number":349,"context_line":"        if value \u003c 1:"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_8fc8ac56","line":346,"in_reply_to":"1a430d35_e8bdc502","updated":"2017-02-09 09:36:43.000000000","message":"Oh, ok. I didn\u0027t think it includes zero. The suggestion sounds good for this function name. Thanks, done.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":349,"context_line":"        if value \u003c 1:"},{"line_number":350,"context_line":"            raise ValueError()"},{"line_number":351,"context_line":"    except (TypeError, ValueError):"},{"line_number":352,"context_line":"        raise ValueError(\u0027Config option must be an natural number\u0027)"},{"line_number":353,"context_line":"    return value"},{"line_number":354,"context_line":""},{"line_number":355,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_a823bd54","line":352,"updated":"2017-02-08 18:01:12.000000000","message":"nit: at line 368 we include the bad value in the message, could do same here for consistency","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":349,"context_line":"        if value \u003c 1:"},{"line_number":350,"context_line":"            raise ValueError()"},{"line_number":351,"context_line":"    except (TypeError, ValueError):"},{"line_number":352,"context_line":"        raise ValueError(\u0027Config option must be an natural number\u0027)"},{"line_number":353,"context_line":"    return value"},{"line_number":354,"context_line":""},{"line_number":355,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_0f7f5ce0","line":352,"in_reply_to":"1a430d35_a823bd54","updated":"2017-02-09 09:36:43.000000000","message":"Done\n\nAnd add one more assertion for the exception message in unit test.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"}],"swift/obj/reconstructor.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"b9968b76f17797c7543271cffbab4257befb5342","unresolved":false,"context_lines":[{"line_number":260,"context_line":"                continue"},{"line_number":261,"context_line":"            resp.headers \u003d HeaderKeyDict(resp.getheaders())"},{"line_number":262,"context_line":"            if str(fi_to_rebuild) \u003d\u003d \\"},{"line_number":263,"context_line":"                    resp.headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027):"},{"line_number":264,"context_line":"                continue"},{"line_number":265,"context_line":"            if resp.headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027) in set("},{"line_number":266,"context_line":"                    r.headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027)"}],"source_content_type":"text/x-python","patch_set":20,"id":"fad55976_6aefecb0","side":"PARENT","line":263,"updated":"2016-07-15 17:46:04.000000000","message":"I know this code *looks* wonky - but it was being defensive against https://bugs.launchpad.net/swift/+bug/1489546\n\nWe need a better test I think to prevent regression:\n\nhttps://gist.github.com/clayg/0e651d70333154efbf8e288e9d4a22a5\n\nI have found the changed code will fail in this case, and I think this is a bad behavior, because I believe we should be mindful not to remove this defensive coding.","commit_id":"d309a5d14881fd2943f3cc3ca894bdef1e24540d"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7616defbc04f817241dbf883df0b173056b244a","unresolved":false,"context_lines":[{"line_number":260,"context_line":"                continue"},{"line_number":261,"context_line":"            resp.headers \u003d HeaderKeyDict(resp.getheaders())"},{"line_number":262,"context_line":"            if str(fi_to_rebuild) \u003d\u003d \\"},{"line_number":263,"context_line":"                    resp.headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027):"},{"line_number":264,"context_line":"                continue"},{"line_number":265,"context_line":"            if resp.headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027) in set("},{"line_number":266,"context_line":"                    r.headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027)"}],"source_content_type":"text/x-python","patch_set":20,"id":"dada55a8_c5c92d5b","side":"PARENT","line":263,"in_reply_to":"fad55976_6aefecb0","updated":"2016-07-20 12:05:35.000000000","message":"ok, that\u0027s an item we have discussed in a previous comment. I agreed with you we still need to consider the live upgrading and older Swift can talk via such a bad frag index (i mean \u0027None\u0027). Will fix and merge your test change into this commit.","commit_id":"d309a5d14881fd2943f3cc3ca894bdef1e24540d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2ba7bc6218b06841791a14e78044af4ec4fe9962","unresolved":false,"context_lines":[{"line_number":265,"context_line":"                if fi_to_rebuild \u003d\u003d unique_index:"},{"line_number":266,"context_line":"                    # TODO: if fi_to_rebuild \u003d\u003d unique_index, it may be good"},{"line_number":267,"context_line":"                    # that just sending local to remote instead of rebuilding"},{"line_number":268,"context_line":"                    # but for now, skipping to simplify."},{"line_number":269,"context_line":"                    continue"},{"line_number":270,"context_line":"                headers_set \u003d set("},{"line_number":271,"context_line":"                    int(r.headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027))"}],"source_content_type":"text/x-python","patch_set":20,"id":"fad55976_6a2c0cac","line":268,"updated":"2016-07-15 18:53:07.000000000","message":"I believe this TODO is good/appropriate because the suggested change is optimal but non-trivial.  This implementation is most safe.  A change is not required for correctness, and the work is not related to PUT performance of EC Fragment Duplication.  I believe we should consider if this item should be proposed to wishlist item (*not* low-hanging-fruit) or perhaps to Swift/ideas page?","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7616defbc04f817241dbf883df0b173056b244a","unresolved":false,"context_lines":[{"line_number":265,"context_line":"                if fi_to_rebuild \u003d\u003d unique_index:"},{"line_number":266,"context_line":"                    # TODO: if fi_to_rebuild \u003d\u003d unique_index, it may be good"},{"line_number":267,"context_line":"                    # that just sending local to remote instead of rebuilding"},{"line_number":268,"context_line":"                    # but for now, skipping to simplify."},{"line_number":269,"context_line":"                    continue"},{"line_number":270,"context_line":"                headers_set \u003d set("},{"line_number":271,"context_line":"                    int(r.headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027))"}],"source_content_type":"text/x-python","patch_set":20,"id":"dada55a8_85d455bd","line":268,"in_reply_to":"fad55976_6a2c0cac","updated":"2016-07-20 12:05:35.000000000","message":"Yes, I meant this comment is for what we can track the improvement. And it seems good to add to wishlit or wiki page because it may be easier to track.","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2ba7bc6218b06841791a14e78044af4ec4fe9962","unresolved":false,"context_lines":[{"line_number":767,"context_line":"                frag_index\u003dfi,"},{"line_number":768,"context_line":"                suffixes\u003ddata_fi_to_suffixes[fi],"},{"line_number":769,"context_line":"                sync_to\u003d[part_nodes[fi]],"},{"line_number":770,"context_line":"            )"},{"line_number":771,"context_line":"            jobs.append(revert_job)"},{"line_number":772,"context_line":""},{"line_number":773,"context_line":"        # now we need to assign suffixes that have no data fragments"}],"source_content_type":"text/x-python","patch_set":20,"id":"fad55976_25b405f1","line":770,"updated":"2016-07-15 18:53:07.000000000","message":"it is not clear to me that this is still correct?  part_nodes may be 2x longer than maximum frag_index.  I believe many part_nodes can not receive revert.  Perhaps composite ring will ensure revert only to local region if nodes are ordered by local region.","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"b1b1915a25e9720dfd8013dc9853974e560269e1","unresolved":false,"context_lines":[{"line_number":767,"context_line":"                frag_index\u003dfi,"},{"line_number":768,"context_line":"                suffixes\u003ddata_fi_to_suffixes[fi],"},{"line_number":769,"context_line":"                sync_to\u003d[part_nodes[fi]],"},{"line_number":770,"context_line":"            )"},{"line_number":771,"context_line":"            jobs.append(revert_job)"},{"line_number":772,"context_line":""},{"line_number":773,"context_line":"        # now we need to assign suffixes that have no data fragments"}],"source_content_type":"text/x-python","patch_set":20,"id":"dada55a8_a4b684f6","line":770,"in_reply_to":"dada55a8_8c475a76","updated":"2016-07-21 06:50:33.000000000","message":"No, I\u0027m wrong because a handoff node (almost) doesn\u0027t know which group he belongs to. It seems like sync to all nodes which should have the fragments is enough?","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7616defbc04f817241dbf883df0b173056b244a","unresolved":false,"context_lines":[{"line_number":767,"context_line":"                frag_index\u003dfi,"},{"line_number":768,"context_line":"                suffixes\u003ddata_fi_to_suffixes[fi],"},{"line_number":769,"context_line":"                sync_to\u003d[part_nodes[fi]],"},{"line_number":770,"context_line":"            )"},{"line_number":771,"context_line":"            jobs.append(revert_job)"},{"line_number":772,"context_line":""},{"line_number":773,"context_line":"        # now we need to assign suffixes that have no data fragments"}],"source_content_type":"text/x-python","patch_set":20,"id":"dada55a8_8c475a76","line":770,"in_reply_to":"fad55976_25b405f1","updated":"2016-07-20 12:05:35.000000000","message":"Good call. Exactly with current implementation, the revert job heads only for the first subset of part_nodes.\n\nAssuming each subset is controlled in a region with the composite ring, following change could solve the indexing problem, right?\n\n group \u003d node[\u0027index\u0027] // policy.ec_n_unique_fragments\n ni_sync_to \u003d fi + policy.ec_n_unique_fragments * group\n\n sync_to \u003d [part_nodes[ni_sync_to]]","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":270,"context_line":"                try:"},{"line_number":271,"context_line":"                    unique_index \u003d int(frag_index)"},{"line_number":272,"context_line":"                except ValueError:"},{"line_number":273,"context_line":"                    # fragm index may be historically \"None\" string instead"},{"line_number":274,"context_line":"                    # of empty so ignore it as well as empty value"},{"line_number":275,"context_line":"                    continue"},{"line_number":276,"context_line":""}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_52ef97e8","line":273,"range":{"start_line":273,"start_character":22,"end_line":273,"end_character":67},"updated":"2017-01-12 00:29:56.000000000","message":"O_o","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":276,"context_line":""},{"line_number":277,"context_line":"                if fi_to_rebuild \u003d\u003d unique_index:"},{"line_number":278,"context_line":"                    # TODO: if fi_to_rebuild \u003d\u003d unique_index, it may be good"},{"line_number":279,"context_line":"                    # that just sending local to remote instead of rebuilding"},{"line_number":280,"context_line":"                    # but for now, skipping to simplify."},{"line_number":281,"context_line":"                    continue"},{"line_number":282,"context_line":"                headers_set \u003d set("}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_48fa8a44","line":279,"range":{"start_line":279,"start_character":27,"end_line":279,"end_character":55},"updated":"2017-01-12 00:29:56.000000000","message":"Yes, definitely, totally. Good TODO.","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":285,"context_line":"                if unique_index in headers_set:"},{"line_number":286,"context_line":"                    continue"},{"line_number":287,"context_line":"            else:"},{"line_number":288,"context_line":"                continue"},{"line_number":289,"context_line":"            responses.append(resp)"},{"line_number":290,"context_line":"            etag \u003d sorted(responses, reverse\u003dTrue,"},{"line_number":291,"context_line":"                          key\u003dlambda r: Timestamp("}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_087962c8","line":288,"updated":"2017-01-12 00:29:56.000000000","message":"Wait, frag_index could be None? Why didn\u0027t the response include X-Object-Sysmeta-Ec-Frag-Index?","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ddab6fb5eac38b4b7d145db57826fcd3948ae2c7","unresolved":false,"context_lines":[{"line_number":285,"context_line":"                if unique_index in headers_set:"},{"line_number":286,"context_line":"                    continue"},{"line_number":287,"context_line":"            else:"},{"line_number":288,"context_line":"                continue"},{"line_number":289,"context_line":"            responses.append(resp)"},{"line_number":290,"context_line":"            etag \u003d sorted(responses, reverse\u003dTrue,"},{"line_number":291,"context_line":"                          key\u003dlambda r: Timestamp("}],"source_content_type":"text/x-python","patch_set":43,"id":"7a3c09a3_70233a06","line":288,"in_reply_to":"ba5201f7_087962c8","updated":"2017-01-13 13:53:40.000000000","message":"Hah, i thought it\u0027s deleted frag case but the newest master, you know, the resp should be none and it should skip at L266.\n\nLooking at the history, the change there was written after my first patch, and then got merged already.\n\nhttps://github.com/openstack/swift/commit/a63f70c17d392379ec75045a94c38a96878b4c5c","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":782,"context_line":"            nodes_sync_to \u003d []"},{"line_number":783,"context_line":"            for n in range(policy.ec_duplication_factor):"},{"line_number":784,"context_line":"                nodes_sync_to.append("},{"line_number":785,"context_line":"                    part_nodes[fi + policy.ec_n_unique_fragments * n])"},{"line_number":786,"context_line":""},{"line_number":787,"context_line":"            revert_job \u003d build_job("},{"line_number":788,"context_line":"                job_type\u003dREVERT,"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_e8ea5e73","line":785,"updated":"2017-01-12 00:29:56.000000000","message":"Maybe this logic should also hang off StoragePolicy? Like, some get_node_indexes function or something? I think having the transformations between node_index/chunk_index and frag_index centralized would be good.","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":266,"context_line":"                continue"},{"line_number":267,"context_line":"            resp.headers \u003d HeaderKeyDict(resp.getheaders())"},{"line_number":268,"context_line":"            if str(fi_to_rebuild) \u003d\u003d \\"},{"line_number":269,"context_line":"                    resp.headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027):"},{"line_number":270,"context_line":"                continue"},{"line_number":271,"context_line":"            if resp.headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027) in set("},{"line_number":272,"context_line":"                    r.headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027)"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_8510f15a","side":"PARENT","line":269,"updated":"2017-01-17 02:54:44.000000000","message":"man this is miles from obvious :\\\n\nI think using the exceptions is more efficient *and* easier to maintain\n\nkudos","commit_id":"436374e66c21b1ea7974d5c10527e72eca47a738"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":269,"context_line":"            try:"},{"line_number":270,"context_line":"                unique_index \u003d int(frag_index)"},{"line_number":271,"context_line":"            except ValueError:"},{"line_number":272,"context_line":"                # fragm index may be historically \"None\" string instead"},{"line_number":273,"context_line":"                # of empty so ignore it as well as empty value"},{"line_number":274,"context_line":"                continue"},{"line_number":275,"context_line":"            except TypeError:"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_454c499e","line":272,"updated":"2017-01-17 02:54:44.000000000","message":"so this the correct type (string) but not-a-digit error\n\ntypo maybe?  s/fragm index/frag_index","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"efd89ba3beb38a31d211f39027728d5a93359721","unresolved":false,"context_lines":[{"line_number":269,"context_line":"            try:"},{"line_number":270,"context_line":"                unique_index \u003d int(frag_index)"},{"line_number":271,"context_line":"            except ValueError:"},{"line_number":272,"context_line":"                # fragm index may be historically \"None\" string instead"},{"line_number":273,"context_line":"                # of empty so ignore it as well as empty value"},{"line_number":274,"context_line":"                continue"},{"line_number":275,"context_line":"            except TypeError:"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_12b0be89","line":272,"in_reply_to":"7a3c09a3_454c499e","updated":"2017-01-17 10:30:20.000000000","message":"Correct. And my type :\\","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":275,"context_line":"            except TypeError:"},{"line_number":276,"context_line":"                # The successful response should include X-Object-Sysmeta-Ec-"},{"line_number":277,"context_line":"                # Frag-Index but for safety, catching the case missing"},{"line_number":278,"context_line":"                # X-Object-Sysmeta-Ec-Frag-Index and dump warning log for that"},{"line_number":279,"context_line":"                self.logger.warning("},{"line_number":280,"context_line":"                    \u0027Unable to find X-Object-Sysmeta-Ec-Frag-Index header in \u0027"},{"line_number":281,"context_line":"                    \u0027the response in reconstruct_fa\u0027)"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_451a897e","line":278,"updated":"2017-01-17 02:54:44.000000000","message":"so the type error here is because .get returned None - which is the only other type we should get that that would cause int(x) to raise TypeError (i.e. if a test stuck a real integer in the response headers dict it would still work)","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"efd89ba3beb38a31d211f39027728d5a93359721","unresolved":false,"context_lines":[{"line_number":275,"context_line":"            except TypeError:"},{"line_number":276,"context_line":"                # The successful response should include X-Object-Sysmeta-Ec-"},{"line_number":277,"context_line":"                # Frag-Index but for safety, catching the case missing"},{"line_number":278,"context_line":"                # X-Object-Sysmeta-Ec-Frag-Index and dump warning log for that"},{"line_number":279,"context_line":"                self.logger.warning("},{"line_number":280,"context_line":"                    \u0027Unable to find X-Object-Sysmeta-Ec-Frag-Index header in \u0027"},{"line_number":281,"context_line":"                    \u0027the response in reconstruct_fa\u0027)"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_1277ded3","line":278,"in_reply_to":"7a3c09a3_451a897e","updated":"2017-01-17 10:30:20.000000000","message":"Yes.","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":284,"context_line":"            if fi_to_rebuild \u003d\u003d unique_index:"},{"line_number":285,"context_line":"                # TODO: if fi_to_rebuild \u003d\u003d unique_index, it may be good"},{"line_number":286,"context_line":"                # that just sending local to remote instead of rebuilding"},{"line_number":287,"context_line":"                # but for now, skipping to simplify."},{"line_number":288,"context_line":"                continue"},{"line_number":289,"context_line":""},{"line_number":290,"context_line":"            headers_set \u003d set("}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_c86a10b3","line":287,"updated":"2017-01-17 02:54:44.000000000","message":"but unique_index is on *the remote* - oh ... you mean transfer abort this pileup; go ahead and read it in and stream it directly... that\u0027s pretty interesting...\n\nunrelated - we should add a info message here and see how often this happens!?","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":289,"context_line":""},{"line_number":290,"context_line":"            headers_set \u003d set("},{"line_number":291,"context_line":"                int(r.headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027))"},{"line_number":292,"context_line":"                for r in responses)"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"            if unique_index in headers_set:"},{"line_number":295,"context_line":"                continue"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_c8c69099","line":292,"updated":"2017-01-17 02:54:44.000000000","message":"and we that no response get\u0027s added to responses unless it\u0027s frag-index was already validated to be an integer.. we could initialize headers_set as we go and keep it updated when we append responses.","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":291,"context_line":"                int(r.headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027))"},{"line_number":292,"context_line":"                for r in responses)"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"            if unique_index in headers_set:"},{"line_number":295,"context_line":"                continue"},{"line_number":296,"context_line":""},{"line_number":297,"context_line":"            responses.append(resp)"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_c8df7067","line":294,"updated":"2017-01-17 02:54:44.000000000","message":"ok, so everything should be int\u0027s (not strings) here","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":293,"context_line":""},{"line_number":294,"context_line":"            if unique_index in headers_set:"},{"line_number":295,"context_line":"                continue"},{"line_number":296,"context_line":""},{"line_number":297,"context_line":"            responses.append(resp)"},{"line_number":298,"context_line":"            etag \u003d sorted(responses, reverse\u003dTrue,"},{"line_number":299,"context_line":"                          key\u003dlambda r: Timestamp("}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_085418c8","line":296,"updated":"2017-01-17 02:54:44.000000000","message":"Everything here seems functionally equivalent to what\u0027s here already?","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"efd89ba3beb38a31d211f39027728d5a93359721","unresolved":false,"context_lines":[{"line_number":293,"context_line":""},{"line_number":294,"context_line":"            if unique_index in headers_set:"},{"line_number":295,"context_line":"                continue"},{"line_number":296,"context_line":""},{"line_number":297,"context_line":"            responses.append(resp)"},{"line_number":298,"context_line":"            etag \u003d sorted(responses, reverse\u003dTrue,"},{"line_number":299,"context_line":"                          key\u003dlambda r: Timestamp("}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_9506581b","line":296,"in_reply_to":"7a3c09a3_085418c8","updated":"2017-01-17 10:30:20.000000000","message":"Yes, except it asserts with *unique_index*.","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"381bbaf5157aaf99c818b3bab373a9845047ca56","unresolved":false,"context_lines":[{"line_number":275,"context_line":"            etag \u003d sorted(responses, reverse\u003dTrue,"},{"line_number":276,"context_line":"                          key\u003dlambda r: Timestamp("},{"line_number":277,"context_line":"                              r.headers.get(\u0027X-Backend-Timestamp\u0027)"},{"line_number":278,"context_line":"                          ))[0].headers.get(\u0027X-Object-Sysmeta-Ec-Etag\u0027)"},{"line_number":279,"context_line":"            responses \u003d [r for r in responses if"},{"line_number":280,"context_line":"                         r.headers.get(\u0027X-Object-Sysmeta-Ec-Etag\u0027) \u003d\u003d etag]"},{"line_number":281,"context_line":""}],"source_content_type":"text/x-python","patch_set":47,"id":"3a461143_bee48cac","side":"PARENT","line":278,"updated":"2017-02-02 03:14:49.000000000","message":"This is surprisingly optimistic given the level of sophistication in the proxy.  There\u0027s a lot of opportunities for rebuild that are throw out reconstructable frag sets.","commit_id":"3282419a46471e6cf93b8236578e6c695ccc95b8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"381bbaf5157aaf99c818b3bab373a9845047ca56","unresolved":false,"context_lines":[{"line_number":283,"context_line":"            if fi_to_rebuild \u003d\u003d unique_index:"},{"line_number":284,"context_line":"                # TODO: if fi_to_rebuild \u003d\u003d unique_index, it may be good"},{"line_number":285,"context_line":"                # that just sending local to remote instead of rebuilding"},{"line_number":286,"context_line":"                # but for now, skipping to simplify."},{"line_number":287,"context_line":"                continue"},{"line_number":288,"context_line":""},{"line_number":289,"context_line":"            headers_set \u003d set("}],"source_content_type":"text/x-python","patch_set":47,"id":"3a461143_7e53046d","line":286,"updated":"2017-02-02 03:14:49.000000000","message":"I think I didn\u0027t grasp that this will be much more common with duplicated frags on the primaries - this is an important optimization.","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"381bbaf5157aaf99c818b3bab373a9845047ca56","unresolved":false,"context_lines":[{"line_number":773,"context_line":"            # should have the same index fragment each other so the revert"},{"line_number":774,"context_line":"            # job will push the local fragment to all the nodes at once."},{"line_number":775,"context_line":"            # if ec_duplication_factor is 1, nodes_sync_to should equal"},{"line_number":776,"context_line":"            # [part_nodes[fi]]"},{"line_number":777,"context_line":"            nodes_sync_to \u003d []"},{"line_number":778,"context_line":"            for n in range(policy.ec_duplication_factor):"},{"line_number":779,"context_line":"                nodes_sync_to.append("}],"source_content_type":"text/x-python","patch_set":47,"id":"3a461143_59a902df","line":776,"updated":"2017-02-02 03:14:49.000000000","message":"I think this comment could be more clear.  But the implication/behavior is exactly correct - awesome.","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"18f22649c4317c3b5930fc2b2735de04703e6dcc","unresolved":false,"context_lines":[{"line_number":347,"context_line":"                                        job[\u0027policy\u0027]),"},{"line_number":348,"context_line":"                        etag))"},{"line_number":349,"context_line":""},{"line_number":350,"context_line":"            if no_resp_count:"},{"line_number":351,"context_line":"                self.logger.error("},{"line_number":352,"context_line":"                    \u0027Unable to get enough responses (%s/%s) \u0027"},{"line_number":353,"context_line":"                    \u0027to reconstruct %s\u0027 % ("},{"line_number":354,"context_line":"                        no_resp_count, job[\u0027policy\u0027].ec_ndata,"},{"line_number":355,"context_line":"                        self._full_path(node, job[\u0027partition\u0027],"},{"line_number":356,"context_line":"                                        datafile_metadata[\u0027name\u0027],"},{"line_number":357,"context_line":"                                        job[\u0027policy\u0027])))"},{"line_number":358,"context_line":""},{"line_number":359,"context_line":"            raise DiskFileError(\u0027Unable to reconstruct EC archive\u0027)"},{"line_number":360,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"1a430d35_7dacbf35","line":357,"range":{"start_line":350,"start_character":1,"end_line":357,"end_character":56},"updated":"2017-02-06 01:14:26.000000000","message":"I added these block here to resolve regression from [1] at patch set 1.\n\nThe reason to have the regression is Clay was doing to make response buckets (and etag_buckets too) to make the reconstuctor robust and it was able to report the not enough buckets for each etag. However, the change drops reporting about no enough response with errors (i.e. resp \u003d\u003d None from pile) so I added the case code as it can count them and report here.\n\n1: https://review.openstack.org/#/c/427994","commit_id":"ce6807ab6fd33d30d7844546c6261951772eb822"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":209,"context_line":"                                    part, \u0027GET\u0027, path, headers\u003dheaders)"},{"line_number":210,"context_line":"            with Timeout(self.node_timeout):"},{"line_number":211,"context_line":"                resp \u003d conn.getresponse()"},{"line_number":212,"context_line":"                resp.full_path \u003d full_path"},{"line_number":213,"context_line":"            if resp.status not in [HTTP_OK, HTTP_NOT_FOUND]:"},{"line_number":214,"context_line":"                self.logger.warning("},{"line_number":215,"context_line":"                    _(\"Invalid response %(resp)s from %(full_path)s\"),"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_baef9ae7","line":212,"updated":"2017-02-08 10:06:42.000000000","message":"the branches that need this aren\u0027t tests - if you remove it no tests fail","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":209,"context_line":"                                    part, \u0027GET\u0027, path, headers\u003dheaders)"},{"line_number":210,"context_line":"            with Timeout(self.node_timeout):"},{"line_number":211,"context_line":"                resp \u003d conn.getresponse()"},{"line_number":212,"context_line":"                resp.full_path \u003d full_path"},{"line_number":213,"context_line":"            if resp.status not in [HTTP_OK, HTTP_NOT_FOUND]:"},{"line_number":214,"context_line":"                self.logger.warning("},{"line_number":215,"context_line":"                    _(\"Invalid response %(resp)s from %(full_path)s\"),"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_0c504f0a","line":212,"in_reply_to":"1a430d35_baef9ae7","updated":"2017-02-09 09:36:43.000000000","message":"Done, the new test\n\n- test_reconstruct_fa_missing_headers\n\nwill fail because the resp.full_path will be referred by logging for the invalid (missing headers) response.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":220,"context_line":"        except (Exception, Timeout):"},{"line_number":221,"context_line":"            self.logger.exception("},{"line_number":222,"context_line":"                _(\"Trying to GET %(full_path)s\"), {"},{"line_number":223,"context_line":"                    \u0027full_path\u0027: full_path})"},{"line_number":224,"context_line":"        return resp"},{"line_number":225,"context_line":""},{"line_number":226,"context_line":"    def reconstruct_fa(self, job, node, datafile_metadata):"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_1ada6e4c","line":223,"updated":"2017-02-08 10:06:42.000000000","message":"I don\u0027t think these logs messages have existing tests","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":267,"context_line":"        no_resp_count \u003d 0"},{"line_number":268,"context_line":"        for resp in pile:"},{"line_number":269,"context_line":"            if not resp:"},{"line_number":270,"context_line":"                no_resp_count +\u003d 1"},{"line_number":271,"context_line":"                continue"},{"line_number":272,"context_line":"            resp.headers \u003d HeaderKeyDict(resp.getheaders())"},{"line_number":273,"context_line":"            frag_index \u003d resp.headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027)"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_2680fabf","line":270,"updated":"2017-02-08 10:06:42.000000000","message":"no tests fail if I don\u0027t do this","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":267,"context_line":"        no_resp_count \u003d 0"},{"line_number":268,"context_line":"        for resp in pile:"},{"line_number":269,"context_line":"            if not resp:"},{"line_number":270,"context_line":"                no_resp_count +\u003d 1"},{"line_number":271,"context_line":"                continue"},{"line_number":272,"context_line":"            resp.headers \u003d HeaderKeyDict(resp.getheaders())"},{"line_number":273,"context_line":"            frag_index \u003d resp.headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027)"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_2b6187a9","line":270,"in_reply_to":"1a430d35_2680fabf","updated":"2017-02-09 09:36:43.000000000","message":"Done, the new tests,\n\n- test_reconstruct_fa_exceptions_fails\n- test_reconstruct_fa_all_404s_fails\n\nwill fail.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":284,"context_line":"                self.logger.warning("},{"line_number":285,"context_line":"                    \u0027Unable to find X-Object-Sysmeta-Ec-Frag-Index header in \u0027"},{"line_number":286,"context_line":"                    \u0027the response in reconstruct_fa\u0027)"},{"line_number":287,"context_line":"                continue"},{"line_number":288,"context_line":""},{"line_number":289,"context_line":"            if fi_to_rebuild \u003d\u003d unique_index:"},{"line_number":290,"context_line":"                # TODO: With duplicated EC frags it\u0027s not unreasonable to find"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_665da278","line":287,"updated":"2017-02-08 10:06:42.000000000","message":"no tests fail if I continue here","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":284,"context_line":"                self.logger.warning("},{"line_number":285,"context_line":"                    \u0027Unable to find X-Object-Sysmeta-Ec-Frag-Index header in \u0027"},{"line_number":286,"context_line":"                    \u0027the response in reconstruct_fa\u0027)"},{"line_number":287,"context_line":"                continue"},{"line_number":288,"context_line":""},{"line_number":289,"context_line":"            if fi_to_rebuild \u003d\u003d unique_index:"},{"line_number":290,"context_line":"                # TODO: With duplicated EC frags it\u0027s not unreasonable to find"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_cc8f2773","line":287,"in_reply_to":"1a430d35_665da278","updated":"2017-02-09 09:36:43.000000000","message":"if no continue?\n\nthe new test\n\n- test_reconstruct_fa_missing_headers\n\nwill fail (actually got ERROR instead of FAIL) due to no assignment of unique_index variable.\n\nProbably Done.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":297,"context_line":"                    unique_index, fi_to_rebuild, self._full_path("},{"line_number":298,"context_line":"                        node, job[\u0027partition\u0027], datafile_metadata[\u0027name\u0027],"},{"line_number":299,"context_line":"                        job[\u0027policy\u0027]))"},{"line_number":300,"context_line":"                continue"},{"line_number":301,"context_line":""},{"line_number":302,"context_line":"            timestamp \u003d resp.headers.get(\u0027X-Backend-Timestamp\u0027)"},{"line_number":303,"context_line":"            if not timestamp:"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_46e6e6b0","line":300,"updated":"2017-02-08 10:06:42.000000000","message":"no tests fail if I comment this block - fwiw it happens a lot with ec_duplication","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":297,"context_line":"                    unique_index, fi_to_rebuild, self._full_path("},{"line_number":298,"context_line":"                        node, job[\u0027partition\u0027], datafile_metadata[\u0027name\u0027],"},{"line_number":299,"context_line":"                        job[\u0027policy\u0027]))"},{"line_number":300,"context_line":"                continue"},{"line_number":301,"context_line":""},{"line_number":302,"context_line":"            timestamp \u003d resp.headers.get(\u0027X-Backend-Timestamp\u0027)"},{"line_number":303,"context_line":"            if not timestamp:"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_ec29439c","line":300,"in_reply_to":"1a430d35_46e6e6b0","updated":"2017-02-09 09:36:43.000000000","message":"test_reconstruct_fa_finds_itself_does_not_fail will fail if this *if-block* commented out.\n\nWhile I\u0027m writing the test, I\u0027m realizing we don\u0027t have to do \"continue\" here because liberasurecode can return the fragment w/o reconstruction (just return the available fragment).\n\nDamn it!!!\n\nInstead, we will get annoying warning log in syslog :,(\n\nhttps://github.com/openstack/liberasurecode/blob/master/src/erasurecode.c#L870\n\nTo suppress the warning log, I keep the continue in this version. And the new assertion will be appeared at\n\n- test_reconstruct_fa_finds_itself_does_not_fail\n- test_reconstruct_fa_finds_duplicate_does_not_fail\n\nHowever, it will be changed when the TODO thing above finished.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":300,"context_line":"                continue"},{"line_number":301,"context_line":""},{"line_number":302,"context_line":"            timestamp \u003d resp.headers.get(\u0027X-Backend-Timestamp\u0027)"},{"line_number":303,"context_line":"            if not timestamp:"},{"line_number":304,"context_line":"                self.logger.warning("},{"line_number":305,"context_line":"                    \u0027Invalid resp from %s (missing X-Backend-Timestamp)\u0027,"},{"line_number":306,"context_line":"                    resp.full_path)"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_868b6ec2","line":303,"updated":"2017-02-08 10:06:42.000000000","message":"un-tested","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":300,"context_line":"                continue"},{"line_number":301,"context_line":""},{"line_number":302,"context_line":"            timestamp \u003d resp.headers.get(\u0027X-Backend-Timestamp\u0027)"},{"line_number":303,"context_line":"            if not timestamp:"},{"line_number":304,"context_line":"                self.logger.warning("},{"line_number":305,"context_line":"                    \u0027Invalid resp from %s (missing X-Backend-Timestamp)\u0027,"},{"line_number":306,"context_line":"                    resp.full_path)"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_8ce0bf2a","line":303,"in_reply_to":"1a430d35_868b6ec2","updated":"2017-02-09 09:36:43.000000000","message":"Done, the new test\n\n- test_reconstruct_fa_missing_headers\n\nwill fail.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":309,"context_line":"            timestamp \u003d Timestamp(timestamp)"},{"line_number":310,"context_line":""},{"line_number":311,"context_line":"            if unique_index in buckets[timestamp]:"},{"line_number":312,"context_line":"                continue"},{"line_number":313,"context_line":""},{"line_number":314,"context_line":"            etag \u003d resp.headers.get(\u0027X-Object-Sysmeta-Ec-Etag\u0027)"},{"line_number":315,"context_line":"            if not etag:"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_0665be1c","line":312,"updated":"2017-02-08 10:06:42.000000000","message":"no test blow up if I pass here","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":309,"context_line":"            timestamp \u003d Timestamp(timestamp)"},{"line_number":310,"context_line":""},{"line_number":311,"context_line":"            if unique_index in buckets[timestamp]:"},{"line_number":312,"context_line":"                continue"},{"line_number":313,"context_line":""},{"line_number":314,"context_line":"            etag \u003d resp.headers.get(\u0027X-Object-Sysmeta-Ec-Etag\u0027)"},{"line_number":315,"context_line":"            if not etag:"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_e04ce79f","line":312,"in_reply_to":"1a430d35_0665be1c","updated":"2017-02-09 09:36:43.000000000","message":"I\u0027m now looking at this if block with skeptical eyes because the bucket[timestamp] should be dict so the assignment at L328 should keep only one response per unique_index.\n\nThat means something like\n\nexample-1:\n\n if key not in sample_dict:\n    sample_dict[key] \u003d value\n\nvs\n\nexample-2:\n\n  sample_dict[key] \u003d value\n\nHowever, we should remember the value (actually, the body in the response) should be same if the unique_index is same. Exactly, here, they should be from *different response* but either response is fine to us to reconstruct the destination fragment, right?\n\nAnd the branch looks being hard to test (it\u0027s possible  but we need more injections in the testing) because we should assert the node info in the buckets.\n\nSo currently I think we can *just remove* the if condition here. It could have more redundant checks between L314-L326 but I don\u0027t think those situation happens frequently so it seems ok to me, right now.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":312,"context_line":"                continue"},{"line_number":313,"context_line":""},{"line_number":314,"context_line":"            etag \u003d resp.headers.get(\u0027X-Object-Sysmeta-Ec-Etag\u0027)"},{"line_number":315,"context_line":"            if not etag:"},{"line_number":316,"context_line":"                self.logger.warning(\u0027Invalid resp from %s (missing Etag)\u0027,"},{"line_number":317,"context_line":"                                    resp.full_path)"},{"line_number":318,"context_line":"                continue"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_e6535237","line":315,"updated":"2017-02-08 10:06:42.000000000","message":"this condition is not tested","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":312,"context_line":"                continue"},{"line_number":313,"context_line":""},{"line_number":314,"context_line":"            etag \u003d resp.headers.get(\u0027X-Object-Sysmeta-Ec-Etag\u0027)"},{"line_number":315,"context_line":"            if not etag:"},{"line_number":316,"context_line":"                self.logger.warning(\u0027Invalid resp from %s (missing Etag)\u0027,"},{"line_number":317,"context_line":"                                    resp.full_path)"},{"line_number":318,"context_line":"                continue"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_2cd98b57","line":315,"in_reply_to":"1a430d35_e6535237","updated":"2017-02-09 09:36:43.000000000","message":"Done, the new test\n\n- test_reconstruct_fa_missing_headers\n\nwill fail.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":317,"context_line":"                                    resp.full_path)"},{"line_number":318,"context_line":"                continue"},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"            if etag !\u003d etag_buckets.setdefault(timestamp, etag):"},{"line_number":321,"context_line":"                self.logger.error("},{"line_number":322,"context_line":"                    \u0027Mixed Etag (%s) for %s\u0027, \u0027, \u0027.join(["},{"line_number":323,"context_line":"                        etag, etag_buckets[timestamp]]),"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_a624eac4","line":320,"updated":"2017-02-08 10:06:42.000000000","message":"this condition is not tested","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":317,"context_line":"                                    resp.full_path)"},{"line_number":318,"context_line":"                continue"},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"            if etag !\u003d etag_buckets.setdefault(timestamp, etag):"},{"line_number":321,"context_line":"                self.logger.error("},{"line_number":322,"context_line":"                    \u0027Mixed Etag (%s) for %s\u0027, \u0027, \u0027.join(["},{"line_number":323,"context_line":"                        etag, etag_buckets[timestamp]]),"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_59b2124d","line":320,"in_reply_to":"1a430d35_a624eac4","updated":"2017-02-09 09:36:43.000000000","message":"Done, the newer tests\n\n- test_reconstruct_fa_with_mixed_not_enough_etags_fail\n- test_reconstruct_fa_with_mixed_etag_with_same_timestamp\n\nwill fail if we remove this if-block.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":336,"context_line":"            responses \u003d get_responses()"},{"line_number":337,"context_line":"            if responses:"},{"line_number":338,"context_line":"                break"},{"line_number":339,"context_line":"        else:"},{"line_number":340,"context_line":"            for timestamp, resp in sorted(buckets.items()):"},{"line_number":341,"context_line":"                etag \u003d etag_buckets[timestamp]"},{"line_number":342,"context_line":"                self.logger.error("}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_bab79a38","line":339,"updated":"2017-02-08 10:06:42.000000000","message":"I don\u0027t think any of this else branch has any tests on them?\n\ntest_reconstruct_fa_errors_fails seems to at least assert this method will raise a DiskFileError in some conditions - maybe it just needs calls to check the logging?","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":336,"context_line":"            responses \u003d get_responses()"},{"line_number":337,"context_line":"            if responses:"},{"line_number":338,"context_line":"                break"},{"line_number":339,"context_line":"        else:"},{"line_number":340,"context_line":"            for timestamp, resp in sorted(buckets.items()):"},{"line_number":341,"context_line":"                etag \u003d etag_buckets[timestamp]"},{"line_number":342,"context_line":"                self.logger.error("}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_accc9b89","line":339,"in_reply_to":"1a430d35_bab79a38","updated":"2017-02-09 09:36:43.000000000","message":"Done, mostly\n\n- test_reconstruct_fa_with_mixed_not_enough_etags_fail\n- test_reconstruct_fa_exceptions_fails\n- test_reconstruct_fa_all_404s_fails\n\ncover those statements here.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":802,"context_line":"        for node in part_nodes:"},{"line_number":803,"context_line":"            if node[\u0027id\u0027] \u003d\u003d local_dev[\u0027id\u0027]:"},{"line_number":804,"context_line":"                # this partition belongs here, we\u0027ll need a sync job"},{"line_number":805,"context_line":"                frag_index \u003d policy.get_backend_index(node[\u0027index\u0027])"},{"line_number":806,"context_line":"                try:"},{"line_number":807,"context_line":"                    suffixes \u003d data_fi_to_suffixes.pop(frag_index)"},{"line_number":808,"context_line":"                except KeyError:"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_1af0aefd","line":805,"updated":"2017-02-08 10:06:42.000000000","message":"nice","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":811,"context_line":"                    job_type\u003dSYNC,"},{"line_number":812,"context_line":"                    frag_index\u003dfrag_index,"},{"line_number":813,"context_line":"                    suffixes\u003dsuffixes,"},{"line_number":814,"context_line":"                    sync_to\u003d_get_partners(node[\u0027index\u0027], part_nodes),"},{"line_number":815,"context_line":"                )"},{"line_number":816,"context_line":"                # ssync callback to rebuild missing fragment_archives"},{"line_number":817,"context_line":"                sync_job[\u0027sync_diskfile_builder\u0027] \u003d self.reconstruct_fa"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_d4fb4045","line":814,"updated":"2017-02-08 18:01:12.000000000","message":"ok, so no change here, local node syncs to two neighbours. Is there ever a case when a neighbour might be assigned duplicate of same frag index? I don\u0027t think so, because neighbours by definition have this frag index +/- 1","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":811,"context_line":"                    job_type\u003dSYNC,"},{"line_number":812,"context_line":"                    frag_index\u003dfrag_index,"},{"line_number":813,"context_line":"                    suffixes\u003dsuffixes,"},{"line_number":814,"context_line":"                    sync_to\u003d_get_partners(node[\u0027index\u0027], part_nodes),"},{"line_number":815,"context_line":"                )"},{"line_number":816,"context_line":"                # ssync callback to rebuild missing fragment_archives"},{"line_number":817,"context_line":"                sync_job[\u0027sync_diskfile_builder\u0027] \u003d self.reconstruct_fa"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_090e77e4","line":814,"in_reply_to":"1a430d35_d4fb4045","updated":"2017-02-09 09:36:43.000000000","message":"yes, IIF, only ec_k \u003d\u003d 1 case could be the case of same frag_index? And i don\u0027t think we want to do that, please use *replication* instead, right?","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":830,"context_line":"            node_index \u003d fi"},{"line_number":831,"context_line":"            for n in range(policy.ec_duplication_factor):"},{"line_number":832,"context_line":"                nodes_sync_to.append(part_nodes[node_index])"},{"line_number":833,"context_line":"                node_index +\u003d policy.ec_duplication_factor"},{"line_number":834,"context_line":""},{"line_number":835,"context_line":"            revert_job \u003d build_job("},{"line_number":836,"context_line":"                job_type\u003dREVERT,"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_dfe6f942","line":833,"range":{"start_line":833,"start_character":30,"end_line":833,"end_character":58},"updated":"2017-02-08 18:01:12.000000000","message":"Is this correct? I was expecting to see \n\n  node.index + policy.ec_n_unique_fragments\n\nIn the obj controller PUT path chunk_transformer, for a 2+ policy with duplication\u003d2, we assigned frags to nodes as:\n\nnode : 0 1 2 4 5 6\nfrag:  0 1 2 0 1 2\n\nbut here it looks like we map frags to nodes as:\n\nfrag:  0 1 2\nnodes: 0 1 2\n       1 2 3\n\nAlso, no unit test fails if I delete line 833","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":830,"context_line":"            node_index \u003d fi"},{"line_number":831,"context_line":"            for n in range(policy.ec_duplication_factor):"},{"line_number":832,"context_line":"                nodes_sync_to.append(part_nodes[node_index])"},{"line_number":833,"context_line":"                node_index +\u003d policy.ec_duplication_factor"},{"line_number":834,"context_line":""},{"line_number":835,"context_line":"            revert_job \u003d build_job("},{"line_number":836,"context_line":"                job_type\u003dREVERT,"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_fa83e253","line":833,"updated":"2017-02-08 10:06:42.000000000","message":"nice","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"53f6c2a601cbbddc38b2337f29499ba738d94766","unresolved":false,"context_lines":[{"line_number":830,"context_line":"            node_index \u003d fi"},{"line_number":831,"context_line":"            for n in range(policy.ec_duplication_factor):"},{"line_number":832,"context_line":"                nodes_sync_to.append(part_nodes[node_index])"},{"line_number":833,"context_line":"                node_index +\u003d policy.ec_duplication_factor"},{"line_number":834,"context_line":""},{"line_number":835,"context_line":"            revert_job \u003d build_job("},{"line_number":836,"context_line":"                job_type\u003dREVERT,"}],"source_content_type":"text/x-python","patch_set":53,"id":"fa31d9ce_7ed5a441","line":833,"in_reply_to":"1a430d35_6fa1bb93","updated":"2017-02-11 01:41:10.000000000","message":"Kota is right - that was *my* bug - sorry","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":830,"context_line":"            node_index \u003d fi"},{"line_number":831,"context_line":"            for n in range(policy.ec_duplication_factor):"},{"line_number":832,"context_line":"                nodes_sync_to.append(part_nodes[node_index])"},{"line_number":833,"context_line":"                node_index +\u003d policy.ec_duplication_factor"},{"line_number":834,"context_line":""},{"line_number":835,"context_line":"            revert_job \u003d build_job("},{"line_number":836,"context_line":"                job_type\u003dREVERT,"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_6fa1bb93","line":833,"range":{"start_line":833,"start_character":30,"end_line":833,"end_character":58},"in_reply_to":"1a430d35_dfe6f942","updated":"2017-02-09 09:36:43.000000000","message":"OK, good call. I added some assertions on build_jobs of REVERT mode.\n\ndiff --git a/test/unit/obj/test_reconstructor.py b/test/unit/obj/test_reconstructor.py\nindex 85818b3..f0a928b 100644\n--- a/test/unit/obj/test_reconstructor.py\n+++ b/test/unit/obj/test_reconstructor.py\n@@ -1720,8 +1720,15 @@ class TestObjectReconstructor(unittest.TestCase):\n         self.assertEqual(job[\u0027job_type\u0027], object_reconstructor.REVERT)\n         self.assertEqual(job[\u0027frag_index\u0027], frag_index)\n         self.assertEqual(sorted(job[\u0027suffixes\u0027]), sorted(stub_hashes.keys()))\n-        self.assertEqual(len(job[\u0027sync_to\u0027]),\n+        # the sync_to node should be different each other\n+        node_ids \u003d set([node[\u0027id\u0027] for node in job[\u0027sync_to\u0027]])\n+        self.assertEqual(len(node_ids),\n                          self.policy.ec_duplication_factor)\n+        # but all the nodes have same backend index to sync\n+        node_indexes \u003d set(\n+            self.policy.get_backend_index(node[\u0027index\u0027])\n+            for node in job[\u0027sync_to\u0027])\n+        self.assertEqual(1, len(node_indexes))\n         self.assertEqual(job[\u0027sync_to\u0027][0][\u0027index\u0027], frag_index)\n         self.assertEqual(job[\u0027path\u0027], part_path)\n         self.assertEqual(job[\u0027partition\u0027], partition)\n\nExactly, it fails with current version. And older version before I squashed up Clay\u0027s change works so that I had a regression at patch set 48.\n\nI confirmed your suggestion (node_index +\u003d policy.ec_n_unique_fragments) works as well. Probably it\u0027s from the lack of the unit test branch and mistake with ec_duplication_factor and ec_n_unique_fragments.\n\nI fixed this issue as you suggested and add the test above. The test also fail correctly if I delete L833.\n\nDone.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"658ffe4423c301dec86659aed84d8327b3fe41f0","unresolved":false,"context_lines":[{"line_number":830,"context_line":"            node_index \u003d fi"},{"line_number":831,"context_line":"            for n in range(policy.ec_duplication_factor):"},{"line_number":832,"context_line":"                nodes_sync_to.append(part_nodes[node_index])"},{"line_number":833,"context_line":"                node_index +\u003d policy.ec_duplication_factor"},{"line_number":834,"context_line":""},{"line_number":835,"context_line":"            revert_job \u003d build_job("},{"line_number":836,"context_line":"                job_type\u003dREVERT,"}],"source_content_type":"text/x-python","patch_set":53,"id":"fa31d9ce_0f7d42e7","line":833,"in_reply_to":"fa31d9ce_7ed5a441","updated":"2017-02-12 06:57:46.000000000","message":"Done","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"98c3d29ae182f94d6263ae739911b2bdba468318","unresolved":false,"context_lines":[{"line_number":262,"context_line":"        for _node in part_nodes:"},{"line_number":263,"context_line":"            pile.spawn(self._get_response, _node, job[\u0027partition\u0027],"},{"line_number":264,"context_line":"                       path, headers, job[\u0027policy\u0027])"},{"line_number":265,"context_line":"        responses \u003d []"},{"line_number":266,"context_line":"        etag \u003d None"},{"line_number":267,"context_line":"        buckets \u003d defaultdict(dict)"},{"line_number":268,"context_line":"        etag_buckets \u003d {}"},{"line_number":269,"context_line":"        error_resp_count \u003d 0"}],"source_content_type":"text/x-python","patch_set":55,"id":"1a430d35_03e719ad","line":266,"range":{"start_line":265,"start_character":8,"end_line":266,"end_character":19},"updated":"2017-02-09 19:16:08.000000000","message":"nit: responses, etag not used before being redeclared","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"841aa930176b969e98312b66b5482291b8c28d99","unresolved":false,"context_lines":[{"line_number":262,"context_line":"        for _node in part_nodes:"},{"line_number":263,"context_line":"            pile.spawn(self._get_response, _node, job[\u0027partition\u0027],"},{"line_number":264,"context_line":"                       path, headers, job[\u0027policy\u0027])"},{"line_number":265,"context_line":"        responses \u003d []"},{"line_number":266,"context_line":"        etag \u003d None"},{"line_number":267,"context_line":"        buckets \u003d defaultdict(dict)"},{"line_number":268,"context_line":"        etag_buckets \u003d {}"},{"line_number":269,"context_line":"        error_resp_count \u003d 0"}],"source_content_type":"text/x-python","patch_set":55,"id":"fa31d9ce_af78b6f3","line":266,"range":{"start_line":265,"start_character":8,"end_line":266,"end_character":19},"in_reply_to":"1a430d35_03e719ad","updated":"2017-02-12 09:01:32.000000000","message":"Good call, done.","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"98c3d29ae182f94d6263ae739911b2bdba468318","unresolved":false,"context_lines":[{"line_number":278,"context_line":"            except ValueError:"},{"line_number":279,"context_line":"                # fragm index may be historically \"None\" string instead"},{"line_number":280,"context_line":"                # of empty so ignore it as well as empty value"},{"line_number":281,"context_line":"                continue"},{"line_number":282,"context_line":"            except TypeError:"},{"line_number":283,"context_line":"                # The successful response should include X-Object-Sysmeta-Ec-"},{"line_number":284,"context_line":"                # Frag-Index but for safety, catching the case missing"}],"source_content_type":"text/x-python","patch_set":55,"id":"1a430d35_88fb2647","line":281,"updated":"2017-02-09 19:16:08.000000000","message":"nit: I didn\u0027t realise we ever expected \"None\". I\u0027m curious why that isn\u0027t logged as a warning same as None (TypeError)?","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"841aa930176b969e98312b66b5482291b8c28d99","unresolved":false,"context_lines":[{"line_number":278,"context_line":"            except ValueError:"},{"line_number":279,"context_line":"                # fragm index may be historically \"None\" string instead"},{"line_number":280,"context_line":"                # of empty so ignore it as well as empty value"},{"line_number":281,"context_line":"                continue"},{"line_number":282,"context_line":"            except TypeError:"},{"line_number":283,"context_line":"                # The successful response should include X-Object-Sysmeta-Ec-"},{"line_number":284,"context_line":"                # Frag-Index but for safety, catching the case missing"}],"source_content_type":"text/x-python","patch_set":55,"id":"fa31d9ce_4f5e5a77","line":281,"in_reply_to":"1a430d35_88fb2647","updated":"2017-02-12 09:01:32.000000000","message":"I\u0027m getting less sure with the value could be \"None\" string. IIRC(not sure even that, because thi change was at since patc set 18 which is a half year ago), I reffered around the change at a3facce53cac0497edb326a93a97f24e02c603ab, maybe? However, in my current eyes, it doesn\u0027t affect here when gathering the fragments to reconstruct, because it shold fail at PUT even if fag_index is \"None\" so no process will store a fragment with index \"None\".\n\nAnd also, it seems like a bunch of improvements around disk file to prevent an invalid frag index merged. At least, the fragment index in *the file name* should be verified in parse_on_diskfile[1] in the GET path. Not sure on the sysmeta header though, but we have many validation in the PUT path too so it seems safe not to consider the situation \u0027None\u0027 string here.\n\nAnyway, it seems super safe to catch ValueError here if we have invalid (i.e. no string of int) value in the header so  I think it\u0027s better to merge this block to into TypeError to log the warning and no specific historical info but just  adding a commnt like as \u0027catch ValueError for safety if we had invalid fragment index value in the response\u0027.\n\nDoes it make you all sense?\n\n1: https://github.com/openstack/swift/blob/master/swift/obj/diskfile.py#L2993","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"98c3d29ae182f94d6263ae739911b2bdba468318","unresolved":false,"context_lines":[{"line_number":295,"context_line":"                # primary node.  In this case we should stream it directly from"},{"line_number":296,"context_line":"                # the remote node to our target instead of rebuild.  But"},{"line_number":297,"context_line":"                # instead we ignore it."},{"line_number":298,"context_line":"                self.logger.debug("},{"line_number":299,"context_line":"                    \u0027Found existing frag #%s while rebuilding #%s from %s\u0027,"},{"line_number":300,"context_line":"                    unique_index, fi_to_rebuild, self._full_path("},{"line_number":301,"context_line":"                        node, job[\u0027partition\u0027], datafile_metadata[\u0027name\u0027],"}],"source_content_type":"text/x-python","patch_set":55,"id":"1a430d35_c861ae13","line":298,"updated":"2017-02-09 19:16:08.000000000","message":"nit: we now expect this to happen sometimes, so why debug log?","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9f5c9ecefb5c6dd59d9a6ce572de86e61efcc1b0","unresolved":false,"context_lines":[{"line_number":295,"context_line":"                # primary node.  In this case we should stream it directly from"},{"line_number":296,"context_line":"                # the remote node to our target instead of rebuild.  But"},{"line_number":297,"context_line":"                # instead we ignore it."},{"line_number":298,"context_line":"                self.logger.debug("},{"line_number":299,"context_line":"                    \u0027Found existing frag #%s while rebuilding #%s from %s\u0027,"},{"line_number":300,"context_line":"                    unique_index, fi_to_rebuild, self._full_path("},{"line_number":301,"context_line":"                        node, job[\u0027partition\u0027], datafile_metadata[\u0027name\u0027],"}],"source_content_type":"text/x-python","patch_set":55,"id":"fa31d9ce_3bfa5e43","line":298,"in_reply_to":"1a430d35_c861ae13","updated":"2017-02-11 01:40:14.000000000","message":"useful in testing/lab to see how often it comes up on given dataset rebalance - but cheaper than instrumenting a new metric","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"841aa930176b969e98312b66b5482291b8c28d99","unresolved":false,"context_lines":[{"line_number":295,"context_line":"                # primary node.  In this case we should stream it directly from"},{"line_number":296,"context_line":"                # the remote node to our target instead of rebuild.  But"},{"line_number":297,"context_line":"                # instead we ignore it."},{"line_number":298,"context_line":"                self.logger.debug("},{"line_number":299,"context_line":"                    \u0027Found existing frag #%s while rebuilding #%s from %s\u0027,"},{"line_number":300,"context_line":"                    unique_index, fi_to_rebuild, self._full_path("},{"line_number":301,"context_line":"                        node, job[\u0027partition\u0027], datafile_metadata[\u0027name\u0027],"}],"source_content_type":"text/x-python","patch_set":55,"id":"fa31d9ce_f2a1b5aa","line":298,"in_reply_to":"fa31d9ce_3bfa5e43","updated":"2017-02-12 09:01:32.000000000","message":"Agree with Clay and now I added an assertion into test_reconstruct_fa_finds_itself_does_not_fail which will be able to remove if this situation resolved as like \"just send the frag streamingly rather than reconstruction\". So the newer patch set will keep this.","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"98c3d29ae182f94d6263ae739911b2bdba468318","unresolved":false,"context_lines":[{"line_number":317,"context_line":"                continue"},{"line_number":318,"context_line":""},{"line_number":319,"context_line":"            if etag !\u003d etag_buckets.setdefault(timestamp, etag):"},{"line_number":320,"context_line":"                self.logger.error("},{"line_number":321,"context_line":"                    \u0027Mixed Etag (%s) for %s\u0027, \u0027, \u0027.join(["},{"line_number":322,"context_line":"                        etag, etag_buckets[timestamp]]),"},{"line_number":323,"context_line":"                    self._full_path(node, job[\u0027partition\u0027],"}],"source_content_type":"text/x-python","patch_set":55,"id":"1a430d35_43ae81e8","line":320,"updated":"2017-02-09 19:16:08.000000000","message":"nit: hmmm, the proxy obj controller also logs this situation as an error, but in fact we keep trying so I wonder if it should be a warning - we have not definitely failed yet. no need to change, just curious what our strategy is in general for error vs warning.","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"9f5c9ecefb5c6dd59d9a6ce572de86e61efcc1b0","unresolved":false,"context_lines":[{"line_number":317,"context_line":"                continue"},{"line_number":318,"context_line":""},{"line_number":319,"context_line":"            if etag !\u003d etag_buckets.setdefault(timestamp, etag):"},{"line_number":320,"context_line":"                self.logger.error("},{"line_number":321,"context_line":"                    \u0027Mixed Etag (%s) for %s\u0027, \u0027, \u0027.join(["},{"line_number":322,"context_line":"                        etag, etag_buckets[timestamp]]),"},{"line_number":323,"context_line":"                    self._full_path(node, job[\u0027partition\u0027],"}],"source_content_type":"text/x-python","patch_set":55,"id":"fa31d9ce_3b7fbeab","line":320,"in_reply_to":"1a430d35_43ae81e8","updated":"2017-02-11 01:40:14.000000000","message":"warning seems appropriate since the code keeps going - but in general I think our backend services tend to be a bit more liberal with the errors - we\u0027ll \"error could not update such and such\" and then go ahead and try again next cycle.\n\nI know some people monitor error counts from logs - which despite having a bit of a background noise problem - large deltas are strong signal something new is going on.  I wouldn\u0027t imagine people pay the same attention to warnings.  So that may be our guidance.","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"841aa930176b969e98312b66b5482291b8c28d99","unresolved":false,"context_lines":[{"line_number":317,"context_line":"                continue"},{"line_number":318,"context_line":""},{"line_number":319,"context_line":"            if etag !\u003d etag_buckets.setdefault(timestamp, etag):"},{"line_number":320,"context_line":"                self.logger.error("},{"line_number":321,"context_line":"                    \u0027Mixed Etag (%s) for %s\u0027, \u0027, \u0027.join(["},{"line_number":322,"context_line":"                        etag, etag_buckets[timestamp]]),"},{"line_number":323,"context_line":"                    self._full_path(node, job[\u0027partition\u0027],"}],"source_content_type":"text/x-python","patch_set":55,"id":"fa31d9ce_32e8adb4","line":320,"in_reply_to":"fa31d9ce_3b7fbeab","updated":"2017-02-12 09:01:32.000000000","message":"Ok, I leave this as it is with keeping our eyes for errors vs warnings. As Alistair said, currently the proxy obj controller logs it as an error so the error is not so bad for now and the situation (different etag but same timestamp even it\u0027s internal timestamp) should be much rare.","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"98c3d29ae182f94d6263ae739911b2bdba468318","unresolved":false,"context_lines":[{"line_number":319,"context_line":"            if etag !\u003d etag_buckets.setdefault(timestamp, etag):"},{"line_number":320,"context_line":"                self.logger.error("},{"line_number":321,"context_line":"                    \u0027Mixed Etag (%s) for %s\u0027, \u0027, \u0027.join(["},{"line_number":322,"context_line":"                        etag, etag_buckets[timestamp]]),"},{"line_number":323,"context_line":"                    self._full_path(node, job[\u0027partition\u0027],"},{"line_number":324,"context_line":"                                    datafile_metadata[\u0027name\u0027], job[\u0027policy\u0027]))"},{"line_number":325,"context_line":"                continue"}],"source_content_type":"text/x-python","patch_set":55,"id":"1a430d35_2345f516","line":322,"updated":"2017-02-09 19:16:08.000000000","message":"nit: the join seems complicated vs using another %s in the format string\n\n  \u0027Mixed Etag (%s, %s) for %s\u0027, etag, etag_buckets[timestamp], ...","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"841aa930176b969e98312b66b5482291b8c28d99","unresolved":false,"context_lines":[{"line_number":319,"context_line":"            if etag !\u003d etag_buckets.setdefault(timestamp, etag):"},{"line_number":320,"context_line":"                self.logger.error("},{"line_number":321,"context_line":"                    \u0027Mixed Etag (%s) for %s\u0027, \u0027, \u0027.join(["},{"line_number":322,"context_line":"                        etag, etag_buckets[timestamp]]),"},{"line_number":323,"context_line":"                    self._full_path(node, job[\u0027partition\u0027],"},{"line_number":324,"context_line":"                                    datafile_metadata[\u0027name\u0027], job[\u0027policy\u0027]))"},{"line_number":325,"context_line":"                continue"}],"source_content_type":"text/x-python","patch_set":55,"id":"fa31d9ce_52eb61b0","line":322,"in_reply_to":"1a430d35_2345f516","updated":"2017-02-12 09:01:32.000000000","message":"Done","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"98c3d29ae182f94d6263ae739911b2bdba468318","unresolved":false,"context_lines":[{"line_number":324,"context_line":"                                    datafile_metadata[\u0027name\u0027], job[\u0027policy\u0027]))"},{"line_number":325,"context_line":"                continue"},{"line_number":326,"context_line":""},{"line_number":327,"context_line":"            buckets[timestamp][unique_index] \u003d resp"},{"line_number":328,"context_line":""},{"line_number":329,"context_line":"            def get_responses():"},{"line_number":330,"context_line":"                for timestamp, fi2resp in sorted(buckets.items(),"},{"line_number":331,"context_line":"                                                 reverse\u003dTrue):"},{"line_number":332,"context_line":"                    if len(fi2resp) \u003e\u003d job[\u0027policy\u0027].ec_ndata:"},{"line_number":333,"context_line":"                        self.logger.debug("},{"line_number":334,"context_line":"                            \u0027Reconstruct frag #%s with frag indexes %s\u0027"},{"line_number":335,"context_line":"                            % (fi_to_rebuild, list(buckets[timestamp])))"},{"line_number":336,"context_line":"                        return fi2resp.values()"},{"line_number":337,"context_line":""},{"line_number":338,"context_line":"            responses \u003d get_responses()"},{"line_number":339,"context_line":"            if responses:"},{"line_number":340,"context_line":"                break"},{"line_number":341,"context_line":"        else:"},{"line_number":342,"context_line":"            for timestamp, resp in sorted(buckets.items()):"},{"line_number":343,"context_line":"                etag \u003d etag_buckets[timestamp]"}],"source_content_type":"text/x-python","patch_set":55,"id":"1a430d35_7ebdd001","line":340,"range":{"start_line":327,"start_character":12,"end_line":340,"end_character":21},"updated":"2017-02-09 19:16:08.000000000","message":"nit: or, simpler...\n\n              if unique_index not in buckets[timestamp]:\n                buckets[timestamp][unique_index] \u003d resp\n                if len(buckets[timestamp]) \u003e\u003d job[\u0027policy\u0027].ec_ndata:\n                    responses \u003d buckets[timestamp].values()\n                    self.logger.debug(\n                             \u0027Reconstruct frag #%s with frag indexes %s\u0027\n                             % (fi_to_rebuild, list(buckets[timestamp])))\n                    break","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"841aa930176b969e98312b66b5482291b8c28d99","unresolved":false,"context_lines":[{"line_number":324,"context_line":"                                    datafile_metadata[\u0027name\u0027], job[\u0027policy\u0027]))"},{"line_number":325,"context_line":"                continue"},{"line_number":326,"context_line":""},{"line_number":327,"context_line":"            buckets[timestamp][unique_index] \u003d resp"},{"line_number":328,"context_line":""},{"line_number":329,"context_line":"            def get_responses():"},{"line_number":330,"context_line":"                for timestamp, fi2resp in sorted(buckets.items(),"},{"line_number":331,"context_line":"                                                 reverse\u003dTrue):"},{"line_number":332,"context_line":"                    if len(fi2resp) \u003e\u003d job[\u0027policy\u0027].ec_ndata:"},{"line_number":333,"context_line":"                        self.logger.debug("},{"line_number":334,"context_line":"                            \u0027Reconstruct frag #%s with frag indexes %s\u0027"},{"line_number":335,"context_line":"                            % (fi_to_rebuild, list(buckets[timestamp])))"},{"line_number":336,"context_line":"                        return fi2resp.values()"},{"line_number":337,"context_line":""},{"line_number":338,"context_line":"            responses \u003d get_responses()"},{"line_number":339,"context_line":"            if responses:"},{"line_number":340,"context_line":"                break"},{"line_number":341,"context_line":"        else:"},{"line_number":342,"context_line":"            for timestamp, resp in sorted(buckets.items()):"},{"line_number":343,"context_line":"                etag \u003d etag_buckets[timestamp]"}],"source_content_type":"text/x-python","patch_set":55,"id":"fa31d9ce_f260d537","line":340,"range":{"start_line":327,"start_character":12,"end_line":340,"end_character":21},"in_reply_to":"1a430d35_7ebdd001","updated":"2017-02-12 09:01:32.000000000","message":"I like it. Done.","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"98c3d29ae182f94d6263ae739911b2bdba468318","unresolved":false,"context_lines":[{"line_number":341,"context_line":"        else:"},{"line_number":342,"context_line":"            for timestamp, resp in sorted(buckets.items()):"},{"line_number":343,"context_line":"                etag \u003d etag_buckets[timestamp]"},{"line_number":344,"context_line":"                self.logger.error("},{"line_number":345,"context_line":"                    \u0027Unable to get enough responses (%s/%s) \u0027"},{"line_number":346,"context_line":"                    \u0027to reconstruct %s with ETag %s\u0027 % ("},{"line_number":347,"context_line":"                        len(resp), job[\u0027policy\u0027].ec_ndata,"}],"source_content_type":"text/x-python","patch_set":55,"id":"1a430d35_e3668d28","line":344,"updated":"2017-02-09 19:16:08.000000000","message":"ok. here we should use error :)","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"841aa930176b969e98312b66b5482291b8c28d99","unresolved":false,"context_lines":[{"line_number":341,"context_line":"        else:"},{"line_number":342,"context_line":"            for timestamp, resp in sorted(buckets.items()):"},{"line_number":343,"context_line":"                etag \u003d etag_buckets[timestamp]"},{"line_number":344,"context_line":"                self.logger.error("},{"line_number":345,"context_line":"                    \u0027Unable to get enough responses (%s/%s) \u0027"},{"line_number":346,"context_line":"                    \u0027to reconstruct %s with ETag %s\u0027 % ("},{"line_number":347,"context_line":"                        len(resp), job[\u0027policy\u0027].ec_ndata,"}],"source_content_type":"text/x-python","patch_set":55,"id":"fa31d9ce_12648947","line":344,"in_reply_to":"1a430d35_e3668d28","updated":"2017-02-12 09:01:32.000000000","message":":)","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"98c3d29ae182f94d6263ae739911b2bdba468318","unresolved":false,"context_lines":[{"line_number":830,"context_line":"            # that should be holding this frag_index."},{"line_number":831,"context_line":"            nodes_sync_to \u003d []"},{"line_number":832,"context_line":"            node_index \u003d fi"},{"line_number":833,"context_line":"            for n in range(policy.ec_duplication_factor):"},{"line_number":834,"context_line":"                nodes_sync_to.append(part_nodes[node_index])"},{"line_number":835,"context_line":"                node_index +\u003d policy.ec_n_unique_fragments"},{"line_number":836,"context_line":""}],"source_content_type":"text/x-python","patch_set":55,"id":"1a430d35_08349648","line":833,"updated":"2017-02-09 19:16:08.000000000","message":"follow-up: might be useful to have a policy method that is symmetric to get_backend_index i.e. takes a frag index and returns node indexes for that frag index","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"841aa930176b969e98312b66b5482291b8c28d99","unresolved":false,"context_lines":[{"line_number":830,"context_line":"            # that should be holding this frag_index."},{"line_number":831,"context_line":"            nodes_sync_to \u003d []"},{"line_number":832,"context_line":"            node_index \u003d fi"},{"line_number":833,"context_line":"            for n in range(policy.ec_duplication_factor):"},{"line_number":834,"context_line":"                nodes_sync_to.append(part_nodes[node_index])"},{"line_number":835,"context_line":"                node_index +\u003d policy.ec_n_unique_fragments"},{"line_number":836,"context_line":""}],"source_content_type":"text/x-python","patch_set":55,"id":"fa31d9ce_525e0177","line":833,"in_reply_to":"1a430d35_08349648","updated":"2017-02-12 09:01:32.000000000","message":"ok, will do in follow-up","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"98c3d29ae182f94d6263ae739911b2bdba468318","unresolved":false,"context_lines":[{"line_number":832,"context_line":"            node_index \u003d fi"},{"line_number":833,"context_line":"            for n in range(policy.ec_duplication_factor):"},{"line_number":834,"context_line":"                nodes_sync_to.append(part_nodes[node_index])"},{"line_number":835,"context_line":"                node_index +\u003d policy.ec_n_unique_fragments"},{"line_number":836,"context_line":""},{"line_number":837,"context_line":"            revert_job \u003d build_job("},{"line_number":838,"context_line":"                job_type\u003dREVERT,"}],"source_content_type":"text/x-python","patch_set":55,"id":"1a430d35_28eb12b2","line":835,"updated":"2017-02-09 19:16:08.000000000","message":"ok. test now fails if this line regresses:\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\nFAIL: test_build_jobs_handoff (test.unit.obj.test_reconstructor.TestObjectReconstructorECDuplicationFactor)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n  File \"/home/anc/0dev/swift/test/unit/obj/test_reconstructor.py\", line 1731, in test_build_jobs_handoff\n    self.assertEqual(1, len(node_indexes))\nAssertionError: 1 !\u003d 2\n    \u00271 !\u003d 2\u0027 \u003d \u0027%s !\u003d %s\u0027 % (safe_repr(1), safe_repr(2))\n    \u00271 !\u003d 2\u0027 \u003d self._formatMessage(\u00271 !\u003d 2\u0027, \u00271 !\u003d 2\u0027)\n\u003e\u003e  raise self.failureException(\u00271 !\u003d 2\u0027)","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"841aa930176b969e98312b66b5482291b8c28d99","unresolved":false,"context_lines":[{"line_number":832,"context_line":"            node_index \u003d fi"},{"line_number":833,"context_line":"            for n in range(policy.ec_duplication_factor):"},{"line_number":834,"context_line":"                nodes_sync_to.append(part_nodes[node_index])"},{"line_number":835,"context_line":"                node_index +\u003d policy.ec_n_unique_fragments"},{"line_number":836,"context_line":""},{"line_number":837,"context_line":"            revert_job \u003d build_job("},{"line_number":838,"context_line":"                job_type\u003dREVERT,"}],"source_content_type":"text/x-python","patch_set":55,"id":"fa31d9ce_7255c54e","line":835,"in_reply_to":"1a430d35_28eb12b2","updated":"2017-02-12 09:01:32.000000000","message":"Done","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"f19621c2546075b18093736e840a23ea03843566","unresolved":false,"context_lines":[{"line_number":312,"context_line":"                                    resp.full_path)"},{"line_number":313,"context_line":"                continue"},{"line_number":314,"context_line":""},{"line_number":315,"context_line":"            if etag !\u003d etag_buckets.setdefault(timestamp, etag):"},{"line_number":316,"context_line":"                self.logger.error("},{"line_number":317,"context_line":"                    \u0027Mixed Etag (%s, %s) for %s\u0027,"},{"line_number":318,"context_line":"                    etag, etag_buckets[timestamp],"}],"source_content_type":"text/x-python","patch_set":56,"id":"fa31d9ce_4e00fc01","line":315,"updated":"2017-02-13 16:03:31.000000000","message":"Is this trying to test if PUT of a chunk at the same timestamp might have different etags?\n\nBecause dict \"etag_buckets\" is not assigned a value prior to this. And each time we loop through we would have a diff timestamp and this condition would end up being \"if etag !\u003d etag\", correct?","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"244170487a9d30ed4af9ea9c01f5ada21ed69639","unresolved":false,"context_lines":[{"line_number":312,"context_line":"                                    resp.full_path)"},{"line_number":313,"context_line":"                continue"},{"line_number":314,"context_line":""},{"line_number":315,"context_line":"            if etag !\u003d etag_buckets.setdefault(timestamp, etag):"},{"line_number":316,"context_line":"                self.logger.error("},{"line_number":317,"context_line":"                    \u0027Mixed Etag (%s, %s) for %s\u0027,"},{"line_number":318,"context_line":"                    etag, etag_buckets[timestamp],"}],"source_content_type":"text/x-python","patch_set":56,"id":"fa31d9ce_ecfcca73","line":315,"in_reply_to":"fa31d9ce_04bde701","updated":"2017-02-16 05:28:58.000000000","message":"Okay, makes sense.","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"553d8dc2d7136e6b0a934d5989dc9f491f6d6a45","unresolved":false,"context_lines":[{"line_number":312,"context_line":"                                    resp.full_path)"},{"line_number":313,"context_line":"                continue"},{"line_number":314,"context_line":""},{"line_number":315,"context_line":"            if etag !\u003d etag_buckets.setdefault(timestamp, etag):"},{"line_number":316,"context_line":"                self.logger.error("},{"line_number":317,"context_line":"                    \u0027Mixed Etag (%s, %s) for %s\u0027,"},{"line_number":318,"context_line":"                    etag, etag_buckets[timestamp],"}],"source_content_type":"text/x-python","patch_set":56,"id":"fa31d9ce_04bde701","line":315,"in_reply_to":"fa31d9ce_4e00fc01","updated":"2017-02-14 01:34:16.000000000","message":"Correct. Probably you know, it\u0027s a much rare case we could hit. This situation should happen IIF another clients PUT a same object at the *really* same time (it should be same via Timestamp.internal). However, if we allows mixed etag to reconstruct, we will make a new *garbage* because AFAIK pyeclib cannot maintain the original etag. So this should be super safe for reconstruction.","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"f19621c2546075b18093736e840a23ea03843566","unresolved":false,"context_lines":[{"line_number":327,"context_line":"                    self.logger.debug("},{"line_number":328,"context_line":"                        \u0027Reconstruct frag #%s with frag indexes %s\u0027"},{"line_number":329,"context_line":"                        % (fi_to_rebuild, list(buckets[timestamp])))"},{"line_number":330,"context_line":"                    break"},{"line_number":331,"context_line":"        else:"},{"line_number":332,"context_line":"            for timestamp, resp in sorted(buckets.items()):"},{"line_number":333,"context_line":"                etag \u003d etag_buckets[timestamp]"}],"source_content_type":"text/x-python","patch_set":56,"id":"fa31d9ce_844e5394","line":330,"updated":"2017-02-13 16:03:31.000000000","message":"So if we get enough responses from unique_index which are *at least* equivalent to ec_ndata we will rebuild fa. looks good.","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"553d8dc2d7136e6b0a934d5989dc9f491f6d6a45","unresolved":false,"context_lines":[{"line_number":327,"context_line":"                    self.logger.debug("},{"line_number":328,"context_line":"                        \u0027Reconstruct frag #%s with frag indexes %s\u0027"},{"line_number":329,"context_line":"                        % (fi_to_rebuild, list(buckets[timestamp])))"},{"line_number":330,"context_line":"                    break"},{"line_number":331,"context_line":"        else:"},{"line_number":332,"context_line":"            for timestamp, resp in sorted(buckets.items()):"},{"line_number":333,"context_line":"                etag \u003d etag_buckets[timestamp]"}],"source_content_type":"text/x-python","patch_set":56,"id":"fa31d9ce_e44a9325","line":330,"in_reply_to":"fa31d9ce_844e5394","updated":"2017-02-14 01:34:16.000000000","message":"Done","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"f19621c2546075b18093736e840a23ea03843566","unresolved":false,"context_lines":[{"line_number":822,"context_line":"            node_index \u003d fi"},{"line_number":823,"context_line":"            for n in range(policy.ec_duplication_factor):"},{"line_number":824,"context_line":"                nodes_sync_to.append(part_nodes[node_index])"},{"line_number":825,"context_line":"                node_index +\u003d policy.ec_n_unique_fragments"},{"line_number":826,"context_line":""},{"line_number":827,"context_line":"            revert_job \u003d build_job("},{"line_number":828,"context_line":"                job_type\u003dREVERT,"}],"source_content_type":"text/x-python","patch_set":56,"id":"fa31d9ce_bde9b782","line":825,"updated":"2017-02-13 16:03:31.000000000","message":"I think this way \"nodes_sync_to\" will end up with duplicate values?\nIn a 2+1*2 setup:\n\nif my ordered_fis \u003d [[3, 0], [3, 0], [3, 1], [3, 1], [3, 2], [3, 2]]\n\nthen, nodes_sync_to \u003d [0, 3, 0, 3, 1, 4, 1, 4, 2, 5, 2, 5]\n\nIs this correct?","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"244170487a9d30ed4af9ea9c01f5ada21ed69639","unresolved":false,"context_lines":[{"line_number":822,"context_line":"            node_index \u003d fi"},{"line_number":823,"context_line":"            for n in range(policy.ec_duplication_factor):"},{"line_number":824,"context_line":"                nodes_sync_to.append(part_nodes[node_index])"},{"line_number":825,"context_line":"                node_index +\u003d policy.ec_n_unique_fragments"},{"line_number":826,"context_line":""},{"line_number":827,"context_line":"            revert_job \u003d build_job("},{"line_number":828,"context_line":"                job_type\u003dREVERT,"}],"source_content_type":"text/x-python","patch_set":56,"id":"fa31d9ce_acb812c9","line":825,"in_reply_to":"fa31d9ce_640b038f","updated":"2017-02-16 05:28:58.000000000","message":"Kota - Yes, thank you. nodes_sync_to will end up having ec_duplication_factor nodes, your assertion helps in verifying that!\n\nI did a few printfs to check what ordered_fis end up and specifically what are the fis in line#758 and line#766. They fetch frag indexes of current nodes (where we run reconstructor).\nThanks for your explanation on IRC!","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"553d8dc2d7136e6b0a934d5989dc9f491f6d6a45","unresolved":false,"context_lines":[{"line_number":822,"context_line":"            node_index \u003d fi"},{"line_number":823,"context_line":"            for n in range(policy.ec_duplication_factor):"},{"line_number":824,"context_line":"                nodes_sync_to.append(part_nodes[node_index])"},{"line_number":825,"context_line":"                node_index +\u003d policy.ec_n_unique_fragments"},{"line_number":826,"context_line":""},{"line_number":827,"context_line":"            revert_job \u003d build_job("},{"line_number":828,"context_line":"                job_type\u003dREVERT,"}],"source_content_type":"text/x-python","patch_set":56,"id":"fa31d9ce_640b038f","line":825,"in_reply_to":"fa31d9ce_bde9b782","updated":"2017-02-14 01:34:16.000000000","message":"I don\u0027t think it happens but... you hits actually in your env?\n\nFor the code perspective,\n\nL766-L771\n\n  data_frag_indexes \u003d [f for f in fi_hash if f is not None]\n  if not data_frag_indexes:\n      non_data_fragment_suffixes.append(suffix)\n  else:\n      for fi in data_frag_indexes:\n          data_fi_to_suffixes[fi].append(suffix)\n\nat first, the f in fi_hash should be constructed from actual device dir listing so that we should never have node_index here, just frag_index. And then data_fi_to_suffxies is a dict so key should be unique. so data_fi_to_suffixes will be a map from fragment index to suffix list w/o duplication.\n\n\nFor the test perspective:\n\nI add one more assertion as follows but it succeed so that doesn\u0027t make duplicate frag index in the sync_to list.\n\nHowever, if you have another test to reproduce that, it will be super helpful to know what\u0027s different from my current thought.\n\nI will add this assertion in the newest patch.\n\ndiff --git a/test/unit/obj/test_reconstructor.py b/test/unit/obj/test_reconstructor.py\nindex aa742f3..e21cc54 100644\n--- a/test/unit/obj/test_reconstructor.py\n+++ b/test/unit/obj/test_reconstructor.py\n@@ -1720,6 +1720,7 @@ class TestObjectReconstructor(unittest.TestCase):\n         self.assertEqual(job[\u0027job_type\u0027], object_reconstructor.REVERT)\n         self.assertEqual(job[\u0027frag_index\u0027], frag_index)\n         self.assertEqual(sorted(job[\u0027suffixes\u0027]), sorted(stub_hashes.keys()))\n+        self.assertEqual(self.policy.ec_duplication_factor, len(job[\u0027sync_to\u0027]))\n         # the sync_to node should be different each other\n         node_ids \u003d set([node[\u0027id\u0027] for node in job[\u0027sync_to\u0027]])\n         self.assertEqual(len(node_ids),","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":308,"context_line":"                # the remote node to our target instead of rebuild.  But"},{"line_number":309,"context_line":"                # instead we ignore it."},{"line_number":310,"context_line":"                self.logger.debug("},{"line_number":311,"context_line":"                    \u0027Found existing frag #%s while rebuilding #%s from %s\u0027,"},{"line_number":312,"context_line":"                    unique_index, fi_to_rebuild, self._full_path("},{"line_number":313,"context_line":"                        node, job[\u0027partition\u0027], datafile_metadata[\u0027name\u0027],"},{"line_number":314,"context_line":"                        job[\u0027policy\u0027]))"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_e94a1f54","line":311,"updated":"2017-02-26 04:44:21.000000000","message":"nit: not sure about use of \"from\" node path in this log message - node is the node we are rebuildng *to*. was the intent to log the node from which the frag came? in that case probably logging resp.full_path will do the job\n\nnit: also, including fi_to_rebuild and unique_index is redundant, we only log this if they are equal","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":308,"context_line":"                # the remote node to our target instead of rebuild.  But"},{"line_number":309,"context_line":"                # instead we ignore it."},{"line_number":310,"context_line":"                self.logger.debug("},{"line_number":311,"context_line":"                    \u0027Found existing frag #%s while rebuilding #%s from %s\u0027,"},{"line_number":312,"context_line":"                    unique_index, fi_to_rebuild, self._full_path("},{"line_number":313,"context_line":"                        node, job[\u0027partition\u0027], datafile_metadata[\u0027name\u0027],"},{"line_number":314,"context_line":"                        job[\u0027policy\u0027]))"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_8f215eb7","line":311,"in_reply_to":"da36d5c6_e94a1f54","updated":"2017-02-28 09:01:43.000000000","message":"Ah, good call.\n\nBetter message seems like \"Found existing frag #%s while rebuilding to %s\" % (fi_to_rebuild, self.full_path(snip))\n\nWill do.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":315,"context_line":"                continue"},{"line_number":316,"context_line":""},{"line_number":317,"context_line":"            timestamp \u003d resp.headers.get(\u0027X-Backend-Timestamp\u0027)"},{"line_number":318,"context_line":"            if not timestamp:"},{"line_number":319,"context_line":"                self.logger.warning("},{"line_number":320,"context_line":"                    \u0027Invalid resp from %s (missing X-Backend-Timestamp)\u0027,"},{"line_number":321,"context_line":"                    resp.full_path)"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_2429be8a","line":318,"updated":"2017-02-26 04:44:21.000000000","message":"ok, checked for test coverage","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":315,"context_line":"                continue"},{"line_number":316,"context_line":""},{"line_number":317,"context_line":"            timestamp \u003d resp.headers.get(\u0027X-Backend-Timestamp\u0027)"},{"line_number":318,"context_line":"            if not timestamp:"},{"line_number":319,"context_line":"                self.logger.warning("},{"line_number":320,"context_line":"                    \u0027Invalid resp from %s (missing X-Backend-Timestamp)\u0027,"},{"line_number":321,"context_line":"                    resp.full_path)"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_af2e22a3","line":318,"in_reply_to":"da36d5c6_2429be8a","updated":"2017-02-28 09:01:43.000000000","message":"Done","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":323,"context_line":"            timestamp \u003d Timestamp(timestamp)"},{"line_number":324,"context_line":""},{"line_number":325,"context_line":"            etag \u003d resp.headers.get(\u0027X-Object-Sysmeta-Ec-Etag\u0027)"},{"line_number":326,"context_line":"            if not etag:"},{"line_number":327,"context_line":"                self.logger.warning(\u0027Invalid resp from %s (missing Etag)\u0027,"},{"line_number":328,"context_line":"                                    resp.full_path)"},{"line_number":329,"context_line":"                continue"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_641f365b","line":326,"updated":"2017-02-26 04:44:21.000000000","message":"ok, checked for test coverage","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":323,"context_line":"            timestamp \u003d Timestamp(timestamp)"},{"line_number":324,"context_line":""},{"line_number":325,"context_line":"            etag \u003d resp.headers.get(\u0027X-Object-Sysmeta-Ec-Etag\u0027)"},{"line_number":326,"context_line":"            if not etag:"},{"line_number":327,"context_line":"                self.logger.warning(\u0027Invalid resp from %s (missing Etag)\u0027,"},{"line_number":328,"context_line":"                                    resp.full_path)"},{"line_number":329,"context_line":"                continue"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_cf2b5693","line":326,"in_reply_to":"da36d5c6_641f365b","updated":"2017-02-28 09:01:43.000000000","message":"Done","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":330,"context_line":""},{"line_number":331,"context_line":"            if etag !\u003d etag_buckets.setdefault(timestamp, etag):"},{"line_number":332,"context_line":"                self.logger.error("},{"line_number":333,"context_line":"                    \u0027Mixed Etag (%s, %s) for %s\u0027,"},{"line_number":334,"context_line":"                    etag, etag_buckets[timestamp],"},{"line_number":335,"context_line":"                    self._full_path(node, job[\u0027partition\u0027],"},{"line_number":336,"context_line":"                                    datafile_metadata[\u0027name\u0027], job[\u0027policy\u0027]))"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_49508b32","line":333,"updated":"2017-02-26 04:44:21.000000000","message":"ok, checked for test coverage","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":330,"context_line":""},{"line_number":331,"context_line":"            if etag !\u003d etag_buckets.setdefault(timestamp, etag):"},{"line_number":332,"context_line":"                self.logger.error("},{"line_number":333,"context_line":"                    \u0027Mixed Etag (%s, %s) for %s\u0027,"},{"line_number":334,"context_line":"                    etag, etag_buckets[timestamp],"},{"line_number":335,"context_line":"                    self._full_path(node, job[\u0027partition\u0027],"},{"line_number":336,"context_line":"                                    datafile_metadata[\u0027name\u0027], job[\u0027policy\u0027]))"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_0f1c8e76","line":333,"in_reply_to":"da36d5c6_49508b32","updated":"2017-02-28 09:01:43.000000000","message":"Done","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":333,"context_line":"                    \u0027Mixed Etag (%s, %s) for %s\u0027,"},{"line_number":334,"context_line":"                    etag, etag_buckets[timestamp],"},{"line_number":335,"context_line":"                    self._full_path(node, job[\u0027partition\u0027],"},{"line_number":336,"context_line":"                                    datafile_metadata[\u0027name\u0027], job[\u0027policy\u0027]))"},{"line_number":337,"context_line":"                continue"},{"line_number":338,"context_line":""},{"line_number":339,"context_line":"            if unique_index not in buckets[timestamp]:"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_898523d0","line":336,"updated":"2017-02-26 04:44:21.000000000","message":"nit: should this be resp.full_path? IDK, I guess the error is with the bucket, not the individual response.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":333,"context_line":"                    \u0027Mixed Etag (%s, %s) for %s\u0027,"},{"line_number":334,"context_line":"                    etag, etag_buckets[timestamp],"},{"line_number":335,"context_line":"                    self._full_path(node, job[\u0027partition\u0027],"},{"line_number":336,"context_line":"                                    datafile_metadata[\u0027name\u0027], job[\u0027policy\u0027]))"},{"line_number":337,"context_line":"                continue"},{"line_number":338,"context_line":""},{"line_number":339,"context_line":"            if unique_index not in buckets[timestamp]:"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_ca5ee411","line":336,"in_reply_to":"da36d5c6_898523d0","updated":"2017-02-28 09:01:43.000000000","message":"Hmm... I think that \"for\" means something like \"rebuilding to\".\n\nIt might be good to change \"Mixed Etag (%s, %s) found while rebuilding to %s\" % ... ? Not sure.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"}],"swift/proxy/controllers/obj.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2ba7bc6218b06841791a14e78044af4ec4fe9962","unresolved":false,"context_lines":[{"line_number":539,"context_line":"        \"\"\""},{"line_number":540,"context_line":"        Establish connections to storage nodes for PUT request"},{"line_number":541,"context_line":"        \"\"\""},{"line_number":542,"context_line":"        obj_ring \u003d policy.object_ring"},{"line_number":543,"context_line":"        node_iter \u003d GreenthreadSafeIterator("},{"line_number":544,"context_line":"            self.iter_nodes_local_first(obj_ring, partition))"},{"line_number":545,"context_line":"        pile \u003d GreenPile(len(nodes))"}],"source_content_type":"text/x-python","patch_set":20,"id":"fad55976_a006231e","side":"PARENT","line":542,"updated":"2016-07-15 18:53:07.000000000","message":"I believe it is better to get object_ring from policy in iter_nodes_local_first","commit_id":"d309a5d14881fd2943f3cc3ca894bdef1e24540d"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7616defbc04f817241dbf883df0b173056b244a","unresolved":false,"context_lines":[{"line_number":539,"context_line":"        \"\"\""},{"line_number":540,"context_line":"        Establish connections to storage nodes for PUT request"},{"line_number":541,"context_line":"        \"\"\""},{"line_number":542,"context_line":"        obj_ring \u003d policy.object_ring"},{"line_number":543,"context_line":"        node_iter \u003d GreenthreadSafeIterator("},{"line_number":544,"context_line":"            self.iter_nodes_local_first(obj_ring, partition))"},{"line_number":545,"context_line":"        pile \u003d GreenPile(len(nodes))"}],"source_content_type":"text/x-python","patch_set":20,"id":"dada55a8_aa867dd8","side":"PARENT","line":542,"in_reply_to":"fad55976_a006231e","updated":"2016-07-20 12:05:35.000000000","message":"yeah, pass the policy instead of ring. make sense.","commit_id":"d309a5d14881fd2943f3cc3ca894bdef1e24540d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2ba7bc6218b06841791a14e78044af4ec4fe9962","unresolved":false,"context_lines":[{"line_number":1773,"context_line":"                    total_buf_len -\u003d len(piece)"},{"line_number":1774,"context_line":"                chunks_to_encode.append(\u0027\u0027.join(pieces))"},{"line_number":1775,"context_line":""},{"line_number":1776,"context_line":"            frags_by_byte_order \u003d []"},{"line_number":1777,"context_line":"            for chunk_to_encode in chunks_to_encode:"},{"line_number":1778,"context_line":"                frags_by_byte_order.append("},{"line_number":1779,"context_line":"                    policy.pyeclib_driver.encode(chunk_to_encode))"}],"source_content_type":"text/x-python","patch_set":20,"id":"fad55976_9b1d5469","side":"PARENT","line":1776,"updated":"2016-07-15 18:53:07.000000000","message":"maybe if frags are [0, 1, 2] it is correct to call them \"by_byte_order\" but variable name is not so good anymore for [0, 1, 2, 0, 1, 2]","commit_id":"d309a5d14881fd2943f3cc3ca894bdef1e24540d"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7616defbc04f817241dbf883df0b173056b244a","unresolved":false,"context_lines":[{"line_number":1773,"context_line":"                    total_buf_len -\u003d len(piece)"},{"line_number":1774,"context_line":"                chunks_to_encode.append(\u0027\u0027.join(pieces))"},{"line_number":1775,"context_line":""},{"line_number":1776,"context_line":"            frags_by_byte_order \u003d []"},{"line_number":1777,"context_line":"            for chunk_to_encode in chunks_to_encode:"},{"line_number":1778,"context_line":"                frags_by_byte_order.append("},{"line_number":1779,"context_line":"                    policy.pyeclib_driver.encode(chunk_to_encode))"}],"source_content_type":"text/x-python","patch_set":20,"id":"dada55a8_4d61dbd2","side":"PARENT","line":1776,"in_reply_to":"fad55976_9b1d5469","updated":"2016-07-20 12:05:35.000000000","message":"Exactly, do you have a good idea for the new name?\n\njust \u0027frags\u0027 seems shortage...","commit_id":"d309a5d14881fd2943f3cc3ca894bdef1e24540d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2ba7bc6218b06841791a14e78044af4ec4fe9962","unresolved":false,"context_lines":[{"line_number":129,"context_line":"        self.container_name \u003d unquote(container_name)"},{"line_number":130,"context_line":"        self.object_name \u003d unquote(object_name)"},{"line_number":131,"context_line":""},{"line_number":132,"context_line":"    def iter_nodes_local_first(self, ring, partition, policy):"},{"line_number":133,"context_line":"        \"\"\""},{"line_number":134,"context_line":"        This is a hook point for _iter_nodes_local_first to setup"},{"line_number":135,"context_line":"        the policy specific node iterator."}],"source_content_type":"text/x-python","patch_set":20,"id":"fad55976_20123363","line":132,"updated":"2016-07-15 18:53:07.000000000","message":"I believe it is better to pass in policy instead of ring","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7616defbc04f817241dbf883df0b173056b244a","unresolved":false,"context_lines":[{"line_number":129,"context_line":"        self.container_name \u003d unquote(container_name)"},{"line_number":130,"context_line":"        self.object_name \u003d unquote(object_name)"},{"line_number":131,"context_line":""},{"line_number":132,"context_line":"    def iter_nodes_local_first(self, ring, partition, policy):"},{"line_number":133,"context_line":"        \"\"\""},{"line_number":134,"context_line":"        This is a hook point for _iter_nodes_local_first to setup"},{"line_number":135,"context_line":"        the policy specific node iterator."}],"source_content_type":"text/x-python","patch_set":20,"id":"dada55a8_8a1459a0","line":132,"in_reply_to":"fad55976_20123363","updated":"2016-07-20 12:05:35.000000000","message":"ah, just replace ring to policy and use policy.object_ring inside. it seems good idea, will try to do.","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2ba7bc6218b06841791a14e78044af4ec4fe9962","unresolved":false,"context_lines":[{"line_number":1883,"context_line":"                (ResumingGetter, iter)"},{"line_number":1884,"context_line":"        \"\"\""},{"line_number":1885,"context_line":"        all_sources \u003d []"},{"line_number":1886,"context_line":"        frag_indexes \u003d []"},{"line_number":1887,"context_line":"        for frag_index, sources in self.gets.items():"},{"line_number":1888,"context_line":"            if frag_index is None:"},{"line_number":1889,"context_line":"                # bad responses don\u0027t have a frag_index (and fake good"}],"source_content_type":"text/x-python","patch_set":20,"id":"fad55976_1b57a403","line":1886,"updated":"2016-07-15 18:53:07.000000000","message":"perhaps use a set() since this is used for inclusion test","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7616defbc04f817241dbf883df0b173056b244a","unresolved":false,"context_lines":[{"line_number":1883,"context_line":"                (ResumingGetter, iter)"},{"line_number":1884,"context_line":"        \"\"\""},{"line_number":1885,"context_line":"        all_sources \u003d []"},{"line_number":1886,"context_line":"        frag_indexes \u003d []"},{"line_number":1887,"context_line":"        for frag_index, sources in self.gets.items():"},{"line_number":1888,"context_line":"            if frag_index is None:"},{"line_number":1889,"context_line":"                # bad responses don\u0027t have a frag_index (and fake good"}],"source_content_type":"text/x-python","patch_set":20,"id":"dada55a8_2dff47ab","line":1886,"in_reply_to":"fad55976_1b57a403","updated":"2016-07-20 12:05:35.000000000","message":"Done","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2ba7bc6218b06841791a14e78044af4ec4fe9962","unresolved":false,"context_lines":[{"line_number":1890,"context_line":"                # responses from some unit tests)"},{"line_number":1891,"context_line":"                all_sources.extend(sources)"},{"line_number":1892,"context_line":"            else:"},{"line_number":1893,"context_line":"                if frag_index in frag_indexes:"},{"line_number":1894,"context_line":"                    continue"},{"line_number":1895,"context_line":"                frag_indexes.append(frag_index)"},{"line_number":1896,"context_line":"                all_sources.extend(sources[:1])"}],"source_content_type":"text/x-python","patch_set":20,"id":"fad55976_5b68fcba","line":1893,"updated":"2016-07-15 18:53:07.000000000","message":"if frag_indexes is long it\u0027s cheaper to test \"in\" set, set of N\u003c25 maybe it does not matter","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7616defbc04f817241dbf883df0b173056b244a","unresolved":false,"context_lines":[{"line_number":1890,"context_line":"                # responses from some unit tests)"},{"line_number":1891,"context_line":"                all_sources.extend(sources)"},{"line_number":1892,"context_line":"            else:"},{"line_number":1893,"context_line":"                if frag_index in frag_indexes:"},{"line_number":1894,"context_line":"                    continue"},{"line_number":1895,"context_line":"                frag_indexes.append(frag_index)"},{"line_number":1896,"context_line":"                all_sources.extend(sources[:1])"}],"source_content_type":"text/x-python","patch_set":20,"id":"dada55a8_8d2e3341","line":1893,"in_reply_to":"fad55976_5b68fcba","updated":"2016-07-20 12:05:35.000000000","message":"Done","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2ba7bc6218b06841791a14e78044af4ec4fe9962","unresolved":false,"context_lines":[{"line_number":2094,"context_line":""},{"line_number":2095,"context_line":"        def update_frag_index(node):"},{"line_number":2096,"context_line":"            if \u0027index\u0027 in node:"},{"line_number":2097,"context_line":"                node[\u0027frag_index\u0027] \u003d policy.get_backend_index(node[\u0027index\u0027])"},{"line_number":2098,"context_line":"            return node"},{"line_number":2099,"context_line":""},{"line_number":2100,"context_line":"        return itertools.imap(update_frag_index, node_iter)"}],"source_content_type":"text/x-python","patch_set":20,"id":"fad55976_20f3530c","line":2097,"updated":"2016-07-15 18:53:07.000000000","message":"I\u0027m not so sure node as representative of entity in the ring should be decorated with \u0027frag_index\u0027 which is component of encoded ec data.\n\nconcept of index was added to the ring for EC but is generally useful to understand order of primaries in many contexts even if they are shuffled.\n\nI\u0027m considering if it\u0027s more obvious to use policy.get_backend_index(node[\u0027index\u0027]) at call sites who need to use frag_index.","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7616defbc04f817241dbf883df0b173056b244a","unresolved":false,"context_lines":[{"line_number":2094,"context_line":""},{"line_number":2095,"context_line":"        def update_frag_index(node):"},{"line_number":2096,"context_line":"            if \u0027index\u0027 in node:"},{"line_number":2097,"context_line":"                node[\u0027frag_index\u0027] \u003d policy.get_backend_index(node[\u0027index\u0027])"},{"line_number":2098,"context_line":"            return node"},{"line_number":2099,"context_line":""},{"line_number":2100,"context_line":"        return itertools.imap(update_frag_index, node_iter)"}],"source_content_type":"text/x-python","patch_set":20,"id":"dada55a8_7b4f396b","line":2097,"in_reply_to":"fad55976_20f3530c","updated":"2016-07-20 12:05:35.000000000","message":"Good catch, it doesn\u0027t seem to be needed. I might be missing something at early implementation, it was used to check if we have enough \"unique fragments\" because the fragment index *was* same with node index. However, during development, I\u0027ve changed the semantics that X-Object-Sysmeta-Ec-Frag-Index to have the real fragment index and, for now we use ResponseBucket to check the uniqueness. With my quick check to remove this, at least test/unit/proxy/test_server.py and test/unit/proxy/controller/test_obj.py worked well.\n\nI\u0027ll try to get rid of this and probably it makes the code simpler. Thanks!","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"2ba7bc6218b06841791a14e78044af4ec4fe9962","unresolved":false,"context_lines":[{"line_number":2365,"context_line":"        # returns 507, in which case a handoff is used to replace it."},{"line_number":2366,"context_line":""},{"line_number":2367,"context_line":"        # lack_list is a dict of list to keep hole indexes"},{"line_number":2368,"context_line":"        # e.g. if we have 2 holes for index 0 with ec_duplication\u003d2"},{"line_number":2369,"context_line":"        # lack_list is like {0: [0], 1: [0]}, and then, if 1 hole found"},{"line_number":2370,"context_line":"        # for index 1, lack_list will be {0: [0, 1], 1: [0]}."},{"line_number":2371,"context_line":"        # After that, holes will be filled from bigger key"}],"source_content_type":"text/x-python","patch_set":20,"id":"fad55976_fba9f0e0","line":2368,"updated":"2016-07-15 18:53:07.000000000","message":"I believe this should say ec_duplication_factor, if name has changed while you were developing, I tried to grep for other instances of \"ec_duplication\" but I did not see any.","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7616defbc04f817241dbf883df0b173056b244a","unresolved":false,"context_lines":[{"line_number":2365,"context_line":"        # returns 507, in which case a handoff is used to replace it."},{"line_number":2366,"context_line":""},{"line_number":2367,"context_line":"        # lack_list is a dict of list to keep hole indexes"},{"line_number":2368,"context_line":"        # e.g. if we have 2 holes for index 0 with ec_duplication\u003d2"},{"line_number":2369,"context_line":"        # lack_list is like {0: [0], 1: [0]}, and then, if 1 hole found"},{"line_number":2370,"context_line":"        # for index 1, lack_list will be {0: [0, 1], 1: [0]}."},{"line_number":2371,"context_line":"        # After that, holes will be filled from bigger key"}],"source_content_type":"text/x-python","patch_set":20,"id":"dada55a8_8dd2b35a","line":2368,"in_reply_to":"fad55976_fba9f0e0","updated":"2016-07-20 12:05:35.000000000","message":"Done","commit_id":"71909ffcb1bcf0f14dff8d80003d2bf7f842098b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":129,"context_line":"        self.container_name \u003d unquote(container_name)"},{"line_number":130,"context_line":"        self.object_name \u003d unquote(object_name)"},{"line_number":131,"context_line":""},{"line_number":132,"context_line":"    def iter_nodes_local_first(self, policy, partition):"},{"line_number":133,"context_line":"        \"\"\""},{"line_number":134,"context_line":"        Yields nodes for a ring partition."},{"line_number":135,"context_line":""}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_126fcf2b","line":132,"updated":"2017-01-12 00:29:56.000000000","message":"Why\u0027d we change this? We don\u0027t seem to use the policy anywhere else in this function...","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ddab6fb5eac38b4b7d145db57826fcd3948ae2c7","unresolved":false,"context_lines":[{"line_number":129,"context_line":"        self.container_name \u003d unquote(container_name)"},{"line_number":130,"context_line":"        self.object_name \u003d unquote(object_name)"},{"line_number":131,"context_line":""},{"line_number":132,"context_line":"    def iter_nodes_local_first(self, policy, partition):"},{"line_number":133,"context_line":"        \"\"\""},{"line_number":134,"context_line":"        Yields nodes for a ring partition."},{"line_number":135,"context_line":""}],"source_content_type":"text/x-python","patch_set":43,"id":"7a3c09a3_6b098b31","line":132,"in_reply_to":"ba5201f7_126fcf2b","updated":"2017-01-13 13:53:40.000000000","message":"Oops, good catch! Probably it has been remaining the patch this one was depending on [1]. And the patch (probably you know!) was changed in the review process so it\u0027s unnecessary change anymore. Done.\n\n1: https://review.openstack.org/#/c/268993/","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":1803,"context_line":"    if last_bytes:"},{"line_number":1804,"context_line":"        last_frags \u003d policy.pyeclib_driver.encode(last_bytes)"},{"line_number":1805,"context_line":"        send_chunks \u003d last_frags * policy.ec_duplication_factor"},{"line_number":1806,"context_line":"        yield send_chunks"},{"line_number":1807,"context_line":"    else:"},{"line_number":1808,"context_line":"        yield [\u0027\u0027] * nstreams"},{"line_number":1809,"context_line":""}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_722adb91","line":1806,"updated":"2017-01-12 00:29:56.000000000","message":"Maybe just\n\n yield last_frags * policy.ec_duplication_factor\n\n?","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ddab6fb5eac38b4b7d145db57826fcd3948ae2c7","unresolved":false,"context_lines":[{"line_number":1803,"context_line":"    if last_bytes:"},{"line_number":1804,"context_line":"        last_frags \u003d policy.pyeclib_driver.encode(last_bytes)"},{"line_number":1805,"context_line":"        send_chunks \u003d last_frags * policy.ec_duplication_factor"},{"line_number":1806,"context_line":"        yield send_chunks"},{"line_number":1807,"context_line":"    else:"},{"line_number":1808,"context_line":"        yield [\u0027\u0027] * nstreams"},{"line_number":1809,"context_line":""}],"source_content_type":"text/x-python","patch_set":43,"id":"7a3c09a3_d6cf86b1","line":1806,"in_reply_to":"ba5201f7_722adb91","updated":"2017-01-13 13:53:40.000000000","message":"Done","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":1903,"context_line":"            else:"},{"line_number":1904,"context_line":"                if frag_index in frag_indexes:"},{"line_number":1905,"context_line":"                    continue"},{"line_number":1906,"context_line":"                frag_indexes.add(frag_index)"},{"line_number":1907,"context_line":"                all_sources.extend(sources[:1])"},{"line_number":1908,"context_line":"        return all_sources"},{"line_number":1909,"context_line":""}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_2d39d8d7","line":1906,"updated":"2017-01-12 00:29:56.000000000","message":"I thought we already did something like this elsewhere? Like, as a result of https://review.openstack.org/#/c/215276/ ?\n\nI think we don\u0027t need this, since self.gets is a defaultdict -- frag_index should already be unique.","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":2184,"context_line":"            range_specs \u003d self._convert_range(req, policy)"},{"line_number":2185,"context_line":""},{"line_number":2186,"context_line":"        # sorting primaries according to sorting key"},{"line_number":2187,"context_line":"        node_iter.primary_nodes.sort(key\u003dpolicy.sort_key)"},{"line_number":2188,"context_line":""},{"line_number":2189,"context_line":"        safe_iter \u003d GreenthreadSafeIterator(node_iter)"},{"line_number":2190,"context_line":""}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_8d89e428","line":2187,"updated":"2017-01-12 00:29:56.000000000","message":"This seems to assume an awful lot about node_iter\u0027s implementation details :-/","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ddab6fb5eac38b4b7d145db57826fcd3948ae2c7","unresolved":false,"context_lines":[{"line_number":2184,"context_line":"            range_specs \u003d self._convert_range(req, policy)"},{"line_number":2185,"context_line":""},{"line_number":2186,"context_line":"        # sorting primaries according to sorting key"},{"line_number":2187,"context_line":"        node_iter.primary_nodes.sort(key\u003dpolicy.sort_key)"},{"line_number":2188,"context_line":""},{"line_number":2189,"context_line":"        safe_iter \u003d GreenthreadSafeIterator(node_iter)"},{"line_number":2190,"context_line":""}],"source_content_type":"text/x-python","patch_set":43,"id":"7a3c09a3_96209ef9","line":2187,"in_reply_to":"ba5201f7_8d89e428","updated":"2017-01-13 13:53:40.000000000","message":"Ah, if we could refactor the NodeIter itself, it could make it more intuitive.\n\nFor example, make swift.proxy.controller.base.NodeIter can take sort_function args (self.app.sort_nodes in default) and around here, set custom sort nodes function like:\n\n def ec_sort_nodes(primaries):\n   sorted_primaries \u003d self.app.sort_nodes(primaries)\n   # re-sort to make it as subset groups)\n   return sorted(sorted_primaries, key\u003dpolicy.sort_key)\n\nMaybe?\n\nBut i\u0027m feeling it\u0027s extra improvement rather than ec because it requires more changes so I\u0027d be happy to work on that in the future. How do you think of?","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":2215,"context_line":"            # server, causes us to otherwise make endless requests e.g. if an"},{"line_number":2216,"context_line":"            # object server were to ignore frag_prefs and always respond with"},{"line_number":2217,"context_line":"            # a frag that is already in a bucket."},{"line_number":2218,"context_line":"            max_extra_requests \u003d 2 * policy.object_ring.replica_count"},{"line_number":2219,"context_line":""},{"line_number":2220,"context_line":"            for get, parts_iter in pile:"},{"line_number":2221,"context_line":"                if get.last_status is None:"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_0dd33405","line":2218,"updated":"2017-01-12 00:29:56.000000000","message":"This seems like it could turn into a *lot* of extra requests. Are we sure something like\n\n 2 * policy.ec_n_unique_fragments\n\nisn\u0027t be more appropriate? Either way, I\u0027m fairly certain that you\u0027re right to think we don\u0027t want the\n\n (2 * policy.ec_nparity) + policy.ec_ndata\n\nwe have now.","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ddab6fb5eac38b4b7d145db57826fcd3948ae2c7","unresolved":false,"context_lines":[{"line_number":2215,"context_line":"            # server, causes us to otherwise make endless requests e.g. if an"},{"line_number":2216,"context_line":"            # object server were to ignore frag_prefs and always respond with"},{"line_number":2217,"context_line":"            # a frag that is already in a bucket."},{"line_number":2218,"context_line":"            max_extra_requests \u003d 2 * policy.object_ring.replica_count"},{"line_number":2219,"context_line":""},{"line_number":2220,"context_line":"            for get, parts_iter in pile:"},{"line_number":2221,"context_line":"                if get.last_status is None:"}],"source_content_type":"text/x-python","patch_set":43,"id":"7a3c09a3_c66271d8","line":2218,"in_reply_to":"ba5201f7_0dd33405","updated":"2017-01-13 13:53:40.000000000","message":"Hmmm.... I\u0027m not sure right now which number of extra requests should be suitable.\n\nFor the first thought, the older code looks to define the request count as 2 x replica_count, and then to fit the definition, I changed it from ec_nprity + ec_ndata to replica_count.\n\nExactly, replica_count could be 2 x (ec_ndata + ec_nparity) in duplication_factor \u003d\u003d 2 case, though.\n\nIn the next patch set, I will change the value as 2 * ec_n_unique_fragments which allows ec_ndata + 2 * ec_nunique_fragments for all tries. Perhaps, it\u0027s enough.","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":2377,"context_line":"        lack_list \u003d collections.defaultdict(list)"},{"line_number":2378,"context_line":"        for index in range(policy.ec_n_unique_fragments):"},{"line_number":2379,"context_line":"            lack \u003d policy.ec_duplication_factor - \\"},{"line_number":2380,"context_line":"                chunk_index.values().count(index)"},{"line_number":2381,"context_line":"            for lack_tier in range(lack):"},{"line_number":2382,"context_line":"                lack_list[lack_tier].append(index)"},{"line_number":2383,"context_line":""}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_6d8e80d1","line":2380,"range":{"start_line":2380,"start_character":16,"end_line":2380,"end_character":49},"updated":"2017-01-12 00:29:56.000000000","message":"Won\u0027t this always be either zero or one? We haven\u0027t mapped chunk_index to frag_index yet, right?\n\nThat said, the idea behind this seems solid: if we have multiple failures such that frag 0 is missing two copies and frag 1 is missing 1, we should prioritize finding a handoff for frag 0.","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ddab6fb5eac38b4b7d145db57826fcd3948ae2c7","unresolved":false,"context_lines":[{"line_number":2377,"context_line":"        lack_list \u003d collections.defaultdict(list)"},{"line_number":2378,"context_line":"        for index in range(policy.ec_n_unique_fragments):"},{"line_number":2379,"context_line":"            lack \u003d policy.ec_duplication_factor - \\"},{"line_number":2380,"context_line":"                chunk_index.values().count(index)"},{"line_number":2381,"context_line":"            for lack_tier in range(lack):"},{"line_number":2382,"context_line":"                lack_list[lack_tier].append(index)"},{"line_number":2383,"context_line":""}],"source_content_type":"text/x-python","patch_set":43,"id":"7a3c09a3_f2c48441","line":2380,"range":{"start_line":2380,"start_character":16,"end_line":2380,"end_character":49},"in_reply_to":"ba5201f7_6d8e80d1","updated":"2017-01-13 13:53:40.000000000","message":"Ah, yeah, good catch, it looks like buggy code,\n\n        # Grouping all missing fragment indexes for each unique_index\n        unique_index_to_holes \u003d collections.defaultdict(list)\n        available_indexes \u003d chunk_index.values()\n        for node_index in range(policy.object_ring.replica_count):\n            if node_index not in available_indexes:\n                unique_index \u003d policy.get_backend_index(node_index)\n                unique_index_to_holes[unique_index].append(node_index)\n\n        # Set the missing index to lack_tier \n        lack_list \u003d collections.defaultdict(list)\n        for unique_index, holes in unique_index_to_holes.items():\n            for lack_tier, hole_node_index in enumerate(holes):\n                lack_list[lack_tier].append(hole_node_index)\n\n        # Extract the lack_list to a flat list \n        holes \u003d []\n        for lack_tier, indexes in sorted(lack_list.items(), reverse\u003dTrue):\n            holes.extend(indexes)\n\n        # Fill chunk_index list with the hole list \n        for hole, p in zip(holes, handoff_conns):\n            chunk_index[p] \u003d hole\n\nThis could work? I\u0027ll add one more unit test for that. Thanks!","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":1747,"context_line":"                   mime_boundary, multiphase\u003dneed_multiphase)"},{"line_number":1748,"context_line":""},{"line_number":1749,"context_line":""},{"line_number":1750,"context_line":"def chunk_transformer(policy, nstreams):"},{"line_number":1751,"context_line":"    segment_size \u003d policy.ec_segment_size"},{"line_number":1752,"context_line":""},{"line_number":1753,"context_line":"    buf \u003d collections.deque()"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_aaf694f6","line":1750,"updated":"2017-01-17 02:54:44.000000000","message":"this method is the bit that makes the transformed chunks have duplicates","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":1773,"context_line":"                    total_buf_len -\u003d len(piece)"},{"line_number":1774,"context_line":"                chunks_to_encode.append(\u0027\u0027.join(pieces))"},{"line_number":1775,"context_line":""},{"line_number":1776,"context_line":"            frags_by_byte_order \u003d []"},{"line_number":1777,"context_line":"            for chunk_to_encode in chunks_to_encode:"},{"line_number":1778,"context_line":"                encoded_chunks \u003d policy.pyeclib_driver.encode(chunk_to_encode)"},{"line_number":1779,"context_line":"                send_chunks \u003d encoded_chunks * policy.ec_duplication_factor"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_3973e816","line":1776,"updated":"2017-01-17 02:54:44.000000000","message":"I still think this is a not great variable name\n\nhttps://en.wikipedia.org/wiki/Byte_order","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"efd89ba3beb38a31d211f39027728d5a93359721","unresolved":false,"context_lines":[{"line_number":1773,"context_line":"                    total_buf_len -\u003d len(piece)"},{"line_number":1774,"context_line":"                chunks_to_encode.append(\u0027\u0027.join(pieces))"},{"line_number":1775,"context_line":""},{"line_number":1776,"context_line":"            frags_by_byte_order \u003d []"},{"line_number":1777,"context_line":"            for chunk_to_encode in chunks_to_encode:"},{"line_number":1778,"context_line":"                encoded_chunks \u003d policy.pyeclib_driver.encode(chunk_to_encode)"},{"line_number":1779,"context_line":"                send_chunks \u003d encoded_chunks * policy.ec_duplication_factor"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_955498ff","line":1776,"in_reply_to":"7a3c09a3_3973e816","updated":"2017-01-17 10:30:20.000000000","message":"Might be. sort of frags_by_arrival_sequence?\n\nBut it doesn\u0027t seem to relate on this change.","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":1902,"context_line":"            else:"},{"line_number":1903,"context_line":"                if frag_index in frag_indexes:"},{"line_number":1904,"context_line":"                    continue"},{"line_number":1905,"context_line":"                frag_indexes.add(frag_index)"},{"line_number":1906,"context_line":"                all_sources.extend(sources[:1])"},{"line_number":1907,"context_line":"        return all_sources"},{"line_number":1908,"context_line":""}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_f9da40e7","line":1905,"updated":"2017-01-17 02:54:44.000000000","message":"it\u0027s inconceivable to me that all of acoles works on EC get didn\u0027t already address this de-duplication using the frag_preferences control?\n\nI checked out HEAD^ and GET still works?","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"efd89ba3beb38a31d211f39027728d5a93359721","unresolved":false,"context_lines":[{"line_number":1902,"context_line":"            else:"},{"line_number":1903,"context_line":"                if frag_index in frag_indexes:"},{"line_number":1904,"context_line":"                    continue"},{"line_number":1905,"context_line":"                frag_indexes.add(frag_index)"},{"line_number":1906,"context_line":"                all_sources.extend(sources[:1])"},{"line_number":1907,"context_line":"        return all_sources"},{"line_number":1908,"context_line":""}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_75072cca","line":1905,"in_reply_to":"7a3c09a3_f9da40e7","updated":"2017-01-17 10:30:20.000000000","message":"Good catch! You\u0027re true. self.gets is a dict with a key of frag index in response \u0027X-Object-Sysmeta-EC-Frag-Index\u0027 defined at L 1885.\n\nPerhaps, it has been remaining in review process (not sure because we had a lot of changes since the original, exactly  acoles optimistic GET too). And I checked we can remove those additional lines here (it passes all unit tests). I will remove those in the next patch set because it\u0027s redundant work.","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"efd89ba3beb38a31d211f39027728d5a93359721","unresolved":false,"context_lines":[{"line_number":2214,"context_line":"            # server, causes us to otherwise make endless requests e.g. if an"},{"line_number":2215,"context_line":"            # object server were to ignore frag_prefs and always respond with"},{"line_number":2216,"context_line":"            # a frag that is already in a bucket."},{"line_number":2217,"context_line":"            # max_extra_requests \u003d 2 * policy.object_ring.replica_count"},{"line_number":2218,"context_line":"            max_extra_requests \u003d 2 * policy.ec_n_unique_fragments"},{"line_number":2219,"context_line":""},{"line_number":2220,"context_line":"            for get, parts_iter in pile:"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_1595083e","line":2217,"updated":"2017-01-17 10:30:20.000000000","message":"Ah, I forgot to remove my comment out from this patch.","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":2215,"context_line":"            # object server were to ignore frag_prefs and always respond with"},{"line_number":2216,"context_line":"            # a frag that is already in a bucket."},{"line_number":2217,"context_line":"            # max_extra_requests \u003d 2 * policy.object_ring.replica_count"},{"line_number":2218,"context_line":"            max_extra_requests \u003d 2 * policy.ec_n_unique_fragments"},{"line_number":2219,"context_line":""},{"line_number":2220,"context_line":"            for get, parts_iter in pile:"},{"line_number":2221,"context_line":"                if get.last_status is None:"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_6ff03eff","line":2218,"updated":"2017-01-17 02:54:44.000000000","message":"I believe this number is equivalent - but is the value correct?  I think the original code was relying on nparity + ndata \u003d\u003d replicas - with this change should we use unique_frag * duplication \u003d\u003d replicas?\n\nI will consider how we might attempt an audit of the code base where other places may make this assumption?","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"efd89ba3beb38a31d211f39027728d5a93359721","unresolved":false,"context_lines":[{"line_number":2215,"context_line":"            # object server were to ignore frag_prefs and always respond with"},{"line_number":2216,"context_line":"            # a frag that is already in a bucket."},{"line_number":2217,"context_line":"            # max_extra_requests \u003d 2 * policy.object_ring.replica_count"},{"line_number":2218,"context_line":"            max_extra_requests \u003d 2 * policy.ec_n_unique_fragments"},{"line_number":2219,"context_line":""},{"line_number":2220,"context_line":"            for get, parts_iter in pile:"},{"line_number":2221,"context_line":"                if get.last_status is None:"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_f5fa3c74","line":2218,"in_reply_to":"7a3c09a3_6ff03eff","updated":"2017-01-17 10:30:20.000000000","message":"Could you make sure the comment[1] from Tim?\n\nAs you said, I thought the original thought from acoles could be 2 * replica as max_extra_requests so at first, it\u0027s like at L2217. However, I am also feeling it may be too large so that I changed the value with current one. Perhaps,\n\n (1 + policy.ec_duplication_factor) * policy.ec_n_unique_fragments\n\ncould be nice to have?\n\nNot sure.\n\n\n1: https://review.openstack.org/#/c/219165/43/swift/proxy/controllers/obj.py@2218","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":2336,"context_line":"    def _determine_chunk_destinations(self, putters, policy):"},{"line_number":2337,"context_line":"        \"\"\""},{"line_number":2338,"context_line":"        Given a list of putters, return a dict where the key is the putter"},{"line_number":2339,"context_line":"        and the value is the node index to use."},{"line_number":2340,"context_line":""},{"line_number":2341,"context_line":"        This is done so that we line up handoffs using the same node index"},{"line_number":2342,"context_line":"        (in the primary part list) as the primary that the handoff is standing"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_4fd5421a","line":2339,"updated":"2017-01-17 02:54:44.000000000","message":"node index?  or backend frag index?  node index is the primary node order in the ring.  I think this doc string was already conlating terms since it returns putters connected to handoffs and handoffs shouldn\u0027t really have a node index?","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":2344,"context_line":"        preferred local primary nodes when possible."},{"line_number":2345,"context_line":""},{"line_number":2346,"context_line":"        :param putters: a list of swift.proxy.controllers.obj.ECPutter"},{"line_number":2347,"context_line":"                        instance"},{"line_number":2348,"context_line":"        :param policy: A policy instance"},{"line_number":2349,"context_line":"        \"\"\""},{"line_number":2350,"context_line":"        # Give each putter a \"chunk index\": the index of the"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_1992acf6","line":2347,"updated":"2017-01-17 02:54:44.000000000","message":"I don\u0027t think ECPutter still exists","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"efd89ba3beb38a31d211f39027728d5a93359721","unresolved":false,"context_lines":[{"line_number":2344,"context_line":"        preferred local primary nodes when possible."},{"line_number":2345,"context_line":""},{"line_number":2346,"context_line":"        :param putters: a list of swift.proxy.controllers.obj.ECPutter"},{"line_number":2347,"context_line":"                        instance"},{"line_number":2348,"context_line":"        :param policy: A policy instance"},{"line_number":2349,"context_line":"        \"\"\""},{"line_number":2350,"context_line":"        # Give each putter a \"chunk index\": the index of the"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_351f64b8","line":2347,"in_reply_to":"7a3c09a3_1992acf6","updated":"2017-01-17 10:30:20.000000000","message":"Nice catch, MIMEPutter is correct.","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":2395,"context_line":""},{"line_number":2396,"context_line":"        # Fill chunk_index list with the hole list"},{"line_number":2397,"context_line":"        for hole, p in zip(holes, handoff_conns):"},{"line_number":2398,"context_line":"            chunk_index[p] \u003d hole"},{"line_number":2399,"context_line":"        return chunk_index"},{"line_number":2400,"context_line":""},{"line_number":2401,"context_line":"    def _transfer_data(self, req, policy, data_source, putters, nodes,"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_2fff16ab","line":2398,"updated":"2017-01-17 02:54:44.000000000","message":"so each putter just needs a index assigned - and it\u0027s a \"node index\" not a \"frag index\"???\n\nShouldn\u0027t we just let holes get a \"node index\" assigned to them (based off replica count) and then when it\u0027s time modulo that to determine the backend frag index?\n\nI don\u0027t understand what any of this code is doing or why it\u0027s doing it - I ripped it all out [1] and everything still seemed to work\n\n1. https://gist.github.com/clayg/02bba6573a17774d34e69dcdbba825b8","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"efd89ba3beb38a31d211f39027728d5a93359721","unresolved":false,"context_lines":[{"line_number":2395,"context_line":""},{"line_number":2396,"context_line":"        # Fill chunk_index list with the hole list"},{"line_number":2397,"context_line":"        for hole, p in zip(holes, handoff_conns):"},{"line_number":2398,"context_line":"            chunk_index[p] \u003d hole"},{"line_number":2399,"context_line":"        return chunk_index"},{"line_number":2400,"context_line":""},{"line_number":2401,"context_line":"    def _transfer_data(self, req, policy, data_source, putters, nodes,"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_dbe9f1e7","line":2398,"in_reply_to":"7a3c09a3_2fff16ab","updated":"2017-01-17 10:30:20.000000000","message":"The reason [1] still passed is from my fault of the lack of unit test coverage.\n\nFor the case on fragment duplication, I\u0027d like to make the pigeon hole problem to prioritize *unique_fragments which has more missing replicas*.\n\nFor example:\nWe have 4 data, 2 parities and duplication factor 2, we have 12 fragments for the replica ring.\n\nAnd then, if frag 0, 1 and 7 (same unique_index 1) are missing and candidates in handoff (due to sort of connection timeout or disk full) but unfortunately we has only 1 nodes can be assigned to a handoff. At that time, we absolutely want to set either frag 1 or 7 to the handoff because frag 6 (same unique_index with 0) is in its primary already, right?\n\nThe original code,\n\n holes \u003d [x for x in range(len(putters))\n          if x not in chunk_index.values()]\n\nwas flatten the holes from the first index to the latter so that in the case above the handoff node is assigned to frag 0 with the original code.\n\nI\u0027ll add the test case above that original code doesn\u0027t pass but with this change, it passe in my local.","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":2430,"context_line":"                ci \u003d chunk_index[putter]"},{"line_number":2431,"context_line":"                backend_chunk \u003d backend_chunks[ci]"},{"line_number":2432,"context_line":"                if not putter.failed:"},{"line_number":2433,"context_line":"                    chunk_hashers[ci].update(backend_chunk)"},{"line_number":2434,"context_line":"                    putter.send_chunk(backend_chunk)"},{"line_number":2435,"context_line":"                else:"},{"line_number":2436,"context_line":"                    putter.close()"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_cac68099","line":2433,"updated":"2017-01-17 02:54:44.000000000","message":"I don\u0027t love if that we keep an md5 hashes going for all the chunks even though some of them are duplicates - we are often reminded just how expensive these md5\u0027s are","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"efd89ba3beb38a31d211f39027728d5a93359721","unresolved":false,"context_lines":[{"line_number":2430,"context_line":"                ci \u003d chunk_index[putter]"},{"line_number":2431,"context_line":"                backend_chunk \u003d backend_chunks[ci]"},{"line_number":2432,"context_line":"                if not putter.failed:"},{"line_number":2433,"context_line":"                    chunk_hashers[ci].update(backend_chunk)"},{"line_number":2434,"context_line":"                    putter.send_chunk(backend_chunk)"},{"line_number":2435,"context_line":"                else:"},{"line_number":2436,"context_line":"                    putter.close()"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_1bf0d9c8","line":2433,"in_reply_to":"7a3c09a3_cac68099","updated":"2017-01-17 10:30:20.000000000","message":"Perhaps, the duplication could happen here instead of chunk_transform. if chunk_index allows to be set duplicated frag_index instead of node_index.\n\nI will try to make sure the capability, probably I will make it as a separate patch to be clear for the change and then merge it into this if it should be included here.","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":2497,"context_line":"                    # Update any footers set by middleware with EC footers"},{"line_number":2498,"context_line":"                    trail_md \u003d trailing_metadata("},{"line_number":2499,"context_line":"                        policy, etag_hasher,"},{"line_number":2500,"context_line":"                        bytes_transferred, policy.get_backend_index(ci))"},{"line_number":2501,"context_line":"                    trail_md.update(footers)"},{"line_number":2502,"context_line":"                    # Etag footer must always be hash of what we sent"},{"line_number":2503,"context_line":"                    trail_md[\u0027Etag\u0027] \u003d chunk_hashers[ci].hexdigest()"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_aaa854dc","line":2500,"updated":"2017-01-17 02:54:44.000000000","message":"I think this is the important bit here","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"381bbaf5157aaf99c818b3bab373a9845047ca56","unresolved":false,"context_lines":[{"line_number":2179,"context_line":"            range_specs \u003d self._convert_range(req, policy)"},{"line_number":2180,"context_line":""},{"line_number":2181,"context_line":"        # sorting primaries according to sorting key"},{"line_number":2182,"context_line":"        node_iter.primary_nodes.sort(key\u003dpolicy.sort_key)"},{"line_number":2183,"context_line":""},{"line_number":2184,"context_line":"        safe_iter \u003d GreenthreadSafeIterator(node_iter)"},{"line_number":2185,"context_line":""}],"source_content_type":"text/x-python","patch_set":47,"id":"3a461143_39aa7686","line":2182,"updated":"2017-02-02 03:14:49.000000000","message":"I think there is some test coupling in TestECDuplicationObjController that makes request counts line up when we force the sort order of the node_iter to mirror that of a ec_duplication \u003d 1 node_iter - but I don\u0027t think it\u0027s really reasonable to do this.\n\nIt doesn\u0027t make sense to always prefer to service reads from r1.\n\nWe should be honoring affinity sort order for global-ec.\n\nI made 10 requests to the same object uploaded with ec duplication factor 2\n\nWith this line in place my request distribution to disk looks like this:\n\n      7 sdb10\n     10 sdb11\n      7 sdb12\n      6 sdb13\n      4 sdb8\n      6 sdb9\n\nWithout everything still works but distribution is better:\n\n      4 sdb10\n      1 sdb11\n      5 sdb12\n      1 sdb13\n      3 sdb16\n      4 sdb2\n      5 sdb3\n      3 sdb4\n      6 sdb5\n      4 sdb7\n      6 sdb8\n      2 sdb9","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"2671effc57b1f727998acb5e80e3d54c801ba99f","unresolved":false,"context_lines":[{"line_number":2179,"context_line":"            range_specs \u003d self._convert_range(req, policy)"},{"line_number":2180,"context_line":""},{"line_number":2181,"context_line":"        # sorting primaries according to sorting key"},{"line_number":2182,"context_line":"        node_iter.primary_nodes.sort(key\u003dpolicy.sort_key)"},{"line_number":2183,"context_line":""},{"line_number":2184,"context_line":"        safe_iter \u003d GreenthreadSafeIterator(node_iter)"},{"line_number":2185,"context_line":""}],"source_content_type":"text/x-python","patch_set":47,"id":"1a430d35_5d6d7931","line":2182,"in_reply_to":"3a461143_39aa7686","updated":"2017-02-03 10:42:24.000000000","message":"Gah, it\u0027s really good call so as you said, exactly current code will ignore read affinity if the subset nodes assigned to a region. Let me consider to get it fixed.\n\nAh, ok. I found you opinion [1] to remove the sorting until we will get more clear/better way to do this, make sense.\n\n1: https://review.openstack.org/#/c/427994/1/swift/proxy/controllers/obj.py@a2182","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":2205,"context_line":"            # server, causes us to otherwise make endless requests e.g. if an"},{"line_number":2206,"context_line":"            # object server were to ignore frag_prefs and always respond with"},{"line_number":2207,"context_line":"            # a frag that is already in a bucket."},{"line_number":2208,"context_line":"            max_extra_requests \u003d 2 * policy.ec_nparity + policy.ec_ndata"},{"line_number":2209,"context_line":"            for get, parts_iter in pile:"},{"line_number":2210,"context_line":"                if get.last_status is None:"},{"line_number":2211,"context_line":"                    # We may have spawned getters that find the node iterator"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_eb1f7fb4","side":"PARENT","line":2208,"updated":"2017-02-08 18:01:12.000000000","message":"was this a bug? i.e. there is a change from master to the patch e.g. 10+4 gave 18 on master, now we get 28","commit_id":"b1c36dc154061413ecd86d5fb19243a30f107512"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"53f6c2a601cbbddc38b2337f29499ba738d94766","unresolved":false,"context_lines":[{"line_number":2205,"context_line":"            # server, causes us to otherwise make endless requests e.g. if an"},{"line_number":2206,"context_line":"            # object server were to ignore frag_prefs and always respond with"},{"line_number":2207,"context_line":"            # a frag that is already in a bucket."},{"line_number":2208,"context_line":"            max_extra_requests \u003d 2 * policy.ec_nparity + policy.ec_ndata"},{"line_number":2209,"context_line":"            for get, parts_iter in pile:"},{"line_number":2210,"context_line":"                if get.last_status is None:"},{"line_number":2211,"context_line":"                    # We may have spawned getters that find the node iterator"}],"source_content_type":"text/x-python","patch_set":53,"id":"fa31d9ce_717eb5e5","side":"PARENT","line":2208,"in_reply_to":"1a430d35_eb1f7fb4","updated":"2017-02-11 01:41:10.000000000","message":"I assumed it was an order of operations bug and the intent was 2(k+m)\n\nbut, perhaps not - the idea here may have been that ndata was a fixed offset - and the nparity was the scaler :\\\n\nSadly no tests fail on master with this change:\n\n    diff --git a/swift/proxy/controllers/obj.py b/swift/proxy/controllers/obj.py\n    index 000c149..e57174a 100644\n    --- a/swift/proxy/controllers/obj.py\n    +++ b/swift/proxy/controllers/obj.py\n    @@ -2205,7 +2205,7 @@ class ECObjectController(BaseObjectController):\n                 # server, causes us to otherwise make endless requests e.g. if an\n                 # object server were to ignore frag_prefs and always respond with\n                 # a frag that is already in a bucket.\n    -            max_extra_requests \u003d 2 * policy.ec_nparity + policy.ec_ndata\n    +            max_extra_requests \u003d 2 * (policy.ec_nparity + policy.ec_ndata)\n                 for get, parts_iter in pile:\n                     if get.last_status is None:\n                         # We may have spawned getters that find the node iterator\n\n\nSo we\u0027re left only to assume.\n\nHowever given how EC policies already tend to make a lot more backend requests than is maybe needed [1] I\u0027d be more inclined to err on the side of *less*\n\nIf we go as low as:\n\n-            max_extra_requests \u003d 2 * policy.ec_nparity + policy.ec_ndata\n+            max_extra_requests \u003d (policy.ec_nparity + policy.ec_ndata) + 4\n\nTests will still pass - but a couple pop if you down to only 3 (on master)\n\nWith this change - test_GET_with_mixed_frags_and_no_quorum_will_503 (test.unit.proxy.controllers.test_obj.TestECDuplicationObjController) seems to really prefer max_extra_requests as written.\n\n1. https://bugs.launchpad.net/swift/+bug/1663742","commit_id":"b1c36dc154061413ecd86d5fb19243a30f107512"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":2205,"context_line":"            # server, causes us to otherwise make endless requests e.g. if an"},{"line_number":2206,"context_line":"            # object server were to ignore frag_prefs and always respond with"},{"line_number":2207,"context_line":"            # a frag that is already in a bucket."},{"line_number":2208,"context_line":"            max_extra_requests \u003d 2 * policy.ec_nparity + policy.ec_ndata"},{"line_number":2209,"context_line":"            for get, parts_iter in pile:"},{"line_number":2210,"context_line":"                if get.last_status is None:"},{"line_number":2211,"context_line":"                    # We may have spawned getters that find the node iterator"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_aa4ab652","side":"PARENT","line":2208,"in_reply_to":"1a430d35_eb1f7fb4","updated":"2017-02-09 09:36:43.000000000","message":"Which test (or situation), do you think of as a bug?\n\nAh, you\u0027re saying a bug *at master*. Hmm... i have no idea for now.\n\nHowever, you may know, we have a couple of limitation for the tries to get backend connection, one is here, max_extra_requests and the other is *request_count* for node iterator.\n\nCurrently, it could cause odd result but I sometimes tried to look at which limitation has come prior to the other.\n\nIf the node iterator consumes the rest of nodes in the ResumingGetter in _fragment_GET_request method (e.g. got Timeout in _make_request), the limitation could be larger than max_extra_requests.\n\nIt\u0027s really confuse-able and we will get frustrated with it, so that, my suggestion is, that\u0027s nice to have how to limit/control the backend requests with the couple of different limiter at *PTG*.","commit_id":"b1c36dc154061413ecd86d5fb19243a30f107512"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"658ffe4423c301dec86659aed84d8327b3fe41f0","unresolved":false,"context_lines":[{"line_number":2205,"context_line":"            # server, causes us to otherwise make endless requests e.g. if an"},{"line_number":2206,"context_line":"            # object server were to ignore frag_prefs and always respond with"},{"line_number":2207,"context_line":"            # a frag that is already in a bucket."},{"line_number":2208,"context_line":"            max_extra_requests \u003d 2 * policy.ec_nparity + policy.ec_ndata"},{"line_number":2209,"context_line":"            for get, parts_iter in pile:"},{"line_number":2210,"context_line":"                if get.last_status is None:"},{"line_number":2211,"context_line":"                    # We may have spawned getters that find the node iterator"}],"source_content_type":"text/x-python","patch_set":53,"id":"fa31d9ce_efbaaee0","side":"PARENT","line":2208,"in_reply_to":"fa31d9ce_717eb5e5","updated":"2017-02-12 06:57:46.000000000","message":"OIC, I finally get what Alistair says and it makes me sense, it *was* intended to 2 * replicas and it\u0027s from the total of \"the first spawn (ec_k) + max_extra_requests\".\n\nThe change was from my mis-understanding/confising on that and I *thought* max_extra_requests is either  ec_n_unique_fragments * 2 or replicas * 2 but both are wrong. The older code was intended, (ec_n_parity * 2) + ec_ndata which will be 2 * replicas with including the first ec_k spawns so I think Clay is correct.\n\n\nAnd the requests should be limited by either that one or request_node_counts in NodeIter. In my sense, I didn\u0027t intend to change that with this patch, so I\u0027ll change the limit as \"(policy.object_ring.replica_count * 2 ) - policy.ec_ndata\". It seems to fit both of the cases w/, w/o ec_duplication.\n\n\nOTOH, the clay\u0027s idea seems important too. Exactly, it may be too many requests to give up with ec duplication and no tests failed in TestECObjController (not duplication) even if the number was changed probably we can consider/add more tests for that in follow up.","commit_id":"b1c36dc154061413ecd86d5fb19243a30f107512"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":2355,"context_line":"                 if x not in chunk_index.values()]"},{"line_number":2356,"context_line":""},{"line_number":2357,"context_line":"        for hole, p in zip(holes, handoff_conns):"},{"line_number":2358,"context_line":"            chunk_index[p] \u003d hole"},{"line_number":2359,"context_line":"        return chunk_index"},{"line_number":2360,"context_line":""},{"line_number":2361,"context_line":"    def _transfer_data(self, req, policy, data_source, putters, nodes,"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_86744e68","side":"PARENT","line":2358,"updated":"2017-02-08 10:06:42.000000000","message":"I struggled *a lot* to understand lack list - it only comes into play when you run out of node_iter - given a set of primary holes - and not enough handoffs to put them on - how do you choose *which* frag_indexes to assign to your handoffs.\n\nConsider a 4+2x2 - if you happen to hit failures on node 3 and 9,10 - and only pull two handoffs - you would in the ideal assign backend frag indexes #3 and #4 - and *not* node index 3 \u0026 9 (both frag index #3)\n\nin practice https://gist.github.com/clayg/36c87fc8fdb07bff70f7160828725e95\n\nWith half my cluster down I was missing half my primaries and could only pull two handoffs. #1, #2, #3 \u0026 #5 were represented on primaries - the best frag indexes for handoffs were #0 and #4.\n\nWithout frag list handoffs I got #0 and #3 (a duplicate)","commit_id":"b1c36dc154061413ecd86d5fb19243a30f107512"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":1776,"context_line":"            frags_by_byte_order \u003d []"},{"line_number":1777,"context_line":"            for chunk_to_encode in chunks_to_encode:"},{"line_number":1778,"context_line":"                encoded_chunks \u003d policy.pyeclib_driver.encode(chunk_to_encode)"},{"line_number":1779,"context_line":"                send_chunks \u003d encoded_chunks * policy.ec_duplication_factor"},{"line_number":1780,"context_line":"                frags_by_byte_order.append(send_chunks)"},{"line_number":1781,"context_line":"            # Sequential calls to encode() have given us a list that"},{"line_number":1782,"context_line":"            # looks like this:"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_197c21eb","line":1779,"updated":"2017-02-08 18:01:12.000000000","message":"do we need to duplicate the encoded_chunks? I understand that this generates a list of encoded chunks equal in length to the number of primary nodes, but it means that in _transfer_data-\u003esend_chunk we md5 hash each chunk duplication_factor times (once for each duplicate of the frag) which is unnecessary.\n\nI wonder if the send_chunks could be same length as ec_unique_fragments and then in _transfer_data we use get_backend_index to map the putter node index to the correct frag index in the chunk list?","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":1776,"context_line":"            frags_by_byte_order \u003d []"},{"line_number":1777,"context_line":"            for chunk_to_encode in chunks_to_encode:"},{"line_number":1778,"context_line":"                encoded_chunks \u003d policy.pyeclib_driver.encode(chunk_to_encode)"},{"line_number":1779,"context_line":"                send_chunks \u003d encoded_chunks * policy.ec_duplication_factor"},{"line_number":1780,"context_line":"                frags_by_byte_order.append(send_chunks)"},{"line_number":1781,"context_line":"            # Sequential calls to encode() have given us a list that"},{"line_number":1782,"context_line":"            # looks like this:"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_8f00ac35","line":1779,"in_reply_to":"1a430d35_197c21eb","updated":"2017-02-09 09:36:43.000000000","message":"Yes, please check out my follow up at [1].\n\nIn the follow up, we don\u0027t have to duplicate the frag here, but it will be able to pull from send_chunks list via *frag_index* and update md5 only once per unique index.\n\nDoes it need to merge the follow-up into this?\n\n1: https://review.openstack.org/#/c/421673","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f90c30a46d20b933970f063a350dc2d2085389b7","unresolved":false,"context_lines":[{"line_number":1776,"context_line":"            frags_by_byte_order \u003d []"},{"line_number":1777,"context_line":"            for chunk_to_encode in chunks_to_encode:"},{"line_number":1778,"context_line":"                encoded_chunks \u003d policy.pyeclib_driver.encode(chunk_to_encode)"},{"line_number":1779,"context_line":"                send_chunks \u003d encoded_chunks * policy.ec_duplication_factor"},{"line_number":1780,"context_line":"                frags_by_byte_order.append(send_chunks)"},{"line_number":1781,"context_line":"            # Sequential calls to encode() have given us a list that"},{"line_number":1782,"context_line":"            # looks like this:"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_4d915052","line":1779,"in_reply_to":"1a430d35_8f00ac35","updated":"2017-02-09 18:00:58.000000000","message":"OIC, follow up is ok.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":1777,"context_line":"            for chunk_to_encode in chunks_to_encode:"},{"line_number":1778,"context_line":"                encoded_chunks \u003d policy.pyeclib_driver.encode(chunk_to_encode)"},{"line_number":1779,"context_line":"                send_chunks \u003d encoded_chunks * policy.ec_duplication_factor"},{"line_number":1780,"context_line":"                frags_by_byte_order.append(send_chunks)"},{"line_number":1781,"context_line":"            # Sequential calls to encode() have given us a list that"},{"line_number":1782,"context_line":"            # looks like this:"},{"line_number":1783,"context_line":"            #"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_ad4e906c","line":1780,"updated":"2017-02-08 10:06:42.000000000","message":"nice","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":1802,"context_line":"    last_bytes \u003d \u0027\u0027.join(buf)"},{"line_number":1803,"context_line":"    if last_bytes:"},{"line_number":1804,"context_line":"        last_frags \u003d policy.pyeclib_driver.encode(last_bytes)"},{"line_number":1805,"context_line":"        yield last_frags * policy.ec_duplication_factor"},{"line_number":1806,"context_line":"    else:"},{"line_number":1807,"context_line":"        yield [\u0027\u0027] * nstreams"},{"line_number":1808,"context_line":""}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_0d5a442a","line":1805,"updated":"2017-02-08 10:06:42.000000000","message":"nice","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":2207,"context_line":"            # server, causes us to otherwise make endless requests e.g. if an"},{"line_number":2208,"context_line":"            # object server were to ignore frag_prefs and always respond with"},{"line_number":2209,"context_line":"            # a frag that is already in a bucket."},{"line_number":2210,"context_line":"            max_extra_requests \u003d 2 * policy.ec_n_unique_fragments"},{"line_number":2211,"context_line":""},{"line_number":2212,"context_line":"            for get, parts_iter in pile:"},{"line_number":2213,"context_line":"                if get.last_status is None:"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_6d32e8f3","line":2210,"updated":"2017-02-08 10:06:42.000000000","message":"nice","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d70caf31539aa2bc61cf876f2a9994bf3812e53","unresolved":false,"context_lines":[{"line_number":2420,"context_line":""},{"line_number":2421,"context_line":"            for putter in list(putters):"},{"line_number":2422,"context_line":"                ci \u003d chunk_index[putter]"},{"line_number":2423,"context_line":"                backend_chunk \u003d backend_chunks[ci]"},{"line_number":2424,"context_line":"                if not putter.failed:"},{"line_number":2425,"context_line":"                    chunk_hashers[ci].update(backend_chunk)"},{"line_number":2426,"context_line":"                    putter.send_chunk(backend_chunk)"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_54f2f006","line":2423,"updated":"2017-02-08 18:01:12.000000000","message":"(ref comment line 1779) ok, so this maps each node chunk index to a list of backend_chunks that contains duplicates, but then we update an md5 for all duplicates.\n\n(These are formative thoughts, so apologies if there is a gotcha I haven\u0027t seen yet...) Could we alternatively have backend_chunks be of length unique_fragments and then use:\n\n  backend_chunk \u003d backend_chunks[policy.get_backend_index(ci)]\n  if not putter.failed:\n      if ci \u003c policy.ec_num_unique_fragments:\n          chunk_hashers[ci].update(backend_chunk)\n\nthen some other changes to use get_backend_index when the nd5 hasher result is passed to construct trailing metadata??\n\n\ncould all be follow-up of course","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":2420,"context_line":""},{"line_number":2421,"context_line":"            for putter in list(putters):"},{"line_number":2422,"context_line":"                ci \u003d chunk_index[putter]"},{"line_number":2423,"context_line":"                backend_chunk \u003d backend_chunks[ci]"},{"line_number":2424,"context_line":"                if not putter.failed:"},{"line_number":2425,"context_line":"                    chunk_hashers[ci].update(backend_chunk)"},{"line_number":2426,"context_line":"                    putter.send_chunk(backend_chunk)"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_8a941a8b","line":2423,"in_reply_to":"1a430d35_54f2f006","updated":"2017-02-09 09:36:43.000000000","message":"Please see my comments at line 1779. In my follow up, all of proxy/controllers/obj.py works with *frag_index* instead of node_index so that it resolve duplicate md5 calculation, you are worried about.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"f19621c2546075b18093736e840a23ea03843566","unresolved":false,"context_lines":[{"line_number":2384,"context_line":""},{"line_number":2385,"context_line":"        # Extract the lack_list to a flat list"},{"line_number":2386,"context_line":"        holes \u003d []"},{"line_number":2387,"context_line":"        for lack_tier, indexes in sorted(lack_list.items(), reverse\u003dTrue):"},{"line_number":2388,"context_line":"            holes.extend(indexes)"},{"line_number":2389,"context_line":""},{"line_number":2390,"context_line":"        # Fill chunk_index list with the hole list"}],"source_content_type":"text/x-python","patch_set":56,"id":"fa31d9ce_8bf73bf4","line":2387,"range":{"start_line":2387,"start_character":34,"end_line":2387,"end_character":73},"updated":"2017-02-13 16:03:31.000000000","message":"Not sure I understand - wouldn\u0027t this result in a list of just \"lack_tier\" values? Which would be counter values as a result of \"enumerate(holes)\". For eg, if lack_list is:\n\n{0: [0, 1, 2], 1: [0]} then, sorting it would give [0, 1].\n\nIs that what we want?","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":12261,"name":"Mahati","email":"mahati.chamarthy@gmail.com","username":"Mahati"},"change_message_id":"244170487a9d30ed4af9ea9c01f5ada21ed69639","unresolved":false,"context_lines":[{"line_number":2384,"context_line":""},{"line_number":2385,"context_line":"        # Extract the lack_list to a flat list"},{"line_number":2386,"context_line":"        holes \u003d []"},{"line_number":2387,"context_line":"        for lack_tier, indexes in sorted(lack_list.items(), reverse\u003dTrue):"},{"line_number":2388,"context_line":"            holes.extend(indexes)"},{"line_number":2389,"context_line":""},{"line_number":2390,"context_line":"        # Fill chunk_index list with the hole list"}],"source_content_type":"text/x-python","patch_set":56,"id":"fa31d9ce_6c761a07","line":2387,"range":{"start_line":2387,"start_character":34,"end_line":2387,"end_character":73},"in_reply_to":"fa31d9ce_77c817a9","updated":"2017-02-16 05:28:58.000000000","message":"Yes, it does. I didn\u0027t realize that we were doing reverse\u003dTrue :) Thanks!","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"553d8dc2d7136e6b0a934d5989dc9f491f6d6a45","unresolved":false,"context_lines":[{"line_number":2384,"context_line":""},{"line_number":2385,"context_line":"        # Extract the lack_list to a flat list"},{"line_number":2386,"context_line":"        holes \u003d []"},{"line_number":2387,"context_line":"        for lack_tier, indexes in sorted(lack_list.items(), reverse\u003dTrue):"},{"line_number":2388,"context_line":"            holes.extend(indexes)"},{"line_number":2389,"context_line":""},{"line_number":2390,"context_line":"        # Fill chunk_index list with the hole list"}],"source_content_type":"text/x-python","patch_set":56,"id":"fa31d9ce_77c817a9","line":2387,"range":{"start_line":2387,"start_character":34,"end_line":2387,"end_character":73},"in_reply_to":"fa31d9ce_8bf73bf4","updated":"2017-02-14 01:34:16.000000000","message":"AFAIK, the sorted() affects the key of the dict and we use the sort with reverse\u003dTrue, so that means in the situation, {0: [0, 1, 2], 1: [0]}, it will be:\n\n [(1, [0]), (0, [0, 1, 2])]\n\nand holes below will have flatten list like:\n\n [0, 0, 1, 2]\n\nso... in the example frag_index 0 appears both key 1 and key 0 that means frag index 0 loose 2 nodes to put. And then both frag_index 1, 2 is only in key 0 that means frag_index 1 and 2 loose 1 node to put for each. On that situation, we *want* prior frag_index 0 because it loose more nodes than others. and then, the rest will be just flatten.\n\nDoes it make you sense?","commit_id":"661256a5167da13b956acd5628bc2380f4bcc0dd"}],"test/unit/__init__.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":228,"context_line":""},{"line_number":229,"context_line":"    def _init_device_char(self):"},{"line_number":230,"context_line":"        self._device_char_iter \u003d itertools.cycle("},{"line_number":231,"context_line":"            [\u0027sd%s\u0027 % chr(ord(\u0027a\u0027) + x) for x in range(26)])"},{"line_number":232,"context_line":""},{"line_number":233,"context_line":"    def set_replicas(self, replicas):"},{"line_number":234,"context_line":"        self.replicas \u003d replicas"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_c8559ac2","line":231,"updated":"2017-01-12 00:29:56.000000000","message":"Nice bit of convenience. Maybe consider inlining _init_device_char in __init__?","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"5b61d6be0e06bd567b79b295f1001bf9749a64b8","unresolved":false,"context_lines":[{"line_number":300,"context_line":"        self.devices \u003d devices"},{"line_number":301,"context_line":"        self.nodes \u003d nodes"},{"line_number":302,"context_line":"        self.port \u003d port"},{"line_number":303,"context_line":"        self.replicas \u003d replicas"},{"line_number":304,"context_line":"        self.part_power \u003d part_power"},{"line_number":305,"context_line":"        self._part_shift \u003d 32 - self.part_power"},{"line_number":306,"context_line":"        self._reload()"}],"source_content_type":"text/x-python","patch_set":43,"id":"ba5201f7_c8067a1b","line":303,"updated":"2017-01-12 00:29:56.000000000","message":"Whoops. Good call!","commit_id":"2db05dd07de5a909b1b60396fef2e7a26d71bda8"}],"test/unit/common/test_storage_policy.py":[{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"18f22649c4317c3b5930fc2b2735de04703e6dcc","unresolved":false,"context_lines":[{"line_number":1400,"context_line":"                # pyeclib_driver.get_segment_info is called only once"},{"line_number":1401,"context_line":"                self.assertEqual(1, fake.call_count)"},{"line_number":1402,"context_line":""},{"line_number":1403,"context_line":"    def _check_policy_sort_method(self, policy, primaries):"},{"line_number":1404,"context_line":"        initial \u003d copy(primaries)"},{"line_number":1405,"context_line":"        primaries.sort(key\u003dpolicy.sort_key)"},{"line_number":1406,"context_line":"        if policy.ec_duplication_factor \u003d\u003d 1:"}],"source_content_type":"text/x-python","patch_set":48,"id":"1a430d35_18582932","line":1403,"updated":"2017-02-06 01:14:26.000000000","message":"Ah... probably, I should revert this because the sorting key should be in follow up, right now.","commit_id":"ce6807ab6fd33d30d7844546c6261951772eb822"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"523012c4e0c116a61580c86b2f732e7185482e2a","unresolved":false,"context_lines":[{"line_number":1400,"context_line":"                # pyeclib_driver.get_segment_info is called only once"},{"line_number":1401,"context_line":"                self.assertEqual(1, fake.call_count)"},{"line_number":1402,"context_line":""},{"line_number":1403,"context_line":"    def _check_policy_sort_method(self, policy, primaries):"},{"line_number":1404,"context_line":"        initial \u003d copy(primaries)"},{"line_number":1405,"context_line":"        primaries.sort(key\u003dpolicy.sort_key)"},{"line_number":1406,"context_line":"        if policy.ec_duplication_factor \u003d\u003d 1:"}],"source_content_type":"text/x-python","patch_set":48,"id":"1a430d35_624c1b43","line":1403,"in_reply_to":"1a430d35_18582932","updated":"2017-02-06 06:40:28.000000000","message":"Done (removed)","commit_id":"ce6807ab6fd33d30d7844546c6261951772eb822"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":388,"context_line":"        name \u003d one"},{"line_number":389,"context_line":"        aliases \u003d uno, tahi"},{"line_number":390,"context_line":"        default \u003d yes"},{"line_number":391,"context_line":"        \"\"\")"},{"line_number":392,"context_line":""},{"line_number":393,"context_line":"        policies \u003d parse_storage_policies(good_conf)"},{"line_number":394,"context_line":"        self.assertEqual(policies.get_by_name(\u0027one\u0027),"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_b3742536","line":391,"updated":"2017-02-08 10:06:42.000000000","message":"I think some _conf tests to demonstrate the default duplication_factor - and some explicit valid (and invalid) settings would look nice","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":388,"context_line":"        name \u003d one"},{"line_number":389,"context_line":"        aliases \u003d uno, tahi"},{"line_number":390,"context_line":"        default \u003d yes"},{"line_number":391,"context_line":"        \"\"\")"},{"line_number":392,"context_line":""},{"line_number":393,"context_line":"        policies \u003d parse_storage_policies(good_conf)"},{"line_number":394,"context_line":"        self.assertEqual(policies.get_by_name(\u0027one\u0027),"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_258279c8","line":391,"in_reply_to":"1a430d35_b3742536","updated":"2017-02-09 09:36:43.000000000","message":"I added a few valid tests around here but i think current test sets need more tests and need to be corrected on some points so that i\u0027d leave the rest of works to the follow-up.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":1257,"context_line":"            k \u003d ec_policy.ec_ndata"},{"line_number":1258,"context_line":"            expected_size \u003d \\"},{"line_number":1259,"context_line":"                k + ec_policy.pyeclib_driver.min_parity_fragments_needed()"},{"line_number":1260,"context_line":"            self.assertEqual(expected_size, ec_policy.quorum)"},{"line_number":1261,"context_line":""},{"line_number":1262,"context_line":"    def test_validate_ring(self):"},{"line_number":1263,"context_line":"        test_policies \u003d ["}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_b318a51f","line":1260,"updated":"2017-02-08 10:06:42.000000000","message":"I think we should demonstrate/validate the behavior here with duplication_factor (I of course also think we should increase quorum by a factor of duplication)","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":1257,"context_line":"            k \u003d ec_policy.ec_ndata"},{"line_number":1258,"context_line":"            expected_size \u003d \\"},{"line_number":1259,"context_line":"                k + ec_policy.pyeclib_driver.min_parity_fragments_needed()"},{"line_number":1260,"context_line":"            self.assertEqual(expected_size, ec_policy.quorum)"},{"line_number":1261,"context_line":""},{"line_number":1262,"context_line":"    def test_validate_ring(self):"},{"line_number":1263,"context_line":"        test_policies \u003d ["}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_85d96df5","line":1260,"in_reply_to":"1a430d35_b318a51f","updated":"2017-02-09 09:36:43.000000000","message":"Done","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":1360,"context_line":"                \u0027ec_num_data_fragments\u0027: 10,"},{"line_number":1361,"context_line":"                \u0027ec_num_parity_fragments\u0027: 3,"},{"line_number":1362,"context_line":"                \u0027ec_object_segment_size\u0027: DEFAULT_EC_OBJECT_SEGMENT_SIZE,"},{"line_number":1363,"context_line":"                \u0027ec_duplication_factor\u0027: 1,"},{"line_number":1364,"context_line":"            },"},{"line_number":1365,"context_line":"            (11, False): {"},{"line_number":1366,"context_line":"                \u0027name\u0027: \u0027done\u0027,"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_53aea198","line":1363,"updated":"2017-02-08 10:06:42.000000000","message":"should a couple of these be added with various duplication factor values?","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":1360,"context_line":"                \u0027ec_num_data_fragments\u0027: 10,"},{"line_number":1361,"context_line":"                \u0027ec_num_parity_fragments\u0027: 3,"},{"line_number":1362,"context_line":"                \u0027ec_object_segment_size\u0027: DEFAULT_EC_OBJECT_SEGMENT_SIZE,"},{"line_number":1363,"context_line":"                \u0027ec_duplication_factor\u0027: 1,"},{"line_number":1364,"context_line":"            },"},{"line_number":1365,"context_line":"            (11, False): {"},{"line_number":1366,"context_line":"                \u0027name\u0027: \u0027done\u0027,"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_456f85fb","line":1363,"in_reply_to":"1a430d35_53aea198","updated":"2017-02-09 09:36:43.000000000","message":"Done","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":1307,"context_line":"            with mock.patch(\u0027swift.common.ring.ring.RingData.load\u0027,"},{"line_number":1308,"context_line":"                            return_value\u003dMockRingData(ring_replicas)):"},{"line_number":1309,"context_line":"                necessary_replica_num \u003d \\"},{"line_number":1310,"context_line":"                    policy.ec_n_unique_fragments * policy.ec_duplication_factor"},{"line_number":1311,"context_line":"                with mock.patch("},{"line_number":1312,"context_line":"                        \u0027swift.common.ring.ring.validate_configuration\u0027):"},{"line_number":1313,"context_line":"                    msg \u003d \u0027EC ring for policy %s needs to be configured with \u0027 \\"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_fe701742","line":1310,"updated":"2017-02-26 04:44:21.000000000","message":"ok. test fails with change reverted\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\nFAIL: test_validate_ring (test.unit.common.test_storage_policy.TestStoragePolicies)\n----------------------------------------------------------------------\nTraceback (most recent call last):\n  File \"/home/swift/swift/test/unit/common/test_storage_policy.py\", line 1319, in test_validate_ring\n    policy.load_ring, \u0027mock\u0027)\n  File \"/home/swift/swift/test/unit/common/test_storage_policy.py\", line 83, in assertRaisesWithMessage\n    \u0027have expected substring %r\u0027 % (err_msg, message))\nAssertionError: Error message \u0027EC ring for policy ec4-2-2dup needs to be configured with exactly 6 replicas. Got 11.\u0027 did not have expected substring \u0027EC ring for policy ec4-2-2dup needs to be configured with exactly 12 replicas.\u0027\n    \"Error message \u0027EC ring for policy ec4-2-2dup needs to be configured with exactly 6 replicas. Got 11.\u0027 did not have expected substring \u0027EC ring for policy ec4-2-2dup needs to be configured with exactly 12 replicas.\u0027\" \u003d self._formatMessage(\"Error message \u0027EC ring for policy ec4-2-2dup needs to be configured with exactly 6 replicas. Got 11.\u0027 did not have expected substring \u0027EC ring for policy ec4-2-2dup needs to be configured with exactly 12 replicas.\u0027\", \"%s is not true\" % safe_repr(False))\n\u003e\u003e  raise self.failureException(\"Error message \u0027EC ring for policy ec4-2-2dup needs to be configured with exactly 6 replicas. Got 11.\u0027 did not have expected substring \u0027EC ring for policy ec4-2-2dup needs to be configured with exactly 12 replicas.\u0027\")","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":1307,"context_line":"            with mock.patch(\u0027swift.common.ring.ring.RingData.load\u0027,"},{"line_number":1308,"context_line":"                            return_value\u003dMockRingData(ring_replicas)):"},{"line_number":1309,"context_line":"                necessary_replica_num \u003d \\"},{"line_number":1310,"context_line":"                    policy.ec_n_unique_fragments * policy.ec_duplication_factor"},{"line_number":1311,"context_line":"                with mock.patch("},{"line_number":1312,"context_line":"                        \u0027swift.common.ring.ring.validate_configuration\u0027):"},{"line_number":1313,"context_line":"                    msg \u003d \u0027EC ring for policy %s needs to be configured with \u0027 \\"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_4aa914df","line":1310,"in_reply_to":"da36d5c6_fe701742","updated":"2017-02-28 09:01:43.000000000","message":"Done","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"}],"test/unit/common/test_utils.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f4454737d5cb3123a8c4786b639bb20cc6487b1b","unresolved":false,"context_lines":[{"line_number":2597,"context_line":"                if e.__class__ is not expected:"},{"line_number":2598,"context_line":"                    raise"},{"line_number":2599,"context_line":"            else:"},{"line_number":2600,"context_line":"                self.assertEqual(expected, rv)"},{"line_number":2601,"context_line":""},{"line_number":2602,"context_line":"    def test_config_auto_int_value(self):"},{"line_number":2603,"context_line":"        expectations \u003d {"}],"source_content_type":"text/x-python","patch_set":44,"id":"7a3c09a3_85b47182","line":2600,"updated":"2017-01-17 02:54:44.000000000","message":"nice!","commit_id":"2d37559753262ef9bb5d2abd2f77c4494d8ff164"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":2589,"context_line":"            None: ValueError,"},{"line_number":2590,"context_line":"            0: ValueError,"},{"line_number":2591,"context_line":"            -1: ValueError,"},{"line_number":2592,"context_line":"            \u00271.2\u0027: ValueError,  # string expresses float should be value error"},{"line_number":2593,"context_line":"        }"},{"line_number":2594,"context_line":"        for value, expected in expectations.items():"},{"line_number":2595,"context_line":"            try:"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_ae84a80a","line":2592,"updated":"2017-02-26 04:44:21.000000000","message":"nit: add cases for \u0027-1\u0027 and \u00270\u0027","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":2589,"context_line":"            None: ValueError,"},{"line_number":2590,"context_line":"            0: ValueError,"},{"line_number":2591,"context_line":"            -1: ValueError,"},{"line_number":2592,"context_line":"            \u00271.2\u0027: ValueError,  # string expresses float should be value error"},{"line_number":2593,"context_line":"        }"},{"line_number":2594,"context_line":"        for value, expected in expectations.items():"},{"line_number":2595,"context_line":"            try:"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_6aaed8e8","line":2592,"in_reply_to":"da36d5c6_ae84a80a","updated":"2017-02-28 09:01:43.000000000","message":"Done at your follow up [1]\n\n1: https://review.openstack.org/#/c/438231/1/test/unit/common/test_utils.py","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"}],"test/unit/helpers.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"381bbaf5157aaf99c818b3bab373a9845047ca56","unresolved":false,"context_lines":[{"line_number":221,"context_line":"    obj3spa \u003d spawn(wsgi.server, obj3lis, obj3srv, nl)"},{"line_number":222,"context_line":"    obj4spa \u003d spawn(wsgi.server, obj4lis, obj4srv, nl)"},{"line_number":223,"context_line":"    obj5spa \u003d spawn(wsgi.server, obj5lis, obj5srv, nl)"},{"line_number":224,"context_line":"    obj6spa \u003d spawn(wsgi.server, obj6lis, obj6srv, nl)"},{"line_number":225,"context_line":"    context[\"test_coros\"] \u003d \\"},{"line_number":226,"context_line":"        (prospa, acc1spa, acc2spa, con1spa, con2spa, obj1spa, obj2spa, obj3spa,"},{"line_number":227,"context_line":"         obj4spa, obj5spa, obj6spa)"}],"source_content_type":"text/x-python","patch_set":47,"id":"3a461143_94924f9e","line":224,"updated":"2017-02-02 03:14:49.000000000","message":"This is a non-trival overhead during the test run even when running tests that are not exercising ec_duplication\n\nIMHO our backend socket test infrastructure is very messy and tends to get abused - I\u0027d like to see it segregated so we can start to clean it up - this change conflicts with that goal [1]\n\n1. https://review.openstack.org/#/c/415473/","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"2671effc57b1f727998acb5e80e3d54c801ba99f","unresolved":false,"context_lines":[{"line_number":221,"context_line":"    obj3spa \u003d spawn(wsgi.server, obj3lis, obj3srv, nl)"},{"line_number":222,"context_line":"    obj4spa \u003d spawn(wsgi.server, obj4lis, obj4srv, nl)"},{"line_number":223,"context_line":"    obj5spa \u003d spawn(wsgi.server, obj5lis, obj5srv, nl)"},{"line_number":224,"context_line":"    obj6spa \u003d spawn(wsgi.server, obj6lis, obj6srv, nl)"},{"line_number":225,"context_line":"    context[\"test_coros\"] \u003d \\"},{"line_number":226,"context_line":"        (prospa, acc1spa, acc2spa, con1spa, con2spa, obj1spa, obj2spa, obj3spa,"},{"line_number":227,"context_line":"         obj4spa, obj5spa, obj6spa)"}],"source_content_type":"text/x-python","patch_set":47,"id":"1a430d35_0052aa13","line":224,"in_reply_to":"3a461143_94924f9e","updated":"2017-02-03 10:42:24.000000000","message":"So you mean, it would be better to make something like setup_ec_duplication_servers and separate the setups into that, right?\n\nIt could be... but it may need more time to address.","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"}],"test/unit/obj/test_reconstructor.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"381bbaf5157aaf99c818b3bab373a9845047ca56","unresolved":false,"context_lines":[{"line_number":3018,"context_line":"    def test_reconstruct_with_duplicate_frags_no_errors(self):"},{"line_number":3019,"context_line":"        # any fragments can be broken"},{"line_number":3020,"context_line":"        for index in range(28):"},{"line_number":3021,"context_line":"            self._test_reconstruct_with_duplicate_frags_no_errors(index)"},{"line_number":3022,"context_line":""},{"line_number":3023,"context_line":""},{"line_number":3024,"context_line":"if __name__ \u003d\u003d \u0027__main__\u0027:"}],"source_content_type":"text/x-python","patch_set":47,"id":"3a461143_d4c0572d","line":3021,"updated":"2017-02-02 03:14:49.000000000","message":"This test looks good","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"2671effc57b1f727998acb5e80e3d54c801ba99f","unresolved":false,"context_lines":[{"line_number":3018,"context_line":"    def test_reconstruct_with_duplicate_frags_no_errors(self):"},{"line_number":3019,"context_line":"        # any fragments can be broken"},{"line_number":3020,"context_line":"        for index in range(28):"},{"line_number":3021,"context_line":"            self._test_reconstruct_with_duplicate_frags_no_errors(index)"},{"line_number":3022,"context_line":""},{"line_number":3023,"context_line":""},{"line_number":3024,"context_line":"if __name__ \u003d\u003d \u0027__main__\u0027:"}],"source_content_type":"text/x-python","patch_set":47,"id":"1a430d35_c048a25e","line":3021,"in_reply_to":"3a461143_d4c0572d","updated":"2017-02-03 10:42:24.000000000","message":":-)","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":2855,"context_line":"            fixed_body \u003d \u0027\u0027.join(df.reader())"},{"line_number":2856,"context_line":"            self.assertEqual(len(fixed_body), len(broken_body))"},{"line_number":2857,"context_line":"            self.assertEqual(md5(fixed_body).hexdigest(),"},{"line_number":2858,"context_line":"                             md5(broken_body).hexdigest())"},{"line_number":2859,"context_line":""},{"line_number":2860,"context_line":"    def test_reconstruct_fa_finds_itself_does_not_fail(self):"},{"line_number":2861,"context_line":"        job \u003d {"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_f35f8de2","line":2858,"updated":"2017-02-08 10:06:42.000000000","message":"Is the only test that setup something that looked like not enough frags to rebuild behavior?\n\nmaybe we need some negative testing to demonstrate what happens when too many nodes with duplicate frags respond but not enough to rebuild the object?","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":2855,"context_line":"            fixed_body \u003d \u0027\u0027.join(df.reader())"},{"line_number":2856,"context_line":"            self.assertEqual(len(fixed_body), len(broken_body))"},{"line_number":2857,"context_line":"            self.assertEqual(md5(fixed_body).hexdigest(),"},{"line_number":2858,"context_line":"                             md5(broken_body).hexdigest())"},{"line_number":2859,"context_line":""},{"line_number":2860,"context_line":"    def test_reconstruct_fa_finds_itself_does_not_fail(self):"},{"line_number":2861,"context_line":"        job \u003d {"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_855c0d4c","line":2858,"in_reply_to":"1a430d35_f35f8de2","updated":"2017-02-09 09:36:43.000000000","message":"Done","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":3020,"context_line":"    def test_reconstruct_with_duplicate_frags_no_errors(self):"},{"line_number":3021,"context_line":"        # any fragments can be broken"},{"line_number":3022,"context_line":"        for index in range(28):"},{"line_number":3023,"context_line":"            self._test_reconstruct_with_duplicate_frags_no_errors(index)"},{"line_number":3024,"context_line":""},{"line_number":3025,"context_line":""},{"line_number":3026,"context_line":"if __name__ \u003d\u003d \u0027__main__\u0027:"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_b38ee576","line":3023,"updated":"2017-02-08 10:06:42.000000000","message":"I\u0027d like to see a test that setups up the skipped duplicate frag behavior","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ae07023dda7ae398a2434c5da6f212b056b15a35","unresolved":false,"context_lines":[{"line_number":2757,"context_line":"        responses \u003d base_responses"},{"line_number":2758,"context_line":"        # since we\u0027re already missing a fragment a +2 scheme can only support"},{"line_number":2759,"context_line":"        # one additional failure at a time; stick it in near the front"},{"line_number":2760,"context_line":"        error_index \u003d random.randint(0, len(responses) // 2 - 1)"},{"line_number":2761,"context_line":"        status, body, headers \u003d responses[error_index]"},{"line_number":2762,"context_line":"        # one esoteric failure is a literal string \u0027None\u0027 in place of the"},{"line_number":2763,"context_line":"        # X-Object-Sysmeta-EC-Frag-Index"}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_d0f560cb","line":2760,"updated":"2017-02-22 16:12:19.000000000","message":"In the case of a duplicated policy - this error condition may introduced at the end of the list and not acctually exercise the bad response handling.\n\nWe need to make sure that the error is introduced early enough in the response pile that we encounter the failure\n\n    diff --git a/test/unit/obj/test_reconstructor.py b/test/unit/obj/test_reconstructor.py\n    index 352609c..15a6e21 100644\n    --- a/test/unit/obj/test_reconstructor.py\n    +++ b/test/unit/obj/test_reconstructor.py\n    @@ -2755,9 +2755,10 @@ class TestObjectReconstructor(unittest.TestCase):\n                 base_responses.append((200, body, headers))\n     \n             responses \u003d base_responses\n    -        # since we\u0027re already missing a fragment a +2 scheme can only support\n    -        # one additional failure at a time; stick it in near the front\n    -        error_index \u003d random.randint(0, len(responses) // 2 - 1)\n    +        # force the test to exercise the handling of this bad response by\n    +        # sticking it in near the front\n    +        error_index \u003d random.randint(\n    +            0, self.policy.ec_ndata - 1)\n             status, body, headers \u003d responses[error_index]\n             # one esoteric failure is a literal string \u0027None\u0027 in place of the\n             # X-Object-Sysmeta-EC-Frag-Index","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        yield fake_ssync"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"def make_ec_archive_bodies(policy, test_body):"},{"line_number":69,"context_line":"    segment_size \u003d policy.ec_segment_size"},{"line_number":70,"context_line":"    # split up the body into buffers"},{"line_number":71,"context_line":"    chunks \u003d [test_body[x:x + segment_size]"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_0eaa1419","line":68,"updated":"2017-02-26 04:44:21.000000000","message":"this is redundant, we can use encode_frag_archive_bodies in unit/__init__.py","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        yield fake_ssync"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"def make_ec_archive_bodies(policy, test_body):"},{"line_number":69,"context_line":"    segment_size \u003d policy.ec_segment_size"},{"line_number":70,"context_line":"    # split up the body into buffers"},{"line_number":71,"context_line":"    chunks \u003d [test_body[x:x + segment_size]"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_aae61042","line":68,"in_reply_to":"da36d5c6_0eaa1419","updated":"2017-02-28 09:01:43.000000000","message":"Good catch! Thanks!\n\nAnd it\u0027s in your follow-up [1]\n\n1: https://review.openstack.org/#/c/438231/1/test/unit/obj/test_reconstructor.py","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":666,"context_line":""},{"line_number":667,"context_line":"    def test_get_response(self):"},{"line_number":668,"context_line":"        part \u003d self.part_nums[0]"},{"line_number":669,"context_line":"        node \u003d POLICIES[1].object_ring.get_part_nodes(int(part))[0]"},{"line_number":670,"context_line":"        for stat_code in (200, 400):"},{"line_number":671,"context_line":"            with mocked_http_conn(stat_code):"},{"line_number":672,"context_line":"                resp \u003d self.reconstructor._get_response(node, part,"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_8e3a84e5","line":669,"updated":"2017-02-26 04:44:21.000000000","message":"nit: could just use self.policy instead of POLICIES[1] throughout","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":666,"context_line":""},{"line_number":667,"context_line":"    def test_get_response(self):"},{"line_number":668,"context_line":"        part \u003d self.part_nums[0]"},{"line_number":669,"context_line":"        node \u003d POLICIES[1].object_ring.get_part_nodes(int(part))[0]"},{"line_number":670,"context_line":"        for stat_code in (200, 400):"},{"line_number":671,"context_line":"            with mocked_http_conn(stat_code):"},{"line_number":672,"context_line":"                resp \u003d self.reconstructor._get_response(node, part,"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_4a867414","line":669,"in_reply_to":"da36d5c6_8e3a84e5","updated":"2017-02-28 09:01:43.000000000","message":"Exactly. And i will fix some part using POLICIES[1]","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":1784,"context_line":"        # since this part doesn\u0027t belong on us it doesn\u0027t matter what"},{"line_number":1785,"context_line":"        # frag_index we have"},{"line_number":1786,"context_line":"        frag_index \u003d self.policy.get_backend_index("},{"line_number":1787,"context_line":"            random.randint(0, ring.replicas - 1))"},{"line_number":1788,"context_line":"        stub_hashes \u003d {"},{"line_number":1789,"context_line":"            \u0027123\u0027: {frag_index: \u0027hash\u0027, None: \u0027hash\u0027},"},{"line_number":1790,"context_line":"            \u0027abc\u0027: {None: \u0027hash\u0027},"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_f13845d5","line":1787,"updated":"2017-02-26 04:44:21.000000000","message":"nit: more direct:\n  \n  random.randint(0, self.policy.ec_n_unique_fragments - 1)\n\nmaybe??","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":1784,"context_line":"        # since this part doesn\u0027t belong on us it doesn\u0027t matter what"},{"line_number":1785,"context_line":"        # frag_index we have"},{"line_number":1786,"context_line":"        frag_index \u003d self.policy.get_backend_index("},{"line_number":1787,"context_line":"            random.randint(0, ring.replicas - 1))"},{"line_number":1788,"context_line":"        stub_hashes \u003d {"},{"line_number":1789,"context_line":"            \u0027123\u0027: {frag_index: \u0027hash\u0027, None: \u0027hash\u0027},"},{"line_number":1790,"context_line":"            \u0027abc\u0027: {None: \u0027hash\u0027},"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_6a3ed82a","line":1787,"in_reply_to":"da36d5c6_f13845d5","updated":"2017-02-28 09:01:43.000000000","message":"good call and it must be consistent with test_process_job_xxx tests. thanks.\n\nAh... I got some failures if I did that and, to enable it, I found we need one more fix for the fabricate ring setting at L1145 like:\n\n self.fabricated_ring \u003d FabricatedRing(replicas\u003d14, devices\u003d28)","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":1838,"context_line":"            \u0027part_path\u0027: part_path,"},{"line_number":1839,"context_line":"        }"},{"line_number":1840,"context_line":"        frag_index \u003d self.policy.get_backend_index(node_index)"},{"line_number":1841,"context_line":"        other_frag_index \u003d self.policy.get_backend_index("},{"line_number":1842,"context_line":"            random.choice("},{"line_number":1843,"context_line":"                [f for f in range(ring.replicas) if f !\u003d node_index]))"},{"line_number":1844,"context_line":"        stub_hashes \u003d {"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_116239d8","line":1841,"updated":"2017-02-26 04:44:21.000000000","message":"nit: same as above, could use ec_n_unique_fragments maybe??","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":1838,"context_line":"            \u0027part_path\u0027: part_path,"},{"line_number":1839,"context_line":"        }"},{"line_number":1840,"context_line":"        frag_index \u003d self.policy.get_backend_index(node_index)"},{"line_number":1841,"context_line":"        other_frag_index \u003d self.policy.get_backend_index("},{"line_number":1842,"context_line":"            random.choice("},{"line_number":1843,"context_line":"                [f for f in range(ring.replicas) if f !\u003d node_index]))"},{"line_number":1844,"context_line":"        stub_hashes \u003d {"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_85af7e93","line":1841,"in_reply_to":"da36d5c6_116239d8","updated":"2017-02-28 09:01:43.000000000","message":"Yes!","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":2763,"context_line":"        # X-Object-Sysmeta-EC-Frag-Index"},{"line_number":2764,"context_line":"        stub_node_job \u003d {\u0027some_keys\u0027: \u0027foo\u0027, \u0027but_not\u0027: \u0027frag_index\u0027}"},{"line_number":2765,"context_line":"        headers[\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027] \u003d str("},{"line_number":2766,"context_line":"            stub_node_job.get(\u0027frag_index\u0027))"},{"line_number":2767,"context_line":"        # oops!"},{"line_number":2768,"context_line":"        self.assertEqual(\u0027None\u0027,"},{"line_number":2769,"context_line":"                         headers.get(\u0027X-Object-Sysmeta-Ec-Frag-Index\u0027))"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_06310f5a","line":2766,"updated":"2017-02-26 04:44:21.000000000","message":"ok I am assuming this roundabout way fo setting to header to None is meant to illustrate how that regression might occur\n\nok :) this test fails when I regress these lines in reconstructor:\n\n              try:\n                unique_index \u003d int(frag_index)\n            except (TypeError, ValueError):\n                # The successful response should include valid X-Object-\n\nby re-raising the exception","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":2774,"context_line":"            df \u003d self.reconstructor.reconstruct_fa("},{"line_number":2775,"context_line":"                job, node, dict(metadata))"},{"line_number":2776,"context_line":"            fixed_body \u003d \u0027\u0027.join(df.reader())"},{"line_number":2777,"context_line":"            # ... this bad request should be treated like any other failure"},{"line_number":2778,"context_line":"            self.assertEqual(len(fixed_body), len(broken_body))"},{"line_number":2779,"context_line":"            self.assertEqual(md5(fixed_body).hexdigest(),"},{"line_number":2780,"context_line":"                             md5(broken_body).hexdigest())"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_260b737e","line":2777,"updated":"2017-02-26 04:44:21.000000000","message":"nit: s/request/response/","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":2774,"context_line":"            df \u003d self.reconstructor.reconstruct_fa("},{"line_number":2775,"context_line":"                job, node, dict(metadata))"},{"line_number":2776,"context_line":"            fixed_body \u003d \u0027\u0027.join(df.reader())"},{"line_number":2777,"context_line":"            # ... this bad request should be treated like any other failure"},{"line_number":2778,"context_line":"            self.assertEqual(len(fixed_body), len(broken_body))"},{"line_number":2779,"context_line":"            self.assertEqual(md5(fixed_body).hexdigest(),"},{"line_number":2780,"context_line":"                             md5(broken_body).hexdigest())"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_258ed227","line":2777,"in_reply_to":"da36d5c6_260b737e","updated":"2017-02-28 09:01:43.000000000","message":"Done at follow-up","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":2904,"context_line":""},{"line_number":2905,"context_line":"        # bad response"},{"line_number":2906,"context_line":"        broken_body \u003d ec_archive_bodies.pop(1)"},{"line_number":2907,"context_line":"        ts \u003d (utils.Timestamp(t) for t in itertools.count(int(time.time())))"},{"line_number":2908,"context_line":"        bad_headers \u003d get_header_frag_index(self, broken_body)"},{"line_number":2909,"context_line":"        bad_headers.update({"},{"line_number":2910,"context_line":"            \u0027X-Object-Sysmeta-Ec-Etag\u0027: \u0027some garbage\u0027,"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_e6bebb63","line":2907,"updated":"2017-02-26 04:44:21.000000000","message":"can use make_timestamp_iter()","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":2904,"context_line":""},{"line_number":2905,"context_line":"        # bad response"},{"line_number":2906,"context_line":"        broken_body \u003d ec_archive_bodies.pop(1)"},{"line_number":2907,"context_line":"        ts \u003d (utils.Timestamp(t) for t in itertools.count(int(time.time())))"},{"line_number":2908,"context_line":"        bad_headers \u003d get_header_frag_index(self, broken_body)"},{"line_number":2909,"context_line":"        bad_headers.update({"},{"line_number":2910,"context_line":"            \u0027X-Object-Sysmeta-Ec-Etag\u0027: \u0027some garbage\u0027,"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_e5acba8e","line":2907,"in_reply_to":"da36d5c6_e6bebb63","updated":"2017-02-28 09:01:43.000000000","message":"Done at follow-up","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":2921,"context_line":"            responses.append((200, body, headers))"},{"line_number":2922,"context_line":""},{"line_number":2923,"context_line":"        # mixed together"},{"line_number":2924,"context_line":"        error_index \u003d random.randint(0, self.policy.ec_ndata)"},{"line_number":2925,"context_line":"        error_headers \u003d get_header_frag_index(self,"},{"line_number":2926,"context_line":"                                              (responses[error_index])[1])"},{"line_number":2927,"context_line":"        error_headers.update(bad_headers)"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_46b86775","line":2924,"updated":"2017-02-26 04:44:21.000000000","message":"hmmm, so here we choose randint between 0 and ec_ndata inclusive - elsewhere the max is ec_ndata-1. This does result in the bad response being considered in reconstructor because the responses also include the frag index that is broken (which gets ignored) so ec_ndata+1 responses are used.\n\nbut maybe the limit should eb set to ec_ndata - 1 for consistency","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":2921,"context_line":"            responses.append((200, body, headers))"},{"line_number":2922,"context_line":""},{"line_number":2923,"context_line":"        # mixed together"},{"line_number":2924,"context_line":"        error_index \u003d random.randint(0, self.policy.ec_ndata)"},{"line_number":2925,"context_line":"        error_headers \u003d get_header_frag_index(self,"},{"line_number":2926,"context_line":"                                              (responses[error_index])[1])"},{"line_number":2927,"context_line":"        error_headers.update(bad_headers)"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_05ef0eb1","line":2924,"in_reply_to":"da36d5c6_46b86775","updated":"2017-02-28 09:01:43.000000000","message":"Oh, I think that\u0027s correct. I didn\u0027t touch there in this patch but you looks already to work on that at the follow-up. Nice.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":3037,"context_line":"            self.assertEqual(md5(fixed_body).hexdigest(),"},{"line_number":3038,"context_line":"                             md5(broken_body).hexdigest())"},{"line_number":3039,"context_line":""},{"line_number":3040,"context_line":"        # one newer timestamp but same etag won\u0027t spoil the bunch"},{"line_number":3041,"context_line":"        # N.B. (FIXIME). we choose the first response as garbage, the"},{"line_number":3042,"context_line":"        # reconstruction fails because all other *correct* frags will be"},{"line_number":3043,"context_line":"        # assumed as garbage. To avoid the freaky failing set randint"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_667acbbe","line":3040,"updated":"2017-02-26 04:44:21.000000000","message":"its not a newer timestamp","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":3037,"context_line":"            self.assertEqual(md5(fixed_body).hexdigest(),"},{"line_number":3038,"context_line":"                             md5(broken_body).hexdigest())"},{"line_number":3039,"context_line":""},{"line_number":3040,"context_line":"        # one newer timestamp but same etag won\u0027t spoil the bunch"},{"line_number":3041,"context_line":"        # N.B. (FIXIME). we choose the first response as garbage, the"},{"line_number":3042,"context_line":"        # reconstruction fails because all other *correct* frags will be"},{"line_number":3043,"context_line":"        # assumed as garbage. To avoid the freaky failing set randint"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_a53e4227","line":3040,"in_reply_to":"da36d5c6_667acbbe","updated":"2017-02-28 09:01:43.000000000","message":"Oops, thanks! Done at the follow up.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":3118,"context_line":"                              job, node, metadata)"},{"line_number":3119,"context_line":""},{"line_number":3120,"context_line":"        error_lines \u003d self.logger.get_lines_for_level(\u0027error\u0027)"},{"line_number":3121,"context_line":"        # only 1 log to report no enough responses"},{"line_number":3122,"context_line":"        self.assertEqual(3, len(error_lines))"},{"line_number":3123,"context_line":"        for error_line in error_lines:"},{"line_number":3124,"context_line":"            for expected_etag, ts in ec_archive_dict:"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_4646a77b","line":3121,"updated":"2017-02-26 04:44:21.000000000","message":"there are 3 error logs","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":3118,"context_line":"                              job, node, metadata)"},{"line_number":3119,"context_line":""},{"line_number":3120,"context_line":"        error_lines \u003d self.logger.get_lines_for_level(\u0027error\u0027)"},{"line_number":3121,"context_line":"        # only 1 log to report no enough responses"},{"line_number":3122,"context_line":"        self.assertEqual(3, len(error_lines))"},{"line_number":3123,"context_line":"        for error_line in error_lines:"},{"line_number":3124,"context_line":"            for expected_etag, ts in ec_archive_dict:"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_257892f8","line":3121,"in_reply_to":"da36d5c6_4646a77b","updated":"2017-02-28 09:01:43.000000000","message":"correct. 1 error log per etag, thanks for the follow!","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":3122,"context_line":"        self.assertEqual(3, len(error_lines))"},{"line_number":3123,"context_line":"        for error_line in error_lines:"},{"line_number":3124,"context_line":"            for expected_etag, ts in ec_archive_dict:"},{"line_number":3125,"context_line":"                if expected_etag in error_line:"},{"line_number":3126,"context_line":"                    break"},{"line_number":3127,"context_line":"            else:"},{"line_number":3128,"context_line":"                self.fail("}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_a6576324","line":3125,"updated":"2017-02-26 04:44:21.000000000","message":"nit: I don\u0027t think this verifies that all 3 etags are reported - expected_etag should be eliminated from the candidates once it has been matched","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":3122,"context_line":"        self.assertEqual(3, len(error_lines))"},{"line_number":3123,"context_line":"        for error_line in error_lines:"},{"line_number":3124,"context_line":"            for expected_etag, ts in ec_archive_dict:"},{"line_number":3125,"context_line":"                if expected_etag in error_line:"},{"line_number":3126,"context_line":"                    break"},{"line_number":3127,"context_line":"            else:"},{"line_number":3128,"context_line":"                self.fail("}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_0590eeeb","line":3125,"in_reply_to":"da36d5c6_a6576324","updated":"2017-02-28 09:01:43.000000000","message":"Correct. And it doesn\u0027t look that you worked on that in the follow up so that I\u0027ll address this to be more robust.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":3186,"context_line":"        self.assertEqual(2, len(debug_log_lines))"},{"line_number":3187,"context_line":"        self.assertIn("},{"line_number":3188,"context_line":"            \u0027Found existing frag #1 while rebuilding #1 from\u0027,"},{"line_number":3189,"context_line":"            debug_log_lines[0])"},{"line_number":3190,"context_line":"        # ... and then, it should be skipped in the responses"},{"line_number":3191,"context_line":""},{"line_number":3192,"context_line":"        # N.B. in the future, we could avoid those check because"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_86233fbc","line":3189,"updated":"2017-02-26 04:44:21.000000000","message":"nit: with a duplication factor \u003e1, the reconstructor might receive \u003e1 frags of the index that is being rebuilt. this test does not exercise that case because (AFAICT) the duplicate frags are not consumed, because sufficient frags are found in first ec_ndata responses.\n\nIDK - maybe the responses could be shuffled so that sometimes duplicate frags will be consumed/ignored during the test??","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":3186,"context_line":"        self.assertEqual(2, len(debug_log_lines))"},{"line_number":3187,"context_line":"        self.assertIn("},{"line_number":3188,"context_line":"            \u0027Found existing frag #1 while rebuilding #1 from\u0027,"},{"line_number":3189,"context_line":"            debug_log_lines[0])"},{"line_number":3190,"context_line":"        # ... and then, it should be skipped in the responses"},{"line_number":3191,"context_line":""},{"line_number":3192,"context_line":"        # N.B. in the future, we could avoid those check because"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_48303b9f","line":3189,"in_reply_to":"da36d5c6_86233fbc","updated":"2017-02-28 09:01:43.000000000","message":"I think you\u0027re correct on that. I have an idea to improve this. Will do in another patch set.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":3313,"context_line":"        test_missing_header("},{"line_number":3314,"context_line":"            \u0027X-Object-Sysmeta-Ec-Etag\u0027,"},{"line_number":3315,"context_line":"            \"%s %s\" % (message_base, \"(missing Etag)\"))"},{"line_number":3316,"context_line":"        test_missing_header("},{"line_number":3317,"context_line":"            \u0027X-Object-Sysmeta-Ec-Frag-Index\u0027,"},{"line_number":3318,"context_line":"            \"%s %s\" % (message_base,"},{"line_number":3319,"context_line":"                       \"(invalid X-Object-Sysmeta-Ec-Frag-Index)\"))"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_061e6f6f","line":3316,"updated":"2017-02-26 04:44:21.000000000","message":"does this case duplicate test_reconstruct_fa_error_with_invalid_header? if not, could there be another case here and remove test_reconstruct_fa_error_with_invalid_header?","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":3313,"context_line":"        test_missing_header("},{"line_number":3314,"context_line":"            \u0027X-Object-Sysmeta-Ec-Etag\u0027,"},{"line_number":3315,"context_line":"            \"%s %s\" % (message_base, \"(missing Etag)\"))"},{"line_number":3316,"context_line":"        test_missing_header("},{"line_number":3317,"context_line":"            \u0027X-Object-Sysmeta-Ec-Frag-Index\u0027,"},{"line_number":3318,"context_line":"            \"%s %s\" % (message_base,"},{"line_number":3319,"context_line":"                       \"(invalid X-Object-Sysmeta-Ec-Frag-Index)\"))"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_4b783590","line":3316,"in_reply_to":"da36d5c6_061e6f6f","updated":"2017-02-28 09:01:43.000000000","message":"It\u0027s not duplicate with test_reconstruct_fa_error_with_invalid_header. That case is for the value \u0027None\u0027 (string) but this is for lack of the header.\n\nProbably L3291 would misread you but it\u0027s needed by annoying fake_http_connect constraint[1] that when we drop the key from the header dict (i.e. del responses[0][2][missing_header]), fake_http_connect insert the default value (1 for X-Backend-Timestamp) automatically.\n\nI will add small comments at the line 3291 for the fact.\n\n1: https://github.com/openstack/swift/blob/master/test/unit/__init__.py#L869","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":3432,"context_line":"        failed_start_at \u003d ("},{"line_number":3433,"context_line":"            self.policy.ec_n_unique_fragments - self.policy.ec_nparity - 1)"},{"line_number":3434,"context_line":""},{"line_number":3435,"context_line":"        # set Timeout for node #10, #11, #12, #13, #14"},{"line_number":3436,"context_line":"        for i in range(self.policy.ec_nparity + 1):"},{"line_number":3437,"context_line":"            responses[failed_start_at + i] \u003d (Timeout(), \u0027\u0027, \u0027\u0027)"},{"line_number":3438,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_a91c946a","line":3435,"updated":"2017-02-26 04:44:21.000000000","message":"it\u0027s nodes 9-13","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":3432,"context_line":"        failed_start_at \u003d ("},{"line_number":3433,"context_line":"            self.policy.ec_n_unique_fragments - self.policy.ec_nparity - 1)"},{"line_number":3434,"context_line":""},{"line_number":3435,"context_line":"        # set Timeout for node #10, #11, #12, #13, #14"},{"line_number":3436,"context_line":"        for i in range(self.policy.ec_nparity + 1):"},{"line_number":3437,"context_line":"            responses[failed_start_at + i] \u003d (Timeout(), \u0027\u0027, \u0027\u0027)"},{"line_number":3438,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_8b16ad53","line":3435,"in_reply_to":"da36d5c6_a91c946a","updated":"2017-02-28 09:01:43.000000000","message":"Correct. Thanks for follow up!","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"}],"test/unit/proxy/controllers/test_obj.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"381bbaf5157aaf99c818b3bab373a9845047ca56","unresolved":false,"context_lines":[{"line_number":3600,"context_line":"        responses \u003d ["},{"line_number":3601,"context_line":"            (200, SlowBody(body, 0.1), self._add_frag_index(i, headers))"},{"line_number":3602,"context_line":"            for i, body in enumerate(ec_archive_bodies)"},{"line_number":3603,"context_line":"        ] * self.policy.ec_duplication_factor"},{"line_number":3604,"context_line":""},{"line_number":3605,"context_line":"        req \u003d swob.Request.blank(\u0027/v1/a/c/o\u0027)"},{"line_number":3606,"context_line":""}],"source_content_type":"text/x-python","patch_set":47,"id":"3a461143_7453236d","line":3603,"updated":"2017-02-02 03:14:49.000000000","message":"it\u0027s subtle little changes like this which make me worry it will be annoying down the road to add new tests to this TestCase.\n\nI like getting test coverage for ec duplication - but I\u0027m worried we\u0027ll trick ourselves into some contortions trying to make this work (e.g. policy.sort_order)","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"381bbaf5157aaf99c818b3bab373a9845047ca56","unresolved":false,"context_lines":[{"line_number":3866,"context_line":"                                 ec_duplication_factor\u003d2),"},{"line_number":3867,"context_line":"                 StoragePolicy(1, name\u003d\u0027unu\u0027)],"},{"line_number":3868,"context_line":"                fake_ring_args\u003d[{\u0027replicas\u0027: 28}, {}])"},{"line_number":3869,"context_line":"class TestECDuplicationObjController(TestECObjController):"},{"line_number":3870,"context_line":"    # TODO: actually \"frags\" in node_frags is meaning \"node_index\" right now"},{"line_number":3871,"context_line":"    # in following tests. Reconsidering the name and semantics change needed."},{"line_number":3872,"context_line":"    # Or, just mapping to be correct as frag_index is enough?."}],"source_content_type":"text/x-python","patch_set":47,"id":"3a461143_94224f00","line":3869,"updated":"2017-02-02 03:14:49.000000000","message":"I\u0027m much more interested in seeing targeted tests for ec_duplication that scatter coverage from hi-jacking the ECObjController tests.\n\nThose tests were written for a different policy with half the nodes storing totally different data fragments - in most cases the backend requests *should* be different.\n\nEven if it works for (or can be made to work) it\u0027s going to harder to build and maintain these tests if every test written in ECObjController has to also pass with a duplicated policy.","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"2671effc57b1f727998acb5e80e3d54c801ba99f","unresolved":false,"context_lines":[{"line_number":3866,"context_line":"                                 ec_duplication_factor\u003d2),"},{"line_number":3867,"context_line":"                 StoragePolicy(1, name\u003d\u0027unu\u0027)],"},{"line_number":3868,"context_line":"                fake_ring_args\u003d[{\u0027replicas\u0027: 28}, {}])"},{"line_number":3869,"context_line":"class TestECDuplicationObjController(TestECObjController):"},{"line_number":3870,"context_line":"    # TODO: actually \"frags\" in node_frags is meaning \"node_index\" right now"},{"line_number":3871,"context_line":"    # in following tests. Reconsidering the name and semantics change needed."},{"line_number":3872,"context_line":"    # Or, just mapping to be correct as frag_index is enough?."}],"source_content_type":"text/x-python","patch_set":47,"id":"1a430d35_2035e645","line":3869,"in_reply_to":"3a461143_94224f00","updated":"2017-02-03 10:42:24.000000000","message":"Hmm... in my first idea, I intended to guarantee the transparent access. And then, override some tests which should have different backend requests but exactly, I\u0027m realizing it could be going to harder to maintain :/","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"18f22649c4317c3b5930fc2b2735de04703e6dcc","unresolved":false,"context_lines":[{"line_number":3867,"context_line":"                 StoragePolicy(1, name\u003d\u0027unu\u0027)],"},{"line_number":3868,"context_line":"                fake_ring_args\u003d[{\u0027replicas\u0027: 28}, {}])"},{"line_number":3869,"context_line":"class TestECDuplicationObjController("},{"line_number":3870,"context_line":"        BaseObjectControllerMixin, unittest.TestCase):"},{"line_number":3871,"context_line":"    container_info \u003d {"},{"line_number":3872,"context_line":"        \u0027status\u0027: 200,"},{"line_number":3873,"context_line":"        \u0027read_acl\u0027: None,"}],"source_content_type":"text/x-python","patch_set":48,"id":"1a430d35_38a965e0","line":3870,"updated":"2017-02-06 01:14:26.000000000","message":"I changed here, not inherit TestECObjController but BaseObjectContollerMixin to avoid any failures with different backend requests in non-duplication EC.\n\nIn today\u0027s work, I\u0027ll continue to think of how we could make the tests more robust.","commit_id":"ce6807ab6fd33d30d7844546c6261951772eb822"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":331,"context_line":"        req \u003d swift.common.swob.Request.blank(\u0027/v1/a/c/o\u0027, method\u003d\u0027DELETE\u0027)"},{"line_number":332,"context_line":"        mostly_404s \u003d [404] * self.quorum()"},{"line_number":333,"context_line":"        if isinstance(self.policy, ECStoragePolicy):"},{"line_number":334,"context_line":"            mostly_404s *\u003d self.policy.ec_duplication_factor"},{"line_number":335,"context_line":"        codes \u003d mostly_404s + [204] * (self.replicas() - len(mostly_404s))"},{"line_number":336,"context_line":"        self.assertEqual(len(codes), self.replicas())"},{"line_number":337,"context_line":"        with set_http_connect(*codes):"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_86fa8e73","line":334,"updated":"2017-02-08 10:06:42.000000000","message":"I think we can drop these if we do the right thing on quorum?\n\nhttps://gist.github.com/clayg/ac96b102c32e0149f8abcb6fe19ecc59","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":331,"context_line":"        req \u003d swift.common.swob.Request.blank(\u0027/v1/a/c/o\u0027, method\u003d\u0027DELETE\u0027)"},{"line_number":332,"context_line":"        mostly_404s \u003d [404] * self.quorum()"},{"line_number":333,"context_line":"        if isinstance(self.policy, ECStoragePolicy):"},{"line_number":334,"context_line":"            mostly_404s *\u003d self.policy.ec_duplication_factor"},{"line_number":335,"context_line":"        codes \u003d mostly_404s + [204] * (self.replicas() - len(mostly_404s))"},{"line_number":336,"context_line":"        self.assertEqual(len(codes), self.replicas())"},{"line_number":337,"context_line":"        with set_http_connect(*codes):"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_e904cb15","line":334,"in_reply_to":"1a430d35_86fa8e73","updated":"2017-02-09 09:36:43.000000000","message":"the gist applied in the new patch set.\nDone","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":4357,"context_line":"        # drop 0, 14 and 1 should work"},{"line_number":4358,"context_line":"        self._test_determine_chunk_destinations_prioritize(0, 14, 1)"},{"line_number":4359,"context_line":"        # drop 1, 15 and 0 should work, too"},{"line_number":4360,"context_line":"        self._test_determine_chunk_destinations_prioritize(1, 15, 0)"},{"line_number":4361,"context_line":""},{"line_number":4362,"context_line":""},{"line_number":4363,"context_line":"if __name__ \u003d\u003d \u0027__main__\u0027:"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_5a7a3b78","line":4360,"updated":"2017-02-08 10:06:42.000000000","message":"So when I take out the lack_list stuff\n\n    diff --git a/swift/proxy/controllers/obj.py b/swift/proxy/controllers/obj.py\n    index a645899..6d7fa24 100644\n    --- a/swift/proxy/controllers/obj.py\n    +++ b/swift/proxy/controllers/obj.py\n    @@ -2358,34 +2358,9 @@ class ECObjectController(BaseObjectController):\n             # nodes. Holes occur when a storage node is down, in which\n             # case the connection is not replaced, and when a storage node\n             # returns 507, in which case a handoff is used to replace it.\n    +        holes \u003d [x for x in range(len(putters))\n    +                 if x not in chunk_index.values()]\n     \n    -        # lack_list is a dict of list to keep hole indexes\n    -        # e.g. if we have 2 holes for index 0 with ec_duplication_factor\u003d2\n    -        # lack_list is like {0: [0], 1: [0]}, and then, if 1 hole found\n    -        # for index 1, lack_list will be {0: [0, 1], 1: [0]}.\n    -        # After that, holes will be filled from bigger key\n    -        # (i.e. 1:[0] at first)\n    -\n    -        # Grouping all missing fragment indexes for each unique_index\n    -        unique_index_to_holes \u003d collections.defaultdict(list)\n    -        available_indexes \u003d chunk_index.values()\n    -        for node_index in range(policy.object_ring.replica_count):\n    -            if node_index not in available_indexes:\n    -                unique_index \u003d policy.get_backend_index(node_index)\n    -                unique_index_to_holes[unique_index].append(node_index)\n    -\n    -        # Set the missing index to lack_list\n    -        lack_list \u003d collections.defaultdict(list)\n    -        for unique_index, holes in unique_index_to_holes.items():\n    -            for lack_tier, hole_node_index in enumerate(holes):\n    -                lack_list[lack_tier].append(hole_node_index)\n    -\n    -        # Extract the lack_list to a flat list\n    -        holes \u003d []\n    -        for lack_tier, indexes in sorted(lack_list.items(), reverse\u003dTrue):\n    -            holes.extend(indexes)\n    -\n    -        # Fill chunk_index list with the hole list\n             for hole, p in zip(holes, handoff_conns):\n                 chunk_index[p] \u003d hole\n             return chunk_index\n\n\n\nThis is the only test that fails.\n\n    ubuntu@saio:~$ nosetests swift/test/unit/proxy/controllers/test_obj.py\n    ....................................F...............................................................................................................................................................................................\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\n    FAIL: test_determine_chunk_destinations_prioritize_more_missing (test.unit.proxy.controllers.test_obj.TestECDuplicationObjController)\n    ----------------------------------------------------------------------\n    Traceback (most recent call last):\n      File \"/home/ubuntu/swift/test/unit/proxy/controllers/test_obj.py\", line 4360, in test_determine_chunk_destinations_prioritize_more_missing\n        self._test_determine_chunk_destinations_prioritize(1, 15, 0)\n      File \"/home/ubuntu/swift/test/unit/proxy/controllers/test_obj.py\", line 4348, in _test_determine_chunk_destinations_prioritize\n        self.assertNotIn(one_more_missing, got.values())\n    AssertionError: 0 unexpectedly found in [26, 24, 23, 0, 22, 21, 3, 20, 19, 18, 17, 16, 2, 14, 25, 13, 12, 11, 10, 9, 27, 8, 7, 6, 5, 4]\n\n    ----------------------------------------------------------------------\n    Ran 228 tests in 4.104s\n\n    FAILED (failures\u003d1)","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"e7145451863651e42029d87619c6717832b0dfbe","unresolved":false,"context_lines":[{"line_number":3040,"context_line":"        self.assertEqual(resp.headers[\u0027etag\u0027], obj3[\u0027etag\u0027])"},{"line_number":3041,"context_line":"        self.assertEqual(md5(resp.body).hexdigest(), obj3[\u0027etag\u0027])"},{"line_number":3042,"context_line":"        self.assertGreaterEqual(len(log), self.policy.ec_ndata + 1)"},{"line_number":3043,"context_line":"        self.assertLessEqual(len(log), self.policy.ec_ndata + 4)"},{"line_number":3044,"context_line":""},{"line_number":3045,"context_line":"    def test_GET_with_missing_durables_and_older_non_durables(self):"},{"line_number":3046,"context_line":"        # scenario: non-durable frags of newer obj1 obscure all frags"}],"source_content_type":"text/x-python","patch_set":55,"id":"1a430d35_5cc74e63","line":3043,"updated":"2017-02-09 13:52:10.000000000","message":"Actually, this is not related to my change but I hit a gate failure here. Looking at the scenario L3003-L3008, when failing with the old assertion, it seems to have all non-durable frags with index 2-13 and then get obj1 with frag 0, 1. That is because obj1 is newer than obj3 durable and the backend fragments list won\u0027t be cared with the durable (only newer obj1 was checked if durable or not. As a result, we have obj1 response bucket with 2 resp and obj3 response bucket with 11 response, both of then non-durable, after that, node provider will pop obj3 as candidate (not preference by durable but just by timestamp order) and we finally find a durable frag so the total responses (backend requests) can be 11 + 2 + 1 \u003d 14.\n\nThat is what I finally get on this.\n\nIs that right?","commit_id":"1e2e67b7f00017f327c4cb28777c899ed050870f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":1374,"context_line":""},{"line_number":1375,"context_line":""},{"line_number":1376,"context_line":"class StubResponse(object):"},{"line_number":1377,"context_line":""},{"line_number":1378,"context_line":"    def __init__(self, status, body\u003d\u0027\u0027, headers\u003dNone, frag_index\u003dNone):"},{"line_number":1379,"context_line":"        self.status \u003d status"},{"line_number":1380,"context_line":"        self.body \u003d body"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_5834d6fa","side":"PARENT","line":1377,"updated":"2017-02-26 04:44:21.000000000","message":"ok relocated to __init__.py","commit_id":"cdd72dd34f879c7340d4c379db955ea82db3cfe2"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":1374,"context_line":""},{"line_number":1375,"context_line":""},{"line_number":1376,"context_line":"class StubResponse(object):"},{"line_number":1377,"context_line":""},{"line_number":1378,"context_line":"    def __init__(self, status, body\u003d\u0027\u0027, headers\u003dNone, frag_index\u003dNone):"},{"line_number":1379,"context_line":"        self.status \u003d status"},{"line_number":1380,"context_line":"        self.body \u003d body"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_4e03e30d","side":"PARENT","line":1377,"in_reply_to":"da36d5c6_5834d6fa","updated":"2017-02-28 09:01:43.000000000","message":"Done","commit_id":"cdd72dd34f879c7340d4c379db955ea82db3cfe2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":2210,"context_line":""},{"line_number":2211,"context_line":"    def _make_ec_object_stub(self, test_body\u003dNone, policy\u003dNone,"},{"line_number":2212,"context_line":"                             timestamp\u003dNone):"},{"line_number":2213,"context_line":"        policy \u003d policy or self.policy"},{"line_number":2214,"context_line":"        segment_size \u003d policy.ec_segment_size"},{"line_number":2215,"context_line":"        test_body \u003d test_body or ("},{"line_number":2216,"context_line":"            \u0027test\u0027 * segment_size)[:-random.randint(1, 1000)]"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_d8052646","side":"PARENT","line":2213,"updated":"2017-02-26 04:44:21.000000000","message":"ok refactored to __init__.py","commit_id":"cdd72dd34f879c7340d4c379db955ea82db3cfe2"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":2210,"context_line":""},{"line_number":2211,"context_line":"    def _make_ec_object_stub(self, test_body\u003dNone, policy\u003dNone,"},{"line_number":2212,"context_line":"                             timestamp\u003dNone):"},{"line_number":2213,"context_line":"        policy \u003d policy or self.policy"},{"line_number":2214,"context_line":"        segment_size \u003d policy.ec_segment_size"},{"line_number":2215,"context_line":"        test_body \u003d test_body or ("},{"line_number":2216,"context_line":"            \u0027test\u0027 * segment_size)[:-random.randint(1, 1000)]"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_ae129f56","side":"PARENT","line":2213,"in_reply_to":"da36d5c6_d8052646","updated":"2017-02-28 09:01:43.000000000","message":"Done","commit_id":"cdd72dd34f879c7340d4c379db955ea82db3cfe2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":2225,"context_line":"            \u0027timestamp\u0027: timestamp"},{"line_number":2226,"context_line":"        }"},{"line_number":2227,"context_line":""},{"line_number":2228,"context_line":"    def _fake_ec_node_response(self, node_frags):"},{"line_number":2229,"context_line":"        \"\"\""},{"line_number":2230,"context_line":"        Given a list of entries for each node in ring order, where the entries"},{"line_number":2231,"context_line":"        are a dict (or list of dicts) which describes the fragment (or"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_1877be02","side":"PARENT","line":2228,"updated":"2017-02-26 04:44:21.000000000","message":"ok moved to unit/__init__.py","commit_id":"cdd72dd34f879c7340d4c379db955ea82db3cfe2"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":2225,"context_line":"            \u0027timestamp\u0027: timestamp"},{"line_number":2226,"context_line":"        }"},{"line_number":2227,"context_line":""},{"line_number":2228,"context_line":"    def _fake_ec_node_response(self, node_frags):"},{"line_number":2229,"context_line":"        \"\"\""},{"line_number":2230,"context_line":"        Given a list of entries for each node in ring order, where the entries"},{"line_number":2231,"context_line":"        are a dict (or list of dicts) which describes the fragment (or"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_ee1c976c","side":"PARENT","line":2228,"in_reply_to":"da36d5c6_1877be02","updated":"2017-02-28 09:01:43.000000000","message":"Done","commit_id":"cdd72dd34f879c7340d4c379db955ea82db3cfe2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":2205,"context_line":"        _part, primary_nodes \u003d self.obj_ring.get_nodes(\u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"},{"line_number":2206,"context_line":""},{"line_number":2207,"context_line":"        node_key \u003d lambda n: (n[\u0027ip\u0027], n[\u0027port\u0027])"},{"line_number":2208,"context_line":"        backend_index \u003d lambda index: self.policy.get_backend_index(index)"},{"line_number":2209,"context_line":"        ts \u003d self._ts_iter.next()"},{"line_number":2210,"context_line":""},{"line_number":2211,"context_line":"        response_map \u003d {"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_7ba194f7","line":2208,"updated":"2017-02-26 04:44:21.000000000","message":"nit lambda not necessary:\n\n  backend_index \u003d self.policy.get_backend_index","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":2205,"context_line":"        _part, primary_nodes \u003d self.obj_ring.get_nodes(\u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"},{"line_number":2206,"context_line":""},{"line_number":2207,"context_line":"        node_key \u003d lambda n: (n[\u0027ip\u0027], n[\u0027port\u0027])"},{"line_number":2208,"context_line":"        backend_index \u003d lambda index: self.policy.get_backend_index(index)"},{"line_number":2209,"context_line":"        ts \u003d self._ts_iter.next()"},{"line_number":2210,"context_line":""},{"line_number":2211,"context_line":"        response_map \u003d {"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_0e31ebec","line":2208,"in_reply_to":"da36d5c6_7ba194f7","updated":"2017-02-28 09:01:43.000000000","message":"Nice catch, done at follow up.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":3040,"context_line":"        self.assertEqual(resp.headers[\u0027etag\u0027], obj3[\u0027etag\u0027])"},{"line_number":3041,"context_line":"        self.assertEqual(md5(resp.body).hexdigest(), obj3[\u0027etag\u0027])"},{"line_number":3042,"context_line":"        self.assertGreaterEqual(len(log), self.policy.ec_ndata + 1)"},{"line_number":3043,"context_line":"        self.assertLessEqual(len(log), self.policy.ec_ndata + 4)"},{"line_number":3044,"context_line":""},{"line_number":3045,"context_line":"    def test_GET_with_missing_durables_and_older_non_durables(self):"},{"line_number":3046,"context_line":"        # scenario: non-durable frags of newer obj1 obscure all frags"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_3b9abc6e","line":3043,"updated":"2017-02-26 04:44:21.000000000","message":"nit: I\u0027m not convinced by this change...\n\nworst case, first ec_ndata responses include 2 frags for obj1 and 1 frag for obj 2, meaning another 3 responses are required.\n\nsee comment line 3461 - possibly same issue","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":3040,"context_line":"        self.assertEqual(resp.headers[\u0027etag\u0027], obj3[\u0027etag\u0027])"},{"line_number":3041,"context_line":"        self.assertEqual(md5(resp.body).hexdigest(), obj3[\u0027etag\u0027])"},{"line_number":3042,"context_line":"        self.assertGreaterEqual(len(log), self.policy.ec_ndata + 1)"},{"line_number":3043,"context_line":"        self.assertLessEqual(len(log), self.policy.ec_ndata + 4)"},{"line_number":3044,"context_line":""},{"line_number":3045,"context_line":"    def test_GET_with_missing_durables_and_older_non_durables(self):"},{"line_number":3046,"context_line":"        # scenario: non-durable frags of newer obj1 obscure all frags"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_8ecebbb2","line":3043,"in_reply_to":"da36d5c6_3b9abc6e","updated":"2017-02-28 09:01:43.000000000","message":"Added a comment at L3461.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":3458,"context_line":"        responses \u003d ["},{"line_number":3459,"context_line":"            (200, SlowBody(body, 0.1), self._add_frag_index(i, headers))"},{"line_number":3460,"context_line":"            for i, body in enumerate(ec_archive_bodies)"},{"line_number":3461,"context_line":"        ] * self.policy.ec_duplication_factor"},{"line_number":3462,"context_line":""},{"line_number":3463,"context_line":"        req \u003d swob.Request.blank(\u0027/v1/a/c/o\u0027)"},{"line_number":3464,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_bbb86c76","line":3461,"updated":"2017-02-26 04:44:21.000000000","message":"nit: this class does not use duplication factor and is not subclassed\n\n(discussed with Kota - this is a hangover from previous patch when TestECDuplicationObjController extended this class)\n\nhappy to fix this in a follow up - it is harmless","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":3458,"context_line":"        responses \u003d ["},{"line_number":3459,"context_line":"            (200, SlowBody(body, 0.1), self._add_frag_index(i, headers))"},{"line_number":3460,"context_line":"            for i, body in enumerate(ec_archive_bodies)"},{"line_number":3461,"context_line":"        ] * self.policy.ec_duplication_factor"},{"line_number":3462,"context_line":""},{"line_number":3463,"context_line":"        req \u003d swob.Request.blank(\u0027/v1/a/c/o\u0027)"},{"line_number":3464,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_2e814f4e","line":3461,"in_reply_to":"da36d5c6_bbb86c76","updated":"2017-02-28 09:01:43.000000000","message":"OK, thank you for catching. I\u0027ll do the refactor and it will resolve this.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":3618,"context_line":"                     \u0027Range\u0027: \u0027bytes\u003d%s\u0027 % (req_range)})"},{"line_number":3619,"context_line":""},{"line_number":3620,"context_line":"        fragments \u003d self.policy.pyeclib_driver.encode(real_body)"},{"line_number":3621,"context_line":"        fragment_payloads \u003d [fragments * self.policy.ec_duplication_factor]"},{"line_number":3622,"context_line":""},{"line_number":3623,"context_line":"        node_fragments \u003d zip(*fragment_payloads)"},{"line_number":3624,"context_line":"        self.assertEqual(len(node_fragments), self.replicas())  # sanity"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_5b4db098","line":3621,"updated":"2017-02-26 04:44:21.000000000","message":"nit: needless changes, see comment line 3461","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":3618,"context_line":"                     \u0027Range\u0027: \u0027bytes\u003d%s\u0027 % (req_range)})"},{"line_number":3619,"context_line":""},{"line_number":3620,"context_line":"        fragments \u003d self.policy.pyeclib_driver.encode(real_body)"},{"line_number":3621,"context_line":"        fragment_payloads \u003d [fragments * self.policy.ec_duplication_factor]"},{"line_number":3622,"context_line":""},{"line_number":3623,"context_line":"        node_fragments \u003d zip(*fragment_payloads)"},{"line_number":3624,"context_line":"        self.assertEqual(len(node_fragments), self.replicas())  # sanity"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_cec0b37f","line":3621,"in_reply_to":"da36d5c6_5b4db098","updated":"2017-02-28 09:01:43.000000000","message":"ok, I should work for the refactor anyway.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":3695,"context_line":"        self.assertEqual("},{"line_number":3696,"context_line":"            len(backend_chunks), policy.object_ring.replica_count)"},{"line_number":3697,"context_line":"        self.assertEqual([\u0027\u0027] * policy.object_ring.replica_count,"},{"line_number":3698,"context_line":"                         backend_chunks)"},{"line_number":3699,"context_line":""},{"line_number":3700,"context_line":"    def test_chunk_transformer_duplication_factor_non_aligned_last_chunk(self):"},{"line_number":3701,"context_line":"        last_chunk \u003d \u0027a\u0027 * 128"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_eee5c008","line":3698,"updated":"2017-02-26 04:44:21.000000000","message":"nit: do same for non-duplication tests. in fact, the two tests could easily be refactored to share common check","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":3695,"context_line":"        self.assertEqual("},{"line_number":3696,"context_line":"            len(backend_chunks), policy.object_ring.replica_count)"},{"line_number":3697,"context_line":"        self.assertEqual([\u0027\u0027] * policy.object_ring.replica_count,"},{"line_number":3698,"context_line":"                         backend_chunks)"},{"line_number":3699,"context_line":""},{"line_number":3700,"context_line":"    def test_chunk_transformer_duplication_factor_non_aligned_last_chunk(self):"},{"line_number":3701,"context_line":"        last_chunk \u003d \u0027a\u0027 * 128"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_ce47d31b","line":3698,"in_reply_to":"da36d5c6_eee5c008","updated":"2017-02-28 09:01:43.000000000","message":"Oh, nice. this has been addressed at follow-up.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":3697,"context_line":"        self.assertEqual([\u0027\u0027] * policy.object_ring.replica_count,"},{"line_number":3698,"context_line":"                         backend_chunks)"},{"line_number":3699,"context_line":""},{"line_number":3700,"context_line":"    def test_chunk_transformer_duplication_factor_non_aligned_last_chunk(self):"},{"line_number":3701,"context_line":"        last_chunk \u003d \u0027a\u0027 * 128"},{"line_number":3702,"context_line":"        policy \u003d ECStoragePolicy(0, \u0027ec8-2\u0027, ec_type\u003dDEFAULT_TEST_EC_TYPE,"},{"line_number":3703,"context_line":"                                 ec_ndata\u003d8, ec_nparity\u003d2,"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_8eb36409","line":3700,"updated":"2017-02-26 04:44:21.000000000","message":"nit: add same test without duplication factor","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":3697,"context_line":"        self.assertEqual([\u0027\u0027] * policy.object_ring.replica_count,"},{"line_number":3698,"context_line":"                         backend_chunks)"},{"line_number":3699,"context_line":""},{"line_number":3700,"context_line":"    def test_chunk_transformer_duplication_factor_non_aligned_last_chunk(self):"},{"line_number":3701,"context_line":"        last_chunk \u003d \u0027a\u0027 * 128"},{"line_number":3702,"context_line":"        policy \u003d ECStoragePolicy(0, \u0027ec8-2\u0027, ec_type\u003dDEFAULT_TEST_EC_TYPE,"},{"line_number":3703,"context_line":"                                 ec_ndata\u003d8, ec_nparity\u003d2,"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_4e6203af","line":3700,"in_reply_to":"da36d5c6_8eb36409","updated":"2017-02-28 09:01:43.000000000","message":"ditto","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":3867,"context_line":"        # ... and the rests are 404s which is limited by request_count"},{"line_number":3868,"context_line":"        # (2 * replicas in default) rather than max_extra_count limitation"},{"line_number":3869,"context_line":"        # because the retries will be in ResumingGetter if the responses"},{"line_number":3870,"context_line":"        # are 404s"},{"line_number":3871,"context_line":"        node_frags +\u003d [[]] * (self.replicas() * 2 - len(node_frags))"},{"line_number":3872,"context_line":"        fake_response \u003d self._fake_ec_node_response(node_frags)"},{"line_number":3873,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_c92e288b","line":3870,"updated":"2017-02-26 04:44:21.000000000","message":"yes!","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":3867,"context_line":"        # ... and the rests are 404s which is limited by request_count"},{"line_number":3868,"context_line":"        # (2 * replicas in default) rather than max_extra_count limitation"},{"line_number":3869,"context_line":"        # because the retries will be in ResumingGetter if the responses"},{"line_number":3870,"context_line":"        # are 404s"},{"line_number":3871,"context_line":"        node_frags +\u003d [[]] * (self.replicas() * 2 - len(node_frags))"},{"line_number":3872,"context_line":"        fake_response \u003d self._fake_ec_node_response(node_frags)"},{"line_number":3873,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_2e04efc4","line":3870,"in_reply_to":"da36d5c6_c92e288b","updated":"2017-02-28 09:01:43.000000000","message":"Done","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":3938,"context_line":"                collected_indexes[fi].append(conn)"},{"line_number":3939,"context_line":"        self.assertEqual(len(collected_indexes), self.policy.ec_ndata - 1)"},{"line_number":3940,"context_line":""},{"line_number":3941,"context_line":"    def test_GET_with_many_missed_overwrite_will_need_handoff(self):"},{"line_number":3942,"context_line":"        obj1 \u003d self._make_ec_object_stub()"},{"line_number":3943,"context_line":"        obj2 \u003d self._make_ec_object_stub()"},{"line_number":3944,"context_line":"        # primaries"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_e984cc5e","line":3941,"updated":"2017-02-26 04:44:21.000000000","message":"feels like it ought to be possible to parameterise the superclass test rather than override and duplicate so much code?","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":3938,"context_line":"                collected_indexes[fi].append(conn)"},{"line_number":3939,"context_line":"        self.assertEqual(len(collected_indexes), self.policy.ec_ndata - 1)"},{"line_number":3940,"context_line":""},{"line_number":3941,"context_line":"    def test_GET_with_many_missed_overwrite_will_need_handoff(self):"},{"line_number":3942,"context_line":"        obj1 \u003d self._make_ec_object_stub()"},{"line_number":3943,"context_line":"        obj2 \u003d self._make_ec_object_stub()"},{"line_number":3944,"context_line":"        # primaries"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_aee61f14","line":3941,"in_reply_to":"da36d5c6_e984cc5e","updated":"2017-02-28 09:01:43.000000000","message":"might be... in the refactoring?","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":3991,"context_line":"        # ... regardless we should never need to fetch more than ec_ndata"},{"line_number":3992,"context_line":"        # frags for any given etag"},{"line_number":3993,"context_line":"        for etag, frags in collected_responses.items():"},{"line_number":3994,"context_line":"            self.assertTrue(len(frags) \u003c\u003d self.policy.ec_ndata,"},{"line_number":3995,"context_line":"                            \u0027collected %s frags for etag %s\u0027 % ("},{"line_number":3996,"context_line":"                                len(frags), etag))"},{"line_number":3997,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_a9b8142b","line":3994,"updated":"2017-02-26 04:44:21.000000000","message":"use assertLessEqual","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":3991,"context_line":"        # ... regardless we should never need to fetch more than ec_ndata"},{"line_number":3992,"context_line":"        # frags for any given etag"},{"line_number":3993,"context_line":"        for etag, frags in collected_responses.items():"},{"line_number":3994,"context_line":"            self.assertTrue(len(frags) \u003c\u003d self.policy.ec_ndata,"},{"line_number":3995,"context_line":"                            \u0027collected %s frags for etag %s\u0027 % ("},{"line_number":3996,"context_line":"                                len(frags), etag))"},{"line_number":3997,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_4ebe83d5","line":3994,"in_reply_to":"da36d5c6_a9b8142b","updated":"2017-02-28 09:01:43.000000000","message":"Resolved at follow-up.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":4079,"context_line":"            [],"},{"line_number":4080,"context_line":"        ]"},{"line_number":4081,"context_line":""},{"line_number":4082,"context_line":"        node_frags +\u003d [[]] * 13  # Plus 13 nodes in handoff"},{"line_number":4083,"context_line":""},{"line_number":4084,"context_line":"        # finally 10th fragment for obj2 found"},{"line_number":4085,"context_line":"        node_frags +\u003d [[{\u0027obj\u0027: obj2, \u0027frag\u0027: 9}]]"},{"line_number":4086,"context_line":""},{"line_number":4087,"context_line":"        fake_response \u003d self._fake_ec_node_response(node_frags)"},{"line_number":4088,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_694e1c3c","line":4085,"range":{"start_line":4082,"start_character":1,"end_line":4085,"end_character":50},"updated":"2017-02-26 04:44:21.000000000","message":"this is the difference w.r.t. superclass method - but is this change actually specific to duplication factor \u003d\u003d 2?","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":4079,"context_line":"            [],"},{"line_number":4080,"context_line":"        ]"},{"line_number":4081,"context_line":""},{"line_number":4082,"context_line":"        node_frags +\u003d [[]] * 13  # Plus 13 nodes in handoff"},{"line_number":4083,"context_line":""},{"line_number":4084,"context_line":"        # finally 10th fragment for obj2 found"},{"line_number":4085,"context_line":"        node_frags +\u003d [[{\u0027obj\u0027: obj2, \u0027frag\u0027: 9}]]"},{"line_number":4086,"context_line":""},{"line_number":4087,"context_line":"        fake_response \u003d self._fake_ec_node_response(node_frags)"},{"line_number":4088,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_8e5ebb74","line":4085,"range":{"start_line":4082,"start_character":1,"end_line":4085,"end_character":50},"in_reply_to":"da36d5c6_694e1c3c","updated":"2017-02-28 09:01:43.000000000","message":"Ah... perhaps, the # of nodes was incorrect. I\n\nI think this is affected from request_node_count and max_extra_request discussion.\n\nI suppose this test should be something like \u0027the 10th fragment found at the last candidate node\u0027.\n\nI\u0027ll care of that in the refactoring work. Thanks.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":4108,"context_line":"        # ... regardless we should never need to fetch more than ec_ndata"},{"line_number":4109,"context_line":"        # frags for any given etag"},{"line_number":4110,"context_line":"        for etag, frags in collected_responses.items():"},{"line_number":4111,"context_line":"            self.assertTrue(len(frags) \u003c\u003d self.policy.ec_ndata,"},{"line_number":4112,"context_line":"                            \u0027collected %s frags for etag %s\u0027 % ("},{"line_number":4113,"context_line":"                                len(frags), etag))"},{"line_number":4114,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_6999bcc3","line":4111,"updated":"2017-02-26 04:44:21.000000000","message":"use assertLessEqual","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":4108,"context_line":"        # ... regardless we should never need to fetch more than ec_ndata"},{"line_number":4109,"context_line":"        # frags for any given etag"},{"line_number":4110,"context_line":"        for etag, frags in collected_responses.items():"},{"line_number":4111,"context_line":"            self.assertTrue(len(frags) \u003c\u003d self.policy.ec_ndata,"},{"line_number":4112,"context_line":"                            \u0027collected %s frags for etag %s\u0027 % ("},{"line_number":4113,"context_line":"                                len(frags), etag))"},{"line_number":4114,"context_line":""}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_aeda9fe7","line":4111,"in_reply_to":"da36d5c6_6999bcc3","updated":"2017-02-28 09:01:43.000000000","message":"Done","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":4329,"context_line":""},{"line_number":4330,"context_line":"        # and then, pop a fragment which has same fragment index with unique"},{"line_number":4331,"context_line":"        self.assertEqual("},{"line_number":4332,"context_line":"            unique, self.policy.get_backend_index(duplicated))  # sanity"},{"line_number":4333,"context_line":"        putters.pop(duplicated)"},{"line_number":4334,"context_line":""},{"line_number":4335,"context_line":"        # pop one more frag ment too to make one missing hole"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_c9e1c82b","line":4332,"updated":"2017-02-26 04:44:21.000000000","message":"if this is true then why pass both unique and duplicated as args, it would be sufficient to only pass duplicated to this method","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":4329,"context_line":""},{"line_number":4330,"context_line":"        # and then, pop a fragment which has same fragment index with unique"},{"line_number":4331,"context_line":"        self.assertEqual("},{"line_number":4332,"context_line":"            unique, self.policy.get_backend_index(duplicated))  # sanity"},{"line_number":4333,"context_line":"        putters.pop(duplicated)"},{"line_number":4334,"context_line":""},{"line_number":4335,"context_line":"        # pop one more frag ment too to make one missing hole"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_2e494f8f","line":4332,"in_reply_to":"da36d5c6_c9e1c82b","updated":"2017-02-28 09:01:43.000000000","message":"Er, probably\n\n # sanity\n self.assertEqual(unique, self.policy.get_backend_index(unique))\n\ncould help us from broken tests.\n\nWill add it to the top of this test helper.","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":4336,"context_line":"        putters.pop(one_more_missing)"},{"line_number":4337,"context_line":""},{"line_number":4338,"context_line":"        # then determine chunk, we have 26 putters here and unique frag"},{"line_number":4339,"context_line":"        # index 0 missing 2 copies and unique frag index 1 missing 1 copy"},{"line_number":4340,"context_line":"        # i.e. the handoff node should be assigned to unique frag index 1"},{"line_number":4341,"context_line":"        got \u003d controller._determine_chunk_destinations(putters, self.policy)"},{"line_number":4342,"context_line":"        self.assertEqual(len(expected) - 2, len(got))"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_49431813","line":4339,"updated":"2017-02-26 04:44:21.000000000","message":"this comment confused me - what are the unique frag index 0 and 1?","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":4336,"context_line":"        putters.pop(one_more_missing)"},{"line_number":4337,"context_line":""},{"line_number":4338,"context_line":"        # then determine chunk, we have 26 putters here and unique frag"},{"line_number":4339,"context_line":"        # index 0 missing 2 copies and unique frag index 1 missing 1 copy"},{"line_number":4340,"context_line":"        # i.e. the handoff node should be assigned to unique frag index 1"},{"line_number":4341,"context_line":"        got \u003d controller._determine_chunk_destinations(putters, self.policy)"},{"line_number":4342,"context_line":"        self.assertEqual(len(expected) - 2, len(got))"}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_7925d35a","line":4339,"in_reply_to":"da36d5c6_49431813","updated":"2017-02-28 09:01:43.000000000","message":"I meant, for the 10-4 x 2 case, frag index 0, 14 are indexes for unique frag index 0...\n\nAh... I found the message is not generalize and it could confuse you, make sense. The description explains only for the L4355 test case so possibly better docs will be like:\n\n  # we have 26 putters here and frag index \"unique\" missing 2\n  # copies. (i.e. missing \"unique\" and  \"duplicated\" which \n  # should be same unique index). Then \"one_more_missing\" frag \n  # is different from both of the \"unique\" and \"duplicated\"\n  # but it\u0027s only 1 copy missing so that the handoff node should\n  # be assigned to either \"unique\" or \"duplicated\" prior to\n  # \"one_more_missing\"\n\nDoes it make you sense?","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"}],"test/unit/proxy/test_server.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"381bbaf5157aaf99c818b3bab373a9845047ca56","unresolved":false,"context_lines":[{"line_number":5547,"context_line":""},{"line_number":5548,"context_line":""},{"line_number":5549,"context_line":"@patch_policies([StoragePolicy(0, \u0027zero\u0027, True,"},{"line_number":5550,"context_line":"                               object_ring\u003dFakeRing(base_port\u003d3000))])"},{"line_number":5551,"context_line":"class TestObjectControllerECDuplication(ECTestMixin, unittest.TestCase):"},{"line_number":5552,"context_line":"    ec_policy_index \u003d 4"},{"line_number":5553,"context_line":""}],"source_content_type":"text/x-python","patch_set":47,"id":"3a461143_34dc3b46","line":5550,"updated":"2017-02-02 03:14:49.000000000","message":"None of the tests mixed into the TestCase do *not* @unpatch_policies - this isn\u0027t needed - test still pass without it.\n\nThis test module is huge a mess [1].  This change makes it much worse.\n\nI don\u0027t think we need to do this.  I think we\u0027re trying to get away with not writing tests targeted at ec_duplication.  If we want to splatter cover the happy path we should use a in-process functional test job.\n\nWe can make a handful of non-socket unittests in proxy.controller.test_obj that cover the bases and a few error conditions and we\u0027ll be a lot happier maintenance wise than doing this.\n\n1. https://launchpad.net/bugs/1646963","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"2671effc57b1f727998acb5e80e3d54c801ba99f","unresolved":false,"context_lines":[{"line_number":5547,"context_line":""},{"line_number":5548,"context_line":""},{"line_number":5549,"context_line":"@patch_policies([StoragePolicy(0, \u0027zero\u0027, True,"},{"line_number":5550,"context_line":"                               object_ring\u003dFakeRing(base_port\u003d3000))])"},{"line_number":5551,"context_line":"class TestObjectControllerECDuplication(ECTestMixin, unittest.TestCase):"},{"line_number":5552,"context_line":"    ec_policy_index \u003d 4"},{"line_number":5553,"context_line":""}],"source_content_type":"text/x-python","patch_set":47,"id":"1a430d35_a0e556a9","line":5550,"in_reply_to":"3a461143_34dc3b46","updated":"2017-02-03 10:42:24.000000000","message":"Oh, yes, so on your opinion, we don\u0027t have to have the unit tests for ec duplication but it could be into in-process testing.","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"381bbaf5157aaf99c818b3bab373a9845047ca56","unresolved":false,"context_lines":[{"line_number":5655,"context_line":"            resp \u003d get_req.get_response(prosrv)"},{"line_number":5656,"context_line":"        self.assertEqual(resp.status_int, 503)"},{"line_number":5657,"context_line":""},{"line_number":5658,"context_line":"    def test_mixing_different_objects_fragment_archives_with_dup_factor(self):"},{"line_number":5659,"context_line":"        (prosrv, acc1srv, acc2srv, con1srv, con2srv, obj1srv,"},{"line_number":5660,"context_line":"         obj2srv, obj3srv, obj4srv, obj5srv, obj6srv) \u003d _test_servers"},{"line_number":5661,"context_line":""}],"source_content_type":"text/x-python","patch_set":47,"id":"3a461143_94916f55","line":5658,"updated":"2017-02-02 03:14:49.000000000","message":"wow, so this entire test case is using the socket servers so it doesn\u0027t have to unpatch policies.","commit_id":"647c96a163eb54fa1df6817e452a8c5536d95069"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"18f22649c4317c3b5930fc2b2735de04703e6dcc","unresolved":false,"context_lines":[{"line_number":5547,"context_line":""},{"line_number":5548,"context_line":""},{"line_number":5549,"context_line":"@patch_policies([StoragePolicy(0, \u0027zero\u0027, True,"},{"line_number":5550,"context_line":"                               object_ring\u003dFakeRing(base_port\u003d3000))])"},{"line_number":5551,"context_line":"class TestObjectControllerECDuplication(ECTestMixin, unittest.TestCase):"},{"line_number":5552,"context_line":"    ec_policy_index \u003d 4"},{"line_number":5553,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"1a430d35_d8822152","line":5550,"updated":"2017-02-06 01:14:26.000000000","message":"Clayg: I re-add this patch_policies here. I didn\u0027t get all about of this yet but the removal causes a bunch of test failures on your patch [1]\n\nThis also my WIP in today\u0027s work to make sure why we need patch_policies for EC test cases.\n\n1: https://review.openstack.org/#/c/427994","commit_id":"ce6807ab6fd33d30d7844546c6261951772eb822"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"e8b4df90cc2ea86645452cc971f73b423aa42797","unresolved":false,"context_lines":[{"line_number":5547,"context_line":""},{"line_number":5548,"context_line":""},{"line_number":5549,"context_line":"@patch_policies([StoragePolicy(0, \u0027zero\u0027, True,"},{"line_number":5550,"context_line":"                               object_ring\u003dFakeRing(base_port\u003d3000))])"},{"line_number":5551,"context_line":"class TestObjectControllerECDuplication(ECTestMixin, unittest.TestCase):"},{"line_number":5552,"context_line":"    ec_policy_index \u003d 4"},{"line_number":5553,"context_line":""}],"source_content_type":"text/x-python","patch_set":48,"id":"1a430d35_31cb3ba7","line":5550,"in_reply_to":"1a430d35_d8822152","updated":"2017-02-06 08:43:22.000000000","message":"Ah, ok. I finally got the reason why we did need the patch_policies here. In older patch set, this test inherited TestObjectController *and it makes some weird requirements to cleanup in tearDown at L5563. And it affects some tests even though all of tests in ECTestMixin are unpatched so we need both this decorator and tearDown from this class to work well with the Mixin.","commit_id":"ce6807ab6fd33d30d7844546c6261951772eb822"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":2174,"context_line":""},{"line_number":2175,"context_line":"    @unpatch_policies"},{"line_number":2176,"context_line":"    def test_PUT_ec_if_none_match(self):"},{"line_number":2177,"context_line":"        self.put_container(\"ec\", \"ec-con\")"},{"line_number":2178,"context_line":""},{"line_number":2179,"context_line":"        obj \u003d \u0027ananepionic-lepidophyllous-ropewalker-neglectful\u0027"},{"line_number":2180,"context_line":"        prolis \u003d _test_sockets[0]"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_90a2bf97","side":"PARENT","line":2177,"updated":"2017-02-08 10:06:42.000000000","message":"this was different right?","commit_id":"b1c36dc154061413ecd86d5fb19243a30f107512"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":2174,"context_line":""},{"line_number":2175,"context_line":"    @unpatch_policies"},{"line_number":2176,"context_line":"    def test_PUT_ec_if_none_match(self):"},{"line_number":2177,"context_line":"        self.put_container(\"ec\", \"ec-con\")"},{"line_number":2178,"context_line":""},{"line_number":2179,"context_line":"        obj \u003d \u0027ananepionic-lepidophyllous-ropewalker-neglectful\u0027"},{"line_number":2180,"context_line":"        prolis \u003d _test_sockets[0]"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_29cc13ba","side":"PARENT","line":2177,"in_reply_to":"1a430d35_90a2bf97","updated":"2017-02-09 09:36:43.000000000","message":"Yes, please see my response at L1558","commit_id":"b1c36dc154061413ecd86d5fb19243a30f107512"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":3126,"context_line":"        finally:"},{"line_number":3127,"context_line":"            policy.object_ring._rtime \u003d orig_rtime"},{"line_number":3128,"context_line":"            os.rename(policy.object_ring.serialized_path + \u0027.bak\u0027,"},{"line_number":3129,"context_line":"                      policy.object_ring.serialized_path)"},{"line_number":3130,"context_line":""},{"line_number":3131,"context_line":"    def test_custom_mime_types_files(self):"},{"line_number":3132,"context_line":"        swift_dir \u003d mkdtemp()"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_93400936","side":"PARENT","line":3129,"updated":"2017-02-08 10:06:42.000000000","message":"jerking around all the tests in this diff module really hurt this change for me.\n\nAdding in unrelated cleanup/refactoring made it even harder (moving prolis \u003d _test_sockets[0] to the top of the test method, etc)\n\nBut i\u0027ve reviewed it now!  I can\u0027t say for sure there\u0027s no changes in there I missed.  But I mostly like starting to move the the unpatch_policies tests out of this TestCase?","commit_id":"b1c36dc154061413ecd86d5fb19243a30f107512"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6496ede5d44b14721d236b641a23b3cf2258eb67","unresolved":false,"context_lines":[{"line_number":1555,"context_line":"    @unpatch_policies"},{"line_number":1556,"context_line":"    def test_PUT_ec_if_none_match(self):"},{"line_number":1557,"context_line":"        ec_policy \u003d POLICIES[self.ec_policy_index]"},{"line_number":1558,"context_line":"        self.put_container(ec_policy.name, ec_policy.name)"},{"line_number":1559,"context_line":""},{"line_number":1560,"context_line":"        obj \u003d \u0027ananepionic-lepidophyllous-ropewalker-neglectful\u0027"},{"line_number":1561,"context_line":"        prolis \u003d _test_sockets[0]"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_30974b3b","line":1558,"updated":"2017-02-08 10:06:42.000000000","message":"why was this line changed?\n\nbecause it doesn\u0027t matter:\n\n    def put_container(self, policy_name, container_name):","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"6d5774022e9344d2b86357725e31c5cee463837f","unresolved":false,"context_lines":[{"line_number":1555,"context_line":"    @unpatch_policies"},{"line_number":1556,"context_line":"    def test_PUT_ec_if_none_match(self):"},{"line_number":1557,"context_line":"        ec_policy \u003d POLICIES[self.ec_policy_index]"},{"line_number":1558,"context_line":"        self.put_container(ec_policy.name, ec_policy.name)"},{"line_number":1559,"context_line":""},{"line_number":1560,"context_line":"        obj \u003d \u0027ananepionic-lepidophyllous-ropewalker-neglectful\u0027"},{"line_number":1561,"context_line":"        prolis \u003d _test_sockets[0]"}],"source_content_type":"text/x-python","patch_set":53,"id":"1a430d35_c9eb8f11","line":1558,"in_reply_to":"1a430d35_30974b3b","updated":"2017-02-09 09:36:43.000000000","message":"Not sure it could be still there but I hit some errors on the put_container. That is because now we\u0027re doing those tests for both normal ec policy and duplicate ec policy.\n\nAt that time, it seems the old container could be remaining (not cleanup completely) on some tests and it causes conflicts as \"the container already exists with a different policy\". To avoid that, I set the container_name being as the policy name which can not be same with different policies.","commit_id":"33fe68248a51b829cbccae58a5d0f28be243f7b9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f7fa6be9ea5550a37d950e2ce3c3f6a3175e5c3b","unresolved":false,"context_lines":[{"line_number":1160,"context_line":"        self.app.account_ring.set_replicas(3)"},{"line_number":1161,"context_line":"        self.app.container_ring.set_replicas(3)"},{"line_number":1162,"context_line":"        for policy in POLICIES:"},{"line_number":1163,"context_line":"            policy.object_ring \u003d FakeRing(base_port\u003d3000)"},{"line_number":1164,"context_line":""},{"line_number":1165,"context_line":"    def put_container(self, policy_name, container_name):"},{"line_number":1166,"context_line":"        # Note: only works if called with unpatched policies"}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_c4504161","side":"PARENT","line":1163,"updated":"2017-02-22 17:08:31.000000000","message":"ok this code just moved unchanged","commit_id":"cdd72dd34f879c7340d4c379db955ea82db3cfe2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f7fa6be9ea5550a37d950e2ce3c3f6a3175e5c3b","unresolved":false,"context_lines":[{"line_number":1784,"context_line":"        self.assertEqual(got_byteranges[2], obj[2000:2501])"},{"line_number":1785,"context_line":""},{"line_number":1786,"context_line":"    @unpatch_policies"},{"line_number":1787,"context_line":"    def test_PUT_ec(self):"},{"line_number":1788,"context_line":"        policy \u003d POLICIES[3]"},{"line_number":1789,"context_line":"        self.put_container(\"ec\", \"ec-con\")"},{"line_number":1790,"context_line":""}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_64a07544","side":"PARENT","line":1787,"updated":"2017-02-22 17:08:31.000000000","message":"ok this code chunk moved to ECTestMixin and was parameterized for policy","commit_id":"cdd72dd34f879c7340d4c379db955ea82db3cfe2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f7fa6be9ea5550a37d950e2ce3c3f6a3175e5c3b","unresolved":false,"context_lines":[{"line_number":1144,"context_line":""},{"line_number":1145,"context_line":""},{"line_number":1146,"context_line":"class ECTestMixin(object):"},{"line_number":1147,"context_line":"    def put_container(self, policy_name, container_name):"},{"line_number":1148,"context_line":"        # Note: only works if called with unpatched policies"},{"line_number":1149,"context_line":"        prolis \u003d _test_sockets[0]"},{"line_number":1150,"context_line":"        sock \u003d connect_tcp((\u0027localhost\u0027, prolis.getsockname()[1]))"}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_a426edcb","line":1147,"updated":"2017-02-22 17:08:31.000000000","message":"ok this helper method is only used in ec policy tests so does not need to move with other TestObjectController code","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f7fa6be9ea5550a37d950e2ce3c3f6a3175e5c3b","unresolved":false,"context_lines":[{"line_number":1380,"context_line":"        self.put_container(ec_policy.name, ec_policy.name)"},{"line_number":1381,"context_line":""},{"line_number":1382,"context_line":"        # Cause a hash mismatch by feeding one particular MD5 hasher some"},{"line_number":1383,"context_line":"        # extra data. The goal here is to get exactly one of the hashers in"},{"line_number":1384,"context_line":"        # an object server."},{"line_number":1385,"context_line":"        count \u003d (ec_policy.object_ring.replica_count - ec_policy.ec_ndata)"},{"line_number":1386,"context_line":"        countdown \u003d [count]"}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_aa0dd93f","line":1383,"updated":"2017-02-22 17:08:31.000000000","message":"coment is stale - is now more than one bad hasher","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"94e3bdf80e8a54a5b84ad7413aa4c07869130515","unresolved":false,"context_lines":[{"line_number":1380,"context_line":"        self.put_container(ec_policy.name, ec_policy.name)"},{"line_number":1381,"context_line":""},{"line_number":1382,"context_line":"        # Cause a hash mismatch by feeding one particular MD5 hasher some"},{"line_number":1383,"context_line":"        # extra data. The goal here is to get exactly one of the hashers in"},{"line_number":1384,"context_line":"        # an object server."},{"line_number":1385,"context_line":"        count \u003d (ec_policy.object_ring.replica_count - ec_policy.ec_ndata)"},{"line_number":1386,"context_line":"        countdown \u003d [count]"}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_490aa222","line":1383,"in_reply_to":"da36d5c6_aa0dd93f","updated":"2017-02-22 18:52:53.000000000","message":"Done","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f7fa6be9ea5550a37d950e2ce3c3f6a3175e5c3b","unresolved":false,"context_lines":[{"line_number":1429,"context_line":"                # diskfile open won\u0027t succeed because no durable was"},{"line_number":1430,"context_line":"                # written, so look under the hood for data files."},{"line_number":1431,"context_line":"                files \u003d os.listdir(df._datadir)"},{"line_number":1432,"context_line":"                if len(files) \u003e 0:"},{"line_number":1433,"context_line":"                    num_data_files \u003d len("},{"line_number":1434,"context_line":"                        [f for f in files if f.endswith(\u0027.data\u0027)])"},{"line_number":1435,"context_line":"                    found +\u003d 1"}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_55088291","line":1432,"updated":"2017-02-22 17:08:31.000000000","message":"looks like a rebase has lost a comment here, these lines were:\n\n                  if len(files) \u003e 0:\n                    # Although the third fragment archive hasn\u0027t landed on\n                    # disk, the directory df._datadir is pre-maturely created\n                    # and is empty when we use O_TMPFILE + linkat()\n                    num_data_files \u003d \\\n                        len([f for f in files if f.endswith(\u0027.data\u0027)])\n                    self.assertEqual(1, num_data_files)\n                    found +\u003d 1","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"94e3bdf80e8a54a5b84ad7413aa4c07869130515","unresolved":false,"context_lines":[{"line_number":1429,"context_line":"                # diskfile open won\u0027t succeed because no durable was"},{"line_number":1430,"context_line":"                # written, so look under the hood for data files."},{"line_number":1431,"context_line":"                files \u003d os.listdir(df._datadir)"},{"line_number":1432,"context_line":"                if len(files) \u003e 0:"},{"line_number":1433,"context_line":"                    num_data_files \u003d len("},{"line_number":1434,"context_line":"                        [f for f in files if f.endswith(\u0027.data\u0027)])"},{"line_number":1435,"context_line":"                    found +\u003d 1"}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_29080e91","line":1432,"in_reply_to":"da36d5c6_55088291","updated":"2017-02-22 18:52:53.000000000","message":"Good catch! Thanks! Done with your paste.","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f7fa6be9ea5550a37d950e2ce3c3f6a3175e5c3b","unresolved":false,"context_lines":[{"line_number":1436,"context_line":"                    self.assertEqual(1, num_data_files)"},{"line_number":1437,"context_line":"            except OSError:"},{"line_number":1438,"context_line":"                pass"},{"line_number":1439,"context_line":"        self.assertEqual(found, ec_policy.ec_ndata)"},{"line_number":1440,"context_line":""},{"line_number":1441,"context_line":"    @unpatch_policies"},{"line_number":1442,"context_line":"    def test_PUT_ec_fragment_quorum_archive_etag_mismatch(self):"}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_955e7a74","line":1439,"updated":"2017-02-22 17:08:31.000000000","message":"so before the assertion was found\u003d\u003d2, now we have found\u003d\u003dec_ndata - is that because before the policy was fixed as POLICIES[3]","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"94e3bdf80e8a54a5b84ad7413aa4c07869130515","unresolved":false,"context_lines":[{"line_number":1436,"context_line":"                    self.assertEqual(1, num_data_files)"},{"line_number":1437,"context_line":"            except OSError:"},{"line_number":1438,"context_line":"                pass"},{"line_number":1439,"context_line":"        self.assertEqual(found, ec_policy.ec_ndata)"},{"line_number":1440,"context_line":""},{"line_number":1441,"context_line":"    @unpatch_policies"},{"line_number":1442,"context_line":"    def test_PUT_ec_fragment_quorum_archive_etag_mismatch(self):"}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_d9c66367","line":1439,"in_reply_to":"da36d5c6_955e7a74","updated":"2017-02-22 18:52:53.000000000","message":"Yes! POLICIES[3] is ec_k \u003d 2, ec_m \u003d 1 and quorum should be 3 (ec_k + 1). so 2 .data (not durable) found.\n\nNow, this test has been changed as ec_k responses return correct etag which is still less than quorum, so ec_k frags will be in the disks. (they\u0027re still not durable though)","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f7fa6be9ea5550a37d950e2ce3c3f6a3175e5c3b","unresolved":false,"context_lines":[{"line_number":1739,"context_line":"    def test_conditional_GET_ec(self):"},{"line_number":1740,"context_line":"        policy \u003d POLICIES[self.ec_policy_index]"},{"line_number":1741,"context_line":"        self.assertEqual(\u0027erasure_coding\u0027, policy.policy_type)  # sanity"},{"line_number":1742,"context_line":"        self._test_conditional_GET(policy)"},{"line_number":1743,"context_line":""},{"line_number":1744,"context_line":"    @unpatch_policies"},{"line_number":1745,"context_line":"    def test_GET_ec_big(self):"}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_d06e4095","line":1742,"updated":"2017-02-22 17:08:31.000000000","message":"ok the matching test for conditional replication GET is now at around line 2700","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f7fa6be9ea5550a37d950e2ce3c3f6a3175e5c3b","unresolved":false,"context_lines":[{"line_number":1752,"context_line":"        # our EC segment size is 4 KiB, so this is multiple (3) segments;"},{"line_number":1753,"context_line":"        # we\u0027ll verify that with a sanity check"},{"line_number":1754,"context_line":"        obj \u003d \u0027a moose once bit my sister\u0027 * 400"},{"line_number":1755,"context_line":"        self.assertTrue("},{"line_number":1756,"context_line":"            len(obj) \u003e ec_policy.ec_segment_size * 2,"},{"line_number":1757,"context_line":"            \"object is too small for proper testing\")"},{"line_number":1758,"context_line":""}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_30907c43","line":1755,"updated":"2017-02-22 17:08:31.000000000","message":"rebase error? this was assertGreater at line 2372","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"94e3bdf80e8a54a5b84ad7413aa4c07869130515","unresolved":false,"context_lines":[{"line_number":1752,"context_line":"        # our EC segment size is 4 KiB, so this is multiple (3) segments;"},{"line_number":1753,"context_line":"        # we\u0027ll verify that with a sanity check"},{"line_number":1754,"context_line":"        obj \u003d \u0027a moose once bit my sister\u0027 * 400"},{"line_number":1755,"context_line":"        self.assertTrue("},{"line_number":1756,"context_line":"            len(obj) \u003e ec_policy.ec_segment_size * 2,"},{"line_number":1757,"context_line":"            \"object is too small for proper testing\")"},{"line_number":1758,"context_line":""}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_e930b6ea","line":1755,"in_reply_to":"da36d5c6_30907c43","updated":"2017-02-22 18:52:53.000000000","message":"Done with your paste.","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f7fa6be9ea5550a37d950e2ce3c3f6a3175e5c3b","unresolved":false,"context_lines":[{"line_number":1982,"context_line":"        self.assertEqual(len(warn_lines), 0)  # sanity"},{"line_number":1983,"context_line":""},{"line_number":1984,"context_line":"    @unpatch_policies"},{"line_number":1985,"context_line":"    def test_reload_ring_ec(self):"},{"line_number":1986,"context_line":"        policy \u003d POLICIES[self.ec_policy_index]"},{"line_number":1987,"context_line":"        self.put_container(\"ec\", \"ec-con\")"},{"line_number":1988,"context_line":""}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_102c58aa","line":1985,"updated":"2017-02-22 17:08:31.000000000","message":"ok. this test was at line 3041, only changes are parameterized expected original replica count","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f7fa6be9ea5550a37d950e2ce3c3f6a3175e5c3b","unresolved":false,"context_lines":[{"line_number":2080,"context_line":"class TestObjectController(ECTestMixin, unittest.TestCase):"},{"line_number":2081,"context_line":"    ec_policy_index \u003d 3"},{"line_number":2082,"context_line":""},{"line_number":2083,"context_line":"    def setUp(self):"},{"line_number":2084,"context_line":"        self.app \u003d proxy_server.Application("},{"line_number":2085,"context_line":"            None, FakeMemcache(),"},{"line_number":2086,"context_line":"            logger\u003ddebug_logger(\u0027proxy-ut\u0027),"},{"line_number":2087,"context_line":"            account_ring\u003dFakeRing(),"},{"line_number":2088,"context_line":"            container_ring\u003dFakeRing())"},{"line_number":2089,"context_line":"        # clear proxy logger result for each test"},{"line_number":2090,"context_line":"        _test_servers[0].logger._clear()"},{"line_number":2091,"context_line":""},{"line_number":2092,"context_line":"    def tearDown(self):"},{"line_number":2093,"context_line":"        self.app.account_ring.set_replicas(3)"},{"line_number":2094,"context_line":"        self.app.container_ring.set_replicas(3)"},{"line_number":2095,"context_line":"        for policy in POLICIES:"},{"line_number":2096,"context_line":"            policy.object_ring \u003d FakeRing(base_port\u003d3000)"},{"line_number":2097,"context_line":""},{"line_number":2098,"context_line":"    def assert_status_map(self, method, statuses, expected, raise_exc\u003dFalse):"},{"line_number":2099,"context_line":"        with save_globals():"}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_e4e625b3","line":2096,"range":{"start_line":2083,"start_character":0,"end_line":2096,"end_character":57},"updated":"2017-02-22 17:08:31.000000000","message":"ok this chunk of code just moved unchanged","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f7fa6be9ea5550a37d950e2ce3c3f6a3175e5c3b","unresolved":false,"context_lines":[{"line_number":4460,"context_line":"    def test_chunked_put_bad_version(self):"},{"line_number":4461,"context_line":"        # Check bad version"},{"line_number":4462,"context_line":"        (prolis, acc1lis, acc2lis, con1lis, con2lis, obj1lis,"},{"line_number":4463,"context_line":"         obj2lis, obj3lis, obj4lis, obj5lis, obj6lis) \u003d _test_sockets"},{"line_number":4464,"context_line":"        sock \u003d connect_tcp((\u0027localhost\u0027, prolis.getsockname()[1]))"},{"line_number":4465,"context_line":"        fd \u003d sock.makefile()"},{"line_number":4466,"context_line":"        fd.write(\u0027GET /v0 HTTP/1.1\\r\\nHost: localhost\\r\\n\u0027"}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_242d9d46","line":4463,"updated":"2017-02-22 17:08:31.000000000","message":"#follow-up refactor this method to return a dict now that the return tuple has got so long???","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"94e3bdf80e8a54a5b84ad7413aa4c07869130515","unresolved":false,"context_lines":[{"line_number":4460,"context_line":"    def test_chunked_put_bad_version(self):"},{"line_number":4461,"context_line":"        # Check bad version"},{"line_number":4462,"context_line":"        (prolis, acc1lis, acc2lis, con1lis, con2lis, obj1lis,"},{"line_number":4463,"context_line":"         obj2lis, obj3lis, obj4lis, obj5lis, obj6lis) \u003d _test_sockets"},{"line_number":4464,"context_line":"        sock \u003d connect_tcp((\u0027localhost\u0027, prolis.getsockname()[1]))"},{"line_number":4465,"context_line":"        fd \u003d sock.makefile()"},{"line_number":4466,"context_line":"        fd.write(\u0027GET /v0 HTTP/1.1\\r\\nHost: localhost\\r\\n\u0027"}],"source_content_type":"text/x-python","patch_set":58,"id":"da36d5c6_09750a97","line":4463,"in_reply_to":"da36d5c6_242d9d46","updated":"2017-02-22 18:52:53.000000000","message":"good call for followup. IIRC, Clay also has an opinion about the setup because obj4, 5, 6 is only used in ECDuplication.\n\nPerhaps... in addition to your suggestion, configurable setup for each Test class could be worth in the future rather than setup whole at once?","commit_id":"4bb5ce1c17b1fa8f3c30081075d3ce074051415d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5afd0458da9c67ea410ac98a3068ad56db501ff1","unresolved":false,"context_lines":[{"line_number":5665,"context_line":"            environ\u003d{\"REQUEST_METHOD\": \"PUT\"},"},{"line_number":5666,"context_line":"            headers\u003d{\"X-Storage-Policy\": \"ec-dup\", \"X-Auth-Token\": \"t\"})"},{"line_number":5667,"context_line":"        resp \u003d ensure_container.get_response(prosrv)"},{"line_number":5668,"context_line":"        self.assertTrue(resp.status_int in (201, 202))"},{"line_number":5669,"context_line":""},{"line_number":5670,"context_line":"        obj1 \u003d \"first version...\""},{"line_number":5671,"context_line":"        put_req1 \u003d Request.blank("}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_495a38f3","line":5668,"updated":"2017-02-26 04:44:21.000000000","message":"use assertIn - the original method on which this is based has assertIn and it is the preferred pattern","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"047aca34a64b69c72b26a199ef3357063d3c0627","unresolved":false,"context_lines":[{"line_number":5665,"context_line":"            environ\u003d{\"REQUEST_METHOD\": \"PUT\"},"},{"line_number":5666,"context_line":"            headers\u003d{\"X-Storage-Policy\": \"ec-dup\", \"X-Auth-Token\": \"t\"})"},{"line_number":5667,"context_line":"        resp \u003d ensure_container.get_response(prosrv)"},{"line_number":5668,"context_line":"        self.assertTrue(resp.status_int in (201, 202))"},{"line_number":5669,"context_line":""},{"line_number":5670,"context_line":"        obj1 \u003d \"first version...\""},{"line_number":5671,"context_line":"        put_req1 \u003d Request.blank("}],"source_content_type":"text/x-python","patch_set":60,"id":"da36d5c6_b9c90b5d","line":5668,"in_reply_to":"da36d5c6_495a38f3","updated":"2017-02-28 09:01:43.000000000","message":"Done at the follow-up","commit_id":"40ba7f6172465c2f9bc63fb6f4d24f8bb5f96ef9"}]}
