)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"9fa3250f6e09bd02275aac639f0dbc33ab03b1a2","unresolved":true,"context_lines":[{"line_number":4,"context_line":"Commit:     Jianjian Huo \u003cjhuo@nvidia.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2025-12-15 10:17:22 -0800"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"object-server: handle ec timestamp collision during commit"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Change-Id: I69c2ceeca5ce6495414e92a57b19bfb16a21e526"},{"line_number":10,"context_line":"Co-Authored-By: Jianjian Huo \u003cjhuo@nvidia.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"445ae06c_6d84088b","line":7,"updated":"2026-01-16 04:16:55.000000000","message":"Can we please have some more information in the commit message on what this is about, why it\u0027s important. exp because it seems to be about commiting with different metadata in a collision.","commit_id":"f24579d405af55eb79165e0496d835fd5c6b0d43"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"806080e96daac2d94dc13fce43afe527e48712df","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"89cb4b3a_408d6b23","updated":"2026-01-19 14:58:01.000000000","message":"I don\u0027t think I understand the motivation yet. Could you describe the bad scenario and how this prevent it in the commit message. Thanks!\n\nUnfortunately the build results have expired. But OMM I see a pre-existing test fail:\n\n```\nFAILED\ntest/unit/obj/test_diskfile.py:6401 (TestECDiskFile.test_commit_overwritten_before_ppi_rename)\n5 !\u003d 4\n\nExpected :4\nActual   :5\n\u003cClick to see difference\u003e\n\ntest_diskfile.py:6438: in test_commit_overwritten_before_ppi_rename\n    self.assertEqual(4, len(captured_renames))\n\n```","commit_id":"f24579d405af55eb79165e0496d835fd5c6b0d43"}],"swift/obj/diskfile.py":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"a4e215d50a58ffb933f076192e18b964c1fbe01c","unresolved":true,"context_lines":[{"line_number":3248,"context_line":""},{"line_number":3249,"context_line":"    def _finalize_durable(self, data_file_path, durable_data_file_path,"},{"line_number":3250,"context_line":"                          timestamp):"},{"line_number":3251,"context_line":"        if os.path.exists(durable_data_file_path):"},{"line_number":3252,"context_line":"            raise DiskFileError("},{"line_number":3253,"context_line":"                \u0027encoutered pre-existing durable for %s\u0027 % ("},{"line_number":3254,"context_line":"                    durable_data_file_path,))"}],"source_content_type":"text/x-python","patch_set":1,"id":"a6af9417_91390cb0","line":3251,"updated":"2025-12-15 17:11:38.000000000","message":"this is not enough, we will need:\n1. read_metadata(durable_data_file_path) and check if it matches the in-progress writer.\n2. let reconstructor overwrite if os.path.exists(durable_data_file_path), since reconstructor has the quorum and that\u0027s the correct version of data.\n3. just return if durable_data_file_path exists and metadata matches (reconstructor races)","commit_id":"d5ec70648bfe2c2a704471caa10ed36277267890"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"806080e96daac2d94dc13fce43afe527e48712df","unresolved":true,"context_lines":[{"line_number":3330,"context_line":"            if existing_metadata !\u003d metadata:"},{"line_number":3331,"context_line":"                raise DiskFileError("},{"line_number":3332,"context_line":"                    \u0027encountered pre-existing durable for %s with different\u0027"},{"line_number":3333,"context_line":"                    \u0027 ETag\u0027 % (durable_data_file_path,))"},{"line_number":3334,"context_line":"            else:"},{"line_number":3335,"context_line":"                return"},{"line_number":3336,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"383710b9_3bdded57","line":3333,"updated":"2026-01-19 14:58:01.000000000","message":"is the idea that by raising an error here, the object server returns 500 and the proxy doesn\u0027t reach quorum for the commit phase?\n\nIIUC this makes no difference to the outcome in the on-disk files (we still have a durable data file), but does send a different result. Oh, but maybe there is a difference in the on-disk files: if there\u0027s a nondurable and a durable then we will no longer replace the durable with a different durable?\n\nI\u0027m not sure I yet understand how this helps back at the proxy-server:\n\nAssume we have concurrent PUTs at same timestamp but different content: variant X and Y.\n\nBefore this patch, we can end up with a mixture of frags:\nOn one object server we have durable X, then nondurable Y is written, then Y is made durable by commit Y.\n\nOn another object server we have durable Y, then nondurable X is written, then X is made durable by commit X.\n\nOn another object server we have nondurable Y, then nondurable X is written, then X is made durable by commit Y.\n\n\nAfter this patch we can still end up with a different mix of fragments:\nOn one object server we have durable X, then nondurable Y is written, then Y is NOT made durable by commit Y.\n\nOn another object server we have durable Y, then nondurable X is written, then X is NOT made durable by commit X.\n\nOn another object server we have nondurable Y, then nondurable X is written, then X is made durable by commit Y.","commit_id":"f24579d405af55eb79165e0496d835fd5c6b0d43"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"d599475843a8b316e27e8d10f8ed3b54923a30df","unresolved":true,"context_lines":[{"line_number":3330,"context_line":"            if existing_metadata !\u003d metadata:"},{"line_number":3331,"context_line":"                raise DiskFileError("},{"line_number":3332,"context_line":"                    \u0027encountered pre-existing durable for %s with different\u0027"},{"line_number":3333,"context_line":"                    \u0027 ETag\u0027 % (durable_data_file_path,))"},{"line_number":3334,"context_line":"            else:"},{"line_number":3335,"context_line":"                return"},{"line_number":3336,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"452ce2dc_1c39d2a5","line":3333,"in_reply_to":"383710b9_3bdded57","updated":"2026-03-18 00:27:21.000000000","message":"the original idea was to close the loop after we introduced a patch for object-server to return 500 when detecting overwrite of nondurable fragments with different metadata, it would be good to have similar mechanism when committing durable fragments as well. For example, when X committed into a first set of nodes and Y is committing into a second set of nodes, and the second set overlaps the first set a little bit; then Y would see some 500s and the proxy doesn\u0027t reach quorum for the commit phase.\n\nSince we all agreed the ultimate solution is v2 timestamp: https://review.opendev.org/c/openstack/swift/+/967738. I am not planning to invest more time on this patch.","commit_id":"f24579d405af55eb79165e0496d835fd5c6b0d43"}]}
