protected void updateLoad( final Map<ServerName, ServerAndLoad> map, final ServerName sn, final int diff) { ServerAndLoad sal = map.get(sn); if (sal == null) sal = new ServerAndLoad(sn, 0); sal = new ServerAndLoad(sn, sal.getLoad() + diff); map.put(sn, sal); }
/** * This assumes the RegionPlan HSI instances are the same ones in the map, so actually no need to * even pass in the map, but I think it's clearer. * * @param list * @param plans * @return */ protected List<ServerAndLoad> reconcile( List<ServerAndLoad> list, List<RegionPlan> plans, Map<ServerName, List<HRegionInfo>> servers) { List<ServerAndLoad> result = new ArrayList<ServerAndLoad>(list.size()); Map<ServerName, ServerAndLoad> map = new HashMap<ServerName, ServerAndLoad>(list.size()); for (ServerAndLoad sl : list) { map.put(sl.getServerName(), sl); } if (plans != null) { for (RegionPlan plan : plans) { ServerName source = plan.getSource(); updateLoad(map, source, -1); ServerName destination = plan.getDestination(); updateLoad(map, destination, +1); servers.get(source).remove(plan.getRegionInfo()); servers.get(destination).add(plan.getRegionInfo()); } } result.clear(); result.addAll(map.values()); return result; }
/** Invariant is that all servers have between acceptable range number of regions. */ public boolean assertClusterOverallAsBalanced(List<ServerAndLoad> servers, int tablenum) { int numServers = servers.size(); int numRegions = 0; int maxRegions = 0; int minRegions = Integer.MAX_VALUE; for (ServerAndLoad server : servers) { int nr = server.getLoad(); if (nr > maxRegions) { maxRegions = nr; } if (nr < minRegions) { minRegions = nr; } numRegions += nr; } if (maxRegions - minRegions < 2) { // less than 2 between max and min, can't balance return true; } int min = numRegions / numServers; int max = numRegions % numServers == 0 ? min : min + 1; for (ServerAndLoad server : servers) { if (server.getLoad() < 0 || server.getLoad() > max + tablenum / 2 + 1 || server.getLoad() < min - tablenum / 2 - 1) return false; } return true; }
/** Invariant is that all servers have between floor(avg) and ceiling(avg) number of regions. */ public void assertClusterAsBalanced(List<ServerAndLoad> servers) { int numServers = servers.size(); int numRegions = 0; int maxRegions = 0; int minRegions = Integer.MAX_VALUE; for (ServerAndLoad server : servers) { int nr = server.getLoad(); if (nr > maxRegions) { maxRegions = nr; } if (nr < minRegions) { minRegions = nr; } numRegions += nr; } if (maxRegions - minRegions < 2) { // less than 2 between max and min, can't balance return; } int min = numRegions / numServers; int max = numRegions % numServers == 0 ? min : min + 1; for (ServerAndLoad server : servers) { assertTrue(server.getLoad() >= 0); assertTrue(server.getLoad() <= max); assertTrue(server.getLoad() >= min); } }
protected TreeMap<ServerName, List<HRegionInfo>> mockUniformClusterServers(int[] mockCluster) { int numServers = mockCluster.length; TreeMap<ServerName, List<HRegionInfo>> servers = new TreeMap<ServerName, List<HRegionInfo>>(); for (int i = 0; i < numServers; i++) { int numRegions = mockCluster[i]; ServerAndLoad sal = randomServer(0); List<HRegionInfo> regions = uniformRegions(numRegions); servers.put(sal.getServerName(), regions); } return servers; }
protected String printStats(List<ServerAndLoad> servers) { int numServers = servers.size(); int totalRegions = 0; for (ServerAndLoad server : servers) { totalRegions += server.getLoad(); } float average = (float) totalRegions / numServers; int max = (int) Math.ceil(average); int min = (int) Math.floor(average); return "[srvr=" + numServers + " rgns=" + totalRegions + " avg=" + average + " max=" + max + " min=" + min + "]"; }