)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":19,"context_line":"- Moves most of the functionality of ECPutter into a generic Putter"},{"line_number":20,"context_line":"  class that is used for replicated object PUTs without footers."},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"- Creates a MIMEPutter subclass to support  multipart and multiphase"},{"line_number":23,"context_line":"  behaviour required for any replicated object PUT with footers and"},{"line_number":24,"context_line":"  all EC PUTs."},{"line_number":25,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"7aa08908_0ee5fca2","line":22,"range":{"start_line":22,"start_character":42,"end_line":22,"end_character":44},"updated":"2016-06-14 05:17:47.000000000","message":"nit: doubled-up space","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":19,"context_line":"- Moves most of the functionality of ECPutter into a generic Putter"},{"line_number":20,"context_line":"  class that is used for replicated object PUTs without footers."},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"- Creates a MIMEPutter subclass to support  multipart and multiphase"},{"line_number":23,"context_line":"  behaviour required for any replicated object PUT with footers and"},{"line_number":24,"context_line":"  all EC PUTs."},{"line_number":25,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"7aa08908_1a6cbacf","line":22,"range":{"start_line":22,"start_character":42,"end_line":22,"end_character":44},"in_reply_to":"7aa08908_0ee5fca2","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":23,"context_line":"  behaviour required for any replicated object PUT with footers and"},{"line_number":24,"context_line":"  all EC PUTs."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"- modifies ReplicatedObjectController to use Putter objects in place"},{"line_number":27,"context_line":"  of raw connection objects."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"- refactors the _get_put_reponses method and called methods so that"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"7aa08908_0e417c63","line":26,"range":{"start_line":26,"start_character":2,"end_line":26,"end_character":3},"updated":"2016-06-14 05:17:47.000000000","message":"nit: the previous two items started with a capital letter; the next two start lower-case. We should probably pick one.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":23,"context_line":"  behaviour required for any replicated object PUT with footers and"},{"line_number":24,"context_line":"  all EC PUTs."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"- modifies ReplicatedObjectController to use Putter objects in place"},{"line_number":27,"context_line":"  of raw connection objects."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"- refactors the _get_put_reponses method and called methods so that"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"7aa08908_fa70cea6","line":26,"range":{"start_line":26,"start_character":2,"end_line":26,"end_character":3},"in_reply_to":"7aa08908_0e417c63","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":26,"context_line":"- modifies ReplicatedObjectController to use Putter objects in place"},{"line_number":27,"context_line":"  of raw connection objects."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"- refactors the _get_put_reponses method and called methods so that"},{"line_number":30,"context_line":"  more code is in the BaseObjectController class and therefore shared"},{"line_number":31,"context_line":"  by [EC|Replicated]ObjectController classes."},{"line_number":32,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"7aa08908_0e385ced","line":29,"range":{"start_line":29,"start_character":45,"end_line":29,"end_character":59},"updated":"2016-06-14 05:17:47.000000000","message":"What are \"called methods\"? Or rather, what methods *aren\u0027t* called? Can we just delete them? :P","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":26,"context_line":"- modifies ReplicatedObjectController to use Putter objects in place"},{"line_number":27,"context_line":"  of raw connection objects."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"- refactors the _get_put_reponses method and called methods so that"},{"line_number":30,"context_line":"  more code is in the BaseObjectController class and therefore shared"},{"line_number":31,"context_line":"  by [EC|Replicated]ObjectController classes."},{"line_number":32,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"7aa08908_1adb1a51","line":29,"range":{"start_line":29,"start_character":45,"end_line":29,"end_character":59},"in_reply_to":"7aa08908_0e385ced","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":44,"context_line":"value rather than the EC fragment Etag."},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"Encryption will also need to add a pointer to an encrypted Etag value"},{"line_number":47,"context_line":"that *may* have been stored with an object, so the"},{"line_number":48,"context_line":"X-Backend-Etag-Is-At value is changed to support a list of possible"},{"line_number":49,"context_line":"locations for alternate Etag values. Encryption will place its"},{"line_number":50,"context_line":"expected alternative Etag location on this list, as will the"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"7aa08908_102cfa97","line":47,"range":{"start_line":47,"start_character":5,"end_line":47,"end_character":42},"updated":"2016-06-14 05:17:47.000000000","message":"Maybe worth highlighting the expected cases where it wouldn\u0027t have been set. Something like this?\n\n\u003e Encryption will also need to add a pointer to an encrypted Etag value. However, the referenced sysmeta may not exist, for example if the object was created before encryption was enabled. As a result, the X-Backend-Etag-Is-At value...","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":44,"context_line":"value rather than the EC fragment Etag."},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"Encryption will also need to add a pointer to an encrypted Etag value"},{"line_number":47,"context_line":"that *may* have been stored with an object, so the"},{"line_number":48,"context_line":"X-Backend-Etag-Is-At value is changed to support a list of possible"},{"line_number":49,"context_line":"locations for alternate Etag values. Encryption will place its"},{"line_number":50,"context_line":"expected alternative Etag location on this list, as will the"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"7aa08908_1a979a3b","line":47,"range":{"start_line":47,"start_character":5,"end_line":47,"end_character":42},"in_reply_to":"7aa08908_102cfa97","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"7c67bcd4ba086ad0e54759183d76105bcdee689b","unresolved":false,"context_lines":[{"line_number":57,"context_line":""},{"line_number":58,"context_line":"Co-Authored-By: Alistair Coles \u003calistair.coles@hpe.com\u003e"},{"line_number":59,"context_line":"Co-Authored-By: Thiago da Silva \u003cthiago@redhat.com\u003e"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"Change-Id: I12a6e41150f90de746ce03623032b83ed1987ee1"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"7aa08908_b75323e1","line":60,"updated":"2016-06-14 18:48:57.000000000","message":"Probably deserves an UpgradeImpact. If your proxy has a (third-party) middleware that uses X-Backend-Etag-Is-At and it upgrades before an object server it\u0027s talking to, conditional requests will be broken.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":57,"context_line":""},{"line_number":58,"context_line":"Co-Authored-By: Alistair Coles \u003calistair.coles@hpe.com\u003e"},{"line_number":59,"context_line":"Co-Authored-By: Thiago da Silva \u003cthiago@redhat.com\u003e"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"Change-Id: I12a6e41150f90de746ce03623032b83ed1987ee1"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"7aa08908_9c18a777","line":60,"in_reply_to":"7aa08908_b75323e1","updated":"2016-06-15 15:20:40.000000000","message":"Done.\n\nI thought about how the upgrade issue could be avoided by inventing another header (X-Backend-Etag-Is-Also-At?) but couldn\u0027t see a way to guarantee no upgrade impact. If we were to continue to respect X-Backend-Etag-Is-At that may have been set by another middleware then we wouldn\u0027t know where in the order of precedence it should be w.r.t. the list if alternates. And we can\u0027t assume that the other middleware has done the right thing and used setdefault when setting X-Backend-Etag-Is-At, meaning we can\u0027t assume that if the other middleware were to come to right of encrypter, it wouldn\u0027t erroneously override the encrypter\u0027s value.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"}],"swift/common/request_helpers.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":561,"context_line":"    :param name: name of a sysmeta where alternative etag may be found"},{"line_number":562,"context_line":"    \"\"\""},{"line_number":563,"context_line":"    existing \u003d req.headers.get(\"X-Backend-Etag-Is-At\")"},{"line_number":564,"context_line":"    req.headers[\"X-Backend-Etag-Is-At\"] \u003d csv_append("},{"line_number":565,"context_line":"        existing, name)"},{"line_number":566,"context_line":""},{"line_number":567,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_f0d84e20","line":564,"updated":"2016-06-14 05:17:47.000000000","message":"Is it worth adding something like\n\n if \u0027,\u0027 in name:\n     raise ValueError(\u0027header name may not contain commas\u0027)\n\n?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":561,"context_line":"    :param name: name of a sysmeta where alternative etag may be found"},{"line_number":562,"context_line":"    \"\"\""},{"line_number":563,"context_line":"    existing \u003d req.headers.get(\"X-Backend-Etag-Is-At\")"},{"line_number":564,"context_line":"    req.headers[\"X-Backend-Etag-Is-At\"] \u003d csv_append("},{"line_number":565,"context_line":"        existing, name)"},{"line_number":566,"context_line":""},{"line_number":567,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_2e924ef6","line":564,"in_reply_to":"7aa08908_f0d84e20","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":582,"context_line":"    alternate_etag \u003d None"},{"line_number":583,"context_line":"    if \"X-Backend-Etag-Is-At\" in req.headers:"},{"line_number":584,"context_line":"        names \u003d list_from_csv(req.headers[\"X-Backend-Etag-Is-At\"])"},{"line_number":585,"context_line":"        for name in names:"},{"line_number":586,"context_line":"            if name in metadata:"},{"line_number":587,"context_line":"                alternate_etag \u003d metadata.get(name)"},{"line_number":588,"context_line":"                break"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_14cbff72","line":585,"updated":"2016-06-15 12:15:22.000000000","message":"Can we assume the priority order of Etags as First In as High?\n\nThis resolver looks to search the csv from the first item in the list. That means the resolver always look up the most left side Etag in the list if the name in the metadata. Is it...correct?\n\nI have to look at other code to think this but even if we have both encryption etag and ec etag in the metadata, this resolver seems to return always only one (the first appended item) of them. Am I missing something?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":582,"context_line":"    alternate_etag \u003d None"},{"line_number":583,"context_line":"    if \"X-Backend-Etag-Is-At\" in req.headers:"},{"line_number":584,"context_line":"        names \u003d list_from_csv(req.headers[\"X-Backend-Etag-Is-At\"])"},{"line_number":585,"context_line":"        for name in names:"},{"line_number":586,"context_line":"            if name in metadata:"},{"line_number":587,"context_line":"                alternate_etag \u003d metadata.get(name)"},{"line_number":588,"context_line":"                break"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_1c5b17f8","line":585,"in_reply_to":"7aa08908_14cbff72","updated":"2016-06-15 15:20:40.000000000","message":"The left most value in X-Backend-Etag-Is-At will have been set by the left most middleware, or if no middleware, by ECObjectController, if EC policy. The left most middleware is assumed to be the authority on what the etag value of the object content is.\n\nSo, the resolver will work from left to right in the list until it finds a value that is a name in the given metadata. So the left most winds, IF it exists in the metadata.\n\nThat way, if an object is not encrypted then the resolver will not find the encrytper\u0027s alternate etag sysmeta (X-Object-Sysmeta-Crypto-Etag) but will then find the EC alternate etag (if EC policy). But if the object is encrypted then X-Object-Sysmeta-Crypto-Etag is found and used, which is correct but it should be preferred over X-Object-Sysmeta-Crypto-Etag.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"7a198a346c6cc54243a42dc1773da6ec841f5849","unresolved":false,"context_lines":[{"line_number":582,"context_line":"    alternate_etag \u003d None"},{"line_number":583,"context_line":"    if \"X-Backend-Etag-Is-At\" in req.headers:"},{"line_number":584,"context_line":"        names \u003d list_from_csv(req.headers[\"X-Backend-Etag-Is-At\"])"},{"line_number":585,"context_line":"        for name in names:"},{"line_number":586,"context_line":"            if name in metadata:"},{"line_number":587,"context_line":"                alternate_etag \u003d metadata.get(name)"},{"line_number":588,"context_line":"                break"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_d524b20f","line":585,"in_reply_to":"7aa08908_1c5b17f8","updated":"2016-06-15 18:41:35.000000000","message":"Maybe stick this explanation in the docstring? It really cleared things up for me.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7e38683ba7481db6934a5be9ee9ad8bffa9e6d6c","unresolved":false,"context_lines":[{"line_number":582,"context_line":"    alternate_etag \u003d None"},{"line_number":583,"context_line":"    if \"X-Backend-Etag-Is-At\" in req.headers:"},{"line_number":584,"context_line":"        names \u003d list_from_csv(req.headers[\"X-Backend-Etag-Is-At\"])"},{"line_number":585,"context_line":"        for name in names:"},{"line_number":586,"context_line":"            if name in metadata:"},{"line_number":587,"context_line":"                alternate_etag \u003d metadata.get(name)"},{"line_number":588,"context_line":"                break"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_8715d84a","line":585,"in_reply_to":"7aa08908_d524b20f","updated":"2016-06-15 19:24:48.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":584,"context_line":"        names \u003d list_from_csv(req.headers[\"X-Backend-Etag-Is-At\"])"},{"line_number":585,"context_line":"        for name in names:"},{"line_number":586,"context_line":"            if name in metadata:"},{"line_number":587,"context_line":"                alternate_etag \u003d metadata.get(name)"},{"line_number":588,"context_line":"                break"},{"line_number":589,"context_line":"    return alternate_etag"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_302c9601","line":587,"range":{"start_line":587,"start_character":33,"end_line":587,"end_character":51},"updated":"2016-06-14 05:17:47.000000000","message":"nit: could just be metadata[name]","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":584,"context_line":"        names \u003d list_from_csv(req.headers[\"X-Backend-Etag-Is-At\"])"},{"line_number":585,"context_line":"        for name in names:"},{"line_number":586,"context_line":"            if name in metadata:"},{"line_number":587,"context_line":"                alternate_etag \u003d metadata.get(name)"},{"line_number":588,"context_line":"                break"},{"line_number":589,"context_line":"    return alternate_etag"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_ae6bdeef","line":587,"range":{"start_line":587,"start_character":33,"end_line":587,"end_character":51},"in_reply_to":"7aa08908_302c9601","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"}],"swift/obj/server.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"7aa08908_6e71200c","updated":"2016-06-14 05:17:47.000000000","message":"So obj server already had footer support for replicated policies? Nice.\n\nBut, assuming:\n- you\u0027re upgrading from pre-EC swift and\n- you turned on encryption (or some other footers-using middleware) as part of the upgrade,\n\nhow much is it going to suck if a proxy upgrades before an object server?\n\nMaybe not too much. From Id38f7e93e3473f19ff88123ae0501000ed9b2e89,\n\n\u003e For sanity during a rolling upgrade, the multipart MIME document is only sent to the object server if it indicates, via 100 Continue header, that it knows how to consume it.\n\n(Though note that it\u0027s less \"won\u0027t send a footer\", more \"will abort the upload\". Probably with a 503?)\n\nSince we changed the semantics of X-Backend-Etag-Is-At, though, a new-proxy talking to old-object-server will still cause issues in the GET path (even for post-EC swift) if you\u0027re using an EC policy. Worth including in an UpgradeImpact?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"7aa08908_647635a5","in_reply_to":"7aa08908_6e71200c","updated":"2016-06-15 15:20:40.000000000","message":"We\u0027ve made X-Backend-Etag-Is-At extensible but I\u0027m not sure we have changed anything for  EC-only usage, so I\u0027m not sure *this* patch has an UpgradeImpact.\n\nWe are with the feature as a whole requiring backend upgrade for encryption to work e.g. we need transient object sysmeta and the persistent container override header support for encryption (but not for encryption-less upgrade). So yes, UpgradeImpact should be on that patch.\n\nI\u0027m not sure how we have handled upgrade to new features that require backend support in the past e.g. when sysmeta was first introduced and then was taken advantage of by middlewares (IIRC Account level ACLs was first use of sysmeta).","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":832,"context_line":"                keep_cache \u003d (self.keep_cache_private or"},{"line_number":833,"context_line":"                              (\u0027X-Auth-Token\u0027 not in request.headers and"},{"line_number":834,"context_line":"                               \u0027X-Storage-Token\u0027 not in request.headers))"},{"line_number":835,"context_line":"                conditional_etag \u003d resolve_etag_is_at_header(request, metadata)"},{"line_number":836,"context_line":"                response \u003d Response("},{"line_number":837,"context_line":"                    app_iter\u003ddisk_file.reader(keep_cache\u003dkeep_cache),"},{"line_number":838,"context_line":"                    request\u003drequest, conditional_response\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_541584e3","line":835,"updated":"2016-06-15 12:15:22.000000000","message":"Ok, this is a caller of resolve_etag_is_at_header.\n\nmemo)\nX-Backend-Etag-Is-At should be...\n\nencryption, ec\n\nso that resolver pick up the conditional etag of encryption.\n\nI\u0027m wondering why we have to have the Etag-Is-At as csv? The etag should be determined as uniquely for an object. i.e. the updater does just like as:\n\n  if not \u0027X-Backend-Etag-Is-At\u0027 in request.headers:\n    request.headers[\u0027X-Backend-Etag-Is-At\u0027] \u003d value","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":832,"context_line":"                keep_cache \u003d (self.keep_cache_private or"},{"line_number":833,"context_line":"                              (\u0027X-Auth-Token\u0027 not in request.headers and"},{"line_number":834,"context_line":"                               \u0027X-Storage-Token\u0027 not in request.headers))"},{"line_number":835,"context_line":"                conditional_etag \u003d resolve_etag_is_at_header(request, metadata)"},{"line_number":836,"context_line":"                response \u003d Response("},{"line_number":837,"context_line":"                    app_iter\u003ddisk_file.reader(keep_cache\u003dkeep_cache),"},{"line_number":838,"context_line":"                    request\u003drequest, conditional_response\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_3ca9b391","line":835,"in_reply_to":"7aa08908_541584e3","updated":"2016-06-15 15:20:40.000000000","message":"No, we need the list because the first \u0027Is-At\u0027 location in the list may not in fact exist in object sysmeta.\n\nSpecifically, the encrypter sets X-Backend-Etag-Is-At\u003dX-Object-Sysmeta-Crypto-Etag, but if the object was PUT before encryption was enabled then that sysmeta does not exist, and in that case for an EC policy X-Object-Sysmeta-EC-Etag should be used.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"}],"swift/proxy/controllers/obj.py":[{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":291,"context_line":""},{"line_number":292,"context_line":"        return headers"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"    def _get_conn_response(self, conn, req, logger_thread_locals,"},{"line_number":295,"context_line":"                           final_phase, **kwargs):"},{"line_number":296,"context_line":"        self.app.logger.thread_locals \u003d logger_thread_locals"},{"line_number":297,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_57a8e677","line":294,"range":{"start_line":294,"start_character":33,"end_line":294,"end_character":37},"updated":"2016-06-15 12:15:22.000000000","message":"This is not a BufferredHTTPConnection (or HTTPConnection) anymore but Putter. Thus we should change the variable name from \"conn\" to \"putter\". Otherwise, readers may look at swift/common/bufferedhttp looking for the await_response implementation at line 298 but nothing found with tears like as me :,P","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":291,"context_line":""},{"line_number":292,"context_line":"        return headers"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"    def _get_conn_response(self, conn, req, logger_thread_locals,"},{"line_number":295,"context_line":"                           final_phase, **kwargs):"},{"line_number":296,"context_line":"        self.app.logger.thread_locals \u003d logger_thread_locals"},{"line_number":297,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_1feb097a","line":294,"range":{"start_line":294,"start_character":33,"end_line":294,"end_character":37},"in_reply_to":"7aa08908_57a8e677","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":295,"context_line":"                           final_phase, **kwargs):"},{"line_number":296,"context_line":"        self.app.logger.thread_locals \u003d logger_thread_locals"},{"line_number":297,"context_line":"        try:"},{"line_number":298,"context_line":"            resp \u003d conn.await_response(self.app.node_timeout, not final_phase)"},{"line_number":299,"context_line":"        except (Exception, Timeout):"},{"line_number":300,"context_line":"            resp \u003d None"},{"line_number":301,"context_line":"            if final_phase:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_574906b7","line":298,"updated":"2016-06-15 12:15:22.000000000","message":"so this is Putter.await_response()","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":295,"context_line":"                           final_phase, **kwargs):"},{"line_number":296,"context_line":"        self.app.logger.thread_locals \u003d logger_thread_locals"},{"line_number":297,"context_line":"        try:"},{"line_number":298,"context_line":"            resp \u003d conn.await_response(self.app.node_timeout, not final_phase)"},{"line_number":299,"context_line":"        except (Exception, Timeout):"},{"line_number":300,"context_line":"            resp \u003d None"},{"line_number":301,"context_line":"            if final_phase:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_79cce261","line":298,"in_reply_to":"7aa08908_574906b7","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":301,"context_line":"            if final_phase:"},{"line_number":302,"context_line":"                status_type \u003d \u0027final\u0027"},{"line_number":303,"context_line":"            else:"},{"line_number":304,"context_line":"                status_type \u003d \u0027commit\u0027"},{"line_number":305,"context_line":"            self.app.exception_occurred("},{"line_number":306,"context_line":"                conn.node, _(\u0027Object\u0027),"},{"line_number":307,"context_line":"                _(\u0027Trying to get %(status_type)s status of PUT to %(path)s\u0027) %"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_b05fe63f","line":304,"range":{"start_line":304,"start_character":31,"end_line":304,"end_character":37},"updated":"2016-06-14 05:17:47.000000000","message":"Is \"commit\" the best description here? This is triggered when we\u0027re waiting on responses *before* sending the commit, right? Eh, I suppose it came from ECObjectController\u0027s _get_conn_response. No need to change it now.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":301,"context_line":"            if final_phase:"},{"line_number":302,"context_line":"                status_type \u003d \u0027final\u0027"},{"line_number":303,"context_line":"            else:"},{"line_number":304,"context_line":"                status_type \u003d \u0027commit\u0027"},{"line_number":305,"context_line":"            self.app.exception_occurred("},{"line_number":306,"context_line":"                conn.node, _(\u0027Object\u0027),"},{"line_number":307,"context_line":"                _(\u0027Trying to get %(status_type)s status of PUT to %(path)s\u0027) %"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_f9061284","line":304,"range":{"start_line":304,"start_character":31,"end_line":304,"end_character":37},"in_reply_to":"7aa08908_b05fe63f","updated":"2016-06-15 15:20:40.000000000","message":"follow up","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":304,"context_line":"                status_type \u003d \u0027commit\u0027"},{"line_number":305,"context_line":"            self.app.exception_occurred("},{"line_number":306,"context_line":"                conn.node, _(\u0027Object\u0027),"},{"line_number":307,"context_line":"                _(\u0027Trying to get %(status_type)s status of PUT to %(path)s\u0027) %"},{"line_number":308,"context_line":"                {\u0027status_type\u0027: status_type, \u0027path\u0027: req.path})"},{"line_number":309,"context_line":"        return (conn, resp)"},{"line_number":310,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_b33b70d0","line":307,"updated":"2016-06-14 05:17:47.000000000","message":"Is it intentional that we don\u0027t translate status_type? This will change the log message for replicated errors... though I suppose the alternative is to change the log messages for EC errors...","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":304,"context_line":"                status_type \u003d \u0027commit\u0027"},{"line_number":305,"context_line":"            self.app.exception_occurred("},{"line_number":306,"context_line":"                conn.node, _(\u0027Object\u0027),"},{"line_number":307,"context_line":"                _(\u0027Trying to get %(status_type)s status of PUT to %(path)s\u0027) %"},{"line_number":308,"context_line":"                {\u0027status_type\u0027: status_type, \u0027path\u0027: req.path})"},{"line_number":309,"context_line":"        return (conn, resp)"},{"line_number":310,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_c46a8919","line":307,"in_reply_to":"7aa08908_b33b70d0","updated":"2016-06-15 15:20:40.000000000","message":"Interesting. You\u0027re right, with this change, for replication policies, \u0027final\u0027 would no longer be translated. But for EC it never was. Not sure what to do about that.\n\nScares me that someone might have tooling that depended on the translation of \u0027final\u0027, given that there is almost zero oversight of the stability of the translations. Meaning, the translation could change and none of us swift devs are likely to know about it anyway.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":314,"context_line":"        PUT handling."},{"line_number":315,"context_line":""},{"line_number":316,"context_line":"        :param statuses: a list of response statuses."},{"line_number":317,"context_line":"        :param num_nodes: number of backend nodes to which PUT requests may be"},{"line_number":318,"context_line":"                          issued."},{"line_number":319,"context_line":"        :param min_responses: (optional) minimum number of nodes required to"},{"line_number":320,"context_line":"                              have responded with satisfactory status code."}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_0495d831","line":317,"updated":"2016-06-14 05:17:47.000000000","message":"We can\u0027t just use len(statuses)?\n\nIs it a subtle difference between number of requests issued (`num_nodes`) and number of responses received (`len(statuses)`)?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":314,"context_line":"        PUT handling."},{"line_number":315,"context_line":""},{"line_number":316,"context_line":"        :param statuses: a list of response statuses."},{"line_number":317,"context_line":"        :param num_nodes: number of backend nodes to which PUT requests may be"},{"line_number":318,"context_line":"                          issued."},{"line_number":319,"context_line":"        :param min_responses: (optional) minimum number of nodes required to"},{"line_number":320,"context_line":"                              have responded with satisfactory status code."}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_fdf2b76d","line":317,"in_reply_to":"7aa08908_0495d831","updated":"2016-06-15 15:20:40.000000000","message":"I think that the number of statuses is not necessarily equal to number of nodes when puts fail to backends.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":321,"context_line":"        :return: True if sufficient backend responses have returned a"},{"line_number":322,"context_line":"                 satisfactory status code."},{"line_number":323,"context_line":"        \"\"\""},{"line_number":324,"context_line":"        raise NotImplementedError"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"    def _get_put_responses(self, req, putters, num_nodes, final_phase\u003dTrue,"},{"line_number":327,"context_line":"                           min_responses\u003dNone):"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_e2114e06","line":324,"updated":"2016-06-15 12:15:22.000000000","message":"nits) s/NotImplementedError/NotImplementedError()/\n\nIt needs instantiation with ().","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d8d695ae47b9b30e92f4bb1ff426217b1b8b786b","unresolved":false,"context_lines":[{"line_number":321,"context_line":"        :return: True if sufficient backend responses have returned a"},{"line_number":322,"context_line":"                 satisfactory status code."},{"line_number":323,"context_line":"        \"\"\""},{"line_number":324,"context_line":"        raise NotImplementedError"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"    def _get_put_responses(self, req, putters, num_nodes, final_phase\u003dTrue,"},{"line_number":327,"context_line":"                           min_responses\u003dNone):"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_879f8764","line":324,"in_reply_to":"7aa08908_a550e2d5","updated":"2016-06-16 06:41:39.000000000","message":"Alright, gotcha.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":321,"context_line":"        :return: True if sufficient backend responses have returned a"},{"line_number":322,"context_line":"                 satisfactory status code."},{"line_number":323,"context_line":"        \"\"\""},{"line_number":324,"context_line":"        raise NotImplementedError"},{"line_number":325,"context_line":""},{"line_number":326,"context_line":"    def _get_put_responses(self, req, putters, num_nodes, final_phase\u003dTrue,"},{"line_number":327,"context_line":"                           min_responses\u003dNone):"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_a550e2d5","line":324,"in_reply_to":"7aa08908_e2114e06","updated":"2016-06-15 15:20:40.000000000","message":"Python syntax allows to raise a class or an instance: https://docs.python.org/2.7/tutorial/errors.html#raising-exceptions\n\nThis syntax is already used elsewhere in swift","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":347,"context_line":"        pile \u003d GreenAsyncPile(len(putters))"},{"line_number":348,"context_line":"        for putter in putters:"},{"line_number":349,"context_line":"            # sanity check"},{"line_number":350,"context_line":"            if putter.failed:"},{"line_number":351,"context_line":"                continue"},{"line_number":352,"context_line":"            pile.spawn(self._get_conn_response, putter, req,"},{"line_number":353,"context_line":"                       self.app.logger.thread_locals, final_phase\u003dfinal_phase)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_131ec46f","line":350,"updated":"2016-06-14 05:17:47.000000000","message":"Should we just do this check here? Then we could avoid the extra filtering in ReplicatedObjectController and ECObjectController.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":347,"context_line":"        pile \u003d GreenAsyncPile(len(putters))"},{"line_number":348,"context_line":"        for putter in putters:"},{"line_number":349,"context_line":"            # sanity check"},{"line_number":350,"context_line":"            if putter.failed:"},{"line_number":351,"context_line":"                continue"},{"line_number":352,"context_line":"            pile.spawn(self._get_conn_response, putter, req,"},{"line_number":353,"context_line":"                       self.app.logger.thread_locals, final_phase\u003dfinal_phase)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_e047aab9","line":350,"in_reply_to":"7aa08908_131ec46f","updated":"2016-06-15 15:20:40.000000000","message":"not sure I understand, what check/where is the extra filtering?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":349,"context_line":"            # sanity check"},{"line_number":350,"context_line":"            if putter.failed:"},{"line_number":351,"context_line":"                continue"},{"line_number":352,"context_line":"            pile.spawn(self._get_conn_response, putter, req,"},{"line_number":353,"context_line":"                       self.app.logger.thread_locals, final_phase\u003dfinal_phase)"},{"line_number":354,"context_line":""},{"line_number":355,"context_line":"        def _handle_response(putter, response):"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_ed17cca0","line":352,"range":{"start_line":352,"start_character":56,"end_line":352,"end_character":59},"updated":"2016-06-14 05:17:47.000000000","message":"The only bit of req that we care about in _get_conn_response is req.path, right? Should we just pass that, so we don\u0027t have to think about whether we\u0027re mutating something we shouldn\u0027t?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":349,"context_line":"            # sanity check"},{"line_number":350,"context_line":"            if putter.failed:"},{"line_number":351,"context_line":"                continue"},{"line_number":352,"context_line":"            pile.spawn(self._get_conn_response, putter, req,"},{"line_number":353,"context_line":"                       self.app.logger.thread_locals, final_phase\u003dfinal_phase)"},{"line_number":354,"context_line":""},{"line_number":355,"context_line":"        def _handle_response(putter, response):"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_c070ae0a","line":352,"range":{"start_line":352,"start_character":56,"end_line":352,"end_character":59},"in_reply_to":"7aa08908_ed17cca0","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":381,"context_line":"                if self._have_adequate_put_responses("},{"line_number":382,"context_line":"                        statuses, num_nodes, min_responses):"},{"line_number":383,"context_line":"                    break"},{"line_number":384,"context_line":""},{"line_number":385,"context_line":"        # give any pending requests *some* chance to finish"},{"line_number":386,"context_line":"        finished_quickly \u003d pile.waitall(self.app.post_quorum_timeout)"},{"line_number":387,"context_line":"        for (putter, response) in finished_quickly:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_10006f00","line":384,"updated":"2016-06-14 05:17:47.000000000","message":"We lost the `else` to `if response`; intentional?\n\nIf we catch something up around L299, does the putter ever get marked as failed?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":381,"context_line":"                if self._have_adequate_put_responses("},{"line_number":382,"context_line":"                        statuses, num_nodes, min_responses):"},{"line_number":383,"context_line":"                    break"},{"line_number":384,"context_line":""},{"line_number":385,"context_line":"        # give any pending requests *some* chance to finish"},{"line_number":386,"context_line":"        finished_quickly \u003d pile.waitall(self.app.post_quorum_timeout)"},{"line_number":387,"context_line":"        for (putter, response) in finished_quickly:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_493ce9e0","line":384,"in_reply_to":"7aa08908_10006f00","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":446,"context_line":"            req.headers[\u0027X-Timestamp\u0027] \u003d Timestamp(time.time()).internal"},{"line_number":447,"context_line":"        return None"},{"line_number":448,"context_line":""},{"line_number":449,"context_line":"    def _check_failure_put_connections(self, putters, req, min_conns):"},{"line_number":450,"context_line":"        \"\"\""},{"line_number":451,"context_line":"        Identify any failed connections and check minimum connection count."},{"line_number":452,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_2438d49f","line":449,"updated":"2016-06-14 05:17:47.000000000","message":"Huh. So we were never using `nodes`? Weird.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":446,"context_line":"            req.headers[\u0027X-Timestamp\u0027] \u003d Timestamp(time.time()).internal"},{"line_number":447,"context_line":"        return None"},{"line_number":448,"context_line":""},{"line_number":449,"context_line":"    def _check_failure_put_connections(self, putters, req, min_conns):"},{"line_number":450,"context_line":"        \"\"\""},{"line_number":451,"context_line":"        Identify any failed connections and check minimum connection count."},{"line_number":452,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_f92d72fe","line":449,"in_reply_to":"7aa08908_2438d49f","updated":"2016-06-15 15:20:40.000000000","message":":)","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":455,"context_line":"        :param min_conns: minimum number of putter connections required"},{"line_number":456,"context_line":"        \"\"\""},{"line_number":457,"context_line":"        if req.if_none_match is not None and \u0027*\u0027 in req.if_none_match:"},{"line_number":458,"context_line":"            statuses \u003d [conn.resp.status for conn in putters if conn.resp]"},{"line_number":459,"context_line":"            if HTTP_PRECONDITION_FAILED in statuses:"},{"line_number":460,"context_line":"                # If we find any copy of the file, it shouldn\u0027t be uploaded"},{"line_number":461,"context_line":"                self.app.logger.debug("}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_68bfffaa","line":458,"range":{"start_line":458,"start_character":44,"end_line":458,"end_character":49},"updated":"2016-06-15 12:15:22.000000000","message":"putter?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d8d695ae47b9b30e92f4bb1ff426217b1b8b786b","unresolved":false,"context_lines":[{"line_number":455,"context_line":"        :param min_conns: minimum number of putter connections required"},{"line_number":456,"context_line":"        \"\"\""},{"line_number":457,"context_line":"        if req.if_none_match is not None and \u0027*\u0027 in req.if_none_match:"},{"line_number":458,"context_line":"            statuses \u003d [conn.resp.status for conn in putters if conn.resp]"},{"line_number":459,"context_line":"            if HTTP_PRECONDITION_FAILED in statuses:"},{"line_number":460,"context_line":"                # If we find any copy of the file, it shouldn\u0027t be uploaded"},{"line_number":461,"context_line":"                self.app.logger.debug("}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_a7ae0396","line":458,"range":{"start_line":458,"start_character":44,"end_line":458,"end_character":49},"in_reply_to":"7aa08908_059f3666","updated":"2016-06-16 06:41:39.000000000","message":"This doesn\u0027t seem to be addressed the newest patch set 3 yet?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":455,"context_line":"        :param min_conns: minimum number of putter connections required"},{"line_number":456,"context_line":"        \"\"\""},{"line_number":457,"context_line":"        if req.if_none_match is not None and \u0027*\u0027 in req.if_none_match:"},{"line_number":458,"context_line":"            statuses \u003d [conn.resp.status for conn in putters if conn.resp]"},{"line_number":459,"context_line":"            if HTTP_PRECONDITION_FAILED in statuses:"},{"line_number":460,"context_line":"                # If we find any copy of the file, it shouldn\u0027t be uploaded"},{"line_number":461,"context_line":"                self.app.logger.debug("}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_059f3666","line":458,"range":{"start_line":458,"start_character":44,"end_line":458,"end_character":49},"in_reply_to":"7aa08908_68bfffaa","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e3b7e2d3690dddfb27a9de615d45c0ca9f1aaba4","unresolved":false,"context_lines":[{"line_number":455,"context_line":"        :param min_conns: minimum number of putter connections required"},{"line_number":456,"context_line":"        \"\"\""},{"line_number":457,"context_line":"        if req.if_none_match is not None and \u0027*\u0027 in req.if_none_match:"},{"line_number":458,"context_line":"            statuses \u003d [conn.resp.status for conn in putters if conn.resp]"},{"line_number":459,"context_line":"            if HTTP_PRECONDITION_FAILED in statuses:"},{"line_number":460,"context_line":"                # If we find any copy of the file, it shouldn\u0027t be uploaded"},{"line_number":461,"context_line":"                self.app.logger.debug("}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_11f8f148","line":458,"range":{"start_line":458,"start_character":44,"end_line":458,"end_character":49},"in_reply_to":"7aa08908_a7ae0396","updated":"2016-06-16 08:32:10.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"7a198a346c6cc54243a42dc1773da6ec841f5849","unresolved":false,"context_lines":[{"line_number":491,"context_line":"        :param part: ring partition number"},{"line_number":492,"context_line":"        :param req: a swob Request"},{"line_number":493,"context_line":"        :param headers: request headers"},{"line_number":494,"context_line":"        :return: an instance of BasePutter"},{"line_number":495,"context_line":"        \"\"\""},{"line_number":496,"context_line":"        raise NotImplementedError"},{"line_number":497,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_612ffca7","line":494,"updated":"2016-06-15 18:41:35.000000000","message":"I don\u0027t think there is anything called BasePutter.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7e38683ba7481db6934a5be9ee9ad8bffa9e6d6c","unresolved":false,"context_lines":[{"line_number":491,"context_line":"        :param part: ring partition number"},{"line_number":492,"context_line":"        :param req: a swob Request"},{"line_number":493,"context_line":"        :param headers: request headers"},{"line_number":494,"context_line":"        :return: an instance of BasePutter"},{"line_number":495,"context_line":"        \"\"\""},{"line_number":496,"context_line":"        raise NotImplementedError"},{"line_number":497,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_597118a8","line":494,"in_reply_to":"7aa08908_612ffca7","updated":"2016-06-15 19:24:48.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":493,"context_line":"        :param headers: request headers"},{"line_number":494,"context_line":"        :return: an instance of BasePutter"},{"line_number":495,"context_line":"        \"\"\""},{"line_number":496,"context_line":"        raise NotImplementedError"},{"line_number":497,"context_line":""},{"line_number":498,"context_line":"    def _connect_put_node(self, nodes, part, req, headers,"},{"line_number":499,"context_line":"                          logger_thread_locals):"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_83bccc07","line":496,"updated":"2016-06-15 12:15:22.000000000","message":"ditto, ()","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":493,"context_line":"        :param headers: request headers"},{"line_number":494,"context_line":"        :return: an instance of BasePutter"},{"line_number":495,"context_line":"        \"\"\""},{"line_number":496,"context_line":"        raise NotImplementedError"},{"line_number":497,"context_line":""},{"line_number":498,"context_line":"    def _connect_put_node(self, nodes, part, req, headers,"},{"line_number":499,"context_line":"                          logger_thread_locals):"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_6590ba4f","line":496,"in_reply_to":"7aa08908_83bccc07","updated":"2016-06-15 15:20:40.000000000","message":"Done, as above","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"7a198a346c6cc54243a42dc1773da6ec841f5849","unresolved":false,"context_lines":[{"line_number":511,"context_line":"        :param logger_thread_locals: The thread local values to be set on the"},{"line_number":512,"context_line":"                                     self.app.logger to retain transaction"},{"line_number":513,"context_line":"                                     logging information."},{"line_number":514,"context_line":"        :return: an instance of BasePutter"},{"line_number":515,"context_line":"        \"\"\""},{"line_number":516,"context_line":"        self.app.logger.thread_locals \u003d logger_thread_locals"},{"line_number":517,"context_line":"        for node in nodes:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_413480fa","line":514,"updated":"2016-06-15 18:41:35.000000000","message":"I don\u0027t think there is anything called BasePutter.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7e38683ba7481db6934a5be9ee9ad8bffa9e6d6c","unresolved":false,"context_lines":[{"line_number":511,"context_line":"        :param logger_thread_locals: The thread local values to be set on the"},{"line_number":512,"context_line":"                                     self.app.logger to retain transaction"},{"line_number":513,"context_line":"                                     logging information."},{"line_number":514,"context_line":"        :return: an instance of BasePutter"},{"line_number":515,"context_line":"        \"\"\""},{"line_number":516,"context_line":"        self.app.logger.thread_locals \u003d logger_thread_locals"},{"line_number":517,"context_line":"        for node in nodes:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_d95d0817","line":514,"in_reply_to":"7aa08908_413480fa","updated":"2016-06-15 19:24:48.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":544,"context_line":"        for nheaders in outgoing_headers:"},{"line_number":545,"context_line":"            # RFC2616:8.2.3 disallows 100-continue without a body"},{"line_number":546,"context_line":"            if (req.content_length \u003e 0) or req.is_chunked:"},{"line_number":547,"context_line":"                nheaders[\u0027Expect\u0027] \u003d \u0027100-continue\u0027"},{"line_number":548,"context_line":"            pile.spawn(self._connect_put_node, node_iter, partition,"},{"line_number":549,"context_line":"                       req, nheaders, self.app.logger.thread_locals)"},{"line_number":550,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_7979e981","line":547,"updated":"2016-06-14 05:17:47.000000000","message":"The fact that ECObjectController always set expect\u003dTrue in _get_put_connections is irrelevant because we\u0027d set Expect: 100-continue in ECPutter.connect. Right?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":544,"context_line":"        for nheaders in outgoing_headers:"},{"line_number":545,"context_line":"            # RFC2616:8.2.3 disallows 100-continue without a body"},{"line_number":546,"context_line":"            if (req.content_length \u003e 0) or req.is_chunked:"},{"line_number":547,"context_line":"                nheaders[\u0027Expect\u0027] \u003d \u0027100-continue\u0027"},{"line_number":548,"context_line":"            pile.spawn(self._connect_put_node, node_iter, partition,"},{"line_number":549,"context_line":"                       req, nheaders, self.app.logger.thread_locals)"},{"line_number":550,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_74b25c07","line":547,"in_reply_to":"7aa08908_7979e981","updated":"2016-06-15 15:20:40.000000000","message":"Correct, so IIRC this reduces the places where we made choices about sending Expect to just here.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":546,"context_line":"            if (req.content_length \u003e 0) or req.is_chunked:"},{"line_number":547,"context_line":"                nheaders[\u0027Expect\u0027] \u003d \u0027100-continue\u0027"},{"line_number":548,"context_line":"            pile.spawn(self._connect_put_node, node_iter, partition,"},{"line_number":549,"context_line":"                       req, nheaders, self.app.logger.thread_locals)"},{"line_number":550,"context_line":""},{"line_number":551,"context_line":"        conns \u003d [conn for conn in pile if conn]"},{"line_number":552,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_e4aa4c70","line":549,"range":{"start_line":549,"start_character":23,"end_line":549,"end_character":26},"updated":"2016-06-14 05:17:47.000000000","message":"Without any additional context/guarantees, we\u0027re going to have to be very careful about whether/how we affect state in the request.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":546,"context_line":"            if (req.content_length \u003e 0) or req.is_chunked:"},{"line_number":547,"context_line":"                nheaders[\u0027Expect\u0027] \u003d \u0027100-continue\u0027"},{"line_number":548,"context_line":"            pile.spawn(self._connect_put_node, node_iter, partition,"},{"line_number":549,"context_line":"                       req, nheaders, self.app.logger.thread_locals)"},{"line_number":550,"context_line":""},{"line_number":551,"context_line":"        conns \u003d [conn for conn in pile if conn]"},{"line_number":552,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_cb625f3d","line":549,"range":{"start_line":549,"start_character":23,"end_line":549,"end_character":26},"in_reply_to":"7aa08908_e4aa4c70","updated":"2016-06-15 15:20:40.000000000","message":"See Kota\u0027s comment on Putter class - will change to restrict req from being passed into the Putters at least.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":565,"context_line":"        footers \u003d HeaderKeyDict()"},{"line_number":566,"context_line":"        footer_callback \u003d req.environ.get("},{"line_number":567,"context_line":"            \u0027swift.callback.update_footers\u0027, lambda _footer: None)"},{"line_number":568,"context_line":"        footer_callback(footers)"},{"line_number":569,"context_line":"        return footers"},{"line_number":570,"context_line":""},{"line_number":571,"context_line":"    def _store_object(self, req, data_source, nodes, partition,"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_a48e2b77","line":568,"updated":"2016-06-15 12:15:22.000000000","message":"If \u0027swift.callback.update_footers\u0027 is set but it\u0027s not callable (or few/more args required), does this make 500 InternalServerError, doesn\u0027t it?\n\nThat is probably a bug case but I\u0027m not sure we don\u0027t have to care of the case.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":565,"context_line":"        footers \u003d HeaderKeyDict()"},{"line_number":566,"context_line":"        footer_callback \u003d req.environ.get("},{"line_number":567,"context_line":"            \u0027swift.callback.update_footers\u0027, lambda _footer: None)"},{"line_number":568,"context_line":"        footer_callback(footers)"},{"line_number":569,"context_line":"        return footers"},{"line_number":570,"context_line":""},{"line_number":571,"context_line":"    def _store_object(self, req, data_source, nodes, partition,"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_25ea32ad","line":568,"in_reply_to":"7aa08908_a48e2b77","updated":"2016-06-15 15:20:40.000000000","message":"proxy server catches all Exceptions and returns a 500.\n\nhttps://github.com/openstack/swift/blob/master/swift/proxy/server.py#L421\n\nSimilar would happen if \u0027swift.authorize\u0027 was not callable","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":744,"context_line":"            # when using a multipart mime request to backend the actual"},{"line_number":745,"context_line":"            # content-length is not equal to the object content size."},{"line_number":746,"context_line":"            headers[\u0027X-Backend-Obj-Content-Length\u0027] \u003d \\"},{"line_number":747,"context_line":"                headers.pop(\u0027Content-Length\u0027, None)"},{"line_number":748,"context_line":"            putter \u003d MIMEPutter.connect("},{"line_number":749,"context_line":"                node, part, req, headers,"},{"line_number":750,"context_line":"                conn_timeout\u003dself.app.conn_timeout,"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_843f08b3","line":747,"updated":"2016-06-14 05:17:47.000000000","message":"This mutation makes me nervous.\n\nWhat happens when the putter we create here fails in such a way that we can still try a handoff? Isn\u0027t headers already modified such that there will never be a Content-Length?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":744,"context_line":"            # when using a multipart mime request to backend the actual"},{"line_number":745,"context_line":"            # content-length is not equal to the object content size."},{"line_number":746,"context_line":"            headers[\u0027X-Backend-Obj-Content-Length\u0027] \u003d \\"},{"line_number":747,"context_line":"                headers.pop(\u0027Content-Length\u0027, None)"},{"line_number":748,"context_line":"            putter \u003d MIMEPutter.connect("},{"line_number":749,"context_line":"                node, part, req, headers,"},{"line_number":750,"context_line":"                conn_timeout\u003dself.app.conn_timeout,"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_a12da190","line":747,"in_reply_to":"7aa08908_843f08b3","updated":"2016-06-15 15:20:40.000000000","message":"Great spot. Combined with addressing similar concern in EC _makePutter, I will move this to the MimePutter and copy the dict first.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":775,"context_line":"                    putters.remove(putter)"},{"line_number":776,"context_line":"            self._check_min_conn("},{"line_number":777,"context_line":"                req, putters, min_conns, msg\u003d\u0027Object PUT exceptions during\u0027"},{"line_number":778,"context_line":"                \u0027 send, %(conns)s/%(nodes)s required connections\u0027)"},{"line_number":779,"context_line":""},{"line_number":780,"context_line":"        min_conns \u003d quorum_size(len(nodes))"},{"line_number":781,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_b9d231fe","line":778,"updated":"2016-06-14 05:17:47.000000000","message":"Worth marking for translation?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":775,"context_line":"                    putters.remove(putter)"},{"line_number":776,"context_line":"            self._check_min_conn("},{"line_number":777,"context_line":"                req, putters, min_conns, msg\u003d\u0027Object PUT exceptions during\u0027"},{"line_number":778,"context_line":"                \u0027 send, %(conns)s/%(nodes)s required connections\u0027)"},{"line_number":779,"context_line":""},{"line_number":780,"context_line":"        min_conns \u003d quorum_size(len(nodes))"},{"line_number":781,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_d42214a3","line":778,"in_reply_to":"7aa08908_b9d231fe","updated":"2016-06-15 15:20:40.000000000","message":"Done here and 3 other calls to check_min_conns","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":781,"context_line":"        try:"},{"line_number":782,"context_line":"            with ContextPool(len(nodes)) as pool:"},{"line_number":783,"context_line":"                for putter in putters:"},{"line_number":784,"context_line":"                    putter.spawn_sender_greenthread("},{"line_number":785,"context_line":"                        pool, self.app.put_queue_depth, self.app.node_timeout,"},{"line_number":786,"context_line":"                        self.app.exception_occurred)"},{"line_number":787,"context_line":"                while True:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_b9551151","line":784,"updated":"2016-06-14 05:17:47.000000000","message":"So here we spawn N greenthreads to start sending data... and over in _get_put_responses we spawn another N to check the responses. I wonder if we could reduce that; have the senders watch for a sentinel on the queue and switch to watching for a response?\n\nEh, later, follow-up. If at all.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":781,"context_line":"        try:"},{"line_number":782,"context_line":"            with ContextPool(len(nodes)) as pool:"},{"line_number":783,"context_line":"                for putter in putters:"},{"line_number":784,"context_line":"                    putter.spawn_sender_greenthread("},{"line_number":785,"context_line":"                        pool, self.app.put_queue_depth, self.app.node_timeout,"},{"line_number":786,"context_line":"                        self.app.exception_occurred)"},{"line_number":787,"context_line":"                while True:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_793a2236","line":784,"in_reply_to":"7aa08908_b9551151","updated":"2016-06-15 15:20:40.000000000","message":"follow up","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":806,"context_line":""},{"line_number":807,"context_line":"                for putter in putters:"},{"line_number":808,"context_line":"                    # send any footers set by middleware"},{"line_number":809,"context_line":"                    trail_md \u003d self._get_footers(req)"},{"line_number":810,"context_line":"                    putter.end_of_object_data(footer_metadata\u003dtrail_md)"},{"line_number":811,"context_line":""},{"line_number":812,"context_line":"                for putter in putters:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_8494288b","line":809,"updated":"2016-06-14 05:17:47.000000000","message":"So the footer callback is called once per putter? Why not something like\n\n trail_md \u003d self._get_footers(req)\n for putter in putters:\n     putter.end_of_object_data(footer_metadata\u003ddict(trail_md))\n\n? Although we may want some sort of check that the footers are all strings first (so we can be confident that a shallow copy is sufficient).","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":806,"context_line":""},{"line_number":807,"context_line":"                for putter in putters:"},{"line_number":808,"context_line":"                    # send any footers set by middleware"},{"line_number":809,"context_line":"                    trail_md \u003d self._get_footers(req)"},{"line_number":810,"context_line":"                    putter.end_of_object_data(footer_metadata\u003dtrail_md)"},{"line_number":811,"context_line":""},{"line_number":812,"context_line":"                for putter in putters:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_d45cd47f","line":809,"in_reply_to":"7aa08908_8494288b","updated":"2016-06-15 15:20:40.000000000","message":"Done, but I don\u0027t think the copy is necessary because end_of_object_data does not change the dict.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":815,"context_line":"                self._check_min_conn("},{"line_number":816,"context_line":"                    req, putters, min_conns,"},{"line_number":817,"context_line":"                    msg\u003d\u0027Object PUT exceptions after last send, \u0027"},{"line_number":818,"context_line":"                    \u0027%(conns)s/%(nodes)s required connections\u0027)"},{"line_number":819,"context_line":"        except ChunkReadTimeout as err:"},{"line_number":820,"context_line":"            self.app.logger.warning("},{"line_number":821,"context_line":"                _(\u0027ERROR Client read timeout (%ss)\u0027), err.seconds)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_04ef981e","line":818,"updated":"2016-06-14 05:17:47.000000000","message":"Maybe mark for translation?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":815,"context_line":"                self._check_min_conn("},{"line_number":816,"context_line":"                    req, putters, min_conns,"},{"line_number":817,"context_line":"                    msg\u003d\u0027Object PUT exceptions after last send, \u0027"},{"line_number":818,"context_line":"                    \u0027%(conns)s/%(nodes)s required connections\u0027)"},{"line_number":819,"context_line":"        except ChunkReadTimeout as err:"},{"line_number":820,"context_line":"            self.app.logger.warning("},{"line_number":821,"context_line":"                _(\u0027ERROR Client read timeout (%ss)\u0027), err.seconds)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_544904b7","line":818,"in_reply_to":"7aa08908_04ef981e","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":827,"context_line":"                _(\u0027Client disconnected without sending last chunk\u0027))"},{"line_number":828,"context_line":"            self.app.logger.increment(\u0027client_disconnects\u0027)"},{"line_number":829,"context_line":"            raise HTTPClientDisconnect(request\u003dreq)"},{"line_number":830,"context_line":"        except HTTPException:"},{"line_number":831,"context_line":"            raise"},{"line_number":832,"context_line":"        except Timeout:"},{"line_number":833,"context_line":"            self.app.logger.exception("}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_841ee809","line":830,"updated":"2016-06-14 05:17:47.000000000","message":"This should have no impact, right? ChunkReadError doesn\u0027t inherit from it, so this change of order doesn\u0027t matter?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":827,"context_line":"                _(\u0027Client disconnected without sending last chunk\u0027))"},{"line_number":828,"context_line":"            self.app.logger.increment(\u0027client_disconnects\u0027)"},{"line_number":829,"context_line":"            raise HTTPClientDisconnect(request\u003dreq)"},{"line_number":830,"context_line":"        except HTTPException:"},{"line_number":831,"context_line":"            raise"},{"line_number":832,"context_line":"        except Timeout:"},{"line_number":833,"context_line":"            self.app.logger.exception("}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_f4ce302c","line":830,"in_reply_to":"7aa08908_841ee809","updated":"2016-06-15 15:20:40.000000000","message":"IDK why it moved, reverting.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":1442,"context_line":"        self.failed \u003d False"},{"line_number":1443,"context_line":"        self.queue \u003d None"},{"line_number":1444,"context_line":"        self.state \u003d NO_DATA_SENT"},{"line_number":1445,"context_line":"        self.chunked \u003d req.is_chunked"},{"line_number":1446,"context_line":"        self.logger \u003d logger"},{"line_number":1447,"context_line":""},{"line_number":1448,"context_line":"    def await_response(self, timeout, informational\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_f50e278b","line":1445,"updated":"2016-06-15 12:15:22.000000000","message":"Ah, this is why we need to change the \"path\" arg to \"req\"\n\nHmm... that seems probably \"More Args vs Just A capsule(or dict)\" but honesty, I\u0027d like to bet it\u0027s better to add \"chunked\" arg for init instead of changing the path arg into req. That is because feeding a request instance would blind \"what info we need in the class\" from us and it may make someone to mis-read like \"putter needs request instance to connect to backend servers\" but actually it\u0027s not true. We don\u0027t keep the request instance in the putter and no-reuse (like make subrequest) for anything.\n\n\nIn my idea, the role should be separated like as:\n\n\n- Controller -\u003e Request handling\n- Putter -\u003e HTTPConnection handling\n\n\nAnd if it\u0027s sparse, it would be robust for later changes.\nHow do you think of it?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d8d695ae47b9b30e92f4bb1ff426217b1b8b786b","unresolved":false,"context_lines":[{"line_number":1442,"context_line":"        self.failed \u003d False"},{"line_number":1443,"context_line":"        self.queue \u003d None"},{"line_number":1444,"context_line":"        self.state \u003d NO_DATA_SENT"},{"line_number":1445,"context_line":"        self.chunked \u003d req.is_chunked"},{"line_number":1446,"context_line":"        self.logger \u003d logger"},{"line_number":1447,"context_line":""},{"line_number":1448,"context_line":"    def await_response(self, timeout, informational\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_8702e770","line":1445,"in_reply_to":"7aa08908_4bf30fa0","updated":"2016-06-16 06:41:39.000000000","message":"Thanks for addressing to that :-D","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":1442,"context_line":"        self.failed \u003d False"},{"line_number":1443,"context_line":"        self.queue \u003d None"},{"line_number":1444,"context_line":"        self.state \u003d NO_DATA_SENT"},{"line_number":1445,"context_line":"        self.chunked \u003d req.is_chunked"},{"line_number":1446,"context_line":"        self.logger \u003d logger"},{"line_number":1447,"context_line":""},{"line_number":1448,"context_line":"    def await_response(self, timeout, informational\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_4bf30fa0","line":1445,"in_reply_to":"7aa08908_f50e278b","updated":"2016-06-15 15:20:40.000000000","message":"Done. I tend to prefer passing fewer args when one parameter (req) already encapuslates the other parameters that are needed by the method. But I take your point about the separation of concerns.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":1462,"context_line":"        :returns: HTTPResponse"},{"line_number":1463,"context_line":"        :raises: Timeout if the response took too long"},{"line_number":1464,"context_line":"        \"\"\""},{"line_number":1465,"context_line":"        conn \u003d self.conn"},{"line_number":1466,"context_line":"        with Timeout(timeout):"},{"line_number":1467,"context_line":"            if not conn.resp:"},{"line_number":1468,"context_line":"                if informational:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_c271b2ad","line":1465,"updated":"2016-06-15 12:15:22.000000000","message":"Out of curiosity, I\u0027m wondering why we need to re-assign the instance to local variable. I know that\u0027s existed since the original code so probably this is out of scope of this patch though.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":1462,"context_line":"        :returns: HTTPResponse"},{"line_number":1463,"context_line":"        :raises: Timeout if the response took too long"},{"line_number":1464,"context_line":"        \"\"\""},{"line_number":1465,"context_line":"        conn \u003d self.conn"},{"line_number":1466,"context_line":"        with Timeout(timeout):"},{"line_number":1467,"context_line":"            if not conn.resp:"},{"line_number":1468,"context_line":"                if informational:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_0ba2a74b","line":1465,"in_reply_to":"7aa08908_c271b2ad","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":1466,"context_line":"        with Timeout(timeout):"},{"line_number":1467,"context_line":"            if not conn.resp:"},{"line_number":1468,"context_line":"                if informational:"},{"line_number":1469,"context_line":"                    self.resp \u003d conn.getexpect()"},{"line_number":1470,"context_line":"                else:"},{"line_number":1471,"context_line":"                    self.resp \u003d conn.getresponse()"},{"line_number":1472,"context_line":"            return self.resp"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_789a2e70","line":1469,"updated":"2016-06-15 12:15:22.000000000","message":"I wish if we can use this context also for the first connection. (I know, this is used only for waiting response in MIME)","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d8d695ae47b9b30e92f4bb1ff426217b1b8b786b","unresolved":false,"context_lines":[{"line_number":1466,"context_line":"        with Timeout(timeout):"},{"line_number":1467,"context_line":"            if not conn.resp:"},{"line_number":1468,"context_line":"                if informational:"},{"line_number":1469,"context_line":"                    self.resp \u003d conn.getexpect()"},{"line_number":1470,"context_line":"                else:"},{"line_number":1471,"context_line":"                    self.resp \u003d conn.getresponse()"},{"line_number":1472,"context_line":"            return self.resp"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_c7e6afaf","line":1469,"in_reply_to":"7aa08908_6b87ebb6","updated":"2016-06-16 06:41:39.000000000","message":"Sorry my lack of explanation. That might not be actually here and it\u0027s probably ok to do in the followup.\n\n\nWhat I wanted to say is the informational\u003dTrue will happen only in MIMEPutter, right? That is because the fist connection (almostly conn.getexpect() with content body) occurs at Putter._make_connection at L1560. i.e. the primary user of informational\u003dTrue is only the Putter waiting MIME doc response (with \"not final_phase\")\n\n\n...ah, I notice right now, it\u0027s partially true. The await_response with informational\u003dTrue happens only when \"multiphase commit\" mode so it should be MIMEPutter instance but we don\u0027t need it in replicated case. I thought we need getexpect() for each MIME docs but it\u0027s false. We need it *only before commit*.\n\n\nSo... I thought we could use this function against to the first connection in _make_connection, too. Or, on my second thought, I\u0027m realizing the informational arg is only needed in MIMEPutter class . Not sure though. Still need more deep digging.\n\n\nAnd yes, as you answered at L1552, the fist connection happen in *class method*, I have no clear answer how we should change this so +1 we bring this into follow up, anyway.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":1466,"context_line":"        with Timeout(timeout):"},{"line_number":1467,"context_line":"            if not conn.resp:"},{"line_number":1468,"context_line":"                if informational:"},{"line_number":1469,"context_line":"                    self.resp \u003d conn.getexpect()"},{"line_number":1470,"context_line":"                else:"},{"line_number":1471,"context_line":"                    self.resp \u003d conn.getresponse()"},{"line_number":1472,"context_line":"            return self.resp"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_6b87ebb6","line":1469,"in_reply_to":"7aa08908_789a2e70","updated":"2016-06-15 15:20:40.000000000","message":"Sorry, I don\u0027t understand the comment. Is there a change to make?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e3b7e2d3690dddfb27a9de615d45c0ca9f1aaba4","unresolved":false,"context_lines":[{"line_number":1466,"context_line":"        with Timeout(timeout):"},{"line_number":1467,"context_line":"            if not conn.resp:"},{"line_number":1468,"context_line":"                if informational:"},{"line_number":1469,"context_line":"                    self.resp \u003d conn.getexpect()"},{"line_number":1470,"context_line":"                else:"},{"line_number":1471,"context_line":"                    self.resp \u003d conn.getresponse()"},{"line_number":1472,"context_line":"            return self.resp"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_31808d8b","line":1469,"in_reply_to":"7aa08908_c7e6afaf","updated":"2016-06-16 08:32:10.000000000","message":"ok, so follow up perhaps","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":1514,"context_line":""},{"line_number":1515,"context_line":"    def _send_file(self, write_timeout, exception_handler):"},{"line_number":1516,"context_line":"        \"\"\""},{"line_number":1517,"context_line":"        Method for a file PUT coro. Takes chunks from a queue and sends them"},{"line_number":1518,"context_line":"        down a socket."},{"line_number":1519,"context_line":""},{"line_number":1520,"context_line":"        If something goes wrong, the \"failed\" attribute will be set to true"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_bf4fb132","line":1517,"range":{"start_line":1517,"start_character":30,"end_line":1517,"end_character":34},"updated":"2016-06-14 05:17:47.000000000","message":"Should we just spell this out as coroutine?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":1514,"context_line":""},{"line_number":1515,"context_line":"    def _send_file(self, write_timeout, exception_handler):"},{"line_number":1516,"context_line":"        \"\"\""},{"line_number":1517,"context_line":"        Method for a file PUT coro. Takes chunks from a queue and sends them"},{"line_number":1518,"context_line":"        down a socket."},{"line_number":1519,"context_line":""},{"line_number":1520,"context_line":"        If something goes wrong, the \"failed\" attribute will be set to true"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_3400b835","line":1517,"range":{"start_line":1517,"start_character":30,"end_line":1517,"end_character":34},"in_reply_to":"7aa08908_bf4fb132","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":1549,"context_line":"                                part, \u0027PUT\u0027, req.swift_entity_path, headers)"},{"line_number":1550,"context_line":"        connect_duration \u003d time.time() - start_time"},{"line_number":1551,"context_line":""},{"line_number":1552,"context_line":"        with ResponseTimeout(node_timeout):"},{"line_number":1553,"context_line":"            resp \u003d conn.getexpect()"},{"line_number":1554,"context_line":""},{"line_number":1555,"context_line":"        if resp.status \u003d\u003d HTTP_INSUFFICIENT_STORAGE:"},{"line_number":1556,"context_line":"            raise InsufficientStorage"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_2391989b","line":1553,"range":{"start_line":1552,"start_character":0,"end_line":1553,"end_character":35},"updated":"2016-06-15 12:15:22.000000000","message":"This looks similar with putter.await_response(node_timeout, informational\u003dTrue)","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":1549,"context_line":"                                part, \u0027PUT\u0027, req.swift_entity_path, headers)"},{"line_number":1550,"context_line":"        connect_duration \u003d time.time() - start_time"},{"line_number":1551,"context_line":""},{"line_number":1552,"context_line":"        with ResponseTimeout(node_timeout):"},{"line_number":1553,"context_line":"            resp \u003d conn.getexpect()"},{"line_number":1554,"context_line":""},{"line_number":1555,"context_line":"        if resp.status \u003d\u003d HTTP_INSUFFICIENT_STORAGE:"},{"line_number":1556,"context_line":"            raise InsufficientStorage"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_d6bcc6dd","line":1553,"range":{"start_line":1552,"start_character":0,"end_line":1553,"end_character":35},"in_reply_to":"7aa08908_2391989b","updated":"2016-06-15 15:20:40.000000000","message":"Similar but this is in a classmethod so swe cannot use await_response since there is no instance of the class yet ad no conn variable set in the class.\n\nThis code was moved unchanged from ECPutter.connect() method","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":1553,"context_line":"            resp \u003d conn.getexpect()"},{"line_number":1554,"context_line":""},{"line_number":1555,"context_line":"        if resp.status \u003d\u003d HTTP_INSUFFICIENT_STORAGE:"},{"line_number":1556,"context_line":"            raise InsufficientStorage"},{"line_number":1557,"context_line":""},{"line_number":1558,"context_line":"        if is_server_error(resp.status):"},{"line_number":1559,"context_line":"            raise PutterConnectError(resp.status)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_d801a26f","line":1556,"updated":"2016-06-15 12:15:22.000000000","message":"Needs \"()\" for instantiation.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d8d695ae47b9b30e92f4bb1ff426217b1b8b786b","unresolved":false,"context_lines":[{"line_number":1553,"context_line":"            resp \u003d conn.getexpect()"},{"line_number":1554,"context_line":""},{"line_number":1555,"context_line":"        if resp.status \u003d\u003d HTTP_INSUFFICIENT_STORAGE:"},{"line_number":1556,"context_line":"            raise InsufficientStorage"},{"line_number":1557,"context_line":""},{"line_number":1558,"context_line":"        if is_server_error(resp.status):"},{"line_number":1559,"context_line":"            raise PutterConnectError(resp.status)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_ca0d16ea","line":1556,"in_reply_to":"7aa08908_16b76ef6","updated":"2016-06-16 06:41:39.000000000","message":"huh! Exactly current Swift has the code for raising an error w/o instantiation :/","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":1553,"context_line":"            resp \u003d conn.getexpect()"},{"line_number":1554,"context_line":""},{"line_number":1555,"context_line":"        if resp.status \u003d\u003d HTTP_INSUFFICIENT_STORAGE:"},{"line_number":1556,"context_line":"            raise InsufficientStorage"},{"line_number":1557,"context_line":""},{"line_number":1558,"context_line":"        if is_server_error(resp.status):"},{"line_number":1559,"context_line":"            raise PutterConnectError(resp.status)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_16b76ef6","line":1556,"in_reply_to":"7aa08908_d801a26f","updated":"2016-06-15 15:20:40.000000000","message":":)\n\nThis code was moved unchanged from ECPutter.connect() method","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":1560,"context_line":""},{"line_number":1561,"context_line":"        conn.node \u003d node"},{"line_number":1562,"context_line":"        conn.resp \u003d None"},{"line_number":1563,"context_line":"        if is_success(resp.status) or resp.status \u003d\u003d HTTP_CONFLICT:"},{"line_number":1564,"context_line":"            conn.resp \u003d resp"},{"line_number":1565,"context_line":"        elif (headers.get(\u0027If-None-Match\u0027, None) is not None and"},{"line_number":1566,"context_line":"              resp.status \u003d\u003d HTTP_PRECONDITION_FAILED):"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_6a96253f","line":1563,"updated":"2016-06-14 05:17:47.000000000","message":"Nothing about HTTP_UNPROCESSABLE_ENTITY?\n\nI guess because we don\u0027t expect there to be anything actionable wrt Etags yet?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":1560,"context_line":""},{"line_number":1561,"context_line":"        conn.node \u003d node"},{"line_number":1562,"context_line":"        conn.resp \u003d None"},{"line_number":1563,"context_line":"        if is_success(resp.status) or resp.status \u003d\u003d HTTP_CONFLICT:"},{"line_number":1564,"context_line":"            conn.resp \u003d resp"},{"line_number":1565,"context_line":"        elif (headers.get(\u0027If-None-Match\u0027, None) is not None and"},{"line_number":1566,"context_line":"              resp.status \u003d\u003d HTTP_PRECONDITION_FAILED):"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_17f49ecd","line":1563,"in_reply_to":"7aa08908_6a96253f","updated":"2016-06-15 15:20:40.000000000","message":"No data has been sent yet so HTTP_UNPROCESSABLE_ENTITY not expected.\n\nThese lines are refactored from ECPutter.connect()","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":1560,"context_line":""},{"line_number":1561,"context_line":"        conn.node \u003d node"},{"line_number":1562,"context_line":"        conn.resp \u003d None"},{"line_number":1563,"context_line":"        if is_success(resp.status) or resp.status \u003d\u003d HTTP_CONFLICT:"},{"line_number":1564,"context_line":"            conn.resp \u003d resp"},{"line_number":1565,"context_line":"        elif (headers.get(\u0027If-None-Match\u0027, None) is not None and"},{"line_number":1566,"context_line":"              resp.status \u003d\u003d HTTP_PRECONDITION_FAILED):"},{"line_number":1567,"context_line":"            conn.resp \u003d resp"},{"line_number":1568,"context_line":""},{"line_number":1569,"context_line":"        return conn, resp, connect_duration"},{"line_number":1570,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_58ae5230","line":1567,"range":{"start_line":1563,"start_character":7,"end_line":1567,"end_character":28},"updated":"2016-06-15 12:15:22.000000000","message":"Looks like no behavior difference between if and elif so it seems like as:\n\n if is_success(resp.status) or resp.status \u003d\u003d HTTP_CONFLICT\n   or (headers.get(\u0027If-None-Match\u0027, None) is not None and \n       resp.status \u003d\u003d HTTP_PRECONDITIONAL_FAILED):\n     conn.resp \u003d resp\n else:\n     conn.resp \u003d None\n\n?\n\nHmm... I\u0027m not sure which is better for this, though.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":1560,"context_line":""},{"line_number":1561,"context_line":"        conn.node \u003d node"},{"line_number":1562,"context_line":"        conn.resp \u003d None"},{"line_number":1563,"context_line":"        if is_success(resp.status) or resp.status \u003d\u003d HTTP_CONFLICT:"},{"line_number":1564,"context_line":"            conn.resp \u003d resp"},{"line_number":1565,"context_line":"        elif (headers.get(\u0027If-None-Match\u0027, None) is not None and"},{"line_number":1566,"context_line":"              resp.status \u003d\u003d HTTP_PRECONDITION_FAILED):"},{"line_number":1567,"context_line":"            conn.resp \u003d resp"},{"line_number":1568,"context_line":""},{"line_number":1569,"context_line":"        return conn, resp, connect_duration"},{"line_number":1570,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_310d54e9","line":1567,"range":{"start_line":1563,"start_character":7,"end_line":1567,"end_character":28},"in_reply_to":"7aa08908_58ae5230","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":1648,"context_line":"        self.queue.put(\"\".join(message_parts))"},{"line_number":1649,"context_line":""},{"line_number":1650,"context_line":"        self.queue.put(\u0027\u0027)"},{"line_number":1651,"context_line":"        self.state \u003d DATA_SENT"},{"line_number":1652,"context_line":""},{"line_number":1653,"context_line":"    def send_commit_confirmation(self):"},{"line_number":1654,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_ff3c9994","line":1651,"updated":"2016-06-14 05:17:47.000000000","message":"I kinda want to just call super().end_of_object_data() here, but maybe it\u0027s more readable this way, with all that needs to happen between the double-call check and putting the empty chunk on the queue...","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d8d695ae47b9b30e92f4bb1ff426217b1b8b786b","unresolved":false,"context_lines":[{"line_number":1648,"context_line":"        self.queue.put(\"\".join(message_parts))"},{"line_number":1649,"context_line":""},{"line_number":1650,"context_line":"        self.queue.put(\u0027\u0027)"},{"line_number":1651,"context_line":"        self.state \u003d DATA_SENT"},{"line_number":1652,"context_line":""},{"line_number":1653,"context_line":"    def send_commit_confirmation(self):"},{"line_number":1654,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_6ad6a228","line":1651,"in_reply_to":"7aa08908_79686222","updated":"2016-06-16 06:41:39.000000000","message":"sure","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":1648,"context_line":"        self.queue.put(\"\".join(message_parts))"},{"line_number":1649,"context_line":""},{"line_number":1650,"context_line":"        self.queue.put(\u0027\u0027)"},{"line_number":1651,"context_line":"        self.state \u003d DATA_SENT"},{"line_number":1652,"context_line":""},{"line_number":1653,"context_line":"    def send_commit_confirmation(self):"},{"line_number":1654,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_79686222","line":1651,"in_reply_to":"7aa08908_cb926afc","updated":"2016-06-15 15:20:40.000000000","message":"follow up","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":1648,"context_line":"        self.queue.put(\"\".join(message_parts))"},{"line_number":1649,"context_line":""},{"line_number":1650,"context_line":"        self.queue.put(\u0027\u0027)"},{"line_number":1651,"context_line":"        self.state \u003d DATA_SENT"},{"line_number":1652,"context_line":""},{"line_number":1653,"context_line":"    def send_commit_confirmation(self):"},{"line_number":1654,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_cb926afc","line":1651,"in_reply_to":"7aa08908_ff3c9994","updated":"2016-06-15 12:15:22.000000000","message":"That sounds sort of the refactoring things. (but I like your idea :))\n\nI think we could make 3 classes actually? Like:\n\nPutter -\u003e (inherits) -\u003e MIMEPutter -\u003e (inherits) -\u003e MIMEMultiphasePutter\n\nPutter: for normal put\nMIMEPutter: sort of encryption\nMIMEMultiphasePutter: EC!\n\nIt exactly requires more work to refactor though so probably we can try it in follow-up like we did in EC diskfile refactoring.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":1648,"context_line":"        self.queue.put(\"\".join(message_parts))"},{"line_number":1649,"context_line":""},{"line_number":1650,"context_line":"        self.queue.put(\u0027\u0027)"},{"line_number":1651,"context_line":"        self.state \u003d DATA_SENT"},{"line_number":1652,"context_line":""},{"line_number":1653,"context_line":"    def send_commit_confirmation(self):"},{"line_number":1654,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_296cd6cf","line":1651,"in_reply_to":"7aa08908_ff3c9994","updated":"2016-06-15 15:20:40.000000000","message":"Yeah, I know that feeling... in fact Thiago and I felt that it ought to be possible to squeeze some more shared code aout of _store_object and or _transfer_data, but that\u0027s for another patch :)","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":1989,"context_line":"        # We\u0027re about to invoke conditional response checking so set the"},{"line_number":1990,"context_line":"        # correct conditional etag from wherever X-Backend-Etag-Is-At points,"},{"line_number":1991,"context_line":"        # if it exists at all."},{"line_number":1992,"context_line":"        resp._conditional_etag \u003d resolve_etag_is_at_header(req, resp.headers)"},{"line_number":1993,"context_line":"        if (is_success(resp.status_int) or is_redirection(resp.status_int) or"},{"line_number":1994,"context_line":"                resp.status_int \u003d\u003d HTTP_REQUESTED_RANGE_NOT_SATISFIABLE):"},{"line_number":1995,"context_line":"            resp.accept_ranges \u003d \u0027bytes\u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_2e3cdcbe","line":1992,"updated":"2016-06-15 12:15:22.000000000","message":"Why do we need to invoke the conditional etag ressolving at *proxy-server*?\n\nObject-server has the capability to check the conditional response (i.e. comparing if-match header value to the etag pointed out by X-Backend-Etag-Is-At) so... am I missing something?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":1989,"context_line":"        # We\u0027re about to invoke conditional response checking so set the"},{"line_number":1990,"context_line":"        # correct conditional etag from wherever X-Backend-Etag-Is-At points,"},{"line_number":1991,"context_line":"        # if it exists at all."},{"line_number":1992,"context_line":"        resp._conditional_etag \u003d resolve_etag_is_at_header(req, resp.headers)"},{"line_number":1993,"context_line":"        if (is_success(resp.status_int) or is_redirection(resp.status_int) or"},{"line_number":1994,"context_line":"                resp.status_int \u003d\u003d HTTP_REQUESTED_RANGE_NOT_SATISFIABLE):"},{"line_number":1995,"context_line":"            resp.accept_ranges \u003d \u0027bytes\u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_63a38f01","line":1992,"in_reply_to":"7aa08908_2e3cdcbe","updated":"2016-06-15 15:20:40.000000000","message":"This is necessary because the Response object is instantiated with conditional_response\u003dTrue (line 1960), which means that the Response will perform conditional If-[None-]Match checks. But those checks will compare against Etag (which was just set with the \u0027X-Object-Sysmeta-Ec-Etag\u0027 value) which is the wrong value if encryption has been used.\n\nSo we need to setup conditional_etag (same as on object server).\n\nIt *may* be that conditional_response\u003dTrue is not required at line 1960, but I do not feel confident to change that here without more research.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d8d695ae47b9b30e92f4bb1ff426217b1b8b786b","unresolved":false,"context_lines":[{"line_number":1989,"context_line":"        # We\u0027re about to invoke conditional response checking so set the"},{"line_number":1990,"context_line":"        # correct conditional etag from wherever X-Backend-Etag-Is-At points,"},{"line_number":1991,"context_line":"        # if it exists at all."},{"line_number":1992,"context_line":"        resp._conditional_etag \u003d resolve_etag_is_at_header(req, resp.headers)"},{"line_number":1993,"context_line":"        if (is_success(resp.status_int) or is_redirection(resp.status_int) or"},{"line_number":1994,"context_line":"                resp.status_int \u003d\u003d HTTP_REQUESTED_RANGE_NOT_SATISFIABLE):"},{"line_number":1995,"context_line":"            resp.accept_ranges \u003d \u0027bytes\u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_ea4f32bc","line":1992,"in_reply_to":"7aa08908_63a38f01","updated":"2016-06-16 06:41:39.000000000","message":"Make sense. Exactly conditional_response\u003dTrue triggers the conditional check and it needs the etag resolver. Probably, I\u0027m feeling same thing with you like that *we might remove the redundant (both at proxy and at object-server) conditional check* because X-Backend-Etag-Is-At is assigned by *proxy* expecting object-server resolves it, *maybe?*\n\nBut I agree that needs more research if we can get rid of really so it\u0027s ok to pend it *after* the this patch chain landed onto master.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e3b7e2d3690dddfb27a9de615d45c0ca9f1aaba4","unresolved":false,"context_lines":[{"line_number":1989,"context_line":"        # We\u0027re about to invoke conditional response checking so set the"},{"line_number":1990,"context_line":"        # correct conditional etag from wherever X-Backend-Etag-Is-At points,"},{"line_number":1991,"context_line":"        # if it exists at all."},{"line_number":1992,"context_line":"        resp._conditional_etag \u003d resolve_etag_is_at_header(req, resp.headers)"},{"line_number":1993,"context_line":"        if (is_success(resp.status_int) or is_redirection(resp.status_int) or"},{"line_number":1994,"context_line":"                resp.status_int \u003d\u003d HTTP_REQUESTED_RANGE_NOT_SATISFIABLE):"},{"line_number":1995,"context_line":"            resp.accept_ranges \u003d \u0027bytes\u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_b1391df5","line":1992,"in_reply_to":"7aa08908_ea4f32bc","updated":"2016-06-16 08:32:10.000000000","message":"ok, follow up task","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":1998,"context_line":"                \u0027X-Object-Sysmeta-Ec-Content-Length\u0027)"},{"line_number":1999,"context_line":"            resp.fix_conditional_response()"},{"line_number":2000,"context_line":""},{"line_number":2001,"context_line":"    def _make_putter(self, node, part, req, headers):"},{"line_number":2002,"context_line":"        # the object server will get different bytes, so these"},{"line_number":2003,"context_line":"        # values do not apply (Content-Length might, in general, but"},{"line_number":2004,"context_line":"        # in the specific case of replication vs. EC, it doesn\u0027t)."}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_4a288933","line":2001,"range":{"start_line":2001,"start_character":27,"end_line":2001,"end_character":31},"updated":"2016-06-14 05:17:47.000000000","message":"Since we now get a specific node and let the caller iterate through nodes until we return a live putter, the expected_frag_size calculation can call out to PyECLib repeatedly. Am I right to think that presents minimal overhead?\n\nWhat about the header mutations? Are those safe? We pop off Content-Length then stuff a derived value into X-Backend-Obj-Content-Length; if our putter fails, will the subsequent call send a fresh header dict (with Content-Length) or a dirty one (with no Content-Length, but a X-Backend-Obj-Content-Length that will get overwritten with None)?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":1998,"context_line":"                \u0027X-Object-Sysmeta-Ec-Content-Length\u0027)"},{"line_number":1999,"context_line":"            resp.fix_conditional_response()"},{"line_number":2000,"context_line":""},{"line_number":2001,"context_line":"    def _make_putter(self, node, part, req, headers):"},{"line_number":2002,"context_line":"        # the object server will get different bytes, so these"},{"line_number":2003,"context_line":"        # values do not apply (Content-Length might, in general, but"},{"line_number":2004,"context_line":"        # in the specific case of replication vs. EC, it doesn\u0027t)."}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_0ee640b0","line":2001,"range":{"start_line":2001,"start_character":27,"end_line":2001,"end_character":31},"in_reply_to":"7aa08908_4a288933","updated":"2016-06-15 15:20:40.000000000","message":"We\u0027re already repeating the expected_frag_size calculation for each backend PUT, so repeating again for when a putter fails is probably ok. BUT we can do better and move the calculation to _store_object, do it once and fix up the backend request headers there.\n\nThat will also take care of the dict mutation concern you mention, which is valid I think (in this version).","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":2151,"context_line":"                        bytes_transferred,"},{"line_number":2152,"context_line":"                        chunk_index[putter])"},{"line_number":2153,"context_line":"                    # update with any footers set by middleware"},{"line_number":2154,"context_line":"                    trail_md.update(self._get_footers(req))"},{"line_number":2155,"context_line":"                    # but Etag must always be hash of what we sent"},{"line_number":2156,"context_line":"                    trail_md[\u0027Etag\u0027] \u003d \\"},{"line_number":2157,"context_line":"                        putter.chunk_hasher.hexdigest()"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_ce0f188a","line":2154,"updated":"2016-06-15 12:15:22.000000000","message":"I think we should make something to reserve the original metadata for EC (e.g. segment size, chunk_index or whatever). Otherwise, any middleware can break everything easily.\n\n\nAnd when I was playing with this to try to break EC footer like as [1], unexpectedly I found one more bug that trail_md is just a dict but _get_footers try to update it wiht *HeadersKeyDict*. That means we can make duplicate header keys with both title case and non-title case which is unsafe for HTTP.\n\n\ne.g.:\nwe can make a header like,\n\n{\u0027X-Object-Sysmeta-Ec-Content-Length\u0027: \u002710\u0027, \u0027X-Object-Sysmeta-EC-Content-Length\u0027: \u002720\u0027}\n\n*Note that the second one\u0027s EC is upper case\n\n1: http://paste.openstack.org/show/516234/","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":2151,"context_line":"                        bytes_transferred,"},{"line_number":2152,"context_line":"                        chunk_index[putter])"},{"line_number":2153,"context_line":"                    # update with any footers set by middleware"},{"line_number":2154,"context_line":"                    trail_md.update(self._get_footers(req))"},{"line_number":2155,"context_line":"                    # but Etag must always be hash of what we sent"},{"line_number":2156,"context_line":"                    trail_md[\u0027Etag\u0027] \u003d \\"},{"line_number":2157,"context_line":"                        putter.chunk_hasher.hexdigest()"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_d9b7d638","line":2154,"in_reply_to":"7aa08908_ce0f188a","updated":"2016-06-15 15:20:40.000000000","message":"Good catch. I think I can simply reverse the update so EC updates middleware headers and that takes care of both concerns.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":2152,"context_line":"                        chunk_index[putter])"},{"line_number":2153,"context_line":"                    # update with any footers set by middleware"},{"line_number":2154,"context_line":"                    trail_md.update(self._get_footers(req))"},{"line_number":2155,"context_line":"                    # but Etag must always be hash of what we sent"},{"line_number":2156,"context_line":"                    trail_md[\u0027Etag\u0027] \u003d \\"},{"line_number":2157,"context_line":"                        putter.chunk_hasher.hexdigest()"},{"line_number":2158,"context_line":"                    putter.end_of_object_data(footer_metadata\u003dtrail_md)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_2abb7de6","line":2155,"updated":"2016-06-14 05:17:47.000000000","message":"If a trailing Etag was set, should we do any sort of validation before throwing it away? Say, against computed_etag?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":2152,"context_line":"                        chunk_index[putter])"},{"line_number":2153,"context_line":"                    # update with any footers set by middleware"},{"line_number":2154,"context_line":"                    trail_md.update(self._get_footers(req))"},{"line_number":2155,"context_line":"                    # but Etag must always be hash of what we sent"},{"line_number":2156,"context_line":"                    trail_md[\u0027Etag\u0027] \u003d \\"},{"line_number":2157,"context_line":"                        putter.chunk_hasher.hexdigest()"},{"line_number":2158,"context_line":"                    putter.end_of_object_data(footer_metadata\u003dtrail_md)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_29e696b0","line":2155,"in_reply_to":"7aa08908_2abb7de6","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"50b60af499537a75c1535843649efa2ae77ce6ae","unresolved":false,"context_lines":[{"line_number":2258,"context_line":"        # For an EC PUT we require a quorum of responses with success statuses"},{"line_number":2259,"context_line":"        # in order to move on to next phase of PUT request handling without"},{"line_number":2260,"context_line":"        # having to wait for *all* responses."},{"line_number":2261,"context_line":"        # TODO: this implies that in the first phase of the backend PUTs when"},{"line_number":2262,"context_line":"        # we are actually expecting 1xx responses that we will end up waiting"},{"line_number":2263,"context_line":"        # for *all* responses. That seems inefficient since we only need a"},{"line_number":2264,"context_line":"        # quorum of 1xx responses to proceed."}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_223d6f2b","line":2261,"updated":"2016-06-14 05:17:47.000000000","message":"Dangling TODO.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":2258,"context_line":"        # For an EC PUT we require a quorum of responses with success statuses"},{"line_number":2259,"context_line":"        # in order to move on to next phase of PUT request handling without"},{"line_number":2260,"context_line":"        # having to wait for *all* responses."},{"line_number":2261,"context_line":"        # TODO: this implies that in the first phase of the backend PUTs when"},{"line_number":2262,"context_line":"        # we are actually expecting 1xx responses that we will end up waiting"},{"line_number":2263,"context_line":"        # for *all* responses. That seems inefficient since we only need a"},{"line_number":2264,"context_line":"        # quorum of 1xx responses to proceed."}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_c9339212","line":2261,"in_reply_to":"7aa08908_223d6f2b","updated":"2016-06-15 15:20:40.000000000","message":"This TODO is noting current behaviour that seems like it could be improved but I am not taking it on in this patch. Seems a shame to lose the information, should I file it as a bug report instead?","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"609d39c789667525b33a73d561b8d60a54e82a8b","unresolved":false,"context_lines":[{"line_number":2144,"context_line":"                    trail_md.update(trailing_metadata("},{"line_number":2145,"context_line":"                        policy, etag_hasher,"},{"line_number":2146,"context_line":"                        bytes_transferred,"},{"line_number":2147,"context_line":"                        chunk_index[putter]))"},{"line_number":2148,"context_line":"                    # Etag footer must always be hash of what we sent"},{"line_number":2149,"context_line":"                    trail_md[\u0027Etag\u0027] \u003d \\"},{"line_number":2150,"context_line":"                        putter.chunk_hasher.hexdigest()"}],"source_content_type":"text/x-python","patch_set":3,"id":"7aa08908_bd7a9675","line":2147,"updated":"2016-06-16 06:52:41.000000000","message":"I think we should save \u0027X-Backend-Container-Update-Override-Etag\u0027 and \u0027X-Backend-Container-Update-Override-Size\u0027 comes from middleware.","commit_id":"75cf885aa72f67306cd82e642b4d2d2fc3c1899e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8d411d6c3568907ebf1649c835f0744f3c8040fa","unresolved":false,"context_lines":[{"line_number":2144,"context_line":"                    trail_md.update(trailing_metadata("},{"line_number":2145,"context_line":"                        policy, etag_hasher,"},{"line_number":2146,"context_line":"                        bytes_transferred,"},{"line_number":2147,"context_line":"                        chunk_index[putter]))"},{"line_number":2148,"context_line":"                    # Etag footer must always be hash of what we sent"},{"line_number":2149,"context_line":"                    trail_md[\u0027Etag\u0027] \u003d \\"},{"line_number":2150,"context_line":"                        putter.chunk_hasher.hexdigest()"}],"source_content_type":"text/x-python","patch_set":3,"id":"7aa08908_212aede7","line":2147,"in_reply_to":"7aa08908_bd7a9675","updated":"2016-06-16 12:45:24.000000000","message":"Done","commit_id":"75cf885aa72f67306cd82e642b4d2d2fc3c1899e"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"9b91c393ed3dc9ad431621ad5cf8db544acfd410","unresolved":false,"context_lines":[{"line_number":813,"context_line":""},{"line_number":814,"context_line":"                for putter in putters:"},{"line_number":815,"context_line":"                    putter.wait()"},{"line_number":816,"context_line":"                putters \u003d [p for p in putters if not p.failed]"},{"line_number":817,"context_line":"                self._check_min_conn("},{"line_number":818,"context_line":"                    req, putters, min_conns,"},{"line_number":819,"context_line":"                    msg\u003d_(\u0027Object PUT exceptions after last send, \u0027"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_1091289a","line":816,"updated":"2016-06-22 08:34:46.000000000","message":"It seems safe because the new putters variable is used as local variable but I like to avoid reassignment in particular here. That is because the putters list has important role to close all available backend connections.\n\nJust like as:\n\n self._check_min_conn(\n   req, [p for p in putters if not p.failed], min_conns,\n   msg\u003d_(\u0027Object PUT exceptions after last send, \u0027\n         \u0027%(conns)s/%(nodes)s required connections\u0027))\n\n\n?","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f21be46131f7797c2c41bbb942f80fe0f3589423","unresolved":false,"context_lines":[{"line_number":813,"context_line":""},{"line_number":814,"context_line":"                for putter in putters:"},{"line_number":815,"context_line":"                    putter.wait()"},{"line_number":816,"context_line":"                putters \u003d [p for p in putters if not p.failed]"},{"line_number":817,"context_line":"                self._check_min_conn("},{"line_number":818,"context_line":"                    req, putters, min_conns,"},{"line_number":819,"context_line":"                    msg\u003d_(\u0027Object PUT exceptions after last send, \u0027"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_b06809bc","line":816,"in_reply_to":"3aaa91ec_1091289a","updated":"2016-06-22 10:54:37.000000000","message":"Done","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"9b91c393ed3dc9ad431621ad5cf8db544acfd410","unresolved":false,"context_lines":[{"line_number":1548,"context_line":""},{"line_number":1549,"context_line":"    def close(self):"},{"line_number":1550,"context_line":"        # release reference to response to ensure connection really does close"},{"line_number":1551,"context_line":"        self.resp \u003d self.conn.resp \u003d None"},{"line_number":1552,"context_line":"        self.conn.close()"},{"line_number":1553,"context_line":""},{"line_number":1554,"context_line":"    @classmethod"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_fff9c74e","line":1551,"updated":"2016-06-22 08:34:46.000000000","message":"Yeah, nice. Exactly this magic kicks to propagate the connection close to object-server. If we don\u0027t have this, object-server doesn\u0027t notice the connection closed until request timeout.","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"9b91c393ed3dc9ad431621ad5cf8db544acfd410","unresolved":false,"context_lines":[{"line_number":1593,"context_line":"        :raises: InsufficientStorage on 507 response from node"},{"line_number":1594,"context_line":"        :raises: PutterConnectError on non-507 server error response from node"},{"line_number":1595,"context_line":"        \"\"\""},{"line_number":1596,"context_line":"        conn, resp, connect_duration \u003d cls._make_connection("},{"line_number":1597,"context_line":"            node, part, path, headers, conn_timeout, node_timeout)"},{"line_number":1598,"context_line":"        return cls(conn, node, conn.resp, path, connect_duration, logger,"},{"line_number":1599,"context_line":"                   chunked\u003dchunked)"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_051ba473","line":1596,"updated":"2016-06-22 08:34:46.000000000","message":"nits) resp is not used anymore.\n\nThis change makes ne sense, though probably I\u0027d like to refactor around the resp control, but it\u0027s ok in followup. \n\n_make_connection will return response of getexpect() so probably it\u0027s \"expect_response\" and conn.resp means \"whether we need more response from object-server or not\". For example, if conn.resp is None, yes we need getexpect() or getresponse() and if conn.resp is not None, that means it is enough for handling. Howver, I\u0027m thinking of sort of the capability if we could handle the status in Putter and Putter.resp (and also conn.node)?\n\nI think, the reason we have some instance variables in conn variable (i.e. resp, node) is why we want to encapsulate such information into an instance. However, since this patch, we have the capsule (i.e. Putter/MIMEPutter) here, so it doesn\u0027t seem to have to keep the old style anymore.","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f21be46131f7797c2c41bbb942f80fe0f3589423","unresolved":false,"context_lines":[{"line_number":1593,"context_line":"        :raises: InsufficientStorage on 507 response from node"},{"line_number":1594,"context_line":"        :raises: PutterConnectError on non-507 server error response from node"},{"line_number":1595,"context_line":"        \"\"\""},{"line_number":1596,"context_line":"        conn, resp, connect_duration \u003d cls._make_connection("},{"line_number":1597,"context_line":"            node, part, path, headers, conn_timeout, node_timeout)"},{"line_number":1598,"context_line":"        return cls(conn, node, conn.resp, path, connect_duration, logger,"},{"line_number":1599,"context_line":"                   chunked\u003dchunked)"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_50b9e5e8","line":1596,"in_reply_to":"3aaa91ec_051ba473","updated":"2016-06-22 10:54:37.000000000","message":"resp is used in MIMEPutter.connect so we still need to return it from _make_connection for that case\n\nAgree re potential to refactor and cleanup, we do seem to be encapsulating some state in conn and some in the Putter","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"264c5ee8bd8388112427a31a9ab86a1d510fd300","unresolved":false,"context_lines":[{"line_number":1712,"context_line":"        # content-length is not equal to the object content size, so move the"},{"line_number":1713,"context_line":"        # object content size to X-Backend-Obj-Content-Length if that has not"},{"line_number":1714,"context_line":"        # already been set by the EC PUT path."},{"line_number":1715,"context_line":"        headers.setdefault(\u0027X-Backend-Obj-Content-Length\u0027,"},{"line_number":1716,"context_line":"                           headers.pop(\u0027Content-Length\u0027, None))"},{"line_number":1717,"context_line":"        # We\u0027re going to be adding some unknown amount of data to the"},{"line_number":1718,"context_line":"        # request, so we can\u0027t use an explicit content length, and thus"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_68d1aecd","line":1715,"updated":"2016-06-22 01:20:33.000000000","message":"So earlier, were we sending both Content-Length and Transfer-Encoding for replicated-with-crypto? I\u0027m a little surprised nothing complained about the extra data...","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f21be46131f7797c2c41bbb942f80fe0f3589423","unresolved":false,"context_lines":[{"line_number":1712,"context_line":"        # content-length is not equal to the object content size, so move the"},{"line_number":1713,"context_line":"        # object content size to X-Backend-Obj-Content-Length if that has not"},{"line_number":1714,"context_line":"        # already been set by the EC PUT path."},{"line_number":1715,"context_line":"        headers.setdefault(\u0027X-Backend-Obj-Content-Length\u0027,"},{"line_number":1716,"context_line":"                           headers.pop(\u0027Content-Length\u0027, None))"},{"line_number":1717,"context_line":"        # We\u0027re going to be adding some unknown amount of data to the"},{"line_number":1718,"context_line":"        # request, so we can\u0027t use an explicit content length, and thus"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_a5dd6616","line":1715,"in_reply_to":"3aaa91ec_68d1aecd","updated":"2016-06-22 10:54:37.000000000","message":"I don\u0027t think we have ever sent both. Earlier on this review (e.g. at version 2 of this review, line 74) we popped Content-Length off in make_putter, then moved it here to avoid a mutation problem that you spotted.","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"264c5ee8bd8388112427a31a9ab86a1d510fd300","unresolved":false,"context_lines":[{"line_number":1743,"context_line":"            if need_multiphase and not can_handle_multiphase_put:"},{"line_number":1744,"context_line":"                raise MultiphasePUTNotSupported()"},{"line_number":1745,"context_line":""},{"line_number":1746,"context_line":"        return cls(conn, node, conn.resp, req, connect_duration, logger,"},{"line_number":1747,"context_line":"                   mime_boundary, multiphase\u003dneed_multiphase)"},{"line_number":1748,"context_line":""},{"line_number":1749,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_08f3ca74","line":1746,"range":{"start_line":1746,"start_character":31,"end_line":1746,"end_character":35},"updated":"2016-06-22 01:20:33.000000000","message":"What\u0027s the difference between resp and conn.resp? Why did we get both out of _make_connection?","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"9b91c393ed3dc9ad431621ad5cf8db544acfd410","unresolved":false,"context_lines":[{"line_number":1743,"context_line":"            if need_multiphase and not can_handle_multiphase_put:"},{"line_number":1744,"context_line":"                raise MultiphasePUTNotSupported()"},{"line_number":1745,"context_line":""},{"line_number":1746,"context_line":"        return cls(conn, node, conn.resp, req, connect_duration, logger,"},{"line_number":1747,"context_line":"                   mime_boundary, multiphase\u003dneed_multiphase)"},{"line_number":1748,"context_line":""},{"line_number":1749,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_e5e77810","line":1746,"range":{"start_line":1746,"start_character":31,"end_line":1746,"end_character":35},"in_reply_to":"3aaa91ec_08f3ca74","updated":"2016-06-22 08:34:46.000000000","message":"See my comment at L1596. Actually, resp rom _make_connection is the response of getexpect() and conn.resp is just a flag whether we need more response from object-server. (see Putter.await_response implementation)\n\nI think, we could refactor around this weird handling in the future.","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f21be46131f7797c2c41bbb942f80fe0f3589423","unresolved":false,"context_lines":[{"line_number":1743,"context_line":"            if need_multiphase and not can_handle_multiphase_put:"},{"line_number":1744,"context_line":"                raise MultiphasePUTNotSupported()"},{"line_number":1745,"context_line":""},{"line_number":1746,"context_line":"        return cls(conn, node, conn.resp, req, connect_duration, logger,"},{"line_number":1747,"context_line":"                   mime_boundary, multiphase\u003dneed_multiphase)"},{"line_number":1748,"context_line":""},{"line_number":1749,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_85ee6a20","line":1746,"range":{"start_line":1746,"start_character":31,"end_line":1746,"end_character":35},"in_reply_to":"3aaa91ec_e5e77810","updated":"2016-06-22 10:54:37.000000000","message":"+1 Kota\u0027s comments here and L1596. The mix of conn.resp and resp is on master in ECPutter too. conn.resp is being used to remember if there has been a final response to the connect getexpect. So conn.resp \u003d resp IFF resp is a final response.\n\nI have attempted some clarification in next version i.e. no longer use conn to encapsulate state, just use the Putter class. There\u0027s probably more that could be cleaned up but I don\u0027t want to mess with the logic too much, particularly in await_response. I have found it is easy to break things!","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"9b91c393ed3dc9ad431621ad5cf8db544acfd410","unresolved":false,"context_lines":[{"line_number":2070,"context_line":"        bytes_transferred \u003d 0"},{"line_number":2071,"context_line":"        chunk_transform \u003d chunk_transformer(policy, len(nodes))"},{"line_number":2072,"context_line":"        chunk_transform.send(None)"},{"line_number":2073,"context_line":"        chunk_hashers \u003d collections.defaultdict(md5)"},{"line_number":2074,"context_line":""},{"line_number":2075,"context_line":"        def send_chunk(chunk):"},{"line_number":2076,"context_line":"            # Note: there\u0027s two different hashers in here. etag_hasher is"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_f7b9eb2f","line":2073,"updated":"2016-06-22 08:34:46.000000000","message":"I think, this is prep to address to Sam\u0027s opinion[1]. Make sense. Is it great to add Sam as co-author?\n\n1: https://github.com/smerritt/swift/commit/2f4893d10bbe61127aafc298747301c66ae9a7d8","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f21be46131f7797c2c41bbb942f80fe0f3589423","unresolved":false,"context_lines":[{"line_number":2070,"context_line":"        bytes_transferred \u003d 0"},{"line_number":2071,"context_line":"        chunk_transform \u003d chunk_transformer(policy, len(nodes))"},{"line_number":2072,"context_line":"        chunk_transform.send(None)"},{"line_number":2073,"context_line":"        chunk_hashers \u003d collections.defaultdict(md5)"},{"line_number":2074,"context_line":""},{"line_number":2075,"context_line":"        def send_chunk(chunk):"},{"line_number":2076,"context_line":"            # Note: there\u0027s two different hashers in here. etag_hasher is"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_b03ac9cb","line":2073,"in_reply_to":"3aaa91ec_f7b9eb2f","updated":"2016-06-22 10:54:37.000000000","message":"Yes I applied Sam\u0027s first commit at that link, and I had intended (but then forgot) to add him as co-author, thanks for reminder.","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"57763779258221ad6c0667e5e672834f3bd8f2b0","unresolved":false,"context_lines":[{"line_number":1471,"context_line":"        :returns: HTTPResponse"},{"line_number":1472,"context_line":"        :raises: Timeout if the response took too long"},{"line_number":1473,"context_line":"        \"\"\""},{"line_number":1474,"context_line":"        with Timeout(timeout):"},{"line_number":1475,"context_line":"            # don\u0027t do this update of self.resp if the Expect response during"},{"line_number":1476,"context_line":"            # conenct() was actually a final response"},{"line_number":1477,"context_line":"            if not self.final_resp:"}],"source_content_type":"text/x-python","patch_set":7,"id":"3aaa91ec_ca3808a3","line":1474,"updated":"2016-06-24 07:20:25.000000000","message":"Does the Timeout context cost us much of anything? Wondering if it might make sense to swap things about to have\n\n if not self.final_resp:\n     with Timeout(timeout):\n         ...\n return self.resp","commit_id":"03b762e80a9b3d33ce13b8222f4cd2b549171c51"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"00339c9171df4b1552663d3801af8c3f9ea6c38c","unresolved":false,"context_lines":[{"line_number":1471,"context_line":"        :returns: HTTPResponse"},{"line_number":1472,"context_line":"        :raises: Timeout if the response took too long"},{"line_number":1473,"context_line":"        \"\"\""},{"line_number":1474,"context_line":"        with Timeout(timeout):"},{"line_number":1475,"context_line":"            # don\u0027t do this update of self.resp if the Expect response during"},{"line_number":1476,"context_line":"            # conenct() was actually a final response"},{"line_number":1477,"context_line":"            if not self.final_resp:"}],"source_content_type":"text/x-python","patch_set":7,"id":"3aaa91ec_6c012c06","line":1474,"in_reply_to":"3aaa91ec_ca3808a3","updated":"2016-06-24 09:46:58.000000000","message":"Agree. But given +2s on this patch and the next dependent patch I\u0027m inclined to leave this unchanged and make a note for follow up. Since we are anticpating Sam\u0027s Putter unification to also be a follow up then that will be an opportunity perhaps.\n\nNoted here https://trello.com/c/wj2fFw3l/120-move-timeout-inside-if-clause","commit_id":"03b762e80a9b3d33ce13b8222f4cd2b549171c51"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"57763779258221ad6c0667e5e672834f3bd8f2b0","unresolved":false,"context_lines":[{"line_number":1478,"context_line":"                if informational:"},{"line_number":1479,"context_line":"                    self.resp \u003d self.conn.getexpect()"},{"line_number":1480,"context_line":"                else:"},{"line_number":1481,"context_line":"                    self.resp \u003d self.conn.getresponse()"},{"line_number":1482,"context_line":"            return self.resp"},{"line_number":1483,"context_line":""},{"line_number":1484,"context_line":"    def spawn_sender_greenthread(self, pool, queue_depth, write_timeout,"}],"source_content_type":"text/x-python","patch_set":7,"id":"3aaa91ec_296ba8b8","line":1481,"updated":"2016-06-24 07:20:25.000000000","message":"Should we also set self.final_resp here?","commit_id":"03b762e80a9b3d33ce13b8222f4cd2b549171c51"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"00339c9171df4b1552663d3801af8c3f9ea6c38c","unresolved":false,"context_lines":[{"line_number":1478,"context_line":"                if informational:"},{"line_number":1479,"context_line":"                    self.resp \u003d self.conn.getexpect()"},{"line_number":1480,"context_line":"                else:"},{"line_number":1481,"context_line":"                    self.resp \u003d self.conn.getresponse()"},{"line_number":1482,"context_line":"            return self.resp"},{"line_number":1483,"context_line":""},{"line_number":1484,"context_line":"    def spawn_sender_greenthread(self, pool, queue_depth, write_timeout,"}],"source_content_type":"text/x-python","patch_set":7,"id":"3aaa91ec_8ca8d821","line":1481,"in_reply_to":"3aaa91ec_296ba8b8","updated":"2016-06-24 09:46:58.000000000","message":"Good question, and one I also pondered. The logic here is same as on master.\n\nThe getexpect here is the second getexpect (first was during connect()) and is used druing a two phase PUT to figure out if commit should be sent. We don\u0027t check the status code here to see if we get back a final response, and we would not expect to. But AFAICT if we bail out in pet_put_responses if there aren\u0027t sufficient 100\u0027s returned.\n\nThe getresponse() is only called at end of transaction, so we never then call await_response again.\n\nSo maybe we could set final_resp, but we probably don\u0027t need to and in the end I decided not to tinker with it in the context of this patch given that\u0027s how it is on master.","commit_id":"03b762e80a9b3d33ce13b8222f4cd2b549171c51"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"57763779258221ad6c0667e5e672834f3bd8f2b0","unresolved":false,"context_lines":[{"line_number":1551,"context_line":"        # release reference to response to ensure connection really does close,"},{"line_number":1552,"context_line":"        # see bug https://bugs.launchpad.net/swift/+bug/1594739"},{"line_number":1553,"context_line":"        self.resp \u003d self.final_resp \u003d None"},{"line_number":1554,"context_line":"        self.conn.close()"},{"line_number":1555,"context_line":""},{"line_number":1556,"context_line":"    @classmethod"},{"line_number":1557,"context_line":"    def _make_connection(cls, node, part, path, headers, conn_timeout,"}],"source_content_type":"text/x-python","patch_set":7,"id":"3aaa91ec_2adc2c72","line":1554,"updated":"2016-06-24 07:20:25.000000000","message":"So self.conn no longer has any resp attribute? Nice.","commit_id":"03b762e80a9b3d33ce13b8222f4cd2b549171c51"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"00339c9171df4b1552663d3801af8c3f9ea6c38c","unresolved":false,"context_lines":[{"line_number":1551,"context_line":"        # release reference to response to ensure connection really does close,"},{"line_number":1552,"context_line":"        # see bug https://bugs.launchpad.net/swift/+bug/1594739"},{"line_number":1553,"context_line":"        self.resp \u003d self.final_resp \u003d None"},{"line_number":1554,"context_line":"        self.conn.close()"},{"line_number":1555,"context_line":""},{"line_number":1556,"context_line":"    @classmethod"},{"line_number":1557,"context_line":"    def _make_connection(cls, node, part, path, headers, conn_timeout,"}],"source_content_type":"text/x-python","patch_set":7,"id":"3aaa91ec_8c7f38aa","line":1554,"in_reply_to":"3aaa91ec_2adc2c72","updated":"2016-06-24 09:46:58.000000000","message":"Correct. The Putter now acts as the home for all the state we want to track, the conn is left unadorned.","commit_id":"03b762e80a9b3d33ce13b8222f4cd2b549171c51"}],"test/unit/__init__.py":[{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"9b91c393ed3dc9ad431621ad5cf8db544acfd410","unresolved":false,"context_lines":[{"line_number":866,"context_line":"            self.timestamp \u003d timestamp"},{"line_number":867,"context_line":"            self.connection_id \u003d connection_id"},{"line_number":868,"context_line":"            self.give_send \u003d give_send"},{"line_number":869,"context_line":"            self.give_expect \u003d give_expect"},{"line_number":870,"context_line":"            self.closed \u003d False"},{"line_number":871,"context_line":"            if \u0027slow\u0027 in kwargs and isinstance(kwargs[\u0027slow\u0027], list):"},{"line_number":872,"context_line":"                try:"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_5788bfe7","line":869,"updated":"2016-06-22 08:34:46.000000000","message":"hehe, give_expect seems better than my draft patch for capturing connection.","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f21be46131f7797c2c41bbb942f80fe0f3589423","unresolved":false,"context_lines":[{"line_number":866,"context_line":"            self.timestamp \u003d timestamp"},{"line_number":867,"context_line":"            self.connection_id \u003d connection_id"},{"line_number":868,"context_line":"            self.give_send \u003d give_send"},{"line_number":869,"context_line":"            self.give_expect \u003d give_expect"},{"line_number":870,"context_line":"            self.closed \u003d False"},{"line_number":871,"context_line":"            if \u0027slow\u0027 in kwargs and isinstance(kwargs[\u0027slow\u0027], list):"},{"line_number":872,"context_line":"                try:"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_086611ed","line":869,"in_reply_to":"3aaa91ec_5788bfe7","updated":"2016-06-22 10:54:37.000000000","message":"Its a shame that give_connect is called before the FakeConn has been instantiated, and I didn\u0027t want to change that for fear of disturbing other tests.","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"9b91c393ed3dc9ad431621ad5cf8db544acfd410","unresolved":false,"context_lines":[{"line_number":971,"context_line":""},{"line_number":972,"context_line":"        def close(self):"},{"line_number":973,"context_line":"            self.closed \u003d True"},{"line_number":974,"context_line":"            pass"},{"line_number":975,"context_line":""},{"line_number":976,"context_line":"    timestamps_iter \u003d iter(kwargs.get(\u0027timestamps\u0027) or [\u00271\u0027] * len(code_iter))"},{"line_number":977,"context_line":"    etag_iter \u003d iter(kwargs.get(\u0027etags\u0027) or [None] * len(code_iter))"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_d7ef8fae","line":974,"range":{"start_line":974,"start_character":11,"end_line":974,"end_character":16},"updated":"2016-06-22 08:34:46.000000000","message":"nits) pass is needn\u0027t anymore","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f21be46131f7797c2c41bbb942f80fe0f3589423","unresolved":false,"context_lines":[{"line_number":971,"context_line":""},{"line_number":972,"context_line":"        def close(self):"},{"line_number":973,"context_line":"            self.closed \u003d True"},{"line_number":974,"context_line":"            pass"},{"line_number":975,"context_line":""},{"line_number":976,"context_line":"    timestamps_iter \u003d iter(kwargs.get(\u0027timestamps\u0027) or [\u00271\u0027] * len(code_iter))"},{"line_number":977,"context_line":"    etag_iter \u003d iter(kwargs.get(\u0027etags\u0027) or [None] * len(code_iter))"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_a89b7dc8","line":974,"range":{"start_line":974,"start_character":11,"end_line":974,"end_character":16},"in_reply_to":"3aaa91ec_d7ef8fae","updated":"2016-06-22 10:54:37.000000000","message":"Done","commit_id":"b9f4df2a7fe58bb17682f0ec68a5d05578b05a83"}],"test/unit/common/test_request_helpers.py":[{"author":{"_account_id":330,"name":"John Dickinson","email":"me@not.mn","username":"notmyname"},"change_message_id":"4934f152fa68caf0280204f8549924651baffccc","unresolved":false,"context_lines":[{"line_number":325,"context_line":"        req.headers[\u0027X-Backend-Etag-Is-At\u0027] \u003d \\"},{"line_number":326,"context_line":"            \u0027X-Bogus, X-Object-Sysmeta-My-Etag , X-Object-Sysmeta-Ec-Etag\u0027"},{"line_number":327,"context_line":"        self.assertEqual(\u0027another etag value\u0027,"},{"line_number":328,"context_line":"                         resolve_etag_is_at_header(req, metadata))"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a9d85d2_f73f1923","line":328,"updated":"2016-06-20 23:49:06.000000000","message":"Might be nice to have a case test here. Header keys are case-insensitive.","commit_id":"9cab7bbc4c43238ffdd2d70260302e911c44a705"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"775cee8ffe75b4ffeb08ffd31860dc7c603deae9","unresolved":false,"context_lines":[{"line_number":325,"context_line":"        req.headers[\u0027X-Backend-Etag-Is-At\u0027] \u003d \\"},{"line_number":326,"context_line":"            \u0027X-Bogus, X-Object-Sysmeta-My-Etag , X-Object-Sysmeta-Ec-Etag\u0027"},{"line_number":327,"context_line":"        self.assertEqual(\u0027another etag value\u0027,"},{"line_number":328,"context_line":"                         resolve_etag_is_at_header(req, metadata))"}],"source_content_type":"text/x-python","patch_set":5,"id":"3aaa91ec_b29af8c3","line":328,"in_reply_to":"5a9d85d2_f73f1923","updated":"2016-06-21 18:17:11.000000000","message":"Done. Turns out the test failed :/","commit_id":"9cab7bbc4c43238ffdd2d70260302e911c44a705"}],"test/unit/obj/test_server.py":[{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":2415,"context_line":"            \u0027X-Backend-Etag-Is-At\u0027: alts})"},{"line_number":2416,"context_line":"        resp \u003d req.get_response(self.object_controller)"},{"line_number":2417,"context_line":"        self.assertEqual(resp.status_int, 200)"},{"line_number":2418,"context_line":""},{"line_number":2419,"context_line":"        # no match x-backend-etag-is-at"},{"line_number":2420,"context_line":"        req \u003d Request.blank(\u0027/sda1/p/a/c/o\u0027, headers\u003d{"},{"line_number":2421,"context_line":"            \u0027If-Match\u0027: real_etag,"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_8967cab6","line":2418,"updated":"2016-06-15 12:15:22.000000000","message":"Should we have one more test with 2 candidate exist in object metadata?\n\ne.g. :\nthe stored object has both X-Object-Meta-Xtag and X-Object-Sysmteta-Z and X-Backend-Etag-Is-At is \"X-Object-Sysmeta-Y,X-Object-Meta-Xtag,X-Object-Sysmeta-Z\" and it will choose X-Object-Meta-Xtag value.","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":2415,"context_line":"            \u0027X-Backend-Etag-Is-At\u0027: alts})"},{"line_number":2416,"context_line":"        resp \u003d req.get_response(self.object_controller)"},{"line_number":2417,"context_line":"        self.assertEqual(resp.status_int, 200)"},{"line_number":2418,"context_line":""},{"line_number":2419,"context_line":"        # no match x-backend-etag-is-at"},{"line_number":2420,"context_line":"        req \u003d Request.blank(\u0027/sda1/p/a/c/o\u0027, headers\u003d{"},{"line_number":2421,"context_line":"            \u0027If-Match\u0027: real_etag,"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_b9a80a79","line":2418,"in_reply_to":"7aa08908_8967cab6","updated":"2016-06-15 15:20:40.000000000","message":"Done","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":330,"name":"John Dickinson","email":"me@not.mn","username":"notmyname"},"change_message_id":"4934f152fa68caf0280204f8549924651baffccc","unresolved":false,"context_lines":[{"line_number":2426,"context_line":"        self.assertEqual(resp.status_int, 200)"},{"line_number":2427,"context_line":""},{"line_number":2428,"context_line":"        # match x-backend-etag-is-at, choosing first of multiple alternates"},{"line_number":2429,"context_line":"        alts \u003d \u0027X-Object-Sysmeta-Y,X-Object-Sysmeta-Xtag,X-Object-Meta-Xtag\u0027"},{"line_number":2430,"context_line":"        req \u003d Request.blank(\u0027/sda1/p/a/c/o\u0027, headers\u003d{"},{"line_number":2431,"context_line":"            \u0027If-Match\u0027: \u0027alternate madeup\u0027,"},{"line_number":2432,"context_line":"            \u0027X-Backend-Etag-Is-At\u0027: alts})"}],"source_content_type":"text/x-python","patch_set":5,"id":"5a9d85d2_f789d9cb","line":2429,"updated":"2016-06-20 23:49:06.000000000","message":"Took me a while to see the difference in this line and 2421.\n\nMight be worth an explicit \"this swaps the 2nd two from the above order\" comment, or similar","commit_id":"9cab7bbc4c43238ffdd2d70260302e911c44a705"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"775cee8ffe75b4ffeb08ffd31860dc7c603deae9","unresolved":false,"context_lines":[{"line_number":2426,"context_line":"        self.assertEqual(resp.status_int, 200)"},{"line_number":2427,"context_line":""},{"line_number":2428,"context_line":"        # match x-backend-etag-is-at, choosing first of multiple alternates"},{"line_number":2429,"context_line":"        alts \u003d \u0027X-Object-Sysmeta-Y,X-Object-Sysmeta-Xtag,X-Object-Meta-Xtag\u0027"},{"line_number":2430,"context_line":"        req \u003d Request.blank(\u0027/sda1/p/a/c/o\u0027, headers\u003d{"},{"line_number":2431,"context_line":"            \u0027If-Match\u0027: \u0027alternate madeup\u0027,"},{"line_number":2432,"context_line":"            \u0027X-Backend-Etag-Is-At\u0027: alts})"}],"source_content_type":"text/x-python","patch_set":5,"id":"3aaa91ec_529c7469","line":2429,"in_reply_to":"5a9d85d2_f789d9cb","updated":"2016-06-21 18:17:11.000000000","message":"Done","commit_id":"9cab7bbc4c43238ffdd2d70260302e911c44a705"}],"test/unit/proxy/controllers/test_obj.py":[{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"d7c6e18e85a4cc62aa75376a528f193c0418c596","unresolved":false,"context_lines":[{"line_number":735,"context_line":"            footers_callback(expected)"},{"line_number":736,"context_line":"            self.assertDictEqual(expected, footer_metadata)"},{"line_number":737,"context_line":""},{"line_number":738,"context_line":"            self.assertTrue(info[\u0027connection\u0027].closed)"},{"line_number":739,"context_line":""},{"line_number":740,"context_line":"    def test_PUT_with_body_and_footers(self):"},{"line_number":741,"context_line":"        self._test_PUT_with_footers(test_body\u003d\u0027asdf\u0027)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_44fdc73a","line":738,"updated":"2016-06-15 12:15:22.000000000","message":"Awesome, those test looks great!","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02e456bf9dc6b594d21376555b792eb05244eaeb","unresolved":false,"context_lines":[{"line_number":735,"context_line":"            footers_callback(expected)"},{"line_number":736,"context_line":"            self.assertDictEqual(expected, footer_metadata)"},{"line_number":737,"context_line":""},{"line_number":738,"context_line":"            self.assertTrue(info[\u0027connection\u0027].closed)"},{"line_number":739,"context_line":""},{"line_number":740,"context_line":"    def test_PUT_with_body_and_footers(self):"},{"line_number":741,"context_line":"        self._test_PUT_with_footers(test_body\u003d\u0027asdf\u0027)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7aa08908_5c5594f8","line":738,"in_reply_to":"7aa08908_44fdc73a","updated":"2016-06-15 15:20:40.000000000","message":":)","commit_id":"48edce640643a96db9847b69e8153d03bd12c56b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"609d39c789667525b33a73d561b8d60a54e82a8b","unresolved":false,"context_lines":[{"line_number":1714,"context_line":"        footers_callback \u003d make_footers_callback()"},{"line_number":1715,"context_line":"        env \u003d {\u0027swift.callback.update_footers\u0027: footers_callback}"},{"line_number":1716,"context_line":"        req \u003d swift.common.swob.Request.blank("},{"line_number":1717,"context_line":"            \u0027/v1/a/c/o\u0027, method\u003d\u0027PUT\u0027, environ\u003denv)"},{"line_number":1718,"context_line":"        etag \u003d md5(test_body).hexdigest()"},{"line_number":1719,"context_line":"        size \u003d len(test_body)"},{"line_number":1720,"context_line":"        req.body \u003d test_body"}],"source_content_type":"text/x-python","patch_set":3,"id":"7aa08908_5d2f323e","line":1717,"updated":"2016-06-16 06:52:41.000000000","message":"Nice insertion and... (see a few line below).","commit_id":"75cf885aa72f67306cd82e642b4d2d2fc3c1899e"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"609d39c789667525b33a73d561b8d60a54e82a8b","unresolved":false,"context_lines":[{"line_number":1788,"context_line":"                \u0027X-Object-Sysmeta-Ec-Content-Length\u0027: str(size),"},{"line_number":1789,"context_line":"                \u0027X-Backend-Container-Update-Override-Size\u0027: str(size),"},{"line_number":1790,"context_line":"                \u0027X-Object-Sysmeta-Ec-Etag\u0027: etag,"},{"line_number":1791,"context_line":"                \u0027X-Backend-Container-Update-Override-Etag\u0027: etag,"},{"line_number":1792,"context_line":"                \u0027X-Object-Sysmeta-Ec-Segment-Size\u0027: str(segment_size),"},{"line_number":1793,"context_line":"            }"},{"line_number":1794,"context_line":"            footers_callback(expected)"}],"source_content_type":"text/x-python","patch_set":3,"id":"7aa08908_5d8bb21e","line":1791,"range":{"start_line":1791,"start_character":15,"end_line":1791,"end_character":65},"updated":"2016-06-16 06:52:41.000000000","message":"Yes, this means probably current patch set breaks the encyrpted object etag in container db, right? etag is calculated at L1718 so that is md5 hash of *raw object* and footer call back cannot change anything for container-update-overrides.","commit_id":"75cf885aa72f67306cd82e642b4d2d2fc3c1899e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8d411d6c3568907ebf1649c835f0744f3c8040fa","unresolved":false,"context_lines":[{"line_number":1788,"context_line":"                \u0027X-Object-Sysmeta-Ec-Content-Length\u0027: str(size),"},{"line_number":1789,"context_line":"                \u0027X-Backend-Container-Update-Override-Size\u0027: str(size),"},{"line_number":1790,"context_line":"                \u0027X-Object-Sysmeta-Ec-Etag\u0027: etag,"},{"line_number":1791,"context_line":"                \u0027X-Backend-Container-Update-Override-Etag\u0027: etag,"},{"line_number":1792,"context_line":"                \u0027X-Object-Sysmeta-Ec-Segment-Size\u0027: str(segment_size),"},{"line_number":1793,"context_line":"            }"},{"line_number":1794,"context_line":"            footers_callback(expected)"}],"source_content_type":"text/x-python","patch_set":3,"id":"7aa08908_81d5a1b8","line":1791,"range":{"start_line":1791,"start_character":15,"end_line":1791,"end_character":65},"in_reply_to":"7aa08908_5d8bb21e","updated":"2016-06-16 12:45:24.000000000","message":"encrypter will set x-object-sysmeta-container-update-override-etag \u003d encrypted_plaintext_etag and the object server will prefer this value over x-backend-container-update-override-etag \u003d ciphertext_etag\n\nSee https://review.openstack.org/#/c/328205/4/swift/obj/server.py","commit_id":"75cf885aa72f67306cd82e642b4d2d2fc3c1899e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"a1f6488e106ac9279428a691fa6b2b30cf601ea8","unresolved":false,"context_lines":[{"line_number":133,"context_line":"    footers_to_add \u003d {"},{"line_number":134,"context_line":"        \u0027X-Object-Sysmeta-Container-Update-Override-Etag\u0027: cont_etag,"},{"line_number":135,"context_line":"        \u0027X-Object-Sysmeta-Crypto-Etag\u0027: crypto_etag,"},{"line_number":136,"context_line":"        \u0027X-Object-Sysmeta-Crypto-Meta-Etag\u0027: etag_crypto_meta,"},{"line_number":137,"context_line":"        \u0027X-I-Feel-Lucky\u0027: \u0027Not blocked\u0027,"},{"line_number":138,"context_line":"        \u0027Etag\u0027: etag}"},{"line_number":139,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"3aaa91ec_5d20b249","line":136,"updated":"2016-06-28 17:55:50.000000000","message":"Might need to fix this in a later patchset -- X-Object-Sysmeta-Crypto-Meta-Etag got rolled into X-Object-Sysmeta-Crypto-Etag. Might be worth adding a X-Object-Sysmeta-Crypto-Etag-Mac?","commit_id":"03b762e80a9b3d33ce13b8222f4cd2b549171c51"}]}
