From a5fccbc1d6539cdccf5366edf26382a139897789 Mon Sep 17 00:00:00 2001 From: Stephen O'Donnell Date: Fri, 12 Apr 2024 21:02:33 +0100 Subject: [PATCH] HDDS-10682. EC Reconstruction creates empty chunks at the end of blocks with partial stripes (#6515) --- .../ECReconstructionCoordinator.java | 10 +++++++--- .../hdds/scm/storage/TestContainerCommandsEC.java | 14 ++++++++------ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ec/reconstruction/ECReconstructionCoordinator.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ec/reconstruction/ECReconstructionCoordinator.java index 774c7d83454..8fadd19b67d 100644 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ec/reconstruction/ECReconstructionCoordinator.java +++ b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/ec/reconstruction/ECReconstructionCoordinator.java @@ -323,9 +323,13 @@ public void reconstructECBlockGroup(BlockLocationInfo blockLocationInfo, } // TODO: can be submitted in parallel for (int i = 0; i < bufs.length; i++) { - CompletableFuture - future = targetBlockStreams[i].write(bufs[i]); - checkFailures(targetBlockStreams[i], future); + if (bufs[i].remaining() != 0) { + // If the buffer is empty, we don't need to write it as it will cause + // an empty chunk to be added to the end of the block. + CompletableFuture + future = targetBlockStreams[i].write(bufs[i]); + checkFailures(targetBlockStreams[i], future); + } bufs[i].clear(); } length -= readLen; diff --git a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/storage/TestContainerCommandsEC.java b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/storage/TestContainerCommandsEC.java index 5254f8748c8..b4814d7b5e5 100644 --- a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/storage/TestContainerCommandsEC.java +++ b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/storage/TestContainerCommandsEC.java @@ -136,7 +136,9 @@ public class TestContainerCommandsEC { private static final int EC_CHUNK_SIZE = 1024 * 1024; private static final int STRIPE_DATA_SIZE = EC_DATA * EC_CHUNK_SIZE; private static final int NUM_DN = EC_DATA + EC_PARITY + 3; - private static byte[][] inputChunks = new byte[EC_DATA][EC_CHUNK_SIZE]; + // Data slots are EC_DATA + 1 so we can generate enough data to have a full stripe + // plus one extra chunk. + private static byte[][] inputChunks = new byte[EC_DATA + 1][EC_CHUNK_SIZE]; // Each key size will be in range [min, max), min inclusive, max exclusive private static final int[][] KEY_SIZE_RANGES = @@ -621,13 +623,13 @@ void testECReconstructionCoordinatorWithPartialStripe(List missingIndex testECReconstructionCoordinator(missingIndexes, 1); } - @Test - void testECReconstructParityWithPartialStripe() - throws Exception { - testECReconstructionCoordinator(ImmutableList.of(4, 5), 1); + @ParameterizedTest + @MethodSource("recoverableMissingIndexes") + void testECReconstructionCoordinatorWithFullAndPartialStripe(List missingIndexes) + throws Exception { + testECReconstructionCoordinator(missingIndexes, 4); } - static Stream> recoverableMissingIndexes() { return Stream .concat(IntStream.rangeClosed(1, 5).mapToObj(ImmutableList::of), Stream