From b2d95c625dc08f9d8af080bd1b192cc0a3b710b4 Mon Sep 17 00:00:00 2001 From: Mike Percy Date: Tue, 5 Feb 2019 15:50:12 -0800 Subject: [PATCH] KUDU-2411: Remove binary test artifact files on JVM exit This patch adds a JVM shutdown hook to remove the mini cluster binary test artifact at shutdown time. Change-Id: I51701e14eb2f2eb541c04813e74ddc02bf431c3d Reviewed-on: http://gerrit.cloudera.org:8080/12377 Reviewed-by: Grant Henke Tested-by: Kudu Jenkins --- java/kudu-test-utils/build.gradle | 3 +- .../org/apache/kudu/test/TempDirUtils.java | 47 +++++++++++++++++-- .../kudu/test/cluster/KuduBinaryLocator.java | 7 +-- .../kudu/test/cluster/MiniKuduCluster.java | 4 +- 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/java/kudu-test-utils/build.gradle b/java/kudu-test-utils/build.gradle index ebe5c248ff..e172c2af82 100644 --- a/java/kudu-test-utils/build.gradle +++ b/java/kudu-test-utils/build.gradle @@ -19,6 +19,7 @@ apply from: "$rootDir/gradle/shadow.gradle" dependencies { compile project(path: ":kudu-client") + compile libs.commonsIo compile libs.guava compile libs.osdetector @@ -36,4 +37,4 @@ dependencies { // kudu-test-utils has no public Javadoc. javadoc { enabled = false -} \ No newline at end of file +} diff --git a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/TempDirUtils.java b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/TempDirUtils.java index dcb905a444..01d435be47 100644 --- a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/TempDirUtils.java +++ b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/TempDirUtils.java @@ -17,12 +17,14 @@ package org.apache.kudu.test; +import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; /** @@ -30,6 +32,18 @@ */ public class TempDirUtils { + /** + * An enum to control whether a temporary directory created by + * {@link #makeTempDirectory(String, DeleteOnExit)} is recursively deleted on JVM exit, + * including the contents of the directory. + */ + public enum DeleteOnExit { + /** Do not delete the directory on exit. */ + NO_DELETE_ON_EXIT, + /** Recursively delete the directory and its contents on exit. */ + DELETE_RECURSIVELY_ON_EXIT, + } + private static final Logger LOG = LoggerFactory.getLogger(TempDirUtils.class); /** @@ -40,16 +54,43 @@ public class TempDirUtils { * * @param prefix a directory name to be created, in environment variable TEST_TMPDIR if defined, * else within the java.io.tmpdir system property + * @param deleteRecursivelyOnExit whether to recursively delete the directory and all its + * contents on JVM exit * @return temp directory as a file * @throws IOException if a temp directory cannot be created */ - public static File getTempDirectory(String prefix) throws IOException { + public static File makeTempDirectory(String prefix, DeleteOnExit deleteRecursivelyOnExit) + throws IOException { String testTmpdir = System.getenv("TEST_TMPDIR"); + File newDir; if (testTmpdir != null) { LOG.info("Using the temp directory defined by TEST_TMPDIR: " + testTmpdir); - return Files.createTempDirectory(Paths.get(testTmpdir), prefix).toFile(); + newDir = Files.createTempDirectory(Paths.get(testTmpdir), prefix).toFile(); } else { - return Files.createTempDirectory(prefix).toFile(); + newDir = Files.createTempDirectory(prefix).toFile(); + } + if (deleteRecursivelyOnExit == DeleteOnExit.DELETE_RECURSIVELY_ON_EXIT) { + registerToRecursivelyDeleteOnShutdown(newDir.toPath()); } + return newDir; + } + + /** + * Register a JVM shutdown hook to recursively delete the specified directory on JVM shutdown. + * @param path directory to delete on shutdown + */ + private static void registerToRecursivelyDeleteOnShutdown(Path path) { + final Path absPath = path.toAbsolutePath(); + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + File dir = absPath.toFile(); + if (!dir.exists()) return; + try { + FileUtils.deleteDirectory(dir); + } catch (IOException exc) { + LOG.warn("Unable to remove directory tree " + absPath.toString(), exc); + } + } + }); } } diff --git a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/KuduBinaryLocator.java b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/KuduBinaryLocator.java index 6a983b84a4..b88798ae6f 100644 --- a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/KuduBinaryLocator.java +++ b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/KuduBinaryLocator.java @@ -83,9 +83,10 @@ private static KuduBinaryInfo findBinaryLocation() { try { KuduBinaryJarExtractor extractor = new KuduBinaryJarExtractor(); if (extractor.isKuduBinaryJarOnClasspath()) { - String testTmpDir = TempDirUtils.getTempDirectory("kudu-binary-jar").toString(); - LOG.info("Using Kudu binary jar directory: {}", testTmpDir); - return extractor.extractKuduBinaryArtifact(testTmpDir); + File testTmpDir = TempDirUtils.makeTempDirectory("kudu-binary-jar", + TempDirUtils.DeleteOnExit.DELETE_RECURSIVELY_ON_EXIT); + LOG.info("Using Kudu binary jar directory: {}", testTmpDir.getAbsolutePath()); + return extractor.extractKuduBinaryArtifact(testTmpDir.getAbsolutePath()); } } catch (IOException ex) { LOG.warn("Unable to extract a Kudu binary jar", ex); diff --git a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/MiniKuduCluster.java b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/MiniKuduCluster.java index 2a0fe30ad2..2d40df6944 100644 --- a/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/MiniKuduCluster.java +++ b/java/kudu-test-utils/src/main/java/org/apache/kudu/test/cluster/MiniKuduCluster.java @@ -25,7 +25,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; @@ -130,7 +129,8 @@ private MiniKuduCluster(boolean enableKerberos, // If a cluster root was not set, create a unique temp directory to use. // The mini cluster will clean this directory up on exit. try { - File tempRoot = TempDirUtils.getTempDirectory("mini-kudu-cluster"); + File tempRoot = TempDirUtils.makeTempDirectory("mini-kudu-cluster", + TempDirUtils.DeleteOnExit.NO_DELETE_ON_EXIT); this.clusterRoot = tempRoot.toString(); } catch (IOException ex) { throw new RuntimeException("Could not create cluster root directory", ex);