)]}'
{"etc/object-expirer.conf-sample":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":7,"context_line":"# log_level \u003d INFO"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"[object-expirer]"},{"line_number":10,"context_line":"interval \u003d 300"},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"[pipeline:main]"},{"line_number":13,"context_line":"pipeline \u003d catch_errors cache proxy-server"}],"source_content_type":"application/octet-stream","patch_set":2,"id":"AAAACX%2F%2F6F8%3D","line":10,"updated":"2011-10-27 21:04:25.000000000","message":"default value could be commented out","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":7,"context_line":"# log_level \u003d INFO"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"[object-expirer]"},{"line_number":10,"context_line":"interval \u003d 300"},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"[pipeline:main]"},{"line_number":13,"context_line":"pipeline \u003d catch_errors cache proxy-server"}],"source_content_type":"application/octet-stream","patch_set":2,"id":"AAAACX%2F%2F5yg%3D","line":10,"in_reply_to":"AAAACX%2F%2F6F8%3D","updated":"2011-10-29 00:21:01.000000000","message":"Done","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"}],"swift/common/utils.py":[{"author":{"_account_id":866,"name":"Chmouel Boudjnah","email":"chmouel@chmouel.com","username":"chmouel"},"change_message_id":"76e22a53685dab3dfb703c4141036df1830e7656","unresolved":false,"context_lines":[{"line_number":823,"context_line":"        if c.has_section(section_name):"},{"line_number":824,"context_line":"            conf \u003d dict(c.items(section_name))"},{"line_number":825,"context_line":"        else:"},{"line_number":826,"context_line":"            print c.sections()"},{"line_number":827,"context_line":"            print _(\"Unable to find %s config section in %s\") % \\"},{"line_number":828,"context_line":"                 (section_name, conffile)"},{"line_number":829,"context_line":"            sys.exit(1)"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6TM%3D","line":826,"updated":"2011-10-27 05:08:59.000000000","message":"I guess this is debug statement left in the code.","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":823,"context_line":"        if c.has_section(section_name):"},{"line_number":824,"context_line":"            conf \u003d dict(c.items(section_name))"},{"line_number":825,"context_line":"        else:"},{"line_number":826,"context_line":"            print c.sections()"},{"line_number":827,"context_line":"            print _(\"Unable to find %s config section in %s\") % \\"},{"line_number":828,"context_line":"                 (section_name, conffile)"},{"line_number":829,"context_line":"            sys.exit(1)"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5yc%3D","line":826,"in_reply_to":"AAAACX%2F%2F6TM%3D","updated":"2011-10-29 00:21:01.000000000","message":"Done","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"}],"swift/container/server.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":196,"context_line":"        if obj:     # put container object"},{"line_number":197,"context_line":"            if account.startswith(self.auto_create_account_prefix) and \\"},{"line_number":198,"context_line":"                    not os.path.exists(broker.db_file):"},{"line_number":199,"context_line":"                broker.initialize(timestamp)"},{"line_number":200,"context_line":"            if not os.path.exists(broker.db_file):"},{"line_number":201,"context_line":"                return HTTPNotFound()"},{"line_number":202,"context_line":"            broker.put_object(obj, timestamp, int(req.headers[\u0027x-size\u0027]),"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6H4%3D","line":199,"updated":"2011-10-27 21:04:25.000000000","message":"since we\u0027re automatically creating this container for the object put, it\u0027d be nice to send an account_update to update the container listing (and possibly auto create the account).  But I guess that\u0027s difficult without the x-account-* headers...\n\nIn testing I failed to note the object-expirer doesn\u0027t really work with-out the container updaters running... which is somewhat counter-intutive since I typically think of the container updaters mostly being about pushing stats more that notifying of new container creates.","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":196,"context_line":"        if obj:     # put container object"},{"line_number":197,"context_line":"            if account.startswith(self.auto_create_account_prefix) and \\"},{"line_number":198,"context_line":"                    not os.path.exists(broker.db_file):"},{"line_number":199,"context_line":"                broker.initialize(timestamp)"},{"line_number":200,"context_line":"            if not os.path.exists(broker.db_file):"},{"line_number":201,"context_line":"                return HTTPNotFound()"},{"line_number":202,"context_line":"            broker.put_object(obj, timestamp, int(req.headers[\u0027x-size\u0027]),"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F500%3D","line":199,"in_reply_to":"AAAACX%2F%2F6H4%3D","updated":"2011-10-29 00:21:01.000000000","message":"I understand what you\u0027re saying here, but I can\u0027t do what you ask. I have no ring here and the incoming requests are usually from object servers which also have no rings. Adding rings would up the memory footprint of these workers and so had been avoided from the beginning. To be honest, I forget what the extra memory amount was though.","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"}],"swift/obj/expirer.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":34,"context_line":""},{"line_number":35,"context_line":"class ObjectExpirer(Daemon):"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def __init__(self, conf\u003dNone):"},{"line_number":38,"context_line":"        if conf is None:"},{"line_number":39,"context_line":"            conf \u003d {\u0027__file__\u0027: \u0027unit_test\u0027}"},{"line_number":40,"context_line":"        self.conf \u003d conf"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6S4%3D","line":37,"updated":"2011-10-27 21:04:25.000000000","message":"There\u0027s no need for docstrings in this module?","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":34,"context_line":""},{"line_number":35,"context_line":"class ObjectExpirer(Daemon):"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def __init__(self, conf\u003dNone):"},{"line_number":38,"context_line":"        if conf is None:"},{"line_number":39,"context_line":"            conf \u003d {\u0027__file__\u0027: \u0027unit_test\u0027}"},{"line_number":40,"context_line":"        self.conf \u003d conf"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5yI%3D","line":37,"in_reply_to":"AAAACX%2F%2F6S4%3D","updated":"2011-10-29 00:21:01.000000000","message":"Done","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":39,"context_line":"            conf \u003d {\u0027__file__\u0027: \u0027unit_test\u0027}"},{"line_number":40,"context_line":"        self.conf \u003d conf"},{"line_number":41,"context_line":"        self.logger \u003d get_logger(conf, log_route\u003d\u0027object-expirer\u0027)"},{"line_number":42,"context_line":"        self.interval \u003d int(conf.get(\u0027interval\u0027) or 300)"},{"line_number":43,"context_line":"        self.expiring_objects_account \u003d \\"},{"line_number":44,"context_line":"            (conf.get(\u0027auto_create_account_prefix\u0027) or \u0027.\u0027) + \\"},{"line_number":45,"context_line":"            \u0027expiring_objects\u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6Sk%3D","line":42,"updated":"2011-10-27 21:04:25.000000000","message":"the optional default argument to {}.get has served us well in the rest of the code base... why is or better here?","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":39,"context_line":"            conf \u003d {\u0027__file__\u0027: \u0027unit_test\u0027}"},{"line_number":40,"context_line":"        self.conf \u003d conf"},{"line_number":41,"context_line":"        self.logger \u003d get_logger(conf, log_route\u003d\u0027object-expirer\u0027)"},{"line_number":42,"context_line":"        self.interval \u003d int(conf.get(\u0027interval\u0027) or 300)"},{"line_number":43,"context_line":"        self.expiring_objects_account \u003d \\"},{"line_number":44,"context_line":"            (conf.get(\u0027auto_create_account_prefix\u0027) or \u0027.\u0027) + \\"},{"line_number":45,"context_line":"            \u0027expiring_objects\u0027"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5zA%3D","line":42,"in_reply_to":"AAAACX%2F%2F6Sk%3D","updated":"2011-10-29 00:21:01.000000000","message":"Actually, what has gotten us elsewhere in the code is when someone sets:\n\ninterval \u003d\n\nNot a big deal, and debatable whether the code should blow up with a config error in that case or use the default value as this code does.","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":45,"context_line":"            \u0027expiring_objects\u0027"},{"line_number":46,"context_line":"        self.retries \u003d int(conf.get(\u0027retries\u0027) or 3)"},{"line_number":47,"context_line":"        if conf.get(\u0027__file__\u0027) \u003d\u003d \u0027unit_test\u0027:"},{"line_number":48,"context_line":"            self.app \u003d Application(None)"},{"line_number":49,"context_line":"        else:"},{"line_number":50,"context_line":"            self.app \u003d loadapp(\u0027config:\u0027 + (conf.get(\u0027__file__\u0027) or"},{"line_number":51,"context_line":"                               \u0027/etc/swift/object-expirer.conf\u0027))"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6TQ%3D","line":48,"updated":"2011-10-27 21:04:25.000000000","message":"Maybe better to just mock loadapp in the unittests?  You should probably use a FakeRing instead of trying to read out of /etc/swift anyway...","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":45,"context_line":"            \u0027expiring_objects\u0027"},{"line_number":46,"context_line":"        self.retries \u003d int(conf.get(\u0027retries\u0027) or 3)"},{"line_number":47,"context_line":"        if conf.get(\u0027__file__\u0027) \u003d\u003d \u0027unit_test\u0027:"},{"line_number":48,"context_line":"            self.app \u003d Application(None)"},{"line_number":49,"context_line":"        else:"},{"line_number":50,"context_line":"            self.app \u003d loadapp(\u0027config:\u0027 + (conf.get(\u0027__file__\u0027) or"},{"line_number":51,"context_line":"                               \u0027/etc/swift/object-expirer.conf\u0027))"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5xs%3D","line":48,"in_reply_to":"AAAACX%2F%2F6TQ%3D","updated":"2011-10-29 00:21:01.000000000","message":"Done","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":866,"name":"Chmouel Boudjnah","email":"chmouel@chmouel.com","username":"chmouel"},"change_message_id":"76e22a53685dab3dfb703c4141036df1830e7656","unresolved":false,"context_lines":[{"line_number":53,"context_line":"        self.report_first_time \u003d self.report_last_time \u003d time()"},{"line_number":54,"context_line":"        self.report_objects \u003d 0"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def report(self, final\u003dFalse):"},{"line_number":57,"context_line":"        if final:"},{"line_number":58,"context_line":"            elapsed \u003d time() - self.report_first_time"},{"line_number":59,"context_line":"            self.logger.info(_(\u0027Pass completed in %ds; %d objects expired\u0027) %"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6TI%3D","line":56,"updated":"2011-10-27 05:08:59.000000000","message":"It would be nice to add this to swift-recon.","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":53,"context_line":"        self.report_first_time \u003d self.report_last_time \u003d time()"},{"line_number":54,"context_line":"        self.report_objects \u003d 0"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def report(self, final\u003dFalse):"},{"line_number":57,"context_line":"        if final:"},{"line_number":58,"context_line":"            elapsed \u003d time() - self.report_first_time"},{"line_number":59,"context_line":"            self.logger.info(_(\u0027Pass completed in %ds; %d objects expired\u0027) %"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5xo%3D","line":56,"in_reply_to":"AAAACX%2F%2F6TI%3D","updated":"2011-10-29 00:21:01.000000000","message":"While definitely true, I\u0027m not sure how that\u0027d work atm. To gather the recon stats, there needs to be a WSGI server on the box where the stats are dropped. In this case, the expirer will probably be running on an admin box or maybe (in the case of Cloud Files) a services box. Services does have a WSGI server, but the admin box doesn\u0027t (yet). I think I\u0027ll leave this for the future as recon solidifies.","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":88,"context_line":"                        self.logger.exception("},{"line_number":89,"context_line":"                            _(\u0027Exception while deleting object %s %s %s\u0027) %"},{"line_number":90,"context_line":"                            (container, obj, str(err)))"},{"line_number":91,"context_line":"                    self.report()"},{"line_number":92,"context_line":"                try:"},{"line_number":93,"context_line":"                    self.delete_container(container)"},{"line_number":94,"context_line":"                except (Exception, TimeoutError), err:"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6SY%3D","line":91,"updated":"2011-10-27 21:04:25.000000000","message":"seems like this is going to get called a lot and mostly _not_ log anything... maybe better to check report interval before calling... maybe better than that to start a separate greenthread at the top of run_once to sleep for report interval?","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":88,"context_line":"                        self.logger.exception("},{"line_number":89,"context_line":"                            _(\u0027Exception while deleting object %s %s %s\u0027) %"},{"line_number":90,"context_line":"                            (container, obj, str(err)))"},{"line_number":91,"context_line":"                    self.report()"},{"line_number":92,"context_line":"                try:"},{"line_number":93,"context_line":"                    self.delete_container(container)"},{"line_number":94,"context_line":"                except (Exception, TimeoutError), err:"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5yw%3D","line":91,"in_reply_to":"AAAACX%2F%2F6SY%3D","updated":"2011-10-29 00:21:01.000000000","message":"Checking the interval before each call would really just save a call, since the first thing the call does is check the interval. Considering the percentage overhead compared to the total runtime, I think this is easier/more-readable. Spawning a thread is an option, but seems like unneeded complexity (passing the final later to kill the report, restarting on next run...)","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":112,"context_line":"            if elapsed \u003c self.interval:"},{"line_number":113,"context_line":"                sleep(random() * (self.interval - elapsed))"},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"    def get_response(self, method, path, headers, acceptable_statuses):"},{"line_number":116,"context_line":"        headers[\u0027user-agent\u0027] \u003d \u0027Swift Object Expirer\u0027"},{"line_number":117,"context_line":"        resp \u003d exc_type \u003d exc_value \u003d exc_traceback \u003d None"},{"line_number":118,"context_line":"        for attempt in xrange(self.retries):"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6S8%3D","line":115,"updated":"2011-10-27 21:04:25.000000000","message":"I think it\u0027d be pretty reasonable to kwarg headers and accept_statuses, to None \u0026 (2, 404) - perhaps even stylish to use them in the 4 out 6 calls that use those defaults.","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":112,"context_line":"            if elapsed \u003c self.interval:"},{"line_number":113,"context_line":"                sleep(random() * (self.interval - elapsed))"},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"    def get_response(self, method, path, headers, acceptable_statuses):"},{"line_number":116,"context_line":"        headers[\u0027user-agent\u0027] \u003d \u0027Swift Object Expirer\u0027"},{"line_number":117,"context_line":"        resp \u003d exc_type \u003d exc_value \u003d exc_traceback \u003d None"},{"line_number":118,"context_line":"        for attempt in xrange(self.retries):"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5yo%3D","line":115,"in_reply_to":"AAAACX%2F%2F6S8%3D","updated":"2011-10-29 00:21:01.000000000","message":"Sure, but I personally like having it explicit with each call. Seems to me to be easier to read the other code this way. Debatable, and I guess I win since I\u0027m writing the code. :)","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":126,"context_line":"            except (Exception, TimeoutError):"},{"line_number":127,"context_line":"                exc_type, exc_value, exc_traceback \u003d exc_info()"},{"line_number":128,"context_line":"            sleep(2 ** (attempt + 1))"},{"line_number":129,"context_line":"        else:"},{"line_number":130,"context_line":"            if resp:"},{"line_number":131,"context_line":"                raise Exception(\u0027Unexpected response %s\u0027 % (resp.status,))"},{"line_number":132,"context_line":"            if exc_type:"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6Sc%3D","line":129,"updated":"2011-10-27 21:04:25.000000000","message":"I\u0027m a big fan of for/break/else, and as fan, I discourage it\u0027s use anywhere else.  I don\u0027t see why for/else is needed here, and it makes it look like you could accidentally introduce a control structure edge-case where you break from the loop and return None...","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":126,"context_line":"            except (Exception, TimeoutError):"},{"line_number":127,"context_line":"                exc_type, exc_value, exc_traceback \u003d exc_info()"},{"line_number":128,"context_line":"            sleep(2 ** (attempt + 1))"},{"line_number":129,"context_line":"        else:"},{"line_number":130,"context_line":"            if resp:"},{"line_number":131,"context_line":"                raise Exception(\u0027Unexpected response %s\u0027 % (resp.status,))"},{"line_number":132,"context_line":"            if exc_type:"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5xg%3D","line":129,"in_reply_to":"AAAACX%2F%2F6Sc%3D","updated":"2011-10-29 00:21:01.000000000","message":"I can see your point, but... In this case I\u0027m trying self.retries times to get a good response. If I get a response, but not a good one, I\u0027m raising an exception indicating I got an unexpected response. If I get nothing but exceptions, I\u0027m raising the last one of those I got. I just tried rewriting this several ways, but all I got was even uglier code.","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":128,"context_line":"            sleep(2 ** (attempt + 1))"},{"line_number":129,"context_line":"        else:"},{"line_number":130,"context_line":"            if resp:"},{"line_number":131,"context_line":"                raise Exception(\u0027Unexpected response %s\u0027 % (resp.status,))"},{"line_number":132,"context_line":"            if exc_type:"},{"line_number":133,"context_line":"                raise exc_type, exc_value, exc_traceback"},{"line_number":134,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6Sg%3D","line":131,"updated":"2011-10-27 21:04:25.000000000","message":"i18n.  txn_id of most recently failed attempt?","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":128,"context_line":"            sleep(2 ** (attempt + 1))"},{"line_number":129,"context_line":"        else:"},{"line_number":130,"context_line":"            if resp:"},{"line_number":131,"context_line":"                raise Exception(\u0027Unexpected response %s\u0027 % (resp.status,))"},{"line_number":132,"context_line":"            if exc_type:"},{"line_number":133,"context_line":"                raise exc_type, exc_value, exc_traceback"},{"line_number":134,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5xk%3D","line":131,"in_reply_to":"AAAACX%2F%2F6Sg%3D","updated":"2011-10-29 00:21:01.000000000","message":"txn_id is always included by the logger if not included already. Added the _() part though.","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":866,"name":"Chmouel Boudjnah","email":"chmouel@chmouel.com","username":"chmouel"},"change_message_id":"76e22a53685dab3dfb703c4141036df1830e7656","unresolved":false,"context_lines":[{"line_number":130,"context_line":"            if resp:"},{"line_number":131,"context_line":"                raise Exception(\u0027Unexpected response %s\u0027 % (resp.status,))"},{"line_number":132,"context_line":"            if exc_type:"},{"line_number":133,"context_line":"                raise exc_type, exc_value, exc_traceback"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"    def get_account_info(self):"},{"line_number":136,"context_line":"        resp \u003d self.get_response(\u0027HEAD\u0027,"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6TA%3D","line":133,"updated":"2011-10-27 05:08:59.000000000","message":"I get a PEP8 error on this, needs to be a proper error class..","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":130,"context_line":"            if resp:"},{"line_number":131,"context_line":"                raise Exception(\u0027Unexpected response %s\u0027 % (resp.status,))"},{"line_number":132,"context_line":"            if exc_type:"},{"line_number":133,"context_line":"                raise exc_type, exc_value, exc_traceback"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"    def get_account_info(self):"},{"line_number":136,"context_line":"        resp \u003d self.get_response(\u0027HEAD\u0027,"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5yk%3D","line":133,"in_reply_to":"AAAACX%2F%2F6TA%3D","updated":"2011-10-29 00:21:01.000000000","message":"See https://github.com/jcrocholl/pep8/issues/34 Converting it to  a \"proper\" error class (it already is...) would lose the original stack trace.","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def iter_containers(self):"},{"line_number":144,"context_line":"        path \u003d \u0027/v1/%s?marker\u003d%%s\u0026format\u003djson\u0027 % \\"},{"line_number":145,"context_line":"               (quote(self.expiring_objects_account),)"},{"line_number":146,"context_line":"        marker \u003d \u0027\u0027"},{"line_number":147,"context_line":"        while True:"},{"line_number":148,"context_line":"            resp \u003d self.get_response(\u0027GET\u0027, path % (quote(marker),),"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6TE%3D","line":145,"updated":"2011-10-27 21:04:25.000000000","message":"why create the explicit tuple?  The %%s thing is gross, easier to read if you just build and cat the query string to path in the loop?","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def iter_containers(self):"},{"line_number":144,"context_line":"        path \u003d \u0027/v1/%s?marker\u003d%%s\u0026format\u003djson\u0027 % \\"},{"line_number":145,"context_line":"               (quote(self.expiring_objects_account),)"},{"line_number":146,"context_line":"        marker \u003d \u0027\u0027"},{"line_number":147,"context_line":"        while True:"},{"line_number":148,"context_line":"            resp \u003d self.get_response(\u0027GET\u0027, path % (quote(marker),),"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5xc%3D","line":145,"in_reply_to":"AAAACX%2F%2F6TE%3D","updated":"2011-10-29 00:21:01.000000000","message":"Done","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":180,"context_line":"        self.get_response(\u0027DELETE\u0027,"},{"line_number":181,"context_line":"            \u0027/v1/%s/%s/%s\u0027 % (quote(self.expiring_objects_account),"},{"line_number":182,"context_line":"                              quote(container), quote(obj)),"},{"line_number":183,"context_line":"            {}, (204, 404))"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"    def delete_container(self, container):"},{"line_number":186,"context_line":"        self.get_response(\u0027DELETE\u0027,"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6Ss%3D","line":183,"updated":"2011-10-27 21:04:25.000000000","message":"accept other 2XX status codes?","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":180,"context_line":"        self.get_response(\u0027DELETE\u0027,"},{"line_number":181,"context_line":"            \u0027/v1/%s/%s/%s\u0027 % (quote(self.expiring_objects_account),"},{"line_number":182,"context_line":"                              quote(container), quote(obj)),"},{"line_number":183,"context_line":"            {}, (204, 404))"},{"line_number":184,"context_line":""},{"line_number":185,"context_line":"    def delete_container(self, container):"},{"line_number":186,"context_line":"        self.get_response(\u0027DELETE\u0027,"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5xY%3D","line":183,"in_reply_to":"AAAACX%2F%2F6Ss%3D","updated":"2011-10-29 00:21:01.000000000","message":"Done","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0dd2b8024642bb59e9eaf3c03485b74dade0ac91","unresolved":false,"context_lines":[{"line_number":149,"context_line":"            except (Exception, TimeoutError):"},{"line_number":150,"context_line":"                exc_type, exc_value, exc_traceback \u003d exc_info()"},{"line_number":151,"context_line":"            sleep(2 ** (attempt + 1))"},{"line_number":152,"context_line":"        else:"},{"line_number":153,"context_line":"            if resp:"},{"line_number":154,"context_line":"                raise Exception(_(\u0027Unexpected response %s\u0027) % (resp.status,))"},{"line_number":155,"context_line":"            if exc_type:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAACX%2F%2F5uc%3D","line":152,"updated":"2011-10-29 08:05:53.000000000","message":"But.. But... Just delete the else and shift these lines back 4 spaces - code still works!?  If you were to break 5 lines up and return resp 5 lines below that\u0027d be one thing.\n\nI always think of the \"else\" is a modifier on the \"break\" part of a \"for/break\" - it just doesn\u0027t make sense or belong without the break.\n\nPlease enlighten me if I\u0027m wrong!?","commit_id":"a07f05421d59053121d53caa8a1308ddc9fbb804"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"bbd677576309fd6022e8a77bfc05020229ca9358","unresolved":false,"context_lines":[{"line_number":149,"context_line":"            except (Exception, TimeoutError):"},{"line_number":150,"context_line":"                exc_type, exc_value, exc_traceback \u003d exc_info()"},{"line_number":151,"context_line":"            sleep(2 ** (attempt + 1))"},{"line_number":152,"context_line":"        else:"},{"line_number":153,"context_line":"            if resp:"},{"line_number":154,"context_line":"                raise Exception(_(\u0027Unexpected response %s\u0027) % (resp.status,))"},{"line_number":155,"context_line":"            if exc_type:"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAACX%2F%2F5t4%3D","line":152,"in_reply_to":"AAAACX%2F%2F5uc%3D","updated":"2011-10-29 15:08:36.000000000","message":"Fine.","commit_id":"a07f05421d59053121d53caa8a1308ddc9fbb804"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0dd2b8024642bb59e9eaf3c03485b74dade0ac91","unresolved":false,"context_lines":[{"line_number":153,"context_line":"            if resp:"},{"line_number":154,"context_line":"                raise Exception(_(\u0027Unexpected response %s\u0027) % (resp.status,))"},{"line_number":155,"context_line":"            if exc_type:"},{"line_number":156,"context_line":"                raise exc_type, exc_value, exc_traceback"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"    def get_account_info(self):"},{"line_number":159,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAACX%2F%2F5uY%3D","line":156,"updated":"2011-10-29 08:05:53.000000000","message":"if it was a webob bug we\u0027d work around it, pep8 just wants the parans:\n\nraise exc_type(*exc_value.args), None, exc_traceback\n\n... just saying","commit_id":"a07f05421d59053121d53caa8a1308ddc9fbb804"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"bbd677576309fd6022e8a77bfc05020229ca9358","unresolved":false,"context_lines":[{"line_number":153,"context_line":"            if resp:"},{"line_number":154,"context_line":"                raise Exception(_(\u0027Unexpected response %s\u0027) % (resp.status,))"},{"line_number":155,"context_line":"            if exc_type:"},{"line_number":156,"context_line":"                raise exc_type, exc_value, exc_traceback"},{"line_number":157,"context_line":""},{"line_number":158,"context_line":"    def get_account_info(self):"},{"line_number":159,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAACX%2F%2F5t0%3D","line":156,"in_reply_to":"AAAACX%2F%2F5uY%3D","updated":"2011-10-29 15:08:36.000000000","message":"Actually we\u0027d try to submit a patch to webob, or get webob to fix their bug, failing that we\u0027d make our own patched webob, and failing that we\u0027d work around it.\n\nPerhaps it would be cool if you posted your solution to that bug report? No one had come up with that.\n\nhttps://github.com/jcrocholl/pep8/issues/34\n\nIt does avoid what pep8 checks for, but obviously there\u0027s either a bug in pep8 or your code subverts the spirit of what pep8 wants. :)","commit_id":"a07f05421d59053121d53caa8a1308ddc9fbb804"}],"swift/obj/server.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":498,"context_line":""},{"line_number":499,"context_line":"        if file.is_deleted() or (\u0027X-Delete-At\u0027 in file.metadata and"},{"line_number":500,"context_line":"                int(file.metadata[\u0027X-Delete-At\u0027]) \u003c\u003d time.time()):"},{"line_number":501,"context_line":"            response_class \u003d HTTPNotFound"},{"line_number":502,"context_line":"        else:"},{"line_number":503,"context_line":"            response_class \u003d HTTPAccepted"},{"line_number":504,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6Jk%3D","line":501,"updated":"2011-10-27 21:04:25.000000000","message":"There\u0027s an odd behavior here for object_post_as_copy \u003d false where you can update metadata on an expired-but-not-deleted object (including x-delete-at).","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":498,"context_line":""},{"line_number":499,"context_line":"        if file.is_deleted() or (\u0027X-Delete-At\u0027 in file.metadata and"},{"line_number":500,"context_line":"                int(file.metadata[\u0027X-Delete-At\u0027]) \u003c\u003d time.time()):"},{"line_number":501,"context_line":"            response_class \u003d HTTPNotFound"},{"line_number":502,"context_line":"        else:"},{"line_number":503,"context_line":"            response_class \u003d HTTPAccepted"},{"line_number":504,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5xU%3D","line":501,"in_reply_to":"AAAACX%2F%2F6Jk%3D","updated":"2011-10-29 00:21:01.000000000","message":"Yes, this is weird code. The previous code had this response_class thing as you can see in the diff. The thing was, if an object server got a POST for a file that was currently deleted, it couldn\u0027t really know if it happened to have received the POST before it got a PUT that was after existing DELETE.\n\nSo, it started with:\n\n1.ts\n\nThen got a POST, saved it, but returned 404.\n\n1.ts\n3.meta\n\nThen later got a PUT (out of order):\n\n1.ts\n2.data\n3.meta\n\nThat would ensure it had the newest metadata to go along with the newest PUT.\n\nWeird stuff.\n\nI didn\u0027t want to break that, so, assuming a different scenario of:\n\n1.ts\n\nAnd then a POST with no futher PUT ever (this responds with 404, but saves the data):\n\n1.ts\n3.meta\n\nIf you GET this, it\u0027ll 404 no matter what the X-Delete-At is set to since there is no .data.","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":747,"context_line":"        if \u0027x-if-delete-at\u0027 in request.headers and \\"},{"line_number":748,"context_line":"                int(request.headers[\u0027x-if-delete-at\u0027]) !\u003d \\"},{"line_number":749,"context_line":"                int(file.metadata.get(\u0027X-Delete-At\u0027) or 0):"},{"line_number":750,"context_line":"            return HTTPPreconditionFailed(request\u003drequest)"},{"line_number":751,"context_line":"        orig_timestamp \u003d file.metadata.get(\u0027X-Timestamp\u0027)"},{"line_number":752,"context_line":"        if file.is_deleted():"},{"line_number":753,"context_line":"            response_class \u003d HTTPNotFound"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6GE%3D","line":750,"updated":"2011-10-27 21:04:25.000000000","message":"body message?","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":747,"context_line":"        if \u0027x-if-delete-at\u0027 in request.headers and \\"},{"line_number":748,"context_line":"                int(request.headers[\u0027x-if-delete-at\u0027]) !\u003d \\"},{"line_number":749,"context_line":"                int(file.metadata.get(\u0027X-Delete-At\u0027) or 0):"},{"line_number":750,"context_line":"            return HTTPPreconditionFailed(request\u003drequest)"},{"line_number":751,"context_line":"        orig_timestamp \u003d file.metadata.get(\u0027X-Timestamp\u0027)"},{"line_number":752,"context_line":"        if file.is_deleted():"},{"line_number":753,"context_line":"            response_class \u003d HTTPNotFound"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5xQ%3D","line":750,"in_reply_to":"AAAACX%2F%2F6GE%3D","updated":"2011-10-29 00:21:01.000000000","message":"Done","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0dd2b8024642bb59e9eaf3c03485b74dade0ac91","unresolved":false,"context_lines":[{"line_number":502,"context_line":"        else:"},{"line_number":503,"context_line":"            response_class \u003d HTTPAccepted"},{"line_number":504,"context_line":"        try:"},{"line_number":505,"context_line":"            file_size \u003d file.get_data_file_size()"},{"line_number":506,"context_line":"        except (DiskFileError, DiskFileNotExist):"},{"line_number":507,"context_line":"            file.quarantine()"},{"line_number":508,"context_line":"            return HTTPNotFound(request\u003drequest)"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAACX%2F%2F5uQ%3D","line":505,"updated":"2011-10-29 08:05:53.000000000","message":"dfg and I looked at this... In scenario #1 if it starts with a .ts - it blows up here cause file.__init__ set\u0027s data_file to None and .get_data_file_size raises an Exception.  I could see the original intent, but I couldn\u0027t get it work that way.\n\nBut in the case of x-delete-at, and post-as-copy\u003dfalse - get_data_file_size won\u0027t blow up because you have an \"expired-but-not-deleted\" data - so now you _can_ still update the meta even tho it 404\u0027s.\n\nso that leaves this:\n\nAll nodes have:\n\n1.data (expired)\n\nnodes 1\u00262 receive POST with new X-Delete-At in the future (but expirer already has it\u0027s listings and is on it\u0027s way) - Response is 404, but new X-Delete-At is written, subsequent requests will 200!\n\n1.data 2.meta\n\nDELETE from expirer\nnodes 1\u00262\u0027s new x-delete-at/x-if-delete-at rejects the delete, 412\n\nBut on node 3 I missed the POST, and accept the expirer\u0027s DELETE\n\n1.data 3.ts\n\nNote the expirer probably gets a 500 here because only one node accepted the DELETE.\n\nbut regardless, on consistent:\n\n1.data 2.meta 3.ts\n\nI\u0027m not sure how I\u0027d work around for now.  I guess I\u0027m ok if you to save for future - or just deprecate post_as_copy \u003d false?","commit_id":"a07f05421d59053121d53caa8a1308ddc9fbb804"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"bbd677576309fd6022e8a77bfc05020229ca9358","unresolved":false,"context_lines":[{"line_number":502,"context_line":"        else:"},{"line_number":503,"context_line":"            response_class \u003d HTTPAccepted"},{"line_number":504,"context_line":"        try:"},{"line_number":505,"context_line":"            file_size \u003d file.get_data_file_size()"},{"line_number":506,"context_line":"        except (DiskFileError, DiskFileNotExist):"},{"line_number":507,"context_line":"            file.quarantine()"},{"line_number":508,"context_line":"            return HTTPNotFound(request\u003drequest)"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAACX%2F%2F5tw%3D","line":505,"in_reply_to":"AAAACX%2F%2F5uQ%3D","updated":"2011-10-29 15:08:36.000000000","message":"Hmmm, gotcha. I was doing my best to not break whatever was there before, but how about I just immediately 404 with x-delete-at expiration and we fix/verify whatever the rest is later?","commit_id":"a07f05421d59053121d53caa8a1308ddc9fbb804"},{"author":{"_account_id":995,"name":"David Goetz","email":"david.goetz@rackspace.com","username":"david-goetz"},"change_message_id":"502eef97e6c73c9f6fadc00dcc9c7e56d2fddac9","unresolved":false,"context_lines":[{"line_number":496,"context_line":"        file \u003d DiskFile(self.devices, device, partition, account, container,"},{"line_number":497,"context_line":"                        obj, self.logger, disk_chunk_size\u003dself.disk_chunk_size)"},{"line_number":498,"context_line":""},{"line_number":499,"context_line":"        if file.is_deleted() or (\u0027X-Delete-At\u0027 in file.metadata and"},{"line_number":500,"context_line":"                int(file.metadata[\u0027X-Delete-At\u0027]) \u003c\u003d time.time()):"},{"line_number":501,"context_line":"            response_class \u003d HTTPNotFound"},{"line_number":502,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAACX%2F%2F5og%3D","line":499,"updated":"2011-10-31 19:24:28.000000000","message":"not a big deal but this may be easier to read.  instead of:\n\nif file.is_deleted() or (\u0027X-Delete-At\u0027 in file.metadata and\n                int(file.metadata[\u0027X-Delete-At\u0027]) \u003c\u003d time.time()):\n    response_class \u003d HTTPNotFound\nelse:\n    response_class \u003d HTTPAccepted\nif \u0027X-Delete-At\u0027 in file.metadata and \\\n                int(file.metadata[\u0027X-Delete-At\u0027]) \u003c\u003d time.time():\n    return HTTPNotFound(request\u003drequest)\n\ndo this:\n\nif \u0027X-Delete-At\u0027 in file.metadata and \\\n                int(file.metadata[\u0027X-Delete-At\u0027]) \u003c\u003d time.time():\n    return HTTPNotFound(request\u003drequest)\n\nif file.is_deleted():\n    response_class \u003d HTTPNotFound\nelse:\n    response_class \u003d HTTPAccepted","commit_id":"5061dc38f175bc2876e79239e5053ee0bbe0b9f9"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"fbf508dfcbe822328939874c79269ab9cbf0ee9f","unresolved":false,"context_lines":[{"line_number":496,"context_line":"        file \u003d DiskFile(self.devices, device, partition, account, container,"},{"line_number":497,"context_line":"                        obj, self.logger, disk_chunk_size\u003dself.disk_chunk_size)"},{"line_number":498,"context_line":""},{"line_number":499,"context_line":"        if file.is_deleted() or (\u0027X-Delete-At\u0027 in file.metadata and"},{"line_number":500,"context_line":"                int(file.metadata[\u0027X-Delete-At\u0027]) \u003c\u003d time.time()):"},{"line_number":501,"context_line":"            response_class \u003d HTTPNotFound"},{"line_number":502,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAACX%2F%2F5bU%3D","line":499,"in_reply_to":"AAAACX%2F%2F5og%3D","updated":"2011-11-01 15:48:53.000000000","message":"Yeah, I\u0027m not sure what happened there; fixed.","commit_id":"5061dc38f175bc2876e79239e5053ee0bbe0b9f9"}],"swift/proxy/server.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":64,"context_line":"        if name \u003d\u003d \u0027etag\u0027:"},{"line_number":65,"context_line":"            response.headers[name] \u003d value.replace(\u0027\"\u0027, \u0027\u0027)"},{"line_number":66,"context_line":"        elif name not in (\u0027date\u0027, \u0027content-length\u0027, \u0027content-type\u0027,"},{"line_number":67,"context_line":"                          \u0027connection\u0027, \u0027x-timestamp\u0027, \u0027x-put-timestamp\u0027):"},{"line_number":68,"context_line":"            response.headers[name] \u003d value"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6GA%3D","side":"PARENT","line":67,"updated":"2011-10-27 21:04:25.000000000","message":"add x-if-delete-after here?  It\u0027s kind of a weird feature to expose to users.  And the precondition error message is kinda generic...","commit_id":"ef75e14741aab9d58c806554c42e474e491ae0db"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":64,"context_line":"        if name \u003d\u003d \u0027etag\u0027:"},{"line_number":65,"context_line":"            response.headers[name] \u003d value.replace(\u0027\"\u0027, \u0027\u0027)"},{"line_number":66,"context_line":"        elif name not in (\u0027date\u0027, \u0027content-length\u0027, \u0027content-type\u0027,"},{"line_number":67,"context_line":"                          \u0027connection\u0027, \u0027x-timestamp\u0027, \u0027x-put-timestamp\u0027):"},{"line_number":68,"context_line":"            response.headers[name] \u003d value"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5xM%3D","side":"PARENT","line":67,"in_reply_to":"AAAACX%2F%2F6GA%3D","updated":"2011-10-29 00:21:01.000000000","message":"I think you meant add X-Delete-After since X-If-Delete-After is never returned in a response.","commit_id":"ef75e14741aab9d58c806554c42e474e491ae0db"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":1072,"context_line":"                _(\u0027Object PUT returning 503, %(conns)s/%(nodes)s \u0027"},{"line_number":1073,"context_line":"                \u0027required connections\u0027),"},{"line_number":1074,"context_line":"                {\u0027conns\u0027: len(conns), \u0027nodes\u0027: len(nodes) // 2 + 1})"},{"line_number":1075,"context_line":"            return HTTPServiceUnavailable(request\u003dreq)"},{"line_number":1076,"context_line":"        chunked \u003d req.headers.get(\u0027transfer-encoding\u0027)"},{"line_number":1077,"context_line":"        try:"},{"line_number":1078,"context_line":"            with ContextPool(len(nodes)) as pool:"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6GI%3D","side":"PARENT","line":1075,"updated":"2011-10-27 21:04:25.000000000","message":"400\u0027s on PUTs to the object-server don\u0027t seem to come back out to the user since they don\u0027t get added to the conns pool (100-continue and all that...)\n\nI know for GETs we try to let those 400\u0027s propagate out, on a PUT maybe it\u0027s more reasonable to see invalid data/headers going to the object-server as a bug in the proxy?\n\nNot sure here, but it\u0027s currently broken.","commit_id":"ef75e14741aab9d58c806554c42e474e491ae0db"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":1072,"context_line":"                _(\u0027Object PUT returning 503, %(conns)s/%(nodes)s \u0027"},{"line_number":1073,"context_line":"                \u0027required connections\u0027),"},{"line_number":1074,"context_line":"                {\u0027conns\u0027: len(conns), \u0027nodes\u0027: len(nodes) // 2 + 1})"},{"line_number":1075,"context_line":"            return HTTPServiceUnavailable(request\u003dreq)"},{"line_number":1076,"context_line":"        chunked \u003d req.headers.get(\u0027transfer-encoding\u0027)"},{"line_number":1077,"context_line":"        try:"},{"line_number":1078,"context_line":"            with ContextPool(len(nodes)) as pool:"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5w8%3D","side":"PARENT","line":1075,"in_reply_to":"AAAACX%2F%2F6GI%3D","updated":"2011-10-29 00:21:01.000000000","message":"What you describe is a more general problem and should probably be a separate commit. Fixing the x-delete-at-in-past as a 400 earlier as you suggested fixes the immediate problem.","commit_id":"ef75e14741aab9d58c806554c42e474e491ae0db"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":1000,"context_line":"                x_delete_at \u003d int(req.headers[\u0027x-delete-at\u0027])"},{"line_number":1001,"context_line":"            except ValueError:"},{"line_number":1002,"context_line":"                return HTTPBadRequest(request\u003dreq, content_type\u003d\u0027text/plain\u0027,"},{"line_number":1003,"context_line":"                                      body\u003d\u0027Non-integer X-Delete-At\u0027)"},{"line_number":1004,"context_line":"            delete_at_container \u003d str(x_delete_at /"},{"line_number":1005,"context_line":"                self.app.expiring_objects_container_divisor *"},{"line_number":1006,"context_line":"                self.app.expiring_objects_container_divisor)"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6Gk%3D","line":1003,"updated":"2011-10-27 21:04:25.000000000","message":"x-delete-at in past seems to trigger 503, maybe precheck here.","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":1000,"context_line":"                x_delete_at \u003d int(req.headers[\u0027x-delete-at\u0027])"},{"line_number":1001,"context_line":"            except ValueError:"},{"line_number":1002,"context_line":"                return HTTPBadRequest(request\u003dreq, content_type\u003d\u0027text/plain\u0027,"},{"line_number":1003,"context_line":"                                      body\u003d\u0027Non-integer X-Delete-At\u0027)"},{"line_number":1004,"context_line":"            delete_at_container \u003d str(x_delete_at /"},{"line_number":1005,"context_line":"                self.app.expiring_objects_container_divisor *"},{"line_number":1006,"context_line":"                self.app.expiring_objects_container_divisor)"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5xA%3D","line":1003,"in_reply_to":"AAAACX%2F%2F6Gk%3D","updated":"2011-10-29 00:21:01.000000000","message":"Done","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0dd2b8024642bb59e9eaf3c03485b74dade0ac91","unresolved":false,"context_lines":[{"line_number":65,"context_line":"            response.headers[name] \u003d value.replace(\u0027\"\u0027, \u0027\u0027)"},{"line_number":66,"context_line":"        elif name not in (\u0027date\u0027, \u0027content-length\u0027, \u0027content-type\u0027,"},{"line_number":67,"context_line":"                          \u0027connection\u0027, \u0027x-timestamp\u0027, \u0027x-put-timestamp\u0027,"},{"line_number":68,"context_line":"                          \u0027x-delete-after\u0027):"},{"line_number":69,"context_line":"            response.headers[name] \u003d value"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAACX%2F%2F5uM%3D","line":68,"updated":"2011-10-29 08:05:53.000000000","message":"That\u0027s so sweet to give me the benefit of the doubt.  No I was actually thinking about REQUEST headers that we don\u0027t want the user to be able to send - but now I\u0027m not even sure how to do that since the expirer actually uses the proxy app.\n\nDoesn\u0027t matter, might be nice to add a body to the \u0027x-delete-at !\u003d x-if-delete-at\u0027 412 in the object-server, but I think it\u0027s probably ok to let someone try and take advantage of the new \u0027x-if-delete-at\u0027 header if they can come up with a use-case...","commit_id":"a07f05421d59053121d53caa8a1308ddc9fbb804"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"bbd677576309fd6022e8a77bfc05020229ca9358","unresolved":false,"context_lines":[{"line_number":65,"context_line":"            response.headers[name] \u003d value.replace(\u0027\"\u0027, \u0027\u0027)"},{"line_number":66,"context_line":"        elif name not in (\u0027date\u0027, \u0027content-length\u0027, \u0027content-type\u0027,"},{"line_number":67,"context_line":"                          \u0027connection\u0027, \u0027x-timestamp\u0027, \u0027x-put-timestamp\u0027,"},{"line_number":68,"context_line":"                          \u0027x-delete-after\u0027):"},{"line_number":69,"context_line":"            response.headers[name] \u003d value"},{"line_number":70,"context_line":""},{"line_number":71,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAACX%2F%2F5ts%3D","line":68,"in_reply_to":"AAAACX%2F%2F5uM%3D","updated":"2011-10-29 15:08:36.000000000","message":"I\u0027ll add the bodies to the 412s I\u0027ve added (there are existing ones there that didn\u0027t have them yet, but I don\u0027t want this patch to ballon any further if I can help it) and we\u0027ll have to fix that 4xxs don\u0027t get returned from make_requests or whatever later.","commit_id":"a07f05421d59053121d53caa8a1308ddc9fbb804"},{"author":{"_account_id":995,"name":"David Goetz","email":"david.goetz@rackspace.com","username":"david-goetz"},"change_message_id":"502eef97e6c73c9f6fadc00dcc9c7e56d2fddac9","unresolved":false,"context_lines":[{"line_number":883,"context_line":"    @delay_denial"},{"line_number":884,"context_line":"    def POST(self, req):"},{"line_number":885,"context_line":"        \"\"\"HTTP POST request handler.\"\"\""},{"line_number":886,"context_line":"        if \u0027x-delete-after\u0027 in req.headers:"},{"line_number":887,"context_line":"            req.headers[\u0027x-delete-at\u0027] \u003d \\"},{"line_number":888,"context_line":"                \u0027%d\u0027 % (time.time() + int(req.headers[\u0027x-delete-after\u0027]))"},{"line_number":889,"context_line":"        if self.app.object_post_as_copy:"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAACX%2F%2F5ok%3D","line":886,"updated":"2011-10-31 19:24:28.000000000","message":"this has the 500 on non int stuff (sorry didn\u0027t see it earlier)","commit_id":"5061dc38f175bc2876e79239e5053ee0bbe0b9f9"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"fbf508dfcbe822328939874c79269ab9cbf0ee9f","unresolved":false,"context_lines":[{"line_number":883,"context_line":"    @delay_denial"},{"line_number":884,"context_line":"    def POST(self, req):"},{"line_number":885,"context_line":"        \"\"\"HTTP POST request handler.\"\"\""},{"line_number":886,"context_line":"        if \u0027x-delete-after\u0027 in req.headers:"},{"line_number":887,"context_line":"            req.headers[\u0027x-delete-at\u0027] \u003d \\"},{"line_number":888,"context_line":"                \u0027%d\u0027 % (time.time() + int(req.headers[\u0027x-delete-after\u0027]))"},{"line_number":889,"context_line":"        if self.app.object_post_as_copy:"}],"source_content_type":"text/x-python","patch_set":4,"id":"AAAACX%2F%2F5bI%3D","line":886,"in_reply_to":"AAAACX%2F%2F5ok%3D","updated":"2011-11-01 15:48:53.000000000","message":"Done","commit_id":"5061dc38f175bc2876e79239e5053ee0bbe0b9f9"}],"test/unit/obj/test_expirer.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":19,"context_line":"from unittest import main, TestCase"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from swift.obj import expirer"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"def not_random():"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6LQ%3D","line":22,"updated":"2011-10-27 21:04:25.000000000","message":"To run stand-alone need to mock utils.HASH_PATH_SUFFIX and use fake rings.","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":19,"context_line":"from unittest import main, TestCase"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from swift.obj import expirer"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"def not_random():"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5w4%3D","line":22,"in_reply_to":"AAAACX%2F%2F6LQ%3D","updated":"2011-10-29 00:21:01.000000000","message":"I didn\u0027t need the utils.HASH_PATH_SUFFIX thing since this stuff doesn\u0027t care what the ring does, but FakeRings are in use now.","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"}],"test/unit/obj/test_server.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8b538f5c9a2427b5bc7a8239d354a28d9ab227e8","unresolved":false,"context_lines":[{"line_number":1805,"context_line":"        resp \u003d self.object_controller.GET(req)"},{"line_number":1806,"context_line":"        self.assertEquals(resp.status_int, 200)"},{"line_number":1807,"context_line":""},{"line_number":1808,"context_line":"        sleep(2)  # To get past the x-delete-at time"},{"line_number":1809,"context_line":""},{"line_number":1810,"context_line":"        req \u003d Request.blank(\u0027/sda1/p/a/c/o\u0027, environ\u003d{\u0027REQUEST_METHOD\u0027: \u0027GET\u0027},"},{"line_number":1811,"context_line":"            headers\u003d{\u0027X-Timestamp\u0027: normalize_timestamp(time())})"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F6SU%3D","line":1808,"updated":"2011-10-27 21:04:25.000000000","message":"time nosetests test/unit/obj/test_server.py\nruns like 6 seconds faster for me on master - there are a number of other tests that mock time...","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"903a76018a7e59b9a3e4067a10b84339d9968241","unresolved":false,"context_lines":[{"line_number":1805,"context_line":"        resp \u003d self.object_controller.GET(req)"},{"line_number":1806,"context_line":"        self.assertEquals(resp.status_int, 200)"},{"line_number":1807,"context_line":""},{"line_number":1808,"context_line":"        sleep(2)  # To get past the x-delete-at time"},{"line_number":1809,"context_line":""},{"line_number":1810,"context_line":"        req \u003d Request.blank(\u0027/sda1/p/a/c/o\u0027, environ\u003d{\u0027REQUEST_METHOD\u0027: \u0027GET\u0027},"},{"line_number":1811,"context_line":"            headers\u003d{\u0027X-Timestamp\u0027: normalize_timestamp(time())})"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAACX%2F%2F5w0%3D","line":1808,"in_reply_to":"AAAACX%2F%2F6SU%3D","updated":"2011-10-29 00:21:01.000000000","message":"Done","commit_id":"097342ec5bd78ad37bb691dfa5f2e60b80d8eefa"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0dd2b8024642bb59e9eaf3c03485b74dade0ac91","unresolved":false,"context_lines":[{"line_number":1887,"context_line":"        resp \u003d self.object_controller.PUT(req)"},{"line_number":1888,"context_line":"        self.assertEquals(resp.status_int, 201)"},{"line_number":1889,"context_line":""},{"line_number":1890,"context_line":"        sleep(2)  # To get past the x-delete-at time"},{"line_number":1891,"context_line":""},{"line_number":1892,"context_line":"        req \u003d Request.blank(\u0027/sda1/p/a/c/o\u0027,"},{"line_number":1893,"context_line":"            environ\u003d{\u0027REQUEST_METHOD\u0027: \u0027POST\u0027},"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAACX%2F%2F5uE%3D","line":1890,"updated":"2011-10-29 08:05:53.000000000","message":"missed one?","commit_id":"a07f05421d59053121d53caa8a1308ddc9fbb804"},{"author":{"_account_id":1216,"name":"gholt","email":"z-launchpad@brim.net","username":"gholt"},"change_message_id":"bbd677576309fd6022e8a77bfc05020229ca9358","unresolved":false,"context_lines":[{"line_number":1887,"context_line":"        resp \u003d self.object_controller.PUT(req)"},{"line_number":1888,"context_line":"        self.assertEquals(resp.status_int, 201)"},{"line_number":1889,"context_line":""},{"line_number":1890,"context_line":"        sleep(2)  # To get past the x-delete-at time"},{"line_number":1891,"context_line":""},{"line_number":1892,"context_line":"        req \u003d Request.blank(\u0027/sda1/p/a/c/o\u0027,"},{"line_number":1893,"context_line":"            environ\u003d{\u0027REQUEST_METHOD\u0027: \u0027POST\u0027},"}],"source_content_type":"text/x-python","patch_set":3,"id":"AAAACX%2F%2F5tk%3D","line":1890,"in_reply_to":"AAAACX%2F%2F5uE%3D","updated":"2011-10-29 15:08:36.000000000","message":"Damn. I thought there were only two of them when I started. They must\u0027ve been replicating when I wasn\u0027t looking.","commit_id":"a07f05421d59053121d53caa8a1308ddc9fbb804"}]}
