Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
67b897a306 | ||
|
394b94c34e | ||
|
74936bf577 | ||
|
3e09e81219 | ||
|
585b9eeb99 | ||
|
22796e6e71 | ||
|
edd6100e2b | ||
|
b11a617acd | ||
|
f96bb67e5e | ||
|
0b18f648e7 | ||
|
6ef136a7c6 | ||
|
ca41f994dd | ||
|
f92646cef2 |
1
Makefile
1
Makefile
@ -69,7 +69,6 @@ install:
|
||||
@[ ! -e $(SHARED) ] || install -C -m 644 $(SHARED) $(INSTALL_PATH)/lib
|
||||
#-------------------------------------------------
|
||||
|
||||
WARNING_FLAGS = -Wall -Werror -Wsign-compare
|
||||
CFLAGS += $(WARNING_FLAGS) -I. -I./include $(PLATFORM_CCFLAGS) $(OPT)
|
||||
CXXFLAGS += $(WARNING_FLAGS) -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT) -Woverloaded-virtual
|
||||
|
||||
|
@ -49,13 +49,7 @@ COMMON_FLAGS="-DROCKSDB_PLATFORM_POSIX"
|
||||
if [ -z "$ROCKSDB_NO_FBCODE" -a -d /mnt/gvfs/third-party ]; then
|
||||
FBCODE_BUILD="true"
|
||||
if [ -z "$USE_CLANG" ]; then
|
||||
CENTOS_VERSION=`rpm -q --qf "%{VERSION}" \
|
||||
$(rpm -q --whatprovides redhat-release)`
|
||||
if [ "$CENTOS_VERSION" = "6" ]; then
|
||||
source "$PWD/build_tools/fbcode.gcc481.sh"
|
||||
else
|
||||
source "$PWD/build_tools/fbcode.gcc471.sh"
|
||||
fi
|
||||
source $PWD/build_tools/fbcode_config.sh
|
||||
else
|
||||
source "$PWD/build_tools/fbcode.clang31.sh"
|
||||
fi
|
||||
@ -242,7 +236,7 @@ EOF
|
||||
int main() {}
|
||||
EOF
|
||||
if [ "$?" = 0 ]; then
|
||||
COMMON_FLAGS="$COMMON_FLAGS -DGFLAGS=google"
|
||||
COMMON_FLAGS="$COMMON_FLAGS -DGFLAGS=gflags"
|
||||
PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lgflags"
|
||||
fi
|
||||
|
||||
|
19
build_tools/dependencies.sh
Normal file
19
build_tools/dependencies.sh
Normal file
@ -0,0 +1,19 @@
|
||||
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
|
||||
GCC_BASE=/mnt/gvfs/third-party2/gcc/7331085db891a2ef4a88a48a751d834e8d68f4cb/7.x/centos7-native/b2ef2b6
|
||||
CLANG_BASE=/mnt/gvfs/third-party2/llvm-fb/963d9aeda70cc4779885b1277484fe7544a04e3e/9.0.0/platform007/9e92d53/
|
||||
LIBGCC_BASE=/mnt/gvfs/third-party2/libgcc/6ace84e956873d53638c738b6f65f3f469cca74c/7.x/platform007/5620abc
|
||||
GLIBC_BASE=/mnt/gvfs/third-party2/glibc/192b0f42d63dcf6210d6ceae387b49af049e6e0c/2.26/platform007/f259413
|
||||
SNAPPY_BASE=/mnt/gvfs/third-party2/snappy/7f9bdaada18f59bc27ec2b0871eb8a6144343aef/1.1.3/platform007/ca4da3d
|
||||
ZLIB_BASE=/mnt/gvfs/third-party2/zlib/2d9f0b9a4274cc21f61272a9e89bdb859bce8f1f/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/0f607f8fc442ea7d6b876931b1898bb573d5e5da/1.9.1/platform007/ca4da3d
|
||||
ZSTD_BASE=/mnt/gvfs/third-party2/zstd/ca22bc441a4eb709e9e0b1f9fec9750fed7b31c5/1.4.x/platform007/15a3614
|
||||
GFLAGS_BASE=/mnt/gvfs/third-party2/gflags/0b9929d2588991c65a57168bf88aff2db87c5d48/2.2.0/platform007/ca4da3d
|
||||
JEMALLOC_BASE=/mnt/gvfs/third-party2/jemalloc/c26f08f47ac35fc31da2633b7da92d6b863246eb/master/platform007/c26c002
|
||||
NUMA_BASE=/mnt/gvfs/third-party2/numa/3f3fb57a5ccc5fd21c66416c0b83e0aa76a05376/2.0.11/platform007/ca4da3d
|
||||
LIBUNWIND_BASE=/mnt/gvfs/third-party2/libunwind/40c73d874898b386a71847f1b99115d93822d11f/1.4/platform007/6f3e0a9
|
||||
TBB_BASE=/mnt/gvfs/third-party2/tbb/4ce8e8dba77cdbd81b75d6f0c32fd7a1b76a11ec/2018_U5/platform007/ca4da3d
|
||||
KERNEL_HEADERS_BASE=/mnt/gvfs/third-party2/kernel-headers/fb251ecd2f5ae16f8671f7014c246e52a748fe0b/fb/platform007/da39a3e
|
||||
BINUTILS_BASE=/mnt/gvfs/third-party2/binutils/ab9f09bba370e7066cafd4eb59752db93f2e8312/2.29.1/platform007/15a3614
|
||||
VALGRIND_BASE=/mnt/gvfs/third-party2/valgrind/d42d152a15636529b0861ec493927200ebebca8e/3.15.0/platform007/ca4da3d
|
||||
LUA_BASE=/mnt/gvfs/third-party2/lua/f0cd714433206d5139df61659eb7b28b1dea6683/5.3.4/platform007/5007832
|
134
build_tools/fbcode_config.sh
Normal file
134
build_tools/fbcode_config.sh
Normal file
@ -0,0 +1,134 @@
|
||||
#!/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.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"
|
||||
|
||||
LZ4_INCLUDE=" -I $LZ4_BASE/include/"
|
||||
LZ4_LIBS=" $LZ4_BASE/lib/liblz4.a"
|
||||
CFLAGS+=" -DLZ4"
|
||||
fi
|
||||
|
||||
# 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 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=" -msse -msse4.2 "
|
||||
|
||||
BINUTILS="$BINUTILS_BASE/bin"
|
||||
AR="$BINUTILS/ar"
|
||||
|
||||
DEPS_INCLUDE="$SNAPPY_INCLUDE $ZLIB_INCLUDE $LZ4_INCLUDE $GFLAGS_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 $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 $LZ4_LIBS $ZSTD_LIBS $GFLAGS_LIBS $TBB_LIBS"
|
||||
|
||||
VALGRIND_VER="$VALGRIND_BASE/bin/"
|
||||
|
||||
export CC CXX AR CFLAGS CXXFLAGS EXEC_LDFLAGS EXEC_LDFLAGS_SHARED VALGRIND_VER JEMALLOC_LIB JEMALLOC_INCLUDE CLANG_ANALYZER CLANG_SCAN_BUILD
|
@ -2320,12 +2320,14 @@ Status DBImpl::BackgroundCompaction(bool* madeProgress,
|
||||
} else {
|
||||
// no need to refcount in iteration since it's always under a mutex
|
||||
for (auto cfd : *versions_->GetColumnFamilySet()) {
|
||||
if (!cfd->options()->disable_auto_compactions) {
|
||||
// Pick up latest mutable CF Options and use it throughout the
|
||||
// compaction job
|
||||
auto* mutable_cf_options = cfd->GetLatestMutableCFOptions();
|
||||
if (!mutable_cf_options->disable_auto_compactions) {
|
||||
// NOTE: try to avoid unnecessary copy of MutableCFOptions if
|
||||
// compaction is not necessary. Need to make sure mutex is held
|
||||
// until we make a copy in the following code
|
||||
c.reset(cfd->PickCompaction(
|
||||
*cfd->GetLatestMutableCFOptions(), log_buffer));
|
||||
c.reset(cfd->PickCompaction(*mutable_cf_options, log_buffer));
|
||||
if (c != nullptr) {
|
||||
// update statistics
|
||||
MeasureTime(stats_, NUM_FILES_IN_SINGLE_COMPACTION,
|
||||
@ -2453,7 +2455,7 @@ void DBImpl::CleanupCompaction(CompactionState* compact, Status status) {
|
||||
compact->builder->Abandon();
|
||||
compact->builder.reset();
|
||||
} else {
|
||||
assert(compact->outfile == nullptr);
|
||||
assert(!status.ok() || compact->outfile == nullptr);
|
||||
}
|
||||
for (size_t i = 0; i < compact->outputs.size(); i++) {
|
||||
const CompactionState::Output& out = compact->outputs[i];
|
||||
@ -2508,6 +2510,20 @@ Status DBImpl::OpenCompactionOutputFile(
|
||||
pending_outputs_[file_number] = compact->compaction->GetOutputPathId();
|
||||
mutex_.Unlock();
|
||||
}
|
||||
// Make the output file
|
||||
std::string fname = TableFileName(db_options_.db_paths, file_number,
|
||||
compact->compaction->GetOutputPathId());
|
||||
Status s = env_->NewWritableFile(fname, &compact->outfile, env_options_);
|
||||
|
||||
if (!s.ok()) {
|
||||
Log(InfoLogLevel::ERROR_LEVEL, db_options_.info_log,
|
||||
"[%s] OpenCompactionOutputFiles for table #%" PRIu64 " "
|
||||
"fails at NewWritableFile with status %s",
|
||||
compact->compaction->column_family_data()->GetName().c_str(),
|
||||
file_number, s.ToString().c_str());
|
||||
LogFlush(db_options_.info_log);
|
||||
return s;
|
||||
}
|
||||
CompactionState::Output out;
|
||||
out.number = file_number;
|
||||
out.path_id = compact->compaction->GetOutputPathId();
|
||||
@ -2516,12 +2532,6 @@ Status DBImpl::OpenCompactionOutputFile(
|
||||
out.smallest_seqno = out.largest_seqno = 0;
|
||||
compact->outputs.push_back(out);
|
||||
|
||||
// Make the output file
|
||||
std::string fname = TableFileName(db_options_.db_paths, file_number,
|
||||
compact->compaction->GetOutputPathId());
|
||||
Status s = env_->NewWritableFile(fname, &compact->outfile, env_options_);
|
||||
|
||||
if (s.ok()) {
|
||||
compact->outfile->SetIOPriority(Env::IO_LOW);
|
||||
compact->outfile->SetPreallocationBlockSize(
|
||||
compact->compaction->OutputFilePreallocationSize(mutable_cf_options));
|
||||
@ -2531,7 +2541,6 @@ Status DBImpl::OpenCompactionOutputFile(
|
||||
*cfd->ioptions(), cfd->internal_comparator(), compact->outfile.get(),
|
||||
compact->compaction->OutputCompressionType(),
|
||||
cfd->ioptions()->compression_opts));
|
||||
}
|
||||
LogFlush(db_options_.info_log);
|
||||
return s;
|
||||
}
|
||||
@ -2729,7 +2738,7 @@ Status DBImpl::ProcessKeyValueCompaction(
|
||||
int64_t key_drop_obsolete = 0;
|
||||
int64_t loop_cnt = 0;
|
||||
while (input->Valid() && !shutting_down_.Acquire_Load() &&
|
||||
!cfd->IsDropped()) {
|
||||
!cfd->IsDropped() && status.ok()) {
|
||||
if (++loop_cnt > 1000) {
|
||||
if (key_drop_user > 0) {
|
||||
RecordTick(stats_, COMPACTION_KEY_DROP_USER, key_drop_user);
|
||||
@ -3296,6 +3305,9 @@ Status DBImpl::DoCompactionWork(CompactionState* compact,
|
||||
true,
|
||||
&num_output_records,
|
||||
log_buffer);
|
||||
if (!status.ok()) {
|
||||
break;
|
||||
}
|
||||
|
||||
compact->CleanupBatchBuffer();
|
||||
compact->CleanupMergedBuffer();
|
||||
@ -3306,6 +3318,7 @@ Status DBImpl::DoCompactionWork(CompactionState* compact,
|
||||
CallCompactionFilterV2(compact, compaction_filter_v2);
|
||||
}
|
||||
compact->MergeKeyValueSliceBuffer(&cfd->internal_comparator());
|
||||
if (status.ok()) {
|
||||
status = ProcessKeyValueCompaction(
|
||||
mutable_cf_options,
|
||||
is_snapshot_supported,
|
||||
@ -3320,6 +3333,7 @@ Status DBImpl::DoCompactionWork(CompactionState* compact,
|
||||
true,
|
||||
&num_output_records,
|
||||
log_buffer);
|
||||
}
|
||||
} // checking for compaction filter v2
|
||||
|
||||
if (status.ok() && (shutting_down_.Acquire_Load() || cfd->IsDropped())) {
|
||||
@ -4232,6 +4246,9 @@ Status DBImpl::SetNewMemtableAndNewLogFile(ColumnFamilyData* cfd,
|
||||
new_superversion = new SuperVersion();
|
||||
}
|
||||
}
|
||||
Log(db_options_.info_log,
|
||||
"[%s] New memtable created with log file: #%" PRIu64 "\n",
|
||||
cfd->GetName().c_str(), new_log_number);
|
||||
mutex_.Lock();
|
||||
if (!s.ok()) {
|
||||
// how do we fail if we're not creating new log?
|
||||
@ -4264,9 +4281,6 @@ Status DBImpl::SetNewMemtableAndNewLogFile(ColumnFamilyData* cfd,
|
||||
cfd->imm()->Add(cfd->mem());
|
||||
new_mem->Ref();
|
||||
cfd->SetMemtable(new_mem);
|
||||
Log(db_options_.info_log,
|
||||
"[%s] New memtable created with log file: #%" PRIu64 "\n",
|
||||
cfd->GetName().c_str(), logfile_number_);
|
||||
context->superversions_to_free_.push_back(
|
||||
cfd->InstallSuperVersion(new_superversion, &mutex_, mutable_cf_options));
|
||||
return s;
|
||||
|
260
db/db_test.cc
260
db/db_test.cc
@ -120,6 +120,8 @@ static std::string Key(int i) {
|
||||
// Special Env used to delay background operations
|
||||
class SpecialEnv : public EnvWrapper {
|
||||
public:
|
||||
Random rnd_;
|
||||
|
||||
// sstable Sync() calls are blocked while this pointer is non-nullptr.
|
||||
port::AtomicPointer delay_sstable_sync_;
|
||||
|
||||
@ -153,7 +155,13 @@ class SpecialEnv : public EnvWrapper {
|
||||
|
||||
std::atomic<int> sync_counter_;
|
||||
|
||||
explicit SpecialEnv(Env* base) : EnvWrapper(base) {
|
||||
std::atomic<uint32_t> non_writeable_rate_;
|
||||
|
||||
std::atomic<uint32_t> new_writable_count_;
|
||||
|
||||
std::atomic<uint32_t> periodic_non_writable_;
|
||||
|
||||
explicit SpecialEnv(Env* base) : EnvWrapper(base), rnd_(301) {
|
||||
delay_sstable_sync_.Release_Store(nullptr);
|
||||
drop_writes_.Release_Store(nullptr);
|
||||
no_space_.Release_Store(nullptr);
|
||||
@ -165,6 +173,9 @@ class SpecialEnv : public EnvWrapper {
|
||||
log_write_error_.Release_Store(nullptr);
|
||||
bytes_written_ = 0;
|
||||
sync_counter_ = 0;
|
||||
non_writeable_rate_ = 0;
|
||||
new_writable_count_ = 0;
|
||||
periodic_non_writable_ = 0;
|
||||
}
|
||||
|
||||
Status NewWritableFile(const std::string& f, unique_ptr<WritableFile>* r,
|
||||
@ -250,8 +261,19 @@ class SpecialEnv : public EnvWrapper {
|
||||
}
|
||||
};
|
||||
|
||||
if (non_writable_.Acquire_Load() != nullptr) {
|
||||
return Status::IOError("simulated write error");
|
||||
if (non_writeable_rate_.load(std::memory_order_acquire) > 0) {
|
||||
auto random_number = rnd_.Uniform(100);
|
||||
if (random_number < non_writeable_rate_.load()) {
|
||||
return Status::IOError("simulated random write error");
|
||||
}
|
||||
}
|
||||
|
||||
new_writable_count_++;
|
||||
|
||||
auto periodic_fail = periodic_non_writable_.load();
|
||||
if (periodic_fail > 0 &&
|
||||
new_writable_count_.load() % periodic_fail == 0) {
|
||||
return Status::IOError("simulated periodic write error");
|
||||
}
|
||||
|
||||
Status s = target()->NewWritableFile(f, r, soptions);
|
||||
@ -5864,7 +5886,7 @@ TEST(DBTest, NonWritableFileSystem) {
|
||||
options.env = env_;
|
||||
Reopen(&options);
|
||||
ASSERT_OK(Put("foo", "v1"));
|
||||
env_->non_writable_.Release_Store(env_); // Force errors for new files
|
||||
env_->non_writeable_rate_.store(100); // Force errors for new files
|
||||
std::string big(100000, 'x');
|
||||
int errors = 0;
|
||||
for (int i = 0; i < 20; i++) {
|
||||
@ -5874,7 +5896,7 @@ TEST(DBTest, NonWritableFileSystem) {
|
||||
}
|
||||
}
|
||||
ASSERT_GT(errors, 0);
|
||||
env_->non_writable_.Release_Store(nullptr);
|
||||
env_->non_writeable_rate_.store(0);
|
||||
} while (ChangeCompactOptions());
|
||||
}
|
||||
|
||||
@ -8589,6 +8611,142 @@ TEST(DBTest, DynamicMemtableOptions) {
|
||||
ASSERT_TRUE(SizeAtLevel(0) > k128KB + k64KB - 2 * k5KB);
|
||||
}
|
||||
|
||||
TEST(DBTest, FileCreationRandomFailure) {
|
||||
Options options;
|
||||
options.env = env_;
|
||||
options.create_if_missing = true;
|
||||
options.write_buffer_size = 100000; // Small write buffer
|
||||
options.target_file_size_base = 200000;
|
||||
options.max_bytes_for_level_base = 1000000;
|
||||
options.max_bytes_for_level_multiplier = 2;
|
||||
|
||||
DestroyAndReopen(&options);
|
||||
Random rnd(301);
|
||||
|
||||
const int kTestSize = kCDTKeysPerBuffer * 4096;
|
||||
const int kTotalIteration = 100;
|
||||
// the second half of the test involves in random failure
|
||||
// of file creation.
|
||||
const int kRandomFailureTest = kTotalIteration / 2;
|
||||
std::vector<std::string> values;
|
||||
for (int i = 0; i < kTestSize; ++i) {
|
||||
values.push_back("NOT_FOUND");
|
||||
}
|
||||
for (int j = 0; j < kTotalIteration; ++j) {
|
||||
if (j == kRandomFailureTest) {
|
||||
env_->non_writeable_rate_.store(90);
|
||||
}
|
||||
for (int k = 0; k < kTestSize; ++k) {
|
||||
// here we expect some of the Put fails.
|
||||
std::string value = RandomString(&rnd, 100);
|
||||
Status s = Put(Key(k), Slice(value));
|
||||
if (s.ok()) {
|
||||
// update the latest successful put
|
||||
values[k] = value;
|
||||
}
|
||||
// But everything before we simulate the failure-test should succeed.
|
||||
if (j < kRandomFailureTest) {
|
||||
ASSERT_OK(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If rocksdb does not do the correct job, internal assert will fail here.
|
||||
dbfull()->TEST_WaitForFlushMemTable();
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
|
||||
// verify we have the latest successful update
|
||||
for (int k = 0; k < kTestSize; ++k) {
|
||||
auto v = Get(Key(k));
|
||||
ASSERT_EQ(v, values[k]);
|
||||
}
|
||||
|
||||
// reopen and reverify we have the latest successful update
|
||||
env_->non_writeable_rate_.store(0);
|
||||
Reopen(&options);
|
||||
for (int k = 0; k < kTestSize; ++k) {
|
||||
auto v = Get(Key(k));
|
||||
ASSERT_EQ(v, values[k]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DBTest, PartialCompactionFailure) {
|
||||
Options options;
|
||||
const int kKeySize = 16;
|
||||
const int kKvSize = 1000;
|
||||
const int kKeysPerBuffer = 100;
|
||||
const int kNumL1Files = 5;
|
||||
options.create_if_missing = true;
|
||||
options.write_buffer_size = kKeysPerBuffer * kKvSize;
|
||||
options.max_write_buffer_number = 2;
|
||||
options.target_file_size_base =
|
||||
options.write_buffer_size *
|
||||
(options.max_write_buffer_number - 1);
|
||||
options.level0_file_num_compaction_trigger = kNumL1Files;
|
||||
options.max_bytes_for_level_base =
|
||||
options.level0_file_num_compaction_trigger *
|
||||
options.target_file_size_base;
|
||||
options.max_bytes_for_level_multiplier = 2;
|
||||
options.compression = kNoCompression;
|
||||
|
||||
// The number of NewWritableFiles calls required by each operation.
|
||||
const int kNumInitialNewWritableFiles = 4;
|
||||
const int kNumLevel0FlushNewWritableFiles =
|
||||
options.level0_file_num_compaction_trigger * 2;
|
||||
const int kNumLevel1NewWritableFiles =
|
||||
options.level0_file_num_compaction_trigger + 1;
|
||||
// This setting will make one of the file-creation fail
|
||||
// in the first L0 -> L1 compaction while making sure
|
||||
// all flushes succeeed.
|
||||
env_->periodic_non_writable_ =
|
||||
kNumInitialNewWritableFiles + kNumLevel0FlushNewWritableFiles +
|
||||
kNumLevel1NewWritableFiles - 3;
|
||||
options.env = env_;
|
||||
|
||||
DestroyAndReopen(&options);
|
||||
|
||||
const int kNumKeys =
|
||||
options.level0_file_num_compaction_trigger *
|
||||
(options.max_write_buffer_number - 1) *
|
||||
kKeysPerBuffer * 1.0;
|
||||
|
||||
Random rnd(301);
|
||||
std::vector<std::string> keys;
|
||||
std::vector<std::string> values;
|
||||
for (int k = 0; k < kNumKeys; ++k) {
|
||||
keys.emplace_back(RandomString(&rnd, kKeySize));
|
||||
values.emplace_back(RandomString(&rnd, kKvSize - kKeySize));
|
||||
ASSERT_OK(Put(Slice(keys[k]), Slice(values[k])));
|
||||
}
|
||||
|
||||
dbfull()->TEST_WaitForFlushMemTable();
|
||||
// Make sure the number of L0 files can trigger compaction.
|
||||
ASSERT_GE(NumTableFilesAtLevel(0),
|
||||
options.level0_file_num_compaction_trigger);
|
||||
auto previous_num_level0_files = NumTableFilesAtLevel(0);
|
||||
// Expect compaction to fail here as one file will fail its
|
||||
// creation.
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
// Verify L0 -> L1 compaction does fail.
|
||||
ASSERT_EQ(NumTableFilesAtLevel(1), 0);
|
||||
// Verify all L0 files are still there.
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), previous_num_level0_files);
|
||||
|
||||
// All key-values must exist after compaction fails.
|
||||
for (int k = 0; k < kNumKeys; ++k) {
|
||||
ASSERT_EQ(values[k], Get(keys[k]));
|
||||
}
|
||||
|
||||
// Make sure RocksDB will not get into corrupted state.
|
||||
Reopen(&options);
|
||||
|
||||
// Verify again after reopen.
|
||||
for (int k = 0; k < kNumKeys; ++k) {
|
||||
ASSERT_EQ(values[k], Get(keys[k]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(DBTest, DynamicCompactionOptions) {
|
||||
const uint64_t k64KB = 1 << 16;
|
||||
const uint64_t k128KB = 1 << 17;
|
||||
@ -8598,14 +8756,13 @@ TEST(DBTest, DynamicCompactionOptions) {
|
||||
options.env = env_;
|
||||
options.create_if_missing = true;
|
||||
options.compression = kNoCompression;
|
||||
options.max_background_compactions = 4;
|
||||
options.hard_rate_limit = 1.1;
|
||||
options.write_buffer_size = k128KB;
|
||||
options.max_write_buffer_number = 2;
|
||||
// Compaction related options
|
||||
options.level0_file_num_compaction_trigger = 3;
|
||||
options.level0_slowdown_writes_trigger = 10;
|
||||
options.level0_stop_writes_trigger = 20;
|
||||
options.level0_slowdown_writes_trigger = 4;
|
||||
options.level0_stop_writes_trigger = 8;
|
||||
options.max_grandparent_overlap_factor = 10;
|
||||
options.expanded_compaction_factor = 25;
|
||||
options.source_compaction_factor = 1;
|
||||
@ -8613,9 +8770,13 @@ TEST(DBTest, DynamicCompactionOptions) {
|
||||
options.target_file_size_multiplier = 1;
|
||||
options.max_bytes_for_level_base = k256KB;
|
||||
options.max_bytes_for_level_multiplier = 4;
|
||||
|
||||
// Block flush thread and disable compaction thread
|
||||
env_->SetBackgroundThreads(1, Env::LOW);
|
||||
env_->SetBackgroundThreads(1, Env::HIGH);
|
||||
DestroyAndReopen(&options);
|
||||
|
||||
auto gen_l0_kb = [this](int start, int size, int stride = 1) {
|
||||
auto gen_l0_kb = [this](int start, int size, int stride) {
|
||||
Random rnd(301);
|
||||
std::vector<std::string> values;
|
||||
for (int i = 0; i < size; i++) {
|
||||
@ -8627,11 +8788,11 @@ TEST(DBTest, DynamicCompactionOptions) {
|
||||
|
||||
// Write 3 files that have the same key range, trigger compaction and
|
||||
// result in one L1 file
|
||||
gen_l0_kb(0, 128);
|
||||
gen_l0_kb(0, 128, 1);
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 1);
|
||||
gen_l0_kb(0, 128);
|
||||
gen_l0_kb(0, 128, 1);
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 2);
|
||||
gen_l0_kb(0, 128);
|
||||
gen_l0_kb(0, 128, 1);
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
ASSERT_EQ("0,1", FilesPerLevel());
|
||||
std::vector<LiveFileMetaData> metadata;
|
||||
@ -8646,9 +8807,9 @@ TEST(DBTest, DynamicCompactionOptions) {
|
||||
{"target_file_size_base", "65536"}
|
||||
}));
|
||||
|
||||
gen_l0_kb(0, 128);
|
||||
gen_l0_kb(0, 128, 1);
|
||||
ASSERT_EQ("1,1", FilesPerLevel());
|
||||
gen_l0_kb(0, 128);
|
||||
gen_l0_kb(0, 128, 1);
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
ASSERT_EQ("0,2", FilesPerLevel());
|
||||
metadata.clear();
|
||||
@ -8684,6 +8845,77 @@ TEST(DBTest, DynamicCompactionOptions) {
|
||||
ASSERT_TRUE(SizeAtLevel(1) < 262144 * 1.1);
|
||||
ASSERT_TRUE(SizeAtLevel(2) < 2 * 262144 * 1.1);
|
||||
ASSERT_TRUE(SizeAtLevel(3) < 4 * 262144 * 1.1);
|
||||
// Clean up memtable and L0
|
||||
dbfull()->CompactRange(nullptr, nullptr);
|
||||
// Block compaction
|
||||
SleepingBackgroundTask sleeping_task_low1;
|
||||
env_->Schedule(&SleepingBackgroundTask::DoSleepTask, &sleeping_task_low1,
|
||||
Env::Priority::LOW);
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 0);
|
||||
int count = 0;
|
||||
Random rnd(301);
|
||||
WriteOptions wo;
|
||||
wo.timeout_hint_us = 10000;
|
||||
while (Put(Key(count), RandomString(&rnd, 1024), wo).ok() && count < 64) {
|
||||
// Wait for compaction so that put won't timeout
|
||||
dbfull()->TEST_FlushMemTable(true);
|
||||
count++;
|
||||
}
|
||||
ASSERT_EQ(count, 8);
|
||||
// Unblock
|
||||
sleeping_task_low1.WakeUp();
|
||||
sleeping_task_low1.WaitUntilDone();
|
||||
|
||||
// Reduce stop trigger
|
||||
ASSERT_TRUE(dbfull()->SetOptions({
|
||||
{"level0_stop_writes_trigger", "6"}
|
||||
}));
|
||||
dbfull()->CompactRange(nullptr, nullptr);
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 0);
|
||||
|
||||
// Block compaction
|
||||
SleepingBackgroundTask sleeping_task_low2;
|
||||
env_->Schedule(&SleepingBackgroundTask::DoSleepTask, &sleeping_task_low2,
|
||||
Env::Priority::LOW);
|
||||
count = 0;
|
||||
while (Put(Key(count), RandomString(&rnd, 1024), wo).ok() && count < 64) {
|
||||
// Wait for compaction so that put won't timeout
|
||||
dbfull()->TEST_FlushMemTable(true);
|
||||
count++;
|
||||
}
|
||||
ASSERT_EQ(count, 6);
|
||||
// Unblock
|
||||
sleeping_task_low2.WakeUp();
|
||||
sleeping_task_low2.WaitUntilDone();
|
||||
|
||||
// Test disable_auto_compactions
|
||||
ASSERT_TRUE(dbfull()->SetOptions({
|
||||
{"disable_auto_compactions", "true"}
|
||||
}));
|
||||
dbfull()->CompactRange(nullptr, nullptr);
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 0);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
ASSERT_OK(Put(Key(i), RandomString(&rnd, 1024)));
|
||||
// Wait for compaction so that put won't timeout
|
||||
dbfull()->TEST_FlushMemTable(true);
|
||||
}
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 4);
|
||||
|
||||
ASSERT_TRUE(dbfull()->SetOptions({
|
||||
{"disable_auto_compactions", "false"}
|
||||
}));
|
||||
dbfull()->CompactRange(nullptr, nullptr);
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 0);
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
ASSERT_OK(Put(Key(i), RandomString(&rnd, 1024)));
|
||||
// Wait for compaction so that put won't timeout
|
||||
dbfull()->TEST_FlushMemTable(true);
|
||||
}
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
ASSERT_LT(NumTableFilesAtLevel(0), 4);
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
@ -64,7 +64,7 @@ void VersionEdit::Clear() {
|
||||
column_family_name_.clear();
|
||||
}
|
||||
|
||||
void VersionEdit::EncodeTo(std::string* dst) const {
|
||||
bool VersionEdit::EncodeTo(std::string* dst) const {
|
||||
if (has_comparator_) {
|
||||
PutVarint32(dst, kComparator);
|
||||
PutLengthPrefixedSlice(dst, comparator_);
|
||||
@ -98,6 +98,9 @@ void VersionEdit::EncodeTo(std::string* dst) const {
|
||||
|
||||
for (size_t i = 0; i < new_files_.size(); i++) {
|
||||
const FileMetaData& f = new_files_[i].second;
|
||||
if (!f.smallest.Valid() || !f.largest.Valid()) {
|
||||
return false;
|
||||
}
|
||||
if (f.fd.GetPathId() == 0) {
|
||||
// Use older format to make sure user can roll back the build if they
|
||||
// don't config multiple DB paths.
|
||||
@ -131,6 +134,7 @@ void VersionEdit::EncodeTo(std::string* dst) const {
|
||||
if (is_column_family_drop_) {
|
||||
PutVarint32(dst, kColumnFamilyDrop);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool GetInternalKey(Slice* input, InternalKey* dst) {
|
||||
|
@ -212,7 +212,8 @@ class VersionEdit {
|
||||
is_column_family_drop_ = true;
|
||||
}
|
||||
|
||||
void EncodeTo(std::string* dst) const;
|
||||
// return true on success.
|
||||
bool EncodeTo(std::string* dst) const;
|
||||
Status DecodeFrom(const Slice& src);
|
||||
|
||||
std::string DebugString(bool hex_key = false) const;
|
||||
|
@ -44,6 +44,16 @@ TEST(VersionEditTest, EncodeDecode) {
|
||||
TestEncodeDecode(edit);
|
||||
}
|
||||
|
||||
TEST(VersionEditTest, EncodeEmptyFile) {
|
||||
VersionEdit edit;
|
||||
edit.AddFile(0, 0, 0, 0,
|
||||
InternalKey(),
|
||||
InternalKey(),
|
||||
0, 0);
|
||||
std::string buffer;
|
||||
ASSERT_TRUE(!edit.EncodeTo(&buffer));
|
||||
}
|
||||
|
||||
TEST(VersionEditTest, ColumnFamilyTest) {
|
||||
VersionEdit edit;
|
||||
edit.SetColumnFamily(2);
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#define ROCKSDB_MAJOR 3
|
||||
#define ROCKSDB_MINOR 6
|
||||
#define ROCKSDB_PATCH 0
|
||||
#define ROCKSDB_PATCH 2
|
||||
|
||||
// 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,7 +20,9 @@ void PrintStack(int first_frames_to_skip) {}
|
||||
#include <execinfo.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
// It's odd that including this breaks in GCC 7 but the build doesn't break
|
||||
// if I remove it even under GCC 4.8.
|
||||
// #include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <cxxabi.h>
|
||||
|
@ -736,15 +736,30 @@ class PosixWritableFile : public WritableFile {
|
||||
GetPreallocationStatus(&block_size, &last_allocated_block);
|
||||
if (last_allocated_block > 0) {
|
||||
// trim the extra space preallocated at the end of the file
|
||||
// NOTE(ljin): we probably don't want to surface failure as an IOError,
|
||||
// but it will be nice to log these errors.
|
||||
int dummy __attribute__((unused));
|
||||
dummy = ftruncate(fd_, filesize_); // ignore errors
|
||||
dummy = ftruncate(fd_, filesize_);
|
||||
#ifdef ROCKSDB_FALLOCATE_PRESENT
|
||||
// in some file systems, ftruncate only trims trailing space if the
|
||||
// new file size is smaller than the current size. Calling fallocate
|
||||
// with FALLOC_FL_PUNCH_HOLE flag to explicitly release these unused
|
||||
// blocks. FALLOC_FL_PUNCH_HOLE is supported on at least the following
|
||||
// filesystems:
|
||||
// XFS (since Linux 2.6.38)
|
||||
// ext4 (since Linux 3.0)
|
||||
// Btrfs (since Linux 3.7)
|
||||
// tmpfs (since Linux 3.5)
|
||||
// We ignore error since failure of this operation does not affect
|
||||
// correctness.
|
||||
fallocate(fd_, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
|
||||
filesize_, block_size * last_allocated_block - filesize_);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (close(fd_) < 0) {
|
||||
if (s.ok()) {
|
||||
s = IOError(filename_, errno);
|
||||
}
|
||||
}
|
||||
fd_ = -1;
|
||||
return s;
|
||||
}
|
||||
|
@ -516,7 +516,7 @@ TEST(EnvPosixTest, AllocateTest) {
|
||||
// allocate 100 MB
|
||||
size_t kPreallocateSize = 100 * 1024 * 1024;
|
||||
size_t kBlockSize = 512;
|
||||
std::string data = "test";
|
||||
std::string data(1024 * 1024, 'a');
|
||||
wfile->SetPreallocationBlockSize(kPreallocateSize);
|
||||
ASSERT_OK(wfile->Append(Slice(data)));
|
||||
ASSERT_OK(wfile->Flush());
|
||||
@ -538,7 +538,7 @@ TEST(EnvPosixTest, AllocateTest) {
|
||||
stat(fname.c_str(), &f_stat);
|
||||
ASSERT_EQ((unsigned int)data.size(), f_stat.st_size);
|
||||
// verify that preallocated blocks were deallocated on file close
|
||||
ASSERT_GT(st_blocks, f_stat.st_blocks);
|
||||
ASSERT_EQ((f_stat.st_size + kBlockSize - 1) / kBlockSize, f_stat.st_blocks);
|
||||
}
|
||||
#endif // ROCKSDB_FALLOCATE_PRESENT
|
||||
|
||||
|
@ -21,6 +21,7 @@ struct MutableCFOptions {
|
||||
options.memtable_prefix_bloom_huge_page_tlb_size),
|
||||
max_successive_merges(options.max_successive_merges),
|
||||
filter_deletes(options.filter_deletes),
|
||||
disable_auto_compactions(options.disable_auto_compactions),
|
||||
level0_file_num_compaction_trigger(
|
||||
options.level0_file_num_compaction_trigger),
|
||||
level0_slowdown_writes_trigger(options.level0_slowdown_writes_trigger),
|
||||
@ -45,6 +46,7 @@ struct MutableCFOptions {
|
||||
memtable_prefix_bloom_huge_page_tlb_size(0),
|
||||
max_successive_merges(0),
|
||||
filter_deletes(false),
|
||||
disable_auto_compactions(false),
|
||||
level0_file_num_compaction_trigger(0),
|
||||
level0_slowdown_writes_trigger(0),
|
||||
level0_stop_writes_trigger(0),
|
||||
@ -80,6 +82,7 @@ struct MutableCFOptions {
|
||||
bool filter_deletes;
|
||||
|
||||
// Compaction related options
|
||||
bool disable_auto_compactions;
|
||||
int level0_file_num_compaction_trigger;
|
||||
int level0_slowdown_writes_trigger;
|
||||
int level0_stop_writes_trigger;
|
||||
|
@ -100,7 +100,9 @@ bool ParseMemtableOptions(const std::string& name, const std::string& value,
|
||||
template<typename OptionsType>
|
||||
bool ParseCompactionOptions(const std::string& name, const std::string& value,
|
||||
OptionsType* new_options) {
|
||||
if (name == "level0_file_num_compaction_trigger") {
|
||||
if (name == "disable_auto_compactions") {
|
||||
new_options->disable_auto_compactions = ParseBoolean(name, value);
|
||||
} else if (name == "level0_file_num_compaction_trigger") {
|
||||
new_options->level0_file_num_compaction_trigger = ParseInt(value);
|
||||
} else if (name == "level0_slowdown_writes_trigger") {
|
||||
new_options->level0_slowdown_writes_trigger = ParseInt(value);
|
||||
@ -221,8 +223,6 @@ bool GetOptionsFromStrings(
|
||||
new_options->soft_rate_limit = ParseDouble(o.second);
|
||||
} else if (o.first == "hard_rate_limit") {
|
||||
new_options->hard_rate_limit = ParseDouble(o.second);
|
||||
} else if (o.first == "disable_auto_compactions") {
|
||||
new_options->disable_auto_compactions = ParseBoolean(o.first, o.second);
|
||||
} else if (o.first == "purge_redundant_kvs_while_flush") {
|
||||
new_options->purge_redundant_kvs_while_flush =
|
||||
ParseBoolean(o.first, o.second);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user