)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":38496,"name":"Andressa Cabistani","display_name":"Andressa","email":"acabistani@gmail.com","username":"andressadotpy","status":"I\u0027m a Software Engineer at Red Hat and I love Open Source and connect with people! Feel free to DM through IRC, I\u0027ll be delighted to chat"},"change_message_id":"51b024cb7d49308083bd7c2440b2066d05240a4d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":18,"id":"862ad697_7d98199b","updated":"2026-09-30 12:16:33.000000000","message":"I reviewed this against PS18 on a VSAIO with Claude\u0027s help to write scripts to verify the findings. The lock decomposition is the right call and it\u0027s the part I\u0027d most like to see land. I believe there\u0027s still a bit of work to be done but I can\u0027t wait to re-review it soon!","commit_id":"a7328065033c3eba644ee647dc691caaa197631a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"948578af213905e47519fec008bde8eb6f9b33bd","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":18,"id":"855bd6fe_d89e33b7","updated":"2026-09-29 03:26:55.000000000","message":"Maybe it\u0027s the `blocking\u003dFalse` that\u0027s causing the probe test failures? I still can\u0027t repro locally...","commit_id":"a7328065033c3eba644ee647dc691caaa197631a"},{"author":{"_account_id":38368,"name":"Christian Ohanaja","display_name":"Christian Ohanaja","email":"cohanaja@nvidia.com","username":"cohanaja"},"change_message_id":"b4d30348a2f55bde6d040737b84ff9cf2e065571","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":18,"id":"6e2be1f1_14e0c429","updated":"2026-09-30 07:38:23.000000000","message":"Not gonna make code-level comments on the patch just yet... (was busy through the day, the patch is def readable I just haven\u0027t sat down to do so!)\n\nBut a particular thing I was wondering about:\n\nwhy do we base the cap of pending file on actual file size, rather than rows? For your testing, I\u0027m unsure of what like length the names of the objects you\u0027re PUTting into the containers via the container server, but one fun fact I\u0027ve learned over looking at some of the objects in our clusters is that our names are long!! Like you could super easily pick out some objects with name lengths of like 180-250 chars, which doesn\u0027t sound like much at all initially but it adds up like crazy. \n\n```\n\u003e doing some napkin math, how big of a difference in KB would two pending file DBs (assuming there was no cap) have if we had 100k objects, but one db had 30-char length objs, while the other had 200 length?\n\n\tPer entry\t100k entries\n30-char names\t197 bytes\t~19,700 KB (19.7 MB)\n200-char names\t425 bytes\t~42,500 KB (42.5 MB)\nDifference\t228 bytes\t~22,800 KB (22.8 MB)\n\n\u003e thanks clawd\n```\n\nThe way I see it, in scenarios where names are long like for directory objects, performance degrades pretty hard and we\u0027d have to drain the dbs pretty often, which would cause even more issues now that there\u0027re multiple that have to do the locking song and dance (that I still need to actually read up on)\n\nMy benchmarking scripts (i have a patch up with them! 🤓) gave me trouble when I used longer names (217 chars to match some prod scenarios) because I lowkey started running out of SAIO disk space enough times to make me have to sit down and go through the rigmarole of resizing disks\n\nI\u0027m sure there\u0027s great reasoning behind the pending cap being in size rather than pending count (save disk space probs), I just think the current way we have things may be causing some perf troubles","commit_id":"a7328065033c3eba644ee647dc691caaa197631a"}],"swift/common/db.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f94b29ee1190860a7aedd64ba054c6ef809a3ab8","unresolved":true,"context_lines":[{"line_number":93,"context_line":"            return []"},{"line_number":94,"context_line":"        raise"},{"line_number":95,"context_line":"    if not files:"},{"line_number":96,"context_line":"        return []"},{"line_number":97,"context_line":"    results \u003d []"},{"line_number":98,"context_line":"    for f in files:"},{"line_number":99,"context_line":"        _root, ext \u003d os.path.splitext(f)"}],"source_content_type":"text/x-python","patch_set":8,"id":"8af9a0d6_3b0288af","line":96,"updated":"2022-03-24 23:30:31.000000000","message":"nit: We could drop this clause -- it\u0027ll get handled by the for loop anyway,","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"6da015605349bf6e143dc3a6f03f425758c34412","unresolved":false,"context_lines":[{"line_number":93,"context_line":"            return []"},{"line_number":94,"context_line":"        raise"},{"line_number":95,"context_line":"    if not files:"},{"line_number":96,"context_line":"        return []"},{"line_number":97,"context_line":"    results \u003d []"},{"line_number":98,"context_line":"    for f in files:"},{"line_number":99,"context_line":"        _root, ext \u003d os.path.splitext(f)"}],"source_content_type":"text/x-python","patch_set":8,"id":"0aa11cc7_44bb5ac0","line":96,"in_reply_to":"8af9a0d6_3b0288af","updated":"2022-03-25 05:37:41.000000000","message":"Done","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f94b29ee1190860a7aedd64ba054c6ef809a3ab8","unresolved":true,"context_lines":[{"line_number":353,"context_line":"        self.conn \u003d None"},{"line_number":354,"context_line":"        self._db_file \u003d db_file"},{"line_number":355,"context_line":"        if not pending_shards:"},{"line_number":356,"context_line":"            pending_shards \u003d 1"},{"line_number":357,"context_line":"        self.pending_files \u003d ["},{"line_number":358,"context_line":"            get_zero_indexed_base_string(self._db_file, i) + \u0027.pending\u0027"},{"line_number":359,"context_line":"            for i in range(pending_shards)]"}],"source_content_type":"text/x-python","patch_set":8,"id":"b6e92f6e_63ea5429","line":356,"updated":"2022-03-24 23:30:31.000000000","message":"When would we pass in a False-y pending_shards value? Or are we just being defensive?","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"6da015605349bf6e143dc3a6f03f425758c34412","unresolved":true,"context_lines":[{"line_number":353,"context_line":"        self.conn \u003d None"},{"line_number":354,"context_line":"        self._db_file \u003d db_file"},{"line_number":355,"context_line":"        if not pending_shards:"},{"line_number":356,"context_line":"            pending_shards \u003d 1"},{"line_number":357,"context_line":"        self.pending_files \u003d ["},{"line_number":358,"context_line":"            get_zero_indexed_base_string(self._db_file, i) + \u0027.pending\u0027"},{"line_number":359,"context_line":"            for i in range(pending_shards)]"}],"source_content_type":"text/x-python","patch_set":8,"id":"e0e828f4_aee5cbdb","line":356,"in_reply_to":"b6e92f6e_63ea5429","updated":"2022-03-25 05:37:41.000000000","message":"Just being defensive. But happy to remove it if we \"trust\" ourselves :P","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f94b29ee1190860a7aedd64ba054c6ef809a3ab8","unresolved":true,"context_lines":[{"line_number":820,"context_line":"            if err.errno !\u003d errno.ENOENT:"},{"line_number":821,"context_line":"                raise"},{"line_number":822,"context_line":"        if pending_size \u003e PENDING_CAP:"},{"line_number":823,"context_line":"            with lock_parent_directory("},{"line_number":824,"context_line":"                    self.pending_files[0],"},{"line_number":825,"context_line":"                    self.pending_timeout, blocking\u003dFalse) as locked:"},{"line_number":826,"context_line":"                if locked:"}],"source_content_type":"text/x-python","patch_set":8,"id":"3cfd8d3b_2b7feea8","line":823,"updated":"2022-03-24 23:30:31.000000000","message":"What happens if somebody takes this lock and dies/hangs so it\u0027s never released? Currently on master, we\u0027ll start seeing a ton of lock timeouts popping, which\u0027ll be a decent signal to ops to investigate -- restart container-server and if that doesn\u0027t fix it, reboot the node.\n\nAs it is, looks like we\u0027ll just balloon the many pending files...\n\nMaybe we could do something with skipping any pending files that are already at the cap, and throwing an error if that means we don\u0027t have anywhere left to put it?","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"6da015605349bf6e143dc3a6f03f425758c34412","unresolved":true,"context_lines":[{"line_number":820,"context_line":"            if err.errno !\u003d errno.ENOENT:"},{"line_number":821,"context_line":"                raise"},{"line_number":822,"context_line":"        if pending_size \u003e PENDING_CAP:"},{"line_number":823,"context_line":"            with lock_parent_directory("},{"line_number":824,"context_line":"                    self.pending_files[0],"},{"line_number":825,"context_line":"                    self.pending_timeout, blocking\u003dFalse) as locked:"},{"line_number":826,"context_line":"                if locked:"}],"source_content_type":"text/x-python","patch_set":8,"id":"7a14054b_b706fc5a","line":823,"in_reply_to":"3cfd8d3b_2b7feea8","updated":"2022-03-25 05:37:41.000000000","message":"Good idea. I\u0027ll raise an error for now. Another option is to allow them to balloon but once they get bigger then the pending_cap start logging a warning for OPs.","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f94b29ee1190860a7aedd64ba054c6ef809a3ab8","unresolved":true,"context_lines":[{"line_number":871,"context_line":"        for pending_file, size in zip(pending_files, pending_sizes):"},{"line_number":872,"context_line":"            if not size:"},{"line_number":873,"context_line":"                continue"},{"line_number":874,"context_line":"            with lock_file(pending_file, unlink\u003dFalse) as fp:"},{"line_number":875,"context_line":"                for entry in fp.read().split(b\u0027:\u0027):"},{"line_number":876,"context_line":"                    if entry:"},{"line_number":877,"context_line":"                        try:"}],"source_content_type":"text/x-python","patch_set":8,"id":"c83c3be0_164d8324","line":874,"updated":"2022-03-24 23:30:31.000000000","message":"What happens when one of these times out?","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdf2492b5a01520f21491218f4d1af3139f10d17","unresolved":true,"context_lines":[{"line_number":871,"context_line":"        for pending_file, size in zip(pending_files, pending_sizes):"},{"line_number":872,"context_line":"            if not size:"},{"line_number":873,"context_line":"                continue"},{"line_number":874,"context_line":"            with lock_file(pending_file, unlink\u003dFalse) as fp:"},{"line_number":875,"context_line":"                for entry in fp.read().split(b\u0027:\u0027):"},{"line_number":876,"context_line":"                    if entry:"},{"line_number":877,"context_line":"                        try:"}],"source_content_type":"text/x-python","patch_set":8,"id":"51690974_28d30e0d","line":874,"in_reply_to":"9efe5139_0495ee0e","updated":"2022-03-28 05:49:23.000000000","message":"So my thinking was, if we\n\n* process one pending file, merging its items with the one we just got from the client,\n* call merge_items() to get all that into the DB, but then\n* pop a lock timeout on the next pending file\n\nwe return an error to the client even though we *could* justifiably return success. The trouble, of course, is differentiating it (as a caller) from the case when the timeout pops on the first file (so we *haven\u0027t* written down the client\u0027s row).\n\nI\u0027m probably just over-thinking it, though -- we definitely want \"all succeed or raise a timeout\" behavior in the read path, for example, so it\u0027s probably best \u0026 simplest to impose that everywhere. I was just thinking about whether the new partial-failure case might warrant different handling in some cases.","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"6da015605349bf6e143dc3a6f03f425758c34412","unresolved":true,"context_lines":[{"line_number":871,"context_line":"        for pending_file, size in zip(pending_files, pending_sizes):"},{"line_number":872,"context_line":"            if not size:"},{"line_number":873,"context_line":"                continue"},{"line_number":874,"context_line":"            with lock_file(pending_file, unlink\u003dFalse) as fp:"},{"line_number":875,"context_line":"                for entry in fp.read().split(b\u0027:\u0027):"},{"line_number":876,"context_line":"                    if entry:"},{"line_number":877,"context_line":"                        try:"}],"source_content_type":"text/x-python","patch_set":8,"id":"9efe5139_0495ee0e","line":874,"in_reply_to":"c83c3be0_164d8324","updated":"2022-03-25 05:37:41.000000000","message":"hmm, I hope we get it next time?","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f94b29ee1190860a7aedd64ba054c6ef809a3ab8","unresolved":true,"context_lines":[{"line_number":886,"context_line":"                                _(\u0027Invalid pending entry %(file)s: %(entry)s\u0027),"},{"line_number":887,"context_line":"                                {\u0027file\u0027: pending_file, \u0027entry\u0027: entry})"},{"line_number":888,"context_line":"                            # TODO(matt) Instead of bombing out maybe continue"},{"line_number":889,"context_line":"                            #  with the next pending file?"},{"line_number":890,"context_line":"                if item_list:"},{"line_number":891,"context_line":"                    self.merge_items(item_list)"},{"line_number":892,"context_line":"                try:"}],"source_content_type":"text/x-python","patch_set":8,"id":"1cd3ab76_be5dc8b1","line":889,"updated":"2022-03-24 23:30:31.000000000","message":"We don\u0027t bomb out, though -- we just skip this entry.\n\n*Does* make me think that logger.exception() probably isn\u0027t appropriate, though -- there isn\u0027t much of anything the stack trace will tell us that we couldn\u0027t pick up from the distinctive error message. Might could use a reference to the actual error, though.","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"6da015605349bf6e143dc3a6f03f425758c34412","unresolved":false,"context_lines":[{"line_number":886,"context_line":"                                _(\u0027Invalid pending entry %(file)s: %(entry)s\u0027),"},{"line_number":887,"context_line":"                                {\u0027file\u0027: pending_file, \u0027entry\u0027: entry})"},{"line_number":888,"context_line":"                            # TODO(matt) Instead of bombing out maybe continue"},{"line_number":889,"context_line":"                            #  with the next pending file?"},{"line_number":890,"context_line":"                if item_list:"},{"line_number":891,"context_line":"                    self.merge_items(item_list)"},{"line_number":892,"context_line":"                try:"}],"source_content_type":"text/x-python","patch_set":8,"id":"99021399_88e3df9e","line":889,"in_reply_to":"1cd3ab76_be5dc8b1","updated":"2022-03-25 05:37:41.000000000","message":"Ack","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f94b29ee1190860a7aedd64ba054c6ef809a3ab8","unresolved":true,"context_lines":[{"line_number":888,"context_line":"                            # TODO(matt) Instead of bombing out maybe continue"},{"line_number":889,"context_line":"                            #  with the next pending file?"},{"line_number":890,"context_line":"                if item_list:"},{"line_number":891,"context_line":"                    self.merge_items(item_list)"},{"line_number":892,"context_line":"                try:"},{"line_number":893,"context_line":"                    os.ftruncate(fp.fileno(), 0)"},{"line_number":894,"context_line":"                except OSError as err:"}],"source_content_type":"text/x-python","patch_set":8,"id":"3df5aed6_ce32d702","line":891,"updated":"2022-03-24 23:30:31.000000000","message":"We should clear item_list once we call merge_items to avoid quadratic behaviors.","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"6da015605349bf6e143dc3a6f03f425758c34412","unresolved":false,"context_lines":[{"line_number":888,"context_line":"                            # TODO(matt) Instead of bombing out maybe continue"},{"line_number":889,"context_line":"                            #  with the next pending file?"},{"line_number":890,"context_line":"                if item_list:"},{"line_number":891,"context_line":"                    self.merge_items(item_list)"},{"line_number":892,"context_line":"                try:"},{"line_number":893,"context_line":"                    os.ftruncate(fp.fileno(), 0)"},{"line_number":894,"context_line":"                except OSError as err:"}],"source_content_type":"text/x-python","patch_set":8,"id":"35497aa2_20d77d28","line":891,"in_reply_to":"3df5aed6_ce32d702","updated":"2022-03-25 05:37:41.000000000","message":"Done","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f94b29ee1190860a7aedd64ba054c6ef809a3ab8","unresolved":true,"context_lines":[{"line_number":903,"context_line":"        if self._skip_commit_puts():"},{"line_number":904,"context_line":"            return"},{"line_number":905,"context_line":"        try:"},{"line_number":906,"context_line":"            with lock_parent_directory(self.pending_files[0],"},{"line_number":907,"context_line":"                                       self.pending_timeout):"},{"line_number":908,"context_line":"                self._commit_puts()"},{"line_number":909,"context_line":"        except (LockTimeout, sqlite3.OperationalError):"}],"source_content_type":"text/x-python","patch_set":8,"id":"b7d2875d_9ddea282","line":906,"updated":"2022-03-24 23:30:31.000000000","message":"I wonder if these would be more obvious if we used self.db_file / self.db_dir ...","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"528cbd4141596bcfcc58e3059da3641990047e3c","unresolved":false,"context_lines":[{"line_number":903,"context_line":"        if self._skip_commit_puts():"},{"line_number":904,"context_line":"            return"},{"line_number":905,"context_line":"        try:"},{"line_number":906,"context_line":"            with lock_parent_directory(self.pending_files[0],"},{"line_number":907,"context_line":"                                       self.pending_timeout):"},{"line_number":908,"context_line":"                self._commit_puts()"},{"line_number":909,"context_line":"        except (LockTimeout, sqlite3.OperationalError):"}],"source_content_type":"text/x-python","patch_set":8,"id":"20e1b718_e3351e06","line":906,"in_reply_to":"10bea723_74b76349","updated":"2022-03-31 06:15:37.000000000","message":"Done","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"f78a6ec1e55f9c9d815fa1034b8ff9849c851f4b","unresolved":true,"context_lines":[{"line_number":903,"context_line":"        if self._skip_commit_puts():"},{"line_number":904,"context_line":"            return"},{"line_number":905,"context_line":"        try:"},{"line_number":906,"context_line":"            with lock_parent_directory(self.pending_files[0],"},{"line_number":907,"context_line":"                                       self.pending_timeout):"},{"line_number":908,"context_line":"                self._commit_puts()"},{"line_number":909,"context_line":"        except (LockTimeout, sqlite3.OperationalError):"}],"source_content_type":"text/x-python","patch_set":8,"id":"10bea723_74b76349","line":906,"in_reply_to":"b7d2875d_9ddea282","updated":"2022-03-29 23:57:04.000000000","message":"Good idea","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdf2492b5a01520f21491218f4d1af3139f10d17","unresolved":true,"context_lines":[{"line_number":868,"context_line":"        self._preallocate()"},{"line_number":869,"context_line":"        # There could be more or less pending files then we expect, so grab"},{"line_number":870,"context_line":"        # the names from disk."},{"line_number":871,"context_line":"        pending_files \u003d get_pending_files(self.db_file)"},{"line_number":872,"context_line":"        pending_sizes \u003d list(map(os.path.getsize, pending_files))"},{"line_number":873,"context_line":"        if not any(pending_sizes):"},{"line_number":874,"context_line":"            if item_list:"}],"source_content_type":"text/x-python","patch_set":9,"id":"a272c064_98317d65","line":871,"updated":"2022-03-28 05:49:23.000000000","message":"I wonder if we might want to shuffle these before processing, similar to what we do when we\u0027re filling them.\n\nBasically, in case there\u0027s some weird thing where we\u0027re frequently unable to process all the files -- the first few files might get cleared, but then there\u0027s a lock timeout or something, and none of the rest get processed, so they just keep filling. Once we\u0027ve got something in place where we\u0027re unwilling to write to a shard that\u0027s larger than the pending cap, that\u0027ll shrink the set of available pending files such that even though you\u0027ve configured 10 files (say), you\u0027re only able to make use of 2 or something.","commit_id":"7221b3ddc1c60742972aa7db5ed26e2d57ce7eee"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"528cbd4141596bcfcc58e3059da3641990047e3c","unresolved":false,"context_lines":[{"line_number":868,"context_line":"        self._preallocate()"},{"line_number":869,"context_line":"        # There could be more or less pending files then we expect, so grab"},{"line_number":870,"context_line":"        # the names from disk."},{"line_number":871,"context_line":"        pending_files \u003d get_pending_files(self.db_file)"},{"line_number":872,"context_line":"        pending_sizes \u003d list(map(os.path.getsize, pending_files))"},{"line_number":873,"context_line":"        if not any(pending_sizes):"},{"line_number":874,"context_line":"            if item_list:"}],"source_content_type":"text/x-python","patch_set":9,"id":"83d33511_cb02f1e7","line":871,"in_reply_to":"04420456_9fb4b633","updated":"2022-03-31 06:15:37.000000000","message":"Done","commit_id":"7221b3ddc1c60742972aa7db5ed26e2d57ce7eee"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"f78a6ec1e55f9c9d815fa1034b8ff9849c851f4b","unresolved":true,"context_lines":[{"line_number":868,"context_line":"        self._preallocate()"},{"line_number":869,"context_line":"        # There could be more or less pending files then we expect, so grab"},{"line_number":870,"context_line":"        # the names from disk."},{"line_number":871,"context_line":"        pending_files \u003d get_pending_files(self.db_file)"},{"line_number":872,"context_line":"        pending_sizes \u003d list(map(os.path.getsize, pending_files))"},{"line_number":873,"context_line":"        if not any(pending_sizes):"},{"line_number":874,"context_line":"            if item_list:"}],"source_content_type":"text/x-python","patch_set":9,"id":"04420456_9fb4b633","line":871,"in_reply_to":"a272c064_98317d65","updated":"2022-03-29 23:57:04.000000000","message":"yeah, we shuffle on the other side, we should also do it here. Great idea!","commit_id":"7221b3ddc1c60742972aa7db5ed26e2d57ce7eee"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"966c28e5c4025dce090d321bf08a55136095abc8","unresolved":true,"context_lines":[{"line_number":837,"context_line":"            for pending_file in self.pending_files:"},{"line_number":838,"context_line":"                size \u003d 0"},{"line_number":839,"context_line":"                if os.path.exists(pending_file):"},{"line_number":840,"context_line":"                    size \u003d os.path.getsize(pending_file)"},{"line_number":841,"context_line":"                pending_size +\u003d size"},{"line_number":842,"context_line":"                if size \u003c\u003d self.max_size_per_shard:"},{"line_number":843,"context_line":"                    pending_files.append(pending_file)"}],"source_content_type":"text/x-python","patch_set":17,"id":"d78889a8_e51ab9f8","line":840,"updated":"2026-09-29 00:06:53.000000000","message":"This LBYL smells racy -- and I feel like the `ENOENT` handling is much too broad. *Maybe* that\u0027s the cause of the probe test failure? I can\u0027t repro locally...","commit_id":"c095707e849faba00c7b074097726fe5efb1e6b7"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"948578af213905e47519fec008bde8eb6f9b33bd","unresolved":true,"context_lines":[{"line_number":80,"context_line":"    results \u003d []"},{"line_number":81,"context_line":"    for f in files:"},{"line_number":82,"context_line":"        _root, ext \u003d os.path.splitext(f)"},{"line_number":83,"context_line":"        if ext !\u003d \u0027.pending\u0027:"},{"line_number":84,"context_line":"            continue"},{"line_number":85,"context_line":"        results.append(os.path.join(db_dir, f))"},{"line_number":86,"context_line":"    return results"}],"source_content_type":"text/x-python","patch_set":18,"id":"3a7a9a75_797e2265","line":83,"updated":"2026-09-29 03:26:55.000000000","message":"`if not f.endswith(\u0027.pending\u0027):`?","commit_id":"a7328065033c3eba644ee647dc691caaa197631a"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"d853c26e7e514d11f8d01974df4f77e2ed56cfd0","unresolved":true,"context_lines":[{"line_number":80,"context_line":"    results \u003d []"},{"line_number":81,"context_line":"    for f in files:"},{"line_number":82,"context_line":"        _root, ext \u003d os.path.splitext(f)"},{"line_number":83,"context_line":"        if ext !\u003d \u0027.pending\u0027:"},{"line_number":84,"context_line":"            continue"},{"line_number":85,"context_line":"        results.append(os.path.join(db_dir, f))"},{"line_number":86,"context_line":"    return results"}],"source_content_type":"text/x-python","patch_set":18,"id":"8399e2e8_2a2b4ede","line":83,"in_reply_to":"3a7a9a75_797e2265","updated":"2026-09-29 05:36:27.000000000","message":"yup, no idea what I didn\u0027t just do that 🤷\nesp seeing w don\u0027t use the _root or the ext ever again!","commit_id":"a7328065033c3eba644ee647dc691caaa197631a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"948578af213905e47519fec008bde8eb6f9b33bd","unresolved":true,"context_lines":[{"line_number":846,"context_line":"        if pending_size \u003e self.pending_cap:"},{"line_number":847,"context_line":"            with lock_parent_directory("},{"line_number":848,"context_line":"                    self.pending_files[0],"},{"line_number":849,"context_line":"                    self.pending_timeout, blocking\u003dFalse) as locked:"},{"line_number":850,"context_line":"                if locked:"},{"line_number":851,"context_line":"                    self._commit_puts([record])"},{"line_number":852,"context_line":"                    write_to_pending \u003d False"}],"source_content_type":"text/x-python","patch_set":18,"id":"dcf196a5_bedb611b","line":849,"range":{"start_line":849,"start_character":42,"end_line":849,"end_character":56},"updated":"2026-09-29 03:26:55.000000000","message":"Why `blocking\u003dFalse`? We\u0027re trying to flush all the pending files, right? That\u0027s why we\u0027re locking the whole parent directory... so shouldn\u0027t we be willing to wait a bit to do the complete flush?\n\nThough, where else do we lock the parent directory? Like, what\u0027s contending with this for the lock? Replication, maybe?","commit_id":"a7328065033c3eba644ee647dc691caaa197631a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f08984052a9a87c222e00e435e109a2ed7d76a21","unresolved":true,"context_lines":[{"line_number":846,"context_line":"        if pending_size \u003e self.pending_cap:"},{"line_number":847,"context_line":"            with lock_parent_directory("},{"line_number":848,"context_line":"                    self.pending_files[0],"},{"line_number":849,"context_line":"                    self.pending_timeout, blocking\u003dFalse) as locked:"},{"line_number":850,"context_line":"                if locked:"},{"line_number":851,"context_line":"                    self._commit_puts([record])"},{"line_number":852,"context_line":"                    write_to_pending \u003d False"}],"source_content_type":"text/x-python","patch_set":18,"id":"5774be26_62a67d9f","line":849,"range":{"start_line":849,"start_character":42,"end_line":849,"end_character":56},"in_reply_to":"509648d8_6a479c4e","updated":"2026-09-29 14:44:27.000000000","message":"But at some point we *have* to be willing to wait, no? What about when all the pending files are over the cap?\n\nMaybe we want `blocking\u003dnot pending_files`? The trouble we\u0027re seeing in the gate is that we trip that `EBUSY` a bunch, causing async pendings to not get resolved, which seems to be the opposite of the goal of the patch.","commit_id":"a7328065033c3eba644ee647dc691caaa197631a"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"d853c26e7e514d11f8d01974df4f77e2ed56cfd0","unresolved":true,"context_lines":[{"line_number":846,"context_line":"        if pending_size \u003e self.pending_cap:"},{"line_number":847,"context_line":"            with lock_parent_directory("},{"line_number":848,"context_line":"                    self.pending_files[0],"},{"line_number":849,"context_line":"                    self.pending_timeout, blocking\u003dFalse) as locked:"},{"line_number":850,"context_line":"                if locked:"},{"line_number":851,"context_line":"                    self._commit_puts([record])"},{"line_number":852,"context_line":"                    write_to_pending \u003d False"}],"source_content_type":"text/x-python","patch_set":18,"id":"509648d8_6a479c4e","line":849,"range":{"start_line":849,"start_character":42,"end_line":849,"end_character":56},"in_reply_to":"dcf196a5_bedb611b","updated":"2026-09-29 05:36:27.000000000","message":"I think it\u0027s suppose to be another worker or thread hitting the same put_record (ie thundering herd).\nAnd we don\u0027t want to block, we just let it go find a pending file to write to.","commit_id":"a7328065033c3eba644ee647dc691caaa197631a"},{"author":{"_account_id":38496,"name":"Andressa Cabistani","display_name":"Andressa","email":"acabistani@gmail.com","username":"andressadotpy","status":"I\u0027m a Software Engineer at Red Hat and I love Open Source and connect with people! Feel free to DM through IRC, I\u0027ll be delighted to chat"},"change_message_id":"51b024cb7d49308083bd7c2440b2066d05240a4d","unresolved":true,"context_lines":[{"line_number":853,"context_line":"        if write_to_pending:"},{"line_number":854,"context_line":"            if not pending_files:"},{"line_number":855,"context_line":"                # Or should this be ENOLCK"},{"line_number":856,"context_line":"                raise IOError(errno.EBUSY, \"Pending files full\")"},{"line_number":857,"context_line":"            with lock_one_file("},{"line_number":858,"context_line":"                    pending_files, append\u003dTrue, unlink\u003dFalse) as fp:"},{"line_number":859,"context_line":"                # Colons aren\u0027t used in base64 encoding; so they are our"}],"source_content_type":"text/x-python","patch_set":18,"id":"e89791ce_60ff41e8","line":856,"updated":"2026-09-30 12:16:33.000000000","message":"Suggestion: I couldn\u0027t find any unit tests for this line. Given it\u0027s a new way for a PUT to fail, it\u0027s worth a test.","commit_id":"a7328065033c3eba644ee647dc691caaa197631a"},{"author":{"_account_id":38496,"name":"Andressa Cabistani","display_name":"Andressa","email":"acabistani@gmail.com","username":"andressadotpy","status":"I\u0027m a Software Engineer at Red Hat and I love Open Source and connect with people! Feel free to DM through IRC, I\u0027ll be delighted to chat"},"change_message_id":"51b024cb7d49308083bd7c2440b2066d05240a4d","unresolved":true,"context_lines":[{"line_number":854,"context_line":"            if not pending_files:"},{"line_number":855,"context_line":"                # Or should this be ENOLCK"},{"line_number":856,"context_line":"                raise IOError(errno.EBUSY, \"Pending files full\")"},{"line_number":857,"context_line":"            with lock_one_file("},{"line_number":858,"context_line":"                    pending_files, append\u003dTrue, unlink\u003dFalse) as fp:"},{"line_number":859,"context_line":"                # Colons aren\u0027t used in base64 encoding; so they are our"},{"line_number":860,"context_line":"                # delimiter"}],"source_content_type":"text/x-python","patch_set":18,"id":"3d4b246b_18fe5f4b","line":857,"updated":"2026-09-30 12:16:33.000000000","message":"Suggestion: self.pending_timeout isn\u0027t passed, so this gets `DEFAULT_LOCK_TIMEOUT (10)` while the directory lock eight lines up honours `self.pending_timeout`. Two different timeouts inside one `put_record()`. This is a live regression for the replicator, which explicitly passes `pending_timeout\u003d30`. Measured: a broker with `pending_timeout\u003d1` waited the full `10.0s` before raising. Same at line 902.","commit_id":"a7328065033c3eba644ee647dc691caaa197631a"},{"author":{"_account_id":38496,"name":"Andressa Cabistani","display_name":"Andressa","email":"acabistani@gmail.com","username":"andressadotpy","status":"I\u0027m a Software Engineer at Red Hat and I love Open Source and connect with people! Feel free to DM through IRC, I\u0027ll be delighted to chat"},"change_message_id":"51b024cb7d49308083bd7c2440b2066d05240a4d","unresolved":true,"context_lines":[{"line_number":865,"context_line":"                fp.flush()"},{"line_number":866,"context_line":""},{"line_number":867,"context_line":"    def _skip_commit_puts(self):"},{"line_number":868,"context_line":"        return self.skip_commits or not any(map(os.path.exists,"},{"line_number":869,"context_line":"                                                self.pending_files))"},{"line_number":870,"context_line":""},{"line_number":871,"context_line":"    def _commit_puts(self, item_list\u003dNone):"}],"source_content_type":"text/x-python","patch_set":18,"id":"af2a9463_82274318","line":868,"updated":"2026-09-30 12:16:33.000000000","message":"`pending_shards` is only read from [app:container-server] / [app:account-server].\nThe replicator daemon, updater, sharder, sync and reaper all get the default\nof 1. Because `lock_one_file()` shuffles, a fresh container creates exactly one\npending file at random, so at `pending_shards\u003d5` there\u0027s a big chance\n`\u003chash\u003e.db.pending` is absent while a numbered shard holds real records. I\nmeasured 16/20 over fresh containers.\n\nEvery read path funnels through here: `_commit_puts_stale_ok()`, `reclaim()`, and\n`_commit_puts()` itself. So on a handoff:\n\n  1. handoff accepts a `PUT` -\u003e record lands in `\u003chash\u003e.db-3.pending`\n  2. replicator builds a broker with the default `pending_shards\u003d1`\n  3. `_reclaim()` -\u003e this returns `True` -\u003e no commit\n  4. `get_replication_info()` -\u003e same gate -\u003e reports `max_row\u003d-1`\n  5. the empty db replicates, all primaries return `200`\n  6. `cleanup_post_replicate` -\u003e `delete_db` -\u003e `shutil.rmtree(hash_dir, True)`\n\nThe record is gone, on the path whose job is to prevent that.\n\nHow to reproduce, no SAIO needed:\n```python\nimport os, shutil, tempfile\nfrom swift.common.db import get_pending_files\nfrom swift.common.utils.timestamp import Timestamp\nfrom swift.container.backend import ContainerBroker\n\nd \u003d tempfile.mkdtemp()\ndb \u003d os.path.join(d, \u0027x.db\u0027)\nb \u003d ContainerBroker(db, account\u003d\u0027a\u0027, container\u003d\u0027c\u0027, pending_shards\u003d5)\nb.initialize(Timestamp.now().internal, 0)\nb.put_object(\u0027o\u0027, Timestamp.now().internal, 0, \u0027text/plain\u0027, \u0027etag\u0027)\nprint(\u0027on disk :\u0027, [os.path.basename(p) for p in get_pending_files(db)])\n\n# exactly what db_replicator._replicate_object constructs:\ndaemon \u003d ContainerBroker(db, pending_timeout\u003d30)\nprint(\u0027skip    :\u0027, daemon._skip_commit_puts())\nprint(\u0027count   :\u0027, daemon.get_info()[\u0027object_count\u0027])\nprint(\u0027max_row :\u0027, daemon.get_replication_info()[\u0027max_row\u0027])\nshutil.rmtree(d)\n```\nRoughly 4 runs in 5:\n```\non disk : [\u0027x.db-3.pending\u0027]\nskip    : True\ncount   : 0\nmax_row : -1\n```\n\nFix idea — make the gate agree with the committer, so it\u0027s correct regardless\nof how any given process is configured:\n\n```python\n    def _skip_commit_puts(self):\n        return self.skip_commits or not any(\n            os.path.getsize(f) for f in get_pending_files(self.db_file))\n```\n\nThat alone closes the hole. Plumbing pending_shards through the daemons is\nstill worth doing so they size their write path correctly, but I\u0027d rather\ndurability didn\u0027t depend on it.","commit_id":"a7328065033c3eba644ee647dc691caaa197631a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"948578af213905e47519fec008bde8eb6f9b33bd","unresolved":true,"context_lines":[{"line_number":891,"context_line":"        # the names from disk."},{"line_number":892,"context_line":"        pending_files \u003d get_pending_files(self.db_file)"},{"line_number":893,"context_line":"        shuffle(pending_files)"},{"line_number":894,"context_line":"        pending_sizes \u003d list(map(os.path.getsize, pending_files))"},{"line_number":895,"context_line":"        if not any(pending_sizes):"},{"line_number":896,"context_line":"            if item_list:"},{"line_number":897,"context_line":"                self.merge_items(item_list)"}],"source_content_type":"text/x-python","patch_set":18,"id":"cc11c3ff_90dd52ea","line":894,"updated":"2026-09-29 03:26:55.000000000","message":"Probably want to do this in a way that tolerates `ENOENT`...","commit_id":"a7328065033c3eba644ee647dc691caaa197631a"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"d853c26e7e514d11f8d01974df4f77e2ed56cfd0","unresolved":true,"context_lines":[{"line_number":891,"context_line":"        # the names from disk."},{"line_number":892,"context_line":"        pending_files \u003d get_pending_files(self.db_file)"},{"line_number":893,"context_line":"        shuffle(pending_files)"},{"line_number":894,"context_line":"        pending_sizes \u003d list(map(os.path.getsize, pending_files))"},{"line_number":895,"context_line":"        if not any(pending_sizes):"},{"line_number":896,"context_line":"            if item_list:"},{"line_number":897,"context_line":"                self.merge_items(item_list)"}],"source_content_type":"text/x-python","patch_set":18,"id":"5f9dfbf5_01730e9d","line":894,"in_reply_to":"cc11c3ff_90dd52ea","updated":"2026-09-29 05:36:27.000000000","message":"yes! that\u0027s a good idea!","commit_id":"a7328065033c3eba644ee647dc691caaa197631a"}],"swift/common/db_replicator.py":[{"author":{"_account_id":38496,"name":"Andressa Cabistani","display_name":"Andressa","email":"acabistani@gmail.com","username":"andressadotpy","status":"I\u0027m a Software Engineer at Red Hat and I love Open Source and connect with people! Feel free to DM through IRC, I\u0027ll be delighted to chat"},"change_message_id":"51b024cb7d49308083bd7c2440b2066d05240a4d","unresolved":true,"context_lines":[{"line_number":946,"context_line":"    \"\"\"Handle Replication RPC calls.  TODO(redbo): document please :)\"\"\""},{"line_number":947,"context_line":""},{"line_number":948,"context_line":"    def __init__(self, root, datadir, broker_class, mount_check\u003dTrue,"},{"line_number":949,"context_line":"                 logger\u003dNone, pending_shards\u003d1):"},{"line_number":950,"context_line":"        self.root \u003d root"},{"line_number":951,"context_line":"        self.datadir \u003d datadir"},{"line_number":952,"context_line":"        self.broker_class \u003d broker_class"}],"source_content_type":"text/x-python","patch_set":18,"id":"ee589adb_7d8ee461","line":949,"updated":"2026-09-30 12:16:33.000000000","message":"(same root cause as db.py:868): `pending_shards` is plumbed into `ReplicatorRpc` here, but not into the Replicator daemon itself, `_replicate_object` still builds `self.brokerclass(object_file, pending_timeout\u003d30, logger\u003dself.logger)`\n\nSo the receiving side of replication is configured and the deleting side is not, and it\u0027s the deleting side that calls `get_replication_info()` and then `cleanup_post_replicate -\u003e delete_db`. Same for container/updater.py,\ncontainer/sharder.py, container/sync.py and account/reaper.py, none of which\nmention `pending_shards` at all.","commit_id":"a7328065033c3eba644ee647dc691caaa197631a"}],"swift/common/utils.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f94b29ee1190860a7aedd64ba054c6ef809a3ab8","unresolved":true,"context_lines":[{"line_number":3015,"context_line":"        fd \u003d os.open(filename, flags)"},{"line_number":3016,"context_line":"        file_obj \u003d os.fdopen(fd, mode)"},{"line_number":3017,"context_line":"        try:"},{"line_number":3018,"context_line":"            with swift.common.exceptions.LockTimeout(timeout, filename):"},{"line_number":3019,"context_line":"                try:"},{"line_number":3020,"context_line":"                    fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)"},{"line_number":3021,"context_line":"                    try:"}],"source_content_type":"text/x-python","patch_set":8,"id":"47a80745_d13d7f10","line":3018,"updated":"2022-03-24 23:30:31.000000000","message":"If everybody\u0027s locked... I\u0027m not sure we\u0027ll ever trip the timeout. We want this outside the for loop.","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"6da015605349bf6e143dc3a6f03f425758c34412","unresolved":false,"context_lines":[{"line_number":3015,"context_line":"        fd \u003d os.open(filename, flags)"},{"line_number":3016,"context_line":"        file_obj \u003d os.fdopen(fd, mode)"},{"line_number":3017,"context_line":"        try:"},{"line_number":3018,"context_line":"            with swift.common.exceptions.LockTimeout(timeout, filename):"},{"line_number":3019,"context_line":"                try:"},{"line_number":3020,"context_line":"                    fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)"},{"line_number":3021,"context_line":"                    try:"}],"source_content_type":"text/x-python","patch_set":8,"id":"64184b97_e1bda4af","line":3018,"in_reply_to":"47a80745_d13d7f10","updated":"2022-03-25 05:37:41.000000000","message":"Done","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f94b29ee1190860a7aedd64ba054c6ef809a3ab8","unresolved":true,"context_lines":[{"line_number":3027,"context_line":"                            file_obj.close()"},{"line_number":3028,"context_line":"                            continue"},{"line_number":3029,"context_line":"                        raise"},{"line_number":3030,"context_line":"                    yield file_obj"},{"line_number":3031,"context_line":"                    if unlink:"},{"line_number":3032,"context_line":"                        os.unlink(filename)"},{"line_number":3033,"context_line":"                    break"}],"source_content_type":"text/x-python","patch_set":8,"id":"0fa0f12c_15f02c84","line":3030,"updated":"2022-03-24 23:30:31.000000000","message":"Definitely *don\u0027t* want the yield inside the LockTimeout -- the guy that *succeeds* in getting the lock can have a LockTimeout pop in the middle of its work!","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"6da015605349bf6e143dc3a6f03f425758c34412","unresolved":false,"context_lines":[{"line_number":3027,"context_line":"                            file_obj.close()"},{"line_number":3028,"context_line":"                            continue"},{"line_number":3029,"context_line":"                        raise"},{"line_number":3030,"context_line":"                    yield file_obj"},{"line_number":3031,"context_line":"                    if unlink:"},{"line_number":3032,"context_line":"                        os.unlink(filename)"},{"line_number":3033,"context_line":"                    break"}],"source_content_type":"text/x-python","patch_set":8,"id":"f499b07d_34a392e4","line":3030,"in_reply_to":"0fa0f12c_15f02c84","updated":"2022-03-25 05:37:41.000000000","message":"Done","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f94b29ee1190860a7aedd64ba054c6ef809a3ab8","unresolved":true,"context_lines":[{"line_number":3034,"context_line":"                except IOError as err:"},{"line_number":3035,"context_line":"                    if err.errno !\u003d errno.EAGAIN:"},{"line_number":3036,"context_line":"                        raise"},{"line_number":3037,"context_line":"                sleep(0.01)"},{"line_number":3038,"context_line":"        finally:"},{"line_number":3039,"context_line":"            file_obj.close()"},{"line_number":3040,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"98c1bf0a_17e37a6d","line":3037,"updated":"2022-03-24 23:30:31.000000000","message":"I\u0027m not sure I like this between every lock attempt -- maybe we could do something closer to\n\n\n have_lock \u003d False\n with LockTimeout(...):\n     while True:\n         for filename in filenames:\n             try:\n                 # get lock\n                 have_lock \u003d True\n                 break\n             except:\n                 ...\n         if have_lock:\n             break\n         sleep(0.01)\n yield ...","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"6da015605349bf6e143dc3a6f03f425758c34412","unresolved":false,"context_lines":[{"line_number":3034,"context_line":"                except IOError as err:"},{"line_number":3035,"context_line":"                    if err.errno !\u003d errno.EAGAIN:"},{"line_number":3036,"context_line":"                        raise"},{"line_number":3037,"context_line":"                sleep(0.01)"},{"line_number":3038,"context_line":"        finally:"},{"line_number":3039,"context_line":"            file_obj.close()"},{"line_number":3040,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"0a1e9b1c_6f29dbf1","line":3037,"in_reply_to":"98c1bf0a_17e37a6d","updated":"2022-03-25 05:37:41.000000000","message":"Done","commit_id":"38a6616894f99b99e97e6c793c74848dfec482c4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdf2492b5a01520f21491218f4d1af3139f10d17","unresolved":true,"context_lines":[{"line_number":3000,"context_line":"    :param unlink: True if the file should be unlinked at the end"},{"line_number":3001,"context_line":"    :param shuffle_files: True if the list should be shuffled before cycled"},{"line_number":3002,"context_line":"        through"},{"line_number":3003,"context_line":"    :param max_file_size: If provided will skip files once they get to this"},{"line_number":3004,"context_line":"        size"},{"line_number":3005,"context_line":"    \"\"\""},{"line_number":3006,"context_line":"    if timeout is None:"}],"source_content_type":"text/x-python","patch_set":9,"id":"0f8b5bbf_faf93a9b","line":3003,"updated":"2022-03-28 05:49:23.000000000","message":"I was thinking, since we already call getsize() on everybody in the caller, we could just filter the filenames we pass in. Sure, there could be a write between then and when we actually manage to take the lock, but I don\u0027t think we actually need a *hard* cap -- just something to make sure these guys don\u0027t grow without bound.","commit_id":"7221b3ddc1c60742972aa7db5ed26e2d57ce7eee"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"f78a6ec1e55f9c9d815fa1034b8ff9849c851f4b","unresolved":true,"context_lines":[{"line_number":3000,"context_line":"    :param unlink: True if the file should be unlinked at the end"},{"line_number":3001,"context_line":"    :param shuffle_files: True if the list should be shuffled before cycled"},{"line_number":3002,"context_line":"        through"},{"line_number":3003,"context_line":"    :param max_file_size: If provided will skip files once they get to this"},{"line_number":3004,"context_line":"        size"},{"line_number":3005,"context_line":"    \"\"\""},{"line_number":3006,"context_line":"    if timeout is None:"}],"source_content_type":"text/x-python","patch_set":9,"id":"bf84d4fd_85bfac76","line":3003,"in_reply_to":"0f8b5bbf_faf93a9b","updated":"2022-03-29 23:57:04.000000000","message":"oh, I didn\u0027t even think about that. So that could make it more of a soft block. Once it gets into this function it\u0027s a viable file to return. Also love that we could use the existing getsize values and save some extra IO.","commit_id":"7221b3ddc1c60742972aa7db5ed26e2d57ce7eee"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cdf2492b5a01520f21491218f4d1af3139f10d17","unresolved":true,"context_lines":[{"line_number":3038,"context_line":"                break"},{"line_number":3039,"context_line":"            except IOError as err:"},{"line_number":3040,"context_line":"                if err.errno !\u003d errno.EAGAIN:"},{"line_number":3041,"context_line":"                    raise"},{"line_number":3042,"context_line":"            sleep(0.01)"},{"line_number":3043,"context_line":"            file_obj.close()"},{"line_number":3044,"context_line":""}],"source_content_type":"text/x-python","patch_set":9,"id":"781695e5_c141c49d","line":3041,"updated":"2022-03-28 05:49:23.000000000","message":"I think we leave a file descriptor open here. Also, if there\u0027s any *other* sort of error raised...","commit_id":"7221b3ddc1c60742972aa7db5ed26e2d57ce7eee"}],"swift/common/utils/__init__.py":[{"author":{"_account_id":38496,"name":"Andressa Cabistani","display_name":"Andressa","email":"acabistani@gmail.com","username":"andressadotpy","status":"I\u0027m a Software Engineer at Red Hat and I love Open Source and connect with people! Feel free to DM through IRC, I\u0027ll be delighted to chat"},"change_message_id":"51b024cb7d49308083bd7c2440b2066d05240a4d","unresolved":true,"context_lines":[{"line_number":1413,"context_line":"                    next_file \u003d True"},{"line_number":1414,"context_line":"                if next_file:"},{"line_number":1415,"context_line":"                    file_obj.close()"},{"line_number":1416,"context_line":"                    continue"},{"line_number":1417,"context_line":"                break"},{"line_number":1418,"context_line":"            except IOError as err:"},{"line_number":1419,"context_line":"                if err.errno !\u003d errno.EAGAIN:"}],"source_content_type":"text/x-python","patch_set":18,"id":"21e7f900_a9edb16b","line":1416,"updated":"2026-09-30 12:16:33.000000000","message":"The `continue` on the next line jumps past the `sleep(0.01)` at line 1423, so this is a tight loop with no yield.\n\nUnder eventlet that blocks the whole worker and because `LockTimeout` is an eventlet timer, it can never fire either. So it isn\u0027t a 10s hang, it\u0027s an unbounded one.\n\nMeasured by forcing the inode mismatch: 3001 `os.open()` calls in 0.047s (~64k/sec) while a peer greenthread ran 0 times and a 0.3s LockTimeout never fired.\n\nThe branch is reachable whenever another process unlinks and recreates a pending file, which is exactly what `unlink\u003dTrue` does and that\u0027s the default and what `test_lock_one_file` exercises.","commit_id":"a7328065033c3eba644ee647dc691caaa197631a"}],"test/unit/container/test_backend.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c72e421d83e3857463104dcc83e49ab3934ed168","unresolved":true,"context_lines":[{"line_number":969,"context_line":"                return real_loads(*args, **kwargs)"},{"line_number":970,"context_line":""},{"line_number":971,"context_line":"            with mock.patch(\u0027pickle.dumps\u0027, mock_pickle_dumps), \\"},{"line_number":972,"context_line":"                    mock.patch(\u0027pickle.loads\u0027, mock_pickle_loads):"},{"line_number":973,"context_line":"                put_broker.put_object(b\u0027obj-%s\u0027 % str(uuid4()).encode(\u0027ascii\u0027),"},{"line_number":974,"context_line":"                                      ts, 123, \u0027application/x-test\u0027,"},{"line_number":975,"context_line":"                                      \u00275af83e3196bf99f440f31f2e1a6c9afe\u0027, 0, 0)"}],"source_content_type":"text/x-python","patch_set":13,"id":"0828f045_1612fdb8","line":972,"updated":"2026-09-28 19:17:24.000000000","message":"We really don\u0027t want to be doing global mocking in threads -- it\u0027s gonna be chock-full of race conditions. Either we need to get the mocks in place before starting threads, or we need to get the threads mocking thread-local things (like attributes of their particular broker -- maybe we could use `_commit_puts_load` / `make_tuple_for_pickle`?)","commit_id":"bce629106baf50f520e7191e073af570e514081c"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c72e421d83e3857463104dcc83e49ab3934ed168","unresolved":true,"context_lines":[{"line_number":1012,"context_line":""},{"line_number":1013,"context_line":"        # Now let the first finish"},{"line_number":1014,"context_line":"        put_1_q.put(None)"},{"line_number":1015,"context_line":"        pile.waitall(5)"},{"line_number":1016,"context_line":""},{"line_number":1017,"context_line":"        # They both ran,"},{"line_number":1018,"context_line":"        pending_files \u003d get_pending_files(broker.db_file)"}],"source_content_type":"text/x-python","patch_set":13,"id":"d296c6c7_e5acaef6","line":1015,"updated":"2026-09-28 19:17:24.000000000","message":"`waitall` doesn\u0027t necessarily wait for all coros to finish -- it just collects the ones that did. Maybe we want something more like\n```\nself.assertEqual(2, len(pile.waitall(5)))\n```\n? Failures probably won\u0027t be super-helpful, though. FWIW, I found something like https://paste.opendev.org/show/b98bvEg58BMdxddCh8rE/ handy.","commit_id":"bce629106baf50f520e7191e073af570e514081c"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c72e421d83e3857463104dcc83e49ab3934ed168","unresolved":true,"context_lines":[{"line_number":1082,"context_line":""},{"line_number":1083,"context_line":"        # We may have to wait for the another commit because there are 2"},{"line_number":1084,"context_line":"        # pending files."},{"line_number":1085,"context_line":"        lock_log_q.get(0.1)"},{"line_number":1086,"context_line":"        put_1_q.put(None)"},{"line_number":1087,"context_line":"        lock_log_q.get(0.1)"},{"line_number":1088,"context_line":"        pile.waitall(1)"}],"source_content_type":"text/x-python","patch_set":13,"id":"72d51fac_71f6ded0","line":1085,"updated":"2026-09-28 19:17:24.000000000","message":"`get`\u0027s [first arg is `block`](https://github.com/eventlet/eventlet/blob/0.41.2/eventlet/queue.py#L289) -- did you mean to have this be `lock_log_q.get(timeout\u003d0.1)`?","commit_id":"bce629106baf50f520e7191e073af570e514081c"}]}
