Minor fixes to RocksJava Native Library initialization (#1287)

* [bugfix] Make sure the Native Library is initialized. Closes https://github.com/facebook/rocksdb/issues/989

* [bugfix] Just load the native libraries once
This commit is contained in:
Adam Retter 2016-10-19 21:21:22 -04:00 committed by Yueh-Hsuan Chiang
parent 48e4e842b7
commit 48fd619a47
2 changed files with 92 additions and 42 deletions

View file

@ -5,6 +5,9 @@ package org.rocksdb;
* {@link org.rocksdb.RocksDB}.
*/
public class FlushOptions extends RocksObject {
static {
RocksDB.loadLibrary();
}
/**
* Construct a new instance of FlushOptions.

View file

@ -7,6 +7,9 @@ package org.rocksdb;
import java.util.*;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.rocksdb.util.Environment;
/**
@ -19,6 +22,15 @@ public class RocksDB extends RocksObject {
public static final byte[] DEFAULT_COLUMN_FAMILY = "default".getBytes();
public static final int NOT_FOUND = -1;
private enum LibraryState {
NOT_LOADED,
LOADING,
LOADED
}
private static AtomicReference<LibraryState> libraryLoaded
= new AtomicReference<>(LibraryState.NOT_LOADED);
static {
RocksDB.loadLibrary();
}
@ -30,10 +42,16 @@ public class RocksDB extends RocksObject {
* java.io.tmpdir, however, you can override this temporary location by
* setting the environment variable ROCKSDB_SHAREDLIB_DIR.
*/
public static synchronized void loadLibrary() {
String tmpDir = System.getenv("ROCKSDB_SHAREDLIB_DIR");
public static void loadLibrary() {
if (libraryLoaded.get() == LibraryState.LOADED) {
return;
}
if (libraryLoaded.compareAndSet(LibraryState.NOT_LOADED,
LibraryState.LOADING)) {
final String tmpDir = System.getenv("ROCKSDB_SHAREDLIB_DIR");
// loading possibly necessary libraries.
for (CompressionType compressionType : CompressionType.values()) {
for (final CompressionType compressionType : CompressionType.values()) {
try {
if (compressionType.getLibraryName() != null) {
System.loadLibrary(compressionType.getLibraryName());
@ -42,15 +60,25 @@ public class RocksDB extends RocksObject {
// since it may be optional, we ignore its loading failure here.
}
}
try
{
try {
NativeLibraryLoader.getInstance().loadLibrary(tmpDir);
}
catch (IOException e)
{
} catch (IOException e) {
libraryLoaded.set(LibraryState.NOT_LOADED);
throw new RuntimeException("Unable to load the RocksDB shared library"
+ e);
}
libraryLoaded.set(LibraryState.LOADED);
return;
}
while (libraryLoaded.get() == LibraryState.LOADING) {
try {
Thread.sleep(10);
} catch(final InterruptedException e) {
//ignore
}
}
}
/**
@ -60,12 +88,18 @@ public class RocksDB extends RocksObject {
* @param paths a list of strings where each describes a directory
* of a library.
*/
public static synchronized void loadLibrary(final List<String> paths) {
for (CompressionType compressionType : CompressionType.values()) {
public static void loadLibrary(final List<String> paths) {
if (libraryLoaded.get() == LibraryState.LOADED) {
return;
}
if (libraryLoaded.compareAndSet(LibraryState.NOT_LOADED,
LibraryState.LOADING)) {
for (final CompressionType compressionType : CompressionType.values()) {
if (compressionType.equals(CompressionType.NO_COMPRESSION)) {
continue;
}
for (String path : paths) {
for (final String path : paths) {
try {
System.load(path + "/" + Environment.getSharedLibraryFileName(
compressionType.getLibraryName()));
@ -77,7 +111,7 @@ public class RocksDB extends RocksObject {
}
boolean success = false;
UnsatisfiedLinkError err = null;
for (String path : paths) {
for (final String path : paths) {
try {
System.load(path + "/" +
Environment.getJniLibraryFileName("rocksdbjni"));
@ -88,8 +122,21 @@ public class RocksDB extends RocksObject {
}
}
if (!success) {
libraryLoaded.set(LibraryState.NOT_LOADED);
throw err;
}
libraryLoaded.set(LibraryState.LOADED);
return;
}
while (libraryLoaded.get() == LibraryState.LOADING) {
try {
Thread.sleep(10);
} catch(final InterruptedException e) {
//ignore
}
}
}
/**