)]}'
{"swift/common/exceptions.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":196,"context_line":""},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"class BadSuffixHashesAdd(SwiftException):"},{"line_number":199,"context_line":"    pass"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":""},{"line_number":202,"context_line":"class ClientException(Exception):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_610d2337","line":199,"updated":"2015-03-06 21:28:39.000000000","message":"who uses BadSuffixHashesAdd","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"47b6452f50fe0654c3960f658bfd89dd6f474250","unresolved":false,"context_lines":[{"line_number":196,"context_line":""},{"line_number":197,"context_line":""},{"line_number":198,"context_line":"class BadSuffixHashesAdd(SwiftException):"},{"line_number":199,"context_line":"    pass"},{"line_number":200,"context_line":""},{"line_number":201,"context_line":""},{"line_number":202,"context_line":"class ClientException(Exception):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_7ec75096","line":199,"in_reply_to":"9a80dd14_610d2337","updated":"2015-03-09 14:03:21.000000000","message":"SuffixHashesEC add()","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"}],"swift/common/storage_policy.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fcd9ad80249767f29b6bab797dbe2cf43c4a6009","unresolved":false,"context_lines":[{"line_number":212,"context_line":"        return fname"},{"line_number":213,"context_line":""},{"line_number":214,"context_line":"    def fname_to_ts(self, fname, *a, **kw):"},{"line_number":215,"context_line":"        return fname, None"},{"line_number":216,"context_line":""},{"line_number":217,"context_line":"    @property"},{"line_number":218,"context_line":"    def stores_objects_verbatim(self):"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_1eba920a","line":215,"updated":"2015-02-27 03:50:51.000000000","message":"Nothing mentions what the 2 return values are and you can\u0027t tell from the base class. Maybe a doc string is in order?","commit_id":"c407c895de060f650ee543b713f27525daeaf3e0"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":175,"context_line":"        :param fname: a string representing the filename"},{"line_number":176,"context_line":"        \"\"\""},{"line_number":177,"context_line":"        raise NotImplementedError(\"fname_to_ts is undefined for base \""},{"line_number":178,"context_line":"                                  \"StoragePolicy class \")"},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"    def is_older(self, filename, other_filename):"},{"line_number":181,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_55dfce39","line":178,"updated":"2015-03-04 03:40:36.000000000","message":"the return signatures of these api\u0027s should be described here on the doc anchor point","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"ea4b9861245b554cd0841f6547b9800189c18d68","unresolved":false,"context_lines":[{"line_number":175,"context_line":"        :param fname: a string representing the filename"},{"line_number":176,"context_line":"        \"\"\""},{"line_number":177,"context_line":"        raise NotImplementedError(\"fname_to_ts is undefined for base \""},{"line_number":178,"context_line":"                                  \"StoragePolicy class \")"},{"line_number":179,"context_line":""},{"line_number":180,"context_line":"    def is_older(self, filename, other_filename):"},{"line_number":181,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_174124a9","line":178,"in_reply_to":"ba7be1f8_55dfce39","updated":"2015-03-06 17:33:05.000000000","message":"Done","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":189,"context_line":"        :returns: True if filename is consider older than other_filename and"},{"line_number":190,"context_line":"                  should therefore be deleted; False otherwise."},{"line_number":191,"context_line":"        \"\"\""},{"line_number":192,"context_line":"        return filename \u003c other_filename"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"    @property"},{"line_number":195,"context_line":"    def stores_objects_verbatim(self):"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_d5fc9eb7","line":192,"updated":"2015-03-04 03:40:36.000000000","message":"I thought we were all jazzed up by the idea that we don\u0027t need to maintain lexicographic sorting of timestamps anymore.","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5e9b16111a5d928ea76909dc6f73653b92b3422c","unresolved":false,"context_lines":[{"line_number":189,"context_line":"        :returns: True if filename is consider older than other_filename and"},{"line_number":190,"context_line":"                  should therefore be deleted; False otherwise."},{"line_number":191,"context_line":"        \"\"\""},{"line_number":192,"context_line":"        return filename \u003c other_filename"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"    @property"},{"line_number":195,"context_line":"    def stores_objects_verbatim(self):"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_1cfc573e","line":192,"in_reply_to":"ba7be1f8_d5fc9eb7","updated":"2015-03-04 15:25:14.000000000","message":"We don\u0027t need to maintain it but here it is true, until maybe fast-post lands. And now I\u0027ve said that, I wish I had called this method something else such as is_unwanted() because with fast post we\u0027ll need to keep meta\u0027s that are \"older\" in strict time sense, but still have valid metadata.","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":248,"context_line":"        For replication the fname is the timestamp, there are no other pieces"},{"line_number":249,"context_line":"        to return in the second item of the tuple."},{"line_number":250,"context_line":"        \"\"\""},{"line_number":251,"context_line":"        return fname, None"},{"line_number":252,"context_line":""},{"line_number":253,"context_line":"    @property"},{"line_number":254,"context_line":"    def stores_objects_verbatim(self):"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_75977248","line":251,"updated":"2015-03-04 03:40:36.000000000","message":"if this is going to return all the \"parts\" extracted from the filename we may as well make it a dictionary - if not just an instance of the Timestamp class.","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"ea4b9861245b554cd0841f6547b9800189c18d68","unresolved":false,"context_lines":[{"line_number":248,"context_line":"        For replication the fname is the timestamp, there are no other pieces"},{"line_number":249,"context_line":"        to return in the second item of the tuple."},{"line_number":250,"context_line":"        \"\"\""},{"line_number":251,"context_line":"        return fname, None"},{"line_number":252,"context_line":""},{"line_number":253,"context_line":"    @property"},{"line_number":254,"context_line":"    def stores_objects_verbatim(self):"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_b732185d","line":251,"in_reply_to":"ba7be1f8_75977248","updated":"2015-03-06 17:33:05.000000000","message":"Done - I added doc to abstract class that return is \u003ctimestamp\u003e, \u003cqualifier\u003e.\n\nOr did you mean return {\u0027ts\u0027: \u003ctimestamp\u003e} and other impls can add keys e.g. {\u0027ts\u0027: \u003ctimestamp\u003e, \u0027frag_index\u0027: \u003cfi\u003e}  - is that overkill?","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"a07b78853da6ba9c732478b1bfbde65a4367862e","unresolved":false,"context_lines":[{"line_number":247,"context_line":"        # end-of-message; otherwise, they get a StopIteration"},{"line_number":248,"context_line":"        chunk \u003d yield [chunk] * nstreams"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"    def ts_to_fname(self, timestamp, ext\u003dNone, *a, **kw):"},{"line_number":251,"context_line":"        if ext:"},{"line_number":252,"context_line":"            return \u0027%s%s\u0027 % (timestamp, ext)"},{"line_number":253,"context_line":"        return timestamp"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_05328e5e","line":250,"updated":"2015-03-09 10:14:49.000000000","message":"I am wondering why \"ext\" arg is None in default because Swift seems not to expect the file name without extension. (i.e. diskfile pass self._extention to here so I didn\u0027t imagine we use this method with no ext arg though I might miss something.","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":462,"context_line":"        else:"},{"line_number":463,"context_line":"            yield [\u0027\u0027] * nstreams"},{"line_number":464,"context_line":""},{"line_number":465,"context_line":"    def ts_to_fname(self, timestamp, ext\u003dNone, *a, **kw):"},{"line_number":466,"context_line":"        fragment_index \u003d kw.get(\u0027frag_index\u0027)"},{"line_number":467,"context_line":"        rv \u003d timestamp"},{"line_number":468,"context_line":"        if fragment_index not in (None, \u0027\u0027):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_66161957","line":465,"updated":"2015-03-06 21:28:39.000000000","message":"i always get confused by *a after a kwarg","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d69e1e2cae2c2a48a2a0412e5dda59cc81fd6a38","unresolved":false,"context_lines":[{"line_number":462,"context_line":"        else:"},{"line_number":463,"context_line":"            yield [\u0027\u0027] * nstreams"},{"line_number":464,"context_line":""},{"line_number":465,"context_line":"    def ts_to_fname(self, timestamp, ext\u003dNone, *a, **kw):"},{"line_number":466,"context_line":"        fragment_index \u003d kw.get(\u0027frag_index\u0027)"},{"line_number":467,"context_line":"        rv \u003d timestamp"},{"line_number":468,"context_line":"        if fragment_index not in (None, \u0027\u0027):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_3a994479","line":465,"in_reply_to":"9a80dd14_45f646fa","updated":"2015-03-10 06:08:43.000000000","message":"oh it\u0027s *valid* - it\u0027s just confusing.\n\nIf you want to accept ext as either a named arg or the second positional arg and still except other positional args - then that\u0027s how you spell it.\n\nBut is that what we want?\n\nIf you go with:\n\n    def ts_to_fname(self, timestamp, ext\u003dNone, **kw):\n        ...\n\nYou can call with:\n\n    ts_to_fname(timestamp, ext, something\u003d\u0027foo\u0027)\n\nBut not:\n\n    ts_to_fname(timestamp, ext, something)\n\n^ because there\u0027s no place to stick extra unnamed args (fine with me)\n\nIf you go with \n\n    def ts_to_fname(self, timestamp, *a, **kw):\n        ext \u003d kw.get(\u0027ext\u0027)\n        ...\n\nYou can\u0027t call with\n\n    ts_to_fname(timestamp, ext)\n\n^ because ext isn\u0027t a named arg (I\u0027m less good with this, I think here you\u0027d be better to just not allow un-named args)\n\nIf you go with:\n\n    def ts_to_fname(self, timestamp, ext\u003dNone, *a, **kw):\n        ...\n\nYou can call with\n\n    ts_to_fname(timestamp, ext, something\u003d\u0027foo\u0027)\n\nor\n\n    ts_to_fname(timestamp, ext, something)\n\nor\n\n   ts_to_fname(timestamp, something\u003d\u0027foo\u0027, ext\u003dext)\n\nand still get the right values for timestamp and ext in the signature (let the darkness *flow* through you)\n\nIf you really wanna warp your mind try:\n\n    def f(a, b):\n        print \u0027a\u0027, a\n        print \u0027b\u0027, b\n\n    f(b\u003d1, a\u003d2)\n\nIf it helps, in python3 you can say:\n\n    def ts_to_fname(timestamp, *args, ext\u003dNone, **kwargs):\n        ...\n\nSo you can call with:\n\n    ts_to_fname(timestamp, \u0027foo\u0027, ext\u003dext)\n\nBut not:\n\n    ts_to_fname(timestamp, ext)\n\n^ because all unnamed params get gobbled up in *args\n\nA better python developer once told me that \"everything except for *args is a named parameter in the end\" - and it\u0027s helps sometimes - to remember that the names you stick in the signature are just the names that get assigned to parameters if the caller didn\u0027t name them.  (Protip: if you want to be defensive as a caller it\u0027s maybe not such a bad idea to name your parameters!)","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e2dd0a07da6c16953fde33687eef37bdfe48e931","unresolved":false,"context_lines":[{"line_number":462,"context_line":"        else:"},{"line_number":463,"context_line":"            yield [\u0027\u0027] * nstreams"},{"line_number":464,"context_line":""},{"line_number":465,"context_line":"    def ts_to_fname(self, timestamp, ext\u003dNone, *a, **kw):"},{"line_number":466,"context_line":"        fragment_index \u003d kw.get(\u0027frag_index\u0027)"},{"line_number":467,"context_line":"        rv \u003d timestamp"},{"line_number":468,"context_line":"        if fragment_index not in (None, \u0027\u0027):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_45f646fa","line":465,"in_reply_to":"9a80dd14_66161957","updated":"2015-03-09 10:53:29.000000000","message":"@Clay yeah, this method signature is broken right? I could never override with ts_to_fname(self, timestamp, ext\u003dNone, foo, *a, **kw)?? So should I fix this by dropping *a from the signature:\n\n  ts_to_fname(self, timestamp, ext\u003dNone, **kw)\n\nor make ext be parsed in the method body:\n\n  ts_to_fname(self, timestamp, *a, **kw):\n      ext \u003d kw.get(\u0027ext\u0027)\n\nstill feel like a python beginner...:/","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ea4d64bd2e1f1bc2c5438d377b123b8a6d19e7fd","unresolved":false,"context_lines":[{"line_number":277,"context_line":"        # end-of-message; otherwise, they get a StopIteration"},{"line_number":278,"context_line":"        chunk \u003d yield [chunk] * nstreams"},{"line_number":279,"context_line":""},{"line_number":280,"context_line":"    def ts_to_fname(self, timestamp, ext\u003dNone, *a, **kw):"},{"line_number":281,"context_line":"        if ext:"},{"line_number":282,"context_line":"            return \u0027%s%s\u0027 % (timestamp, ext)"},{"line_number":283,"context_line":"        return timestamp"}],"source_content_type":"text/x-python","patch_set":17,"id":"9a80dd14_6510dd4e","line":280,"updated":"2015-03-19 07:31:56.000000000","message":"I still wonder why we need to set \"ext\" argument to None in default.\n\nts_to_fname seems to be called only at swift.obj.diskfile and self._extention seems to take only \".data\" or \".meta\" or \".ts\" (perhaps \".durable\" in the future) so we don\u0027t have to return pure timestamp on this function, IMHO.\n\nI\u0027m not sure because I might miss some use cases of ext\u003dNone, however, anyways, the result which allows to return timestamp seems far from the name \"ts_to_fname\" because it absolutely \"ts_to_ts\" in the case.","commit_id":"1345e85440cd25a860aabed6c7d8fec071365645"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a101612e3902123a678a62998514345f86e88684","unresolved":false,"context_lines":[{"line_number":277,"context_line":"        # end-of-message; otherwise, they get a StopIteration"},{"line_number":278,"context_line":"        chunk \u003d yield [chunk] * nstreams"},{"line_number":279,"context_line":""},{"line_number":280,"context_line":"    def ts_to_fname(self, timestamp, ext\u003dNone, *a, **kw):"},{"line_number":281,"context_line":"        if ext:"},{"line_number":282,"context_line":"            return \u0027%s%s\u0027 % (timestamp, ext)"},{"line_number":283,"context_line":"        return timestamp"}],"source_content_type":"text/x-python","patch_set":17,"id":"9a80dd14_5ca1d8f5","line":280,"in_reply_to":"9a80dd14_6510dd4e","updated":"2015-03-19 15:09:14.000000000","message":"Good question. It *may* be that a dependent patch would call an EC subclass implementation of the method with ts_to_fname(time, frag_index\u003d\u003cint\u003e) expecting a return value \u003ctime\u003e#\u003cint\u003e. I will make a note to check.","commit_id":"1345e85440cd25a860aabed6c7d8fec071365645"}],"swift/obj/diskfile.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fcd9ad80249767f29b6bab797dbe2cf43c4a6009","unresolved":false,"context_lines":[{"line_number":91,"context_line":"        if self.__class__ \u003d\u003d SuffixHashes:"},{"line_number":92,"context_line":"            raise TypeError(\"Can\u0027t instantiate SuffixHashes class directly\")"},{"line_number":93,"context_line":"        self.by_suffix \u003d {}"},{"line_number":94,"context_line":"        self._by_frag_index \u003d {}"},{"line_number":95,"context_line":"        self.repl_style \u003d {}"},{"line_number":96,"context_line":"        self.file_error \u003d False"},{"line_number":97,"context_line":"        self._hashes_file \u003d hashes_file"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_bd7269ab","line":94,"updated":"2015-02-27 03:50:51.000000000","message":"by_frag_index is being defined in the EC class, not needed here.","commit_id":"c407c895de060f650ee543b713f27525daeaf3e0"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fcd9ad80249767f29b6bab797dbe2cf43c4a6009","unresolved":false,"context_lines":[{"line_number":416,"context_line":"                        so if specified this identifies the desired one"},{"line_number":417,"context_line":"    :returns: a tuple of data, meta, tombstone and durable, in one of"},{"line_number":418,"context_line":"              two states:"},{"line_number":419,"context_line":""},{"line_number":420,"context_line":"    * ts_file is not None, data_file is None, meta_file is None"},{"line_number":421,"context_line":""},{"line_number":422,"context_line":"      object is considered deleted"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_9d404509","line":419,"updated":"2015-02-27 03:50:51.000000000","message":"policy_index param needs to be added","commit_id":"c407c895de060f650ee543b713f27525daeaf3e0"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1a7386d694caa113ba055c486c451bdeac01da3e","unresolved":false,"context_lines":[{"line_number":435,"context_line":"    data_file \u003d meta_file \u003d ts_file \u003d durable_file \u003d None"},{"line_number":436,"context_line":"    for afile in files:"},{"line_number":437,"context_line":"        # don\u0027t include a .ts found after a .data"},{"line_number":438,"context_line":"        if afile.endswith(\u0027.ts\u0027) and not data_file:"},{"line_number":439,"context_line":"            meta_file \u003d None"},{"line_number":440,"context_line":"            ts_file \u003d join(datadir, afile)"},{"line_number":441,"context_line":"            break"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_9a2aeee5","line":438,"updated":"2015-02-27 19:01:51.000000000","message":"but don\u0027t we want to break on finding ts file and having data file? sure we don\u0027t include the .ts, but if we don\u0027t break we could return a .durable that is older than .ts?","commit_id":"c407c895de060f650ee543b713f27525daeaf3e0"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1a7386d694caa113ba055c486c451bdeac01da3e","unresolved":false,"context_lines":[{"line_number":439,"context_line":"            meta_file \u003d None"},{"line_number":440,"context_line":"            ts_file \u003d join(datadir, afile)"},{"line_number":441,"context_line":"            break"},{"line_number":442,"context_line":"        if afile.endswith(\u0027.meta\u0027) and not meta_file:"},{"line_number":443,"context_line":"            meta_file \u003d join(datadir, afile)"},{"line_number":444,"context_line":"            # NOTE: this does not exit this loop, since a fast-POST"},{"line_number":445,"context_line":"            # operation just updates metadata, writing one or more"}],"source_content_type":"text/x-python","patch_set":1,"id":"ba7be1f8_5afb1647","line":442,"updated":"2015-02-27 19:01:51.000000000","message":"re comment line 438\n\n  if afile.endswith(\u0027.meta\u0027) and not meta_file and not data_file:","commit_id":"c407c895de060f650ee543b713f27525daeaf3e0"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":121,"context_line":""},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"# for SuffixHashesRepl, we just have a simple dict:"},{"line_number":124,"context_line":"# {\u0027suff1\u0027: hash1, \u0027suff2\u0027: hash2, \u0027suff3\u0027:hash3}"},{"line_number":125,"context_line":"class SuffixHashesRepl(SuffixHashes):"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":"    def __init__(self, hashes_file\u003dNone, hashes_dict\u003dNone):"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_b51e4ab9","line":124,"updated":"2015-03-04 03:40:36.000000000","message":"nit: This would look better as a class docstring","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":189,"context_line":"    def by_frag_index(self):"},{"line_number":190,"context_line":"        if self._by_frag_index \u003d\u003d {}:"},{"line_number":191,"context_line":"            self.build_by_frag_index()"},{"line_number":192,"context_line":"        return self._by_frag_index"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"    def _deserialize(self, hashes_file):"},{"line_number":195,"context_line":"        self.by_suffix \u003d {}"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_752852e2","line":192,"updated":"2015-03-04 03:40:36.000000000","message":"I think the decision to make the reconstructor go suffix by suffix instead of trying to split the jobs by part into update/update_deleted means the second dict will definitely not be needed.\n\nBut you\u0027re really only talking about dropping this property and the associated build method right?  Nothing ever tries to update/store anything in by_frag_index?","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"c0073583a17aa86bf967d40b3a6c0a5e9a609910","unresolved":false,"context_lines":[{"line_number":189,"context_line":"    def by_frag_index(self):"},{"line_number":190,"context_line":"        if self._by_frag_index \u003d\u003d {}:"},{"line_number":191,"context_line":"            self.build_by_frag_index()"},{"line_number":192,"context_line":"        return self._by_frag_index"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"    def _deserialize(self, hashes_file):"},{"line_number":195,"context_line":"        self.by_suffix \u003d {}"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_5a03dd72","line":192,"in_reply_to":"ba7be1f8_752852e2","updated":"2015-03-05 20:55:09.000000000","message":"actually I was talking about dropping the whole thing but actually I am using it in the current ver of the reconstructor so I need to review again but my preference would be to go to a single class and just have the serialization method be conditional on policy","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":289,"context_line":"    if POLICIES.get_by_index(policy_index).policy_type \u003d\u003d REPL_POLICY:"},{"line_number":290,"context_line":"        suffix_hashes \u003d SuffixHashesRepl(hashes_file)"},{"line_number":291,"context_line":"    else:"},{"line_number":292,"context_line":"        suffix_hashes \u003d SuffixHashesEC(hashes_file)"},{"line_number":293,"context_line":"    return suffix_hashes"},{"line_number":294,"context_line":""},{"line_number":295,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_75605201","line":292,"updated":"2015-03-04 03:40:36.000000000","message":"nit: if you define a global dict mapping policy_type -\u003e SuffixClass it\u0027s easier monkey patch.","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5e9b16111a5d928ea76909dc6f73653b92b3422c","unresolved":false,"context_lines":[{"line_number":424,"context_line":""},{"line_number":425,"context_line":"      object is considered deleted"},{"line_number":426,"context_line":""},{"line_number":427,"context_line":"    * (data_file is not None or durable_file is not None) and ts_file is None"},{"line_number":428,"context_line":""},{"line_number":429,"context_line":"      object exists, and optionally has fast-POST metadata"},{"line_number":430,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_68a02df5","line":427,"updated":"2015-03-04 15:25:14.000000000","message":"add \n\ndata_file is not None or (data_file is None and meta_file is None)","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"ea4b9861245b554cd0841f6547b9800189c18d68","unresolved":false,"context_lines":[{"line_number":424,"context_line":""},{"line_number":425,"context_line":"      object is considered deleted"},{"line_number":426,"context_line":""},{"line_number":427,"context_line":"    * (data_file is not None or durable_file is not None) and ts_file is None"},{"line_number":428,"context_line":""},{"line_number":429,"context_line":"      object exists, and optionally has fast-POST metadata"},{"line_number":430,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_97919449","line":427,"in_reply_to":"9a80dd14_68a02df5","updated":"2015-03-06 17:33:05.000000000","message":"Done","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"aa08344ef86c3868d11b6f174456662310d9f29d","unresolved":false,"context_lines":[{"line_number":476,"context_line":"            if durable_file:"},{"line_number":477,"context_line":"                # this file must be older than already found durable file,"},{"line_number":478,"context_line":"                # so matching data file will not be found"},{"line_number":479,"context_line":"                meta_file \u003d None"},{"line_number":480,"context_line":"                break"},{"line_number":481,"context_line":"            # continue to look for same timestamp data file"},{"line_number":482,"context_line":"            durable_file \u003d join(datadir, afile)"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_1bf1046b","line":479,"updated":"2015-03-04 03:02:19.000000000","message":"Why do we nuke the meta_file here? The meta_file, if there is one, will be newer or the same age as the .durable. So valid right? \n\nAm I missing something?","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"ea4b9861245b554cd0841f6547b9800189c18d68","unresolved":false,"context_lines":[{"line_number":476,"context_line":"            if durable_file:"},{"line_number":477,"context_line":"                # this file must be older than already found durable file,"},{"line_number":478,"context_line":"                # so matching data file will not be found"},{"line_number":479,"context_line":"                meta_file \u003d None"},{"line_number":480,"context_line":"                break"},{"line_number":481,"context_line":"            # continue to look for same timestamp data file"},{"line_number":482,"context_line":"            durable_file \u003d join(datadir, afile)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_3128f0e1","line":479,"in_reply_to":"9a80dd14_5b9f9552","updated":"2015-03-06 17:33:05.000000000","message":"Done","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"8acbbd4b1f933fe7dd350bbeda7c89d221e42162","unresolved":false,"context_lines":[{"line_number":476,"context_line":"            if durable_file:"},{"line_number":477,"context_line":"                # this file must be older than already found durable file,"},{"line_number":478,"context_line":"                # so matching data file will not be found"},{"line_number":479,"context_line":"                meta_file \u003d None"},{"line_number":480,"context_line":"                break"},{"line_number":481,"context_line":"            # continue to look for same timestamp data file"},{"line_number":482,"context_line":"            durable_file \u003d join(datadir, afile)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_5b9f9552","line":479,"in_reply_to":"9a80dd14_ff0f752c","updated":"2015-03-05 02:56:47.000000000","message":"Right, that makes sense, if it gets here \u003d\u003d no .data found.\nThanks for explaining!\n\nLol, glad i\u0027m not the only one this gave a mental workout too :P","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5e9b16111a5d928ea76909dc6f73653b92b3422c","unresolved":false,"context_lines":[{"line_number":476,"context_line":"            if durable_file:"},{"line_number":477,"context_line":"                # this file must be older than already found durable file,"},{"line_number":478,"context_line":"                # so matching data file will not be found"},{"line_number":479,"context_line":"                meta_file \u003d None"},{"line_number":480,"context_line":"                break"},{"line_number":481,"context_line":"            # continue to look for same timestamp data file"},{"line_number":482,"context_line":"            durable_file \u003d join(datadir, afile)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_ff0f752c","line":479,"in_reply_to":"ba7be1f8_1bf1046b","updated":"2015-03-04 15:25:14.000000000","message":"First, I thought you\u0027re right. Then, I thought not - but that means I have bugs elsewhere :/\n\nThe logic here is: \n* if a second durable file is found, that means that no data file has been found that has same timestamp as the first durable file found, since we always break on finding a matching data file.\n* if no matching data file then never return a meta file\n\nBut that should be taken care of at a (corrected) line 487. So will fix here and at 487.\n\nI *was* thinking its ok to return a meta with just a durable (meaning this line is a bug) because it means we can serve a HEAD despite missing .data.\n\nNow I realise that\u0027s broken thinking because the diskfile open() will raise Exception if there is no data file, so my logic here *is* correct (but wrong elswhere!).\n\nAnd clearly a test scenario is needed to cover this.","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5e9b16111a5d928ea76909dc6f73653b92b3422c","unresolved":false,"context_lines":[{"line_number":484,"context_line":"    if policy.policy_type \u003d\u003d EC_POLICY:"},{"line_number":485,"context_line":"        # We could find only a meta_file if searching for a frag index"},{"line_number":486,"context_line":"        # that is not present. Clear it to comply with following assertion."},{"line_number":487,"context_line":"        meta_file \u003d meta_file if (data_file or durable_file) else None"},{"line_number":488,"context_line":"        # EC-specific contract"},{"line_number":489,"context_line":"        assert ((data_file is None)"},{"line_number":490,"context_line":"                or (data_file is not None and durable_file is not None))"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_a2e8867d","line":487,"updated":"2015-03-04 15:25:14.000000000","message":"meta_file \u003d meta_file if data_file else None\n\nnever return a meta without a data","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"ea4b9861245b554cd0841f6547b9800189c18d68","unresolved":false,"context_lines":[{"line_number":484,"context_line":"    if policy.policy_type \u003d\u003d EC_POLICY:"},{"line_number":485,"context_line":"        # We could find only a meta_file if searching for a frag index"},{"line_number":486,"context_line":"        # that is not present. Clear it to comply with following assertion."},{"line_number":487,"context_line":"        meta_file \u003d meta_file if (data_file or durable_file) else None"},{"line_number":488,"context_line":"        # EC-specific contract"},{"line_number":489,"context_line":"        assert ((data_file is None)"},{"line_number":490,"context_line":"                or (data_file is not None and durable_file is not None))"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_176f642c","line":487,"in_reply_to":"9a80dd14_a2e8867d","updated":"2015-03-06 17:33:05.000000000","message":"Done","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":923,"context_line":""},{"line_number":924,"context_line":"    def get_diskfile_from_hash(self, device, partition, object_hash,"},{"line_number":925,"context_line":"                               policy_index, frag_index\u003dNone,"},{"line_number":926,"context_line":"                               timestamp\u003dNone, **kwargs):"},{"line_number":927,"context_line":"        \"\"\""},{"line_number":928,"context_line":"        Returns a DiskFile instance for an object at the given"},{"line_number":929,"context_line":"        object_hash. Just in case someone thinks of refactoring, be"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_bde55039","line":926,"updated":"2015-03-04 03:40:36.000000000","message":"this method is getting on my nerves, it should be replaced with a call to from_hash_dir that knows how to plumb through a call to  hash_cleanup_listdir instead of just os.listdir when it gets down into _get_ondisk_file","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":969,"context_line":"        # exist, for EC there may be other FI\u0027s present so we need to"},{"line_number":970,"context_line":"        # dig a little deeper and make sure that the desired one isn\u0027t"},{"line_number":971,"context_line":"        # there before we can say if file exists or not"},{"line_number":972,"context_line":"        if frag_index:"},{"line_number":973,"context_line":"            looking_for \u003d POLICIES.get_by_index(policy_index).ts_to_fname("},{"line_number":974,"context_line":"                timestamp, frag_index) + \u0027.data\u0027"},{"line_number":975,"context_line":"            if looking_for not in filenames:"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_eaeb80a1","line":972,"updated":"2015-03-04 03:40:36.000000000","message":"can frag_index be 0?  oh oh - or is this the case when frag_index is a string?!","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"ea4b9861245b554cd0841f6547b9800189c18d68","unresolved":false,"context_lines":[{"line_number":969,"context_line":"        # exist, for EC there may be other FI\u0027s present so we need to"},{"line_number":970,"context_line":"        # dig a little deeper and make sure that the desired one isn\u0027t"},{"line_number":971,"context_line":"        # there before we can say if file exists or not"},{"line_number":972,"context_line":"        if frag_index:"},{"line_number":973,"context_line":"            looking_for \u003d POLICIES.get_by_index(policy_index).ts_to_fname("},{"line_number":974,"context_line":"                timestamp, frag_index) + \u0027.data\u0027"},{"line_number":975,"context_line":"            if looking_for not in filenames:"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_97f0b468","line":972,"in_reply_to":"9a80dd14_fabd7169","updated":"2015-03-06 17:33:05.000000000","message":"I *think* the comment (and code) is wrong: hash_cleanup_listdir *will* return whatever files are left in the dir - frag_index is not an arg to h_c_l() - lines 973 to 976 cause this method to raise DiskFileNotExist if the specific timestamp is not found, which breaks ssync_receiver when the receiver actually has a newer timestamp than the sender.\n\nTests didn;t reveal this because test used frag_index\u003d0 so \u0027if frag_index\u0027 is False :/","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"c0073583a17aa86bf967d40b3a6c0a5e9a609910","unresolved":false,"context_lines":[{"line_number":969,"context_line":"        # exist, for EC there may be other FI\u0027s present so we need to"},{"line_number":970,"context_line":"        # dig a little deeper and make sure that the desired one isn\u0027t"},{"line_number":971,"context_line":"        # there before we can say if file exists or not"},{"line_number":972,"context_line":"        if frag_index:"},{"line_number":973,"context_line":"            looking_for \u003d POLICIES.get_by_index(policy_index).ts_to_fname("},{"line_number":974,"context_line":"                timestamp, frag_index) + \u0027.data\u0027"},{"line_number":975,"context_line":"            if looking_for not in filenames:"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_fabd7169","line":972,"in_reply_to":"ba7be1f8_eaeb80a1","updated":"2015-03-05 20:55:09.000000000","message":"damn it.  should be if not None, thanks","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":1096,"context_line":"        self._tmppath \u003d tmppath"},{"line_number":1097,"context_line":"        self._bytes_per_sync \u003d bytes_per_sync"},{"line_number":1098,"context_line":"        self._threadpool \u003d threadpool"},{"line_number":1099,"context_line":"        self._policy_index \u003d extract_policy_index(self._datadir)"},{"line_number":1100,"context_line":""},{"line_number":1101,"context_line":"        # Internal attributes"},{"line_number":1102,"context_line":"        self._upload_size \u003d 0"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_e7e01928","line":1099,"updated":"2015-03-04 03:40:36.000000000","message":"why can\u0027t the policy just be passed in explicitly?  I think create is defined on DiskFile who has a _policy_index attribute.","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"c0073583a17aa86bf967d40b3a6c0a5e9a609910","unresolved":false,"context_lines":[{"line_number":1096,"context_line":"        self._tmppath \u003d tmppath"},{"line_number":1097,"context_line":"        self._bytes_per_sync \u003d bytes_per_sync"},{"line_number":1098,"context_line":"        self._threadpool \u003d threadpool"},{"line_number":1099,"context_line":"        self._policy_index \u003d extract_policy_index(self._datadir)"},{"line_number":1100,"context_line":""},{"line_number":1101,"context_line":"        # Internal attributes"},{"line_number":1102,"context_line":"        self._upload_size \u003d 0"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_daa6ed52","line":1099,"in_reply_to":"9a80dd14_df955189","updated":"2015-03-05 20:55:09.000000000","message":"yup, it\u0027s just been iterated on a few times and can be cleaned up","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5e9b16111a5d928ea76909dc6f73653b92b3422c","unresolved":false,"context_lines":[{"line_number":1096,"context_line":"        self._tmppath \u003d tmppath"},{"line_number":1097,"context_line":"        self._bytes_per_sync \u003d bytes_per_sync"},{"line_number":1098,"context_line":"        self._threadpool \u003d threadpool"},{"line_number":1099,"context_line":"        self._policy_index \u003d extract_policy_index(self._datadir)"},{"line_number":1100,"context_line":""},{"line_number":1101,"context_line":"        # Internal attributes"},{"line_number":1102,"context_line":"        self._upload_size \u003d 0"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_df955189","line":1099,"in_reply_to":"ba7be1f8_e7e01928","updated":"2015-03-04 15:25:14.000000000","message":"You know, I stared at that with same question - policy_index gets passed in other places too when we could resolve earlier to a policy instance.","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":1176,"context_line":"        \"\"\""},{"line_number":1177,"context_line":"        fi \u003d metadata.get(\u0027X-Object-Sysmeta-Ec-Archive-Index\u0027, \u0027\u0027)"},{"line_number":1178,"context_line":"        timestamp \u003d POLICIES.get_by_index(self._policy_index). \\"},{"line_number":1179,"context_line":"            ts_to_fname(Timestamp(metadata[\u0027X-Timestamp\u0027]).internal, fi)"},{"line_number":1180,"context_line":"        metadata[\u0027name\u0027] \u003d self._name"},{"line_number":1181,"context_line":"        target_path \u003d join(self._datadir, timestamp + self._extension)"},{"line_number":1182,"context_line":"        self._threadpool.force_run_in_thread("}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_3d57a0cb","line":1179,"updated":"2015-03-04 03:40:36.000000000","message":"this variable should not be called timestamp, it\u0027s an fname.\n\nAlso what\u0027s the difference between X-Backend-Node-Index and X-Object-Sysmeta-Ec-Archive-Index?","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"ea4b9861245b554cd0841f6547b9800189c18d68","unresolved":false,"context_lines":[{"line_number":1176,"context_line":"        \"\"\""},{"line_number":1177,"context_line":"        fi \u003d metadata.get(\u0027X-Object-Sysmeta-Ec-Archive-Index\u0027, \u0027\u0027)"},{"line_number":1178,"context_line":"        timestamp \u003d POLICIES.get_by_index(self._policy_index). \\"},{"line_number":1179,"context_line":"            ts_to_fname(Timestamp(metadata[\u0027X-Timestamp\u0027]).internal, fi)"},{"line_number":1180,"context_line":"        metadata[\u0027name\u0027] \u003d self._name"},{"line_number":1181,"context_line":"        target_path \u003d join(self._datadir, timestamp + self._extension)"},{"line_number":1182,"context_line":"        self._threadpool.force_run_in_thread("}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_b76a18ec","line":1179,"in_reply_to":"9a80dd14_05010a05","updated":"2015-03-06 17:33:05.000000000","message":"Done the variable name change","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"c0073583a17aa86bf967d40b3a6c0a5e9a609910","unresolved":false,"context_lines":[{"line_number":1176,"context_line":"        \"\"\""},{"line_number":1177,"context_line":"        fi \u003d metadata.get(\u0027X-Object-Sysmeta-Ec-Archive-Index\u0027, \u0027\u0027)"},{"line_number":1178,"context_line":"        timestamp \u003d POLICIES.get_by_index(self._policy_index). \\"},{"line_number":1179,"context_line":"            ts_to_fname(Timestamp(metadata[\u0027X-Timestamp\u0027]).internal, fi)"},{"line_number":1180,"context_line":"        metadata[\u0027name\u0027] \u003d self._name"},{"line_number":1181,"context_line":"        target_path \u003d join(self._datadir, timestamp + self._extension)"},{"line_number":1182,"context_line":"        self._threadpool.force_run_in_thread("}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_05010a05","line":1179,"in_reply_to":"ba7be1f8_3d57a0cb","updated":"2015-03-05 20:55:09.000000000","message":"agree, the names can be better.  good question on the two headers, I did one on the recon/fi work and I think the other came in on the PUT patch.  I\u0027ll add a trello item to compare/scrub as I\u0027m assuming we can just use one","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":1525,"context_line":"        self._pipe_size \u003d pipe_size"},{"line_number":1526,"context_line":"        self._policy_index \u003d policy_index"},{"line_number":1527,"context_line":"        self._policy \u003d POLICIES.get_by_index(policy_index)"},{"line_number":1528,"context_line":"        self._frag_index \u003d str(frag_index) if frag_index is not None else None"},{"line_number":1529,"context_line":"        if account and container and obj:"},{"line_number":1530,"context_line":"            self._name \u003d \u0027/\u0027 + \u0027/\u0027.join((account, container, obj))"},{"line_number":1531,"context_line":"            self._account \u003d account"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_1d32dca6","line":1528,"updated":"2015-03-04 03:40:36.000000000","message":"so self._policy_index is an integer and self._frag_index is a str :\\","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"ea4b9861245b554cd0841f6547b9800189c18d68","unresolved":false,"context_lines":[{"line_number":1525,"context_line":"        self._pipe_size \u003d pipe_size"},{"line_number":1526,"context_line":"        self._policy_index \u003d policy_index"},{"line_number":1527,"context_line":"        self._policy \u003d POLICIES.get_by_index(policy_index)"},{"line_number":1528,"context_line":"        self._frag_index \u003d str(frag_index) if frag_index is not None else None"},{"line_number":1529,"context_line":"        if account and container and obj:"},{"line_number":1530,"context_line":"            self._name \u003d \u0027/\u0027 + \u0027/\u0027.join((account, container, obj))"},{"line_number":1531,"context_line":"            self._account \u003d account"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_11d5acb8","line":1528,"in_reply_to":"9a80dd14_853b3ad0","updated":"2015-03-06 17:33:05.000000000","message":"Done - diskfile will cast frag_index to int","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"c0073583a17aa86bf967d40b3a6c0a5e9a609910","unresolved":false,"context_lines":[{"line_number":1525,"context_line":"        self._pipe_size \u003d pipe_size"},{"line_number":1526,"context_line":"        self._policy_index \u003d policy_index"},{"line_number":1527,"context_line":"        self._policy \u003d POLICIES.get_by_index(policy_index)"},{"line_number":1528,"context_line":"        self._frag_index \u003d str(frag_index) if frag_index is not None else None"},{"line_number":1529,"context_line":"        if account and container and obj:"},{"line_number":1530,"context_line":"            self._name \u003d \u0027/\u0027 + \u0027/\u0027.join((account, container, obj))"},{"line_number":1531,"context_line":"            self._account \u003d account"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_853b3ad0","line":1528,"in_reply_to":"ba7be1f8_1d32dca6","updated":"2015-03-05 20:55:09.000000000","message":"yeah, should make that consistent","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":1701,"context_line":"            data_file, meta_file, ts_file, durable_file_ \u003d \\"},{"line_number":1702,"context_line":"                get_ondisk_files(files, self._datadir, self._policy,"},{"line_number":1703,"context_line":"                                 self._frag_index)"},{"line_number":1704,"context_line":"            fileset \u003d (data_file, meta_file, ts_file)"},{"line_number":1705,"context_line":""},{"line_number":1706,"context_line":"        return fileset"},{"line_number":1707,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_1da73cbe","line":1704,"updated":"2015-03-04 03:40:36.000000000","message":"why did we just throw out durable?","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"c0073583a17aa86bf967d40b3a6c0a5e9a609910","unresolved":false,"context_lines":[{"line_number":1701,"context_line":"            data_file, meta_file, ts_file, durable_file_ \u003d \\"},{"line_number":1702,"context_line":"                get_ondisk_files(files, self._datadir, self._policy,"},{"line_number":1703,"context_line":"                                 self._frag_index)"},{"line_number":1704,"context_line":"            fileset \u003d (data_file, meta_file, ts_file)"},{"line_number":1705,"context_line":""},{"line_number":1706,"context_line":"        return fileset"},{"line_number":1707,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_a53d9ebd","line":1704,"in_reply_to":"9a80dd14_7f30e556","updated":"2015-03-05 20:55:09.000000000","message":"yup","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"ea4b9861245b554cd0841f6547b9800189c18d68","unresolved":false,"context_lines":[{"line_number":1701,"context_line":"            data_file, meta_file, ts_file, durable_file_ \u003d \\"},{"line_number":1702,"context_line":"                get_ondisk_files(files, self._datadir, self._policy,"},{"line_number":1703,"context_line":"                                 self._frag_index)"},{"line_number":1704,"context_line":"            fileset \u003d (data_file, meta_file, ts_file)"},{"line_number":1705,"context_line":""},{"line_number":1706,"context_line":"        return fileset"},{"line_number":1707,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_fa7f1564","line":1704,"in_reply_to":"9a80dd14_a53d9ebd","updated":"2015-03-06 17:33:05.000000000","message":"Done, changed to return all four files, open() then ignore durable. Makes for simpler code here.","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5e9b16111a5d928ea76909dc6f73653b92b3422c","unresolved":false,"context_lines":[{"line_number":1701,"context_line":"            data_file, meta_file, ts_file, durable_file_ \u003d \\"},{"line_number":1702,"context_line":"                get_ondisk_files(files, self._datadir, self._policy,"},{"line_number":1703,"context_line":"                                 self._frag_index)"},{"line_number":1704,"context_line":"            fileset \u003d (data_file, meta_file, ts_file)"},{"line_number":1705,"context_line":""},{"line_number":1706,"context_line":"        return fileset"},{"line_number":1707,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_7f30e556","line":1704,"in_reply_to":"ba7be1f8_1da73cbe","updated":"2015-03-04 15:25:14.000000000","message":"Didn\u0027t write this piece, but the only place calling _get_ondisk_file is open() and it has no use for durable file. data_file not None implies a durable was found so ok to open the diskfile.\n\nBut we could just return all files and discard the durable in open()...","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3dc3dd4b802b98449787ca779ece0a5ce80a3c69","unresolved":false,"context_lines":[{"line_number":1982,"context_line":"                            errors as the `create()` method."},{"line_number":1983,"context_line":"        \"\"\""},{"line_number":1984,"context_line":"        timestamp, fi \u003d \\"},{"line_number":1985,"context_line":"            POLICIES.get_by_index(self._policy_index).fname_to_ts(timestamp)"},{"line_number":1986,"context_line":"        timestamp \u003d Timestamp(timestamp).internal"},{"line_number":1987,"context_line":"        assert(self._frag_index \u003d\u003d fi)"},{"line_number":1988,"context_line":"        with self.create() as deleter:"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_2cf8fb7b","line":1985,"updated":"2015-03-04 20:14:17.000000000","message":"... is timestamp a fname?  I get a *splosion* when I try to delete objects","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"c0073583a17aa86bf967d40b3a6c0a5e9a609910","unresolved":false,"context_lines":[{"line_number":1982,"context_line":"                            errors as the `create()` method."},{"line_number":1983,"context_line":"        \"\"\""},{"line_number":1984,"context_line":"        timestamp, fi \u003d \\"},{"line_number":1985,"context_line":"            POLICIES.get_by_index(self._policy_index).fname_to_ts(timestamp)"},{"line_number":1986,"context_line":"        timestamp \u003d Timestamp(timestamp).internal"},{"line_number":1987,"context_line":"        assert(self._frag_index \u003d\u003d fi)"},{"line_number":1988,"context_line":"        with self.create() as deleter:"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_85deda6b","line":1985,"in_reply_to":"9a80dd14_2cf8fb7b","updated":"2015-03-05 20:55:09.000000000","message":"i thought we never deleted things :)","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":1984,"context_line":"        timestamp, fi \u003d \\"},{"line_number":1985,"context_line":"            POLICIES.get_by_index(self._policy_index).fname_to_ts(timestamp)"},{"line_number":1986,"context_line":"        timestamp \u003d Timestamp(timestamp).internal"},{"line_number":1987,"context_line":"        assert(self._frag_index \u003d\u003d fi)"},{"line_number":1988,"context_line":"        with self.create() as deleter:"},{"line_number":1989,"context_line":"            deleter._extension \u003d \u0027.ts\u0027"},{"line_number":1990,"context_line":"            deleter.put({\u0027X-Timestamp\u0027: timestamp,"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_fd8a6819","line":1987,"updated":"2015-03-04 03:40:36.000000000","message":"does some one catch this assertion error","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"c0073583a17aa86bf967d40b3a6c0a5e9a609910","unresolved":false,"context_lines":[{"line_number":1984,"context_line":"        timestamp, fi \u003d \\"},{"line_number":1985,"context_line":"            POLICIES.get_by_index(self._policy_index).fname_to_ts(timestamp)"},{"line_number":1986,"context_line":"        timestamp \u003d Timestamp(timestamp).internal"},{"line_number":1987,"context_line":"        assert(self._frag_index \u003d\u003d fi)"},{"line_number":1988,"context_line":"        with self.create() as deleter:"},{"line_number":1989,"context_line":"            deleter._extension \u003d \u0027.ts\u0027"},{"line_number":1990,"context_line":"            deleter.put({\u0027X-Timestamp\u0027: timestamp,"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_25d52e43","line":1987,"in_reply_to":"ba7be1f8_fd8a6819","updated":"2015-03-05 20:55:09.000000000","message":"leftover code from doing debug - need to delete","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":121,"context_line":""},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"# for SuffixHashesRepl, we just have a simple dict:"},{"line_number":124,"context_line":"# {\u0027suff1\u0027: hash1, \u0027suff2\u0027: hash2, \u0027suff3\u0027:hash3}"},{"line_number":125,"context_line":"class SuffixHashesRepl(SuffixHashes):"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":"    def __init__(self, hashes_file\u003dNone, hashes_dict\u003dNone):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_212ecb92","line":124,"updated":"2015-03-06 21:28:39.000000000","message":"class doc string *please*","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":177,"context_line":"# by_frag_index:"},{"line_number":178,"context_line":"# {\u00271\u0027: [\u0027suff1\u0027, \u0027suff2\u0027],"},{"line_number":179,"context_line":"#  \u00272\u0027: [\u0027suff1\u0027, \u0027suff2\u0027],"},{"line_number":180,"context_line":"#  \u00273\u0027: [\u0027suff1\u0027, \u0027suff2\u0027]},"},{"line_number":181,"context_line":"class SuffixHashesEC(SuffixHashes):"},{"line_number":182,"context_line":""},{"line_number":183,"context_line":"    def __init__(self, hashes_file\u003dNone, hashes_dict\u003dNone):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_612443af","line":180,"updated":"2015-03-06 21:28:39.000000000","message":"class doc string *please* - it\u0027ll be much for useful in the sphinx autodoc","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":245,"context_line":"        sub_dict \u003d self.by_suffix[suffix].copy()"},{"line_number":246,"context_line":"        for fi in sub_dict:"},{"line_number":247,"context_line":"            if sub_dict[fi] is None:"},{"line_number":248,"context_line":"                del self.by_suffix[suffix][fi]"},{"line_number":249,"context_line":""},{"line_number":250,"context_line":"    def invalidate(self, suffix):"},{"line_number":251,"context_line":"        changed \u003d False"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_fc84565f","line":248,"updated":"2015-03-06 21:28:39.000000000","message":"Probably just:\n\n    self.by_suffix[suffix] \u003d dict((k, v) for k, v in self.by_suffix[suffix] \n                                  if v is not None)","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":395,"context_line":"    to_dir \u003d join(device_path, \u0027quarantined\u0027,"},{"line_number":396,"context_line":"                  get_data_dir(policy_index),"},{"line_number":397,"context_line":"                  basename(from_dir))"},{"line_number":398,"context_line":"    invalidate_hash(dirname(from_dir), policy_index)"},{"line_number":399,"context_line":"    try:"},{"line_number":400,"context_line":"        renamer(from_dir, to_dir)"},{"line_number":401,"context_line":"    except OSError as e:"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_6113630d","line":398,"updated":"2015-03-06 21:28:39.000000000","message":"invalidate_hash could just as easily use extract - I guess one call sight thinks it already knows the policy, but doesn\u0027t want to get the policy\u0027s suffix instance and just call invalidate directly...","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":501,"context_line":"    return data_file, meta_file, ts_file, durable_file"},{"line_number":502,"context_line":""},{"line_number":503,"context_line":""},{"line_number":504,"context_line":"def hash_cleanup_listdir(hsh_path, policy_index, reclaim_age\u003dONE_WEEK):"},{"line_number":505,"context_line":"    \"\"\""},{"line_number":506,"context_line":"    List contents of a hash directory and clean up any old files:"},{"line_number":507,"context_line":"    - For replication policy, delete files older than a .data or .ts file"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_61e1a3fd","line":504,"updated":"2015-03-06 21:28:39.000000000","message":"should we be worried about moving the posistion args here in case some script someone was calling hash_cleanup_listdir like\n\n    hash_cleanup_listdir(path, 2_DAYS)","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":512,"context_line":"    :param reclaim_age: age in seconds at which to remove tombstones"},{"line_number":513,"context_line":"    :returns: list of files remaining in the directory, reverse sorted"},{"line_number":514,"context_line":"    \"\"\""},{"line_number":515,"context_line":"    policy \u003d POLICIES.get_by_index(policy_index)"},{"line_number":516,"context_line":"    files \u003d listdir(hsh_path)"},{"line_number":517,"context_line":"    if len(files) \u003d\u003d 1:"},{"line_number":518,"context_line":"        if files[0].endswith(\u0027.ts\u0027):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_81a5b7a3","line":515,"updated":"2015-03-06 21:28:39.000000000","message":"this can be None right?  Do we ever say POLICIES[policy_index] in swift or just in tests?\n\nYou might be able to get away with:\n\n    POLICIES.get_by_index(policy_index, 0)\n\nMaybe it\u0027s find isn\u0027t no worse to just let it AttributeError - no KeyError is probably the best...","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":528,"context_line":"        newest_file \u003d durable_file or data_file or ts_file"},{"line_number":529,"context_line":"        if newest_file:"},{"line_number":530,"context_line":"            for filename in list(files):"},{"line_number":531,"context_line":"                if (policy.is_obsolete(filename, newest_file)"},{"line_number":532,"context_line":"                        or (meta_file"},{"line_number":533,"context_line":"                            and filename.endswith(\u0027.meta\u0027)"},{"line_number":534,"context_line":"                            and filename \u003c meta_file)):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_a1255b0a","line":531,"updated":"2015-03-06 21:28:39.000000000","message":"it\u0027s weird, i rather like calling into the policy here... i guess it\u0027s still not as good as some sort of implementation specific helper.","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e2dd0a07da6c16953fde33687eef37bdfe48e931","unresolved":false,"context_lines":[{"line_number":528,"context_line":"        newest_file \u003d durable_file or data_file or ts_file"},{"line_number":529,"context_line":"        if newest_file:"},{"line_number":530,"context_line":"            for filename in list(files):"},{"line_number":531,"context_line":"                if (policy.is_obsolete(filename, newest_file)"},{"line_number":532,"context_line":"                        or (meta_file"},{"line_number":533,"context_line":"                            and filename.endswith(\u0027.meta\u0027)"},{"line_number":534,"context_line":"                            and filename \u003c meta_file)):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_c5eb16da","line":531,"in_reply_to":"9a80dd14_a1255b0a","updated":"2015-03-09 10:53:29.000000000","message":"I like calling *somewhere* rather than inline policy-conditional code. I don\u0027t like that I have still exposed policy-specific\u0027s in line 528 :/\n\n  newest_file \u003d durable_file or data_file or ts_file\n\nI nearly changed this to pass the ondisk file set to is_obsolete() and let that method take care of (a) determining the policy-specific newest file and then (b) determining if the file under test is obsolete. But backed off because there would be a slight loss of optimisation because as it stands, the loop is never executed if there is *no* newest file.\n\nI guess a call to a policy.get_newest(file_set) would do it. But what I\u0027d really like to do is have a policy.get_ondisk_files() method return the wanted set and optionally the unwanted set as result of a single iteration over the dir listing.","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":637,"context_line":"    suffix_hashes \u003d _get_suffix_hashes(policy_index, hashes_file)"},{"line_number":638,"context_line":""},{"line_number":639,"context_line":"    # if a new suffix dir is found add it without any FI or hash info"},{"line_number":640,"context_line":"    if do_listdir or suffix_hashes.file_error:"},{"line_number":641,"context_line":"        for suffix in os.listdir(partition_dir):"},{"line_number":642,"context_line":"            if len(suffix) \u003d\u003d 3:"},{"line_number":643,"context_line":"                suffix_hashes.add(suffix)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_fcd2965a","line":640,"updated":"2015-03-06 21:28:39.000000000","message":"oh this property feels so weird to me - i\u0027m pretty sure it\u0027s trying to tell me that we\u0027re leaking implementation of the suffix out of the suffix class.\n\nOne idea might be:\n\n    success, suffix_hashes \u003d _get_suffix_hashes(...)\n\nwhere success indicates it\u0027s created a new empty one for you and you can do the needful.","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":646,"context_line":"    # TODO: need a better way to figure out which suffixes to recalc"},{"line_number":647,"context_line":"    # following completion of partition job level processing in recon"},{"line_number":648,"context_line":"    if recalculate \u003d\u003d \u0027all\u0027:"},{"line_number":649,"context_line":"        recalculate \u003d suffix_hashes.by_suffix.keys()"},{"line_number":650,"context_line":""},{"line_number":651,"context_line":"    # add/invalidate any suffixes per caller"},{"line_number":652,"context_line":"    for suffix in recalculate:"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_8104d74a","line":649,"updated":"2015-03-06 21:28:39.000000000","message":"recon does *what* now?","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"47b6452f50fe0654c3960f658bfd89dd6f474250","unresolved":false,"context_lines":[{"line_number":646,"context_line":"    # TODO: need a better way to figure out which suffixes to recalc"},{"line_number":647,"context_line":"    # following completion of partition job level processing in recon"},{"line_number":648,"context_line":"    if recalculate \u003d\u003d \u0027all\u0027:"},{"line_number":649,"context_line":"        recalculate \u003d suffix_hashes.by_suffix.keys()"},{"line_number":650,"context_line":""},{"line_number":651,"context_line":"    # add/invalidate any suffixes per caller"},{"line_number":652,"context_line":"    for suffix in recalculate:"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_fe2fc03c","line":649,"in_reply_to":"9a80dd14_8104d74a","updated":"2015-03-09 14:03:21.000000000","message":"better to save addressing this comment for when this patch is done and we\u0027re focused on the reconstructor - its the only one that uses this parm and it will be easy to see how over there","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":654,"context_line":"        suffix_hashes.invalidate(suffix)"},{"line_number":655,"context_line":""},{"line_number":656,"context_line":"    # loop through all suffixes needing hash recalc"},{"line_number":657,"context_line":"    for suffix, hash_dict in suffix_hashes.walk_items():"},{"line_number":658,"context_line":"        if any(h is None for h in hash_dict.values()):"},{"line_number":659,"context_line":"            suffix_dir \u003d join(partition_dir, suffix)"},{"line_number":660,"context_line":"            try:"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_013467fa","line":657,"updated":"2015-03-06 21:28:39.000000000","message":"this is such a goofy interface for suffix_hashes to have :P\n\nI wonder who is calling these methods that doesn\u0027t have access to a DiskFileManager - I\u0027m going to try to push more of these onto the Suffix classes.","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"47b6452f50fe0654c3960f658bfd89dd6f474250","unresolved":false,"context_lines":[{"line_number":654,"context_line":"        suffix_hashes.invalidate(suffix)"},{"line_number":655,"context_line":""},{"line_number":656,"context_line":"    # loop through all suffixes needing hash recalc"},{"line_number":657,"context_line":"    for suffix, hash_dict in suffix_hashes.walk_items():"},{"line_number":658,"context_line":"        if any(h is None for h in hash_dict.values()):"},{"line_number":659,"context_line":"            suffix_dir \u003d join(partition_dir, suffix)"},{"line_number":660,"context_line":"            try:"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_be9e2861","line":657,"in_reply_to":"9a80dd14_013467fa","updated":"2015-03-09 14:03:21.000000000","message":"they are only used here and they\u0027re walking the items in the class, not on disk. yeah, I guess its a little odd but I wanted a quick way to munge, on the repl side, the suffix entries to append a None:hash for the hash_dict without storing this info","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":655,"context_line":""},{"line_number":656,"context_line":"    # loop through all suffixes needing hash recalc"},{"line_number":657,"context_line":"    for suffix, hash_dict in suffix_hashes.walk_items():"},{"line_number":658,"context_line":"        if any(h is None for h in hash_dict.values()):"},{"line_number":659,"context_line":"            suffix_dir \u003d join(partition_dir, suffix)"},{"line_number":660,"context_line":"            try:"},{"line_number":661,"context_line":"                # hash suffix will give us a hash per fragment"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_fc01b605","line":658,"updated":"2015-03-06 21:28:39.000000000","message":"ok, so any invalidated suffix/fi means we rehash the whole thing - so maybe EC doesn\u0027t need to invalidate per FI?  Oh it doesn\u0027t - it sets all the values of the fi-\u003ehash dict to None... but we don\u0027t *know* what FI\u0027s we\u0027re going to find, should we just set the suffix to {}?","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"47b6452f50fe0654c3960f658bfd89dd6f474250","unresolved":false,"context_lines":[{"line_number":655,"context_line":""},{"line_number":656,"context_line":"    # loop through all suffixes needing hash recalc"},{"line_number":657,"context_line":"    for suffix, hash_dict in suffix_hashes.walk_items():"},{"line_number":658,"context_line":"        if any(h is None for h in hash_dict.values()):"},{"line_number":659,"context_line":"            suffix_dir \u003d join(partition_dir, suffix)"},{"line_number":660,"context_line":"            try:"},{"line_number":661,"context_line":"                # hash suffix will give us a hash per fragment"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_5e01ac68","line":658,"in_reply_to":"9a80dd14_fc01b605","updated":"2015-03-09 14:03:21.000000000","message":"hmmm....not sure if that would simplify things or not - possibly will have to think","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":672,"context_line":"                # can happen when 2 reconstructors race to fix/revert"},{"line_number":673,"context_line":"                # something, if the reconstruction happens first, the reverter"},{"line_number":674,"context_line":"                # won\u0027t copy/delete anything so will end up with an out of"},{"line_number":675,"context_line":"                # date suffix_hashes"},{"line_number":676,"context_line":"                suffix_hashes.cleanup(suffix)"},{"line_number":677,"context_line":"            except PathNotDir:"},{"line_number":678,"context_line":"                suffix_hashes.delete(suffix)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_dc46b24e","line":675,"updated":"2015-03-06 21:28:39.000000000","message":"oh that comment sounds complicated, I\u0027m quite sure I don\u0027t understand it - probably can\u0027t understand it in the context of this patch.  my gut is to trust Paul.","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"47b6452f50fe0654c3960f658bfd89dd6f474250","unresolved":false,"context_lines":[{"line_number":672,"context_line":"                # can happen when 2 reconstructors race to fix/revert"},{"line_number":673,"context_line":"                # something, if the reconstruction happens first, the reverter"},{"line_number":674,"context_line":"                # won\u0027t copy/delete anything so will end up with an out of"},{"line_number":675,"context_line":"                # date suffix_hashes"},{"line_number":676,"context_line":"                suffix_hashes.cleanup(suffix)"},{"line_number":677,"context_line":"            except PathNotDir:"},{"line_number":678,"context_line":"                suffix_hashes.delete(suffix)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_de483cb5","line":675,"in_reply_to":"9a80dd14_dc46b24e","updated":"2015-03-09 14:03:21.000000000","message":"yeah, this is another one that\u0027s best reviewed when we focus on the reconstructor. One of the many things that\u0027s different here between repl/recon is that a race, with repl, between one repl doing an update() and another doing update_deleted() is that it doesn\u0027t matter who wins.  It does with how the recon works with ssync.  There\u0027s likely a better way to do this but again lets look closer once this patch and its core functionality lands","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":682,"context_line":"    if modified:"},{"line_number":683,"context_line":"        with lock_path(partition_dir):"},{"line_number":684,"context_line":"            if suffix_hashes.file_error or not exists(hashes_file) or \\"},{"line_number":685,"context_line":"                    getmtime(hashes_file) \u003d\u003d suffix_hashes.mtime:"},{"line_number":686,"context_line":"                suffix_hashes.serialize(partition_dir)"},{"line_number":687,"context_line":"                return hashed, suffix_hashes"},{"line_number":688,"context_line":"        return get_hashes(partition_dir, policy_index, recalculate,"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_bc6ade7e","line":685,"updated":"2015-03-06 21:28:39.000000000","message":"oh goodness this is so implementation specific :\u0027(","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"47b6452f50fe0654c3960f658bfd89dd6f474250","unresolved":false,"context_lines":[{"line_number":682,"context_line":"    if modified:"},{"line_number":683,"context_line":"        with lock_path(partition_dir):"},{"line_number":684,"context_line":"            if suffix_hashes.file_error or not exists(hashes_file) or \\"},{"line_number":685,"context_line":"                    getmtime(hashes_file) \u003d\u003d suffix_hashes.mtime:"},{"line_number":686,"context_line":"                suffix_hashes.serialize(partition_dir)"},{"line_number":687,"context_line":"                return hashed, suffix_hashes"},{"line_number":688,"context_line":"        return get_hashes(partition_dir, policy_index, recalculate,"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_5eeb6c77","line":685,"in_reply_to":"9a80dd14_bc6ade7e","updated":"2015-03-09 14:03:21.000000000","message":"yeah, I pretty much lifted previous local flags into class properties, sorry not the best OO here","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":683,"context_line":"        with lock_path(partition_dir):"},{"line_number":684,"context_line":"            if suffix_hashes.file_error or not exists(hashes_file) or \\"},{"line_number":685,"context_line":"                    getmtime(hashes_file) \u003d\u003d suffix_hashes.mtime:"},{"line_number":686,"context_line":"                suffix_hashes.serialize(partition_dir)"},{"line_number":687,"context_line":"                return hashed, suffix_hashes"},{"line_number":688,"context_line":"        return get_hashes(partition_dir, policy_index, recalculate,"},{"line_number":689,"context_line":"                          do_listdir, reclaim_age)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_3c0eeee5","line":686,"updated":"2015-03-06 21:28:39.000000000","message":"bah - so suffix_hashes *also* knows how to build the hashes_file path\n\n/me cries","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"47b6452f50fe0654c3960f658bfd89dd6f474250","unresolved":false,"context_lines":[{"line_number":683,"context_line":"        with lock_path(partition_dir):"},{"line_number":684,"context_line":"            if suffix_hashes.file_error or not exists(hashes_file) or \\"},{"line_number":685,"context_line":"                    getmtime(hashes_file) \u003d\u003d suffix_hashes.mtime:"},{"line_number":686,"context_line":"                suffix_hashes.serialize(partition_dir)"},{"line_number":687,"context_line":"                return hashed, suffix_hashes"},{"line_number":688,"context_line":"        return get_hashes(partition_dir, policy_index, recalculate,"},{"line_number":689,"context_line":"                          do_listdir, reclaim_age)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_def67c5c","line":686,"in_reply_to":"9a80dd14_3c0eeee5","updated":"2015-03-09 14:03:21.000000000","message":"/me provides a box of tissues","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":923,"context_line":"            audit_location.partition)"},{"line_number":924,"context_line":""},{"line_number":925,"context_line":"    def get_diskfile_from_hash(self, device, partition, object_hash,"},{"line_number":926,"context_line":"                               policy_index, frag_index\u003dNone, **kwargs):"},{"line_number":927,"context_line":"        \"\"\""},{"line_number":928,"context_line":"        Returns a DiskFile instance for an object at the given"},{"line_number":929,"context_line":"        object_hash. Just in case someone thinks of refactoring, be"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_bc1e5eb9","line":926,"updated":"2015-03-06 21:28:39.000000000","message":"why does ssync_receiver need this but ssync_sender doesn\u0027t :\\","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"47b6452f50fe0654c3960f658bfd89dd6f474250","unresolved":false,"context_lines":[{"line_number":923,"context_line":"            audit_location.partition)"},{"line_number":924,"context_line":""},{"line_number":925,"context_line":"    def get_diskfile_from_hash(self, device, partition, object_hash,"},{"line_number":926,"context_line":"                               policy_index, frag_index\u003dNone, **kwargs):"},{"line_number":927,"context_line":"        \"\"\""},{"line_number":928,"context_line":"        Returns a DiskFile instance for an object at the given"},{"line_number":929,"context_line":"        object_hash. Just in case someone thinks of refactoring, be"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_7e8cb0da","line":926,"in_reply_to":"9a80dd14_bc1e5eb9","updated":"2015-03-09 14:03:21.000000000","message":"you\u0027ll see...","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":981,"context_line":"        _junk, hashes \u003d self.threadpools[device].force_run_in_thread("},{"line_number":982,"context_line":"            get_hashes, partition_path, policy_index, recalculate\u003dsuffixes)"},{"line_number":983,"context_line":"        # we don\u0027t pass around the full SuffixHashes class"},{"line_number":984,"context_line":"        return hashes.by_suffix"},{"line_number":985,"context_line":""},{"line_number":986,"context_line":"    def _listdir(self, path):"},{"line_number":987,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_bcfade40","line":984,"updated":"2015-03-06 21:28:39.000000000","message":"maybe we should just give the object server the data it wants already in the transmission format?  The replicator and reconstructor use the *other* get_hashes method.","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"47b6452f50fe0654c3960f658bfd89dd6f474250","unresolved":false,"context_lines":[{"line_number":981,"context_line":"        _junk, hashes \u003d self.threadpools[device].force_run_in_thread("},{"line_number":982,"context_line":"            get_hashes, partition_path, policy_index, recalculate\u003dsuffixes)"},{"line_number":983,"context_line":"        # we don\u0027t pass around the full SuffixHashes class"},{"line_number":984,"context_line":"        return hashes.by_suffix"},{"line_number":985,"context_line":""},{"line_number":986,"context_line":"    def _listdir(self, path):"},{"line_number":987,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_7e7af0bd","line":984,"in_reply_to":"9a80dd14_bcfade40","updated":"2015-03-09 14:03:21.000000000","message":"not sure I follow exactly what you\u0027re suggesting but I can only think of one other way to do this and I\u0027m OK with either...","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":1044,"context_line":"                object_path \u003d os.path.join(suffix_path, object_hash)"},{"line_number":1045,"context_line":"                for name in hash_cleanup_listdir(object_path,"},{"line_number":1046,"context_line":"                                                 policy_index,"},{"line_number":1047,"context_line":"                                                 self.reclaim_age):"},{"line_number":1048,"context_line":"                    ts, fi \u003d policy.fname_to_ts(name)"},{"line_number":1049,"context_line":"                    if fi \u003d\u003d trailing_filter:"},{"line_number":1050,"context_line":"                        # TODO: (acoles) does trailing filter include the #?"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_b76039d0","line":1047,"updated":"2015-03-06 21:28:39.000000000","message":"oh look, someone who was calling hash_cleanup_listdir with positional args!","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"47b6452f50fe0654c3960f658bfd89dd6f474250","unresolved":false,"context_lines":[{"line_number":1044,"context_line":"                object_path \u003d os.path.join(suffix_path, object_hash)"},{"line_number":1045,"context_line":"                for name in hash_cleanup_listdir(object_path,"},{"line_number":1046,"context_line":"                                                 policy_index,"},{"line_number":1047,"context_line":"                                                 self.reclaim_age):"},{"line_number":1048,"context_line":"                    ts, fi \u003d policy.fname_to_ts(name)"},{"line_number":1049,"context_line":"                    if fi \u003d\u003d trailing_filter:"},{"line_number":1050,"context_line":"                        # TODO: (acoles) does trailing filter include the #?"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_be80e88b","line":1047,"in_reply_to":"9a80dd14_b76039d0","updated":"2015-03-09 14:03:21.000000000","message":"ugh","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":1049,"context_line":"                    if fi \u003d\u003d trailing_filter:"},{"line_number":1050,"context_line":"                        # TODO: (acoles) does trailing filter include the #?"},{"line_number":1051,"context_line":"                        # TODO: (acoles) what about yielding ts and meta files?"},{"line_number":1052,"context_line":"                        yield (object_path, object_hash, ts)"},{"line_number":1053,"context_line":"                    else:"},{"line_number":1054,"context_line":"                        continue"},{"line_number":1055,"context_line":"                    break"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_57f7fdf4","line":1052,"updated":"2015-03-06 21:28:39.000000000","message":"so is ts here tombstone or timestamp?","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e2dd0a07da6c16953fde33687eef37bdfe48e931","unresolved":false,"context_lines":[{"line_number":1049,"context_line":"                    if fi \u003d\u003d trailing_filter:"},{"line_number":1050,"context_line":"                        # TODO: (acoles) does trailing filter include the #?"},{"line_number":1051,"context_line":"                        # TODO: (acoles) what about yielding ts and meta files?"},{"line_number":1052,"context_line":"                        yield (object_path, object_hash, ts)"},{"line_number":1053,"context_line":"                    else:"},{"line_number":1054,"context_line":"                        continue"},{"line_number":1055,"context_line":"                    break"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_c571560d","line":1052,"in_reply_to":"9a80dd14_57f7fdf4","updated":"2015-03-09 10:53:29.000000000","message":"in my TODO comment I meant tombstone. tombstone and meta files have no \u0027#frag_index\u0027 to match trailing_filter (correct?) so they won\u0027t be yielded :(\n\nwhat I\u0027d like to explore is (another) policy method to replace \n\n  if fi \u003d\u003d trailing_filter:\n\nwith\n\n  if policy.matches_frag_index(name, fi)\n\nor maybe better, pass frag_index to hash_cleanup_listdir and have it return a filtered set of remaining files.","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":1147,"context_line":"        # drop_cache() after fsync() to avoid redundant work (pages all"},{"line_number":1148,"context_line":"        # clean)."},{"line_number":1149,"context_line":"        drop_buffer_cache(self._fd, 0, self._upload_size)"},{"line_number":1150,"context_line":"        invalidate_hash(dirname(self._datadir), self._diskfile.policy.idx)"},{"line_number":1151,"context_line":"        # After the rename completes, this object will be available for other"},{"line_number":1152,"context_line":"        # requests to reference."},{"line_number":1153,"context_line":"        renamer(self._tmppath, target_path)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_1c0ccaa4","line":1150,"updated":"2015-03-06 21:28:39.000000000","message":"I may be the only one on the planet who feels this way - but I prefer\n\n    int(self._diskfile.policy)","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"a07b78853da6ba9c732478b1bfbde65a4367862e","unresolved":false,"context_lines":[{"line_number":1147,"context_line":"        # drop_cache() after fsync() to avoid redundant work (pages all"},{"line_number":1148,"context_line":"        # clean)."},{"line_number":1149,"context_line":"        drop_buffer_cache(self._fd, 0, self._upload_size)"},{"line_number":1150,"context_line":"        invalidate_hash(dirname(self._datadir), self._diskfile.policy.idx)"},{"line_number":1151,"context_line":"        # After the rename completes, this object will be available for other"},{"line_number":1152,"context_line":"        # requests to reference."},{"line_number":1153,"context_line":"        renamer(self._tmppath, target_path)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_4523a6a6","line":1150,"in_reply_to":"9a80dd14_1c0ccaa4","updated":"2015-03-09 10:14:49.000000000","message":"+1","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e2dd0a07da6c16953fde33687eef37bdfe48e931","unresolved":false,"context_lines":[{"line_number":1147,"context_line":"        # drop_cache() after fsync() to avoid redundant work (pages all"},{"line_number":1148,"context_line":"        # clean)."},{"line_number":1149,"context_line":"        drop_buffer_cache(self._fd, 0, self._upload_size)"},{"line_number":1150,"context_line":"        invalidate_hash(dirname(self._datadir), self._diskfile.policy.idx)"},{"line_number":1151,"context_line":"        # After the rename completes, this object will be available for other"},{"line_number":1152,"context_line":"        # requests to reference."},{"line_number":1153,"context_line":"        renamer(self._tmppath, target_path)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_256dd204","line":1150,"in_reply_to":"9a80dd14_1c0ccaa4","updated":"2015-03-09 10:53:29.000000000","message":"Putting on my python beginners hat again for a moment, why that preference? For me, policy.idx tells me immediately that its referring to the index, whereas int(policy) might require me to go look at the policy implementation to see what __int__ returns.  Just asking, not picking a fight :)","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d69e1e2cae2c2a48a2a0412e5dda59cc81fd6a38","unresolved":false,"context_lines":[{"line_number":1147,"context_line":"        # drop_cache() after fsync() to avoid redundant work (pages all"},{"line_number":1148,"context_line":"        # clean)."},{"line_number":1149,"context_line":"        drop_buffer_cache(self._fd, 0, self._upload_size)"},{"line_number":1150,"context_line":"        invalidate_hash(dirname(self._datadir), self._diskfile.policy.idx)"},{"line_number":1151,"context_line":"        # After the rename completes, this object will be available for other"},{"line_number":1152,"context_line":"        # requests to reference."},{"line_number":1153,"context_line":"        renamer(self._tmppath, target_path)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_35523c67","line":1150,"in_reply_to":"9a80dd14_256dd204","updated":"2015-03-10 06:08:43.000000000","message":"Yeah, I think it\u0027s a fairly trivial stylistic thing.  But since you asked, here\u0027s my experience/justification/line-of-thinking (also not picking any fight!)\n\n1) It\u0027d be incredibly bad form if int(something) returned *anything* that wasn\u0027t an int - you can go look it up to see *which* int it\u0027s returning, but once you grok that we often represent policies by just their index it\u0027s as easy as anything to read int(policy) as the policy index.  OTOH some random attribute - I have no idea what that is, especially when you consider @property - I might get lucky and find self.idx \u003d int(something) and then at least I know it\u0027s an int - could probably guess idx is a short form for index.  If I search for def __int__ I know I\u0027ll get a hit - and there\u0027s even a doc anchor point since we\u0027re exposing this as part of the api [1]\n\n2) because python lacks private attributes and discourages getters/setters - it\u0027s not uncommon for some attribute on an object to be part of it\u0027s public interface - BUT that doesn\u0027t mean it doesn\u0027t sucks from a encapsulation standpoint.  a) I don\u0027t care for the attribute name \"idx\" being part of the public interface, renaming to index helps, but policy.index is a bit longer than int(policy) b) I don\u0027t think most places we reach into the policy to grab that attribute really even *want* that attribute access to index as part of the interface (god help us if some random test rewriting attributes on the global StoragePolicy instances) - what they *want* is the integer representation of the StroagePolicy class that they have in hand.\n\nand that\u0027s why I like int(policy) - because it can reasonably mean only one thing:\n\n   give me the integer representation of this policy\n\nI think it\u0027s less ambiguous in the long run, but maybe surprising at first glance - \"Did someone really go define a double-und int on this thing?! ... Oh, I guess they did... a\u0027ight that\u0027s cool.\"\n\n1. I should probably put some of this on the docstring for StoragePolicy.__int__","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":1178,"context_line":"            self._extension,"},{"line_number":1179,"context_line":"            frag_index\u003dfi)"},{"line_number":1180,"context_line":"        metadata[\u0027name\u0027] \u003d self._name"},{"line_number":1181,"context_line":"        target_path \u003d join(self._datadir, filename)"},{"line_number":1182,"context_line":"        self._threadpool.force_run_in_thread("},{"line_number":1183,"context_line":"            self._finalize_put, metadata, target_path)"},{"line_number":1184,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_77c6c19b","line":1181,"updated":"2015-03-06 21:28:39.000000000","message":"thanks!","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":1524,"context_line":"        self._bytes_per_sync \u003d mgr.bytes_per_sync"},{"line_number":1525,"context_line":"        self._use_splice \u003d use_splice"},{"line_number":1526,"context_line":"        self._pipe_size \u003d pipe_size"},{"line_number":1527,"context_line":"        self.policy \u003d POLICIES.get_by_index(policy_index)"},{"line_number":1528,"context_line":"        self._frag_index \u003d int(frag_index) if frag_index is not None else None"},{"line_number":1529,"context_line":"        if account and container and obj:"},{"line_number":1530,"context_line":"            self._name \u003d \u0027/\u0027 + \u0027/\u0027.join((account, container, obj))"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_77224153","line":1527,"updated":"2015-03-06 21:28:39.000000000","message":"I keep worrying about if \n\n   self.policy \u003d None\n\nis cool?","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":1525,"context_line":"        self._use_splice \u003d use_splice"},{"line_number":1526,"context_line":"        self._pipe_size \u003d pipe_size"},{"line_number":1527,"context_line":"        self.policy \u003d POLICIES.get_by_index(policy_index)"},{"line_number":1528,"context_line":"        self._frag_index \u003d int(frag_index) if frag_index is not None else None"},{"line_number":1529,"context_line":"        if account and container and obj:"},{"line_number":1530,"context_line":"            self._name \u003d \u0027/\u0027 + \u0027/\u0027.join((account, container, obj))"},{"line_number":1531,"context_line":"            self._account \u003d account"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_37b3690b","line":1528,"updated":"2015-03-06 21:28:39.000000000","message":"I\u0027m guessing POLICIES does something where it doesn\u0027t care if policy_index is a string or an int - and frag_index and it both come in as strings normally from headers in the object server and are then coverted to int\u0027s here...","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"47b6452f50fe0654c3960f658bfd89dd6f474250","unresolved":false,"context_lines":[{"line_number":1525,"context_line":"        self._use_splice \u003d use_splice"},{"line_number":1526,"context_line":"        self._pipe_size \u003d pipe_size"},{"line_number":1527,"context_line":"        self.policy \u003d POLICIES.get_by_index(policy_index)"},{"line_number":1528,"context_line":"        self._frag_index \u003d int(frag_index) if frag_index is not None else None"},{"line_number":1529,"context_line":"        if account and container and obj:"},{"line_number":1530,"context_line":"            self._name \u003d \u0027/\u0027 + \u0027/\u0027.join((account, container, obj))"},{"line_number":1531,"context_line":"            self._account \u003d account"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_5e3e0cdb","line":1528,"in_reply_to":"9a80dd14_37b3690b","updated":"2015-03-09 14:03:21.000000000","message":"would have to go review again but we did bottom out on int vs string wrt policy_index (I though) but frag_index is likely not consistently treated and could be a good candidate for a one pass cleanup once the complicated stuff is done","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fcc8e5305bb591708142c079168d870182c028e6","unresolved":false,"context_lines":[{"line_number":136,"context_line":"                self.by_suffix \u003d pickle.load(fp)"},{"line_number":137,"context_line":"            self.mtime \u003d getmtime(hashes_file)"},{"line_number":138,"context_line":"        except Exception:"},{"line_number":139,"context_line":"            self.file_error \u003d True"},{"line_number":140,"context_line":""},{"line_number":141,"context_line":"    def walk_items(self):"},{"line_number":142,"context_line":"        for suff, hash in self.by_suffix.items():"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_78cf9b56","line":139,"updated":"2015-03-13 04:29:51.000000000","message":"This _deserialize method can be moved into the parent SuffixHashes Class.","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fcc8e5305bb591708142c079168d870182c028e6","unresolved":false,"context_lines":[{"line_number":152,"context_line":"            self.by_suffix[suffix] \u003d hash"},{"line_number":153,"context_line":""},{"line_number":154,"context_line":"    def delete(self, suffix):"},{"line_number":155,"context_line":"        del self.by_suffix[suffix]"},{"line_number":156,"context_line":""},{"line_number":157,"context_line":"    def cleanup(self, suffix):"},{"line_number":158,"context_line":"        pass"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_580d773d","line":155,"updated":"2015-03-13 04:29:51.000000000","message":"This also can be moved to the parent class (if we want to keep implementation down).","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fcc8e5305bb591708142c079168d870182c028e6","unresolved":false,"context_lines":[{"line_number":155,"context_line":"        del self.by_suffix[suffix]"},{"line_number":156,"context_line":""},{"line_number":157,"context_line":"    def cleanup(self, suffix):"},{"line_number":158,"context_line":"        pass"},{"line_number":159,"context_line":""},{"line_number":160,"context_line":"    def invalidate(self, suffix):"},{"line_number":161,"context_line":"        changed \u003d False"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_6342903f","line":158,"updated":"2015-03-13 04:29:51.000000000","message":"If this _must_ be initiated by all subclasses, can we just make this the default implementation in the parent class?","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fcc8e5305bb591708142c079168d870182c028e6","unresolved":false,"context_lines":[{"line_number":200,"context_line":"            self.mtime \u003d getmtime(hashes_file)"},{"line_number":201,"context_line":"        except Exception:"},{"line_number":202,"context_line":"            self.file_error \u003d True"},{"line_number":203,"context_line":"        self._by_frag_index \u003d {}"},{"line_number":204,"context_line":""},{"line_number":205,"context_line":"    def walk_items(self):"},{"line_number":206,"context_line":"        return self.by_suffix.items()"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_180a1f79","line":203,"updated":"2015-03-13 04:29:51.000000000","message":"This is almost identical to the _deserialize class in repl so if that is moved to the parent class (SuffixHashes) then this can be:\n\n  def _deserialize(self, hashes_file):\n      super(SuffixHashesEC, self)._deserialize(hashes_file)\n      self._by_frag_index \u003d {}","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fcc8e5305bb591708142c079168d870182c028e6","unresolved":false,"context_lines":[{"line_number":236,"context_line":"                self.by_suffix[suffix].update({frag_index: hash})"},{"line_number":237,"context_line":"            else:"},{"line_number":238,"context_line":"                raise BadSuffixHashesAdd()"},{"line_number":239,"context_line":"        self._by_frag_index \u003d {}"},{"line_number":240,"context_line":""},{"line_number":241,"context_line":"    def delete(self, suffix):"},{"line_number":242,"context_line":"        del self.by_suffix[suffix]"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_785cfb4b","line":239,"updated":"2015-03-13 04:29:51.000000000","message":"To keep the add method signature order the same in both sub-classes hash should be defined before frag_index:\n\n  def add(self, suffix, hash\u003dNone, frag_index\u003d\u0027unknown\u0027)\n\nThat way, if someone ever has a SuffixHashes class and uses the method form:\n\n  suffixhashes.add(my_suffix, my_hash)\n\nIt will work no matter what subclass it happens to be.","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fcc8e5305bb591708142c079168d870182c028e6","unresolved":false,"context_lines":[{"line_number":240,"context_line":""},{"line_number":241,"context_line":"    def delete(self, suffix):"},{"line_number":242,"context_line":"        del self.by_suffix[suffix]"},{"line_number":243,"context_line":"        self._by_frag_index \u003d {}"},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"    def cleanup(self, suffix):"},{"line_number":246,"context_line":"        sub_dict \u003d self.by_suffix[suffix].copy()"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_633b70d1","line":243,"updated":"2015-03-13 04:29:51.000000000","message":"This could become:\n\n  super(SuffixHashesEC, self).delete(suffix)\n  self._by_frag_index \u003d {}","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fcc8e5305bb591708142c079168d870182c028e6","unresolved":false,"context_lines":[{"line_number":279,"context_line":""},{"line_number":280,"context_line":"def _get_suffix_hashes(policy, hashes_file):"},{"line_number":281,"context_line":"    \"\"\""},{"line_number":282,"context_line":"    Helper function to resturn the correct instantation of a"},{"line_number":283,"context_line":"    SuffixHashes class based on policy index."},{"line_number":284,"context_line":""},{"line_number":285,"context_line":"    :param policy: the StoragePolicy instance"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_a35f280e","line":282,"updated":"2015-03-13 04:29:51.000000000","message":"s/resturn/return/","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fcc8e5305bb591708142c079168d870182c028e6","unresolved":false,"context_lines":[{"line_number":467,"context_line":"                t_durable \u003d splitext(basename(durable_file))[0]"},{"line_number":468,"context_line":"                if t_data !\u003d t_durable:"},{"line_number":469,"context_line":"                    # this and remaining data files are older than durable"},{"line_number":470,"context_line":"                    break"},{"line_number":471,"context_line":"                if frag_index is not None and frag_index !\u003d int(fi):"},{"line_number":472,"context_line":"                    # for EC we keep searching first for a .data file that"},{"line_number":473,"context_line":"                    # matches the specific frag_index requested by the caller"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_83706473","line":470,"updated":"2015-03-13 04:29:51.000000000","message":"Is this a case for is_obsolete method you just added to SP classes?","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5b7d482cf2345f1607fcb45cf1911ef092171685","unresolved":false,"context_lines":[{"line_number":467,"context_line":"                t_durable \u003d splitext(basename(durable_file))[0]"},{"line_number":468,"context_line":"                if t_data !\u003d t_durable:"},{"line_number":469,"context_line":"                    # this and remaining data files are older than durable"},{"line_number":470,"context_line":"                    break"},{"line_number":471,"context_line":"                if frag_index is not None and frag_index !\u003d int(fi):"},{"line_number":472,"context_line":"                    # for EC we keep searching first for a .data file that"},{"line_number":473,"context_line":"                    # matches the specific frag_index requested by the caller"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_fb8a3763","line":470,"in_reply_to":"9a80dd14_7c8a26c0","updated":"2015-03-16 18:09:42.000000000","message":"Done. Changed to use is_obsolete in version 16","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"eba1e8c275f719b9a41951958b79b7a12d3a990f","unresolved":false,"context_lines":[{"line_number":467,"context_line":"                t_durable \u003d splitext(basename(durable_file))[0]"},{"line_number":468,"context_line":"                if t_data !\u003d t_durable:"},{"line_number":469,"context_line":"                    # this and remaining data files are older than durable"},{"line_number":470,"context_line":"                    break"},{"line_number":471,"context_line":"                if frag_index is not None and frag_index !\u003d int(fi):"},{"line_number":472,"context_line":"                    # for EC we keep searching first for a .data file that"},{"line_number":473,"context_line":"                    # matches the specific frag_index requested by the caller"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_7c8a26c0","line":470,"in_reply_to":"9a80dd14_83706473","updated":"2015-03-13 09:28:12.000000000","message":"Good spot. It is and I nearly used that but here I also needed the fname so just went for explicitly splitting and comparing the strings. \n\nI hope to rework this into per-policy diskfile classes where it should all get cleaner so will leave as is for now.","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fcc8e5305bb591708142c079168d870182c028e6","unresolved":false,"context_lines":[{"line_number":468,"context_line":"                if t_data !\u003d t_durable:"},{"line_number":469,"context_line":"                    # this and remaining data files are older than durable"},{"line_number":470,"context_line":"                    break"},{"line_number":471,"context_line":"                if frag_index is not None and frag_index !\u003d int(fi):"},{"line_number":472,"context_line":"                    # for EC we keep searching first for a .data file that"},{"line_number":473,"context_line":"                    # matches the specific frag_index requested by the caller"},{"line_number":474,"context_line":"                    continue"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_83f784d2","line":471,"updated":"2015-03-13 04:29:51.000000000","message":"I\u0027m sure it\u0027s probably fine, but do we have to be careful of a ValueError here when using int()?","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"eba1e8c275f719b9a41951958b79b7a12d3a990f","unresolved":false,"context_lines":[{"line_number":468,"context_line":"                if t_data !\u003d t_durable:"},{"line_number":469,"context_line":"                    # this and remaining data files are older than durable"},{"line_number":470,"context_line":"                    break"},{"line_number":471,"context_line":"                if frag_index is not None and frag_index !\u003d int(fi):"},{"line_number":472,"context_line":"                    # for EC we keep searching first for a .data file that"},{"line_number":473,"context_line":"                    # matches the specific frag_index requested by the caller"},{"line_number":474,"context_line":"                    continue"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_d745ad43","line":471,"in_reply_to":"9a80dd14_83f784d2","updated":"2015-03-13 09:28:12.000000000","message":"Oh man I guess that the fname_to_ts abstract method only contracts to return a string so yeah, it *could* somehow not be a str(int) :/ if something screwed up the frag index filename suffix and we had a \u00271234567890.00000#banana.data\u0027 file\n\nCan I invoke the same stalling tactic - that this will most likely be cleaned up by per-policy diskfile where I intend to move fname_to_ts into the diskfile class?","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5b7d482cf2345f1607fcb45cf1911ef092171685","unresolved":false,"context_lines":[{"line_number":468,"context_line":"                if t_data !\u003d t_durable:"},{"line_number":469,"context_line":"                    # this and remaining data files are older than durable"},{"line_number":470,"context_line":"                    break"},{"line_number":471,"context_line":"                if frag_index is not None and frag_index !\u003d int(fi):"},{"line_number":472,"context_line":"                    # for EC we keep searching first for a .data file that"},{"line_number":473,"context_line":"                    # matches the specific frag_index requested by the caller"},{"line_number":474,"context_line":"                    continue"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_5b3fc387","line":471,"in_reply_to":"9a80dd14_d745ad43","updated":"2015-03-16 18:09:42.000000000","message":"Done added a try/except in version 16 and a test for when there is a non-int frag index part in a file name.","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fcc8e5305bb591708142c079168d870182c028e6","unresolved":false,"context_lines":[{"line_number":671,"context_line":"                    suffix_hashes.add(suffix, frag_index\u003dfi, hash\u003dhashes)"},{"line_number":672,"context_line":"                hashed +\u003d 1"},{"line_number":673,"context_line":"                # now that we have a current view of suffixes, fi\u0027s and hashes"},{"line_number":674,"context_line":"                # perform any cleanup that needed - for EC this would mean"},{"line_number":675,"context_line":"                # killing any fi entries that still have None for a hash which"},{"line_number":676,"context_line":"                # can happen when 2 reconstructors race to fix/revert"},{"line_number":677,"context_line":"                # something, if the reconstruction happens first, the reverter"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_23fc1872","line":674,"updated":"2015-03-13 04:29:51.000000000","message":"s/that/that\u0027s/","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fcc8e5305bb591708142c079168d870182c028e6","unresolved":false,"context_lines":[{"line_number":1048,"context_line":"                                                 reclaim_age\u003dself.reclaim_age):"},{"line_number":1049,"context_line":"                    ts, fi \u003d policy.fname_to_ts(name)"},{"line_number":1050,"context_line":"                    if fi \u003d\u003d trailing_filter:"},{"line_number":1051,"context_line":"                        # TODO: (acoles) does trailing filter include the #?"},{"line_number":1052,"context_line":"                        # TODO: (acoles) what about yielding ts and meta files?"},{"line_number":1053,"context_line":"                        yield (object_path, object_hash, ts)"},{"line_number":1054,"context_line":"                    else:"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_c31a5cc5","line":1051,"updated":"2015-03-13 04:29:51.000000000","message":"The fi returned by repl StoragePolicy fname_to_ts, simply returns an empty string, according to the the EC policy it splits on # so no it isn\u0027t included.","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"eba1e8c275f719b9a41951958b79b7a12d3a990f","unresolved":false,"context_lines":[{"line_number":1048,"context_line":"                                                 reclaim_age\u003dself.reclaim_age):"},{"line_number":1049,"context_line":"                    ts, fi \u003d policy.fname_to_ts(name)"},{"line_number":1050,"context_line":"                    if fi \u003d\u003d trailing_filter:"},{"line_number":1051,"context_line":"                        # TODO: (acoles) does trailing filter include the #?"},{"line_number":1052,"context_line":"                        # TODO: (acoles) what about yielding ts and meta files?"},{"line_number":1053,"context_line":"                        yield (object_path, object_hash, ts)"},{"line_number":1054,"context_line":"                    else:"}],"source_content_type":"text/x-python","patch_set":10,"id":"9a80dd14_f738f1a1","line":1051,"in_reply_to":"9a80dd14_c31a5cc5","updated":"2015-03-13 09:28:12.000000000","message":"Yep. I *think* what was bothering me was not being able to find where yield_hashes got called with a trailing_filter arg, and what value that arg might take - but things are changing all around so I made a not to come back and check. I actually wonder if \u0027trailing_filter\u0027 should be \u0027frag_index\u0027 to make it clearer.\n\nAgain, roll-on per-policy diskfiles ;)\n\nMy bigger concern is the next TODO - this would seem to filter out the meta and ts files that will *not* have a trailing frag index.\n\nPS OH I remember - in previous version the matching was something like \n\n  if filename.endswith(trailing_filter) \n\nwhich implied to me that the # must be in the trailing_filter, but now I don\u0027t want it to be, so I need to find the caller(s) and figure out what they are doing!","commit_id":"3b1547291d0dafee2dc56ff302123acf63a581b1"},{"author":{"_account_id":9625,"name":"Thiago da Silva","email":"thiagodasilva@gmail.com","username":"thiago"},"change_message_id":"d98e9600277283528ba431bc816f6b35f50cfc25","unresolved":false,"context_lines":[{"line_number":533,"context_line":"    elif files:"},{"line_number":534,"context_line":"        files.sort(reverse\u003dTrue)"},{"line_number":535,"context_line":"        data_file, meta_file, ts_file, durable_file \u003d \\"},{"line_number":536,"context_line":"            get_ondisk_files(files, \u0027\u0027, policy)"},{"line_number":537,"context_line":"        newest_file \u003d durable_file or data_file or ts_file"},{"line_number":538,"context_line":"        if newest_file:"},{"line_number":539,"context_line":"            for filename in list(files):"}],"source_content_type":"text/x-python","patch_set":16,"id":"9a80dd14_7b3e47dc","line":536,"updated":"2015-03-16 19:03:34.000000000","message":"isn\u0027t the frag_index needed here? is it possible you might clean up .data files you want to keep around?","commit_id":"450eb0e2b5b8de04e8ed5181057cad6f2cc13621"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1679435abfeb525963b42a381c8620c295409ccc","unresolved":false,"context_lines":[{"line_number":533,"context_line":"    elif files:"},{"line_number":534,"context_line":"        files.sort(reverse\u003dTrue)"},{"line_number":535,"context_line":"        data_file, meta_file, ts_file, durable_file \u003d \\"},{"line_number":536,"context_line":"            get_ondisk_files(files, \u0027\u0027, policy)"},{"line_number":537,"context_line":"        newest_file \u003d durable_file or data_file or ts_file"},{"line_number":538,"context_line":"        if newest_file:"},{"line_number":539,"context_line":"            for filename in list(files):"}],"source_content_type":"text/x-python","patch_set":16,"id":"9a80dd14_386671ef","line":536,"in_reply_to":"9a80dd14_7b3e47dc","updated":"2015-03-17 11:15:49.000000000","message":"No, in this context, get_ondisk_files is being used to retrieve the current \u0027validating\u0027\u0027 file (either a .data for replication or a .durable for ec).\n\nThen each file is compared against the validating file to decide if it should be removed. For EC, *no* data file with same time as .durable will be removed - see the call to policy.is_obsolete at line 540.","commit_id":"450eb0e2b5b8de04e8ed5181057cad6f2cc13621"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"05c6e6e4a29dcf1ebbbcb3b3c3b9438afb50bd34","unresolved":false,"context_lines":[{"line_number":119,"context_line":"        write_pickle("},{"line_number":120,"context_line":"            self.by_suffix, self.hashes_file, partition_dir, PICKLE_PROTOCOL)"},{"line_number":121,"context_line":"        self.file_error \u003d False"},{"line_number":122,"context_line":""},{"line_number":123,"context_line":""},{"line_number":124,"context_line":"# for SuffixHashesRepl, we just have a simple dict:"},{"line_number":125,"context_line":"# {\u0027suff1\u0027: hash1, \u0027suff2\u0027: hash2, \u0027suff3\u0027:hash3}"}],"source_content_type":"text/x-python","patch_set":17,"id":"9a80dd14_6070f4dc","line":122,"updated":"2015-03-18 13:33:59.000000000","message":"I would like to see the other required methods implemented as abstract methods as well (add/delete/walk_items/cleanup/invalidate seem to be required at least). And then raise a NotImplementedError in this base class (we already do this in some other classes) for these methods.\nThis makes it more clean and will (hopefully) simplify future development a little bit.","commit_id":"1345e85440cd25a860aabed6c7d8fec071365645"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ea4d64bd2e1f1bc2c5438d377b123b8a6d19e7fd","unresolved":false,"context_lines":[{"line_number":139,"context_line":"            self.file_error \u003d True"},{"line_number":140,"context_line":""},{"line_number":141,"context_line":"    def walk_items(self):"},{"line_number":142,"context_line":"        for suff, hash in self.by_suffix.items():"},{"line_number":143,"context_line":"            yield suff, {None: hash}"},{"line_number":144,"context_line":""},{"line_number":145,"context_line":"    def __repr__(self):"}],"source_content_type":"text/x-python","patch_set":17,"id":"9a80dd14_4554b953","line":142,"updated":"2015-03-19 07:31:56.000000000","message":"This might be a nitpick but we should use iteritems() instead of items() to decrease the overhead of the translation to list, IMHO.\n\nitems() appeared 5 time-sh in the following code.","commit_id":"1345e85440cd25a860aabed6c7d8fec071365645"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"ea4d64bd2e1f1bc2c5438d377b123b8a6d19e7fd","unresolved":false,"context_lines":[{"line_number":203,"context_line":"        self._by_frag_index \u003d {}"},{"line_number":204,"context_line":""},{"line_number":205,"context_line":"    def walk_items(self):"},{"line_number":206,"context_line":"        return self.by_suffix.items()"},{"line_number":207,"context_line":""},{"line_number":208,"context_line":"    def build_by_frag_index(self):"},{"line_number":209,"context_line":"        # build the so we have by_frag_index based on by_suffix,"}],"source_content_type":"text/x-python","patch_set":17,"id":"9a80dd14_69419738","line":206,"updated":"2015-03-19 07:31:56.000000000","message":"To return a generator instance as well as SuffixHashesRepl.walk_item, let\u0027s use iteritems() :-)","commit_id":"1345e85440cd25a860aabed6c7d8fec071365645"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"e9e2c109f4a4d42a4c788a771e1030f7a37c23e0","unresolved":false,"context_lines":[{"line_number":1816,"context_line":"    def _make_ondisk_file_name(self, metadata):"},{"line_number":1817,"context_line":"        # generally we treat the fragment index provided in metadata as canon,"},{"line_number":1818,"context_line":"        # but if it\u0027s unavailable (e.g. tests) it\u0027s reasonable to use the"},{"line_number":1819,"context_line":"        # frag_index provided at instantiation."},{"line_number":1820,"context_line":"        fi \u003d metadata.get(\u0027X-Object-Sysmeta-Ec-Archive-Index\u0027,"},{"line_number":1821,"context_line":"                          self._diskfile._frag_index)"},{"line_number":1822,"context_line":"        timestamp \u003d Timestamp(metadata[\u0027X-Timestamp\u0027]).internal"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a6ced46_a08aa7bc","line":1819,"updated":"2015-03-26 11:50:19.000000000","message":"Note that the frag_index provided at instantiation might be assigned as None.","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"42ab81e04884f24833f3ddc743b60c6d247cdb01","unresolved":false,"context_lines":[{"line_number":1816,"context_line":"    def _make_ondisk_file_name(self, metadata):"},{"line_number":1817,"context_line":"        # generally we treat the fragment index provided in metadata as canon,"},{"line_number":1818,"context_line":"        # but if it\u0027s unavailable (e.g. tests) it\u0027s reasonable to use the"},{"line_number":1819,"context_line":"        # frag_index provided at instantiation."},{"line_number":1820,"context_line":"        fi \u003d metadata.get(\u0027X-Object-Sysmeta-Ec-Archive-Index\u0027,"},{"line_number":1821,"context_line":"                          self._diskfile._frag_index)"},{"line_number":1822,"context_line":"        timestamp \u003d Timestamp(metadata[\u0027X-Timestamp\u0027]).internal"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa963961_d1570ec9","line":1819,"in_reply_to":"1a6ced46_a08aa7bc","updated":"2015-03-26 15:10:07.000000000","message":":( \n\nGreat spot, but I think we should address in a separate patch because if we raise an error when frag_index is None we will break a lot of tests, so all those tests need to be fixed too and I would really like to not see that churn on this patch.","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"980ceab6e535381e1d3afaaf66b159aafb781217","unresolved":false,"context_lines":[{"line_number":1816,"context_line":"    def _make_ondisk_file_name(self, metadata):"},{"line_number":1817,"context_line":"        # generally we treat the fragment index provided in metadata as canon,"},{"line_number":1818,"context_line":"        # but if it\u0027s unavailable (e.g. tests) it\u0027s reasonable to use the"},{"line_number":1819,"context_line":"        # frag_index provided at instantiation."},{"line_number":1820,"context_line":"        fi \u003d metadata.get(\u0027X-Object-Sysmeta-Ec-Archive-Index\u0027,"},{"line_number":1821,"context_line":"                          self._diskfile._frag_index)"},{"line_number":1822,"context_line":"        timestamp \u003d Timestamp(metadata[\u0027X-Timestamp\u0027]).internal"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa963961_b7ad898a","line":1819,"in_reply_to":"fa963961_d1570ec9","updated":"2015-03-27 01:00:09.000000000","message":"yes this needs to be address but it\u0027s a separate code quality issue and not directly related to this feature which is very needed to make progress on EC.","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"a86863bca3f3250ea2bb2779acda8360e847b783","unresolved":false,"context_lines":[{"line_number":2157,"context_line":"        The only difference with this method and the module level function"},{"line_number":2158,"context_line":"        get_hashes is the call to hash_suffix routes to a method _hash_suffix"},{"line_number":2159,"context_line":"        on this instance."},{"line_number":2160,"context_line":"        \"\"\""},{"line_number":2161,"context_line":"        reclaim_age \u003d reclaim_age or self.reclaim_age"},{"line_number":2162,"context_line":"        hashed \u003d 0"},{"line_number":2163,"context_line":"        hashes_file \u003d join(partition_path, HASH_FILE)"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa963961_e2c006e3","line":2160,"updated":"2015-03-26 13:36:49.000000000","message":"This much duplication of code (duplicating an entire method to call one different method) rubs me the wrong way. There must be a better way. Such as passing in hash_suffix callable (say as hash_suffix_fn) to the module level get_hashes. Something roughly like: http://paste.openstack.org/show/196870/\n\nNote, the diff i just an idea, it hasn\u0027t been debugged.\n\nOr even some super/subclassing fu.","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"980ceab6e535381e1d3afaaf66b159aafb781217","unresolved":false,"context_lines":[{"line_number":2157,"context_line":"        The only difference with this method and the module level function"},{"line_number":2158,"context_line":"        get_hashes is the call to hash_suffix routes to a method _hash_suffix"},{"line_number":2159,"context_line":"        on this instance."},{"line_number":2160,"context_line":"        \"\"\""},{"line_number":2161,"context_line":"        reclaim_age \u003d reclaim_age or self.reclaim_age"},{"line_number":2162,"context_line":"        hashed \u003d 0"},{"line_number":2163,"context_line":"        hashes_file \u003d join(partition_path, HASH_FILE)"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa963961_f789d1cb","line":2160,"in_reply_to":"fa963961_e2c006e3","updated":"2015-03-27 01:00:09.000000000","message":"The right way to do it is to move this method to the BaseDiskFile and attach the module level hash_suffix to the ReplicatedDiskFile implementation.\n\nThen get rid of this and the module level function.\n\nBut that\u0027s just refactoring and DRYing stuff out - it\u0027s just one simple example of many changes that could make it easier to maintain both implementations in the long run.  But that\u0027s not what this patch is for.\n\nThis change is to validate that we can have two separate implementations without changing the replicated diskfile - and specifically to isolate and highlight where behavior\u0027s would need to deviate and what common implementation could be shared - and to develop the test infrastructure to support the inevitable and obvious refactoring.\n\nI hope it\u0027ll make sense when we see the diff\u0027s to master next week.  There\u0027s an assumption that it will be easier to review EC additions without also having to review a bunch of refactoring of the base replicated implementation - but if lots of people are put off by the duplicated code we may have to adjust our plan.","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"8e3cb820d3618a4be6f6a5e7038b8be238f408ed","unresolved":false,"context_lines":[{"line_number":2109,"context_line":"        None (indicating a durable, metadata or tombstone)."},{"line_number":2110,"context_line":"        \"\"\""},{"line_number":2111,"context_line":"        # hash_per_fi instead of single hash for whole suffix"},{"line_number":2112,"context_line":"        hash_per_fi \u003d defaultdict(hashlib.md5)"},{"line_number":2113,"context_line":"        try:"},{"line_number":2114,"context_line":"            path_contents \u003d sorted(os.listdir(path))"},{"line_number":2115,"context_line":"        except OSError as err:"}],"source_content_type":"text/x-python","patch_set":28,"id":"fa963961_78dda541","line":2112,"updated":"2015-03-27 10:20:54.000000000","message":"Nice trick!","commit_id":"296afe756c639749616b09802fb4caf54bf2c844"}],"swift/obj/replicator.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":315,"context_line":"            suffixes \u003d [suffix for suffix in suff_hash1 if"},{"line_number":316,"context_line":"                        suff_hash1[suffix] !\u003d"},{"line_number":317,"context_line":"                        suff_hash2.get(suffix, -1)]"},{"line_number":318,"context_line":"            return suffixes"},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"        self.replication_count +\u003d 1"},{"line_number":321,"context_line":"        self.logger.increment(\u0027partition.update.count.%s\u0027 % (job[\u0027device\u0027],))"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_1de3bcd9","line":318,"updated":"2015-03-04 03:40:36.000000000","message":"I feel like this just might be a method on the SuffixHashesRepl class - if for nothing else but to make it easier to test the behavior.\n\n    suffixes_to_sync \u003d local_hash.suffix_delta(remote_hash)","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":361,"context_line":"                            continue"},{"line_number":362,"context_line":"                        remote_hash \u003d \\"},{"line_number":363,"context_line":"                            SuffixHashesRepl(hashes_dict\u003d"},{"line_number":364,"context_line":"                                             pickle.loads(resp.read()))"},{"line_number":365,"context_line":"                        del resp"},{"line_number":366,"context_line":"                    suffixes \u003d get_suffix_delta(local_hash.by_suffix,"},{"line_number":367,"context_line":"                                                remote_hash.by_suffix)"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_40254b5a","line":364,"updated":"2015-03-04 03:40:36.000000000","message":"I think the serialization format is exactly the kind of implementation detail you want to hide in the... implementation of SuffixHashesRepl","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"}],"swift/obj/server.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":184,"context_line":"        \"\"\""},{"line_number":185,"context_line":"        return self._diskfile_mgr.get_diskfile("},{"line_number":186,"context_line":"            device, partition, account, container, obj, policy_index,"},{"line_number":187,"context_line":"            frag_index, **kwargs)"},{"line_number":188,"context_line":""},{"line_number":189,"context_line":"    def async_update(self, op, account, container, obj, host, partition,"},{"line_number":190,"context_line":"                     contdevice, headers_out, objdevice, policy_index):"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_67dfc93a","line":187,"updated":"2015-03-04 03:40:36.000000000","message":"In retrospect I think *this* might be place to lookup the policy_index in the in the collection and hand the manager a real policy instance instead of just the index.","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"ea4b9861245b554cd0841f6547b9800189c18d68","unresolved":false,"context_lines":[{"line_number":184,"context_line":"        \"\"\""},{"line_number":185,"context_line":"        return self._diskfile_mgr.get_diskfile("},{"line_number":186,"context_line":"            device, partition, account, container, obj, policy_index,"},{"line_number":187,"context_line":"            frag_index, **kwargs)"},{"line_number":188,"context_line":""},{"line_number":189,"context_line":"    def async_update(self, op, account, container, obj, host, partition,"},{"line_number":190,"context_line":"                     contdevice, headers_out, objdevice, policy_index):"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_acdf270c","line":187,"in_reply_to":"9a80dd14_3f1d8dbe","updated":"2015-03-06 17:33:05.000000000","message":"I made DiskFile() init resolve its policy_index arg to a policy and use that internally.\n\nStill agree with this comment but felt like too much code churn right now.","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5e9b16111a5d928ea76909dc6f73653b92b3422c","unresolved":false,"context_lines":[{"line_number":184,"context_line":"        \"\"\""},{"line_number":185,"context_line":"        return self._diskfile_mgr.get_diskfile("},{"line_number":186,"context_line":"            device, partition, account, container, obj, policy_index,"},{"line_number":187,"context_line":"            frag_index, **kwargs)"},{"line_number":188,"context_line":""},{"line_number":189,"context_line":"    def async_update(self, op, account, container, obj, host, partition,"},{"line_number":190,"context_line":"                     contdevice, headers_out, objdevice, policy_index):"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_3f1d8dbe","line":187,"in_reply_to":"ba7be1f8_67dfc93a","updated":"2015-03-04 15:25:14.000000000","message":"+1","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":490,"context_line":"            # (we won\u0027t know it until we get the trailer anyways)"},{"line_number":491,"context_line":"            disk_file \u003d self.get_diskfile("},{"line_number":492,"context_line":"                device, partition, account, container, obj,"},{"line_number":493,"context_line":"                policy_index\u003dpolicy_index, frag_index\u003dNone)"},{"line_number":494,"context_line":"        except DiskFileDeviceUnavailable:"},{"line_number":495,"context_line":"            return HTTPInsufficientStorage(drive\u003ddevice, request\u003drequest)"},{"line_number":496,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_07152d9b","line":493,"updated":"2015-03-04 03:40:36.000000000","message":"hrmm... I\u0027m not sure I follow why the proxy couldn\u0027t send it along in the intial headers before the expect-100 response - i don\u0027t think it\u0027s going to change it\u0027s mind about which node gets which FI.\n\nIn Kinetic I don\u0027t have atomic rename, so not getting the timestamp until after I had to write all the bytes turned out to be sort of a PITA - I think the FI is going to end up being the same deal.\n\nhttps://review.openstack.org/#/c/117359/1/swift/obj/diskfile.py,unified\n\n^ what I was wanting was to get timestamp added to create","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":676,"context_line":"        try:"},{"line_number":677,"context_line":"            disk_file \u003d self.get_diskfile("},{"line_number":678,"context_line":"                device, partition, account, container, obj,"},{"line_number":679,"context_line":"                policy_index\u003dpolicy_index, frag_index\u003dnode_index)"},{"line_number":680,"context_line":"        except DiskFileDeviceUnavailable:"},{"line_number":681,"context_line":"            return HTTPInsufficientStorage(drive\u003ddevice, request\u003drequest)"},{"line_number":682,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_a7c70144","line":679,"updated":"2015-03-04 03:40:36.000000000","message":"I\u0027m dubious of the object-server api calling this argument X-Backend-Node-Index and the DiskFile api calling it frag_index.\n\nIn this case we should pick a name, and Node-Index seems generic enough, might even make sense to add it get_name_and_placement.\n\nIn the future with per storage policy object controllers we may find that we want X-Backend-DiskFile-* to get plumbed in as arguments to get_diskfile.","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":184,"context_line":"        \"\"\""},{"line_number":185,"context_line":"        return self._diskfile_mgr.get_diskfile("},{"line_number":186,"context_line":"            device, partition, account, container, obj, policy_index,"},{"line_number":187,"context_line":"            frag_index, **kwargs)"},{"line_number":188,"context_line":""},{"line_number":189,"context_line":"    def async_update(self, op, account, container, obj, host, partition,"},{"line_number":190,"context_line":"                     contdevice, headers_out, objdevice, policy_index):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_d7676db5","line":187,"updated":"2015-03-06 21:28:39.000000000","message":"oh godness... I wonder if we need to keep policy_idx for legacy compat :\\","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"47b6452f50fe0654c3960f658bfd89dd6f474250","unresolved":false,"context_lines":[{"line_number":184,"context_line":"        \"\"\""},{"line_number":185,"context_line":"        return self._diskfile_mgr.get_diskfile("},{"line_number":186,"context_line":"            device, partition, account, container, obj, policy_index,"},{"line_number":187,"context_line":"            frag_index, **kwargs)"},{"line_number":188,"context_line":""},{"line_number":189,"context_line":"    def async_update(self, op, account, container, obj, host, partition,"},{"line_number":190,"context_line":"                     contdevice, headers_out, objdevice, policy_index):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_9e0a4424","line":187,"in_reply_to":"9a80dd14_d7676db5","updated":"2015-03-09 14:03:21.000000000","message":"argh","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"}],"swift/obj/ssync_receiver.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":172,"context_line":"        self.policy_idx \u003d \\"},{"line_number":173,"context_line":"            int(self.request.headers.get(\u0027X-Backend-Storage-Policy-Index\u0027, 0))"},{"line_number":174,"context_line":"        self.frag_index \u003d \\"},{"line_number":175,"context_line":"            int(self.request.headers.get(\u0027X-Backend-Ssync-Frag-Index\u0027))"},{"line_number":176,"context_line":"        utils.validate_device_partition(self.device, self.partition)"},{"line_number":177,"context_line":"        if self.app._diskfile_mgr.mount_check and \\"},{"line_number":178,"context_line":"                not constraints.check_mount("}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_00a433b8","line":175,"updated":"2015-03-04 03:40:36.000000000","message":"why not X-Backend-Node-Index or X-Object-Sysmeta-Ec-Fragment-Index","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5e9b16111a5d928ea76909dc6f73653b92b3422c","unresolved":false,"context_lines":[{"line_number":235,"context_line":"            # the sender\u0027s file.  We care about the FI that we\u0027re responsible"},{"line_number":236,"context_line":"            # for..."},{"line_number":237,"context_line":"            timestamp, fragment_index_ \u003d \\"},{"line_number":238,"context_line":"                POLICIES.get_by_index(self.policy_idx).fname_to_ts(timestamp)"},{"line_number":239,"context_line":"            want \u003d False"},{"line_number":240,"context_line":"            try:"},{"line_number":241,"context_line":"                df \u003d self.app._diskfile_mgr.get_diskfile_from_hash("}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_42698a8a","line":238,"updated":"2015-03-04 15:25:14.000000000","message":"Since fragment_index is not used by receiver can we just not send it? That would save on adding a bunch of tests to verify that the line above does its job.\n\n(I admit this is also a self-serving suggestion as it could simplify fast-post changes to timestamp read from the ssync_sender)","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":171,"context_line":"        self.policy_idx \u003d \\"},{"line_number":172,"context_line":"            int(self.request.headers.get(\u0027X-Backend-Storage-Policy-Index\u0027, 0))"},{"line_number":173,"context_line":"        self.frag_index \u003d \\"},{"line_number":174,"context_line":"            int(self.request.headers.get(\u0027X-Backend-Ssync-Frag-Index\u0027))"},{"line_number":175,"context_line":"        utils.validate_device_partition(self.device, self.partition)"},{"line_number":176,"context_line":"        if self.app._diskfile_mgr.mount_check and \\"},{"line_number":177,"context_line":"                not constraints.check_mount("}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_173905f3","line":174,"updated":"2015-03-06 21:28:39.000000000","message":"yeah probably need to default to None or something - otherwise this is a 500 during rolling upgrade :\\","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"47b6452f50fe0654c3960f658bfd89dd6f474250","unresolved":false,"context_lines":[{"line_number":171,"context_line":"        self.policy_idx \u003d \\"},{"line_number":172,"context_line":"            int(self.request.headers.get(\u0027X-Backend-Storage-Policy-Index\u0027, 0))"},{"line_number":173,"context_line":"        self.frag_index \u003d \\"},{"line_number":174,"context_line":"            int(self.request.headers.get(\u0027X-Backend-Ssync-Frag-Index\u0027))"},{"line_number":175,"context_line":"        utils.validate_device_partition(self.device, self.partition)"},{"line_number":176,"context_line":"        if self.app._diskfile_mgr.mount_check and \\"},{"line_number":177,"context_line":"                not constraints.check_mount("}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_610c153c","line":174,"in_reply_to":"9a80dd14_173905f3","updated":"2015-03-09 14:03:21.000000000","message":"yeah, I mention the rolling upgrade TODO on the reconstructor patch","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"}],"swift/obj/ssync_sender.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":48,"context_line":""},{"line_number":49,"context_line":"    @property"},{"line_number":50,"context_line":"    def policy_idx(self):"},{"line_number":51,"context_line":"        return int(self.job.get(\u0027policy_idx\u0027, 0))"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":"    def __call__(self):"},{"line_number":54,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_367a5d88","side":"PARENT","line":51,"updated":"2015-03-04 03:40:36.000000000","message":"old code never had to deal with self.job not being a dictionary - what\u0027s going on?","commit_id":"dabf47c0bb6a500c0499163ba800af1f474a68bd"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":266,"context_line":"                try:"},{"line_number":267,"context_line":"                    df \u003d self.daemon._diskfile_mgr.get_diskfile_from_hash("},{"line_number":268,"context_line":"                        self.job[\u0027device\u0027], self.job[\u0027partition\u0027], object_hash,"},{"line_number":269,"context_line":"                        self.policy_idx)"},{"line_number":270,"context_line":"                except exceptions.DiskFileNotExist:"},{"line_number":271,"context_line":"                    continue"},{"line_number":272,"context_line":"                url_path \u003d urllib.quote("}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_b7c2f931","side":"PARENT","line":269,"updated":"2015-03-06 21:28:39.000000000","message":"ok, so sender *is* going to use the fragment index for EC","commit_id":"dabf47c0bb6a500c0499163ba800af1f474a68bd"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"47b6452f50fe0654c3960f658bfd89dd6f474250","unresolved":false,"context_lines":[{"line_number":266,"context_line":"                try:"},{"line_number":267,"context_line":"                    df \u003d self.daemon._diskfile_mgr.get_diskfile_from_hash("},{"line_number":268,"context_line":"                        self.job[\u0027device\u0027], self.job[\u0027partition\u0027], object_hash,"},{"line_number":269,"context_line":"                        self.policy_idx)"},{"line_number":270,"context_line":"                except exceptions.DiskFileNotExist:"},{"line_number":271,"context_line":"                    continue"},{"line_number":272,"context_line":"                url_path \u003d urllib.quote("}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_a138cdd3","side":"PARENT","line":269,"in_reply_to":"9a80dd14_b7c2f931","updated":"2015-03-09 14:03:21.000000000","message":"yessir","commit_id":"dabf47c0bb6a500c0499163ba800af1f474a68bd"}],"swift/proxy/controllers/base.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":784,"context_line":"            # Replication doesn\u0027t really care about this but EC uses"},{"line_number":785,"context_line":"            # it to figure out which of potentially multiple fragment"},{"line_number":786,"context_line":"            # archive index values are available at the storage node"},{"line_number":787,"context_line":"            self.backend_headers[\u0027X-Backend-Node-Index\u0027] \u003d node[\u0027index\u0027]"},{"line_number":788,"context_line":"            try:"},{"line_number":789,"context_line":"                with ConnectionTimeout(self.app.conn_timeout):"},{"line_number":790,"context_line":"                    conn \u003d http_connect("}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_96d06920","line":787,"updated":"2015-03-04 03:40:36.000000000","message":"it\u0027s weird to be updating this shared state with a per request option for me somehow...  GetOrHeadHandler has never had a concept of a per node request header like put and make_requests do...\n\nI forget how things came down on the concurrent GET path, but I\u0027d guess you need to:\n\n    headers \u003d self.backend_headers.copy()\n\nbefore you call http_connect or by the time it goes to put them on the wire they may be different.","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":1035,"context_line":"        :param path: the path to send to the backend"},{"line_number":1036,"context_line":"                     (full path ends up being /\u003c$device\u003e/\u003c$part\u003e/\u003c$path\u003e)"},{"line_number":1037,"context_line":"        :param headers: a list of dicts, where each dict represents one"},{"line_number":1038,"context_line":"                        backend request that should be made."},{"line_number":1039,"context_line":"        :param query: query string to send to the backend."},{"line_number":1040,"context_line":"        :param logger_thread_locals: The thread local values to be set on the"},{"line_number":1041,"context_line":"                                     self.app.logger to retain transaction"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_360b3dd7","line":1038,"updated":"2015-03-04 03:40:36.000000000","message":"this doc string is wrong - it\u0027s correct for make_request from which it\u0027s duplicated, but here in _make_request it\u0027s just a plain old dict","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"eaf2fb12202235d51c24b6a47497d411e2b0897a","unresolved":false,"context_lines":[{"line_number":1048,"context_line":"            # it to figure out which of potentially multiple fragment"},{"line_number":1049,"context_line":"            # archive index values are available at the storage node"},{"line_number":1050,"context_line":"            if headers:"},{"line_number":1051,"context_line":"                headers[\u0027X-Backend-Node-Index\u0027] \u003d node[\u0027index\u0027]"},{"line_number":1052,"context_line":"            try:"},{"line_number":1053,"context_line":"                start_node_timing \u003d time.time()"},{"line_number":1054,"context_line":"                with ConnectionTimeout(self.app.conn_timeout):"}],"source_content_type":"text/x-python","patch_set":4,"id":"ba7be1f8_f66fe55d","line":1051,"updated":"2015-03-04 03:40:36.000000000","message":"is this branch to catch when headers is None or is this some sort of behavior we want when the headers are empty?\n\nDoes this really even matter for POST/DELETE?  who else uses make_requests?","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"}],"test/unit/obj/test_diskfile.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5e9b16111a5d928ea76909dc6f73653b92b3422c","unresolved":false,"context_lines":[{"line_number":1036,"context_line":"            file_list \u003d [file1, file2]"},{"line_number":1037,"context_line":"            expected \u003d [file2]"},{"line_number":1038,"context_line":"            if policy.policy_type \u003d\u003d EC_POLICY:"},{"line_number":1039,"context_line":"                file3 \u003d ts + \u0027.durable\u0027"},{"line_number":1040,"context_line":"                file_list.append(file3)"},{"line_number":1041,"context_line":"                expected \u003d [file3, file2]"},{"line_number":1042,"context_line":"            self.check_hash_cleanup_listdir(file_list, policy.idx, expected)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_ff08552f","line":1039,"updated":"2015-03-04 15:25:14.000000000","message":"add more frag indexes at same timestamp to be sure that they are all retained","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5e9b16111a5d928ea76909dc6f73653b92b3422c","unresolved":false,"context_lines":[{"line_number":1066,"context_line":"            self.check_hash_cleanup_listdir(file_list, policy.idx, [file3])"},{"line_number":1067,"context_line":""},{"line_number":1068,"context_line":"    def test_hash_cleanup_listdir_keep_one_data(self):"},{"line_number":1069,"context_line":"        # keep only latest of multiple .data files"},{"line_number":1070,"context_line":"        for policy in POLICIES:"},{"line_number":1071,"context_line":"            file1 \u003d policy.ts_to_fname(Timestamp(time()).internal, 0) + \u0027.data\u0027"},{"line_number":1072,"context_line":"            file2 \u003d (policy.ts_to_fname(Timestamp(time() + 1).internal, 0)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_421a6a6f","line":1069,"updated":"2015-03-04 15:25:14.000000000","message":"comment not true with EC","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5e9b16111a5d928ea76909dc6f73653b92b3422c","unresolved":false,"context_lines":[{"line_number":1076,"context_line":"            file_list \u003d [file1, file2, file3]"},{"line_number":1077,"context_line":"            expected \u003d [file3]"},{"line_number":1078,"context_line":"            if policy.policy_type \u003d\u003d EC_POLICY:"},{"line_number":1079,"context_line":"                file4 \u003d ts + \u0027.durable\u0027"},{"line_number":1080,"context_line":"                file_list.append(file4)"},{"line_number":1081,"context_line":"                expected \u003d [file4, file3]"},{"line_number":1082,"context_line":"            self.check_hash_cleanup_listdir(file_list, policy.idx, expected)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_62268ebc","line":1079,"updated":"2015-03-04 15:25:14.000000000","message":"add multiple frag index data files, test they are all retained","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5e9b16111a5d928ea76909dc6f73653b92b3422c","unresolved":false,"context_lines":[{"line_number":1224,"context_line":"                      (\u00270000000006.00000.meta\u0027, False),"},{"line_number":1225,"context_line":"                      (\u00270000000004.00000.ts\u0027, False)],"},{"line_number":1226,"context_line":""},{"line_number":1227,"context_line":"                     # meta without data is ignored"},{"line_number":1228,"context_line":"                     [(\u00270000000007.00000.meta\u0027, False),"},{"line_number":1229,"context_line":"                      (\u00270000000006.00000.ts\u0027, \u0027.ts\u0027),"},{"line_number":1230,"context_line":"                      (\u00270000000004.00000.data\u0027, False)],"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_e2aefee6","line":1227,"updated":"2015-03-04 15:25:14.000000000","message":"correct for REPL","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5e9b16111a5d928ea76909dc6f73653b92b3422c","unresolved":false,"context_lines":[{"line_number":1290,"context_line":"                      (\u00270000000006.00000.meta\u0027, False),"},{"line_number":1291,"context_line":"                      (\u00270000000004.00000.ts\u0027, False)],"},{"line_number":1292,"context_line":""},{"line_number":1293,"context_line":"                     # meta without matching data included with older durable"},{"line_number":1294,"context_line":"                     [(\u00270000000007.00000.meta\u0027, \u0027.meta\u0027),"},{"line_number":1295,"context_line":"                      (\u00270000000004.00000.durable\u0027, \u0027.durable\u0027),"},{"line_number":1296,"context_line":"                      (\u00270000000003.00000#0.data\u0027, False)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_a26ec6c7","line":1293,"updated":"2015-03-04 15:25:14.000000000","message":"question whether this should pass","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"5e9b16111a5d928ea76909dc6f73653b92b3422c","unresolved":false,"context_lines":[{"line_number":1352,"context_line":"                      (\u00270000000007.00000#0.data\u0027, False),"},{"line_number":1353,"context_line":"                      (\u00270000000007.00000.durable\u0027, \u0027.durable\u0027)],"},{"line_number":1354,"context_line":""},{"line_number":1355,"context_line":"                     # meta file returned even if specific frag index missing"},{"line_number":1356,"context_line":"                     [(\u00270000000008.00000.meta\u0027, \u0027.meta\u0027),"},{"line_number":1357,"context_line":"                      (\u00270000000007.00000#14.data\u0027, False),"},{"line_number":1358,"context_line":"                      (\u00270000000007.00000#0.data\u0027, False),"}],"source_content_type":"text/x-python","patch_set":4,"id":"9a80dd14_a2a5e605","line":1355,"updated":"2015-03-04 15:25:14.000000000","message":"question whether this should pass (meta with no data)","commit_id":"4e1e4c16e281f3755a68325baf9ef31fb3a777a7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d2496835e53bfe6b6e12e7fc70407f55a5809992","unresolved":false,"context_lines":[{"line_number":190,"context_line":"            self.assertRaises(OSError, diskfile.quarantine_renamer,"},{"line_number":191,"context_line":"                              self.devices, qbit)"},{"line_number":192,"context_line":""},{"line_number":193,"context_line":"    def test_hash_suffix_enoent(self):"},{"line_number":194,"context_line":"        self.assertRaises(PathNotDir, diskfile.hash_suffix,"},{"line_number":195,"context_line":"                          os.path.join(self.testdir, \"doesnotexist\"), 101)"},{"line_number":196,"context_line":""}],"source_content_type":"text/x-python","patch_set":25,"id":"1a6ced46_fc0f0d86","side":"PARENT","line":193,"updated":"2015-03-25 17:39:08.000000000","message":"see test_hash_suffix_listdir_enoent","commit_id":"d14245e17c1b9ea5e8ac49383d4f049725b08798"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d2496835e53bfe6b6e12e7fc70407f55a5809992","unresolved":false,"context_lines":[{"line_number":194,"context_line":"        self.assertRaises(PathNotDir, diskfile.hash_suffix,"},{"line_number":195,"context_line":"                          os.path.join(self.testdir, \"doesnotexist\"), 101)"},{"line_number":196,"context_line":""},{"line_number":197,"context_line":"    def test_hash_suffix_oserror(self):"},{"line_number":198,"context_line":"        mocked_os_listdir \u003d mock.Mock("},{"line_number":199,"context_line":"            side_effect\u003dOSError(errno.EACCES, os.strerror(errno.EACCES)))"},{"line_number":200,"context_line":"        with mock.patch(\"os.listdir\", mocked_os_listdir):"}],"source_content_type":"text/x-python","patch_set":25,"id":"1a6ced46_fc01cd6a","side":"PARENT","line":197,"updated":"2015-03-25 17:39:08.000000000","message":"see test_hash_suffix_hash_cleanup_listdir_other_oserror","commit_id":"d14245e17c1b9ea5e8ac49383d4f049725b08798"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d2496835e53bfe6b6e12e7fc70407f55a5809992","unresolved":false,"context_lines":[{"line_number":970,"context_line":"        locations \u003d list(self.df_mgr.object_audit_location_generator())"},{"line_number":971,"context_line":"        self.assertEqual(locations, [])"},{"line_number":972,"context_line":""},{"line_number":973,"context_line":"    def test_get_hashes_bad_dev(self):"},{"line_number":974,"context_line":"        self.df_mgr.mount_check \u003d True"},{"line_number":975,"context_line":"        with mock.patch(\u0027swift.obj.diskfile.check_mount\u0027,"},{"line_number":976,"context_line":"                        mock.MagicMock(side_effect\u003d[False])):"}],"source_content_type":"text/x-python","patch_set":25,"id":"1a6ced46_dc8171c4","side":"PARENT","line":973,"updated":"2015-03-25 17:39:08.000000000","message":"moved to line 4064","commit_id":"d14245e17c1b9ea5e8ac49383d4f049725b08798"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d2496835e53bfe6b6e12e7fc70407f55a5809992","unresolved":false,"context_lines":[{"line_number":978,"context_line":"                              self.df_mgr.get_hashes, \u0027sdb1\u0027, \u00270\u0027, \u0027123\u0027,"},{"line_number":979,"context_line":"                              \u0027objects\u0027)"},{"line_number":980,"context_line":""},{"line_number":981,"context_line":"    def test_get_hashes_w_nothing(self):"},{"line_number":982,"context_line":"        hashes \u003d self.df_mgr.get_hashes(self.existing_device1, \u00270\u0027, \u0027123\u0027, \u00270\u0027)"},{"line_number":983,"context_line":"        self.assertEqual(hashes, {})"},{"line_number":984,"context_line":"        # get_hashes creates the partition path, so call again for code"}],"source_content_type":"text/x-python","patch_set":25,"id":"1a6ced46_3c88c5c4","side":"PARENT","line":981,"updated":"2015-03-25 17:39:08.000000000","message":"where did this test go ?","commit_id":"d14245e17c1b9ea5e8ac49383d4f049725b08798"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2f710cd41904acc246730729de55b3b926581aab","unresolved":false,"context_lines":[{"line_number":248,"context_line":"            # check tempdir"},{"line_number":249,"context_line":"            self.assertTrue(os.path.isdir(tmp_path))"},{"line_number":250,"context_line":""},{"line_number":251,"context_line":"    def test_hash_suffix_hash_dir_is_file_quarantine(self):"},{"line_number":252,"context_line":"        df \u003d self._create_diskfile(POLICIES.legacy)"},{"line_number":253,"context_line":"        mkdirs(os.path.dirname(df._datadir))"},{"line_number":254,"context_line":"        open(df._datadir, \u0027wb\u0027).close()"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_26b42bd0","side":"PARENT","line":251,"updated":"2015-03-25 17:37:24.000000000","message":"see test_hash_suffix_hash_cleanup_listdir_enotdir_quarantined","commit_id":"0bad452c2f9db477574737b72de036569807960a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2f710cd41904acc246730729de55b3b926581aab","unresolved":false,"context_lines":[{"line_number":269,"context_line":"            diskfile.quarantine_renamer \u003d orig_quarantine_renamer"},{"line_number":270,"context_line":"        self.assertTrue(called[0])"},{"line_number":271,"context_line":""},{"line_number":272,"context_line":"    def test_hash_suffix_one_file(self):"},{"line_number":273,"context_line":"        df \u003d self._create_diskfile(POLICIES.legacy)"},{"line_number":274,"context_line":"        mkdirs(df._datadir)"},{"line_number":275,"context_line":"        f \u003d open("}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_a57570fb","side":"PARENT","line":272,"updated":"2015-03-25 17:37:24.000000000","message":"ding: this tests that reclaim_age is passed through hash_suffix to HCL, I cannot see a replacement and making this change http://paste.openstack.org/show/196674/ does not cause a test_diskfile.py failure","commit_id":"0bad452c2f9db477574737b72de036569807960a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2f710cd41904acc246730729de55b3b926581aab","unresolved":false,"context_lines":[{"line_number":287,"context_line":"        diskfile.hash_suffix(whole_path_from, 99)"},{"line_number":288,"context_line":"        self.assertEquals(len(os.listdir(self.parts[\u00270\u0027])), 0)"},{"line_number":289,"context_line":""},{"line_number":290,"context_line":"    def test_hash_suffix_oserror_on_hcl(self):"},{"line_number":291,"context_line":"        df \u003d self._create_diskfile(POLICIES.legacy)"},{"line_number":292,"context_line":"        mkdirs(df._datadir)"},{"line_number":293,"context_line":"        f \u003d open("}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_855dd449","side":"PARENT","line":290,"updated":"2015-03-25 17:37:24.000000000","message":"covered by test_hash_suffix_hash_cleanup_listdir_other_oserror","commit_id":"0bad452c2f9db477574737b72de036569807960a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2f710cd41904acc246730729de55b3b926581aab","unresolved":false,"context_lines":[{"line_number":316,"context_line":"            self.assertRaises(OSError, diskfile.hash_suffix, whole_path_from,"},{"line_number":317,"context_line":"                              101)"},{"line_number":318,"context_line":""},{"line_number":319,"context_line":"    def test_hash_suffix_multi_file_one(self):"},{"line_number":320,"context_line":"        df \u003d self._create_diskfile(POLICIES.legacy)"},{"line_number":321,"context_line":"        mkdirs(df._datadir)"},{"line_number":322,"context_line":"        for tdiff in [1, 50, 100, 500]:"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_a818e51e","side":"PARENT","line":319,"updated":"2015-03-25 17:37:24.000000000","message":"covered by test_hash_suffix_multi_file_ends_in_tombstone","commit_id":"0bad452c2f9db477574737b72de036569807960a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2f710cd41904acc246730729de55b3b926581aab","unresolved":false,"context_lines":[{"line_number":339,"context_line":"        # only the tombstone should be left"},{"line_number":340,"context_line":"        self.assertEquals(len(os.listdir(whole_hsh_path)), 1)"},{"line_number":341,"context_line":""},{"line_number":342,"context_line":"    def test_hash_suffix_multi_file_two(self):"},{"line_number":343,"context_line":"        df \u003d self._create_diskfile(POLICIES.legacy)"},{"line_number":344,"context_line":"        mkdirs(df._datadir)"},{"line_number":345,"context_line":"        for tdiff in [1, 50, 100, 500]:"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_c8d601f1","side":"PARENT","line":342,"updated":"2015-03-25 17:37:24.000000000","message":"covered by test_hash_suffix_multi_file_ends_in_datafile","commit_id":"0bad452c2f9db477574737b72de036569807960a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2e7c514f0c010647c8d5243148b13fd6bf183b86","unresolved":false,"context_lines":[{"line_number":365,"context_line":"        # only the meta and data should be left"},{"line_number":366,"context_line":"        self.assertEquals(len(os.listdir(whole_hsh_path)), 2)"},{"line_number":367,"context_line":""},{"line_number":368,"context_line":"    def test_hash_suffix_hsh_path_disappearance(self):"},{"line_number":369,"context_line":"        orig_rmdir \u003d os.rmdir"},{"line_number":370,"context_line":""},{"line_number":371,"context_line":"        def _rmdir(path):"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_19e789ad","side":"PARENT","line":368,"updated":"2015-03-25 18:30:38.000000000","message":"see test_hash_suffix_rmdir_suffix_oserror","commit_id":"0bad452c2f9db477574737b72de036569807960a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2e7c514f0c010647c8d5243148b13fd6bf183b86","unresolved":false,"context_lines":[{"line_number":384,"context_line":"            # this test will fail."},{"line_number":385,"context_line":"            diskfile.hash_suffix(suffix_path, 123)"},{"line_number":386,"context_line":""},{"line_number":387,"context_line":"    def test_invalidate_hash(self):"},{"line_number":388,"context_line":""},{"line_number":389,"context_line":"        def assertFileData(file_path, data):"},{"line_number":390,"context_line":"            with open(file_path, \u0027r\u0027) as fp:"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_b953d537","side":"PARENT","line":387,"updated":"2015-03-25 18:30:38.000000000","message":"see test_invalidate_hash_file_does_not_exist\nand test_invalidate_hash_file_exists","commit_id":"0bad452c2f9db477574737b72de036569807960a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2e7c514f0c010647c8d5243148b13fd6bf183b86","unresolved":false,"context_lines":[{"line_number":410,"context_line":"            diskfile.invalidate_hash(whole_path_from)"},{"line_number":411,"context_line":"            assertFileData(hashes_file, check_pickle_data)"},{"line_number":412,"context_line":""},{"line_number":413,"context_line":"    def test_invalidate_hash_bad_pickle(self):"},{"line_number":414,"context_line":"        df \u003d self._create_diskfile(POLICIES.legacy)"},{"line_number":415,"context_line":"        mkdirs(df._datadir)"},{"line_number":416,"context_line":"        ohash \u003d hash_path(\u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_7924fdc4","side":"PARENT","line":413,"updated":"2015-03-25 18:30:38.000000000","message":"see test_invalidate_hash_bad_pickle","commit_id":"0bad452c2f9db477574737b72de036569807960a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2e7c514f0c010647c8d5243148b13fd6bf183b86","unresolved":false,"context_lines":[{"line_number":428,"context_line":"            else:"},{"line_number":429,"context_line":"                pass"},{"line_number":430,"context_line":""},{"line_number":431,"context_line":"    def test_get_hashes(self):"},{"line_number":432,"context_line":"        df \u003d self._create_diskfile(POLICIES.legacy)"},{"line_number":433,"context_line":"        mkdirs(df._datadir)"},{"line_number":434,"context_line":"        with open("}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_b49afc6b","side":"PARENT","line":431,"updated":"2015-03-25 18:30:38.000000000","message":"guess this is covered by test_get_hashes_multi_file_multi_suffix?","commit_id":"0bad452c2f9db477574737b72de036569807960a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2e7c514f0c010647c8d5243148b13fd6bf183b86","unresolved":false,"context_lines":[{"line_number":447,"context_line":"        self.assertEquals(hashed, 1)"},{"line_number":448,"context_line":"        self.assert_(\u0027a83\u0027 in hashes)"},{"line_number":449,"context_line":""},{"line_number":450,"context_line":"    def test_get_hashes_bad_dir(self):"},{"line_number":451,"context_line":"        df \u003d self._create_diskfile(POLICIES.legacy)"},{"line_number":452,"context_line":"        mkdirs(df._datadir)"},{"line_number":453,"context_line":"        with open(os.path.join(self.objects, \u00270\u0027, \u0027bad\u0027), \u0027wb\u0027) as f:"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_546aa8b3","side":"PARENT","line":450,"updated":"2015-03-25 18:30:38.000000000","message":"see test_get_hashes_hash_suffix_enotdir","commit_id":"0bad452c2f9db477574737b72de036569807960a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2e7c514f0c010647c8d5243148b13fd6bf183b86","unresolved":false,"context_lines":[{"line_number":458,"context_line":"        self.assert_(\u0027a83\u0027 in hashes)"},{"line_number":459,"context_line":"        self.assert_(\u0027bad\u0027 not in hashes)"},{"line_number":460,"context_line":""},{"line_number":461,"context_line":"    def test_get_hashes_unmodified(self):"},{"line_number":462,"context_line":"        df \u003d self._create_diskfile(POLICIES.legacy)"},{"line_number":463,"context_line":"        mkdirs(df._datadir)"},{"line_number":464,"context_line":"        with open("}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_94bc2008","side":"PARENT","line":461,"updated":"2015-03-25 18:30:38.000000000","message":"see  test_get_hashes_modified_recursive_retry","commit_id":"0bad452c2f9db477574737b72de036569807960a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2e7c514f0c010647c8d5243148b13fd6bf183b86","unresolved":false,"context_lines":[{"line_number":478,"context_line":"                part, recalculate\u003d[\u0027a83\u0027])"},{"line_number":479,"context_line":"        self.assertEquals(i[0], 2)"},{"line_number":480,"context_line":""},{"line_number":481,"context_line":"    def test_get_hashes_unmodified_norecalc(self):"},{"line_number":482,"context_line":"        df \u003d self._create_diskfile(POLICIES.legacy)"},{"line_number":483,"context_line":"        mkdirs(df._datadir)"},{"line_number":484,"context_line":"        with open("}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_f43e348b","side":"PARENT","line":481,"updated":"2015-03-25 18:30:38.000000000","message":"see  test_get_hashes_modified_recursive_retry","commit_id":"0bad452c2f9db477574737b72de036569807960a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2e7c514f0c010647c8d5243148b13fd6bf183b86","unresolved":false,"context_lines":[{"line_number":495,"context_line":"        self.assertTrue(\u0027a83\u0027 in hashes_0)"},{"line_number":496,"context_line":"        self.assertEqual(hashes_1, hashes_0)"},{"line_number":497,"context_line":""},{"line_number":498,"context_line":"    def test_get_hashes_hash_suffix_error(self):"},{"line_number":499,"context_line":"        df \u003d self._create_diskfile(POLICIES.legacy)"},{"line_number":500,"context_line":"        mkdirs(df._datadir)"},{"line_number":501,"context_line":"        with open("}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_d46058a7","side":"PARENT","line":498,"updated":"2015-03-25 18:30:38.000000000","message":"see test_get_hashes_hash_suffix_other_oserror","commit_id":"0bad452c2f9db477574737b72de036569807960a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2e7c514f0c010647c8d5243148b13fd6bf183b86","unresolved":false,"context_lines":[{"line_number":511,"context_line":"            self.assertEqual(hashed, 0)"},{"line_number":512,"context_line":"            self.assertEqual(hashes, {\u0027a83\u0027: None})"},{"line_number":513,"context_line":""},{"line_number":514,"context_line":"    def test_get_hashes_unmodified_and_zero_bytes(self):"},{"line_number":515,"context_line":"        df \u003d self._create_diskfile(POLICIES.legacy)"},{"line_number":516,"context_line":"        mkdirs(df._datadir)"},{"line_number":517,"context_line":"        part \u003d os.path.join(self.objects, \u00270\u0027)"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_34e1acfe","side":"PARENT","line":514,"updated":"2015-03-25 18:30:38.000000000","message":"see ?","commit_id":"0bad452c2f9db477574737b72de036569807960a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2e7c514f0c010647c8d5243148b13fd6bf183b86","unresolved":false,"context_lines":[{"line_number":978,"context_line":"                              self.df_mgr.get_hashes, \u0027sdb1\u0027, \u00270\u0027, \u0027123\u0027,"},{"line_number":979,"context_line":"                              \u0027objects\u0027)"},{"line_number":980,"context_line":""},{"line_number":981,"context_line":"    def test_get_hashes_w_nothing(self):"},{"line_number":982,"context_line":"        hashes \u003d self.df_mgr.get_hashes(self.existing_device1, \u00270\u0027, \u0027123\u0027, \u00270\u0027)"},{"line_number":983,"context_line":"        self.assertEqual(hashes, {})"},{"line_number":984,"context_line":"        # get_hashes creates the partition path, so call again for code"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_19fdc96e","side":"PARENT","line":981,"updated":"2015-03-25 18:30:38.000000000","message":"see test_get_hashes_creates_partition_and_pkl\n\nbut test_get_hashes_creates_partition_and_pkl doesn\u0027t do the second check after dir has been created","commit_id":"0bad452c2f9db477574737b72de036569807960a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2f710cd41904acc246730729de55b3b926581aab","unresolved":false,"context_lines":[{"line_number":3117,"context_line":"            }[policy.policy_type]"},{"line_number":3118,"context_line":"            self.assertEqual(hashes, expected)"},{"line_number":3119,"context_line":"            # only the tombstone should be left"},{"line_number":3120,"context_line":"            self.assertEquals(len(os.listdir(df._datadir)), 1)"},{"line_number":3121,"context_line":""},{"line_number":3122,"context_line":"    def test_hash_suffix_multi_file_ends_in_datafile(self):"},{"line_number":3123,"context_line":"        for policy in self.iter_policies():"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_68e98de5","line":3120,"updated":"2015-03-25 17:37:24.000000000","message":"add check that the one file *is* the tombstone?","commit_id":"7b8812f319867756acbf4d23aa9179ce9569d929"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2f710cd41904acc246730729de55b3b926581aab","unresolved":false,"context_lines":[{"line_number":3174,"context_line":"                expected, hashes, policy)"},{"line_number":3175,"context_line":"            self.assertEqual(hashes, expected, msg)"},{"line_number":3176,"context_line":"            # only the meta and data should be left"},{"line_number":3177,"context_line":"            self.assertEquals(len(os.listdir(df._datadir)), num_files)"},{"line_number":3178,"context_line":""},{"line_number":3179,"context_line":"    def test_hash_suffix_removes_empty_hashdir_and_suffix(self):"},{"line_number":3180,"context_line":"        for policy in self.iter_policies():"}],"source_content_type":"text/x-python","patch_set":26,"id":"1a6ced46_c8bfe1a8","line":3177,"updated":"2015-03-25 17:37:24.000000000","message":"add check that the 2 files are meta and data","commit_id":"7b8812f319867756acbf4d23aa9179ce9569d929"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"e9e2c109f4a4d42a4c788a771e1030f7a37c23e0","unresolved":false,"context_lines":[{"line_number":2695,"context_line":""},{"line_number":2696,"context_line":"    def iter_policies(self):"},{"line_number":2697,"context_line":"        for policy in POLICIES:"},{"line_number":2698,"context_line":"            self.policy \u003d policy"},{"line_number":2699,"context_line":"            yield policy"},{"line_number":2700,"context_line":""},{"line_number":2701,"context_line":"    def assertEqual(self, *args):"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a6ced46_390c2eed","line":2698,"updated":"2015-03-26 11:50:19.000000000","message":"(memo) ok. self.policy helps us to get easily which policy violate the assertion around L2704.","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"e9e2c109f4a4d42a4c788a771e1030f7a37c23e0","unresolved":false,"context_lines":[{"line_number":2750,"context_line":"        for policy in self.iter_policies():"},{"line_number":2751,"context_line":"            # purge .data if there\u0027s a newer .ts"},{"line_number":2752,"context_line":"            file1 \u003d self._datafilename(Timestamp(time()), policy)"},{"line_number":2753,"context_line":"            file2 \u003d Timestamp(time() + 1).internal + \u0027.ts\u0027"},{"line_number":2754,"context_line":"            file_list \u003d [file1, file2]"},{"line_number":2755,"context_line":"            self.check_hash_cleanup_listdir(policy, file_list, [file2])"},{"line_number":2756,"context_line":""}],"source_content_type":"text/x-python","patch_set":27,"id":"1a6ced46_f95c561b","line":2753,"updated":"2015-03-26 11:50:19.000000000","message":"Why don\u0027t you use self.ts()?","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"980ceab6e535381e1d3afaaf66b159aafb781217","unresolved":false,"context_lines":[{"line_number":2750,"context_line":"        for policy in self.iter_policies():"},{"line_number":2751,"context_line":"            # purge .data if there\u0027s a newer .ts"},{"line_number":2752,"context_line":"            file1 \u003d self._datafilename(Timestamp(time()), policy)"},{"line_number":2753,"context_line":"            file2 \u003d Timestamp(time() + 1).internal + \u0027.ts\u0027"},{"line_number":2754,"context_line":"            file_list \u003d [file1, file2]"},{"line_number":2755,"context_line":"            self.check_hash_cleanup_listdir(policy, file_list, [file2])"},{"line_number":2756,"context_line":""}],"source_content_type":"text/x-python","patch_set":27,"id":"fa963961_37b6198b","line":2753,"in_reply_to":"1a6ced46_f95c561b","updated":"2015-03-27 01:00:09.000000000","message":"Done","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"e9e2c109f4a4d42a4c788a771e1030f7a37c23e0","unresolved":false,"context_lines":[{"line_number":2825,"context_line":"        for policy in self.iter_policies():"},{"line_number":2826,"context_line":"            file1 \u003d Timestamp(time()).internal + \u0027.ts\u0027"},{"line_number":2827,"context_line":"            file2 \u003d Timestamp(time() + 1).internal + \u0027.ts\u0027"},{"line_number":2828,"context_line":"            file3 \u003d Timestamp(time() + 2).internal + \u0027.ts\u0027"},{"line_number":2829,"context_line":"            file_list \u003d [file1, file2, file3]"},{"line_number":2830,"context_line":"            # keep only latest of multiple .ts files"},{"line_number":2831,"context_line":"            self.check_hash_cleanup_listdir(policy, file_list, [file3])"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a6ced46_d99cfa6c","line":2828,"updated":"2015-03-26 11:50:19.000000000","message":"Say again, why don\u0027t you use self.ts(), here?","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"980ceab6e535381e1d3afaaf66b159aafb781217","unresolved":false,"context_lines":[{"line_number":2825,"context_line":"        for policy in self.iter_policies():"},{"line_number":2826,"context_line":"            file1 \u003d Timestamp(time()).internal + \u0027.ts\u0027"},{"line_number":2827,"context_line":"            file2 \u003d Timestamp(time() + 1).internal + \u0027.ts\u0027"},{"line_number":2828,"context_line":"            file3 \u003d Timestamp(time() + 2).internal + \u0027.ts\u0027"},{"line_number":2829,"context_line":"            file_list \u003d [file1, file2, file3]"},{"line_number":2830,"context_line":"            # keep only latest of multiple .ts files"},{"line_number":2831,"context_line":"            self.check_hash_cleanup_listdir(policy, file_list, [file3])"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa963961_97a7254f","line":2828,"in_reply_to":"1a6ced46_d99cfa6c","updated":"2015-03-27 01:00:09.000000000","message":"Done","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"e9e2c109f4a4d42a4c788a771e1030f7a37c23e0","unresolved":false,"context_lines":[{"line_number":2868,"context_line":"            # keep only latest of multiple .meta files"},{"line_number":2869,"context_line":"            file1 \u003d self._datafilename(Timestamp(time()), policy)"},{"line_number":2870,"context_line":"            file2 \u003d Timestamp(time() + 1).internal + \u0027.meta\u0027"},{"line_number":2871,"context_line":"            file3 \u003d Timestamp(time() + 2).internal + \u0027.meta\u0027"},{"line_number":2872,"context_line":"            file_list \u003d [file1, file2, file3]"},{"line_number":2873,"context_line":"            expected \u003d {"},{"line_number":2874,"context_line":"                # the contract validation for EC doesn\u0027t allow for a"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a6ced46_f9a4564c","line":2871,"updated":"2015-03-26 11:50:19.000000000","message":"From here to the bottom, I just add \"self.ts()\" for similar cases.","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"980ceab6e535381e1d3afaaf66b159aafb781217","unresolved":false,"context_lines":[{"line_number":2868,"context_line":"            # keep only latest of multiple .meta files"},{"line_number":2869,"context_line":"            file1 \u003d self._datafilename(Timestamp(time()), policy)"},{"line_number":2870,"context_line":"            file2 \u003d Timestamp(time() + 1).internal + \u0027.meta\u0027"},{"line_number":2871,"context_line":"            file3 \u003d Timestamp(time() + 2).internal + \u0027.meta\u0027"},{"line_number":2872,"context_line":"            file_list \u003d [file1, file2, file3]"},{"line_number":2873,"context_line":"            expected \u003d {"},{"line_number":2874,"context_line":"                # the contract validation for EC doesn\u0027t allow for a"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa963961_7ad00854","line":2871,"in_reply_to":"1a6ced46_f9a4564c","updated":"2015-03-27 01:00:09.000000000","message":"Done","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"e9e2c109f4a4d42a4c788a771e1030f7a37c23e0","unresolved":false,"context_lines":[{"line_number":2872,"context_line":"            file_list \u003d [file1, file2, file3]"},{"line_number":2873,"context_line":"            expected \u003d {"},{"line_number":2874,"context_line":"                # the contract validation for EC doesn\u0027t allow for a"},{"line_number":2875,"context_line":"                # directory will only .meta files"},{"line_number":2876,"context_line":"                EC_POLICY: AssertionError(),"},{"line_number":2877,"context_line":"                REPL_POLICY: [file3, file1]"},{"line_number":2878,"context_line":"            }[policy.policy_type]"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a6ced46_94296939","line":2875,"updated":"2015-03-26 11:50:19.000000000","message":"(memo) exactly, when there is no .durable, all .data files must be in obsolete and then, they won\u0027t appear in the accepted_files so it results in AssertionError at verification the files.","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"42ab81e04884f24833f3ddc743b60c6d247cdb01","unresolved":false,"context_lines":[{"line_number":2872,"context_line":"            file_list \u003d [file1, file2, file3]"},{"line_number":2873,"context_line":"            expected \u003d {"},{"line_number":2874,"context_line":"                # the contract validation for EC doesn\u0027t allow for a"},{"line_number":2875,"context_line":"                # directory will only .meta files"},{"line_number":2876,"context_line":"                EC_POLICY: AssertionError(),"},{"line_number":2877,"context_line":"                REPL_POLICY: [file3, file1]"},{"line_number":2878,"context_line":"            }[policy.policy_type]"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa963961_08e9cb1a","line":2875,"in_reply_to":"1a6ced46_94296939","updated":"2015-03-26 15:10:07.000000000","message":"Neither repl or ec validation allows a dir with only .meta files. The difference here that causes the AssertionError is that EC requires a durable in the dir to validate the data.\n\nSo I think we actually need to fix this test to create the required durable for EC, then check that the older meta is removed for both policy types, AND add a test that verifies that both policy types raise Error when dir has only meta files.","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"e9e2c109f4a4d42a4c788a771e1030f7a37c23e0","unresolved":false,"context_lines":[{"line_number":2884,"context_line":"            # from being cleaned up otherwise"},{"line_number":2885,"context_line":"            file1 \u003d Timestamp(time()).internal + \u0027.ts\u0027"},{"line_number":2886,"context_line":"            file2 \u003d Timestamp(time() + 1).internal + \u0027.ts\u0027"},{"line_number":2887,"context_line":"            file3 \u003d Timestamp(time() + 2).internal + \u0027.meta\u0027"},{"line_number":2888,"context_line":"            file_list \u003d [file1, file2, file3]"},{"line_number":2889,"context_line":"            self.check_hash_cleanup_listdir(policy, file_list, [file3, file2])"},{"line_number":2890,"context_line":""}],"source_content_type":"text/x-python","patch_set":27,"id":"1a6ced46_141579e4","line":2887,"updated":"2015-03-26 11:50:19.000000000","message":"self.ts()","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"980ceab6e535381e1d3afaaf66b159aafb781217","unresolved":false,"context_lines":[{"line_number":2884,"context_line":"            # from being cleaned up otherwise"},{"line_number":2885,"context_line":"            file1 \u003d Timestamp(time()).internal + \u0027.ts\u0027"},{"line_number":2886,"context_line":"            file2 \u003d Timestamp(time() + 1).internal + \u0027.ts\u0027"},{"line_number":2887,"context_line":"            file3 \u003d Timestamp(time() + 2).internal + \u0027.meta\u0027"},{"line_number":2888,"context_line":"            file_list \u003d [file1, file2, file3]"},{"line_number":2889,"context_line":"            self.check_hash_cleanup_listdir(policy, file_list, [file3, file2])"},{"line_number":2890,"context_line":""}],"source_content_type":"text/x-python","patch_set":27,"id":"fa963961_3aca80a2","line":2887,"in_reply_to":"1a6ced46_141579e4","updated":"2015-03-27 01:00:09.000000000","message":"Done","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"e9e2c109f4a4d42a4c788a771e1030f7a37c23e0","unresolved":false,"context_lines":[{"line_number":2893,"context_line":"            # Oldest .data will be purge, .meta and .ts won\u0027t be touched"},{"line_number":2894,"context_line":"            file1 \u003d self._datafilename(Timestamp(time()), policy)"},{"line_number":2895,"context_line":"            file2 \u003d Timestamp(time() + 1).internal + \u0027.ts\u0027"},{"line_number":2896,"context_line":"            file3 \u003d Timestamp(time() + 2).internal + \u0027.meta\u0027"},{"line_number":2897,"context_line":"            file_list \u003d [file1, file2, file3]"},{"line_number":2898,"context_line":"            self.check_hash_cleanup_listdir(policy, file_list, [file3, file2])"},{"line_number":2899,"context_line":""}],"source_content_type":"text/x-python","patch_set":27,"id":"1a6ced46_74b22d07","line":2896,"updated":"2015-03-26 11:50:19.000000000","message":"self.ts()","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"980ceab6e535381e1d3afaaf66b159aafb781217","unresolved":false,"context_lines":[{"line_number":2893,"context_line":"            # Oldest .data will be purge, .meta and .ts won\u0027t be touched"},{"line_number":2894,"context_line":"            file1 \u003d self._datafilename(Timestamp(time()), policy)"},{"line_number":2895,"context_line":"            file2 \u003d Timestamp(time() + 1).internal + \u0027.ts\u0027"},{"line_number":2896,"context_line":"            file3 \u003d Timestamp(time() + 2).internal + \u0027.meta\u0027"},{"line_number":2897,"context_line":"            file_list \u003d [file1, file2, file3]"},{"line_number":2898,"context_line":"            self.check_hash_cleanup_listdir(policy, file_list, [file3, file2])"},{"line_number":2899,"context_line":""}],"source_content_type":"text/x-python","patch_set":27,"id":"fa963961_1acfbcb1","line":2896,"in_reply_to":"1a6ced46_74b22d07","updated":"2015-03-27 01:00:09.000000000","message":"Done","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"42ab81e04884f24833f3ddc743b60c6d247cdb01","unresolved":false,"context_lines":[{"line_number":2914,"context_line":"            file_list \u003d [file1, file2]"},{"line_number":2915,"context_line":"            self.check_hash_cleanup_listdir(policy, file_list, [file2, file1])"},{"line_number":2916,"context_line":""},{"line_number":2917,"context_line":"    def test_hash_cleanup_listdir_keep_single_old_data(self):"},{"line_number":2918,"context_line":"        for policy in self.iter_policies():"},{"line_number":2919,"context_line":"            # A single old .data file will not be removed"},{"line_number":2920,"context_line":"            old_float \u003d time() - (diskfile.ONE_WEEK + 1)"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa963961_b1b48ad1","line":2917,"updated":"2015-03-26 15:10:07.000000000","message":"add test for single old durable when EC policy","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"980ceab6e535381e1d3afaaf66b159aafb781217","unresolved":false,"context_lines":[{"line_number":2914,"context_line":"            file_list \u003d [file1, file2]"},{"line_number":2915,"context_line":"            self.check_hash_cleanup_listdir(policy, file_list, [file2, file1])"},{"line_number":2916,"context_line":""},{"line_number":2917,"context_line":"    def test_hash_cleanup_listdir_keep_single_old_data(self):"},{"line_number":2918,"context_line":"        for policy in self.iter_policies():"},{"line_number":2919,"context_line":"            # A single old .data file will not be removed"},{"line_number":2920,"context_line":"            old_float \u003d time() - (diskfile.ONE_WEEK + 1)"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa963961_fac41893","line":2917,"in_reply_to":"fa963961_b1b48ad1","updated":"2015-03-27 01:00:09.000000000","message":"great, yeah I applied your diff - thanks!","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":4608,"name":"Kota Tsuyuzaki","email":"bloodeagle40234@gmail.com","username":"tsuyuzaki-kota"},"change_message_id":"e9e2c109f4a4d42a4c788a771e1030f7a37c23e0","unresolved":false,"context_lines":[{"line_number":3253,"context_line":"            self.assertFalse(os.path.exists(suffix_path))"},{"line_number":3254,"context_line":"            expected \u003d {"},{"line_number":3255,"context_line":"                EC_POLICY: {\u0027123\u0027: {}},"},{"line_number":3256,"context_line":"                REPL_POLICY: {\u0027123\u0027: \u0027d41d8cd98f00b204e9800998ecf8427e\u0027},"},{"line_number":3257,"context_line":"            }[policy.policy_type]"},{"line_number":3258,"context_line":"            msg \u003d \u0027expected %r !\u003d %r for policy %r\u0027 % (expected, hashes,"},{"line_number":3259,"context_line":"                                                       policy)"}],"source_content_type":"text/x-python","patch_set":27,"id":"1a6ced46_05d625f1","line":3256,"updated":"2015-03-26 11:50:19.000000000","message":"(memo) \u0027d41d8cd98f00b204e9800998ecf8427e\u0027 is hashlib.md5().hexdigest() so it means EMPTY.\n\nWhen there are no files at EC_POLICY, it\u0027ll be empty dict because it will come from:\n\n dict((fi, md5.hexdigest()) for fi, md5 in hash_per_fi.items())","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"42ab81e04884f24833f3ddc743b60c6d247cdb01","unresolved":false,"context_lines":[{"line_number":3253,"context_line":"            self.assertFalse(os.path.exists(suffix_path))"},{"line_number":3254,"context_line":"            expected \u003d {"},{"line_number":3255,"context_line":"                EC_POLICY: {\u0027123\u0027: {}},"},{"line_number":3256,"context_line":"                REPL_POLICY: {\u0027123\u0027: \u0027d41d8cd98f00b204e9800998ecf8427e\u0027},"},{"line_number":3257,"context_line":"            }[policy.policy_type]"},{"line_number":3258,"context_line":"            msg \u003d \u0027expected %r !\u003d %r for policy %r\u0027 % (expected, hashes,"},{"line_number":3259,"context_line":"                                                       policy)"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa963961_4881138f","line":3256,"in_reply_to":"1a6ced46_05d625f1","updated":"2015-03-26 15:10:07.000000000","message":"In swiftclient someone recently added a constant EMPTY_ETAG or similar in the tests as a convenience :)","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"980ceab6e535381e1d3afaaf66b159aafb781217","unresolved":false,"context_lines":[{"line_number":3253,"context_line":"            self.assertFalse(os.path.exists(suffix_path))"},{"line_number":3254,"context_line":"            expected \u003d {"},{"line_number":3255,"context_line":"                EC_POLICY: {\u0027123\u0027: {}},"},{"line_number":3256,"context_line":"                REPL_POLICY: {\u0027123\u0027: \u0027d41d8cd98f00b204e9800998ecf8427e\u0027},"},{"line_number":3257,"context_line":"            }[policy.policy_type]"},{"line_number":3258,"context_line":"            msg \u003d \u0027expected %r !\u003d %r for policy %r\u0027 % (expected, hashes,"},{"line_number":3259,"context_line":"                                                       policy)"}],"source_content_type":"text/x-python","patch_set":27,"id":"fa963961_9a52acdc","line":3256,"in_reply_to":"fa963961_4881138f","updated":"2015-03-27 01:00:09.000000000","message":"Done","commit_id":"3a821b15ec40686689bd3cfe45e3737fbe20da2b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e2ab034fec5b1f27ab1b819252fb9a1c17a5f431","unresolved":false,"context_lines":[{"line_number":2695,"context_line":""},{"line_number":2696,"context_line":"    def iter_policies(self):"},{"line_number":2697,"context_line":"        for policy in POLICIES:"},{"line_number":2698,"context_line":"            self.policy \u003d policy"},{"line_number":2699,"context_line":"            yield policy"},{"line_number":2700,"context_line":""},{"line_number":2701,"context_line":"    def assertEqual(self, *args):"}],"source_content_type":"text/x-python","patch_set":28,"id":"fa963961_4d034174","line":2698,"updated":"2015-03-27 09:59:52.000000000","message":"yeah thats a nice trick","commit_id":"296afe756c639749616b09802fb4caf54bf2c844"}],"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":"cbe43a13edd05999888776020611caa3ba2713a0","unresolved":false,"context_lines":[{"line_number":1395,"context_line":"        req \u003d swob.Request.blank("},{"line_number":1396,"context_line":"            \u0027/device/partition\u0027,"},{"line_number":1397,"context_line":"            environ\u003d{\u0027REQUEST_METHOD\u0027: \u0027RUGGEDIZE\u0027,"},{"line_number":1398,"context_line":"                     \u0027HTTP_X_BACKEND_SSYNC_FRAG_INDEX\u0027: \u00270\u0027},"},{"line_number":1399,"context_line":"            body\u003d\u0027:MISSING_CHECK: START\\r\\n:MISSING_CHECK: END\\r\\n\u0027"},{"line_number":1400,"context_line":"                 \u0027:UPDATES: START\\r\\n\u0027"},{"line_number":1401,"context_line":"                 \u0027PUT /a/c/o1\\r\\n\u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_778b21c3","line":1398,"updated":"2015-03-06 21:28:39.000000000","message":"do these tests *fail* without this header because like rolling upgrade :\\","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e2dd0a07da6c16953fde33687eef37bdfe48e931","unresolved":false,"context_lines":[{"line_number":1395,"context_line":"        req \u003d swob.Request.blank("},{"line_number":1396,"context_line":"            \u0027/device/partition\u0027,"},{"line_number":1397,"context_line":"            environ\u003d{\u0027REQUEST_METHOD\u0027: \u0027RUGGEDIZE\u0027,"},{"line_number":1398,"context_line":"                     \u0027HTTP_X_BACKEND_SSYNC_FRAG_INDEX\u0027: \u00270\u0027},"},{"line_number":1399,"context_line":"            body\u003d\u0027:MISSING_CHECK: START\\r\\n:MISSING_CHECK: END\\r\\n\u0027"},{"line_number":1400,"context_line":"                 \u0027:UPDATES: START\\r\\n\u0027"},{"line_number":1401,"context_line":"                 \u0027PUT /a/c/o1\\r\\n\u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_9375e4cc","line":1398,"in_reply_to":"9a80dd14_778b21c3","updated":"2015-03-09 10:53:29.000000000","message":"+1 these tests need some more work","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"},{"author":{"_account_id":7479,"name":"paul luse","email":"paul.e.luse@intel.com","username":"peluse"},"change_message_id":"47b6452f50fe0654c3960f658bfd89dd6f474250","unresolved":false,"context_lines":[{"line_number":1395,"context_line":"        req \u003d swob.Request.blank("},{"line_number":1396,"context_line":"            \u0027/device/partition\u0027,"},{"line_number":1397,"context_line":"            environ\u003d{\u0027REQUEST_METHOD\u0027: \u0027RUGGEDIZE\u0027,"},{"line_number":1398,"context_line":"                     \u0027HTTP_X_BACKEND_SSYNC_FRAG_INDEX\u0027: \u00270\u0027},"},{"line_number":1399,"context_line":"            body\u003d\u0027:MISSING_CHECK: START\\r\\n:MISSING_CHECK: END\\r\\n\u0027"},{"line_number":1400,"context_line":"                 \u0027:UPDATES: START\\r\\n\u0027"},{"line_number":1401,"context_line":"                 \u0027PUT /a/c/o1\\r\\n\u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"9a80dd14_a1660deb","line":1398,"in_reply_to":"9a80dd14_9375e4cc","updated":"2015-03-09 14:03:21.000000000","message":"yeah, consider the ssync changes on this patch part of the reconstructor.  Looking at this now I\u0027m not sure this one really needed to be here or on the other patch","commit_id":"826326b36f69ba261c5b3a2f0239dbf7fb692a44"}]}
