errose28 commented on code in PR #7293:
URL: https://github.com/apache/ozone/pull/7293#discussion_r1803456094


##########
hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/checksum/ContainerChecksumTreeManager.java:
##########
@@ -143,12 +148,81 @@ public void markBlocksAsDeleted(KeyValueContainerData 
data, Collection<Long> del
     }
   }
 
-  public ContainerDiff diff(KeyValueContainerData thisContainer, 
ContainerProtos.ContainerChecksumInfo otherInfo)
+  public ContainerDiff diff(KeyValueContainerData thisContainer, 
ContainerProtos.ContainerChecksumInfo peerChecksumInfo)
       throws IOException {
-    // TODO HDDS-10928 compare the checksum info of the two containers and 
return a summary.
-    //  Callers can act on this summary to repair their container replica 
using the peer's replica.
-    //  This method will use the read lock, which is unused in the current 
implementation.
-    return new ContainerDiff();
+    Preconditions.assertNotNull(thisContainer, "Container data is null");
+    Optional<ContainerProtos.ContainerChecksumInfo.Builder> 
thisContainerChecksumInfoBuilder =
+        read(thisContainer);
+    if (!thisContainerChecksumInfoBuilder.isPresent()) {
+      // TODO: To create containerMerkleTree or fail the request.

Review Comment:
   IMO we should fail the request for the caller and queue the container for 
on-demand scanning.



##########
hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/checksum/ContainerChecksumTreeManager.java:
##########
@@ -143,12 +148,81 @@ public void markBlocksAsDeleted(KeyValueContainerData 
data, Collection<Long> del
     }
   }
 
-  public ContainerDiff diff(KeyValueContainerData thisContainer, 
ContainerProtos.ContainerChecksumInfo otherInfo)
+  public ContainerDiff diff(KeyValueContainerData thisContainer, 
ContainerProtos.ContainerChecksumInfo peerChecksumInfo)
       throws IOException {
-    // TODO HDDS-10928 compare the checksum info of the two containers and 
return a summary.
-    //  Callers can act on this summary to repair their container replica 
using the peer's replica.
-    //  This method will use the read lock, which is unused in the current 
implementation.
-    return new ContainerDiff();
+    Preconditions.assertNotNull(thisContainer, "Container data is null");
+    Optional<ContainerProtos.ContainerChecksumInfo.Builder> 
thisContainerChecksumInfoBuilder =
+        read(thisContainer);
+    if (!thisContainerChecksumInfoBuilder.isPresent()) {
+      // TODO: To create containerMerkleTree or fail the request.
+      return null;
+    }
+
+    if (thisContainer.getContainerID() != peerChecksumInfo.getContainerID()) {
+      throw new IOException("Container Id does not match");
+    }
+
+    ContainerProtos.ContainerChecksumInfo thisChecksumInfo = 
thisContainerChecksumInfoBuilder.get().build();
+
+    ContainerProtos.ContainerMerkleTree thisMerkleTree = 
thisChecksumInfo.getContainerMerkleTree();
+    ContainerProtos.ContainerMerkleTree peerMerkleTree = 
peerChecksumInfo.getContainerMerkleTree();
+
+    return compareContainerMerkleTree(thisMerkleTree, peerMerkleTree);

Review Comment:
   Each tree diff should have a one line info log summarizing what happened. 
For example, whether containers matched and how many of each type of difference 
were found. This info can come from a `toString` implementation in the 
`ContainerDiff` and we can just log that object. We might want to add this to 
the caller of this method though, since they will have the peer information. I 
think the current plan is that will happen in a follow-up PR.



##########
hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/checksum/ContainerChecksumTreeManager.java:
##########
@@ -143,12 +148,81 @@ public void markBlocksAsDeleted(KeyValueContainerData 
data, Collection<Long> del
     }
   }
 
-  public ContainerDiff diff(KeyValueContainerData thisContainer, 
ContainerProtos.ContainerChecksumInfo otherInfo)
+  public ContainerDiff diff(KeyValueContainerData thisContainer, 
ContainerProtos.ContainerChecksumInfo peerChecksumInfo)
       throws IOException {
-    // TODO HDDS-10928 compare the checksum info of the two containers and 
return a summary.
-    //  Callers can act on this summary to repair their container replica 
using the peer's replica.
-    //  This method will use the read lock, which is unused in the current 
implementation.
-    return new ContainerDiff();
+    Preconditions.assertNotNull(thisContainer, "Container data is null");
+    Optional<ContainerProtos.ContainerChecksumInfo.Builder> 
thisContainerChecksumInfoBuilder =
+        read(thisContainer);
+    if (!thisContainerChecksumInfoBuilder.isPresent()) {
+      // TODO: To create containerMerkleTree or fail the request.
+      return null;
+    }
+
+    if (thisContainer.getContainerID() != peerChecksumInfo.getContainerID()) {
+      throw new IOException("Container Id does not match");
+    }
+
+    ContainerProtos.ContainerChecksumInfo thisChecksumInfo = 
thisContainerChecksumInfoBuilder.get().build();
+
+    ContainerProtos.ContainerMerkleTree thisMerkleTree = 
thisChecksumInfo.getContainerMerkleTree();
+    ContainerProtos.ContainerMerkleTree peerMerkleTree = 
peerChecksumInfo.getContainerMerkleTree();
+
+    return compareContainerMerkleTree(thisMerkleTree, peerMerkleTree);
+  }
+
+  private ContainerDiff 
compareContainerMerkleTree(ContainerProtos.ContainerMerkleTree thisMerkleTree,
+                                                   
ContainerProtos.ContainerMerkleTree peerMerkleTree) {
+
+    ContainerDiff report = new ContainerDiff();

Review Comment:
   nit. We can intern the healthy/empty `ContainerDiff` object since they will 
all be identical.



##########
hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/checksum/TestContainerChecksumTreeManager.java:
##########
@@ -299,6 +301,86 @@ public void testEmptyFile() throws Exception {
     assertEquals(CONTAINER_ID, info.getContainerID());
   }
 
+  @Test
+  public void testContainerWithNoDiff() throws IOException {
+    ContainerMerkleTree ourMerkleTree = buildTestTree(config);
+    ContainerMerkleTree peerMerkleTree = buildTestTree(config);
+    checksumManager.writeContainerDataTree(container, ourMerkleTree);
+    ContainerChecksumTreeManager containerChecksumTreeManager = new 
ContainerChecksumTreeManager(
+        new OzoneConfiguration());
+    ContainerProtos.ContainerChecksumInfo peerChecksumInfo = 
ContainerProtos.ContainerChecksumInfo.newBuilder()
+            .setContainerID(container.getContainerID())
+            .setContainerMerkleTree(peerMerkleTree.toProto()).build();
+    ContainerChecksumTreeManager.ContainerDiff diff =
+        containerChecksumTreeManager.diff(container, peerChecksumInfo);
+    Assertions.assertTrue(diff.getCorruptChunks().isEmpty());
+    Assertions.assertTrue(diff.getMissingBlocks().isEmpty());
+    Assertions.assertTrue(diff.getMissingChunks().isEmpty());

Review Comment:
   We can wrap these in one method to quickly check if we need to drill down 
into the diff. Something like `ContainerDiff#isHealthy`.



##########
hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/checksum/ContainerChecksumTreeManager.java:
##########
@@ -143,12 +148,81 @@ public void markBlocksAsDeleted(KeyValueContainerData 
data, Collection<Long> del
     }
   }
 
-  public ContainerDiff diff(KeyValueContainerData thisContainer, 
ContainerProtos.ContainerChecksumInfo otherInfo)
+  public ContainerDiff diff(KeyValueContainerData thisContainer, 
ContainerProtos.ContainerChecksumInfo peerChecksumInfo)
       throws IOException {
-    // TODO HDDS-10928 compare the checksum info of the two containers and 
return a summary.
-    //  Callers can act on this summary to repair their container replica 
using the peer's replica.
-    //  This method will use the read lock, which is unused in the current 
implementation.
-    return new ContainerDiff();
+    Preconditions.assertNotNull(thisContainer, "Container data is null");
+    Optional<ContainerProtos.ContainerChecksumInfo.Builder> 
thisContainerChecksumInfoBuilder =
+        read(thisContainer);
+    if (!thisContainerChecksumInfoBuilder.isPresent()) {
+      // TODO: To create containerMerkleTree or fail the request.
+      return null;
+    }
+
+    if (thisContainer.getContainerID() != peerChecksumInfo.getContainerID()) {
+      throw new IOException("Container Id does not match");
+    }
+
+    ContainerProtos.ContainerChecksumInfo thisChecksumInfo = 
thisContainerChecksumInfoBuilder.get().build();
+
+    ContainerProtos.ContainerMerkleTree thisMerkleTree = 
thisChecksumInfo.getContainerMerkleTree();
+    ContainerProtos.ContainerMerkleTree peerMerkleTree = 
peerChecksumInfo.getContainerMerkleTree();
+
+    return compareContainerMerkleTree(thisMerkleTree, peerMerkleTree);
+  }
+
+  private ContainerDiff 
compareContainerMerkleTree(ContainerProtos.ContainerMerkleTree thisMerkleTree,
+                                                   
ContainerProtos.ContainerMerkleTree peerMerkleTree) {
+
+    ContainerDiff report = new ContainerDiff();
+    if (thisMerkleTree.getDataChecksum() == peerMerkleTree.getDataChecksum()) {
+      return new ContainerDiff();
+    }
+
+    Map<Long, ContainerProtos.BlockMerkleTree> thisBlockMerkleTreeMap = 
thisMerkleTree.getBlockMerkleTreeList()
+        
.stream().collect(Collectors.toMap(ContainerProtos.BlockMerkleTree::getBlockID,
+            blockMerkleTree -> blockMerkleTree));
+
+    // Since we are reconciling our container with a peer, We only need to go 
through the peer's block list
+    for (ContainerProtos.BlockMerkleTree peerBlockMerkleTree: 
peerMerkleTree.getBlockMerkleTreeList()) {
+      // Check if our container has the peer block.
+      ContainerProtos.BlockMerkleTree thisBlockMerkleTree = 
thisBlockMerkleTreeMap.get(
+          peerBlockMerkleTree.getBlockID());
+      if (thisBlockMerkleTree == null) {
+        report.addMissingBlock(peerBlockMerkleTree);
+        continue;
+      }
+
+      if (thisBlockMerkleTree.getBlockChecksum() != 
peerBlockMerkleTree.getBlockChecksum()) {
+        compareBlockMerkleTree(report, thisBlockMerkleTree, 
peerBlockMerkleTree);
+      }
+    }
+    return report;
+  }
+
+  private void compareBlockMerkleTree(ContainerDiff report, 
ContainerProtos.BlockMerkleTree thisBlockMerkleTree,
+                                      ContainerProtos.BlockMerkleTree 
peerBlockMerkleTree) {
+    Map<Long, ContainerProtos.ChunkMerkleTree> thisChunkMerkleTreeMap = 
thisBlockMerkleTree.getChunkMerkleTreeList()
+        
.stream().collect(Collectors.toMap(ContainerProtos.ChunkMerkleTree::getOffset,
+            chunkMerkleTree -> chunkMerkleTree));
+    List<ContainerProtos.ChunkMerkleTree> peerChunkMerkleTreeList = 
peerBlockMerkleTree.getChunkMerkleTreeList();
+
+    // Since we are reconciling our container with a peer, We only need to go 
through the peer's chunk list
+    for (ContainerProtos.ChunkMerkleTree peerChunkMerkleTree: 
peerChunkMerkleTreeList) {
+      ContainerProtos.ChunkMerkleTree thisChunkMerkleTree = 
thisChunkMerkleTreeMap.get(
+          peerChunkMerkleTree.getOffset());
+      if (thisChunkMerkleTree == null) {
+        report.addMissingChunk(peerChunkMerkleTree);
+        continue;
+      }
+
+      if (thisChunkMerkleTree.getChunkChecksum() != 
peerChunkMerkleTree.getChunkChecksum()) {
+        ChunkArgs thisChunkArgs = new 
ChunkArgs(thisBlockMerkleTree.getBlockID(), thisChunkMerkleTree.getOffset(),
+            thisChunkMerkleTree.getLength(), 
thisChunkMerkleTree.getChunkChecksum());
+        ChunkArgs peerChunkArgs = new 
ChunkArgs(peerBlockMerkleTree.getBlockID(), peerChunkMerkleTree.getOffset(),
+            peerChunkMerkleTree.getLength(), 
peerChunkMerkleTree.getChunkChecksum());
+        report.addCorruptChunks(Pair.of(thisChunkArgs, peerChunkArgs));

Review Comment:
   Why do we need both our and the peer's chunks? The most granular repair we 
are doing is at the chunk level, so we should be able to read the peer's whole 
chunk from just the block ID and chunk merkle tree.



##########
hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/checksum/ContainerChecksumTreeManager.java:
##########
@@ -143,12 +148,81 @@ public void markBlocksAsDeleted(KeyValueContainerData 
data, Collection<Long> del
     }
   }
 
-  public ContainerDiff diff(KeyValueContainerData thisContainer, 
ContainerProtos.ContainerChecksumInfo otherInfo)
+  public ContainerDiff diff(KeyValueContainerData thisContainer, 
ContainerProtos.ContainerChecksumInfo peerChecksumInfo)

Review Comment:
   Can we add diff time to `ContainerMerkleTreeMetrics` as well?



##########
hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/checksum/TestContainerChecksumTreeManager.java:
##########
@@ -299,6 +301,86 @@ public void testEmptyFile() throws Exception {
     assertEquals(CONTAINER_ID, info.getContainerID());
   }
 
+  @Test
+  public void testContainerWithNoDiff() throws IOException {
+    ContainerMerkleTree ourMerkleTree = buildTestTree(config);
+    ContainerMerkleTree peerMerkleTree = buildTestTree(config);
+    checksumManager.writeContainerDataTree(container, ourMerkleTree);
+    ContainerChecksumTreeManager containerChecksumTreeManager = new 
ContainerChecksumTreeManager(
+        new OzoneConfiguration());
+    ContainerProtos.ContainerChecksumInfo peerChecksumInfo = 
ContainerProtos.ContainerChecksumInfo.newBuilder()
+            .setContainerID(container.getContainerID())
+            .setContainerMerkleTree(peerMerkleTree.toProto()).build();
+    ContainerChecksumTreeManager.ContainerDiff diff =
+        containerChecksumTreeManager.diff(container, peerChecksumInfo);
+    Assertions.assertTrue(diff.getCorruptChunks().isEmpty());
+    Assertions.assertTrue(diff.getMissingBlocks().isEmpty());
+    Assertions.assertTrue(diff.getMissingChunks().isEmpty());
+  }
+
+  @Test
+  public void testContainerDiffWithMissingBlocksAndChunks() throws IOException 
{
+    ContainerMerkleTree ourMerkleTree = buildTestTreeWithMismatches(config, 
true, true, false);
+    ContainerMerkleTree peerMerkleTree = buildTestTree(config);
+    checksumManager.writeContainerDataTree(container, ourMerkleTree);
+    ContainerChecksumTreeManager containerChecksumTreeManager = new 
ContainerChecksumTreeManager(
+        new OzoneConfiguration());
+    ContainerProtos.ContainerChecksumInfo peerChecksumInfo = 
ContainerProtos.ContainerChecksumInfo.newBuilder()
+        .setContainerID(container.getContainerID())
+        .setContainerMerkleTree(peerMerkleTree.toProto()).build();
+    ContainerChecksumTreeManager.ContainerDiff diff =
+        containerChecksumTreeManager.diff(container, peerChecksumInfo);
+    Assertions.assertTrue(diff.getCorruptChunks().isEmpty());
+    Assertions.assertFalse(diff.getMissingBlocks().isEmpty());
+    Assertions.assertFalse(diff.getMissingChunks().isEmpty());
+
+    Assertions.assertEquals(diff.getMissingBlocks().size(), 1);
+    Assertions.assertEquals(diff.getMissingChunks().size(), 1);
+  }
+
+  @Test
+  public void testContainerDiffWithMissingBlocksAndMismatchChunks() throws 
IOException {
+    ContainerMerkleTree ourMerkleTree = buildTestTreeWithMismatches(config, 
true, false, true);
+    ContainerMerkleTree peerMerkleTree = buildTestTree(config);
+    checksumManager.writeContainerDataTree(container, ourMerkleTree);
+    ContainerChecksumTreeManager containerChecksumTreeManager = new 
ContainerChecksumTreeManager(
+        new OzoneConfiguration());
+    ContainerProtos.ContainerChecksumInfo peerChecksumInfo = 
ContainerProtos.ContainerChecksumInfo.newBuilder()
+        .setContainerID(container.getContainerID())
+        .setContainerMerkleTree(peerMerkleTree.toProto()).build();
+    ContainerChecksumTreeManager.ContainerDiff diff =
+        containerChecksumTreeManager.diff(container, peerChecksumInfo);
+    Assertions.assertFalse(diff.getCorruptChunks().isEmpty());
+    Assertions.assertFalse(diff.getMissingBlocks().isEmpty());
+    Assertions.assertTrue(diff.getMissingChunks().isEmpty());
+
+    Assertions.assertEquals(diff.getCorruptChunks().size(), 1);
+    Assertions.assertEquals(diff.getMissingBlocks().size(), 1);
+  }
+
+  /**
+   * Test if a peer which has missing blocks and chunks affects our container 
diff.
+   * Only if our merkle tree has missing entries from the peer we need to add 
it the Container Diff.
+   */
+  @Test
+  public void testPeerWithMissingBlockAndMissingChunks() throws IOException {

Review Comment:
   Here's some high level ideas for test improvements:
   - `buildTestTreeWithMismatches` can take counters for the number of each 
type of failure to inject, instead of just a boolean.
   - The test can be parameterized because each input maps to the result of the 
list we check at the end. This way we can quickly check many different 
combinations of diffs.
   - `buildTestTreeWithMismatches` can also return the expected 
`ContainerDiff`. Then add an `equals` method to `ContainerDiff` that checks 
IDs, offsets, etc and just assert that is true at the end of the test.
   - A second test runs the same combinations in reverse, with the failures 
happening in the peer's tree. The difference is that this one always asserts 
our tree is healthy.
   
   I think this would distill most of this into just two small parameterized 
tests. We may need a third case to test when both trees have failures. On top 
of this we should add tests for all exceptional cases.



##########
hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/checksum/ContainerChecksumTreeManager.java:
##########
@@ -143,12 +148,81 @@ public void markBlocksAsDeleted(KeyValueContainerData 
data, Collection<Long> del
     }
   }
 
-  public ContainerDiff diff(KeyValueContainerData thisContainer, 
ContainerProtos.ContainerChecksumInfo otherInfo)
+  public ContainerDiff diff(KeyValueContainerData thisContainer, 
ContainerProtos.ContainerChecksumInfo peerChecksumInfo)
       throws IOException {
-    // TODO HDDS-10928 compare the checksum info of the two containers and 
return a summary.
-    //  Callers can act on this summary to repair their container replica 
using the peer's replica.
-    //  This method will use the read lock, which is unused in the current 
implementation.
-    return new ContainerDiff();
+    Preconditions.assertNotNull(thisContainer, "Container data is null");
+    Optional<ContainerProtos.ContainerChecksumInfo.Builder> 
thisContainerChecksumInfoBuilder =
+        read(thisContainer);
+    if (!thisContainerChecksumInfoBuilder.isPresent()) {
+      // TODO: To create containerMerkleTree or fail the request.
+      return null;
+    }
+
+    if (thisContainer.getContainerID() != peerChecksumInfo.getContainerID()) {
+      throw new IOException("Container Id does not match");
+    }
+
+    ContainerProtos.ContainerChecksumInfo thisChecksumInfo = 
thisContainerChecksumInfoBuilder.get().build();
+
+    ContainerProtos.ContainerMerkleTree thisMerkleTree = 
thisChecksumInfo.getContainerMerkleTree();
+    ContainerProtos.ContainerMerkleTree peerMerkleTree = 
peerChecksumInfo.getContainerMerkleTree();
+
+    return compareContainerMerkleTree(thisMerkleTree, peerMerkleTree);
+  }
+
+  private ContainerDiff 
compareContainerMerkleTree(ContainerProtos.ContainerMerkleTree thisMerkleTree,
+                                                   
ContainerProtos.ContainerMerkleTree peerMerkleTree) {
+
+    ContainerDiff report = new ContainerDiff();
+    if (thisMerkleTree.getDataChecksum() == peerMerkleTree.getDataChecksum()) {
+      return new ContainerDiff();
+    }
+
+    Map<Long, ContainerProtos.BlockMerkleTree> thisBlockMerkleTreeMap = 
thisMerkleTree.getBlockMerkleTreeList()

Review Comment:
   Since both lists are sorted I think we should just walk each one with a 
pointer and compare the block IDs or chunk offsets (whichever is used to sort 
for the current structure):
   1. Start one pointer at the beginning of each list.
   2. If the sorting values match and the checksums match, move both pointers 
forward.
   3. If the sorting values match but the checksums don't match, continue down 
to the chunk level.
   4. If the value of our tree is less, keep moving our pointer forward until 
it is equal or past the peer.
       - These are blocks we have but the peer does not. No action is required 
from our side.
   5. If the value of the peer's tree is less, keep moving the peer pointer 
forward until is equal or past our current value.
       - These are blocks that the peer has but we do not. We should mark them 
as missing.



##########
hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/checksum/ContainerChecksumTreeManager.java:
##########
@@ -143,12 +148,81 @@ public void markBlocksAsDeleted(KeyValueContainerData 
data, Collection<Long> del
     }
   }
 
-  public ContainerDiff diff(KeyValueContainerData thisContainer, 
ContainerProtos.ContainerChecksumInfo otherInfo)
+  public ContainerDiff diff(KeyValueContainerData thisContainer, 
ContainerProtos.ContainerChecksumInfo peerChecksumInfo)
       throws IOException {
-    // TODO HDDS-10928 compare the checksum info of the two containers and 
return a summary.
-    //  Callers can act on this summary to repair their container replica 
using the peer's replica.
-    //  This method will use the read lock, which is unused in the current 
implementation.
-    return new ContainerDiff();
+    Preconditions.assertNotNull(thisContainer, "Container data is null");
+    Optional<ContainerProtos.ContainerChecksumInfo.Builder> 
thisContainerChecksumInfoBuilder =
+        read(thisContainer);
+    if (!thisContainerChecksumInfoBuilder.isPresent()) {
+      // TODO: To create containerMerkleTree or fail the request.
+      return null;
+    }
+
+    if (thisContainer.getContainerID() != peerChecksumInfo.getContainerID()) {
+      throw new IOException("Container Id does not match");
+    }
+
+    ContainerProtos.ContainerChecksumInfo thisChecksumInfo = 
thisContainerChecksumInfoBuilder.get().build();
+
+    ContainerProtos.ContainerMerkleTree thisMerkleTree = 
thisChecksumInfo.getContainerMerkleTree();
+    ContainerProtos.ContainerMerkleTree peerMerkleTree = 
peerChecksumInfo.getContainerMerkleTree();
+
+    return compareContainerMerkleTree(thisMerkleTree, peerMerkleTree);
+  }
+
+  private ContainerDiff 
compareContainerMerkleTree(ContainerProtos.ContainerMerkleTree thisMerkleTree,
+                                                   
ContainerProtos.ContainerMerkleTree peerMerkleTree) {
+
+    ContainerDiff report = new ContainerDiff();
+    if (thisMerkleTree.getDataChecksum() == peerMerkleTree.getDataChecksum()) {
+      return new ContainerDiff();
+    }
+
+    Map<Long, ContainerProtos.BlockMerkleTree> thisBlockMerkleTreeMap = 
thisMerkleTree.getBlockMerkleTreeList()
+        
.stream().collect(Collectors.toMap(ContainerProtos.BlockMerkleTree::getBlockID,
+            blockMerkleTree -> blockMerkleTree));
+
+    // Since we are reconciling our container with a peer, We only need to go 
through the peer's block list
+    for (ContainerProtos.BlockMerkleTree peerBlockMerkleTree: 
peerMerkleTree.getBlockMerkleTreeList()) {
+      // Check if our container has the peer block.
+      ContainerProtos.BlockMerkleTree thisBlockMerkleTree = 
thisBlockMerkleTreeMap.get(
+          peerBlockMerkleTree.getBlockID());
+      if (thisBlockMerkleTree == null) {
+        report.addMissingBlock(peerBlockMerkleTree);
+        continue;
+      }
+
+      if (thisBlockMerkleTree.getBlockChecksum() != 
peerBlockMerkleTree.getBlockChecksum()) {

Review Comment:
   More than just the checksums not matching, we need to know that our checksum 
is incorrect according to the client checksums and the peer's checksum is 
correct. There's two ways to do this:
   - When we get to the bottom of the tree, check all the checksums within the 
chunk to determine which peer is correct.
   - Add an `unhealthy` flag to each node of the tree to indicate a checksum 
mismatch was detected in its subtree. This would be filled in as part of 
HDDS-10374
   
   IMO the second option is better. We can add the `unhealthy` flag here and 
manually set it for unit testing until the scanner sets it automatically.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to