mirror of
https://github.com/facebook/rocksdb.git
synced 2026-11-07 11:32:34 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d5e8110ff | ||
|
|
448d0096fe | ||
|
|
6da4b446be | ||
|
|
808e429bd6 | ||
|
|
8b99935452 | ||
|
|
492ab7c7d9 | ||
|
|
0d4fb0ef1e | ||
|
|
5b0481ef49 | ||
|
|
2f078d57e7 | ||
|
|
ac329cce6e | ||
|
|
3300ca0f39 | ||
|
|
aa3b8bb460 | ||
|
|
0493719649 | ||
|
|
7ad79400af | ||
|
|
257eb0a41c | ||
|
|
54c1984579 |
No files matched your search
+17
@@ -1,4 +1,21 @@
|
||||
# Rocksdb Change Log
|
||||
## 5.10.5 (03/16/2018)
|
||||
### Bug fixes
|
||||
* Fix WAL corruption caused by race condition between user write thread and backup/checkpoint thread.
|
||||
|
||||
## 5.10.4 (02/22/2018)
|
||||
### New Features
|
||||
* Follow rsync-style naming convention for BackupEngine tempfiles. This enables some optimizations when run on GlusterFS.
|
||||
* Fix regression of Java build break on Windows.
|
||||
|
||||
## 5.10.3 (02/21/2018)
|
||||
### Bug fixes
|
||||
* Fix build break regression using gcc-7
|
||||
* Direct I/O writable file should do fsync in Close()
|
||||
|
||||
### New Features
|
||||
* Add rocksdb.iterator.internal-key property
|
||||
|
||||
## 5.10.1 (01/18/2018)
|
||||
### Bug Fixes
|
||||
* Fix DB::Flush() keep waiting after flush finish under certain condition.
|
||||
|
||||
@@ -51,11 +51,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 #
|
||||
###########################################################
|
||||
|
||||
@@ -1388,23 +1388,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;
|
||||
@@ -1649,18 +1650,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;
|
||||
@@ -3104,20 +3093,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;
|
||||
@@ -3126,19 +3116,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;
|
||||
|
||||
+19
-13
@@ -344,12 +344,13 @@ void SuperVersionUnrefHandle(void* ptr) {
|
||||
// When latter happens, we are in ~ColumnFamilyData(), no get should happen as
|
||||
// well.
|
||||
SuperVersion* sv = static_cast<SuperVersion*>(ptr);
|
||||
if (sv->Unref()) {
|
||||
sv->db_mutex->Lock();
|
||||
sv->Cleanup();
|
||||
sv->db_mutex->Unlock();
|
||||
delete sv;
|
||||
}
|
||||
bool was_last_ref __attribute__((__unused__));
|
||||
was_last_ref = sv->Unref();
|
||||
// Thread-local SuperVersions can't outlive ColumnFamilyData::super_version_.
|
||||
// This is important because we can't do SuperVersion cleanup here.
|
||||
// That would require locking DB mutex, which would deadlock because
|
||||
// SuperVersionUnrefHandle is called with locked ThreadLocalPtr mutex.
|
||||
assert(!was_last_ref);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
@@ -966,6 +967,12 @@ void ColumnFamilyData::InstallSuperVersion(
|
||||
RecalculateWriteStallConditions(mutable_cf_options);
|
||||
|
||||
if (old_superversion != nullptr) {
|
||||
// Reset SuperVersions cached in thread local storage.
|
||||
// This should be done before old_superversion->Unref(). That's to ensure
|
||||
// that local_sv_ never holds the last reference to SuperVersion, since
|
||||
// it has no means to safely do SuperVersion cleanup.
|
||||
ResetThreadLocalSuperVersions();
|
||||
|
||||
if (old_superversion->mutable_cf_options.write_buffer_size !=
|
||||
mutable_cf_options.write_buffer_size) {
|
||||
mem_->UpdateWriteBufferSize(mutable_cf_options.write_buffer_size);
|
||||
@@ -981,9 +988,6 @@ void ColumnFamilyData::InstallSuperVersion(
|
||||
sv_context->superversions_to_free.push_back(old_superversion);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset SuperVersions cached in thread local storage
|
||||
ResetThreadLocalSuperVersions();
|
||||
}
|
||||
|
||||
void ColumnFamilyData::ResetThreadLocalSuperVersions() {
|
||||
@@ -995,10 +999,12 @@ void ColumnFamilyData::ResetThreadLocalSuperVersions() {
|
||||
continue;
|
||||
}
|
||||
auto sv = static_cast<SuperVersion*>(ptr);
|
||||
if (sv->Unref()) {
|
||||
sv->Cleanup();
|
||||
delete sv;
|
||||
}
|
||||
bool was_last_ref __attribute__((__unused__));
|
||||
was_last_ref = sv->Unref();
|
||||
// sv couldn't have been the last reference because
|
||||
// ResetThreadLocalSuperVersions() is called before
|
||||
// unref'ing super_version_.
|
||||
assert(!was_last_ref);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -217,6 +217,9 @@ class DBIter final: public Iterator {
|
||||
*prop = "Iterator is not valid.";
|
||||
}
|
||||
return Status::OK();
|
||||
} else if (prop_name == "rocksdb.iterator.internal-key") {
|
||||
*prop = saved_key_.GetUserKey().ToString();
|
||||
return Status::OK();
|
||||
}
|
||||
return Status::InvalidArgument("Undentified property.");
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ TEST_F(DBIteratorTest, IteratorProperty) {
|
||||
Options options = CurrentOptions();
|
||||
CreateAndReopenWithCF({"pikachu"}, options);
|
||||
Put(1, "1", "2");
|
||||
Delete(1, "2");
|
||||
ReadOptions ropt;
|
||||
ropt.pin_data = false;
|
||||
{
|
||||
@@ -64,9 +65,15 @@ TEST_F(DBIteratorTest, IteratorProperty) {
|
||||
ASSERT_NOK(iter->GetProperty("non_existing.value", &prop_value));
|
||||
ASSERT_OK(iter->GetProperty("rocksdb.iterator.is-key-pinned", &prop_value));
|
||||
ASSERT_EQ("0", prop_value);
|
||||
ASSERT_OK(iter->GetProperty("rocksdb.iterator.internal-key", &prop_value));
|
||||
ASSERT_EQ("1", prop_value);
|
||||
iter->Next();
|
||||
ASSERT_OK(iter->GetProperty("rocksdb.iterator.is-key-pinned", &prop_value));
|
||||
ASSERT_EQ("Iterator is not valid.", prop_value);
|
||||
|
||||
// Get internal key at which the iteration stopped (tombstone in this case).
|
||||
ASSERT_OK(iter->GetProperty("rocksdb.iterator.internal-key", &prop_value));
|
||||
ASSERT_EQ("2", prop_value);
|
||||
}
|
||||
Close();
|
||||
}
|
||||
@@ -2157,6 +2164,48 @@ TEST_F(DBIteratorTest, SkipStatistics) {
|
||||
ASSERT_EQ(skip_count, TestGetTickerCount(options, NUMBER_ITER_SKIP));
|
||||
}
|
||||
|
||||
TEST_F(DBIteratorTest, SeekAfterHittingManyInternalKeys) {
|
||||
Options options = CurrentOptions();
|
||||
DestroyAndReopen(options);
|
||||
ReadOptions ropts;
|
||||
ropts.max_skippable_internal_keys = 2;
|
||||
|
||||
Put("1", "val_1");
|
||||
// Add more tombstones than max_skippable_internal_keys so that Next() fails.
|
||||
Delete("2");
|
||||
Delete("3");
|
||||
Delete("4");
|
||||
Delete("5");
|
||||
Put("6", "val_6");
|
||||
|
||||
unique_ptr<Iterator> iter(db_->NewIterator(ropts));
|
||||
iter->SeekToFirst();
|
||||
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(iter->key().ToString(), "1");
|
||||
ASSERT_EQ(iter->value().ToString(), "val_1");
|
||||
|
||||
// This should fail as incomplete due to too many non-visible internal keys on
|
||||
// the way to the next valid user key.
|
||||
iter->Next();
|
||||
ASSERT_TRUE(!iter->Valid());
|
||||
ASSERT_TRUE(iter->status().IsIncomplete());
|
||||
|
||||
// Get the internal key at which Next() failed.
|
||||
std::string prop_value;
|
||||
ASSERT_OK(iter->GetProperty("rocksdb.iterator.internal-key", &prop_value));
|
||||
ASSERT_EQ("4", prop_value);
|
||||
|
||||
// Create a new iterator to seek to the internal key.
|
||||
unique_ptr<Iterator> iter2(db_->NewIterator(ropts));
|
||||
iter2->Seek(prop_value);
|
||||
ASSERT_TRUE(iter2->Valid());
|
||||
ASSERT_OK(iter2->status());
|
||||
|
||||
ASSERT_EQ(iter2->key().ToString(), "6");
|
||||
ASSERT_EQ(iter2->value().ToString(), "val_6");
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
@@ -5651,6 +5651,50 @@ TEST_F(DBTest, PauseBackgroundWorkTest) {
|
||||
// now it's done
|
||||
ASSERT_TRUE(done.load());
|
||||
}
|
||||
|
||||
// Keep spawning short-living threads that create an iterator and quit.
|
||||
// Meanwhile in another thread keep flushing memtables.
|
||||
// This used to cause a deadlock.
|
||||
TEST_F(DBTest, ThreadLocalPtrDeadlock) {
|
||||
std::atomic<int> flushes_done{0};
|
||||
std::atomic<int> threads_destroyed{0};
|
||||
auto done = [&] {
|
||||
return flushes_done.load() > 10;
|
||||
};
|
||||
|
||||
std::thread flushing_thread([&] {
|
||||
for (int i = 0; !done(); ++i) {
|
||||
ASSERT_OK(db_->Put(WriteOptions(), Slice("hi"),
|
||||
Slice(std::to_string(i).c_str())));
|
||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||
int cnt = ++flushes_done;
|
||||
fprintf(stderr, "Flushed %d times\n", cnt);
|
||||
}
|
||||
});
|
||||
|
||||
std::vector<std::thread> thread_spawning_threads(10);
|
||||
for (auto& t: thread_spawning_threads) {
|
||||
t = std::thread([&] {
|
||||
while (!done()) {
|
||||
{
|
||||
std::thread tmp_thread([&] {
|
||||
auto it = db_->NewIterator(ReadOptions());
|
||||
delete it;
|
||||
});
|
||||
tmp_thread.join();
|
||||
}
|
||||
++threads_destroyed;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (auto& t: thread_spawning_threads) {
|
||||
t.join();
|
||||
}
|
||||
flushing_thread.join();
|
||||
fprintf(stderr, "Done. Flushed %d times, destroyed %d threads\n",
|
||||
flushes_done.load(), threads_destroyed.load());
|
||||
}
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
@@ -97,6 +97,9 @@ class Iterator : public Cleanable {
|
||||
// Property "rocksdb.iterator.super-version-number":
|
||||
// LSM version used by the iterator. The same format as DB Property
|
||||
// kCurrentSuperVersionNumber. See its comment for more information.
|
||||
// Property "rocksdb.iterator.internal-key":
|
||||
// Get the user-key portion of the internal key at which the iteration
|
||||
// stopped.
|
||||
virtual Status GetProperty(std::string prop_name, std::string* prop);
|
||||
|
||||
private:
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#define ROCKSDB_MAJOR 5
|
||||
#define ROCKSDB_MINOR 10
|
||||
#define ROCKSDB_PATCH 2
|
||||
#define ROCKSDB_PATCH 5
|
||||
|
||||
// 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
|
||||
|
||||
@@ -7,6 +7,8 @@ set(JNI_NATIVE_SOURCES
|
||||
rocksjni/clock_cache.cc
|
||||
rocksjni/columnfamilyhandle.cc
|
||||
rocksjni/compaction_filter.cc
|
||||
rocksjni/compaction_filter_factory.cc
|
||||
rocksjni/compaction_filter_factory_jnicallback.cc
|
||||
rocksjni/compaction_options_fifo.cc
|
||||
rocksjni/compaction_options_universal.cc
|
||||
rocksjni/comparator.cc
|
||||
@@ -17,6 +19,7 @@ set(JNI_NATIVE_SOURCES
|
||||
rocksjni/filter.cc
|
||||
rocksjni/ingest_external_file_options.cc
|
||||
rocksjni/iterator.cc
|
||||
rocksjni/jnicallback.cc
|
||||
rocksjni/loggerjnicallback.cc
|
||||
rocksjni/lru_cache.cc
|
||||
rocksjni/memtablejni.cc
|
||||
@@ -25,6 +28,7 @@ set(JNI_NATIVE_SOURCES
|
||||
rocksjni/options_util.cc
|
||||
rocksjni/ratelimiterjni.cc
|
||||
rocksjni/remove_emptyvalue_compactionfilterjni.cc
|
||||
rocksjni/rocks_callback_object.cc
|
||||
rocksjni/cassandra_compactionfilterjni.cc
|
||||
rocksjni/cassandra_value_operator.cc
|
||||
rocksjni/restorejni.cc
|
||||
|
||||
@@ -279,7 +279,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
|
||||
@@ -299,30 +299,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.
|
||||
|
||||
+155
@@ -688,259 +688,386 @@ uint32_t crc32c_3way(uint32_t crc, const char* buf, size_t len) {
|
||||
do {
|
||||
// jumps here for a full block of len 128
|
||||
CRCtriplet(crc, next, -128);
|
||||
// FALLTHRU
|
||||
case 127:
|
||||
// jumps here or below for the first block smaller
|
||||
CRCtriplet(crc, next, -127);
|
||||
// FALLTHRU
|
||||
case 126:
|
||||
CRCtriplet(crc, next, -126); // than 128
|
||||
// FALLTHRU
|
||||
case 125:
|
||||
CRCtriplet(crc, next, -125);
|
||||
// FALLTHRU
|
||||
case 124:
|
||||
CRCtriplet(crc, next, -124);
|
||||
// FALLTHRU
|
||||
case 123:
|
||||
CRCtriplet(crc, next, -123);
|
||||
// FALLTHRU
|
||||
case 122:
|
||||
CRCtriplet(crc, next, -122);
|
||||
// FALLTHRU
|
||||
case 121:
|
||||
CRCtriplet(crc, next, -121);
|
||||
// FALLTHRU
|
||||
case 120:
|
||||
CRCtriplet(crc, next, -120);
|
||||
// FALLTHRU
|
||||
case 119:
|
||||
CRCtriplet(crc, next, -119);
|
||||
// FALLTHRU
|
||||
case 118:
|
||||
CRCtriplet(crc, next, -118);
|
||||
// FALLTHRU
|
||||
case 117:
|
||||
CRCtriplet(crc, next, -117);
|
||||
// FALLTHRU
|
||||
case 116:
|
||||
CRCtriplet(crc, next, -116);
|
||||
// FALLTHRU
|
||||
case 115:
|
||||
CRCtriplet(crc, next, -115);
|
||||
// FALLTHRU
|
||||
case 114:
|
||||
CRCtriplet(crc, next, -114);
|
||||
// FALLTHRU
|
||||
case 113:
|
||||
CRCtriplet(crc, next, -113);
|
||||
// FALLTHRU
|
||||
case 112:
|
||||
CRCtriplet(crc, next, -112);
|
||||
// FALLTHRU
|
||||
case 111:
|
||||
CRCtriplet(crc, next, -111);
|
||||
// FALLTHRU
|
||||
case 110:
|
||||
CRCtriplet(crc, next, -110);
|
||||
// FALLTHRU
|
||||
case 109:
|
||||
CRCtriplet(crc, next, -109);
|
||||
// FALLTHRU
|
||||
case 108:
|
||||
CRCtriplet(crc, next, -108);
|
||||
// FALLTHRU
|
||||
case 107:
|
||||
CRCtriplet(crc, next, -107);
|
||||
// FALLTHRU
|
||||
case 106:
|
||||
CRCtriplet(crc, next, -106);
|
||||
// FALLTHRU
|
||||
case 105:
|
||||
CRCtriplet(crc, next, -105);
|
||||
// FALLTHRU
|
||||
case 104:
|
||||
CRCtriplet(crc, next, -104);
|
||||
// FALLTHRU
|
||||
case 103:
|
||||
CRCtriplet(crc, next, -103);
|
||||
// FALLTHRU
|
||||
case 102:
|
||||
CRCtriplet(crc, next, -102);
|
||||
// FALLTHRU
|
||||
case 101:
|
||||
CRCtriplet(crc, next, -101);
|
||||
// FALLTHRU
|
||||
case 100:
|
||||
CRCtriplet(crc, next, -100);
|
||||
// FALLTHRU
|
||||
case 99:
|
||||
CRCtriplet(crc, next, -99);
|
||||
// FALLTHRU
|
||||
case 98:
|
||||
CRCtriplet(crc, next, -98);
|
||||
// FALLTHRU
|
||||
case 97:
|
||||
CRCtriplet(crc, next, -97);
|
||||
// FALLTHRU
|
||||
case 96:
|
||||
CRCtriplet(crc, next, -96);
|
||||
// FALLTHRU
|
||||
case 95:
|
||||
CRCtriplet(crc, next, -95);
|
||||
// FALLTHRU
|
||||
case 94:
|
||||
CRCtriplet(crc, next, -94);
|
||||
// FALLTHRU
|
||||
case 93:
|
||||
CRCtriplet(crc, next, -93);
|
||||
// FALLTHRU
|
||||
case 92:
|
||||
CRCtriplet(crc, next, -92);
|
||||
// FALLTHRU
|
||||
case 91:
|
||||
CRCtriplet(crc, next, -91);
|
||||
// FALLTHRU
|
||||
case 90:
|
||||
CRCtriplet(crc, next, -90);
|
||||
// FALLTHRU
|
||||
case 89:
|
||||
CRCtriplet(crc, next, -89);
|
||||
// FALLTHRU
|
||||
case 88:
|
||||
CRCtriplet(crc, next, -88);
|
||||
// FALLTHRU
|
||||
case 87:
|
||||
CRCtriplet(crc, next, -87);
|
||||
// FALLTHRU
|
||||
case 86:
|
||||
CRCtriplet(crc, next, -86);
|
||||
// FALLTHRU
|
||||
case 85:
|
||||
CRCtriplet(crc, next, -85);
|
||||
// FALLTHRU
|
||||
case 84:
|
||||
CRCtriplet(crc, next, -84);
|
||||
// FALLTHRU
|
||||
case 83:
|
||||
CRCtriplet(crc, next, -83);
|
||||
// FALLTHRU
|
||||
case 82:
|
||||
CRCtriplet(crc, next, -82);
|
||||
// FALLTHRU
|
||||
case 81:
|
||||
CRCtriplet(crc, next, -81);
|
||||
// FALLTHRU
|
||||
case 80:
|
||||
CRCtriplet(crc, next, -80);
|
||||
// FALLTHRU
|
||||
case 79:
|
||||
CRCtriplet(crc, next, -79);
|
||||
// FALLTHRU
|
||||
case 78:
|
||||
CRCtriplet(crc, next, -78);
|
||||
// FALLTHRU
|
||||
case 77:
|
||||
CRCtriplet(crc, next, -77);
|
||||
// FALLTHRU
|
||||
case 76:
|
||||
CRCtriplet(crc, next, -76);
|
||||
// FALLTHRU
|
||||
case 75:
|
||||
CRCtriplet(crc, next, -75);
|
||||
// FALLTHRU
|
||||
case 74:
|
||||
CRCtriplet(crc, next, -74);
|
||||
// FALLTHRU
|
||||
case 73:
|
||||
CRCtriplet(crc, next, -73);
|
||||
// FALLTHRU
|
||||
case 72:
|
||||
CRCtriplet(crc, next, -72);
|
||||
// FALLTHRU
|
||||
case 71:
|
||||
CRCtriplet(crc, next, -71);
|
||||
// FALLTHRU
|
||||
case 70:
|
||||
CRCtriplet(crc, next, -70);
|
||||
// FALLTHRU
|
||||
case 69:
|
||||
CRCtriplet(crc, next, -69);
|
||||
// FALLTHRU
|
||||
case 68:
|
||||
CRCtriplet(crc, next, -68);
|
||||
// FALLTHRU
|
||||
case 67:
|
||||
CRCtriplet(crc, next, -67);
|
||||
// FALLTHRU
|
||||
case 66:
|
||||
CRCtriplet(crc, next, -66);
|
||||
// FALLTHRU
|
||||
case 65:
|
||||
CRCtriplet(crc, next, -65);
|
||||
// FALLTHRU
|
||||
case 64:
|
||||
CRCtriplet(crc, next, -64);
|
||||
// FALLTHRU
|
||||
case 63:
|
||||
CRCtriplet(crc, next, -63);
|
||||
// FALLTHRU
|
||||
case 62:
|
||||
CRCtriplet(crc, next, -62);
|
||||
// FALLTHRU
|
||||
case 61:
|
||||
CRCtriplet(crc, next, -61);
|
||||
// FALLTHRU
|
||||
case 60:
|
||||
CRCtriplet(crc, next, -60);
|
||||
// FALLTHRU
|
||||
case 59:
|
||||
CRCtriplet(crc, next, -59);
|
||||
// FALLTHRU
|
||||
case 58:
|
||||
CRCtriplet(crc, next, -58);
|
||||
// FALLTHRU
|
||||
case 57:
|
||||
CRCtriplet(crc, next, -57);
|
||||
// FALLTHRU
|
||||
case 56:
|
||||
CRCtriplet(crc, next, -56);
|
||||
// FALLTHRU
|
||||
case 55:
|
||||
CRCtriplet(crc, next, -55);
|
||||
// FALLTHRU
|
||||
case 54:
|
||||
CRCtriplet(crc, next, -54);
|
||||
// FALLTHRU
|
||||
case 53:
|
||||
CRCtriplet(crc, next, -53);
|
||||
// FALLTHRU
|
||||
case 52:
|
||||
CRCtriplet(crc, next, -52);
|
||||
// FALLTHRU
|
||||
case 51:
|
||||
CRCtriplet(crc, next, -51);
|
||||
// FALLTHRU
|
||||
case 50:
|
||||
CRCtriplet(crc, next, -50);
|
||||
// FALLTHRU
|
||||
case 49:
|
||||
CRCtriplet(crc, next, -49);
|
||||
// FALLTHRU
|
||||
case 48:
|
||||
CRCtriplet(crc, next, -48);
|
||||
// FALLTHRU
|
||||
case 47:
|
||||
CRCtriplet(crc, next, -47);
|
||||
// FALLTHRU
|
||||
case 46:
|
||||
CRCtriplet(crc, next, -46);
|
||||
// FALLTHRU
|
||||
case 45:
|
||||
CRCtriplet(crc, next, -45);
|
||||
// FALLTHRU
|
||||
case 44:
|
||||
CRCtriplet(crc, next, -44);
|
||||
// FALLTHRU
|
||||
case 43:
|
||||
CRCtriplet(crc, next, -43);
|
||||
// FALLTHRU
|
||||
case 42:
|
||||
CRCtriplet(crc, next, -42);
|
||||
// FALLTHRU
|
||||
case 41:
|
||||
CRCtriplet(crc, next, -41);
|
||||
// FALLTHRU
|
||||
case 40:
|
||||
CRCtriplet(crc, next, -40);
|
||||
// FALLTHRU
|
||||
case 39:
|
||||
CRCtriplet(crc, next, -39);
|
||||
// FALLTHRU
|
||||
case 38:
|
||||
CRCtriplet(crc, next, -38);
|
||||
// FALLTHRU
|
||||
case 37:
|
||||
CRCtriplet(crc, next, -37);
|
||||
// FALLTHRU
|
||||
case 36:
|
||||
CRCtriplet(crc, next, -36);
|
||||
// FALLTHRU
|
||||
case 35:
|
||||
CRCtriplet(crc, next, -35);
|
||||
// FALLTHRU
|
||||
case 34:
|
||||
CRCtriplet(crc, next, -34);
|
||||
// FALLTHRU
|
||||
case 33:
|
||||
CRCtriplet(crc, next, -33);
|
||||
// FALLTHRU
|
||||
case 32:
|
||||
CRCtriplet(crc, next, -32);
|
||||
// FALLTHRU
|
||||
case 31:
|
||||
CRCtriplet(crc, next, -31);
|
||||
// FALLTHRU
|
||||
case 30:
|
||||
CRCtriplet(crc, next, -30);
|
||||
// FALLTHRU
|
||||
case 29:
|
||||
CRCtriplet(crc, next, -29);
|
||||
// FALLTHRU
|
||||
case 28:
|
||||
CRCtriplet(crc, next, -28);
|
||||
// FALLTHRU
|
||||
case 27:
|
||||
CRCtriplet(crc, next, -27);
|
||||
// FALLTHRU
|
||||
case 26:
|
||||
CRCtriplet(crc, next, -26);
|
||||
// FALLTHRU
|
||||
case 25:
|
||||
CRCtriplet(crc, next, -25);
|
||||
// FALLTHRU
|
||||
case 24:
|
||||
CRCtriplet(crc, next, -24);
|
||||
// FALLTHRU
|
||||
case 23:
|
||||
CRCtriplet(crc, next, -23);
|
||||
// FALLTHRU
|
||||
case 22:
|
||||
CRCtriplet(crc, next, -22);
|
||||
// FALLTHRU
|
||||
case 21:
|
||||
CRCtriplet(crc, next, -21);
|
||||
// FALLTHRU
|
||||
case 20:
|
||||
CRCtriplet(crc, next, -20);
|
||||
// FALLTHRU
|
||||
case 19:
|
||||
CRCtriplet(crc, next, -19);
|
||||
// FALLTHRU
|
||||
case 18:
|
||||
CRCtriplet(crc, next, -18);
|
||||
// FALLTHRU
|
||||
case 17:
|
||||
CRCtriplet(crc, next, -17);
|
||||
// FALLTHRU
|
||||
case 16:
|
||||
CRCtriplet(crc, next, -16);
|
||||
// FALLTHRU
|
||||
case 15:
|
||||
CRCtriplet(crc, next, -15);
|
||||
// FALLTHRU
|
||||
case 14:
|
||||
CRCtriplet(crc, next, -14);
|
||||
// FALLTHRU
|
||||
case 13:
|
||||
CRCtriplet(crc, next, -13);
|
||||
// FALLTHRU
|
||||
case 12:
|
||||
CRCtriplet(crc, next, -12);
|
||||
// FALLTHRU
|
||||
case 11:
|
||||
CRCtriplet(crc, next, -11);
|
||||
// FALLTHRU
|
||||
case 10:
|
||||
CRCtriplet(crc, next, -10);
|
||||
// FALLTHRU
|
||||
case 9:
|
||||
CRCtriplet(crc, next, -9);
|
||||
// FALLTHRU
|
||||
case 8:
|
||||
CRCtriplet(crc, next, -8);
|
||||
// FALLTHRU
|
||||
case 7:
|
||||
CRCtriplet(crc, next, -7);
|
||||
// FALLTHRU
|
||||
case 6:
|
||||
CRCtriplet(crc, next, -6);
|
||||
// FALLTHRU
|
||||
case 5:
|
||||
CRCtriplet(crc, next, -5);
|
||||
// FALLTHRU
|
||||
case 4:
|
||||
CRCtriplet(crc, next, -4);
|
||||
// FALLTHRU
|
||||
case 3:
|
||||
CRCtriplet(crc, next, -3);
|
||||
// FALLTHRU
|
||||
case 2:
|
||||
CRCtriplet(crc, next, -2);
|
||||
// FALLTHRU
|
||||
case 1:
|
||||
CRCduplet(crc, next, -1); // the final triplet is actually only 2
|
||||
//{ CombineCRC(); }
|
||||
@@ -953,6 +1080,7 @@ uint32_t crc32c_3way(uint32_t crc, const char* buf, size_t len) {
|
||||
next1 = next0 + 128; // from here on all blocks are 128 long
|
||||
next2 = next1 + 128;
|
||||
}
|
||||
// FALLTHRU
|
||||
case 0:;
|
||||
} while (n > 0);
|
||||
}
|
||||
@@ -964,58 +1092,85 @@ uint32_t crc32c_3way(uint32_t crc, const char* buf, size_t len) {
|
||||
switch (count2) {
|
||||
case 27:
|
||||
CRCsinglet(crc0, next, -27 * 8);
|
||||
// FALLTHRU
|
||||
case 26:
|
||||
CRCsinglet(crc0, next, -26 * 8);
|
||||
// FALLTHRU
|
||||
case 25:
|
||||
CRCsinglet(crc0, next, -25 * 8);
|
||||
// FALLTHRU
|
||||
case 24:
|
||||
CRCsinglet(crc0, next, -24 * 8);
|
||||
// FALLTHRU
|
||||
case 23:
|
||||
CRCsinglet(crc0, next, -23 * 8);
|
||||
// FALLTHRU
|
||||
case 22:
|
||||
CRCsinglet(crc0, next, -22 * 8);
|
||||
// FALLTHRU
|
||||
case 21:
|
||||
CRCsinglet(crc0, next, -21 * 8);
|
||||
// FALLTHRU
|
||||
case 20:
|
||||
CRCsinglet(crc0, next, -20 * 8);
|
||||
// FALLTHRU
|
||||
case 19:
|
||||
CRCsinglet(crc0, next, -19 * 8);
|
||||
// FALLTHRU
|
||||
case 18:
|
||||
CRCsinglet(crc0, next, -18 * 8);
|
||||
// FALLTHRU
|
||||
case 17:
|
||||
CRCsinglet(crc0, next, -17 * 8);
|
||||
// FALLTHRU
|
||||
case 16:
|
||||
CRCsinglet(crc0, next, -16 * 8);
|
||||
// FALLTHRU
|
||||
case 15:
|
||||
CRCsinglet(crc0, next, -15 * 8);
|
||||
// FALLTHRU
|
||||
case 14:
|
||||
CRCsinglet(crc0, next, -14 * 8);
|
||||
// FALLTHRU
|
||||
case 13:
|
||||
CRCsinglet(crc0, next, -13 * 8);
|
||||
// FALLTHRU
|
||||
case 12:
|
||||
CRCsinglet(crc0, next, -12 * 8);
|
||||
// FALLTHRU
|
||||
case 11:
|
||||
CRCsinglet(crc0, next, -11 * 8);
|
||||
// FALLTHRU
|
||||
case 10:
|
||||
CRCsinglet(crc0, next, -10 * 8);
|
||||
// FALLTHRU
|
||||
case 9:
|
||||
CRCsinglet(crc0, next, -9 * 8);
|
||||
// FALLTHRU
|
||||
case 8:
|
||||
CRCsinglet(crc0, next, -8 * 8);
|
||||
// FALLTHRU
|
||||
case 7:
|
||||
CRCsinglet(crc0, next, -7 * 8);
|
||||
// FALLTHRU
|
||||
case 6:
|
||||
CRCsinglet(crc0, next, -6 * 8);
|
||||
// FALLTHRU
|
||||
case 5:
|
||||
CRCsinglet(crc0, next, -5 * 8);
|
||||
// FALLTHRU
|
||||
case 4:
|
||||
CRCsinglet(crc0, next, -4 * 8);
|
||||
// FALLTHRU
|
||||
case 3:
|
||||
CRCsinglet(crc0, next, -3 * 8);
|
||||
// FALLTHRU
|
||||
case 2:
|
||||
CRCsinglet(crc0, next, -2 * 8);
|
||||
// FALLTHRU
|
||||
case 1:
|
||||
CRCsinglet(crc0, next, -1 * 8);
|
||||
// FALLTHRU
|
||||
case 0:;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,6 +239,9 @@ Status WritableFileWriter::Close() {
|
||||
// we need to let the file know where data ends.
|
||||
if (use_direct_io()) {
|
||||
interim = writable_file_->Truncate(filesize_);
|
||||
if (interim.ok()) {
|
||||
interim = writable_file_->Fsync();
|
||||
}
|
||||
if (!interim.ok() && s.ok()) {
|
||||
s = interim;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,13 @@ namespace rocksdb {
|
||||
// pointer (if not NULL) when one of the following happens:
|
||||
// (1) a thread terminates
|
||||
// (2) a ThreadLocalPtr is destroyed
|
||||
//
|
||||
// Warning: this function is called while holding a global mutex. The same mutex
|
||||
// is used (at least in some cases) by most methods of ThreadLocalPtr, and it's
|
||||
// shared across all instances of ThreadLocalPtr. Thereforere extra care
|
||||
// is needed to avoid deadlocks. In particular, the handler shouldn't lock any
|
||||
// mutexes and shouldn't call any methods of any ThreadLocalPtr instances,
|
||||
// unless you know what you're doing.
|
||||
typedef void (*UnrefHandler)(void* ptr);
|
||||
|
||||
// ThreadLocalPtr stores only values of pointer type. Different from
|
||||
|
||||
@@ -77,8 +77,9 @@ Status RandomTransactionInserter::DBGet(
|
||||
uint64_t ikey, bool get_for_update, uint64_t* int_value,
|
||||
std::string* full_key, bool* unexpected_error) {
|
||||
Status s;
|
||||
// four digits and zero end char
|
||||
char prefix_buf[5];
|
||||
// Five digits (since the largest uint16_t is 65535) plus the NUL
|
||||
// end char.
|
||||
char prefix_buf[6];
|
||||
// Pad prefix appropriately so we can iterate over each set
|
||||
snprintf(prefix_buf, sizeof(prefix_buf), "%.4u", set_i + 1);
|
||||
// key format: [SET#][random#]
|
||||
@@ -261,8 +262,10 @@ Status RandomTransactionInserter::Verify(DB* db, uint16_t num_sets,
|
||||
}
|
||||
// For each set of keys with the same prefix, sum all the values
|
||||
for (uint16_t set_i : set_vec) {
|
||||
// four digits and zero end char
|
||||
char prefix_buf[5];
|
||||
// Five digits (since the largest uint16_t is 65535) plus the NUL
|
||||
// end char.
|
||||
char prefix_buf[6];
|
||||
assert(set_i + 1 <= 9999);
|
||||
snprintf(prefix_buf, sizeof(prefix_buf), "%.4u", set_i + 1);
|
||||
uint64_t total = 0;
|
||||
|
||||
|
||||
@@ -146,11 +146,17 @@ class BackupEngineImpl : public BackupEngine {
|
||||
|
||||
class BackupMeta {
|
||||
public:
|
||||
BackupMeta(const std::string& meta_filename,
|
||||
BackupMeta(
|
||||
const std::string& meta_filename, const std::string& meta_tmp_filename,
|
||||
std::unordered_map<std::string, std::shared_ptr<FileInfo>>* file_infos,
|
||||
Env* env)
|
||||
: timestamp_(0), sequence_number_(0), size_(0),
|
||||
meta_filename_(meta_filename), file_infos_(file_infos), env_(env) {}
|
||||
: timestamp_(0),
|
||||
sequence_number_(0),
|
||||
size_(0),
|
||||
meta_filename_(meta_filename),
|
||||
meta_tmp_filename_(meta_tmp_filename),
|
||||
file_infos_(file_infos),
|
||||
env_(env) {}
|
||||
|
||||
BackupMeta(const BackupMeta&) = delete;
|
||||
BackupMeta& operator=(const BackupMeta&) = delete;
|
||||
@@ -228,6 +234,7 @@ class BackupEngineImpl : public BackupEngine {
|
||||
uint64_t size_;
|
||||
std::string app_metadata_;
|
||||
std::string const meta_filename_;
|
||||
std::string const meta_tmp_filename_;
|
||||
// files with relative paths (without "/" prefix!!)
|
||||
std::vector<std::shared_ptr<FileInfo>> files_;
|
||||
std::unordered_map<std::string, std::shared_ptr<FileInfo>>* file_infos_;
|
||||
@@ -257,12 +264,14 @@ class BackupEngineImpl : public BackupEngine {
|
||||
inline std::string GetSharedFileRel(const std::string& file = "",
|
||||
bool tmp = false) const {
|
||||
assert(file.size() == 0 || file[0] != '/');
|
||||
return "shared/" + file + (tmp ? ".tmp" : "");
|
||||
return std::string("shared/") + (tmp ? "." : "") + file +
|
||||
(tmp ? ".tmp" : "");
|
||||
}
|
||||
inline std::string GetSharedFileWithChecksumRel(const std::string& file = "",
|
||||
bool tmp = false) const {
|
||||
assert(file.size() == 0 || file[0] != '/');
|
||||
return GetSharedChecksumDirRel() + "/" + file + (tmp ? ".tmp" : "");
|
||||
return GetSharedChecksumDirRel() + "/" + (tmp ? "." : "") + file +
|
||||
(tmp ? ".tmp" : "");
|
||||
}
|
||||
inline std::string GetSharedFileWithChecksum(const std::string& file,
|
||||
const uint32_t checksum_value,
|
||||
@@ -283,8 +292,9 @@ class BackupEngineImpl : public BackupEngine {
|
||||
inline std::string GetBackupMetaDir() const {
|
||||
return GetAbsolutePath("meta");
|
||||
}
|
||||
inline std::string GetBackupMetaFile(BackupID backup_id) const {
|
||||
return GetBackupMetaDir() + "/" + rocksdb::ToString(backup_id);
|
||||
inline std::string GetBackupMetaFile(BackupID backup_id, bool tmp) const {
|
||||
return GetBackupMetaDir() + "/" + (tmp ? "." : "") +
|
||||
rocksdb::ToString(backup_id) + (tmp ? ".tmp" : "");
|
||||
}
|
||||
|
||||
// If size_limit == 0, there is no size limit, copy everything.
|
||||
@@ -605,10 +615,11 @@ Status BackupEngineImpl::Initialize() {
|
||||
continue;
|
||||
}
|
||||
assert(backups_.find(backup_id) == backups_.end());
|
||||
backups_.insert(
|
||||
std::make_pair(backup_id, unique_ptr<BackupMeta>(new BackupMeta(
|
||||
GetBackupMetaFile(backup_id),
|
||||
&backuped_file_infos_, backup_env_))));
|
||||
backups_.insert(std::make_pair(
|
||||
backup_id, unique_ptr<BackupMeta>(new BackupMeta(
|
||||
GetBackupMetaFile(backup_id, false /* tmp */),
|
||||
GetBackupMetaFile(backup_id, true /* tmp */),
|
||||
&backuped_file_infos_, backup_env_))));
|
||||
}
|
||||
|
||||
latest_backup_id_ = 0;
|
||||
@@ -736,10 +747,11 @@ Status BackupEngineImpl::CreateNewBackupWithMetadata(
|
||||
BackupID new_backup_id = latest_backup_id_ + 1;
|
||||
|
||||
assert(backups_.find(new_backup_id) == backups_.end());
|
||||
auto ret = backups_.insert(
|
||||
std::make_pair(new_backup_id, unique_ptr<BackupMeta>(new BackupMeta(
|
||||
GetBackupMetaFile(new_backup_id),
|
||||
&backuped_file_infos_, backup_env_))));
|
||||
auto ret = backups_.insert(std::make_pair(
|
||||
new_backup_id, unique_ptr<BackupMeta>(new BackupMeta(
|
||||
GetBackupMetaFile(new_backup_id, false /* tmp */),
|
||||
GetBackupMetaFile(new_backup_id, true /* tmp */),
|
||||
&backuped_file_infos_, backup_env_))));
|
||||
assert(ret.second == true);
|
||||
auto& new_backup = ret.first->second;
|
||||
new_backup->RecordTimestamp();
|
||||
@@ -1708,8 +1720,7 @@ Status BackupEngineImpl::BackupMeta::StoreToFile(bool sync) {
|
||||
EnvOptions env_options;
|
||||
env_options.use_mmap_writes = false;
|
||||
env_options.use_direct_writes = false;
|
||||
s = env_->NewWritableFile(meta_filename_ + ".tmp", &backup_meta_file,
|
||||
env_options);
|
||||
s = env_->NewWritableFile(meta_tmp_filename_, &backup_meta_file, env_options);
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
}
|
||||
@@ -1749,7 +1760,7 @@ Status BackupEngineImpl::BackupMeta::StoreToFile(bool sync) {
|
||||
s = backup_meta_file->Close();
|
||||
}
|
||||
if (s.ok()) {
|
||||
s = env_->RenameFile(meta_filename_ + ".tmp", meta_filename_);
|
||||
s = env_->RenameFile(meta_tmp_filename_, meta_filename_);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -810,9 +810,9 @@ 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",
|
||||
"/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"};
|
||||
"/private/1.tmp/00011.log", "/meta/.1.tmp"};
|
||||
AppendPath(backupdir_, should_have_written);
|
||||
test_backup_env_->AssertWrittenFiles(should_have_written);
|
||||
|
||||
@@ -828,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",
|
||||
should_have_written = {"/shared/.00015.sst.tmp", "/private/2.tmp/CURRENT",
|
||||
"/private/2.tmp/MANIFEST-01",
|
||||
"/private/2.tmp/00011.log", "/meta/2.tmp"};
|
||||
"/private/2.tmp/00011.log", "/meta/.2.tmp"};
|
||||
AppendPath(backupdir_, should_have_written);
|
||||
test_backup_env_->AssertWrittenFiles(should_have_written);
|
||||
|
||||
@@ -1169,7 +1169,7 @@ TEST_F(BackupableDBTest, DeleteTmpFiles) {
|
||||
} else {
|
||||
shared_tmp += "/shared";
|
||||
}
|
||||
shared_tmp += "/00006.sst.tmp";
|
||||
shared_tmp += "/.00006.sst.tmp";
|
||||
std::string private_tmp_dir = backupdir_ + "/private/10.tmp";
|
||||
std::string private_tmp_file = private_tmp_dir + "/00003.sst";
|
||||
file_manager_->WriteToFile(shared_tmp, "tmp");
|
||||
|
||||
@@ -207,7 +207,9 @@ Status CheckpointImpl::CreateCustomCheckpoint(
|
||||
|
||||
TEST_SYNC_POINT("CheckpointImpl::CreateCheckpoint:SavedLiveFiles1");
|
||||
TEST_SYNC_POINT("CheckpointImpl::CreateCheckpoint:SavedLiveFiles2");
|
||||
db_->FlushWAL(false /* sync */);
|
||||
if (db_options.manual_wal_flush) {
|
||||
db_->FlushWAL(false /* sync */);
|
||||
}
|
||||
}
|
||||
// if we have more than one column family, we need to also get WAL files
|
||||
if (s.ok()) {
|
||||
|
||||
Reference in new issue
Block a user