mirror of
https://github.com/facebook/rocksdb.git
synced 2026-07-07 22:55:23 +08:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| be955bff18 | |||
| 424a9572e3 | |||
| 4a5f01caa1 | |||
| abc4202e47 | |||
| 198052b24c | |||
| d9c289caa4 | |||
| 3c6bb75133 | |||
| 0c54d2609c | |||
| f9e0a06512 | |||
| 8d7396418c | |||
| d25ca5fd49 | |||
| 2da2286dd0 | |||
| 83973ddd39 | |||
| 1c18482bbf | |||
| b245e51955 | |||
| c60df9d9e7 | |||
| 747c853203 | |||
| f5ee207c64 | |||
| f2fd21fa6f | |||
| 758527812c | |||
| 9d2e34ed4c | |||
| 1f5103d583 | |||
| 163dd4b81b | |||
| 1642582559 | |||
| 8d28083264 |
+27
-1
@@ -1,5 +1,26 @@
|
||||
# Rocksdb Change Log
|
||||
## Unreleased
|
||||
## 5.13.4 (6/12/2018)
|
||||
### Bug Fixes
|
||||
* Fix regression bug of Prev() with ReadOptions.iterate_upper_bound.
|
||||
|
||||
## 5.13.3 (6/6/2018)
|
||||
### Bug Fixes
|
||||
* Fix assertion when reading bloom filter of SST files containing range deletions but no data
|
||||
|
||||
## 5.13.2 (5/25/2018)
|
||||
### Public API Change
|
||||
* Introduced `CompressionOptions::kDefaultCompressionLevel`, which is a generic way to tell RocksDB to use the compression library's default level. It is now the default value for `CompressionOptions::level`. Previously the level defaulted to -1, which gave poor compression ratios in ZSTD.
|
||||
|
||||
### Bug Fixes
|
||||
* Fix segfault caused by object premature destruction (PR #3898)
|
||||
* Fix an issue with unnecessary capture in lambda expressions (PR #3904)
|
||||
|
||||
## 5.13.1 (4/30/2018)
|
||||
### New Features
|
||||
* Add `Env::LowerThreadPoolCPUPriority(Priority)` method, which lowers the CPU priority of background (esp. compaction) threads to minimize interference with foreground tasks.
|
||||
* Eliminate use of temporary directories in BackupEngine to improve reliability on distributed file systems.
|
||||
|
||||
## 5.13.0 (3/20/2018)
|
||||
### 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.
|
||||
* Remove CompactionEventListener.
|
||||
@@ -13,6 +34,11 @@
|
||||
### Bug Fixes
|
||||
* Fix a leak in prepared_section_completed_ where the zeroed entries would not removed from the map.
|
||||
* Fix WAL corruption caused by race condition between user write thread and backup/checkpoint thread.
|
||||
* Fsync after writing global seq number to the ingestion file in ExternalSstFileIngestionJob.
|
||||
* Fix memory leak when pin_l0_filter_and_index_blocks_in_cache is used with partitioned filters
|
||||
|
||||
### Java API Changes
|
||||
* Add `BlockBasedTableConfig.setBlockCache` to allow sharing a block cache across DB instances.
|
||||
|
||||
## 5.12.0 (2/14/2018)
|
||||
### Public API Change
|
||||
|
||||
@@ -53,11 +53,13 @@ if [ -z "$ROCKSDB_NO_FBCODE" -a -d /mnt/gvfs/third-party ]; then
|
||||
FBCODE_BUILD="true"
|
||||
# If we're compiling with TSAN we need pic build
|
||||
PIC_BUILD=$COMPILE_WITH_TSAN
|
||||
if [ -z "$ROCKSDB_FBCODE_BUILD_WITH_481" ]; then
|
||||
source "$PWD/build_tools/fbcode_config.sh"
|
||||
else
|
||||
if [ -n "$ROCKSDB_FBCODE_BUILD_WITH_481" ]; then
|
||||
# we need this to build with MySQL. Don't use for other purposes.
|
||||
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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -85,8 +85,9 @@ NON_SHM="TMPD=/tmp/rocksdb_test_tmp"
|
||||
GCC_481="ROCKSDB_FBCODE_BUILD_WITH_481=1"
|
||||
ASAN="COMPILE_WITH_ASAN=1"
|
||||
CLANG="USE_CLANG=1"
|
||||
LITE="OPT=\"-DROCKSDB_LITE -g\""
|
||||
TSAN="COMPILE_WITH_TSAN=1"
|
||||
# in gcc-5 there are known problems with TSAN like https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71090.
|
||||
# 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"
|
||||
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"
|
||||
|
||||
@@ -53,6 +53,45 @@ function get_lib_base()
|
||||
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 #
|
||||
###########################################################
|
||||
|
||||
@@ -1403,23 +1403,24 @@ void rocksdb_writebatch_put_log_data(
|
||||
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(
|
||||
rocksdb_writebatch_t* b,
|
||||
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)) {
|
||||
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;
|
||||
handler.state_ = state;
|
||||
handler.put_ = put;
|
||||
@@ -1664,18 +1665,6 @@ void rocksdb_writebatch_wi_iterate(
|
||||
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)) {
|
||||
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;
|
||||
handler.state_ = state;
|
||||
handler.put_ = put;
|
||||
@@ -3124,20 +3113,21 @@ void rocksdb_slicetransform_destroy(rocksdb_slicetransform_t* 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) {
|
||||
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->rep_ = rocksdb::NewFixedPrefixTransform(prefixLen);
|
||||
wrapper->state_ = nullptr;
|
||||
@@ -3146,19 +3136,6 @@ rocksdb_slicetransform_t* rocksdb_slicetransform_create_fixed_prefix(size_t pref
|
||||
}
|
||||
|
||||
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->rep_ = rocksdb::NewNoopTransform();
|
||||
wrapper->state_ = nullptr;
|
||||
|
||||
@@ -383,6 +383,9 @@ class ColumnFamilyTest : public testing::Test {
|
||||
void AssertFilesPerLevel(const std::string& value, int cf) {
|
||||
#ifndef ROCKSDB_LITE
|
||||
ASSERT_EQ(value, FilesPerLevel(cf));
|
||||
#else
|
||||
(void) value;
|
||||
(void) cf;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -397,6 +400,8 @@ class ColumnFamilyTest : public testing::Test {
|
||||
void AssertCountLiveFiles(int expected_value) {
|
||||
#ifndef ROCKSDB_LITE
|
||||
ASSERT_EQ(expected_value, CountLiveFiles());
|
||||
#else
|
||||
(void) expected_value;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -445,6 +450,8 @@ class ColumnFamilyTest : public testing::Test {
|
||||
void AssertCountLiveLogFiles(int value) {
|
||||
#ifndef ROCKSDB_LITE // GetSortedWalFiles is not supported
|
||||
ASSERT_EQ(value, CountLiveLogFiles());
|
||||
#else
|
||||
(void) value;
|
||||
#endif // !ROCKSDB_LITE
|
||||
}
|
||||
|
||||
@@ -2791,6 +2798,39 @@ TEST_F(ColumnFamilyTest, CompactionSpeedupTwoColumnFamilies) {
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
}
|
||||
|
||||
TEST_F(ColumnFamilyTest, CreateAndDestoryOptions) {
|
||||
std::unique_ptr<ColumnFamilyOptions> cfo(new ColumnFamilyOptions());
|
||||
ColumnFamilyHandle* cfh;
|
||||
Open();
|
||||
ASSERT_OK(db_->CreateColumnFamily(*(cfo.get()), "yoyo", &cfh));
|
||||
cfo.reset();
|
||||
ASSERT_OK(db_->Put(WriteOptions(), cfh, "foo", "bar"));
|
||||
ASSERT_OK(db_->Flush(FlushOptions(), cfh));
|
||||
ASSERT_OK(db_->DropColumnFamily(cfh));
|
||||
ASSERT_OK(db_->DestroyColumnFamilyHandle(cfh));
|
||||
}
|
||||
|
||||
TEST_F(ColumnFamilyTest, CreateDropAndDestroy) {
|
||||
ColumnFamilyHandle* cfh;
|
||||
Open();
|
||||
ASSERT_OK(db_->CreateColumnFamily(ColumnFamilyOptions(), "yoyo", &cfh));
|
||||
ASSERT_OK(db_->Put(WriteOptions(), cfh, "foo", "bar"));
|
||||
ASSERT_OK(db_->Flush(FlushOptions(), cfh));
|
||||
ASSERT_OK(db_->DropColumnFamily(cfh));
|
||||
ASSERT_OK(db_->DestroyColumnFamilyHandle(cfh));
|
||||
}
|
||||
|
||||
TEST_F(ColumnFamilyTest, CreateDropAndDestroyWithoutFileDeletion) {
|
||||
ColumnFamilyHandle* cfh;
|
||||
Open();
|
||||
ASSERT_OK(db_->CreateColumnFamily(ColumnFamilyOptions(), "yoyo", &cfh));
|
||||
ASSERT_OK(db_->Put(WriteOptions(), cfh, "foo", "bar"));
|
||||
ASSERT_OK(db_->Flush(FlushOptions(), cfh));
|
||||
ASSERT_OK(db_->DisableFileDeletions());
|
||||
ASSERT_OK(db_->DropColumnFamily(cfh));
|
||||
ASSERT_OK(db_->DestroyColumnFamilyHandle(cfh));
|
||||
}
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
TEST_F(ColumnFamilyTest, FlushCloseWALFiles) {
|
||||
SpecialEnv env(Env::Default());
|
||||
|
||||
@@ -318,7 +318,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr,
|
||||
"SKIPPED as DBImpl::CompactFiles is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
|
||||
@@ -1034,7 +1034,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED, not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1043,5 +1043,5 @@ int main(int argc, char** argv) {
|
||||
|
||||
#else
|
||||
|
||||
int main(int argc, char** argv) { return 0; }
|
||||
int main(int /*argc*/, char** /*argv*/) { return 0; }
|
||||
#endif // !defined(IOS_CROSS_COMPILE)
|
||||
|
||||
@@ -946,7 +946,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr,
|
||||
"SKIPPED as CompactionJobStats is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
|
||||
@@ -510,7 +510,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -333,7 +333,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3482,6 +3482,8 @@ int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
#else
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -501,6 +501,8 @@ int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
#else
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
+6
-4
@@ -36,7 +36,9 @@ class TestIterator : public InternalIterator {
|
||||
valid_(false),
|
||||
sequence_number_(0),
|
||||
iter_(0),
|
||||
cmp(comparator) {}
|
||||
cmp(comparator) {
|
||||
data_.reserve(16);
|
||||
}
|
||||
|
||||
void AddPut(std::string argkey, std::string argvalue) {
|
||||
Add(argkey, kTypeValue, argvalue);
|
||||
@@ -2549,7 +2551,7 @@ TEST_F(DBIterWithMergeIterTest, InnerMergeIteratorDataRace1) {
|
||||
// MergeIterator::Prev() realized the mem table iterator is at its end
|
||||
// and before an SeekToLast() is called.
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"MergeIterator::Prev:BeforeSeekToLast",
|
||||
"MergeIterator::Prev:BeforePrev",
|
||||
[&](void* arg) { internal_iter2_->Add("z", kTypeValue, "7", 12u); });
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
@@ -2585,7 +2587,7 @@ TEST_F(DBIterWithMergeIterTest, InnerMergeIteratorDataRace2) {
|
||||
// mem table after MergeIterator::Prev() realized the mem tableiterator is at
|
||||
// its end and before an SeekToLast() is called.
|
||||
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", 11u);
|
||||
});
|
||||
@@ -2623,7 +2625,7 @@ TEST_F(DBIterWithMergeIterTest, InnerMergeIteratorDataRace3) {
|
||||
// mem table after MergeIterator::Prev() realized the mem table iterator is at
|
||||
// its end and before an SeekToLast() is called.
|
||||
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", 15u, true);
|
||||
internal_iter2_->Add("z", kTypeValue, "7", 14u, true);
|
||||
|
||||
@@ -2043,6 +2043,43 @@ TEST_P(DBIteratorTest, CreationFailure) {
|
||||
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) {
|
||||
ASSERT_OK(Put("a", "1"));
|
||||
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) {
|
||||
Options options = CurrentOptions();
|
||||
options.statistics = rocksdb::CreateDBStatistics();
|
||||
|
||||
@@ -289,6 +289,8 @@ int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
#else
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -809,6 +809,8 @@ int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
#else
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1759,6 +1759,8 @@ int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
#else
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -500,7 +500,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr,
|
||||
"SKIPPED as DBImpl::DeleteFile is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
|
||||
@@ -510,6 +510,9 @@ Status ExternalSstFileIngestionJob::AssignGlobalSeqnoForIngestedFile(
|
||||
std::string seqno_val;
|
||||
PutFixed64(&seqno_val, seqno);
|
||||
status = rwfile->Write(file_to_ingest->global_seqno_offset, seqno_val);
|
||||
if (status.ok()) {
|
||||
status = rwfile->Fsync();
|
||||
}
|
||||
if (status.ok()) {
|
||||
file_to_ingest->assigned_seqno = seqno;
|
||||
}
|
||||
|
||||
@@ -2002,7 +2002,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr,
|
||||
"SKIPPED as External SST File Writer and Ingestion are not supported "
|
||||
"in ROCKSDB_LITE\n");
|
||||
|
||||
@@ -112,7 +112,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
#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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1170,7 +1170,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1
-1
@@ -887,7 +887,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr,
|
||||
"SKIPPED as HashSkipList and HashLinkList are not supported in "
|
||||
"ROCKSDB_LITE\n");
|
||||
|
||||
+1
-1
@@ -356,7 +356,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -431,7 +431,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr,
|
||||
"SKIPPED as WriteWithCallback is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
|
||||
Vendored
+9
@@ -802,6 +802,15 @@ class PosixEnv : public Env {
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void LowerThreadPoolCPUPriority(Priority pool = LOW) override {
|
||||
assert(pool >= Priority::BOTTOM && pool <= Priority::HIGH);
|
||||
#ifdef OS_LINUX
|
||||
thread_pools_[pool].LowerCPUPriority();
|
||||
#else
|
||||
(void)pool;
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual std::string TimeToString(uint64_t secondsSince1970) override {
|
||||
const time_t seconds = (time_t)secondsSince1970;
|
||||
struct tm t;
|
||||
|
||||
Vendored
+6
-2
@@ -873,8 +873,12 @@ void PosixWritableFile::SetWriteLifeTimeHint(Env::WriteLifeTimeHint hint) {
|
||||
if (fcntl(fd_, F_SET_RW_HINT, &hint) == 0) {
|
||||
write_hint_ = hint;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
(void)hint;
|
||||
#endif // ROCKSDB_VALGRIND_RUN
|
||||
#else
|
||||
(void)hint;
|
||||
#endif // OS_LINUX
|
||||
}
|
||||
|
||||
Status PosixWritableFile::InvalidateCache(size_t offset, size_t length) {
|
||||
|
||||
@@ -87,6 +87,14 @@ struct CompactionOptionsFIFO {
|
||||
|
||||
// Compression options for different compression algorithms like Zlib
|
||||
struct CompressionOptions {
|
||||
// RocksDB's generic default compression level. Internally it'll be translated
|
||||
// to the default compression level specific to the library being used (see
|
||||
// comment above `ColumnFamilyOptions::compression`).
|
||||
//
|
||||
// The default value is the max 16-bit int as it'll be written out in OPTIONS
|
||||
// file, which should be portable.
|
||||
const static int kDefaultCompressionLevel = 32767;
|
||||
|
||||
int window_bits;
|
||||
int level;
|
||||
int strategy;
|
||||
@@ -120,7 +128,7 @@ struct CompressionOptions {
|
||||
|
||||
CompressionOptions()
|
||||
: window_bits(-14),
|
||||
level(-1),
|
||||
level(kDefaultCompressionLevel),
|
||||
strategy(0),
|
||||
max_dict_bytes(0),
|
||||
zstd_max_train_bytes(0) {}
|
||||
|
||||
@@ -391,6 +391,9 @@ class Env {
|
||||
// Lower IO priority for threads from the specified pool.
|
||||
virtual void LowerThreadPoolIOPriority(Priority /*pool*/ = LOW) {}
|
||||
|
||||
// Lower CPU priority for threads from the specified pool.
|
||||
virtual void LowerThreadPoolCPUPriority(Priority /*pool*/ = LOW) {}
|
||||
|
||||
// Converts seconds-since-Jan-01-1970 to a printable string
|
||||
virtual std::string TimeToString(uint64_t time) = 0;
|
||||
|
||||
@@ -1082,6 +1085,10 @@ class EnvWrapper : public Env {
|
||||
target_->LowerThreadPoolIOPriority(pool);
|
||||
}
|
||||
|
||||
void LowerThreadPoolCPUPriority(Priority pool = LOW) override {
|
||||
target_->LowerThreadPoolCPUPriority(pool);
|
||||
}
|
||||
|
||||
std::string TimeToString(uint64_t time) override {
|
||||
return target_->TimeToString(time);
|
||||
}
|
||||
|
||||
@@ -197,11 +197,21 @@ struct ColumnFamilyOptions : public AdvancedColumnFamilyOptions {
|
||||
// Typical speeds of kSnappyCompression on an Intel(R) Core(TM)2 2.4GHz:
|
||||
// ~200-500MB/s compression
|
||||
// ~400-800MB/s decompression
|
||||
//
|
||||
// Note that these speeds are significantly faster than most
|
||||
// persistent storage speeds, and therefore it is typically never
|
||||
// worth switching to kNoCompression. Even if the input data is
|
||||
// incompressible, the kSnappyCompression implementation will
|
||||
// efficiently detect that and will switch to uncompressed mode.
|
||||
//
|
||||
// If you do not set `compression_opts.level`, or set it to
|
||||
// `CompressionOptions::kDefaultCompressionLevel`, we will attempt to pick the
|
||||
// default corresponding to `compression` as follows:
|
||||
//
|
||||
// - kZSTD: 3
|
||||
// - kZlibCompression: Z_DEFAULT_COMPRESSION (currently -1)
|
||||
// - kLZ4HCCompression: 0
|
||||
// - For all others, we do not specify a compression level
|
||||
CompressionType compression;
|
||||
|
||||
// Compression algorithm that will be used for the bottommost level that
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#pragma once
|
||||
|
||||
#define ROCKSDB_MAJOR 5
|
||||
#define ROCKSDB_MINOR 12
|
||||
#define ROCKSDB_PATCH 0
|
||||
#define ROCKSDB_MINOR 13
|
||||
#define ROCKSDB_PATCH 4
|
||||
|
||||
// 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
|
||||
|
||||
+20
-13
@@ -38,13 +38,14 @@ jlong Java_org_rocksdb_PlainTableConfig_newTableFactoryHandle(
|
||||
/*
|
||||
* Class: org_rocksdb_BlockBasedTableConfig
|
||||
* Method: newTableFactoryHandle
|
||||
* Signature: (ZJIJIIZIZZZJIBBI)J
|
||||
* Signature: (ZJIJJIIZIZZZJIBBI)J
|
||||
*/
|
||||
jlong Java_org_rocksdb_BlockBasedTableConfig_newTableFactoryHandle(
|
||||
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_restart_interval, jboolean whole_key_filtering,
|
||||
jlong jfilterPolicy, jboolean cache_index_and_filter_blocks,
|
||||
JNIEnv *env, jobject jobj, jboolean no_block_cache, jlong block_cache_size,
|
||||
jint block_cache_num_shardbits, jlong jblock_cache, jlong block_size,
|
||||
jint block_size_deviation, jint block_restart_interval,
|
||||
jboolean whole_key_filtering, jlong jfilter_policy,
|
||||
jboolean cache_index_and_filter_blocks,
|
||||
jboolean pin_l0_filter_and_index_blocks_in_cache,
|
||||
jboolean hash_index_allow_collision, jlong block_cache_compressed_size,
|
||||
jint block_cache_compressd_num_shard_bits, jbyte jchecksum_type,
|
||||
@@ -52,22 +53,28 @@ jlong Java_org_rocksdb_BlockBasedTableConfig_newTableFactoryHandle(
|
||||
rocksdb::BlockBasedTableOptions options;
|
||||
options.no_block_cache = no_block_cache;
|
||||
|
||||
if (!no_block_cache && 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);
|
||||
if (!no_block_cache) {
|
||||
if (jblock_cache > 0) {
|
||||
std::shared_ptr<rocksdb::Cache> *pCache =
|
||||
reinterpret_cast<std::shared_ptr<rocksdb::Cache> *>(jblock_cache);
|
||||
options.block_cache = *pCache;
|
||||
} 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_deviation = block_size_deviation;
|
||||
options.block_restart_interval = block_restart_interval;
|
||||
options.whole_key_filtering = whole_key_filtering;
|
||||
if (jfilterPolicy > 0) {
|
||||
if (jfilter_policy > 0) {
|
||||
std::shared_ptr<rocksdb::FilterPolicy> *pFilterPolicy =
|
||||
reinterpret_cast<std::shared_ptr<rocksdb::FilterPolicy> *>(
|
||||
jfilterPolicy);
|
||||
jfilter_policy);
|
||||
options.filter_policy = *pFilterPolicy;
|
||||
}
|
||||
options.cache_index_and_filter_blocks = cache_index_and_filter_blocks;
|
||||
|
||||
@@ -304,11 +304,14 @@ jobject Java_org_rocksdb_TransactionDB_getLockStatusData(
|
||||
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) {
|
||||
const rocksdb::HashMapJni::FnMapKV<const int32_t, const rocksdb::KeyLockInfo>
|
||||
fn_map_kv =
|
||||
[env](
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ public class BlockBasedTableConfig extends TableFormatConfig {
|
||||
noBlockCache_ = false;
|
||||
blockCacheSize_ = 8 * 1024 * 1024;
|
||||
blockCacheNumShardBits_ = 0;
|
||||
blockCache_ = null;
|
||||
blockSize_ = 4 * 1024;
|
||||
blockSizeDeviation_ = 10;
|
||||
blockRestartInterval_ = 16;
|
||||
@@ -71,6 +72,24 @@ public class BlockBasedTableConfig extends TableFormatConfig {
|
||||
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.
|
||||
* This is applied only if cacheSize is set to non-negative.
|
||||
@@ -413,25 +432,25 @@ public class BlockBasedTableConfig extends TableFormatConfig {
|
||||
filterHandle = filter_.nativeHandle_;
|
||||
}
|
||||
|
||||
return newTableFactoryHandle(noBlockCache_, blockCacheSize_,
|
||||
blockCacheNumShardBits_, blockSize_, blockSizeDeviation_,
|
||||
blockRestartInterval_, wholeKeyFiltering_,
|
||||
filterHandle, cacheIndexAndFilterBlocks_,
|
||||
pinL0FilterAndIndexBlocksInCache_,
|
||||
hashIndexAllowCollision_, blockCacheCompressedSize_,
|
||||
blockCacheCompressedNumShardBits_,
|
||||
checksumType_.getValue(), indexType_.getValue(),
|
||||
long blockCacheHandle = 0;
|
||||
if (blockCache_ != null) {
|
||||
blockCacheHandle = blockCache_.nativeHandle_;
|
||||
}
|
||||
|
||||
return newTableFactoryHandle(noBlockCache_, blockCacheSize_, blockCacheNumShardBits_,
|
||||
blockCacheHandle, blockSize_, blockSizeDeviation_, blockRestartInterval_,
|
||||
wholeKeyFiltering_, filterHandle, cacheIndexAndFilterBlocks_,
|
||||
pinL0FilterAndIndexBlocksInCache_, hashIndexAllowCollision_, blockCacheCompressedSize_,
|
||||
blockCacheCompressedNumShardBits_, checksumType_.getValue(), indexType_.getValue(),
|
||||
formatVersion_);
|
||||
}
|
||||
|
||||
private native long newTableFactoryHandle(
|
||||
boolean noBlockCache, long blockCacheSize, int blockCacheNumShardBits,
|
||||
long blockSize, int blockSizeDeviation, int blockRestartInterval,
|
||||
boolean wholeKeyFiltering, long filterPolicyHandle,
|
||||
private native long newTableFactoryHandle(boolean noBlockCache, long blockCacheSize,
|
||||
int blockCacheNumShardBits, long blockCacheHandle, long blockSize, int blockSizeDeviation,
|
||||
int blockRestartInterval, boolean wholeKeyFiltering, long filterPolicyHandle,
|
||||
boolean cacheIndexAndFilterBlocks, boolean pinL0FilterAndIndexBlocksInCache,
|
||||
boolean hashIndexAllowCollision, long blockCacheCompressedSize,
|
||||
int blockCacheCompressedNumShardBits, byte checkSumType,
|
||||
byte indexType, int formatVersion);
|
||||
int blockCacheCompressedNumShardBits, byte checkSumType, byte indexType, int formatVersion);
|
||||
|
||||
private boolean cacheIndexAndFilterBlocks_;
|
||||
private boolean pinL0FilterAndIndexBlocksInCache_;
|
||||
@@ -442,6 +461,7 @@ public class BlockBasedTableConfig extends TableFormatConfig {
|
||||
private long blockSize_;
|
||||
private long blockCacheSize_;
|
||||
private int blockCacheNumShardBits_;
|
||||
private Cache blockCache_;
|
||||
private long blockCacheCompressedSize_;
|
||||
private int blockCacheCompressedNumShardBits_;
|
||||
private int blockSizeDeviation_;
|
||||
|
||||
@@ -6,7 +6,11 @@
|
||||
package org.rocksdb;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -16,6 +20,8 @@ public class BlockBasedTableConfigTest {
|
||||
public static final RocksMemoryResource rocksMemoryResource =
|
||||
new RocksMemoryResource();
|
||||
|
||||
@Rule public TemporaryFolder dbFolder = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void noBlockCache() {
|
||||
BlockBasedTableConfig blockBasedTableConfig = new BlockBasedTableConfig();
|
||||
@@ -31,6 +37,31 @@ public class BlockBasedTableConfigTest {
|
||||
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
|
||||
public void blockSizeDeviation() {
|
||||
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
|
||||
public void blockBasedTableFormatVersion() {
|
||||
BlockBasedTableConfig config = new BlockBasedTableConfig();
|
||||
|
||||
@@ -280,7 +280,7 @@ struct InlineSkipList<Comparator>::Node {
|
||||
// next_[0]. This is used for passing data from AllocateKey to Insert.
|
||||
void StashHeight(const int height) {
|
||||
assert(sizeof(int) <= sizeof(next_[0]));
|
||||
memcpy(&next_[0], &height, sizeof(int));
|
||||
memcpy(static_cast<void*>(&next_[0]), &height, sizeof(int));
|
||||
}
|
||||
|
||||
// Retrieves the value passed to StashHeight. Undefined after a call
|
||||
@@ -300,30 +300,30 @@ struct InlineSkipList<Comparator>::Node {
|
||||
assert(n >= 0);
|
||||
// Use an 'acquire load' so that we observe a fully initialized
|
||||
// version of the returned Node.
|
||||
return (next_[-n].load(std::memory_order_acquire));
|
||||
return ((&next_[0] - n)->load(std::memory_order_acquire));
|
||||
}
|
||||
|
||||
void SetNext(int n, Node* x) {
|
||||
assert(n >= 0);
|
||||
// Use a 'release store' so that anybody who reads through this
|
||||
// pointer observes a fully initialized version of the inserted node.
|
||||
next_[-n].store(x, std::memory_order_release);
|
||||
(&next_[0] - n)->store(x, std::memory_order_release);
|
||||
}
|
||||
|
||||
bool CASNext(int n, Node* expected, Node* x) {
|
||||
assert(n >= 0);
|
||||
return next_[-n].compare_exchange_strong(expected, x);
|
||||
return (&next_[0] - n)->compare_exchange_strong(expected, x);
|
||||
}
|
||||
|
||||
// No-barrier variants that can be safely used in a few locations.
|
||||
Node* NoBarrier_Next(int n) {
|
||||
assert(n >= 0);
|
||||
return next_[-n].load(std::memory_order_relaxed);
|
||||
return (&next_[0] - n)->load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void NoBarrier_SetNext(int n, Node* x) {
|
||||
assert(n >= 0);
|
||||
next_[-n].store(x, std::memory_order_relaxed);
|
||||
(&next_[0] - n)->store(x, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
// Insert node after prev on specific level.
|
||||
|
||||
@@ -67,7 +67,8 @@ BlockBasedFilterBlockBuilder::BlockBasedFilterBlockBuilder(
|
||||
prefix_extractor_(prefix_extractor),
|
||||
whole_key_filtering_(table_opt.whole_key_filtering),
|
||||
prev_prefix_start_(0),
|
||||
prev_prefix_size_(0) {
|
||||
prev_prefix_size_(0),
|
||||
num_added_(0) {
|
||||
assert(policy_);
|
||||
}
|
||||
|
||||
@@ -91,6 +92,7 @@ void BlockBasedFilterBlockBuilder::Add(const Slice& key) {
|
||||
|
||||
// Add key to filter if needed
|
||||
inline void BlockBasedFilterBlockBuilder::AddKey(const Slice& key) {
|
||||
num_added_++;
|
||||
start_.push_back(entries_.size());
|
||||
entries_.append(key.data(), key.size());
|
||||
}
|
||||
@@ -106,10 +108,9 @@ inline void BlockBasedFilterBlockBuilder::AddPrefix(const Slice& key) {
|
||||
Slice prefix = prefix_extractor_->Transform(key);
|
||||
// insert prefix only when it's different from the previous prefix.
|
||||
if (prev.size() == 0 || prefix != prev) {
|
||||
start_.push_back(entries_.size());
|
||||
AddKey(prefix);
|
||||
prev_prefix_start_ = entries_.size();
|
||||
prev_prefix_size_ = prefix.size();
|
||||
entries_.append(prefix.data(), prefix.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ class BlockBasedFilterBlockBuilder : public FilterBlockBuilder {
|
||||
virtual bool IsBlockBased() override { return true; }
|
||||
virtual void StartBlock(uint64_t block_offset) override;
|
||||
virtual void Add(const Slice& key) override;
|
||||
virtual size_t NumAdded() const override { return num_added_; }
|
||||
virtual Slice Finish(const BlockHandle& tmp, Status* status) override;
|
||||
using FilterBlockBuilder::Finish;
|
||||
|
||||
@@ -65,6 +66,7 @@ class BlockBasedFilterBlockBuilder : public FilterBlockBuilder {
|
||||
std::string result_; // Filter data computed so far
|
||||
std::vector<Slice> tmp_entries_; // policy_->CreateFilter() argument
|
||||
std::vector<uint32_t> filter_offsets_;
|
||||
size_t num_added_; // Number of keys added
|
||||
|
||||
// No copying allowed
|
||||
BlockBasedFilterBlockBuilder(const BlockBasedFilterBlockBuilder&);
|
||||
|
||||
@@ -65,6 +65,7 @@ TEST_F(FilterBlockTest, EmptyBuilder) {
|
||||
|
||||
TEST_F(FilterBlockTest, SingleChunk) {
|
||||
BlockBasedFilterBlockBuilder builder(nullptr, table_options_);
|
||||
ASSERT_EQ(0, builder.NumAdded());
|
||||
builder.StartBlock(100);
|
||||
builder.Add("foo");
|
||||
builder.Add("bar");
|
||||
@@ -73,6 +74,7 @@ TEST_F(FilterBlockTest, SingleChunk) {
|
||||
builder.Add("box");
|
||||
builder.StartBlock(300);
|
||||
builder.Add("hello");
|
||||
ASSERT_EQ(5, builder.NumAdded());
|
||||
BlockContents block(builder.Finish(), false, kNoCompression);
|
||||
BlockBasedFilterBlockReader reader(nullptr, table_options_, true,
|
||||
std::move(block), nullptr);
|
||||
|
||||
@@ -650,8 +650,11 @@ Status BlockBasedTableBuilder::Finish() {
|
||||
|
||||
BlockHandle filter_block_handle, metaindex_block_handle, index_block_handle,
|
||||
compression_dict_block_handle, range_del_block_handle;
|
||||
|
||||
// Write filter block
|
||||
if (ok() && r->filter_builder != nullptr) {
|
||||
bool empty_filter_block = (r->filter_builder == nullptr ||
|
||||
r->filter_builder->NumAdded() == 0);
|
||||
if (ok() && !empty_filter_block) {
|
||||
Status s = Status::Incomplete();
|
||||
while (s.IsIncomplete()) {
|
||||
Slice filter_content = r->filter_builder->Finish(filter_block_handle, &s);
|
||||
@@ -687,7 +690,7 @@ Status BlockBasedTableBuilder::Finish() {
|
||||
}
|
||||
|
||||
if (ok()) {
|
||||
if (r->filter_builder != nullptr) {
|
||||
if (!empty_filter_block) {
|
||||
// Add mapping from "<filter_block_prefix>.Name" to location
|
||||
// of filter data.
|
||||
std::string key;
|
||||
|
||||
@@ -120,7 +120,7 @@ void ReleaseCachedEntry(void* arg, void* h) {
|
||||
void ForceReleaseCachedEntry(void* arg, void* h) {
|
||||
Cache* cache = reinterpret_cast<Cache*>(arg);
|
||||
Cache::Handle* handle = reinterpret_cast<Cache::Handle*>(h);
|
||||
cache->Release(handle, true);
|
||||
cache->Release(handle, true /* force_erase */);
|
||||
}
|
||||
|
||||
Slice GetCacheKeyFromOffset(const char* cache_key_prefix,
|
||||
|
||||
@@ -419,7 +419,7 @@ struct BlockBasedTable::Rep {
|
||||
|
||||
const ImmutableCFOptions& ioptions;
|
||||
const EnvOptions& env_options;
|
||||
const BlockBasedTableOptions& table_options;
|
||||
const BlockBasedTableOptions table_options;
|
||||
const FilterPolicy* const filter_policy;
|
||||
const InternalKeyComparator& internal_comparator;
|
||||
Status status;
|
||||
|
||||
@@ -625,7 +625,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -560,7 +560,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ class FilterBlockBuilder {
|
||||
virtual bool IsBlockBased() = 0; // If is blockbased filter
|
||||
virtual void StartBlock(uint64_t block_offset) = 0; // Start new block filter
|
||||
virtual void Add(const Slice& key) = 0; // Add a key to current filter
|
||||
virtual size_t NumAdded() const = 0; // Number of keys added
|
||||
Slice Finish() { // Generate Filter
|
||||
const BlockHandle empty_handle;
|
||||
Status dont_care_status;
|
||||
|
||||
@@ -45,6 +45,7 @@ class FullFilterBlockBuilder : public FilterBlockBuilder {
|
||||
virtual bool IsBlockBased() override { return false; }
|
||||
virtual void StartBlock(uint64_t /*block_offset*/) override {}
|
||||
virtual void Add(const Slice& key) override;
|
||||
virtual size_t NumAdded() const override { return num_added_; }
|
||||
virtual Slice Finish(const BlockHandle& tmp, Status* status) override;
|
||||
using FilterBlockBuilder::Finish;
|
||||
|
||||
|
||||
@@ -163,11 +163,13 @@ TEST_F(FullFilterBlockTest, EmptyBuilder) {
|
||||
TEST_F(FullFilterBlockTest, SingleChunk) {
|
||||
FullFilterBlockBuilder builder(
|
||||
nullptr, true, table_options_.filter_policy->GetFilterBitsBuilder());
|
||||
ASSERT_EQ(0, builder.NumAdded());
|
||||
builder.Add("foo");
|
||||
builder.Add("bar");
|
||||
builder.Add("box");
|
||||
builder.Add("box");
|
||||
builder.Add("hello");
|
||||
ASSERT_EQ(5, builder.NumAdded());
|
||||
Slice block = builder.Finish();
|
||||
FullFilterBlockReader reader(
|
||||
nullptr, true, block,
|
||||
|
||||
@@ -193,23 +193,11 @@ class MergingIterator : public InternalIterator {
|
||||
InitMaxHeap();
|
||||
for (auto& child : children_) {
|
||||
if (&child != current_) {
|
||||
if (!prefix_seek_mode_) {
|
||||
child.Seek(key());
|
||||
if (child.Valid()) {
|
||||
// Child is at first entry >= key(). Step back one to be < key()
|
||||
TEST_SYNC_POINT_CALLBACK("MergeIterator::Prev:BeforePrev",
|
||||
&child);
|
||||
child.Prev();
|
||||
} else {
|
||||
// Child has no entries >= key(). Position at last entry.
|
||||
TEST_SYNC_POINT("MergeIterator::Prev:BeforeSeekToLast");
|
||||
child.SeekToLast();
|
||||
}
|
||||
} else {
|
||||
child.SeekForPrev(key());
|
||||
if (child.Valid() && comparator_->Equal(key(), child.key())) {
|
||||
child.Prev();
|
||||
}
|
||||
child.SeekForPrev(key());
|
||||
// Child is at first entry >= key(). Step back one to be < key()
|
||||
TEST_SYNC_POINT_CALLBACK("MergeIterator::Prev:BeforePrev", &child);
|
||||
if (child.Valid() && comparator_->Equal(key(), child.key())) {
|
||||
child.Prev();
|
||||
}
|
||||
}
|
||||
if (child.Valid()) {
|
||||
|
||||
@@ -25,7 +25,8 @@ PartitionedFilterBlockBuilder::PartitionedFilterBlockBuilder(
|
||||
filter_bits_builder),
|
||||
index_on_filter_block_builder_(index_block_restart_interval),
|
||||
p_index_builder_(p_index_builder),
|
||||
filters_in_partition_(0) {
|
||||
filters_in_partition_(0),
|
||||
num_added_(0) {
|
||||
filters_per_partition_ =
|
||||
filter_bits_builder_->CalculateNumEntry(partition_size);
|
||||
}
|
||||
@@ -53,6 +54,7 @@ void PartitionedFilterBlockBuilder::AddKey(const Slice& key) {
|
||||
MaybeCutAFilterBlock();
|
||||
filter_bits_builder_->AddKey(key);
|
||||
filters_in_partition_++;
|
||||
num_added_++;
|
||||
}
|
||||
|
||||
Slice PartitionedFilterBlockBuilder::Finish(
|
||||
@@ -244,6 +246,13 @@ size_t PartitionedFilterBlockReader::ApproximateMemoryUsage() const {
|
||||
return idx_on_fltr_blk_->size();
|
||||
}
|
||||
|
||||
// Release the cached entry and decrement its ref count.
|
||||
void ReleaseFilterCachedEntry(void* arg, void* h) {
|
||||
Cache* cache = reinterpret_cast<Cache*>(arg);
|
||||
Cache::Handle* handle = reinterpret_cast<Cache::Handle*>(h);
|
||||
cache->Release(handle);
|
||||
}
|
||||
|
||||
// TODO(myabandeh): merge this with the same function in IndexReader
|
||||
void PartitionedFilterBlockReader::CacheDependencies(bool pin) {
|
||||
// Before read partitions, prefetch them to avoid lots of IOs
|
||||
@@ -302,6 +311,8 @@ void PartitionedFilterBlockReader::CacheDependencies(bool pin) {
|
||||
if (LIKELY(filter.IsSet())) {
|
||||
if (pin) {
|
||||
filter_map_[handle.offset()] = std::move(filter);
|
||||
RegisterCleanup(&ReleaseFilterCachedEntry, block_cache,
|
||||
filter.cache_handle);
|
||||
} else {
|
||||
block_cache->Release(filter.cache_handle);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ class PartitionedFilterBlockBuilder : public FullFilterBlockBuilder {
|
||||
|
||||
void AddKey(const Slice& key) override;
|
||||
|
||||
size_t NumAdded() const override { return num_added_; }
|
||||
|
||||
virtual Slice Finish(const BlockHandle& last_partition_block_handle,
|
||||
Status* status) override;
|
||||
|
||||
@@ -59,9 +61,12 @@ class PartitionedFilterBlockBuilder : public FullFilterBlockBuilder {
|
||||
uint32_t filters_per_partition_;
|
||||
// The current number of filters in the last partition
|
||||
uint32_t filters_in_partition_;
|
||||
// Number of keys added
|
||||
size_t num_added_;
|
||||
};
|
||||
|
||||
class PartitionedFilterBlockReader : public FilterBlockReader {
|
||||
class PartitionedFilterBlockReader : public FilterBlockReader,
|
||||
public Cleanable {
|
||||
public:
|
||||
explicit PartitionedFilterBlockReader(const SliceTransform* prefix_extractor,
|
||||
bool whole_key_filtering,
|
||||
|
||||
+18
-11
@@ -302,9 +302,11 @@ class KeyConvertingIterator : public InternalIterator {
|
||||
class TableConstructor: public Constructor {
|
||||
public:
|
||||
explicit TableConstructor(const Comparator* cmp,
|
||||
bool convert_to_internal_key = false)
|
||||
bool convert_to_internal_key = false,
|
||||
int level = -1)
|
||||
: Constructor(cmp),
|
||||
convert_to_internal_key_(convert_to_internal_key) {}
|
||||
convert_to_internal_key_(convert_to_internal_key),
|
||||
level_(level) {}
|
||||
~TableConstructor() { Reset(); }
|
||||
|
||||
virtual Status FinishImpl(const Options& options,
|
||||
@@ -319,14 +321,12 @@ class TableConstructor: public Constructor {
|
||||
std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
|
||||
int_tbl_prop_collector_factories;
|
||||
std::string column_family_name;
|
||||
int unknown_level = -1;
|
||||
builder.reset(ioptions.table_factory->NewTableBuilder(
|
||||
TableBuilderOptions(ioptions, internal_comparator,
|
||||
&int_tbl_prop_collector_factories,
|
||||
options.compression, CompressionOptions(),
|
||||
nullptr /* compression_dict */,
|
||||
false /* skip_filters */, column_family_name,
|
||||
unknown_level),
|
||||
TableBuilderOptions(
|
||||
ioptions, internal_comparator, &int_tbl_prop_collector_factories,
|
||||
options.compression, CompressionOptions(),
|
||||
nullptr /* compression_dict */, false /* skip_filters */,
|
||||
column_family_name, level_),
|
||||
TablePropertiesCollectorFactory::Context::kUnknownColumnFamily,
|
||||
file_writer_.get()));
|
||||
|
||||
@@ -351,8 +351,10 @@ class TableConstructor: public Constructor {
|
||||
uniq_id_ = cur_uniq_id_++;
|
||||
file_reader_.reset(test::GetRandomAccessFileReader(new test::StringSource(
|
||||
GetSink()->contents(), uniq_id_, ioptions.allow_mmap_reads)));
|
||||
const bool skip_filters = false;
|
||||
return ioptions.table_factory->NewTableReader(
|
||||
TableReaderOptions(ioptions, soptions, internal_comparator),
|
||||
TableReaderOptions(ioptions, soptions, internal_comparator,
|
||||
skip_filters, level_),
|
||||
std::move(file_reader_), GetSink()->contents().size(), &table_reader_);
|
||||
}
|
||||
|
||||
@@ -412,6 +414,7 @@ class TableConstructor: public Constructor {
|
||||
unique_ptr<RandomAccessFileReader> file_reader_;
|
||||
unique_ptr<TableReader> table_reader_;
|
||||
bool convert_to_internal_key_;
|
||||
int level_;
|
||||
|
||||
TableConstructor();
|
||||
|
||||
@@ -2249,6 +2252,7 @@ std::map<std::string, size_t> MockCache::marked_data_in_cache_;
|
||||
// table is closed. This test makes sure that the only items remains in the
|
||||
// cache after the table is closed are raw data blocks.
|
||||
TEST_F(BlockBasedTableTest, NoObjectInCacheAfterTableClose) {
|
||||
for (int level: {-1, 0, 1, 10}) {
|
||||
for (auto index_type :
|
||||
{BlockBasedTableOptions::IndexType::kBinarySearch,
|
||||
BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch}) {
|
||||
@@ -2285,7 +2289,9 @@ TEST_F(BlockBasedTableTest, NoObjectInCacheAfterTableClose) {
|
||||
rocksdb::NewBloomFilterPolicy(10, block_based_filter));
|
||||
opt.table_factory.reset(NewBlockBasedTableFactory(table_options));
|
||||
|
||||
TableConstructor c(BytewiseComparator());
|
||||
bool convert_to_internal_key = false;
|
||||
TableConstructor c(BytewiseComparator(), convert_to_internal_key,
|
||||
level);
|
||||
std::string user_key = "k01";
|
||||
std::string key =
|
||||
InternalKey(user_key, 0, kTypeValue).Encode().ToString();
|
||||
@@ -2326,6 +2332,7 @@ TEST_F(BlockBasedTableTest, NoObjectInCacheAfterTableClose) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} // level
|
||||
}
|
||||
|
||||
TEST_F(BlockBasedTableTest, BlockCacheLeak) {
|
||||
|
||||
@@ -24,7 +24,11 @@ class TwoLevelIterator : public InternalIterator {
|
||||
explicit TwoLevelIterator(TwoLevelIteratorState* state,
|
||||
InternalIterator* first_level_iter);
|
||||
|
||||
virtual ~TwoLevelIterator() { delete state_; }
|
||||
virtual ~TwoLevelIterator() {
|
||||
first_level_iter_.DeleteIter(false /* is_arena_mode */);
|
||||
second_level_iter_.DeleteIter(false /* is_arena_mode */);
|
||||
delete state_;
|
||||
}
|
||||
|
||||
virtual void Seek(const Slice& target) override;
|
||||
virtual void SeekForPrev(const Slice& target) override;
|
||||
|
||||
@@ -16,8 +16,8 @@ namespace rocksdb {
|
||||
|
||||
struct ReadOptions;
|
||||
class InternalKeyComparator;
|
||||
class Arena;
|
||||
|
||||
// TwoLevelIteratorState expects iterators are not created using the arena
|
||||
struct TwoLevelIteratorState {
|
||||
TwoLevelIteratorState() {}
|
||||
|
||||
@@ -35,11 +35,7 @@ struct TwoLevelIteratorState {
|
||||
//
|
||||
// Uses a supplied function to convert an index_iter value into
|
||||
// an iterator over the contents of the corresponding block.
|
||||
// arena: If not null, the arena is used to allocate the Iterator.
|
||||
// When destroying the iterator, the destructor will destroy
|
||||
// all the states but those allocated in arena.
|
||||
// need_free_iter_and_state: free `state` and `first_level_iter` if
|
||||
// true. Otherwise, just call destructor.
|
||||
// Note: this function expects first_level_iter was not created using the arena
|
||||
extern InternalIterator* NewTwoLevelIterator(
|
||||
TwoLevelIteratorState* state, InternalIterator* first_level_iter);
|
||||
|
||||
|
||||
@@ -989,6 +989,8 @@ DEFINE_int32(memtable_insert_with_hint_prefix_size, 0,
|
||||
"memtable insert with hint with the given prefix size.");
|
||||
DEFINE_bool(enable_io_prio, false, "Lower the background flush/compaction "
|
||||
"threads' IO priority");
|
||||
DEFINE_bool(enable_cpu_prio, false, "Lower the background flush/compaction "
|
||||
"threads' CPU priority");
|
||||
DEFINE_bool(identity_as_first_hash, false, "the first hash function of cuckoo "
|
||||
"table becomes an identity function. This is only valid when key "
|
||||
"is 8 bytes");
|
||||
@@ -2941,6 +2943,8 @@ void VerifyDBFromDB(std::string& truth_db_name) {
|
||||
FLAGS_options_file.c_str(), s.ToString().c_str());
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
(void)opts;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -3315,6 +3319,10 @@ void VerifyDBFromDB(std::string& truth_db_name) {
|
||||
FLAGS_env->LowerThreadPoolIOPriority(Env::LOW);
|
||||
FLAGS_env->LowerThreadPoolIOPriority(Env::HIGH);
|
||||
}
|
||||
if (FLAGS_enable_cpu_prio) {
|
||||
FLAGS_env->LowerThreadPoolCPUPriority(Env::LOW);
|
||||
FLAGS_env->LowerThreadPoolCPUPriority(Env::HIGH);
|
||||
}
|
||||
options.env = FLAGS_env;
|
||||
|
||||
if (FLAGS_rate_limiter_bytes_per_sec > 0) {
|
||||
@@ -3996,6 +4004,9 @@ void VerifyDBFromDB(std::string& truth_db_name) {
|
||||
}
|
||||
return Status::OK();
|
||||
#else
|
||||
(void)thread;
|
||||
(void)compaction_style;
|
||||
(void)write_mode;
|
||||
fprintf(stderr, "Rocksdb Lite doesn't support filldeterministic\n");
|
||||
return Status::NotSupported(
|
||||
"Rocksdb Lite doesn't support filldeterministic");
|
||||
|
||||
+9
-6
@@ -1021,9 +1021,7 @@ class DbStressListener : public EventListener {
|
||||
: db_name_(db_name), db_paths_(db_paths) {}
|
||||
virtual ~DbStressListener() {}
|
||||
#ifndef ROCKSDB_LITE
|
||||
virtual void OnFlushCompleted(DB* db, const FlushJobInfo& info) override {
|
||||
assert(db);
|
||||
assert(db->GetName() == db_name_);
|
||||
virtual void OnFlushCompleted(DB* /*db*/, const FlushJobInfo& info) override {
|
||||
assert(IsValidColumnFamilyName(info.cf_name));
|
||||
VerifyFilePath(info.file_path);
|
||||
// pretending doing some work here
|
||||
@@ -1031,10 +1029,8 @@ class DbStressListener : public EventListener {
|
||||
std::chrono::microseconds(Random::GetTLSInstance()->Uniform(5000)));
|
||||
}
|
||||
|
||||
virtual void OnCompactionCompleted(DB* db,
|
||||
virtual void OnCompactionCompleted(DB* /*db*/,
|
||||
const CompactionJobInfo& ci) override {
|
||||
assert(db);
|
||||
assert(db->GetName() == db_name_);
|
||||
assert(IsValidColumnFamilyName(ci.cf_name));
|
||||
assert(ci.input_files.size() + ci.output_files.size() > 0U);
|
||||
for (const auto& file_path : ci.input_files) {
|
||||
@@ -1086,6 +1082,8 @@ class DbStressListener : public EventListener {
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
#else
|
||||
(void)file_dir;
|
||||
#endif // !NDEBUG
|
||||
}
|
||||
|
||||
@@ -1096,6 +1094,8 @@ class DbStressListener : public EventListener {
|
||||
bool result = ParseFileName(file_name, &file_number, &file_type);
|
||||
assert(result);
|
||||
assert(file_type == kTableFile);
|
||||
#else
|
||||
(void)file_name;
|
||||
#endif // !NDEBUG
|
||||
}
|
||||
|
||||
@@ -1110,6 +1110,8 @@ class DbStressListener : public EventListener {
|
||||
}
|
||||
VerifyFileName(file_path.substr(pos));
|
||||
}
|
||||
#else
|
||||
(void)file_path;
|
||||
#endif // !NDEBUG
|
||||
}
|
||||
#endif // !ROCKSDB_LITE
|
||||
@@ -2289,6 +2291,7 @@ class StressTest {
|
||||
size_t value_sz =
|
||||
((rand % kRandomValueMaxFactor) + 1) * FLAGS_value_size_mult;
|
||||
assert(value_sz <= max_sz && value_sz >= sizeof(uint32_t));
|
||||
(void) max_sz;
|
||||
*((uint32_t*)v) = rand;
|
||||
for (size_t i=sizeof(uint32_t); i < value_sz; i++) {
|
||||
v[i] = (char)(rand ^ i);
|
||||
|
||||
@@ -54,7 +54,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED as LDBCommand is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED as LDBCommand is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED as SSTDumpTool is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -520,7 +520,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr,
|
||||
"SKIPPED as AutoRollLogger is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
|
||||
@@ -27,6 +27,9 @@ template <class T>
|
||||
void AssertAutoVectorOnlyInStack(autovector<T, kSize>* vec, bool result) {
|
||||
#ifndef ROCKSDB_LITE
|
||||
ASSERT_EQ(vec->only_in_stack(), result);
|
||||
#else
|
||||
(void) vec;
|
||||
(void) result;
|
||||
#endif // !ROCKSDB_LITE
|
||||
}
|
||||
} // namespace
|
||||
|
||||
+25
-5
@@ -246,9 +246,15 @@ inline bool Zlib_Compress(const CompressionOptions& opts,
|
||||
// memLevel=9 uses maximum memory for optimal speed.
|
||||
// The default value is 8. See zconf.h for more details.
|
||||
static const int memLevel = 8;
|
||||
int level;
|
||||
if (opts.level == CompressionOptions::kDefaultCompressionLevel) {
|
||||
level = Z_DEFAULT_COMPRESSION;
|
||||
} else {
|
||||
level = opts.level;
|
||||
}
|
||||
z_stream _stream;
|
||||
memset(&_stream, 0, sizeof(z_stream));
|
||||
int st = deflateInit2(&_stream, opts.level, Z_DEFLATED, opts.window_bits,
|
||||
int st = deflateInit2(&_stream, level, Z_DEFLATED, opts.window_bits,
|
||||
memLevel, opts.strategy);
|
||||
if (st != Z_OK) {
|
||||
return false;
|
||||
@@ -682,9 +688,15 @@ inline bool LZ4HC_Compress(const CompressionOptions& opts,
|
||||
output->resize(static_cast<size_t>(output_header_len + compress_bound));
|
||||
|
||||
int outlen;
|
||||
int level;
|
||||
if (opts.level == CompressionOptions::kDefaultCompressionLevel) {
|
||||
level = 0; // lz4hc.h says any value < 1 will be sanitized to default
|
||||
} else {
|
||||
level = opts.level;
|
||||
}
|
||||
#if LZ4_VERSION_NUMBER >= 10400 // r124+
|
||||
LZ4_streamHC_t* stream = LZ4_createStreamHC();
|
||||
LZ4_resetStreamHC(stream, opts.level);
|
||||
LZ4_resetStreamHC(stream, level);
|
||||
const char* compression_dict_data =
|
||||
compression_dict.size() > 0 ? compression_dict.data() : nullptr;
|
||||
size_t compression_dict_size = compression_dict.size();
|
||||
@@ -705,7 +717,7 @@ inline bool LZ4HC_Compress(const CompressionOptions& opts,
|
||||
#elif LZ4_VERSION_MAJOR // r113-r123
|
||||
outlen = LZ4_compressHC2_limitedOutput(input, &(*output)[output_header_len],
|
||||
static_cast<int>(length),
|
||||
compress_bound, opts.level);
|
||||
compress_bound, level);
|
||||
#else // up to r112
|
||||
outlen =
|
||||
LZ4_compressHC_limitedOutput(input, &(*output)[output_header_len],
|
||||
@@ -766,15 +778,23 @@ inline bool ZSTD_Compress(const CompressionOptions& opts, const char* input,
|
||||
size_t compressBound = ZSTD_compressBound(length);
|
||||
output->resize(static_cast<size_t>(output_header_len + compressBound));
|
||||
size_t outlen;
|
||||
int level;
|
||||
if (opts.level == CompressionOptions::kDefaultCompressionLevel) {
|
||||
// 3 is the value of ZSTD_CLEVEL_DEFAULT (not exposed publicly), see
|
||||
// https://github.com/facebook/zstd/issues/1148
|
||||
level = 3;
|
||||
} else {
|
||||
level = opts.level;
|
||||
}
|
||||
#if ZSTD_VERSION_NUMBER >= 500 // v0.5.0+
|
||||
ZSTD_CCtx* context = ZSTD_createCCtx();
|
||||
outlen = ZSTD_compress_usingDict(
|
||||
context, &(*output)[output_header_len], compressBound, input, length,
|
||||
compression_dict.data(), compression_dict.size(), opts.level);
|
||||
compression_dict.data(), compression_dict.size(), level);
|
||||
ZSTD_freeCCtx(context);
|
||||
#else // up to v0.4.x
|
||||
outlen = ZSTD_compress(&(*output)[output_header_len], compressBound, input,
|
||||
length, opts.level);
|
||||
length, level);
|
||||
#endif // ZSTD_VERSION_NUMBER >= 500
|
||||
if (outlen == 0) {
|
||||
return false;
|
||||
|
||||
@@ -613,7 +613,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
#else
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
printf("DeleteScheduler is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#ifdef OS_LINUX
|
||||
# include <sys/syscall.h>
|
||||
# include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
@@ -53,6 +54,8 @@ struct ThreadPoolImpl::Impl {
|
||||
|
||||
void LowerIOPriority();
|
||||
|
||||
void LowerCPUPriority();
|
||||
|
||||
void WakeUpAllThreads() {
|
||||
bgsignal_.notify_all();
|
||||
}
|
||||
@@ -97,6 +100,7 @@ private:
|
||||
static void* BGThreadWrapper(void* arg);
|
||||
|
||||
bool low_io_priority_;
|
||||
bool low_cpu_priority_;
|
||||
Env::Priority priority_;
|
||||
Env* env_;
|
||||
|
||||
@@ -125,6 +129,7 @@ inline
|
||||
ThreadPoolImpl::Impl::Impl()
|
||||
:
|
||||
low_io_priority_(false),
|
||||
low_cpu_priority_(false),
|
||||
priority_(Env::LOW),
|
||||
env_(nullptr),
|
||||
total_threads_limit_(0),
|
||||
@@ -171,9 +176,16 @@ void ThreadPoolImpl::Impl::LowerIOPriority() {
|
||||
low_io_priority_ = true;
|
||||
}
|
||||
|
||||
inline
|
||||
void ThreadPoolImpl::Impl::LowerCPUPriority() {
|
||||
std::lock_guard<std::mutex> lock(mu_);
|
||||
low_cpu_priority_ = true;
|
||||
}
|
||||
|
||||
void ThreadPoolImpl::Impl::BGThread(size_t thread_id) {
|
||||
bool low_io_priority = false;
|
||||
bool low_cpu_priority = false;
|
||||
|
||||
while (true) {
|
||||
// Wait until there is an item that is ready to run
|
||||
std::unique_lock<std::mutex> lock(mu_);
|
||||
@@ -213,9 +225,20 @@ void ThreadPoolImpl::Impl::BGThread(size_t thread_id) {
|
||||
std::memory_order_relaxed);
|
||||
|
||||
bool decrease_io_priority = (low_io_priority != low_io_priority_);
|
||||
bool decrease_cpu_priority = (low_cpu_priority != low_cpu_priority_);
|
||||
lock.unlock();
|
||||
|
||||
#ifdef OS_LINUX
|
||||
if (decrease_cpu_priority) {
|
||||
setpriority(
|
||||
PRIO_PROCESS,
|
||||
// Current thread.
|
||||
0,
|
||||
// Lowest priority possible.
|
||||
19);
|
||||
low_cpu_priority = true;
|
||||
}
|
||||
|
||||
if (decrease_io_priority) {
|
||||
#define IOPRIO_CLASS_SHIFT (13)
|
||||
#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)
|
||||
@@ -236,6 +259,7 @@ void ThreadPoolImpl::Impl::BGThread(size_t thread_id) {
|
||||
}
|
||||
#else
|
||||
(void)decrease_io_priority; // avoid 'unused variable' error
|
||||
(void)decrease_cpu_priority;
|
||||
#endif
|
||||
func();
|
||||
}
|
||||
@@ -421,6 +445,10 @@ void ThreadPoolImpl::LowerIOPriority() {
|
||||
impl_->LowerIOPriority();
|
||||
}
|
||||
|
||||
void ThreadPoolImpl::LowerCPUPriority() {
|
||||
impl_->LowerCPUPriority();
|
||||
}
|
||||
|
||||
void ThreadPoolImpl::IncBackgroundThreadsIfNeeded(int num) {
|
||||
impl_->SetBackgroundThreadsInternal(num, false);
|
||||
}
|
||||
|
||||
@@ -46,10 +46,14 @@ class ThreadPoolImpl : public ThreadPool {
|
||||
// start yet
|
||||
void WaitForJobsAndJoinAllThreads() override;
|
||||
|
||||
// Make threads to run at a lower kernel priority
|
||||
// Make threads to run at a lower kernel IO priority
|
||||
// Currently only has effect on Linux
|
||||
void LowerIOPriority();
|
||||
|
||||
// Make threads to run at a lower kernel CPU priority
|
||||
// Currently only has effect on Linux
|
||||
void LowerCPUPriority();
|
||||
|
||||
// Ensure there is at aleast num threads in the pool
|
||||
// but do not kill threads if there are more
|
||||
void IncBackgroundThreadsIfNeeded(int num);
|
||||
|
||||
@@ -747,6 +747,19 @@ Status BackupEngineImpl::CreateNewBackupWithMetadata(
|
||||
BackupID new_backup_id = latest_backup_id_ + 1;
|
||||
|
||||
assert(backups_.find(new_backup_id) == backups_.end());
|
||||
|
||||
auto private_dir = GetAbsolutePath(GetPrivateFileRel(new_backup_id));
|
||||
Status s = backup_env_->FileExists(private_dir);
|
||||
if (s.ok()) {
|
||||
// maybe last backup failed and left partial state behind, clean it up.
|
||||
// need to do this before updating backups_ such that a private dir
|
||||
// named after new_backup_id will be cleaned up
|
||||
s = GarbageCollect();
|
||||
} else if (s.IsNotFound()) {
|
||||
// normal case, the new backup's private dir doesn't exist yet
|
||||
s = Status::OK();
|
||||
}
|
||||
|
||||
auto ret = backups_.insert(std::make_pair(
|
||||
new_backup_id, unique_ptr<BackupMeta>(new BackupMeta(
|
||||
GetBackupMetaFile(new_backup_id, false /* tmp */),
|
||||
@@ -757,23 +770,13 @@ Status BackupEngineImpl::CreateNewBackupWithMetadata(
|
||||
new_backup->RecordTimestamp();
|
||||
new_backup->SetAppMetadata(app_metadata);
|
||||
|
||||
auto start_backup = backup_env_-> NowMicros();
|
||||
auto start_backup = backup_env_->NowMicros();
|
||||
|
||||
ROCKS_LOG_INFO(options_.info_log,
|
||||
"Started the backup process -- creating backup %u",
|
||||
new_backup_id);
|
||||
|
||||
auto private_tmp_dir = GetAbsolutePath(GetPrivateFileRel(new_backup_id, true));
|
||||
Status s = backup_env_->FileExists(private_tmp_dir);
|
||||
if (s.ok()) {
|
||||
// maybe last backup failed and left partial state behind, clean it up
|
||||
s = GarbageCollect();
|
||||
} else if (s.IsNotFound()) {
|
||||
// normal case, the new backup's private dir doesn't exist yet
|
||||
s = Status::OK();
|
||||
}
|
||||
if (s.ok()) {
|
||||
s = backup_env_->CreateDir(private_tmp_dir);
|
||||
s = backup_env_->CreateDir(private_dir);
|
||||
}
|
||||
|
||||
RateLimiter* rate_limiter = options_.backup_rate_limiter.get();
|
||||
@@ -859,18 +862,6 @@ Status BackupEngineImpl::CreateNewBackupWithMetadata(
|
||||
// we copied all the files, enable file deletions
|
||||
db->EnableFileDeletions(false);
|
||||
|
||||
if (s.ok()) {
|
||||
// move tmp private backup to real backup folder
|
||||
ROCKS_LOG_INFO(
|
||||
options_.info_log,
|
||||
"Moving tmp backup directory to the real one: %s -> %s\n",
|
||||
GetAbsolutePath(GetPrivateFileRel(new_backup_id, true)).c_str(),
|
||||
GetAbsolutePath(GetPrivateFileRel(new_backup_id, false)).c_str());
|
||||
s = backup_env_->RenameFile(
|
||||
GetAbsolutePath(GetPrivateFileRel(new_backup_id, true)), // tmp
|
||||
GetAbsolutePath(GetPrivateFileRel(new_backup_id, false)));
|
||||
}
|
||||
|
||||
auto backup_time = backup_env_->NowMicros() - start_backup;
|
||||
|
||||
if (s.ok()) {
|
||||
@@ -1307,22 +1298,33 @@ Status BackupEngineImpl::AddBackupFileWorkItem(
|
||||
dst_relative_tmp = GetSharedFileRel(dst_relative, true);
|
||||
dst_relative = GetSharedFileRel(dst_relative, false);
|
||||
} else {
|
||||
dst_relative_tmp = GetPrivateFileRel(backup_id, true, dst_relative);
|
||||
dst_relative = GetPrivateFileRel(backup_id, false, dst_relative);
|
||||
}
|
||||
std::string dst_path = GetAbsolutePath(dst_relative);
|
||||
std::string dst_path_tmp = GetAbsolutePath(dst_relative_tmp);
|
||||
|
||||
// We copy into `temp_dest_path` and, once finished, rename it to
|
||||
// `final_dest_path`. This allows files to atomically appear at
|
||||
// `final_dest_path`. We can copy directly to the final path when atomicity
|
||||
// is unnecessary, like for files in private backup directories.
|
||||
const std::string* copy_dest_path;
|
||||
std::string temp_dest_path;
|
||||
std::string final_dest_path = GetAbsolutePath(dst_relative);
|
||||
if (!dst_relative_tmp.empty()) {
|
||||
temp_dest_path = GetAbsolutePath(dst_relative_tmp);
|
||||
copy_dest_path = &temp_dest_path;
|
||||
} else {
|
||||
copy_dest_path = &final_dest_path;
|
||||
}
|
||||
|
||||
// if it's shared, we also need to check if it exists -- if it does, no need
|
||||
// to copy it again.
|
||||
bool need_to_copy = true;
|
||||
// true if dst_path is the same path as another live file
|
||||
// true if final_dest_path is the same path as another live file
|
||||
const bool same_path =
|
||||
live_dst_paths.find(dst_path) != live_dst_paths.end();
|
||||
live_dst_paths.find(final_dest_path) != live_dst_paths.end();
|
||||
|
||||
bool file_exists = false;
|
||||
if (shared && !same_path) {
|
||||
Status exist = backup_env_->FileExists(dst_path);
|
||||
Status exist = backup_env_->FileExists(final_dest_path);
|
||||
if (exist.ok()) {
|
||||
file_exists = true;
|
||||
} else if (exist.IsNotFound()) {
|
||||
@@ -1351,7 +1353,7 @@ Status BackupEngineImpl::AddBackupFileWorkItem(
|
||||
"overwrite the file.",
|
||||
fname.c_str());
|
||||
need_to_copy = true;
|
||||
backup_env_->DeleteFile(dst_path);
|
||||
backup_env_->DeleteFile(final_dest_path);
|
||||
} else {
|
||||
// the file is present and referenced by a backup
|
||||
ROCKS_LOG_INFO(options_.info_log,
|
||||
@@ -1360,25 +1362,25 @@ Status BackupEngineImpl::AddBackupFileWorkItem(
|
||||
&checksum_value);
|
||||
}
|
||||
}
|
||||
live_dst_paths.insert(dst_path);
|
||||
live_dst_paths.insert(final_dest_path);
|
||||
|
||||
if (!contents.empty() || need_to_copy) {
|
||||
ROCKS_LOG_INFO(options_.info_log, "Copying %s to %s", fname.c_str(),
|
||||
dst_path_tmp.c_str());
|
||||
copy_dest_path->c_str());
|
||||
CopyOrCreateWorkItem copy_or_create_work_item(
|
||||
src_dir.empty() ? "" : src_dir + fname, dst_path_tmp, contents, db_env_,
|
||||
backup_env_, options_.sync, rate_limiter, size_limit,
|
||||
src_dir.empty() ? "" : src_dir + fname, *copy_dest_path, contents,
|
||||
db_env_, backup_env_, options_.sync, rate_limiter, size_limit,
|
||||
progress_callback);
|
||||
BackupAfterCopyOrCreateWorkItem after_copy_or_create_work_item(
|
||||
copy_or_create_work_item.result.get_future(), shared, need_to_copy,
|
||||
backup_env_, dst_path_tmp, dst_path, dst_relative);
|
||||
backup_env_, temp_dest_path, final_dest_path, dst_relative);
|
||||
files_to_copy_or_create_.write(std::move(copy_or_create_work_item));
|
||||
backup_items_to_finish.push_back(std::move(after_copy_or_create_work_item));
|
||||
} else {
|
||||
std::promise<CopyOrCreateResult> promise_result;
|
||||
BackupAfterCopyOrCreateWorkItem after_copy_or_create_work_item(
|
||||
promise_result.get_future(), shared, need_to_copy, backup_env_,
|
||||
dst_path_tmp, dst_path, dst_relative);
|
||||
temp_dest_path, final_dest_path, dst_relative);
|
||||
backup_items_to_finish.push_back(std::move(after_copy_or_create_work_item));
|
||||
CopyOrCreateResult result;
|
||||
result.status = s;
|
||||
@@ -1533,7 +1535,7 @@ Status BackupEngineImpl::GarbageCollect() {
|
||||
}
|
||||
// here we have to delete the dir and all its children
|
||||
std::string full_private_path =
|
||||
GetAbsolutePath(GetPrivateFileRel(backup_id, tmp_dir));
|
||||
GetAbsolutePath(GetPrivateFileRel(backup_id));
|
||||
std::vector<std::string> subchildren;
|
||||
backup_env_->GetChildren(full_private_path, &subchildren);
|
||||
for (auto& subchild : subchildren) {
|
||||
|
||||
@@ -811,9 +811,8 @@ TEST_F(BackupableDBTest, NoDoubleCopy) {
|
||||
test_db_env_->SetFilenamesForMockedAttrs(dummy_db_->live_files_);
|
||||
ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), false));
|
||||
std::vector<std::string> should_have_written = {
|
||||
"/shared/.00010.sst.tmp", "/shared/.00011.sst.tmp",
|
||||
"/private/1.tmp/CURRENT", "/private/1.tmp/MANIFEST-01",
|
||||
"/private/1.tmp/00011.log", "/meta/.1.tmp"};
|
||||
"/shared/.00010.sst.tmp", "/shared/.00011.sst.tmp", "/private/1/CURRENT",
|
||||
"/private/1/MANIFEST-01", "/private/1/00011.log", "/meta/.1.tmp"};
|
||||
AppendPath(backupdir_, should_have_written);
|
||||
test_backup_env_->AssertWrittenFiles(should_have_written);
|
||||
|
||||
@@ -829,9 +828,9 @@ TEST_F(BackupableDBTest, NoDoubleCopy) {
|
||||
ASSERT_OK(backup_engine_->CreateNewBackup(db_.get(), false));
|
||||
// should not open 00010.sst - it's already there
|
||||
|
||||
should_have_written = {"/shared/.00015.sst.tmp", "/private/2.tmp/CURRENT",
|
||||
"/private/2.tmp/MANIFEST-01",
|
||||
"/private/2.tmp/00011.log", "/meta/.2.tmp"};
|
||||
should_have_written = {"/shared/.00015.sst.tmp", "/private/2/CURRENT",
|
||||
"/private/2/MANIFEST-01", "/private/2/00011.log",
|
||||
"/meta/.2.tmp"};
|
||||
AppendPath(backupdir_, should_have_written);
|
||||
test_backup_env_->AssertWrittenFiles(should_have_written);
|
||||
|
||||
@@ -976,7 +975,7 @@ TEST_F(BackupableDBTest, InterruptCreationTest) {
|
||||
backup_engine_->CreateNewBackup(db_.get(), !!(rnd.Next() % 2)).ok());
|
||||
CloseDBAndBackupEngine();
|
||||
// should also fail cleanup so the tmp directory stays behind
|
||||
ASSERT_OK(backup_chroot_env_->FileExists(backupdir_ + "/private/1.tmp/"));
|
||||
ASSERT_OK(backup_chroot_env_->FileExists(backupdir_ + "/private/1/"));
|
||||
|
||||
OpenDBAndBackupEngine(false /* destroy_old_data */);
|
||||
test_backup_env_->SetLimitWrittenFiles(1000000);
|
||||
@@ -1171,7 +1170,7 @@ TEST_F(BackupableDBTest, DeleteTmpFiles) {
|
||||
shared_tmp += "/shared";
|
||||
}
|
||||
shared_tmp += "/.00006.sst.tmp";
|
||||
std::string private_tmp_dir = backupdir_ + "/private/10.tmp";
|
||||
std::string private_tmp_dir = backupdir_ + "/private/10";
|
||||
std::string private_tmp_file = private_tmp_dir + "/00003.sst";
|
||||
file_manager_->WriteToFile(shared_tmp, "tmp");
|
||||
file_manager_->CreateDir(private_tmp_dir);
|
||||
@@ -1589,7 +1588,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED as BackupableDB is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1524,7 +1524,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED as BlobDB is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -584,7 +584,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED as Checkpoint is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ int main() {
|
||||
}
|
||||
#endif // GFLAGS
|
||||
#else
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "Not supported in lite mode.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -460,7 +460,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED as DateTieredDB is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED as DocumentDB is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -333,7 +333,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED as JSONDocument is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ int main(int argc, char** argv) {
|
||||
#else // ROCKSDB_LITE
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED as TimedEnv is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -491,7 +491,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
#else
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
printf("Lua is not supported in RocksDBLite. Ignoring the test.\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -269,7 +269,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <cstdio>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
printf("Skipped in RocksDBLite as utilities are not supported.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ int main(int argc, char** argv) {
|
||||
#else // ROCKSDB_LITE
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED as EnvRegistry is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <cstdio>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
printf("Skipped in RocksDBLite as utilities are not supported.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -886,7 +886,7 @@ int main(int argc, char* argv[]) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED as redis is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED as SpatialDB is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "PASSED\n");
|
||||
}
|
||||
#else
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED as RocksDBLite does not include utilities.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1391,7 +1391,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"SKIPPED as optimistic_transaction is not supported in ROCKSDB_LITE\n");
|
||||
|
||||
@@ -5542,7 +5542,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr,
|
||||
"SKIPPED as Transactions are not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
|
||||
@@ -2003,7 +2003,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr,
|
||||
"SKIPPED as Transactions are not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
|
||||
@@ -655,7 +655,7 @@ int main(int argc, char** argv) {
|
||||
#else
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int /*argc*/, char** /*argv*/) {
|
||||
fprintf(stderr, "SKIPPED as DBWithTTL is not supported in ROCKSDB_LITE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user