diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancerTask.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancerTask.java index 0bfedd43960f..96b2cc8dd672 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancerTask.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancerTask.java @@ -44,6 +44,7 @@ import java.io.IOException; import java.time.Duration; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -52,6 +53,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -472,7 +474,7 @@ private IterationResult doIteration() { findTargetStrategy.reInitialize(potentialTargets, config, upperLimit); findSourceStrategy.reInitialize(getPotentialSources(), config, lowerLimit); - moveSelectionToFutureMap = new HashMap<>(underUtilizedNodes.size() + overUtilizedNodes.size()); + moveSelectionToFutureMap = new ConcurrentHashMap<>(); boolean isMoveGeneratedInThisIteration = false; iterationResult = IterationResult.ITERATION_COMPLETED; boolean canAdaptWhenNearingLimits = true; @@ -598,21 +600,25 @@ private void checkIterationResults(boolean isMoveGeneratedInThisIteration) { */ private void checkIterationMoveResults() { this.countDatanodesInvolvedPerIteration = 0; - CompletableFuture allFuturesResult = CompletableFuture.allOf( - moveSelectionToFutureMap.values() - .toArray(new CompletableFuture[moveSelectionToFutureMap.size()])); - try { - allFuturesResult.get(config.getMoveTimeout().toMillis(), - TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - LOG.warn("Container balancer is interrupted"); - Thread.currentThread().interrupt(); - } catch (TimeoutException e) { - long timeoutCounts = cancelMovesThatExceedTimeoutDuration(); - LOG.warn("{} Container moves are canceled.", timeoutCounts); - metrics.incrementNumContainerMovesTimeoutInLatestIteration(timeoutCounts); - } catch (ExecutionException e) { - LOG.error("Got exception while checkIterationMoveResults", e); + Collection> futures = + moveSelectionToFutureMap.values(); + if (!futures.isEmpty()) { + CompletableFuture allFuturesResult = CompletableFuture.allOf( + futures.toArray(new CompletableFuture[futures.size()])); + try { + allFuturesResult.get(config.getMoveTimeout().toMillis(), + TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + LOG.warn("Container balancer is interrupted"); + Thread.currentThread().interrupt(); + } catch (TimeoutException e) { + long timeoutCounts = cancelMovesThatExceedTimeoutDuration(); + LOG.warn("{} Container moves are canceled.", timeoutCounts); + metrics.incrementNumContainerMovesTimeoutInLatestIteration( + timeoutCounts); + } catch (ExecutionException e) { + LOG.error("Got exception while checkIterationMoveResults", e); + } } countDatanodesInvolvedPerIteration = @@ -828,6 +834,7 @@ private boolean moveContainer(DatanodeDetails source, future = future.whenComplete((result, ex) -> { metrics.incrementCurrentIterationContainerMoveMetric(result, 1); + moveSelectionToFutureMap.remove(moveSelection); if (ex != null) { LOG.info("Container move for container {} from source {} to " + "target {} failed with exceptions.", @@ -883,7 +890,6 @@ private boolean moveContainer(DatanodeDetails source, return false; } else { MoveManager.MoveResult result = future.join(); - moveSelectionToFutureMap.put(moveSelection, future); if (result == MoveManager.MoveResult.REPLICATION_FAIL_NOT_EXIST_IN_SOURCE || result == MoveManager.MoveResult.REPLICATION_FAIL_EXIST_IN_TARGET || result == MoveManager.MoveResult.REPLICATION_FAIL_CONTAINER_NOT_CLOSED || diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerMoveSelection.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerMoveSelection.java index 1a8cbee09d0a..118fa78e3276 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerMoveSelection.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerMoveSelection.java @@ -20,6 +20,8 @@ import org.apache.hadoop.hdds.protocol.DatanodeDetails; import org.apache.hadoop.hdds.scm.container.ContainerID; +import java.util.Objects; + /** * This class represents a target datanode and the container to be moved from * a source to that target. @@ -52,4 +54,24 @@ public void setContainerID( ContainerID containerID) { this.containerID = containerID; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ContainerMoveSelection that = (ContainerMoveSelection) o; + if (targetNode != that.targetNode) { + return false; + } + return containerID == that.containerID; + } + + @Override + public int hashCode() { + return Objects.hash(targetNode, containerID); + } }