This is an automated email from the ASF dual-hosted git repository.

adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 95666ebee7 HDDS-10160. Cache sort results in 
ContainerBalancerSelectionCriteria (#6050)
95666ebee7 is described below

commit 95666ebee7c9944ae03f9c528b9aa04d43c29bb0
Author: Symious <[email protected]>
AuthorDate: Tue Jan 30 17:05:27 2024 +0800

    HDDS-10160. Cache sort results in ContainerBalancerSelectionCriteria (#6050)
---
 .../balancer/AbstractFindTargetGreedy.java         | 38 +++++-----
 .../ContainerBalancerSelectionCriteria.java        | 84 +++++++++++++---------
 .../container/balancer/ContainerBalancerTask.java  | 28 +++++---
 .../scm/container/balancer/FindTargetStrategy.java |  5 +-
 .../hadoop/hdds/scm/container/MockNodeManager.java |  2 +-
 5 files changed, 93 insertions(+), 64 deletions(-)

diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/AbstractFindTargetGreedy.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/AbstractFindTargetGreedy.java
index eb422f13b1..5416a9ff1c 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/AbstractFindTargetGreedy.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/AbstractFindTargetGreedy.java
@@ -96,7 +96,7 @@ public abstract class AbstractFindTargetGreedy implements 
FindTargetStrategy {
    * Find a {@link ContainerMoveSelection} consisting of a target and
    * container to move for a source datanode. Favours more under-utilized 
nodes.
    * @param source Datanode to find a target for
-   * @param candidateContainers Set of candidate containers satisfying
+   * @param container candidate container satisfying
    *                            selection criteria
    *                            {@link ContainerBalancerSelectionCriteria}
    * (DatanodeDetails, Long) method returns true if the size specified in the
@@ -105,29 +105,27 @@ public abstract class AbstractFindTargetGreedy implements 
FindTargetStrategy {
    */
   @Override
   public ContainerMoveSelection findTargetForContainerMove(
-      DatanodeDetails source, Set<ContainerID> candidateContainers) {
+      DatanodeDetails source, ContainerID container) {
     sortTargetForSource(source);
     for (DatanodeUsageInfo targetInfo : potentialTargets) {
       DatanodeDetails target = targetInfo.getDatanodeDetails();
-      for (ContainerID container : candidateContainers) {
-        Set<ContainerReplica> replicas;
-        ContainerInfo containerInfo;
-        try {
-          replicas = containerManager.getContainerReplicas(container);
-          containerInfo = containerManager.getContainer(container);
-        } catch (ContainerNotFoundException e) {
-          logger.warn("Could not get Container {} from Container Manager for " 
+
-              "obtaining replicas in Container Balancer.", container, e);
-          continue;
-        }
+      Set<ContainerReplica> replicas;
+      ContainerInfo containerInfo;
+      try {
+        replicas = containerManager.getContainerReplicas(container);
+        containerInfo = containerManager.getContainer(container);
+      } catch (ContainerNotFoundException e) {
+        logger.warn("Could not get Container {} from Container Manager for " +
+            "obtaining replicas in Container Balancer.", container, e);
+        return null;
+      }
 
-        if (replicas.stream().noneMatch(
-            replica -> replica.getDatanodeDetails().equals(target)) &&
-            containerMoveSatisfiesPlacementPolicy(container, replicas, source,
-            target) &&
-            canSizeEnterTarget(target, containerInfo.getUsedBytes())) {
-          return new ContainerMoveSelection(target, container);
-        }
+      if (replicas.stream().noneMatch(
+          replica -> replica.getDatanodeDetails().equals(target)) &&
+          containerMoveSatisfiesPlacementPolicy(container, replicas, source,
+          target) &&
+          canSizeEnterTarget(target, containerInfo.getUsedBytes())) {
+        return new ContainerMoveSelection(target, container);
       }
     }
     logger.info("Container Balancer could not find a target for " +
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancerSelectionCriteria.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancerSelectionCriteria.java
index 8171320a54..d9102a8832 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancerSelectionCriteria.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/ContainerBalancerSelectionCriteria.java
@@ -31,8 +31,11 @@ import 
org.apache.hadoop.hdds.scm.node.states.NodeNotFoundException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.NavigableSet;
 import java.util.Set;
 import java.util.TreeSet;
@@ -52,6 +55,7 @@ public class ContainerBalancerSelectionCriteria {
   private Set<ContainerID> selectedContainers;
   private Set<ContainerID> excludeContainers;
   private FindSourceStrategy findSourceStrategy;
+  private Map<DatanodeDetails, NavigableSet<ContainerID>> setMap;
 
   public ContainerBalancerSelectionCriteria(
       ContainerBalancerConfiguration balancerConfiguration,
@@ -66,6 +70,7 @@ public class ContainerBalancerSelectionCriteria {
     selectedContainers = new HashSet<>();
     excludeContainers = balancerConfiguration.getExcludeContainers();
     this.findSourceStrategy = findSourceStrategy;
+    this.setMap = new HashMap<>();
   }
 
   /**
@@ -79,38 +84,20 @@ public class ContainerBalancerSelectionCriteria {
   }
 
   /**
-   * Gets containers that are suitable for moving based on the following
-   * required criteria:
-   * 1. Container must not be undergoing replication.
-   * 2. Container must not already be selected for balancing.
-   * 3. Container size should be closer to 5GB.
-   * 4. Container must not be in the configured exclude containers list.
-   * 5. Container should be closed.
-   * 6. If the {@link LegacyReplicationManager} is enabled, then the container 
should not be an EC container.
-   * @param node DatanodeDetails for which to find candidate containers.
-   * @return NavigableSet of candidate containers that satisfy the criteria.
+   * Get ContainerID Set for the Datanode, it will be returned as NavigableSet
+   * Since sorting will be time-consuming, the Set will be cached.
+   *
+   * @param node source datanode
+   * @return cached Navigable ContainerID Set
    */
-  public NavigableSet<ContainerID> getCandidateContainers(
-      DatanodeDetails node, long sizeMovedAlready) {
-    NavigableSet<ContainerID> containerIDSet =
-        new TreeSet<>(orderContainersByUsedBytes().reversed());
-    try {
-      containerIDSet.addAll(nodeManager.getContainers(node));
-    } catch (NodeNotFoundException e) {
-      LOG.warn("Could not find Datanode {} while selecting candidate " +
-          "containers for Container Balancer.", node.toString(), e);
-      return containerIDSet;
+  public Set<ContainerID> getContainerIDSet(DatanodeDetails node) {
+    // Check if the node is registered at the beginning
+    if (!nodeManager.isNodeRegistered(node)) {
+      return Collections.emptySet();
     }
-    if (excludeContainers != null) {
-      containerIDSet.removeAll(excludeContainers);
-    }
-    if (selectedContainers != null) {
-      containerIDSet.removeAll(selectedContainers);
-    }
-
-    containerIDSet.removeIf(
-        containerID -> shouldBeExcluded(containerID, node, sizeMovedAlready));
-    return containerIDSet;
+    Set<ContainerID> containers = setMap.computeIfAbsent(node,
+        this::getCandidateContainers);
+    return containers != null ? containers : Collections.emptySet();
   }
 
   /**
@@ -165,7 +152,19 @@ public class ContainerBalancerSelectionCriteria {
         && replicationManager.getConfig().isLegacyEnabled();
   }
 
-  private boolean shouldBeExcluded(ContainerID containerID,
+  /**
+   * Gets containers that are suitable for moving based on the following
+   * required criteria:
+   * 1. Container must not be undergoing replication.
+   * 2. Container must not already be selected for balancing.
+   * 3. Container size should be closer to 5GB.
+   * 4. Container must not be in the configured exclude containers list.
+   * 5. Container should be closed.
+   * 6. If the {@link LegacyReplicationManager} is enabled, then the container 
should not be an EC container.
+   * @param node DatanodeDetails for which to find candidate containers.
+   * @return true if the container should be excluded, else false
+   */
+  public boolean shouldBeExcluded(ContainerID containerID,
       DatanodeDetails node, long sizeMovedAlready) {
     ContainerInfo container;
     try {
@@ -175,7 +174,8 @@ public class ContainerBalancerSelectionCriteria {
           "candidate container. Excluding it.", containerID);
       return true;
     }
-    return !isContainerClosed(container, node) || 
isECContainerAndLegacyRMEnabled(container) ||
+    return excludeContainers.contains(containerID) || 
selectedContainers.contains(containerID) ||
+        !isContainerClosed(container, node) || 
isECContainerAndLegacyRMEnabled(container) ||
         isContainerReplicatingOrDeleting(containerID) ||
         !findSourceStrategy.canSizeLeaveSource(node, container.getUsedBytes())
         || breaksMaxSizeToMoveLimit(container.containerID(),
@@ -242,4 +242,24 @@ public class ContainerBalancerSelectionCriteria {
     this.selectedContainers = selectedContainers;
   }
 
+
+  private NavigableSet<ContainerID> getCandidateContainers(DatanodeDetails 
node) {
+    NavigableSet<ContainerID> newSet =
+        new TreeSet<>(orderContainersByUsedBytes().reversed());
+    try {
+      Set<ContainerID> idSet = nodeManager.getContainers(node);
+      if (excludeContainers != null) {
+        idSet.removeAll(excludeContainers);
+      }
+      if (selectedContainers != null) {
+        idSet.removeAll(selectedContainers);
+      }
+      newSet.addAll(idSet);
+      return newSet;
+    } catch (NodeNotFoundException e) {
+      LOG.warn("Could not find Datanode {} while selecting candidate " +
+              "containers for Container Balancer.", node, e);
+      return null;
+    }
+  }
 }
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 abbc50ac86..94e8cfd04a 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
@@ -50,7 +50,6 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.NavigableSet;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
@@ -692,11 +691,10 @@ public class ContainerBalancerTask implements Runnable {
    * @return ContainerMoveSelection containing the selected target and 
container
    */
   private ContainerMoveSelection matchSourceWithTarget(DatanodeDetails source) 
{
-    NavigableSet<ContainerID> candidateContainers =
-        selectionCriteria.getCandidateContainers(source,
-            sizeScheduledForMoveInLatestIteration);
+    Set<ContainerID> sourceContainerIDSet =
+        selectionCriteria.getContainerIDSet(source);
 
-    if (candidateContainers.isEmpty()) {
+    if (sourceContainerIDSet.isEmpty()) {
       if (LOG.isDebugEnabled()) {
         LOG.debug("ContainerBalancer could not find any candidate containers " 
+
             "for datanode {}", source.getUuidString());
@@ -708,9 +706,23 @@ public class ContainerBalancerTask implements Runnable {
       LOG.debug("ContainerBalancer is finding suitable target for source " +
           "datanode {}", source.getUuidString());
     }
-    ContainerMoveSelection moveSelection =
-        findTargetStrategy.findTargetForContainerMove(
-            source, candidateContainers);
+
+    ContainerMoveSelection moveSelection = null;
+    Set<ContainerID> toRemoveContainerIds = new HashSet<>();
+    for (ContainerID containerId: sourceContainerIDSet) {
+      if (selectionCriteria.shouldBeExcluded(containerId, source,
+          sizeScheduledForMoveInLatestIteration)) {
+        toRemoveContainerIds.add(containerId);
+        continue;
+      }
+      moveSelection = findTargetStrategy.findTargetForContainerMove(source,
+          containerId);
+      if (moveSelection != null) {
+        break;
+      }
+    }
+    // Update cached containerIDSet in setMap
+    sourceContainerIDSet.removeAll(toRemoveContainerIds);
 
     if (moveSelection == null) {
       if (LOG.isDebugEnabled()) {
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/FindTargetStrategy.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/FindTargetStrategy.java
index a951ca1918..a9f2ee00a2 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/FindTargetStrategy.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/balancer/FindTargetStrategy.java
@@ -25,7 +25,6 @@ import org.apache.hadoop.hdds.scm.node.DatanodeUsageInfo;
 import jakarta.annotation.Nonnull;
 import java.util.Collection;
 import java.util.List;
-import java.util.Set;
 
 /**
  * This interface can be used to implement strategies to find a target for a
@@ -40,7 +39,7 @@ public interface FindTargetStrategy {
    * enter a potential target.
    *
    * @param source Datanode to find a target for
-   * @param candidateContainers Set of candidate containers satisfying
+   * @param candidateContainer candidate containers satisfying
    *                            selection criteria
    *                            {@link ContainerBalancerSelectionCriteria}
    * (DatanodeDetails, Long) method returns true if the size specified in the
@@ -49,7 +48,7 @@ public interface FindTargetStrategy {
    * selected container
    */
   ContainerMoveSelection findTargetForContainerMove(
-      DatanodeDetails source, Set<ContainerID> candidateContainers);
+      DatanodeDetails source, ContainerID candidateContainer);
 
   /**
    * increase the Entering size of a candidate target data node.
diff --git 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/MockNodeManager.java
 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/MockNodeManager.java
index 794dedceef..480f82976f 100644
--- 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/MockNodeManager.java
+++ 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/MockNodeManager.java
@@ -786,7 +786,7 @@ public class MockNodeManager implements NodeManager {
   @Override
   public Boolean isNodeRegistered(
       DatanodeDetails datanodeDetails) {
-    return false;
+    return healthyNodes.contains(datanodeDetails);
   }
 
   @Override


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to