From 1ae7c03e864cecc2f0059555a07d5d2cb0c5f24e Mon Sep 17 00:00:00 2001 From: chaokunyang Date: Thu, 20 Feb 2020 20:38:51 +0800 Subject: [PATCH] fix concurrently extract file (#7225) --- .../org/ray/runtime/util/BinaryFileUtil.java | 49 +++++++++++++------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/java/runtime/src/main/java/org/ray/runtime/util/BinaryFileUtil.java b/java/runtime/src/main/java/org/ray/runtime/util/BinaryFileUtil.java index 4c5cc402f..df8cb8a6f 100644 --- a/java/runtime/src/main/java/org/ray/runtime/util/BinaryFileUtil.java +++ b/java/runtime/src/main/java/org/ray/runtime/util/BinaryFileUtil.java @@ -4,6 +4,8 @@ import com.google.common.base.Preconditions; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.RandomAccessFile; +import java.nio.channels.FileLock; import java.nio.file.Files; import java.nio.file.Paths; import org.apache.commons.io.FileUtils; @@ -22,27 +24,42 @@ public class BinaryFileUtil { public static final String CORE_WORKER_JAVA_LIBRARY = System.mapLibraryName("core_worker_library_java"); + /** + * Extract a resource file to destDir. + * Note that this a process-safe operation. If multi processes extract the file to same + * directory concurrently, this operation will be protected by a file lock. + * + * @param destDir a directory to extract resource file to + * @param fileName resource file name + * @return extracted resource file + */ public static File getFile(String destDir, String fileName) { - File file = new File(String.format("%s/%s", destDir, fileName)); - if (file.exists()) { - return file; - } - - final File dir = file.getParentFile(); - try { - if (!dir.exists()) { + final File dir = new File(destDir); + if (!dir.exists()) { + try { FileUtils.forceMkdir(dir); + } catch (IOException e) { + throw new RuntimeException("Couldn't make directory: " + dir.getAbsolutePath(), e); } - } catch (IOException e) { - throw new RuntimeException("Couldn't make directory: " + dir.getAbsolutePath(), e); } - // File does not exist. - try (InputStream is = BinaryFileUtil.class.getResourceAsStream("/" + fileName)) { - Preconditions.checkNotNull(is, "{} doesn't exist.", fileName); - Files.copy(is, Paths.get(file.getCanonicalPath())); + String lockFilePath = destDir + File.separator + "file_lock"; + try (FileLock ignored = new RandomAccessFile(lockFilePath, "rw") + .getChannel().lock()) { + File file = new File(String.format("%s/%s", destDir, fileName)); + if (file.exists()) { + return file; + } + + // File does not exist. + try (InputStream is = BinaryFileUtil.class.getResourceAsStream("/" + fileName)) { + Preconditions.checkNotNull(is, "{} doesn't exist.", fileName); + Files.copy(is, Paths.get(file.getCanonicalPath())); + } catch (IOException e) { + throw new RuntimeException("Couldn't get temp file from resource " + fileName, e); + } + return file; } catch (IOException e) { - throw new RuntimeException("Couldn't get temp file from resource " + fileName, e); + throw new RuntimeException(e); } - return file; } }