HDDS-6250. EC: Add replica index to the output in the container info command (#3041)
diff --git a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReplicaInfo.java b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReplicaInfo.java
index b30dff7..5a81f6b 100644
--- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReplicaInfo.java
+++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReplicaInfo.java
@@ -34,6 +34,7 @@
private long sequenceId;
private long keyCount;
private long bytesUsed;
+ private int replicaIndex = -1;
public static ContainerReplicaInfo fromProto(
HddsProtos.SCMContainerReplicaProto proto) {
@@ -45,7 +46,9 @@
.setPlaceOfBirth(UUID.fromString(proto.getPlaceOfBirth()))
.setSequenceId(proto.getSequenceID())
.setKeyCount(proto.getKeyCount())
- .setBytesUsed(proto.getBytesUsed());
+ .setBytesUsed(proto.getBytesUsed())
+ .setReplicaIndex(
+ proto.hasReplicaIndex() ? (int)proto.getReplicaIndex() : -1);
return builder.build();
}
@@ -80,6 +83,10 @@
return bytesUsed;
}
+ public int getReplicaIndex() {
+ return replicaIndex;
+ }
+
/**
* Builder for ContainerReplicaInfo class.
*/
@@ -122,6 +129,11 @@
return this;
}
+ public Builder setReplicaIndex(int replicaIndex) {
+ subject.replicaIndex = replicaIndex;
+ return this;
+ }
+
public ContainerReplicaInfo build() {
return subject;
}
diff --git a/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerReplicaInfo.java b/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerReplicaInfo.java
index 195baca..4f63ea7 100644
--- a/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerReplicaInfo.java
+++ b/hadoop-hdds/common/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerReplicaInfo.java
@@ -55,5 +55,36 @@
proto.getDatanodeDetails()), info.getDatanodeDetails());
Assert.assertEquals(proto.getSequenceID(), info.getSequenceId());
Assert.assertEquals(proto.getState(), info.getState());
+ // If replicaIndex is not in the proto, then -1 should be returned
+ Assert.assertEquals(-1, info.getReplicaIndex());
+ }
+
+ @Test
+ public void testObjectCreatedFromProtoWithReplicaIndedx() {
+ HddsProtos.SCMContainerReplicaProto proto =
+ HddsProtos.SCMContainerReplicaProto.newBuilder()
+ .setKeyCount(10)
+ .setBytesUsed(12345)
+ .setContainerID(567)
+ .setPlaceOfBirth(UUID.randomUUID().toString())
+ .setSequenceID(5)
+ .setDatanodeDetails(MockDatanodeDetails.randomDatanodeDetails()
+ .getProtoBufMessage())
+ .setState("OPEN")
+ .setReplicaIndex(4)
+ .build();
+
+ ContainerReplicaInfo info = ContainerReplicaInfo.fromProto(proto);
+
+ Assert.assertEquals(proto.getContainerID(), info.getContainerID());
+ Assert.assertEquals(proto.getBytesUsed(), info.getBytesUsed());
+ Assert.assertEquals(proto.getKeyCount(), info.getKeyCount());
+ Assert.assertEquals(proto.getPlaceOfBirth(),
+ info.getPlaceOfBirth().toString());
+ Assert.assertEquals(DatanodeDetails.getFromProtoBuf(
+ proto.getDatanodeDetails()), info.getDatanodeDetails());
+ Assert.assertEquals(proto.getSequenceID(), info.getSequenceId());
+ Assert.assertEquals(proto.getState(), info.getState());
+ Assert.assertEquals(4, info.getReplicaIndex());
}
}
\ No newline at end of file
diff --git a/hadoop-hdds/interface-client/src/main/proto/hdds.proto b/hadoop-hdds/interface-client/src/main/proto/hdds.proto
index ed296dc..02488e2 100644
--- a/hadoop-hdds/interface-client/src/main/proto/hdds.proto
+++ b/hadoop-hdds/interface-client/src/main/proto/hdds.proto
@@ -406,6 +406,7 @@
required int64 sequenceID = 5;
required int64 keyCount = 6;
required int64 bytesUsed = 7;
+ optional int64 replicaIndex = 8;
}
message KeyContainerIDList {
diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
index 332df77..c95612e 100644
--- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
+++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
@@ -29,7 +29,6 @@
import org.apache.commons.lang3.tuple.Pair;
import org.apache.hadoop.fs.CommonConfigurationKeys;
import org.apache.hadoop.hdds.client.ReplicationConfig;
-import org.apache.hadoop.hdds.client.StandaloneReplicationConfig;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.hdds.protocol.DatanodeDetails;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
@@ -258,8 +257,7 @@
if (pipeline == null) {
pipeline = scm.getPipelineManager().createPipeline(
- new StandaloneReplicationConfig(ReplicationConfig
- .getLegacyFactor(container.getReplicationConfig())),
+ container.getReplicationConfig(),
scm.getContainerManager()
.getContainerReplicas(cid).stream()
.map(ContainerReplica::getDatanodeDetails)
@@ -306,7 +304,8 @@
.setBytesUsed(r.getBytesUsed())
.setPlaceOfBirth(r.getOriginDatanodeId().toString())
.setKeyCount(r.getKeyCount())
- .setSequenceID(r.getSequenceId()).build()
+ .setSequenceID(r.getSequenceId())
+ .setReplicaIndex(r.getReplicaIndex()).build()
);
}
return results;
diff --git a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/InfoSubcommand.java b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/InfoSubcommand.java
index 7b0daa6..25ed0e5 100644
--- a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/InfoSubcommand.java
+++ b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/container/InfoSubcommand.java
@@ -119,6 +119,9 @@
private static String buildReplicaDetails(ContainerReplicaInfo replica) {
StringBuilder sb = new StringBuilder();
sb.append("State: " + replica.getState() + ";");
+ if (replica.getReplicaIndex() != -1) {
+ sb.append(" ReplicaIndex: " + replica.getReplicaIndex() + ";");
+ }
sb.append(" Origin: " + replica.getPlaceOfBirth().toString() + ";");
sb.append(" Location: "
+ buildDatanodeDetails(replica.getDatanodeDetails()));
diff --git a/hadoop-hdds/tools/src/test/java/org/apache/hadoop/hdds/scm/cli/container/TestInfoSubCommand.java b/hadoop-hdds/tools/src/test/java/org/apache/hadoop/hdds/scm/cli/container/TestInfoSubCommand.java
index ad43f9e..2ea34b9 100644
--- a/hadoop-hdds/tools/src/test/java/org/apache/hadoop/hdds/scm/cli/container/TestInfoSubCommand.java
+++ b/hadoop-hdds/tools/src/test/java/org/apache/hadoop/hdds/scm/cli/container/TestInfoSubCommand.java
@@ -17,6 +17,7 @@
*/
package org.apache.hadoop.hdds.scm.cli.container;
+import org.apache.hadoop.hdds.client.ECReplicationConfig;
import org.apache.hadoop.hdds.client.RatisReplicationConfig;
import org.apache.hadoop.hdds.protocol.DatanodeDetails;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
@@ -81,8 +82,19 @@
@Test
public void testReplicasIncludedInOutput() throws Exception {
+ testReplicaIncludedInOutput(false);
+ }
+
+ @Test
+ public void testReplicaIndexInOutput() throws Exception {
+ testReplicaIncludedInOutput(true);
+ }
+
+
+ private void testReplicaIncludedInOutput(boolean includeIndex)
+ throws IOException {
Mockito.when(scmClient.getContainerReplicas(anyLong()))
- .thenReturn(getReplicas());
+ .thenReturn(getReplicas(includeIndex));
cmd = new InfoSubcommand();
CommandLine c = new CommandLine(cmd);
c.parseArgs("1");
@@ -94,7 +106,7 @@
.filter(m -> m.getRenderedMessage().matches("(?s)^Replicas:.*"))
.collect(Collectors.toList());
Assert.assertEquals(1, replica.size());
-
+
// Ensure each DN UUID is mentioned in the message:
for (DatanodeDetails dn : datanodes) {
Pattern pattern = Pattern.compile(".*" + dn.getUuid().toString() + ".*",
@@ -102,6 +114,11 @@
Matcher matcher = pattern.matcher(replica.get(0).getRenderedMessage());
Assert.assertTrue(matcher.matches());
}
+ // Ensure ReplicaIndex is not mentioned as it was not passed in the proto:
+ Pattern pattern = Pattern.compile(".*ReplicaIndex.*",
+ Pattern.DOTALL);
+ Matcher matcher = pattern.matcher(replica.get(0).getRenderedMessage());
+ Assert.assertEquals(includeIndex, matcher.matches());
}
@Test
@@ -151,7 +168,20 @@
@Test
public void testReplicasOutputWithJson() throws IOException {
Mockito.when(scmClient.getContainerReplicas(anyLong()))
- .thenReturn(getReplicas());
+ .thenReturn(getReplicas(true));
+ testJsonOutput();
+ }
+
+ @Test
+ public void testECContainerReplicasOutputWithJson() throws IOException {
+ Mockito.when(scmClient.getContainerReplicas(anyLong()))
+ .thenReturn(getReplicas(true));
+ Mockito.when(scmClient.getContainerWithPipeline(anyLong()))
+ .thenReturn(getECContainerWithPipeline());
+ testJsonOutput();
+ }
+
+ private void testJsonOutput() throws IOException {
cmd = new InfoSubcommand();
CommandLine c = new CommandLine(cmd);
c.parseArgs("1", "--json");
@@ -169,20 +199,29 @@
Matcher matcher = pattern.matcher(json);
Assert.assertTrue(matcher.matches());
}
+ Pattern pattern = Pattern.compile(".*replicaIndex.*",
+ Pattern.DOTALL);
+ Matcher matcher = pattern.matcher(json);
+ Assert.assertTrue(matcher.matches());
}
- private List<ContainerReplicaInfo> getReplicas() {
+
+ private List<ContainerReplicaInfo> getReplicas(boolean includeIndex) {
List<ContainerReplicaInfo> replicas = new ArrayList<>();
for (DatanodeDetails dn : datanodes) {
- ContainerReplicaInfo container = new ContainerReplicaInfo.Builder()
+ ContainerReplicaInfo.Builder container
+ = new ContainerReplicaInfo.Builder()
.setContainerID(1)
.setBytesUsed(1234)
.setState("CLOSED")
.setPlaceOfBirth(dn.getUuid())
.setDatanodeDetails(dn)
.setKeyCount(1)
- .setSequenceId(1).build();
- replicas.add(container);
+ .setSequenceId(1);
+ if (includeIndex) {
+ container.setReplicaIndex(4);
+ }
+ replicas.add(container.build());
}
return replicas;
}
@@ -207,6 +246,26 @@
return new ContainerWithPipeline(container, pipeline);
}
+ private ContainerWithPipeline getECContainerWithPipeline() {
+ Pipeline pipeline = new Pipeline.Builder()
+ .setState(Pipeline.PipelineState.CLOSED)
+ .setReplicationConfig(new ECReplicationConfig(3, 2))
+ .setId(PipelineID.randomId())
+ .setNodes(datanodes)
+ .build();
+
+ ContainerInfo container = new ContainerInfo.Builder()
+ .setSequenceId(1)
+ .setPipelineID(pipeline.getId())
+ .setUsedBytes(1234)
+ .setReplicationConfig(new RatisReplicationConfig(THREE))
+ .setNumberOfKeys(1)
+ .setState(CLOSED)
+ .build();
+
+ return new ContainerWithPipeline(container, pipeline);
+ }
+
private List<DatanodeDetails> createDatanodeDetails(int count) {
List<DatanodeDetails> dns = new ArrayList<>();
for (int i = 0; i < count; i++) {