)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bdbfbbd9d16565231cc290313809a7f9fa487010","unresolved":false,"context_lines":[{"line_number":60,"context_line":"  is the only part required to be sync\u0027d."},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"- object server will allow PUT and DELETE with earlier timestamp than"},{"line_number":63,"context_line":"  a POST"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"Related spec change-id: I60688efc3df692d3a39557114dca8c5490f7837e"},{"line_number":66,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":14,"id":"7a016987_974872b4","line":63,"updated":"2015-05-23 00:06:33.000000000","message":"i wonder if this capability extends to the client.","commit_id":"bc3584df5fd92f0b791cbc992ec544f62a701bea"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":62,"context_line":"  is the only part required to be sync\u0027d."},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"- object server will allow PUT and DELETE with earlier timestamp than"},{"line_number":65,"context_line":"  a POST"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"Related spec change-id: I60688efc3df692d3a39557114dca8c5490f7837e"},{"line_number":68,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":21,"id":"9a1a9d01_2774c6cd","line":65,"updated":"2015-10-02 05:30:01.000000000","message":"lol, gotta read the fine print at the end!\n\ns\u0027ok - I\u0027m on board with this - but if anyone else wants to think about how this might screw us later now is probably as good a time as any.","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"}],"swift/common/utils.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":737,"context_line":"    compatible for normalized timestamps which do not include an offset."},{"line_number":738,"context_line":"    \"\"\""},{"line_number":739,"context_line":""},{"line_number":740,"context_line":"    def __init__(self, timestamp, offset\u003d0, delta\u003d0):"},{"line_number":741,"context_line":"        if isinstance(timestamp, basestring):"},{"line_number":742,"context_line":"            parts \u003d timestamp.split(\u0027_\u0027, 1)"},{"line_number":743,"context_line":"            self.timestamp \u003d float(parts.pop(0))"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_c801643b","line":740,"updated":"2015-10-02 05:30:01.000000000","message":"well, wtf is delta?  #docstring\n\ndon\u0027t love it...\n\nbut i guess it makes decode missing a tiny bit simpler...  I think maybe __add__ and __diff__ methods might have turned out a bit cuter, but it\u0027s just code.  And besides next time I need something like delta I may be overjoyed to find it already implemented!","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":737,"context_line":"    compatible for normalized timestamps which do not include an offset."},{"line_number":738,"context_line":"    \"\"\""},{"line_number":739,"context_line":""},{"line_number":740,"context_line":"    def __init__(self, timestamp, offset\u003d0, delta\u003d0):"},{"line_number":741,"context_line":"        if isinstance(timestamp, basestring):"},{"line_number":742,"context_line":"            parts \u003d timestamp.split(\u0027_\u0027, 1)"},{"line_number":743,"context_line":"            self.timestamp \u003d float(parts.pop(0))"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_75649f48","line":740,"in_reply_to":"9a1a9d01_c801643b","updated":"2015-10-02 11:17:58.000000000","message":"yeah now you say it, dunder methods would have done the job.\n\nfix in a followup?","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"}],"swift/obj/diskfile.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bdbfbbd9d16565231cc290313809a7f9fa487010","unresolved":false,"context_lines":[{"line_number":818,"context_line":"            suffixes \u003d ("},{"line_number":819,"context_line":"                (os.path.join(partition_path, suffix), suffix)"},{"line_number":820,"context_line":"                for suffix in suffixes)"},{"line_number":821,"context_line":"        key_map \u003d {\u0027data\u0027: \u0027ts_data\u0027, \u0027ts\u0027: \u0027ts_data\u0027, \u0027meta\u0027: \u0027ts_meta\u0027}"},{"line_number":822,"context_line":"        for suffix_path, suffix in suffixes:"},{"line_number":823,"context_line":"            for object_hash in self._listdir(suffix_path):"},{"line_number":824,"context_line":"                object_path \u003d os.path.join(suffix_path, object_hash)"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a016987_89f17697","line":821,"updated":"2015-05-23 00:06:33.000000000","message":"alister don\u0027t do this - *tombstone* or just *tomb* or something not ts","commit_id":"bc3584df5fd92f0b791cbc992ec544f62a701bea"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a98f23c3e53926edbb08bb14129bae21d2d06858","unresolved":false,"context_lines":[{"line_number":818,"context_line":"            suffixes \u003d ("},{"line_number":819,"context_line":"                (os.path.join(partition_path, suffix), suffix)"},{"line_number":820,"context_line":"                for suffix in suffixes)"},{"line_number":821,"context_line":"        key_map \u003d {\u0027data\u0027: \u0027ts_data\u0027, \u0027ts\u0027: \u0027ts_data\u0027, \u0027meta\u0027: \u0027ts_meta\u0027}"},{"line_number":822,"context_line":"        for suffix_path, suffix in suffixes:"},{"line_number":823,"context_line":"            for object_hash in self._listdir(suffix_path):"},{"line_number":824,"context_line":"                object_path \u003d os.path.join(suffix_path, object_hash)"}],"source_content_type":"text/x-python","patch_set":14,"id":"3a50d1a3_450435c5","line":821,"in_reply_to":"7a016987_89f17697","updated":"2015-08-03 15:05:04.000000000","message":"Done. this version of yield_hashes goes away with the diskfile refactor.","commit_id":"bc3584df5fd92f0b791cbc992ec544f62a701bea"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bdbfbbd9d16565231cc290313809a7f9fa487010","unresolved":false,"context_lines":[{"line_number":1654,"context_line":"            raise DiskFileNotOpen()"},{"line_number":1655,"context_line":"        return dict("},{"line_number":1656,"context_line":"            (k, v) for (k, v) in self._metadata.iteritems()"},{"line_number":1657,"context_line":"            if ((k not in self._fixed_metadata) and k.lower() !\u003d \u0027name\u0027))"},{"line_number":1658,"context_line":""},{"line_number":1659,"context_line":"    def get_datafile_metadata(self):"},{"line_number":1660,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":14,"id":"7a016987_4915be99","line":1657,"updated":"2015-05-23 00:06:33.000000000","message":"you said maybe you don\u0027t need the filter over *all* the metadata - you just need the metadata\u0027s metadata?\n\nI\u0027m not sure if it\u0027s better to store both *and* the combined - or if it\u0027s better to just store the combined and provide filters...\n\nyour call.","commit_id":"bc3584df5fd92f0b791cbc992ec544f62a701bea"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bdbfbbd9d16565231cc290313809a7f9fa487010","unresolved":false,"context_lines":[{"line_number":2297,"context_line":"            suffixes \u003d ("},{"line_number":2298,"context_line":"                (os.path.join(partition_path, suffix), suffix)"},{"line_number":2299,"context_line":"                for suffix in suffixes)"},{"line_number":2300,"context_line":"        key_map \u003d {\u0027.data\u0027: \u0027ts_data\u0027, \u0027.ts\u0027: \u0027ts_data\u0027, \u0027.meta\u0027: \u0027ts_meta\u0027}"},{"line_number":2301,"context_line":"        for suffix_path, suffix in suffixes:"},{"line_number":2302,"context_line":"            for object_hash in self._listdir(suffix_path):"},{"line_number":2303,"context_line":"                object_path \u003d os.path.join(suffix_path, object_hash)"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a016987_291842d2","line":2300,"updated":"2015-05-23 00:06:33.000000000","message":"this seems better with the .ts","commit_id":"bc3584df5fd92f0b791cbc992ec544f62a701bea"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"580ea0b58dd98646a8419d8a353af029b96926ba","unresolved":false,"context_lines":[{"line_number":1711,"context_line":"        \"\"\""},{"line_number":1712,"context_line":"        fp \u003d open(data_file, \u0027rb\u0027)"},{"line_number":1713,"context_line":"        self._datafile_metadata \u003d self._failsafe_read_metadata(fp, data_file)"},{"line_number":1714,"context_line":"        self._fixed_metadata \u003d dict("},{"line_number":1715,"context_line":"            [(key, val) for key, val in self._datafile_metadata.items()"},{"line_number":1716,"context_line":"             if key.lower() in DATAFILE_SYSTEM_META"},{"line_number":1717,"context_line":"             or is_sys_meta(\u0027object\u0027, key)])"}],"source_content_type":"text/x-python","patch_set":20,"id":"9a1a9d01_9db2e305","line":1714,"updated":"2015-10-01 12:45:13.000000000","message":"see comment below, think this does not need to be self. var, can revert and just save metafile metadata","commit_id":"7058d0ece798bc8f122477837a06140e8c170ad2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6311f689366350eae08e47b3c05bced39c78228a","unresolved":false,"context_lines":[{"line_number":1711,"context_line":"        \"\"\""},{"line_number":1712,"context_line":"        fp \u003d open(data_file, \u0027rb\u0027)"},{"line_number":1713,"context_line":"        self._datafile_metadata \u003d self._failsafe_read_metadata(fp, data_file)"},{"line_number":1714,"context_line":"        self._fixed_metadata \u003d dict("},{"line_number":1715,"context_line":"            [(key, val) for key, val in self._datafile_metadata.items()"},{"line_number":1716,"context_line":"             if key.lower() in DATAFILE_SYSTEM_META"},{"line_number":1717,"context_line":"             or is_sys_meta(\u0027object\u0027, key)])"}],"source_content_type":"text/x-python","patch_set":20,"id":"9a1a9d01_d9a2a64b","line":1714,"in_reply_to":"9a1a9d01_9db2e305","updated":"2015-10-01 15:47:31.000000000","message":"Done","commit_id":"7058d0ece798bc8f122477837a06140e8c170ad2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"580ea0b58dd98646a8419d8a353af029b96926ba","unresolved":false,"context_lines":[{"line_number":1729,"context_line":"        self._verify_data_file(data_file, fp)"},{"line_number":1730,"context_line":"        return fp"},{"line_number":1731,"context_line":""},{"line_number":1732,"context_line":"    def get_mutable_metadata(self):"},{"line_number":1733,"context_line":"        \"\"\""},{"line_number":1734,"context_line":"        Provide the mutable metadata for a previously opened object as a"},{"line_number":1735,"context_line":"        dictionary. This is metadata that could be updated by a POST."}],"source_content_type":"text/x-python","patch_set":20,"id":"9a1a9d01_3a172246","line":1732,"updated":"2015-10-01 12:45:13.000000000","message":"I think this can be simplified: The only time we call this is in ssync_sender to populate a POST subrequest. We only do that when data_timestamp !\u003d timestamp i.e. we know there is a .meta file. So all we need is a method get_metafile_metadata.\n\nThis method was trying to always return the POST-able metadata even when it was in a data file. That\u0027s overkill.","commit_id":"7058d0ece798bc8f122477837a06140e8c170ad2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6311f689366350eae08e47b3c05bced39c78228a","unresolved":false,"context_lines":[{"line_number":1729,"context_line":"        self._verify_data_file(data_file, fp)"},{"line_number":1730,"context_line":"        return fp"},{"line_number":1731,"context_line":""},{"line_number":1732,"context_line":"    def get_mutable_metadata(self):"},{"line_number":1733,"context_line":"        \"\"\""},{"line_number":1734,"context_line":"        Provide the mutable metadata for a previously opened object as a"},{"line_number":1735,"context_line":"        dictionary. This is metadata that could be updated by a POST."}],"source_content_type":"text/x-python","patch_set":20,"id":"9a1a9d01_b99d720c","line":1732,"in_reply_to":"9a1a9d01_3a172246","updated":"2015-10-01 15:47:31.000000000","message":"Done","commit_id":"7058d0ece798bc8f122477837a06140e8c170ad2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":927,"context_line":"                            key \u003d key_map[ext]"},{"line_number":928,"context_line":"                            ts \u003d self.parse_on_disk_filename(f)[\u0027timestamp\u0027]"},{"line_number":929,"context_line":"                            timestamps[key] \u003d ts"},{"line_number":930,"context_line":"                    if timestamps:"},{"line_number":931,"context_line":"                        yield (object_path, object_hash, timestamps)"},{"line_number":932,"context_line":"                except AssertionError as err:"},{"line_number":933,"context_line":"                    self.logger.debug(\u0027Invalid file set in %s (%s)\u0027 % ("}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_c66cf538","line":930,"updated":"2015-10-02 05:30:01.000000000","message":"what if timestamps has only .meta - I don\u0027t think cleanup would blow up - but if the remote asks for it trying to open the DiskFile probably will - maybe it\u0027s about the same as the old - still I think there\u0027s some argument to be made that it shouldn\u0027t even get yielded up..\n\nyeah i think it\u0027s better to make the preference data/ts explicit (even though they can\u0027t ever conflict because god help us)\n\nand not yeilding up stray .meta\u0027s is better","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":927,"context_line":"                            key \u003d key_map[ext]"},{"line_number":928,"context_line":"                            ts \u003d self.parse_on_disk_filename(f)[\u0027timestamp\u0027]"},{"line_number":929,"context_line":"                            timestamps[key] \u003d ts"},{"line_number":930,"context_line":"                    if timestamps:"},{"line_number":931,"context_line":"                        yield (object_path, object_hash, timestamps)"},{"line_number":932,"context_line":"                except AssertionError as err:"},{"line_number":933,"context_line":"                    self.logger.debug(\u0027Invalid file set in %s (%s)\u0027 % ("}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_d0ffb9a8","line":930,"in_reply_to":"9a1a9d01_c66cf538","updated":"2015-10-02 11:17:58.000000000","message":"agree. good call.","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":1723,"context_line":"            # diskfile writer added \u0027name\u0027 to metafile, so remove it here"},{"line_number":1724,"context_line":"            self._metafile_metadata.pop(\u0027name\u0027, None)"},{"line_number":1725,"context_line":"        else:"},{"line_number":1726,"context_line":"            self._metadata \u003d self._datafile_metadata"},{"line_number":1727,"context_line":"        if self._name is None:"},{"line_number":1728,"context_line":"            # If we don\u0027t know our name, we were just given a hash dir at"},{"line_number":1729,"context_line":"            # instantiation, so we\u0027d better validate that the name hashes back"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_469465e7","line":1726,"updated":"2015-10-02 05:30:01.000000000","message":".copy() ?\n\nI think we could do an update only thing to make sure we don\u0027t couple identity in all cases.\n\nyeah .update is better - the bit with the name is tricky tho - you gotta pop that out at the right time","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":1723,"context_line":"            # diskfile writer added \u0027name\u0027 to metafile, so remove it here"},{"line_number":1724,"context_line":"            self._metafile_metadata.pop(\u0027name\u0027, None)"},{"line_number":1725,"context_line":"        else:"},{"line_number":1726,"context_line":"            self._metadata \u003d self._datafile_metadata"},{"line_number":1727,"context_line":"        if self._name is None:"},{"line_number":1728,"context_line":"            # If we don\u0027t know our name, we were just given a hash dir at"},{"line_number":1729,"context_line":"            # instantiation, so we\u0027d better validate that the name hashes back"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_902aa17d","line":1726,"in_reply_to":"9a1a9d01_469465e7","updated":"2015-10-02 11:17:58.000000000","message":"oooh, good call.","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":1749,"context_line":"            raise DiskFileNotOpen()"},{"line_number":1750,"context_line":"        return self._metafile_metadata"},{"line_number":1751,"context_line":""},{"line_number":1752,"context_line":"    def get_datafile_metadata(self):"},{"line_number":1753,"context_line":"        \"\"\""},{"line_number":1754,"context_line":"        Provide the datafile metadata for a previously opened object as a"},{"line_number":1755,"context_line":"        dictionary. This is metadata that was included when the object was"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_41b52fce","line":1752,"updated":"2015-10-02 05:30:01.000000000","message":"hrmm... curious about when this is part of the public interface.\n\n... all over ssync_sender","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":1749,"context_line":"            raise DiskFileNotOpen()"},{"line_number":1750,"context_line":"        return self._metafile_metadata"},{"line_number":1751,"context_line":""},{"line_number":1752,"context_line":"    def get_datafile_metadata(self):"},{"line_number":1753,"context_line":"        \"\"\""},{"line_number":1754,"context_line":"        Provide the datafile metadata for a previously opened object as a"},{"line_number":1755,"context_line":"        dictionary. This is metadata that was included when the object was"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_d05ed911","line":1752,"in_reply_to":"9a1a9d01_41b52fce","updated":"2015-10-02 11:17:58.000000000","message":"On reflection, should I have included \u0027file\u0027 in the method name or made it more abstract wrt implementation, like get_data_metadata, get_meta_metadata...but those names sound crazy so idk whats best.\n\nfollow up?","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":2010,"context_line":"                discard()"},{"line_number":2011,"context_line":"            # if not have_valid_fileset():"},{"line_number":2012,"context_line":"            #     # remove any .meta that may have been previously found"},{"line_number":2013,"context_line":"            #     context[\u0027.meta\u0027] \u003d None"},{"line_number":2014,"context_line":"            set_valid_fileset()"},{"line_number":2015,"context_line":"        elif ext \u003d\u003d \u0027.meta\u0027:"},{"line_number":2016,"context_line":"            if have_valid_fileset() or not accept_first():"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_f01f5d07","line":2013,"updated":"2015-10-02 11:17:58.000000000","message":"whoa, that was on master. oops \u0026 thanks for fixing.","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"}],"swift/obj/mem_diskfile.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":420,"context_line":"            raise DiskFileNotOpen()"},{"line_number":421,"context_line":"        return Timestamp(self._metadata.get(\u0027X-Timestamp\u0027))"},{"line_number":422,"context_line":""},{"line_number":423,"context_line":"    data_timestamp \u003d timestamp"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_5cf74df5","line":423,"updated":"2015-10-02 05:30:01.000000000","message":"jesus, so what does this implementation do with a POST?  Maybe it doesn\u0027t matter to it because it\u0027s not persistent or replicated so there\u0027s only the lasted timestamp?\n\nnm, who cares","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"}],"swift/obj/reconstructor.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"580ea0b58dd98646a8419d8a353af029b96926ba","unresolved":false,"context_lines":[{"line_number":547,"context_line":"                        job[\u0027local_dev\u0027][\u0027device\u0027], job[\u0027partition\u0027],"},{"line_number":548,"context_line":"                        object_hash, job[\u0027policy\u0027],"},{"line_number":549,"context_line":"                        frag_index\u003dfrag_index)"},{"line_number":550,"context_line":"                    df.purge(timestamps[\u0027ts_data\u0027], frag_index)"},{"line_number":551,"context_line":"                except DiskFileError:"},{"line_number":552,"context_line":"                    self.logger.exception("},{"line_number":553,"context_line":"                        \u0027Unable to purge DiskFile (%r %r %r)\u0027,"}],"source_content_type":"text/x-python","patch_set":20,"id":"9a1a9d01_7df4af86","line":550,"updated":"2015-10-01 12:45:13.000000000","message":"now i am curious, on master if we had a .meta file that dictated timestamp, then would the purge not happen because it looks to remove timestamp.data which would not exist? w/e this fixes that.\n\nAny meta file thats left over after the purge should get reclaimed eventually, but they are not as big as data files so I guess thats ok.","commit_id":"7058d0ece798bc8f122477837a06140e8c170ad2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":91,"context_line":"        return self.metadata"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"    def get_datafile_metadata(self):"},{"line_number":94,"context_line":"        # not a mistake, datafile_metadata \u003d\u003d metadata"},{"line_number":95,"context_line":"        return self.metadata"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_c1f7ff8a","line":94,"updated":"2015-10-02 05:30:01.000000000","message":"lol, oic - this is because this artificial diskfile is created for the fragment archive - probably just simpler to rename all the internal references to self.metadata to self._datafile_metadata so no comment is needed.  Or fix the comment to include the why.\n\nnice try tho, it definitely looks like a bug w/o the comment!","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":91,"context_line":"        return self.metadata"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"    def get_datafile_metadata(self):"},{"line_number":94,"context_line":"        # not a mistake, datafile_metadata \u003d\u003d metadata"},{"line_number":95,"context_line":"        return self.metadata"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_6bfe0007","line":94,"in_reply_to":"9a1a9d01_c1f7ff8a","updated":"2015-10-02 11:17:58.000000000","message":"yeah, inverting the naming is clearer. thanks","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":541,"context_line":"        \"\"\""},{"line_number":542,"context_line":"        df_mgr \u003d self._df_router[job[\u0027policy\u0027]]"},{"line_number":543,"context_line":"        for object_hash, timestamps in objects.items():"},{"line_number":544,"context_line":"            if \u0027ts_data\u0027 in timestamps:"},{"line_number":545,"context_line":"                try:"},{"line_number":546,"context_line":"                    df \u003d df_mgr.get_diskfile_from_hash("},{"line_number":547,"context_line":"                        job[\u0027local_dev\u0027][\u0027device\u0027], job[\u0027partition\u0027],"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_4111afae","line":544,"updated":"2015-10-02 05:30:01.000000000","message":"a guard/continue would have made the diff smaller\n\n    if \u0027ts_data\u0027 not in timestamps:\n        continue\n\n...but why isn\u0027t \u0027ts_data\u0027 in the timestamps map if we\u0027re calling purge on this thing?\n\n... man I *could* not find who wasn\u0027t putting in timestamps - I took out the check?  :\\","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":541,"context_line":"        \"\"\""},{"line_number":542,"context_line":"        df_mgr \u003d self._df_router[job[\u0027policy\u0027]]"},{"line_number":543,"context_line":"        for object_hash, timestamps in objects.items():"},{"line_number":544,"context_line":"            if \u0027ts_data\u0027 in timestamps:"},{"line_number":545,"context_line":"                try:"},{"line_number":546,"context_line":"                    df \u003d df_mgr.get_diskfile_from_hash("},{"line_number":547,"context_line":"                        job[\u0027local_dev\u0027][\u0027device\u0027], job[\u0027partition\u0027],"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_eb953088","line":544,"in_reply_to":"9a1a9d01_4111afae","updated":"2015-10-02 11:17:58.000000000","message":"just call me paranoid :)","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"}],"swift/obj/server.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":564,"context_line":"                return HTTPPreconditionFailed(request\u003drequest)"},{"line_number":565,"context_line":""},{"line_number":566,"context_line":"        orig_timestamp \u003d Timestamp(orig_metadata.get(\u0027X-Timestamp\u0027, 0))"},{"line_number":567,"context_line":"        if orig_timestamp \u003e\u003d req_timestamp:"},{"line_number":568,"context_line":"            return HTTPConflict("},{"line_number":569,"context_line":"                request\u003drequest,"},{"line_number":570,"context_line":"                headers\u003d{\u0027X-Backend-Timestamp\u0027: orig_timestamp.internal})"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_5c13cd0d","side":"PARENT","line":567,"updated":"2015-10-02 05:30:01.000000000","message":"so this let\u0027s PUT\u0027s slip a datafile underneath a .metafile in the *general* case where previously this would not happen.\n\nI\u0027d *guess* this change was just made so that seperate .data/.meta replication would work.  And it seems perfectly safe/sane at first impression.\n\nBut it\u0027s totally a change in the object-server API (not limited to X-Backend-Replication requests).\n\nFLW: *SURELY* no one was relying on that 409 to prevent slipping .data files underneath a .meta?  No one ever runs with post_as_copy \u003d False *right*?","commit_id":"167f3c8cbdc09b8161d3a4fcc5b5c57091f0845c"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":491,"context_line":"            request.headers.get("},{"line_number":492,"context_line":"                \u0027X-Backend-Replication-Headers\u0027, \u0027\u0027).split() +"},{"line_number":493,"context_line":"            list(self.allowed_headers))"},{"line_number":494,"context_line":"        for header_key in headers_to_copy:"},{"line_number":495,"context_line":"            if header_key in request.headers:"},{"line_number":496,"context_line":"                header_caps \u003d header_key.title()"},{"line_number":497,"context_line":"                metadata[header_caps] \u003d request.headers[header_key]"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_bcbd4904","line":494,"updated":"2015-10-02 05:30:01.000000000","message":"nice, this was directly lifted from the PUT method","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"}],"swift/obj/ssync_receiver.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"02dfc78471b82a904eef7bb575d11efdd806b973","unresolved":false,"context_lines":[{"line_number":387,"context_line":"                    or resp.status_int \u003d\u003d http.HTTP_NOT_FOUND"},{"line_number":388,"context_line":"                    or resp.status_int \u003d\u003d http.HTTP_CONFLICT):"},{"line_number":389,"context_line":"                # expect some conflicts when receiving PUT then POST"},{"line_number":390,"context_line":"                # subrequests, since one of data or metadata may be up to date"},{"line_number":391,"context_line":"                successes +\u003d 1"},{"line_number":392,"context_line":"            else:"},{"line_number":393,"context_line":"                failures +\u003d 1"}],"source_content_type":"text/x-python","patch_set":4,"id":"3a961159_b2d2bb59","line":390,"updated":"2014-12-23 16:11:41.000000000","message":"this comment needs to be removed/updated","commit_id":"7f914c76748d108124dfed3247dbeaaf9d5f0213"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"580ea0b58dd98646a8419d8a353af029b96926ba","unresolved":false,"context_lines":[{"line_number":30,"context_line":"def _decode_missing(line):"},{"line_number":31,"context_line":"    \"\"\""},{"line_number":32,"context_line":"    Parse a string of the form generated by"},{"line_number":33,"context_line":"    :py:func:`.ssync_sender.encode_missing` and return a dict with keys \u0027hash\u0027,"},{"line_number":34,"context_line":"    \u0027ts_data\u0027, \u0027ts_meta\u0027."},{"line_number":35,"context_line":"    \"\"\""},{"line_number":36,"context_line":"    result \u003d {}"}],"source_content_type":"text/x-python","patch_set":20,"id":"9a1a9d01_3f14f4e6","line":33,"updated":"2015-10-01 12:45:13.000000000","message":"should be .ssync_sender._encode_missing","commit_id":"7058d0ece798bc8f122477837a06140e8c170ad2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6311f689366350eae08e47b3c05bced39c78228a","unresolved":false,"context_lines":[{"line_number":30,"context_line":"def _decode_missing(line):"},{"line_number":31,"context_line":"    \"\"\""},{"line_number":32,"context_line":"    Parse a string of the form generated by"},{"line_number":33,"context_line":"    :py:func:`.ssync_sender.encode_missing` and return a dict with keys \u0027hash\u0027,"},{"line_number":34,"context_line":"    \u0027ts_data\u0027, \u0027ts_meta\u0027."},{"line_number":35,"context_line":"    \"\"\""},{"line_number":36,"context_line":"    result \u003d {}"}],"source_content_type":"text/x-python","patch_set":20,"id":"9a1a9d01_d4c82dab","line":33,"in_reply_to":"9a1a9d01_3f14f4e6","updated":"2015-10-01 15:47:31.000000000","message":"Done","commit_id":"7058d0ece798bc8f122477837a06140e8c170ad2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    result \u003d {}"},{"line_number":37,"context_line":"    parts \u003d line.split()"},{"line_number":38,"context_line":"    result[\u0027hash\u0027], t_data \u003d (urllib.unquote(v) for v in parts[:2])"},{"line_number":39,"context_line":"    result[\u0027ts_data\u0027] \u003d result[\u0027ts_meta\u0027] \u003d Timestamp(t_data)"},{"line_number":40,"context_line":"    if len(parts) \u003e 2:"},{"line_number":41,"context_line":"        # allow for a comma separated list of k:v pairs to future-proof"},{"line_number":42,"context_line":"        subparts \u003d urllib.unquote(parts[2]).split(\u0027,\u0027)"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_ebfea237","line":39,"updated":"2015-10-02 05:30:01.000000000","message":"why is it evar reasonable to make the ts_meta timestamp the ts_data timestamp?  I get maybe always having all the keys, but it seems like None would make a better default value to indicate we didn\u0027t get.\n\nIIRC there\u0027s some check for ts_meta \u003e ts_data\n\nok, i moved the implementation of the encode_wanted closer to this method and it\u0027s more obvious that it simplifies the check if a) the key is always there and b) it\u0027s always directly comparable to a Timestamp (esp. because the diskfile\u0027s ts_meta will be filled in with the X-Timestamp from metadata (which could be equal to ts_data if there\u0027s only a .data file))","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    result \u003d {}"},{"line_number":37,"context_line":"    parts \u003d line.split()"},{"line_number":38,"context_line":"    result[\u0027hash\u0027], t_data \u003d (urllib.unquote(v) for v in parts[:2])"},{"line_number":39,"context_line":"    result[\u0027ts_data\u0027] \u003d result[\u0027ts_meta\u0027] \u003d Timestamp(t_data)"},{"line_number":40,"context_line":"    if len(parts) \u003e 2:"},{"line_number":41,"context_line":"        # allow for a comma separated list of k:v pairs to future-proof"},{"line_number":42,"context_line":"        subparts \u003d urllib.unquote(parts[2]).split(\u0027,\u0027)"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_867d8be9","line":39,"in_reply_to":"9a1a9d01_ebfea237","updated":"2015-10-02 11:17:58.000000000","message":"Its because ts_meta is the time at which meta was last written rather than the timestamp of a .meta file, if any. So ts_meta can equal ts_data.\n\nNice reorganisation thanks.","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":38,"context_line":"    result[\u0027hash\u0027], t_data \u003d (urllib.unquote(v) for v in parts[:2])"},{"line_number":39,"context_line":"    result[\u0027ts_data\u0027] \u003d result[\u0027ts_meta\u0027] \u003d Timestamp(t_data)"},{"line_number":40,"context_line":"    if len(parts) \u003e 2:"},{"line_number":41,"context_line":"        # allow for a comma separated list of k:v pairs to future-proof"},{"line_number":42,"context_line":"        subparts \u003d urllib.unquote(parts[2]).split(\u0027,\u0027)"},{"line_number":43,"context_line":"        for item in [subpart for subpart in subparts if \u0027:\u0027 in subpart]:"},{"line_number":44,"context_line":"            k, v \u003d item.split(\u0027:\u0027)"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_ebac6237","line":41,"updated":"2015-10-02 05:30:01.000000000","message":"why comma separated - we\u0027re currently space separated - if we need to add another column it seems like a generalized k/v structure should be good enough for any additional info","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":38,"context_line":"    result[\u0027hash\u0027], t_data \u003d (urllib.unquote(v) for v in parts[:2])"},{"line_number":39,"context_line":"    result[\u0027ts_data\u0027] \u003d result[\u0027ts_meta\u0027] \u003d Timestamp(t_data)"},{"line_number":40,"context_line":"    if len(parts) \u003e 2:"},{"line_number":41,"context_line":"        # allow for a comma separated list of k:v pairs to future-proof"},{"line_number":42,"context_line":"        subparts \u003d urllib.unquote(parts[2]).split(\u0027,\u0027)"},{"line_number":43,"context_line":"        for item in [subpart for subpart in subparts if \u0027:\u0027 in subpart]:"},{"line_number":44,"context_line":"            k, v \u003d item.split(\u0027:\u0027)"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_6694f7e7","line":41,"in_reply_to":"9a1a9d01_ebac6237","updated":"2015-10-02 11:17:58.000000000","message":"I was thinking ahead to this https://review.openstack.org/#/c/135380/14/swift/obj/ssync_receiver.py","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":206,"context_line":"            raise swob.HTTPInsufficientStorage(drive\u003dself.device)"},{"line_number":207,"context_line":"        self.fp \u003d self.request.environ[\u0027wsgi.input\u0027]"},{"line_number":208,"context_line":""},{"line_number":209,"context_line":"    def _encode_wanted(self, line):"},{"line_number":210,"context_line":"        \"\"\""},{"line_number":211,"context_line":"        Parse a line received during missing_check to determine remote"},{"line_number":212,"context_line":"        timestamps, compare with local diskfile and return representation"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_260db137","line":209,"updated":"2015-10-02 05:30:01.000000000","message":"this is pretty poorly named, it\u0027s hardly just an encode function, the fact that\u0027s it\u0027s return value is the encoded form seems way less important than all the work it does to open the diskfile and compare the timestamps.","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":206,"context_line":"            raise swob.HTTPInsufficientStorage(drive\u003dself.device)"},{"line_number":207,"context_line":"        self.fp \u003d self.request.environ[\u0027wsgi.input\u0027]"},{"line_number":208,"context_line":""},{"line_number":209,"context_line":"    def _encode_wanted(self, line):"},{"line_number":210,"context_line":"        \"\"\""},{"line_number":211,"context_line":"        Parse a line received during missing_check to determine remote"},{"line_number":212,"context_line":"        timestamps, compare with local diskfile and return representation"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_6181414d","line":209,"in_reply_to":"9a1a9d01_260db137","updated":"2015-10-02 11:17:58.000000000","message":"i like your refactoring!","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":232,"context_line":"                # we have a local diskfile so be specific about which"},{"line_number":233,"context_line":"                # elements need to be sync\u0027d"},{"line_number":234,"context_line":"                if df.data_timestamp \u003c remote[\u0027ts_data\u0027]:"},{"line_number":235,"context_line":"                    want \u003d [\u0027data\u0027]"},{"line_number":236,"context_line":"                if (remote[\u0027ts_data\u0027] \u003c remote[\u0027ts_meta\u0027]"},{"line_number":237,"context_line":"                        and df.timestamp \u003c remote[\u0027ts_meta\u0027]):"},{"line_number":238,"context_line":"                    want.append(\u0027meta\u0027)"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_6651690e","line":235,"updated":"2015-10-02 05:30:01.000000000","message":"bah, the type mixing of want here is annoying - I think this method is doing at least two things - pretty sure it should be split up.","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":238,"context_line":"                    want.append(\u0027meta\u0027)"},{"line_number":239,"context_line":"        if want:"},{"line_number":240,"context_line":"            # compress wanted parts to just first letters for response"},{"line_number":241,"context_line":"            want \u003d \u0027\u0027.join(word[0] for word in want)"},{"line_number":242,"context_line":"            return \u0027%s %s\u0027 % (urllib.quote(remote[\u0027hash\u0027]), want)"},{"line_number":243,"context_line":"        return None"},{"line_number":244,"context_line":""}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_06c98dac","line":241,"updated":"2015-10-02 05:30:01.000000000","message":"... the first letter thing is kind of trixy/implicit - it\u0027s ok\u0027ish for now - but seems like a backwards compatibility nightmare","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":272,"context_line":"               Each \u003cwanted_hash\u003e specifier has the form \u003chash\u003e[ \u003cparts\u003e] where"},{"line_number":273,"context_line":"               \u003cparts\u003e is a string containing characters \u0027d\u0027 and/or \u0027m\u0027"},{"line_number":274,"context_line":"               indicating that only data or meta part of object respectively is"},{"line_number":275,"context_line":"               required to be sync\u0027d."},{"line_number":276,"context_line":""},{"line_number":277,"context_line":"            5. Sender gets `:MISSING_CHECK: START` and reads the list"},{"line_number":278,"context_line":"               of hashes desired by the receiver until reading"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_cb0b9e2a","line":275,"updated":"2015-10-02 05:30:01.000000000","message":"so the d is always explicitly stated - i guess that\u0027s still backwards compatible.","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":296,"context_line":"            if not line or line.strip() \u003d\u003d \u0027:MISSING_CHECK: END\u0027:"},{"line_number":297,"context_line":"                break"},{"line_number":298,"context_line":"            want \u003d self._encode_wanted(line)"},{"line_number":299,"context_line":"            if want is not None:"},{"line_number":300,"context_line":"                object_hashes.append(want)"},{"line_number":301,"context_line":"        yield \u0027:MISSING_CHECK: START\\r\\n\u0027"},{"line_number":302,"context_line":"        if object_hashes:"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_0640ad06","line":299,"updated":"2015-10-02 05:30:01.000000000","message":"rly?  if it\u0027s the empty string we want to append to object_hashes?","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":296,"context_line":"            if not line or line.strip() \u003d\u003d \u0027:MISSING_CHECK: END\u0027:"},{"line_number":297,"context_line":"                break"},{"line_number":298,"context_line":"            want \u003d self._encode_wanted(line)"},{"line_number":299,"context_line":"            if want is not None:"},{"line_number":300,"context_line":"                object_hashes.append(want)"},{"line_number":301,"context_line":"        yield \u0027:MISSING_CHECK: START\\r\\n\u0027"},{"line_number":302,"context_line":"        if object_hashes:"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_0148852c","line":299,"in_reply_to":"9a1a9d01_0640ad06","updated":"2015-10-02 11:17:58.000000000","message":"it never could be an empty string, but nevertheless this was crappy","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":384,"context_line":"                if header \u003d\u003d \u0027content-length\u0027:"},{"line_number":385,"context_line":"                    content_length \u003d int(value)"},{"line_number":386,"context_line":"            # Establish subrequest body, if needed."},{"line_number":387,"context_line":"            if method \u003d\u003d \u0027DELETE\u0027 or method \u003d\u003d \u0027POST\u0027:"},{"line_number":388,"context_line":"                if content_length not in (None, 0):"},{"line_number":389,"context_line":"                    raise Exception("},{"line_number":390,"context_line":"                        \u0027%s subrequest with content-length %s\u0027"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_6662c9af","line":387,"updated":"2015-10-02 05:30:01.000000000","message":"better:\n\n    method in (\u0027POST\u0027, \u0027DELETE\u0027)","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":384,"context_line":"                if header \u003d\u003d \u0027content-length\u0027:"},{"line_number":385,"context_line":"                    content_length \u003d int(value)"},{"line_number":386,"context_line":"            # Establish subrequest body, if needed."},{"line_number":387,"context_line":"            if method \u003d\u003d \u0027DELETE\u0027 or method \u003d\u003d \u0027POST\u0027:"},{"line_number":388,"context_line":"                if content_length not in (None, 0):"},{"line_number":389,"context_line":"                    raise Exception("},{"line_number":390,"context_line":"                        \u0027%s subrequest with content-length %s\u0027"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_61b941ec","line":387,"in_reply_to":"9a1a9d01_6662c9af","updated":"2015-10-02 11:17:58.000000000","message":"I think this line reveals that i first wrote some of this code a long time ago when I had accumulated less python idioms :)\n\nAnd/or reveals why having other people\u0027s eyes on code is always a good thing.","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"25f84adbd4ef3b9171c19dc37f9b8047207fd82c","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    with keys ``object_hash``, ``ts_data``, ``ts_meta``."},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"    The encoder for this line is"},{"line_number":37,"context_line":"    :py:func:`~swift.obj.ssync_sender.encode_missing`"},{"line_number":38,"context_line":"    \"\"\""},{"line_number":39,"context_line":"    result \u003d {}"},{"line_number":40,"context_line":"    parts \u003d line.split()"}],"source_content_type":"text/x-python","patch_set":22,"id":"9a1a9d01_013c052e","line":37,"updated":"2015-10-02 11:18:28.000000000","message":"nit: add param definition for line and remove duplicate reference to ~swift.obj.ssync_sender.encode_missing","commit_id":"c12a1cb0a0c933e2219b0665c275baa8a3123360"}],"swift/obj/ssync_sender.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a98f23c3e53926edbb08bb14129bae21d2d06858","unresolved":false,"context_lines":[{"line_number":26,"context_line":"    and the delta back to its datafile timestamp, if non-zero, in the form:"},{"line_number":27,"context_line":"    \u003chash\u003e \u003ctimestamp\u003e d:\u003chex delta\u003e"},{"line_number":28,"context_line":"    \"\"\""},{"line_number":29,"context_line":"    # for backwards compatibility first part of msg is newest timestamp"},{"line_number":30,"context_line":"    msg \u003d \u0027%s %s\u0027 % (urllib.quote(hash), urllib.quote(ts_meta.internal))"},{"line_number":31,"context_line":"    if ts_data and ts_data !\u003d ts_meta:"},{"line_number":32,"context_line":"        delta \u003d ts_meta.raw - ts_data.raw"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a016987_29884270","line":29,"updated":"2015-08-03 15:05:04.000000000","message":"or...to do the right thing, make the first part of the msg be the data file timestamp.","commit_id":"bc3584df5fd92f0b791cbc992ec544f62a701bea"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"bdbfbbd9d16565231cc290313809a7f9fa487010","unresolved":false,"context_lines":[{"line_number":308,"context_line":"                    # the metadata that needs to be sent with the PUT..."},{"line_number":309,"context_line":"                    meta_to_put \u003d df.get_datafile_metadata()"},{"line_number":310,"context_line":"                    if want.get(\u0027legacy\u0027):"},{"line_number":311,"context_line":"                        meta_to_put \u003d df.get_metadata()"},{"line_number":312,"context_line":"                    df_alt \u003d self.job.get("},{"line_number":313,"context_line":"                        \u0027sync_diskfile_builder\u0027, lambda *args: df)("},{"line_number":314,"context_line":"                            self.job, self.node, meta_to_put)"}],"source_content_type":"text/x-python","patch_set":14,"id":"7a016987_a9ad52ea","line":311,"updated":"2015-05-23 00:06:33.000000000","message":"I don\u0027t think creating a data file with a timestamp of the metadata is good enough, I think data should be the driver.","commit_id":"bc3584df5fd92f0b791cbc992ec544f62a701bea"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a98f23c3e53926edbb08bb14129bae21d2d06858","unresolved":false,"context_lines":[{"line_number":308,"context_line":"                    # the metadata that needs to be sent with the PUT..."},{"line_number":309,"context_line":"                    meta_to_put \u003d df.get_datafile_metadata()"},{"line_number":310,"context_line":"                    if want.get(\u0027legacy\u0027):"},{"line_number":311,"context_line":"                        meta_to_put \u003d df.get_metadata()"},{"line_number":312,"context_line":"                    df_alt \u003d self.job.get("},{"line_number":313,"context_line":"                        \u0027sync_diskfile_builder\u0027, lambda *args: df)("},{"line_number":314,"context_line":"                            self.job, self.node, meta_to_put)"}],"source_content_type":"text/x-python","patch_set":14,"id":"3a50d1a3_2fb6aaf9","line":311,"in_reply_to":"7a016987_a9ad52ea","updated":"2015-08-03 15:05:04.000000000","message":"Done. Will change so that a PUT will only ever send datafile metadata. In essence, fix the bad legacy behavior of giving the sync\u0027d datafile the metafile timestamps. So a legacy receiver will only get a PUT and that PUT will only have datafile metadata.\n\nIn Vancouver we noted that once the legacy receiver gets upgraded it would then request the metafile explicitly and the sender would then send a POST subrequest.","commit_id":"bc3584df5fd92f0b791cbc992ec544f62a701bea"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"580ea0b58dd98646a8419d8a353af029b96926ba","unresolved":false,"context_lines":[{"line_number":398,"context_line":"    def send_post(self, url_path, df):"},{"line_number":399,"context_line":"        msg \u003d [\u0027POST \u0027 + url_path]"},{"line_number":400,"context_line":"        # Sorted to make it easier to test."},{"line_number":401,"context_line":"        for key, value in sorted(df.get_mutable_metadata().iteritems()):"},{"line_number":402,"context_line":"            msg.append(\u0027%s: %s\u0027 % (key, value))"},{"line_number":403,"context_line":"        msg \u003d \u0027\\r\\n\u0027.join(msg) + \u0027\\r\\n\\r\\n\u0027"},{"line_number":404,"context_line":"        with exceptions.MessageTimeout(self.daemon.node_timeout, \u0027send_post\u0027):"}],"source_content_type":"text/x-python","patch_set":20,"id":"9a1a9d01_df6058a7","line":401,"updated":"2015-10-01 12:45:13.000000000","message":"don\u0027t use iteritems for py3","commit_id":"7058d0ece798bc8f122477837a06140e8c170ad2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6311f689366350eae08e47b3c05bced39c78228a","unresolved":false,"context_lines":[{"line_number":398,"context_line":"    def send_post(self, url_path, df):"},{"line_number":399,"context_line":"        msg \u003d [\u0027POST \u0027 + url_path]"},{"line_number":400,"context_line":"        # Sorted to make it easier to test."},{"line_number":401,"context_line":"        for key, value in sorted(df.get_mutable_metadata().iteritems()):"},{"line_number":402,"context_line":"            msg.append(\u0027%s: %s\u0027 % (key, value))"},{"line_number":403,"context_line":"        msg \u003d \u0027\\r\\n\u0027.join(msg) + \u0027\\r\\n\\r\\n\u0027"},{"line_number":404,"context_line":"        with exceptions.MessageTimeout(self.daemon.node_timeout, \u0027send_post\u0027):"}],"source_content_type":"text/x-python","patch_set":20,"id":"9a1a9d01_14a0e5a4","line":401,"in_reply_to":"9a1a9d01_df6058a7","updated":"2015-10-01 15:47:31.000000000","message":"Done","commit_id":"7058d0ece798bc8f122477837a06140e8c170ad2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":310,"context_line":"                self.daemon.node_timeout, \u0027updates start\u0027):"},{"line_number":311,"context_line":"            msg \u003d \u0027:UPDATES: START\\r\\n\u0027"},{"line_number":312,"context_line":"            self.connection.send(\u0027%x\\r\\n%s\\r\\n\u0027 % (len(msg), msg))"},{"line_number":313,"context_line":"        for hash, want in self.send_map.items():"},{"line_number":314,"context_line":"            object_hash \u003d urllib.unquote(hash)"},{"line_number":315,"context_line":"            try:"},{"line_number":316,"context_line":"                df \u003d self.df_mgr.get_diskfile_from_hash("}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_7530319f","line":313,"updated":"2015-10-02 05:30:01.000000000","message":":\u0027( hash is a builtin","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":310,"context_line":"                self.daemon.node_timeout, \u0027updates start\u0027):"},{"line_number":311,"context_line":"            msg \u003d \u0027:UPDATES: START\\r\\n\u0027"},{"line_number":312,"context_line":"            self.connection.send(\u0027%x\\r\\n%s\\r\\n\u0027 % (len(msg), msg))"},{"line_number":313,"context_line":"        for hash, want in self.send_map.items():"},{"line_number":314,"context_line":"            object_hash \u003d urllib.unquote(hash)"},{"line_number":315,"context_line":"            try:"},{"line_number":316,"context_line":"                df \u003d self.df_mgr.get_diskfile_from_hash("}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_46af7394","line":313,"in_reply_to":"9a1a9d01_7530319f","updated":"2015-10-02 11:17:58.000000000","message":"yikes. thanks.","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"}],"test/probe/test_object_metadata_replication.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":61,"context_line":"        finally:"},{"line_number":62,"context_line":"            if using_ssync and not failed:"},{"line_number":63,"context_line":"                self.fail(\u0027This test is expected to fail with ssync\u0027)"},{"line_number":64,"context_line":"    return wrapper"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"class Test(ReplProbeTest):"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_fccd0187","side":"PARENT","line":64,"updated":"2015-10-02 05:30:01.000000000","message":"yay!  expected_failures are for the weak!","commit_id":"167f3c8cbdc09b8161d3a4fcc5b5c57091f0845c"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":90,"context_line":"        mgr \u003d DiskFileManager(options, get_logger(options))"},{"line_number":91,"context_line":"        disk_file \u003d mgr.get_diskfile(device, part, account, container, obj,"},{"line_number":92,"context_line":"                                     policy)"},{"line_number":93,"context_line":"        info \u003d disk_file.read_metadata()"},{"line_number":94,"context_line":"        return info"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    def _assert_consistent_object_metadata(self):"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_fca2e199","line":93,"updated":"2015-10-02 05:30:01.000000000","message":"I think there\u0027s a lot of prior art where probetests would restrict themselves to  talking to the object-server API for these kind of checks - but I\u0027ll allow it :P","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":90,"context_line":"        mgr \u003d DiskFileManager(options, get_logger(options))"},{"line_number":91,"context_line":"        disk_file \u003d mgr.get_diskfile(device, part, account, container, obj,"},{"line_number":92,"context_line":"                                     policy)"},{"line_number":93,"context_line":"        info \u003d disk_file.read_metadata()"},{"line_number":94,"context_line":"        return info"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    def _assert_consistent_object_metadata(self):"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_0ba0a48f","line":93,"in_reply_to":"9a1a9d01_fca2e199","updated":"2015-10-02 11:17:58.000000000","message":"fair cop.","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":104,"context_line":"        for other in obj_info[1:]:"},{"line_number":105,"context_line":"            self.assertEqual(obj_info[0], other,"},{"line_number":106,"context_line":"                             \u0027Object metadata mismatch: %s !\u003d %s\u0027"},{"line_number":107,"context_line":"                             % (obj_info[0], other))"},{"line_number":108,"context_line":""},{"line_number":109,"context_line":"    def _assert_consistent_deleted_object(self):"},{"line_number":110,"context_line":"        for i in range(1, 5):"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_fcc9815b","line":107,"updated":"2015-10-02 05:30:01.000000000","message":"probably would be helpful to have included some sort of tip/clue as to which datafile/node was horked.  But harder to add that now that it\u0027s passing ;)","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":280,"context_line":"        for key in sysmeta2:"},{"line_number":281,"context_line":"            self.assertTrue(key in metadata)"},{"line_number":282,"context_line":"            self.assertEqual(metadata[key], sysmeta2[key])"},{"line_number":283,"context_line":"        self._post_object(usermeta)"},{"line_number":284,"context_line":"        metadata \u003d self._get_object_metadata()"},{"line_number":285,"context_line":"        for key in usermeta:"},{"line_number":286,"context_line":"            self.assertTrue(key in metadata)"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_bce469ac","line":283,"updated":"2015-10-02 05:30:01.000000000","message":"wouldn\u0027t this test be more interesting if this post happened on the primary_half while the sysmeta2 was unavailable?\n\noh, nm - that\u0027s test_sysmeta_after_replication_with_subsequent_post\n\nI don\u0027t think I understand all what these tests names mean...\n\nNow that ssync and rsync can both replicate .meta files independently of .data files - maybe we should try to group tests that pass with fast-post and those that would pass with post as copy and then in the setup either examine the proxy.conf or continue to use the internal client for *only* the tests that require fast-post?\n\n... we can probably save that.","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":314,"context_line":"        for key in sysmeta2.keys():"},{"line_number":315,"context_line":"            self.assertTrue(key in metadata, key)"},{"line_number":316,"context_line":"            self.assertEqual(metadata[key], sysmeta2[key])"},{"line_number":317,"context_line":"        self._assert_consistent_object_metadata()"},{"line_number":318,"context_line":""},{"line_number":319,"context_line":"    def test_sysmeta_after_replication_with_subsequent_post(self):"},{"line_number":320,"context_line":"        sysmeta \u003d {\u0027x-object-sysmeta-foo\u0027: \u0027sysmeta-foo\u0027}"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_bca9c926","line":317,"updated":"2015-10-02 05:30:01.000000000","message":"is the db check not useful here?","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"}],"test/unit/common/test_utils.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":412,"context_line":""},{"line_number":413,"context_line":"        # \u0027raw\u0027 does not include offset"},{"line_number":414,"context_line":"        timestamp \u003d utils.Timestamp(1402436408.91203, 0xf0)"},{"line_number":415,"context_line":"        self.assertEqual(expected, timestamp.raw)"},{"line_number":416,"context_line":""},{"line_number":417,"context_line":"    def test_delta(self):"},{"line_number":418,"context_line":"        def _assertWithinBounds(expected, timestamp):"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_47f21a08","line":415,"updated":"2015-10-02 05:30:01.000000000","message":"dunno how I feel about this public attribute, honestly it\u0027s probably *better* than the floats, but I wish we just go balls to the wall with real precision.  \n\nMaybe this is a step down that path.","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":441,"context_line":""},{"line_number":442,"context_line":"        # cannot go negative"},{"line_number":443,"context_line":"        self.assertRaises(ValueError, utils.Timestamp, 1402436408.91203,"},{"line_number":444,"context_line":"                          delta\u003d-140243640891203)"},{"line_number":445,"context_line":""},{"line_number":446,"context_line":"    def test_int(self):"},{"line_number":447,"context_line":"        expected \u003d 1402437965"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_c754eacb","line":444,"updated":"2015-10-02 05:30:01.000000000","message":"You know what I think would have been cuter - implementing __add__\n\nBut I\u0027m not sure about the real precision again...\n\n    t2 \u003d Timestamp(time.time()) + 1\n\ncould mean\n\n    t2 \u003d Timestamp(time.time() + 1)\n\nor\n\n    t2 \u003d Timestamp(time.time() + 1e-5)\n\nHonestly kinda makes you wonder if the delta is really needed, since the real values being wrapped already support this sorts of basic arithmetic?","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"}],"test/unit/obj/test_diskfile.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"580ea0b58dd98646a8419d8a353af029b96926ba","unresolved":false,"context_lines":[{"line_number":1585,"context_line":"        }"},{"line_number":1586,"context_line":"        expected \u003d {"},{"line_number":1587,"context_line":"            # TODO: differs from repl DiskFileManager which *will*"},{"line_number":1588,"context_line":"            # return meta timestamp when only meta and ts on disk"},{"line_number":1589,"context_line":"            \u00279373a92d072897b136b3fc06595b4abc\u0027: {\u0027ts_data\u0027: ts1},"},{"line_number":1590,"context_line":"            \u00279373a92d072897b136b3fc06595b0456\u0027: {\u0027ts_data\u0027: ts1,"},{"line_number":1591,"context_line":"                                                 \u0027ts_meta\u0027: ts3},"}],"source_content_type":"text/x-python","patch_set":20,"id":"9a1a9d01_bd86c7d9","line":1588,"updated":"2015-10-01 12:45:13.000000000","message":"^^ btw this gets fixed in the dependent patch","commit_id":"7058d0ece798bc8f122477837a06140e8c170ad2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"580ea0b58dd98646a8419d8a353af029b96926ba","unresolved":false,"context_lines":[{"line_number":1598,"context_line":"        # is not found"},{"line_number":1599,"context_line":"        expected \u003d {"},{"line_number":1600,"context_line":"            # TODO: differs from repl DiskFileManager which *will*"},{"line_number":1601,"context_line":"            # return meta timestamp when only meta and ts on disk"},{"line_number":1602,"context_line":"            \u00279373a92d072897b136b3fc06595b4abc\u0027: {\u0027ts_data\u0027: ts1},"},{"line_number":1603,"context_line":"            \u00279373a92d072897b136b3fc06595b0456\u0027: {\u0027ts_meta\u0027: ts3},"},{"line_number":1604,"context_line":"            \u00279373a92d072897b136b3fc06595b7456\u0027: {\u0027ts_meta\u0027: ts2},"}],"source_content_type":"text/x-python","patch_set":20,"id":"9a1a9d01_5d6c4b36","line":1601,"updated":"2015-10-01 12:45:13.000000000","message":"ditto","commit_id":"7058d0ece798bc8f122477837a06140e8c170ad2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"580ea0b58dd98646a8419d8a353af029b96926ba","unresolved":false,"context_lines":[{"line_number":2016,"context_line":"                                    metadata\u003dmetadata)"},{"line_number":2017,"context_line":"        expected \u003d {\u0027X-Timestamp\u0027: ts_data.internal,"},{"line_number":2018,"context_line":"                    \u0027X-Object-Meta-Test\u0027: \u0027test1\u0027}"},{"line_number":2019,"context_line":"        self.assertEqual(expected, df.get_mutable_metadata())"},{"line_number":2020,"context_line":"        ts_meta \u003d ts_iter.next()"},{"line_number":2021,"context_line":"        df.write_metadata({\u0027X-Timestamp\u0027: ts_meta.internal,"},{"line_number":2022,"context_line":"                           \u0027X-Object-Meta-Test\u0027: \u0027changed\u0027,"}],"source_content_type":"text/x-python","patch_set":20,"id":"9a1a9d01_5d53eb6c","line":2019,"updated":"2015-10-01 12:45:13.000000000","message":"but we never use get_mutable_metadata unless we have written a meta file","commit_id":"7058d0ece798bc8f122477837a06140e8c170ad2"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6311f689366350eae08e47b3c05bced39c78228a","unresolved":false,"context_lines":[{"line_number":2016,"context_line":"                                    metadata\u003dmetadata)"},{"line_number":2017,"context_line":"        expected \u003d {\u0027X-Timestamp\u0027: ts_data.internal,"},{"line_number":2018,"context_line":"                    \u0027X-Object-Meta-Test\u0027: \u0027test1\u0027}"},{"line_number":2019,"context_line":"        self.assertEqual(expected, df.get_mutable_metadata())"},{"line_number":2020,"context_line":"        ts_meta \u003d ts_iter.next()"},{"line_number":2021,"context_line":"        df.write_metadata({\u0027X-Timestamp\u0027: ts_meta.internal,"},{"line_number":2022,"context_line":"                           \u0027X-Object-Meta-Test\u0027: \u0027changed\u0027,"}],"source_content_type":"text/x-python","patch_set":20,"id":"9a1a9d01_148ea527","line":2019,"in_reply_to":"9a1a9d01_5d53eb6c","updated":"2015-10-01 15:47:31.000000000","message":"Done","commit_id":"7058d0ece798bc8f122477837a06140e8c170ad2"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":1113,"context_line":"        }"},{"line_number":1114,"context_line":"        expected \u003d {"},{"line_number":1115,"context_line":"            \u00279373a92d072897b136b3fc06595b4abc\u0027:"},{"line_number":1116,"context_line":"            {\u0027ts_data\u0027: ts1, \u0027ts_meta\u0027: ts2},"},{"line_number":1117,"context_line":"            \u00279373a92d072897b136b3fc06595b0456\u0027:"},{"line_number":1118,"context_line":"            {\u0027ts_data\u0027: ts1, \u0027ts_meta\u0027: ts3},"},{"line_number":1119,"context_line":"            \u00279373a92d072897b136b3fc06595b7456\u0027:"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_b92ebba3","line":1116,"updated":"2015-10-02 05:30:01.000000000","message":"seriously?  a tombstone with a metadata timestamp?  How is that going to sync?  I mean *mabye* it makes it all the way to the  :UPDATES: as a POST but I\u0027m *pretty* sure the receiving object server\u0027s POST method isn\u0027t going to write a .meta file over it\u0027s .ts and we end up with a .failures +\u003d 1 anyway...","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":1585,"context_line":"        }"},{"line_number":1586,"context_line":"        expected \u003d {"},{"line_number":1587,"context_line":"            # TODO: differs from repl DiskFileManager which *will*"},{"line_number":1588,"context_line":"            # return meta timestamp when only meta and ts on disk"},{"line_number":1589,"context_line":"            \u00279373a92d072897b136b3fc06595b4abc\u0027: {\u0027ts_data\u0027: ts1},"},{"line_number":1590,"context_line":"            \u00279373a92d072897b136b3fc06595b0456\u0027: {\u0027ts_data\u0027: ts1,"},{"line_number":1591,"context_line":"                                                 \u0027ts_meta\u0027: ts3},"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_9935f7f8","line":1588,"updated":"2015-10-02 05:30:01.000000000","message":"bullshit - let\u0027s fix this!","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":330,"name":"John Dickinson","email":"me@not.mn","username":"notmyname"},"change_message_id":"d42636357c9aa313410ce8843462d0d78d3f47e1","unresolved":false,"context_lines":[{"line_number":2027,"context_line":""},{"line_number":2028,"context_line":"    def test_get_metafile_metadata_not_opened(self):"},{"line_number":2029,"context_line":"        df \u003d self._simple_get_diskfile()"},{"line_number":2030,"context_line":"        self.assertRaises(DiskFileNotOpen), df.get_metafile_metadata"},{"line_number":2031,"context_line":""},{"line_number":2032,"context_line":"    def test_not_opened(self):"},{"line_number":2033,"context_line":"        df \u003d self._simple_get_diskfile()"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_4b2b0e34","line":2030,"updated":"2015-10-02 00:22:56.000000000","message":"oops. wrong parens","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":2027,"context_line":""},{"line_number":2028,"context_line":"    def test_get_metafile_metadata_not_opened(self):"},{"line_number":2029,"context_line":"        df \u003d self._simple_get_diskfile()"},{"line_number":2030,"context_line":"        self.assertRaises(DiskFileNotOpen), df.get_metafile_metadata"},{"line_number":2031,"context_line":""},{"line_number":2032,"context_line":"    def test_not_opened(self):"},{"line_number":2033,"context_line":"        df \u003d self._simple_get_diskfile()"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_e509dcde","line":2030,"in_reply_to":"9a1a9d01_1c10f54d","updated":"2015-10-02 11:17:58.000000000","message":"thanks. think i was flipping between the context manager form and the direct form of assertRaises and ended up in the middle :/","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":2027,"context_line":""},{"line_number":2028,"context_line":"    def test_get_metafile_metadata_not_opened(self):"},{"line_number":2029,"context_line":"        df \u003d self._simple_get_diskfile()"},{"line_number":2030,"context_line":"        self.assertRaises(DiskFileNotOpen), df.get_metafile_metadata"},{"line_number":2031,"context_line":""},{"line_number":2032,"context_line":"    def test_not_opened(self):"},{"line_number":2033,"context_line":"        df \u003d self._simple_get_diskfile()"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_1c10f54d","line":2030,"in_reply_to":"9a1a9d01_4b2b0e34","updated":"2015-10-02 05:30:01.000000000","message":"Done","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":3152,"context_line":""},{"line_number":3153,"context_line":"    def test_data_timestamp_not_open(self):"},{"line_number":3154,"context_line":"        df \u003d self._simple_get_diskfile()"},{"line_number":3155,"context_line":"        self.assertRaises(DiskFileNotOpen, lambda: df.data_timestamp)"},{"line_number":3156,"context_line":""},{"line_number":3157,"context_line":"    def test_error_in_hash_cleanup_listdir(self):"},{"line_number":3158,"context_line":""}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_5c80ad46","line":3155,"updated":"2015-10-02 05:30:01.000000000","message":"context manager form here would be better - maybe mostly everywhere","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":3152,"context_line":""},{"line_number":3153,"context_line":"    def test_data_timestamp_not_open(self):"},{"line_number":3154,"context_line":"        df \u003d self._simple_get_diskfile()"},{"line_number":3155,"context_line":"        self.assertRaises(DiskFileNotOpen, lambda: df.data_timestamp)"},{"line_number":3156,"context_line":""},{"line_number":3157,"context_line":"    def test_error_in_hash_cleanup_listdir(self):"},{"line_number":3158,"context_line":""}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_a52a042b","line":3155,"in_reply_to":"9a1a9d01_5c80ad46","updated":"2015-10-02 11:17:58.000000000","message":"yup. did the CM form not exist when we had to support py26? idk, i keep forgetting it is available. thanks.","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"}],"test/unit/obj/test_reconstructor.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":840,"context_line":"                    self.job[\u0027policy\u0027], self.suffixes,"},{"line_number":841,"context_line":"                    frag_index\u003dself.job.get(\u0027frag_index\u0027))"},{"line_number":842,"context_line":"                self.available_map \u003d {}"},{"line_number":843,"context_line":"                for path, hash_, timestamps in hash_gen:"},{"line_number":844,"context_line":"                    self.available_map[hash_] \u003d timestamps"},{"line_number":845,"context_line":"                context[\u0027available_map\u0027] \u003d self.available_map"},{"line_number":846,"context_line":"                ssync_calls.append(context)"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_a7c0d6e1","line":843,"updated":"2015-10-02 05:30:01.000000000","message":"pfhththt - built-in name avoiding was right here!","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":840,"context_line":"                    self.job[\u0027policy\u0027], self.suffixes,"},{"line_number":841,"context_line":"                    frag_index\u003dself.job.get(\u0027frag_index\u0027))"},{"line_number":842,"context_line":"                self.available_map \u003d {}"},{"line_number":843,"context_line":"                for path, hash_, timestamps in hash_gen:"},{"line_number":844,"context_line":"                    self.available_map[hash_] \u003d timestamps"},{"line_number":845,"context_line":"                context[\u0027available_map\u0027] \u003d self.available_map"},{"line_number":846,"context_line":"                ssync_calls.append(context)"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_65e4ec0c","line":843,"in_reply_to":"9a1a9d01_a7c0d6e1","updated":"2015-10-02 11:17:58.000000000","message":"i\u0027m only stupid half the time :P","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"}],"test/unit/obj/test_server.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":1118,"context_line":"                          \u0027X-Object-Sysmeta-1\u0027: \u0027One\u0027,"},{"line_number":1119,"context_line":"                          \u0027X-Object-Sysmeta-Two\u0027: \u0027Two\u0027})"},{"line_number":1120,"context_line":""},{"line_number":1121,"context_line":"    def test_PUT_succeeds_with_later_POST(self):"},{"line_number":1122,"context_line":"        ts_iter \u003d make_timestamp_iter()"},{"line_number":1123,"context_line":"        t_put \u003d ts_iter.next().internal"},{"line_number":1124,"context_line":"        req \u003d Request.blank(\u0027/sda1/p/a/c/o\u0027,"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_476c5a08","line":1121,"updated":"2015-10-02 05:30:01.000000000","message":"ok, so you obviously knew you were changing this :P","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"}],"test/unit/obj/test_ssync_receiver.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":2044,"context_line":""},{"line_number":2045,"context_line":"class TestModuleMethods(unittest.TestCase):"},{"line_number":2046,"context_line":"    def test_decode_missing(self):"},{"line_number":2047,"context_line":"        hash \u003d \u00279d41d8cd98f00b204e9800998ecf0abc\u0027"},{"line_number":2048,"context_line":"        ts_iter \u003d make_timestamp_iter()"},{"line_number":2049,"context_line":"        t_data \u003d ts_iter.next()"},{"line_number":2050,"context_line":"        t_meta \u003d ts_iter.next()"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_87491291","line":2047,"updated":"2015-10-02 05:30:01.000000000","message":"built-in!","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"}],"test/unit/obj/test_ssync_sender.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":532,"context_line":"                    \u0027/srv/node/dev/objects/9/abc/\u0027"},{"line_number":533,"context_line":"                    \u00279d41d8cd98f00b204e9800998ecf0abc\u0027,"},{"line_number":534,"context_line":"                    \u00279d41d8cd98f00b204e9800998ecf0abc\u0027,"},{"line_number":535,"context_line":"                    {\u0027ts_data\u0027: Timestamp(1380144470.00000)})"},{"line_number":536,"context_line":"            else:"},{"line_number":537,"context_line":"                raise Exception("},{"line_number":538,"context_line":"                    \u0027No match for %r %r %r\u0027 % (device, partition, suffixes))"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_8704b2c6","line":535,"updated":"2015-10-02 05:30:01.000000000","message":"gah!  I keep having to update all of these per-test mock yield_hashes functions - need to think of a better way to DRY this out with a _make_yeild_hashes_mock() helper method","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":1002,"context_line":"        self.sender.response \u003d FakeResponse("},{"line_number":1003,"context_line":"            chunk_body\u003d("},{"line_number":1004,"context_line":"                \u0027:MISSING_CHECK: START\\r\\n\u0027"},{"line_number":1005,"context_line":"                \u00270123abc d extra response parts\\r\\n\u0027"},{"line_number":1006,"context_line":"                \u0027:MISSING_CHECK: END\\r\\n\u0027))"},{"line_number":1007,"context_line":"        self.sender.daemon._diskfile_mgr.yield_hashes \u003d yield_hashes"},{"line_number":1008,"context_line":"        self.sender.missing_check()"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_07f982c8","line":1005,"updated":"2015-10-02 05:30:01.000000000","message":"so, not all of the FakeResponse\u0027s got updated to include the \u0027d\u0027 flag - which is great because it validates backward compatibility - but... which ones are supposed to have the current protocol and which ones are now demonstrating legacy behavior?\n\nah test_meta_file_not_synced_to_legacy_receiver looks pretty good, I\u0027ll just update the others.","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"f5da6507ba3882dd7d958960018294b55fdd5d33","unresolved":false,"context_lines":[{"line_number":2371,"context_line":""},{"line_number":2372,"context_line":"class TestModuleMethods(unittest.TestCase):"},{"line_number":2373,"context_line":"    def test_encode_missing(self):"},{"line_number":2374,"context_line":"        hash \u003d \u00279d41d8cd98f00b204e9800998ecf0abc\u0027"},{"line_number":2375,"context_line":"        ts_iter \u003d make_timestamp_iter()"},{"line_number":2376,"context_line":"        t_data \u003d ts_iter.next()"},{"line_number":2377,"context_line":"        t_meta \u003d ts_iter.next()"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_278606ba","line":2374,"updated":"2015-10-02 05:30:01.000000000","message":"moar built-in names!","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"526f7e567a37c78a78d2813c723565138e41b28d","unresolved":false,"context_lines":[{"line_number":2371,"context_line":""},{"line_number":2372,"context_line":"class TestModuleMethods(unittest.TestCase):"},{"line_number":2373,"context_line":"    def test_encode_missing(self):"},{"line_number":2374,"context_line":"        hash \u003d \u00279d41d8cd98f00b204e9800998ecf0abc\u0027"},{"line_number":2375,"context_line":"        ts_iter \u003d make_timestamp_iter()"},{"line_number":2376,"context_line":"        t_data \u003d ts_iter.next()"},{"line_number":2377,"context_line":"        t_meta \u003d ts_iter.next()"}],"source_content_type":"text/x-python","patch_set":21,"id":"9a1a9d01_05f2d09a","line":2374,"in_reply_to":"9a1a9d01_278606ba","updated":"2015-10-02 11:17:58.000000000","message":"oh gosh, i hang my head in shame!","commit_id":"8e7abe6bfd8c020e3fcf22177ff586137fd39ae7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"25f84adbd4ef3b9171c19dc37f9b8047207fd82c","unresolved":false,"context_lines":[{"line_number":2457,"context_line":"        expected \u003d {\u0027data\u0027: True, \u0027meta\u0027: True}"},{"line_number":2458,"context_line":"        self.assertEqual(ssync_sender.decode_wanted(parts), expected)"},{"line_number":2459,"context_line":""},{"line_number":2460,"context_line":"        # you don\u0027t really these next few..."},{"line_number":2461,"context_line":"        parts \u003d [\u0027md\u0027]"},{"line_number":2462,"context_line":"        expected \u003d {\u0027data\u0027: True, \u0027meta\u0027: True}"},{"line_number":2463,"context_line":"        self.assertEqual(ssync_sender.decode_wanted(parts), expected)"}],"source_content_type":"text/x-python","patch_set":22,"id":"9a1a9d01_05065020","line":2460,"updated":"2015-10-02 11:18:28.000000000","message":"nit: insert need?","commit_id":"c12a1cb0a0c933e2219b0665c275baa8a3123360"}]}
