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

erose pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 111161d782 HDDS-8142. Check if no entries in Block DB for a container 
on container delete (#4379)
111161d782 is described below

commit 111161d78253e2afe920b14d2a14be282ea57e90
Author: Ritesh H Shukla <[email protected]>
AuthorDate: Sat Mar 11 17:08:46 2023 -0800

    HDDS-8142. Check if no entries in Block DB for a container on container 
delete (#4379)
---
 .../container/common/helpers/ContainerMetrics.java |   9 +
 .../ozone/container/keyvalue/KeyValueHandler.java  | 132 +++++++++++---
 .../commandhandler/TestDeleteContainerHandler.java | 190 ++++++++++++++++++++-
 3 files changed, 308 insertions(+), 23 deletions(-)

diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerMetrics.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerMetrics.java
index e77b0031b9..e717da65ff 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerMetrics.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/helpers/ContainerMetrics.java
@@ -52,6 +52,7 @@ public class ContainerMetrics {
   @Metric private MutableCounterLong containerDeleteFailedNonEmptyDir;
   @Metric private MutableCounterLong containerDeleteFailedBlockCountNotZero;
   @Metric private MutableCounterLong containerForceDelete;
+  @Metric private MutableCounterLong containerDeleteFailedNonEmptyBlockDB;
 
   private MutableCounterLong[] numOpsArray;
   private MutableCounterLong[] opsBytesArray;
@@ -152,4 +153,12 @@ public class ContainerMetrics {
   public long getContainerForceDelete() {
     return containerForceDelete.value();
   }
+
+  public void incContainerDeleteFailedNonEmptyBlocksDB() {
+    containerDeleteFailedNonEmptyBlockDB.incr();
+  }
+
+  public long getContainerDeleteFailedNonEmptyBlockDB() {
+    return containerDeleteFailedNonEmptyBlockDB.value();
+  }
 }
diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java
index e3396a1755..c50e9bf67f 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java
@@ -24,6 +24,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -42,7 +45,6 @@ import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos;
 import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandRequestProto;
 import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerCommandResponseProto;
 import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerDataProto.State;
-import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerType;
 import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.GetSmallFileRequestProto;
 import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.KeyValue;
 import 
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.PutSmallFileRequestProto;
@@ -64,7 +66,9 @@ import 
org.apache.hadoop.ozone.container.common.helpers.ContainerUtils;
 import org.apache.hadoop.ozone.container.common.impl.ContainerLayoutVersion;
 import org.apache.hadoop.ozone.container.common.impl.ContainerData;
 import org.apache.hadoop.ozone.container.common.impl.ContainerSet;
+import org.apache.hadoop.ozone.container.common.interfaces.BlockIterator;
 import org.apache.hadoop.ozone.container.common.interfaces.Container;
+import org.apache.hadoop.ozone.container.common.interfaces.DBHandle;
 import org.apache.hadoop.ozone.container.common.interfaces.Handler;
 import 
org.apache.hadoop.ozone.container.common.interfaces.VolumeChoosingPolicy;
 import org.apache.hadoop.ozone.container.common.report.IncrementalReportSender;
@@ -124,14 +128,13 @@ public class KeyValueHandler extends Handler {
   private static final Logger LOG = LoggerFactory.getLogger(
       KeyValueHandler.class);
 
-  private final ContainerType containerType;
   private final BlockManager blockManager;
   private final ChunkManager chunkManager;
   private final VolumeChoosingPolicy volumeChoosingPolicy;
   private final long maxContainerSize;
   private final Function<ByteBuffer, ByteString> byteBufferToByteString;
   private final boolean validateChunkChecksumData;
-  private boolean checkIfNoBlockFiles;
+  private final boolean checkIfNoBlockFiles;
 
   // A striped lock that is held during container creation.
   private final Striped<Lock> containerCreationLocks;
@@ -143,7 +146,6 @@ public class KeyValueHandler extends Handler {
                          ContainerMetrics metrics,
                          IncrementalReportSender<Container> icrSender) {
     super(config, datanodeId, contSet, volSet, metrics, icrSender);
-    containerType = ContainerType.KeyValueContainer;
     blockManager = new BlockManagerImpl(config);
     validateChunkChecksumData = conf.getObject(
         DatanodeConfiguration.class).isChunkDataValidationCheck();
@@ -398,11 +400,10 @@ public class KeyValueHandler extends Handler {
   private void populateContainerPathFields(KeyValueContainer container,
       HddsVolume hddsVolume) throws IOException {
     volumeSet.readLock();
-    HddsVolume containerVolume = hddsVolume;
     try {
       String idDir = VersionedDatanodeFeatures.ScmHA.chooseContainerPathID(
-              containerVolume, clusterId);
-      container.populatePathFields(idDir, containerVolume);
+          hddsVolume, clusterId);
+      container.populatePathFields(idDir, hddsVolume);
     } finally {
       volumeSet.readUnlock();
     }
@@ -659,8 +660,8 @@ public class KeyValueHandler extends Handler {
       }
       List<BlockData> responseData =
           blockManager.listBlock(kvContainer, startLocalId, count);
-      for (int i = 0; i < responseData.size(); i++) {
-        returnData.add(responseData.get(i).getProtoBufMessage());
+      for (BlockData responseDatum : responseData) {
+        returnData.add(responseDatum.getProtoBufMessage());
       }
     } catch (StorageContainerException ex) {
       return ContainerUtils.logAndReturnError(LOG, ex, request);
@@ -1226,11 +1227,64 @@ public class KeyValueHandler extends Handler {
     return chunkDir.list(filter);
   }
 
+  private boolean logBlocksIfNonZero(Container container)
+      throws IOException {
+    boolean nonZero = false;
+    try (DBHandle dbHandle
+             = BlockUtils.getDB(
+        (KeyValueContainerData) container.getContainerData(),
+        conf)) {
+      BlockIterator<BlockData>
+          blockIterator = dbHandle.getStore().
+          getBlockIterator(container.getContainerData().getContainerID());
+      StringBuilder stringBuilder = new StringBuilder();
+      while (blockIterator.hasNext()) {
+        nonZero = true;
+        stringBuilder.append(blockIterator.nextBlock());
+        if (stringBuilder.length() > StorageUnit.KB.toBytes(32)) {
+          break;
+        }
+      }
+      if (nonZero) {
+        LOG.error("blocks in rocksDB on container delete: {}",
+            stringBuilder.toString());
+      }
+    }
+    return nonZero;
+  }
+
+  private boolean logBlocksFoundOnDisk(Container container) throws IOException 
{
+    // List files left over
+    File chunksPath = new
+        File(container.getContainerData().getChunksPath());
+    Preconditions.checkArgument(chunksPath.isDirectory());
+    boolean notEmpty = false;
+    try (DirectoryStream<Path> dir
+             = Files.newDirectoryStream(chunksPath.toPath())) {
+      StringBuilder stringBuilder = new StringBuilder();
+      for (Path block : dir) {
+        if (notEmpty) {
+          stringBuilder.append(",");
+        }
+        stringBuilder.append(block);
+        notEmpty = true;
+        if (stringBuilder.length() > StorageUnit.KB.toBytes(16)) {
+          break;
+        }
+      }
+      if (notEmpty) {
+        LOG.error("Files still part of the container on delete: {}",
+            stringBuilder.toString());
+      }
+    }
+    return notEmpty;
+  }
+
   private void deleteInternal(Container container, boolean force)
       throws StorageContainerException {
     container.writeLock();
     try {
-    // If force is false, we check container state.
+      // If force is false, we check container state.
       if (!force) {
         // Check if container is open
         if (container.getContainerData().isOpen()) {
@@ -1245,7 +1299,7 @@ public class KeyValueHandler extends Handler {
         if (container.getContainerData().getBlockCount() != 0) {
           metrics.incContainerDeleteFailedBlockCountNotZero();
           LOG.error("Received container deletion command for container {} but" 
+
-              " the container is not empty with blockCount {}",
+                  " the container is not empty with blockCount {}",
               container.getContainerData().getContainerID(),
               container.getContainerData().getBlockCount());
           throw new StorageContainerException("Non-force deletion of " +
@@ -1253,16 +1307,52 @@ public class KeyValueHandler extends Handler {
               DELETE_ON_NON_EMPTY_CONTAINER);
         }
 
-        if (checkIfNoBlockFiles && !container.isEmpty()) {
-          metrics.incContainerDeleteFailedNonEmpty();
-          LOG.error("Received container deletion command for container {} but" 
+
-                  " the container is not empty",
-              container.getContainerData().getContainerID());
-          throw new StorageContainerException("Non-force deletion of " +
-              "non-empty container:" +
-              container.getContainerData().getContainerID() +
-              " is not allowed.",
-              DELETE_ON_NON_EMPTY_CONTAINER);
+        // This is a defensive check to make sure there is no data loss if
+        // 1. There are one or more blocks on the filesystem
+        // 2. There are one or more blocks in the block table
+        // This can lead to false positives as
+        // 1. Chunks written to disk that did not get recorded in RocksDB can
+        //    occur due to failures during write
+        // 2. Blocks that were deleted from blocks table but the deletion of
+        //    the underlying file could not be completed
+        // 3. Failures between files being deleted from disk but not being
+        //    cleaned up.
+        // 4. Bugs in the code.
+        // Blocks stored on disk represent data written by a client and should
+        // be treated with care at the expense of creating artifacts on disk
+        // that  might be unreferenced.
+        // https://issues.apache.org/jira/browse/HDDS-8138 will move the
+        // implementation to only depend on consistency of the chunks folder
+
+        // First check if any files are in the chunks folder. If there are
+        // to help with debugging also dump the blocks table data.
+        if (checkIfNoBlockFiles) {
+          if (!container.isEmpty()) {
+            metrics.incContainerDeleteFailedNonEmpty();
+            logBlocksFoundOnDisk(container);
+            logBlocksIfNonZero(container);
+            // List Blocks from Blocks Table
+            throw new StorageContainerException("Non-force deletion of " +
+                "non-empty container dir:" +
+                container.getContainerData().getContainerID() +
+                " is not allowed.",
+                DELETE_ON_NON_EMPTY_CONTAINER);
+          }
+
+          // The chunks folder is empty, not check if the blocks table has any
+          // blocks still referenced. This will avoid cleaning up the
+          // blocks table for future debugging.
+          // List rocks
+          if (logBlocksIfNonZero(container)) {
+            LOG.error("Non-empty blocks table for container {}",
+                container.getContainerData().getContainerID());
+            metrics.incContainerDeleteFailedNonEmptyBlocksDB();
+            throw new StorageContainerException("Non-force deletion of " +
+                "non-empty container block table:" +
+                container.getContainerData().getContainerID() +
+                " is not allowed.",
+                DELETE_ON_NON_EMPTY_CONTAINER);
+          }
         }
       } else {
         metrics.incContainersForceDelete();
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/TestDeleteContainerHandler.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/TestDeleteContainerHandler.java
index 2b319365aa..282c4e7f14 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/TestDeleteContainerHandler.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/container/common/statemachine/commandhandler/TestDeleteContainerHandler.java
@@ -19,6 +19,7 @@ package 
org.apache.hadoop.ozone.container.common.statemachine.commandhandler;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.hadoop.hdds.HddsConfigKeys;
+import org.apache.hadoop.hdds.client.BlockID;
 import org.apache.hadoop.hdds.client.ReplicationFactor;
 import org.apache.hadoop.hdds.client.ReplicationType;
 import org.apache.hadoop.hdds.client.StandaloneReplicationConfig;
@@ -29,16 +30,22 @@ import org.apache.hadoop.hdds.scm.container.ContainerID;
 import org.apache.hadoop.hdds.scm.container.ContainerInfo;
 import org.apache.hadoop.hdds.scm.node.NodeManager;
 import org.apache.hadoop.hdds.scm.pipeline.Pipeline;
+import org.apache.hadoop.hdds.utils.db.BatchOperation;
+import org.apache.hadoop.hdds.utils.db.Table;
 import org.apache.hadoop.ozone.HddsDatanodeService;
 import org.apache.hadoop.ozone.MiniOzoneCluster;
 import org.apache.hadoop.ozone.client.ObjectStore;
 import org.apache.hadoop.ozone.client.OzoneClient;
 import org.apache.hadoop.ozone.client.OzoneClientFactory;
 import org.apache.hadoop.ozone.client.io.OzoneOutputStream;
+import org.apache.hadoop.ozone.container.common.helpers.BlockData;
 import org.apache.hadoop.ozone.container.common.helpers.ContainerMetrics;
 import org.apache.hadoop.ozone.container.common.impl.ContainerData;
 import org.apache.hadoop.ozone.container.common.interfaces.Container;
+import org.apache.hadoop.ozone.container.common.interfaces.DBHandle;
+import org.apache.hadoop.ozone.container.keyvalue.KeyValueContainerData;
 import org.apache.hadoop.ozone.container.keyvalue.KeyValueHandler;
+import org.apache.hadoop.ozone.container.keyvalue.helpers.BlockUtils;
 import org.apache.hadoop.ozone.om.helpers.OmKeyArgs;
 import org.apache.hadoop.ozone.om.helpers.OmKeyLocationInfo;
 import org.apache.hadoop.ozone.protocol.commands.CloseContainerCommand;
@@ -53,6 +60,7 @@ import org.junit.Test;
 import java.io.File;
 import java.io.IOException;
 import java.util.HashMap;
+import java.util.List;
 import java.util.UUID;
 
 import org.junit.Rule;
@@ -194,20 +202,171 @@ public class TestDeleteContainerHandler {
         
cluster.getStorageContainerManager().getScmContext().getTermOfLeader());
     nodeManager.addDatanodeCommand(datanodeDetails.getUuid(), command);
 
+    // Check the log for the error message when deleting non-empty containers
+    GenericTestUtils.LogCapturer logCapturer =
+        GenericTestUtils.LogCapturer.captureLogs(
+            LoggerFactory.getLogger(KeyValueHandler.class));
+    GenericTestUtils.waitFor(() ->
+            logCapturer.getOutput().
+                contains("Files still part of the container on delete"),
+        500,
+        5 * 2000);
+    Assert.assertTrue(!isContainerDeleted(hddsDatanodeService,
+        containerId.getId()));
+    Assert.assertEquals(1,
+        metrics.getContainerDeleteFailedNonEmptyDir());
+    // Send the delete command. It should pass with force flag.
     // Deleting a non-empty container should pass on the DN when the force flag
     // is true
+    long beforeForceCount = metrics.getContainerForceDelete();
+    command = new DeleteContainerCommand(containerId.getId(), true);
+
+    command.setTerm(
+        
cluster.getStorageContainerManager().getScmContext().getTermOfLeader());
+    nodeManager.addDatanodeCommand(datanodeDetails.getUuid(), command);
+
+    GenericTestUtils.waitFor(() ->
+            isContainerDeleted(hddsDatanodeService, containerId.getId()),
+        500, 5 * 1000);
+    Assert.assertTrue(isContainerDeleted(hddsDatanodeService,
+        containerId.getId()));
+    Assert.assertTrue(beforeForceCount <
+        metrics.getContainerForceDelete());
+  }
+
+  @Test(timeout = 60000)
+  public void testDeleteNonEmptyContainerBlockTable()
+      throws Exception {
+    // 1. Test if a non force deletion fails if chunks are still present with
+    //    block count set to 0
+    // 2. Test if a force deletion passes even if chunks are still present
+    //the easiest way to create an open container is creating a key
+    String keyName = UUID.randomUUID().toString();
+    // create key
+    createKey(keyName);
+    // get containerID of the key
+    ContainerID containerId = getContainerID(keyName);
+    ContainerInfo container = cluster.getStorageContainerManager()
+        .getContainerManager().getContainer(containerId);
+    Pipeline pipeline = cluster.getStorageContainerManager()
+        .getPipelineManager().getPipeline(container.getPipelineID());
+
+    // We need to close the container because delete container only happens
+    // on closed containers when force flag is set to false.
+
+    HddsDatanodeService hddsDatanodeService =
+        cluster.getHddsDatanodes().get(0);
+
+    Assert.assertFalse(isContainerClosed(hddsDatanodeService,
+        containerId.getId()));
+
+    DatanodeDetails datanodeDetails = hddsDatanodeService.getDatanodeDetails();
+
+    NodeManager nodeManager =
+        cluster.getStorageContainerManager().getScmNodeManager();
+    //send the order to close the container
+    SCMCommand<?> command = new CloseContainerCommand(
+        containerId.getId(), pipeline.getId());
+    command.setTerm(
+        
cluster.getStorageContainerManager().getScmContext().getTermOfLeader());
+    nodeManager.addDatanodeCommand(datanodeDetails.getUuid(), command);
+
+    Container containerInternalObj =
+        hddsDatanodeService.
+            getDatanodeStateMachine().
+            getContainer().getContainerSet().getContainer(containerId.getId());
+
+    // Write a file to the container chunks directory indicating that there
+    // might be a discrepancy between block count as recorded in RocksDB and
+    // what is actually on disk.
+    File lingeringBlock =
+        new File(containerInternalObj.
+            getContainerData().getChunksPath() + "/1.block");
+    lingeringBlock.createNewFile();
+    ContainerMetrics metrics =
+        hddsDatanodeService
+            .getDatanodeStateMachine().getContainer().getMetrics();
+    GenericTestUtils.waitFor(() ->
+            isContainerClosed(hddsDatanodeService, containerId.getId()),
+        500, 5 * 1000);
+
+    //double check if it's really closed (waitFor also throws an exception)
+    Assert.assertTrue(isContainerClosed(hddsDatanodeService,
+        containerId.getId()));
+
+    // Check container exists before sending delete container command
+    Assert.assertFalse(isContainerDeleted(hddsDatanodeService,
+        containerId.getId()));
+
+    // Set container blockCount to 0 to mock that it is empty as per RocksDB
+    getContainerfromDN(hddsDatanodeService, containerId.getId())
+        .getContainerData().setBlockCount(0);
+    // Write entries to the block Table.
+    try (DBHandle dbHandle
+             = BlockUtils.getDB(
+                 (KeyValueContainerData)getContainerfromDN(hddsDatanodeService,
+                     containerId.getId()).getContainerData(),
+        conf)) {
+      BlockData blockData = new BlockData(new BlockID(1, 1));
+      dbHandle.getStore().getBlockDataTable().put("block1", blockData);
+    }
+
+    long containerDeleteFailedNonEmptyBefore =
+        metrics.getContainerDeleteFailedNonEmptyDir();
+    // send delete container to the datanode
+    command = new DeleteContainerCommand(containerId.getId(), false);
+
+    // Send the delete command. It should fail as even though block count
+    // is zero there is a lingering block on disk.
+    command.setTerm(
+        
cluster.getStorageContainerManager().getScmContext().getTermOfLeader());
+    nodeManager.addDatanodeCommand(datanodeDetails.getUuid(), command);
+
+
     // Check the log for the error message when deleting non-empty containers
     GenericTestUtils.LogCapturer logCapturer =
         GenericTestUtils.LogCapturer.captureLogs(
             LoggerFactory.getLogger(KeyValueHandler.class));
     GenericTestUtils.waitFor(() ->
-            logCapturer.getOutput().contains("container is not empty"),
+            logCapturer.getOutput().
+                contains("Files still part of the container on delete"),
         500,
         5 * 2000);
     Assert.assertTrue(!isContainerDeleted(hddsDatanodeService,
         containerId.getId()));
-    Assert.assertEquals(1,
+    Assert.assertTrue(containerDeleteFailedNonEmptyBefore <
         metrics.getContainerDeleteFailedNonEmptyDir());
+
+    // Now empty the container Dir and try with a non empty block table
+    Container containerToDelete = getContainerfromDN(
+        hddsDatanodeService, containerId.getId());
+    File chunkDir = new File(containerToDelete.
+        getContainerData().getChunksPath());
+    File[] files = chunkDir.listFiles();
+    if (files != null) {
+      for (File file : files) {
+        FileUtils.delete(file);
+      }
+    }
+    command = new DeleteContainerCommand(containerId.getId(), false);
+
+    // Send the delete command. It should fail as even though block count
+    // is zero there is a lingering block on disk.
+    command.setTerm(
+        
cluster.getStorageContainerManager().getScmContext().getTermOfLeader());
+    nodeManager.addDatanodeCommand(datanodeDetails.getUuid(), command);
+
+
+    // Check the log for the error message when deleting non-empty containers
+    GenericTestUtils.waitFor(() ->
+            logCapturer.getOutput().
+                contains("Non-empty blocks table for container"),
+        500,
+        5 * 2000);
+    Assert.assertTrue(!isContainerDeleted(hddsDatanodeService,
+        containerId.getId()));
+    Assert.assertEquals(1,
+        metrics.getContainerDeleteFailedNonEmptyBlockDB());
     // Send the delete command. It should pass with force flag.
     long beforeForceCount = metrics.getContainerForceDelete();
     command = new DeleteContainerCommand(containerId.getId(), true);
@@ -225,6 +384,31 @@ public class TestDeleteContainerHandler {
         metrics.getContainerForceDelete());
   }
 
+  private void clearBlocksTable(Container container) throws IOException {
+    try (DBHandle dbHandle
+             = BlockUtils.getDB(
+        (KeyValueContainerData) container.getContainerData(),
+        conf)) {
+      List<? extends Table.KeyValue<String, BlockData>>
+          blocks = dbHandle.getStore().getBlockDataTable().getRangeKVs(
+          ((KeyValueContainerData) container.getContainerData()).
+              startKeyEmpty(),
+          Integer.MAX_VALUE,
+          ((KeyValueContainerData) container.getContainerData()).
+              containerPrefix(),
+          ((KeyValueContainerData) container.getContainerData()).
+              getUnprefixedKeyFilter());
+      try (BatchOperation batch = dbHandle.getStore().getBatchHandler()
+          .initBatchOperation()) {
+        for (Table.KeyValue<String, BlockData> kv : blocks) {
+          String blk = kv.getKey();
+          dbHandle.getStore().getBlockDataTable().deleteWithBatch(batch, blk);
+        }
+        dbHandle.getStore().getBatchHandler().commitBatchOperation(batch);
+      }
+    }
+  }
+
   @Test(timeout = 60000)
   public void testDeleteContainerRequestHandlerOnClosedContainer()
       throws Exception {
@@ -310,6 +494,8 @@ public class TestDeleteContainerHandler {
         FileUtils.delete(file);
       }
     }
+    clearBlocksTable(containerToDelete);
+
     // Send the delete command again. It should succeed this time.
     command.setTerm(
         
cluster.getStorageContainerManager().getScmContext().getTermOfLeader());


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

Reply via email to