)]}'
{"swift/cli/ringbuilder.py":[{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"06cf3d7e8394b2bf2476986b690f00cdcf0cb5e8","unresolved":false,"context_lines":[{"line_number":656,"context_line":"            print \u0027-\u0027 * 79"},{"line_number":657,"context_line":"            exit(EXIT_ERROR)"},{"line_number":658,"context_line":"        print \u0027Reassigned %d (%.02f%%) partitions. Balance is now %.02f.\u0027 % \\"},{"line_number":659,"context_line":"              (parts, 100.0 * parts / builder.parts, balance)"},{"line_number":660,"context_line":"        status \u003d EXIT_SUCCESS"},{"line_number":661,"context_line":"        if balance \u003e 5:"},{"line_number":662,"context_line":"            print \u0027-\u0027 * 79"}],"source_content_type":"text/x-python","patch_set":4,"id":"3a961159_ebf754f3","line":659,"updated":"2014-12-10 19:46:29.000000000","message":"Ehh, somehow forgot to remove this line (it\u0027s now in line 626). Will remove that later, but wait if there is something else to change","commit_id":"6ab4657c9b4c74ab1be1527ffffa22fb89179b0e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cab4eca97074272d5a64875d47687d39711c9176","unresolved":false,"context_lines":[{"line_number":285,"context_line":"                        get_tier_name(tier), at_risk[tier])"},{"line_number":286,"context_line":"                print \u0027To prevent this problem, reduce the weight on these \u0027 \\"},{"line_number":287,"context_line":"                      \u0027devices or raise the weight on the other devices.\u0027"},{"line_number":288,"context_line":"                status \u003d EXIT_WARNING"},{"line_number":289,"context_line":"        exit(status)"},{"line_number":290,"context_line":""},{"line_number":291,"context_line":"    def search():"}],"source_content_type":"text/x-python","patch_set":6,"id":"3a961159_40754cc9","line":288,"updated":"2014-12-12 23:17:05.000000000","message":"How about a test that hits this output?","commit_id":"5a5dfeff410e251c20fa31ea048187f51c367317"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"b91b8a88239f3bd9ccc98d1077b88a79b46e3bb9","unresolved":false,"context_lines":[{"line_number":665,"context_line":"        if not devs_changed and abs(last_balance - balance) \u003c 1 and \\"},{"line_number":666,"context_line":"                not (last_balance \u003d\u003d MAX_BALANCE and balance \u003d\u003d MAX_BALANCE):"},{"line_number":667,"context_line":"            print \u0027Cowardly refusing to save rebalance as it did not change \u0027 \\"},{"line_number":668,"context_line":"                  \u0027at least 1%.\u0027"},{"line_number":669,"context_line":"            exit(EXIT_WARNING)"},{"line_number":670,"context_line":"        try:"},{"line_number":671,"context_line":"            builder.validate()"}],"source_content_type":"text/x-python","patch_set":7,"id":"3a961159_af798a30","line":668,"updated":"2014-12-22 22:07:06.000000000","message":"I think it\u0027s confusing to display the dispersion warning for a ring that\u0027s not going to get saved... maybe we should wait and do the dispersion warning down by where we do the balance warning?","commit_id":"cc66f52b1a51a0426939c0ab0b507ba0f486da6d"}],"swift/common/ring/utils.py":[{"author":{"_account_id":2696,"name":"Darrell Bishop","email":"dbishop@nvidia.com","username":"darrellb"},"change_message_id":"6d716a48efde31fe51b01b09ef4175c1487e3a92","unresolved":false,"context_lines":[{"line_number":335,"context_line":""},{"line_number":336,"context_line":"def get_region_zone_parts(builder):"},{"line_number":337,"context_line":"        region_parts \u003d {}"},{"line_number":338,"context_line":"        zone_parts \u003d {}"},{"line_number":339,"context_line":"        for dev in builder.devs:"},{"line_number":340,"context_line":"            parts \u003d dev[\u0027parts\u0027]"},{"line_number":341,"context_line":"            region \u003d \"R\" + str(dev[\u0027region\u0027])"}],"source_content_type":"text/x-python","patch_set":2,"id":"3a961159_8b1c2d15","line":338,"updated":"2014-12-10 05:03:50.000000000","message":"This needs to go down to the host/IP level.  We had a specific issue with a rolling replacement of nodes storing account/container data on 2T disks (2000 weight/disk at 1 weight/GB ratio) with 100 GB SSDs (100 weight/disk).  By the end, plenty of partitions had all 3 replicas on one *node*.  After that node was decommissioned, you can imagine what happened.\n\nIn any case, I can\u0027t remember how many zones were active, but this problem can exhibit in a bad way at the node level.","commit_id":"ea1e49bd83b01264f2b6862478f92d910d8483eb"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"210afc12e34106bbbb452751cc2b4bbdd9654aca","unresolved":false,"context_lines":[{"line_number":350,"context_line":"                        replicas_at_tier[tier] +\u003d 1"},{"line_number":351,"context_line":"            for tier, replicas in replicas_at_tier.items():"},{"line_number":352,"context_line":"                if replicas \u003e max_replicas.get(tier) and tier not in at_risk:"},{"line_number":353,"context_line":"                    at_risk.append(tier)"},{"line_number":354,"context_line":"        at_risk.sort(key\u003dlambda tier: len(tier))"},{"line_number":355,"context_line":"        return at_risk"},{"line_number":356,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"3a961159_009a8f6d","line":353,"updated":"2014-12-11 21:45:47.000000000","message":"Maybe just use a set for at_risk? It\u0027d save you from doing your own duplicate prevention.","commit_id":"7750fca1ad03e8bb4bbda5108800fdd2fc24c0a7"},{"author":{"_account_id":2622,"name":"Samuel Merritt","email":"spam+launchpad@andcheese.org","username":"torgomatic"},"change_message_id":"210afc12e34106bbbb452751cc2b4bbdd9654aca","unresolved":false,"context_lines":[{"line_number":351,"context_line":"            for tier, replicas in replicas_at_tier.items():"},{"line_number":352,"context_line":"                if replicas \u003e max_replicas.get(tier) and tier not in at_risk:"},{"line_number":353,"context_line":"                    at_risk.append(tier)"},{"line_number":354,"context_line":"        at_risk.sort(key\u003dlambda tier: len(tier))"},{"line_number":355,"context_line":"        return at_risk"},{"line_number":356,"context_line":""},{"line_number":357,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"3a961159_40c1f752","line":354,"updated":"2014-12-11 21:45:47.000000000","message":"nit: just \"key\u003dlen\"","commit_id":"7750fca1ad03e8bb4bbda5108800fdd2fc24c0a7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cab4eca97074272d5a64875d47687d39711c9176","unresolved":false,"context_lines":[{"line_number":333,"context_line":"        return sorted_partition_count"},{"line_number":334,"context_line":""},{"line_number":335,"context_line":""},{"line_number":336,"context_line":"def get_tiers_at_risk(builder):"},{"line_number":337,"context_line":"        at_risk \u003d {}"},{"line_number":338,"context_line":"        max_replicas \u003d builder._build_max_replicas_by_tier()"},{"line_number":339,"context_line":"        # this code is essentially from swift/common/ring/builder.py"}],"source_content_type":"text/x-python","patch_set":6,"id":"3a961159_604888cc","line":336,"updated":"2014-12-12 23:17:05.000000000","message":"Isn\u0027t validate a method on the instance?  Why would this also be a method on the instance - or even part of the validation!?","commit_id":"5a5dfeff410e251c20fa31ea048187f51c367317"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cab4eca97074272d5a64875d47687d39711c9176","unresolved":false,"context_lines":[{"line_number":340,"context_line":"        tfd \u003d {}"},{"line_number":341,"context_line":"        for part in xrange(builder.parts):"},{"line_number":342,"context_line":"            replicas_at_tier \u003d {}"},{"line_number":343,"context_line":"            for dev in builder._devs_for_part(part):"},{"line_number":344,"context_line":"                if dev[\u0027id\u0027] not in tfd:"},{"line_number":345,"context_line":"                    tfd[dev[\u0027id\u0027]] \u003d tiers_for_dev(dev)"},{"line_number":346,"context_line":"                for tier in tfd[dev[\u0027id\u0027]]:"}],"source_content_type":"text/x-python","patch_set":6,"id":"3a961159_2070400a","line":343,"updated":"2014-12-12 23:17:05.000000000","message":"If you\u0027re going to to his every dev and every part, can you just iterate over replica2part2dev once?","commit_id":"5a5dfeff410e251c20fa31ea048187f51c367317"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cab4eca97074272d5a64875d47687d39711c9176","unresolved":false,"context_lines":[{"line_number":349,"context_line":"                    else:"},{"line_number":350,"context_line":"                        replicas_at_tier[tier] +\u003d 1"},{"line_number":351,"context_line":"            for tier, replicas in replicas_at_tier.items():"},{"line_number":352,"context_line":"                if replicas \u003e max_replicas.get(tier):"},{"line_number":353,"context_line":"                    if tier not in at_risk:"},{"line_number":354,"context_line":"                        at_risk[tier] \u003d 0"},{"line_number":355,"context_line":"                    at_risk[tier] +\u003d 1"}],"source_content_type":"text/x-python","patch_set":6,"id":"3a961159_e0e718aa","line":352,"updated":"2014-12-12 23:17:05.000000000","message":"this max_replica number for the tier would be great context.  Having a number of \"at risk\" parts is more informative if you understand the degree of risk.\n\nOne region that wants 2 replicas having 100 parts with 3 replicas is bad.  One server that wants 1 part having 3 replicas is a whole different level of terrible.","commit_id":"5a5dfeff410e251c20fa31ea048187f51c367317"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"cab4eca97074272d5a64875d47687d39711c9176","unresolved":false,"context_lines":[{"line_number":364,"context_line":"    if len(tier) \u003d\u003d 3:"},{"line_number":365,"context_line":"        return \"Node: %s\" % tier[2]"},{"line_number":366,"context_line":"    if len(tier) \u003d\u003d 4:"},{"line_number":367,"context_line":"        return \"Node: %s, Device %s\" % (tier[2], tier[3])"}],"source_content_type":"text/x-python","patch_set":6,"id":"3a961159_20b3e098","line":367,"updated":"2014-12-12 23:17:05.000000000","message":"I actually like the condense drive format better:\n\n  r1z2-192.168.7.8:6000/d1","commit_id":"5a5dfeff410e251c20fa31ea048187f51c367317"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3e7a4b867cf478f5c2fb2165be66b42b0514de69","unresolved":false,"context_lines":[{"line_number":341,"context_line":"    max_replicas \u003d builder._build_max_replicas_by_tier()"},{"line_number":342,"context_line":"    for part in xrange(builder.parts):"},{"line_number":343,"context_line":"        replicas_at_tier \u003d {}"},{"line_number":344,"context_line":"        for dev in builder._devs_for_part(part):"},{"line_number":345,"context_line":"            if dev[\u0027id\u0027] not in tfd:"},{"line_number":346,"context_line":"                tfd[dev[\u0027id\u0027]] \u003d tiers_for_dev(dev)"},{"line_number":347,"context_line":"            for tier in tfd[dev[\u0027id\u0027]]:"}],"source_content_type":"text/x-python","patch_set":7,"id":"3a961159_e08e0a79","line":344,"updated":"2014-12-15 19:25:09.000000000","message":"I guess this is the same as:\n\n    for part, replica2dev in enumerate(izip(*builder._replica2part2dev)):\n        for dev in iter(builder.devs[dev_id] for dev_id in replica2dev):\n\nBut I didn\u0027t really see it as noticeably faster to just iterate over the devices of each part rather than look them up for each part for some reason...","commit_id":"cc66f52b1a51a0426939c0ab0b507ba0f486da6d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3e7a4b867cf478f5c2fb2165be66b42b0514de69","unresolved":false,"context_lines":[{"line_number":353,"context_line":"            if tier not in part_distr:"},{"line_number":354,"context_line":"                part_distr[tier] \u003d {}"},{"line_number":355,"context_line":"                part_distr[tier][\u0027at_risk\u0027] \u003d False"},{"line_number":356,"context_line":"                part_distr[tier][\u0027max\u0027] \u003d int(max_replicas.get(tier))"},{"line_number":357,"context_line":"                part_distr[tier][\u0027replicas\u0027] \u003d {}"},{"line_number":358,"context_line":"                for replica in range(1, int(math.ceil(builder.replicas)) + 1):"},{"line_number":359,"context_line":"                    part_distr[tier][\u0027replicas\u0027][replica] \u003d 0"}],"source_content_type":"text/x-python","patch_set":7,"id":"3a961159_20e81216","line":356,"updated":"2014-12-15 19:25:09.000000000","message":"will max_replicas return None for some tiers?  Looks TypeError-y.","commit_id":"cc66f52b1a51a0426939c0ab0b507ba0f486da6d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3e7a4b867cf478f5c2fb2165be66b42b0514de69","unresolved":false,"context_lines":[{"line_number":356,"context_line":"                part_distr[tier][\u0027max\u0027] \u003d int(max_replicas.get(tier))"},{"line_number":357,"context_line":"                part_distr[tier][\u0027replicas\u0027] \u003d {}"},{"line_number":358,"context_line":"                for replica in range(1, int(math.ceil(builder.replicas)) + 1):"},{"line_number":359,"context_line":"                    part_distr[tier][\u0027replicas\u0027][replica] \u003d 0"},{"line_number":360,"context_line":"            part_distr[tier][\u0027replicas\u0027][replicas] +\u003d 1"},{"line_number":361,"context_line":"            if replicas \u003e max_replicas.get(tier):"},{"line_number":362,"context_line":"                part_distr[tier][\u0027at_risk\u0027] \u003d True"}],"source_content_type":"text/x-python","patch_set":7,"id":"3a961159_a0c88257","line":359,"updated":"2014-12-15 19:25:09.000000000","message":"using a list here instead of dict seemed to be faster - might have just been avoiding the math.ceil function call:\n\npart_distr[tier][\u0027replicas\u0027] \u003d [0] * (builder.replicas + 1)","commit_id":"cc66f52b1a51a0426939c0ab0b507ba0f486da6d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3e7a4b867cf478f5c2fb2165be66b42b0514de69","unresolved":false,"context_lines":[{"line_number":359,"context_line":"                    part_distr[tier][\u0027replicas\u0027][replica] \u003d 0"},{"line_number":360,"context_line":"            part_distr[tier][\u0027replicas\u0027][replicas] +\u003d 1"},{"line_number":361,"context_line":"            if replicas \u003e max_replicas.get(tier):"},{"line_number":362,"context_line":"                part_distr[tier][\u0027at_risk\u0027] \u003d True"},{"line_number":363,"context_line":""},{"line_number":364,"context_line":"    for tier in sorted(part_distr):"},{"line_number":365,"context_line":"        if not part_distr[tier][\u0027at_risk\u0027]:"}],"source_content_type":"text/x-python","patch_set":7,"id":"3a961159_80b8e6e6","line":362,"updated":"2014-12-15 19:25:09.000000000","message":"this part_distr datastructure is pretty great, maybe the util function that builds it should be extracted from the one that uses it to prepare for cli display.\n\n    {(1,): {\u0027at_risk\u0027: False, \u0027max\u0027: 3, \u0027replicas\u0027: [0, 0, 0, 65536]},\n     (1, 1): {\u0027at_risk\u0027: False, \u0027max\u0027: 3, \u0027replicas\u0027: [0, 0, 0, 65536]},\n     (1, 1, \u0027192.168.3.61:6000\u0027): {\u0027at_risk\u0027: True,\n      \u0027max\u0027: 1,\n      \u0027replicas\u0027: [0, 59422, 6110, 4]},\n     (1, 1, \u0027192.168.3.61:6000\u0027, 32): {\u0027at_risk\u0027: False,\n      \u0027max\u0027: 1,\n      \u0027replicas\u0027: [0, 2047, 0, 0]},\n    ...\n    }\n\nIn fact I wonder if the at_risk should be left out of the distribution graph?  Seems like it\u0027d be about as easy to check it as part of the post process filter than trying to keep at_risk True/False and max_replica keys as you go?","commit_id":"cc66f52b1a51a0426939c0ab0b507ba0f486da6d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3e7a4b867cf478f5c2fb2165be66b42b0514de69","unresolved":false,"context_lines":[{"line_number":362,"context_line":"                part_distr[tier][\u0027at_risk\u0027] \u003d True"},{"line_number":363,"context_line":""},{"line_number":364,"context_line":"    for tier in sorted(part_distr):"},{"line_number":365,"context_line":"        if not part_distr[tier][\u0027at_risk\u0027]:"},{"line_number":366,"context_line":"            continue"},{"line_number":367,"context_line":"        replica_count \u003d [str(c) for c in part_distr[tier][\u0027replicas\u0027].values()]"},{"line_number":368,"context_line":"        at_risk.append("}],"source_content_type":"text/x-python","patch_set":7,"id":"3a961159_202bb234","line":365,"updated":"2014-12-15 19:25:09.000000000","message":"maybe if you filter out at_risk before you sort the big list of all devices and tiers?","commit_id":"cc66f52b1a51a0426939c0ab0b507ba0f486da6d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3e7a4b867cf478f5c2fb2165be66b42b0514de69","unresolved":false,"context_lines":[{"line_number":368,"context_line":"        at_risk.append("},{"line_number":369,"context_line":"            [get_tier_name(tier), part_distr[tier][\u0027max\u0027]] + replica_count)"},{"line_number":370,"context_line":""},{"line_number":371,"context_line":"    return at_risk"},{"line_number":372,"context_line":""},{"line_number":373,"context_line":""},{"line_number":374,"context_line":"def get_tier_name(tier):"}],"source_content_type":"text/x-python","patch_set":7,"id":"3a961159_e0752afb","line":371,"updated":"2014-12-15 19:25:09.000000000","message":"this looks like:\n\n    [[\u0027r1z1-192.168.3.61:6000\u0027, 1, \u00270\u0027, \u002759422\u0027, \u00276110\u0027, \u00274\u0027],\n     [\u0027r1z1-192.168.3.62:6000\u0027, 1, \u00270\u0027, \u002765509\u0027, \u002712\u0027, \u00270\u0027]]\n\nWhich is kinda nutso?  You have to know a lot about what all those keys mean and the types are sorta surprising...\n\nI think something that looks more liked a sorted version of part_distr.items() would be close to ideal right?","commit_id":"cc66f52b1a51a0426939c0ab0b507ba0f486da6d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ccded5bb039e528fb07cf41b67c126c6dd2907c1","unresolved":false,"context_lines":[{"line_number":379,"context_line":"    if len(tier) \u003d\u003d 3:"},{"line_number":380,"context_line":"        return \"r%sz%s-%s\" % (tier[0], tier[1], tier[2])"},{"line_number":381,"context_line":"    if len(tier) \u003d\u003d 4:"},{"line_number":382,"context_line":"        return \"r%sz%s-%s/d%s\" % (tier[0], tier[1], tier[2], tier[3])"}],"source_content_type":"text/x-python","patch_set":7,"id":"3a961159_71cce76a","line":382,"updated":"2014-12-22 20:49:43.000000000","message":"hrmm.... /d\u003cid\u003e isn\u0027t at good as say /d\u003cdev[\u0027device\u0027]\u003e","commit_id":"cc66f52b1a51a0426939c0ab0b507ba0f486da6d"}]}
