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

sodonnell 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 5d2fa94  HDDS-6256. EC: Parity blocks are incorrectly padded with 
zeros to the chunk size (#3043)
5d2fa94 is described below

commit 5d2fa9494985edd2ef844e1a8335501d0e76f468
Author: Uma Maheswara Rao G <[email protected]>
AuthorDate: Mon Feb 7 03:33:50 2022 -0800

    HDDS-6256. EC: Parity blocks are incorrectly padded with zeros to the chunk 
size (#3043)
---
 .../hadoop/ozone/client/io/ECKeyOutputStream.java  |  8 +--
 .../hadoop/ozone/client/MockDatanodeStorage.java   | 10 +++
 .../hadoop/ozone/client/TestOzoneECClient.java     | 74 ++++++++++++++++++++++
 3 files changed, 87 insertions(+), 5 deletions(-)

diff --git 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ECKeyOutputStream.java
 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ECKeyOutputStream.java
index db51a65..d738436 100644
--- 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ECKeyOutputStream.java
+++ 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/io/ECKeyOutputStream.java
@@ -380,8 +380,7 @@ public class ECKeyOutputStream extends KeyOutputStream {
     for (int i =
          numDataBlks; i < (this.numDataBlks + this.numParityBlks); i++) {
       // Move the stream entry cursor to parity block index
-      handleParityWrite(i, parityBuffers[i - numDataBlks].array(), 0,
-          parityCellSize, true);
+      handleParityWrite(i, parityCellSize, true);
     }
   }
 
@@ -396,8 +395,7 @@ public class ECKeyOutputStream extends KeyOutputStream {
     return pos;
   }
 
-  private void handleParityWrite(int currIdx, byte[] b, int off, long len,
-      boolean isFullCell) throws IOException {
+  private void handleParityWrite(int currIdx, long len, boolean isFullCell) {
     handleOutputStreamWrite(currIdx, len, isFullCell, true);
     blockOutputStreamEntryPool.getCurrentStreamEntry().useNextBlockStream();
   }
@@ -418,7 +416,7 @@ public class ECKeyOutputStream extends KeyOutputStream {
       try {
         // Since it's a fullcell, let's write all content from buffer.
         writeToOutputStream(current, len, bytesToWrite.array(),
-            bytesToWrite.array().length, 0, isParity);
+            bytesToWrite.limit(), 0, isParity);
       } catch (Exception e) {
         markStreamAsFailed(e);
       }
diff --git 
a/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/MockDatanodeStorage.java
 
b/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/MockDatanodeStorage.java
index ce70c15..41de363 100644
--- 
a/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/MockDatanodeStorage.java
+++ 
b/hadoop-ozone/client/src/test/java/org/apache/hadoop/ozone/client/MockDatanodeStorage.java
@@ -18,6 +18,7 @@
 package org.apache.hadoop.ozone.client;
 
 import org.apache.commons.collections.map.HashedMap;
+import org.apache.hadoop.hdds.client.BlockID;
 import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.BlockData;
 import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ChunkInfo;
 import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.DatanodeBlockID;
@@ -33,6 +34,7 @@ import java.util.Map;
 public class MockDatanodeStorage {
 
   private final Map<DatanodeBlockID, BlockData> blocks = new HashedMap();
+  private final Map<BlockID, String> fullBlockData = new HashMap<>();
 
   private final Map<String, ChunkInfo> chunks = new HashMap<>();
 
@@ -61,6 +63,10 @@ public class MockDatanodeStorage {
     data.put(createKey(blockID, chunkInfo),
         ByteString.copyFrom(bytes.toByteArray()));
     chunks.put(createKey(blockID, chunkInfo), chunkInfo);
+    fullBlockData
+        .put(new BlockID(blockID.getContainerID(), blockID.getLocalID()),
+            fullBlockData.getOrDefault(blockID, "")
+                .concat(bytes.toStringUtf8()));
   }
 
   public ChunkInfo readChunkInfo(
@@ -85,4 +91,8 @@ public class MockDatanodeStorage {
     return this.data;
   }
 
+  public String getFullBlockData(BlockID blockID) {
+    return this.fullBlockData.get(blockID);
+  }
+
 }
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 2804199..c2a9c71 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
@@ -20,6 +20,7 @@ package org.apache.hadoop.ozone.client;
 
 import org.apache.commons.lang3.NotImplementedException;
 import org.apache.hadoop.conf.StorageUnit;
+import org.apache.hadoop.hdds.client.BlockID;
 import org.apache.hadoop.hdds.client.DefaultReplicationConfig;
 import org.apache.hadoop.hdds.client.ECReplicationConfig;
 import org.apache.hadoop.hdds.client.ReplicationType;
@@ -49,6 +50,7 @@ import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
@@ -283,6 +285,78 @@ public class TestOzoneECClient {
   }
 
   @Test
+  public void testSmallerThanChunkSize() throws IOException {
+    byte[] firstSmallChunk = new byte[chunkSize - 1];
+    Arrays.fill(firstSmallChunk, 0, firstSmallChunk.length - 1,
+        Byte.parseByte("1"));
+
+    writeIntoECKey(firstSmallChunk, keyName,
+        new DefaultReplicationConfig(ReplicationType.EC,
+            new ECReplicationConfig(dataBlocks, parityBlocks,
+                ECReplicationConfig.EcCodec.RS, chunkSize)));
+    OzoneManagerProtocolProtos.KeyLocationList blockList =
+        transportStub.getKeys().get(volumeName).get(bucketName).get(keyName)
+            .getKeyLocationListList().get(0);
+
+    Map<DatanodeDetails, MockDatanodeStorage> storages =
+        ((MockXceiverClientFactory) factoryStub).getStorages();
+    OzoneManagerProtocolProtos.KeyLocation keyLocations =
+        blockList.getKeyLocations(0);
+
+    List<MockDatanodeStorage> dns = new ArrayList<>();
+    for (int i = 0; i < dataBlocks + parityBlocks; i++) {
+      HddsProtos.DatanodeDetailsProto member =
+          blockList.getKeyLocations(0).getPipeline().getMembers(i);
+      MockDatanodeStorage mockDatanodeStorage =
+          storages.get(getMatchingStorage(storages, member.getUuid()));
+      dns.add(mockDatanodeStorage);
+    }
+    String firstBlockData = dns.get(0).getFullBlockData(new BlockID(
+        keyLocations.getBlockID().getContainerBlockID().getContainerID(),
+        keyLocations.getBlockID().getContainerBlockID().getLocalID()));
+
+    Assert.assertArrayEquals(firstSmallChunk, firstBlockData.getBytes(UTF_8));
+
+    final ByteBuffer[] dataBuffers = new ByteBuffer[dataBlocks];
+    dataBuffers[0] = ByteBuffer.wrap(firstSmallChunk);
+    //Let's pad the remaining length equal to firstSmall chunk len
+    for (int i = 1; i < dataBlocks; i++) {
+      dataBuffers[i] = ByteBuffer.allocate(firstSmallChunk.length);
+      Arrays.fill(dataBuffers[i].array(), 0, firstSmallChunk.length, (byte) 0);
+    }
+
+    final ByteBuffer[] parityBuffers = new ByteBuffer[parityBlocks];
+    for (int i = 0; i < parityBlocks; i++) {
+      parityBuffers[i] = ByteBuffer.allocate(firstSmallChunk.length);
+    }
+    encoder.encode(dataBuffers, parityBuffers);
+
+    //Lets assert the parity data.
+    for (int i = dataBlocks; i < dataBlocks + parityBlocks; i++) {
+      String parityBlockData = dns.get(i).getFullBlockData(new BlockID(
+          keyLocations.getBlockID().getContainerBlockID().getContainerID(),
+          keyLocations.getBlockID().getContainerBlockID().getLocalID()));
+      String expected =
+          new String(parityBuffers[i - dataBlocks].array(), UTF_8);
+      Assert.assertEquals(expected, parityBlockData);
+      Assert.assertEquals(expected.length(), parityBlockData.length());
+
+    }
+  }
+
+  private static DatanodeDetails getMatchingStorage(
+      Map<DatanodeDetails, MockDatanodeStorage> storages, String uuid) {
+    Iterator<DatanodeDetails> iterator = storages.keySet().iterator();
+    while (iterator.hasNext()) {
+      DatanodeDetails dn = iterator.next();
+      if (dn.getUuid().toString().equals(uuid)) {
+        return dn;
+      }
+    }
+    return null;
+  }
+
+  @Test
   public void testMultipleChunksWithPartialChunkInSingleWriteOp()
       throws IOException {
     final int partialChunkLen = 10;

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

Reply via email to