)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8e8f11f6bb64d578f90df6d4686744a1c0fb32c3","unresolved":false,"context_lines":[{"line_number":18,"context_line":"the dispersion value should improve with every rebalance."},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"N.B. with this change it\u0027s possible for rings with 100% undispersion to"},{"line_number":21,"context_line":"have \u003e100% undispersion after a rebalance (even though they will have"},{"line_number":22,"context_line":"likely had their dispersion *improve*) because we are more accurately"},{"line_number":23,"context_line":"representing how terrible your dispersion is."},{"line_number":24,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"df87a7cf_89896627","line":21,"range":{"start_line":21,"start_character":24,"end_line":21,"end_character":41},"updated":"2017-12-15 18:43:38.000000000","message":"Well... really, they would have had \u003e100% undispersion *before* the rebalance, too, yeah? If they were to just look at the ring after the upgrade, it\u0027d show the new value, right?","commit_id":"dde2d043a07e21634f8ee1627b33ef464ab5563b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c636fede3d526bbb12220238d1035b907c630c4b","unresolved":false,"context_lines":[{"line_number":18,"context_line":"the dispersion value should improve with every rebalance."},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"N.B. with this change it\u0027s possible for rings with 100% undispersion to"},{"line_number":21,"context_line":"have \u003e100% undispersion after a rebalance (even though they will have"},{"line_number":22,"context_line":"likely had their dispersion *improve*) because we are more accurately"},{"line_number":23,"context_line":"representing how terrible your dispersion is."},{"line_number":24,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"df87a7cf_1587a811","line":21,"range":{"start_line":21,"start_character":24,"end_line":21,"end_character":41},"in_reply_to":"df87a7cf_89896627","updated":"2017-12-15 23:32:43.000000000","message":"yes it was \"\u003e100% undispersion\" before.. but that\u0027s not what it would look like to them no, the dispersion calculation is done during rebalance and cached on the builder.","commit_id":"dde2d043a07e21634f8ee1627b33ef464ab5563b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"80af5ec5c61ada9b46f5f4b6bf65fe97b2f064ee","unresolved":false,"context_lines":[{"line_number":21,"context_line":"value to measure as having a significantly smaller dispersion value"},{"line_number":22,"context_line":"after a rebalance (even though they may not have had their dispersion"},{"line_number":23,"context_line":"change) because the total amount of bad dispersion we can measure has"},{"line_number":24,"context_line":"been increased but we\u0027re normalizing within a similar range."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"Closes-Bug: #1697543"},{"line_number":27,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":5,"id":"9f91af0f_a1661551","line":24,"updated":"2017-12-28 19:26:11.000000000","message":"Is there anything operators can do to recalculate the ring\u0027s dispersion *without* a rebalance? Then, when they *do* get around to doing a rebalance, it will be more apples-to-apples.","commit_id":"7013e70ca67891e94664e9eca70925b61ee8f689"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ed31eb72cc637cddc1c2aa71185ebc9752ff76ce","unresolved":false,"context_lines":[{"line_number":21,"context_line":"value to measure as having a significantly smaller dispersion value"},{"line_number":22,"context_line":"after a rebalance (even though they may not have had their dispersion"},{"line_number":23,"context_line":"change) because the total amount of bad dispersion we can measure has"},{"line_number":24,"context_line":"been increased but we\u0027re normalizing within a similar range."},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"Closes-Bug: #1697543"},{"line_number":27,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":5,"id":"9f91af0f_9cb7b4d9","line":24,"in_reply_to":"9f91af0f_a1661551","updated":"2017-12-28 21:23:34.000000000","message":"nothing like that exists today unfortunately","commit_id":"7013e70ca67891e94664e9eca70925b61ee8f689"}],"swift/common/ring/builder.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8e8f11f6bb64d578f90df6d4686744a1c0fb32c3","unresolved":false,"context_lines":[{"line_number":635,"context_line":"                    part_risk_depth[len(tier)] +\u003d ("},{"line_number":636,"context_line":"                        replicas - max_allowed_replicas[tier])"},{"line_number":637,"context_line":"            # count each part-replica once at tier where dispersion is worst"},{"line_number":638,"context_line":"            parts_at_risk +\u003d max(part_risk_depth.values() or [0])"},{"line_number":639,"context_line":"        self._dispersion_graph \u003d dispersion_graph"},{"line_number":640,"context_line":"        self.dispersion \u003d 100.0 * parts_at_risk / self.parts"},{"line_number":641,"context_line":"        return changed_parts"}],"source_content_type":"text/x-python","patch_set":1,"id":"df87a7cf_e66701b7","line":638,"updated":"2017-12-15 18:43:38.000000000","message":"It\u0027s like we\u0027re *trying* to make a py3 port difficult...\n\nCan we set some reasonable default early on? Like\n\n part_risk_depth \u003d defaultdict(int)\n part_risk_depth[0] \u003d 0\n ...\n parts_at_risk +\u003d max(part_risk_depth.values())","commit_id":"dde2d043a07e21634f8ee1627b33ef464ab5563b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8e8f11f6bb64d578f90df6d4686744a1c0fb32c3","unresolved":false,"context_lines":[{"line_number":637,"context_line":"            # count each part-replica once at tier where dispersion is worst"},{"line_number":638,"context_line":"            parts_at_risk +\u003d max(part_risk_depth.values() or [0])"},{"line_number":639,"context_line":"        self._dispersion_graph \u003d dispersion_graph"},{"line_number":640,"context_line":"        self.dispersion \u003d 100.0 * parts_at_risk / self.parts"},{"line_number":641,"context_line":"        return changed_parts"},{"line_number":642,"context_line":""},{"line_number":643,"context_line":"    def validate(self, stats\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":1,"id":"df87a7cf_49f27e08","line":640,"updated":"2017-12-15 18:43:38.000000000","message":"The range of values here used to be [0, 100], but now it\u0027s... [0, 100 * num_replicas]? [0, 100 * (num_replicas - 1)]?","commit_id":"dde2d043a07e21634f8ee1627b33ef464ab5563b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c636fede3d526bbb12220238d1035b907c630c4b","unresolved":false,"context_lines":[{"line_number":637,"context_line":"            # count each part-replica once at tier where dispersion is worst"},{"line_number":638,"context_line":"            parts_at_risk +\u003d max(part_risk_depth.values() or [0])"},{"line_number":639,"context_line":"        self._dispersion_graph \u003d dispersion_graph"},{"line_number":640,"context_line":"        self.dispersion \u003d 100.0 * parts_at_risk / self.parts"},{"line_number":641,"context_line":"        return changed_parts"},{"line_number":642,"context_line":""},{"line_number":643,"context_line":"    def validate(self, stats\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":1,"id":"df87a7cf_35066c88","line":640,"in_reply_to":"df87a7cf_49f27e08","updated":"2017-12-15 23:32:43.000000000","message":"definitely \u003e 100 and yeah I think at least one replicanth has to be disperesed - so I\u0027d buy num_replicas * 100 - 100","commit_id":"dde2d043a07e21634f8ee1627b33ef464ab5563b"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"52ed28bf4d0a85f4706c468aadce70a432c02f0c","unresolved":false,"context_lines":[{"line_number":638,"context_line":"            # count each part-replica once at tier where dispersion is worst"},{"line_number":639,"context_line":"            parts_at_risk +\u003d max(part_risk_depth.values())"},{"line_number":640,"context_line":"        self._dispersion_graph \u003d dispersion_graph"},{"line_number":641,"context_line":"        self.dispersion \u003d 100.0 * parts_at_risk / self.parts"},{"line_number":642,"context_line":"        return changed_parts"},{"line_number":643,"context_line":""},{"line_number":644,"context_line":"    def validate(self, stats\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":3,"id":"bf8cb3f7_5c4a6e27","line":641,"range":{"start_line":641,"start_character":26,"end_line":641,"end_character":60},"updated":"2017-12-22 00:32:44.000000000","message":"I\u0027m not so sure this calculation makes sense anymore.\nPrevious, it was more of a percentage. Ie which partitions where at risk. Now its really how many replicanths, so dividing that by self.parts, will easily jump above 100.\n\nMaybe we should turn it back into a percentage, but of replicaths, so:\n\n  self.dispersion \u003d 100.0 * parts_at_risk / (self.parts * self.replicas)\n\nOf course this means we\u0027ll probably be dealing with lower numbers, but at least when you get the dispersion number it\u0027s mean at a glance it\u0027ll make more sense.\n\nFor example, the test_rebalance_saves_dispersion_improvement in test_ringbuilder, instead of being 200:\n\n  100.0 * 128 / 64\n\nWould become:\n\n  100.0 * 128 / (64 * 6) OR 33.33\n\nThen at a glance we know that 33% of our replicaths in the cluster are not properly dispersed.","commit_id":"b940fc70e40fc9721e32ac462bbdde5e63919c5e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"7ecb7622420f92eb5bc8e33abda54fb3553f8104","unresolved":false,"context_lines":[{"line_number":638,"context_line":"            # count each part-replica once at tier where dispersion is worst"},{"line_number":639,"context_line":"            parts_at_risk +\u003d max(part_risk_depth.values())"},{"line_number":640,"context_line":"        self._dispersion_graph \u003d dispersion_graph"},{"line_number":641,"context_line":"        self.dispersion \u003d 100.0 * parts_at_risk / self.parts"},{"line_number":642,"context_line":"        return changed_parts"},{"line_number":643,"context_line":""},{"line_number":644,"context_line":"    def validate(self, stats\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":3,"id":"bf8cb3f7_0846d97d","line":641,"range":{"start_line":641,"start_character":26,"end_line":641,"end_character":60},"in_reply_to":"bf8cb3f7_5c4a6e27","updated":"2017-12-22 16:49:42.000000000","message":"My initial reaction is that normalization is probably a pretty reasonable idea - I\u0027ll definitely play with it.  One side benefit might be that no existing builders dispersion measurement would go *up* ...","commit_id":"b940fc70e40fc9721e32ac462bbdde5e63919c5e"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"ec61e1aa3e7823cd04fc2ceb52e4ccd6294f6dd6","unresolved":false,"context_lines":[{"line_number":638,"context_line":"            # count each part-replica once at tier where dispersion is worst"},{"line_number":639,"context_line":"            parts_at_risk +\u003d max(part_risk_depth.values())"},{"line_number":640,"context_line":"        self._dispersion_graph \u003d dispersion_graph"},{"line_number":641,"context_line":"        self.dispersion \u003d 100.0 * parts_at_risk / (self.parts * self.replicas)"},{"line_number":642,"context_line":"        return changed_parts"},{"line_number":643,"context_line":""},{"line_number":644,"context_line":"    def validate(self, stats\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":4,"id":"bf8cb3f7_351a117d","line":641,"updated":"2017-12-22 18:38:18.000000000","message":"So how about\n\n 100.0 * parts_at_risk / (self.parts * (self.replicas - 1))\n\n? That should get us in the range [0, 100] all the time, yeah?","commit_id":"877c2c72f27334fb128a6f5c1e306fd5d8d308b8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cd3671bdeac53acada8bda322c83ee254d0943af","unresolved":false,"context_lines":[{"line_number":638,"context_line":"            # count each part-replica once at tier where dispersion is worst"},{"line_number":639,"context_line":"            parts_at_risk +\u003d max(part_risk_depth.values())"},{"line_number":640,"context_line":"        self._dispersion_graph \u003d dispersion_graph"},{"line_number":641,"context_line":"        self.dispersion \u003d 100.0 * parts_at_risk / (self.parts * self.replicas)"},{"line_number":642,"context_line":"        return changed_parts"},{"line_number":643,"context_line":""},{"line_number":644,"context_line":"    def validate(self, stats\u003dFalse):"}],"source_content_type":"text/x-python","patch_set":4,"id":"9f91af0f_c846e350","line":641,"in_reply_to":"bf8cb3f7_351a117d","updated":"2017-12-28 06:19:42.000000000","message":"I wouldn\u0027t bother with this idea -- just know that the upper bounds on dispersion vary with replica count.","commit_id":"877c2c72f27334fb128a6f5c1e306fd5d8d308b8"}],"swift/common/ring/utils.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cd3671bdeac53acada8bda322c83ee254d0943af","unresolved":false,"context_lines":[{"line_number":618,"context_line":"        if search_filter and not re.match(search_filter, tier_name):"},{"line_number":619,"context_line":"            continue"},{"line_number":620,"context_line":"        max_replicas \u003d int(max_allowed_replicas[tier])"},{"line_number":621,"context_line":"        at_risk_parts \u003d sum(replica_counts[i] * i for i in range("},{"line_number":622,"context_line":"            max_replicas + 1, len(replica_counts)))"},{"line_number":623,"context_line":"        placed_parts \u003d sum(replica_counts[i] * i for i in range("},{"line_number":624,"context_line":"            1, len(replica_counts)))"}],"source_content_type":"text/x-python","patch_set":4,"id":"9f91af0f_a5f2aa99","line":621,"range":{"start_line":621,"start_character":24,"end_line":621,"end_character":49},"updated":"2017-12-28 06:19:42.000000000","message":"I think this should be\n\n sum(replica_counts[i] * (i - max_replicas) ...\n\nThe first max_replicas aren\u0027t technically \"at risk\", no?\n\nOr rather, *all* replicas of *all* parts are at risk, and the sooner we come to terms with that, the better. But here we\u0027re interested in the number that are *excessively* at risk as a result of us trying not to fill up smaller drives.","commit_id":"877c2c72f27334fb128a6f5c1e306fd5d8d308b8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"4678cf775fa841a82af3ce892742f376e2d52025","unresolved":false,"context_lines":[{"line_number":618,"context_line":"        if search_filter and not re.match(search_filter, tier_name):"},{"line_number":619,"context_line":"            continue"},{"line_number":620,"context_line":"        max_replicas \u003d int(max_allowed_replicas[tier])"},{"line_number":621,"context_line":"        at_risk_parts \u003d sum(replica_counts[i] * i for i in range("},{"line_number":622,"context_line":"            max_replicas + 1, len(replica_counts)))"},{"line_number":623,"context_line":"        placed_parts \u003d sum(replica_counts[i] * i for i in range("},{"line_number":624,"context_line":"            1, len(replica_counts)))"}],"source_content_type":"text/x-python","patch_set":4,"id":"9f91af0f_c1ab1973","line":621,"range":{"start_line":621,"start_character":24,"end_line":621,"end_character":49},"in_reply_to":"9f91af0f_a5f2aa99","updated":"2017-12-28 19:16:59.000000000","message":"yeah I acctually like that... \n\nbefore:\n\n    Dispersion is 16.666667, Balance is 0.000000, Overload is 0.00%\n    Required overload is 33.333333%\n    Worst tier is 66.666667 (r1z3)\n    --------------------------------------------------------------------------\n    Tier                           Parts      %    Max     0     1     2     3\n    --------------------------------------------------------------------------\n    r1                               768   0.00      3     0     0     0   256\n    r1z1                             192   0.00      1    64   192     0     0\n    r1z1-127.0.0.1                   192   0.00      1    64   192     0     0\n    r1z1-127.0.0.1/sda               192   0.00      1    64   192     0     0\n    r1z2                             192   0.00      1    64   192     0     0\n    r1z2-127.0.0.2                   192   0.00      1    64   192     0     0\n    r1z2-127.0.0.2/sda               192   0.00      1    64   192     0     0\n    r1z3                             384  66.67      1     0   128   128     0\n    r1z3-127.0.0.3                   384  66.67      1     0   128   128     0\n    r1z3-127.0.0.3/sda               192   0.00      1    64   192     0     0\n    r1z3-127.0.0.3/sdb               192   0.00      1    64   192     0     0\n\n\n\nafter:\n\n    Dispersion is 16.666667, Balance is 0.000000, Overload is 0.00%\n    Required overload is 33.333333%\n    Worst tier is 33.333333 (r1z3)\n    --------------------------------------------------------------------------\n    Tier                           Parts      %    Max     0     1     2     3\n    --------------------------------------------------------------------------\n    r1                               768   0.00      3     0     0     0   256\n    r1z1                             192   0.00      1    64   192     0     0\n    r1z1-127.0.0.1                   192   0.00      1    64   192     0     0\n    r1z1-127.0.0.1/sda               192   0.00      1    64   192     0     0\n    r1z2                             192   0.00      1    64   192     0     0\n    r1z2-127.0.0.2                   192   0.00      1    64   192     0     0\n    r1z2-127.0.0.2/sda               192   0.00      1    64   192     0     0\n    r1z3                             384  33.33      1     0   128   128     0\n    r1z3-127.0.0.3                   384  33.33      1     0   128   128     0\n    r1z3-127.0.0.3/sda               192   0.00      1    64   192     0     0\n    r1z3-127.0.0.3/sdb               192   0.00      1    64   192     0     0","commit_id":"877c2c72f27334fb128a6f5c1e306fd5d8d308b8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cd3671bdeac53acada8bda322c83ee254d0943af","unresolved":false,"context_lines":[{"line_number":620,"context_line":"        max_replicas \u003d int(max_allowed_replicas[tier])"},{"line_number":621,"context_line":"        at_risk_parts \u003d sum(replica_counts[i] * i for i in range("},{"line_number":622,"context_line":"            max_replicas + 1, len(replica_counts)))"},{"line_number":623,"context_line":"        placed_parts \u003d sum(replica_counts[i] * i for i in range("},{"line_number":624,"context_line":"            1, len(replica_counts)))"},{"line_number":625,"context_line":"        tier_dispersion \u003d 100.0 * at_risk_parts / placed_parts"},{"line_number":626,"context_line":"        if tier_dispersion \u003e max_dispersion:"},{"line_number":627,"context_line":"            max_dispersion \u003d tier_dispersion"}],"source_content_type":"text/x-python","patch_set":4,"id":"9f91af0f_e523d2bd","line":624,"range":{"start_line":623,"start_character":23,"end_line":624,"end_character":36},"updated":"2017-12-28 06:19:42.000000000","message":"nit: Simpler as\n\n sum(i * c for i, c in enumerate(replica_counts))\n\n?","commit_id":"877c2c72f27334fb128a6f5c1e306fd5d8d308b8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"4678cf775fa841a82af3ce892742f376e2d52025","unresolved":false,"context_lines":[{"line_number":620,"context_line":"        max_replicas \u003d int(max_allowed_replicas[tier])"},{"line_number":621,"context_line":"        at_risk_parts \u003d sum(replica_counts[i] * i for i in range("},{"line_number":622,"context_line":"            max_replicas + 1, len(replica_counts)))"},{"line_number":623,"context_line":"        placed_parts \u003d sum(replica_counts[i] * i for i in range("},{"line_number":624,"context_line":"            1, len(replica_counts)))"},{"line_number":625,"context_line":"        tier_dispersion \u003d 100.0 * at_risk_parts / placed_parts"},{"line_number":626,"context_line":"        if tier_dispersion \u003e max_dispersion:"},{"line_number":627,"context_line":"            max_dispersion \u003d tier_dispersion"}],"source_content_type":"text/x-python","patch_set":4,"id":"9f91af0f_e1a89d78","line":624,"range":{"start_line":623,"start_character":23,"end_line":624,"end_character":36},"in_reply_to":"9f91af0f_e523d2bd","updated":"2017-12-28 19:16:59.000000000","message":"Done","commit_id":"877c2c72f27334fb128a6f5c1e306fd5d8d308b8"}],"test/unit/cli/test_ringbuilder.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8e8f11f6bb64d578f90df6d4686744a1c0fb32c3","unresolved":false,"context_lines":[{"line_number":1927,"context_line":"        # device won\u0027t acquire any partitions, so the ring\u0027s balance won\u0027t"},{"line_number":1928,"context_line":"        # change. However, dispersion will improve."},{"line_number":1929,"context_line":""},{"line_number":1930,"context_line":"        ring \u003d RingBuilder(6, 6, 1)"},{"line_number":1931,"context_line":"        devs \u003d (\u0027d%s\u0027 % i for i in itertools.count())"},{"line_number":1932,"context_line":"        for i in range(6):"},{"line_number":1933,"context_line":"            ring.add_dev({"}],"source_content_type":"text/x-python","patch_set":1,"id":"df87a7cf_26788929","line":1930,"range":{"start_line":1930,"start_character":30,"end_line":1930,"end_character":31},"updated":"2017-12-15 18:43:38.000000000","message":"Why the bump up from 5 to 6?","commit_id":"dde2d043a07e21634f8ee1627b33ef464ab5563b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c636fede3d526bbb12220238d1035b907c630c4b","unresolved":false,"context_lines":[{"line_number":1927,"context_line":"        # device won\u0027t acquire any partitions, so the ring\u0027s balance won\u0027t"},{"line_number":1928,"context_line":"        # change. However, dispersion will improve."},{"line_number":1929,"context_line":""},{"line_number":1930,"context_line":"        ring \u003d RingBuilder(6, 6, 1)"},{"line_number":1931,"context_line":"        devs \u003d (\u0027d%s\u0027 % i for i in itertools.count())"},{"line_number":1932,"context_line":"        for i in range(6):"},{"line_number":1933,"context_line":"            ring.add_dev({"}],"source_content_type":"text/x-python","patch_set":1,"id":"df87a7cf_75f3949f","line":1930,"range":{"start_line":1930,"start_character":30,"end_line":1930,"end_character":31},"in_reply_to":"df87a7cf_26788929","updated":"2017-12-15 23:32:43.000000000","message":"to trigger the reason the original change was partial-bug and not close, it could detect 100 \u003d\u003e 0 with balance stuck, but not 100 \u003d\u003e 100 with balance stuck.  Now we it will detect 200 \u003d\u003e 100 - but we have to have enough replicas to make dispersion that bad.","commit_id":"dde2d043a07e21634f8ee1627b33ef464ab5563b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"330d5d3e01ed2205ea132cf0a7692e949715da59","unresolved":false,"context_lines":[{"line_number":1957,"context_line":"        argv \u003d [\"\", self.tmpfile, \"rebalance\", \"5759339\"]"},{"line_number":1958,"context_line":"        self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)"},{"line_number":1959,"context_line":"        rb \u003d RingBuilder.load(self.tmpfile)"},{"line_number":1960,"context_line":"        self.assertEqual(rb.dispersion, 100)"},{"line_number":1961,"context_line":"        self.assertEqual(rb.get_balance(), 100)"},{"line_number":1962,"context_line":"        self.run_srb(\u0027pretend_min_part_hours_passed\u0027)"},{"line_number":1963,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"bf8cb3f7_bd34f8df","line":1960,"updated":"2017-12-20 19:06:45.000000000","message":"200 now","commit_id":"1061437ec7eab422c6d40d9231736f2c87adbf0c"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"330d5d3e01ed2205ea132cf0a7692e949715da59","unresolved":false,"context_lines":[{"line_number":1976,"context_line":"        with mock.patch(\u0027swift.common.ring.RingBuilder.save\u0027, capture_save):"},{"line_number":1977,"context_line":"            self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)"},{"line_number":1978,"context_line":"        self.assertEqual(captured, {"},{"line_number":1979,"context_line":"            \u0027dispersion\u0027: 0,"},{"line_number":1980,"context_line":"            \u0027balance\u0027: 100,"},{"line_number":1981,"context_line":"        })"},{"line_number":1982,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"bf8cb3f7_bd62b8d7","line":1979,"updated":"2017-12-20 19:06:45.000000000","message":"100 now","commit_id":"1061437ec7eab422c6d40d9231736f2c87adbf0c"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cd3671bdeac53acada8bda322c83ee254d0943af","unresolved":false,"context_lines":[{"line_number":1952,"context_line":"        ring.save(self.tmpfile)"},{"line_number":1953,"context_line":"        del ring"},{"line_number":1954,"context_line":""},{"line_number":1955,"context_line":"        # Rebalance once: this gets 1/5 replica into zone 2; the ring is"},{"line_number":1956,"context_line":"        # saved because devices changed."},{"line_number":1957,"context_line":"        argv \u003d [\"\", self.tmpfile, \"rebalance\", \"5759339\"]"},{"line_number":1958,"context_line":"        self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9f91af0f_c5e24e30","line":1955,"range":{"start_line":1955,"start_character":36,"end_line":1955,"end_character":47},"updated":"2017-12-28 06:19:42.000000000","message":"Not 1/5 *of a* replica! 1 *of* 5 replicas! I\u0027m starting to get it... only now we\u0027re at 1 of *6*.","commit_id":"877c2c72f27334fb128a6f5c1e306fd5d8d308b8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"4678cf775fa841a82af3ce892742f376e2d52025","unresolved":false,"context_lines":[{"line_number":1952,"context_line":"        ring.save(self.tmpfile)"},{"line_number":1953,"context_line":"        del ring"},{"line_number":1954,"context_line":""},{"line_number":1955,"context_line":"        # Rebalance once: this gets 1/5 replica into zone 2; the ring is"},{"line_number":1956,"context_line":"        # saved because devices changed."},{"line_number":1957,"context_line":"        argv \u003d [\"\", self.tmpfile, \"rebalance\", \"5759339\"]"},{"line_number":1958,"context_line":"        self.assertSystemExit(EXIT_WARNING, ringbuilder.main, argv)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9f91af0f_4134e94a","line":1955,"range":{"start_line":1955,"start_character":36,"end_line":1955,"end_character":47},"in_reply_to":"9f91af0f_c5e24e30","updated":"2017-12-28 19:16:59.000000000","message":"Done","commit_id":"877c2c72f27334fb128a6f5c1e306fd5d8d308b8"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cd3671bdeac53acada8bda322c83ee254d0943af","unresolved":false,"context_lines":[{"line_number":1961,"context_line":"        self.assertEqual(rb.get_balance(), 100)"},{"line_number":1962,"context_line":"        self.run_srb(\u0027pretend_min_part_hours_passed\u0027)"},{"line_number":1963,"context_line":""},{"line_number":1964,"context_line":"        # Rebalance again: this gets 2/5 replica into zone 2, but no devices"},{"line_number":1965,"context_line":"        # changed and the balance stays the same. The only improvement is"},{"line_number":1966,"context_line":"        # dispersion."},{"line_number":1967,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"9f91af0f_05f596cb","line":1964,"range":{"start_line":1964,"start_character":37,"end_line":1964,"end_character":40},"updated":"2017-12-28 06:19:42.000000000","message":"Again, needs updating.","commit_id":"877c2c72f27334fb128a6f5c1e306fd5d8d308b8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"4678cf775fa841a82af3ce892742f376e2d52025","unresolved":false,"context_lines":[{"line_number":1961,"context_line":"        self.assertEqual(rb.get_balance(), 100)"},{"line_number":1962,"context_line":"        self.run_srb(\u0027pretend_min_part_hours_passed\u0027)"},{"line_number":1963,"context_line":""},{"line_number":1964,"context_line":"        # Rebalance again: this gets 2/5 replica into zone 2, but no devices"},{"line_number":1965,"context_line":"        # changed and the balance stays the same. The only improvement is"},{"line_number":1966,"context_line":"        # dispersion."},{"line_number":1967,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"9f91af0f_6139ed3f","line":1964,"range":{"start_line":1964,"start_character":37,"end_line":1964,"end_character":40},"in_reply_to":"9f91af0f_05f596cb","updated":"2017-12-28 19:16:59.000000000","message":"Done","commit_id":"877c2c72f27334fb128a6f5c1e306fd5d8d308b8"}],"test/unit/common/ring/test_builder.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8e8f11f6bb64d578f90df6d4686744a1c0fb32c3","unresolved":false,"context_lines":[{"line_number":55,"context_line":"    def tearDown(self):"},{"line_number":56,"context_line":"        rmtree(self.testdir, ignore_errors\u003d1)"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    def _get_population_by_region(self, builder):"},{"line_number":59,"context_line":"        \"\"\""},{"line_number":60,"context_line":"        Returns a dictionary mapping region to number of partitions in that"},{"line_number":61,"context_line":"        region."}],"source_content_type":"text/x-python","patch_set":1,"id":"df87a7cf_669bf165","line":58,"updated":"2017-12-15 18:43:38.000000000","message":"Also a good candidate to move to a module-level function...","commit_id":"dde2d043a07e21634f8ee1627b33ef464ab5563b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c636fede3d526bbb12220238d1035b907c630c4b","unresolved":false,"context_lines":[{"line_number":55,"context_line":"    def tearDown(self):"},{"line_number":56,"context_line":"        rmtree(self.testdir, ignore_errors\u003d1)"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    def _get_population_by_region(self, builder):"},{"line_number":59,"context_line":"        \"\"\""},{"line_number":60,"context_line":"        Returns a dictionary mapping region to number of partitions in that"},{"line_number":61,"context_line":"        region."}],"source_content_type":"text/x-python","patch_set":1,"id":"df87a7cf_f534844c","line":58,"in_reply_to":"df87a7cf_669bf165","updated":"2017-12-15 23:32:43.000000000","message":"but it\u0027s only used in *this* test case?","commit_id":"dde2d043a07e21634f8ee1627b33ef464ab5563b"}],"test/unit/common/ring/test_utils.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8e8f11f6bb64d578f90df6d4686744a1c0fb32c3","unresolved":false,"context_lines":[{"line_number":622,"context_line":"        self.assertEqual(rb.dispersion, 55.46875)"},{"line_number":623,"context_line":"        report \u003d dispersion_report(rb)"},{"line_number":624,"context_line":"        self.assertEqual(report[\u0027worst_tier\u0027], \u0027r1z1\u0027)"},{"line_number":625,"context_line":"        self.assertEqual(report[\u0027max_dispersion\u0027], 55.02392344497608)"},{"line_number":626,"context_line":""},{"line_number":627,"context_line":"        def build_tier_report(max_replicas, placed_parts, dispersion,"},{"line_number":628,"context_line":"                              replicas):"}],"source_content_type":"text/x-python","patch_set":1,"id":"df87a7cf_66b451d2","line":625,"updated":"2017-12-15 18:43:38.000000000","message":"Much closer to rb.dispersion... seems like a good thing.","commit_id":"dde2d043a07e21634f8ee1627b33ef464ab5563b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8e8f11f6bb64d578f90df6d4686744a1c0fb32c3","unresolved":false,"context_lines":[{"line_number":635,"context_line":""},{"line_number":636,"context_line":"        # Each node should store less than or equal to 256 partitions to"},{"line_number":637,"context_line":"        # avoid multiple replicas."},{"line_number":638,"context_line":"        # 2/5 of total weight * 768 ~\u003d 307 -\u003e 51 partitions on each node in"},{"line_number":639,"context_line":"        # zone 1 are stored at least twice on the nodes"},{"line_number":640,"context_line":"        expected \u003d ["},{"line_number":641,"context_line":"            [\u0027r1z1\u0027, build_tier_report("}],"source_content_type":"text/x-python","patch_set":1,"id":"df87a7cf_e6edc1b7","line":638,"updated":"2017-12-15 18:43:38.000000000","message":"I\u0027m having a hard time following this. What\u0027s it about? I can\u0027t even make sense of it in the *old* context...","commit_id":"dde2d043a07e21634f8ee1627b33ef464ab5563b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c636fede3d526bbb12220238d1035b907c630c4b","unresolved":false,"context_lines":[{"line_number":635,"context_line":""},{"line_number":636,"context_line":"        # Each node should store less than or equal to 256 partitions to"},{"line_number":637,"context_line":"        # avoid multiple replicas."},{"line_number":638,"context_line":"        # 2/5 of total weight * 768 ~\u003d 307 -\u003e 51 partitions on each node in"},{"line_number":639,"context_line":"        # zone 1 are stored at least twice on the nodes"},{"line_number":640,"context_line":"        expected \u003d ["},{"line_number":641,"context_line":"            [\u0027r1z1\u0027, build_tier_report("}],"source_content_type":"text/x-python","patch_set":1,"id":"df87a7cf_f55b2484","line":638,"in_reply_to":"df87a7cf_e6edc1b7","updated":"2017-12-15 23:32:43.000000000","message":"yup, i agree, not sure what that math was trying to tell us...","commit_id":"dde2d043a07e21634f8ee1627b33ef464ab5563b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8e8f11f6bb64d578f90df6d4686744a1c0fb32c3","unresolved":false,"context_lines":[{"line_number":670,"context_line":"        report \u003d dispersion_report(rb, verbose\u003dTrue)"},{"line_number":671,"context_line":"        self.assertEqual(rb.dispersion, 11.71875)"},{"line_number":672,"context_line":"        self.assertEqual(report[\u0027worst_tier\u0027], \u0027r1z1-127.0.0.2\u0027)"},{"line_number":673,"context_line":"        self.assertEqual(report[\u0027max_dispersion\u0027], 16.304347826086957)"},{"line_number":674,"context_line":"        # do a sencond rebalance"},{"line_number":675,"context_line":"        rb.rebalance(seed\u003d100)"},{"line_number":676,"context_line":"        report \u003d dispersion_report(rb, verbose\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":1,"id":"df87a7cf_2639693e","line":673,"updated":"2017-12-15 18:43:38.000000000","message":"Huh. So we were pretty far under before, and over now...","commit_id":"dde2d043a07e21634f8ee1627b33ef464ab5563b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"8e8f11f6bb64d578f90df6d4686744a1c0fb32c3","unresolved":false,"context_lines":[{"line_number":676,"context_line":"        report \u003d dispersion_report(rb, verbose\u003dTrue)"},{"line_number":677,"context_line":"        self.assertEqual(rb.dispersion, 50.0)"},{"line_number":678,"context_line":"        self.assertEqual(report[\u0027worst_tier\u0027], \u0027r1z0-127.0.0.3\u0027)"},{"line_number":679,"context_line":"        self.assertEqual(report[\u0027max_dispersion\u0027], 66.66666666666667)"},{"line_number":680,"context_line":""},{"line_number":681,"context_line":"        # ... but overload can square it"},{"line_number":682,"context_line":"        rb.set_overload(rb.get_required_overload())"}],"source_content_type":"text/x-python","patch_set":1,"id":"df87a7cf_a986aa64","line":679,"updated":"2017-12-15 18:43:38.000000000","message":"...but here, things *only* got worse... because dispersion\u0027s *going* to be messed up given how lopsided the region is.\n\nHow did we get 2/3 though? That\u0027s a...weird number. we\u0027re trying for 3/5 of all part-replicas in z0, and 5/6 of *that* in the new node... that\u0027s 1/2 of all part-replicas, or 1.5 replicas, leaving .5 replica at risk. That was how we arrived at 50 before, yeah?\n\nIs it to do with the fact that (for ideal dispersion) we only really want 3/4 of a replica? So we\u0027ve got an \"extra\" 3/4 of a replica that\u0027s \"at risk\"? But then why isn\u0027t it 75? Why 2/3!?","commit_id":"dde2d043a07e21634f8ee1627b33ef464ab5563b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"c636fede3d526bbb12220238d1035b907c630c4b","unresolved":false,"context_lines":[{"line_number":676,"context_line":"        report \u003d dispersion_report(rb, verbose\u003dTrue)"},{"line_number":677,"context_line":"        self.assertEqual(rb.dispersion, 50.0)"},{"line_number":678,"context_line":"        self.assertEqual(report[\u0027worst_tier\u0027], \u0027r1z0-127.0.0.3\u0027)"},{"line_number":679,"context_line":"        self.assertEqual(report[\u0027max_dispersion\u0027], 66.66666666666667)"},{"line_number":680,"context_line":""},{"line_number":681,"context_line":"        # ... but overload can square it"},{"line_number":682,"context_line":"        rb.set_overload(rb.get_required_overload())"}],"source_content_type":"text/x-python","patch_set":1,"id":"df87a7cf_b5883cc6","line":679,"in_reply_to":"df87a7cf_a986aa64","updated":"2017-12-15 23:32:43.000000000","message":"yeah, idk, the worst tier value is funky...\n\nI normally end up dropping into pdb, doing a rb.save(\u0027/tmp/test.builder\u0027) and then going to poke at it with swift-ring-builder test.builder dispersion -v","commit_id":"dde2d043a07e21634f8ee1627b33ef464ab5563b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"cd3671bdeac53acada8bda322c83ee254d0943af","unresolved":false,"context_lines":[{"line_number":674,"context_line":"        report \u003d dispersion_report(rb, verbose\u003dTrue)"},{"line_number":675,"context_line":"        self.assertEqual(rb.dispersion, 16.666666666666668)"},{"line_number":676,"context_line":"        self.assertEqual(report[\u0027worst_tier\u0027], \u0027r1z0-127.0.0.3\u0027)"},{"line_number":677,"context_line":"        self.assertEqual(report[\u0027max_dispersion\u0027], 66.66666666666667)"},{"line_number":678,"context_line":""},{"line_number":679,"context_line":"        # ... but overload can square it"},{"line_number":680,"context_line":"        rb.set_overload(rb.get_required_overload())"}],"source_content_type":"text/x-python","patch_set":4,"id":"9f91af0f_6561023a","line":677,"updated":"2017-12-28 06:19:42.000000000","message":"OK, so, 2/3:\n\n- By weight, we want 1.5 replicas here.\n- By dispersion, we should have at most 1 replica per part here.\n- So, half of all partitions placed here are \"at risk\" (the 50% from before).\n- (Note the \"placed here\" -- in the old math, this was a distinction without much difference; all partitions have at least one replica placed here.)\n- In the new math, we\u0027re looking at *replicanths* and weight the \"at risk\" parts by how many copies got placed at a given tier. As a result, we look at *both copies* of the at risk parts for\n\n                   2 replicas * 1/2 of all partitions\n ----------------------------------------------------------------------\n 1 replica * 1/2 of all partitions + 2 replicas * 1/2 of all partitions\n\n*Not* the extra 1/2 replica past max_replicas, nor the 3/4 replica past what we\u0027d want for ideal dispersion, and basically nothing to do with the *overall* number of replicanths -- no wonder I was having trouble making sense of the number before!\n\nI think part of why I didn\u0027t like it was that the max_dispersion was so radically different from the ring\u0027s overall dispersion -- it just didn\u0027t sit well with me. If we make the adjustment in the per-tier at_risk_parts calculation this should come down to 33%; while still twice the overall dispersion, it\u0027s a decent bit closer.","commit_id":"877c2c72f27334fb128a6f5c1e306fd5d8d308b8"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"4678cf775fa841a82af3ce892742f376e2d52025","unresolved":false,"context_lines":[{"line_number":674,"context_line":"        report \u003d dispersion_report(rb, verbose\u003dTrue)"},{"line_number":675,"context_line":"        self.assertEqual(rb.dispersion, 16.666666666666668)"},{"line_number":676,"context_line":"        self.assertEqual(report[\u0027worst_tier\u0027], \u0027r1z0-127.0.0.3\u0027)"},{"line_number":677,"context_line":"        self.assertEqual(report[\u0027max_dispersion\u0027], 66.66666666666667)"},{"line_number":678,"context_line":""},{"line_number":679,"context_line":"        # ... but overload can square it"},{"line_number":680,"context_line":"        rb.set_overload(rb.get_required_overload())"}],"source_content_type":"text/x-python","patch_set":4,"id":"9f91af0f_c14799bc","line":677,"in_reply_to":"9f91af0f_6561023a","updated":"2017-12-28 19:16:59.000000000","message":"Done","commit_id":"877c2c72f27334fb128a6f5c1e306fd5d8d308b8"}]}
