package io.ray.runtime.util;

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;
import org.apache.commons.lang3.SystemUtils;

public class BinaryFileUtil {

  public static final String CORE_WORKER_JAVA_LIBRARY = "core_worker_library_java";

  /**
   * Extract a platform-native 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 getNativeFile(String destDir, String fileName) {
    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);
      }
    }
    String lockFilePath = destDir + File.separator + "file_lock";
    try (FileLock ignored = new RandomAccessFile(lockFilePath, "rw").getChannel().lock()) {
      String resourceDir;
      if (SystemUtils.IS_OS_MAC) {
        resourceDir = "native/darwin/";
      } else if (SystemUtils.IS_OS_LINUX) {
        resourceDir = "native/linux/";
      } else {
        throw new UnsupportedOperationException("Unsupported os " + SystemUtils.OS_NAME);
      }
      String resourcePath = resourceDir + fileName;
      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("/" + resourcePath)) {
        Preconditions.checkNotNull(is, "{} doesn't exist.", resourcePath);
        Files.copy(is, Paths.get(file.getCanonicalPath()));
      } catch (IOException e) {
        throw new RuntimeException("Couldn't get temp file from resource " + resourcePath, e);
      }
      return file;
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }
}

@@ -1634,24 +1634,505 @@
 E);%0A      %7D%0A
+      /// File doesn't exist. Create a temp file and then rename it.%0A      final String tempFilePath = String.format(%22%25s/%25s.tmp%22, destDir, fileName);%0A      // Adding a temporary file here is used to fix the issue that when%0A      // a java worker crashes during extracting dynamic library file, next%0A      // java worker will use an incomplete file. The issue link is:%0A      //%0A      // https://github.com/ray-project/ray/issues/19341%0A      File tempFile = new File(tempFilePath);%0A%0A
       String
@@ -2182,17 +2182,21 @@
    File 
-f
+destF
 ile = ne
@@ -2256,17 +2256,21 @@
     if (
-f
+destF
 ile.exis
@@ -2284,33 +2284,37 @@
 %0A        return 
-f
+destF
 ile;%0A      %7D%0A%0A  
@@ -2541,17 +2541,21 @@
 ths.get(
-f
+tempF
 ile.getC
@@ -2568,24 +2568,303 @@
 alPath()));%0A
+        if (!tempFile.renameTo(destFile)) %7B%0A          throw new RuntimeException(%0A              String.format(%0A                  %22Couldn't rename temp file(%25s) to %25s%22,%0A                  tempFile.getAbsolutePath(), destFile.getAbsolutePath()));%0A        %7D%0A        return destFile;%0A
       %7D catc
@@ -2990,27 +2990,8 @@
   %7D%0A
-      return file;%0A
     

Fix incompleted core worker dynamic library. (#19342)