Compare commits

...

21 Commits

Author SHA1 Message Date
przemyslaw.skibinski@percona.com 73fc71f933 Fix GitHub issue #3716: gcc-8 warnings
Summary:
Fix the following gcc-8 warnings:
- conflicting C language linkage declaration [-Werror]
- writing to an object with no trivial copy-assignment [-Werror=class-memaccess]
- array subscript -1 is below array bounds [-Werror=array-bounds]

Solves https://github.com/facebook/rocksdb/issues/3716
Closes https://github.com/facebook/rocksdb/pull/3736

Differential Revision: D7684161

Pulled By: yiwu-arbug

fbshipit-source-id: 47c0423d26b74add251f1d3595211eee1e41e54a
2019-10-30 13:15:18 -07:00
Vijay Nadimpalli 07109c4d84 Making platform 007 (gcc 7) default in build_detect_platform.sh (#5947)
Summary:
Making platform 007 (gcc 7) default in build_detect_platform.sh.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/5947

Differential Revision: D18038837

Pulled By: vjnadimpalli

fbshipit-source-id: 9ac2ddaa93bf328a416faec028970e039886378e
2019-10-30 13:14:07 -07:00
Andrew Kryczka 44302dd00c Add latest toolchain (gcc-8, etc.) build support for fbcode users (#4923)
Summary:
- When building with internal dependencies, specify this toolchain by setting `ROCKSDB_FBCODE_BUILD_WITH_PLATFORM007=1`
- It is not enabled by default. However, it is enabled for TSAN builds in CI since there is a known problem with TSAN in gcc-5: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71090
- I did not add support for Lua since (1) we agreed to deprecate it, and (2) we only have an internal build for v5.3 with this toolchain while that has breaking changes compared to our current version (v5.2).
Pull Request resolved: https://github.com/facebook/rocksdb/pull/4923

Differential Revision: D13827226

Pulled By: ajkr

fbshipit-source-id: 9aa3388ed3679777cfb15ef8cbcb83c07f62f947
2019-10-30 13:13:58 -07:00
sdong 005c34f0b8 Bump up to 5.12.5 2018-06-18 09:55:01 -07:00
sdong 843738d8dc Fix regression bug of Prev() with upper bound (#3989)
Summary:
A recent change pushed down the upper bound checking to child iterators. However, this causes the logic of following sequence wrong:
  Seek(key);
  if (!Valid()) SeekToLast();
Because !Valid() may be caused by upper bounds, rather than the end of the iterator. In this case SeekToLast() points to totally wrong places. This can cause wrong results, infinite loops, or segfault in some cases.
This sequence is called when changing direction from forward to backward. And this by itself also implicitly happen during reseeking optimization in Prev().

Fix this bug by using SeekForPrev() rather than this sequence, as what is already done in prefix extrator case.
Closes https://github.com/facebook/rocksdb/pull/3989

Differential Revision: D8385422

Pulled By: siying

fbshipit-source-id: 429e869990cfd2dc389421e0836fc496bed67bb4
2018-06-18 09:50:10 -07:00
Zhongyi Xie cc0a65f428 bump version to 5.12.4 and update history 2018-04-20 14:16:35 -07:00
Zhongyi Xie 4837609ce2 fix memory leak in two_level_iterator
Summary:
this PR fixes a few failed contbuild:
1. ASAN memory leak in Block::NewIterator (table/block.cc:429). the proper destruction of first_level_iter_ and second_level_iter_ of two_level_iterator.cc is missing from the code after the refactoring in https://github.com/facebook/rocksdb/pull/3406
2. various unused param errors introduced by https://github.com/facebook/rocksdb/pull/3662
3. updated comment for `ForceReleaseCachedEntry` to emphasize the use of `force_erase` flag.
Closes https://github.com/facebook/rocksdb/pull/3718

Reviewed By: maysamyabandeh

Differential Revision: D7621192

Pulled By: miasantreble

fbshipit-source-id: 476c94264083a0730ded957c29de7807e4f5b146
2018-04-20 14:14:51 -07:00
Maysam Yabandeh 48171df2bc update history 2018-04-09 19:37:11 -07:00
Maysam Yabandeh d4f30520f9 bump patch number to 5.12.3 2018-04-09 16:55:11 -07:00
Maysam Yabandeh c87e28ddf3 Fix the memory leak with pinned partitioned filters
Summary:
The existing unit test did not set the level so the check for pinned partitioned filter/index being properly released from the block cache was not properly exercised as they only take effect in level 0. As a result a memory leak in pinned partitioned filters was hidden. The patch fix the test as well as the bug.
Closes https://github.com/facebook/rocksdb/pull/3692

Differential Revision: D7559763

Pulled By: maysamyabandeh

fbshipit-source-id: 55eff274945838af983c764a7d71e8daff092e4a
2018-04-09 16:53:16 -07:00
Sagar Vemuri 8969445642 Update history and bump patch number 2018-03-23 11:39:50 -07:00
Sagar Vemuri 250d2a6791 Shared block cache in RocksJava
Summary:
Changes to support sharing block cache using the Java API.

Previously DB instances could share the block cache only when the same Options instance is passed to all the DB instances. But now, with this change, it is possible to explicitly create a cache and pass it to multiple options instances, to share the block cache.

Implementing this for [Rocksandra](https://github.com/instagram/cassandra/tree/rocks_3.0), but this feature has been requested by many java api users over the years.
Closes https://github.com/facebook/rocksdb/pull/3623

Differential Revision: D7305794

Pulled By: sagar0

fbshipit-source-id: 03e4e8ed7aeee6f88bada4a8365d4279ede2ad71
2018-03-23 11:33:26 -07:00
Sagar Vemuri 68d69899a1 Fsync after writing global seq number in ExternalSstFileIngestionJob
Summary:
Fsync after writing global sequence number to the ingestion file in ExternalSstFileIngestionJob. Otherwise the file metadata could be incorrect.
Closes https://github.com/facebook/rocksdb/pull/3644

Differential Revision: D7373813

Pulled By: sagar0

fbshipit-source-id: 4da2c9e71a8beb5c08b4ac955f288ee1576358b8
2018-03-23 11:15:55 -07:00
Andrew Kryczka b4fc156fb8 update history and bump patch number 2018-03-16 14:09:20 -07:00
Andrew Kryczka 34ccab0210 Fix WAL corruption from checkpoint/backup race condition
Summary:
`Writer::WriteBuffer` was always called at the beginning of checkpoint/backup. But that log writer has no internal synchronization, which meant the same buffer could be flushed twice in a race condition case, causing a WAL entry to be duplicated. Then subsequent WAL entries would be at unexpected offsets, causing the 32KB block boundaries to be overlapped and manifesting as a corruption.

This PR fixes the behavior to only use `WriteBuffer` (via `FlushWAL`) in checkpoint/backup when manual WAL flush is enabled. In that case, users are responsible for providing synchronization between WAL flushes. We can also consider removing the call entirely.
Closes https://github.com/facebook/rocksdb/pull/3603

Differential Revision: D7277447

Pulled By: ajkr

fbshipit-source-id: 1b15bd7fd930511222b075418c10de0aaa70a35a
2018-03-16 14:08:01 -07:00
Adam Retter 4f51078c44 Java wrapper for Native Comparators
Summary:
This is an abstraction for working with custom Comparators implemented in native C++ code from Java. Native code must directly extend `rocksdb::Comparator`. When the native code comparator is compiled into the RocksDB codebase, you can then create a Java Class, and JNI stub to wrap it.

Useful if the C++/JNI barrier overhead is too much for your applications comparator performance.

An example is provided in `java/rocksjni/native_comparator_wrapper_test.cc` and `java/src/main/java/org/rocksdb/NativeComparatorWrapperTest.java`.
Closes https://github.com/facebook/rocksdb/pull/3334

Differential Revision: D7172605

Pulled By: miasantreble

fbshipit-source-id: e24b7eb267a3bcb6afa214e0379a1d5e8a2ceabe
2018-03-14 16:59:02 -07:00
Pooya Shareghi 2c3ceec5a3 Added bytes XOR merge operator
Summary:
Closes https://github.com/facebook/rocksdb/pull/575

I fixed the merge conflicts etc.
Closes https://github.com/facebook/rocksdb/pull/3065

Differential Revision: D7128233

Pulled By: sagar0

fbshipit-source-id: 2c23a48c9f0432c290b0cd16a12fb691bb37820c
2018-03-14 16:58:36 -07:00
Adam Retter 5ae32b86ac Brings the Java API for WriteBatch inline with the C++ API
Summary:
* Exposes status
* Corrects some method naming
* Adds missing functionality
Closes https://github.com/facebook/rocksdb/pull/3550

Differential Revision: D7140790

Pulled By: sagar0

fbshipit-source-id: cbdab6c5a7ae4f3030fb46739e9060e381b26fa6
2018-03-14 16:58:02 -07:00
Adam Retter 9e9192c8c6 Add TransactionDB and OptimisticTransactionDB to the Java API
Summary:
Closes https://github.com/facebook/rocksdb/issues/697
Closes https://github.com/facebook/rocksdb/issues/1151
Closes https://github.com/facebook/rocksdb/pull/1298

Differential Revision: D7131402

Pulled By: sagar0

fbshipit-source-id: bcd34ce95ed88cc641786089ff4232df7b2f089f
2018-03-14 16:56:35 -07:00
Siying Dong b04c5d4277 Fix a block pinning regression introduced in b555ed30a4
Summary:
b555ed30a4 introduces a regression, which causes blocks always to be pinned in block based iterators. Fix it.
Closes https://github.com/facebook/rocksdb/pull/3582

Differential Revision: D7189534

Pulled By: siying

fbshipit-source-id: 117dc7a03d0a0e360424db02efb366e12da2be03
2018-03-08 14:05:10 -08:00
Fosco Marotto 8d47fc7199 5.12.fb release 2018-02-28 17:40:14 -08:00
150 changed files with 13128 additions and 896 deletions
+1
View File
@@ -602,6 +602,7 @@ set(SOURCES
utilities/leveldb_options/leveldb_options.cc utilities/leveldb_options/leveldb_options.cc
utilities/lua/rocks_lua_compaction_filter.cc utilities/lua/rocks_lua_compaction_filter.cc
utilities/memory/memory_util.cc utilities/memory/memory_util.cc
utilities/merge_operators/bytesxor.cc
utilities/merge_operators/max.cc utilities/merge_operators/max.cc
utilities/merge_operators/put.cc utilities/merge_operators/put.cc
utilities/merge_operators/string_append/stringappend.cc utilities/merge_operators/string_append/stringappend.cc
+20 -1
View File
@@ -1,11 +1,30 @@
# Rocksdb Change Log # Rocksdb Change Log
## Unreleased ## 5.12.5 (6/18/2018)
### Bug Fixes
* Fix regression bug of Prev() with ReadOptions.iterate_upper_bound.
## 5.12.3 (04/09/2018)
### Bug Fixes
* Fix memory leak when pin_l0_filter_and_index_blocks_in_cache is used with partitioned filters
* Fix memory leak in two_level_iterator
## 5.12.2 (3/23/2018)
### Bug Fixes
* Fsync after writing global seq number to the ingestion file in ExternalSstFileIngestionJob.
### Java API Changes
* Add `BlockBasedTableConfig.setBlockCache` to allow sharing a block cache across DB instances.
## 5.12.1 (3/16/2018)
### Public API Change ### Public API Change
* RocksDBOptionsParser::Parse()'s `ignore_unknown_options` argument will only be effective if the option file shows it is generated using a higher version of RocksDB than the current version. * RocksDBOptionsParser::Parse()'s `ignore_unknown_options` argument will only be effective if the option file shows it is generated using a higher version of RocksDB than the current version.
### New Features ### New Features
* Avoid unnecessarily flushing in `CompactRange()` when the range specified by the user does not overlap unflushed memtables. * Avoid unnecessarily flushing in `CompactRange()` when the range specified by the user does not overlap unflushed memtables.
### Bug Fixes
* Fix WAL corruption caused by race condition between user write thread and backup/checkpoint thread.
## 5.12.0 (2/14/2018) ## 5.12.0 (2/14/2018)
### Public API Change ### Public API Change
* Iterator::SeekForPrev is now a pure virtual method. This is to prevent user who implement the Iterator interface fail to implement SeekForPrev by mistake. * Iterator::SeekForPrev is now a pure virtual method. This is to prevent user who implement the Iterator interface fail to implement SeekForPrev by mistake.
+1
View File
@@ -242,6 +242,7 @@ cpp_library(
"utilities/leveldb_options/leveldb_options.cc", "utilities/leveldb_options/leveldb_options.cc",
"utilities/lua/rocks_lua_compaction_filter.cc", "utilities/lua/rocks_lua_compaction_filter.cc",
"utilities/memory/memory_util.cc", "utilities/memory/memory_util.cc",
"utilities/merge_operators/bytesxor.cc",
"utilities/merge_operators/max.cc", "utilities/merge_operators/max.cc",
"utilities/merge_operators/put.cc", "utilities/merge_operators/put.cc",
"utilities/merge_operators/string_append/stringappend.cc", "utilities/merge_operators/string_append/stringappend.cc",
+5 -3
View File
@@ -51,11 +51,13 @@ if [ -z "$ROCKSDB_NO_FBCODE" -a -d /mnt/gvfs/third-party ]; then
FBCODE_BUILD="true" FBCODE_BUILD="true"
# If we're compiling with TSAN we need pic build # If we're compiling with TSAN we need pic build
PIC_BUILD=$COMPILE_WITH_TSAN PIC_BUILD=$COMPILE_WITH_TSAN
if [ -z "$ROCKSDB_FBCODE_BUILD_WITH_481" ]; then if [ -n "$ROCKSDB_FBCODE_BUILD_WITH_481" ]; then
source "$PWD/build_tools/fbcode_config.sh"
else
# we need this to build with MySQL. Don't use for other purposes. # we need this to build with MySQL. Don't use for other purposes.
source "$PWD/build_tools/fbcode_config4.8.1.sh" source "$PWD/build_tools/fbcode_config4.8.1.sh"
elif [ -n "$ROCKSDB_FBCODE_BUILD_WITH_5xx" ]; then
source "$PWD/build_tools/fbcode_config.sh"
else
source "$PWD/build_tools/fbcode_config_platform007.sh"
fi fi
fi fi
+18
View File
@@ -0,0 +1,18 @@
GCC_BASE=/mnt/gvfs/third-party2/gcc/6e8e715624fd15256a7970073387793dfcf79b46/7.x/centos7-native/b2ef2b6
CLANG_BASE=/mnt/gvfs/third-party2/llvm-fb/ef37e1faa1c29782abfac1ae65a291b9b7966f6d/stable/centos7-native/c9f9104
LIBGCC_BASE=/mnt/gvfs/third-party2/libgcc/c67031f0f739ac61575a061518d6ef5038f99f90/7.x/platform007/5620abc
GLIBC_BASE=/mnt/gvfs/third-party2/glibc/60d6f124a78798b73944f5ba87c2306ae3460153/2.26/platform007/f259413
SNAPPY_BASE=/mnt/gvfs/third-party2/snappy/7f9bdaada18f59bc27ec2b0871eb8a6144343aef/1.1.3/platform007/ca4da3d
ZLIB_BASE=/mnt/gvfs/third-party2/zlib/22c2d65676fb7c23cfa797c4f6937f38b026f3cf/1.2.8/platform007/ca4da3d
BZIP2_BASE=/mnt/gvfs/third-party2/bzip2/dc49a21c5fceec6456a7a28a94dcd16690af1337/1.0.6/platform007/ca4da3d
LZ4_BASE=/mnt/gvfs/third-party2/lz4/907b498203d297947f3bb70b9466f47e100f1873/r131/platform007/ca4da3d
ZSTD_BASE=/mnt/gvfs/third-party2/zstd/3ee276cbacfad3074e3f07bf826ac47f06970f4e/1.3.5/platform007/15a3614
GFLAGS_BASE=/mnt/gvfs/third-party2/gflags/0b9929d2588991c65a57168bf88aff2db87c5d48/2.2.0/platform007/ca4da3d
JEMALLOC_BASE=/mnt/gvfs/third-party2/jemalloc/9c910d36d6235cc40e8ff559358f1833452300ca/master/platform007/5b0f53e
NUMA_BASE=/mnt/gvfs/third-party2/numa/9cbf2460284c669ed19c3ccb200a71f7dd7e53c7/2.0.11/platform007/ca4da3d
LIBUNWIND_BASE=/mnt/gvfs/third-party2/libunwind/bf3d7497fe4e6d007354f0adffa16ce3003f8338/1.3/platform007/6f3e0a9
TBB_BASE=/mnt/gvfs/third-party2/tbb/ff4e0b093534704d8abab678a4fd7f5ea7b094c7/2018_U5/platform007/ca4da3d
KERNEL_HEADERS_BASE=/mnt/gvfs/third-party2/kernel-headers/b5c4a61a5c483ba24722005ae07895971a2ac707/fb/platform007/da39a3e
BINUTILS_BASE=/mnt/gvfs/third-party2/binutils/92ff90349e2f43ea0a8246d8b1cf17b6869013e3/2.29.1/centos7-native/da39a3e
VALGRIND_BASE=/mnt/gvfs/third-party2/valgrind/f3f697a28122e6bcd513273dd9c1ff23852fc59f/3.13.0/platform007/ca4da3d
LUA_BASE=/mnt/gvfs/third-party2/lua/f0cd714433206d5139df61659eb7b28b1dea6683/5.3.4/platform007/5007832
+157
View File
@@ -0,0 +1,157 @@
#!/bin/sh
#
# Set environment variables so that we can compile rocksdb using
# fbcode settings. It uses the latest g++ and clang compilers and also
# uses jemalloc
# Environment variables that change the behavior of this script:
# PIC_BUILD -- if true, it will only take pic versions of libraries from fbcode. libraries that don't have pic variant will not be included
BASEDIR=`dirname $BASH_SOURCE`
source "$BASEDIR/dependencies_platform007.sh"
CFLAGS=""
# libgcc
LIBGCC_INCLUDE="$LIBGCC_BASE/include/c++/7.3.0"
LIBGCC_LIBS=" -L $LIBGCC_BASE/lib"
# glibc
GLIBC_INCLUDE="$GLIBC_BASE/include"
GLIBC_LIBS=" -L $GLIBC_BASE/lib"
# snappy
SNAPPY_INCLUDE=" -I $SNAPPY_BASE/include/"
if test -z $PIC_BUILD; then
SNAPPY_LIBS=" $SNAPPY_BASE/lib/libsnappy.a"
else
SNAPPY_LIBS=" $SNAPPY_BASE/lib/libsnappy_pic.a"
fi
CFLAGS+=" -DSNAPPY"
if test -z $PIC_BUILD; then
# location of zlib headers and libraries
ZLIB_INCLUDE=" -I $ZLIB_BASE/include/"
ZLIB_LIBS=" $ZLIB_BASE/lib/libz.a"
CFLAGS+=" -DZLIB"
# location of bzip headers and libraries
BZIP_INCLUDE=" -I $BZIP2_BASE/include/"
BZIP_LIBS=" $BZIP2_BASE/lib/libbz2.a"
CFLAGS+=" -DBZIP2"
LZ4_INCLUDE=" -I $LZ4_BASE/include/"
LZ4_LIBS=" $LZ4_BASE/lib/liblz4.a"
CFLAGS+=" -DLZ4"
fi
ZSTD_INCLUDE=" -I $ZSTD_BASE/include/"
if test -z $PIC_BUILD; then
ZSTD_LIBS=" $ZSTD_BASE/lib/libzstd.a"
else
ZSTD_LIBS=" $ZSTD_BASE/lib/libzstd_pic.a"
fi
CFLAGS+=" -DZSTD"
# location of gflags headers and libraries
GFLAGS_INCLUDE=" -I $GFLAGS_BASE/include/"
if test -z $PIC_BUILD; then
GFLAGS_LIBS=" $GFLAGS_BASE/lib/libgflags.a"
else
GFLAGS_LIBS=" $GFLAGS_BASE/lib/libgflags_pic.a"
fi
CFLAGS+=" -DGFLAGS=gflags"
# location of jemalloc
JEMALLOC_INCLUDE=" -I $JEMALLOC_BASE/include/"
JEMALLOC_LIB=" $JEMALLOC_BASE/lib/libjemalloc.a"
if test -z $PIC_BUILD; then
# location of numa
NUMA_INCLUDE=" -I $NUMA_BASE/include/"
NUMA_LIB=" $NUMA_BASE/lib/libnuma.a"
CFLAGS+=" -DNUMA"
# location of libunwind
LIBUNWIND="$LIBUNWIND_BASE/lib/libunwind.a"
fi
# location of TBB
TBB_INCLUDE=" -isystem $TBB_BASE/include/"
if test -z $PIC_BUILD; then
TBB_LIBS="$TBB_BASE/lib/libtbb.a"
else
TBB_LIBS="$TBB_BASE/lib/libtbb_pic.a"
fi
CFLAGS+=" -DTBB"
# use Intel SSE support for checksum calculations
export USE_SSE=1
export PORTABLE=1
BINUTILS="$BINUTILS_BASE/bin"
AR="$BINUTILS/ar"
DEPS_INCLUDE="$SNAPPY_INCLUDE $ZLIB_INCLUDE $BZIP_INCLUDE $LZ4_INCLUDE $ZSTD_INCLUDE $GFLAGS_INCLUDE $NUMA_INCLUDE $TBB_INCLUDE"
STDLIBS="-L $GCC_BASE/lib64"
CLANG_BIN="$CLANG_BASE/bin"
CLANG_LIB="$CLANG_BASE/lib"
CLANG_SRC="$CLANG_BASE/../../src"
CLANG_ANALYZER="$CLANG_BIN/clang++"
CLANG_SCAN_BUILD="$CLANG_SRC/llvm/tools/clang/tools/scan-build/bin/scan-build"
if [ -z "$USE_CLANG" ]; then
# gcc
CC="$GCC_BASE/bin/gcc"
CXX="$GCC_BASE/bin/g++"
CFLAGS+=" -B$BINUTILS/gold"
CFLAGS+=" -isystem $LIBGCC_INCLUDE"
CFLAGS+=" -isystem $GLIBC_INCLUDE"
JEMALLOC=1
else
# clang
CLANG_INCLUDE="$CLANG_LIB/clang/stable/include"
CC="$CLANG_BIN/clang"
CXX="$CLANG_BIN/clang++"
KERNEL_HEADERS_INCLUDE="$KERNEL_HEADERS_BASE/include"
CFLAGS+=" -B$BINUTILS/gold -nostdinc -nostdlib"
CFLAGS+=" -isystem $LIBGCC_BASE/include/c++/7.x "
CFLAGS+=" -isystem $LIBGCC_BASE/include/c++/7.x/x86_64-facebook-linux "
CFLAGS+=" -isystem $GLIBC_INCLUDE"
CFLAGS+=" -isystem $LIBGCC_INCLUDE"
CFLAGS+=" -isystem $CLANG_INCLUDE"
CFLAGS+=" -isystem $KERNEL_HEADERS_INCLUDE/linux "
CFLAGS+=" -isystem $KERNEL_HEADERS_INCLUDE "
CFLAGS+=" -Wno-expansion-to-defined "
CXXFLAGS="-nostdinc++"
fi
CFLAGS+=" $DEPS_INCLUDE"
CFLAGS+=" -DROCKSDB_PLATFORM_POSIX -DROCKSDB_LIB_IO_POSIX -DROCKSDB_FALLOCATE_PRESENT -DROCKSDB_MALLOC_USABLE_SIZE -DROCKSDB_RANGESYNC_PRESENT -DROCKSDB_SCHED_GETCPU_PRESENT -DROCKSDB_SUPPORT_THREAD_LOCAL -DHAVE_SSE42"
CXXFLAGS+=" $CFLAGS"
EXEC_LDFLAGS=" $SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GFLAGS_LIBS $NUMA_LIB $TBB_LIBS"
EXEC_LDFLAGS+=" -B$BINUTILS/gold"
EXEC_LDFLAGS+=" -Wl,--dynamic-linker,/usr/local/fbcode/platform007/lib/ld.so"
EXEC_LDFLAGS+=" $LIBUNWIND"
EXEC_LDFLAGS+=" -Wl,-rpath=/usr/local/fbcode/platform007/lib"
# required by libtbb
EXEC_LDFLAGS+=" -ldl"
PLATFORM_LDFLAGS="$LIBGCC_LIBS $GLIBC_LIBS $STDLIBS -lgcc -lstdc++"
EXEC_LDFLAGS_SHARED="$SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GFLAGS_LIBS $TBB_LIBS"
VALGRIND_VER="$VALGRIND_BASE/bin/"
# lua not supported because it's on track for deprecation, I think
LUA_PATH=
LUA_LIB=
export CC CXX AR CFLAGS CXXFLAGS EXEC_LDFLAGS EXEC_LDFLAGS_SHARED VALGRIND_VER JEMALLOC_LIB JEMALLOC_INCLUDE CLANG_ANALYZER CLANG_SCAN_BUILD LUA_PATH LUA_LIB
+3 -2
View File
@@ -85,8 +85,9 @@ NON_SHM="TMPD=/tmp/rocksdb_test_tmp"
GCC_481="ROCKSDB_FBCODE_BUILD_WITH_481=1" GCC_481="ROCKSDB_FBCODE_BUILD_WITH_481=1"
ASAN="COMPILE_WITH_ASAN=1" ASAN="COMPILE_WITH_ASAN=1"
CLANG="USE_CLANG=1" CLANG="USE_CLANG=1"
LITE="OPT=\"-DROCKSDB_LITE -g\"" # in gcc-5 there are known problems with TSAN like https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71090.
TSAN="COMPILE_WITH_TSAN=1" # using platform007 gives us gcc-8 or higher which has that bug fixed.
TSAN="ROCKSDB_FBCODE_BUILD_WITH_PLATFORM007=1 COMPILE_WITH_TSAN=1"
UBSAN="COMPILE_WITH_UBSAN=1" UBSAN="COMPILE_WITH_UBSAN=1"
DISABLE_JEMALLOC="DISABLE_JEMALLOC=1" DISABLE_JEMALLOC="DISABLE_JEMALLOC=1"
HTTP_PROXY="https_proxy=http://fwdproxy.29.prn1:8080 http_proxy=http://fwdproxy.29.prn1:8080 ftp_proxy=http://fwdproxy.29.prn1:8080" HTTP_PROXY="https_proxy=http://fwdproxy.29.prn1:8080 http_proxy=http://fwdproxy.29.prn1:8080 ftp_proxy=http://fwdproxy.29.prn1:8080"
+39
View File
@@ -53,6 +53,45 @@ function get_lib_base()
log_variable $__res_var log_variable $__res_var
} }
###########################################################
# platform007 dependencies #
###########################################################
OUTPUT="$BASEDIR/dependencies_platform007.sh"
rm -f "$OUTPUT"
touch "$OUTPUT"
echo "Writing dependencies to $OUTPUT"
# Compilers locations
GCC_BASE=`readlink -f $TP2_LATEST/gcc/7.x/centos7-native/*/`
CLANG_BASE=`readlink -f $TP2_LATEST/llvm-fb/stable/centos7-native/*/`
log_variable GCC_BASE
log_variable CLANG_BASE
# Libraries locations
get_lib_base libgcc 7.x platform007
get_lib_base glibc 2.26 platform007
get_lib_base snappy LATEST platform007
get_lib_base zlib LATEST platform007
get_lib_base bzip2 LATEST platform007
get_lib_base lz4 LATEST platform007
get_lib_base zstd LATEST platform007
get_lib_base gflags LATEST platform007
get_lib_base jemalloc LATEST platform007
get_lib_base numa LATEST platform007
get_lib_base libunwind LATEST platform007
get_lib_base tbb LATEST platform007
get_lib_base kernel-headers fb platform007
get_lib_base binutils LATEST centos7-native
get_lib_base valgrind LATEST platform007
get_lib_base lua 5.3.4 platform007
git diff $OUTPUT
########################################################### ###########################################################
# 5.x dependencies # # 5.x dependencies #
########################################################### ###########################################################
+27 -50
View File
@@ -1388,23 +1388,24 @@ void rocksdb_writebatch_put_log_data(
b->rep.PutLogData(Slice(blob, len)); b->rep.PutLogData(Slice(blob, len));
} }
class H : public WriteBatch::Handler {
public:
void* state_;
void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen);
void (*deleted_)(void*, const char* k, size_t klen);
virtual void Put(const Slice& key, const Slice& value) override {
(*put_)(state_, key.data(), key.size(), value.data(), value.size());
}
virtual void Delete(const Slice& key) override {
(*deleted_)(state_, key.data(), key.size());
}
};
void rocksdb_writebatch_iterate( void rocksdb_writebatch_iterate(
rocksdb_writebatch_t* b, rocksdb_writebatch_t* b,
void* state, void* state,
void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen), void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen),
void (*deleted)(void*, const char* k, size_t klen)) { void (*deleted)(void*, const char* k, size_t klen)) {
class H : public WriteBatch::Handler {
public:
void* state_;
void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen);
void (*deleted_)(void*, const char* k, size_t klen);
virtual void Put(const Slice& key, const Slice& value) override {
(*put_)(state_, key.data(), key.size(), value.data(), value.size());
}
virtual void Delete(const Slice& key) override {
(*deleted_)(state_, key.data(), key.size());
}
};
H handler; H handler;
handler.state_ = state; handler.state_ = state;
handler.put_ = put; handler.put_ = put;
@@ -1649,18 +1650,6 @@ void rocksdb_writebatch_wi_iterate(
void* state, void* state,
void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen), void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen),
void (*deleted)(void*, const char* k, size_t klen)) { void (*deleted)(void*, const char* k, size_t klen)) {
class H : public WriteBatch::Handler {
public:
void* state_;
void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen);
void (*deleted_)(void*, const char* k, size_t klen);
virtual void Put(const Slice& key, const Slice& value) override {
(*put_)(state_, key.data(), key.size(), value.data(), value.size());
}
virtual void Delete(const Slice& key) override {
(*deleted_)(state_, key.data(), key.size());
}
};
H handler; H handler;
handler.state_ = state; handler.state_ = state;
handler.put_ = put; handler.put_ = put;
@@ -3109,20 +3098,21 @@ void rocksdb_slicetransform_destroy(rocksdb_slicetransform_t* st) {
delete st; delete st;
} }
struct Wrapper : public rocksdb_slicetransform_t {
const SliceTransform* rep_;
~Wrapper() { delete rep_; }
const char* Name() const override { return rep_->Name(); }
Slice Transform(const Slice& src) const override {
return rep_->Transform(src);
}
bool InDomain(const Slice& src) const override {
return rep_->InDomain(src);
}
bool InRange(const Slice& src) const override { return rep_->InRange(src); }
static void DoNothing(void*) { }
};
rocksdb_slicetransform_t* rocksdb_slicetransform_create_fixed_prefix(size_t prefixLen) { rocksdb_slicetransform_t* rocksdb_slicetransform_create_fixed_prefix(size_t prefixLen) {
struct Wrapper : public rocksdb_slicetransform_t {
const SliceTransform* rep_;
~Wrapper() { delete rep_; }
const char* Name() const override { return rep_->Name(); }
Slice Transform(const Slice& src) const override {
return rep_->Transform(src);
}
bool InDomain(const Slice& src) const override {
return rep_->InDomain(src);
}
bool InRange(const Slice& src) const override { return rep_->InRange(src); }
static void DoNothing(void*) { }
};
Wrapper* wrapper = new Wrapper; Wrapper* wrapper = new Wrapper;
wrapper->rep_ = rocksdb::NewFixedPrefixTransform(prefixLen); wrapper->rep_ = rocksdb::NewFixedPrefixTransform(prefixLen);
wrapper->state_ = nullptr; wrapper->state_ = nullptr;
@@ -3131,19 +3121,6 @@ rocksdb_slicetransform_t* rocksdb_slicetransform_create_fixed_prefix(size_t pref
} }
rocksdb_slicetransform_t* rocksdb_slicetransform_create_noop() { rocksdb_slicetransform_t* rocksdb_slicetransform_create_noop() {
struct Wrapper : public rocksdb_slicetransform_t {
const SliceTransform* rep_;
~Wrapper() { delete rep_; }
const char* Name() const override { return rep_->Name(); }
Slice Transform(const Slice& src) const override {
return rep_->Transform(src);
}
bool InDomain(const Slice& src) const override {
return rep_->InDomain(src);
}
bool InRange(const Slice& src) const override { return rep_->InRange(src); }
static void DoNothing(void*) { }
};
Wrapper* wrapper = new Wrapper; Wrapper* wrapper = new Wrapper;
wrapper->rep_ = rocksdb::NewNoopTransform(); wrapper->rep_ = rocksdb::NewNoopTransform();
wrapper->state_ = nullptr; wrapper->state_ = nullptr;
+7
View File
@@ -383,6 +383,9 @@ class ColumnFamilyTest : public testing::Test {
void AssertFilesPerLevel(const std::string& value, int cf) { void AssertFilesPerLevel(const std::string& value, int cf) {
#ifndef ROCKSDB_LITE #ifndef ROCKSDB_LITE
ASSERT_EQ(value, FilesPerLevel(cf)); ASSERT_EQ(value, FilesPerLevel(cf));
#else
(void) value;
(void) cf;
#endif #endif
} }
@@ -397,6 +400,8 @@ class ColumnFamilyTest : public testing::Test {
void AssertCountLiveFiles(int expected_value) { void AssertCountLiveFiles(int expected_value) {
#ifndef ROCKSDB_LITE #ifndef ROCKSDB_LITE
ASSERT_EQ(expected_value, CountLiveFiles()); ASSERT_EQ(expected_value, CountLiveFiles());
#else
(void) expected_value;
#endif #endif
} }
@@ -445,6 +450,8 @@ class ColumnFamilyTest : public testing::Test {
void AssertCountLiveLogFiles(int value) { void AssertCountLiveLogFiles(int value) {
#ifndef ROCKSDB_LITE // GetSortedWalFiles is not supported #ifndef ROCKSDB_LITE // GetSortedWalFiles is not supported
ASSERT_EQ(value, CountLiveLogFiles()); ASSERT_EQ(value, CountLiveLogFiles());
#else
(void) value;
#endif // !ROCKSDB_LITE #endif // !ROCKSDB_LITE
} }
+1 -1
View File
@@ -319,7 +319,7 @@ int main(int argc, char** argv) {
#else #else
#include <stdio.h> #include <stdio.h>
int main(int argc, char** argv) { int main(int /*argc*/, char** /*argv*/) {
fprintf(stderr, fprintf(stderr,
"SKIPPED as DBImpl::CompactFiles is not supported in ROCKSDB_LITE\n"); "SKIPPED as DBImpl::CompactFiles is not supported in ROCKSDB_LITE\n");
return 0; return 0;
+2 -2
View File
@@ -1034,7 +1034,7 @@ int main(int argc, char** argv) {
#else #else
#include <stdio.h> #include <stdio.h>
int main(int argc, char** argv) { int main(int /*argc*/, char** /*argv*/) {
fprintf(stderr, "SKIPPED, not supported in ROCKSDB_LITE\n"); fprintf(stderr, "SKIPPED, not supported in ROCKSDB_LITE\n");
return 0; return 0;
} }
@@ -1043,5 +1043,5 @@ int main(int argc, char** argv) {
#else #else
int main(int argc, char** argv) { return 0; } int main(int /*argc*/, char** /*argv*/) { return 0; }
#endif // !defined(IOS_CROSS_COMPILE) #endif // !defined(IOS_CROSS_COMPILE)
+1 -1
View File
@@ -946,7 +946,7 @@ int main(int argc, char** argv) {
#else #else
#include <stdio.h> #include <stdio.h>
int main(int argc, char** argv) { int main(int /*argc*/, char** /*argv*/) {
fprintf(stderr, fprintf(stderr,
"SKIPPED as CompactionJobStats is not supported in ROCKSDB_LITE\n"); "SKIPPED as CompactionJobStats is not supported in ROCKSDB_LITE\n");
return 0; return 0;
+1 -1
View File
@@ -510,7 +510,7 @@ int main(int argc, char** argv) {
#else #else
#include <stdio.h> #include <stdio.h>
int main(int argc, char** argv) { int main(int /*argc*/, char** /*argv*/) {
fprintf(stderr, "SKIPPED as RepairDB() is not supported in ROCKSDB_LITE\n"); fprintf(stderr, "SKIPPED as RepairDB() is not supported in ROCKSDB_LITE\n");
return 0; return 0;
} }
+1 -1
View File
@@ -333,7 +333,7 @@ int main(int argc, char** argv) {
#else #else
#include <stdio.h> #include <stdio.h>
int main(int argc, char** argv) { int main(int /*argc*/, char** /*argv*/) {
fprintf(stderr, "SKIPPED as Cuckoo table is not supported in ROCKSDB_LITE\n"); fprintf(stderr, "SKIPPED as Cuckoo table is not supported in ROCKSDB_LITE\n");
return 0; return 0;
} }
+2
View File
@@ -3481,6 +3481,8 @@ int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
#else #else
(void) argc;
(void) argv;
return 0; return 0;
#endif #endif
} }
+2
View File
@@ -501,6 +501,8 @@ int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
#else #else
(void) argc;
(void) argv;
return 0; return 0;
#endif #endif
} }
+6 -4
View File
@@ -36,7 +36,9 @@ class TestIterator : public InternalIterator {
valid_(false), valid_(false),
sequence_number_(0), sequence_number_(0),
iter_(0), iter_(0),
cmp(comparator) {} cmp(comparator) {
data_.reserve(16);
}
void AddPut(std::string argkey, std::string argvalue) { void AddPut(std::string argkey, std::string argvalue) {
Add(argkey, kTypeValue, argvalue); Add(argkey, kTypeValue, argvalue);
@@ -2549,7 +2551,7 @@ TEST_F(DBIterWithMergeIterTest, InnerMergeIteratorDataRace1) {
// MergeIterator::Prev() realized the mem table iterator is at its end // MergeIterator::Prev() realized the mem table iterator is at its end
// and before an SeekToLast() is called. // and before an SeekToLast() is called.
rocksdb::SyncPoint::GetInstance()->SetCallBack( rocksdb::SyncPoint::GetInstance()->SetCallBack(
"MergeIterator::Prev:BeforeSeekToLast", "MergeIterator::Prev:BeforePrev",
[&](void* arg) { internal_iter2_->Add("z", kTypeValue, "7", 12u); }); [&](void* arg) { internal_iter2_->Add("z", kTypeValue, "7", 12u); });
rocksdb::SyncPoint::GetInstance()->EnableProcessing(); rocksdb::SyncPoint::GetInstance()->EnableProcessing();
@@ -2585,7 +2587,7 @@ TEST_F(DBIterWithMergeIterTest, InnerMergeIteratorDataRace2) {
// mem table after MergeIterator::Prev() realized the mem tableiterator is at // mem table after MergeIterator::Prev() realized the mem tableiterator is at
// its end and before an SeekToLast() is called. // its end and before an SeekToLast() is called.
rocksdb::SyncPoint::GetInstance()->SetCallBack( rocksdb::SyncPoint::GetInstance()->SetCallBack(
"MergeIterator::Prev:BeforeSeekToLast", [&](void* arg) { "MergeIterator::Prev:BeforePrev", [&](void* arg) {
internal_iter2_->Add("z", kTypeValue, "7", 12u); internal_iter2_->Add("z", kTypeValue, "7", 12u);
internal_iter2_->Add("z", kTypeValue, "7", 11u); internal_iter2_->Add("z", kTypeValue, "7", 11u);
}); });
@@ -2623,7 +2625,7 @@ TEST_F(DBIterWithMergeIterTest, InnerMergeIteratorDataRace3) {
// mem table after MergeIterator::Prev() realized the mem table iterator is at // mem table after MergeIterator::Prev() realized the mem table iterator is at
// its end and before an SeekToLast() is called. // its end and before an SeekToLast() is called.
rocksdb::SyncPoint::GetInstance()->SetCallBack( rocksdb::SyncPoint::GetInstance()->SetCallBack(
"MergeIterator::Prev:BeforeSeekToLast", [&](void* arg) { "MergeIterator::Prev:BeforePrev", [&](void* arg) {
internal_iter2_->Add("z", kTypeValue, "7", 16u, true); internal_iter2_->Add("z", kTypeValue, "7", 16u, true);
internal_iter2_->Add("z", kTypeValue, "7", 15u, true); internal_iter2_->Add("z", kTypeValue, "7", 15u, true);
internal_iter2_->Add("z", kTypeValue, "7", 14u, true); internal_iter2_->Add("z", kTypeValue, "7", 14u, true);
+78
View File
@@ -2043,6 +2043,43 @@ TEST_P(DBIteratorTest, CreationFailure) {
delete iter; delete iter;
} }
TEST_P(DBIteratorTest, UpperBoundWithChangeDirection) {
Options options = CurrentOptions();
options.max_sequential_skip_in_iterations = 3;
DestroyAndReopen(options);
// write a bunch of kvs to the database.
ASSERT_OK(Put("a", "1"));
ASSERT_OK(Put("y", "1"));
ASSERT_OK(Put("y1", "1"));
ASSERT_OK(Put("y2", "1"));
ASSERT_OK(Put("y3", "1"));
ASSERT_OK(Put("z", "1"));
ASSERT_OK(Flush());
ASSERT_OK(Put("a", "1"));
ASSERT_OK(Put("z", "1"));
ASSERT_OK(Put("bar", "1"));
ASSERT_OK(Put("foo", "1"));
std::string upper_bound = "x";
Slice ub_slice(upper_bound);
ReadOptions ro;
ro.iterate_upper_bound = &ub_slice;
ro.max_skippable_internal_keys = 1000;
Iterator* iter = NewIterator(ro);
iter->Seek("foo");
ASSERT_TRUE(iter->Valid());
ASSERT_EQ("foo", iter->key().ToString());
iter->Prev();
ASSERT_TRUE(iter->Valid());
ASSERT_OK(iter->status());
ASSERT_EQ("bar", iter->key().ToString());
delete iter;
}
TEST_P(DBIteratorTest, TableFilter) { TEST_P(DBIteratorTest, TableFilter) {
ASSERT_OK(Put("a", "1")); ASSERT_OK(Put("a", "1"));
dbfull()->Flush(FlushOptions()); dbfull()->Flush(FlushOptions());
@@ -2109,6 +2146,47 @@ TEST_P(DBIteratorTest, TableFilter) {
} }
} }
TEST_P(DBIteratorTest, UpperBoundWithPrevReseek) {
Options options = CurrentOptions();
options.max_sequential_skip_in_iterations = 3;
DestroyAndReopen(options);
// write a bunch of kvs to the database.
ASSERT_OK(Put("a", "1"));
ASSERT_OK(Put("y", "1"));
ASSERT_OK(Put("z", "1"));
ASSERT_OK(Flush());
ASSERT_OK(Put("a", "1"));
ASSERT_OK(Put("z", "1"));
ASSERT_OK(Put("bar", "1"));
ASSERT_OK(Put("foo", "1"));
ASSERT_OK(Put("foo", "2"));
ASSERT_OK(Put("foo", "3"));
ASSERT_OK(Put("foo", "4"));
ASSERT_OK(Put("foo", "5"));
const Snapshot* snapshot = db_->GetSnapshot();
ASSERT_OK(Put("foo", "6"));
std::string upper_bound = "x";
Slice ub_slice(upper_bound);
ReadOptions ro;
ro.snapshot = snapshot;
ro.iterate_upper_bound = &ub_slice;
Iterator* iter = NewIterator(ro);
iter->SeekForPrev("goo");
ASSERT_TRUE(iter->Valid());
ASSERT_EQ("foo", iter->key().ToString());
iter->Prev();
ASSERT_TRUE(iter->Valid());
ASSERT_EQ("bar", iter->key().ToString());
delete iter;
db_->ReleaseSnapshot(snapshot);
}
TEST_P(DBIteratorTest, SkipStatistics) { TEST_P(DBIteratorTest, SkipStatistics) {
Options options = CurrentOptions(); Options options = CurrentOptions();
options.statistics = rocksdb::CreateDBStatistics(); options.statistics = rocksdb::CreateDBStatistics();
+2
View File
@@ -289,6 +289,8 @@ int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
#else #else
(void) argc;
(void) argv;
return 0; return 0;
#endif #endif
} }
+2
View File
@@ -809,6 +809,8 @@ int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
#else #else
(void) argc;
(void) argv;
return 0; return 0;
#endif #endif
} }
+2
View File
@@ -1759,6 +1759,8 @@ int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
#else #else
(void) argc;
(void) argv;
return 0; return 0;
#endif #endif
} }
+1 -1
View File
@@ -500,7 +500,7 @@ int main(int argc, char** argv) {
#else #else
#include <stdio.h> #include <stdio.h>
int main(int argc, char** argv) { int main(int /*argc*/, char** /*argv*/) {
fprintf(stderr, fprintf(stderr,
"SKIPPED as DBImpl::DeleteFile is not supported in ROCKSDB_LITE\n"); "SKIPPED as DBImpl::DeleteFile is not supported in ROCKSDB_LITE\n");
return 0; return 0;
+3
View File
@@ -509,6 +509,9 @@ Status ExternalSstFileIngestionJob::AssignGlobalSeqnoForIngestedFile(
std::string seqno_val; std::string seqno_val;
PutFixed64(&seqno_val, seqno); PutFixed64(&seqno_val, seqno);
status = rwfile->Write(file_to_ingest->global_seqno_offset, seqno_val); status = rwfile->Write(file_to_ingest->global_seqno_offset, seqno_val);
if (status.ok()) {
status = rwfile->Fsync();
}
if (status.ok()) { if (status.ok()) {
file_to_ingest->assigned_seqno = seqno; file_to_ingest->assigned_seqno = seqno;
} }
+1 -1
View File
@@ -2001,7 +2001,7 @@ int main(int argc, char** argv) {
#else #else
#include <stdio.h> #include <stdio.h>
int main(int argc, char** argv) { int main(int /*argc*/, char** /*argv*/) {
fprintf(stderr, fprintf(stderr,
"SKIPPED as External SST File Writer and Ingestion are not supported " "SKIPPED as External SST File Writer and Ingestion are not supported "
"in ROCKSDB_LITE\n"); "in ROCKSDB_LITE\n");
+1 -1
View File
@@ -112,7 +112,7 @@ int main(int argc, char** argv) {
#include <cstdio> #include <cstdio>
int main(int argc, char** argv) { int main(int /*argc*/, char** /*argv*/) {
printf("Skipped as Options file is not supported in RocksDBLite.\n"); printf("Skipped as Options file is not supported in RocksDBLite.\n");
return 0; return 0;
} }
+1 -1
View File
@@ -1170,7 +1170,7 @@ int main(int argc, char** argv) {
#else #else
#include <stdio.h> #include <stdio.h>
int main(int argc, char** argv) { int main(int /*argc*/, char** /*argv*/) {
fprintf(stderr, "SKIPPED as plain table is not supported in ROCKSDB_LITE\n"); fprintf(stderr, "SKIPPED as plain table is not supported in ROCKSDB_LITE\n");
return 0; return 0;
} }
+1 -1
View File
@@ -887,7 +887,7 @@ int main(int argc, char** argv) {
#else #else
#include <stdio.h> #include <stdio.h>
int main(int argc, char** argv) { int main(int /*argc*/, char** /*argv*/) {
fprintf(stderr, fprintf(stderr,
"SKIPPED as HashSkipList and HashLinkList are not supported in " "SKIPPED as HashSkipList and HashLinkList are not supported in "
"ROCKSDB_LITE\n"); "ROCKSDB_LITE\n");
+1 -1
View File
@@ -356,7 +356,7 @@ int main(int argc, char** argv) {
#else #else
#include <stdio.h> #include <stdio.h>
int main(int argc, char** argv) { int main(int /*argc*/, char** /*argv*/) {
fprintf(stderr, "SKIPPED as RepairDB is not supported in ROCKSDB_LITE\n"); fprintf(stderr, "SKIPPED as RepairDB is not supported in ROCKSDB_LITE\n");
return 0; return 0;
} }
+1 -1
View File
@@ -303,7 +303,7 @@ int main(int argc, char** argv) {
#else #else
#include <stdio.h> #include <stdio.h>
int main(int argc, char** argv) { int main(int /*argc*/, char** /*argv*/) {
fprintf(stderr, "SKIPPED as WalManager is not supported in ROCKSDB_LITE\n"); fprintf(stderr, "SKIPPED as WalManager is not supported in ROCKSDB_LITE\n");
return 0; return 0;
} }
+1 -1
View File
@@ -433,7 +433,7 @@ int main(int argc, char** argv) {
#else #else
#include <stdio.h> #include <stdio.h>
int main(int argc, char** argv) { int main(int /*argc*/, char** /*argv*/) {
fprintf(stderr, fprintf(stderr,
"SKIPPED as WriteWithCallback is not supported in ROCKSDB_LITE\n"); "SKIPPED as WriteWithCallback is not supported in ROCKSDB_LITE\n");
return 0; return 0;
+6 -2
View File
@@ -873,8 +873,12 @@ void PosixWritableFile::SetWriteLifeTimeHint(Env::WriteLifeTimeHint hint) {
if (fcntl(fd_, F_SET_RW_HINT, &hint) == 0) { if (fcntl(fd_, F_SET_RW_HINT, &hint) == 0) {
write_hint_ = hint; write_hint_ = hint;
} }
#endif #else
#endif (void)hint;
#endif // ROCKSDB_VALGRIND_RUN
#else
(void)hint;
#endif // OS_LINUX
} }
Status PosixWritableFile::InvalidateCache(size_t offset, size_t length) { Status PosixWritableFile::InvalidateCache(size_t offset, size_t length) {
+2 -2
View File
@@ -5,8 +5,8 @@
#pragma once #pragma once
#define ROCKSDB_MAJOR 5 #define ROCKSDB_MAJOR 5
#define ROCKSDB_MINOR 10 #define ROCKSDB_MINOR 12
#define ROCKSDB_PATCH 0 #define ROCKSDB_PATCH 5
// Do not use these. We made the mistake of declaring macros starting with // Do not use these. We made the mistake of declaring macros starting with
// double underscore. Now we have to live with our choice. We'll deprecate these // double underscore. Now we have to live with our choice. We'll deprecate these
+10
View File
@@ -24,6 +24,7 @@ set(JNI_NATIVE_SOURCES
rocksjni/lru_cache.cc rocksjni/lru_cache.cc
rocksjni/memtablejni.cc rocksjni/memtablejni.cc
rocksjni/merge_operator.cc rocksjni/merge_operator.cc
rocksjni/native_comparator_wrapper_test.cc
rocksjni/options.cc rocksjni/options.cc
rocksjni/options_util.cc rocksjni/options_util.cc
rocksjni/ratelimiterjni.cc rocksjni/ratelimiterjni.cc
@@ -87,6 +88,8 @@ set(NATIVE_JAVA_CLASSES
org.rocksdb.LRUCache org.rocksdb.LRUCache
org.rocksdb.MemTableConfig org.rocksdb.MemTableConfig
org.rocksdb.MergeOperator org.rocksdb.MergeOperator
org.rocksdb.NativeComparatorWrapper
org.rocksdb.NativeComparatorWrapperTest.NativeStringComparatorWrapper
org.rocksdb.NativeLibraryLoader org.rocksdb.NativeLibraryLoader
org.rocksdb.Options org.rocksdb.Options
org.rocksdb.OptionsUtil org.rocksdb.OptionsUtil
@@ -122,6 +125,8 @@ set(NATIVE_JAVA_CLASSES
org.rocksdb.WriteBatchTestInternalHelper org.rocksdb.WriteBatchTestInternalHelper
org.rocksdb.WriteBatchWithIndex org.rocksdb.WriteBatchWithIndex
org.rocksdb.WriteOptions org.rocksdb.WriteOptions
org.rocksdb.util.CapturingWriteBatchHandler
org.rocksdb.util.WriteBatchGetter
) )
include(FindJava) include(FindJava)
@@ -177,6 +182,7 @@ add_jar(
src/main/java/org/rocksdb/CompactionStyle.java src/main/java/org/rocksdb/CompactionStyle.java
src/main/java/org/rocksdb/Comparator.java src/main/java/org/rocksdb/Comparator.java
src/main/java/org/rocksdb/ComparatorOptions.java src/main/java/org/rocksdb/ComparatorOptions.java
src/main/java/org/rocksdb/ComparatorType.java
src/main/java/org/rocksdb/CompressionOptions.java src/main/java/org/rocksdb/CompressionOptions.java
src/main/java/org/rocksdb/CompressionType.java src/main/java/org/rocksdb/CompressionType.java
src/main/java/org/rocksdb/DBOptions.java src/main/java/org/rocksdb/DBOptions.java
@@ -203,6 +209,7 @@ add_jar(
src/main/java/org/rocksdb/MergeOperator.java src/main/java/org/rocksdb/MergeOperator.java
src/main/java/org/rocksdb/MutableColumnFamilyOptions.java src/main/java/org/rocksdb/MutableColumnFamilyOptions.java
src/main/java/org/rocksdb/MutableColumnFamilyOptionsInterface.java src/main/java/org/rocksdb/MutableColumnFamilyOptionsInterface.java
src/main/java/org/rocksdb/NativeComparatorWrapper.java
src/main/java/org/rocksdb/NativeLibraryLoader.java src/main/java/org/rocksdb/NativeLibraryLoader.java
src/main/java/org/rocksdb/Options.java src/main/java/org/rocksdb/Options.java
src/main/java/org/rocksdb/OptionsUtil.java src/main/java/org/rocksdb/OptionsUtil.java
@@ -244,11 +251,14 @@ add_jar(
src/main/java/org/rocksdb/WriteOptions.java src/main/java/org/rocksdb/WriteOptions.java
src/test/java/org/rocksdb/BackupEngineTest.java src/test/java/org/rocksdb/BackupEngineTest.java
src/test/java/org/rocksdb/IngestExternalFileOptionsTest.java src/test/java/org/rocksdb/IngestExternalFileOptionsTest.java
src/test/java/org/rocksdb/NativeComparatorWrapperTest.java
src/test/java/org/rocksdb/PlatformRandomHelper.java src/test/java/org/rocksdb/PlatformRandomHelper.java
src/test/java/org/rocksdb/RocksDBExceptionTest.java src/test/java/org/rocksdb/RocksDBExceptionTest.java
src/test/java/org/rocksdb/RocksMemoryResource.java src/test/java/org/rocksdb/RocksMemoryResource.java
src/test/java/org/rocksdb/SnapshotTest.java src/test/java/org/rocksdb/SnapshotTest.java
src/test/java/org/rocksdb/WriteBatchTest.java src/test/java/org/rocksdb/WriteBatchTest.java
src/test/java/org/rocksdb/util/CapturingWriteBatchHandler.java
src/test/java/org/rocksdb/util/WriteBatchGetter.java
INCLUDE_JARS ${JAVA_TESTCLASSPATH} INCLUDE_JARS ${JAVA_TESTCLASSPATH}
) )
+31
View File
@@ -1,6 +1,7 @@
NATIVE_JAVA_CLASSES = org.rocksdb.AbstractCompactionFilter\ NATIVE_JAVA_CLASSES = org.rocksdb.AbstractCompactionFilter\
org.rocksdb.AbstractCompactionFilterFactory\ org.rocksdb.AbstractCompactionFilterFactory\
org.rocksdb.AbstractSlice\ org.rocksdb.AbstractSlice\
org.rocksdb.AbstractTransactionNotifier\
org.rocksdb.BackupEngine\ org.rocksdb.BackupEngine\
org.rocksdb.BackupableDBOptions\ org.rocksdb.BackupableDBOptions\
org.rocksdb.BlockBasedTableConfig\ org.rocksdb.BlockBasedTableConfig\
@@ -29,6 +30,9 @@ NATIVE_JAVA_CLASSES = org.rocksdb.AbstractCompactionFilter\
org.rocksdb.Logger\ org.rocksdb.Logger\
org.rocksdb.LRUCache\ org.rocksdb.LRUCache\
org.rocksdb.MergeOperator\ org.rocksdb.MergeOperator\
org.rocksdb.NativeComparatorWrapper\
org.rocksdb.OptimisticTransactionDB\
org.rocksdb.OptimisticTransactionOptions\
org.rocksdb.Options\ org.rocksdb.Options\
org.rocksdb.OptionsUtil\ org.rocksdb.OptionsUtil\
org.rocksdb.PlainTableConfig\ org.rocksdb.PlainTableConfig\
@@ -45,6 +49,10 @@ NATIVE_JAVA_CLASSES = org.rocksdb.AbstractCompactionFilter\
org.rocksdb.Slice\ org.rocksdb.Slice\
org.rocksdb.SstFileWriter\ org.rocksdb.SstFileWriter\
org.rocksdb.Statistics\ org.rocksdb.Statistics\
org.rocksdb.Transaction\
org.rocksdb.TransactionDB\
org.rocksdb.TransactionDBOptions\
org.rocksdb.TransactionOptions\
org.rocksdb.TransactionLogIterator\ org.rocksdb.TransactionLogIterator\
org.rocksdb.TtlDB\ org.rocksdb.TtlDB\
org.rocksdb.VectorMemTableConfig\ org.rocksdb.VectorMemTableConfig\
@@ -57,6 +65,7 @@ NATIVE_JAVA_CLASSES = org.rocksdb.AbstractCompactionFilter\
org.rocksdb.WBWIRocksIterator org.rocksdb.WBWIRocksIterator
NATIVE_JAVA_TEST_CLASSES = org.rocksdb.RocksDBExceptionTest\ NATIVE_JAVA_TEST_CLASSES = org.rocksdb.RocksDBExceptionTest\
org.rocksdb.NativeComparatorWrapperTest.NativeStringComparatorWrapper\
org.rocksdb.WriteBatchTest\ org.rocksdb.WriteBatchTest\
org.rocksdb.WriteBatchTestInternalHelper org.rocksdb.WriteBatchTestInternalHelper
@@ -104,7 +113,11 @@ JAVA_TESTS = org.rocksdb.BackupableDBOptionsTest\
org.rocksdb.MergeTest\ org.rocksdb.MergeTest\
org.rocksdb.MixedOptionsTest\ org.rocksdb.MixedOptionsTest\
org.rocksdb.MutableColumnFamilyOptionsTest\ org.rocksdb.MutableColumnFamilyOptionsTest\
org.rocksdb.NativeComparatorWrapperTest\
org.rocksdb.NativeLibraryLoaderTest\ org.rocksdb.NativeLibraryLoaderTest\
org.rocksdb.OptimisticTransactionTest\
org.rocksdb.OptimisticTransactionDBTest\
org.rocksdb.OptimisticTransactionOptionsTest\
org.rocksdb.OptionsUtilTest\ org.rocksdb.OptionsUtilTest\
org.rocksdb.OptionsTest\ org.rocksdb.OptionsTest\
org.rocksdb.PlainTableConfigTest\ org.rocksdb.PlainTableConfigTest\
@@ -120,6 +133,10 @@ JAVA_TESTS = org.rocksdb.BackupableDBOptionsTest\
org.rocksdb.SliceTest\ org.rocksdb.SliceTest\
org.rocksdb.SnapshotTest\ org.rocksdb.SnapshotTest\
org.rocksdb.SstFileWriterTest\ org.rocksdb.SstFileWriterTest\
org.rocksdb.TransactionTest\
org.rocksdb.TransactionDBTest\
org.rocksdb.TransactionOptionsTest\
org.rocksdb.TransactionDBOptionsTest\
org.rocksdb.TransactionLogIteratorTest\ org.rocksdb.TransactionLogIteratorTest\
org.rocksdb.TtlDBTest\ org.rocksdb.TtlDBTest\
org.rocksdb.StatisticsTest\ org.rocksdb.StatisticsTest\
@@ -209,6 +226,20 @@ column_family_sample: java
java $(JAVA_ARGS) -Djava.library.path=target -cp $(MAIN_CLASSES):$(SAMPLES_MAIN_CLASSES) RocksDBColumnFamilySample /tmp/rocksdbjni java $(JAVA_ARGS) -Djava.library.path=target -cp $(MAIN_CLASSES):$(SAMPLES_MAIN_CLASSES) RocksDBColumnFamilySample /tmp/rocksdbjni
$(AM_V_at)@rm -rf /tmp/rocksdbjni $(AM_V_at)@rm -rf /tmp/rocksdbjni
transaction_sample: java
$(AM_V_GEN)mkdir -p $(SAMPLES_MAIN_CLASSES)
$(AM_V_at)javac -cp $(MAIN_CLASSES) -d $(SAMPLES_MAIN_CLASSES) $(SAMPLES_MAIN_SRC)/TransactionSample.java
$(AM_V_at)@rm -rf /tmp/rocksdbjni
java -ea -Xcheck:jni -Djava.library.path=target -cp $(MAIN_CLASSES):$(SAMPLES_MAIN_CLASSES) TransactionSample /tmp/rocksdbjni
$(AM_V_at)@rm -rf /tmp/rocksdbjni
optimistic_transaction_sample: java
$(AM_V_GEN)mkdir -p $(SAMPLES_MAIN_CLASSES)
$(AM_V_at)javac -cp $(MAIN_CLASSES) -d $(SAMPLES_MAIN_CLASSES) $(SAMPLES_MAIN_SRC)/OptimisticTransactionSample.java
$(AM_V_at)@rm -rf /tmp/rocksdbjni
java -ea -Xcheck:jni -Djava.library.path=target -cp $(MAIN_CLASSES):$(SAMPLES_MAIN_CLASSES) OptimisticTransactionSample /tmp/rocksdbjni
$(AM_V_at)@rm -rf /tmp/rocksdbjni
resolve_test_deps: resolve_test_deps:
test -d "$(JAVA_TEST_LIBDIR)" || mkdir -p "$(JAVA_TEST_LIBDIR)" test -d "$(JAVA_TEST_LIBDIR)" || mkdir -p "$(JAVA_TEST_LIBDIR)"
test -s "$(JAVA_JUNIT_JAR)" || cp $(MVN_LOCAL)/junit/junit/4.12/junit-4.12.jar $(JAVA_TEST_LIBDIR) || curl -k -L -o $(JAVA_JUNIT_JAR) $(SEARCH_REPO_URL)junit/junit/4.12/junit-4.12.jar test -s "$(JAVA_JUNIT_JAR)" || cp $(MVN_LOCAL)/junit/junit/4.12/junit-4.12.jar $(JAVA_TEST_LIBDIR) || curl -k -L -o $(JAVA_JUNIT_JAR) $(SEARCH_REPO_URL)junit/junit/4.12/junit-4.12.jar
+46 -4
View File
@@ -3,8 +3,8 @@
// COPYING file in the root directory) and Apache 2.0 License // COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory). // (found in the LICENSE.Apache file in the root directory).
// //
// This file implements the "bridge" between Java and C++ and enables // This file implements the "bridge" between Java and C++ for
// calling c++ rocksdb::Iterator methods from Java side. // rocksdb::ColumnFamilyHandle.
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -13,14 +13,56 @@
#include "include/org_rocksdb_ColumnFamilyHandle.h" #include "include/org_rocksdb_ColumnFamilyHandle.h"
#include "rocksjni/portal.h" #include "rocksjni/portal.h"
/*
* Class: org_rocksdb_ColumnFamilyHandle
* Method: getName
* Signature: (J)[B
*/
jbyteArray Java_org_rocksdb_ColumnFamilyHandle_getName(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* cfh = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jhandle);
std::string cf_name = cfh->GetName();
return rocksdb::JniUtil::copyBytes(env, cf_name);
}
/*
* Class: org_rocksdb_ColumnFamilyHandle
* Method: getID
* Signature: (J)I
*/
jint Java_org_rocksdb_ColumnFamilyHandle_getID(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* cfh = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jhandle);
const int32_t id = cfh->GetID();
return static_cast<jint>(id);
}
/*
* Class: org_rocksdb_ColumnFamilyHandle
* Method: getDescriptor
* Signature: (J)Lorg/rocksdb/ColumnFamilyDescriptor;
*/
jobject Java_org_rocksdb_ColumnFamilyHandle_getDescriptor(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* cfh = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jhandle);
rocksdb::ColumnFamilyDescriptor desc;
rocksdb::Status s = cfh->GetDescriptor(&desc);
if (s.ok()) {
return rocksdb::ColumnFamilyDescriptorJni::construct(env, &desc);
} else {
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
return nullptr;
}
}
/* /*
* Class: org_rocksdb_ColumnFamilyHandle * Class: org_rocksdb_ColumnFamilyHandle
* Method: disposeInternal * Method: disposeInternal
* Signature: (J)V * Signature: (J)V
*/ */
void Java_org_rocksdb_ColumnFamilyHandle_disposeInternal( void Java_org_rocksdb_ColumnFamilyHandle_disposeInternal(
JNIEnv* env, jobject jobj, jlong handle) { JNIEnv* env, jobject jobj, jlong jhandle) {
auto* cfh = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(handle); auto* cfh = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jhandle);
assert(cfh != nullptr); assert(cfh != nullptr);
delete cfh; delete cfh;
} }
+13
View File
@@ -14,6 +14,7 @@
#include "include/org_rocksdb_Comparator.h" #include "include/org_rocksdb_Comparator.h"
#include "include/org_rocksdb_DirectComparator.h" #include "include/org_rocksdb_DirectComparator.h"
#include "include/org_rocksdb_NativeComparatorWrapper.h"
#include "rocksjni/comparatorjnicallback.h" #include "rocksjni/comparatorjnicallback.h"
#include "rocksjni/portal.h" #include "rocksjni/portal.h"
@@ -49,4 +50,16 @@ jlong Java_org_rocksdb_DirectComparator_createNewDirectComparator0(
new rocksdb::DirectComparatorJniCallback(env, jobj, copt); new rocksdb::DirectComparatorJniCallback(env, jobj, copt);
return reinterpret_cast<jlong>(c); return reinterpret_cast<jlong>(c);
} }
/*
* Class: org_rocksdb_NativeComparatorWrapper
* Method: disposeInternal
* Signature: (J)V
*/
void Java_org_rocksdb_NativeComparatorWrapper_disposeInternal(
JNIEnv* env, jobject jobj, jlong jcomparator_handle) {
auto* comparator =
reinterpret_cast<rocksdb::Comparator*>(jcomparator_handle);
delete comparator;
}
// </editor-fold> // </editor-fold>
@@ -0,0 +1,50 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
#include <jni.h>
#include <string>
#include "rocksdb/comparator.h"
#include "rocksdb/slice.h"
#include "include/org_rocksdb_NativeComparatorWrapperTest_NativeStringComparatorWrapper.h"
namespace rocksdb {
class NativeComparatorWrapperTestStringComparator
: public Comparator {
const char* Name() const {
return "NativeComparatorWrapperTestStringComparator";
}
int Compare(
const Slice& a, const Slice& b) const {
return a.ToString().compare(b.ToString());
}
void FindShortestSeparator(
std::string* start, const Slice& limit) const {
return;
}
void FindShortSuccessor(
std::string* key) const {
return;
}
};
} // end of rocksdb namespace
/*
* Class: org_rocksdb_NativeComparatorWrapperTest_NativeStringComparatorWrapper
* Method: newStringComparator
* Signature: ()J
*/
jlong Java_org_rocksdb_NativeComparatorWrapperTest_00024NativeStringComparatorWrapper_newStringComparator(
JNIEnv* env , jobject jobj) {
auto* comparator =
new rocksdb::NativeComparatorWrapperTestStringComparator();
return reinterpret_cast<jlong>(comparator);
}
+267
View File
@@ -0,0 +1,267 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
//
// This file implements the "bridge" between Java and C++
// for rocksdb::TransactionDB.
#include <jni.h>
#include "include/org_rocksdb_OptimisticTransactionDB.h"
#include "rocksdb/options.h"
#include "rocksdb/utilities/optimistic_transaction_db.h"
#include "rocksdb/utilities/transaction.h"
#include "rocksjni/portal.h"
/*
* Class: org_rocksdb_OptimisticTransactionDB
* Method: open
* Signature: (JLjava/lang/String;)J
*/
jlong Java_org_rocksdb_OptimisticTransactionDB_open__JLjava_lang_String_2(
JNIEnv* env, jclass jcls, jlong joptions_handle, jstring jdb_path) {
const char* db_path = env->GetStringUTFChars(jdb_path, nullptr);
if (db_path == nullptr) {
// exception thrown: OutOfMemoryError
return 0;
}
auto* options = reinterpret_cast<rocksdb::Options*>(joptions_handle);
rocksdb::OptimisticTransactionDB* otdb = nullptr;
rocksdb::Status s =
rocksdb::OptimisticTransactionDB::Open(*options, db_path, &otdb);
env->ReleaseStringUTFChars(jdb_path, db_path);
if (s.ok()) {
return reinterpret_cast<jlong>(otdb);
} else {
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
return 0;
}
}
/*
* Class: org_rocksdb_OptimisticTransactionDB
* Method: open
* Signature: (JLjava/lang/String;[[B[J)[J
*/
jlongArray Java_org_rocksdb_OptimisticTransactionDB_open__JLjava_lang_String_2_3_3B_3J(
JNIEnv* env, jclass jcls, jlong jdb_options_handle, jstring jdb_path,
jobjectArray jcolumn_names, jlongArray jcolumn_options_handles) {
const char* db_path = env->GetStringUTFChars(jdb_path, nullptr);
if (db_path == nullptr) {
// exception thrown: OutOfMemoryError
return nullptr;
}
std::vector<rocksdb::ColumnFamilyDescriptor> column_families;
const jsize len_cols = env->GetArrayLength(jcolumn_names);
if (len_cols > 0) {
if (env->EnsureLocalCapacity(len_cols) != 0) {
// out of memory
env->ReleaseStringUTFChars(jdb_path, db_path);
return nullptr;
}
jlong* jco =
env->GetLongArrayElements(jcolumn_options_handles, nullptr);
if(jco == nullptr) {
// exception thrown: OutOfMemoryError
env->ReleaseStringUTFChars(jdb_path, db_path);
return nullptr;
}
for (int i = 0; i < len_cols; i++) {
const jobject jcn = env->GetObjectArrayElement(jcolumn_names, i);
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT);
env->ReleaseStringUTFChars(jdb_path, db_path);
return nullptr;
}
const jbyteArray jcn_ba = reinterpret_cast<jbyteArray>(jcn);
const jsize jcf_name_len = env->GetArrayLength(jcn_ba);
if (env->EnsureLocalCapacity(jcf_name_len) != 0) {
// out of memory
env->DeleteLocalRef(jcn);
env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT);
env->ReleaseStringUTFChars(jdb_path, db_path);
return nullptr;
}
jbyte* jcf_name = env->GetByteArrayElements(jcn_ba, nullptr);
if (jcf_name == nullptr) {
// exception thrown: OutOfMemoryError
env->DeleteLocalRef(jcn);
env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT);
env->ReleaseStringUTFChars(jdb_path, db_path);
return nullptr;
}
const std::string cf_name(reinterpret_cast<char *>(jcf_name), jcf_name_len);
const rocksdb::ColumnFamilyOptions* cf_options =
reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jco[i]);
column_families.push_back(
rocksdb::ColumnFamilyDescriptor(cf_name, *cf_options));
env->ReleaseByteArrayElements(jcn_ba, jcf_name, JNI_ABORT);
env->DeleteLocalRef(jcn);
}
env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT);
}
auto* db_options = reinterpret_cast<rocksdb::DBOptions*>(jdb_options_handle);
std::vector<rocksdb::ColumnFamilyHandle*> handles;
rocksdb::OptimisticTransactionDB* otdb = nullptr;
const rocksdb::Status s = rocksdb::OptimisticTransactionDB::Open(*db_options,
db_path, column_families, &handles, &otdb);
env->ReleaseStringUTFChars(jdb_path, db_path);
// check if open operation was successful
if (s.ok()) {
const jsize resultsLen = 1 + len_cols; // db handle + column family handles
std::unique_ptr<jlong[]> results =
std::unique_ptr<jlong[]>(new jlong[resultsLen]);
results[0] = reinterpret_cast<jlong>(otdb);
for (int i = 1; i <= len_cols; i++) {
results[i] = reinterpret_cast<jlong>(handles[i - 1]);
}
jlongArray jresults = env->NewLongArray(resultsLen);
if (jresults == nullptr) {
// exception thrown: OutOfMemoryError
return nullptr;
}
env->SetLongArrayRegion(jresults, 0, resultsLen, results.get());
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
return nullptr;
}
return jresults;
}
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
return nullptr;
}
/*
* Class: org_rocksdb_OptimisticTransactionDB
* Method: beginTransaction
* Signature: (JJ)J
*/
jlong Java_org_rocksdb_OptimisticTransactionDB_beginTransaction__JJ(
JNIEnv* env, jobject jobj, jlong jhandle, jlong jwrite_options_handle) {
auto* optimistic_txn_db =
reinterpret_cast<rocksdb::OptimisticTransactionDB*>(jhandle);
auto* write_options =
reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle);
rocksdb::Transaction* txn =
optimistic_txn_db->BeginTransaction(*write_options);
return reinterpret_cast<jlong>(txn);
}
/*
* Class: org_rocksdb_OptimisticTransactionDB
* Method: beginTransaction
* Signature: (JJJ)J
*/
jlong Java_org_rocksdb_OptimisticTransactionDB_beginTransaction__JJJ(
JNIEnv* env, jobject jobj, jlong jhandle, jlong jwrite_options_handle,
jlong joptimistic_txn_options_handle) {
auto* optimistic_txn_db =
reinterpret_cast<rocksdb::OptimisticTransactionDB*>(jhandle);
auto* write_options =
reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle);
auto* optimistic_txn_options =
reinterpret_cast<rocksdb::OptimisticTransactionOptions*>(
joptimistic_txn_options_handle);
rocksdb::Transaction* txn =
optimistic_txn_db->BeginTransaction(*write_options,
*optimistic_txn_options);
return reinterpret_cast<jlong>(txn);
}
/*
* Class: org_rocksdb_OptimisticTransactionDB
* Method: beginTransaction_withOld
* Signature: (JJJ)J
*/
jlong Java_org_rocksdb_OptimisticTransactionDB_beginTransaction_1withOld__JJJ(
JNIEnv* env, jobject jobj, jlong jhandle, jlong jwrite_options_handle,
jlong jold_txn_handle) {
auto* optimistic_txn_db =
reinterpret_cast<rocksdb::OptimisticTransactionDB*>(jhandle);
auto* write_options =
reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle);
auto* old_txn =
reinterpret_cast<rocksdb::Transaction*>(
jold_txn_handle);
rocksdb::OptimisticTransactionOptions optimistic_txn_options;
rocksdb::Transaction* txn =
optimistic_txn_db->BeginTransaction(*write_options,
optimistic_txn_options, old_txn);
// RocksJava relies on the assumption that
// we do not allocate a new Transaction object
// when providing an old_optimistic_txn
assert(txn == old_txn);
return reinterpret_cast<jlong>(txn);
}
/*
* Class: org_rocksdb_OptimisticTransactionDB
* Method: beginTransaction_withOld
* Signature: (JJJJ)J
*/
jlong Java_org_rocksdb_OptimisticTransactionDB_beginTransaction_1withOld__JJJJ(
JNIEnv* env, jobject jobj, jlong jhandle, jlong jwrite_options_handle,
jlong joptimistic_txn_options_handle, jlong jold_txn_handle) {
auto* optimistic_txn_db =
reinterpret_cast<rocksdb::OptimisticTransactionDB*>(jhandle);
auto* write_options =
reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle);
auto* optimistic_txn_options =
reinterpret_cast<rocksdb::OptimisticTransactionOptions*>(
joptimistic_txn_options_handle);
auto* old_txn =
reinterpret_cast<rocksdb::Transaction*>(
jold_txn_handle);
rocksdb::Transaction* txn =
optimistic_txn_db->BeginTransaction(*write_options,
*optimistic_txn_options, old_txn);
// RocksJava relies on the assumption that
// we do not allocate a new Transaction object
// when providing an old_optimisic_txn
assert(txn == old_txn);
return reinterpret_cast<jlong>(txn);
}
/*
* Class: org_rocksdb_OptimisticTransactionDB
* Method: getBaseDB
* Signature: (J)J
*/
jlong Java_org_rocksdb_OptimisticTransactionDB_getBaseDB(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* optimistic_txn_db =
reinterpret_cast<rocksdb::OptimisticTransactionDB*>(jhandle);
return reinterpret_cast<jlong>(optimistic_txn_db->GetBaseDB());
}
/*
* Class: org_rocksdb_OptimisticTransactionDB
* Method: disposeInternal
* Signature: (J)V
*/
void Java_org_rocksdb_OptimisticTransactionDB_disposeInternal(JNIEnv* env,
jobject jobj, jlong jhandle) {
delete reinterpret_cast<rocksdb::OptimisticTransactionDB*>(jhandle);
}
@@ -0,0 +1,72 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
//
// This file implements the "bridge" between Java and C++
// for rocksdb::OptimisticTransactionOptions.
#include <jni.h>
#include "include/org_rocksdb_OptimisticTransactionOptions.h"
#include "rocksdb/comparator.h"
#include "rocksdb/utilities/optimistic_transaction_db.h"
/*
* Class: org_rocksdb_OptimisticTransactionOptions
* Method: newOptimisticTransactionOptions
* Signature: ()J
*/
jlong Java_org_rocksdb_OptimisticTransactionOptions_newOptimisticTransactionOptions(
JNIEnv* env, jclass jcls) {
rocksdb::OptimisticTransactionOptions* opts =
new rocksdb::OptimisticTransactionOptions();
return reinterpret_cast<jlong>(opts);
}
/*
* Class: org_rocksdb_OptimisticTransactionOptions
* Method: isSetSnapshot
* Signature: (J)Z
*/
jboolean Java_org_rocksdb_OptimisticTransactionOptions_isSetSnapshot(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* opts =
reinterpret_cast<rocksdb::OptimisticTransactionOptions*>(jhandle);
return opts->set_snapshot;
}
/*
* Class: org_rocksdb_OptimisticTransactionOptions
* Method: setSetSnapshot
* Signature: (JZ)V
*/
void Java_org_rocksdb_OptimisticTransactionOptions_setSetSnapshot(JNIEnv* env,
jobject jobj, jlong jhandle, jboolean jset_snapshot) {
auto* opts =
reinterpret_cast<rocksdb::OptimisticTransactionOptions*>(jhandle);
opts->set_snapshot = jset_snapshot;
}
/*
* Class: org_rocksdb_OptimisticTransactionOptions
* Method: setComparator
* Signature: (JJ)V
*/
void Java_org_rocksdb_OptimisticTransactionOptions_setComparator(
JNIEnv* env, jobject jobj, jlong jhandle, jlong jcomparator_handle) {
auto* opts =
reinterpret_cast<rocksdb::OptimisticTransactionOptions*>(jhandle);
opts->cmp = reinterpret_cast<rocksdb::Comparator*>(jcomparator_handle);
}
/*
* Class: org_rocksdb_OptimisticTransactionOptions
* Method: disposeInternal
* Signature: (J)V
*/
void Java_org_rocksdb_OptimisticTransactionOptions_disposeInternal(JNIEnv* env,
jobject jobj, jlong jhandle) {
delete reinterpret_cast<rocksdb::OptimisticTransactionOptions*>(jhandle);
}
+48 -20
View File
@@ -158,19 +158,33 @@ void Java_org_rocksdb_Options_setComparatorHandle__JI(
/* /*
* Class: org_rocksdb_Options * Class: org_rocksdb_Options
* Method: setComparatorHandle * Method: setComparatorHandle
* Signature: (JJZ)V * Signature: (JJB)V
*/ */
void Java_org_rocksdb_Options_setComparatorHandle__JJZ( void Java_org_rocksdb_Options_setComparatorHandle__JJB(
JNIEnv* env, jobject jobj, jlong jopt_handle, jlong jcomparator_handle, JNIEnv* env, jobject jobj, jlong jopt_handle, jlong jcomparator_handle,
jboolean is_direct) { jbyte jcomparator_type) {
auto* opt = reinterpret_cast<rocksdb::Options*>(jopt_handle); rocksdb::Comparator *comparator = nullptr;
if(is_direct) { switch(jcomparator_type) {
opt->comparator = // JAVA_COMPARATOR
reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jcomparator_handle); case 0x0:
} else { comparator =
opt->comparator = reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator_handle);
reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator_handle); break;
// JAVA_DIRECT_COMPARATOR
case 0x1:
comparator =
reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jcomparator_handle);
break;
// JAVA_NATIVE_COMPARATOR_WRAPPER
case 0x2:
comparator =
reinterpret_cast<rocksdb::Comparator*>(jcomparator_handle);
break;
} }
auto* opt = reinterpret_cast<rocksdb::Options*>(jopt_handle);
opt->comparator = comparator;
} }
/* /*
@@ -2984,19 +2998,33 @@ void Java_org_rocksdb_ColumnFamilyOptions_setComparatorHandle__JI(
/* /*
* Class: org_rocksdb_ColumnFamilyOptions * Class: org_rocksdb_ColumnFamilyOptions
* Method: setComparatorHandle * Method: setComparatorHandle
* Signature: (JJZ)V * Signature: (JJB)V
*/ */
void Java_org_rocksdb_ColumnFamilyOptions_setComparatorHandle__JJZ( void Java_org_rocksdb_ColumnFamilyOptions_setComparatorHandle__JJB(
JNIEnv* env, jobject jobj, jlong jopt_handle, jlong jcomparator_handle, JNIEnv* env, jobject jobj, jlong jopt_handle, jlong jcomparator_handle,
jboolean is_direct) { jbyte jcomparator_type) {
auto* opt = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jopt_handle); rocksdb::Comparator *comparator = nullptr;
if(is_direct) { switch(jcomparator_type) {
opt->comparator = // JAVA_COMPARATOR
reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jcomparator_handle); case 0x0:
} else { comparator =
opt->comparator = reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator_handle);
reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator_handle); break;
// JAVA_DIRECT_COMPARATOR
case 0x1:
comparator =
reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jcomparator_handle);
break;
// JAVA_NATIVE_COMPARATOR_WRAPPER
case 0x2:
comparator =
reinterpret_cast<rocksdb::Comparator*>(jcomparator_handle);
break;
} }
auto* opt = reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jopt_handle);
opt->comparator = comparator;
} }
/* /*
+1376 -62
View File
File diff suppressed because it is too large Load Diff
+24 -14
View File
@@ -20,24 +20,34 @@
/* /*
* Class: org_rocksdb_SstFileWriter * Class: org_rocksdb_SstFileWriter
* Method: newSstFileWriter * Method: newSstFileWriter
* Signature: (JJJZ)J * Signature: (JJJB)J
*/ */
jlong Java_org_rocksdb_SstFileWriter_newSstFileWriter__JJJZ(JNIEnv *env, jlong Java_org_rocksdb_SstFileWriter_newSstFileWriter__JJJB(JNIEnv *env,
jclass jcls, jlong jenvoptions, jlong joptions, jlong jcomparator, jclass jcls, jlong jenvoptions, jlong joptions, jlong jcomparator_handle,
jboolean is_direct) { jbyte jcomparator_type) {
rocksdb::Comparator *comparator = nullptr;
switch(jcomparator_type) {
// JAVA_COMPARATOR
case 0x0:
comparator =
reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator_handle);
break;
// JAVA_DIRECT_COMPARATOR
case 0x1:
comparator =
reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jcomparator_handle);
break;
// JAVA_NATIVE_COMPARATOR_WRAPPER
case 0x2:
comparator =
reinterpret_cast<rocksdb::Comparator*>(jcomparator_handle);
break;
}
auto *env_options = auto *env_options =
reinterpret_cast<const rocksdb::EnvOptions *>(jenvoptions); reinterpret_cast<const rocksdb::EnvOptions *>(jenvoptions);
auto *options = reinterpret_cast<const rocksdb::Options *>(joptions); auto *options = reinterpret_cast<const rocksdb::Options *>(joptions);
rocksdb::Comparator *comparator = nullptr;
if(is_direct) {
comparator =
reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jcomparator);
} else {
comparator =
reinterpret_cast<rocksdb::ComparatorJniCallback*>(jcomparator);
}
rocksdb::SstFileWriter *sst_file_writer = rocksdb::SstFileWriter *sst_file_writer =
new rocksdb::SstFileWriter(*env_options, *options, comparator); new rocksdb::SstFileWriter(*env_options, *options, comparator);
return reinterpret_cast<jlong>(sst_file_writer); return reinterpret_cast<jlong>(sst_file_writer);
+20 -13
View File
@@ -38,13 +38,14 @@ jlong Java_org_rocksdb_PlainTableConfig_newTableFactoryHandle(
/* /*
* Class: org_rocksdb_BlockBasedTableConfig * Class: org_rocksdb_BlockBasedTableConfig
* Method: newTableFactoryHandle * Method: newTableFactoryHandle
* Signature: (ZJIJIIZIZZZJIBBI)J * Signature: (ZJIJJIIZIZZZJIBBI)J
*/ */
jlong Java_org_rocksdb_BlockBasedTableConfig_newTableFactoryHandle( jlong Java_org_rocksdb_BlockBasedTableConfig_newTableFactoryHandle(
JNIEnv* env, jobject jobj, jboolean no_block_cache, jlong block_cache_size, JNIEnv *env, jobject jobj, jboolean no_block_cache, jlong block_cache_size,
jint block_cache_num_shardbits, jlong block_size, jint block_size_deviation, jint block_cache_num_shardbits, jlong jblock_cache, jlong block_size,
jint block_restart_interval, jboolean whole_key_filtering, jint block_size_deviation, jint block_restart_interval,
jlong jfilterPolicy, jboolean cache_index_and_filter_blocks, jboolean whole_key_filtering, jlong jfilter_policy,
jboolean cache_index_and_filter_blocks,
jboolean pin_l0_filter_and_index_blocks_in_cache, jboolean pin_l0_filter_and_index_blocks_in_cache,
jboolean hash_index_allow_collision, jlong block_cache_compressed_size, jboolean hash_index_allow_collision, jlong block_cache_compressed_size,
jint block_cache_compressd_num_shard_bits, jbyte jchecksum_type, jint block_cache_compressd_num_shard_bits, jbyte jchecksum_type,
@@ -52,22 +53,28 @@ jlong Java_org_rocksdb_BlockBasedTableConfig_newTableFactoryHandle(
rocksdb::BlockBasedTableOptions options; rocksdb::BlockBasedTableOptions options;
options.no_block_cache = no_block_cache; options.no_block_cache = no_block_cache;
if (!no_block_cache && block_cache_size > 0) { if (!no_block_cache) {
if (block_cache_num_shardbits > 0) { if (jblock_cache > 0) {
options.block_cache = std::shared_ptr<rocksdb::Cache> *pCache =
rocksdb::NewLRUCache(block_cache_size, block_cache_num_shardbits); reinterpret_cast<std::shared_ptr<rocksdb::Cache> *>(jblock_cache);
} else { options.block_cache = *pCache;
options.block_cache = rocksdb::NewLRUCache(block_cache_size); } else if (block_cache_size > 0) {
if (block_cache_num_shardbits > 0) {
options.block_cache =
rocksdb::NewLRUCache(block_cache_size, block_cache_num_shardbits);
} else {
options.block_cache = rocksdb::NewLRUCache(block_cache_size);
}
} }
} }
options.block_size = block_size; options.block_size = block_size;
options.block_size_deviation = block_size_deviation; options.block_size_deviation = block_size_deviation;
options.block_restart_interval = block_restart_interval; options.block_restart_interval = block_restart_interval;
options.whole_key_filtering = whole_key_filtering; options.whole_key_filtering = whole_key_filtering;
if (jfilterPolicy > 0) { if (jfilter_policy > 0) {
std::shared_ptr<rocksdb::FilterPolicy> *pFilterPolicy = std::shared_ptr<rocksdb::FilterPolicy> *pFilterPolicy =
reinterpret_cast<std::shared_ptr<rocksdb::FilterPolicy> *>( reinterpret_cast<std::shared_ptr<rocksdb::FilterPolicy> *>(
jfilterPolicy); jfilter_policy);
options.filter_policy = *pFilterPolicy; options.filter_policy = *pFilterPolicy;
} }
options.cache_index_and_filter_blocks = cache_index_and_filter_blocks; options.cache_index_and_filter_blocks = cache_index_and_filter_blocks;
File diff suppressed because it is too large Load Diff
+431
View File
@@ -0,0 +1,431 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
//
// This file implements the "bridge" between Java and C++
// for rocksdb::TransactionDB.
#include <jni.h>
#include <functional>
#include <memory>
#include <utility>
#include "include/org_rocksdb_TransactionDB.h"
#include "rocksdb/options.h"
#include "rocksdb/utilities/transaction.h"
#include "rocksdb/utilities/transaction_db.h"
#include "rocksjni/portal.h"
/*
* Class: org_rocksdb_TransactionDB
* Method: open
* Signature: (JJLjava/lang/String;)J
*/
jlong Java_org_rocksdb_TransactionDB_open__JJLjava_lang_String_2(JNIEnv* env,
jclass jcls, jlong joptions_handle, jlong jtxn_db_options_handle,
jstring jdb_path) {
auto* options = reinterpret_cast<rocksdb::Options*>(joptions_handle);
auto* txn_db_options =
reinterpret_cast<rocksdb::TransactionDBOptions*>(jtxn_db_options_handle);
rocksdb::TransactionDB* tdb = nullptr;
const char* db_path = env->GetStringUTFChars(jdb_path, nullptr);
if (db_path == nullptr) {
// exception thrown: OutOfMemoryError
return 0;
}
rocksdb::Status s =
rocksdb::TransactionDB::Open(*options, *txn_db_options, db_path, &tdb);
env->ReleaseStringUTFChars(jdb_path, db_path);
if (s.ok()) {
return reinterpret_cast<jlong>(tdb);
} else {
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
return 0;
}
}
/*
* Class: org_rocksdb_TransactionDB
* Method: open
* Signature: (JJLjava/lang/String;[[B[J)[J
*/
jlongArray Java_org_rocksdb_TransactionDB_open__JJLjava_lang_String_2_3_3B_3J(
JNIEnv* env, jclass jcls, jlong jdb_options_handle,
jlong jtxn_db_options_handle, jstring jdb_path,
jobjectArray jcolumn_names,
jlongArray jcolumn_options_handles) {
const char* db_path = env->GetStringUTFChars(jdb_path, nullptr);
if (db_path == nullptr) {
// exception thrown: OutOfMemoryError
return nullptr;
}
const jsize len_cols = env->GetArrayLength(jcolumn_names);
if (env->EnsureLocalCapacity(len_cols) != 0) {
// out of memory
env->ReleaseStringUTFChars(jdb_path, db_path);
return nullptr;
}
jlong* jco = env->GetLongArrayElements(jcolumn_options_handles, nullptr);
if (jco == nullptr) {
// exception thrown: OutOfMemoryError
env->ReleaseStringUTFChars(jdb_path, db_path);
return nullptr;
}
std::vector<rocksdb::ColumnFamilyDescriptor> column_families;
for (int i = 0; i < len_cols; i++) {
const jobject jcn = env->GetObjectArrayElement(jcolumn_names, i);
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT);
env->ReleaseStringUTFChars(jdb_path, db_path);
return nullptr;
}
const jbyteArray jcn_ba = reinterpret_cast<jbyteArray>(jcn);
jbyte* jcf_name = env->GetByteArrayElements(jcn_ba, nullptr);
if (jcf_name == nullptr) {
// exception thrown: OutOfMemoryError
env->DeleteLocalRef(jcn);
env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT);
env->ReleaseStringUTFChars(jdb_path, db_path);
return nullptr;
}
const int jcf_name_len = env->GetArrayLength(jcn_ba);
if (env->EnsureLocalCapacity(jcf_name_len) != 0) {
// out of memory
env->ReleaseByteArrayElements(jcn_ba, jcf_name, JNI_ABORT);
env->DeleteLocalRef(jcn);
env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT);
env->ReleaseStringUTFChars(jdb_path, db_path);
return nullptr;
}
const std::string cf_name(reinterpret_cast<char *>(jcf_name), jcf_name_len);
const rocksdb::ColumnFamilyOptions* cf_options =
reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jco[i]);
column_families.push_back(
rocksdb::ColumnFamilyDescriptor(cf_name, *cf_options));
env->ReleaseByteArrayElements(jcn_ba, jcf_name, JNI_ABORT);
env->DeleteLocalRef(jcn);
}
env->ReleaseLongArrayElements(jcolumn_options_handles, jco, JNI_ABORT);
auto* db_options = reinterpret_cast<rocksdb::DBOptions*>(jdb_options_handle);
auto* txn_db_options =
reinterpret_cast<rocksdb::TransactionDBOptions*>(jtxn_db_options_handle);
std::vector<rocksdb::ColumnFamilyHandle*> handles;
rocksdb::TransactionDB* tdb = nullptr;
const rocksdb::Status s = rocksdb::TransactionDB::Open(*db_options, *txn_db_options,
db_path, column_families, &handles, &tdb);
// check if open operation was successful
if (s.ok()) {
const jsize resultsLen = 1 + len_cols; // db handle + column family handles
std::unique_ptr<jlong[]> results =
std::unique_ptr<jlong[]>(new jlong[resultsLen]);
results[0] = reinterpret_cast<jlong>(tdb);
for (int i = 1; i <= len_cols; i++) {
results[i] = reinterpret_cast<jlong>(handles[i - 1]);
}
jlongArray jresults = env->NewLongArray(resultsLen);
if (jresults == nullptr) {
// exception thrown: OutOfMemoryError
return nullptr;
}
env->SetLongArrayRegion(jresults, 0, resultsLen, results.get());
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
env->DeleteLocalRef(jresults);
return nullptr;
}
return jresults;
} else {
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
return nullptr;
}
}
/*
* Class: org_rocksdb_TransactionDB
* Method: beginTransaction
* Signature: (JJ)J
*/
jlong Java_org_rocksdb_TransactionDB_beginTransaction__JJ(JNIEnv* env,
jobject jobj, jlong jhandle, jlong jwrite_options_handle) {
auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle);
auto* write_options =
reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle);
rocksdb::Transaction* txn = txn_db->BeginTransaction(*write_options);
return reinterpret_cast<jlong>(txn);
}
/*
* Class: org_rocksdb_TransactionDB
* Method: beginTransaction
* Signature: (JJJ)J
*/
jlong Java_org_rocksdb_TransactionDB_beginTransaction__JJJ(JNIEnv* env,
jobject jobj, jlong jhandle, jlong jwrite_options_handle,
jlong jtxn_options_handle) {
auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle);
auto* write_options =
reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle);
auto* txn_options =
reinterpret_cast<rocksdb::TransactionOptions*>(jtxn_options_handle);
rocksdb::Transaction* txn =
txn_db->BeginTransaction(*write_options, *txn_options);
return reinterpret_cast<jlong>(txn);
}
/*
* Class: org_rocksdb_TransactionDB
* Method: beginTransaction_withOld
* Signature: (JJJ)J
*/
jlong Java_org_rocksdb_TransactionDB_beginTransaction_1withOld__JJJ(
JNIEnv* env, jobject jobj, jlong jhandle, jlong jwrite_options_handle,
jlong jold_txn_handle) {
auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle);
auto* write_options =
reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle);
auto* old_txn = reinterpret_cast<rocksdb::Transaction*>(jold_txn_handle);
rocksdb::TransactionOptions txn_options;
rocksdb::Transaction* txn =
txn_db->BeginTransaction(*write_options, txn_options, old_txn);
// RocksJava relies on the assumption that
// we do not allocate a new Transaction object
// when providing an old_txn
assert(txn == old_txn);
return reinterpret_cast<jlong>(txn);
}
/*
* Class: org_rocksdb_TransactionDB
* Method: beginTransaction_withOld
* Signature: (JJJJ)J
*/
jlong Java_org_rocksdb_TransactionDB_beginTransaction_1withOld__JJJJ(
JNIEnv* env, jobject jobj, jlong jhandle, jlong jwrite_options_handle,
jlong jtxn_options_handle, jlong jold_txn_handle) {
auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle);
auto* write_options =
reinterpret_cast<rocksdb::WriteOptions*>(jwrite_options_handle);
auto* txn_options =
reinterpret_cast<rocksdb::TransactionOptions*>(jtxn_options_handle);
auto* old_txn = reinterpret_cast<rocksdb::Transaction*>(jold_txn_handle);
rocksdb::Transaction* txn = txn_db->BeginTransaction(*write_options,
*txn_options, old_txn);
// RocksJava relies on the assumption that
// we do not allocate a new Transaction object
// when providing an old_txn
assert(txn == old_txn);
return reinterpret_cast<jlong>(txn);
}
/*
* Class: org_rocksdb_TransactionDB
* Method: getTransactionByName
* Signature: (JLjava/lang/String;)J
*/
jlong Java_org_rocksdb_TransactionDB_getTransactionByName(JNIEnv* env,
jobject jobj, jlong jhandle, jstring jname) {
auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle);
const char* name = env->GetStringUTFChars(jname, nullptr);
if (name == nullptr) {
// exception thrown: OutOfMemoryError
return 0;
}
rocksdb::Transaction* txn = txn_db->GetTransactionByName(name);
env->ReleaseStringUTFChars(jname, name);
return reinterpret_cast<jlong>(txn);
}
/*
* Class: org_rocksdb_TransactionDB
* Method: getAllPreparedTransactions
* Signature: (J)[J
*/
jlongArray Java_org_rocksdb_TransactionDB_getAllPreparedTransactions(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle);
std::vector<rocksdb::Transaction*> txns;
txn_db->GetAllPreparedTransactions(&txns);
const size_t size = txns.size();
assert(size < UINT32_MAX); // does it fit in a jint?
const jsize len = static_cast<jsize>(size);
jlong tmp[len];
for (jsize i = 0; i < len; ++i) {
tmp[i] = reinterpret_cast<jlong>(txns[i]);
}
jlongArray jtxns = env->NewLongArray(len);
if (jtxns == nullptr) {
// exception thrown: OutOfMemoryError
return nullptr;
}
env->SetLongArrayRegion(jtxns, 0, len, tmp);
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException
env->DeleteLocalRef(jtxns);
return nullptr;
}
return jtxns;
}
/*
* Class: org_rocksdb_TransactionDB
* Method: getLockStatusData
* Signature: (J)Ljava/util/Map;
*/
jobject Java_org_rocksdb_TransactionDB_getLockStatusData(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle);
const std::unordered_multimap<uint32_t, rocksdb::KeyLockInfo> lock_status_data =
txn_db->GetLockStatusData();
const jobject jlock_status_data = rocksdb::HashMapJni::construct(env,
static_cast<uint32_t>(lock_status_data.size()));
if (jlock_status_data == nullptr) {
// exception occurred
return nullptr;
}
const rocksdb::HashMapJni::FnMapKV<const int32_t, const rocksdb::KeyLockInfo> fn_map_kv =
[env, txn_db, &lock_status_data](const std::pair<const int32_t, const rocksdb::KeyLockInfo>& pair) {
const jobject jlong_column_family_id =
rocksdb::LongJni::valueOf(env, pair.first);
if (jlong_column_family_id == nullptr) {
// an error occurred
return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
}
const jobject jkey_lock_info =
rocksdb::KeyLockInfoJni::construct(env, pair.second);
if (jkey_lock_info == nullptr) {
// an error occurred
return std::unique_ptr<std::pair<jobject, jobject>>(nullptr);
}
return std::unique_ptr<std::pair<jobject, jobject>>(new std::pair<jobject, jobject>(jlong_column_family_id,
jkey_lock_info));
};
if(!rocksdb::HashMapJni::putAll(env, jlock_status_data,
lock_status_data.begin(), lock_status_data.end(), fn_map_kv)) {
// exception occcurred
return nullptr;
}
return jlock_status_data;
}
/*
* Class: org_rocksdb_TransactionDB
* Method: getDeadlockInfoBuffer
* Signature: (J)[Lorg/rocksdb/TransactionDB/DeadlockPath;
*/
jobjectArray Java_org_rocksdb_TransactionDB_getDeadlockInfoBuffer(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle);
const std::vector<rocksdb::DeadlockPath> deadlock_info_buffer =
txn_db->GetDeadlockInfoBuffer();
const jsize deadlock_info_buffer_len =
static_cast<jsize>(deadlock_info_buffer.size());
jobjectArray jdeadlock_info_buffer =
env->NewObjectArray(deadlock_info_buffer_len,
rocksdb::DeadlockPathJni::getJClass(env), nullptr);
if (jdeadlock_info_buffer == nullptr) {
// exception thrown: OutOfMemoryError
return nullptr;
}
jsize jdeadlock_info_buffer_offset = 0;
auto buf_end = deadlock_info_buffer.end();
for (auto buf_it = deadlock_info_buffer.begin(); buf_it != buf_end; ++buf_it) {
const rocksdb::DeadlockPath deadlock_path = *buf_it;
const std::vector<rocksdb::DeadlockInfo> deadlock_infos
= deadlock_path.path;
const jsize deadlock_infos_len =
static_cast<jsize>(deadlock_info_buffer.size());
jobjectArray jdeadlock_infos = env->NewObjectArray(deadlock_infos_len,
rocksdb::DeadlockInfoJni::getJClass(env), nullptr);
if (jdeadlock_infos == nullptr) {
// exception thrown: OutOfMemoryError
env->DeleteLocalRef(jdeadlock_info_buffer);
return nullptr;
}
jsize jdeadlock_infos_offset = 0;
auto infos_end = deadlock_infos.end();
for (auto infos_it = deadlock_infos.begin(); infos_it != infos_end; ++infos_it) {
const rocksdb::DeadlockInfo deadlock_info = *infos_it;
const jobject jdeadlock_info = rocksdb::TransactionDBJni::newDeadlockInfo(
env, jobj, deadlock_info.m_txn_id, deadlock_info.m_cf_id,
deadlock_info.m_waiting_key, deadlock_info.m_exclusive);
if (jdeadlock_info == nullptr) {
// exception occcurred
env->DeleteLocalRef(jdeadlock_info_buffer);
return nullptr;
}
env->SetObjectArrayElement(jdeadlock_infos, jdeadlock_infos_offset++, jdeadlock_info);
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException or ArrayStoreException
env->DeleteLocalRef(jdeadlock_info);
env->DeleteLocalRef(jdeadlock_info_buffer);
return nullptr;
}
}
const jobject jdeadlock_path =
rocksdb::DeadlockPathJni::construct(env, jdeadlock_infos,
deadlock_path.limit_exceeded);
if(jdeadlock_path == nullptr) {
// exception occcurred
env->DeleteLocalRef(jdeadlock_info_buffer);
return nullptr;
}
env->SetObjectArrayElement(jdeadlock_info_buffer, jdeadlock_info_buffer_offset++, jdeadlock_path);
if (env->ExceptionCheck()) {
// exception thrown: ArrayIndexOutOfBoundsException or ArrayStoreException
env->DeleteLocalRef(jdeadlock_path);
env->DeleteLocalRef(jdeadlock_info_buffer);
return nullptr;
}
}
return jdeadlock_info_buffer;
}
/*
* Class: org_rocksdb_TransactionDB
* Method: setDeadlockInfoBufferSize
* Signature: (JI)V
*/
void Java_org_rocksdb_TransactionDB_setDeadlockInfoBufferSize(
JNIEnv* env, jobject jobj, jlong jhandle, jint jdeadlock_info_buffer_size) {
auto* txn_db = reinterpret_cast<rocksdb::TransactionDB*>(jhandle);
txn_db->SetDeadlockInfoBufferSize(jdeadlock_info_buffer_size);
}
/*
* Class: org_rocksdb_TransactionDB
* Method: disposeInternal
* Signature: (J)V
*/
void Java_org_rocksdb_TransactionDB_disposeInternal(JNIEnv* env, jobject jobj,
jlong jhandle) {
delete reinterpret_cast<rocksdb::TransactionDB*>(jhandle);
}
+147
View File
@@ -0,0 +1,147 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
//
// This file implements the "bridge" between Java and C++
// for rocksdb::TransactionDBOptions.
#include <jni.h>
#include "include/org_rocksdb_TransactionDBOptions.h"
#include "rocksdb/utilities/transaction_db.h"
#include "rocksjni/portal.h"
/*
* Class: org_rocksdb_TransactionDBOptions
* Method: newTransactionDBOptions
* Signature: ()J
*/
jlong Java_org_rocksdb_TransactionDBOptions_newTransactionDBOptions(
JNIEnv* env, jclass jcls) {
rocksdb::TransactionDBOptions* opts = new rocksdb::TransactionDBOptions();
return reinterpret_cast<jlong>(opts);
}
/*
* Class: org_rocksdb_TransactionDBOptions
* Method: getMaxNumLocks
* Signature: (J)J
*/
jlong Java_org_rocksdb_TransactionDBOptions_getMaxNumLocks(JNIEnv* env,
jobject jobj, jlong jhandle) {
auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle);
return opts->max_num_locks;
}
/*
* Class: org_rocksdb_TransactionDBOptions
* Method: setMaxNumLocks
* Signature: (JJ)V
*/
void Java_org_rocksdb_TransactionDBOptions_setMaxNumLocks(JNIEnv* env,
jobject jobj, jlong jhandle, jlong jmax_num_locks) {
auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle);
opts->max_num_locks = jmax_num_locks;
}
/*
* Class: org_rocksdb_TransactionDBOptions
* Method: getNumStripes
* Signature: (J)J
*/
jlong Java_org_rocksdb_TransactionDBOptions_getNumStripes(JNIEnv* env,
jobject jobj, jlong jhandle) {
auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle);
return opts->num_stripes;
}
/*
* Class: org_rocksdb_TransactionDBOptions
* Method: setNumStripes
* Signature: (JJ)V
*/
void Java_org_rocksdb_TransactionDBOptions_setNumStripes(JNIEnv* env,
jobject jobj, jlong jhandle, jlong jnum_stripes) {
auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle);
opts->num_stripes = jnum_stripes;
}
/*
* Class: org_rocksdb_TransactionDBOptions
* Method: getTransactionLockTimeout
* Signature: (J)J
*/
jlong Java_org_rocksdb_TransactionDBOptions_getTransactionLockTimeout(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle);
return opts->transaction_lock_timeout;
}
/*
* Class: org_rocksdb_TransactionDBOptions
* Method: setTransactionLockTimeout
* Signature: (JJ)V
*/
void Java_org_rocksdb_TransactionDBOptions_setTransactionLockTimeout(
JNIEnv* env, jobject jobj, jlong jhandle, jlong jtransaction_lock_timeout) {
auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle);
opts->transaction_lock_timeout = jtransaction_lock_timeout;
}
/*
* Class: org_rocksdb_TransactionDBOptions
* Method: getDefaultLockTimeout
* Signature: (J)J
*/
jlong Java_org_rocksdb_TransactionDBOptions_getDefaultLockTimeout(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle);
return opts->default_lock_timeout;
}
/*
* Class: org_rocksdb_TransactionDBOptions
* Method: setDefaultLockTimeout
* Signature: (JJ)V
*/
void Java_org_rocksdb_TransactionDBOptions_setDefaultLockTimeout(
JNIEnv* env, jobject jobj, jlong jhandle, jlong jdefault_lock_timeout) {
auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle);
opts->default_lock_timeout = jdefault_lock_timeout;
}
/*
* Class: org_rocksdb_TransactionDBOptions
* Method: getWritePolicy
* Signature: (J)B
*/
jbyte Java_org_rocksdb_TransactionDBOptions_getWritePolicy(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle);
return rocksdb::TxnDBWritePolicyJni::toJavaTxnDBWritePolicy(opts->write_policy);
}
/*
* Class: org_rocksdb_TransactionDBOptions
* Method: setWritePolicy
* Signature: (JB)V
*/
void Java_org_rocksdb_TransactionDBOptions_setWritePolicy(
JNIEnv* env, jobject jobj, jlong jhandle, jbyte jwrite_policy) {
auto* opts = reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle);
opts->write_policy =
rocksdb::TxnDBWritePolicyJni::toCppTxnDBWritePolicy(jwrite_policy);
}
/*
* Class: org_rocksdb_TransactionDBOptions
* Method: disposeInternal
* Signature: (J)V
*/
void Java_org_rocksdb_TransactionDBOptions_disposeInternal(JNIEnv* env,
jobject jobj, jlong jhandle) {
delete reinterpret_cast<rocksdb::TransactionDBOptions*>(jhandle);
}
+42
View File
@@ -0,0 +1,42 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
//
// This file implements the "bridge" between Java and C++
// for rocksdb::TransactionNotifier.
#include <jni.h>
#include "include/org_rocksdb_AbstractTransactionNotifier.h"
#include "rocksjni/transaction_notifier_jnicallback.h"
/*
* Class: org_rocksdb_AbstractTransactionNotifier
* Method: createNewTransactionNotifier
* Signature: ()J
*/
jlong Java_org_rocksdb_AbstractTransactionNotifier_createNewTransactionNotifier(
JNIEnv* env, jobject jobj) {
auto* transaction_notifier =
new rocksdb::TransactionNotifierJniCallback(env, jobj);
auto* sptr_transaction_notifier =
new std::shared_ptr<rocksdb::TransactionNotifierJniCallback>(
transaction_notifier);
return reinterpret_cast<jlong>(sptr_transaction_notifier);
}
/*
* Class: org_rocksdb_AbstractTransactionNotifier
* Method: disposeInternal
* Signature: (J)V
*/
void Java_org_rocksdb_AbstractTransactionNotifier_disposeInternal(JNIEnv* env,
jobject jobj, jlong jhandle) {
// TODO(AR) refactor to use JniCallback::JniCallback
// when https://github.com/facebook/rocksdb/pull/1241/ is merged
std::shared_ptr<rocksdb::TransactionNotifierJniCallback>* handle =
reinterpret_cast<std::shared_ptr<
rocksdb::TransactionNotifierJniCallback>*>(jhandle);
delete handle;
}
@@ -0,0 +1,39 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
//
// This file implements the callback "bridge" between Java and C++ for
// rocksdb::TransactionNotifier.
#include "rocksjni/transaction_notifier_jnicallback.h"
#include "rocksjni/portal.h"
namespace rocksdb {
TransactionNotifierJniCallback::TransactionNotifierJniCallback(JNIEnv* env,
jobject jtransaction_notifier) : JniCallback(env, jtransaction_notifier) {
// we cache the method id for the JNI callback
m_jsnapshot_created_methodID =
AbstractTransactionNotifierJni::getSnapshotCreatedMethodId(env);
}
void TransactionNotifierJniCallback::SnapshotCreated(
const Snapshot* newSnapshot) {
jboolean attached_thread = JNI_FALSE;
JNIEnv* env = getJniEnv(&attached_thread);
assert(env != nullptr);
env->CallVoidMethod(m_jcallback_obj,
m_jsnapshot_created_methodID, reinterpret_cast<jlong>(newSnapshot));
if(env->ExceptionCheck()) {
// exception thrown from CallVoidMethod
env->ExceptionDescribe(); // print out exception to stderr
releaseJniEnv(attached_thread);
return;
}
releaseJniEnv(attached_thread);
}
} // namespace rocksdb
@@ -0,0 +1,42 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
//
// This file implements the callback "bridge" between Java and C++ for
// rocksdb::TransactionNotifier.
#ifndef JAVA_ROCKSJNI_TRANSACTION_NOTIFIER_JNICALLBACK_H_
#define JAVA_ROCKSJNI_TRANSACTION_NOTIFIER_JNICALLBACK_H_
#include <jni.h>
#include "rocksdb/utilities/transaction.h"
#include "rocksjni/jnicallback.h"
namespace rocksdb {
/**
* This class acts as a bridge between C++
* and Java. The methods in this class will be
* called back from the RocksDB TransactionDB or OptimisticTransactionDB (C++),
* we then callback to the appropriate Java method
* this enables TransactionNotifier to be implemented in Java.
*
* Unlike RocksJava's Comparator JNI Callback, we do not attempt
* to reduce Java object allocations by caching the Snapshot object
* presented to the callback. This could be revisited in future
* if performance is lacking.
*/
class TransactionNotifierJniCallback: public JniCallback,
public TransactionNotifier {
public:
TransactionNotifierJniCallback(JNIEnv* env, jobject jtransaction_notifier);
virtual void SnapshotCreated(const Snapshot* newSnapshot);
private:
jmethodID m_jsnapshot_created_methodID;
};
} // namespace rocksdb
#endif // JAVA_ROCKSJNI_TRANSACTION_NOTIFIER_JNICALLBACK_H_
+166
View File
@@ -0,0 +1,166 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
//
// This file implements the "bridge" between Java and C++
// for rocksdb::TransactionOptions.
#include <jni.h>
#include "include/org_rocksdb_TransactionOptions.h"
#include "rocksdb/utilities/transaction_db.h"
/*
* Class: org_rocksdb_TransactionOptions
* Method: newTransactionOptions
* Signature: ()J
*/
jlong Java_org_rocksdb_TransactionOptions_newTransactionOptions(JNIEnv* env,
jclass jcls) {
auto* opts = new rocksdb::TransactionOptions();
return reinterpret_cast<jlong>(opts);
}
/*
* Class: org_rocksdb_TransactionOptions
* Method: isSetSnapshot
* Signature: (J)Z
*/
jboolean Java_org_rocksdb_TransactionOptions_isSetSnapshot(JNIEnv* env,
jobject jobj, jlong jhandle) {
auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle);
return opts->set_snapshot;
}
/*
* Class: org_rocksdb_TransactionOptions
* Method: setSetSnapshot
* Signature: (JZ)V
*/
void Java_org_rocksdb_TransactionOptions_setSetSnapshot(JNIEnv* env,
jobject jobj, jlong jhandle, jboolean jset_snapshot) {
auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle);
opts->set_snapshot = jset_snapshot;
}
/*
* Class: org_rocksdb_TransactionOptions
* Method: isDeadlockDetect
* Signature: (J)Z
*/
jboolean Java_org_rocksdb_TransactionOptions_isDeadlockDetect(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle);
return opts->deadlock_detect;
}
/*
* Class: org_rocksdb_TransactionOptions
* Method: setDeadlockDetect
* Signature: (JZ)V
*/
void Java_org_rocksdb_TransactionOptions_setDeadlockDetect(
JNIEnv* env, jobject jobj, jlong jhandle, jboolean jdeadlock_detect) {
auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle);
opts->deadlock_detect = jdeadlock_detect;
}
/*
* Class: org_rocksdb_TransactionOptions
* Method: getLockTimeout
* Signature: (J)J
*/
jlong Java_org_rocksdb_TransactionOptions_getLockTimeout(JNIEnv* env,
jobject jobj, jlong jhandle) {
auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle);
return opts->lock_timeout;
}
/*
* Class: org_rocksdb_TransactionOptions
* Method: setLockTimeout
* Signature: (JJ)V
*/
void Java_org_rocksdb_TransactionOptions_setLockTimeout(JNIEnv* env,
jobject jobj, jlong jhandle, jlong jlock_timeout) {
auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle);
opts->lock_timeout = jlock_timeout;
}
/*
* Class: org_rocksdb_TransactionOptions
* Method: getExpiration
* Signature: (J)J
*/
jlong Java_org_rocksdb_TransactionOptions_getExpiration(JNIEnv* env,
jobject jobj, jlong jhandle) {
auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle);
return opts->expiration;
}
/*
* Class: org_rocksdb_TransactionOptions
* Method: setExpiration
* Signature: (JJ)V
*/
void Java_org_rocksdb_TransactionOptions_setExpiration(JNIEnv* env,
jobject jobj, jlong jhandle, jlong jexpiration) {
auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle);
opts->expiration = jexpiration;
}
/*
* Class: org_rocksdb_TransactionOptions
* Method: getDeadlockDetectDepth
* Signature: (J)J
*/
jlong Java_org_rocksdb_TransactionOptions_getDeadlockDetectDepth(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle);
return opts->deadlock_detect_depth;
}
/*
* Class: org_rocksdb_TransactionOptions
* Method: setDeadlockDetectDepth
* Signature: (JJ)V
*/
void Java_org_rocksdb_TransactionOptions_setDeadlockDetectDepth(
JNIEnv* env, jobject jobj, jlong jhandle, jlong jdeadlock_detect_depth) {
auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle);
opts->deadlock_detect_depth = jdeadlock_detect_depth;
}
/*
* Class: org_rocksdb_TransactionOptions
* Method: getMaxWriteBatchSize
* Signature: (J)J
*/
jlong Java_org_rocksdb_TransactionOptions_getMaxWriteBatchSize(
JNIEnv* env, jobject jobj, jlong jhandle) {
auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle);
return opts->max_write_batch_size;
}
/*
* Class: org_rocksdb_TransactionOptions
* Method: setMaxWriteBatchSize
* Signature: (JJ)V
*/
void Java_org_rocksdb_TransactionOptions_setMaxWriteBatchSize(
JNIEnv* env, jobject jobj, jlong jhandle, jlong jmax_write_batch_size) {
auto* opts = reinterpret_cast<rocksdb::TransactionOptions*>(jhandle);
opts->max_write_batch_size = jmax_write_batch_size;
}
/*
* Class: org_rocksdb_TransactionOptions
* Method: disposeInternal
* Signature: (J)V
*/
void Java_org_rocksdb_TransactionOptions_disposeInternal(JNIEnv* env,
jobject jobj, jlong jhandle) {
delete reinterpret_cast<rocksdb::TransactionOptions*>(jhandle);
}
+330 -34
View File
@@ -27,12 +27,34 @@
* Method: newWriteBatch * Method: newWriteBatch
* Signature: (I)J * Signature: (I)J
*/ */
jlong Java_org_rocksdb_WriteBatch_newWriteBatch( jlong Java_org_rocksdb_WriteBatch_newWriteBatch__I(
JNIEnv* env, jclass jcls, jint jreserved_bytes) { JNIEnv* env, jclass jcls, jint jreserved_bytes) {
auto* wb = new rocksdb::WriteBatch(static_cast<size_t>(jreserved_bytes)); auto* wb = new rocksdb::WriteBatch(static_cast<size_t>(jreserved_bytes));
return reinterpret_cast<jlong>(wb); return reinterpret_cast<jlong>(wb);
} }
/*
* Class: org_rocksdb_WriteBatch
* Method: newWriteBatch
* Signature: ([BI)J
*/
jlong Java_org_rocksdb_WriteBatch_newWriteBatch___3BI(
JNIEnv* env, jclass jcls, jbyteArray jserialized,
jint jserialized_length) {
jboolean has_exception = JNI_FALSE;
std::string serialized = rocksdb::JniUtil::byteString<std::string>(env,
jserialized, jserialized_length,
[](const char* str, const size_t len) { return std::string(str, len); },
&has_exception);
if(has_exception == JNI_TRUE) {
// exception occurred
return 0;
}
auto* wb = new rocksdb::WriteBatch(serialized);
return reinterpret_cast<jlong>(wb);
}
/* /*
* Class: org_rocksdb_WriteBatch * Class: org_rocksdb_WriteBatch
* Method: count0 * Method: count0
@@ -90,6 +112,37 @@ void Java_org_rocksdb_WriteBatch_rollbackToSavePoint0(
rocksdb::RocksDBExceptionJni::ThrowNew(env, s); rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
} }
/*
* Class: org_rocksdb_WriteBatch
* Method: popSavePoint
* Signature: (J)V
*/
void Java_org_rocksdb_WriteBatch_popSavePoint(
JNIEnv* env, jobject jobj, jlong jwb_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
auto s = wb->PopSavePoint();
if (s.ok()) {
return;
}
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
}
/*
* Class: org_rocksdb_WriteBatch
* Method: setMaxBytes
* Signature: (JJ)V
*/
void Java_org_rocksdb_WriteBatch_setMaxBytes(
JNIEnv* env, jobject jobj, jlong jwb_handle, jlong jmax_bytes) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
wb->SetMaxBytes(static_cast<size_t>(jmax_bytes));
}
/* /*
* Class: org_rocksdb_WriteBatch * Class: org_rocksdb_WriteBatch
* Method: put * Method: put
@@ -102,10 +155,13 @@ void Java_org_rocksdb_WriteBatch_put__J_3BI_3BI(
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr); assert(wb != nullptr);
auto put = [&wb] (rocksdb::Slice key, rocksdb::Slice value) { auto put = [&wb] (rocksdb::Slice key, rocksdb::Slice value) {
wb->Put(key, value); return wb->Put(key, value);
}; };
rocksdb::JniUtil::kv_op(put, env, jobj, jkey, jkey_len, jentry_value, std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(put, env,
jentry_value_len); jobj, jkey, jkey_len, jentry_value, jentry_value_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
@@ -122,10 +178,13 @@ void Java_org_rocksdb_WriteBatch_put__J_3BI_3BIJ(
auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
assert(cf_handle != nullptr); assert(cf_handle != nullptr);
auto put = [&wb, &cf_handle] (rocksdb::Slice key, rocksdb::Slice value) { auto put = [&wb, &cf_handle] (rocksdb::Slice key, rocksdb::Slice value) {
wb->Put(cf_handle, key, value); return wb->Put(cf_handle, key, value);
}; };
rocksdb::JniUtil::kv_op(put, env, jobj, jkey, jkey_len, jentry_value, std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(put, env,
jentry_value_len); jobj, jkey, jkey_len, jentry_value, jentry_value_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
@@ -140,10 +199,13 @@ void Java_org_rocksdb_WriteBatch_merge__J_3BI_3BI(
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr); assert(wb != nullptr);
auto merge = [&wb] (rocksdb::Slice key, rocksdb::Slice value) { auto merge = [&wb] (rocksdb::Slice key, rocksdb::Slice value) {
wb->Merge(key, value); return wb->Merge(key, value);
}; };
rocksdb::JniUtil::kv_op(merge, env, jobj, jkey, jkey_len, jentry_value, std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(merge, env,
jentry_value_len); jobj, jkey, jkey_len, jentry_value, jentry_value_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
@@ -160,34 +222,41 @@ void Java_org_rocksdb_WriteBatch_merge__J_3BI_3BIJ(
auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
assert(cf_handle != nullptr); assert(cf_handle != nullptr);
auto merge = [&wb, &cf_handle] (rocksdb::Slice key, rocksdb::Slice value) { auto merge = [&wb, &cf_handle] (rocksdb::Slice key, rocksdb::Slice value) {
wb->Merge(cf_handle, key, value); return wb->Merge(cf_handle, key, value);
}; };
rocksdb::JniUtil::kv_op(merge, env, jobj, jkey, jkey_len, jentry_value, std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(merge, env,
jentry_value_len); jobj, jkey, jkey_len, jentry_value, jentry_value_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
* Class: org_rocksdb_WriteBatch * Class: org_rocksdb_WriteBatch
* Method: remove * Method: delete
* Signature: (J[BI)V * Signature: (J[BI)V
*/ */
void Java_org_rocksdb_WriteBatch_remove__J_3BI( void Java_org_rocksdb_WriteBatch_delete__J_3BI(
JNIEnv* env, jobject jobj, jlong jwb_handle, JNIEnv* env, jobject jobj, jlong jwb_handle,
jbyteArray jkey, jint jkey_len) { jbyteArray jkey, jint jkey_len) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr); assert(wb != nullptr);
auto remove = [&wb] (rocksdb::Slice key) { auto remove = [&wb] (rocksdb::Slice key) {
wb->Delete(key); return wb->Delete(key);
}; };
rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len); std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::k_op(remove, env,
jobj, jkey, jkey_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
* Class: org_rocksdb_WriteBatch * Class: org_rocksdb_WriteBatch
* Method: remove * Method: delete
* Signature: (J[BIJ)V * Signature: (J[BIJ)V
*/ */
void Java_org_rocksdb_WriteBatch_remove__J_3BIJ( void Java_org_rocksdb_WriteBatch_delete__J_3BIJ(
JNIEnv* env, jobject jobj, jlong jwb_handle, JNIEnv* env, jobject jobj, jlong jwb_handle,
jbyteArray jkey, jint jkey_len, jlong jcf_handle) { jbyteArray jkey, jint jkey_len, jlong jcf_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
@@ -195,9 +264,55 @@ void Java_org_rocksdb_WriteBatch_remove__J_3BIJ(
auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
assert(cf_handle != nullptr); assert(cf_handle != nullptr);
auto remove = [&wb, &cf_handle] (rocksdb::Slice key) { auto remove = [&wb, &cf_handle] (rocksdb::Slice key) {
wb->Delete(cf_handle, key); return wb->Delete(cf_handle, key);
}; };
rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len); std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::k_op(remove, env,
jobj, jkey, jkey_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
}
/*
* Class: org_rocksdb_WriteBatch
* Method: singleDelete
* Signature: (J[BI)V
*/
void Java_org_rocksdb_WriteBatch_singleDelete__J_3BI(
JNIEnv* env, jobject jobj, jlong jwb_handle, jbyteArray jkey,
jint jkey_len) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
auto single_delete = [&wb] (rocksdb::Slice key) {
return wb->SingleDelete(key);
};
std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::k_op(single_delete,
env, jobj, jkey, jkey_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
}
/*
* Class: org_rocksdb_WriteBatch
* Method: singleDelete
* Signature: (J[BIJ)V
*/
void Java_org_rocksdb_WriteBatch_singleDelete__J_3BIJ(
JNIEnv* env, jobject jobj, jlong jwb_handle, jbyteArray jkey,
jint jkey_len, jlong jcf_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
assert(cf_handle != nullptr);
auto single_delete = [&wb, &cf_handle] (rocksdb::Slice key) {
return wb->SingleDelete(cf_handle, key);
};
std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::k_op(single_delete,
env, jobj, jkey, jkey_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
@@ -205,19 +320,20 @@ void Java_org_rocksdb_WriteBatch_remove__J_3BIJ(
* Method: deleteRange * Method: deleteRange
* Signature: (J[BI[BI)V * Signature: (J[BI[BI)V
*/ */
JNIEXPORT void JNICALL Java_org_rocksdb_WriteBatch_deleteRange__J_3BI_3BI(
JNIEnv*, jobject, jlong, jbyteArray, jint, jbyteArray, jint);
void Java_org_rocksdb_WriteBatch_deleteRange__J_3BI_3BI( void Java_org_rocksdb_WriteBatch_deleteRange__J_3BI_3BI(
JNIEnv* env, jobject jobj, jlong jwb_handle, jbyteArray jbegin_key, JNIEnv* env, jobject jobj, jlong jwb_handle, jbyteArray jbegin_key,
jint jbegin_key_len, jbyteArray jend_key, jint jend_key_len) { jint jbegin_key_len, jbyteArray jend_key, jint jend_key_len) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr); assert(wb != nullptr);
auto deleteRange = [&wb](rocksdb::Slice beginKey, rocksdb::Slice endKey) { auto deleteRange = [&wb](rocksdb::Slice beginKey, rocksdb::Slice endKey) {
wb->DeleteRange(beginKey, endKey); return wb->DeleteRange(beginKey, endKey);
}; };
rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key, jbegin_key_len, std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(
jend_key, jend_key_len); deleteRange, env, jobj, jbegin_key, jbegin_key_len, jend_key,
jend_key_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
@@ -234,11 +350,15 @@ void Java_org_rocksdb_WriteBatch_deleteRange__J_3BI_3BIJ(
auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
assert(cf_handle != nullptr); assert(cf_handle != nullptr);
auto deleteRange = [&wb, &cf_handle](rocksdb::Slice beginKey, auto deleteRange = [&wb, &cf_handle](rocksdb::Slice beginKey,
rocksdb::Slice endKey) { rocksdb::Slice endKey) {
wb->DeleteRange(cf_handle, beginKey, endKey); return wb->DeleteRange(cf_handle, beginKey, endKey);
}; };
rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key, jbegin_key_len, std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(
jend_key, jend_key_len); deleteRange, env, jobj, jbegin_key, jbegin_key_len, jend_key,
jend_key_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
@@ -252,9 +372,13 @@ void Java_org_rocksdb_WriteBatch_putLogData(
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr); assert(wb != nullptr);
auto putLogData = [&wb] (rocksdb::Slice blob) { auto putLogData = [&wb] (rocksdb::Slice blob) {
wb->PutLogData(blob); return wb->PutLogData(blob);
}; };
rocksdb::JniUtil::k_op(putLogData, env, jobj, jblob, jblob_len); std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::k_op(putLogData,
env, jobj, jblob, jblob_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
@@ -263,7 +387,7 @@ void Java_org_rocksdb_WriteBatch_putLogData(
* Signature: (JJ)V * Signature: (JJ)V
*/ */
void Java_org_rocksdb_WriteBatch_iterate( void Java_org_rocksdb_WriteBatch_iterate(
JNIEnv* env , jobject jobj, jlong jwb_handle, jlong handlerHandle) { JNIEnv* env, jobject jobj, jlong jwb_handle, jlong handlerHandle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle); auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr); assert(wb != nullptr);
@@ -276,6 +400,178 @@ void Java_org_rocksdb_WriteBatch_iterate(
rocksdb::RocksDBExceptionJni::ThrowNew(env, s); rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
} }
/*
* Class: org_rocksdb_WriteBatch
* Method: data
* Signature: (J)[B
*/
jbyteArray Java_org_rocksdb_WriteBatch_data(
JNIEnv* env, jobject jobj, jlong jwb_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
auto data = wb->Data();
return rocksdb::JniUtil::copyBytes(env, data);
}
/*
* Class: org_rocksdb_WriteBatch
* Method: getDataSize
* Signature: (J)J
*/
jlong Java_org_rocksdb_WriteBatch_getDataSize(
JNIEnv* env, jobject jobj, jlong jwb_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
auto data_size = wb->GetDataSize();
return static_cast<jlong>(data_size);
}
/*
* Class: org_rocksdb_WriteBatch
* Method: hasPut
* Signature: (J)Z
*/
jboolean Java_org_rocksdb_WriteBatch_hasPut(
JNIEnv* env, jobject jobj, jlong jwb_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
return wb->HasPut();
}
/*
* Class: org_rocksdb_WriteBatch
* Method: hasDelete
* Signature: (J)Z
*/
jboolean Java_org_rocksdb_WriteBatch_hasDelete(
JNIEnv* env, jobject jobj, jlong jwb_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
return wb->HasDelete();
}
/*
* Class: org_rocksdb_WriteBatch
* Method: hasSingleDelete
* Signature: (J)Z
*/
JNIEXPORT jboolean JNICALL Java_org_rocksdb_WriteBatch_hasSingleDelete(
JNIEnv* env , jobject jobj, jlong jwb_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
return wb->HasSingleDelete();
}
/*
* Class: org_rocksdb_WriteBatch
* Method: hasDeleteRange
* Signature: (J)Z
*/
JNIEXPORT jboolean JNICALL Java_org_rocksdb_WriteBatch_hasDeleteRange(
JNIEnv* env , jobject jobj, jlong jwb_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
return wb->HasDeleteRange();
}
/*
* Class: org_rocksdb_WriteBatch
* Method: hasMerge
* Signature: (J)Z
*/
JNIEXPORT jboolean JNICALL Java_org_rocksdb_WriteBatch_hasMerge(
JNIEnv* env , jobject jobj, jlong jwb_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
return wb->HasMerge();
}
/*
* Class: org_rocksdb_WriteBatch
* Method: hasBeginPrepare
* Signature: (J)Z
*/
JNIEXPORT jboolean JNICALL Java_org_rocksdb_WriteBatch_hasBeginPrepare(
JNIEnv* env , jobject jobj, jlong jwb_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
return wb->HasBeginPrepare();
}
/*
* Class: org_rocksdb_WriteBatch
* Method: hasEndPrepare
* Signature: (J)Z
*/
JNIEXPORT jboolean JNICALL Java_org_rocksdb_WriteBatch_hasEndPrepare(
JNIEnv* env , jobject jobj, jlong jwb_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
return wb->HasEndPrepare();
}
/*
* Class: org_rocksdb_WriteBatch
* Method: hasCommit
* Signature: (J)Z
*/
JNIEXPORT jboolean JNICALL Java_org_rocksdb_WriteBatch_hasCommit(
JNIEnv* env , jobject jobj, jlong jwb_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
return wb->HasCommit();
}
/*
* Class: org_rocksdb_WriteBatch
* Method: hasRollback
* Signature: (J)Z
*/
JNIEXPORT jboolean JNICALL Java_org_rocksdb_WriteBatch_hasRollback(
JNIEnv* env , jobject jobj, jlong jwb_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
return wb->HasRollback();
}
/*
* Class: org_rocksdb_WriteBatch
* Method: markWalTerminationPoint
* Signature: (J)V
*/
void Java_org_rocksdb_WriteBatch_markWalTerminationPoint(
JNIEnv* env, jobject jobj, jlong jwb_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
wb->MarkWalTerminationPoint();
}
/*
* Class: org_rocksdb_WriteBatch
* Method: getWalTerminationPoint
* Signature: (J)Lorg/rocksdb/WriteBatch/SavePoint;
*/
jobject Java_org_rocksdb_WriteBatch_getWalTerminationPoint(
JNIEnv* env, jobject jobj, jlong jwb_handle) {
auto* wb = reinterpret_cast<rocksdb::WriteBatch*>(jwb_handle);
assert(wb != nullptr);
auto save_point = wb->GetWalTerminationPoint();
return rocksdb::WriteBatchSavePointJni::construct(env, save_point);
}
/* /*
* Class: org_rocksdb_WriteBatch * Class: org_rocksdb_WriteBatch
* Method: disposeInternal * Method: disposeInternal
+30 -2
View File
@@ -87,8 +87,32 @@ jbyteArray Java_org_rocksdb_WriteBatchTest_getContents(
state.append(")"); state.append(")");
count++; count++;
break; break;
case rocksdb::kTypeSingleDeletion:
state.append("SingleDelete(");
state.append(ikey.user_key.ToString());
state.append(")");
count++;
break;
case rocksdb::kTypeRangeDeletion:
state.append("DeleteRange(");
state.append(ikey.user_key.ToString());
state.append(", ");
state.append(iter->value().ToString());
state.append(")");
count++;
break;
case rocksdb::kTypeLogData:
state.append("LogData(");
state.append(ikey.user_key.ToString());
state.append(")");
count++;
break;
default: default:
assert(false); assert(false);
state.append("Err:Expected(");
state.append(std::to_string(ikey.type));
state.append(")");
count++;
break; break;
} }
state.append("@"); state.append("@");
@@ -96,8 +120,12 @@ jbyteArray Java_org_rocksdb_WriteBatchTest_getContents(
} }
if (!s.ok()) { if (!s.ok()) {
state.append(s.ToString()); state.append(s.ToString());
} else if (count != rocksdb::WriteBatchInternal::Count(b)) { } else if (rocksdb::WriteBatchInternal::Count(b) != count) {
state.append("CountMismatch()"); state.append("Err:CountMismatch(expected=");
state.append(std::to_string(rocksdb::WriteBatchInternal::Count(b)));
state.append(", actual=");
state.append(std::to_string(count));
state.append(")");
} }
delete mem->Unref(); delete mem->Unref();
+178 -62
View File
@@ -39,19 +39,31 @@ jlong Java_org_rocksdb_WriteBatchWithIndex_newWriteBatchWithIndex__Z(
/* /*
* Class: org_rocksdb_WriteBatchWithIndex * Class: org_rocksdb_WriteBatchWithIndex
* Method: newWriteBatchWithIndex * Method: newWriteBatchWithIndex
* Signature: (JZIZ)J * Signature: (JBIZ)J
*/ */
jlong Java_org_rocksdb_WriteBatchWithIndex_newWriteBatchWithIndex__JZIZ( jlong Java_org_rocksdb_WriteBatchWithIndex_newWriteBatchWithIndex__JBIZ(
JNIEnv* env, jclass jcls, jlong jfallback_index_comparator_handle, JNIEnv* env, jclass jcls, jlong jfallback_index_comparator_handle,
jboolean is_direct, jint jreserved_bytes, jboolean joverwrite_key) { jbyte jcomparator_type, jint jreserved_bytes, jboolean joverwrite_key) {
rocksdb::Comparator *fallback_comparator = nullptr; rocksdb::Comparator *fallback_comparator = nullptr;
if(is_direct) { switch(jcomparator_type) {
fallback_comparator = // JAVA_COMPARATOR
reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jfallback_index_comparator_handle); case 0x0:
} else { fallback_comparator =
fallback_comparator = reinterpret_cast<rocksdb::ComparatorJniCallback*>(jfallback_index_comparator_handle);
reinterpret_cast<rocksdb::ComparatorJniCallback*>(jfallback_index_comparator_handle); break;
}
// JAVA_DIRECT_COMPARATOR
case 0x1:
fallback_comparator =
reinterpret_cast<rocksdb::DirectComparatorJniCallback*>(jfallback_index_comparator_handle);
break;
// JAVA_NATIVE_COMPARATOR_WRAPPER
case 0x2:
fallback_comparator =
reinterpret_cast<rocksdb::Comparator*>(jfallback_index_comparator_handle);
break;
}
auto* wbwi = auto* wbwi =
new rocksdb::WriteBatchWithIndex( new rocksdb::WriteBatchWithIndex(
fallback_comparator, fallback_comparator,
@@ -83,10 +95,13 @@ void Java_org_rocksdb_WriteBatchWithIndex_put__J_3BI_3BI(
auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
assert(wbwi != nullptr); assert(wbwi != nullptr);
auto put = [&wbwi] (rocksdb::Slice key, rocksdb::Slice value) { auto put = [&wbwi] (rocksdb::Slice key, rocksdb::Slice value) {
wbwi->Put(key, value); return wbwi->Put(key, value);
}; };
rocksdb::JniUtil::kv_op(put, env, jobj, jkey, jkey_len, jentry_value, std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(put, env,
jentry_value_len); jobj, jkey, jkey_len, jentry_value, jentry_value_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
@@ -103,10 +118,13 @@ void Java_org_rocksdb_WriteBatchWithIndex_put__J_3BI_3BIJ(
auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
assert(cf_handle != nullptr); assert(cf_handle != nullptr);
auto put = [&wbwi, &cf_handle] (rocksdb::Slice key, rocksdb::Slice value) { auto put = [&wbwi, &cf_handle] (rocksdb::Slice key, rocksdb::Slice value) {
wbwi->Put(cf_handle, key, value); return wbwi->Put(cf_handle, key, value);
}; };
rocksdb::JniUtil::kv_op(put, env, jobj, jkey, jkey_len, jentry_value, std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(put, env,
jentry_value_len); jobj, jkey, jkey_len, jentry_value, jentry_value_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
@@ -120,10 +138,13 @@ void Java_org_rocksdb_WriteBatchWithIndex_merge__J_3BI_3BI(
auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
assert(wbwi != nullptr); assert(wbwi != nullptr);
auto merge = [&wbwi] (rocksdb::Slice key, rocksdb::Slice value) { auto merge = [&wbwi] (rocksdb::Slice key, rocksdb::Slice value) {
wbwi->Merge(key, value); return wbwi->Merge(key, value);
}; };
rocksdb::JniUtil::kv_op(merge, env, jobj, jkey, jkey_len, jentry_value, std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(merge, env,
jentry_value_len); jobj, jkey, jkey_len, jentry_value, jentry_value_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
@@ -140,34 +161,41 @@ void Java_org_rocksdb_WriteBatchWithIndex_merge__J_3BI_3BIJ(
auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
assert(cf_handle != nullptr); assert(cf_handle != nullptr);
auto merge = [&wbwi, &cf_handle] (rocksdb::Slice key, rocksdb::Slice value) { auto merge = [&wbwi, &cf_handle] (rocksdb::Slice key, rocksdb::Slice value) {
wbwi->Merge(cf_handle, key, value); return wbwi->Merge(cf_handle, key, value);
}; };
rocksdb::JniUtil::kv_op(merge, env, jobj, jkey, jkey_len, jentry_value, std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(merge, env,
jentry_value_len); jobj, jkey, jkey_len, jentry_value, jentry_value_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
* Class: org_rocksdb_WriteBatchWithIndex * Class: org_rocksdb_WriteBatchWithIndex
* Method: remove * Method: delete
* Signature: (J[BI)V * Signature: (J[BI)V
*/ */
void Java_org_rocksdb_WriteBatchWithIndex_remove__J_3BI( void Java_org_rocksdb_WriteBatchWithIndex_delete__J_3BI(
JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey, JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey,
jint jkey_len) { jint jkey_len) {
auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
assert(wbwi != nullptr); assert(wbwi != nullptr);
auto remove = [&wbwi] (rocksdb::Slice key) { auto remove = [&wbwi] (rocksdb::Slice key) {
wbwi->Delete(key); return wbwi->Delete(key);
}; };
rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len); std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::k_op(remove, env,
jobj, jkey, jkey_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
* Class: org_rocksdb_WriteBatchWithIndex * Class: org_rocksdb_WriteBatchWithIndex
* Method: remove * Method: delete
* Signature: (J[BIJ)V * Signature: (J[BIJ)V
*/ */
void Java_org_rocksdb_WriteBatchWithIndex_remove__J_3BIJ( void Java_org_rocksdb_WriteBatchWithIndex_delete__J_3BIJ(
JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey, JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey,
jint jkey_len, jlong jcf_handle) { jint jkey_len, jlong jcf_handle) {
auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
@@ -175,9 +203,55 @@ void Java_org_rocksdb_WriteBatchWithIndex_remove__J_3BIJ(
auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
assert(cf_handle != nullptr); assert(cf_handle != nullptr);
auto remove = [&wbwi, &cf_handle] (rocksdb::Slice key) { auto remove = [&wbwi, &cf_handle] (rocksdb::Slice key) {
wbwi->Delete(cf_handle, key); return wbwi->Delete(cf_handle, key);
}; };
rocksdb::JniUtil::k_op(remove, env, jobj, jkey, jkey_len); std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::k_op(remove, env,
jobj, jkey, jkey_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
}
/*
* Class: org_rocksdb_WriteBatchWithIndex
* Method: singleDelete
* Signature: (J[BI)V
*/
void Java_org_rocksdb_WriteBatchWithIndex_singleDelete__J_3BI(
JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey,
jint jkey_len) {
auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
assert(wbwi != nullptr);
auto single_delete = [&wbwi] (rocksdb::Slice key) {
return wbwi->SingleDelete(key);
};
std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::k_op(single_delete,
env, jobj, jkey, jkey_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
}
/*
* Class: org_rocksdb_WriteBatchWithIndex
* Method: singleDelete
* Signature: (J[BIJ)V
*/
void Java_org_rocksdb_WriteBatchWithIndex_singleDelete__J_3BIJ(
JNIEnv* env, jobject jobj, jlong jwbwi_handle, jbyteArray jkey,
jint jkey_len, jlong jcf_handle) {
auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
assert(wbwi != nullptr);
auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
assert(cf_handle != nullptr);
auto single_delete = [&wbwi, &cf_handle] (rocksdb::Slice key) {
return wbwi->SingleDelete(cf_handle, key);
};
std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::k_op(single_delete,
env, jobj, jkey, jkey_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
@@ -191,10 +265,14 @@ void Java_org_rocksdb_WriteBatchWithIndex_deleteRange__J_3BI_3BI(
auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
assert(wbwi != nullptr); assert(wbwi != nullptr);
auto deleteRange = [&wbwi](rocksdb::Slice beginKey, rocksdb::Slice endKey) { auto deleteRange = [&wbwi](rocksdb::Slice beginKey, rocksdb::Slice endKey) {
wbwi->DeleteRange(beginKey, endKey); return wbwi->DeleteRange(beginKey, endKey);
}; };
rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key, jbegin_key_len, std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(
jend_key, jend_key_len); deleteRange, env, jobj, jbegin_key, jbegin_key_len, jend_key,
jend_key_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
@@ -211,11 +289,15 @@ void Java_org_rocksdb_WriteBatchWithIndex_deleteRange__J_3BI_3BIJ(
auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle); auto* cf_handle = reinterpret_cast<rocksdb::ColumnFamilyHandle*>(jcf_handle);
assert(cf_handle != nullptr); assert(cf_handle != nullptr);
auto deleteRange = [&wbwi, &cf_handle](rocksdb::Slice beginKey, auto deleteRange = [&wbwi, &cf_handle](rocksdb::Slice beginKey,
rocksdb::Slice endKey) { rocksdb::Slice endKey) {
wbwi->DeleteRange(cf_handle, beginKey, endKey); return wbwi->DeleteRange(cf_handle, beginKey, endKey);
}; };
rocksdb::JniUtil::kv_op(deleteRange, env, jobj, jbegin_key, jbegin_key_len, std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::kv_op(
jend_key, jend_key_len); deleteRange, env, jobj, jbegin_key, jbegin_key_len, jend_key,
jend_key_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
@@ -229,9 +311,13 @@ void Java_org_rocksdb_WriteBatchWithIndex_putLogData(
auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle); auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
assert(wbwi != nullptr); assert(wbwi != nullptr);
auto putLogData = [&wbwi] (rocksdb::Slice blob) { auto putLogData = [&wbwi] (rocksdb::Slice blob) {
wbwi->PutLogData(blob); return wbwi->PutLogData(blob);
}; };
rocksdb::JniUtil::k_op(putLogData, env, jobj, jblob, jblob_len); std::unique_ptr<rocksdb::Status> status = rocksdb::JniUtil::k_op(putLogData,
env, jobj, jblob, jblob_len);
if (status != nullptr && !status->ok()) {
rocksdb::RocksDBExceptionJni::ThrowNew(env, status);
}
} }
/* /*
@@ -279,6 +365,54 @@ void Java_org_rocksdb_WriteBatchWithIndex_rollbackToSavePoint0(
rocksdb::RocksDBExceptionJni::ThrowNew(env, s); rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
} }
/*
* Class: org_rocksdb_WriteBatchWithIndex
* Method: popSavePoint
* Signature: (J)V
*/
void Java_org_rocksdb_WriteBatchWithIndex_popSavePoint(
JNIEnv* env, jobject jobj, jlong jwbwi_handle) {
auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
assert(wbwi != nullptr);
auto s = wbwi->PopSavePoint();
if (s.ok()) {
return;
}
rocksdb::RocksDBExceptionJni::ThrowNew(env, s);
}
/*
* Class: org_rocksdb_WriteBatchWithIndex
* Method: setMaxBytes
* Signature: (JJ)V
*/
void Java_org_rocksdb_WriteBatchWithIndex_setMaxBytes(
JNIEnv* env, jobject jobj, jlong jwbwi_handle, jlong jmax_bytes) {
auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
assert(wbwi != nullptr);
wbwi->SetMaxBytes(static_cast<size_t>(jmax_bytes));
}
/*
* Class: org_rocksdb_WriteBatchWithIndex
* Method: getWriteBatch
* Signature: (J)Lorg/rocksdb/WriteBatch;
*/
jobject Java_org_rocksdb_WriteBatchWithIndex_getWriteBatch(
JNIEnv* env, jobject jobj, jlong jwbwi_handle) {
auto* wbwi = reinterpret_cast<rocksdb::WriteBatchWithIndex*>(jwbwi_handle);
assert(wbwi != nullptr);
auto* wb = wbwi->GetWriteBatch();
// TODO(AR) is the `wb` object owned by us?
return rocksdb::WriteBatchJni::construct(env, wb);
}
/* /*
* Class: org_rocksdb_WriteBatchWithIndex * Class: org_rocksdb_WriteBatchWithIndex
* Method: iterator0 * Method: iterator0
@@ -551,33 +685,15 @@ jlongArray Java_org_rocksdb_WBWIRocksIterator_entry1(
jlong results[3]; jlong results[3];
//set the type of the write entry // set the type of the write entry
switch (we.type) { results[0] = rocksdb::WriteTypeJni::toJavaWriteType(we.type);
case rocksdb::kPutRecord:
results[0] = 0x1;
break;
case rocksdb::kMergeRecord: // NOTE: key_slice and value_slice will be freed by org.rocksdb.DirectSlice#close
results[0] = 0x2;
break;
case rocksdb::kDeleteRecord:
results[0] = 0x4;
break;
case rocksdb::kLogDataRecord:
results[0] = 0x8;
break;
default:
results[0] = 0x0;
}
// key_slice and value_slice will be freed by org.rocksdb.DirectSlice#close
auto* key_slice = new rocksdb::Slice(we.key.data(), we.key.size()); auto* key_slice = new rocksdb::Slice(we.key.data(), we.key.size());
results[1] = reinterpret_cast<jlong>(key_slice); results[1] = reinterpret_cast<jlong>(key_slice);
if (we.type == rocksdb::kDeleteRecord if (we.type == rocksdb::kDeleteRecord
|| we.type == rocksdb::kSingleDeleteRecord
|| we.type == rocksdb::kLogDataRecord) { || we.type == rocksdb::kLogDataRecord) {
// set native handle of value slice to null if no value available // set native handle of value slice to null if no value available
results[2] = 0; results[2] = 0;
+398 -183
View File
@@ -14,24 +14,62 @@ WriteBatchHandlerJniCallback::WriteBatchHandlerJniCallback(
JNIEnv* env, jobject jWriteBatchHandler) JNIEnv* env, jobject jWriteBatchHandler)
: JniCallback(env, jWriteBatchHandler), m_env(env) { : JniCallback(env, jWriteBatchHandler), m_env(env) {
m_jPutCfMethodId = WriteBatchHandlerJni::getPutCfMethodId(env);
if(m_jPutCfMethodId == nullptr) {
// exception thrown
return;
}
m_jPutMethodId = WriteBatchHandlerJni::getPutMethodId(env); m_jPutMethodId = WriteBatchHandlerJni::getPutMethodId(env);
if(m_jPutMethodId == nullptr) { if(m_jPutMethodId == nullptr) {
// exception thrown // exception thrown
return; return;
} }
m_jMergeCfMethodId = WriteBatchHandlerJni::getMergeCfMethodId(env);
if(m_jMergeCfMethodId == nullptr) {
// exception thrown
return;
}
m_jMergeMethodId = WriteBatchHandlerJni::getMergeMethodId(env); m_jMergeMethodId = WriteBatchHandlerJni::getMergeMethodId(env);
if(m_jMergeMethodId == nullptr) { if(m_jMergeMethodId == nullptr) {
// exception thrown // exception thrown
return; return;
} }
m_jDeleteCfMethodId = WriteBatchHandlerJni::getDeleteCfMethodId(env);
if(m_jDeleteCfMethodId == nullptr) {
// exception thrown
return;
}
m_jDeleteMethodId = WriteBatchHandlerJni::getDeleteMethodId(env); m_jDeleteMethodId = WriteBatchHandlerJni::getDeleteMethodId(env);
if(m_jDeleteMethodId == nullptr) { if(m_jDeleteMethodId == nullptr) {
// exception thrown // exception thrown
return; return;
} }
m_jSingleDeleteCfMethodId =
WriteBatchHandlerJni::getSingleDeleteCfMethodId(env);
if(m_jSingleDeleteCfMethodId == nullptr) {
// exception thrown
return;
}
m_jSingleDeleteMethodId = WriteBatchHandlerJni::getSingleDeleteMethodId(env);
if(m_jSingleDeleteMethodId == nullptr) {
// exception thrown
return;
}
m_jDeleteRangeCfMethodId =
WriteBatchHandlerJni::getDeleteRangeCfMethodId(env);
if (m_jDeleteRangeCfMethodId == nullptr) {
// exception thrown
return;
}
m_jDeleteRangeMethodId = WriteBatchHandlerJni::getDeleteRangeMethodId(env); m_jDeleteRangeMethodId = WriteBatchHandlerJni::getDeleteRangeMethodId(env);
if (m_jDeleteRangeMethodId == nullptr) { if (m_jDeleteRangeMethodId == nullptr) {
// exception thrown // exception thrown
@@ -44,6 +82,45 @@ WriteBatchHandlerJniCallback::WriteBatchHandlerJniCallback(
return; return;
} }
m_jPutBlobIndexCfMethodId =
WriteBatchHandlerJni::getPutBlobIndexCfMethodId(env);
if(m_jPutBlobIndexCfMethodId == nullptr) {
// exception thrown
return;
}
m_jMarkBeginPrepareMethodId =
WriteBatchHandlerJni::getMarkBeginPrepareMethodId(env);
if(m_jMarkBeginPrepareMethodId == nullptr) {
// exception thrown
return;
}
m_jMarkEndPrepareMethodId =
WriteBatchHandlerJni::getMarkEndPrepareMethodId(env);
if(m_jMarkEndPrepareMethodId == nullptr) {
// exception thrown
return;
}
m_jMarkNoopMethodId = WriteBatchHandlerJni::getMarkNoopMethodId(env);
if(m_jMarkNoopMethodId == nullptr) {
// exception thrown
return;
}
m_jMarkRollbackMethodId = WriteBatchHandlerJni::getMarkRollbackMethodId(env);
if(m_jMarkRollbackMethodId == nullptr) {
// exception thrown
return;
}
m_jMarkCommitMethodId = WriteBatchHandlerJni::getMarkCommitMethodId(env);
if(m_jMarkCommitMethodId == nullptr) {
// exception thrown
return;
}
m_jContinueMethodId = WriteBatchHandlerJni::getContinueMethodId(env); m_jContinueMethodId = WriteBatchHandlerJni::getContinueMethodId(env);
if(m_jContinueMethodId == nullptr) { if(m_jContinueMethodId == nullptr) {
// exception thrown // exception thrown
@@ -51,196 +128,272 @@ WriteBatchHandlerJniCallback::WriteBatchHandlerJniCallback(
} }
} }
rocksdb::Status WriteBatchHandlerJniCallback::PutCF(uint32_t column_family_id,
const Slice& key, const Slice& value) {
auto put = [this, column_family_id] (
jbyteArray j_key, jbyteArray j_value) {
m_env->CallVoidMethod(
m_jcallback_obj,
m_jPutCfMethodId,
static_cast<jint>(column_family_id),
j_key,
j_value);
};
auto status = WriteBatchHandlerJniCallback::kv_op(key, value, put);
if(status == nullptr) {
return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status?
} else {
return rocksdb::Status(*status);
}
}
void WriteBatchHandlerJniCallback::Put(const Slice& key, const Slice& value) { void WriteBatchHandlerJniCallback::Put(const Slice& key, const Slice& value) {
const jbyteArray j_key = sliceToJArray(key); auto put = [this] (
if(j_key == nullptr) { jbyteArray j_key, jbyteArray j_value) {
// exception thrown m_env->CallVoidMethod(
if(m_env->ExceptionCheck()) {
m_env->ExceptionDescribe();
}
return;
}
const jbyteArray j_value = sliceToJArray(value);
if(j_value == nullptr) {
// exception thrown
if(m_env->ExceptionCheck()) {
m_env->ExceptionDescribe();
}
if(j_key != nullptr) {
m_env->DeleteLocalRef(j_key);
}
return;
}
m_env->CallVoidMethod(
m_jcallback_obj, m_jcallback_obj,
m_jPutMethodId, m_jPutMethodId,
j_key, j_key,
j_value); j_value);
if(m_env->ExceptionCheck()) { };
// exception thrown WriteBatchHandlerJniCallback::kv_op(key, value, put);
m_env->ExceptionDescribe(); }
if(j_value != nullptr) {
m_env->DeleteLocalRef(j_value);
}
if(j_key != nullptr) {
m_env->DeleteLocalRef(j_key);
}
return;
}
if(j_value != nullptr) { rocksdb::Status WriteBatchHandlerJniCallback::MergeCF(uint32_t column_family_id,
m_env->DeleteLocalRef(j_value); const Slice& key, const Slice& value) {
} auto merge = [this, column_family_id] (
if(j_key != nullptr) { jbyteArray j_key, jbyteArray j_value) {
m_env->DeleteLocalRef(j_key); m_env->CallVoidMethod(
m_jcallback_obj,
m_jMergeCfMethodId,
static_cast<jint>(column_family_id),
j_key,
j_value);
};
auto status = WriteBatchHandlerJniCallback::kv_op(key, value, merge);
if(status == nullptr) {
return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status?
} else {
return rocksdb::Status(*status);
} }
} }
void WriteBatchHandlerJniCallback::Merge(const Slice& key, const Slice& value) { void WriteBatchHandlerJniCallback::Merge(const Slice& key, const Slice& value) {
const jbyteArray j_key = sliceToJArray(key); auto merge = [this] (
if(j_key == nullptr) { jbyteArray j_key, jbyteArray j_value) {
// exception thrown m_env->CallVoidMethod(
if(m_env->ExceptionCheck()) {
m_env->ExceptionDescribe();
}
return;
}
const jbyteArray j_value = sliceToJArray(value);
if(j_value == nullptr) {
// exception thrown
if(m_env->ExceptionCheck()) {
m_env->ExceptionDescribe();
}
if(j_key != nullptr) {
m_env->DeleteLocalRef(j_key);
}
return;
}
m_env->CallVoidMethod(
m_jcallback_obj, m_jcallback_obj,
m_jMergeMethodId, m_jMergeMethodId,
j_key, j_key,
j_value); j_value);
if(m_env->ExceptionCheck()) { };
// exception thrown WriteBatchHandlerJniCallback::kv_op(key, value, merge);
m_env->ExceptionDescribe(); }
if(j_value != nullptr) {
m_env->DeleteLocalRef(j_value);
}
if(j_key != nullptr) {
m_env->DeleteLocalRef(j_key);
}
return;
}
if(j_value != nullptr) { rocksdb::Status WriteBatchHandlerJniCallback::DeleteCF(uint32_t column_family_id,
m_env->DeleteLocalRef(j_value); const Slice& key) {
} auto remove = [this, column_family_id] (jbyteArray j_key) {
if(j_key != nullptr) { m_env->CallVoidMethod(
m_env->DeleteLocalRef(j_key); m_jcallback_obj,
m_jDeleteCfMethodId,
static_cast<jint>(column_family_id),
j_key);
};
auto status = WriteBatchHandlerJniCallback::k_op(key, remove);
if(status == nullptr) {
return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status?
} else {
return rocksdb::Status(*status);
} }
} }
void WriteBatchHandlerJniCallback::Delete(const Slice& key) { void WriteBatchHandlerJniCallback::Delete(const Slice& key) {
const jbyteArray j_key = sliceToJArray(key); auto remove = [this] (jbyteArray j_key) {
if(j_key == nullptr) { m_env->CallVoidMethod(
// exception thrown
if(m_env->ExceptionCheck()) {
m_env->ExceptionDescribe();
}
return;
}
m_env->CallVoidMethod(
m_jcallback_obj, m_jcallback_obj,
m_jDeleteMethodId, m_jDeleteMethodId,
j_key); j_key);
if(m_env->ExceptionCheck()) { };
// exception thrown WriteBatchHandlerJniCallback::k_op(key, remove);
m_env->ExceptionDescribe(); }
if(j_key != nullptr) {
m_env->DeleteLocalRef(j_key);
}
return;
}
if(j_key != nullptr) { rocksdb::Status WriteBatchHandlerJniCallback::SingleDeleteCF(uint32_t column_family_id,
m_env->DeleteLocalRef(j_key); const Slice& key) {
auto singleDelete = [this, column_family_id] (jbyteArray j_key) {
m_env->CallVoidMethod(
m_jcallback_obj,
m_jSingleDeleteCfMethodId,
static_cast<jint>(column_family_id),
j_key);
};
auto status = WriteBatchHandlerJniCallback::k_op(key, singleDelete);
if(status == nullptr) {
return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status?
} else {
return rocksdb::Status(*status);
}
}
void WriteBatchHandlerJniCallback::SingleDelete(const Slice& key) {
auto singleDelete = [this] (jbyteArray j_key) {
m_env->CallVoidMethod(
m_jcallback_obj,
m_jSingleDeleteMethodId,
j_key);
};
WriteBatchHandlerJniCallback::k_op(key, singleDelete);
}
rocksdb::Status WriteBatchHandlerJniCallback::DeleteRangeCF(uint32_t column_family_id,
const Slice& beginKey, const Slice& endKey) {
auto deleteRange = [this, column_family_id] (
jbyteArray j_beginKey, jbyteArray j_endKey) {
m_env->CallVoidMethod(
m_jcallback_obj,
m_jDeleteRangeCfMethodId,
static_cast<jint>(column_family_id),
j_beginKey,
j_endKey);
};
auto status = WriteBatchHandlerJniCallback::kv_op(beginKey, endKey, deleteRange);
if(status == nullptr) {
return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status?
} else {
return rocksdb::Status(*status);
} }
} }
void WriteBatchHandlerJniCallback::DeleteRange(const Slice& beginKey, void WriteBatchHandlerJniCallback::DeleteRange(const Slice& beginKey,
const Slice& endKey) { const Slice& endKey) {
const jbyteArray j_beginKey = sliceToJArray(beginKey); auto deleteRange = [this] (
if (j_beginKey == nullptr) { jbyteArray j_beginKey, jbyteArray j_endKey) {
// exception thrown m_env->CallVoidMethod(
if (m_env->ExceptionCheck()) { m_jcallback_obj,
m_env->ExceptionDescribe(); m_jDeleteRangeMethodId,
} j_beginKey,
return; j_endKey);
} };
WriteBatchHandlerJniCallback::kv_op(beginKey, endKey, deleteRange);
const jbyteArray j_endKey = sliceToJArray(beginKey);
if (j_endKey == nullptr) {
// exception thrown
if (m_env->ExceptionCheck()) {
m_env->ExceptionDescribe();
}
return;
}
m_env->CallVoidMethod(m_jcallback_obj, m_jDeleteRangeMethodId,
j_beginKey, j_endKey);
if (m_env->ExceptionCheck()) {
// exception thrown
m_env->ExceptionDescribe();
if (j_beginKey != nullptr) {
m_env->DeleteLocalRef(j_beginKey);
}
if (j_endKey != nullptr) {
m_env->DeleteLocalRef(j_endKey);
}
return;
}
if (j_beginKey != nullptr) {
m_env->DeleteLocalRef(j_beginKey);
}
if (j_endKey != nullptr) {
m_env->DeleteLocalRef(j_endKey);
}
} }
void WriteBatchHandlerJniCallback::LogData(const Slice& blob) { void WriteBatchHandlerJniCallback::LogData(const Slice& blob) {
const jbyteArray j_blob = sliceToJArray(blob); auto logData = [this] (jbyteArray j_blob) {
if(j_blob == nullptr) { m_env->CallVoidMethod(
// exception thrown
if(m_env->ExceptionCheck()) {
m_env->ExceptionDescribe();
}
return;
}
m_env->CallVoidMethod(
m_jcallback_obj, m_jcallback_obj,
m_jLogDataMethodId, m_jLogDataMethodId,
j_blob); j_blob);
if(m_env->ExceptionCheck()) { };
WriteBatchHandlerJniCallback::k_op(blob, logData);
}
rocksdb::Status WriteBatchHandlerJniCallback::PutBlobIndexCF(uint32_t column_family_id,
const Slice& key, const Slice& value) {
auto putBlobIndex = [this, column_family_id] (
jbyteArray j_key, jbyteArray j_value) {
m_env->CallVoidMethod(
m_jcallback_obj,
m_jPutBlobIndexCfMethodId,
static_cast<jint>(column_family_id),
j_key,
j_value);
};
auto status = WriteBatchHandlerJniCallback::kv_op(key, value, putBlobIndex);
if(status == nullptr) {
return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status?
} else {
return rocksdb::Status(*status);
}
}
rocksdb::Status WriteBatchHandlerJniCallback::MarkBeginPrepare() {
m_env->CallVoidMethod(m_jcallback_obj, m_jMarkBeginPrepareMethodId);
// check for Exception, in-particular RocksDBException
if (m_env->ExceptionCheck()) {
// exception thrown // exception thrown
m_env->ExceptionDescribe(); jthrowable exception = m_env->ExceptionOccurred();
if(j_blob != nullptr) { std::unique_ptr<rocksdb::Status> status = rocksdb::RocksDBExceptionJni::toCppStatus(m_env, exception);
m_env->DeleteLocalRef(j_blob); if (status == nullptr) {
// unkown status or exception occurred extracting status
m_env->ExceptionDescribe();
return rocksdb::Status::OK(); // TODO(AR) probably need a better error code here
} else {
m_env->ExceptionClear(); // clear the exception, as we have extracted the status
return rocksdb::Status(*status);
} }
return;
} }
if(j_blob != nullptr) { return rocksdb::Status::OK();
m_env->DeleteLocalRef(j_blob); }
rocksdb::Status WriteBatchHandlerJniCallback::MarkEndPrepare(const Slice& xid) {
auto markEndPrepare = [this] (
jbyteArray j_xid) {
m_env->CallVoidMethod(
m_jcallback_obj,
m_jMarkEndPrepareMethodId,
j_xid);
};
auto status = WriteBatchHandlerJniCallback::k_op(xid, markEndPrepare);
if(status == nullptr) {
return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status?
} else {
return rocksdb::Status(*status);
}
}
rocksdb::Status WriteBatchHandlerJniCallback::MarkNoop(bool empty_batch) {
m_env->CallVoidMethod(m_jcallback_obj, m_jMarkNoopMethodId, static_cast<jboolean>(empty_batch));
// check for Exception, in-particular RocksDBException
if (m_env->ExceptionCheck()) {
// exception thrown
jthrowable exception = m_env->ExceptionOccurred();
std::unique_ptr<rocksdb::Status> status = rocksdb::RocksDBExceptionJni::toCppStatus(m_env, exception);
if (status == nullptr) {
// unkown status or exception occurred extracting status
m_env->ExceptionDescribe();
return rocksdb::Status::OK(); // TODO(AR) probably need a better error code here
} else {
m_env->ExceptionClear(); // clear the exception, as we have extracted the status
return rocksdb::Status(*status);
}
}
return rocksdb::Status::OK();
}
rocksdb::Status WriteBatchHandlerJniCallback::MarkRollback(const Slice& xid) {
auto markRollback = [this] (
jbyteArray j_xid) {
m_env->CallVoidMethod(
m_jcallback_obj,
m_jMarkRollbackMethodId,
j_xid);
};
auto status = WriteBatchHandlerJniCallback::k_op(xid, markRollback);
if(status == nullptr) {
return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status?
} else {
return rocksdb::Status(*status);
}
}
rocksdb::Status WriteBatchHandlerJniCallback::MarkCommit(const Slice& xid) {
auto markCommit = [this] (
jbyteArray j_xid) {
m_env->CallVoidMethod(
m_jcallback_obj,
m_jMarkCommitMethodId,
j_xid);
};
auto status = WriteBatchHandlerJniCallback::k_op(xid, markCommit);
if(status == nullptr) {
return rocksdb::Status::OK(); // TODO(AR) what to do if there is an Exception but we don't know the rocksdb::Status?
} else {
return rocksdb::Status(*status);
} }
} }
@@ -256,39 +409,101 @@ bool WriteBatchHandlerJniCallback::Continue() {
return static_cast<bool>(jContinue == JNI_TRUE); return static_cast<bool>(jContinue == JNI_TRUE);
} }
/* std::unique_ptr<rocksdb::Status> WriteBatchHandlerJniCallback::kv_op(const Slice& key, const Slice& value, std::function<void(jbyteArray, jbyteArray)> kvFn) {
* Creates a Java Byte Array from the data in a Slice const jbyteArray j_key = JniUtil::copyBytes(m_env, key);
* if (j_key == nullptr) {
* When calling this function // exception thrown
* you must remember to call env->DeleteLocalRef if (m_env->ExceptionCheck()) {
* on the result after you have finished with it m_env->ExceptionDescribe();
*
* @param s A Slice to convery to a Java byte array
*
* @return A reference to a Java byte array, or a nullptr if an
* exception occurs
*/
jbyteArray WriteBatchHandlerJniCallback::sliceToJArray(const Slice& s) {
// TODO(AR) move to JniUtil
jbyteArray ja = m_env->NewByteArray(static_cast<jsize>(s.size()));
if(ja == nullptr) {
// exception thrown: OutOfMemoryError
return nullptr;
}
m_env->SetByteArrayRegion(
ja, 0, static_cast<jsize>(s.size()),
const_cast<jbyte*>(reinterpret_cast<const jbyte*>(s.data())));
if(m_env->ExceptionCheck()) {
if(ja != nullptr) {
m_env->DeleteLocalRef(ja);
} }
// exception thrown: ArrayIndexOutOfBoundsException
return nullptr; return nullptr;
} }
return ja; const jbyteArray j_value = JniUtil::copyBytes(m_env, value);
if (j_value == nullptr) {
// exception thrown
if (m_env->ExceptionCheck()) {
m_env->ExceptionDescribe();
}
if (j_key != nullptr) {
m_env->DeleteLocalRef(j_key);
}
return nullptr;
}
kvFn(j_key, j_value);
// check for Exception, in-particular RocksDBException
if (m_env->ExceptionCheck()) {
if (j_value != nullptr) {
m_env->DeleteLocalRef(j_value);
}
if (j_key != nullptr) {
m_env->DeleteLocalRef(j_key);
}
// exception thrown
jthrowable exception = m_env->ExceptionOccurred();
std::unique_ptr<rocksdb::Status> status = rocksdb::RocksDBExceptionJni::toCppStatus(m_env, exception);
if (status == nullptr) {
// unkown status or exception occurred extracting status
m_env->ExceptionDescribe();
return nullptr;
} else {
m_env->ExceptionClear(); // clear the exception, as we have extracted the status
return status;
}
}
if (j_value != nullptr) {
m_env->DeleteLocalRef(j_value);
}
if (j_key != nullptr) {
m_env->DeleteLocalRef(j_key);
}
// all OK
return std::unique_ptr<rocksdb::Status>(new rocksdb::Status(rocksdb::Status::OK()));
}
std::unique_ptr<rocksdb::Status> WriteBatchHandlerJniCallback::k_op(const Slice& key, std::function<void(jbyteArray)> kFn) {
const jbyteArray j_key = JniUtil::copyBytes(m_env, key);
if (j_key == nullptr) {
// exception thrown
if (m_env->ExceptionCheck()) {
m_env->ExceptionDescribe();
}
return nullptr;
}
kFn(j_key);
// check for Exception, in-particular RocksDBException
if (m_env->ExceptionCheck()) {
if (j_key != nullptr) {
m_env->DeleteLocalRef(j_key);
}
// exception thrown
jthrowable exception = m_env->ExceptionOccurred();
std::unique_ptr<rocksdb::Status> status = rocksdb::RocksDBExceptionJni::toCppStatus(m_env, exception);
if (status == nullptr) {
// unkown status or exception occurred extracting status
m_env->ExceptionDescribe();
return nullptr;
} else {
m_env->ExceptionClear(); // clear the exception, as we have extracted the status
return status;
}
}
if (j_key != nullptr) {
m_env->DeleteLocalRef(j_key);
}
// all OK
return std::unique_ptr<rocksdb::Status>(new rocksdb::Status(rocksdb::Status::OK()));
} }
} // namespace rocksdb } // namespace rocksdb
+38 -1
View File
@@ -9,7 +9,9 @@
#ifndef JAVA_ROCKSJNI_WRITEBATCHHANDLERJNICALLBACK_H_ #ifndef JAVA_ROCKSJNI_WRITEBATCHHANDLERJNICALLBACK_H_
#define JAVA_ROCKSJNI_WRITEBATCHHANDLERJNICALLBACK_H_ #define JAVA_ROCKSJNI_WRITEBATCHHANDLERJNICALLBACK_H_
#include <functional>
#include <jni.h> #include <jni.h>
#include <memory>
#include "rocksjni/jnicallback.h" #include "rocksjni/jnicallback.h"
#include "rocksdb/write_batch.h" #include "rocksdb/write_batch.h"
@@ -25,22 +27,57 @@ class WriteBatchHandlerJniCallback : public JniCallback, public WriteBatch::Hand
public: public:
WriteBatchHandlerJniCallback( WriteBatchHandlerJniCallback(
JNIEnv* env, jobject jWriteBackHandler); JNIEnv* env, jobject jWriteBackHandler);
Status PutCF(uint32_t column_family_id, const Slice& key,
const Slice& value);
void Put(const Slice& key, const Slice& value); void Put(const Slice& key, const Slice& value);
Status MergeCF(uint32_t column_family_id, const Slice& key,
const Slice& value);
void Merge(const Slice& key, const Slice& value); void Merge(const Slice& key, const Slice& value);
Status DeleteCF(uint32_t column_family_id, const Slice& key);
void Delete(const Slice& key); void Delete(const Slice& key);
Status SingleDeleteCF(uint32_t column_family_id, const Slice& key);
void SingleDelete(const Slice& key);
Status DeleteRangeCF(uint32_t column_family_id, const Slice& beginKey,
const Slice& endKey);
void DeleteRange(const Slice& beginKey, const Slice& endKey); void DeleteRange(const Slice& beginKey, const Slice& endKey);
void LogData(const Slice& blob); void LogData(const Slice& blob);
Status PutBlobIndexCF(uint32_t column_family_id, const Slice& key,
const Slice& value);
Status MarkBeginPrepare();
Status MarkEndPrepare(const Slice& xid);
Status MarkNoop(bool empty_batch);
Status MarkRollback(const Slice& xid);
Status MarkCommit(const Slice& xid);
bool Continue(); bool Continue();
private: private:
JNIEnv* m_env; JNIEnv* m_env;
jbyteArray sliceToJArray(const Slice& s); jmethodID m_jPutCfMethodId;
jmethodID m_jPutMethodId; jmethodID m_jPutMethodId;
jmethodID m_jMergeCfMethodId;
jmethodID m_jMergeMethodId; jmethodID m_jMergeMethodId;
jmethodID m_jDeleteCfMethodId;
jmethodID m_jDeleteMethodId; jmethodID m_jDeleteMethodId;
jmethodID m_jSingleDeleteCfMethodId;
jmethodID m_jSingleDeleteMethodId;
jmethodID m_jDeleteRangeCfMethodId;
jmethodID m_jDeleteRangeMethodId; jmethodID m_jDeleteRangeMethodId;
jmethodID m_jLogDataMethodId; jmethodID m_jLogDataMethodId;
jmethodID m_jPutBlobIndexCfMethodId;
jmethodID m_jMarkBeginPrepareMethodId;
jmethodID m_jMarkEndPrepareMethodId;
jmethodID m_jMarkNoopMethodId;
jmethodID m_jMarkRollbackMethodId;
jmethodID m_jMarkCommitMethodId;
jmethodID m_jContinueMethodId; jmethodID m_jContinueMethodId;
/**
* @return A pointer to a rocksdb::Status or nullptr if an unexpected exception occurred
*/
std::unique_ptr<rocksdb::Status> kv_op(const Slice& key, const Slice& value, std::function<void(jbyteArray, jbyteArray)> kvFn);
/**
* @return A pointer to a rocksdb::Status or nullptr if an unexpected exception occurred
*/
std::unique_ptr<rocksdb::Status> k_op(const Slice& key, std::function<void(jbyteArray)> kFn);
}; };
} // namespace rocksdb } // namespace rocksdb
@@ -0,0 +1,184 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
import org.rocksdb.*;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
* Demonstrates using Transactions on an OptimisticTransactionDB with
* varying isolation guarantees
*/
public class OptimisticTransactionSample {
private static final String dbPath = "/tmp/rocksdb_optimistic_transaction_example";
public static final void main(final String args[]) throws RocksDBException {
try(final Options options = new Options()
.setCreateIfMissing(true);
final OptimisticTransactionDB txnDb =
OptimisticTransactionDB.open(options, dbPath)) {
try (final WriteOptions writeOptions = new WriteOptions();
final ReadOptions readOptions = new ReadOptions()) {
////////////////////////////////////////////////////////
//
// Simple OptimisticTransaction Example ("Read Committed")
//
////////////////////////////////////////////////////////
readCommitted(txnDb, writeOptions, readOptions);
////////////////////////////////////////////////////////
//
// "Repeatable Read" (Snapshot Isolation) Example
// -- Using a single Snapshot
//
////////////////////////////////////////////////////////
repeatableRead(txnDb, writeOptions, readOptions);
////////////////////////////////////////////////////////
//
// "Read Committed" (Monotonic Atomic Views) Example
// --Using multiple Snapshots
//
////////////////////////////////////////////////////////
readCommitted_monotonicAtomicViews(txnDb, writeOptions, readOptions);
}
}
}
/**
* Demonstrates "Read Committed" isolation
*/
private static void readCommitted(final OptimisticTransactionDB txnDb,
final WriteOptions writeOptions, final ReadOptions readOptions)
throws RocksDBException {
final byte key1[] = "abc".getBytes(UTF_8);
final byte value1[] = "def".getBytes(UTF_8);
final byte key2[] = "xyz".getBytes(UTF_8);
final byte value2[] = "zzz".getBytes(UTF_8);
// Start a transaction
try(final Transaction txn = txnDb.beginTransaction(writeOptions)) {
// Read a key in this transaction
byte[] value = txn.get(readOptions, key1);
assert(value == null);
// Write a key in this transaction
txn.put(key1, value1);
// Read a key OUTSIDE this transaction. Does not affect txn.
value = txnDb.get(readOptions, key1);
assert(value == null);
// Write a key OUTSIDE of this transaction.
// Does not affect txn since this is an unrelated key.
// If we wrote key 'abc' here, the transaction would fail to commit.
txnDb.put(writeOptions, key2, value2);
// Commit transaction
txn.commit();
}
}
/**
* Demonstrates "Repeatable Read" (Snapshot Isolation) isolation
*/
private static void repeatableRead(final OptimisticTransactionDB txnDb,
final WriteOptions writeOptions, final ReadOptions readOptions)
throws RocksDBException {
final byte key1[] = "ghi".getBytes(UTF_8);
final byte value1[] = "jkl".getBytes(UTF_8);
// Set a snapshot at start of transaction by setting setSnapshot(true)
try(final OptimisticTransactionOptions txnOptions =
new OptimisticTransactionOptions().setSetSnapshot(true);
final Transaction txn =
txnDb.beginTransaction(writeOptions, txnOptions)) {
final Snapshot snapshot = txn.getSnapshot();
// Write a key OUTSIDE of transaction
txnDb.put(writeOptions, key1, value1);
// Read a key using the snapshot.
readOptions.setSnapshot(snapshot);
final byte[] value = txn.getForUpdate(readOptions, key1, true);
assert(value == value1);
try {
// Attempt to commit transaction
txn.commit();
throw new IllegalStateException();
} catch(final RocksDBException e) {
// Transaction could not commit since the write outside of the txn
// conflicted with the read!
assert(e.getStatus().getCode() == Status.Code.Busy);
}
txn.rollback();
} finally {
// Clear snapshot from read options since it is no longer valid
readOptions.setSnapshot(null);
}
}
/**
* Demonstrates "Read Committed" (Monotonic Atomic Views) isolation
*
* In this example, we set the snapshot multiple times. This is probably
* only necessary if you have very strict isolation requirements to
* implement.
*/
private static void readCommitted_monotonicAtomicViews(
final OptimisticTransactionDB txnDb, final WriteOptions writeOptions,
final ReadOptions readOptions) throws RocksDBException {
final byte keyX[] = "x".getBytes(UTF_8);
final byte valueX[] = "x".getBytes(UTF_8);
final byte keyY[] = "y".getBytes(UTF_8);
final byte valueY[] = "y".getBytes(UTF_8);
try (final OptimisticTransactionOptions txnOptions =
new OptimisticTransactionOptions().setSetSnapshot(true);
final Transaction txn =
txnDb.beginTransaction(writeOptions, txnOptions)) {
// Do some reads and writes to key "x"
Snapshot snapshot = txnDb.getSnapshot();
readOptions.setSnapshot(snapshot);
byte[] value = txn.get(readOptions, keyX);
txn.put(valueX, valueX);
// Do a write outside of the transaction to key "y"
txnDb.put(writeOptions, keyY, valueY);
// Set a new snapshot in the transaction
txn.setSnapshot();
snapshot = txnDb.getSnapshot();
readOptions.setSnapshot(snapshot);
// Do some reads and writes to key "y"
// Since the snapshot was advanced, the write done outside of the
// transaction does not conflict.
value = txn.getForUpdate(readOptions, keyY, true);
txn.put(keyY, valueY);
// Commit. Since the snapshot was advanced, the write done outside of the
// transaction does not prevent this transaction from Committing.
txn.commit();
} finally {
// Clear snapshot from read options since it is no longer valid
readOptions.setSnapshot(null);
}
}
}
@@ -0,0 +1,183 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
import org.rocksdb.*;
import static java.nio.charset.StandardCharsets.UTF_8;
/**
* Demonstrates using Transactions on a TransactionDB with
* varying isolation guarantees
*/
public class TransactionSample {
private static final String dbPath = "/tmp/rocksdb_transaction_example";
public static final void main(final String args[]) throws RocksDBException {
try(final Options options = new Options()
.setCreateIfMissing(true);
final TransactionDBOptions txnDbOptions = new TransactionDBOptions();
final TransactionDB txnDb =
TransactionDB.open(options, txnDbOptions, dbPath)) {
try (final WriteOptions writeOptions = new WriteOptions();
final ReadOptions readOptions = new ReadOptions()) {
////////////////////////////////////////////////////////
//
// Simple Transaction Example ("Read Committed")
//
////////////////////////////////////////////////////////
readCommitted(txnDb, writeOptions, readOptions);
////////////////////////////////////////////////////////
//
// "Repeatable Read" (Snapshot Isolation) Example
// -- Using a single Snapshot
//
////////////////////////////////////////////////////////
repeatableRead(txnDb, writeOptions, readOptions);
////////////////////////////////////////////////////////
//
// "Read Committed" (Monotonic Atomic Views) Example
// --Using multiple Snapshots
//
////////////////////////////////////////////////////////
readCommitted_monotonicAtomicViews(txnDb, writeOptions, readOptions);
}
}
}
/**
* Demonstrates "Read Committed" isolation
*/
private static void readCommitted(final TransactionDB txnDb,
final WriteOptions writeOptions, final ReadOptions readOptions)
throws RocksDBException {
final byte key1[] = "abc".getBytes(UTF_8);
final byte value1[] = "def".getBytes(UTF_8);
final byte key2[] = "xyz".getBytes(UTF_8);
final byte value2[] = "zzz".getBytes(UTF_8);
// Start a transaction
try(final Transaction txn = txnDb.beginTransaction(writeOptions)) {
// Read a key in this transaction
byte[] value = txn.get(readOptions, key1);
assert(value == null);
// Write a key in this transaction
txn.put(key1, value1);
// Read a key OUTSIDE this transaction. Does not affect txn.
value = txnDb.get(readOptions, key1);
assert(value == null);
// Write a key OUTSIDE of this transaction.
// Does not affect txn since this is an unrelated key.
// If we wrote key 'abc' here, the transaction would fail to commit.
txnDb.put(writeOptions, key2, value2);
// Commit transaction
txn.commit();
}
}
/**
* Demonstrates "Repeatable Read" (Snapshot Isolation) isolation
*/
private static void repeatableRead(final TransactionDB txnDb,
final WriteOptions writeOptions, final ReadOptions readOptions)
throws RocksDBException {
final byte key1[] = "ghi".getBytes(UTF_8);
final byte value1[] = "jkl".getBytes(UTF_8);
// Set a snapshot at start of transaction by setting setSnapshot(true)
try(final TransactionOptions txnOptions = new TransactionOptions()
.setSetSnapshot(true);
final Transaction txn =
txnDb.beginTransaction(writeOptions, txnOptions)) {
final Snapshot snapshot = txn.getSnapshot();
// Write a key OUTSIDE of transaction
txnDb.put(writeOptions, key1, value1);
// Attempt to read a key using the snapshot. This will fail since
// the previous write outside this txn conflicts with this read.
readOptions.setSnapshot(snapshot);
try {
final byte[] value = txn.getForUpdate(readOptions, key1, true);
throw new IllegalStateException();
} catch(final RocksDBException e) {
assert(e.getStatus().getCode() == Status.Code.Busy);
}
txn.rollback();
} finally {
// Clear snapshot from read options since it is no longer valid
readOptions.setSnapshot(null);
}
}
/**
* Demonstrates "Read Committed" (Monotonic Atomic Views) isolation
*
* In this example, we set the snapshot multiple times. This is probably
* only necessary if you have very strict isolation requirements to
* implement.
*/
private static void readCommitted_monotonicAtomicViews(
final TransactionDB txnDb, final WriteOptions writeOptions,
final ReadOptions readOptions) throws RocksDBException {
final byte keyX[] = "x".getBytes(UTF_8);
final byte valueX[] = "x".getBytes(UTF_8);
final byte keyY[] = "y".getBytes(UTF_8);
final byte valueY[] = "y".getBytes(UTF_8);
try (final TransactionOptions txnOptions = new TransactionOptions()
.setSetSnapshot(true);
final Transaction txn =
txnDb.beginTransaction(writeOptions, txnOptions)) {
// Do some reads and writes to key "x"
Snapshot snapshot = txnDb.getSnapshot();
readOptions.setSnapshot(snapshot);
byte[] value = txn.get(readOptions, keyX);
txn.put(valueX, valueX);
// Do a write outside of the transaction to key "y"
txnDb.put(writeOptions, keyY, valueY);
// Set a new snapshot in the transaction
txn.setSnapshot();
txn.setSavePoint();
snapshot = txnDb.getSnapshot();
readOptions.setSnapshot(snapshot);
// Do some reads and writes to key "y"
// Since the snapshot was advanced, the write done outside of the
// transaction does not conflict.
value = txn.getForUpdate(readOptions, keyY, true);
txn.put(keyY, valueY);
// Decide we want to revert the last write from this transaction.
txn.rollbackToSavePoint();
// Commit.
txn.commit();
} finally {
// Clear snapshot from read options since it is no longer valid
readOptions.setSnapshot(null);
}
}
}
@@ -17,10 +17,23 @@ package org.rocksdb;
public abstract class AbstractComparator<T extends AbstractSlice<?>> public abstract class AbstractComparator<T extends AbstractSlice<?>>
extends RocksCallbackObject { extends RocksCallbackObject {
protected AbstractComparator() {
super();
}
protected AbstractComparator(final ComparatorOptions copt) { protected AbstractComparator(final ComparatorOptions copt) {
super(copt.nativeHandle_); super(copt.nativeHandle_);
} }
/**
* Get the type of this comparator.
*
* Used for determining the correct C++ cast in native code.
*
* @return The type of the comparator.
*/
abstract ComparatorType getComparatorType();
/** /**
* The name of the comparator. Used to check for comparator * The name of the comparator. Used to check for comparator
* mismatches (i.e., a DB created with one comparator is * mismatches (i.e., a DB created with one comparator is
@@ -0,0 +1,54 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
/**
* Provides notification to the caller of SetSnapshotOnNextOperation when
* the actual snapshot gets created
*/
public abstract class AbstractTransactionNotifier
extends RocksCallbackObject {
protected AbstractTransactionNotifier() {
super();
}
/**
* Implement this method to receive notification when a snapshot is
* requested via {@link Transaction#setSnapshotOnNextOperation()}.
*
* @param newSnapshot the snapshot that has been created.
*/
public abstract void snapshotCreated(final Snapshot newSnapshot);
/**
* This is intentionally private as it is the callback hook
* from JNI
*/
private void snapshotCreated(final long snapshotHandle) {
snapshotCreated(new Snapshot(snapshotHandle));
}
@Override
protected long initializeNative(final long... nativeParameterHandles) {
return createNewTransactionNotifier();
}
private native long createNewTransactionNotifier();
/**
* Deletes underlying C++ TransactionNotifier pointer.
*
* Note that this function should be called only after all
* Transactions referencing the comparator are closed.
* Otherwise an undefined behavior will occur.
*/
@Override
protected void disposeInternal() {
disposeInternal(nativeHandle_);
}
protected final native void disposeInternal(final long handle);
}
@@ -18,52 +18,80 @@ public abstract class AbstractWriteBatch extends RocksObject
} }
@Override @Override
public void put(byte[] key, byte[] value) { public void put(byte[] key, byte[] value) throws RocksDBException {
put(nativeHandle_, key, key.length, value, value.length); put(nativeHandle_, key, key.length, value, value.length);
} }
@Override @Override
public void put(ColumnFamilyHandle columnFamilyHandle, byte[] key, public void put(ColumnFamilyHandle columnFamilyHandle, byte[] key,
byte[] value) { byte[] value) throws RocksDBException {
put(nativeHandle_, key, key.length, value, value.length, put(nativeHandle_, key, key.length, value, value.length,
columnFamilyHandle.nativeHandle_); columnFamilyHandle.nativeHandle_);
} }
@Override @Override
public void merge(byte[] key, byte[] value) { public void merge(byte[] key, byte[] value) throws RocksDBException {
merge(nativeHandle_, key, key.length, value, value.length); merge(nativeHandle_, key, key.length, value, value.length);
} }
@Override @Override
public void merge(ColumnFamilyHandle columnFamilyHandle, byte[] key, public void merge(ColumnFamilyHandle columnFamilyHandle, byte[] key,
byte[] value) { byte[] value) throws RocksDBException {
merge(nativeHandle_, key, key.length, value, value.length, merge(nativeHandle_, key, key.length, value, value.length,
columnFamilyHandle.nativeHandle_); columnFamilyHandle.nativeHandle_);
} }
@Override @Override
public void remove(byte[] key) { @Deprecated
remove(nativeHandle_, key, key.length); public void remove(byte[] key) throws RocksDBException {
delete(nativeHandle_, key, key.length);
} }
@Override @Override
public void remove(ColumnFamilyHandle columnFamilyHandle, byte[] key) { @Deprecated
remove(nativeHandle_, key, key.length, columnFamilyHandle.nativeHandle_); public void remove(ColumnFamilyHandle columnFamilyHandle, byte[] key)
throws RocksDBException {
delete(nativeHandle_, key, key.length, columnFamilyHandle.nativeHandle_);
} }
@Override @Override
public void deleteRange(byte[] beginKey, byte[] endKey) { public void delete(byte[] key) throws RocksDBException {
delete(nativeHandle_, key, key.length);
}
@Override
public void delete(ColumnFamilyHandle columnFamilyHandle, byte[] key)
throws RocksDBException {
delete(nativeHandle_, key, key.length, columnFamilyHandle.nativeHandle_);
}
@Override
public void singleDelete(byte[] key) throws RocksDBException {
singleDelete(nativeHandle_, key, key.length);
}
@Override
public void singleDelete(ColumnFamilyHandle columnFamilyHandle, byte[] key)
throws RocksDBException {
singleDelete(nativeHandle_, key, key.length, columnFamilyHandle.nativeHandle_);
}
@Override
public void deleteRange(byte[] beginKey, byte[] endKey)
throws RocksDBException {
deleteRange(nativeHandle_, beginKey, beginKey.length, endKey, endKey.length); deleteRange(nativeHandle_, beginKey, beginKey.length, endKey, endKey.length);
} }
@Override @Override
public void deleteRange(ColumnFamilyHandle columnFamilyHandle, byte[] beginKey, byte[] endKey) { public void deleteRange(ColumnFamilyHandle columnFamilyHandle,
byte[] beginKey, byte[] endKey) throws RocksDBException {
deleteRange(nativeHandle_, beginKey, beginKey.length, endKey, endKey.length, deleteRange(nativeHandle_, beginKey, beginKey.length, endKey, endKey.length,
columnFamilyHandle.nativeHandle_); columnFamilyHandle.nativeHandle_);
} }
@Override @Override
public void putLogData(byte[] blob) { public void putLogData(byte[] blob) throws RocksDBException {
putLogData(nativeHandle_, blob, blob.length); putLogData(nativeHandle_, blob, blob.length);
} }
@@ -82,38 +110,67 @@ public abstract class AbstractWriteBatch extends RocksObject
rollbackToSavePoint0(nativeHandle_); rollbackToSavePoint0(nativeHandle_);
} }
@Override
public void popSavePoint() throws RocksDBException {
popSavePoint(nativeHandle_);
}
@Override
public void setMaxBytes(final long maxBytes) {
setMaxBytes(nativeHandle_, maxBytes);
}
@Override
public WriteBatch getWriteBatch() {
return getWriteBatch(nativeHandle_);
}
abstract int count0(final long handle); abstract int count0(final long handle);
abstract void put(final long handle, final byte[] key, final int keyLen, abstract void put(final long handle, final byte[] key, final int keyLen,
final byte[] value, final int valueLen); final byte[] value, final int valueLen) throws RocksDBException;
abstract void put(final long handle, final byte[] key, final int keyLen, abstract void put(final long handle, final byte[] key, final int keyLen,
final byte[] value, final int valueLen, final long cfHandle); final byte[] value, final int valueLen, final long cfHandle)
throws RocksDBException;
abstract void merge(final long handle, final byte[] key, final int keyLen, abstract void merge(final long handle, final byte[] key, final int keyLen,
final byte[] value, final int valueLen); final byte[] value, final int valueLen) throws RocksDBException;
abstract void merge(final long handle, final byte[] key, final int keyLen, abstract void merge(final long handle, final byte[] key, final int keyLen,
final byte[] value, final int valueLen, final long cfHandle); final byte[] value, final int valueLen, final long cfHandle)
throws RocksDBException;
abstract void remove(final long handle, final byte[] key, abstract void delete(final long handle, final byte[] key,
final int keyLen); final int keyLen) throws RocksDBException;
abstract void remove(final long handle, final byte[] key, abstract void delete(final long handle, final byte[] key,
final int keyLen, final long cfHandle); final int keyLen, final long cfHandle) throws RocksDBException;
abstract void singleDelete(final long handle, final byte[] key,
final int keyLen) throws RocksDBException;
abstract void singleDelete(final long handle, final byte[] key,
final int keyLen, final long cfHandle) throws RocksDBException;
abstract void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen, abstract void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen,
final byte[] endKey, final int endKeyLen); final byte[] endKey, final int endKeyLen) throws RocksDBException;
abstract void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen, abstract void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen,
final byte[] endKey, final int endKeyLen, final long cfHandle); final byte[] endKey, final int endKeyLen, final long cfHandle) throws RocksDBException;
abstract void putLogData(final long handle, final byte[] blob, abstract void putLogData(final long handle, final byte[] blob,
final int blobLen); final int blobLen) throws RocksDBException;
abstract void clear0(final long handle); abstract void clear0(final long handle);
abstract void setSavePoint0(final long handle); abstract void setSavePoint0(final long handle);
abstract void rollbackToSavePoint0(final long handle); abstract void rollbackToSavePoint0(final long handle);
abstract void popSavePoint(final long handle) throws RocksDBException;
abstract void setMaxBytes(final long handle, long maxBytes);
abstract WriteBatch getWriteBatch(final long handle);
} }
@@ -15,6 +15,7 @@ public class BlockBasedTableConfig extends TableFormatConfig {
noBlockCache_ = false; noBlockCache_ = false;
blockCacheSize_ = 8 * 1024 * 1024; blockCacheSize_ = 8 * 1024 * 1024;
blockCacheNumShardBits_ = 0; blockCacheNumShardBits_ = 0;
blockCache_ = null;
blockSize_ = 4 * 1024; blockSize_ = 4 * 1024;
blockSizeDeviation_ = 10; blockSizeDeviation_ = 10;
blockRestartInterval_ = 16; blockRestartInterval_ = 16;
@@ -71,6 +72,24 @@ public class BlockBasedTableConfig extends TableFormatConfig {
return blockCacheSize_; return blockCacheSize_;
} }
/**
* Use the specified cache for blocks.
* When not null this take precedence even if the user sets a block cache size.
*
* {@link org.rocksdb.Cache} should not be disposed before options instances
* using this cache is disposed.
*
* {@link org.rocksdb.Cache} instance can be re-used in multiple options
* instances.
*
* @param cache {@link org.rocksdb.Cache} Cache java instance (e.g. LRUCache).
* @return the reference to the current config.
*/
public BlockBasedTableConfig setBlockCache(final Cache cache) {
blockCache_ = cache;
return this;
}
/** /**
* Controls the number of shards for the block cache. * Controls the number of shards for the block cache.
* This is applied only if cacheSize is set to non-negative. * This is applied only if cacheSize is set to non-negative.
@@ -413,25 +432,25 @@ public class BlockBasedTableConfig extends TableFormatConfig {
filterHandle = filter_.nativeHandle_; filterHandle = filter_.nativeHandle_;
} }
return newTableFactoryHandle(noBlockCache_, blockCacheSize_, long blockCacheHandle = 0;
blockCacheNumShardBits_, blockSize_, blockSizeDeviation_, if (blockCache_ != null) {
blockRestartInterval_, wholeKeyFiltering_, blockCacheHandle = blockCache_.nativeHandle_;
filterHandle, cacheIndexAndFilterBlocks_, }
pinL0FilterAndIndexBlocksInCache_,
hashIndexAllowCollision_, blockCacheCompressedSize_, return newTableFactoryHandle(noBlockCache_, blockCacheSize_, blockCacheNumShardBits_,
blockCacheCompressedNumShardBits_, blockCacheHandle, blockSize_, blockSizeDeviation_, blockRestartInterval_,
checksumType_.getValue(), indexType_.getValue(), wholeKeyFiltering_, filterHandle, cacheIndexAndFilterBlocks_,
pinL0FilterAndIndexBlocksInCache_, hashIndexAllowCollision_, blockCacheCompressedSize_,
blockCacheCompressedNumShardBits_, checksumType_.getValue(), indexType_.getValue(),
formatVersion_); formatVersion_);
} }
private native long newTableFactoryHandle( private native long newTableFactoryHandle(boolean noBlockCache, long blockCacheSize,
boolean noBlockCache, long blockCacheSize, int blockCacheNumShardBits, int blockCacheNumShardBits, long blockCacheHandle, long blockSize, int blockSizeDeviation,
long blockSize, int blockSizeDeviation, int blockRestartInterval, int blockRestartInterval, boolean wholeKeyFiltering, long filterPolicyHandle,
boolean wholeKeyFiltering, long filterPolicyHandle,
boolean cacheIndexAndFilterBlocks, boolean pinL0FilterAndIndexBlocksInCache, boolean cacheIndexAndFilterBlocks, boolean pinL0FilterAndIndexBlocksInCache,
boolean hashIndexAllowCollision, long blockCacheCompressedSize, boolean hashIndexAllowCollision, long blockCacheCompressedSize,
int blockCacheCompressedNumShardBits, byte checkSumType, int blockCacheCompressedNumShardBits, byte checkSumType, byte indexType, int formatVersion);
byte indexType, int formatVersion);
private boolean cacheIndexAndFilterBlocks_; private boolean cacheIndexAndFilterBlocks_;
private boolean pinL0FilterAndIndexBlocksInCache_; private boolean pinL0FilterAndIndexBlocksInCache_;
@@ -442,6 +461,7 @@ public class BlockBasedTableConfig extends TableFormatConfig {
private long blockSize_; private long blockSize_;
private long blockCacheSize_; private long blockCacheSize_;
private int blockCacheNumShardBits_; private int blockCacheNumShardBits_;
private Cache blockCache_;
private long blockCacheCompressedSize_; private long blockCacheCompressedSize_;
private int blockCacheCompressedNumShardBits_; private int blockCacheCompressedNumShardBits_;
private int blockSizeDeviation_; private int blockSizeDeviation_;
@@ -5,6 +5,8 @@
package org.rocksdb; package org.rocksdb;
import java.util.Arrays;
/** /**
* <p>Describes a column family with a * <p>Describes a column family with a
* name and respective Options.</p> * name and respective Options.</p>
@@ -32,7 +34,7 @@ public class ColumnFamilyDescriptor {
* @since 3.10.0 * @since 3.10.0
*/ */
public ColumnFamilyDescriptor(final byte[] columnFamilyName, public ColumnFamilyDescriptor(final byte[] columnFamilyName,
final ColumnFamilyOptions columnFamilyOptions) { final ColumnFamilyOptions columnFamilyOptions) {
columnFamilyName_ = columnFamilyName; columnFamilyName_ = columnFamilyName;
columnFamilyOptions_ = columnFamilyOptions; columnFamilyOptions_ = columnFamilyOptions;
} }
@@ -43,19 +45,65 @@ public class ColumnFamilyDescriptor {
* @return column family name. * @return column family name.
* @since 3.10.0 * @since 3.10.0
*/ */
public byte[] columnFamilyName() { public byte[] getName() {
return columnFamilyName_; return columnFamilyName_;
} }
/**
* Retrieve name of column family.
*
* @return column family name.
* @since 3.10.0
*
* @deprecated Use {@link #getName()} instead.
*/
@Deprecated
public byte[] columnFamilyName() {
return getName();
}
/** /**
* Retrieve assigned options instance. * Retrieve assigned options instance.
* *
* @return Options instance assigned to this instance. * @return Options instance assigned to this instance.
*/ */
public ColumnFamilyOptions columnFamilyOptions() { public ColumnFamilyOptions getOptions() {
return columnFamilyOptions_; return columnFamilyOptions_;
} }
/**
* Retrieve assigned options instance.
*
* @return Options instance assigned to this instance.
*
* @deprecated Use {@link #getOptions()} instead.
*/
@Deprecated
public ColumnFamilyOptions columnFamilyOptions() {
return getOptions();
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final ColumnFamilyDescriptor that = (ColumnFamilyDescriptor) o;
return Arrays.equals(columnFamilyName_, that.columnFamilyName_)
&& columnFamilyOptions_.nativeHandle_ == that.columnFamilyOptions_.nativeHandle_;
}
@Override
public int hashCode() {
int result = (int) (columnFamilyOptions_.nativeHandle_ ^ (columnFamilyOptions_.nativeHandle_ >>> 32));
result = 31 * result + Arrays.hashCode(columnFamilyName_);
return result;
}
private final byte[] columnFamilyName_; private final byte[] columnFamilyName_;
private final ColumnFamilyOptions columnFamilyOptions_; private final ColumnFamilyOptions columnFamilyOptions_;
} }
@@ -5,6 +5,9 @@
package org.rocksdb; package org.rocksdb;
import java.util.Arrays;
import java.util.Objects;
/** /**
* ColumnFamilyHandle class to hold handles to underlying rocksdb * ColumnFamilyHandle class to hold handles to underlying rocksdb
* ColumnFamily Pointers. * ColumnFamily Pointers.
@@ -21,6 +24,63 @@ public class ColumnFamilyHandle extends RocksObject {
this.rocksDB_ = rocksDB; this.rocksDB_ = rocksDB;
} }
/**
* Gets the name of the Column Family.
*
* @return The name of the Column Family.
*/
public byte[] getName() {
return getName(nativeHandle_);
}
/**
* Gets the ID of the Column Family.
*
* @return the ID of the Column Family.
*/
public int getID() {
return getID(nativeHandle_);
}
/**
* Gets the up-to-date descriptor of the column family
* associated with this handle. Since it fills "*desc" with the up-to-date
* information, this call might internally lock and release DB mutex to
* access the up-to-date CF options. In addition, all the pointer-typed
* options cannot be referenced any longer than the original options exist.
*
* Note that this function is not supported in RocksDBLite.
*
* @return the up-to-date descriptor.
*
* @throws RocksDBException if an error occurs whilst retrieving the
* descriptor.
*/
public ColumnFamilyDescriptor getDescriptor() throws RocksDBException {
assert(isOwningHandle());
return getDescriptor(nativeHandle_);
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final ColumnFamilyHandle that = (ColumnFamilyHandle) o;
return rocksDB_.nativeHandle_ == that.rocksDB_.nativeHandle_ &&
getID() == that.getID() &&
Arrays.equals(getName(), that.getName());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getID(), rocksDB_.nativeHandle_);
}
/** /**
* <p>Deletes underlying C++ iterator pointer.</p> * <p>Deletes underlying C++ iterator pointer.</p>
* *
@@ -36,6 +96,9 @@ public class ColumnFamilyHandle extends RocksObject {
} }
} }
private native byte[] getName(final long handle);
private native int getID(final long handle);
private native ColumnFamilyDescriptor getDescriptor(final long handle) throws RocksDBException;
@Override protected final native void disposeInternal(final long handle); @Override protected final native void disposeInternal(final long handle);
private final RocksDB rocksDB_; private final RocksDB rocksDB_;
@@ -53,6 +53,18 @@ public class ColumnFamilyOptions extends RocksObject
this.compressionOptions_ = other.compressionOptions_; this.compressionOptions_ = other.compressionOptions_;
} }
/**
* <p>Constructor to be used by
* {@link #getColumnFamilyOptionsFromProps(java.util.Properties)},
* {@link ColumnFamilyDescriptor#columnFamilyOptions()}
* and also called via JNI.</p>
*
* @param handle native handle to ColumnFamilyOptions instance.
*/
ColumnFamilyOptions(final long handle) {
super(handle);
}
/** /**
* <p>Method to get a options instance by using pre-configured * <p>Method to get a options instance by using pre-configured
* property values. If one or many values are undefined in * property values. If one or many values are undefined in
@@ -151,7 +163,7 @@ public class ColumnFamilyOptions extends RocksObject
final AbstractComparator<? extends AbstractSlice<?>> comparator) { final AbstractComparator<? extends AbstractSlice<?>> comparator) {
assert (isOwningHandle()); assert (isOwningHandle());
setComparatorHandle(nativeHandle_, comparator.nativeHandle_, setComparatorHandle(nativeHandle_, comparator.nativeHandle_,
comparator instanceof DirectComparator); comparator.getComparatorType().getValue());
comparator_ = comparator; comparator_ = comparator;
return this; return this;
} }
@@ -788,17 +800,6 @@ public class ColumnFamilyOptions extends RocksObject
return forceConsistencyChecks(nativeHandle_); return forceConsistencyChecks(nativeHandle_);
} }
/**
* <p>Constructor to be used by
* {@link #getColumnFamilyOptionsFromProps(java.util.Properties)}</p>
* and also called via JNI.
*
* @param handle native handle to ColumnFamilyOptions instance.
*/
public ColumnFamilyOptions(final long handle) {
super(handle);
}
private static native long getColumnFamilyOptionsFromProps( private static native long getColumnFamilyOptionsFromProps(
String optString); String optString);
@@ -815,7 +816,7 @@ public class ColumnFamilyOptions extends RocksObject
long memtableMemoryBudget); long memtableMemoryBudget);
private native void setComparatorHandle(long handle, int builtinComparator); private native void setComparatorHandle(long handle, int builtinComparator);
private native void setComparatorHandle(long optHandle, private native void setComparatorHandle(long optHandle,
long comparatorHandle, boolean isDirect); long comparatorHandle, byte comparatorType);
private native void setMergeOperatorName(long handle, String name); private native void setMergeOperatorName(long handle, String name);
private native void setMergeOperator(long handle, long mergeOperatorHandle); private native void setMergeOperator(long handle, long mergeOperatorHandle);
private native void setCompactionFilterHandle(long handle, private native void setCompactionFilterHandle(long handle,
@@ -25,5 +25,10 @@ public abstract class Comparator extends AbstractComparator<Slice> {
return createNewComparator0(nativeParameterHandles[0]); return createNewComparator0(nativeParameterHandles[0]);
} }
@Override
final ComparatorType getComparatorType() {
return ComparatorType.JAVA_COMPARATOR;
}
private native long createNewComparator0(final long comparatorOptionsHandle); private native long createNewComparator0(final long comparatorOptionsHandle);
} }
@@ -0,0 +1,49 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
enum ComparatorType {
JAVA_COMPARATOR((byte)0x0),
JAVA_DIRECT_COMPARATOR((byte)0x1),
JAVA_NATIVE_COMPARATOR_WRAPPER((byte)0x2);
private final byte value;
ComparatorType(final byte value) {
this.value = value;
}
/**
* <p>Returns the byte value of the enumerations value.</p>
*
* @return byte representation
*/
byte getValue() {
return value;
}
/**
* <p>Get the ComparatorType enumeration value by
* passing the byte identifier to this method.</p>
*
* @param byteIdentifier of ComparatorType.
*
* @return ComparatorType instance.
*
* @throws IllegalArgumentException if the comparator type for the byteIdentifier
* cannot be found
*/
static ComparatorType getComparatorType(final byte byteIdentifier) {
for (final ComparatorType comparatorType : ComparatorType.values()) {
if (comparatorType.getValue() == byteIdentifier) {
return comparatorType;
}
}
throw new IllegalArgumentException(
"Illegal value provided for ComparatorType.");
}
}
@@ -269,7 +269,10 @@ public interface DBOptionsInterface<T extends DBOptionsInterface> {
* Statistics objects should not be shared between DB instances as * Statistics objects should not be shared between DB instances as
* it does not use any locks to prevent concurrent updates.</p> * it does not use any locks to prevent concurrent updates.</p>
* *
* @param statistics The statistics to set
*
* @return the instance of the current object. * @return the instance of the current object.
*
* @see RocksDB#open(org.rocksdb.Options, String) * @see RocksDB#open(org.rocksdb.Options, String)
*/ */
T setStatistics(final Statistics statistics); T setStatistics(final Statistics statistics);
@@ -277,7 +280,9 @@ public interface DBOptionsInterface<T extends DBOptionsInterface> {
/** /**
* <p>Returns statistics object.</p> * <p>Returns statistics object.</p>
* *
* @return the instance of the statistics object or null if there is no statistics object. * @return the instance of the statistics object or null if there is no
* statistics object.
*
* @see #setStatistics(Statistics) * @see #setStatistics(Statistics)
*/ */
Statistics statistics(); Statistics statistics();
@@ -25,6 +25,11 @@ public abstract class DirectComparator extends AbstractComparator<DirectSlice> {
return createNewDirectComparator0(nativeParameterHandles[0]); return createNewDirectComparator0(nativeParameterHandles[0]);
} }
@Override
final ComparatorType getComparatorType() {
return ComparatorType.JAVA_DIRECT_COMPARATOR;
}
private native long createNewDirectComparator0( private native long createNewDirectComparator0(
final long comparatorOptionsHandle); final long comparatorOptionsHandle);
} }
@@ -0,0 +1,57 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
/**
* A simple abstraction to allow a Java class to wrap a custom comparator
* implemented in C++.
*
* The native comparator must directly extend rocksdb::Comparator.
*/
public abstract class NativeComparatorWrapper
extends AbstractComparator<Slice> {
@Override
final ComparatorType getComparatorType() {
return ComparatorType.JAVA_NATIVE_COMPARATOR_WRAPPER;
}
@Override
public final String name() {
throw new IllegalStateException("This should not be called. " +
"Implementation is in Native code");
}
@Override
public final int compare(final Slice s1, final Slice s2) {
throw new IllegalStateException("This should not be called. " +
"Implementation is in Native code");
}
@Override
public final String findShortestSeparator(final String start, final Slice limit) {
throw new IllegalStateException("This should not be called. " +
"Implementation is in Native code");
}
@Override
public final String findShortSuccessor(final String key) {
throw new IllegalStateException("This should not be called. " +
"Implementation is in Native code");
}
/**
* We override {@link RocksCallbackObject#disposeInternal()}
* as disposing of a native rocksd::Comparator extension requires
* a slightly different approach as it is not really a RocksCallbackObject
*/
@Override
protected void disposeInternal() {
disposeInternal(nativeHandle_);
}
private native void disposeInternal(final long handle);
}
@@ -0,0 +1,175 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
import java.util.List;
/**
* Database with Transaction support.
*/
public class OptimisticTransactionDB extends RocksDB
implements TransactionalDB<OptimisticTransactionOptions> {
/**
* Private constructor.
*
* @param nativeHandle The native handle of the C++ OptimisticTransactionDB
* object
*/
private OptimisticTransactionDB(final long nativeHandle) {
super(nativeHandle);
}
/**
* Open an OptimisticTransactionDB similar to
* {@link RocksDB#open(Options, String)}.
*
* @param options {@link org.rocksdb.Options} instance.
* @param path the path to the rocksdb.
*
* @return a {@link OptimisticTransactionDB} instance on success, null if the
* specified {@link OptimisticTransactionDB} can not be opened.
*
* @throws RocksDBException if an error occurs whilst opening the database.
*/
public static OptimisticTransactionDB open(final Options options,
final String path) throws RocksDBException {
final OptimisticTransactionDB otdb = new OptimisticTransactionDB(open(
options.nativeHandle_, path));
// when non-default Options is used, keeping an Options reference
// in RocksDB can prevent Java to GC during the life-time of
// the currently-created RocksDB.
otdb.storeOptionsInstance(options);
return otdb;
}
/**
* Open an OptimisticTransactionDB similar to
* {@link RocksDB#open(DBOptions, String, List, List)}.
*
* @param dbOptions {@link org.rocksdb.DBOptions} instance.
* @param path the path to the rocksdb.
* @param columnFamilyDescriptors list of column family descriptors
* @param columnFamilyHandles will be filled with ColumnFamilyHandle instances
*
* @return a {@link OptimisticTransactionDB} instance on success, null if the
* specified {@link OptimisticTransactionDB} can not be opened.
*
* @throws RocksDBException if an error occurs whilst opening the database.
*/
public static OptimisticTransactionDB open(final DBOptions dbOptions,
final String path,
final List<ColumnFamilyDescriptor> columnFamilyDescriptors,
final List<ColumnFamilyHandle> columnFamilyHandles)
throws RocksDBException {
final byte[][] cfNames = new byte[columnFamilyDescriptors.size()][];
final long[] cfOptionHandles = new long[columnFamilyDescriptors.size()];
for (int i = 0; i < columnFamilyDescriptors.size(); i++) {
final ColumnFamilyDescriptor cfDescriptor = columnFamilyDescriptors
.get(i);
cfNames[i] = cfDescriptor.columnFamilyName();
cfOptionHandles[i] = cfDescriptor.columnFamilyOptions().nativeHandle_;
}
final long[] handles = open(dbOptions.nativeHandle_, path, cfNames,
cfOptionHandles);
final OptimisticTransactionDB otdb =
new OptimisticTransactionDB(handles[0]);
// when non-default Options is used, keeping an Options reference
// in RocksDB can prevent Java to GC during the life-time of
// the currently-created RocksDB.
otdb.storeOptionsInstance(dbOptions);
for (int i = 1; i < handles.length; i++) {
columnFamilyHandles.add(new ColumnFamilyHandle(otdb, handles[i]));
}
return otdb;
}
@Override
public Transaction beginTransaction(final WriteOptions writeOptions) {
return new Transaction(this, beginTransaction(nativeHandle_,
writeOptions.nativeHandle_));
}
@Override
public Transaction beginTransaction(final WriteOptions writeOptions,
final OptimisticTransactionOptions optimisticTransactionOptions) {
return new Transaction(this, beginTransaction(nativeHandle_,
writeOptions.nativeHandle_,
optimisticTransactionOptions.nativeHandle_));
}
// TODO(AR) consider having beingTransaction(... oldTransaction) set a
// reference count inside Transaction, so that we can always call
// Transaction#close but the object is only disposed when there are as many
// closes as beginTransaction. Makes the try-with-resources paradigm easier for
// java developers
@Override
public Transaction beginTransaction(final WriteOptions writeOptions,
final Transaction oldTransaction) {
final long jtxn_handle = beginTransaction_withOld(nativeHandle_,
writeOptions.nativeHandle_, oldTransaction.nativeHandle_);
// RocksJava relies on the assumption that
// we do not allocate a new Transaction object
// when providing an old_txn
assert(jtxn_handle == oldTransaction.nativeHandle_);
return oldTransaction;
}
@Override
public Transaction beginTransaction(final WriteOptions writeOptions,
final OptimisticTransactionOptions optimisticTransactionOptions,
final Transaction oldTransaction) {
final long jtxn_handle = beginTransaction_withOld(nativeHandle_,
writeOptions.nativeHandle_, optimisticTransactionOptions.nativeHandle_,
oldTransaction.nativeHandle_);
// RocksJava relies on the assumption that
// we do not allocate a new Transaction object
// when providing an old_txn
assert(jtxn_handle == oldTransaction.nativeHandle_);
return oldTransaction;
}
/**
* Get the underlying database that was opened.
*
* @return The underlying database that was opened.
*/
public RocksDB getBaseDB() {
final RocksDB db = new RocksDB(getBaseDB(nativeHandle_));
db.disOwnNativeHandle();
return db;
}
protected static native long open(final long optionsHandle,
final String path) throws RocksDBException;
protected static native long[] open(final long handle, final String path,
final byte[][] columnFamilyNames, final long[] columnFamilyOptions);
private native long beginTransaction(final long handle,
final long writeOptionsHandle);
private native long beginTransaction(final long handle,
final long writeOptionsHandle,
final long optimisticTransactionOptionsHandle);
private native long beginTransaction_withOld(final long handle,
final long writeOptionsHandle, final long oldTransactionHandle);
private native long beginTransaction_withOld(final long handle,
final long writeOptionsHandle,
final long optimisticTransactionOptionsHandle,
final long oldTransactionHandle);
private native long getBaseDB(final long handle);
@Override protected final native void disposeInternal(final long handle);
}
@@ -0,0 +1,53 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
public class OptimisticTransactionOptions extends RocksObject
implements TransactionalOptions {
public OptimisticTransactionOptions() {
super(newOptimisticTransactionOptions());
}
@Override
public boolean isSetSnapshot() {
assert(isOwningHandle());
return isSetSnapshot(nativeHandle_);
}
@Override
public OptimisticTransactionOptions setSetSnapshot(
final boolean setSnapshot) {
assert(isOwningHandle());
setSetSnapshot(nativeHandle_, setSnapshot);
return this;
}
/**
* Should be set if the DB has a non-default comparator.
* See comment in
* {@link WriteBatchWithIndex#WriteBatchWithIndex(AbstractComparator, int, boolean)}
* constructor.
*
* @param comparator The comparator to use for the transaction.
*
* @return this OptimisticTransactionOptions instance
*/
public OptimisticTransactionOptions setComparator(
final AbstractComparator<? extends AbstractSlice<?>> comparator) {
assert(isOwningHandle());
setComparator(nativeHandle_, comparator.nativeHandle_);
return this;
}
private native static long newOptimisticTransactionOptions();
private native boolean isSetSnapshot(final long handle);
private native void setSetSnapshot(final long handle,
final boolean setSnapshot);
private native void setComparator(final long handle,
final long comparatorHandle);
@Override protected final native void disposeInternal(final long handle);
}
+2 -2
View File
@@ -191,7 +191,7 @@ public class Options extends RocksObject
final AbstractComparator<? extends AbstractSlice<?>> comparator) { final AbstractComparator<? extends AbstractSlice<?>> comparator) {
assert(isOwningHandle()); assert(isOwningHandle());
setComparatorHandle(nativeHandle_, comparator.nativeHandle_, setComparatorHandle(nativeHandle_, comparator.nativeHandle_,
comparator instanceof DirectComparator); comparator.getComparatorType().getValue());
comparator_ = comparator; comparator_ = comparator;
return this; return this;
} }
@@ -1756,7 +1756,7 @@ public class Options extends RocksObject
long memtableMemoryBudget); long memtableMemoryBudget);
private native void setComparatorHandle(long handle, int builtinComparator); private native void setComparatorHandle(long handle, int builtinComparator);
private native void setComparatorHandle(long optHandle, private native void setComparatorHandle(long optHandle,
long comparatorHandle, boolean isDirect); long comparatorHandle, byte comparatorType);
private native void setMergeOperatorName( private native void setMergeOperatorName(
long handle, String name); long handle, String name);
private native void setMergeOperator( private native void setMergeOperator(
+5 -4
View File
@@ -435,7 +435,7 @@ public class RocksDB extends RocksObject {
path)); path));
} }
private void storeOptionsInstance(DBOptionsInterface options) { protected void storeOptionsInstance(DBOptionsInterface options) {
options_ = options; options_ = options;
} }
@@ -1683,7 +1683,7 @@ public class RocksDB extends RocksObject {
* @return The handle of the default column family * @return The handle of the default column family
*/ */
public ColumnFamilyHandle getDefaultColumnFamily() { public ColumnFamilyHandle getDefaultColumnFamily() {
ColumnFamilyHandle cfHandle = new ColumnFamilyHandle(this, final ColumnFamilyHandle cfHandle = new ColumnFamilyHandle(this,
getDefaultColumnFamily(nativeHandle_)); getDefaultColumnFamily(nativeHandle_));
cfHandle.disOwnNativeHandle(); cfHandle.disOwnNativeHandle();
return cfHandle; return cfHandle;
@@ -2359,8 +2359,9 @@ public class RocksDB extends RocksObject {
final long[] columnFamilyHandles, final long readOptHandle) final long[] columnFamilyHandles, final long readOptHandle)
throws RocksDBException; throws RocksDBException;
protected native long getSnapshot(long nativeHandle); protected native long getSnapshot(long nativeHandle);
protected native void releaseSnapshot(long nativeHandle, long snapshotHandle); protected native void releaseSnapshot(
@Override protected final native void disposeInternal(final long handle); long nativeHandle, long snapshotHandle);
@Override protected native void disposeInternal(final long handle);
private native long getDefaultColumnFamily(long handle); private native long getDefaultColumnFamily(long handle);
private native long createColumnFamily(final long handle, private native long createColumnFamily(final long handle,
final byte[] columnFamilyName, final long columnFamilyOptions) final byte[] columnFamilyName, final long columnFamilyOptions)
+10 -6
View File
@@ -11,6 +11,10 @@ package org.rocksdb;
public class Snapshot extends RocksObject { public class Snapshot extends RocksObject {
Snapshot(final long nativeHandle) { Snapshot(final long nativeHandle) {
super(nativeHandle); super(nativeHandle);
// The pointer to the snapshot is always released
// by the database instance.
disOwnNativeHandle();
} }
/** /**
@@ -20,17 +24,17 @@ public class Snapshot extends RocksObject {
* this snapshot. * this snapshot.
*/ */
public long getSequenceNumber() { public long getSequenceNumber() {
assert(isOwningHandle());
return getSequenceNumber(nativeHandle_); return getSequenceNumber(nativeHandle_);
} }
/**
* Dont release C++ Snapshot pointer. The pointer
* to the snapshot is released by the database
* instance.
*/
@Override @Override
protected final void disposeInternal(final long handle) { protected final void disposeInternal(final long handle) {
/**
* Nothing to release, we never own the pointer for a
* Snapshot. The pointer
* to the snapshot is released by the database
* instance.
*/
} }
private native long getSequenceNumber(long handle); private native long getSequenceNumber(long handle);
@@ -31,7 +31,7 @@ public class SstFileWriter extends RocksObject {
final AbstractComparator<? extends AbstractSlice<?>> comparator) { final AbstractComparator<? extends AbstractSlice<?>> comparator) {
super(newSstFileWriter( super(newSstFileWriter(
envOptions.nativeHandle_, options.nativeHandle_, comparator.nativeHandle_, envOptions.nativeHandle_, options.nativeHandle_, comparator.nativeHandle_,
comparator instanceof DirectComparator)); comparator.getComparatorType().getValue()));
} }
/** /**
@@ -225,7 +225,7 @@ public void put(final byte[] key, final byte[] value)
private native static long newSstFileWriter( private native static long newSstFileWriter(
final long envOptionsHandle, final long optionsHandle, final long envOptionsHandle, final long optionsHandle,
final long userComparatorHandle, final boolean isDirect); final long userComparatorHandle, final byte comparatorType);
private native static long newSstFileWriter(final long envOptionsHandle, private native static long newSstFileWriter(final long envOptionsHandle,
final long optionsHandle); final long optionsHandle);
@@ -117,6 +117,8 @@ public class Statistics extends RocksObject {
/** /**
* Resets all ticker and histogram stats. * Resets all ticker and histogram stats.
*
* @throws RocksDBException if an error occurs when resetting the statistics.
*/ */
public void reset() throws RocksDBException { public void reset() throws RocksDBException {
assert(isOwningHandle()); assert(isOwningHandle());
@@ -126,6 +128,7 @@ public class Statistics extends RocksObject {
/** /**
* String representation of the statistic object. * String representation of the statistic object.
*/ */
@Override
public String toString() { public String toString() {
assert(isOwningHandle()); assert(isOwningHandle());
return toString(nativeHandle_); return toString(nativeHandle_);
@@ -87,6 +87,15 @@ public class Status {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Illegal value provided for Code (" + value + ")."); "Illegal value provided for Code (" + value + ").");
} }
/**
* Returns the byte value of the enumerations value.
*
* @return byte representation
*/
public byte getValue() {
return value;
}
} }
// should stay in sync with /include/rocksdb/status.h:SubCode and /java/rocksjni/portal.h:toJavaStatusSubCode // should stay in sync with /include/rocksdb/status.h:SubCode and /java/rocksjni/portal.h:toJavaStatusSubCode
@@ -116,5 +125,14 @@ public class Status {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Illegal value provided for SubCode (" + value + ")."); "Illegal value provided for SubCode (" + value + ").");
} }
/**
* Returns the byte value of the enumerations value.
*
* @return byte representation
*/
public byte getValue() {
return value;
}
} }
} }
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,354 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Database with Transaction support
*/
public class TransactionDB extends RocksDB
implements TransactionalDB<TransactionOptions> {
private TransactionDBOptions transactionDbOptions_;
/**
* Private constructor.
*
* @param nativeHandle The native handle of the C++ TransactionDB object
*/
private TransactionDB(final long nativeHandle) {
super(nativeHandle);
}
/**
* Open a TransactionDB, similar to {@link RocksDB#open(Options, String)}.
*
* @param options {@link org.rocksdb.Options} instance.
* @param transactionDbOptions {@link org.rocksdb.TransactionDBOptions}
* instance.
* @param path the path to the rocksdb.
*
* @return a {@link TransactionDB} instance on success, null if the specified
* {@link TransactionDB} can not be opened.
*
* @throws RocksDBException if an error occurs whilst opening the database.
*/
public static TransactionDB open(final Options options,
final TransactionDBOptions transactionDbOptions, final String path)
throws RocksDBException {
final TransactionDB tdb = new TransactionDB(open(options.nativeHandle_,
transactionDbOptions.nativeHandle_, path));
// when non-default Options is used, keeping an Options reference
// in RocksDB can prevent Java to GC during the life-time of
// the currently-created RocksDB.
tdb.storeOptionsInstance(options);
tdb.storeTransactionDbOptions(transactionDbOptions);
return tdb;
}
/**
* Open a TransactionDB, similar to
* {@link RocksDB#open(DBOptions, String, List, List)}.
*
* @param dbOptions {@link org.rocksdb.DBOptions} instance.
* @param transactionDbOptions {@link org.rocksdb.TransactionDBOptions}
* instance.
* @param path the path to the rocksdb.
* @param columnFamilyDescriptors list of column family descriptors
* @param columnFamilyHandles will be filled with ColumnFamilyHandle instances
*
* @return a {@link TransactionDB} instance on success, null if the specified
* {@link TransactionDB} can not be opened.
*
* @throws RocksDBException if an error occurs whilst opening the database.
*/
public static TransactionDB open(final DBOptions dbOptions,
final TransactionDBOptions transactionDbOptions,
final String path,
final List<ColumnFamilyDescriptor> columnFamilyDescriptors,
final List<ColumnFamilyHandle> columnFamilyHandles)
throws RocksDBException {
final byte[][] cfNames = new byte[columnFamilyDescriptors.size()][];
final long[] cfOptionHandles = new long[columnFamilyDescriptors.size()];
for (int i = 0; i < columnFamilyDescriptors.size(); i++) {
final ColumnFamilyDescriptor cfDescriptor = columnFamilyDescriptors
.get(i);
cfNames[i] = cfDescriptor.columnFamilyName();
cfOptionHandles[i] = cfDescriptor.columnFamilyOptions().nativeHandle_;
}
final long[] handles = open(dbOptions.nativeHandle_,
transactionDbOptions.nativeHandle_, path, cfNames, cfOptionHandles);
final TransactionDB tdb = new TransactionDB(handles[0]);
// when non-default Options is used, keeping an Options reference
// in RocksDB can prevent Java to GC during the life-time of
// the currently-created RocksDB.
tdb.storeOptionsInstance(dbOptions);
tdb.storeTransactionDbOptions(transactionDbOptions);
for (int i = 1; i < handles.length; i++) {
columnFamilyHandles.add(new ColumnFamilyHandle(tdb, handles[i]));
}
return tdb;
}
@Override
public Transaction beginTransaction(final WriteOptions writeOptions) {
return new Transaction(this, beginTransaction(nativeHandle_,
writeOptions.nativeHandle_));
}
@Override
public Transaction beginTransaction(final WriteOptions writeOptions,
final TransactionOptions transactionOptions) {
return new Transaction(this, beginTransaction(nativeHandle_,
writeOptions.nativeHandle_, transactionOptions.nativeHandle_));
}
// TODO(AR) consider having beingTransaction(... oldTransaction) set a
// reference count inside Transaction, so that we can always call
// Transaction#close but the object is only disposed when there are as many
// closes as beginTransaction. Makes the try-with-resources paradigm easier for
// java developers
@Override
public Transaction beginTransaction(final WriteOptions writeOptions,
final Transaction oldTransaction) {
final long jtxnHandle = beginTransaction_withOld(nativeHandle_,
writeOptions.nativeHandle_, oldTransaction.nativeHandle_);
// RocksJava relies on the assumption that
// we do not allocate a new Transaction object
// when providing an old_txn
assert(jtxnHandle == oldTransaction.nativeHandle_);
return oldTransaction;
}
@Override
public Transaction beginTransaction(final WriteOptions writeOptions,
final TransactionOptions transactionOptions,
final Transaction oldTransaction) {
final long jtxn_handle = beginTransaction_withOld(nativeHandle_,
writeOptions.nativeHandle_, transactionOptions.nativeHandle_,
oldTransaction.nativeHandle_);
// RocksJava relies on the assumption that
// we do not allocate a new Transaction object
// when providing an old_txn
assert(jtxn_handle == oldTransaction.nativeHandle_);
return oldTransaction;
}
public Transaction getTransactionByName(final String transactionName) {
final long jtxnHandle = getTransactionByName(nativeHandle_, transactionName);
if(jtxnHandle == 0) {
return null;
}
final Transaction txn = new Transaction(this, jtxnHandle);
// this instance doesn't own the underlying C++ object
txn.disOwnNativeHandle();
return txn;
}
public List<Transaction> getAllPreparedTransactions() {
final long[] jtxnHandles = getAllPreparedTransactions(nativeHandle_);
final List<Transaction> txns = new ArrayList<>();
for(final long jtxnHandle : jtxnHandles) {
final Transaction txn = new Transaction(this, jtxnHandle);
// this instance doesn't own the underlying C++ object
txn.disOwnNativeHandle();
txns.add(txn);
}
return txns;
}
public static class KeyLockInfo {
private final String key;
private final long[] transactionIDs;
private final boolean exclusive;
public KeyLockInfo(final String key, final long transactionIDs[],
final boolean exclusive) {
this.key = key;
this.transactionIDs = transactionIDs;
this.exclusive = exclusive;
}
/**
* Get the key.
*
* @return the key
*/
public String getKey() {
return key;
}
/**
* Get the Transaction IDs.
*
* @return the Transaction IDs.
*/
public long[] getTransactionIDs() {
return transactionIDs;
}
/**
* Get the Lock status.
*
* @return true if the lock is exclusive, false if the lock is shared.
*/
public boolean isExclusive() {
return exclusive;
}
}
/**
* Returns map of all locks held.
*
* @return a map of all the locks held.
*/
public Map<Long, KeyLockInfo> getLockStatusData() {
return getLockStatusData(nativeHandle_);
}
/**
* Called from C++ native method {@link #getDeadlockInfoBuffer(long)}
* to construct a DeadlockInfo object.
*
* @param transactionID The transaction id
* @param columnFamilyId The id of the {@link ColumnFamilyHandle}
* @param waitingKey the key that we are waiting on
* @param exclusive true if the lock is exclusive, false if the lock is shared
*
* @return The waiting transactions
*/
private DeadlockInfo newDeadlockInfo(
final long transactionID, final long columnFamilyId,
final String waitingKey, final boolean exclusive) {
return new DeadlockInfo(transactionID, columnFamilyId,
waitingKey, exclusive);
}
public static class DeadlockInfo {
private final long transactionID;
private final long columnFamilyId;
private final String waitingKey;
private final boolean exclusive;
private DeadlockInfo(final long transactionID, final long columnFamilyId,
final String waitingKey, final boolean exclusive) {
this.transactionID = transactionID;
this.columnFamilyId = columnFamilyId;
this.waitingKey = waitingKey;
this.exclusive = exclusive;
}
/**
* Get the Transaction ID.
*
* @return the transaction ID
*/
public long getTransactionID() {
return transactionID;
}
/**
* Get the Column Family ID.
*
* @return The column family ID
*/
public long getColumnFamilyId() {
return columnFamilyId;
}
/**
* Get the key that we are waiting on.
*
* @return the key that we are waiting on
*/
public String getWaitingKey() {
return waitingKey;
}
/**
* Get the Lock status.
*
* @return true if the lock is exclusive, false if the lock is shared.
*/
public boolean isExclusive() {
return exclusive;
}
}
public static class DeadlockPath {
final DeadlockInfo[] path;
final boolean limitExceeded;
public DeadlockPath(final DeadlockInfo[] path, final boolean limitExceeded) {
this.path = path;
this.limitExceeded = limitExceeded;
}
public boolean isEmpty() {
return path.length == 0 && !limitExceeded;
}
}
public DeadlockPath[] getDeadlockInfoBuffer() {
return getDeadlockInfoBuffer(nativeHandle_);
}
public void setDeadlockInfoBufferSize(final int targetSize) {
setDeadlockInfoBufferSize(nativeHandle_, targetSize);
}
private void storeTransactionDbOptions(
final TransactionDBOptions transactionDbOptions) {
this.transactionDbOptions_ = transactionDbOptions;
}
private static native long open(final long optionsHandle,
final long transactionDbOptionsHandle, final String path)
throws RocksDBException;
private static native long[] open(final long dbOptionsHandle,
final long transactionDbOptionsHandle, final String path,
final byte[][] columnFamilyNames, final long[] columnFamilyOptions);
private native long beginTransaction(final long handle,
final long writeOptionsHandle);
private native long beginTransaction(final long handle,
final long writeOptionsHandle, final long transactionOptionsHandle);
private native long beginTransaction_withOld(final long handle,
final long writeOptionsHandle, final long oldTransactionHandle);
private native long beginTransaction_withOld(final long handle,
final long writeOptionsHandle, final long transactionOptionsHandle,
final long oldTransactionHandle);
private native long getTransactionByName(final long handle,
final String name);
private native long[] getAllPreparedTransactions(final long handle);
private native Map<Long, KeyLockInfo> getLockStatusData(
final long handle);
private native DeadlockPath[] getDeadlockInfoBuffer(final long handle);
private native void setDeadlockInfoBufferSize(final long handle,
final int targetSize);
@Override protected final native void disposeInternal(final long handle);
}
@@ -0,0 +1,217 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
public class TransactionDBOptions extends RocksObject {
public TransactionDBOptions() {
super(newTransactionDBOptions());
}
/**
* Specifies the maximum number of keys that can be locked at the same time
* per column family.
*
* If the number of locked keys is greater than {@link #getMaxNumLocks()},
* transaction writes (or GetForUpdate) will return an error.
*
* @return The maximum number of keys that can be locked
*/
public long getMaxNumLocks() {
assert(isOwningHandle());
return getMaxNumLocks(nativeHandle_);
}
/**
* Specifies the maximum number of keys that can be locked at the same time
* per column family.
*
* If the number of locked keys is greater than {@link #getMaxNumLocks()},
* transaction writes (or GetForUpdate) will return an error.
*
* @param maxNumLocks The maximum number of keys that can be locked;
* If this value is not positive, no limit will be enforced.
*
* @return this TransactionDBOptions instance
*/
public TransactionDBOptions setMaxNumLocks(final long maxNumLocks) {
assert(isOwningHandle());
setMaxNumLocks(nativeHandle_, maxNumLocks);
return this;
}
/**
* The number of sub-tables per lock table (per column family)
*
* @return The number of sub-tables
*/
public long getNumStripes() {
assert(isOwningHandle());
return getNumStripes(nativeHandle_);
}
/**
* Increasing this value will increase the concurrency by dividing the lock
* table (per column family) into more sub-tables, each with their own
* separate mutex.
*
* Default: 16
*
* @param numStripes The number of sub-tables
*
* @return this TransactionDBOptions instance
*/
public TransactionDBOptions setNumStripes(final long numStripes) {
assert(isOwningHandle());
setNumStripes(nativeHandle_, numStripes);
return this;
}
/**
* The default wait timeout in milliseconds when
* a transaction attempts to lock a key if not specified by
* {@link TransactionOptions#setLockTimeout(long)}
*
* If 0, no waiting is done if a lock cannot instantly be acquired.
* If negative, there is no timeout.
*
* @return the default wait timeout in milliseconds
*/
public long getTransactionLockTimeout() {
assert(isOwningHandle());
return getTransactionLockTimeout(nativeHandle_);
}
/**
* If positive, specifies the default wait timeout in milliseconds when
* a transaction attempts to lock a key if not specified by
* {@link TransactionOptions#setLockTimeout(long)}
*
* If 0, no waiting is done if a lock cannot instantly be acquired.
* If negative, there is no timeout. Not using a timeout is not recommended
* as it can lead to deadlocks. Currently, there is no deadlock-detection to
* recover from a deadlock.
*
* Default: 1000
*
* @param transactionLockTimeout the default wait timeout in milliseconds
*
* @return this TransactionDBOptions instance
*/
public TransactionDBOptions setTransactionLockTimeout(
final long transactionLockTimeout) {
assert(isOwningHandle());
setTransactionLockTimeout(nativeHandle_, transactionLockTimeout);
return this;
}
/**
* The wait timeout in milliseconds when writing a key
* OUTSIDE of a transaction (ie by calling {@link RocksDB#put},
* {@link RocksDB#merge}, {@link RocksDB#remove} or {@link RocksDB#write}
* directly).
*
* If 0, no waiting is done if a lock cannot instantly be acquired.
* If negative, there is no timeout and will block indefinitely when acquiring
* a lock.
*
* @return the timeout in milliseconds when writing a key OUTSIDE of a
* transaction
*/
public long getDefaultLockTimeout() {
assert(isOwningHandle());
return getDefaultLockTimeout(nativeHandle_);
}
/**
* If positive, specifies the wait timeout in milliseconds when writing a key
* OUTSIDE of a transaction (ie by calling {@link RocksDB#put},
* {@link RocksDB#merge}, {@link RocksDB#remove} or {@link RocksDB#write}
* directly).
*
* If 0, no waiting is done if a lock cannot instantly be acquired.
* If negative, there is no timeout and will block indefinitely when acquiring
* a lock.
*
* Not using a timeout can lead to deadlocks. Currently, there
* is no deadlock-detection to recover from a deadlock. While DB writes
* cannot deadlock with other DB writes, they can deadlock with a transaction.
* A negative timeout should only be used if all transactions have a small
* expiration set.
*
* Default: 1000
*
* @param defaultLockTimeout the timeout in milliseconds when writing a key
* OUTSIDE of a transaction
* @return this TransactionDBOptions instance
*/
public TransactionDBOptions setDefaultLockTimeout(
final long defaultLockTimeout) {
assert(isOwningHandle());
setDefaultLockTimeout(nativeHandle_, defaultLockTimeout);
return this;
}
// /**
// * If set, the {@link TransactionDB} will use this implementation of a mutex
// * and condition variable for all transaction locking instead of the default
// * mutex/condvar implementation.
// *
// * @param transactionDbMutexFactory the mutex factory for the transactions
// *
// * @return this TransactionDBOptions instance
// */
// public TransactionDBOptions setCustomMutexFactory(
// final TransactionDBMutexFactory transactionDbMutexFactory) {
//
// }
/**
* The policy for when to write the data into the DB. The default policy is to
* write only the committed data {@link TxnDBWritePolicy#WRITE_COMMITTED}.
* The data could be written before the commit phase. The DB then needs to
* provide the mechanisms to tell apart committed from uncommitted data.
*
* @return The write policy.
*/
public TxnDBWritePolicy getWritePolicy() {
assert(isOwningHandle());
return TxnDBWritePolicy.getTxnDBWritePolicy(getWritePolicy(nativeHandle_));
}
/**
* The policy for when to write the data into the DB. The default policy is to
* write only the committed data {@link TxnDBWritePolicy#WRITE_COMMITTED}.
* The data could be written before the commit phase. The DB then needs to
* provide the mechanisms to tell apart committed from uncommitted data.
*
* @param writePolicy The write policy.
*
* @return this TransactionDBOptions instance
*/
public TransactionDBOptions setWritePolicy(
final TxnDBWritePolicy writePolicy) {
assert(isOwningHandle());
setWritePolicy(nativeHandle_, writePolicy.getValue());
return this;
}
private native static long newTransactionDBOptions();
private native long getMaxNumLocks(final long handle);
private native void setMaxNumLocks(final long handle,
final long maxNumLocks);
private native long getNumStripes(final long handle);
private native void setNumStripes(final long handle, final long numStripes);
private native long getTransactionLockTimeout(final long handle);
private native void setTransactionLockTimeout(final long handle,
final long transactionLockTimeout);
private native long getDefaultLockTimeout(final long handle);
private native void setDefaultLockTimeout(final long handle,
final long transactionLockTimeout);
private native byte getWritePolicy(final long handle);
private native void setWritePolicy(final long handle, final byte writePolicy);
@Override protected final native void disposeInternal(final long handle);
}
@@ -0,0 +1,189 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
public class TransactionOptions extends RocksObject
implements TransactionalOptions {
public TransactionOptions() {
super(newTransactionOptions());
}
@Override
public boolean isSetSnapshot() {
assert(isOwningHandle());
return isSetSnapshot(nativeHandle_);
}
@Override
public TransactionOptions setSetSnapshot(final boolean setSnapshot) {
assert(isOwningHandle());
setSetSnapshot(nativeHandle_, setSnapshot);
return this;
}
/**
* True means that before acquiring locks, this transaction will
* check if doing so will cause a deadlock. If so, it will return with
* {@link Status.Code#Busy}. The user should retry their transaction.
*
* @return true if a deadlock is detected.
*/
public boolean isDeadlockDetect() {
assert(isOwningHandle());
return isDeadlockDetect(nativeHandle_);
}
/**
* Setting to true means that before acquiring locks, this transaction will
* check if doing so will cause a deadlock. If so, it will return with
* {@link Status.Code#Busy}. The user should retry their transaction.
*
* @param deadlockDetect true if we should detect deadlocks.
*
* @return this TransactionOptions instance
*/
public TransactionOptions setDeadlockDetect(final boolean deadlockDetect) {
assert(isOwningHandle());
setDeadlockDetect(nativeHandle_, deadlockDetect);
return this;
}
/**
* The wait timeout in milliseconds when a transaction attempts to lock a key.
*
* If 0, no waiting is done if a lock cannot instantly be acquired.
* If negative, {@link TransactionDBOptions#getTransactionLockTimeout(long)}
* will be used
*
* @return the lock tiemout in milliseconds
*/
public long getLockTimeout() {
assert(isOwningHandle());
return getLockTimeout(nativeHandle_);
}
/**
* If positive, specifies the wait timeout in milliseconds when
* a transaction attempts to lock a key.
*
* If 0, no waiting is done if a lock cannot instantly be acquired.
* If negative, {@link TransactionDBOptions#getTransactionLockTimeout(long)}
* will be used
*
* Default: -1
*
* @param lockTimeout the lock tiemout in milliseconds
*
* @return this TransactionOptions instance
*/
public TransactionOptions setLockTimeout(final long lockTimeout) {
assert(isOwningHandle());
setLockTimeout(nativeHandle_, lockTimeout);
return this;
}
/**
* Expiration duration in milliseconds.
*
* If non-negative, transactions that last longer than this many milliseconds
* will fail to commit. If not set, a forgotten transaction that is never
* committed, rolled back, or deleted will never relinquish any locks it
* holds. This could prevent keys from being written by other writers.
*
* @return expiration the expiration duration in milliseconds
*/
public long getExpiration() {
assert(isOwningHandle());
return getExpiration(nativeHandle_);
}
/**
* Expiration duration in milliseconds.
*
* If non-negative, transactions that last longer than this many milliseconds
* will fail to commit. If not set, a forgotten transaction that is never
* committed, rolled back, or deleted will never relinquish any locks it
* holds. This could prevent keys from being written by other writers.
*
* Default: -1
*
* @param expiration the expiration duration in milliseconds
*
* @return this TransactionOptions instance
*/
public TransactionOptions setExpiration(final long expiration) {
assert(isOwningHandle());
setExpiration(nativeHandle_, expiration);
return this;
}
/**
* Gets the number of traversals to make during deadlock detection.
*
* @return the number of traversals to make during
* deadlock detection
*/
public long getDeadlockDetectDepth() {
return getDeadlockDetectDepth(nativeHandle_);
}
/**
* Sets the number of traversals to make during deadlock detection.
*
* Default: 50
*
* @param deadlockDetectDepth the the number of traversals to make during
* deadlock detection
*
* @return this TransactionOptions instance
*/
public TransactionOptions setDeadlockDetectDepth(
final long deadlockDetectDepth) {
setDeadlockDetectDepth(nativeHandle_, deadlockDetectDepth);
return this;
}
/**
* Get the maximum number of bytes that may be used for the write batch.
*
* @return the maximum number of bytes, 0 means no limit.
*/
public long getMaxWriteBatchSize() {
return getMaxWriteBatchSize(nativeHandle_);
}
/**
* Set the maximum number of bytes that may be used for the write batch.
*
* @param maxWriteBatchSize the maximum number of bytes, 0 means no limit.
*
* @return this TransactionOptions instance
*/
public TransactionOptions setMaxWriteBatchSize(final long maxWriteBatchSize) {
setMaxWriteBatchSize(nativeHandle_, maxWriteBatchSize);
return this;
}
private native static long newTransactionOptions();
private native boolean isSetSnapshot(final long handle);
private native void setSetSnapshot(final long handle,
final boolean setSnapshot);
private native boolean isDeadlockDetect(final long handle);
private native void setDeadlockDetect(final long handle,
final boolean deadlockDetect);
private native long getLockTimeout(final long handle);
private native void setLockTimeout(final long handle, final long lockTimeout);
private native long getExpiration(final long handle);
private native void setExpiration(final long handle, final long expiration);
private native long getDeadlockDetectDepth(final long handle);
private native void setDeadlockDetectDepth(final long handle,
final long deadlockDetectDepth);
private native long getMaxWriteBatchSize(final long handle);
private native void setMaxWriteBatchSize(final long handle,
final long maxWriteBatchSize);
@Override protected final native void disposeInternal(final long handle);
}
@@ -0,0 +1,68 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
interface TransactionalDB<T extends TransactionalOptions>
extends AutoCloseable {
/**
* Starts a new Transaction.
*
* Caller is responsible for calling {@link #close()} on the returned
* transaction when it is no longer needed.
*
* @param writeOptions Any write options for the transaction
* @return a new transaction
*/
Transaction beginTransaction(final WriteOptions writeOptions);
/**
* Starts a new Transaction.
*
* Caller is responsible for calling {@link #close()} on the returned
* transaction when it is no longer needed.
*
* @param writeOptions Any write options for the transaction
* @param transactionOptions Any options for the transaction
* @return a new transaction
*/
Transaction beginTransaction(final WriteOptions writeOptions,
final T transactionOptions);
/**
* Starts a new Transaction.
*
* Caller is responsible for calling {@link #close()} on the returned
* transaction when it is no longer needed.
*
* @param writeOptions Any write options for the transaction
* @param oldTransaction this Transaction will be reused instead of allocating
* a new one. This is an optimization to avoid extra allocations
* when repeatedly creating transactions.
* @return The oldTransaction which has been reinitialized as a new
* transaction
*/
Transaction beginTransaction(final WriteOptions writeOptions,
final Transaction oldTransaction);
/**
* Starts a new Transaction.
*
* Caller is responsible for calling {@link #close()} on the returned
* transaction when it is no longer needed.
*
* @param writeOptions Any write options for the transaction
* @param transactionOptions Any options for the transaction
* @param oldTransaction this Transaction will be reused instead of allocating
* a new one. This is an optimization to avoid extra allocations
* when repeatedly creating transactions.
* @return The oldTransaction which has been reinitialized as a new
* transaction
*/
Transaction beginTransaction(final WriteOptions writeOptions,
final T transactionOptions, final Transaction oldTransaction);
}
@@ -0,0 +1,31 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
interface TransactionalOptions extends AutoCloseable {
/**
* True indicates snapshots will be set, just like if
* {@link Transaction#setSnapshot()} had been called
*
* @return whether a snapshot will be set
*/
boolean isSetSnapshot();
/**
* Setting the setSnapshot to true is the same as calling
* {@link Transaction#setSnapshot()}.
*
* Default: false
*
* @param <T> The type of transactional options.
* @param setSnapshot Whether to set a snapshot
*
* @return this TransactionalOptions instance
*/
<T extends TransactionalOptions> T setSetSnapshot(final boolean setSnapshot);
}
@@ -0,0 +1,62 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
/**
* The transaction db write policy.
*/
public enum TxnDBWritePolicy {
/**
* Write only the committed data.
*/
WRITE_COMMITTED((byte)0x00),
/**
* Write data after the prepare phase of 2pc.
*/
WRITE_PREPARED((byte)0x1),
/**
* Write data before the prepare phase of 2pc.
*/
WRITE_UNPREPARED((byte)0x2);
private byte value;
TxnDBWritePolicy(final byte value) {
this.value = value;
}
/**
* <p>Returns the byte value of the enumerations value.</p>
*
* @return byte representation
*/
public byte getValue() {
return value;
}
/**
* <p>Get the TxnDBWritePolicy enumeration value by
* passing the byte identifier to this method.</p>
*
* @param byteIdentifier of TxnDBWritePolicy.
*
* @return TxnDBWritePolicy instance.
*
* @throws IllegalArgumentException If TxnDBWritePolicy cannot be found for
* the provided byteIdentifier
*/
public static TxnDBWritePolicy getTxnDBWritePolicy(final byte byteIdentifier) {
for (final TxnDBWritePolicy txnDBWritePolicy : TxnDBWritePolicy.values()) {
if (txnDBWritePolicy.getValue() == byteIdentifier) {
return txnDBWritePolicy;
}
}
throw new IllegalArgumentException(
"Illegal value provided for TxnDBWritePolicy.");
}
}
@@ -65,7 +65,7 @@ public enum WALRecoveryMode {
* *
* @param byteIdentifier of WALRecoveryMode. * @param byteIdentifier of WALRecoveryMode.
* *
* @return CompressionType instance. * @return WALRecoveryMode instance.
* *
* @throws IllegalArgumentException If WALRecoveryMode cannot be found for the * @throws IllegalArgumentException If WALRecoveryMode cannot be found for the
* provided byteIdentifier * provided byteIdentifier
@@ -55,10 +55,13 @@ public class WBWIRocksIterator
* that created the record in the Write Batch * that created the record in the Write Batch
*/ */
public enum WriteType { public enum WriteType {
PUT((byte)0x1), PUT((byte)0x0),
MERGE((byte)0x2), MERGE((byte)0x1),
DELETE((byte)0x4), DELETE((byte)0x2),
LOG((byte)0x8); SINGLE_DELETE((byte)0x3),
DELETE_RANGE((byte)0x4),
LOG((byte)0x5),
XID((byte)0x6);
final byte id; final byte id;
WriteType(final byte id) { WriteType(final byte id) {
+245 -12
View File
@@ -39,6 +39,14 @@ public class WriteBatch extends AbstractWriteBatch {
super(newWriteBatch(reserved_bytes)); super(newWriteBatch(reserved_bytes));
} }
/**
* Constructs a WriteBatch instance from a serialized representation
* as returned by {@link #data()}.
*/
public WriteBatch(final byte[] serialized) {
super(newWriteBatch(serialized, serialized.length));
}
/** /**
* Support for iterating over the contents of a batch. * Support for iterating over the contents of a batch.
* *
@@ -51,6 +59,134 @@ public class WriteBatch extends AbstractWriteBatch {
iterate(nativeHandle_, handler.nativeHandle_); iterate(nativeHandle_, handler.nativeHandle_);
} }
/**
* Retrieve the serialized version of this batch.
*
* @return the serialized representation of this write batch.
*/
public byte[] data() {
return data(nativeHandle_);
}
/**
* Retrieve data size of the batch.
*
* @return the serialized data size of the batch.
*/
public long getDataSize() {
return getDataSize(nativeHandle_);
}
/**
* Returns true if PutCF will be called during Iterate.
*
* Return true if PutCF will be called during Iterate.
*/
public boolean hasPut() {
return hasPut(nativeHandle_);
}
/**
* Returns true if DeleteCF will be called during Iterate.
*
* Return true if DeleteCF will be called during Iterate.
*/
public boolean hasDelete() {
return hasDelete(nativeHandle_);
}
/**
* Returns true if SingleDeleteCF will be called during Iterate.
*
* Return true if SingleDeleteCF will be called during Iterate.
*/
public boolean hasSingleDelete() {
return hasSingleDelete(nativeHandle_);
}
/**
* Returns true if DeleteRangeCF will be called during Iterate.
*
* Return true if DeleteRangeCF will be called during Iterate.
*/
public boolean hasDeleteRange() {
return hasDeleteRange(nativeHandle_);
}
/**
* Returns true if MergeCF will be called during Iterate.
*
* Return true if MergeCF will be called during Iterate.
*/
public boolean hasMerge() {
return hasMerge(nativeHandle_);
}
/**
* Returns true if MarkBeginPrepare will be called during Iterate.
*
* Return true if MarkBeginPrepare will be called during Iterate.
*/
public boolean hasBeginPrepare() {
return hasBeginPrepare(nativeHandle_);
}
/**
* Returns true if MarkEndPrepare will be called during Iterate.
*
* Return true if MarkEndPrepare will be called during Iterate.
*/
public boolean hasEndPrepare() {
return hasEndPrepare(nativeHandle_);
}
/**
* Returns true if MarkCommit will be called during Iterate.
*
* Return true if MarkCommit will be called during Iterate.
*/
public boolean hasCommit() {
return hasCommit(nativeHandle_);
}
/**
* Returns true if MarkRollback will be called during Iterate.
*
* Return true if MarkRollback will be called during Iterate.
*/
public boolean hasRollback() {
return hasRollback(nativeHandle_);
}
@Override
public WriteBatch getWriteBatch() {
return this;
}
/**
* Marks this point in the WriteBatch as the last record to
* be inserted into the WAL, provided the WAL is enabled.
*/
public void markWalTerminationPoint() {
markWalTerminationPoint(nativeHandle_);
}
/**
* Gets the WAL termination point.
*
* See {@link #markWalTerminationPoint()}
*
* @return the WAL termination point
*/
public SavePoint getWalTerminationPoint() {
return getWalTerminationPoint(nativeHandle_);
}
@Override
WriteBatch getWriteBatch(final long handle) {
return this;
}
/** /**
* <p>Private WriteBatch constructor which is used to construct * <p>Private WriteBatch constructor which is used to construct
* WriteBatch instances from C++ side. As the reference to this * WriteBatch instances from C++ side. As the reference to this
@@ -87,10 +223,14 @@ public class WriteBatch extends AbstractWriteBatch {
@Override final native void merge(final long handle, final byte[] key, @Override final native void merge(final long handle, final byte[] key,
final int keyLen, final byte[] value, final int valueLen, final int keyLen, final byte[] value, final int valueLen,
final long cfHandle); final long cfHandle);
@Override final native void remove(final long handle, final byte[] key, @Override final native void delete(final long handle, final byte[] key,
final int keyLen); final int keyLen) throws RocksDBException;
@Override final native void remove(final long handle, final byte[] key, @Override final native void delete(final long handle, final byte[] key,
final int keyLen, final long cfHandle); final int keyLen, final long cfHandle) throws RocksDBException;
@Override final native void singleDelete(final long handle, final byte[] key,
final int keyLen) throws RocksDBException;
@Override final native void singleDelete(final long handle, final byte[] key,
final int keyLen, final long cfHandle) throws RocksDBException;
@Override @Override
final native void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen, final native void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen,
final byte[] endKey, final int endKeyLen); final byte[] endKey, final int endKeyLen);
@@ -98,15 +238,32 @@ public class WriteBatch extends AbstractWriteBatch {
final native void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen, final native void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen,
final byte[] endKey, final int endKeyLen, final long cfHandle); final byte[] endKey, final int endKeyLen, final long cfHandle);
@Override final native void putLogData(final long handle, @Override final native void putLogData(final long handle,
final byte[] blob, final int blobLen); final byte[] blob, final int blobLen) throws RocksDBException;
@Override final native void clear0(final long handle); @Override final native void clear0(final long handle);
@Override final native void setSavePoint0(final long handle); @Override final native void setSavePoint0(final long handle);
@Override final native void rollbackToSavePoint0(final long handle); @Override final native void rollbackToSavePoint0(final long handle);
@Override final native void popSavePoint(final long handle) throws RocksDBException;
@Override final native void setMaxBytes(final long nativeHandle,
final long maxBytes);
private native static long newWriteBatch(final int reserved_bytes); private native static long newWriteBatch(final int reserved_bytes);
private native static long newWriteBatch(final byte[] serialized,
final int serializedLength);
private native void iterate(final long handle, final long handlerHandle) private native void iterate(final long handle, final long handlerHandle)
throws RocksDBException; throws RocksDBException;
private native byte[] data(final long nativeHandle);
private native long getDataSize(final long nativeHandle);
private native boolean hasPut(final long nativeHandle);
private native boolean hasDelete(final long nativeHandle);
private native boolean hasSingleDelete(final long nativeHandle);
private native boolean hasDeleteRange(final long nativeHandle);
private native boolean hasMerge(final long nativeHandle);
private native boolean hasBeginPrepare(final long nativeHandle);
private native boolean hasEndPrepare(final long nativeHandle);
private native boolean hasCommit(final long nativeHandle);
private native boolean hasRollback(final long nativeHandle);
private native void markWalTerminationPoint(final long nativeHandle);
private native SavePoint getWalTerminationPoint(final long nativeHandle);
/** /**
* Handler callback for iterating over the contents of a batch. * Handler callback for iterating over the contents of a batch.
@@ -122,15 +279,38 @@ public class WriteBatch extends AbstractWriteBatch {
return createNewHandler0(); return createNewHandler0();
} }
public abstract void put(byte[] key, byte[] value); public abstract void put(final int columnFamilyId, final byte[] key,
public abstract void merge(byte[] key, byte[] value); final byte[] value) throws RocksDBException;
public abstract void delete(byte[] key); public abstract void put(final byte[] key, final byte[] value);
public abstract void deleteRange(byte[] beginKey, byte[] endKey); public abstract void merge(final int columnFamilyId, final byte[] key,
public abstract void logData(byte[] blob); final byte[] value) throws RocksDBException;
public abstract void merge(final byte[] key, final byte[] value);
public abstract void delete(final int columnFamilyId, final byte[] key)
throws RocksDBException;
public abstract void delete(final byte[] key);
public abstract void singleDelete(final int columnFamilyId,
final byte[] key) throws RocksDBException;
public abstract void singleDelete(final byte[] key);
public abstract void deleteRange(final int columnFamilyId,
final byte[] beginKey, final byte[] endKey) throws RocksDBException;
public abstract void deleteRange(final byte[] beginKey,
final byte[] endKey);
public abstract void logData(final byte[] blob);
public abstract void putBlobIndex(final int columnFamilyId,
final byte[] key, final byte[] value) throws RocksDBException;
public abstract void markBeginPrepare() throws RocksDBException;
public abstract void markEndPrepare(final byte[] xid)
throws RocksDBException;
public abstract void markNoop(final boolean emptyBatch)
throws RocksDBException;
public abstract void markRollback(final byte[] xid)
throws RocksDBException;
public abstract void markCommit(final byte[] xid)
throws RocksDBException;
/** /**
* shouldContinue is called by the underlying iterator * shouldContinue is called by the underlying iterator
* WriteBatch::Iterate. If it returns false, * {@link WriteBatch#iterate(Handler)}. If it returns false,
* iteration is halted. Otherwise, it continues * iteration is halted. Otherwise, it continues
* iterating. The default implementation always * iterating. The default implementation always
* returns true. * returns true.
@@ -144,4 +324,57 @@ public class WriteBatch extends AbstractWriteBatch {
private native long createNewHandler0(); private native long createNewHandler0();
} }
/**
* A structure for describing the save point in the Write Batch.
*/
public static class SavePoint {
private long size;
private long count;
private long contentFlags;
public SavePoint(final long size, final long count,
final long contentFlags) {
this.size = size;
this.count = count;
this.contentFlags = contentFlags;
}
public void clear() {
this.size = 0;
this.count = 0;
this.contentFlags = 0;
}
/**
* Get the size of the serialized representation.
*
* @return the size of the serialized representation.
*/
public long getSize() {
return size;
}
/**
* Get the number of elements.
*
* @return the number of elements.
*/
public long getCount() {
return count;
}
/**
* Get the content flags.
*
* @return the content flags.
*/
public long getContentFlags() {
return contentFlags;
}
public boolean isCleared() {
return (size | count | contentFlags) == 0;
}
}
} }
@@ -24,7 +24,7 @@ public interface WriteBatchInterface {
* @param key the specified key to be inserted. * @param key the specified key to be inserted.
* @param value the value associated with the specified key. * @param value the value associated with the specified key.
*/ */
void put(byte[] key, byte[] value); void put(byte[] key, byte[] value) throws RocksDBException;
/** /**
* <p>Store the mapping "key-&gt;value" within given column * <p>Store the mapping "key-&gt;value" within given column
@@ -36,7 +36,7 @@ public interface WriteBatchInterface {
* @param value the value associated with the specified key. * @param value the value associated with the specified key.
*/ */
void put(ColumnFamilyHandle columnFamilyHandle, void put(ColumnFamilyHandle columnFamilyHandle,
byte[] key, byte[] value); byte[] key, byte[] value) throws RocksDBException;
/** /**
* <p>Merge "value" with the existing value of "key" in the database. * <p>Merge "value" with the existing value of "key" in the database.
@@ -46,7 +46,7 @@ public interface WriteBatchInterface {
* @param value the value to be merged with the current value for * @param value the value to be merged with the current value for
* the specified key. * the specified key.
*/ */
void merge(byte[] key, byte[] value); void merge(byte[] key, byte[] value) throws RocksDBException;
/** /**
* <p>Merge "value" with the existing value of "key" in given column family. * <p>Merge "value" with the existing value of "key" in given column family.
@@ -58,14 +58,36 @@ public interface WriteBatchInterface {
* the specified key. * the specified key.
*/ */
void merge(ColumnFamilyHandle columnFamilyHandle, void merge(ColumnFamilyHandle columnFamilyHandle,
byte[] key, byte[] value); byte[] key, byte[] value) throws RocksDBException;
/**
* <p>If the database contains a mapping for "key", erase it. Else do nothing.</p>
*
* @param key Key to delete within database
*
* @deprecated Use {@link #delete(byte[])}
*/
@Deprecated
void remove(byte[] key) throws RocksDBException;
/**
* <p>If column family contains a mapping for "key", erase it. Else do nothing.</p>
*
* @param columnFamilyHandle {@link ColumnFamilyHandle} instance
* @param key Key to delete within database
*
* @deprecated Use {@link #delete(ColumnFamilyHandle, byte[])}
*/
@Deprecated
void remove(ColumnFamilyHandle columnFamilyHandle, byte[] key)
throws RocksDBException;
/** /**
* <p>If the database contains a mapping for "key", erase it. Else do nothing.</p> * <p>If the database contains a mapping for "key", erase it. Else do nothing.</p>
* *
* @param key Key to delete within database * @param key Key to delete within database
*/ */
void remove(byte[] key); void delete(byte[] key) throws RocksDBException;
/** /**
* <p>If column family contains a mapping for "key", erase it. Else do nothing.</p> * <p>If column family contains a mapping for "key", erase it. Else do nothing.</p>
@@ -73,7 +95,58 @@ public interface WriteBatchInterface {
* @param columnFamilyHandle {@link ColumnFamilyHandle} instance * @param columnFamilyHandle {@link ColumnFamilyHandle} instance
* @param key Key to delete within database * @param key Key to delete within database
*/ */
void remove(ColumnFamilyHandle columnFamilyHandle, byte[] key); void delete(ColumnFamilyHandle columnFamilyHandle, byte[] key)
throws RocksDBException;
/**
* Remove the database entry for {@code key}. Requires that the key exists
* and was not overwritten. It is not an error if the key did not exist
* in the database.
*
* If a key is overwritten (by calling {@link #put(byte[], byte[])} multiple
* times), then the result of calling SingleDelete() on this key is undefined.
* SingleDelete() only behaves correctly if there has been only one Put()
* for this key since the previous call to SingleDelete() for this key.
*
* This feature is currently an experimental performance optimization
* for a very specific workload. It is up to the caller to ensure that
* SingleDelete is only used for a key that is not deleted using Delete() or
* written using Merge(). Mixing SingleDelete operations with Deletes and
* Merges can result in undefined behavior.
*
* @param key Key to delete within database
*
* @throws RocksDBException thrown if error happens in underlying
* native library.
*/
@Experimental("Performance optimization for a very specific workload")
void singleDelete(final byte[] key) throws RocksDBException;
/**
* Remove the database entry for {@code key}. Requires that the key exists
* and was not overwritten. It is not an error if the key did not exist
* in the database.
*
* If a key is overwritten (by calling {@link #put(byte[], byte[])} multiple
* times), then the result of calling SingleDelete() on this key is undefined.
* SingleDelete() only behaves correctly if there has been only one Put()
* for this key since the previous call to SingleDelete() for this key.
*
* This feature is currently an experimental performance optimization
* for a very specific workload. It is up to the caller to ensure that
* SingleDelete is only used for a key that is not deleted using Delete() or
* written using Merge(). Mixing SingleDelete operations with Deletes and
* Merges can result in undefined behavior.
*
* @param columnFamilyHandle The column family to delete the key from
* @param key Key to delete within database
*
* @throws RocksDBException thrown if error happens in underlying
* native library.
*/
@Experimental("Performance optimization for a very specific workload")
void singleDelete(final ColumnFamilyHandle columnFamilyHandle,
final byte[] key) throws RocksDBException;
/** /**
* Removes the database entries in the range ["beginKey", "endKey"), i.e., * Removes the database entries in the range ["beginKey", "endKey"), i.e.,
@@ -89,7 +162,7 @@ public interface WriteBatchInterface {
* @param endKey * @param endKey
* Last key to delete within database (excluded) * Last key to delete within database (excluded)
*/ */
void deleteRange(byte[] beginKey, byte[] endKey); void deleteRange(byte[] beginKey, byte[] endKey) throws RocksDBException;
/** /**
* Removes the database entries in the range ["beginKey", "endKey"), i.e., * Removes the database entries in the range ["beginKey", "endKey"), i.e.,
@@ -106,7 +179,8 @@ public interface WriteBatchInterface {
* @param endKey * @param endKey
* Last key to delete within database (excluded) * Last key to delete within database (excluded)
*/ */
void deleteRange(ColumnFamilyHandle columnFamilyHandle, byte[] beginKey, byte[] endKey); void deleteRange(ColumnFamilyHandle columnFamilyHandle, byte[] beginKey,
byte[] endKey) throws RocksDBException;
/** /**
* Append a blob of arbitrary size to the records in this batch. The blob will * Append a blob of arbitrary size to the records in this batch. The blob will
@@ -122,7 +196,7 @@ public interface WriteBatchInterface {
* *
* @param blob binary object to be inserted * @param blob binary object to be inserted
*/ */
void putLogData(byte[] blob); void putLogData(byte[] blob) throws RocksDBException;
/** /**
* Clear all updates buffered in this batch * Clear all updates buffered in this batch
@@ -143,4 +217,30 @@ public interface WriteBatchInterface {
* @throws RocksDBException if there is no previous call to SetSavePoint() * @throws RocksDBException if there is no previous call to SetSavePoint()
*/ */
void rollbackToSavePoint() throws RocksDBException; void rollbackToSavePoint() throws RocksDBException;
/**
* Pop the most recent save point.
*
* That is to say that it removes the last save point,
* which was set by {@link #setSavePoint()}.
*
* @throws RocksDBException If there is no previous call to
* {@link #setSavePoint()}, an exception with
* {@link Status.Code#NotFound} will be thrown.
*/
void popSavePoint() throws RocksDBException;
/**
* Set the maximum size of the write batch.
*
* @param maxBytes the maximum size in bytes.
*/
void setMaxBytes(long maxBytes);
/**
* Get the underlying Write Batch.
*
* @return the underlying WriteBatch.
*/
WriteBatch getWriteBatch();
} }
@@ -61,7 +61,20 @@ public class WriteBatchWithIndex extends AbstractWriteBatch {
fallbackIndexComparator, final int reservedBytes, fallbackIndexComparator, final int reservedBytes,
final boolean overwriteKey) { final boolean overwriteKey) {
super(newWriteBatchWithIndex(fallbackIndexComparator.nativeHandle_, super(newWriteBatchWithIndex(fallbackIndexComparator.nativeHandle_,
fallbackIndexComparator instanceof DirectComparator, reservedBytes, overwriteKey)); fallbackIndexComparator.getComparatorType().getValue(), reservedBytes,
overwriteKey));
}
/**
* <p>Private WriteBatchWithIndex constructor which is used to construct
* WriteBatchWithIndex instances from C++ side. As the reference to this
* object is also managed from C++ side the handle will be disowned.</p>
*
* @param nativeHandle address of native instance.
*/
WriteBatchWithIndex(final long nativeHandle) {
super(nativeHandle);
disOwnNativeHandle();
} }
/** /**
@@ -244,10 +257,14 @@ public class WriteBatchWithIndex extends AbstractWriteBatch {
@Override final native void merge(final long handle, final byte[] key, @Override final native void merge(final long handle, final byte[] key,
final int keyLen, final byte[] value, final int valueLen, final int keyLen, final byte[] value, final int valueLen,
final long cfHandle); final long cfHandle);
@Override final native void remove(final long handle, final byte[] key, @Override final native void delete(final long handle, final byte[] key,
final int keyLen); final int keyLen) throws RocksDBException;
@Override final native void remove(final long handle, final byte[] key, @Override final native void delete(final long handle, final byte[] key,
final int keyLen, final long cfHandle); final int keyLen, final long cfHandle) throws RocksDBException;
@Override final native void singleDelete(final long handle, final byte[] key,
final int keyLen) throws RocksDBException;
@Override final native void singleDelete(final long handle, final byte[] key,
final int keyLen, final long cfHandle) throws RocksDBException;
@Override @Override
final native void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen, final native void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen,
final byte[] endKey, final int endKeyLen); final byte[] endKey, final int endKeyLen);
@@ -255,15 +272,20 @@ public class WriteBatchWithIndex extends AbstractWriteBatch {
final native void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen, final native void deleteRange(final long handle, final byte[] beginKey, final int beginKeyLen,
final byte[] endKey, final int endKeyLen, final long cfHandle); final byte[] endKey, final int endKeyLen, final long cfHandle);
@Override final native void putLogData(final long handle, final byte[] blob, @Override final native void putLogData(final long handle, final byte[] blob,
final int blobLen); final int blobLen) throws RocksDBException;
@Override final native void clear0(final long handle); @Override final native void clear0(final long handle);
@Override final native void setSavePoint0(final long handle); @Override final native void setSavePoint0(final long handle);
@Override final native void rollbackToSavePoint0(final long handle); @Override final native void rollbackToSavePoint0(final long handle);
@Override final native void popSavePoint(final long handle) throws RocksDBException;
@Override final native void setMaxBytes(final long nativeHandle,
final long maxBytes);
@Override final native WriteBatch getWriteBatch(final long handle);
private native static long newWriteBatchWithIndex(); private native static long newWriteBatchWithIndex();
private native static long newWriteBatchWithIndex(final boolean overwriteKey); private native static long newWriteBatchWithIndex(final boolean overwriteKey);
private native static long newWriteBatchWithIndex( private native static long newWriteBatchWithIndex(
final long fallbackIndexComparatorHandle, final boolean isDirect, final int reservedBytes, final long fallbackIndexComparatorHandle,
final byte comparatorType, final int reservedBytes,
final boolean overwriteKey); final boolean overwriteKey);
private native long iterator0(final long handle); private native long iterator0(final long handle);
private native long iterator1(final long handle, final long cfHandle); private native long iterator1(final long handle, final long cfHandle);
@@ -20,6 +20,12 @@ public class WriteOptions extends RocksObject {
} }
// TODO(AR) consider ownership
WriteOptions(final long nativeHandle) {
super(nativeHandle);
disOwnNativeHandle();
}
/** /**
* Copy constructor for WriteOptions. * Copy constructor for WriteOptions.
* *
@@ -0,0 +1,903 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
/**
* Base class of {@link TransactionTest} and {@link OptimisticTransactionTest}
*/
public abstract class AbstractTransactionTest {
protected final static byte[] TXN_TEST_COLUMN_FAMILY = "txn_test_cf"
.getBytes();
protected static final Random rand = PlatformRandomHelper.
getPlatformSpecificRandomFactory();
@Rule
public TemporaryFolder dbFolder = new TemporaryFolder();
public abstract DBContainer startDb()
throws RocksDBException;
@Test
public void setSnapshot() throws RocksDBException {
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
txn.setSnapshot();
}
}
@Test
public void setSnapshotOnNextOperation() throws RocksDBException {
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
txn.setSnapshotOnNextOperation();
txn.put("key1".getBytes(), "value1".getBytes());
}
}
@Test
public void setSnapshotOnNextOperation_transactionNotifier() throws RocksDBException {
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
try(final TestTransactionNotifier notifier = new TestTransactionNotifier()) {
txn.setSnapshotOnNextOperation(notifier);
txn.put("key1".getBytes(), "value1".getBytes());
txn.setSnapshotOnNextOperation(notifier);
txn.put("key2".getBytes(), "value2".getBytes());
assertThat(notifier.getCreatedSnapshots().size()).isEqualTo(2);
}
}
}
@Test
public void getSnapshot() throws RocksDBException {
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
txn.setSnapshot();
final Snapshot snapshot = txn.getSnapshot();
assertThat(snapshot.isOwningHandle()).isFalse();
}
}
@Test
public void getSnapshot_null() throws RocksDBException {
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
final Snapshot snapshot = txn.getSnapshot();
assertThat(snapshot).isNull();
}
}
@Test
public void clearSnapshot() throws RocksDBException {
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
txn.setSnapshot();
txn.clearSnapshot();
}
}
@Test
public void clearSnapshot_none() throws RocksDBException {
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
txn.clearSnapshot();
}
}
@Test
public void commit() throws RocksDBException {
final byte k1[] = "rollback-key1".getBytes(UTF_8);
final byte v1[] = "rollback-value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb()) {
try(final Transaction txn = dbContainer.beginTransaction()) {
txn.put(k1, v1);
txn.commit();
}
try(final ReadOptions readOptions = new ReadOptions();
final Transaction txn2 = dbContainer.beginTransaction()) {
assertThat(txn2.get(readOptions, k1)).isEqualTo(v1);
}
}
}
@Test
public void rollback() throws RocksDBException {
final byte k1[] = "rollback-key1".getBytes(UTF_8);
final byte v1[] = "rollback-value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb()) {
try(final Transaction txn = dbContainer.beginTransaction()) {
txn.put(k1, v1);
txn.rollback();
}
try(final ReadOptions readOptions = new ReadOptions();
final Transaction txn2 = dbContainer.beginTransaction()) {
assertThat(txn2.get(readOptions, k1)).isNull();
}
}
}
@Test
public void savePoint() throws RocksDBException {
final byte k1[] = "savePoint-key1".getBytes(UTF_8);
final byte v1[] = "savePoint-value1".getBytes(UTF_8);
final byte k2[] = "savePoint-key2".getBytes(UTF_8);
final byte v2[] = "savePoint-value2".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions()) {
try(final Transaction txn = dbContainer.beginTransaction()) {
txn.put(k1, v1);
assertThat(txn.get(readOptions, k1)).isEqualTo(v1);
txn.setSavePoint();
txn.put(k2, v2);
assertThat(txn.get(readOptions, k1)).isEqualTo(v1);
assertThat(txn.get(readOptions, k2)).isEqualTo(v2);
txn.rollbackToSavePoint();
assertThat(txn.get(readOptions, k1)).isEqualTo(v1);
assertThat(txn.get(readOptions, k2)).isNull();
txn.commit();
}
try(final Transaction txn2 = dbContainer.beginTransaction()) {
assertThat(txn2.get(readOptions, k1)).isEqualTo(v1);
assertThat(txn2.get(readOptions, k2)).isNull();
}
}
}
@Test
public void getPut_cf() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
assertThat(txn.get(testCf, readOptions, k1)).isNull();
txn.put(testCf, k1, v1);
assertThat(txn.get(testCf, readOptions, k1)).isEqualTo(v1);
}
}
@Test
public void getPut() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
assertThat(txn.get(readOptions, k1)).isNull();
txn.put(k1, v1);
assertThat(txn.get(readOptions, k1)).isEqualTo(v1);
}
}
@Test
public void multiGetPut_cf() throws RocksDBException {
final byte keys[][] = new byte[][] {
"key1".getBytes(UTF_8),
"key2".getBytes(UTF_8)};
final byte values[][] = new byte[][] {
"value1".getBytes(UTF_8),
"value2".getBytes(UTF_8)};
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
final List<ColumnFamilyHandle> cfList = Arrays.asList(testCf, testCf);
assertThat(txn.multiGet(readOptions, cfList, keys)).isEqualTo(new byte[][] { null, null });
txn.put(testCf, keys[0], values[0]);
txn.put(testCf, keys[1], values[1]);
assertThat(txn.multiGet(readOptions, cfList, keys)).isEqualTo(values);
}
}
@Test
public void multiGetPut() throws RocksDBException {
final byte keys[][] = new byte[][] {
"key1".getBytes(UTF_8),
"key2".getBytes(UTF_8)};
final byte values[][] = new byte[][] {
"value1".getBytes(UTF_8),
"value2".getBytes(UTF_8)};
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
assertThat(txn.multiGet(readOptions, keys)).isEqualTo(new byte[][] { null, null });
txn.put(keys[0], values[0]);
txn.put(keys[1], values[1]);
assertThat(txn.multiGet(readOptions, keys)).isEqualTo(values);
}
}
@Test
public void getForUpdate_cf() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
assertThat(txn.getForUpdate(readOptions, testCf, k1, true)).isNull();
txn.put(testCf, k1, v1);
assertThat(txn.getForUpdate(readOptions, testCf, k1, true)).isEqualTo(v1);
}
}
@Test
public void getForUpdate() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
assertThat(txn.getForUpdate(readOptions, k1, true)).isNull();
txn.put(k1, v1);
assertThat(txn.getForUpdate(readOptions, k1, true)).isEqualTo(v1);
}
}
@Test
public void multiGetForUpdate_cf() throws RocksDBException {
final byte keys[][] = new byte[][] {
"key1".getBytes(UTF_8),
"key2".getBytes(UTF_8)};
final byte values[][] = new byte[][] {
"value1".getBytes(UTF_8),
"value2".getBytes(UTF_8)};
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
final List<ColumnFamilyHandle> cfList = Arrays.asList(testCf, testCf);
assertThat(txn.multiGetForUpdate(readOptions, cfList, keys))
.isEqualTo(new byte[][] { null, null });
txn.put(testCf, keys[0], values[0]);
txn.put(testCf, keys[1], values[1]);
assertThat(txn.multiGetForUpdate(readOptions, cfList, keys))
.isEqualTo(values);
}
}
@Test
public void multiGetForUpdate() throws RocksDBException {
final byte keys[][] = new byte[][]{
"key1".getBytes(UTF_8),
"key2".getBytes(UTF_8)};
final byte values[][] = new byte[][]{
"value1".getBytes(UTF_8),
"value2".getBytes(UTF_8)};
try (final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
assertThat(txn.multiGetForUpdate(readOptions, keys)).isEqualTo(new byte[][]{null, null});
txn.put(keys[0], values[0]);
txn.put(keys[1], values[1]);
assertThat(txn.multiGetForUpdate(readOptions, keys)).isEqualTo(values);
}
}
@Test
public void getIterator() throws RocksDBException {
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
final byte[] k1 = "key1".getBytes(UTF_8);
final byte[] v1 = "value1".getBytes(UTF_8);
txn.put(k1, v1);
try(final RocksIterator iterator = txn.getIterator(readOptions)) {
iterator.seek(k1);
assertThat(iterator.isValid()).isTrue();
assertThat(iterator.key()).isEqualTo(k1);
assertThat(iterator.value()).isEqualTo(v1);
}
}
}
@Test
public void getIterator_cf() throws RocksDBException {
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
final byte[] k1 = "key1".getBytes(UTF_8);
final byte[] v1 = "value1".getBytes(UTF_8);
txn.put(testCf, k1, v1);
try(final RocksIterator iterator = txn.getIterator(readOptions, testCf)) {
iterator.seek(k1);
assertThat(iterator.isValid()).isTrue();
assertThat(iterator.key()).isEqualTo(k1);
assertThat(iterator.value()).isEqualTo(v1);
}
}
}
@Test
public void merge_cf() throws RocksDBException {
final byte[] k1 = "key1".getBytes(UTF_8);
final byte[] v1 = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
txn.merge(testCf, k1, v1);
}
}
@Test
public void merge() throws RocksDBException {
final byte[] k1 = "key1".getBytes(UTF_8);
final byte[] v1 = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
txn.merge(k1, v1);
}
}
@Test
public void delete_cf() throws RocksDBException {
final byte[] k1 = "key1".getBytes(UTF_8);
final byte[] v1 = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
txn.put(testCf, k1, v1);
assertThat(txn.get(testCf, readOptions, k1)).isEqualTo(v1);
txn.delete(testCf, k1);
assertThat(txn.get(testCf, readOptions, k1)).isNull();
}
}
@Test
public void delete() throws RocksDBException {
final byte[] k1 = "key1".getBytes(UTF_8);
final byte[] v1 = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
txn.put(k1, v1);
assertThat(txn.get(readOptions, k1)).isEqualTo(v1);
txn.delete(k1);
assertThat(txn.get(readOptions, k1)).isNull();
}
}
@Test
public void delete_parts_cf() throws RocksDBException {
final byte keyParts[][] = new byte[][] {
"ke".getBytes(UTF_8),
"y1".getBytes(UTF_8)};
final byte valueParts[][] = new byte[][] {
"val".getBytes(UTF_8),
"ue1".getBytes(UTF_8)};
final byte[] key = concat(keyParts);
final byte[] value = concat(valueParts);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
txn.put(testCf, keyParts, valueParts);
assertThat(txn.get(testCf, readOptions, key)).isEqualTo(value);
txn.delete(testCf, keyParts);
assertThat(txn.get(testCf, readOptions, key))
.isNull();
}
}
@Test
public void delete_parts() throws RocksDBException {
final byte keyParts[][] = new byte[][] {
"ke".getBytes(UTF_8),
"y1".getBytes(UTF_8)};
final byte valueParts[][] = new byte[][] {
"val".getBytes(UTF_8),
"ue1".getBytes(UTF_8)};
final byte[] key = concat(keyParts);
final byte[] value = concat(valueParts);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
txn.put(keyParts, valueParts);
assertThat(txn.get(readOptions, key)).isEqualTo(value);
txn.delete(keyParts);
assertThat(txn.get(readOptions, key)).isNull();
}
}
@Test
public void getPutUntracked_cf() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
assertThat(txn.get(testCf, readOptions, k1)).isNull();
txn.putUntracked(testCf, k1, v1);
assertThat(txn.get(testCf, readOptions, k1)).isEqualTo(v1);
}
}
@Test
public void getPutUntracked() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
assertThat(txn.get(readOptions, k1)).isNull();
txn.putUntracked(k1, v1);
assertThat(txn.get(readOptions, k1)).isEqualTo(v1);
}
}
@Test
public void multiGetPutUntracked_cf() throws RocksDBException {
final byte keys[][] = new byte[][] {
"key1".getBytes(UTF_8),
"key2".getBytes(UTF_8)};
final byte values[][] = new byte[][] {
"value1".getBytes(UTF_8),
"value2".getBytes(UTF_8)};
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
final List<ColumnFamilyHandle> cfList = Arrays.asList(testCf, testCf);
assertThat(txn.multiGet(readOptions, cfList, keys)).isEqualTo(new byte[][] { null, null });
txn.putUntracked(testCf, keys[0], values[0]);
txn.putUntracked(testCf, keys[1], values[1]);
assertThat(txn.multiGet(readOptions, cfList, keys)).isEqualTo(values);
}
}
@Test
public void multiGetPutUntracked() throws RocksDBException {
final byte keys[][] = new byte[][] {
"key1".getBytes(UTF_8),
"key2".getBytes(UTF_8)};
final byte values[][] = new byte[][] {
"value1".getBytes(UTF_8),
"value2".getBytes(UTF_8)};
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
assertThat(txn.multiGet(readOptions, keys)).isEqualTo(new byte[][] { null, null });
txn.putUntracked(keys[0], values[0]);
txn.putUntracked(keys[1], values[1]);
assertThat(txn.multiGet(readOptions, keys)).isEqualTo(values);
}
}
@Test
public void mergeUntracked_cf() throws RocksDBException {
final byte[] k1 = "key1".getBytes(UTF_8);
final byte[] v1 = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
txn.mergeUntracked(testCf, k1, v1);
}
}
@Test
public void mergeUntracked() throws RocksDBException {
final byte[] k1 = "key1".getBytes(UTF_8);
final byte[] v1 = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
txn.mergeUntracked(k1, v1);
}
}
@Test
public void deleteUntracked_cf() throws RocksDBException {
final byte[] k1 = "key1".getBytes(UTF_8);
final byte[] v1 = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
txn.put(testCf, k1, v1);
assertThat(txn.get(testCf, readOptions, k1)).isEqualTo(v1);
txn.deleteUntracked(testCf, k1);
assertThat(txn.get(testCf, readOptions, k1)).isNull();
}
}
@Test
public void deleteUntracked() throws RocksDBException {
final byte[] k1 = "key1".getBytes(UTF_8);
final byte[] v1 = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
txn.put(k1, v1);
assertThat(txn.get(readOptions, k1)).isEqualTo(v1);
txn.deleteUntracked(k1);
assertThat(txn.get(readOptions, k1)).isNull();
}
}
@Test
public void deleteUntracked_parts_cf() throws RocksDBException {
final byte keyParts[][] = new byte[][] {
"ke".getBytes(UTF_8),
"y1".getBytes(UTF_8)};
final byte valueParts[][] = new byte[][] {
"val".getBytes(UTF_8),
"ue1".getBytes(UTF_8)};
final byte[] key = concat(keyParts);
final byte[] value = concat(valueParts);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
txn.put(testCf, keyParts, valueParts);
assertThat(txn.get(testCf, readOptions, key)).isEqualTo(value);
txn.deleteUntracked(testCf, keyParts);
assertThat(txn.get(testCf, readOptions, key)).isNull();
}
}
@Test
public void deleteUntracked_parts() throws RocksDBException {
final byte keyParts[][] = new byte[][] {
"ke".getBytes(UTF_8),
"y1".getBytes(UTF_8)};
final byte valueParts[][] = new byte[][] {
"val".getBytes(UTF_8),
"ue1".getBytes(UTF_8)};
final byte[] key = concat(keyParts);
final byte[] value = concat(valueParts);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
txn.put(keyParts, valueParts);
assertThat(txn.get(readOptions, key)).isEqualTo(value);
txn.deleteUntracked(keyParts);
assertThat(txn.get(readOptions, key)).isNull();
}
}
@Test
public void putLogData() throws RocksDBException {
final byte[] blob = "blobby".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
txn.putLogData(blob);
}
}
@Test
public void enabledDisableIndexing() throws RocksDBException {
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
txn.disableIndexing();
txn.enableIndexing();
txn.disableIndexing();
txn.enableIndexing();
}
}
@Test
public void numKeys() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
final byte k2[] = "key2".getBytes(UTF_8);
final byte v2[] = "value2".getBytes(UTF_8);
final byte k3[] = "key3".getBytes(UTF_8);
final byte v3[] = "value3".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
txn.put(k1, v1);
txn.put(testCf, k2, v2);
txn.merge(k3, v3);
txn.delete(testCf, k2);
assertThat(txn.getNumKeys()).isEqualTo(3);
assertThat(txn.getNumPuts()).isEqualTo(2);
assertThat(txn.getNumMerges()).isEqualTo(1);
assertThat(txn.getNumDeletes()).isEqualTo(1);
}
}
@Test
public void elapsedTime() throws RocksDBException, InterruptedException {
final long preStartTxnTime = System.currentTimeMillis();
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
Thread.sleep(1);
final long txnElapsedTime = txn.getElapsedTime();
assertThat(txnElapsedTime).isLessThan(System.currentTimeMillis()
- preStartTxnTime);
assertThat(txnElapsedTime).isGreaterThan(0);
}
}
@Test
public void getWriteBatch() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
txn.put(k1, v1);
final WriteBatchWithIndex writeBatch = txn.getWriteBatch();
assertThat(writeBatch).isNotNull();
assertThat(writeBatch.isOwningHandle()).isFalse();
assertThat(writeBatch.count()).isEqualTo(1);
}
}
@Test
public void setLockTimeout() throws RocksDBException {
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
txn.setLockTimeout(1000);
}
}
@Test
public void writeOptions() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final WriteOptions writeOptions = new WriteOptions()
.setDisableWAL(true)
.setSync(true);
final Transaction txn = dbContainer.beginTransaction(writeOptions)) {
txn.put(k1, v1);
WriteOptions txnWriteOptions = txn.getWriteOptions();
assertThat(txnWriteOptions).isNotNull();
assertThat(txnWriteOptions.isOwningHandle()).isFalse();
assertThat(txnWriteOptions).isNotSameAs(writeOptions);
assertThat(txnWriteOptions.disableWAL()).isTrue();
assertThat(txnWriteOptions.sync()).isTrue();
txn.setWriteOptions(txnWriteOptions.setSync(false));
txnWriteOptions = txn.getWriteOptions();
assertThat(txnWriteOptions).isNotNull();
assertThat(txnWriteOptions.isOwningHandle()).isFalse();
assertThat(txnWriteOptions).isNotSameAs(writeOptions);
assertThat(txnWriteOptions.disableWAL()).isTrue();
assertThat(txnWriteOptions.sync()).isFalse();
}
}
@Test
public void undoGetForUpdate_cf() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
assertThat(txn.getForUpdate(readOptions, testCf, k1, true)).isNull();
txn.put(testCf, k1, v1);
assertThat(txn.getForUpdate(readOptions, testCf, k1, true)).isEqualTo(v1);
txn.undoGetForUpdate(testCf, k1);
}
}
@Test
public void undoGetForUpdate() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
assertThat(txn.getForUpdate(readOptions, k1, true)).isNull();
txn.put(k1, v1);
assertThat(txn.getForUpdate(readOptions, k1, true)).isEqualTo(v1);
txn.undoGetForUpdate(k1);
}
}
@Test
public void rebuildFromWriteBatch() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
final byte k2[] = "key2".getBytes(UTF_8);
final byte v2[] = "value2".getBytes(UTF_8);
final byte k3[] = "key3".getBytes(UTF_8);
final byte v3[] = "value3".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions();
final Transaction txn = dbContainer.beginTransaction()) {
txn.put(k1, v1);
assertThat(txn.get(readOptions, k1)).isEqualTo(v1);
assertThat(txn.getNumKeys()).isEqualTo(1);
try(final WriteBatch writeBatch = new WriteBatch()) {
writeBatch.put(k2, v2);
writeBatch.put(k3, v3);
txn.rebuildFromWriteBatch(writeBatch);
assertThat(txn.get(readOptions, k1)).isEqualTo(v1);
assertThat(txn.get(readOptions, k2)).isEqualTo(v2);
assertThat(txn.get(readOptions, k3)).isEqualTo(v3);
assertThat(txn.getNumKeys()).isEqualTo(3);
}
}
}
@Test
public void getCommitTimeWriteBatch() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
txn.put(k1, v1);
final WriteBatch writeBatch = txn.getCommitTimeWriteBatch();
assertThat(writeBatch).isNotNull();
assertThat(writeBatch.isOwningHandle()).isFalse();
assertThat(writeBatch.count()).isEqualTo(0);
}
}
@Test
public void logNumber() throws RocksDBException {
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
assertThat(txn.getLogNumber()).isEqualTo(0);
final long logNumber = rand.nextLong();
txn.setLogNumber(logNumber);
assertThat(txn.getLogNumber()).isEqualTo(logNumber);
}
}
private static byte[] concat(final byte[][] bufs) {
int resultLength = 0;
for(final byte[] buf : bufs) {
resultLength += buf.length;
}
final byte[] result = new byte[resultLength];
int resultOffset = 0;
for(final byte[] buf : bufs) {
final int srcLength = buf.length;
System.arraycopy(buf, 0, result, resultOffset, srcLength);
resultOffset += srcLength;
}
return result;
}
private static class TestTransactionNotifier
extends AbstractTransactionNotifier {
private final List<Snapshot> createdSnapshots = new ArrayList<>();
@Override
public void snapshotCreated(final Snapshot newSnapshot) {
createdSnapshots.add(newSnapshot);
}
public List<Snapshot> getCreatedSnapshots() {
return createdSnapshots;
}
}
protected static abstract class DBContainer
implements AutoCloseable {
protected final WriteOptions writeOptions;
protected final List<ColumnFamilyHandle> columnFamilyHandles;
protected final ColumnFamilyOptions columnFamilyOptions;
protected final DBOptions options;
public DBContainer(final WriteOptions writeOptions,
final List<ColumnFamilyHandle> columnFamilyHandles,
final ColumnFamilyOptions columnFamilyOptions,
final DBOptions options) {
this.writeOptions = writeOptions;
this.columnFamilyHandles = columnFamilyHandles;
this.columnFamilyOptions = columnFamilyOptions;
this.options = options;
}
public abstract Transaction beginTransaction();
public abstract Transaction beginTransaction(
final WriteOptions writeOptions);
public ColumnFamilyHandle getTestColumnFamily() {
return columnFamilyHandles.get(1);
}
@Override
public abstract void close();
}
}
@@ -6,7 +6,11 @@
package org.rocksdb; package org.rocksdb;
import org.junit.ClassRule; import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.nio.charset.StandardCharsets;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@@ -16,6 +20,8 @@ public class BlockBasedTableConfigTest {
public static final RocksMemoryResource rocksMemoryResource = public static final RocksMemoryResource rocksMemoryResource =
new RocksMemoryResource(); new RocksMemoryResource();
@Rule public TemporaryFolder dbFolder = new TemporaryFolder();
@Test @Test
public void noBlockCache() { public void noBlockCache() {
BlockBasedTableConfig blockBasedTableConfig = new BlockBasedTableConfig(); BlockBasedTableConfig blockBasedTableConfig = new BlockBasedTableConfig();
@@ -31,6 +37,31 @@ public class BlockBasedTableConfigTest {
isEqualTo(8 * 1024); isEqualTo(8 * 1024);
} }
@Test
public void sharedBlockCache() throws RocksDBException {
try (final Cache cache = new LRUCache(8 * 1024 * 1024);
final Statistics statistics = new Statistics()) {
for (int shard = 0; shard < 8; shard++) {
try (final Options options =
new Options()
.setCreateIfMissing(true)
.setStatistics(statistics)
.setTableFormatConfig(new BlockBasedTableConfig().setBlockCache(cache));
final RocksDB db =
RocksDB.open(options, dbFolder.getRoot().getAbsolutePath() + "/" + shard)) {
final byte[] key = "some-key".getBytes(StandardCharsets.UTF_8);
final byte[] value = "some-value".getBytes(StandardCharsets.UTF_8);
db.put(key, value);
db.flush(new FlushOptions());
db.get(key);
assertThat(statistics.getTickerCount(TickerType.BLOCK_CACHE_ADD)).isEqualTo(shard + 1);
}
}
}
}
@Test @Test
public void blockSizeDeviation() { public void blockSizeDeviation() {
BlockBasedTableConfig blockBasedTableConfig = new BlockBasedTableConfig(); BlockBasedTableConfig blockBasedTableConfig = new BlockBasedTableConfig();
@@ -148,6 +179,14 @@ public class BlockBasedTableConfigTest {
} }
} }
@Test
public void blockBasedTableWithBlockCache() {
try (final Options options = new Options().setTableFormatConfig(
new BlockBasedTableConfig().setBlockCache(new LRUCache(17 * 1024 * 1024)))) {
assertThat(options.tableFactoryName()).isEqualTo("BlockBasedTable");
}
}
@Test @Test
public void blockBasedTableFormatVersion() { public void blockBasedTableFormatVersion() {
BlockBasedTableConfig config = new BlockBasedTableConfig(); BlockBasedTableConfig config = new BlockBasedTableConfig();
@@ -12,6 +12,7 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
public class ColumnFamilyTest { public class ColumnFamilyTest {
@@ -23,6 +24,31 @@ public class ColumnFamilyTest {
@Rule @Rule
public TemporaryFolder dbFolder = new TemporaryFolder(); public TemporaryFolder dbFolder = new TemporaryFolder();
@Test
public void columnFamilyDescriptorName() throws RocksDBException {
final byte[] cfName = "some_name".getBytes(UTF_8);
try(final ColumnFamilyOptions cfOptions = new ColumnFamilyOptions()) {
final ColumnFamilyDescriptor cfDescriptor =
new ColumnFamilyDescriptor(cfName, cfOptions);
assertThat(cfDescriptor.getName()).isEqualTo(cfName);
}
}
@Test
public void columnFamilyDescriptorOptions() throws RocksDBException {
final byte[] cfName = "some_name".getBytes(UTF_8);
try(final ColumnFamilyOptions cfOptions = new ColumnFamilyOptions()
.setCompressionType(CompressionType.BZLIB2_COMPRESSION)) {
final ColumnFamilyDescriptor cfDescriptor =
new ColumnFamilyDescriptor(cfName, cfOptions);
assertThat(cfDescriptor.getOptions().compressionType())
.isEqualTo(CompressionType.BZLIB2_COMPRESSION);
}
}
@Test @Test
public void listColumnFamilies() throws RocksDBException { public void listColumnFamilies() throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true); try (final Options options = new Options().setCreateIfMissing(true);
@@ -47,6 +73,9 @@ public class ColumnFamilyTest {
try { try {
assertThat(cfh).isNotNull(); assertThat(cfh).isNotNull();
assertThat(cfh.getName()).isEqualTo("default".getBytes(UTF_8));
assertThat(cfh.getID()).isEqualTo(0);
final byte[] key = "key".getBytes(); final byte[] key = "key".getBytes();
final byte[] value = "value".getBytes(); final byte[] value = "value".getBytes();
@@ -64,15 +93,25 @@ public class ColumnFamilyTest {
@Test @Test
public void createColumnFamily() throws RocksDBException { public void createColumnFamily() throws RocksDBException {
final byte[] cfName = "new_cf".getBytes(UTF_8);
final ColumnFamilyDescriptor cfDescriptor = new ColumnFamilyDescriptor(cfName,
new ColumnFamilyOptions());
try (final Options options = new Options().setCreateIfMissing(true); try (final Options options = new Options().setCreateIfMissing(true);
final RocksDB db = RocksDB.open(options, final RocksDB db = RocksDB.open(options,
dbFolder.getRoot().getAbsolutePath())) { dbFolder.getRoot().getAbsolutePath())) {
final ColumnFamilyHandle columnFamilyHandle = db.createColumnFamily(
new ColumnFamilyDescriptor("new_cf".getBytes(), final ColumnFamilyHandle columnFamilyHandle = db.createColumnFamily(cfDescriptor);
new ColumnFamilyOptions()));
try { try {
assertThat(columnFamilyHandle.getName()).isEqualTo(cfName);
assertThat(columnFamilyHandle.getID()).isEqualTo(1);
final ColumnFamilyDescriptor latestDescriptor = columnFamilyHandle.getDescriptor();
assertThat(latestDescriptor.getName()).isEqualTo(cfName);
final List<byte[]> columnFamilyNames = RocksDB.listColumnFamilies( final List<byte[]> columnFamilyNames = RocksDB.listColumnFamilies(
options, dbFolder.getRoot().getAbsolutePath()); options, dbFolder.getRoot().getAbsolutePath());
assertThat(columnFamilyNames).isNotNull(); assertThat(columnFamilyNames).isNotNull();
assertThat(columnFamilyNames.size()).isGreaterThan(0); assertThat(columnFamilyNames.size()).isGreaterThan(0);
assertThat(columnFamilyNames.size()).isEqualTo(2); assertThat(columnFamilyNames.size()).isEqualTo(2);
@@ -0,0 +1,92 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.util.*;
import java.util.Comparator;
import static org.junit.Assert.assertEquals;
public class NativeComparatorWrapperTest {
@Rule
public TemporaryFolder dbFolder = new TemporaryFolder();
private static final Random random = new Random();
@Test
public void rountrip() throws RocksDBException {
final String dbPath = dbFolder.getRoot().getAbsolutePath();
final int ITERATIONS = 1_000;
final String[] storedKeys = new String[ITERATIONS];
try (final NativeStringComparatorWrapper comparator = new NativeStringComparatorWrapper();
final Options opt = new Options()
.setCreateIfMissing(true)
.setComparator(comparator)) {
// store random integer keys
try (final RocksDB db = RocksDB.open(opt, dbPath)) {
for (int i = 0; i < ITERATIONS; i++) {
final String strKey = randomString();
final byte key[] = strKey.getBytes();
// does key already exist (avoid duplicates)
if (i > 0 && db.get(key) != null) {
i--; // generate a different key
} else {
db.put(key, "value".getBytes());
storedKeys[i] = strKey;
}
}
}
// sort the stored keys into ascending alpha-numeric order
Arrays.sort(storedKeys, new Comparator<String>() {
@Override
public int compare(final String o1, final String o2) {
return o1.compareTo(o2);
}
});
// re-open db and read from start to end
// string keys should be in ascending
// order
try (final RocksDB db = RocksDB.open(opt, dbPath);
final RocksIterator it = db.newIterator()) {
int count = 0;
for (it.seekToFirst(); it.isValid(); it.next()) {
final String strKey = new String(it.key());
assertEquals(storedKeys[count++], strKey);
}
}
}
}
private String randomString() {
final char[] chars = new char[12];
for(int i = 0; i < 12; i++) {
final int letterCode = random.nextInt(24);
final char letter = (char) (((int) 'a') + letterCode);
chars[i] = letter;
}
return String.copyValueOf(chars);
}
public static class NativeStringComparatorWrapper
extends NativeComparatorWrapper {
@Override
protected long initializeNative(final long... nativeParameterHandles) {
return newStringComparator();
}
private native long newStringComparator();
}
}
@@ -0,0 +1,131 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class OptimisticTransactionDBTest {
@Rule
public TemporaryFolder dbFolder = new TemporaryFolder();
@Test
public void open() throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true);
final OptimisticTransactionDB otdb = OptimisticTransactionDB.open(options,
dbFolder.getRoot().getAbsolutePath())) {
assertThat(otdb).isNotNull();
}
}
@Test
public void open_columnFamilies() throws RocksDBException {
try(final DBOptions dbOptions = new DBOptions().setCreateIfMissing(true)
.setCreateMissingColumnFamilies(true);
final ColumnFamilyOptions myCfOpts = new ColumnFamilyOptions()) {
final List<ColumnFamilyDescriptor> columnFamilyDescriptors =
Arrays.asList(
new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY),
new ColumnFamilyDescriptor("myCf".getBytes(), myCfOpts));
final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
try (final OptimisticTransactionDB otdb = OptimisticTransactionDB.open(dbOptions,
dbFolder.getRoot().getAbsolutePath(),
columnFamilyDescriptors, columnFamilyHandles)) {
try {
assertThat(otdb).isNotNull();
} finally {
for (final ColumnFamilyHandle handle : columnFamilyHandles) {
handle.close();
}
}
}
}
}
@Test
public void beginTransaction() throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true);
final OptimisticTransactionDB otdb = OptimisticTransactionDB.open(
options, dbFolder.getRoot().getAbsolutePath());
final WriteOptions writeOptions = new WriteOptions()) {
try(final Transaction txn = otdb.beginTransaction(writeOptions)) {
assertThat(txn).isNotNull();
}
}
}
@Test
public void beginTransaction_transactionOptions() throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true);
final OptimisticTransactionDB otdb = OptimisticTransactionDB.open(
options, dbFolder.getRoot().getAbsolutePath());
final WriteOptions writeOptions = new WriteOptions();
final OptimisticTransactionOptions optimisticTxnOptions =
new OptimisticTransactionOptions()) {
try(final Transaction txn = otdb.beginTransaction(writeOptions,
optimisticTxnOptions)) {
assertThat(txn).isNotNull();
}
}
}
@Test
public void beginTransaction_withOld() throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true);
final OptimisticTransactionDB otdb = OptimisticTransactionDB.open(
options, dbFolder.getRoot().getAbsolutePath());
final WriteOptions writeOptions = new WriteOptions()) {
try(final Transaction txn = otdb.beginTransaction(writeOptions)) {
final Transaction txnReused = otdb.beginTransaction(writeOptions, txn);
assertThat(txnReused).isSameAs(txn);
}
}
}
@Test
public void beginTransaction_withOld_transactionOptions()
throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true);
final OptimisticTransactionDB otdb = OptimisticTransactionDB.open(
options, dbFolder.getRoot().getAbsolutePath());
final WriteOptions writeOptions = new WriteOptions();
final OptimisticTransactionOptions optimisticTxnOptions =
new OptimisticTransactionOptions()) {
try(final Transaction txn = otdb.beginTransaction(writeOptions)) {
final Transaction txnReused = otdb.beginTransaction(writeOptions,
optimisticTxnOptions, txn);
assertThat(txnReused).isSameAs(txn);
}
}
}
@Test
public void baseDB() throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true);
final OptimisticTransactionDB otdb = OptimisticTransactionDB.open(options,
dbFolder.getRoot().getAbsolutePath())) {
assertThat(otdb).isNotNull();
final RocksDB db = otdb.getBaseDB();
assertThat(db).isNotNull();
assertThat(db.isOwningHandle()).isFalse();
}
}
}
@@ -0,0 +1,37 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
import org.junit.Test;
import org.rocksdb.util.DirectBytewiseComparator;
import java.util.Random;
import static org.assertj.core.api.Assertions.assertThat;
public class OptimisticTransactionOptionsTest {
private static final Random rand = PlatformRandomHelper.
getPlatformSpecificRandomFactory();
@Test
public void setSnapshot() {
try (final OptimisticTransactionOptions opt = new OptimisticTransactionOptions()) {
final boolean boolValue = rand.nextBoolean();
opt.setSetSnapshot(boolValue);
assertThat(opt.isSetSnapshot()).isEqualTo(boolValue);
}
}
@Test
public void comparator() {
try (final OptimisticTransactionOptions opt = new OptimisticTransactionOptions();
final ComparatorOptions copt = new ComparatorOptions();
final DirectComparator comparator = new DirectBytewiseComparator(copt)) {
opt.setComparator(comparator);
}
}
}
@@ -0,0 +1,350 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
public class OptimisticTransactionTest extends AbstractTransactionTest {
@Test
public void getForUpdate_cf_conflict() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
final byte v12[] = "value12".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
try(final Transaction txn = dbContainer.beginTransaction()) {
txn.put(testCf, k1, v1);
assertThat(txn.get(testCf, readOptions, k1)).isEqualTo(v1);
txn.commit();
}
try(final Transaction txn2 = dbContainer.beginTransaction()) {
try(final Transaction txn3 = dbContainer.beginTransaction()) {
assertThat(txn3.getForUpdate(readOptions, testCf, k1, true)).isEqualTo(v1);
// NOTE: txn2 updates k1, during txn3
txn2.put(testCf, k1, v12);
assertThat(txn2.get(testCf, readOptions, k1)).isEqualTo(v12);
txn2.commit();
try {
txn3.commit(); // should cause an exception!
} catch(final RocksDBException e) {
assertThat(e.getStatus().getCode()).isSameAs(Status.Code.Busy);
return;
}
}
}
fail("Expected an exception for put after getForUpdate from conflicting" +
"transactions");
}
}
@Test
public void getForUpdate_conflict() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
final byte v12[] = "value12".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions()) {
try(final Transaction txn = dbContainer.beginTransaction()) {
txn.put(k1, v1);
assertThat(txn.get(readOptions, k1)).isEqualTo(v1);
txn.commit();
}
try(final Transaction txn2 = dbContainer.beginTransaction()) {
try(final Transaction txn3 = dbContainer.beginTransaction()) {
assertThat(txn3.getForUpdate(readOptions, k1, true)).isEqualTo(v1);
// NOTE: txn2 updates k1, during txn3
txn2.put(k1, v12);
assertThat(txn2.get(readOptions, k1)).isEqualTo(v12);
txn2.commit();
try {
txn3.commit(); // should cause an exception!
} catch(final RocksDBException e) {
assertThat(e.getStatus().getCode()).isSameAs(Status.Code.Busy);
return;
}
}
}
fail("Expected an exception for put after getForUpdate from conflicting" +
"transactions");
}
}
@Test
public void multiGetForUpdate_cf_conflict() throws RocksDBException {
final byte keys[][] = new byte[][] {
"key1".getBytes(UTF_8),
"key2".getBytes(UTF_8)};
final byte values[][] = new byte[][] {
"value1".getBytes(UTF_8),
"value2".getBytes(UTF_8)};
final byte[] otherValue = "otherValue".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
final List<ColumnFamilyHandle> cfList = Arrays.asList(testCf, testCf);
try(final Transaction txn = dbContainer.beginTransaction()) {
txn.put(testCf, keys[0], values[0]);
txn.put(testCf, keys[1], values[1]);
assertThat(txn.multiGet(readOptions, cfList, keys)).isEqualTo(values);
txn.commit();
}
try(final Transaction txn2 = dbContainer.beginTransaction()) {
try(final Transaction txn3 = dbContainer.beginTransaction()) {
assertThat(txn3.multiGetForUpdate(readOptions, cfList, keys))
.isEqualTo(values);
// NOTE: txn2 updates k1, during txn3
txn2.put(testCf, keys[0], otherValue);
assertThat(txn2.get(testCf, readOptions, keys[0]))
.isEqualTo(otherValue);
txn2.commit();
try {
txn3.commit(); // should cause an exception!
} catch(final RocksDBException e) {
assertThat(e.getStatus().getCode()).isSameAs(Status.Code.Busy);
return;
}
}
}
fail("Expected an exception for put after getForUpdate from conflicting" +
"transactions");
}
}
@Test
public void multiGetForUpdate_conflict() throws RocksDBException {
final byte keys[][] = new byte[][] {
"key1".getBytes(UTF_8),
"key2".getBytes(UTF_8)};
final byte values[][] = new byte[][] {
"value1".getBytes(UTF_8),
"value2".getBytes(UTF_8)};
final byte[] otherValue = "otherValue".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions()) {
try(final Transaction txn = dbContainer.beginTransaction()) {
txn.put(keys[0], values[0]);
txn.put(keys[1], values[1]);
assertThat(txn.multiGet(readOptions, keys)).isEqualTo(values);
txn.commit();
}
try(final Transaction txn2 = dbContainer.beginTransaction()) {
try(final Transaction txn3 = dbContainer.beginTransaction()) {
assertThat(txn3.multiGetForUpdate(readOptions, keys))
.isEqualTo(values);
// NOTE: txn2 updates k1, during txn3
txn2.put(keys[0], otherValue);
assertThat(txn2.get(readOptions, keys[0]))
.isEqualTo(otherValue);
txn2.commit();
try {
txn3.commit(); // should cause an exception!
} catch(final RocksDBException e) {
assertThat(e.getStatus().getCode()).isSameAs(Status.Code.Busy);
return;
}
}
}
fail("Expected an exception for put after getForUpdate from conflicting" +
"transactions");
}
}
@Test
public void undoGetForUpdate_cf_conflict() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
final byte v12[] = "value12".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions()) {
final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily();
try(final Transaction txn = dbContainer.beginTransaction()) {
txn.put(testCf, k1, v1);
assertThat(txn.get(testCf, readOptions, k1)).isEqualTo(v1);
txn.commit();
}
try(final Transaction txn2 = dbContainer.beginTransaction()) {
try(final Transaction txn3 = dbContainer.beginTransaction()) {
assertThat(txn3.getForUpdate(readOptions, testCf, k1, true)).isEqualTo(v1);
// undo the getForUpdate
txn3.undoGetForUpdate(testCf, k1);
// NOTE: txn2 updates k1, during txn3
txn2.put(testCf, k1, v12);
assertThat(txn2.get(testCf, readOptions, k1)).isEqualTo(v12);
txn2.commit();
// should not cause an exception
// because we undid the getForUpdate above!
txn3.commit();
}
}
}
}
@Test
public void undoGetForUpdate_conflict() throws RocksDBException {
final byte k1[] = "key1".getBytes(UTF_8);
final byte v1[] = "value1".getBytes(UTF_8);
final byte v12[] = "value12".getBytes(UTF_8);
try(final DBContainer dbContainer = startDb();
final ReadOptions readOptions = new ReadOptions()) {
try(final Transaction txn = dbContainer.beginTransaction()) {
txn.put(k1, v1);
assertThat(txn.get(readOptions, k1)).isEqualTo(v1);
txn.commit();
}
try(final Transaction txn2 = dbContainer.beginTransaction()) {
try(final Transaction txn3 = dbContainer.beginTransaction()) {
assertThat(txn3.getForUpdate(readOptions, k1, true)).isEqualTo(v1);
// undo the getForUpdate
txn3.undoGetForUpdate(k1);
// NOTE: txn2 updates k1, during txn3
txn2.put(k1, v12);
assertThat(txn2.get(readOptions, k1)).isEqualTo(v12);
txn2.commit();
// should not cause an exception
// because we undid the getForUpdate above!
txn3.commit();
}
}
}
}
@Test
public void name() throws RocksDBException {
try(final DBContainer dbContainer = startDb();
final Transaction txn = dbContainer.beginTransaction()) {
assertThat(txn.getName()).isEmpty();
final String name = "my-transaction-" + rand.nextLong();
try {
txn.setName(name);
} catch(final RocksDBException e) {
assertThat(e.getStatus().getCode() == Status.Code.InvalidArgument);
return;
}
fail("Optimistic transactions cannot be named.");
}
}
@Override
public OptimisticTransactionDBContainer startDb()
throws RocksDBException {
final DBOptions options = new DBOptions()
.setCreateIfMissing(true)
.setCreateMissingColumnFamilies(true);
final ColumnFamilyOptions columnFamilyOptions = new ColumnFamilyOptions();
final List<ColumnFamilyDescriptor> columnFamilyDescriptors =
Arrays.asList(
new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY),
new ColumnFamilyDescriptor(TXN_TEST_COLUMN_FAMILY,
columnFamilyOptions));
final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
final OptimisticTransactionDB optimisticTxnDb;
try {
optimisticTxnDb = OptimisticTransactionDB.open(
options, dbFolder.getRoot().getAbsolutePath(),
columnFamilyDescriptors, columnFamilyHandles);
} catch(final RocksDBException e) {
columnFamilyOptions.close();
options.close();
throw e;
}
final WriteOptions writeOptions = new WriteOptions();
final OptimisticTransactionOptions optimisticTxnOptions =
new OptimisticTransactionOptions();
return new OptimisticTransactionDBContainer(optimisticTxnOptions,
writeOptions, columnFamilyHandles, optimisticTxnDb, columnFamilyOptions,
options);
}
private static class OptimisticTransactionDBContainer
extends DBContainer {
private final OptimisticTransactionOptions optimisticTxnOptions;
private final OptimisticTransactionDB optimisticTxnDb;
public OptimisticTransactionDBContainer(
final OptimisticTransactionOptions optimisticTxnOptions,
final WriteOptions writeOptions,
final List<ColumnFamilyHandle> columnFamilyHandles,
final OptimisticTransactionDB optimisticTxnDb,
final ColumnFamilyOptions columnFamilyOptions,
final DBOptions options) {
super(writeOptions, columnFamilyHandles, columnFamilyOptions,
options);
this.optimisticTxnOptions = optimisticTxnOptions;
this.optimisticTxnDb = optimisticTxnDb;
}
@Override
public Transaction beginTransaction() {
return optimisticTxnDb.beginTransaction(writeOptions,
optimisticTxnOptions);
}
@Override
public Transaction beginTransaction(final WriteOptions writeOptions) {
return optimisticTxnDb.beginTransaction(writeOptions,
optimisticTxnOptions);
}
@Override
public void close() {
optimisticTxnOptions.close();
writeOptions.close();
for(final ColumnFamilyHandle columnFamilyHandle : columnFamilyHandles) {
columnFamilyHandle.close();
}
optimisticTxnDb.close();
options.close();
}
}
}
@@ -0,0 +1,64 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
import org.junit.Test;
import java.util.Random;
import static org.assertj.core.api.Assertions.assertThat;
public class TransactionDBOptionsTest {
private static final Random rand = PlatformRandomHelper.
getPlatformSpecificRandomFactory();
@Test
public void maxNumLocks() {
try (final TransactionDBOptions opt = new TransactionDBOptions()) {
final long longValue = rand.nextLong();
opt.setMaxNumLocks(longValue);
assertThat(opt.getMaxNumLocks()).isEqualTo(longValue);
}
}
@Test
public void maxNumStripes() {
try (final TransactionDBOptions opt = new TransactionDBOptions()) {
final long longValue = rand.nextLong();
opt.setNumStripes(longValue);
assertThat(opt.getNumStripes()).isEqualTo(longValue);
}
}
@Test
public void transactionLockTimeout() {
try (final TransactionDBOptions opt = new TransactionDBOptions()) {
final long longValue = rand.nextLong();
opt.setTransactionLockTimeout(longValue);
assertThat(opt.getTransactionLockTimeout()).isEqualTo(longValue);
}
}
@Test
public void defaultLockTimeout() {
try (final TransactionDBOptions opt = new TransactionDBOptions()) {
final long longValue = rand.nextLong();
opt.setDefaultLockTimeout(longValue);
assertThat(opt.getDefaultLockTimeout()).isEqualTo(longValue);
}
}
@Test
public void writePolicy() {
try (final TransactionDBOptions opt = new TransactionDBOptions()) {
final TxnDBWritePolicy writePolicy = TxnDBWritePolicy.WRITE_UNPREPARED; // non-default
opt.setWritePolicy(writePolicy);
assertThat(opt.getWritePolicy()).isEqualTo(writePolicy);
}
}
}
@@ -0,0 +1,178 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
package org.rocksdb;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.util.*;
import static org.assertj.core.api.Assertions.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
public class TransactionDBTest {
@Rule
public TemporaryFolder dbFolder = new TemporaryFolder();
@Test
public void open() throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true);
final TransactionDBOptions txnDbOptions = new TransactionDBOptions();
final TransactionDB tdb = TransactionDB.open(options, txnDbOptions,
dbFolder.getRoot().getAbsolutePath())) {
assertThat(tdb).isNotNull();
}
}
@Test
public void open_columnFamilies() throws RocksDBException {
try(final DBOptions dbOptions = new DBOptions().setCreateIfMissing(true)
.setCreateMissingColumnFamilies(true);
final ColumnFamilyOptions myCfOpts = new ColumnFamilyOptions()) {
final List<ColumnFamilyDescriptor> columnFamilyDescriptors =
Arrays.asList(
new ColumnFamilyDescriptor(RocksDB.DEFAULT_COLUMN_FAMILY),
new ColumnFamilyDescriptor("myCf".getBytes(), myCfOpts));
final List<ColumnFamilyHandle> columnFamilyHandles = new ArrayList<>();
try (final TransactionDBOptions txnDbOptions = new TransactionDBOptions();
final TransactionDB tdb = TransactionDB.open(dbOptions, txnDbOptions,
dbFolder.getRoot().getAbsolutePath(),
columnFamilyDescriptors, columnFamilyHandles)) {
try {
assertThat(tdb).isNotNull();
} finally {
for (final ColumnFamilyHandle handle : columnFamilyHandles) {
handle.close();
}
}
}
}
}
@Test
public void beginTransaction() throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true);
final TransactionDBOptions txnDbOptions = new TransactionDBOptions();
final TransactionDB tdb = TransactionDB.open(options, txnDbOptions,
dbFolder.getRoot().getAbsolutePath());
final WriteOptions writeOptions = new WriteOptions()) {
try(final Transaction txn = tdb.beginTransaction(writeOptions)) {
assertThat(txn).isNotNull();
}
}
}
@Test
public void beginTransaction_transactionOptions() throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true);
final TransactionDBOptions txnDbOptions = new TransactionDBOptions();
final TransactionDB tdb = TransactionDB.open(options, txnDbOptions,
dbFolder.getRoot().getAbsolutePath());
final WriteOptions writeOptions = new WriteOptions();
final TransactionOptions txnOptions = new TransactionOptions()) {
try(final Transaction txn = tdb.beginTransaction(writeOptions,
txnOptions)) {
assertThat(txn).isNotNull();
}
}
}
@Test
public void beginTransaction_withOld() throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true);
final TransactionDBOptions txnDbOptions = new TransactionDBOptions();
final TransactionDB tdb = TransactionDB.open(options, txnDbOptions,
dbFolder.getRoot().getAbsolutePath());
final WriteOptions writeOptions = new WriteOptions()) {
try(final Transaction txn = tdb.beginTransaction(writeOptions)) {
final Transaction txnReused = tdb.beginTransaction(writeOptions, txn);
assertThat(txnReused).isSameAs(txn);
}
}
}
@Test
public void beginTransaction_withOld_transactionOptions()
throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true);
final TransactionDBOptions txnDbOptions = new TransactionDBOptions();
final TransactionDB tdb = TransactionDB.open(options, txnDbOptions,
dbFolder.getRoot().getAbsolutePath());
final WriteOptions writeOptions = new WriteOptions();
final TransactionOptions txnOptions = new TransactionOptions()) {
try(final Transaction txn = tdb.beginTransaction(writeOptions)) {
final Transaction txnReused = tdb.beginTransaction(writeOptions,
txnOptions, txn);
assertThat(txnReused).isSameAs(txn);
}
}
}
@Test
public void lockStatusData() throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true);
final TransactionDBOptions txnDbOptions = new TransactionDBOptions();
final TransactionDB tdb = TransactionDB.open(options, txnDbOptions,
dbFolder.getRoot().getAbsolutePath());
final WriteOptions writeOptions = new WriteOptions();
final ReadOptions readOptions = new ReadOptions()) {
try (final Transaction txn = tdb.beginTransaction(writeOptions)) {
final byte key[] = "key".getBytes(UTF_8);
final byte value[] = "value".getBytes(UTF_8);
txn.put(key, value);
assertThat(txn.getForUpdate(readOptions, key, true)).isEqualTo(value);
final Map<Long, TransactionDB.KeyLockInfo> lockStatus =
tdb.getLockStatusData();
assertThat(lockStatus.size()).isEqualTo(1);
final Set<Map.Entry<Long, TransactionDB.KeyLockInfo>> entrySet = lockStatus.entrySet();
final Map.Entry<Long, TransactionDB.KeyLockInfo> entry = entrySet.iterator().next();
final long columnFamilyId = entry.getKey();
assertThat(columnFamilyId).isEqualTo(0);
final TransactionDB.KeyLockInfo keyLockInfo = entry.getValue();
assertThat(keyLockInfo.getKey()).isEqualTo(new String(key, UTF_8));
assertThat(keyLockInfo.getTransactionIDs().length).isEqualTo(1);
assertThat(keyLockInfo.getTransactionIDs()[0]).isEqualTo(txn.getId());
assertThat(keyLockInfo.isExclusive()).isTrue();
}
}
}
@Test
public void deadlockInfoBuffer() throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true);
final TransactionDBOptions txnDbOptions = new TransactionDBOptions();
final TransactionDB tdb = TransactionDB.open(options, txnDbOptions,
dbFolder.getRoot().getAbsolutePath())) {
// TODO(AR) can we cause a deadlock so that we can test the output here?
assertThat(tdb.getDeadlockInfoBuffer()).isEmpty();
}
}
@Test
public void setDeadlockInfoBufferSize() throws RocksDBException {
try (final Options options = new Options().setCreateIfMissing(true);
final TransactionDBOptions txnDbOptions = new TransactionDBOptions();
final TransactionDB tdb = TransactionDB.open(options, txnDbOptions,
dbFolder.getRoot().getAbsolutePath())) {
tdb.setDeadlockInfoBufferSize(123);
}
}
}

Some files were not shown because too many files have changed in this diff Show More