fix concurrently extract file (#7225)

This commit is contained in:
chaokunyang 2020-02-20 20:38:51 +08:00 committed by GitHub
parent d7f8d18a86
commit 1ae7c03e86
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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 <code>destDir</code>.
* 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;
}
}