)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"dd2d561d7baf5958cde1ea7be6b66de04dc24463","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"...while returning whatever\u0027s currently in hashes.pkl."},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Have the post-sync REPLICATE calls use this, since they don\u0027t actually"},{"line_number":12,"context_line":"look at the response, anyway."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Change-Id: I1de62140e7eb9a23152bb9fdb1fa0934e827bfda"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":5,"id":"1f621f24_b785e05c","line":11,"updated":"2020-11-06 16:32:12.000000000","message":"Maybe have the subject indicate this - currently it sounds like just an option was added","commit_id":"c11286ed108ceb4e5ec5aa48eca0cfeb86dcaf70"}],"swift/obj/diskfile.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"dd2d561d7baf5958cde1ea7be6b66de04dc24463","unresolved":false,"context_lines":[{"line_number":1498,"context_line":"                                 policy\u003dpolicy, **kwargs)"},{"line_number":1499,"context_line":""},{"line_number":1500,"context_line":"    def get_hashes(self, device, partition, suffixes, policy,"},{"line_number":1501,"context_line":"                   delay_rehash\u003dFalse):"},{"line_number":1502,"context_line":"        \"\"\""},{"line_number":1503,"context_line":""},{"line_number":1504,"context_line":"        :param device: name of target device"}],"source_content_type":"text/x-python","patch_set":5,"id":"1f621f24_6c8fff74","line":1501,"updated":"2020-11-06 16:32:12.000000000","message":"naming nit: not sure I perceive this to be a \"delay\" rather than a \"don\u0027t\". Yes, there is a delay in terms of the replication system, but in terms of this method\u0027s behaviour the semantic is simply \"don\u0027t rehash\"","commit_id":"c11286ed108ceb4e5ec5aa48eca0cfeb86dcaf70"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"1146882f2f0fadb441d728cc970b704a63294a74","unresolved":false,"context_lines":[{"line_number":1498,"context_line":"                                 policy\u003dpolicy, **kwargs)"},{"line_number":1499,"context_line":""},{"line_number":1500,"context_line":"    def get_hashes(self, device, partition, suffixes, policy,"},{"line_number":1501,"context_line":"                   delay_rehash\u003dFalse):"},{"line_number":1502,"context_line":"        \"\"\""},{"line_number":1503,"context_line":""},{"line_number":1504,"context_line":"        :param device: name of target device"}],"source_content_type":"text/x-python","patch_set":5,"id":"1f621f24_98a1f1fb","line":1501,"in_reply_to":"1f621f24_6c8fff74","updated":"2020-11-06 23:16:39.000000000","message":"Renamed to skip_rehash.","commit_id":"c11286ed108ceb4e5ec5aa48eca0cfeb86dcaf70"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"dd2d561d7baf5958cde1ea7be6b66de04dc24463","unresolved":false,"context_lines":[{"line_number":1518,"context_line":"        if delay_rehash:"},{"line_number":1519,"context_line":"            for suffix in suffixes or []:"},{"line_number":1520,"context_line":"                invalidate_hash(os.path.join(partition_path, suffix))"},{"line_number":1521,"context_line":"            hashes \u003d read_hashes(partition_path)"},{"line_number":1522,"context_line":"            if suffixes:"},{"line_number":1523,"context_line":"                hashes \u003d {suffix: val for suffix, val in hashes.items()"},{"line_number":1524,"context_line":"                          if suffix in suffixes}"}],"source_content_type":"text/x-python","patch_set":5,"id":"1f621f24_97a1c4fb","line":1521,"updated":"2020-11-06 16:32:12.000000000","message":"if we do need to return something, would it make sense to do consolidate_hashes and then return the full map of hashes (which won\u0027t have the recently invalidated suffixes) so that the semantic of the call is \u0027returns known valid hashes with or without rehashing\u0027?","commit_id":"c11286ed108ceb4e5ec5aa48eca0cfeb86dcaf70"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"dd2d561d7baf5958cde1ea7be6b66de04dc24463","unresolved":false,"context_lines":[{"line_number":1521,"context_line":"            hashes \u003d read_hashes(partition_path)"},{"line_number":1522,"context_line":"            if suffixes:"},{"line_number":1523,"context_line":"                hashes \u003d {suffix: val for suffix, val in hashes.items()"},{"line_number":1524,"context_line":"                          if suffix in suffixes}"},{"line_number":1525,"context_line":"            return hashes"},{"line_number":1526,"context_line":"        else:"},{"line_number":1527,"context_line":"            _junk, hashes \u003d tpool.execute("}],"source_content_type":"text/x-python","patch_set":5,"id":"1f621f24_4c8cc37e","line":1524,"updated":"2020-11-06 16:32:12.000000000","message":"I don\u0027t understand this part: hashes is read from hashes.pkl but is stale (because invalidate_hash only updated hashes.invalid) and then we return only the stale hashes for the suffixes that were just invalidated?","commit_id":"c11286ed108ceb4e5ec5aa48eca0cfeb86dcaf70"}],"swift/obj/replicator.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"2ec838d9b3b1473116613b51e8ce4e85ff17cc7b","unresolved":false,"context_lines":[{"line_number":700,"context_line":"                            node[\u0027device\u0027], job[\u0027partition\u0027], \u0027REPLICATE\u0027,"},{"line_number":701,"context_line":"                            \u0027/\u0027 + \u0027-\u0027.join(suffixes),"},{"line_number":702,"context_line":"                            headers\u003dheaders)"},{"line_number":703,"context_line":"                        conn.getresponse().read()"},{"line_number":704,"context_line":"                    if not success:"},{"line_number":705,"context_line":"                        failure_devs_info.add((node[\u0027replication_ip\u0027],"},{"line_number":706,"context_line":"                                               node[\u0027device\u0027]))"}],"source_content_type":"text/x-python","patch_set":1,"id":"5f681702_09122b59","line":703,"updated":"2020-10-19 04:53:38.000000000","message":"Hmm... we don\u0027t look at *this* response, either...","commit_id":"d6279ad62525f6a3e3d008ccaa27dce516cd7b37"},{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"d70e6d2f79cfb36ae721c788ca9ef1f11cbdfe2c","unresolved":false,"context_lines":[{"line_number":47,"context_line":"DEFAULT_RSYNC_TIMEOUT \u003d 900"},{"line_number":48,"context_line":"DELAY_REHASH_HDR \u003d {\u0027X-Backend-Delay-Rehash\u0027: \u0027true\u0027}"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":"def _do_listdir(partition, replication_cycle):"},{"line_number":51,"context_line":"    return (((partition + replication_cycle) % 10) \u003d\u003d 0)"},{"line_number":52,"context_line":""},{"line_number":53,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"3f65232a_69676327","line":50,"updated":"2020-10-21 21:49:29.000000000","message":"pep8: E302 expected 2 blank lines, found 1","commit_id":"0da346a424f47e998620c381a32d966484475126"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"dd2d561d7baf5958cde1ea7be6b66de04dc24463","unresolved":false,"context_lines":[{"line_number":45,"context_line":"from swift.common.storage_policy import POLICIES, REPL_POLICY"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"DEFAULT_RSYNC_TIMEOUT \u003d 900"},{"line_number":48,"context_line":"DELAY_REHASH_HDR \u003d {\u0027X-Backend-Delay-Rehash\u0027: \u0027true\u0027}"},{"line_number":49,"context_line":""},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"def _do_listdir(partition, replication_cycle):"}],"source_content_type":"text/x-python","patch_set":5,"id":"1f621f24_4c4fa333","line":48,"updated":"2020-11-06 16:32:12.000000000","message":"naming nit: (also mentioned in diskfle) as I understand it, the semantic of this, in terms of the server\u0027s behaviour, is more like \"don\u0027t rehash\"","commit_id":"c11286ed108ceb4e5ec5aa48eca0cfeb86dcaf70"}],"swift/obj/server.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"0f8a085d73c1be82b44306347a3763cf6a336180","unresolved":false,"context_lines":[{"line_number":1300,"context_line":"            hashes \u003d self._diskfile_router[policy].get_hashes("},{"line_number":1301,"context_line":"                device, partition, suffixes, policy,"},{"line_number":1302,"context_line":"                delay_rehash\u003dconfig_true_value("},{"line_number":1303,"context_line":"                    request.headers.get(\u0027X-Backend-Delay-Rehash\u0027)))"},{"line_number":1304,"context_line":"        except DiskFileDeviceUnavailable:"},{"line_number":1305,"context_line":"            resp \u003d HTTPInsufficientStorage(drive\u003ddevice, request\u003drequest)"},{"line_number":1306,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":1,"id":"5f681702_0547a71f","line":1303,"updated":"2020-11-30 17:48:17.000000000","message":"seems reasonable","commit_id":"d6279ad62525f6a3e3d008ccaa27dce516cd7b37"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"dd2d561d7baf5958cde1ea7be6b66de04dc24463","unresolved":false,"context_lines":[{"line_number":1300,"context_line":"            hashes \u003d self._diskfile_router[policy].get_hashes("},{"line_number":1301,"context_line":"                device, partition, suffixes, policy,"},{"line_number":1302,"context_line":"                delay_rehash\u003dconfig_true_value("},{"line_number":1303,"context_line":"                    request.headers.get(\u0027X-Backend-Delay-Rehash\u0027)))"},{"line_number":1304,"context_line":"        except DiskFileDeviceUnavailable:"},{"line_number":1305,"context_line":"            resp \u003d HTTPInsufficientStorage(drive\u003ddevice, request\u003drequest)"},{"line_number":1306,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":5,"id":"1f621f24_8c3d3b91","line":1303,"updated":"2020-11-06 16:32:12.000000000","message":"is there ever a case where REPLICATE is called *with* suffixes and we *do* want to rehash? I\u0027m wondering if it can just be inferred that the existence of suffixes implies \"invalidate only\"?\n\nI added an exception to blow up if get_hashes is called with delay_rehash\u003dFalse and suffixes, and probe/test_replicator passed (of course, that\u0027s just an indicator, not proof!)","commit_id":"c11286ed108ceb4e5ec5aa48eca0cfeb86dcaf70"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"1146882f2f0fadb441d728cc970b704a63294a74","unresolved":false,"context_lines":[{"line_number":1300,"context_line":"            hashes \u003d self._diskfile_router[policy].get_hashes("},{"line_number":1301,"context_line":"                device, partition, suffixes, policy,"},{"line_number":1302,"context_line":"                delay_rehash\u003dconfig_true_value("},{"line_number":1303,"context_line":"                    request.headers.get(\u0027X-Backend-Delay-Rehash\u0027)))"},{"line_number":1304,"context_line":"        except DiskFileDeviceUnavailable:"},{"line_number":1305,"context_line":"            resp \u003d HTTPInsufficientStorage(drive\u003ddevice, request\u003drequest)"},{"line_number":1306,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":5,"id":"1f621f24_d87249ad","line":1303,"in_reply_to":"1f621f24_8c3d3b91","updated":"2020-11-06 23:16:39.000000000","message":"Nope (or at least, not yet!) -- good call.","commit_id":"c11286ed108ceb4e5ec5aa48eca0cfeb86dcaf70"}],"test/probe/test_replication_servers_working.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e4b48b0c3f798f932d8ca43b57c0415b2776698d","unresolved":false,"context_lines":[{"line_number":158,"context_line":"            self.replicators.stop()"},{"line_number":159,"context_line":""},{"line_number":160,"context_line":"            # Run replicators *one more time* to make sure invalidated hashes"},{"line_number":161,"context_line":"            # get rolled up to hashes.pkl"},{"line_number":162,"context_line":"            self.replicators.once()"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"            # Delete directories and files in objects storage without"}],"source_content_type":"text/x-python","patch_set":6,"id":"1f621f24_fed9de56","line":161,"updated":"2020-11-09 18:09:31.000000000","message":"Would be good to have a little more explanation here","commit_id":"f6493c131d988e07e773906db2a86528900d63fb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a0370aa849edb6179ccbfaac2295d84aefeabdef","unresolved":false,"context_lines":[{"line_number":159,"context_line":""},{"line_number":160,"context_line":"            # Run replicators *one more time* to make sure invalidated hashes"},{"line_number":161,"context_line":"            # get rolled up to hashes.pkl"},{"line_number":162,"context_line":"            self.replicators.once()"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"            # Delete directories and files in objects storage without"},{"line_number":165,"context_line":"            # deleting file \"hashes.pkl\" / \"hashes.invalid\"."}],"source_content_type":"text/x-python","patch_set":6,"id":"1f621f24_5893cf5b","line":162,"updated":"2020-11-09 11:30:06.000000000","message":"this shouldn\u0027t be necessary. If it is necessary then it implies that maybe the rehash/consolidation was necessary at end of last cycle after all. But, I removed the change and probe test passes for me.","commit_id":"f6493c131d988e07e773906db2a86528900d63fb"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e8546d794f80ffd05cc916f411ae0d22803296f5","unresolved":false,"context_lines":[{"line_number":159,"context_line":""},{"line_number":160,"context_line":"            # Run replicators *one more time* to make sure invalidated hashes"},{"line_number":161,"context_line":"            # get rolled up to hashes.pkl"},{"line_number":162,"context_line":"            self.replicators.once()"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"            # Delete directories and files in objects storage without"},{"line_number":165,"context_line":"            # deleting file \"hashes.pkl\" / \"hashes.invalid\"."}],"source_content_type":"text/x-python","patch_set":6,"id":"1f621f24_6a998dc2","line":162,"in_reply_to":"1f621f24_5893cf5b","updated":"2020-11-09 16:49:25.000000000","message":"I added this after seeing https://zuul.opendev.org/t/openstack/build/3714d89c0c7b498fae3df1959c15b6d3/log/job-output.txt#1124-1129\n\nThere definitely is a chance that we see the files get replicated (and break out of the loop) while the suffixes are still sitting in the .invalid. If we go unlinking a bunch of data *before* we\u0027ve actually rehashed, of course the rehash will say \"I don\u0027t have this\" and when we run the replicators down at L174, we\u0027ll go copying data.\n\nSince the point of the loop is to get things to a settled state, it seemed (to me) like running replicators one more time would be acceptable.\n\nFWIW, if I run this test 10x without this change, I tend to get ~2 failures with a pretty even split on TestReplicatorFunctions vs TestReplicatorFunctionsReservedNames.","commit_id":"f6493c131d988e07e773906db2a86528900d63fb"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"499640dd58007bfd5a3727423b5e5da522d95452","unresolved":false,"context_lines":[{"line_number":159,"context_line":""},{"line_number":160,"context_line":"            # Run replicators *one more time* to make sure invalidated hashes"},{"line_number":161,"context_line":"            # get rolled up to hashes.pkl"},{"line_number":162,"context_line":"            self.replicators.once()"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"            # Delete directories and files in objects storage without"},{"line_number":165,"context_line":"            # deleting file \"hashes.pkl\" / \"hashes.invalid\"."}],"source_content_type":"text/x-python","patch_set":6,"id":"1f621f24_1e077acc","line":162,"in_reply_to":"1f621f24_6a998dc2","updated":"2020-11-09 18:07:41.000000000","message":"OK I see it now: the next part of the test verifies/demonstrates that once the hashes.pkl is up to date then deleting object files under hood would not be detected by subsequent replication. If the replicator on test_node ran *after the objects had been replicated* during the last cycle then it would have already caused rehash to update hashes.pkl, so the test would proceed OK as it was. But if the test_node replicator ran before the object data was replicated, then test_node is left with invalid hashes in hashes.invalid which means that the next part of the test *would* replicate data and fail.","commit_id":"f6493c131d988e07e773906db2a86528900d63fb"}],"test/unit/obj/test_diskfile.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"a9a4d4000cc47aa13a7863da7763cfbd76dbd63e","unresolved":false,"context_lines":[{"line_number":6895,"context_line":"            self.assertEqual(hashes, {suffix: non_local[\u0027hash\u0027]})"},{"line_number":6896,"context_line":""},{"line_number":6897,"context_line":""},{"line_number":6898,"context_line":"    def test_hash_invalidations_race_get_hashes_same_suffix_new(self):"},{"line_number":6899,"context_line":"        self._check_hash_invalidations_race_get_hashes_same_suffix(False)"},{"line_number":6900,"context_line":""},{"line_number":6901,"context_line":"    def test_hash_invalidations_race_get_hashes_same_suffix_existing(self):"}],"source_content_type":"text/x-python","patch_set":4,"id":"1f621f24_0b833155","line":6898,"updated":"2020-10-30 05:23:09.000000000","message":"pep8: E303 too many blank lines (2)","commit_id":"aa4cada54e7cbdd4e8a3bb456e061f0ce0dd6aaf"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"dd2d561d7baf5958cde1ea7be6b66de04dc24463","unresolved":false,"context_lines":[{"line_number":6850,"context_line":"            # can skip rehash/updating pickle"},{"line_number":6851,"context_line":"            hashes \u003d df_mgr.get_hashes(\u0027sda1\u0027, \u00270\u0027, [suffix], policy,"},{"line_number":6852,"context_line":"                                       delay_rehash\u003dTrue)"},{"line_number":6853,"context_line":"            self.assertEqual(hashes, {})"},{"line_number":6854,"context_line":""},{"line_number":6855,"context_line":"            def mock_hash_suffix(*args, **kwargs):"},{"line_number":6856,"context_line":"                # after first get_hashes has called _hash_suffix, simulate a"}],"source_content_type":"text/x-python","patch_set":5,"id":"1f621f24_ec0b0f7a","line":6853,"updated":"2020-11-06 16:32:12.000000000","message":"but if the suffix had previously been in hashes.pkl it would be returned, as per lines 6890-6895, so the test demonstrates that the return values are unpredictable???","commit_id":"c11286ed108ceb4e5ec5aa48eca0cfeb86dcaf70"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"dd2d561d7baf5958cde1ea7be6b66de04dc24463","unresolved":false,"context_lines":[{"line_number":6892,"context_line":"                hashes \u003d df_mgr.get_hashes(\u0027sda1\u0027, \u00270\u0027, [suffix], policy,"},{"line_number":6893,"context_line":"                                           delay_rehash\u003dTrue)"},{"line_number":6894,"context_line":"            self.assertFalse(non_local[\u0027called\u0027])"},{"line_number":6895,"context_line":"            self.assertEqual(hashes, {suffix: non_local[\u0027hash\u0027]})"},{"line_number":6896,"context_line":""},{"line_number":6897,"context_line":"    def test_hash_invalidations_race_get_hashes_same_suffix_new(self):"},{"line_number":6898,"context_line":"        self._check_hash_invalidations_race_get_hashes_same_suffix(False)"}],"source_content_type":"text/x-python","patch_set":5,"id":"1f621f24_ac15979e","line":6895,"updated":"2020-11-06 16:32:12.000000000","message":"is this the desired result? we just invalidated this suffix so the hash values is stale?","commit_id":"c11286ed108ceb4e5ec5aa48eca0cfeb86dcaf70"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"dd2d561d7baf5958cde1ea7be6b66de04dc24463","unresolved":false,"context_lines":[{"line_number":7049,"context_line":"                hashes \u003d df_mgr.get_hashes(\u0027sda1\u0027, \u00270\u0027, [], policy,"},{"line_number":7050,"context_line":"                                           delay_rehash\u003dTrue)"},{"line_number":7051,"context_line":"                mock_consolidate_hashes.assert_not_called()"},{"line_number":7052,"context_line":"                self.assertEqual(hashes, {\u0027updated\u0027: -1, \u0027valid\u0027: False})"},{"line_number":7053,"context_line":""},{"line_number":7054,"context_line":"                # creates pkl file"},{"line_number":7055,"context_line":"                df_mgr.get_hashes(\u0027sda1\u0027, \u00270\u0027, [], policy)"}],"source_content_type":"text/x-python","patch_set":5,"id":"1f621f24_2c57c75a","line":7052,"updated":"2020-11-06 16:32:12.000000000","message":"if delay_rehash\u003dFalse these keys get popped out of the results dict","commit_id":"c11286ed108ceb4e5ec5aa48eca0cfeb86dcaf70"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a0370aa849edb6179ccbfaac2295d84aefeabdef","unresolved":false,"context_lines":[{"line_number":6884,"context_line":""},{"line_number":6885,"context_line":"            non_local[\u0027called\u0027] \u003d False"},{"line_number":6886,"context_line":"            with mock.patch.object(df_mgr, \u0027_hash_suffix\u0027, mock_hash_suffix):"},{"line_number":6887,"context_line":"                df_mgr.get_hashes(\u0027sda1\u0027, \u00270\u0027, [suffix], policy,"},{"line_number":6888,"context_line":"                                  skip_rehash\u003dTrue)"},{"line_number":6889,"context_line":"            self.assertFalse(non_local[\u0027called\u0027])"},{"line_number":6890,"context_line":"            with open(invalidations_file) as f:"}],"source_content_type":"text/x-python","patch_set":6,"id":"1f621f24_78a4cba6","line":6887,"updated":"2020-11-09 11:30:06.000000000","message":"maybe assert None return value, and non-None at line 6873","commit_id":"f6493c131d988e07e773906db2a86528900d63fb"}]}
