From a5eba25506a4ca7ac9efa9b60b204c8cf1aa4160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Elek?= Date: Fri, 24 Aug 2018 22:27:43 +0200 Subject: [PATCH] HDDS-364. Update open container replica information in SCM during DN register. Contributed by Ajay Kumar. --- .../hdds/scm/container/ContainerMapping.java | 25 +++++++++++++------ .../scm/container/ContainerReportHandler.java | 3 ++- .../hadoop/hdds/scm/container/Mapping.java | 2 +- .../scm/server/SCMDatanodeProtocolServer.java | 2 +- .../scm/container/TestContainerMapping.java | 19 +++++++++++--- .../container/closer/TestContainerCloser.java | 2 +- .../commandhandler/TestBlockDeletion.java | 3 ++- 7 files changed, 41 insertions(+), 15 deletions(-) diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerMapping.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerMapping.java index ba957642b08..b000bfd0b22 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerMapping.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerMapping.java @@ -505,15 +505,26 @@ public class ContainerMapping implements Mapping { */ @Override public void processContainerReports(DatanodeDetails datanodeDetails, - ContainerReportsProto reports) + ContainerReportsProto reports, boolean isRegisterCall) throws IOException { List containerInfos = reports.getReportsList(); PendingDeleteStatusList pendingDeleteStatusList = new PendingDeleteStatusList(datanodeDetails); - for (StorageContainerDatanodeProtocolProtos.ContainerInfo datanodeState : + for (StorageContainerDatanodeProtocolProtos.ContainerInfo contInfo : containerInfos) { - byte[] dbKey = Longs.toByteArray(datanodeState.getContainerID()); + // Update replica info during registration process. + if (isRegisterCall) { + try { + getStateManager().addContainerReplica(ContainerID. + valueof(contInfo.getContainerID()), datanodeDetails); + } catch (Exception ex) { + // Continue to next one after logging the error. + LOG.error("Error while adding replica for containerId {}.", + contInfo.getContainerID(), ex); + } + } + byte[] dbKey = Longs.toByteArray(contInfo.getContainerID()); lock.lock(); try { byte[] containerBytes = containerStore.get(dbKey); @@ -522,12 +533,12 @@ public class ContainerMapping implements Mapping { HddsProtos.SCMContainerInfo.PARSER.parseFrom(containerBytes); HddsProtos.SCMContainerInfo newState = - reconcileState(datanodeState, knownState, datanodeDetails); + reconcileState(contInfo, knownState, datanodeDetails); - if (knownState.getDeleteTransactionId() > datanodeState + if (knownState.getDeleteTransactionId() > contInfo .getDeleteTransactionId()) { pendingDeleteStatusList - .addPendingDeleteStatus(datanodeState.getDeleteTransactionId(), + .addPendingDeleteStatus(contInfo.getDeleteTransactionId(), knownState.getDeleteTransactionId(), knownState.getContainerID()); } @@ -558,7 +569,7 @@ public class ContainerMapping implements Mapping { LOG.error("Error while processing container report from datanode :" + " {}, for container: {}, reason: container doesn't exist in" + "container database.", datanodeDetails, - datanodeState.getContainerID()); + contInfo.getContainerID()); } } finally { lock.unlock(); diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReportHandler.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReportHandler.java index b26eed2c75d..5a9e726f888 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReportHandler.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReportHandler.java @@ -84,7 +84,8 @@ public class ContainerReportHandler implements try { //update state in container db and trigger close container events - containerMapping.processContainerReports(datanodeOrigin, containerReport); + containerMapping + .processContainerReports(datanodeOrigin, containerReport, false); Set containerIds = containerReport.getReportsList().stream() .map(containerProto -> containerProto.getContainerID()) diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/Mapping.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/Mapping.java index ac84be44a38..f4b5bb22f6f 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/Mapping.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/Mapping.java @@ -115,7 +115,7 @@ public interface Mapping extends Closeable { * @param reports Container report */ void processContainerReports(DatanodeDetails datanodeDetails, - ContainerReportsProto reports) + ContainerReportsProto reports, boolean isRegisterCall) throws IOException; /** diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeProtocolServer.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeProtocolServer.java index 0d34787cc6d..92158039cd8 100644 --- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeProtocolServer.java +++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMDatanodeProtocolServer.java @@ -196,7 +196,7 @@ public class SCMDatanodeProtocolServer implements if (registeredCommand.getError() == SCMRegisteredResponseProto.ErrorCode.success) { scm.getScmContainerManager().processContainerReports(datanodeDetails, - containerReportsProto); + containerReportsProto, true); } return getRegisteredResponse(registeredCommand); } diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerMapping.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerMapping.java index 1e9c35b65df..b0b39f17689 100644 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerMapping.java +++ b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/TestContainerMapping.java @@ -242,7 +242,7 @@ public class TestContainerMapping { } @Test - public void testFullContainerReport() throws IOException { + public void testFullContainerReport() throws Exception { ContainerInfo info = createContainer(); DatanodeDetails datanodeDetails = TestUtils.randomDatanodeDetails(); List reports = @@ -266,13 +266,26 @@ public class TestContainerMapping { .newBuilder(); crBuilder.addAllReports(reports); - mapping.processContainerReports(datanodeDetails, crBuilder.build()); + mapping.processContainerReports(datanodeDetails, crBuilder.build(), false); ContainerInfo updatedContainer = mapping.getContainer(info.getContainerID()); Assert.assertEquals(100000000L, updatedContainer.getNumberOfKeys()); Assert.assertEquals(2000000000L, updatedContainer.getUsedBytes()); + + for (StorageContainerDatanodeProtocolProtos.ContainerInfo c : reports) { + LambdaTestUtils.intercept(SCMException.class, "No entry " + + "exist for containerId:", () -> mapping.getStateManager() + .getContainerReplicas(ContainerID.valueof(c.getContainerID()))); + } + + mapping.processContainerReports(TestUtils.randomDatanodeDetails(), + crBuilder.build(), true); + for (StorageContainerDatanodeProtocolProtos.ContainerInfo c : reports) { + Assert.assertTrue(mapping.getStateManager().getContainerReplicas( + ContainerID.valueof(c.getContainerID())).size() > 0); + } } @Test @@ -301,7 +314,7 @@ public class TestContainerMapping { ContainerReportsProto.newBuilder(); crBuilder.addAllReports(reports); - mapping.processContainerReports(datanodeDetails, crBuilder.build()); + mapping.processContainerReports(datanodeDetails, crBuilder.build(), false); ContainerInfo updatedContainer = mapping.getContainer(info.getContainerID()); diff --git a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/closer/TestContainerCloser.java b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/closer/TestContainerCloser.java index 608bb9242ba..210df088f84 100644 --- a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/closer/TestContainerCloser.java +++ b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/container/closer/TestContainerCloser.java @@ -223,6 +223,6 @@ public class TestContainerCloser { .setDeleteTransactionId(0); reports.addReports(ciBuilder); mapping.processContainerReports(TestUtils.randomDatanodeDetails(), - reports.build()); + reports.build(), false); } } \ No newline at end of file diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/TestBlockDeletion.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/TestBlockDeletion.java index 94cdf6131a9..57941515e9c 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/TestBlockDeletion.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/TestBlockDeletion.java @@ -187,7 +187,8 @@ public class TestBlockDeletion { logCapturer.clearOutput(); scm.getScmContainerManager().processContainerReports( - cluster.getHddsDatanodes().get(0).getDatanodeDetails(), dummyReport); + cluster.getHddsDatanodes().get(0).getDatanodeDetails(), dummyReport, + false); // wait for event to be handled by event handler Thread.sleep(1000); String output = logCapturer.getOutput();