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
|
@[ ! -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)
|
CFLAGS += $(WARNING_FLAGS) -I. -I./include $(PLATFORM_CCFLAGS) $(OPT)
|
||||||
CXXFLAGS += $(WARNING_FLAGS) -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT) -Woverloaded-virtual
|
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
|
if [ -z "$ROCKSDB_NO_FBCODE" -a -d /mnt/gvfs/third-party ]; then
|
||||||
FBCODE_BUILD="true"
|
FBCODE_BUILD="true"
|
||||||
if [ -z "$USE_CLANG" ]; then
|
if [ -z "$USE_CLANG" ]; then
|
||||||
CENTOS_VERSION=`rpm -q --qf "%{VERSION}" \
|
source $PWD/build_tools/fbcode_config.sh
|
||||||
$(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
|
|
||||||
else
|
else
|
||||||
source "$PWD/build_tools/fbcode.clang31.sh"
|
source "$PWD/build_tools/fbcode.clang31.sh"
|
||||||
fi
|
fi
|
||||||
@ -242,7 +236,7 @@ EOF
|
|||||||
int main() {}
|
int main() {}
|
||||||
EOF
|
EOF
|
||||||
if [ "$?" = 0 ]; then
|
if [ "$?" = 0 ]; then
|
||||||
COMMON_FLAGS="$COMMON_FLAGS -DGFLAGS=google"
|
COMMON_FLAGS="$COMMON_FLAGS -DGFLAGS=gflags"
|
||||||
PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lgflags"
|
PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lgflags"
|
||||||
fi
|
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 {
|
} else {
|
||||||
// no need to refcount in iteration since it's always under a mutex
|
// no need to refcount in iteration since it's always under a mutex
|
||||||
for (auto cfd : *versions_->GetColumnFamilySet()) {
|
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
|
// NOTE: try to avoid unnecessary copy of MutableCFOptions if
|
||||||
// compaction is not necessary. Need to make sure mutex is held
|
// compaction is not necessary. Need to make sure mutex is held
|
||||||
// until we make a copy in the following code
|
// until we make a copy in the following code
|
||||||
c.reset(cfd->PickCompaction(
|
c.reset(cfd->PickCompaction(*mutable_cf_options, log_buffer));
|
||||||
*cfd->GetLatestMutableCFOptions(), log_buffer));
|
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
// update statistics
|
// update statistics
|
||||||
MeasureTime(stats_, NUM_FILES_IN_SINGLE_COMPACTION,
|
MeasureTime(stats_, NUM_FILES_IN_SINGLE_COMPACTION,
|
||||||
@ -2453,7 +2455,7 @@ void DBImpl::CleanupCompaction(CompactionState* compact, Status status) {
|
|||||||
compact->builder->Abandon();
|
compact->builder->Abandon();
|
||||||
compact->builder.reset();
|
compact->builder.reset();
|
||||||
} else {
|
} else {
|
||||||
assert(compact->outfile == nullptr);
|
assert(!status.ok() || compact->outfile == nullptr);
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < compact->outputs.size(); i++) {
|
for (size_t i = 0; i < compact->outputs.size(); i++) {
|
||||||
const CompactionState::Output& out = compact->outputs[i];
|
const CompactionState::Output& out = compact->outputs[i];
|
||||||
@ -2508,6 +2510,20 @@ Status DBImpl::OpenCompactionOutputFile(
|
|||||||
pending_outputs_[file_number] = compact->compaction->GetOutputPathId();
|
pending_outputs_[file_number] = compact->compaction->GetOutputPathId();
|
||||||
mutex_.Unlock();
|
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;
|
CompactionState::Output out;
|
||||||
out.number = file_number;
|
out.number = file_number;
|
||||||
out.path_id = compact->compaction->GetOutputPathId();
|
out.path_id = compact->compaction->GetOutputPathId();
|
||||||
@ -2516,22 +2532,15 @@ Status DBImpl::OpenCompactionOutputFile(
|
|||||||
out.smallest_seqno = out.largest_seqno = 0;
|
out.smallest_seqno = out.largest_seqno = 0;
|
||||||
compact->outputs.push_back(out);
|
compact->outputs.push_back(out);
|
||||||
|
|
||||||
// Make the output file
|
compact->outfile->SetIOPriority(Env::IO_LOW);
|
||||||
std::string fname = TableFileName(db_options_.db_paths, file_number,
|
compact->outfile->SetPreallocationBlockSize(
|
||||||
compact->compaction->GetOutputPathId());
|
compact->compaction->OutputFilePreallocationSize(mutable_cf_options));
|
||||||
Status s = env_->NewWritableFile(fname, &compact->outfile, env_options_);
|
|
||||||
|
|
||||||
if (s.ok()) {
|
ColumnFamilyData* cfd = compact->compaction->column_family_data();
|
||||||
compact->outfile->SetIOPriority(Env::IO_LOW);
|
compact->builder.reset(NewTableBuilder(
|
||||||
compact->outfile->SetPreallocationBlockSize(
|
*cfd->ioptions(), cfd->internal_comparator(), compact->outfile.get(),
|
||||||
compact->compaction->OutputFilePreallocationSize(mutable_cf_options));
|
compact->compaction->OutputCompressionType(),
|
||||||
|
cfd->ioptions()->compression_opts));
|
||||||
ColumnFamilyData* cfd = compact->compaction->column_family_data();
|
|
||||||
compact->builder.reset(NewTableBuilder(
|
|
||||||
*cfd->ioptions(), cfd->internal_comparator(), compact->outfile.get(),
|
|
||||||
compact->compaction->OutputCompressionType(),
|
|
||||||
cfd->ioptions()->compression_opts));
|
|
||||||
}
|
|
||||||
LogFlush(db_options_.info_log);
|
LogFlush(db_options_.info_log);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -2729,7 +2738,7 @@ Status DBImpl::ProcessKeyValueCompaction(
|
|||||||
int64_t key_drop_obsolete = 0;
|
int64_t key_drop_obsolete = 0;
|
||||||
int64_t loop_cnt = 0;
|
int64_t loop_cnt = 0;
|
||||||
while (input->Valid() && !shutting_down_.Acquire_Load() &&
|
while (input->Valid() && !shutting_down_.Acquire_Load() &&
|
||||||
!cfd->IsDropped()) {
|
!cfd->IsDropped() && status.ok()) {
|
||||||
if (++loop_cnt > 1000) {
|
if (++loop_cnt > 1000) {
|
||||||
if (key_drop_user > 0) {
|
if (key_drop_user > 0) {
|
||||||
RecordTick(stats_, COMPACTION_KEY_DROP_USER, key_drop_user);
|
RecordTick(stats_, COMPACTION_KEY_DROP_USER, key_drop_user);
|
||||||
@ -3296,6 +3305,9 @@ Status DBImpl::DoCompactionWork(CompactionState* compact,
|
|||||||
true,
|
true,
|
||||||
&num_output_records,
|
&num_output_records,
|
||||||
log_buffer);
|
log_buffer);
|
||||||
|
if (!status.ok()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
compact->CleanupBatchBuffer();
|
compact->CleanupBatchBuffer();
|
||||||
compact->CleanupMergedBuffer();
|
compact->CleanupMergedBuffer();
|
||||||
@ -3306,20 +3318,22 @@ Status DBImpl::DoCompactionWork(CompactionState* compact,
|
|||||||
CallCompactionFilterV2(compact, compaction_filter_v2);
|
CallCompactionFilterV2(compact, compaction_filter_v2);
|
||||||
}
|
}
|
||||||
compact->MergeKeyValueSliceBuffer(&cfd->internal_comparator());
|
compact->MergeKeyValueSliceBuffer(&cfd->internal_comparator());
|
||||||
status = ProcessKeyValueCompaction(
|
if (status.ok()) {
|
||||||
mutable_cf_options,
|
status = ProcessKeyValueCompaction(
|
||||||
is_snapshot_supported,
|
mutable_cf_options,
|
||||||
visible_at_tip,
|
is_snapshot_supported,
|
||||||
earliest_snapshot,
|
visible_at_tip,
|
||||||
latest_snapshot,
|
earliest_snapshot,
|
||||||
deletion_state,
|
latest_snapshot,
|
||||||
bottommost_level,
|
deletion_state,
|
||||||
imm_micros,
|
bottommost_level,
|
||||||
input.get(),
|
imm_micros,
|
||||||
compact,
|
input.get(),
|
||||||
true,
|
compact,
|
||||||
&num_output_records,
|
true,
|
||||||
log_buffer);
|
&num_output_records,
|
||||||
|
log_buffer);
|
||||||
|
}
|
||||||
} // checking for compaction filter v2
|
} // checking for compaction filter v2
|
||||||
|
|
||||||
if (status.ok() && (shutting_down_.Acquire_Load() || cfd->IsDropped())) {
|
if (status.ok() && (shutting_down_.Acquire_Load() || cfd->IsDropped())) {
|
||||||
@ -4232,6 +4246,9 @@ Status DBImpl::SetNewMemtableAndNewLogFile(ColumnFamilyData* cfd,
|
|||||||
new_superversion = new SuperVersion();
|
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();
|
mutex_.Lock();
|
||||||
if (!s.ok()) {
|
if (!s.ok()) {
|
||||||
// how do we fail if we're not creating new log?
|
// 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());
|
cfd->imm()->Add(cfd->mem());
|
||||||
new_mem->Ref();
|
new_mem->Ref();
|
||||||
cfd->SetMemtable(new_mem);
|
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(
|
context->superversions_to_free_.push_back(
|
||||||
cfd->InstallSuperVersion(new_superversion, &mutex_, mutable_cf_options));
|
cfd->InstallSuperVersion(new_superversion, &mutex_, mutable_cf_options));
|
||||||
return s;
|
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
|
// Special Env used to delay background operations
|
||||||
class SpecialEnv : public EnvWrapper {
|
class SpecialEnv : public EnvWrapper {
|
||||||
public:
|
public:
|
||||||
|
Random rnd_;
|
||||||
|
|
||||||
// sstable Sync() calls are blocked while this pointer is non-nullptr.
|
// sstable Sync() calls are blocked while this pointer is non-nullptr.
|
||||||
port::AtomicPointer delay_sstable_sync_;
|
port::AtomicPointer delay_sstable_sync_;
|
||||||
|
|
||||||
@ -153,7 +155,13 @@ class SpecialEnv : public EnvWrapper {
|
|||||||
|
|
||||||
std::atomic<int> sync_counter_;
|
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);
|
delay_sstable_sync_.Release_Store(nullptr);
|
||||||
drop_writes_.Release_Store(nullptr);
|
drop_writes_.Release_Store(nullptr);
|
||||||
no_space_.Release_Store(nullptr);
|
no_space_.Release_Store(nullptr);
|
||||||
@ -165,6 +173,9 @@ class SpecialEnv : public EnvWrapper {
|
|||||||
log_write_error_.Release_Store(nullptr);
|
log_write_error_.Release_Store(nullptr);
|
||||||
bytes_written_ = 0;
|
bytes_written_ = 0;
|
||||||
sync_counter_ = 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,
|
Status NewWritableFile(const std::string& f, unique_ptr<WritableFile>* r,
|
||||||
@ -250,8 +261,19 @@ class SpecialEnv : public EnvWrapper {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (non_writable_.Acquire_Load() != nullptr) {
|
if (non_writeable_rate_.load(std::memory_order_acquire) > 0) {
|
||||||
return Status::IOError("simulated write error");
|
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);
|
Status s = target()->NewWritableFile(f, r, soptions);
|
||||||
@ -5864,7 +5886,7 @@ TEST(DBTest, NonWritableFileSystem) {
|
|||||||
options.env = env_;
|
options.env = env_;
|
||||||
Reopen(&options);
|
Reopen(&options);
|
||||||
ASSERT_OK(Put("foo", "v1"));
|
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');
|
std::string big(100000, 'x');
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
for (int i = 0; i < 20; i++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
@ -5874,7 +5896,7 @@ TEST(DBTest, NonWritableFileSystem) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ASSERT_GT(errors, 0);
|
ASSERT_GT(errors, 0);
|
||||||
env_->non_writable_.Release_Store(nullptr);
|
env_->non_writeable_rate_.store(0);
|
||||||
} while (ChangeCompactOptions());
|
} while (ChangeCompactOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8589,6 +8611,142 @@ TEST(DBTest, DynamicMemtableOptions) {
|
|||||||
ASSERT_TRUE(SizeAtLevel(0) > k128KB + k64KB - 2 * k5KB);
|
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) {
|
TEST(DBTest, DynamicCompactionOptions) {
|
||||||
const uint64_t k64KB = 1 << 16;
|
const uint64_t k64KB = 1 << 16;
|
||||||
const uint64_t k128KB = 1 << 17;
|
const uint64_t k128KB = 1 << 17;
|
||||||
@ -8598,14 +8756,13 @@ TEST(DBTest, DynamicCompactionOptions) {
|
|||||||
options.env = env_;
|
options.env = env_;
|
||||||
options.create_if_missing = true;
|
options.create_if_missing = true;
|
||||||
options.compression = kNoCompression;
|
options.compression = kNoCompression;
|
||||||
options.max_background_compactions = 4;
|
|
||||||
options.hard_rate_limit = 1.1;
|
options.hard_rate_limit = 1.1;
|
||||||
options.write_buffer_size = k128KB;
|
options.write_buffer_size = k128KB;
|
||||||
options.max_write_buffer_number = 2;
|
options.max_write_buffer_number = 2;
|
||||||
// Compaction related options
|
// Compaction related options
|
||||||
options.level0_file_num_compaction_trigger = 3;
|
options.level0_file_num_compaction_trigger = 3;
|
||||||
options.level0_slowdown_writes_trigger = 10;
|
options.level0_slowdown_writes_trigger = 4;
|
||||||
options.level0_stop_writes_trigger = 20;
|
options.level0_stop_writes_trigger = 8;
|
||||||
options.max_grandparent_overlap_factor = 10;
|
options.max_grandparent_overlap_factor = 10;
|
||||||
options.expanded_compaction_factor = 25;
|
options.expanded_compaction_factor = 25;
|
||||||
options.source_compaction_factor = 1;
|
options.source_compaction_factor = 1;
|
||||||
@ -8613,9 +8770,13 @@ TEST(DBTest, DynamicCompactionOptions) {
|
|||||||
options.target_file_size_multiplier = 1;
|
options.target_file_size_multiplier = 1;
|
||||||
options.max_bytes_for_level_base = k256KB;
|
options.max_bytes_for_level_base = k256KB;
|
||||||
options.max_bytes_for_level_multiplier = 4;
|
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);
|
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);
|
Random rnd(301);
|
||||||
std::vector<std::string> values;
|
std::vector<std::string> values;
|
||||||
for (int i = 0; i < size; i++) {
|
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
|
// Write 3 files that have the same key range, trigger compaction and
|
||||||
// result in one L1 file
|
// result in one L1 file
|
||||||
gen_l0_kb(0, 128);
|
gen_l0_kb(0, 128, 1);
|
||||||
ASSERT_EQ(NumTableFilesAtLevel(0), 1);
|
ASSERT_EQ(NumTableFilesAtLevel(0), 1);
|
||||||
gen_l0_kb(0, 128);
|
gen_l0_kb(0, 128, 1);
|
||||||
ASSERT_EQ(NumTableFilesAtLevel(0), 2);
|
ASSERT_EQ(NumTableFilesAtLevel(0), 2);
|
||||||
gen_l0_kb(0, 128);
|
gen_l0_kb(0, 128, 1);
|
||||||
dbfull()->TEST_WaitForCompact();
|
dbfull()->TEST_WaitForCompact();
|
||||||
ASSERT_EQ("0,1", FilesPerLevel());
|
ASSERT_EQ("0,1", FilesPerLevel());
|
||||||
std::vector<LiveFileMetaData> metadata;
|
std::vector<LiveFileMetaData> metadata;
|
||||||
@ -8646,9 +8807,9 @@ TEST(DBTest, DynamicCompactionOptions) {
|
|||||||
{"target_file_size_base", "65536"}
|
{"target_file_size_base", "65536"}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
gen_l0_kb(0, 128);
|
gen_l0_kb(0, 128, 1);
|
||||||
ASSERT_EQ("1,1", FilesPerLevel());
|
ASSERT_EQ("1,1", FilesPerLevel());
|
||||||
gen_l0_kb(0, 128);
|
gen_l0_kb(0, 128, 1);
|
||||||
dbfull()->TEST_WaitForCompact();
|
dbfull()->TEST_WaitForCompact();
|
||||||
ASSERT_EQ("0,2", FilesPerLevel());
|
ASSERT_EQ("0,2", FilesPerLevel());
|
||||||
metadata.clear();
|
metadata.clear();
|
||||||
@ -8684,6 +8845,77 @@ TEST(DBTest, DynamicCompactionOptions) {
|
|||||||
ASSERT_TRUE(SizeAtLevel(1) < 262144 * 1.1);
|
ASSERT_TRUE(SizeAtLevel(1) < 262144 * 1.1);
|
||||||
ASSERT_TRUE(SizeAtLevel(2) < 2 * 262144 * 1.1);
|
ASSERT_TRUE(SizeAtLevel(2) < 2 * 262144 * 1.1);
|
||||||
ASSERT_TRUE(SizeAtLevel(3) < 4 * 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
|
} // namespace rocksdb
|
||||||
|
@ -64,7 +64,7 @@ void VersionEdit::Clear() {
|
|||||||
column_family_name_.clear();
|
column_family_name_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionEdit::EncodeTo(std::string* dst) const {
|
bool VersionEdit::EncodeTo(std::string* dst) const {
|
||||||
if (has_comparator_) {
|
if (has_comparator_) {
|
||||||
PutVarint32(dst, kComparator);
|
PutVarint32(dst, kComparator);
|
||||||
PutLengthPrefixedSlice(dst, comparator_);
|
PutLengthPrefixedSlice(dst, comparator_);
|
||||||
@ -98,6 +98,9 @@ void VersionEdit::EncodeTo(std::string* dst) const {
|
|||||||
|
|
||||||
for (size_t i = 0; i < new_files_.size(); i++) {
|
for (size_t i = 0; i < new_files_.size(); i++) {
|
||||||
const FileMetaData& f = new_files_[i].second;
|
const FileMetaData& f = new_files_[i].second;
|
||||||
|
if (!f.smallest.Valid() || !f.largest.Valid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (f.fd.GetPathId() == 0) {
|
if (f.fd.GetPathId() == 0) {
|
||||||
// Use older format to make sure user can roll back the build if they
|
// Use older format to make sure user can roll back the build if they
|
||||||
// don't config multiple DB paths.
|
// don't config multiple DB paths.
|
||||||
@ -131,6 +134,7 @@ void VersionEdit::EncodeTo(std::string* dst) const {
|
|||||||
if (is_column_family_drop_) {
|
if (is_column_family_drop_) {
|
||||||
PutVarint32(dst, kColumnFamilyDrop);
|
PutVarint32(dst, kColumnFamilyDrop);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool GetInternalKey(Slice* input, InternalKey* dst) {
|
static bool GetInternalKey(Slice* input, InternalKey* dst) {
|
||||||
|
@ -212,7 +212,8 @@ class VersionEdit {
|
|||||||
is_column_family_drop_ = true;
|
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);
|
Status DecodeFrom(const Slice& src);
|
||||||
|
|
||||||
std::string DebugString(bool hex_key = false) const;
|
std::string DebugString(bool hex_key = false) const;
|
||||||
|
@ -44,6 +44,16 @@ TEST(VersionEditTest, EncodeDecode) {
|
|||||||
TestEncodeDecode(edit);
|
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) {
|
TEST(VersionEditTest, ColumnFamilyTest) {
|
||||||
VersionEdit edit;
|
VersionEdit edit;
|
||||||
edit.SetColumnFamily(2);
|
edit.SetColumnFamily(2);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#define ROCKSDB_MAJOR 3
|
#define ROCKSDB_MAJOR 3
|
||||||
#define ROCKSDB_MINOR 6
|
#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
|
// Do not use these. We made the mistake of declaring macros starting with
|
||||||
// double underscore. Now we have to live with our choice. We'll deprecate these
|
// double underscore. Now we have to live with our choice. We'll deprecate these
|
||||||
|
@ -20,7 +20,9 @@ void PrintStack(int first_frames_to_skip) {}
|
|||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.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 <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <cxxabi.h>
|
#include <cxxabi.h>
|
||||||
|
@ -736,14 +736,29 @@ class PosixWritableFile : public WritableFile {
|
|||||||
GetPreallocationStatus(&block_size, &last_allocated_block);
|
GetPreallocationStatus(&block_size, &last_allocated_block);
|
||||||
if (last_allocated_block > 0) {
|
if (last_allocated_block > 0) {
|
||||||
// trim the extra space preallocated at the end of the file
|
// 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));
|
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 (close(fd_) < 0) {
|
||||||
if (s.ok()) {
|
s = IOError(filename_, errno);
|
||||||
s = IOError(filename_, errno);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fd_ = -1;
|
fd_ = -1;
|
||||||
return s;
|
return s;
|
||||||
|
@ -516,7 +516,7 @@ TEST(EnvPosixTest, AllocateTest) {
|
|||||||
// allocate 100 MB
|
// allocate 100 MB
|
||||||
size_t kPreallocateSize = 100 * 1024 * 1024;
|
size_t kPreallocateSize = 100 * 1024 * 1024;
|
||||||
size_t kBlockSize = 512;
|
size_t kBlockSize = 512;
|
||||||
std::string data = "test";
|
std::string data(1024 * 1024, 'a');
|
||||||
wfile->SetPreallocationBlockSize(kPreallocateSize);
|
wfile->SetPreallocationBlockSize(kPreallocateSize);
|
||||||
ASSERT_OK(wfile->Append(Slice(data)));
|
ASSERT_OK(wfile->Append(Slice(data)));
|
||||||
ASSERT_OK(wfile->Flush());
|
ASSERT_OK(wfile->Flush());
|
||||||
@ -538,7 +538,7 @@ TEST(EnvPosixTest, AllocateTest) {
|
|||||||
stat(fname.c_str(), &f_stat);
|
stat(fname.c_str(), &f_stat);
|
||||||
ASSERT_EQ((unsigned int)data.size(), f_stat.st_size);
|
ASSERT_EQ((unsigned int)data.size(), f_stat.st_size);
|
||||||
// verify that preallocated blocks were deallocated on file close
|
// 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
|
#endif // ROCKSDB_FALLOCATE_PRESENT
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ struct MutableCFOptions {
|
|||||||
options.memtable_prefix_bloom_huge_page_tlb_size),
|
options.memtable_prefix_bloom_huge_page_tlb_size),
|
||||||
max_successive_merges(options.max_successive_merges),
|
max_successive_merges(options.max_successive_merges),
|
||||||
filter_deletes(options.filter_deletes),
|
filter_deletes(options.filter_deletes),
|
||||||
|
disable_auto_compactions(options.disable_auto_compactions),
|
||||||
level0_file_num_compaction_trigger(
|
level0_file_num_compaction_trigger(
|
||||||
options.level0_file_num_compaction_trigger),
|
options.level0_file_num_compaction_trigger),
|
||||||
level0_slowdown_writes_trigger(options.level0_slowdown_writes_trigger),
|
level0_slowdown_writes_trigger(options.level0_slowdown_writes_trigger),
|
||||||
@ -45,6 +46,7 @@ struct MutableCFOptions {
|
|||||||
memtable_prefix_bloom_huge_page_tlb_size(0),
|
memtable_prefix_bloom_huge_page_tlb_size(0),
|
||||||
max_successive_merges(0),
|
max_successive_merges(0),
|
||||||
filter_deletes(false),
|
filter_deletes(false),
|
||||||
|
disable_auto_compactions(false),
|
||||||
level0_file_num_compaction_trigger(0),
|
level0_file_num_compaction_trigger(0),
|
||||||
level0_slowdown_writes_trigger(0),
|
level0_slowdown_writes_trigger(0),
|
||||||
level0_stop_writes_trigger(0),
|
level0_stop_writes_trigger(0),
|
||||||
@ -80,6 +82,7 @@ struct MutableCFOptions {
|
|||||||
bool filter_deletes;
|
bool filter_deletes;
|
||||||
|
|
||||||
// Compaction related options
|
// Compaction related options
|
||||||
|
bool disable_auto_compactions;
|
||||||
int level0_file_num_compaction_trigger;
|
int level0_file_num_compaction_trigger;
|
||||||
int level0_slowdown_writes_trigger;
|
int level0_slowdown_writes_trigger;
|
||||||
int level0_stop_writes_trigger;
|
int level0_stop_writes_trigger;
|
||||||
|
@ -100,7 +100,9 @@ bool ParseMemtableOptions(const std::string& name, const std::string& value,
|
|||||||
template<typename OptionsType>
|
template<typename OptionsType>
|
||||||
bool ParseCompactionOptions(const std::string& name, const std::string& value,
|
bool ParseCompactionOptions(const std::string& name, const std::string& value,
|
||||||
OptionsType* new_options) {
|
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);
|
new_options->level0_file_num_compaction_trigger = ParseInt(value);
|
||||||
} else if (name == "level0_slowdown_writes_trigger") {
|
} else if (name == "level0_slowdown_writes_trigger") {
|
||||||
new_options->level0_slowdown_writes_trigger = ParseInt(value);
|
new_options->level0_slowdown_writes_trigger = ParseInt(value);
|
||||||
@ -221,8 +223,6 @@ bool GetOptionsFromStrings(
|
|||||||
new_options->soft_rate_limit = ParseDouble(o.second);
|
new_options->soft_rate_limit = ParseDouble(o.second);
|
||||||
} else if (o.first == "hard_rate_limit") {
|
} else if (o.first == "hard_rate_limit") {
|
||||||
new_options->hard_rate_limit = ParseDouble(o.second);
|
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") {
|
} else if (o.first == "purge_redundant_kvs_while_flush") {
|
||||||
new_options->purge_redundant_kvs_while_flush =
|
new_options->purge_redundant_kvs_while_flush =
|
||||||
ParseBoolean(o.first, o.second);
|
ParseBoolean(o.first, o.second);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <atomic>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user