diff --git a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/pipe/PipeTaskInfoConsensusPipeTest.java b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/pipe/PipeTaskInfoConsensusPipeTest.java index 95f03683336a0..1511c76abbc43 100644 --- a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/pipe/PipeTaskInfoConsensusPipeTest.java +++ b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/pipe/PipeTaskInfoConsensusPipeTest.java @@ -25,6 +25,7 @@ import org.apache.iotdb.commons.pipe.agent.task.meta.PipeStaticMeta; import org.apache.iotdb.commons.pipe.agent.task.meta.PipeStatus; import org.apache.iotdb.commons.pipe.agent.task.meta.PipeTaskMeta; +import org.apache.iotdb.commons.utils.FileUtils; import org.apache.iotdb.confignode.consensus.request.write.pipe.task.CreatePipePlanV2; import org.apache.iotdb.confignode.consensus.request.write.pipe.task.SetPipeStatusPlanV2; import org.apache.iotdb.confignode.consensus.request.write.pipe.task.SetPipeStatusWithStoppedByRuntimeExceptionPlanV2; @@ -203,8 +204,7 @@ public void testProcessLoadSnapshotRestartsOnlyHealthyStoppedConsensusPipes() th .getStatus() .get()); } finally { - new File(snapshotDir, "pipe_task_info.bin").delete(); - snapshotDir.delete(); + FileUtils.deleteFileOrDirectory(snapshotDir, true); } } diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/pipe/agent/plugin/PipeDataNodePluginAgentTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/pipe/agent/plugin/PipeDataNodePluginAgentTest.java index b0f0b34e92a51..118ec430b9b5e 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/pipe/agent/plugin/PipeDataNodePluginAgentTest.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/pipe/agent/plugin/PipeDataNodePluginAgentTest.java @@ -30,6 +30,7 @@ import org.apache.iotdb.db.pipe.sink.protocol.iotconsensusv2.IoTConsensusV2AsyncSink; import org.apache.iotdb.db.pipe.sink.protocol.thrift.async.IoTDBDataRegionAsyncSink; import org.apache.iotdb.db.pipe.source.dataregion.IoTDBDataRegionSource; +import org.apache.iotdb.db.utils.EnvironmentUtils; import org.apache.iotdb.pipe.api.customizer.parameter.PipeParameters; import org.junit.After; @@ -73,10 +74,10 @@ public void after() { String pluginPath = PipePluginExecutableManager.getInstance() .getPluginsDirPath(PIPE_PLUGIN_META.getPluginName()); - Files.deleteIfExists(Paths.get(pluginPath)); - Files.deleteIfExists(Paths.get(PipePluginExecutableManager.getInstance().getInstallDir())); - Files.deleteIfExists(Paths.get(TMP_TEMP_LIB_ROOT_DIR)); - Files.deleteIfExists(Paths.get(TMP_LIB_ROOT_DIR)); + EnvironmentUtils.cleanDir(pluginPath); + EnvironmentUtils.cleanDir(PipePluginExecutableManager.getInstance().getInstallDir()); + EnvironmentUtils.cleanDir(TMP_TEMP_LIB_ROOT_DIR); + EnvironmentUtils.cleanDir(TMP_LIB_ROOT_DIR); } catch (IOException e) { Assert.fail(); } diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/repair/AbstractRepairDataTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/repair/AbstractRepairDataTest.java index 673e7f88106b4..70e4859786b74 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/repair/AbstractRepairDataTest.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/compaction/repair/AbstractRepairDataTest.java @@ -22,6 +22,7 @@ import org.apache.iotdb.commons.exception.MetadataException; import org.apache.iotdb.db.exception.StorageEngineException; import org.apache.iotdb.db.storageengine.dataregion.compaction.AbstractCompactionTest; +import org.apache.iotdb.db.utils.EnvironmentUtils; import org.apache.iotdb.db.utils.constant.TestConstant; import org.apache.tsfile.exception.write.WriteProcessException; @@ -54,14 +55,6 @@ public File getEmptyRepairDataLogDir() throws IOException { } private void deleteRepairDataLogDir() throws IOException { - if (repairDataLogDir.exists()) { - if (repairDataLogDir.isDirectory()) { - File[] files = repairDataLogDir.listFiles(); - for (File file : files == null ? new File[] {} : files) { - Files.deleteIfExists(file.toPath()); - } - } - Files.deleteIfExists(repairDataLogDir.toPath()); - } + EnvironmentUtils.cleanDir(repairDataLogDir.getPath()); } } diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/ConfigurationFileUtilsTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/ConfigurationFileUtilsTest.java index af0fc1ae83e37..090aec9029d28 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/ConfigurationFileUtilsTest.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/ConfigurationFileUtilsTest.java @@ -31,7 +31,6 @@ import java.io.IOException; import java.nio.file.Files; import java.util.Map; -import java.util.Objects; import java.util.Properties; public class ConfigurationFileUtilsTest { @@ -41,13 +40,7 @@ public class ConfigurationFileUtilsTest { @After public void tearDown() throws IOException { - if (!dir.exists()) { - return; - } - for (File file : Objects.requireNonNull(dir.listFiles())) { - Files.delete(file.toPath()); - } - Files.delete(dir.toPath()); + EnvironmentUtils.cleanDir(dir.getPath()); } @Test diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java index 440e32df46ed2..4c2e1c9c95b98 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java @@ -55,7 +55,6 @@ import org.apache.thrift.TConfiguration; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; -import org.apache.tsfile.external.commons.io.FileUtils; import org.apache.tsfile.fileSystem.FSFactoryProducer; import org.apache.tsfile.utils.FilePathUtils; import org.slf4j.Logger; @@ -69,6 +68,12 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; import java.util.concurrent.TimeUnit; import static org.junit.Assert.fail; @@ -83,6 +88,8 @@ public class EnvironmentUtils { private static final DataNodeMemoryConfig memoryConfig = IoTDBDescriptor.getInstance().getMemoryConfig(); private static final TierManager tierManager = TierManager.getInstance(); + private static final int DELETE_RETRY_TIMES = 5; + private static final long DELETE_RETRY_INTERVAL_MS = 100; public static long TEST_QUERY_JOB_ID = 1; public static QueryContext TEST_QUERY_CONTEXT = new QueryContext(TEST_QUERY_JOB_ID, false); @@ -277,7 +284,69 @@ public static void cleanAllDir() throws IOException { } public static void cleanDir(String dir) throws IOException { - FSFactoryProducer.getFSFactory().deleteDirectory(dir); + Path path = FSFactoryProducer.getFSFactory().getFile(dir).toPath(); + if (!Files.exists(path)) { + return; + } + + IOException lastException = null; + for (int i = 0; i < DELETE_RETRY_TIMES; i++) { + try { + deleteRecursively(path); + return; + } catch (NoSuchFileException e) { + return; + } catch (IOException e) { + lastException = e; + if (i + 1 == DELETE_RETRY_TIMES) { + break; + } + try { + TimeUnit.MILLISECONDS.sleep(DELETE_RETRY_INTERVAL_MS); + } catch (InterruptedException interruptedException) { + Thread.currentThread().interrupt(); + IOException ioException = + new IOException("Interrupted while deleting " + dir, interruptedException); + ioException.addSuppressed(e); + throw ioException; + } + } + } + throw lastException; + } + + private static void deleteRecursively(Path path) throws IOException { + if (!Files.exists(path)) { + return; + } + + Files.walkFileTree( + path, + new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + Files.deleteIfExists(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { + if (exc instanceof NoSuchFileException) { + return FileVisitResult.CONTINUE; + } + throw exc; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + if (exc != null) { + throw exc; + } + Files.deleteIfExists(dir); + return FileVisitResult.CONTINUE; + } + }); } /** disable memory control
this function should be called before all code in the setup */ @@ -338,19 +407,6 @@ private static void createDir(String dir) { } public static void recursiveDeleteFolder(String path) throws IOException { - File file = new File(path); - if (file.isDirectory()) { - File[] files = file.listFiles(); - if (files == null || files.length == 0) { - FileUtils.deleteDirectory(file); - } else { - for (File f : files) { - recursiveDeleteFolder(f.getAbsolutePath()); - } - FileUtils.deleteDirectory(file); - } - } else { - FileUtils.delete(file); - } + cleanDir(path); } } diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtilsTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtilsTest.java new file mode 100644 index 0000000000000..36783d78deceb --- /dev/null +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtilsTest.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.db.utils; + +import org.apache.iotdb.db.utils.constant.TestConstant; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Collections; + +public class EnvironmentUtilsTest { + + private final File testDir = new File(TestConstant.BASE_OUTPUT_PATH, "EnvironmentUtilsTest"); + + @After + public void tearDown() throws IOException { + EnvironmentUtils.cleanDir(testDir.getPath()); + } + + @Test + public void testCleanDirDeletesNestedDirectory() throws IOException { + File nestedDir = new File(testDir, "ext" + File.separator + "udf" + File.separator + "tmp"); + Assert.assertTrue(nestedDir.isDirectory() || nestedDir.mkdirs()); + Files.write(new File(nestedDir, "plugin.txt").toPath(), Collections.singletonList("plugin")); + + EnvironmentUtils.cleanDir(testDir.getPath()); + + Assert.assertFalse(testDir.exists()); + } +} diff --git a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/FileUtilsTest.java b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/FileUtilsTest.java index e25755f4c17ac..7a038af24cbe3 100644 --- a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/FileUtilsTest.java +++ b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/FileUtilsTest.java @@ -45,8 +45,12 @@ public void setUp() throws Exception { @After public void tearDown() throws Exception { - tmpDir.delete(); - targetDir.delete(); + if (tmpDir != null) { + FileUtils.deleteFileOrDirectory(tmpDir, true); + } + if (targetDir != null) { + FileUtils.deleteFileOrDirectory(targetDir, true); + } } @Test