BalancingNodePlacementStrategy implements NodePlacementStrategy { @Override public List<Entity> entitiesToRemove(Multimap<Location, Entity> currentMembers, int numToRemove) { if (currentMembers.isEmpty()) { throw new IllegalArgumentException("No members supplied, when requesting removal of "+numToRemove+" nodes"); } if (currentMembers.size() < numToRemove) { LOG.warn("Request to remove "+numToRemove+" when only "+currentMembers.size()+" members (continuing): "+currentMembers); numToRemove = currentMembers.size(); } Map<Location, Integer> numToRemovePerLoc = Maps.newLinkedHashMap(); Map<Location, Integer> locSizes = toMutableLocationSizes(currentMembers, ImmutableList.<Location>of()); for (int i = 0; i < numToRemove; i++) { Location mostPopulatedLoc = null; int mostPopulatedLocSize = 0; for (Location loc : locSizes.keySet()) { int locSize = locSizes.get(loc); if (locSize > 0 && (mostPopulatedLoc == null || locSize > mostPopulatedLocSize)) { mostPopulatedLoc = loc; mostPopulatedLocSize = locSize; } } assert mostPopulatedLoc != null : "leastPopulatedLoc=null; currentMembers="+currentMembers; numToRemovePerLoc.put(mostPopulatedLoc, ((numToRemovePerLoc.get(mostPopulatedLoc) == null) ? 0 : numToRemovePerLoc.get(mostPopulatedLoc))+ 1); locSizes.put(mostPopulatedLoc, locSizes.get(mostPopulatedLoc)-1); } List<Entity> result = Lists.newArrayList(); for (Map.Entry<Location, Integer> entry : numToRemovePerLoc.entrySet()) { result.addAll(pickNewest(currentMembers.get(entry.getKey()), entry.getValue())); } return result; }  @Override List<Location> locationsForAdditions(Multimap<Location, Entity> currentMembers, Collection<? extends Location> locs, int numToAdd); @Override List<Entity> entitiesToRemove(Multimap<Location, Entity> currentMembers, int numToRemove); @Override String toString();  }
@Test public void testRemovesNewest() throws Exception { LinkedHashMultimap<Location, Entity> currentMembers = LinkedHashMultimap.<Location,Entity>create(); currentMembers.put(loc1, entity1); currentMembers.put(loc1, entity2); List<Entity> result = placementStrategy.entitiesToRemove(currentMembers, 1); Asserts.assertEqualsIgnoringOrder(result, ImmutableList.of(entity2)); }
@Test public void testRemovesFromBiggestLocation() throws Exception { LinkedHashMultimap<Location, Entity> currentMembers = LinkedHashMultimap.<Location,Entity>create(); currentMembers.put(loc1, entity1); currentMembers.put(loc1, entity2); currentMembers.put(loc2, entity3); List<Entity> result = placementStrategy.entitiesToRemove(currentMembers, 1); Asserts.assertEqualsIgnoringOrder(result, ImmutableList.of(entity2)); currentMembers = LinkedHashMultimap.<Location,Entity>create(); currentMembers.put(loc1, entity3); currentMembers.put(loc2, entity1); currentMembers.put(loc2, entity2); result = placementStrategy.entitiesToRemove(currentMembers, 1); Asserts.assertEqualsIgnoringOrder(result, ImmutableList.of(entity2)); }