@Test public void testAssignMigrations() { servers.put(new TServerInstance(HostAndPort.fromParts("127.0.0.1", 1234), "a"), new FakeTServer()); servers.put(new TServerInstance(HostAndPort.fromParts("127.0.0.2", 1234), "b"), new FakeTServer()); servers.put(new TServerInstance(HostAndPort.fromParts("127.0.0.3", 1234), "c"), new FakeTServer()); List<KeyExtent> metadataTable = new ArrayList<>(); String table = "t1"; metadataTable.add(makeExtent(table, null, null)); table = "t2"; metadataTable.add(makeExtent(table, "a", null)); metadataTable.add(makeExtent(table, null, "a")); table = "t3"; metadataTable.add(makeExtent(table, "a", null)); metadataTable.add(makeExtent(table, "b", "a")); metadataTable.add(makeExtent(table, "c", "b")); metadataTable.add(makeExtent(table, "d", "c")); metadataTable.add(makeExtent(table, "e", "d")); metadataTable.add(makeExtent(table, null, "e")); Collections.sort(metadataTable); TestDefaultLoadBalancer balancer = new TestDefaultLoadBalancer(); SortedMap<TServerInstance,TabletServerStatus> current = new TreeMap<>(); for (Entry<TServerInstance,FakeTServer> entry : servers.entrySet()) { current.put(entry.getKey(), entry.getValue().getStatus()); } assignTablets(metadataTable, servers, current, balancer); Map<String,Integer> expectedCounts = new HashMap<>(); expectedCounts.put("t1", 1); expectedCounts.put("t2", 1); expectedCounts.put("t3", 2); checkBalance(metadataTable, servers, expectedCounts); for (Entry<TServerInstance,FakeTServer> entry : servers.entrySet()) { current.put(entry.getKey(), entry.getValue().getStatus()); } ArrayList<TabletMigration> out = new ArrayList<>(); balancer.getMigrations(current, out); assertEquals(out.size(), 0); TServerInstance first = current.keySet().iterator().next(); current.remove(first); FakeTServer remove = servers.remove(first); assignTablets(remove.extents, servers, current, balancer); checkBalance(metadataTable, servers, null); }
public boolean getMigrations(Map<TServerInstance,TabletServerStatus> current, List<TabletMigration> result) { boolean moreBalancingNeeded = false; try { if (current.size() < 2) { return false; } final Map<TableId,Map<KeyExtent,TabletStats>> donerTabletStats = new HashMap<>(); int total = 0; ArrayList<ServerCounts> totals = new ArrayList<>(); for (Entry<TServerInstance,TabletServerStatus> entry : current.entrySet()) { int serverTotal = 0; if (entry.getValue() != null && entry.getValue().tableMap != null) { for (Entry<String,TableInfo> e : entry.getValue().tableMap.entrySet()) { if (tableToBalance == null || tableToBalance.canonical().equals(e.getKey())) serverTotal += e.getValue().onlineTablets; } } totals.add(new ServerCounts(serverTotal, entry.getKey(), entry.getValue())); total += serverTotal; } totals.sort(Collections.reverseOrder()); int even = total / totals.size(); int numServersOverEven = total % totals.size(); int end = totals.size() - 1; int movedAlready = 0; int tooManyIndex = 0; while (tooManyIndex < end) { ServerCounts tooMany = totals.get(tooManyIndex); int goal = even; if (tooManyIndex < numServersOverEven) { goal++; } int needToUnload = tooMany.count - goal; ServerCounts tooLittle = totals.get(end); int needToLoad = goal - tooLittle.count - movedAlready; if (needToUnload < 1 && needToLoad < 1) { break; } if (needToUnload >= needToLoad) { result.addAll(move(tooMany, tooLittle, needToLoad, donerTabletStats)); end--; movedAlready = 0; } else { result.addAll(move(tooMany, tooLittle, needToUnload, donerTabletStats)); movedAlready += needToUnload; } if (needToUnload > needToLoad) { moreBalancingNeeded = true; } else { tooManyIndex++; donerTabletStats.clear(); } } } finally { log.trace("balance ended with {} migrations", result.size()); } return moreBalancingNeeded; }
DefaultLoadBalancer extends TabletBalancer { public boolean getMigrations(Map<TServerInstance,TabletServerStatus> current, List<TabletMigration> result) { boolean moreBalancingNeeded = false; try { if (current.size() < 2) { return false; } final Map<TableId,Map<KeyExtent,TabletStats>> donerTabletStats = new HashMap<>(); int total = 0; ArrayList<ServerCounts> totals = new ArrayList<>(); for (Entry<TServerInstance,TabletServerStatus> entry : current.entrySet()) { int serverTotal = 0; if (entry.getValue() != null && entry.getValue().tableMap != null) { for (Entry<String,TableInfo> e : entry.getValue().tableMap.entrySet()) { if (tableToBalance == null || tableToBalance.canonical().equals(e.getKey())) serverTotal += e.getValue().onlineTablets; } } totals.add(new ServerCounts(serverTotal, entry.getKey(), entry.getValue())); total += serverTotal; } totals.sort(Collections.reverseOrder()); int even = total / totals.size(); int numServersOverEven = total % totals.size(); int end = totals.size() - 1; int movedAlready = 0; int tooManyIndex = 0; while (tooManyIndex < end) { ServerCounts tooMany = totals.get(tooManyIndex); int goal = even; if (tooManyIndex < numServersOverEven) { goal++; } int needToUnload = tooMany.count - goal; ServerCounts tooLittle = totals.get(end); int needToLoad = goal - tooLittle.count - movedAlready; if (needToUnload < 1 && needToLoad < 1) { break; } if (needToUnload >= needToLoad) { result.addAll(move(tooMany, tooLittle, needToLoad, donerTabletStats)); end--; movedAlready = 0; } else { result.addAll(move(tooMany, tooLittle, needToUnload, donerTabletStats)); movedAlready += needToUnload; } if (needToUnload > needToLoad) { moreBalancingNeeded = true; } else { tooManyIndex++; donerTabletStats.clear(); } } } finally { log.trace("balance ended with {} migrations", result.size()); } return moreBalancingNeeded; } }
DefaultLoadBalancer extends TabletBalancer { public boolean getMigrations(Map<TServerInstance,TabletServerStatus> current, List<TabletMigration> result) { boolean moreBalancingNeeded = false; try { if (current.size() < 2) { return false; } final Map<TableId,Map<KeyExtent,TabletStats>> donerTabletStats = new HashMap<>(); int total = 0; ArrayList<ServerCounts> totals = new ArrayList<>(); for (Entry<TServerInstance,TabletServerStatus> entry : current.entrySet()) { int serverTotal = 0; if (entry.getValue() != null && entry.getValue().tableMap != null) { for (Entry<String,TableInfo> e : entry.getValue().tableMap.entrySet()) { if (tableToBalance == null || tableToBalance.canonical().equals(e.getKey())) serverTotal += e.getValue().onlineTablets; } } totals.add(new ServerCounts(serverTotal, entry.getKey(), entry.getValue())); total += serverTotal; } totals.sort(Collections.reverseOrder()); int even = total / totals.size(); int numServersOverEven = total % totals.size(); int end = totals.size() - 1; int movedAlready = 0; int tooManyIndex = 0; while (tooManyIndex < end) { ServerCounts tooMany = totals.get(tooManyIndex); int goal = even; if (tooManyIndex < numServersOverEven) { goal++; } int needToUnload = tooMany.count - goal; ServerCounts tooLittle = totals.get(end); int needToLoad = goal - tooLittle.count - movedAlready; if (needToUnload < 1 && needToLoad < 1) { break; } if (needToUnload >= needToLoad) { result.addAll(move(tooMany, tooLittle, needToLoad, donerTabletStats)); end--; movedAlready = 0; } else { result.addAll(move(tooMany, tooLittle, needToUnload, donerTabletStats)); movedAlready += needToUnload; } if (needToUnload > needToLoad) { moreBalancingNeeded = true; } else { tooManyIndex++; donerTabletStats.clear(); } } } finally { log.trace("balance ended with {} migrations", result.size()); } return moreBalancingNeeded; } DefaultLoadBalancer();  DefaultLoadBalancer(TableId table); }
DefaultLoadBalancer extends TabletBalancer { public boolean getMigrations(Map<TServerInstance,TabletServerStatus> current, List<TabletMigration> result) { boolean moreBalancingNeeded = false; try { if (current.size() < 2) { return false; } final Map<TableId,Map<KeyExtent,TabletStats>> donerTabletStats = new HashMap<>(); int total = 0; ArrayList<ServerCounts> totals = new ArrayList<>(); for (Entry<TServerInstance,TabletServerStatus> entry : current.entrySet()) { int serverTotal = 0; if (entry.getValue() != null && entry.getValue().tableMap != null) { for (Entry<String,TableInfo> e : entry.getValue().tableMap.entrySet()) { if (tableToBalance == null || tableToBalance.canonical().equals(e.getKey())) serverTotal += e.getValue().onlineTablets; } } totals.add(new ServerCounts(serverTotal, entry.getKey(), entry.getValue())); total += serverTotal; } totals.sort(Collections.reverseOrder()); int even = total / totals.size(); int numServersOverEven = total % totals.size(); int end = totals.size() - 1; int movedAlready = 0; int tooManyIndex = 0; while (tooManyIndex < end) { ServerCounts tooMany = totals.get(tooManyIndex); int goal = even; if (tooManyIndex < numServersOverEven) { goal++; } int needToUnload = tooMany.count - goal; ServerCounts tooLittle = totals.get(end); int needToLoad = goal - tooLittle.count - movedAlready; if (needToUnload < 1 && needToLoad < 1) { break; } if (needToUnload >= needToLoad) { result.addAll(move(tooMany, tooLittle, needToLoad, donerTabletStats)); end--; movedAlready = 0; } else { result.addAll(move(tooMany, tooLittle, needToUnload, donerTabletStats)); movedAlready += needToUnload; } if (needToUnload > needToLoad) { moreBalancingNeeded = true; } else { tooManyIndex++; donerTabletStats.clear(); } } } finally { log.trace("balance ended with {} migrations", result.size()); } return moreBalancingNeeded; } DefaultLoadBalancer();  DefaultLoadBalancer(TableId table); TServerInstance getAssignment(SortedMap<TServerInstance,TabletServerStatus> locations,
      TServerInstance last); boolean getMigrations(Map<TServerInstance,TabletServerStatus> current,
      List<TabletMigration> result); @Override void getAssignments(SortedMap<TServerInstance,TabletServerStatus> current,
      Map<KeyExtent,TServerInstance> unassigned, Map<KeyExtent,TServerInstance> assignments); @Override long balance(SortedMap<TServerInstance,TabletServerStatus> current,
      Set<KeyExtent> migrations, List<TabletMigration> migrationsOut); }
DefaultLoadBalancer extends TabletBalancer { public boolean getMigrations(Map<TServerInstance,TabletServerStatus> current, List<TabletMigration> result) { boolean moreBalancingNeeded = false; try { if (current.size() < 2) { return false; } final Map<TableId,Map<KeyExtent,TabletStats>> donerTabletStats = new HashMap<>(); int total = 0; ArrayList<ServerCounts> totals = new ArrayList<>(); for (Entry<TServerInstance,TabletServerStatus> entry : current.entrySet()) { int serverTotal = 0; if (entry.getValue() != null && entry.getValue().tableMap != null) { for (Entry<String,TableInfo> e : entry.getValue().tableMap.entrySet()) { if (tableToBalance == null || tableToBalance.canonical().equals(e.getKey())) serverTotal += e.getValue().onlineTablets; } } totals.add(new ServerCounts(serverTotal, entry.getKey(), entry.getValue())); total += serverTotal; } totals.sort(Collections.reverseOrder()); int even = total / totals.size(); int numServersOverEven = total % totals.size(); int end = totals.size() - 1; int movedAlready = 0; int tooManyIndex = 0; while (tooManyIndex < end) { ServerCounts tooMany = totals.get(tooManyIndex); int goal = even; if (tooManyIndex < numServersOverEven) { goal++; } int needToUnload = tooMany.count - goal; ServerCounts tooLittle = totals.get(end); int needToLoad = goal - tooLittle.count - movedAlready; if (needToUnload < 1 && needToLoad < 1) { break; } if (needToUnload >= needToLoad) { result.addAll(move(tooMany, tooLittle, needToLoad, donerTabletStats)); end--; movedAlready = 0; } else { result.addAll(move(tooMany, tooLittle, needToUnload, donerTabletStats)); movedAlready += needToUnload; } if (needToUnload > needToLoad) { moreBalancingNeeded = true; } else { tooManyIndex++; donerTabletStats.clear(); } } } finally { log.trace("balance ended with {} migrations", result.size()); } return moreBalancingNeeded; } DefaultLoadBalancer();  DefaultLoadBalancer(TableId table); TServerInstance getAssignment(SortedMap<TServerInstance,TabletServerStatus> locations,
      TServerInstance last); boolean getMigrations(Map<TServerInstance,TabletServerStatus> current,
      List<TabletMigration> result); @Override void getAssignments(SortedMap<TServerInstance,TabletServerStatus> current,
      Map<KeyExtent,TServerInstance> unassigned, Map<KeyExtent,TServerInstance> assignments); @Override long balance(SortedMap<TServerInstance,TabletServerStatus> current,
      Set<KeyExtent> migrations, List<TabletMigration> migrationsOut);  }