]> git.proxmox.com Git - ceph.git/blame - ceph/src/rocksdb/java/src/main/java/org/rocksdb/NativeLibraryLoader.java
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / java / src / main / java / org / rocksdb / NativeLibraryLoader.java
CommitLineData
f67539c2 1// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
7c673cae
FG
2package org.rocksdb;
3
4import java.io.*;
5import java.nio.file.Files;
6import java.nio.file.StandardCopyOption;
7
8import org.rocksdb.util.Environment;
9
10/**
11 * This class is used to load the RocksDB shared library from within the jar.
12 * The shared library is extracted to a temp folder and loaded from there.
13 */
14public class NativeLibraryLoader {
15 //singleton
16 private static final NativeLibraryLoader instance = new NativeLibraryLoader();
17 private static boolean initialized = false;
18
19 private static final String sharedLibraryName = Environment.getSharedLibraryName("rocksdb");
20 private static final String jniLibraryName = Environment.getJniLibraryName("rocksdb");
1e59de90
TL
21 private static final /* @Nullable */ String fallbackJniLibraryName =
22 Environment.getFallbackJniLibraryName("rocksdb");
7c673cae 23 private static final String jniLibraryFileName = Environment.getJniLibraryFileName("rocksdb");
1e59de90
TL
24 private static final /* @Nullable */ String fallbackJniLibraryFileName =
25 Environment.getFallbackJniLibraryFileName("rocksdb");
7c673cae
FG
26 private static final String tempFilePrefix = "librocksdbjni";
27 private static final String tempFileSuffix = Environment.getJniLibraryExtension();
28
29 /**
30 * Get a reference to the NativeLibraryLoader
31 *
32 * @return The NativeLibraryLoader
33 */
34 public static NativeLibraryLoader getInstance() {
35 return instance;
36 }
37
38 /**
39 * Firstly attempts to load the library from <i>java.library.path</i>,
40 * if that fails then it falls back to extracting
41 * the library from the classpath
42 * {@link org.rocksdb.NativeLibraryLoader#loadLibraryFromJar(java.lang.String)}
43 *
44 * @param tmpDir A temporary directory to use
45 * to copy the native library to when loading from the classpath.
46 * If null, or the empty string, we rely on Java's
47 * {@link java.io.File#createTempFile(String, String)}
48 * function to provide a temporary location.
49 * The temporary file will be registered for deletion
50 * on exit.
51 *
52 * @throws java.io.IOException if a filesystem operation fails.
53 */
54 public synchronized void loadLibrary(final String tmpDir) throws IOException {
55 try {
1e59de90
TL
56 // try dynamic library
57 System.loadLibrary(sharedLibraryName);
58 return;
59 } catch (final UnsatisfiedLinkError ule) {
60 // ignore - try from static library
61 }
62
63 try {
64 // try static library
65 System.loadLibrary(jniLibraryName);
66 return;
67 } catch (final UnsatisfiedLinkError ule) {
68 // ignore - then try static library fallback or from jar
69 }
70
71 if (fallbackJniLibraryName != null) {
7c673cae 72 try {
1e59de90
TL
73 // try static library fallback
74 System.loadLibrary(fallbackJniLibraryName);
75 return;
76 } catch (final UnsatisfiedLinkError ule) {
77 // ignore - then try from jar
7c673cae
FG
78 }
79 }
1e59de90
TL
80
81 // try jar
82 loadLibraryFromJar(tmpDir);
7c673cae
FG
83 }
84
85 /**
86 * Attempts to extract the native RocksDB library
87 * from the classpath and load it
88 *
89 * @param tmpDir A temporary directory to use
90 * to copy the native library to. If null,
91 * or the empty string, we rely on Java's
92 * {@link java.io.File#createTempFile(String, String)}
93 * function to provide a temporary location.
94 * The temporary file will be registered for deletion
95 * on exit.
96 *
97 * @throws java.io.IOException if a filesystem operation fails.
98 */
99 void loadLibraryFromJar(final String tmpDir)
100 throws IOException {
101 if (!initialized) {
102 System.load(loadLibraryFromJarToTemp(tmpDir).getAbsolutePath());
103 initialized = true;
104 }
105 }
106
107 File loadLibraryFromJarToTemp(final String tmpDir)
108 throws IOException {
1e59de90
TL
109 InputStream is = null;
110 try {
111 // attempt to look up the static library in the jar file
112 String libraryFileName = jniLibraryFileName;
113 is = getClass().getClassLoader().getResourceAsStream(libraryFileName);
114
115 if (is == null) {
116 // is there a fallback we can try
117 if (fallbackJniLibraryFileName == null) {
118 throw new RuntimeException(libraryFileName + " was not found inside JAR.");
119 }
120
121 // attempt to look up the fallback static library in the jar file
122 libraryFileName = fallbackJniLibraryFileName;
123 is = getClass().getClassLoader().getResourceAsStream(libraryFileName);
124 if (is == null) {
125 throw new RuntimeException(libraryFileName + " was not found inside JAR.");
126 }
20effc67 127 }
1e59de90
TL
128
129 // create a temporary file to copy the library to
130 final File temp;
131 if (tmpDir == null || tmpDir.isEmpty()) {
132 temp = File.createTempFile(tempFilePrefix, tempFileSuffix);
133 } else {
134 final File parentDir = new File(tmpDir);
135 if (!parentDir.exists()) {
136 throw new RuntimeException(
137 "Directory: " + parentDir.getAbsolutePath() + " does not exist!");
138 }
139 temp = new File(parentDir, libraryFileName);
140 if (temp.exists() && !temp.delete()) {
141 throw new RuntimeException(
142 "File: " + temp.getAbsolutePath() + " already exists and cannot be removed.");
143 }
144 if (!temp.createNewFile()) {
145 throw new RuntimeException("File: " + temp.getAbsolutePath() + " could not be created.");
146 }
7c673cae 147 }
1e59de90
TL
148 if (!temp.exists()) {
149 throw new RuntimeException("File " + temp.getAbsolutePath() + " does not exist.");
150 } else {
151 temp.deleteOnExit();
7c673cae 152 }
7c673cae 153
1e59de90
TL
154 // copy the library from the Jar file to the temp destination
155 Files.copy(is, temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
7c673cae 156
1e59de90
TL
157 // return the temporary library file
158 return temp;
159
160 } finally {
161 if (is != null) {
162 is.close();
7c673cae
FG
163 }
164 }
7c673cae
FG
165 }
166
167 /**
168 * Private constructor to disallow instantiation
169 */
170 private NativeLibraryLoader() {
171 }
172}