This is an automated email from the ASF dual-hosted git repository.

umamahesh pushed a commit to branch HDDS-3816-ec
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/HDDS-3816-ec by this push:
     new 6f64eb7  HDDS-6342. EC: Fix large write with multiple stripes upon 
stripe failure. (#3108)
6f64eb7 is described below

commit 6f64eb77d579629fd79705b112d9a5e01937dd84
Author: Gui Hecheng <[email protected]>
AuthorDate: Fri Feb 18 06:12:51 2022 +0800

    HDDS-6342. EC: Fix large write with multiple stripes upon stripe failure. 
(#3108)
---
 .../ozone/client/io/ECBlockOutputStreamEntry.java  |  2 +-
 .../hadoop/ozone/client/TestOzoneECClient.java     | 80 ++++++++++++++++++++++
 2 files changed, 81 insertions(+), 1 deletion(-)

diff --git 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ECBlockOutputStreamEntry.java
 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ECBlockOutputStreamEntry.java
index 3a86bd5..88f8d2e 100644
--- 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ECBlockOutputStreamEntry.java
+++ 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ECBlockOutputStreamEntry.java
@@ -212,7 +212,7 @@ public class ECBlockOutputStreamEntry extends 
BlockOutputStreamEntry {
     if (isWritingParity()) {
       return;
     }
-    this.successfulBlkGrpAckedLen += len;
+    this.successfulBlkGrpAckedLen = len;
   }
 
   /**
diff --git 
a/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/TestOzoneECClient.java
 
b/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/TestOzoneECClient.java
index 758e3bd..8b2a8a1 100644
--- 
a/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/TestOzoneECClient.java
+++ 
b/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/TestOzoneECClient.java
@@ -763,6 +763,86 @@ public class TestOzoneECClient {
     }
   }
 
+  @Test
+  public void testLargeWriteOfMultipleStripesWithStripeFailure()
+      throws IOException {
+    close();
+    OzoneConfiguration con = new OzoneConfiguration();
+    // block size of 3KB could hold 3 full stripes
+    con.setStorageSize(OzoneConfigKeys.OZONE_SCM_BLOCK_SIZE, 3, 
StorageUnit.KB);
+    con.setInt(OzoneConfigKeys.OZONE_CLIENT_MAX_EC_STRIPE_WRITE_RETRIES, 3);
+    MultiNodePipelineBlockAllocator blkAllocator =
+        new MultiNodePipelineBlockAllocator(con, dataBlocks + parityBlocks,
+            15);
+    createNewClient(con, blkAllocator);
+
+    store.createVolume(volumeName);
+    OzoneVolume volume = store.getVolume(volumeName);
+    volume.createBucket(bucketName);
+    OzoneBucket bucket = volume.getBucket(bucketName);
+
+    // should write > 1 full stripe to trigger potential issue
+    int numFullStripesBeforeFailure = 2;
+    int numChunksToWriteAfterFailure = dataBlocks;
+    int numExpectedBlockGrps = 2;
+    // fail the DNs for parity blocks
+    int[] nodesIndexesToMarkFailure = {3, 4};
+
+    try (OzoneOutputStream out = bucket.createKey(keyName,
+        1024 * dataBlocks * numFullStripesBeforeFailure
+            + numChunksToWriteAfterFailure,
+        new ECReplicationConfig(dataBlocks, parityBlocks,
+            ECReplicationConfig.EcCodec.RS,
+            chunkSize), new HashMap<>())) {
+      for (int j = 0; j < numFullStripesBeforeFailure; j++) {
+        for (int i = 0; i < dataBlocks; i++) {
+          out.write(inputChunks[i]);
+        }
+      }
+
+      List<DatanodeDetails> failedDNs = new ArrayList<>();
+      List<HddsProtos.DatanodeDetailsProto> dns = allocator.getClusterDns();
+      for (int j = 0; j < nodesIndexesToMarkFailure.length; j++) {
+        failedDNs.add(DatanodeDetails
+            .getFromProtoBuf(dns.get(nodesIndexesToMarkFailure[j])));
+      }
+
+      // First let's set storage as bad
+      ((MockXceiverClientFactory) factoryStub).setFailedStorages(failedDNs);
+
+      for (int i = 0; i < numChunksToWriteAfterFailure; i++) {
+        out.write(inputChunks[i % dataBlocks]);
+      }
+    }
+
+    final OzoneKeyDetails key = bucket.getKey(keyName);
+    // Data supposed to store in single block group. Since we introduced the
+    // failures after first stripe, the second stripe data should have been
+    // written into new block group. So, we should have numExpectedBlockGrps.
+    // That means two keyLocations.
+    Assert
+        .assertEquals(numExpectedBlockGrps, key.getOzoneKeyLocations().size());
+    try (OzoneInputStream is = bucket.readKey(keyName)) {
+      byte[] fileContent = new byte[chunkSize];
+      for (int i = 0; i < dataBlocks * numFullStripesBeforeFailure; i++) {
+        Assert.assertEquals(inputChunks[i % dataBlocks].length,
+            is.read(fileContent));
+        Assert.assertTrue(
+            "Expected: " + new String(inputChunks[i % dataBlocks], UTF_8)
+                + " \n " + "Actual: " + new String(fileContent, UTF_8),
+            Arrays.equals(inputChunks[i % dataBlocks], fileContent));
+      }
+      for (int i = 0; i < numChunksToWriteAfterFailure; i++) {
+        Assert.assertEquals(inputChunks[i % dataBlocks].length,
+            is.read(fileContent));
+        Assert.assertTrue(
+            "Expected: " + new String(inputChunks[i % dataBlocks],
+                UTF_8) + " \n " + "Actual: " + new String(fileContent, UTF_8),
+            Arrays.equals(inputChunks[i % dataBlocks], fileContent));
+      }
+    }
+  }
+
   @Test(expected = NotImplementedException.class)
   public void testFlushShouldThrowNotImplementedException() throws IOException 
{
     store.createVolume(volumeName);

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

Reply via email to