)]}'
{"swift/common/utils.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fea24ad52e835ca234e8c69579a0de82890de426","unresolved":false,"context_lines":[{"line_number":855,"context_line":"    sorting of encoded timestamp strings."},{"line_number":856,"context_line":""},{"line_number":857,"context_line":"    The format of the encoded string is:"},{"line_number":858,"context_line":"        \u003ct1\u003e[\u003c+/-\u003e\u003ct2 - t3\u003e\u003c+/-\u003e\u003ct3 - t2\u003e]"},{"line_number":859,"context_line":""},{"line_number":860,"context_line":"    i.e. if t1 \u003d t2 \u003d t3 then just the string representation of t1 is returned,"},{"line_number":861,"context_line":"    otherwise the time offsets for t2 and t3 are appended. If explicit is True"}],"source_content_type":"text/x-python","patch_set":19,"id":"ba8a016a_1de790e5","line":858,"updated":"2015-11-17 01:38:58.000000000","message":"According to the code below, the form should be:\n\n  \u003ct1\u003e[\u003c+/-\u003e\u003ct2 - t1\u003e\u003c+/-\u003e\u003ct3 - t2\u003e]\n\nAs line 867 is t2.raw - t1.raw and in the decode function.","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3af5c9242d90d4c5a17e140b589ebda10c63bf90","unresolved":false,"context_lines":[{"line_number":855,"context_line":"    sorting of encoded timestamp strings."},{"line_number":856,"context_line":""},{"line_number":857,"context_line":"    The format of the encoded string is:"},{"line_number":858,"context_line":"        \u003ct1\u003e[\u003c+/-\u003e\u003ct2 - t3\u003e\u003c+/-\u003e\u003ct3 - t2\u003e]"},{"line_number":859,"context_line":""},{"line_number":860,"context_line":"    i.e. if t1 \u003d t2 \u003d t3 then just the string representation of t1 is returned,"},{"line_number":861,"context_line":"    otherwise the time offsets for t2 and t3 are appended. If explicit is True"}],"source_content_type":"text/x-python","patch_set":19,"id":"da6ed579_10ac18ec","line":858,"in_reply_to":"3a7e1126_ca59c836","updated":"2016-01-18 19:27:23.000000000","message":"Done","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"e959c3192374327104fab327449314758a947b94","unresolved":false,"context_lines":[{"line_number":855,"context_line":"    sorting of encoded timestamp strings."},{"line_number":856,"context_line":""},{"line_number":857,"context_line":"    The format of the encoded string is:"},{"line_number":858,"context_line":"        \u003ct1\u003e[\u003c+/-\u003e\u003ct2 - t3\u003e\u003c+/-\u003e\u003ct3 - t2\u003e]"},{"line_number":859,"context_line":""},{"line_number":860,"context_line":"    i.e. if t1 \u003d t2 \u003d t3 then just the string representation of t1 is returned,"},{"line_number":861,"context_line":"    otherwise the time offsets for t2 and t3 are appended. If explicit is True"}],"source_content_type":"text/x-python","patch_set":19,"id":"3a7e1126_ca59c836","line":858,"in_reply_to":"ba8a016a_1de790e5","updated":"2016-01-07 18:50:43.000000000","message":"Agreed, clearly a typo for t2-t1.","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fea24ad52e835ca234e8c69579a0de82890de426","unresolved":false,"context_lines":[{"line_number":868,"context_line":"        explicit \u003d explicit or (t2_t1_delta !\u003d 0)"},{"line_number":869,"context_line":"        values.append(t2_t1_delta)"},{"line_number":870,"context_line":"    if t3:"},{"line_number":871,"context_line":"        t3_t2_delta \u003d t3.raw - t2.raw"},{"line_number":872,"context_line":"        explicit \u003d explicit or (t3_t2_delta !\u003d 0)"},{"line_number":873,"context_line":"        values.append(t3_t2_delta)"},{"line_number":874,"context_line":"    if explicit and t2:"}],"source_content_type":"text/x-python","patch_set":19,"id":"ba8a016a_9dc86076","line":871,"updated":"2015-11-17 01:38:58.000000000","message":"This assumes that if there is a t3 there is a t2.. but this might not be the case.","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3af5c9242d90d4c5a17e140b589ebda10c63bf90","unresolved":false,"context_lines":[{"line_number":868,"context_line":"        explicit \u003d explicit or (t2_t1_delta !\u003d 0)"},{"line_number":869,"context_line":"        values.append(t2_t1_delta)"},{"line_number":870,"context_line":"    if t3:"},{"line_number":871,"context_line":"        t3_t2_delta \u003d t3.raw - t2.raw"},{"line_number":872,"context_line":"        explicit \u003d explicit or (t3_t2_delta !\u003d 0)"},{"line_number":873,"context_line":"        values.append(t3_t2_delta)"},{"line_number":874,"context_line":"    if explicit and t2:"}],"source_content_type":"text/x-python","patch_set":19,"id":"da6ed579_d08c4081","line":871,"in_reply_to":"ba8a016a_9dc86076","updated":"2016-01-18 19:27:23.000000000","message":"Done - indent problem","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"e959c3192374327104fab327449314758a947b94","unresolved":false,"context_lines":[{"line_number":871,"context_line":"        t3_t2_delta \u003d t3.raw - t2.raw"},{"line_number":872,"context_line":"        explicit \u003d explicit or (t3_t2_delta !\u003d 0)"},{"line_number":873,"context_line":"        values.append(t3_t2_delta)"},{"line_number":874,"context_line":"    if explicit and t2:"},{"line_number":875,"context_line":"        form +\u003d \u0027{1:+x}\u0027"},{"line_number":876,"context_line":"        if t3:"},{"line_number":877,"context_line":"            form +\u003d \u0027{2:+x}\u0027"}],"source_content_type":"text/x-python","patch_set":19,"id":"3a7e1126_2a32ccf2","line":874,"updated":"2016-01-07 18:50:43.000000000","message":"This can\u0027t be right - we\u0027re setting explicit above in accordance with comment. The \"and t2\" part makes no sense.","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3af5c9242d90d4c5a17e140b589ebda10c63bf90","unresolved":false,"context_lines":[{"line_number":871,"context_line":"        t3_t2_delta \u003d t3.raw - t2.raw"},{"line_number":872,"context_line":"        explicit \u003d explicit or (t3_t2_delta !\u003d 0)"},{"line_number":873,"context_line":"        values.append(t3_t2_delta)"},{"line_number":874,"context_line":"    if explicit and t2:"},{"line_number":875,"context_line":"        form +\u003d \u0027{1:+x}\u0027"},{"line_number":876,"context_line":"        if t3:"},{"line_number":877,"context_line":"            form +\u003d \u0027{2:+x}\u0027"}],"source_content_type":"text/x-python","patch_set":19,"id":"da6ed579_10e4180b","line":874,"in_reply_to":"3a7e1126_2a32ccf2","updated":"2016-01-18 19:27:23.000000000","message":"Done","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"e959c3192374327104fab327449314758a947b94","unresolved":false,"context_lines":[{"line_number":873,"context_line":"        values.append(t3_t2_delta)"},{"line_number":874,"context_line":"    if explicit and t2:"},{"line_number":875,"context_line":"        form +\u003d \u0027{1:+x}\u0027"},{"line_number":876,"context_line":"        if t3:"},{"line_number":877,"context_line":"            form +\u003d \u0027{2:+x}\u0027"},{"line_number":878,"context_line":"    return form.format(*values)"},{"line_number":879,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"3a7e1126_aa547cfd","line":876,"updated":"2016-01-07 18:50:43.000000000","message":"The form in the comment does not allow to discard just the t3 (e.g. not \u003ct1\u003e[+\u003ct2-t1\u003e[+\u003ct3-t2]]). So we should not check for nonzero t3 here, or change the comment.\n\nI see that decode_timestamps is set up to deal with missing t3. Looks like optional t3 was the initial design, but then things got muddied by a case when t2\u003d\u003d0 t3!\u003d0.","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3af5c9242d90d4c5a17e140b589ebda10c63bf90","unresolved":false,"context_lines":[{"line_number":873,"context_line":"        values.append(t3_t2_delta)"},{"line_number":874,"context_line":"    if explicit and t2:"},{"line_number":875,"context_line":"        form +\u003d \u0027{1:+x}\u0027"},{"line_number":876,"context_line":"        if t3:"},{"line_number":877,"context_line":"            form +\u003d \u0027{2:+x}\u0027"},{"line_number":878,"context_line":"    return form.format(*values)"},{"line_number":879,"context_line":""}],"source_content_type":"text/x-python","patch_set":19,"id":"da6ed579_b06d0c9a","line":876,"in_reply_to":"3a7e1126_aa547cfd","updated":"2016-01-18 19:27:23.000000000","message":"fixed comment - the tests were asserting that t3 is not required i.e. a form t1-delta can be returned when t3\u003dNone","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"e959c3192374327104fab327449314758a947b94","unresolved":false,"context_lines":[{"line_number":893,"context_line":"    for part in pos_parts:"},{"line_number":894,"context_line":"        neg_parts \u003d part.split(\u0027-\u0027)"},{"line_number":895,"context_line":"        parts \u003d parts + neg_parts"},{"line_number":896,"context_line":"        signs \u003d signs + [-1] * (len(neg_parts) - 1) + [1]"},{"line_number":897,"context_line":"    t1 \u003d Timestamp(parts[0])"},{"line_number":898,"context_line":"    t2 \u003d t3 \u003d None"},{"line_number":899,"context_line":"    if len(parts) \u003e 1:"}],"source_content_type":"text/x-python","patch_set":19,"id":"3a7e1126_2ae5ec36","line":896,"updated":"2016-01-07 18:50:43.000000000","message":"This would be _way_ easier to understand if you used\n signs \u003d signs + [1] + [-1] * (len(neg_parts) - 1)\ninstead, then referred to sing of t2 as signs[1] and sign of t3 as signs[2].","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3af5c9242d90d4c5a17e140b589ebda10c63bf90","unresolved":false,"context_lines":[{"line_number":893,"context_line":"    for part in pos_parts:"},{"line_number":894,"context_line":"        neg_parts \u003d part.split(\u0027-\u0027)"},{"line_number":895,"context_line":"        parts \u003d parts + neg_parts"},{"line_number":896,"context_line":"        signs \u003d signs + [-1] * (len(neg_parts) - 1) + [1]"},{"line_number":897,"context_line":"    t1 \u003d Timestamp(parts[0])"},{"line_number":898,"context_line":"    t2 \u003d t3 \u003d None"},{"line_number":899,"context_line":"    if len(parts) \u003e 1:"}],"source_content_type":"text/x-python","patch_set":19,"id":"da6ed579_b582de92","line":896,"in_reply_to":"3a7e1126_2ae5ec36","updated":"2016-01-18 19:27:23.000000000","message":"nice idea","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fea24ad52e835ca234e8c69579a0de82890de426","unresolved":false,"context_lines":[{"line_number":913,"context_line":"            t3 \u003d Timestamp((t2.raw + delta) * PRECISION)"},{"line_number":914,"context_line":"    elif not explicit:"},{"line_number":915,"context_line":"        t3 \u003d t2"},{"line_number":916,"context_line":"    return t1, t2, t3"},{"line_number":917,"context_line":""},{"line_number":918,"context_line":""},{"line_number":919,"context_line":"def normalize_timestamp(timestamp):"}],"source_content_type":"text/x-python","patch_set":19,"id":"ba8a016a_1858fef9","line":916,"updated":"2015-11-17 01:38:58.000000000","message":"In my testing when dealing with offsets, the offsets for t2 and t3 are lost when encoded then decoded. t1 is kept so should be enough for db replication.. I think.\n\n  In [1]: from swift.common.utils import *\n  In [2]: import time\n  In [3]: t1 \u003d Timestamp(time.time())\n  In [4]: t2 \u003d Timestamp(time.time())\n  In [5]: t3 \u003d Timestamp(time.time())\n  In [6]: t1.offset +\u003d 3\n  In [7]: t2.offset +\u003d 2\n  In [8]: t3.offset +\u003d 1\n  In [9]: encoded \u003d encode_timestamps(t1, t2, t3)\n  In [10]: encoded\n  Out[10]: \u00271447721931.67214_3+b3e45+af987\u0027\n\n  In [11]: t1\n  Out[11]: 1447721931.67214_0000000000000003\n\n  In [12]: t2\n  Out[12]: 1447721939.04051_0000000000000002\n\n  In [13]: t3\n  Out[13]: 1447721946.23290_0000000000000001\n\n  In [14]: decode_timestamps(encoded)\n  Out[14]:\n  (1447721931.67214_0000000000000003,\n   1447721939.04051_0000000000000000,\n   1447721946.23290_0000000000000000)\n\nJust a FYI, maybe we need to document this, or add a test.","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3af5c9242d90d4c5a17e140b589ebda10c63bf90","unresolved":false,"context_lines":[{"line_number":913,"context_line":"            t3 \u003d Timestamp((t2.raw + delta) * PRECISION)"},{"line_number":914,"context_line":"    elif not explicit:"},{"line_number":915,"context_line":"        t3 \u003d t2"},{"line_number":916,"context_line":"    return t1, t2, t3"},{"line_number":917,"context_line":""},{"line_number":918,"context_line":""},{"line_number":919,"context_line":"def normalize_timestamp(timestamp):"}],"source_content_type":"text/x-python","patch_set":19,"id":"da6ed579_303cbce1","line":916,"in_reply_to":"ba8a016a_1858fef9","updated":"2016-01-18 19:27:23.000000000","message":"Yes, well spotted. Offsets are not preserved for t2 and t3, but I don\u0027t expect those timestamps to have offsets. My rationale was:\n\nI only expect to see an offset on an object PUT or DELETE timestamp (i.e. the data file or tombstone) but not on a POST timestamp.\n\nIn the case where the encoding is used in a container objects table row, t1 could be the PUT or DELETE time but t2 and t3 represent the content type and metadata times (IF different from the data file) i.e. correspond to POST timestamps.\n\nIn the case where the encoded form is used in a meta file name, t1 and t2 both correspond to POST timestamps.\n\nI\u0027ll add a comment.","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"4735a336592f01743a1153842d489bd2ed7bc854","unresolved":false,"context_lines":[{"line_number":862,"context_line":""},{"line_number":863,"context_line":"    def __ne__(self, other):"},{"line_number":864,"context_line":"        if other is None:"},{"line_number":865,"context_line":"            return False"},{"line_number":866,"context_line":"        if not isinstance(other, Timestamp):"},{"line_number":867,"context_line":"            other \u003d Timestamp(other)"},{"line_number":868,"context_line":"        return self.internal !\u003d other.internal"}],"source_content_type":"text/x-python","patch_set":26,"id":"9aed3d3a_5a97b547","line":865,"updated":"2016-03-03 09:38:25.000000000","message":"Silly question, if A is not None, A!\u003dNone should be True, right? This one says False. Not that it matters, probably.","commit_id":"d50c6729a80842c094356de65d9e189ba39826fc"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"32c6c90faaeb7eec8a66c22aa6a1ff8151ef53bf","unresolved":false,"context_lines":[{"line_number":862,"context_line":""},{"line_number":863,"context_line":"    def __ne__(self, other):"},{"line_number":864,"context_line":"        if other is None:"},{"line_number":865,"context_line":"            return False"},{"line_number":866,"context_line":"        if not isinstance(other, Timestamp):"},{"line_number":867,"context_line":"            other \u003d Timestamp(other)"},{"line_number":868,"context_line":"        return self.internal !\u003d other.internal"}],"source_content_type":"text/x-python","patch_set":26,"id":"7af24918_9ebc8ebc","line":865,"in_reply_to":"7af24918_385d9d47","updated":"2016-03-03 14:07:44.000000000","message":"Good catch, Fixed.","commit_id":"d50c6729a80842c094356de65d9e189ba39826fc"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"85ce44b86990e7eebc9767ff750738bd20f738ef","unresolved":false,"context_lines":[{"line_number":862,"context_line":""},{"line_number":863,"context_line":"    def __ne__(self, other):"},{"line_number":864,"context_line":"        if other is None:"},{"line_number":865,"context_line":"            return False"},{"line_number":866,"context_line":"        if not isinstance(other, Timestamp):"},{"line_number":867,"context_line":"            other \u003d Timestamp(other)"},{"line_number":868,"context_line":"        return self.internal !\u003d other.internal"}],"source_content_type":"text/x-python","patch_set":26,"id":"7af24918_385d9d47","line":865,"in_reply_to":"9aed3d3a_5a97b547","updated":"2016-03-03 10:48:20.000000000","message":"gah!  only the second assertion fails:\n\ndiff --git a/test/unit/common/test_utils.py b/test/unit/common/test_utils.py\nindex fa15ece..06f6a48 100644\n--- a/test/unit/common/test_utils.py\n+++ b/test/unit/common/test_utils.py\n@@ -290,6 +290,8 @@ class TestTimestamp(unittest.TestCase):\n         self.assertIs(True, utils.Timestamp(ts) \u003d\u003d ts)  # sanity\n         self.assertIs(False, utils.Timestamp(ts) !\u003d utils.Timestamp(ts))\n         self.assertIs(False, utils.Timestamp(ts) !\u003d ts)\n+        self.assertFalse(utils.Timestamp(ts) \u003d\u003d None)\n+        self.assertTrue(utils.Timestamp(ts) !\u003d None)\n \n     def test_no_force_internal_no_offset(self):\n         \"\"\"Test that internal is the same as normal with no offset\"\"\"","commit_id":"d50c6729a80842c094356de65d9e189ba39826fc"}],"swift/container/backend.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5dcdd88e39b034e0179f723fb5ee74a0ee62bab7","unresolved":false,"context_lines":[{"line_number":698,"context_line":"            curs.execute(\u0027BEGIN IMMEDIATE\u0027)"},{"line_number":699,"context_line":"            # Get created_at times for objects in item_list that already exist."},{"line_number":700,"context_line":"            # We must chunk it up to avoid sqlite\u0027s limit of 999 args."},{"line_number":701,"context_line":"            created_at \u003d {}"},{"line_number":702,"context_line":"            for offset in range(0, len(item_list), SQLITE_ARG_LIMIT):"},{"line_number":703,"context_line":"                chunk \u003d [rec[\u0027name\u0027] for rec in"},{"line_number":704,"context_line":"                         item_list[offset:offset + SQLITE_ARG_LIMIT]]"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a4dcd0f_44e00497","side":"PARENT","line":701,"updated":"2015-08-13 20:07:19.000000000","message":"can you add a comment here to better describe that \"created_at\" is a map of (name, storage_policy_index) \u003d\u003e sqlite_record\n\nbecause I think it would make it more obvious that that variable name is no longer relevant to what you\u0027re putting in it.","commit_id":"14b72b014bda40087fd5555c36b803a9839050d8"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f3d2041a63999d257420c7f12a2053e3271a0e2","unresolved":false,"context_lines":[{"line_number":698,"context_line":"            curs.execute(\u0027BEGIN IMMEDIATE\u0027)"},{"line_number":699,"context_line":"            # Get created_at times for objects in item_list that already exist."},{"line_number":700,"context_line":"            # We must chunk it up to avoid sqlite\u0027s limit of 999 args."},{"line_number":701,"context_line":"            created_at \u003d {}"},{"line_number":702,"context_line":"            for offset in range(0, len(item_list), SQLITE_ARG_LIMIT):"},{"line_number":703,"context_line":"                chunk \u003d [rec[\u0027name\u0027] for rec in"},{"line_number":704,"context_line":"                         item_list[offset:offset + SQLITE_ARG_LIMIT]]"}],"source_content_type":"text/x-python","patch_set":14,"id":"3a29b11f_4a282a33","side":"PARENT","line":701,"in_reply_to":"1a4dcd0f_44e00497","updated":"2015-10-23 13:27:44.000000000","message":"yep, good point, that var name is no longer appropriate, i\u0027ll change it","commit_id":"14b72b014bda40087fd5555c36b803a9839050d8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5dcdd88e39b034e0179f723fb5ee74a0ee62bab7","unresolved":false,"context_lines":[{"line_number":713,"context_line":"        Compare the data and meta related timestamps of an object update item"},{"line_number":714,"context_line":"        with the timestamps of an existing object record, and copy data"},{"line_number":715,"context_line":"        and/or meta related attributes from the existing record to the update"},{"line_number":716,"context_line":"        item if their timestamps are newer."},{"line_number":717,"context_line":""},{"line_number":718,"context_line":"        The multiple timestamps are encoded into a single string for storing"},{"line_number":719,"context_line":"        in the \u0027created_at\u0027 column of the the objects db table."}],"source_content_type":"text/x-python","patch_set":14,"id":"1a4dcd0f_0a8be31f","line":716,"updated":"2015-08-13 20:07:19.000000000","message":"I don\u0027t tend to like in-place modification too much if it can be avoided.  Maybe if the method was called \"_update_new_from_existing\"?  I tend to think of \"merge\" as creating a new thing based of two things - but *really* this method just (potentially) updates the \"new\" row based on the data in the existing row that might actually be newer.","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f3d2041a63999d257420c7f12a2053e3271a0e2","unresolved":false,"context_lines":[{"line_number":713,"context_line":"        Compare the data and meta related timestamps of an object update item"},{"line_number":714,"context_line":"        with the timestamps of an existing object record, and copy data"},{"line_number":715,"context_line":"        and/or meta related attributes from the existing record to the update"},{"line_number":716,"context_line":"        item if their timestamps are newer."},{"line_number":717,"context_line":""},{"line_number":718,"context_line":"        The multiple timestamps are encoded into a single string for storing"},{"line_number":719,"context_line":"        in the \u0027created_at\u0027 column of the the objects db table."}],"source_content_type":"text/x-python","patch_set":14,"id":"3a29b11f_af2eb0a2","line":716,"in_reply_to":"1a4dcd0f_0a8be31f","updated":"2015-10-23 13:27:44.000000000","message":"Done","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5dcdd88e39b034e0179f723fb5ee74a0ee62bab7","unresolved":false,"context_lines":[{"line_number":721,"context_line":"        :param item: A dict of object update attributes"},{"line_number":722,"context_line":"        :param existing: A dict of existing object attributes"},{"line_number":723,"context_line":"        :return: True if the item dict is newer than the existing,"},{"line_number":724,"context_line":"                 False otherwise"},{"line_number":725,"context_line":"        \"\"\""},{"line_number":726,"context_line":""},{"line_number":727,"context_line":"        if not existing:"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a4dcd0f_ca289b36","line":724,"updated":"2015-08-13 20:07:19.000000000","message":"i don\u0027t really understand this return value - can\u0027t they sometimes \"both\" be newer (i have the newest t_data, you have the newest t_meta, etc)?","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f3d2041a63999d257420c7f12a2053e3271a0e2","unresolved":false,"context_lines":[{"line_number":721,"context_line":"        :param item: A dict of object update attributes"},{"line_number":722,"context_line":"        :param existing: A dict of existing object attributes"},{"line_number":723,"context_line":"        :return: True if the item dict is newer than the existing,"},{"line_number":724,"context_line":"                 False otherwise"},{"line_number":725,"context_line":"        \"\"\""},{"line_number":726,"context_line":""},{"line_number":727,"context_line":"        if not existing:"}],"source_content_type":"text/x-python","patch_set":14,"id":"3a29b11f_8a2c029a","line":724,"in_reply_to":"1a4dcd0f_ca289b36","updated":"2015-10-23 13:27:44.000000000","message":"Once new item has been updated it has newest of every attribute. Returning True means that one or more of its attributes are newer than the existing --\u003e \"it is worth applying this new item to the db\"","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5dcdd88e39b034e0179f723fb5ee74a0ee62bab7","unresolved":false,"context_lines":[{"line_number":722,"context_line":"        :param existing: A dict of existing object attributes"},{"line_number":723,"context_line":"        :return: True if the item dict is newer than the existing,"},{"line_number":724,"context_line":"                 False otherwise"},{"line_number":725,"context_line":"        \"\"\""},{"line_number":726,"context_line":""},{"line_number":727,"context_line":"        if not existing:"},{"line_number":728,"context_line":"            return True"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a4dcd0f_447c84b5","line":725,"updated":"2015-08-13 20:07:19.000000000","message":"I think this is a pure function - think I\u0027d like to see it pulled off the class to highlight that fact (it has good tests already tho i suppose).","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f3d2041a63999d257420c7f12a2053e3271a0e2","unresolved":false,"context_lines":[{"line_number":722,"context_line":"        :param existing: A dict of existing object attributes"},{"line_number":723,"context_line":"        :return: True if the item dict is newer than the existing,"},{"line_number":724,"context_line":"                 False otherwise"},{"line_number":725,"context_line":"        \"\"\""},{"line_number":726,"context_line":""},{"line_number":727,"context_line":"        if not existing:"},{"line_number":728,"context_line":"            return True"}],"source_content_type":"text/x-python","patch_set":14,"id":"3a29b11f_2a1fee5b","line":725,"in_reply_to":"1a4dcd0f_447c84b5","updated":"2015-10-23 13:27:44.000000000","message":"Done","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5dcdd88e39b034e0179f723fb5ee74a0ee62bab7","unresolved":false,"context_lines":[{"line_number":808,"context_line":"            for item in item_list:"},{"line_number":809,"context_line":"                item.setdefault(\u0027storage_policy_index\u0027, 0)  # legacy"},{"line_number":810,"context_line":"                item_ident \u003d (item[\u0027name\u0027], item[\u0027storage_policy_index\u0027])"},{"line_number":811,"context_line":"                existing \u003d self._record_to_dict(created_at.get(item_ident))"},{"line_number":812,"context_line":"                if self._merge_item(item, existing):"},{"line_number":813,"context_line":"                    if item_ident in created_at:  # exists with older timestamp"},{"line_number":814,"context_line":"                        to_delete[item_ident] \u003d item"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a4dcd0f_44f7a459","line":811,"updated":"2015-08-13 20:07:19.000000000","message":"I wonder if this _record_to_dict call would look better above where we\u0027re pulling the rows out of the database (instead of here were we\u0027re sorting the rows we\u0027re going to add)","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f3d2041a63999d257420c7f12a2053e3271a0e2","unresolved":false,"context_lines":[{"line_number":808,"context_line":"            for item in item_list:"},{"line_number":809,"context_line":"                item.setdefault(\u0027storage_policy_index\u0027, 0)  # legacy"},{"line_number":810,"context_line":"                item_ident \u003d (item[\u0027name\u0027], item[\u0027storage_policy_index\u0027])"},{"line_number":811,"context_line":"                existing \u003d self._record_to_dict(created_at.get(item_ident))"},{"line_number":812,"context_line":"                if self._merge_item(item, existing):"},{"line_number":813,"context_line":"                    if item_ident in created_at:  # exists with older timestamp"},{"line_number":814,"context_line":"                        to_delete[item_ident] \u003d item"}],"source_content_type":"text/x-python","patch_set":14,"id":"3a29b11f_ea4256ad","line":811,"in_reply_to":"1a4dcd0f_44f7a459","updated":"2015-10-23 13:27:44.000000000","message":"maybe it is insignificant, but this way the zip into a dict is only done when we actually use an existing record, rather than doing it upfront for every existing record.","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fea24ad52e835ca234e8c69579a0de82890de426","unresolved":false,"context_lines":[{"line_number":358,"context_line":"                          \u0027deleted\u0027: deleted,"},{"line_number":359,"context_line":"                          \u0027storage_policy_index\u0027: storage_policy_index,"},{"line_number":360,"context_line":"                          \u0027ctype_timestamp\u0027: content_type_timestamp,"},{"line_number":361,"context_line":"                          \u0027meta_timestamp\u0027: meta_timestamp})"},{"line_number":362,"context_line":""},{"line_number":363,"context_line":"    def empty(self):"},{"line_number":364,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":19,"id":"ba8a016a_787eeae5","line":361,"updated":"2015-11-17 01:38:58.000000000","message":"I did a similar thing in the sharding POC, so one of us will have to update our code depend on who lands first.. I really hope it\u0027s me having to update cause I\u0027d rather this land sooner then my POC code :P","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"}],"swift/obj/diskfile.py":[{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"e959c3192374327104fab327449314758a947b94","unresolved":false,"context_lines":[{"line_number":1048,"context_line":"            (\u0027ts_meta\u0027, \u0027.meta\u0027, \u0027timestamp\u0027),"},{"line_number":1049,"context_line":"            (\u0027ts_data\u0027, \u0027.data\u0027, \u0027timestamp\u0027),"},{"line_number":1050,"context_line":"            (\u0027ts_data\u0027, \u0027.ts\u0027, \u0027timestamp\u0027),"},{"line_number":1051,"context_line":"            (\u0027ts_ctype\u0027, \u0027ctype\u0027, \u0027ctype_timestamp\u0027),"},{"line_number":1052,"context_line":"        )"},{"line_number":1053,"context_line":"        for suffix_path, suffix in suffixes:"},{"line_number":1054,"context_line":"            for object_hash in self._listdir(suffix_path):"}],"source_content_type":"text/x-python","patch_set":19,"id":"3a7e1126_f909f284","line":1051,"updated":"2016-01-07 18:50:43.000000000","message":"No period in \u0027.ctype\u0027? Strange.","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3af5c9242d90d4c5a17e140b589ebda10c63bf90","unresolved":false,"context_lines":[{"line_number":1048,"context_line":"            (\u0027ts_meta\u0027, \u0027.meta\u0027, \u0027timestamp\u0027),"},{"line_number":1049,"context_line":"            (\u0027ts_data\u0027, \u0027.data\u0027, \u0027timestamp\u0027),"},{"line_number":1050,"context_line":"            (\u0027ts_data\u0027, \u0027.ts\u0027, \u0027timestamp\u0027),"},{"line_number":1051,"context_line":"            (\u0027ts_ctype\u0027, \u0027ctype\u0027, \u0027ctype_timestamp\u0027),"},{"line_number":1052,"context_line":"        )"},{"line_number":1053,"context_line":"        for suffix_path, suffix in suffixes:"},{"line_number":1054,"context_line":"            for object_hash in self._listdir(suffix_path):"}],"source_content_type":"text/x-python","patch_set":19,"id":"da6ed579_1b93e1a4","line":1051,"in_reply_to":"3a7e1126_f909f284","updated":"2016-01-18 19:27:23.000000000","message":"This changes in the next version because a change on master means that cleanup_ondisk_files() now returns a richer dict of ondisk info.\n\nBut, FWIW, I wanted to avoid the suggestion that there was a \u0027ctype\u0027 file extension - \u0027ctype\u0027 here was just a key in a dict but not an extension. Anyway, its gone.","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"bc28c6cb247770633d53042e6229f660d55929f2","unresolved":false,"context_lines":[{"line_number":670,"context_line":"                    reverse\u003dTrue)"},{"line_number":671,"context_line":"                # ...and retain this IFF its ctype_timestamp is greater than"},{"line_number":672,"context_line":"                # newest meta file"},{"line_number":673,"context_line":"                cmp_key \u003d \u0027ctype_timestamp\u0027"},{"line_number":674,"context_line":"                if exts[\u0027.meta\u0027][1][cmp_key] \u003e exts[\u0027.meta\u0027][0][cmp_key]:"},{"line_number":675,"context_line":"                    cmp_key \u003d \u0027timestamp\u0027"},{"line_number":676,"context_line":"                    if exts[\u0027.meta\u0027][1][cmp_key] \u003d\u003d exts[\u0027.meta\u0027][0][cmp_key]:"}],"source_content_type":"text/x-python","patch_set":26,"id":"7af24918_3e7e1a19","line":673,"updated":"2016-03-03 13:56:46.000000000","message":"Nit: you don\u0027t really need cmp_key here; it\u0027s not passed to anything and it\u0027s not used outside of this block. This might be a little easier to read if the comparisons just had the literal strings \u0027timestamp\u0027 and \u0027ctype_timestamp\u0027.","commit_id":"d50c6729a80842c094356de65d9e189ba39826fc"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"32c6c90faaeb7eec8a66c22aa6a1ff8151ef53bf","unresolved":false,"context_lines":[{"line_number":670,"context_line":"                    reverse\u003dTrue)"},{"line_number":671,"context_line":"                # ...and retain this IFF its ctype_timestamp is greater than"},{"line_number":672,"context_line":"                # newest meta file"},{"line_number":673,"context_line":"                cmp_key \u003d \u0027ctype_timestamp\u0027"},{"line_number":674,"context_line":"                if exts[\u0027.meta\u0027][1][cmp_key] \u003e exts[\u0027.meta\u0027][0][cmp_key]:"},{"line_number":675,"context_line":"                    cmp_key \u003d \u0027timestamp\u0027"},{"line_number":676,"context_line":"                    if exts[\u0027.meta\u0027][1][cmp_key] \u003d\u003d exts[\u0027.meta\u0027][0][cmp_key]:"}],"source_content_type":"text/x-python","patch_set":26,"id":"7af24918_7ea8a220","line":673,"in_reply_to":"7af24918_3e7e1a19","updated":"2016-03-03 14:07:44.000000000","message":"Done","commit_id":"d50c6729a80842c094356de65d9e189ba39826fc"},{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"04fbcebf2690bf57c0b1e5e258c9dea1f09833d1","unresolved":false,"context_lines":[{"line_number":673,"context_line":"                if (exts[\u0027.meta\u0027][1][\u0027ctype_timestamp\u0027] \u003e"},{"line_number":674,"context_line":"                        exts[\u0027.meta\u0027][0][\u0027ctype_timestamp\u0027]):"},{"line_number":675,"context_line":"                    if (exts[\u0027.meta\u0027][1][\u0027timestamp\u0027] \u003d\u003d"},{"line_number":676,"context_line":"                            exts[\u0027.meta\u0027][0][\u0027timestamp\u0027]):"},{"line_number":677,"context_line":"                        # both at same timestamp so retain only the one with"},{"line_number":678,"context_line":"                        # newest ctype"},{"line_number":679,"context_line":"                        exts[\u0027.meta\u0027][:2] \u003d [exts[\u0027.meta\u0027][1],"}],"source_content_type":"text/x-python","patch_set":27,"id":"7af24918_2a852a06","line":676,"updated":"2016-03-03 15:55:11.000000000","message":"it was prettier with cmp_key, shorter lines without breaks","commit_id":"e91de49d6864b3794f8dc5acd9c1bf0c2f7409d1"}],"swift/obj/server.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"fea24ad52e835ca234e8c69579a0de82890de426","unresolved":false,"context_lines":[{"line_number":518,"context_line":"        else:"},{"line_number":519,"context_line":"            # preserve existing metadata, content-type will be updated"},{"line_number":520,"context_line":"            # metadata \u003d dict(item for item in orig_metadata.iteritems()"},{"line_number":521,"context_line":"            #                 if item[0] not in disk_file.get_fixed_metadata())"},{"line_number":522,"context_line":"            metadata \u003d dict(disk_file.get_metafile_metadata())"},{"line_number":523,"context_line":"        if req_ctype_timestamp \u003e orig_ctype_timestamp:"},{"line_number":524,"context_line":"            content_type_headers \u003d {"}],"source_content_type":"text/x-python","patch_set":19,"id":"ba8a016a_fe908397","line":521,"updated":"2015-11-17 01:38:58.000000000","message":"Do we need to have the above commented out code around anymore?","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3af5c9242d90d4c5a17e140b589ebda10c63bf90","unresolved":false,"context_lines":[{"line_number":518,"context_line":"        else:"},{"line_number":519,"context_line":"            # preserve existing metadata, content-type will be updated"},{"line_number":520,"context_line":"            # metadata \u003d dict(item for item in orig_metadata.iteritems()"},{"line_number":521,"context_line":"            #                 if item[0] not in disk_file.get_fixed_metadata())"},{"line_number":522,"context_line":"            metadata \u003d dict(disk_file.get_metafile_metadata())"},{"line_number":523,"context_line":"        if req_ctype_timestamp \u003e orig_ctype_timestamp:"},{"line_number":524,"context_line":"            content_type_headers \u003d {"}],"source_content_type":"text/x-python","patch_set":19,"id":"da6ed579_9b3b519c","line":521,"in_reply_to":"ba8a016a_fe908397","updated":"2016-01-18 19:27:23.000000000","message":"ooops. deleted. thanks","commit_id":"1c636c454d51a16242bf85208918f9a39a989936"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"1cff56860139aece571b394107da2f3e7ff9959b","unresolved":false,"context_lines":[{"line_number":542,"context_line":"            return HTTPInsufficientStorage(drive\u003ddevice, request\u003drequest)"},{"line_number":543,"context_line":""},{"line_number":544,"context_line":"        update_etag \u003d orig_metadata[\u0027ETag\u0027]"},{"line_number":545,"context_line":"        if \u0027X-Object-Sysmeta-Ec-Etag\u0027 in orig_metadata:"},{"line_number":546,"context_line":"            # For EC policy, send X-Object-Sysmeta-Ec-Etag which is same as the"},{"line_number":547,"context_line":"            # X-Backend-Container-Update-Override-Etag value sent with the"},{"line_number":548,"context_line":"            # original PUT. We have to send Etag (and size etc) with a POST"}],"source_content_type":"text/x-python","patch_set":26,"id":"7af24918_8fef3e1d","line":545,"updated":"2016-03-03 12:40:28.000000000","message":"This points out a deficiency in our Etag processing. I\u0027d made the PUT path driven by a header from the proxy (\"X-Backend-Etag-Is-At\") so that the object server didn\u0027t need to know about EC specifically, but (of course) I didn\u0027t persist it, so now you\u0027ve got this ugliness.\n\nThere should probably be a follow-on patch to make that where-is-my-etag field persistent.\n\nThe follow-on may or may not be a requirement for crypto, depending on how their etag stuff is handled.","commit_id":"d50c6729a80842c094356de65d9e189ba39826fc"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"1079b57827469d118ccfa0487ace43ce98cb4d61","unresolved":false,"context_lines":[{"line_number":542,"context_line":"            return HTTPInsufficientStorage(drive\u003ddevice, request\u003drequest)"},{"line_number":543,"context_line":""},{"line_number":544,"context_line":"        update_etag \u003d orig_metadata[\u0027ETag\u0027]"},{"line_number":545,"context_line":"        if \u0027X-Object-Sysmeta-Ec-Etag\u0027 in orig_metadata:"},{"line_number":546,"context_line":"            # For EC policy, send X-Object-Sysmeta-Ec-Etag which is same as the"},{"line_number":547,"context_line":"            # X-Backend-Container-Update-Override-Etag value sent with the"},{"line_number":548,"context_line":"            # original PUT. We have to send Etag (and size etc) with a POST"}],"source_content_type":"text/x-python","patch_set":26,"id":"7af24918_400fc087","line":545,"in_reply_to":"7af24918_3e0e1a3b","updated":"2016-03-03 14:15:09.000000000","message":"Yes, this\u0027ll need to remain as a fallback. I would just like to avoid the extension of this hack for, say, crypto etags.","commit_id":"d50c6729a80842c094356de65d9e189ba39826fc"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"32c6c90faaeb7eec8a66c22aa6a1ff8151ef53bf","unresolved":false,"context_lines":[{"line_number":542,"context_line":"            return HTTPInsufficientStorage(drive\u003ddevice, request\u003drequest)"},{"line_number":543,"context_line":""},{"line_number":544,"context_line":"        update_etag \u003d orig_metadata[\u0027ETag\u0027]"},{"line_number":545,"context_line":"        if \u0027X-Object-Sysmeta-Ec-Etag\u0027 in orig_metadata:"},{"line_number":546,"context_line":"            # For EC policy, send X-Object-Sysmeta-Ec-Etag which is same as the"},{"line_number":547,"context_line":"            # X-Backend-Container-Update-Override-Etag value sent with the"},{"line_number":548,"context_line":"            # original PUT. We have to send Etag (and size etc) with a POST"}],"source_content_type":"text/x-python","patch_set":26,"id":"7af24918_3e0e1a3b","line":545,"in_reply_to":"7af24918_8fef3e1d","updated":"2016-03-03 14:07:44.000000000","message":"Yup. Considered doing this ^^ in this patch but decided to keep this patch simple, albeit a bit hacky.\n\nWould be a great follow up. But we may have existing objects that will never get a future where-is-my-etag metadata item to refer to, so I think this hack will need to stay.","commit_id":"d50c6729a80842c094356de65d9e189ba39826fc"}],"swift/obj/ssync_sender.py":[{"author":{"_account_id":597,"name":"Pete Zaitcev","email":"zaitcev@kotori.zaitcev.us","username":"zaitcev"},"change_message_id":"e760bde1d89f0dad23c664be8184527b2ca28643","unresolved":false,"context_lines":[{"line_number":37,"context_line":"    if ts_meta and ts_meta !\u003d ts_data:"},{"line_number":38,"context_line":"        delta \u003d ts_meta.raw - ts_data.raw"},{"line_number":39,"context_line":"        msg \u003d \u0027%s m:%x\u0027 % (msg, delta)"},{"line_number":40,"context_line":"        if ts_ctype and ts_ctype !\u003d ts_data:"},{"line_number":41,"context_line":"            delta \u003d ts_ctype.raw - ts_data.raw"},{"line_number":42,"context_line":"            msg \u003d \u0027%s,t:%x\u0027 % (msg, delta)"},{"line_number":43,"context_line":"    return msg"}],"source_content_type":"text/x-python","patch_set":26,"id":"7af24918_789a856f","line":40,"updated":"2016-03-03 10:44:25.000000000","message":"Is it possible to have ts_data\u003dT2 ts_meta\u003dT2 ts_ctype\u003dT1, and if yes, is it harmful?","commit_id":"d50c6729a80842c094356de65d9e189ba39826fc"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"4a37296072fb445935457a9f6655b381fa0ac368","unresolved":false,"context_lines":[{"line_number":37,"context_line":"    if ts_meta and ts_meta !\u003d ts_data:"},{"line_number":38,"context_line":"        delta \u003d ts_meta.raw - ts_data.raw"},{"line_number":39,"context_line":"        msg \u003d \u0027%s m:%x\u0027 % (msg, delta)"},{"line_number":40,"context_line":"        if ts_ctype and ts_ctype !\u003d ts_data:"},{"line_number":41,"context_line":"            delta \u003d ts_ctype.raw - ts_data.raw"},{"line_number":42,"context_line":"            msg \u003d \u0027%s,t:%x\u0027 % (msg, delta)"},{"line_number":43,"context_line":"    return msg"}],"source_content_type":"text/x-python","patch_set":26,"id":"7af24918_9b32ebf0","line":40,"in_reply_to":"7af24918_789a856f","updated":"2016-03-03 10:52:18.000000000","message":"newer data always takes precedence of older ctype - it\u0027s just a property of the DiskFile loading - did you have an idea for a test to prove it - other than what\u0027s already in test_diskfile (like test_get_ondisk_files_with_repl_policy)?","commit_id":"d50c6729a80842c094356de65d9e189ba39826fc"}],"test/probe/test_object_metadata_replication.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"81f8780d91b32c926a4f55435a105c4c65890102","unresolved":false,"context_lines":[{"line_number":247,"context_line":""},{"line_number":248,"context_line":"        self._assert_consistent_object_metadata()"},{"line_number":249,"context_line":"        self._assert_consistent_container_dbs()"},{"line_number":250,"context_line":"        self._assert_consistent_suffix_hashes()"},{"line_number":251,"context_line":""},{"line_number":252,"context_line":"    def test_sysmeta_after_replication_with_subsequent_put(self):"},{"line_number":253,"context_line":"        sysmeta \u003d {\u0027x-object-sysmeta-foo\u0027: \u0027older\u0027}"}],"source_content_type":"text/x-python","patch_set":26,"id":"9aed3d3a_30578427","line":250,"updated":"2016-02-29 13:14:28.000000000","message":"nice","commit_id":"d50c6729a80842c094356de65d9e189ba39826fc"}],"test/unit/common/test_utils.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5dcdd88e39b034e0179f723fb5ee74a0ee62bab7","unresolved":false,"context_lines":[{"line_number":706,"context_line":"        self.assertEqual(1, cmp(utils.Timestamp(-1.0), None))"},{"line_number":707,"context_line":"        self.assertEqual(1, cmp(utils.Timestamp(0), None))"},{"line_number":708,"context_line":"        self.assertEqual(1, cmp(utils.Timestamp(1.0), None))"},{"line_number":709,"context_line":"        self.assertEqual(1, cmp(utils.Timestamp(1.0, 42), None))"},{"line_number":710,"context_line":""},{"line_number":711,"context_line":"    def test_ordering(self):"},{"line_number":712,"context_line":"        given \u003d ["}],"source_content_type":"text/x-python","patch_set":14,"id":"1a4dcd0f_5da8ce77","line":709,"updated":"2015-08-13 20:07:19.000000000","message":"in python 2.7 I think we have assertGreaterThan","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f3d2041a63999d257420c7f12a2053e3271a0e2","unresolved":false,"context_lines":[{"line_number":706,"context_line":"        self.assertEqual(1, cmp(utils.Timestamp(-1.0), None))"},{"line_number":707,"context_line":"        self.assertEqual(1, cmp(utils.Timestamp(0), None))"},{"line_number":708,"context_line":"        self.assertEqual(1, cmp(utils.Timestamp(1.0), None))"},{"line_number":709,"context_line":"        self.assertEqual(1, cmp(utils.Timestamp(1.0, 42), None))"},{"line_number":710,"context_line":""},{"line_number":711,"context_line":"    def test_ordering(self):"},{"line_number":712,"context_line":"        given \u003d ["}],"source_content_type":"text/x-python","patch_set":14,"id":"3a29b11f_8a6962fb","line":709,"in_reply_to":"1a4dcd0f_5da8ce77","updated":"2015-10-23 13:27:44.000000000","message":"Done","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5dcdd88e39b034e0179f723fb5ee74a0ee62bab7","unresolved":false,"context_lines":[{"line_number":836,"context_line":"            (\u00270000001000.00000_18-186a0+0\u0027, (t2, t1, t1)),"},{"line_number":837,"context_line":"            (\u00270000001000.00000_18+0-186a0\u0027, (t2, t2, t1)),"},{"line_number":838,"context_line":"            (\u00270000001000.00000_18-186a0-186c8\u0027, (t2, t1, t0)),"},{"line_number":839,"context_line":"        )"},{"line_number":840,"context_line":""},{"line_number":841,"context_line":"    def test_encoding(self):"},{"line_number":842,"context_line":"        for test in self.explicit_mappings:"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a4dcd0f_7dcfca57","line":839,"updated":"2015-08-13 20:07:19.000000000","message":"I like the layout of these tests better than the container backend tests for _merge_items","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"}],"test/unit/container/test_backend.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5dcdd88e39b034e0179f723fb5ee74a0ee62bab7","unresolved":false,"context_lines":[{"line_number":1665,"context_line":"        self.assertTrue(broker._merge_item(item, rec))"},{"line_number":1666,"context_line":"        self.assertEqual(item, exp)"},{"line_number":1667,"context_line":""},{"line_number":1668,"context_line":"        # use a multi-timed record"},{"line_number":1669,"context_line":"        rec \u003d build_rec(\u00271234567890.00003+3+3\u0027,"},{"line_number":1670,"context_line":"                        \u00271234567890.00003\u0027,"},{"line_number":1671,"context_line":"                        \u00271234567890.00006\u0027)"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a4dcd0f_3afaa844","line":1668,"updated":"2015-08-13 20:07:19.000000000","message":"so this is the degenerate case:\n\n * t_data \u003d 3\n * t_ctype \u003d 6\n * t_meta \u003d 9\n\n... I think you\u0027re missing a set of tests for a created_at that has a t_ctype \u003d\u003d t_meta.","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f3d2041a63999d257420c7f12a2053e3271a0e2","unresolved":false,"context_lines":[{"line_number":1665,"context_line":"        self.assertTrue(broker._merge_item(item, rec))"},{"line_number":1666,"context_line":"        self.assertEqual(item, exp)"},{"line_number":1667,"context_line":""},{"line_number":1668,"context_line":"        # use a multi-timed record"},{"line_number":1669,"context_line":"        rec \u003d build_rec(\u00271234567890.00003+3+3\u0027,"},{"line_number":1670,"context_line":"                        \u00271234567890.00003\u0027,"},{"line_number":1671,"context_line":"                        \u00271234567890.00006\u0027)"}],"source_content_type":"text/x-python","patch_set":14,"id":"3a29b11f_d3913548","line":1668,"in_reply_to":"1a4dcd0f_3afaa844","updated":"2015-10-23 13:27:44.000000000","message":"Done","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5dcdd88e39b034e0179f723fb5ee74a0ee62bab7","unresolved":false,"context_lines":[{"line_number":1668,"context_line":"        # use a multi-timed record"},{"line_number":1669,"context_line":"        rec \u003d build_rec(\u00271234567890.00003+3+3\u0027,"},{"line_number":1670,"context_line":"                        \u00271234567890.00003\u0027,"},{"line_number":1671,"context_line":"                        \u00271234567890.00006\u0027)"},{"line_number":1672,"context_line":""},{"line_number":1673,"context_line":"        # item data time is newer, content type time and meta time are older"},{"line_number":1674,"context_line":"        item \u003d build_item(\u00271234567890.00004\u0027,"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a4dcd0f_7a003036","line":1671,"updated":"2015-08-13 20:07:19.000000000","message":"this seems like TMI - isn\u0027t everything in the t_data \u0026 t_type actually encoded in \"created_at\" - specifically the container has only the one column for created_at - so it must be?\n\nI think the tests would read easier without the duplicated data - plus i feel like not making it DRY means you could have a test that creates an impossible situation that might shadow a bug.\n\n(speaking off - took me for ever to realize the t_meta of this record is *9*","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"1f3d2041a63999d257420c7f12a2053e3271a0e2","unresolved":false,"context_lines":[{"line_number":1668,"context_line":"        # use a multi-timed record"},{"line_number":1669,"context_line":"        rec \u003d build_rec(\u00271234567890.00003+3+3\u0027,"},{"line_number":1670,"context_line":"                        \u00271234567890.00003\u0027,"},{"line_number":1671,"context_line":"                        \u00271234567890.00006\u0027)"},{"line_number":1672,"context_line":""},{"line_number":1673,"context_line":"        # item data time is newer, content type time and meta time are older"},{"line_number":1674,"context_line":"        item \u003d build_item(\u00271234567890.00004\u0027,"}],"source_content_type":"text/x-python","patch_set":14,"id":"3a29b11f_f3947137","line":1671,"in_reply_to":"1a4dcd0f_7a003036","updated":"2015-10-23 13:27:44.000000000","message":"I completely reworked this test in next version, hoping to make it easier to grok. Lets see if I succeed!","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5dcdd88e39b034e0179f723fb5ee74a0ee62bab7","unresolved":false,"context_lines":[{"line_number":1681,"context_line":"        self.assertEqual(item, exp)"},{"line_number":1682,"context_line":""},{"line_number":1683,"context_line":"        # item data time is newer, content type time is newer"},{"line_number":1684,"context_line":"        # and meta time is older"},{"line_number":1685,"context_line":"        item \u003d build_item(\u00271234567890.00004\u0027,"},{"line_number":1686,"context_line":"                          \u00271234567890.00007\u0027,"},{"line_number":1687,"context_line":"                          \u00271234567890.00008\u0027)"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a4dcd0f_3d32a2f3","line":1684,"updated":"2015-08-13 20:07:19.000000000","message":"... and therefore \"8\" is an older meta time","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5dcdd88e39b034e0179f723fb5ee74a0ee62bab7","unresolved":false,"context_lines":[{"line_number":1685,"context_line":"        item \u003d build_item(\u00271234567890.00004\u0027,"},{"line_number":1686,"context_line":"                          \u00271234567890.00007\u0027,"},{"line_number":1687,"context_line":"                          \u00271234567890.00008\u0027)"},{"line_number":1688,"context_line":"        exp \u003d build_expected(item, \u00271234567890.00004+3+2\u0027,"},{"line_number":1689,"context_line":"                                   \u00271234567890.00004\u0027,"},{"line_number":1690,"context_line":"                                   \u00271234567890.00007\u0027)"},{"line_number":1691,"context_line":"        self.assertTrue(broker._merge_item(item, rec))"}],"source_content_type":"text/x-python","patch_set":14,"id":"1a4dcd0f_bd5472fe","line":1688,"updated":"2015-08-13 20:07:19.000000000","message":"... even though 2 \u003c 3 - because the base offset changed.\n\n4 + 3 + 2 \u003d 9 (yay!)","commit_id":"d2195daee05612e8dd53ee8aafc1aabd6f03859f"}]}
