Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ public ContainerBalancer(
this.containerManager = containerManager;
this.replicationManager = replicationManager;
this.ozoneConfiguration = ozoneConfiguration;
this.config = new ContainerBalancerConfiguration(ozoneConfiguration);
this.config = ozoneConfiguration.
getObject(ContainerBalancerConfiguration.class);
config.initialize(ozoneConfiguration);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may be we can add a static build function to ContainerBalancerConfiguration class to build and initialize a ContainerBalancerConfiguration instance, for example:

public static ContainerBalancerConfiguration buildFrom(ozoneConfiguration oc) {
.....
}

this.metrics = ContainerBalancerMetrics.create();
this.scmContext = scmContext;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
Expand Down Expand Up @@ -73,15 +72,15 @@ public final class ContainerBalancerConfiguration {
private long maxSizeToMovePerIteration = 30 * OzoneConsts.GB;

@Config(key = "size.entering.target.max", type = ConfigType.SIZE,
defaultValue = "", tags = {ConfigTag.BALANCER}, description = "The " +
defaultValue = "6GB", tags = {ConfigTag.BALANCER}, description = "The " +
"maximum size that can enter a target datanode in each " +
"iteration while balancing. This is the sum of data from multiple " +
"sources. The default value is greater than the configured" +
" (or default) ozone.scm.container.size by 1GB.")
private long maxSizeEnteringTarget;

@Config(key = "size.leaving.source.max", type = ConfigType.SIZE,
defaultValue = "", tags = {ConfigTag.BALANCER}, description = "The " +
defaultValue = "6GB", tags = {ConfigTag.BALANCER}, description = "The " +
"maximum size that can leave a source datanode in each " +
"iteration while balancing. This is the sum of data moving to multiple " +
"targets. The default value is greater than the configured" +
Expand All @@ -99,13 +98,13 @@ public final class ContainerBalancerConfiguration {
private String excludeContainers = "";

@Config(key = "move.timeout", type = ConfigType.TIME, defaultValue = "30m",
timeUnit = TimeUnit.MINUTES, tags = {ConfigTag.BALANCER}, description =
tags = {ConfigTag.BALANCER}, description =
"The amount of time in minutes to allow a single container to move " +
"from source to target.")
private long moveTimeout = Duration.ofMinutes(30).toMillis();

@Config(key = "balancing.iteration.interval", type = ConfigType.TIME,
defaultValue = "1h", timeUnit = TimeUnit.MINUTES, tags = {
defaultValue = "1h", tags = {
ConfigTag.BALANCER}, description = "The interval period between each " +
"iteration of Container Balancer.")
private long balancingInterval;
Expand All @@ -127,11 +126,11 @@ public final class ContainerBalancerConfiguration {
private DUFactory.Conf duConf;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this isn't getting initialised now, we can remove this and its usages in the setBalancingInterval method.


/**
* Create configuration with default values.
* Modify configuration with default values.
*
* @param config Ozone configuration
*/
public ContainerBalancerConfiguration(OzoneConfiguration config) {
public void initialize(OzoneConfiguration config) {
Preconditions.checkNotNull(config,
"OzoneConfiguration should not be null.");
this.ozoneConfiguration = config;
Expand All @@ -140,7 +139,7 @@ public ContainerBalancerConfiguration(OzoneConfiguration config) {
// greater than container size
long size = (long) ozoneConfiguration.getStorageSize(
ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE,
ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE_DEFAULT, StorageUnit.GB) +
ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE_DEFAULT, StorageUnit.BYTES) +

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@siddhantsangwan Another issue is the StorageUnit here.
The value from Unit.GB is "5 + 1GB", need to changed to Unit.BYTES.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I was just going to raise a jira for this particular bug when I saw that you've pushed an update. Thanks!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems the other configs, like "move.timeout" and "balancing.interval", also have the same issue.

OzoneConsts.GB;
maxSizeEnteringTarget = size;
maxSizeLeavingSource = size;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,8 @@ public boolean startContainerBalancer(
Optional<Long> maxSizeLeavingSource) throws IOException {
getScm().checkAdminAccess(getRemoteUser());
ContainerBalancerConfiguration cbc =
new ContainerBalancerConfiguration(scm.getConfiguration());
scm.getConfiguration().getObject(ContainerBalancerConfiguration.class);
cbc.initialize(scm.getConfiguration());
if (threshold.isPresent()) {
double tsd = threshold.get();
Preconditions.checkState(tsd >= 0.0D && tsd < 1.0D,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public class TestContainerBalancer {
private Map<DatanodeUsageInfo, Set<ContainerID>> datanodeToContainersMap =
new HashMap<>();
private static final ThreadLocalRandom RANDOM = ThreadLocalRandom.current();
private static final double DELTA = 1e-15;

@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();
Expand All @@ -102,7 +103,9 @@ public void setup() throws SCMException, NodeNotFoundException {
containerManager = Mockito.mock(ContainerManager.class);
replicationManager = Mockito.mock(ReplicationManager.class);

balancerConfiguration = new ContainerBalancerConfiguration(conf);
balancerConfiguration =
conf.getObject(ContainerBalancerConfiguration.class);
balancerConfiguration.initialize(conf);
balancerConfiguration.setThreshold(0.1);
balancerConfiguration.setIdleIteration(1);
balancerConfiguration.setMaxDatanodesRatioToInvolvePerIteration(1.0d);
Expand Down Expand Up @@ -486,8 +489,11 @@ public void balancerShouldObeyMaxSizeEnteringTargetLimit() {
Assert.assertTrue(containerBalancer.getSourceToTargetMap().isEmpty());

// some containers should be selected when using default values
containerBalancer.start(
new ContainerBalancerConfiguration(new OzoneConfiguration()));
OzoneConfiguration ozoneConfiguration = new OzoneConfiguration();
ContainerBalancerConfiguration cbc = ozoneConfiguration.
getObject(ContainerBalancerConfiguration.class);
cbc.initialize(ozoneConfiguration);
containerBalancer.start(cbc);

// waiting for balance completed.
// TODO: this is a temporary implementation for now
Expand Down Expand Up @@ -589,6 +595,24 @@ public void balancerShouldFollowExcludeAndIncludeDatanodesConfigurations() {
}
}

@Test
public void testContainerBalancerConfiguration() {
OzoneConfiguration ozoneConfiguration = new OzoneConfiguration();
ozoneConfiguration.set("ozone.scm.container.size", "5GB");
ozoneConfiguration.setDouble(
"hdds.container.balancer.utilization.threshold", 0.01);

ContainerBalancerConfiguration cbConf =
ozoneConfiguration.getObject(ContainerBalancerConfiguration.class);
cbConf.initialize(ozoneConfiguration);
Assert.assertEquals(cbConf.getThreshold(), 0.01d, DELTA);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we remove DELTA and use assertTrue(Doublu.compare(a,b) == 0)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have removed DELTA and use a similar comparison as


, please have a check.

Assert.assertEquals(cbConf.getMaxSizeLeavingSource(),
6 * 1024 * 1024 * 1024L);

Assert.assertEquals(cbConf.getMoveTimeout().toMillis(), 30 * 60 * 1000);
}

/**
* Determines unBalanced nodes, that is, over and under utilized nodes,
* according to the generated utilization values for nodes and the threshold.
Expand Down