Gargi-jais11 commented on code in PR #11322:
URL: https://github.com/apache/ozone/pull/11322#discussion_r4205335867


##########
hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/DiskBalancerVolumeCalculation.java:
##########


Review Comment:
   `getIdealUsage` is not considering Storage Type. It should be per Storage 
type evaluated.



##########
hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/DiskBalancerService.java:
##########
@@ -717,26 +724,57 @@ private boolean tryCleanupOnePendingDeletionContainer() {
 
   public DiskBalancerInfo getDiskBalancerInfo() {
     final List<VolumeFixedUsage> volumeUsages = getVolumeUsages(volumeSet, 
deltaSizes);
-
-    // Calculate volumeDataDensity
-    final double volumeDataDensity = calculateVolumeDataDensity(volumeUsages);
-
-    long bytesToMove = 0;
-    if (this.operationalState == DiskBalancerRunningStatus.RUNNING) {
-      // this calculates live changes in bytesToMove
-      // calculate bytes to move if the balancer is in a running state, else 0.
-      bytesToMove = calculateBytesToMove(volumeUsages);
-    }
+    final List<StorageTypeDiskBalancerInfoProto> storageTypeInfo =
+        buildStorageTypeInfo(volumeUsages, threshold,
+            this.operationalState == DiskBalancerRunningStatus.RUNNING);
+    final double volumeDataDensity = storageTypeInfo.stream()
+        
.mapToDouble(StorageTypeDiskBalancerInfoProto::getCurrentVolumeDensitySum)
+        .sum();
+    final long bytesToMove = storageTypeInfo.stream()
+        .mapToLong(StorageTypeDiskBalancerInfoProto::getBytesToMove)
+        .sum();
 
     DiskBalancerInfo info = new DiskBalancerInfo(operationalState, threshold, 
bandwidthInMB,
         parallelThread, stopAfterDiskEven, version, 
formatContainerStates(movableContainerStates),
         metrics.getSuccessCount(),
         metrics.getFailureCount(), bytesToMove, metrics.getSuccessBytes(), 
volumeDataDensity);
     info.setIdealUsage(getIdealUsage(volumeUsages));
     info.setVolumeInfo(buildVolumeReportProto(volumeUsages));
+    info.setStorageTypeInfo(storageTypeInfo);
     return info;
   }
 
+  @VisibleForTesting

Review Comment:
   `@VisibleFprTesting` is no more supported. Refernce: 
https://issues.apache.org/jira/browse/HDDS-12725



##########
hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/policy/DefaultContainerChoosingPolicy.java:
##########
@@ -91,62 +99,123 @@ public ContainerCandidate 
chooseVolumesAndContainer(OzoneContainer ozoneContaine
         return null;
       }
 
-      // Calculate ideal usage and threshold range (once)
-      final double idealUsage = getIdealUsage(volumeUsages);
-      final double actualThreshold = thresholdPercentage / 100.0;
-      final double lowerThreshold = idealUsage - actualThreshold;
-      final double upperThreshold = idealUsage + actualThreshold;
-
-      if (LOG.isDebugEnabled()) {
-        logVolumeBalancingState(volumeUsages, idealUsage, thresholdPercentage,
-            lowerThreshold, upperThreshold, deltaMap);
+      // Balance each storage type independently so a container never crosses 
types. Try the type
+      // with the largest threshold violation first. StorageType order is only 
a deterministic
+      // tie-breaker.
+      final Map<StorageType, List<VolumeFixedUsage>> usagesByStorageType =
+          getUsableVolumesByStorageType(volumeUsages);
+      final List<Map.Entry<StorageType, List<VolumeFixedUsage>>> 
storageTypeGroups =
+          usagesByStorageType.entrySet().stream()
+              .filter(entry -> hasMultipleUsableVolumes(entry.getKey(), 
entry.getValue()))
+              .sorted(Comparator
+                  .<Map.Entry<StorageType, 
List<VolumeFixedUsage>>>comparingDouble(
+                      entry -> getThresholdViolation(entry.getValue(), 
thresholdPercentage))
+                  .reversed()
+                  .thenComparingInt(entry -> entry.getKey().ordinal()))
+              .collect(Collectors.toList());
+      for (Map.Entry<StorageType, List<VolumeFixedUsage>> entry : 
storageTypeGroups) {
+        final StorageType storageType = entry.getKey();
+        final List<VolumeFixedUsage> sameTypeUsages = entry.getValue();
+        final ContainerCandidate candidate = 
chooseWithinStorageType(ozoneContainer, sameTypeUsages,
+            deltaMap, inProgressContainerIDs, thresholdPercentage, 
movableContainerStates, storageType);
+        if (candidate != null) {
+          return candidate;
+        }
       }
+      LOG.debug("Failed to find appropriate destination volume and container 
in any storage type.");
+      return null;
+    } finally {
+      lock.unlock();
+    }
+  }
 
-      // Get highest and lowest utilization volumes
-      final VolumeFixedUsage highestUsage = 
volumeUsages.get(volumeUsages.size() - 1);
-      final VolumeFixedUsage lowestUsage = volumeUsages.get(0);
+  private static boolean hasMultipleUsableVolumes(StorageType storageType,
+      List<VolumeFixedUsage> volumeUsages) {
+    if (volumeUsages.size() >= 2) {
+      return true;
+    }
+    LOG.debug("Skipping storage type {} for disk balancing: only {} usable 
volume(s)",
+        storageType, volumeUsages.size());
+    return false;
+  }
 
-      // Only return null if highest is below upper threshold AND lowest is 
above lower threshold
-      if (highestUsage.getUtilization() < upperThreshold &&
-          lowestUsage.getUtilization() > lowerThreshold) {
-        return null;
-      }
+  private static double getThresholdViolation(List<VolumeFixedUsage> 
volumeUsages,

Review Comment:
   Many new helper methods are added and calling `VolumeUsages`. These helper 
methods should be moved to `DiskBalancerVolumeCalaculation` class as the logic 
can be reused and Each calculation will get one time snapshot of the 
VolumeUsages.



##########
hadoop-hdds/interface-client/src/main/proto/hdds.proto:
##########
@@ -608,6 +608,16 @@ message VolumeReportProto {
     optional uint64 effectiveUsedSpace = 6;
     optional double utilization = 7;
     optional uint64 ozoneAvailable = 8;
+    optional StorageTypeProto storageType = 9;
+}
+
+message StorageTypeDiskBalancerInfoProto {

Review Comment:
   Please check the existing proto messages it those can be reused else we can 
keep the new ones.



##########
hadoop-hdds/interface-client/src/main/resources/proto.lock:
##########
@@ -4625,6 +4625,53 @@
                 "name": "ozoneAvailable",
                 "type": "uint64",
                 "optional": true
+              },

Review Comment:
   Do we really need in this PR?



##########
hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/datanode/DiskBalancerReportSubcommand.java:
##########
@@ -123,7 +125,10 @@ private String generateReport(
           .append(formatPercent(p.getCurrentVolumeDensitySum()))
           .append(System.lineSeparator());
 
-      if (p.hasIdealUsage() && p.hasDiskBalancerConf()
+      if (p.getStorageTypeInfoCount() > 0 && p.hasDiskBalancerConf()
+          && p.getDiskBalancerConf().hasThreshold()) {
+        appendStorageTypeDetails(header, p);
+      } else if (p.hasIdealUsage() && p.hasDiskBalancerConf()
           && p.getDiskBalancerConf().hasThreshold()) {
         double idealUsage = p.getIdealUsage();

Review Comment:
   here in report we should display idealUsage for each storageType so that 
it's easy for user to compare.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to