package org.rocksdb;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;

import org.rocksdb.util.Environment;

/**
 * This class is used to load the RocksDB shared library from within the jar.
 * The shared library is extracted to a temp folder and loaded from there.
 */
public class NativeLibraryLoader {
  //singleton
  private static final NativeLibraryLoader instance = new NativeLibraryLoader();

  private static final String sharedLibraryName = Environment.getJniLibraryName("rocksdb");
  private static final String tempFilePrefix = "librocksdbjni";
  private static final String tempFileSuffix = "." + Environment.getJniLibraryExtension();

  /**
   * Get a reference to the NativeLibraryLoader
   *
   * @return The NativeLibraryLoader
   */
  public static NativeLibraryLoader getInstance() {
    return instance;
  }

  /**
   * Attempts to extract the native RocksDB library
   * from the classpath and load it
   *
   * @param tmpDir A temporary directory to use
   *   to copy the native library to. If null,
   *   or the empty string, we rely on Java's
   *   {@link java.io.File#createTempFile(String, String)}
   *   function to provide a temporary location.
   *   The temporary file will be registered for deletion
   *   on exit.
   *
   * @throws java.io.IOException if a filesystem operation fails.
   */
  public void loadLibraryFromJar(final String tmpDir)
      throws IOException {
    final File temp;
    if(tmpDir == null || tmpDir.equals("")) {
      temp = File.createTempFile(tempFilePrefix, tempFileSuffix);
    } else {
      temp = new File(tmpDir, sharedLibraryName);
    }

    if (!temp.exists()) {
      throw new RuntimeException("File " + temp.getAbsolutePath() + " does not exist.");
    } else {
      temp.deleteOnExit();
    }

    // attempt to copy the library from the Jar file to the temp destination
    try(final InputStream is = getClass().getClassLoader().getResourceAsStream(sharedLibraryName)) {
      if (is == null) {
        throw new RuntimeException(sharedLibraryName + " was not found inside JAR.");
      } else {
        Files.copy(is, temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
      }
    }

    System.load(temp.getAbsolutePath());
  }
  /**
   * Private constructor to disallow instantiation
   */
  private NativeLibraryLoader() {
  }
}

@@ -431,16 +431,62 @@
 oader();
+%0A  private static boolean initialized = false;
 %0A%0A  priv
@@ -1415,16 +1415,29 @@
  public 
+synchronized 
 void loa
@@ -1500,16 +1500,42 @@
 ption %7B%0A
+    if (!initialized) %7B%0A  
     fina
@@ -1551,18 +1551,21 @@
 mp;%0A    
+  
 if
+ 
 (tmpDir 
@@ -1592,24 +1592,26 @@
 uals(%22%22)) %7B%0A
+  
       temp =
@@ -1664,16 +1664,18 @@
 uffix);%0A
+  
     %7D el
@@ -1681,24 +1681,26 @@
 lse %7B%0A      
+  
 temp = new F
@@ -1731,27 +1731,31 @@
 yName);%0A    
+  
 %7D%0A%0A
+  
     if (!tem
@@ -1764,24 +1764,26 @@
 exists()) %7B%0A
+  
       throw 
@@ -1859,24 +1859,26 @@
 ist.%22);%0A    
+  
 %7D else %7B%0A   
@@ -1870,24 +1870,26 @@
    %7D else %7B%0A
+  
       temp.d
@@ -1907,23 +1907,27 @@
 ();%0A    
+  
 %7D%0A%0A    
+ 
+ 
 // attem
@@ -1999,11 +1999,14 @@
     
+  
 try
+ 
 (fin
@@ -2053,16 +2053,27 @@
 oader().
+%0A          
 getResou
@@ -2108,24 +2108,26 @@
 e)) %7B%0A      
+ 
+ 
 if (is == nu
@@ -2128,24 +2128,26 @@
  == null) %7B%0A
+  
         thro
@@ -2218,32 +2218,34 @@
 e JAR.%22);%0A      
+ 
+ 
 %7D else %7B%0A       
@@ -2229,32 +2229,34 @@
        %7D else %7B%0A
+  
         Files.co
@@ -2325,17 +2325,23 @@
     
+ 
+ 
 %7D%0A
+  
     %7D%0A%0A
+  
     
@@ -2377,16 +2377,48 @@
 ath());%0A
+      initialized = true;%0A    %7D%0A
   %7D%0A  /*

Fix native library loader