aboutsummaryrefslogtreecommitdiff
path: root/common/network-common
diff options
context:
space:
mode:
Diffstat (limited to 'common/network-common')
-rw-r--r--common/network-common/pom.xml4
-rw-r--r--common/network-common/src/main/java/org/apache/spark/network/util/JavaUtils.java49
2 files changed, 51 insertions, 2 deletions
diff --git a/common/network-common/pom.xml b/common/network-common/pom.xml
index 5444ae6d70..12d89273d7 100644
--- a/common/network-common/pom.xml
+++ b/common/network-common/pom.xml
@@ -41,6 +41,10 @@
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
<!-- Provided dependencies -->
<dependency>
diff --git a/common/network-common/src/main/java/org/apache/spark/network/util/JavaUtils.java b/common/network-common/src/main/java/org/apache/spark/network/util/JavaUtils.java
index fbed2f053d..eb534eed24 100644
--- a/common/network-common/src/main/java/org/apache/spark/network/util/JavaUtils.java
+++ b/common/network-common/src/main/java/org/apache/spark/network/util/JavaUtils.java
@@ -29,6 +29,7 @@ import java.util.regex.Pattern;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import io.netty.buffer.Unpooled;
+import org.apache.commons.lang3.SystemUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -79,14 +80,32 @@ public class JavaUtils {
return Unpooled.wrappedBuffer(b).toString(StandardCharsets.UTF_8);
}
- /*
+ /**
* Delete a file or directory and its contents recursively.
* Don't follow directories if they are symlinks.
- * Throws an exception if deletion is unsuccessful.
+ *
+ * @param file Input file / dir to be deleted
+ * @throws IOException if deletion is unsuccessful
*/
public static void deleteRecursively(File file) throws IOException {
if (file == null) { return; }
+ // On Unix systems, use operating system command to run faster
+ // If that does not work out, fallback to the Java IO way
+ if (SystemUtils.IS_OS_UNIX) {
+ try {
+ deleteRecursivelyUsingUnixNative(file);
+ return;
+ } catch (IOException e) {
+ logger.warn("Attempt to delete using native Unix OS command failed for path = {}. " +
+ "Falling back to Java IO way", file.getAbsolutePath(), e);
+ }
+ }
+
+ deleteRecursivelyUsingJavaIO(file);
+ }
+
+ private static void deleteRecursivelyUsingJavaIO(File file) throws IOException {
if (file.isDirectory() && !isSymlink(file)) {
IOException savedIOException = null;
for (File child : listFilesSafely(file)) {
@@ -109,6 +128,32 @@ public class JavaUtils {
}
}
+ private static void deleteRecursivelyUsingUnixNative(File file) throws IOException {
+ ProcessBuilder builder = new ProcessBuilder("rm", "-rf", file.getAbsolutePath());
+ Process process = null;
+ int exitCode = -1;
+
+ try {
+ // In order to avoid deadlocks, consume the stdout (and stderr) of the process
+ builder.redirectErrorStream(true);
+ builder.redirectOutput(new File("/dev/null"));
+
+ process = builder.start();
+
+ exitCode = process.waitFor();
+ } catch (Exception e) {
+ throw new IOException("Failed to delete: " + file.getAbsolutePath(), e);
+ } finally {
+ if (process != null && process.isAlive()) {
+ process.destroy();
+ }
+ }
+
+ if (exitCode != 0 || file.exists()) {
+ throw new IOException("Failed to delete: " + file.getAbsolutePath());
+ }
+ }
+
private static File[] listFilesSafely(File file) throws IOException {
if (file.exists()) {
File[] files = file.listFiles();