All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.lmdbjava.Library Maven / Gradle / Ivy

Go to download

Low latency Java API for the ultra-fast, embedded Symas Lightning Database (LMDB)

There is a newer version: 0.9.0
Show newest version
/*-
 * #%L
 * LmdbJava
 * %%
 * Copyright (C) 2016 - 2019 The LmdbJava Open Source Project
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

package org.lmdbjava;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.File;
import static java.io.File.createTempFile;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import static java.lang.Boolean.getBoolean;
import static java.lang.System.getProperty;
import static java.lang.Thread.currentThread;
import java.nio.file.Files;
import static java.util.Locale.ENGLISH;
import static java.util.Objects.nonNull;
import static java.util.Objects.requireNonNull;
import static jnr.ffi.LibraryLoader.create;
import jnr.ffi.Pointer;
import static jnr.ffi.Runtime.getRuntime;
import jnr.ffi.Struct;
import jnr.ffi.annotations.Delegate;
import jnr.ffi.annotations.In;
import jnr.ffi.annotations.Out;
import jnr.ffi.byref.IntByReference;
import jnr.ffi.byref.NativeLongByReference;
import jnr.ffi.byref.PointerByReference;
import jnr.ffi.types.size_t;

/**
 * JNR-FFI interface to LMDB.
 *
 * 

* For performance reasons pointers are used rather than structs. */ final class Library { /** * Java system property name that can be set to disable automatic extraction * of the LMDB system library from the LmdbJava JAR. This may be desirable if * an operating system-provided LMDB system library is preferred (eg operating * system package management, vendor support, special compiler flags, security * auditing, profile guided optimization builds, faster startup time by * avoiding the library copy etc). */ public static final String DISABLE_EXTRACT_PROP = "lmdbjava.disable.extract"; /** * Java system property name that can be set to provide a custom path to a * external LMDB system library. If set, the system property * DISABLE_EXTRACT_PROP will be overridden. */ public static final String LMDB_NATIVE_LIB_PROP = "lmdbjava.native.lib"; /** * Indicates whether automatic extraction of the LMDB system library is * permitted. */ public static final boolean SHOULD_EXTRACT = !getBoolean(DISABLE_EXTRACT_PROP); static final Lmdb LIB; static final jnr.ffi.Runtime RUNTIME; /** * Indicates whether external LMDB system library is provided. */ static final boolean SHOULD_USE_LIB = nonNull( getProperty(LMDB_NATIVE_LIB_PROP)); private static final String LIB_NAME = "lmdb"; static { final String libToLoad; final String arch = getProperty("os.arch"); final boolean arch64 = "x64".equals(arch) || "amd64".equals(arch) || "x86_64".equals(arch); final String os = getProperty("os.name"); final boolean linux = os.toLowerCase(ENGLISH).startsWith("linux"); final boolean osx = os.startsWith("Mac OS X"); final boolean windows = os.startsWith("Windows"); if (SHOULD_USE_LIB) { libToLoad = getProperty(LMDB_NATIVE_LIB_PROP); } else if (SHOULD_EXTRACT && arch64 && linux) { libToLoad = extract("org/lmdbjava/lmdbjava-native-linux-x86_64.so"); } else if (SHOULD_EXTRACT && arch64 && osx) { libToLoad = extract("org/lmdbjava/lmdbjava-native-osx-x86_64.dylib"); } else if (SHOULD_EXTRACT && arch64 && windows) { libToLoad = extract("org/lmdbjava/lmdbjava-native-windows-x86_64.dll"); } else { libToLoad = LIB_NAME; } LIB = create(Lmdb.class).load(libToLoad); RUNTIME = getRuntime(LIB); } private Library() { } @SuppressWarnings("PMD.AssignmentInOperand") @SuppressFBWarnings("OBL_UNSATISFIED_OBLIGATION") // Spotbugs issue #432 private static String extract(final String name) { final String suffix = name.substring(name.lastIndexOf('.')); final File file; try { file = createTempFile("lmdbjava-native-library-", suffix); file.deleteOnExit(); final ClassLoader cl = currentThread().getContextClassLoader(); try (InputStream in = cl.getResourceAsStream(name); OutputStream out = Files.newOutputStream(file.toPath())) { requireNonNull(in, "Classpath resource not found"); int bytes; final byte[] buffer = new byte[4_096]; while (-1 != (bytes = in.read(buffer))) { out.write(buffer, 0, bytes); } } return file.getAbsolutePath(); } catch (final IOException e) { throw new LmdbException("Failed to extract " + name, e); } } /** * Structure to wrap a native MDB_envinfo. Not for external use. */ @SuppressWarnings({"checkstyle:typename", "checkstyle:visibilitymodifier", "checkstyle:membername"}) public static final class MDB_envinfo extends Struct { public final Pointer f0_me_mapaddr; public final size_t f1_me_mapsize; public final size_t f2_me_last_pgno; public final size_t f3_me_last_txnid; public final u_int32_t f4_me_maxreaders; public final u_int32_t f5_me_numreaders; MDB_envinfo(final jnr.ffi.Runtime runtime) { super(runtime); this.f0_me_mapaddr = new Pointer(); this.f1_me_mapsize = new size_t(); this.f2_me_last_pgno = new size_t(); this.f3_me_last_txnid = new size_t(); this.f4_me_maxreaders = new u_int32_t(); this.f5_me_numreaders = new u_int32_t(); } } /** * Structure to wrap a native MDB_stat. Not for external use. */ @SuppressWarnings({"checkstyle:typename", "checkstyle:visibilitymodifier", "checkstyle:membername"}) public static final class MDB_stat extends Struct { public final u_int32_t f0_ms_psize; public final u_int32_t f1_ms_depth; public final size_t f2_ms_branch_pages; public final size_t f3_ms_leaf_pages; public final size_t f4_ms_overflow_pages; public final size_t f5_ms_entries; MDB_stat(final jnr.ffi.Runtime runtime) { super(runtime); this.f0_ms_psize = new u_int32_t(); this.f1_ms_depth = new u_int32_t(); this.f2_ms_branch_pages = new size_t(); this.f3_ms_leaf_pages = new size_t(); this.f4_ms_overflow_pages = new size_t(); this.f5_ms_entries = new size_t(); } } /** * Custom comparator callback used by mdb_set_compare. */ public interface ComparatorCallback { @Delegate int compare(@In Pointer keyA, @In Pointer keyB); } /** * JNR API for MDB-defined C functions. Not for external use. */ @SuppressWarnings("checkstyle:methodname") public interface Lmdb { void mdb_cursor_close(@In Pointer cursor); int mdb_cursor_count(@In Pointer cursor, NativeLongByReference countp); int mdb_cursor_del(@In Pointer cursor, int flags); int mdb_cursor_get(@In Pointer cursor, Pointer k, @Out Pointer v, int cursorOp); int mdb_cursor_open(@In Pointer txn, @In Pointer dbi, PointerByReference cursorPtr); int mdb_cursor_put(@In Pointer cursor, @In Pointer key, @In Pointer data, int flags); int mdb_cursor_renew(@In Pointer txn, @In Pointer cursor); void mdb_dbi_close(@In Pointer env, @In Pointer dbi); int mdb_dbi_flags(@In Pointer txn, @In Pointer dbi, int flags); int mdb_dbi_open(@In Pointer txn, @In byte[] name, int flags, @In Pointer dbiPtr); int mdb_del(@In Pointer txn, @In Pointer dbi, @In Pointer key, @In Pointer data); int mdb_drop(@In Pointer txn, @In Pointer dbi, int del); void mdb_env_close(@In Pointer env); int mdb_env_copy2(@In Pointer env, @In String path, int flags); int mdb_env_create(PointerByReference envPtr); int mdb_env_get_fd(@In Pointer env, @In Pointer fd); int mdb_env_get_flags(@In Pointer env, int flags); int mdb_env_get_maxkeysize(@In Pointer env); int mdb_env_get_maxreaders(@In Pointer env, int readers); int mdb_env_get_path(@In Pointer env, String path); int mdb_env_info(@In Pointer env, @Out MDB_envinfo info); int mdb_env_open(@In Pointer env, @In String path, int flags, int mode); int mdb_env_set_flags(@In Pointer env, int flags, int onoff); int mdb_env_set_mapsize(@In Pointer env, @size_t long size); int mdb_env_set_maxdbs(@In Pointer env, int dbs); int mdb_env_set_maxreaders(@In Pointer env, int readers); int mdb_env_stat(@In Pointer env, @Out MDB_stat stat); int mdb_env_sync(@In Pointer env, int f); int mdb_get(@In Pointer txn, @In Pointer dbi, @In Pointer key, @Out Pointer data); int mdb_put(@In Pointer txn, @In Pointer dbi, @In Pointer key, @In Pointer data, int flags); int mdb_reader_check(@In Pointer env, int dead); int mdb_set_compare(@In Pointer txn, @In Pointer dbi, ComparatorCallback cb); int mdb_stat(@In Pointer txn, @In Pointer dbi, @Out MDB_stat stat); String mdb_strerror(int rc); void mdb_txn_abort(@In Pointer txn); int mdb_txn_begin(@In Pointer env, @In Pointer parentTx, int flags, Pointer txPtr); int mdb_txn_commit(@In Pointer txn); Pointer mdb_txn_env(@In Pointer txn); long mdb_txn_id(@In Pointer txn); int mdb_txn_renew(@In Pointer txn); void mdb_txn_reset(@In Pointer txn); Pointer mdb_version(IntByReference major, IntByReference minor, IntByReference patch); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy