mirror of
https://github.com/facebook/rocksdb.git
synced 2026-11-06 11:02:36 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8c78da6ed | ||
|
|
5dac6ba2dc | ||
|
|
61d6cab888 | ||
|
|
26a2fb1cea | ||
|
|
41eb08a960 | ||
|
|
e7708343f3 | ||
|
|
dbffb828fa | ||
|
|
2ed9b9206b | ||
|
|
4860bfdeab | ||
|
|
74bcf18772 | ||
|
|
18a4f6a1de | ||
|
|
f300da40d0 | ||
|
|
b8f656767a | ||
|
|
fab086daa1 | ||
|
|
f9a3440b76 | ||
|
|
3bbf0e1e4f | ||
|
|
0be02649d8 |
No files matched your search
+1
-1
@@ -34,7 +34,7 @@ before_script:
|
||||
# as EnvPosixTest::AllocateTest expects within the Travis OpenVZ environment.
|
||||
script:
|
||||
- if [[ "${TRAVIS_OS_NAME}" == 'linux' ]]; then OPT=-DTRAVIS CLANG_FORMAT_DIFF=/tmp/clang-format-diff.py make format || true; fi
|
||||
- OPT=-DTRAVIS V=1 make -j4 check && OPT=-DTRAVIS V=1 make clean jclean rocksdbjava jtest && make clean && OPT="-DTRAVIS -DROCKSDB_LITE" V=1 make -j4 static_lib
|
||||
- OPT=-DTRAVIS V=1 make -j4 check && OPT=-DTRAVIS V=1 make clean jclean rocksdbjava jtest && make clean && OPT="-DTRAVIS -DROCKSDB_LITE" V=1 make -j4 check
|
||||
|
||||
notifications:
|
||||
email:
|
||||
|
||||
+18
-32
@@ -13,8 +13,8 @@
|
||||
# cd build
|
||||
# 3. Run cmake to generate project files for Windows, add more options to enable required third-party libraries.
|
||||
# See thirdparty.inc for more information.
|
||||
# sample command: cmake -G "Visual Studio 12 Win64" -DGFLAGS=1 -DSNAPPY=1 -DJEMALLOC=1 -DJNI=1 ..
|
||||
# OR for VS Studio 15 cmake -G "Visual Studio 14 Win64" -DGFLAGS=1 -DSNAPPY=1 -DJEMALLOC=1 -DJNI=1 ..
|
||||
# sample command: cmake -G "Visual Studio 12 Win64" -DGFLAGS=1 -DSNAPPY=1 -DJEMALLOC=1 ..
|
||||
# OR for VS Studio 15 cmake -G "Visual Studio 14 Win64" -DGFLAGS=1 -DSNAPPY=1 -DJEMALLOC=1 ..
|
||||
# 4. Then build the project in debug mode (you may want to add /m[:<N>] flag to run msbuild in <N> parallel threads
|
||||
# or simply /m ot use all avail cores)
|
||||
# msbuild rocksdb.sln
|
||||
@@ -30,9 +30,10 @@ cmake_minimum_required(VERSION 2.6)
|
||||
project(rocksdb)
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/thirdparty.inc)
|
||||
execute_process(COMMAND powershell -Command "Get-Date -format MM_dd_yyyy" OUTPUT_VARIABLE DATE)
|
||||
execute_process(COMMAND powershell -Command "Get-Date -format HH:mm:ss" OUTPUT_VARIABLE TIME)
|
||||
string(REGEX REPLACE "(..)_(..)_..(..).*" "\\1/\\2/\\3" DATE ${DATE})
|
||||
|
||||
execute_process(COMMAND $ENV{COMSPEC} " /C date /T" OUTPUT_VARIABLE DATE)
|
||||
execute_process(COMMAND $ENV{COMSPEC} " /C time /T" OUTPUT_VARIABLE TIME)
|
||||
string(REGEX REPLACE "(..)/(..)/..(..).*" "\\1/\\2/\\3" DATE ${DATE})
|
||||
string(REGEX REPLACE "(..):(.....).*" " \\1:\\2" TIME ${TIME})
|
||||
string(CONCAT GIT_DATE_TIME ${DATE} ${TIME})
|
||||
|
||||
@@ -98,7 +99,6 @@ add_subdirectory(third-party/gtest-1.7.0/fused-src/gtest)
|
||||
|
||||
# Main library source code
|
||||
set(SOURCES
|
||||
db/auto_roll_logger.cc
|
||||
db/builder.cc
|
||||
db/c.cc
|
||||
db/column_family.cc
|
||||
@@ -114,7 +114,6 @@ set(SOURCES
|
||||
db/db_impl_debug.cc
|
||||
db/db_impl_experimental.cc
|
||||
db/db_impl_readonly.cc
|
||||
db/db_info_dumper.cc
|
||||
db/db_iter.cc
|
||||
db/event_helpers.cc
|
||||
db/experimental.cc
|
||||
@@ -146,12 +145,9 @@ set(SOURCES
|
||||
db/write_batch_base.cc
|
||||
db/write_controller.cc
|
||||
db/write_thread.cc
|
||||
db/xfunc_test_points.cc
|
||||
memtable/hash_cuckoo_rep.cc
|
||||
memtable/hash_linklist_rep.cc
|
||||
memtable/hash_skiplist_rep.cc
|
||||
memtable/skiplistrep.cc
|
||||
memtable/vectorrep.cc
|
||||
port/stack_trace.cc
|
||||
port/win/env_win.cc
|
||||
port/win/port_win.cc
|
||||
@@ -177,6 +173,7 @@ set(SOURCES
|
||||
table/merger.cc
|
||||
table/sst_file_writer.cc
|
||||
table/meta_blocks.cc
|
||||
table/mock_table.cc
|
||||
table/plain_table_builder.cc
|
||||
table/plain_table_factory.cc
|
||||
table/plain_table_index.cc
|
||||
@@ -187,6 +184,7 @@ set(SOURCES
|
||||
tools/sst_dump_tool.cc
|
||||
tools/dump/db_dump_tool.cc
|
||||
util/arena.cc
|
||||
util/auto_roll_logger.cc
|
||||
util/bloom.cc
|
||||
util/build_version.cc
|
||||
util/cache.cc
|
||||
@@ -195,14 +193,14 @@ set(SOURCES
|
||||
util/comparator.cc
|
||||
util/concurrent_arena.cc
|
||||
util/crc32c.cc
|
||||
util/delete_scheduler.cc
|
||||
util/db_info_dumper.cc
|
||||
util/delete_scheduler_impl.cc
|
||||
util/dynamic_bloom.cc
|
||||
util/env.cc
|
||||
util/env_hdfs.cc
|
||||
util/event_logger.cc
|
||||
util/file_util.cc
|
||||
util/file_reader_writer.cc
|
||||
util/sst_file_manager_impl.cc
|
||||
util/filter_policy.cc
|
||||
util/hash.cc
|
||||
util/histogram.cc
|
||||
@@ -213,6 +211,7 @@ set(SOURCES
|
||||
util/logging.cc
|
||||
util/log_buffer.cc
|
||||
util/memenv.cc
|
||||
util/mock_env.cc
|
||||
util/murmurhash.cc
|
||||
util/mutable_cf_options.cc
|
||||
util/options.cc
|
||||
@@ -224,6 +223,7 @@ set(SOURCES
|
||||
util/perf_level.cc
|
||||
util/random.cc
|
||||
util/rate_limiter.cc
|
||||
util/skiplistrep.cc
|
||||
util/slice.cc
|
||||
util/statistics.cc
|
||||
util/status.cc
|
||||
@@ -237,11 +237,11 @@ set(SOURCES
|
||||
util/thread_status_updater.cc
|
||||
util/thread_status_util.cc
|
||||
util/thread_status_util_debug.cc
|
||||
util/vectorrep.cc
|
||||
util/xfunc.cc
|
||||
util/xxhash.cc
|
||||
utilities/backupable/backupable_db.cc
|
||||
utilities/checkpoint/checkpoint.cc
|
||||
utilities/compaction_filters/remove_emptyvalue_compactionfilter.cc
|
||||
utilities/document/document_db.cc
|
||||
utilities/document/json_document.cc
|
||||
utilities/document/json_document_builder.cc
|
||||
@@ -275,8 +275,6 @@ set(SOURCES
|
||||
# and linked to tests. Add test only code that is not #ifdefed for Release here.
|
||||
set(TESTUTIL_SOURCE
|
||||
db/db_test_util.cc
|
||||
table/mock_table.cc
|
||||
util/mock_env.cc
|
||||
util/thread_status_updater_debug.cc
|
||||
)
|
||||
|
||||
@@ -289,17 +287,6 @@ set_target_properties(rocksdb${ARTIFACT_SUFFIX} PROPERTIES COMPILE_FLAGS "-DROCK
|
||||
add_dependencies(rocksdb${ARTIFACT_SUFFIX} GenerateBuildVersion)
|
||||
target_link_libraries(rocksdb${ARTIFACT_SUFFIX} ${LIBS})
|
||||
|
||||
if (DEFINED JNI)
|
||||
if (${JNI} EQUAL 1)
|
||||
message(STATUS "JNI library is enabled")
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/java)
|
||||
else()
|
||||
message(STATUS "JNI library is disabled")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "JNI library is disabled")
|
||||
endif()
|
||||
|
||||
set(APPS
|
||||
db/db_bench.cc
|
||||
db/memtablerep_bench.cc
|
||||
@@ -316,7 +303,6 @@ set(APPS
|
||||
set(C_TESTS db/c_test.c)
|
||||
|
||||
set(TESTS
|
||||
db/auto_roll_logger_test.cc
|
||||
db/column_family_test.cc
|
||||
db/compact_files_test.cc
|
||||
db/compaction_iterator_test.cc
|
||||
@@ -326,18 +312,17 @@ set(TESTS
|
||||
db/comparator_db_test.cc
|
||||
db/corruption_test.cc
|
||||
db/cuckoo_table_db_test.cc
|
||||
db/db_iter_test.cc
|
||||
db/db_test.cc
|
||||
db/db_compaction_filter_test.cc
|
||||
db/db_compaction_test.cc
|
||||
db/db_dynamic_level_test.cc
|
||||
db/db_inplace_update_test.cc
|
||||
db/db_iter_test.cc
|
||||
db/db_log_iter_test.cc
|
||||
db/db_properties_test.cc
|
||||
db/db_table_properties_test.cc
|
||||
db/db_tailing_iter_test.cc
|
||||
db/db_test.cc
|
||||
db/db_universal_compaction_test.cc
|
||||
db/db_wal_test.cc
|
||||
db/db_tailing_iter_test.cc
|
||||
db/db_table_properties_test.cc
|
||||
db/dbformat_test.cc
|
||||
db/deletefile_test.cc
|
||||
db/fault_injection_test.cc
|
||||
@@ -378,6 +363,7 @@ set(TESTS
|
||||
tools/sst_dump_test.cc
|
||||
util/arena_test.cc
|
||||
util/autovector_test.cc
|
||||
util/auto_roll_logger_test.cc
|
||||
util/bloom_test.cc
|
||||
util/cache_test.cc
|
||||
util/coding_test.cc
|
||||
|
||||
+1
-15
@@ -1,20 +1,6 @@
|
||||
# Rocksdb Change Log
|
||||
## Unreleased
|
||||
|
||||
## 4.5.1 (3/25/2016)
|
||||
### Bug Fixes
|
||||
* Fix failures caused by the destorying order of singleton objects.
|
||||
|
||||
## 4.5.0 (2/5/2016)
|
||||
### Public API Changes
|
||||
* Add a new perf context level between kEnableCount and kEnableTime. Level 2 now does not include timers for mutexes.
|
||||
* Statistics of mutex operation durations will not be measured by default. If you want to have them enabled, you need to set Statistics::stats_level_ to kAll.
|
||||
* DBOptions::delete_scheduler and NewDeleteScheduler() are removed, please use DBOptions::sst_file_manager and NewSstFileManager() instead
|
||||
|
||||
### New Features
|
||||
* ldb tool now supports operations to non-default column families.
|
||||
* Add kPersistedTier to ReadTier. This option allows Get and MultiGet to read only the persited data and skip mem-tables if writes were done with disableWAL = true.
|
||||
* Add DBOptions::sst_file_manager. Use NewSstFileManager() in include/rocksdb/sst_file_manager.h to create a SstFileManager that can be used to track the total size of SST files and control the SST files deletion rate.
|
||||
## 4.4.1 (2/18/2016)
|
||||
|
||||
## 4.4.0 (1/14/2016)
|
||||
### Public API Changes
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ depend on gflags. You will need to have gflags installed to run `make all`. This
|
||||
use binaries compiled by `make all` in production.
|
||||
|
||||
* By default the binary we produce is optimized for the platform you're compiling on
|
||||
(-march=native or the equivalent). If you want to build a portable binary, add 'PORTABLE=1' before
|
||||
(-march=native). If you want to build a portable binary, add 'PORTABLE=1' before
|
||||
your make commands, like this: `PORTABLE=1 make static_lib`
|
||||
|
||||
## Dependencies
|
||||
|
||||
@@ -84,12 +84,10 @@ endif
|
||||
# compile with -O2 if debug level is not 2
|
||||
ifneq ($(DEBUG_LEVEL), 2)
|
||||
OPT += -O2 -fno-omit-frame-pointer
|
||||
ifeq (,$(findstring ppc64,$(MACHINE))) # ppc64[le] doesn't support -momit-leaf-frame-pointer
|
||||
ifneq ($(MACHINE),armv7l)
|
||||
ifneq ($(MACHINE),ppc64) # ppc64 doesn't support -momit-leaf-frame-pointer
|
||||
OPT += -momit-leaf-frame-pointer
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# if we're compiling for release, compile without debug code (-DNDEBUG) and
|
||||
# don't treat warnings as errors
|
||||
@@ -145,9 +143,6 @@ else
|
||||
OPT += -DNDEBUG
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), OS_SOLARIS)
|
||||
PLATFORM_CXXFLAGS += -D _GLIBCXX_USE_C99
|
||||
endif
|
||||
ifneq ($(filter -DROCKSDB_LITE,$(OPT)),)
|
||||
# found
|
||||
CFLAGS += -fno-exceptions
|
||||
@@ -192,6 +187,10 @@ default: all
|
||||
WARNING_FLAGS = -W -Wextra -Wall -Wsign-compare -Wshadow \
|
||||
-Wno-unused-parameter
|
||||
|
||||
ifndef DISABLE_WARNING_AS_ERROR
|
||||
WARNING_FLAGS += -Werror
|
||||
endif
|
||||
|
||||
CFLAGS += $(WARNING_FLAGS) -I. -I./include $(PLATFORM_CCFLAGS) $(OPT)
|
||||
CXXFLAGS += $(WARNING_FLAGS) -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT) -Woverloaded-virtual -Wnon-virtual-dtor -Wno-missing-field-initializers
|
||||
|
||||
@@ -249,7 +248,6 @@ TESTS = \
|
||||
db_tailing_iter_test \
|
||||
db_universal_compaction_test \
|
||||
db_wal_test \
|
||||
db_properties_test \
|
||||
db_table_properties_test \
|
||||
block_hash_index_test \
|
||||
autovector_test \
|
||||
@@ -462,7 +460,7 @@ test_names = \
|
||||
-e '/^(\s*)(\S+)/; !$$1 and do {$$p=$$2; break};' \
|
||||
-e 'print qq! $$p$$2!'
|
||||
|
||||
ifneq (,$(filter check parallel_check,$(MAKECMDGOALS)),)
|
||||
ifeq ($(MAKECMDGOALS),check)
|
||||
# Use /dev/shm if it has the sticky bit set (otherwise, /tmp),
|
||||
# and create a randomly-named rocksdb.XXXX directory therein.
|
||||
# We'll use that directory in the "make check" rules.
|
||||
@@ -618,48 +616,6 @@ valgrind_check: $(TESTS)
|
||||
fi; \
|
||||
done
|
||||
|
||||
|
||||
ifneq ($(PAR_TEST),)
|
||||
parloop:
|
||||
ret_bad=0; \
|
||||
for t in $(PAR_TEST); do \
|
||||
echo "===== Running $$t in parallel $(NUM_PAR)";\
|
||||
if [ $(db_test) -eq 1 ]; then \
|
||||
seq $(J) | v="$$t" parallel --gnu 's=$(TMPD)/rdb-{}; export TEST_TMPDIR=$$s;' \
|
||||
'timeout 2m ./db_test --gtest_filter=$$v >> $$s/log-{} 2>1'; \
|
||||
else\
|
||||
seq $(J) | v="./$$t" parallel --gnu 's=$(TMPD)/rdb-{};' \
|
||||
'export TEST_TMPDIR=$$s; timeout 10m $$v >> $$s/log-{} 2>1'; \
|
||||
fi; \
|
||||
ret_code=$$?; \
|
||||
if [ $$ret_code -ne 0 ]; then \
|
||||
ret_bad=$$ret_code; \
|
||||
echo $$t exited with $$ret_code; \
|
||||
fi; \
|
||||
done; \
|
||||
exit $$ret_bad;
|
||||
endif
|
||||
|
||||
all_tests:=$(shell $(test_names))
|
||||
|
||||
parallel_check: $(TESTS)
|
||||
$(AM_V_GEN)if test "$(J)" > 1 \
|
||||
&& (parallel --gnu --help 2>/dev/null) | \
|
||||
grep -q 'GNU Parallel'; \
|
||||
then \
|
||||
echo Running in parallel $(J); \
|
||||
else \
|
||||
echo "Need to have GNU Parallel and J > 1"; exit 1; \
|
||||
fi; \
|
||||
ret_bad=0; \
|
||||
echo $(J);\
|
||||
echo Test Dir: $(TMPD); \
|
||||
seq $(J) | parallel --gnu 's=$(TMPD)/rdb-{}; rm -rf $$s; mkdir $$s'; \
|
||||
$(MAKE) PAR_TEST="$(all_tests)" TMPD=$(TMPD) \
|
||||
J=$(J) db_test=1 parloop; \
|
||||
$(MAKE) PAR_TEST="$(filter-out db_test, $(TESTS))" \
|
||||
TMPD=$(TMPD) J=$(J) db_test=0 parloop;
|
||||
|
||||
analyze: clean
|
||||
$(CLANG_SCAN_BUILD) --use-analyzer=$(CLANG_ANALYZER) \
|
||||
--use-c++=$(CXX) --use-cc=$(CC) --status-bugs \
|
||||
@@ -696,7 +652,7 @@ clean:
|
||||
|
||||
tags:
|
||||
ctags * -R
|
||||
cscope -b `find . -name '*.cc'` `find . -name '*.h'` `find . -name '*.c'`
|
||||
cscope -b `find . -name '*.cc'` `find . -name '*.h'`
|
||||
|
||||
format:
|
||||
build_tools/format-diff.sh
|
||||
@@ -813,9 +769,6 @@ db_universal_compaction_test: db/db_universal_compaction_test.o db/db_test_util.
|
||||
db_wal_test: db/db_wal_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
db_properties_test: db/db_properties_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
db_table_properties_test: db/db_table_properties_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
@@ -1017,7 +970,7 @@ manual_compaction_test: db/manual_compaction_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
filelock_test: util/filelock_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
auto_roll_logger_test: db/auto_roll_logger_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
auto_roll_logger_test: util/auto_roll_logger_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
memtable_list_test: db/memtable_list_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
@@ -1083,11 +1036,7 @@ install: install-static
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
JAVA_INCLUDE = -I$(JAVA_HOME)/include/ -I$(JAVA_HOME)/include/linux
|
||||
ifeq ($(PLATFORM), OS_SOLARIS)
|
||||
ARCH := $(shell isainfo -b)
|
||||
else
|
||||
ARCH := $(shell getconf LONG_BIT)
|
||||
endif
|
||||
ARCH := $(shell getconf LONG_BIT)
|
||||
ROCKSDBJNILIB = librocksdbjni-linux$(ARCH).so
|
||||
ROCKSDB_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-linux$(ARCH).jar
|
||||
ROCKSDB_JAR_ALL = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH).jar
|
||||
@@ -1095,19 +1044,14 @@ ROCKSDB_JAVADOCS_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PA
|
||||
ROCKSDB_SOURCES_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-sources.jar
|
||||
|
||||
ifeq ($(PLATFORM), OS_MACOSX)
|
||||
ROCKSDBJNILIB = librocksdbjni-osx.jnilib
|
||||
ROCKSDB_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-osx.jar
|
||||
ROCKSDBJNILIB = librocksdbjni-osx.jnilib
|
||||
ROCKSDB_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-osx.jar
|
||||
ifneq ("$(wildcard $(JAVA_HOME)/include/darwin)","")
|
||||
JAVA_INCLUDE = -I$(JAVA_HOME)/include -I $(JAVA_HOME)/include/darwin
|
||||
else
|
||||
JAVA_INCLUDE = -I/System/Library/Frameworks/JavaVM.framework/Headers/
|
||||
endif
|
||||
endif
|
||||
ifeq ($(PLATFORM), OS_SOLARIS)
|
||||
ROCKSDBJNILIB = librocksdbjni-solaris$(ARCH).so
|
||||
ROCKSDB_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-solaris$(ARCH).jar
|
||||
JAVA_INCLUDE = -I$(JAVA_HOME)/include/ -I$(JAVA_HOME)/include/solaris
|
||||
endif
|
||||
|
||||
libz.a:
|
||||
-rm -rf zlib-1.2.8
|
||||
@@ -1201,10 +1145,11 @@ jtest: rocksdbjava
|
||||
jdb_bench:
|
||||
cd java;$(MAKE) db_bench;
|
||||
|
||||
commit_prereq: build_tools/rocksdb-lego-determinator \
|
||||
build_tools/precommit_checker.py
|
||||
build_tools/precommit_checker.py unit unit_481 clang_unit tsan asan lite
|
||||
commit-prereq:
|
||||
$(MAKE) clean && $(MAKE) all check;
|
||||
$(MAKE) clean && $(MAKE) jclean && $(MAKE) rocksdbjava;
|
||||
$(MAKE) clean && USE_CLANG=1 $(MAKE) all;
|
||||
$(MAKE) clean && OPT=-DROCKSDB_LITE $(MAKE) static_lib;
|
||||
|
||||
xfunc:
|
||||
for xftest in $(XFUNC_TESTS); do \
|
||||
|
||||
@@ -45,10 +45,4 @@ Airbnb is using RocksDB as a storage engine for their personalized search servic
|
||||
Pinterest's Object Retrieval System uses RocksDB for storage: https://www.youtube.com/watch?v=MtFEVEs_2Vo
|
||||
|
||||
## Smyte
|
||||
[Smyte](https://www.smyte.com/) uses RocksDB as the storage layer for their core key-value storage, high-performance counters and time-windowed HyperLogLog services.
|
||||
|
||||
## Rakuten Marketing
|
||||
[Rakuten Marketing](https://marketing.rakuten.com/) uses RocksDB as the disk cache layer for the real-time bidding service in their Performance DSP.
|
||||
|
||||
## VWO, Wingify
|
||||
[VWO's](https://vwo.com/) Smart Code checker and URL helper uses RocksDB to store all the URLs where VWO's Smart Code is installed.
|
||||
[Smyte](https://www.smyte.com/) uses RocksDB as the storage layer for their core key-value storage, high-performance counters and time-windowed HyperLogLog services.
|
||||
@@ -10,184 +10,13 @@ class FacebookArcanistConfiguration extends ArcanistConfiguration {
|
||||
ArcanistBaseWorkflow $workflow,
|
||||
$error_code) {
|
||||
if ($command == 'diff' && !$workflow->isRawDiffSource()) {
|
||||
$this->startTestsInJenkins($workflow);
|
||||
$this->startTestsInSandcastle($workflow);
|
||||
$this->maybePushToJenkins($workflow);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
/* Run tests in sandcastle */
|
||||
function postURL($diffID, $url) {
|
||||
$cmd = 'echo \'{"diff_id": "' . $diffID . '", '
|
||||
. '"name":"click here for sandcastle tests for D' . $diffID . '", '
|
||||
. '"link":"' . $url . '"}\' | '
|
||||
. 'http_proxy=fwdproxy.any.facebook.com:8080 '
|
||||
. 'https_proxy=fwdproxy.any.facebook.com:8080 arc call-conduit '
|
||||
. 'differential.updateunitresults';
|
||||
shell_exec($cmd);
|
||||
}
|
||||
|
||||
function updateTestCommand($diffID, $test, $status) {
|
||||
$cmd = 'echo \'{"diff_id": "' . $diffID . '", '
|
||||
. '"name":"' . $test . '", '
|
||||
. '"result":"' . $status . '"}\' | '
|
||||
. 'http_proxy=fwdproxy.any.facebook.com:8080 '
|
||||
. 'https_proxy=fwdproxy.any.facebook.com:8080 arc call-conduit '
|
||||
. 'differential.updateunitresults';
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
function updateTest($diffID, $test) {
|
||||
shell_exec($this->updateTestCommand($diffID, $test, "waiting"));
|
||||
}
|
||||
|
||||
function getSteps($diffID, $username, $test) {
|
||||
$arcrc_content = exec("cat ~/.arcrc | gzip -f | base64 -w0");
|
||||
|
||||
// Sandcastle machines don't have arc setup. We copy the user certificate
|
||||
// and authenticate using that in sandcastle
|
||||
$setup = array(
|
||||
"name" => "Setup arcrc",
|
||||
"shell" => "echo " . $arcrc_content . " | base64 --decode"
|
||||
. " | gzip -d > ~/.arcrc",
|
||||
"user" => "root"
|
||||
);
|
||||
|
||||
// arc demands certain permission on its config
|
||||
$fix_permission = array(
|
||||
"name" => "Fix environment",
|
||||
"shell" => "chmod 600 ~/.arcrc",
|
||||
"user" => "root"
|
||||
);
|
||||
|
||||
// fbcode is a sub-repo. We cannot patch until we add it to ignore otherwise
|
||||
// git thinks it is uncommited change
|
||||
$fix_git_ignore = array(
|
||||
"name" => "Fix git ignore",
|
||||
"shell" => "echo fbcode >> .git/info/exclude",
|
||||
"user" => "root"
|
||||
);
|
||||
|
||||
// Patch the code (keep your fingures crossed)
|
||||
$patch = array(
|
||||
"name" => "Patch " . $diffID,
|
||||
"shell" => "HTTPS_PROXY=fwdproxy:8080 arc --arcrc-file ~/.arcrc "
|
||||
. "patch --diff " . $diffID,
|
||||
"user" => "root"
|
||||
);
|
||||
|
||||
// Clean up the user arc config we are using
|
||||
$cleanup = array(
|
||||
"name" => "Arc cleanup",
|
||||
"shell" => "rm -f ~/.arcrc",
|
||||
"user" => "root"
|
||||
);
|
||||
|
||||
// Construct the steps in the order of execution
|
||||
$steps[] = $setup;
|
||||
$steps[] = $fix_permission;
|
||||
$steps[] = $fix_git_ignore;
|
||||
$steps[] = $patch;
|
||||
|
||||
// Run the actual command
|
||||
$this->updateTest($diffID, $test);
|
||||
$cmd = $this->updateTestCommand($diffID, $test, "running") . ";"
|
||||
. "(./build_tools/precommit_checker.py " . $test
|
||||
. "&& "
|
||||
. $this->updateTestCommand($diffID, $test, "pass") . ")"
|
||||
. "|| " . $this->updateTestCommand($diffID, $test, "fail")
|
||||
. "; cat /tmp/precommit-check.log"
|
||||
. "; for f in `ls t/log-*`; do echo \$f; cat \$f; done";
|
||||
|
||||
$run_test = array(
|
||||
"name" => "Run " . $test,
|
||||
"shell" => $cmd,
|
||||
"user" => "root",
|
||||
);
|
||||
|
||||
$steps[] = $run_test;
|
||||
$steps[] = $cleanup;
|
||||
|
||||
return $steps;
|
||||
}
|
||||
|
||||
function startTestsInSandcastle($workflow) {
|
||||
// extract information we need from workflow or CLI
|
||||
$diffID = $workflow->getDiffId();
|
||||
$username = exec("whoami");
|
||||
|
||||
if ($diffID == null || $username == null) {
|
||||
// there is no diff and we can't extract username
|
||||
// we cannot schedule sandcasstle job
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(getenv("ROCKSDB_CHECK_ALL"), 1) == 0) {
|
||||
// extract all tests from the CI definition
|
||||
$output = file_get_contents("build_tools/rocksdb-lego-determinator");
|
||||
preg_match_all('/[ ]{2}([a-zA-Z0-9_]+)[\)]{1}/', $output, $matches);
|
||||
$tests = $matches[1];
|
||||
} else {
|
||||
// manually list of tests we want to run in sandcastle
|
||||
$tests = array(
|
||||
"unit", "unit_481", "clang_unit", "tsan", "asan", "lite", "valgrind"
|
||||
);
|
||||
}
|
||||
|
||||
// construct a job definition for each test and add it to the master plan
|
||||
foreach ($tests as $test) {
|
||||
$arg[] = array(
|
||||
"name" => "RocksDB diff " . $diffID . " test " . $test,
|
||||
"steps" => $this->getSteps($diffID, $username, $test)
|
||||
);
|
||||
}
|
||||
|
||||
// we cannot submit the parallel execution master plan to sandcastle
|
||||
// we need supply the job plan as a determinator
|
||||
// so we construct a small job that will spit out the master job plan
|
||||
// which sandcastle will parse and execute
|
||||
// Why compress ? Otherwise we run over the max string size.
|
||||
$cmd = "echo " . base64_encode(json_encode($arg))
|
||||
. " | gzip -f | base64 -w0";
|
||||
$arg_encoded = shell_exec($cmd);
|
||||
|
||||
$command = array(
|
||||
"name" => "Run diff " . $diffID . "for user " . $username,
|
||||
"steps" => array()
|
||||
);
|
||||
|
||||
$command["steps"][] = array(
|
||||
"name" => "Generate determinator",
|
||||
"shell" => "echo " . $arg_encoded . " | base64 --decode | gzip -d"
|
||||
. " | base64 --decode",
|
||||
"determinator" => true,
|
||||
"user" => "root"
|
||||
);
|
||||
|
||||
// submit to sandcastle
|
||||
$url = 'https://interngraph.intern.facebook.com/sandcastle/generate?'
|
||||
.'command=SandcastleUniversalCommand'
|
||||
.'&vcs=rocksdb-git&revision=origin%2Fmaster&type=lego'
|
||||
.'&user=krad&alias=rocksdb-precommit'
|
||||
.'&command-args=' . urlencode(json_encode($command));
|
||||
|
||||
$cmd = 'https_proxy= HTTPS_PROXY= curl -s -k -F app=659387027470559 '
|
||||
. '-F token=AeO_3f2Ya3TujjnxGD4 "' . $url . '"';
|
||||
|
||||
$output = shell_exec($cmd);
|
||||
|
||||
// extract sandcastle URL from the response
|
||||
preg_match('/url": "(.+)"/', $output, $sandcastle_url);
|
||||
|
||||
echo "\nSandcastle URL: " . $sandcastle_url[1] . "\n";
|
||||
|
||||
// Ask phabricator to display it on the diff UI
|
||||
$this->postURL($diffID, $sandcastle_url[1]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
/* Send off builds to jenkins */
|
||||
function startTestsInJenkins($workflow) {
|
||||
function maybePushToJenkins($workflow) {
|
||||
$diffID = $workflow->getDiffID();
|
||||
if ($diffID === null) {
|
||||
return;
|
||||
@@ -202,4 +31,5 @@ class FacebookArcanistConfiguration extends ArcanistConfiguration {
|
||||
."buildWithParameters?token=AUTH&DIFF_ID=$diffID";
|
||||
system("curl --noproxy '*' \"$url\" > /dev/null 2>&1");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -52,7 +52,12 @@ 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
|
||||
source "$PWD/build_tools/fbcode_config.sh"
|
||||
if [ -z "$ROCKSDB_FBCODE_BUILD_WITH_481" ]; then
|
||||
source "$PWD/build_tools/fbcode_config.sh"
|
||||
else
|
||||
# we need this to build with MySQL. Don't use for other purposes.
|
||||
source "$PWD/build_tools/fbcode_config4.8.1.sh"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Delete existing output, if it exists
|
||||
@@ -354,13 +359,7 @@ if test "$USE_SSE"; then
|
||||
# if Intel SSE instruction set is supported, set USE_SSE=1
|
||||
COMMON_FLAGS="$COMMON_FLAGS -msse -msse4.2 "
|
||||
elif test -z "$PORTABLE"; then
|
||||
if test -n "`echo $TARGET_ARCHITECTURE | grep ^ppc64`"; then
|
||||
# Tune for this POWER processor, treating '+' models as base models
|
||||
POWER=`LD_SHOW_AUXV=1 /bin/true | grep AT_PLATFORM | grep -E -o power[0-9]+`
|
||||
COMMON_FLAGS="$COMMON_FLAGS -mcpu=$POWER -mtune=$POWER "
|
||||
else
|
||||
COMMON_FLAGS="$COMMON_FLAGS -march=native "
|
||||
fi
|
||||
COMMON_FLAGS="$COMMON_FLAGS -march=native "
|
||||
fi
|
||||
|
||||
PLATFORM_CCFLAGS="$PLATFORM_CCFLAGS $COMMON_FLAGS"
|
||||
|
||||
+16
-19
@@ -1,19 +1,16 @@
|
||||
# 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
|
||||
GCC_BASE=/mnt/vol/engshare/fbcode/third-party2/gcc/4.9.x/centos6-native/1317bc4/
|
||||
CLANG_BASE=/mnt/vol/engshare/fbcode/third-party2/clang/3.7.1/centos6-native/9d9ecb9/
|
||||
LIBGCC_BASE=/mnt/gvfs/third-party2/libgcc/ea2fd1278810d3af2ea52218d2767e09d786dbd0/4.9.x/gcc-4.9-glibc-2.20/024dbc3
|
||||
GLIBC_BASE=/mnt/gvfs/third-party2/glibc/f5484f168c0e4d19823d41df052c5870c6e575a4/2.20/gcc-4.9-glibc-2.20/500e281
|
||||
SNAPPY_BASE=/mnt/gvfs/third-party2/snappy/cbf6f1f209e5bd160bdc5d971744e039f36b1566/1.1.3/gcc-4.9-glibc-2.20/e9936bf
|
||||
ZLIB_BASE=/mnt/gvfs/third-party2/zlib/6d39cb54708049f527e713ad19f2aadb9d3667e8/1.2.8/gcc-4.9-glibc-2.20/e9936bf
|
||||
BZIP2_BASE=/mnt/gvfs/third-party2/bzip2/2ddd45f0853bfc8bb1c27f0f447236a1a26c338a/1.0.6/gcc-4.9-glibc-2.20/e9936bf
|
||||
LZ4_BASE=/mnt/gvfs/third-party2/lz4/6858fac689e0f92e584224d91bdb0e39f6c8320d/r131/gcc-4.9-glibc-2.20/e9936bf
|
||||
ZSTD_BASE=/mnt/gvfs/third-party2/zstd/9c833012dea9ae6de1df2cbdcb7aebc57ba2cb39/0.5.0/gcc-4.9-glibc-2.20/e9936bf
|
||||
GFLAGS_BASE=/mnt/gvfs/third-party2/gflags/c7275a4ceae0aca0929e56964a31dafc53c1ee96/2.1.1/gcc-4.8.1-glibc-2.17/c3f970a
|
||||
JEMALLOC_BASE=/mnt/gvfs/third-party2/jemalloc/378c8f95cf28c833e121ca73432101e451c3e62a/4.0.3/gcc-4.9-glibc-2.20/a6c5e1e
|
||||
NUMA_BASE=/mnt/gvfs/third-party2/numa/ae54a5ed22cdabb1c6446dce4e8ffae5b4446d73/2.0.8/gcc-4.9-glibc-2.20/e9936bf
|
||||
LIBUNWIND_BASE=/mnt/gvfs/third-party2/libunwind/303048f72efc92ae079e62dfc84823401aecfd94/trunk/gcc-4.9-glibc-2.20/12266b1
|
||||
KERNEL_HEADERS_BASE=/mnt/gvfs/third-party2/kernel-headers/1a48835975c66d30e47770ec419758ed3b9ba010/3.10.62-62_fbk17_03959_ge29cc63/gcc-4.9-glibc-2.20/da39a3e
|
||||
BINUTILS_BASE=/mnt/gvfs/third-party2/binutils/a5b8152b2a15ce8a98808cf954fbccec825a97bc/2.25/centos6-native/da39a3e
|
||||
VALGRIND_BASE=/mnt/gvfs/third-party2/valgrind/af85c56f424cd5edfc2c97588299b44ecdec96bb/3.10.0/gcc-4.9-glibc-2.20/e9936bf
|
||||
@@ -1,16 +1,16 @@
|
||||
GCC_BASE=/mnt/gvfs/third-party2/gcc/ebc96bc2fb751b5a0300b8d91a95bdf24ac1d88b/4.8.1/centos6-native/cc6c9dc
|
||||
GCC_BASE=/mnt/vol/engshare/fbcode/third-party2/gcc/4.8.1/centos6-native/cc6c9dc/
|
||||
CLANG_BASE=/mnt/vol/engshare/fbcode/third-party2/clang/3.7.1/centos6-native/9d9ecb9/
|
||||
LIBGCC_BASE=/mnt/gvfs/third-party2/libgcc/5710d6a0fb0d12820aac0bffcd7fcb8646e7fff7/4.8.1/gcc-4.8.1-glibc-2.17/8aac7fc
|
||||
GLIBC_BASE=/mnt/gvfs/third-party2/glibc/0600c95b31226b5e535614c590677d87c62d8016/2.17/gcc-4.8.1-glibc-2.17/99df8fc
|
||||
LIBGCC_BASE=/mnt/gvfs/third-party2/libgcc/ea2fd1278810d3af2ea52218d2767e09d786dbd0/4.8.1/gcc-4.8.1-glibc-2.17/8aac7fc
|
||||
GLIBC_BASE=/mnt/gvfs/third-party2/glibc/f5484f168c0e4d19823d41df052c5870c6e575a4/2.17/gcc-4.8.1-glibc-2.17/99df8fc
|
||||
SNAPPY_BASE=/mnt/gvfs/third-party2/snappy/cbf6f1f209e5bd160bdc5d971744e039f36b1566/1.1.3/gcc-4.8.1-glibc-2.17/c3f970a
|
||||
ZLIB_BASE=/mnt/gvfs/third-party2/zlib/6d39cb54708049f527e713ad19f2aadb9d3667e8/1.2.8/gcc-4.8.1-glibc-2.17/c3f970a
|
||||
BZIP2_BASE=/mnt/gvfs/third-party2/bzip2/2ddd45f0853bfc8bb1c27f0f447236a1a26c338a/1.0.6/gcc-4.8.1-glibc-2.17/c3f970a
|
||||
LZ4_BASE=/mnt/gvfs/third-party2/lz4/6858fac689e0f92e584224d91bdb0e39f6c8320d/r131/gcc-4.8.1-glibc-2.17/c3f970a
|
||||
ZSTD_BASE=/mnt/gvfs/third-party2/zstd/69d56740ffb89d8bc81ded8ec428c01a813ea948/0.4.7/gcc-4.8.1-glibc-2.17/c3f970a
|
||||
ZSTD_BASE=/mnt/gvfs/third-party2/zstd/9c833012dea9ae6de1df2cbdcb7aebc57ba2cb39/0.5.0/gcc-4.8.1-glibc-2.17/c3f970a
|
||||
GFLAGS_BASE=/mnt/gvfs/third-party2/gflags/c7275a4ceae0aca0929e56964a31dafc53c1ee96/2.1.1/gcc-4.8.1-glibc-2.17/c3f970a
|
||||
JEMALLOC_BASE=/mnt/gvfs/third-party2/jemalloc/5f0be745ddc0f86f22c8c8bb64b6b1163c93df91/4.0.3/gcc-4.8.1-glibc-2.17/8d31e51
|
||||
JEMALLOC_BASE=/mnt/gvfs/third-party2/jemalloc/378c8f95cf28c833e121ca73432101e451c3e62a/4.0.3/gcc-4.8.1-glibc-2.17/8d31e51
|
||||
NUMA_BASE=/mnt/gvfs/third-party2/numa/ae54a5ed22cdabb1c6446dce4e8ffae5b4446d73/2.0.8/gcc-4.8.1-glibc-2.17/c3f970a
|
||||
LIBUNWIND_BASE=/mnt/gvfs/third-party2/libunwind/121f1a75c4414683aea8c70b761bfaf187f7c1a3/trunk/gcc-4.8.1-glibc-2.17/675d945
|
||||
LIBUNWIND_BASE=/mnt/gvfs/third-party2/libunwind/303048f72efc92ae079e62dfc84823401aecfd94/trunk/gcc-4.8.1-glibc-2.17/675d945
|
||||
KERNEL_HEADERS_BASE=/mnt/gvfs/third-party2/kernel-headers/1a48835975c66d30e47770ec419758ed3b9ba010/3.10.62-62_fbk17_03959_ge29cc63/gcc-4.8.1-glibc-2.17/da39a3e
|
||||
BINUTILS_BASE=/mnt/gvfs/third-party2/binutils/75670d0d8ef4891fd1ec2a7513ef01cd002c823b/2.25/centos6-native/da39a3e
|
||||
BINUTILS_BASE=/mnt/gvfs/third-party2/binutils/a5b8152b2a15ce8a98808cf954fbccec825a97bc/2.25/centos6-native/da39a3e
|
||||
VALGRIND_BASE=/mnt/gvfs/third-party2/valgrind/af85c56f424cd5edfc2c97588299b44ecdec96bb/3.8.1/gcc-4.8.1-glibc-2.17/c3f970a
|
||||
@@ -13,12 +13,12 @@ source "$BASEDIR/dependencies.sh"
|
||||
CFLAGS=""
|
||||
|
||||
# libgcc
|
||||
LIBGCC_INCLUDE="$LIBGCC_BASE/include/c++/7.3.0"
|
||||
LIBGCC_LIBS=" -L $LIBGCC_BASE/lib"
|
||||
LIBGCC_INCLUDE="$LIBGCC_BASE/include"
|
||||
LIBGCC_LIBS=" -L $LIBGCC_BASE/libs"
|
||||
|
||||
# glibc
|
||||
GLIBC_INCLUDE="$GLIBC_BASE/include"
|
||||
GLIBC_LIBS=" -L $GLIBC_BASE/lib"
|
||||
GLIBC_LIBS=" -L $GLIB_BASE/lib"
|
||||
|
||||
# snappy
|
||||
SNAPPY_INCLUDE=" -I $SNAPPY_BASE/include/"
|
||||
@@ -43,15 +43,11 @@ if test -z $PIC_BUILD; then
|
||||
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_INCLUDE=" -I $ZSTD_BASE/include/"
|
||||
ZSTD_LIBS=" $ZSTD_BASE/lib/libzstd.a"
|
||||
else
|
||||
ZSTD_LIBS=" $ZSTD_BASE/lib/libzstd_pic.a"
|
||||
CFLAGS+=" -DZSTD"
|
||||
fi
|
||||
CFLAGS+=" -DZSTD"
|
||||
|
||||
# location of gflags headers and libraries
|
||||
GFLAGS_INCLUDE=" -I $GFLAGS_BASE/include/"
|
||||
@@ -60,7 +56,7 @@ if test -z $PIC_BUILD; then
|
||||
else
|
||||
GFLAGS_LIBS=" $GFLAGS_BASE/lib/libgflags_pic.a"
|
||||
fi
|
||||
CFLAGS+=" -DGFLAGS=gflags"
|
||||
CFLAGS+=" -DGFLAGS=google"
|
||||
|
||||
# location of jemalloc
|
||||
JEMALLOC_INCLUDE=" -I $JEMALLOC_BASE/include/"
|
||||
@@ -76,22 +72,13 @@ if test -z $PIC_BUILD; then
|
||||
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
|
||||
|
||||
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"
|
||||
DEPS_INCLUDE="$SNAPPY_INCLUDE $ZLIB_INCLUDE $BZIP_INCLUDE $LZ4_INCLUDE $ZSTD_INCLUDE $GFLAGS_INCLUDE $NUMA_INCLUDE"
|
||||
|
||||
STDLIBS="-L $GCC_BASE/lib64"
|
||||
|
||||
@@ -100,7 +87,7 @@ 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"
|
||||
CLANG_SCAN_BUILD="$CLANG_SRC/clang/tools/scan-build/scan-build"
|
||||
|
||||
if [ -z "$USE_CLANG" ]; then
|
||||
# gcc
|
||||
@@ -108,45 +95,40 @@ if [ -z "$USE_CLANG" ]; then
|
||||
CXX="$GCC_BASE/bin/g++"
|
||||
|
||||
CFLAGS+=" -B$BINUTILS/gold"
|
||||
CFLAGS+=" -isystem $LIBGCC_INCLUDE"
|
||||
CFLAGS+=" -isystem $GLIBC_INCLUDE"
|
||||
JEMALLOC=1
|
||||
CFLAGS+=" -isystem $LIBGCC_INCLUDE"
|
||||
else
|
||||
# clang
|
||||
CLANG_INCLUDE="$CLANG_LIB/clang/stable/include"
|
||||
CLANG_INCLUDE="$CLANG_LIB/clang/*/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 $LIBGCC_BASE/include/c++/4.9.x "
|
||||
CFLAGS+=" -isystem $LIBGCC_BASE/include/c++/4.9.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"
|
||||
CFLAGS+=" -DROCKSDB_PLATFORM_POSIX -DROCKSDB_LIB_IO_POSIX -DROCKSDB_FALLOCATE_PRESENT -DROCKSDB_MALLOC_USABLE_SIZE"
|
||||
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=" $SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GFLAGS_LIBS $NUMA_LIB"
|
||||
EXEC_LDFLAGS+=" -Wl,--dynamic-linker,/usr/local/fbcode/gcc-4.9-glibc-2.20/lib/ld.so"
|
||||
EXEC_LDFLAGS+=" $LIBUNWIND"
|
||||
EXEC_LDFLAGS+=" -Wl,-rpath=/usr/local/fbcode/platform007/lib"
|
||||
# required by libtbb
|
||||
EXEC_LDFLAGS+=" -ldl"
|
||||
EXEC_LDFLAGS+=" -Wl,-rpath=/usr/local/fbcode/gcc-4.9-glibc-2.20/lib"
|
||||
|
||||
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"
|
||||
EXEC_LDFLAGS_SHARED="$SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GFLAGS_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
|
||||
export CC CXX AR CFLAGS CXXFLAGS EXEC_LDFLAGS EXEC_LDFLAGS_SHARED VALGRIND_VER JEMALLOC_LIB JEMALLOC_INCLUDE CLANG_ANALYZER CLANG_SCAN_BUILD
|
||||
@@ -1,198 +0,0 @@
|
||||
#!/usr/local/fbcode/gcc-4.8.1-glibc-2.17-fb/bin/python2.7
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
import argparse
|
||||
import commands
|
||||
import subprocess
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
import time
|
||||
|
||||
#
|
||||
# Simple logger
|
||||
#
|
||||
|
||||
|
||||
class Log:
|
||||
|
||||
LOG_FILE = "/tmp/precommit-check.log"
|
||||
|
||||
def __init__(self):
|
||||
self.filename = Log.LOG_FILE
|
||||
self.f = open(self.filename, 'w+', 0)
|
||||
|
||||
def caption(self, str):
|
||||
line = "\n##### %s #####\n" % str
|
||||
if self.f:
|
||||
self.f.write("%s \n" % line)
|
||||
else:
|
||||
print(line)
|
||||
|
||||
def error(self, str):
|
||||
data = "\n\n##### ERROR ##### %s" % str
|
||||
if self.f:
|
||||
self.f.write("%s \n" % data)
|
||||
else:
|
||||
print(data)
|
||||
|
||||
def log(self, str):
|
||||
if self.f:
|
||||
self.f.write("%s \n" % str)
|
||||
else:
|
||||
print(str)
|
||||
|
||||
#
|
||||
# Shell Environment
|
||||
#
|
||||
|
||||
|
||||
class Env(object):
|
||||
|
||||
def __init__(self, tests):
|
||||
self.tests = tests
|
||||
self.log = Log()
|
||||
|
||||
def shell(self, cmd, path=os.getcwd()):
|
||||
if path:
|
||||
os.chdir(path)
|
||||
|
||||
self.log.log("==== shell session ===========================")
|
||||
self.log.log("%s> %s" % (path, cmd))
|
||||
status = subprocess.call("cd %s; %s" % (path, cmd), shell=True,
|
||||
stdout=self.log.f, stderr=self.log.f)
|
||||
self.log.log("status = %s" % status)
|
||||
self.log.log("============================================== \n\n")
|
||||
return status
|
||||
|
||||
def GetOutput(self, cmd, path=os.getcwd()):
|
||||
if path:
|
||||
os.chdir(path)
|
||||
|
||||
self.log.log("==== shell session ===========================")
|
||||
self.log.log("%s> %s" % (path, cmd))
|
||||
status, out = commands.getstatusoutput(cmd)
|
||||
self.log.log("status = %s" % status)
|
||||
self.log.log("out = %s" % out)
|
||||
self.log.log("============================================== \n\n")
|
||||
return status, out
|
||||
|
||||
#
|
||||
# Pre-commit checker
|
||||
#
|
||||
|
||||
|
||||
class PreCommitChecker(Env):
|
||||
|
||||
def __init__(self, tests):
|
||||
Env.__init__(self, tests)
|
||||
|
||||
#
|
||||
# Get commands for a given job from the determinator file
|
||||
#
|
||||
def get_commands(self, test):
|
||||
status, out = self.GetOutput(
|
||||
"build_tools/rocksdb-lego-determinator %s" % test, ".")
|
||||
return status, out
|
||||
|
||||
#
|
||||
# Run a specific CI job
|
||||
#
|
||||
def run_test(self, test):
|
||||
self.log.caption("Running test %s locally" % test)
|
||||
|
||||
# get commands for the CI job determinator
|
||||
status, cmds = self.get_commands(test)
|
||||
if status != 0:
|
||||
self.log.error("Error getting commands for test %s" % test)
|
||||
return False
|
||||
|
||||
# Parse the JSON to extract the commands to run
|
||||
cmds = re.findall("'shell':'([^\']*)'", cmds)
|
||||
|
||||
if len(cmds) == 0:
|
||||
self.log.log("No commands found")
|
||||
return False
|
||||
|
||||
# Run commands
|
||||
for cmd in cmds:
|
||||
# Replace J=<..> with the local environment variable
|
||||
if "J" in os.environ:
|
||||
cmd = cmd.replace("J=1", "J=%s" % os.environ["J"])
|
||||
cmd = cmd.replace("make ", "make -j%s " % os.environ["J"])
|
||||
# Run the command
|
||||
status = self.shell(cmd, ".")
|
||||
if status != 0:
|
||||
self.log.error("Error running command %s for test %s"
|
||||
% (cmd, test))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
#
|
||||
# Run specified CI jobs
|
||||
#
|
||||
def run_tests(self):
|
||||
if not self.tests:
|
||||
self.log.error("Invalid args. Please provide tests")
|
||||
return False
|
||||
|
||||
self.print_separator()
|
||||
self.print_row("TEST", "RESULT")
|
||||
self.print_separator()
|
||||
|
||||
for test in self.tests:
|
||||
start_time = time.time()
|
||||
self.print_test(test)
|
||||
result = self.run_test(test)
|
||||
elapsed_min = (time.time() - start_time) / 60
|
||||
if not result:
|
||||
self.log.error("Error running test %s" % test)
|
||||
self.print_result("FAIL (%dm)" % elapsed_min)
|
||||
return False
|
||||
self.print_result("PASS (%dm)" % elapsed_min)
|
||||
|
||||
self.print_separator()
|
||||
return True
|
||||
|
||||
#
|
||||
# Print a line
|
||||
#
|
||||
def print_separator(self):
|
||||
print("".ljust(60, "-"))
|
||||
|
||||
#
|
||||
# Print two colums
|
||||
#
|
||||
def print_row(self, c0, c1):
|
||||
print("%s%s" % (c0.ljust(40), c1.ljust(20)))
|
||||
|
||||
def print_test(self, test):
|
||||
print(test.ljust(40), end="")
|
||||
sys.stdout.flush()
|
||||
|
||||
def print_result(self, result):
|
||||
print(result.ljust(20))
|
||||
|
||||
#
|
||||
# Main
|
||||
#
|
||||
parser = argparse.ArgumentParser(description='RocksDB pre-commit checker.')
|
||||
|
||||
# <test ....>
|
||||
parser.add_argument('test', nargs='+',
|
||||
help='CI test(s) to run. e.g: unit punit asan tsan')
|
||||
|
||||
print("Please follow log %s" % Log.LOG_FILE)
|
||||
|
||||
args = parser.parse_args()
|
||||
checker = PreCommitChecker(args.test)
|
||||
|
||||
if not checker.run_tests():
|
||||
print("Error running tests. Please check log file %s" % Log.LOG_FILE)
|
||||
sys.exit(1)
|
||||
|
||||
sys.exit(0)
|
||||
@@ -64,8 +64,8 @@ touch "$OUTPUT"
|
||||
echo "Writing dependencies to $OUTPUT"
|
||||
|
||||
# Compilers locations
|
||||
GCC_BASE=`readlink -f $TP2_LATEST/gcc/4.9.x/centos6-native/*/`
|
||||
CLANG_BASE=`readlink -f $TP2_LATEST/llvm-fb/stable/centos6-native/*/`
|
||||
GCC_BASE=`ls -d1 $TP2_LATEST/gcc/4.9.x/centos6-native/*/ | head -n1`
|
||||
CLANG_BASE=`ls -d1 $TP2_LATEST/clang/3.7.1/centos6-native/*/ | head -n1`
|
||||
|
||||
log_variable GCC_BASE
|
||||
log_variable CLANG_BASE
|
||||
@@ -101,8 +101,8 @@ touch "$OUTPUT"
|
||||
echo "Writing 4.8.1 dependencies to $OUTPUT"
|
||||
|
||||
# Compilers locations
|
||||
GCC_BASE=`readlink -f $TP2_LATEST/gcc/4.8.1/centos6-native/*/`
|
||||
CLANG_BASE=`readlink -f $TP2_LATEST/llvm-fb/stable/centos6-native/*/`
|
||||
GCC_BASE=`ls -d1 $TP2_LATEST/gcc/4.8.1/centos6-native/*/ | head -n1`
|
||||
CLANG_BASE=`ls -d1 $TP2_LATEST/clang/3.7.1/centos6-native/*/ | head -n1`
|
||||
|
||||
log_variable GCC_BASE
|
||||
log_variable CLANG_BASE
|
||||
|
||||
+15
-64
@@ -243,17 +243,6 @@ ColumnFamilyOptions SanitizeOptions(const DBOptions& db_options,
|
||||
result.level0_slowdown_writes_trigger,
|
||||
result.level0_file_num_compaction_trigger);
|
||||
}
|
||||
|
||||
if (result.soft_pending_compaction_bytes_limit == 0) {
|
||||
result.soft_pending_compaction_bytes_limit =
|
||||
result.hard_pending_compaction_bytes_limit;
|
||||
} else if (result.hard_pending_compaction_bytes_limit > 0 &&
|
||||
result.soft_pending_compaction_bytes_limit >
|
||||
result.hard_pending_compaction_bytes_limit) {
|
||||
result.soft_pending_compaction_bytes_limit =
|
||||
result.hard_pending_compaction_bytes_limit;
|
||||
}
|
||||
|
||||
if (result.level_compaction_dynamic_level_bytes) {
|
||||
if (result.compaction_style != kCompactionStyleLevel ||
|
||||
db_options.db_paths.size() > 1U) {
|
||||
@@ -528,21 +517,6 @@ std::unique_ptr<WriteControllerToken> SetupDelay(
|
||||
}
|
||||
return write_controller->GetDelayToken(write_rate);
|
||||
}
|
||||
|
||||
int GetL0ThresholdSpeedupCompaction(int level0_file_num_compaction_trigger,
|
||||
int level0_slowdown_writes_trigger) {
|
||||
// SanitizeOptions() ensures it.
|
||||
assert(level0_file_num_compaction_trigger <= level0_slowdown_writes_trigger);
|
||||
|
||||
// 1/4 of the way between L0 compaction trigger threshold and slowdown
|
||||
// condition.
|
||||
// Or twice as compaction trigger, if it is smaller.
|
||||
return std::min(level0_file_num_compaction_trigger * 2,
|
||||
level0_file_num_compaction_trigger +
|
||||
(level0_slowdown_writes_trigger -
|
||||
level0_file_num_compaction_trigger) /
|
||||
4);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void ColumnFamilyData::RecalculateWriteStallConditions(
|
||||
@@ -561,6 +535,21 @@ void ColumnFamilyData::RecalculateWriteStallConditions(
|
||||
"(waiting for flush), max_write_buffer_number is set to %d",
|
||||
name_.c_str(), imm()->NumNotFlushed(),
|
||||
mutable_cf_options.max_write_buffer_number);
|
||||
} else if (mutable_cf_options.max_write_buffer_number > 3 &&
|
||||
imm()->NumNotFlushed() >=
|
||||
mutable_cf_options.max_write_buffer_number - 1) {
|
||||
write_controller_token_ =
|
||||
SetupDelay(ioptions_.delayed_write_rate, write_controller,
|
||||
compaction_needed_bytes, prev_compaction_needed_bytes_,
|
||||
mutable_cf_options.disable_auto_compactions);
|
||||
internal_stats_->AddCFStats(InternalStats::MEMTABLE_SLOWDOWN, 1);
|
||||
Log(InfoLogLevel::WARN_LEVEL, ioptions_.info_log,
|
||||
"[%s] Stalling writes because we have %d immutable memtables "
|
||||
"(waiting for flush), max_write_buffer_number is set to %d "
|
||||
"rate %" PRIu64,
|
||||
name_.c_str(), imm()->NumNotFlushed(),
|
||||
mutable_cf_options.max_write_buffer_number,
|
||||
write_controller->delayed_write_rate());
|
||||
} else if (vstorage->l0_delay_trigger_count() >=
|
||||
mutable_cf_options.level0_stop_writes_trigger) {
|
||||
write_controller_token_ = write_controller->GetStopToken();
|
||||
@@ -582,21 +571,6 @@ void ColumnFamilyData::RecalculateWriteStallConditions(
|
||||
"[%s] Stopping writes because of estimated pending compaction "
|
||||
"bytes %" PRIu64,
|
||||
name_.c_str(), compaction_needed_bytes);
|
||||
} else if (mutable_cf_options.max_write_buffer_number > 3 &&
|
||||
imm()->NumNotFlushed() >=
|
||||
mutable_cf_options.max_write_buffer_number - 1) {
|
||||
write_controller_token_ =
|
||||
SetupDelay(ioptions_.delayed_write_rate, write_controller,
|
||||
compaction_needed_bytes, prev_compaction_needed_bytes_,
|
||||
mutable_cf_options.disable_auto_compactions);
|
||||
internal_stats_->AddCFStats(InternalStats::MEMTABLE_SLOWDOWN, 1);
|
||||
Log(InfoLogLevel::WARN_LEVEL, ioptions_.info_log,
|
||||
"[%s] Stalling writes because we have %d immutable memtables "
|
||||
"(waiting for flush), max_write_buffer_number is set to %d "
|
||||
"rate %" PRIu64,
|
||||
name_.c_str(), imm()->NumNotFlushed(),
|
||||
mutable_cf_options.max_write_buffer_number,
|
||||
write_controller->delayed_write_rate());
|
||||
} else if (mutable_cf_options.level0_slowdown_writes_trigger >= 0 &&
|
||||
vstorage->l0_delay_trigger_count() >=
|
||||
mutable_cf_options.level0_slowdown_writes_trigger) {
|
||||
@@ -628,29 +602,6 @@ void ColumnFamilyData::RecalculateWriteStallConditions(
|
||||
"bytes %" PRIu64 " rate %" PRIu64,
|
||||
name_.c_str(), vstorage->estimated_compaction_needed_bytes(),
|
||||
write_controller->delayed_write_rate());
|
||||
} else if (vstorage->l0_delay_trigger_count() >=
|
||||
GetL0ThresholdSpeedupCompaction(
|
||||
mutable_cf_options.level0_file_num_compaction_trigger,
|
||||
mutable_cf_options.level0_slowdown_writes_trigger)) {
|
||||
write_controller_token_ = write_controller->GetCompactionPressureToken();
|
||||
Log(InfoLogLevel::WARN_LEVEL, ioptions_.info_log,
|
||||
"[%s] Increasing compaction threads because we have %d level-0 "
|
||||
"files ",
|
||||
name_.c_str(), vstorage->l0_delay_trigger_count());
|
||||
} else if (vstorage->estimated_compaction_needed_bytes() >=
|
||||
mutable_cf_options.soft_pending_compaction_bytes_limit / 4) {
|
||||
// Increase compaction threads if bytes needed for compaction exceeds
|
||||
// 1/4 of threshold for slowing down.
|
||||
// If soft pending compaction byte limit is not set, always speed up
|
||||
// compaction.
|
||||
write_controller_token_ = write_controller->GetCompactionPressureToken();
|
||||
if (mutable_cf_options.soft_pending_compaction_bytes_limit > 0) {
|
||||
Log(InfoLogLevel::WARN_LEVEL, ioptions_.info_log,
|
||||
"[%s] Increasing compaction threads because of estimated pending "
|
||||
"compaction "
|
||||
"bytes %" PRIu64,
|
||||
name_.c_str(), vstorage->estimated_compaction_needed_bytes());
|
||||
}
|
||||
} else {
|
||||
write_controller_token_.reset();
|
||||
}
|
||||
|
||||
+3
-146
@@ -65,7 +65,6 @@ class ColumnFamilyTest : public testing::Test {
|
||||
|
||||
~ColumnFamilyTest() {
|
||||
Close();
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
Destroy();
|
||||
delete env_;
|
||||
}
|
||||
@@ -2000,9 +1999,7 @@ TEST_F(ColumnFamilyTest, FlushAndDropRaceCondition) {
|
||||
Reopen({options, options});
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->LoadDependency(
|
||||
{{"VersionSet::LogAndApply::ColumnFamilyDrop:0",
|
||||
"FlushJob::WriteLevel0Table"},
|
||||
{"VersionSet::LogAndApply::ColumnFamilyDrop:1",
|
||||
{{"VersionSet::LogAndApply::ColumnFamilyDrop:1",
|
||||
"FlushJob::InstallResults"},
|
||||
{"FlushJob::InstallResults",
|
||||
"VersionSet::LogAndApply::ColumnFamilyDrop:2"}});
|
||||
@@ -2048,6 +2045,7 @@ TEST_F(ColumnFamilyTest, FlushAndDropRaceCondition) {
|
||||
|
||||
Close();
|
||||
Destroy();
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
}
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
@@ -2125,6 +2123,7 @@ TEST_F(ColumnFamilyTest, CreateAndDropRace) {
|
||||
drop_cf_thread.join();
|
||||
Close();
|
||||
Destroy();
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
for (auto* comparator : comparators) {
|
||||
if (comparator) {
|
||||
delete comparator;
|
||||
@@ -2136,9 +2135,6 @@ TEST_F(ColumnFamilyTest, CreateAndDropRace) {
|
||||
TEST_F(ColumnFamilyTest, WriteStallSingleColumnFamily) {
|
||||
const uint64_t kBaseRate = 810000u;
|
||||
db_options_.delayed_write_rate = kBaseRate;
|
||||
db_options_.base_background_compactions = 2;
|
||||
db_options_.max_background_compactions = 6;
|
||||
|
||||
Open({"default"});
|
||||
ColumnFamilyData* cfd =
|
||||
static_cast<ColumnFamilyHandleImpl*>(db_->DefaultColumnFamily())->cfd();
|
||||
@@ -2164,7 +2160,6 @@ TEST_F(ColumnFamilyTest, WriteStallSingleColumnFamily) {
|
||||
ASSERT_TRUE(!dbfull()->TEST_write_controler().IsStopped());
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate, dbfull()->TEST_write_controler().delayed_write_rate());
|
||||
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(400);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
@@ -2172,7 +2167,6 @@ TEST_F(ColumnFamilyTest, WriteStallSingleColumnFamily) {
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate / 1.2,
|
||||
dbfull()->TEST_write_controler().delayed_write_rate());
|
||||
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(500);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
@@ -2228,7 +2222,6 @@ TEST_F(ColumnFamilyTest, WriteStallSingleColumnFamily) {
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().IsStopped());
|
||||
ASSERT_TRUE(!dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(3001);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
@@ -2253,7 +2246,6 @@ TEST_F(ColumnFamilyTest, WriteStallSingleColumnFamily) {
|
||||
ASSERT_TRUE(dbfull()->TEST_write_controler().NeedsDelay());
|
||||
ASSERT_EQ(kBaseRate / 1.2,
|
||||
dbfull()->TEST_write_controler().delayed_write_rate());
|
||||
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(101);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
@@ -2326,73 +2318,6 @@ TEST_F(ColumnFamilyTest, WriteStallSingleColumnFamily) {
|
||||
dbfull()->TEST_write_controler().delayed_write_rate());
|
||||
}
|
||||
|
||||
TEST_F(ColumnFamilyTest, CompactionSpeedupSingleColumnFamily) {
|
||||
db_options_.base_background_compactions = 2;
|
||||
db_options_.max_background_compactions = 6;
|
||||
Open({"default"});
|
||||
ColumnFamilyData* cfd =
|
||||
static_cast<ColumnFamilyHandleImpl*>(db_->DefaultColumnFamily())->cfd();
|
||||
|
||||
VersionStorageInfo* vstorage = cfd->current()->storage_info();
|
||||
|
||||
MutableCFOptions mutable_cf_options(
|
||||
Options(db_options_, column_family_options_),
|
||||
ImmutableCFOptions(Options(db_options_, column_family_options_)));
|
||||
|
||||
// Speed up threshold = min(4 * 2, 4 + (36 - 4)/4) = 8
|
||||
mutable_cf_options.level0_file_num_compaction_trigger = 4;
|
||||
mutable_cf_options.level0_slowdown_writes_trigger = 36;
|
||||
mutable_cf_options.level0_stop_writes_trigger = 50;
|
||||
// Speedup threshold = 200 / 4 = 50
|
||||
mutable_cf_options.soft_pending_compaction_bytes_limit = 200;
|
||||
mutable_cf_options.hard_pending_compaction_bytes_limit = 2000;
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(40);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(50);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(300);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(45);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(7);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(9);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(6);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
// Speed up threshold = min(4 * 2, 4 + (12 - 4)/4) = 6
|
||||
mutable_cf_options.level0_file_num_compaction_trigger = 4;
|
||||
mutable_cf_options.level0_slowdown_writes_trigger = 16;
|
||||
mutable_cf_options.level0_stop_writes_trigger = 30;
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(5);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(7);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(3);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed());
|
||||
}
|
||||
|
||||
TEST_F(ColumnFamilyTest, WriteStallTwoColumnFamilies) {
|
||||
const uint64_t kBaseRate = 810000u;
|
||||
db_options_.delayed_write_rate = kBaseRate;
|
||||
@@ -2474,74 +2399,6 @@ TEST_F(ColumnFamilyTest, WriteStallTwoColumnFamilies) {
|
||||
ASSERT_EQ(kBaseRate / 1.2,
|
||||
dbfull()->TEST_write_controler().delayed_write_rate());
|
||||
}
|
||||
|
||||
TEST_F(ColumnFamilyTest, CompactionSpeedupTwoColumnFamilies) {
|
||||
db_options_.base_background_compactions = 2;
|
||||
db_options_.max_background_compactions = 6;
|
||||
column_family_options_.soft_pending_compaction_bytes_limit = 200;
|
||||
column_family_options_.hard_pending_compaction_bytes_limit = 2000;
|
||||
Open();
|
||||
CreateColumnFamilies({"one"});
|
||||
ColumnFamilyData* cfd =
|
||||
static_cast<ColumnFamilyHandleImpl*>(db_->DefaultColumnFamily())->cfd();
|
||||
VersionStorageInfo* vstorage = cfd->current()->storage_info();
|
||||
|
||||
ColumnFamilyData* cfd1 =
|
||||
static_cast<ColumnFamilyHandleImpl*>(handles_[1])->cfd();
|
||||
VersionStorageInfo* vstorage1 = cfd1->current()->storage_info();
|
||||
|
||||
MutableCFOptions mutable_cf_options(
|
||||
Options(db_options_, column_family_options_),
|
||||
ImmutableCFOptions(Options(db_options_, column_family_options_)));
|
||||
// Speed up threshold = min(4 * 2, 4 + (36 - 4)/4) = 8
|
||||
mutable_cf_options.level0_file_num_compaction_trigger = 4;
|
||||
mutable_cf_options.level0_slowdown_writes_trigger = 36;
|
||||
mutable_cf_options.level0_stop_writes_trigger = 30;
|
||||
// Speedup threshold = 200 / 4 = 50
|
||||
mutable_cf_options.soft_pending_compaction_bytes_limit = 200;
|
||||
mutable_cf_options.hard_pending_compaction_bytes_limit = 2000;
|
||||
|
||||
MutableCFOptions mutable_cf_options1 = mutable_cf_options;
|
||||
mutable_cf_options1.level0_slowdown_writes_trigger = 16;
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(40);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(60);
|
||||
cfd1->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed());
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(30);
|
||||
cfd1->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(70);
|
||||
cfd1->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(20);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(3);
|
||||
cfd1->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(9);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage1->set_l0_delay_trigger_count(2);
|
||||
cfd1->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->BGCompactionsAllowed());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(0);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(2, dbfull()->BGCompactionsAllowed());
|
||||
}
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "rocksdb/db.h"
|
||||
@@ -143,6 +142,9 @@ TEST_F(CompactFilesTest, ObsoleteFiles) {
|
||||
}
|
||||
|
||||
auto l0_files = collector->GetFlushedFiles();
|
||||
CompactionOptions compact_opt;
|
||||
compact_opt.compression = kNoCompression;
|
||||
compact_opt.output_file_size_limit = kWriteBufferSize * 5;
|
||||
ASSERT_OK(db->CompactFiles(CompactionOptions(), l0_files, 1));
|
||||
|
||||
// verify all compaction input files are deleted
|
||||
@@ -152,62 +154,6 @@ TEST_F(CompactFilesTest, ObsoleteFiles) {
|
||||
delete db;
|
||||
}
|
||||
|
||||
TEST_F(CompactFilesTest, CapturingPendingFiles) {
|
||||
Options options;
|
||||
options.create_if_missing = true;
|
||||
// Disable RocksDB background compaction.
|
||||
options.compaction_style = kCompactionStyleNone;
|
||||
// Always do full scans for obsolete files (needed to reproduce the issue).
|
||||
options.delete_obsolete_files_period_micros = 0;
|
||||
|
||||
// Add listener.
|
||||
FlushedFileCollector* collector = new FlushedFileCollector();
|
||||
options.listeners.emplace_back(collector);
|
||||
|
||||
DB* db = nullptr;
|
||||
DestroyDB(db_name_, options);
|
||||
Status s = DB::Open(options, db_name_, &db);
|
||||
assert(s.ok());
|
||||
assert(db);
|
||||
|
||||
// Create 5 files.
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
db->Put(WriteOptions(), "key" + ToString(i), "value");
|
||||
db->Flush(FlushOptions());
|
||||
}
|
||||
|
||||
auto l0_files = collector->GetFlushedFiles();
|
||||
EXPECT_EQ(5, l0_files.size());
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->LoadDependency({
|
||||
{"CompactFilesImpl:2", "CompactFilesTest.CapturingPendingFiles:0"},
|
||||
{"CompactFilesTest.CapturingPendingFiles:1", "CompactFilesImpl:3"},
|
||||
});
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
// Start compacting files.
|
||||
std::thread compaction_thread(
|
||||
[&] { EXPECT_OK(db->CompactFiles(CompactionOptions(), l0_files, 1)); });
|
||||
|
||||
// In the meantime flush another file.
|
||||
TEST_SYNC_POINT("CompactFilesTest.CapturingPendingFiles:0");
|
||||
db->Put(WriteOptions(), "key5", "value");
|
||||
db->Flush(FlushOptions());
|
||||
TEST_SYNC_POINT("CompactFilesTest.CapturingPendingFiles:1");
|
||||
|
||||
compaction_thread.join();
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
|
||||
delete db;
|
||||
|
||||
// Make sure we can reopen the DB.
|
||||
s = DB::Open(options, db_name_, &db);
|
||||
ASSERT_TRUE(s.ok());
|
||||
assert(db);
|
||||
delete db;
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
+9
-15
@@ -51,7 +51,6 @@
|
||||
#include "util/iostats_context_imp.h"
|
||||
#include "util/log_buffer.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/sst_file_manager_impl.h"
|
||||
#include "util/mutexlock.h"
|
||||
#include "util/perf_context_imp.h"
|
||||
#include "util/stop_watch.h"
|
||||
@@ -238,9 +237,7 @@ CompactionJob::CompactionJob(
|
||||
paranoid_file_checks_(paranoid_file_checks),
|
||||
measure_io_stats_(measure_io_stats) {
|
||||
assert(log_buffer_ != nullptr);
|
||||
const auto* cfd = compact_->compaction->column_family_data();
|
||||
ThreadStatusUtil::SetColumnFamily(cfd, cfd->ioptions()->env,
|
||||
cfd->options()->enable_thread_tracking);
|
||||
ThreadStatusUtil::SetColumnFamily(compact_->compaction->column_family_data());
|
||||
ThreadStatusUtil::SetThreadOperation(ThreadStatus::OP_COMPACTION);
|
||||
ReportStartedCompaction(compaction);
|
||||
}
|
||||
@@ -252,9 +249,8 @@ CompactionJob::~CompactionJob() {
|
||||
|
||||
void CompactionJob::ReportStartedCompaction(
|
||||
Compaction* compaction) {
|
||||
const auto* cfd = compact_->compaction->column_family_data();
|
||||
ThreadStatusUtil::SetColumnFamily(cfd, cfd->ioptions()->env,
|
||||
cfd->options()->enable_thread_tracking);
|
||||
ThreadStatusUtil::SetColumnFamily(
|
||||
compact_->compaction->column_family_data());
|
||||
|
||||
ThreadStatusUtil::SetThreadOperationProperty(
|
||||
ThreadStatus::COMPACTION_JOB_ID,
|
||||
@@ -419,9 +415,12 @@ void CompactionJob::GenSubcompactionBoundaries() {
|
||||
|
||||
// Group the ranges into subcompactions
|
||||
const double min_file_fill_percent = 4.0 / 5;
|
||||
uint64_t max_output_files = static_cast<uint64_t>(std::ceil(
|
||||
sum / min_file_fill_percent /
|
||||
cfd->GetCurrentMutableCFOptions()->MaxFileSizeForLevel(out_lvl)));
|
||||
uint64_t max_output_files =
|
||||
static_cast<uint64_t>(
|
||||
std::ceil(
|
||||
sum / min_file_fill_percent /
|
||||
cfd->GetCurrentMutableCFOptions()->MaxFileSizeForLevel(out_lvl))
|
||||
);
|
||||
uint64_t subcompactions =
|
||||
std::min({static_cast<uint64_t>(ranges.size()),
|
||||
static_cast<uint64_t>(db_options_.max_subcompactions),
|
||||
@@ -499,16 +498,11 @@ Status CompactionJob::Run() {
|
||||
}
|
||||
|
||||
TablePropertiesCollection tp;
|
||||
auto sfm =
|
||||
static_cast<SstFileManagerImpl*>(db_options_.sst_file_manager.get());
|
||||
for (const auto& state : compact_->sub_compact_states) {
|
||||
for (const auto& output : state.outputs) {
|
||||
auto fn = TableFileName(db_options_.db_paths, output.meta.fd.GetNumber(),
|
||||
output.meta.fd.GetPathId());
|
||||
tp[fn] = output.table_properties;
|
||||
if (sfm && output.meta.fd.GetPathId() == 0) {
|
||||
sfm->OnAddFile(fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
compact_->compaction->SetOutputTableProperties(std::move(tp));
|
||||
|
||||
@@ -2262,7 +2262,6 @@ class Benchmark {
|
||||
|
||||
// Compress 1G
|
||||
while (ok && bytes < int64_t(1) << 30) {
|
||||
compressed.clear();
|
||||
ok = CompressSlice(input, &compressed);
|
||||
produced += compressed.size();
|
||||
bytes += input.size();
|
||||
|
||||
+1
-118
@@ -533,104 +533,6 @@ TEST_P(DBCompactionTestWithParam, CompactionTrigger) {
|
||||
ASSERT_EQ(NumTableFilesAtLevel(1, 1), 1);
|
||||
}
|
||||
|
||||
TEST_F(DBCompactionTest, BGCompactionsAllowed) {
|
||||
// Create several column families. Make compaction triggers in all of them
|
||||
// and see number of compactions scheduled to be less than allowed.
|
||||
const int kNumKeysPerFile = 100;
|
||||
|
||||
Options options;
|
||||
options.write_buffer_size = 110 << 10; // 110KB
|
||||
options.arena_block_size = 4 << 10;
|
||||
options.num_levels = 3;
|
||||
// Should speed up compaction when there are 4 files.
|
||||
options.level0_file_num_compaction_trigger = 2;
|
||||
options.level0_slowdown_writes_trigger = 20;
|
||||
options.soft_pending_compaction_bytes_limit = 1 << 30; // Infinitely large
|
||||
options.base_background_compactions = 1;
|
||||
options.max_background_compactions = 3;
|
||||
options.memtable_factory.reset(new SpecialSkipListFactory(kNumKeysPerFile));
|
||||
options = CurrentOptions(options);
|
||||
|
||||
// Block all threads in thread pool.
|
||||
const size_t kTotalTasks = 4;
|
||||
env_->SetBackgroundThreads(4, Env::LOW);
|
||||
test::SleepingBackgroundTask sleeping_tasks[kTotalTasks];
|
||||
for (size_t i = 0; i < kTotalTasks; i++) {
|
||||
env_->Schedule(&test::SleepingBackgroundTask::DoSleepTask,
|
||||
&sleeping_tasks[i], Env::Priority::LOW);
|
||||
sleeping_tasks[i].WaitUntilSleeping();
|
||||
}
|
||||
|
||||
CreateAndReopenWithCF({"one", "two", "three"}, options);
|
||||
|
||||
Random rnd(301);
|
||||
for (int cf = 0; cf < 4; cf++) {
|
||||
for (int num = 0; num < options.level0_file_num_compaction_trigger; num++) {
|
||||
for (int i = 0; i < kNumKeysPerFile; i++) {
|
||||
ASSERT_OK(Put(cf, Key(i), ""));
|
||||
}
|
||||
// put extra key to trigger flush
|
||||
ASSERT_OK(Put(cf, "", ""));
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[cf]);
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0, cf), num + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Now all column families qualify compaction but only one should be
|
||||
// scheduled, because no column family hits speed up condition.
|
||||
ASSERT_EQ(1, env_->GetThreadPoolQueueLen(Env::Priority::LOW));
|
||||
|
||||
// Create two more files for one column family, which triggers speed up
|
||||
// condition, three compactions will be scheduled.
|
||||
for (int num = 0; num < options.level0_file_num_compaction_trigger; num++) {
|
||||
for (int i = 0; i < kNumKeysPerFile; i++) {
|
||||
ASSERT_OK(Put(2, Key(i), ""));
|
||||
}
|
||||
// put extra key to trigger flush
|
||||
ASSERT_OK(Put(2, "", ""));
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[2]);
|
||||
ASSERT_EQ(options.level0_file_num_compaction_trigger + num + 1,
|
||||
NumTableFilesAtLevel(0, 2));
|
||||
}
|
||||
ASSERT_EQ(3, env_->GetThreadPoolQueueLen(Env::Priority::LOW));
|
||||
|
||||
// Unblock all threads to unblock all compactions.
|
||||
for (size_t i = 0; i < kTotalTasks; i++) {
|
||||
sleeping_tasks[i].WakeUp();
|
||||
sleeping_tasks[i].WaitUntilDone();
|
||||
}
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
|
||||
// Verify number of compactions allowed will come back to 1.
|
||||
|
||||
for (size_t i = 0; i < kTotalTasks; i++) {
|
||||
sleeping_tasks[i].Reset();
|
||||
env_->Schedule(&test::SleepingBackgroundTask::DoSleepTask,
|
||||
&sleeping_tasks[i], Env::Priority::LOW);
|
||||
sleeping_tasks[i].WaitUntilSleeping();
|
||||
}
|
||||
for (int cf = 0; cf < 4; cf++) {
|
||||
for (int num = 0; num < options.level0_file_num_compaction_trigger; num++) {
|
||||
for (int i = 0; i < kNumKeysPerFile; i++) {
|
||||
ASSERT_OK(Put(cf, Key(i), ""));
|
||||
}
|
||||
// put extra key to trigger flush
|
||||
ASSERT_OK(Put(cf, "", ""));
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[cf]);
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0, cf), num + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Now all column families qualify compaction but only one should be
|
||||
// scheduled, because no column family hits speed up condition.
|
||||
ASSERT_EQ(1, env_->GetThreadPoolQueueLen(Env::Priority::LOW));
|
||||
|
||||
for (size_t i = 0; i < kTotalTasks; i++) {
|
||||
sleeping_tasks[i].WakeUp();
|
||||
sleeping_tasks[i].WaitUntilDone();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(DBCompactionTestWithParam, CompactionsGenerateMultipleFiles) {
|
||||
Options options;
|
||||
options.write_buffer_size = 100000000; // Large write buffer
|
||||
@@ -1996,7 +1898,7 @@ TEST_P(DBCompactionTestWithParam, DISABLED_CompactFilesOnLevelCompaction) {
|
||||
std::set<std::string> overlapping_file_names;
|
||||
std::vector<std::string> compaction_input_file_names;
|
||||
for (int f = 0; f < file_picked; ++f) {
|
||||
int level = 0;
|
||||
int level;
|
||||
auto file_meta = PickFileRandomly(cf_meta, &rnd, &level);
|
||||
compaction_input_file_names.push_back(file_meta->name);
|
||||
GetOverlappingFileNumbersForLevelCompaction(
|
||||
@@ -2296,25 +2198,6 @@ TEST_P(DBCompactionTestWithParam, CompressLevelCompaction) {
|
||||
Destroy(options);
|
||||
}
|
||||
|
||||
TEST_F(DBCompactionTest, SanitizeCompactionOptionsTest) {
|
||||
Options options = CurrentOptions();
|
||||
options.max_background_compactions = 5;
|
||||
options.soft_pending_compaction_bytes_limit = 0;
|
||||
options.hard_pending_compaction_bytes_limit = 100;
|
||||
options.create_if_missing = true;
|
||||
DestroyAndReopen(options);
|
||||
ASSERT_EQ(5, db_->GetOptions().base_background_compactions);
|
||||
ASSERT_EQ(100, db_->GetOptions().soft_pending_compaction_bytes_limit);
|
||||
|
||||
options.base_background_compactions = 4;
|
||||
options.max_background_compactions = 3;
|
||||
options.soft_pending_compaction_bytes_limit = 200;
|
||||
options.hard_pending_compaction_bytes_limit = 150;
|
||||
DestroyAndReopen(options);
|
||||
ASSERT_EQ(3, db_->GetOptions().base_background_compactions);
|
||||
ASSERT_EQ(150, db_->GetOptions().soft_pending_compaction_bytes_limit);
|
||||
}
|
||||
|
||||
// This tests for a bug that could cause two level0 compactions running
|
||||
// concurrently
|
||||
// TODO(aekmekji): Make sure that the reason this fails when run with
|
||||
|
||||
+79
-156
@@ -15,9 +15,6 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#ifdef OS_SOLARIS
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
@@ -31,10 +28,8 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "db/auto_roll_logger.h"
|
||||
#include "db/builder.h"
|
||||
#include "db/compaction_job.h"
|
||||
#include "db/db_info_dumper.h"
|
||||
#include "db/db_iter.h"
|
||||
#include "db/dbformat.h"
|
||||
#include "db/event_helpers.h"
|
||||
@@ -56,7 +51,6 @@
|
||||
#include "db/write_batch_internal.h"
|
||||
#include "db/write_callback.h"
|
||||
#include "db/writebuffer.h"
|
||||
#include "db/xfunc_test_points.h"
|
||||
#include "memtable/hash_linklist_rep.h"
|
||||
#include "memtable/hash_skiplist_rep.h"
|
||||
#include "port/likely.h"
|
||||
@@ -64,6 +58,7 @@
|
||||
#include "rocksdb/cache.h"
|
||||
#include "rocksdb/compaction_filter.h"
|
||||
#include "rocksdb/db.h"
|
||||
#include "rocksdb/delete_scheduler.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "rocksdb/merge_operator.h"
|
||||
#include "rocksdb/sst_file_writer.h"
|
||||
@@ -77,18 +72,19 @@
|
||||
#include "table/merger.h"
|
||||
#include "table/table_builder.h"
|
||||
#include "table/two_level_iterator.h"
|
||||
#include "util/auto_roll_logger.h"
|
||||
#include "util/autovector.h"
|
||||
#include "util/build_version.h"
|
||||
#include "util/coding.h"
|
||||
#include "util/compression.h"
|
||||
#include "util/crc32c.h"
|
||||
#include "util/db_info_dumper.h"
|
||||
#include "util/file_reader_writer.h"
|
||||
#include "util/file_util.h"
|
||||
#include "util/iostats_context_imp.h"
|
||||
#include "util/log_buffer.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/mutexlock.h"
|
||||
#include "util/sst_file_manager_impl.h"
|
||||
#include "util/options_helper.h"
|
||||
#include "util/options_parser.h"
|
||||
#include "util/perf_context_imp.h"
|
||||
@@ -146,12 +142,6 @@ DBOptions SanitizeOptions(const std::string& dbname, const DBOptions& src) {
|
||||
result.info_log = nullptr;
|
||||
}
|
||||
}
|
||||
if (result.base_background_compactions == -1) {
|
||||
result.base_background_compactions = result.max_background_compactions;
|
||||
}
|
||||
if (result.base_background_compactions > result.max_background_compactions) {
|
||||
result.base_background_compactions = result.max_background_compactions;
|
||||
}
|
||||
result.env->IncBackgroundThreadsIfNeeded(src.max_background_compactions,
|
||||
Env::Priority::LOW);
|
||||
result.env->IncBackgroundThreadsIfNeeded(src.max_background_flushes,
|
||||
@@ -275,7 +265,7 @@ DBImpl::DBImpl(const DBOptions& options, const std::string& dbname)
|
||||
db_options_.delete_obsolete_files_period_micros),
|
||||
last_stats_dump_time_microsec_(0),
|
||||
next_job_id_(1),
|
||||
has_unpersisted_data_(false),
|
||||
flush_on_destroy_(false),
|
||||
env_options_(db_options_),
|
||||
#ifndef ROCKSDB_LITE
|
||||
wal_manager_(db_options_, env_options_),
|
||||
@@ -322,8 +312,7 @@ void DBImpl::CancelAllBackgroundWork(bool wait) {
|
||||
DBImpl::~DBImpl() {
|
||||
mutex_.Lock();
|
||||
|
||||
if (!shutting_down_.load(std::memory_order_acquire) &&
|
||||
has_unpersisted_data_) {
|
||||
if (!shutting_down_.load(std::memory_order_acquire) && flush_on_destroy_) {
|
||||
for (auto cfd : *versions_->GetColumnFamilySet()) {
|
||||
if (!cfd->IsDropped() && !cfd->mem()->IsEmpty()) {
|
||||
cfd->Ref();
|
||||
@@ -495,22 +484,23 @@ void DBImpl::MaybeDumpStats() {
|
||||
last_stats_dump_time_microsec_ = now_micros;
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
const DBPropertyInfo* cf_property_info =
|
||||
GetPropertyInfo(DB::Properties::kCFStats);
|
||||
assert(cf_property_info != nullptr);
|
||||
const DBPropertyInfo* db_property_info =
|
||||
GetPropertyInfo(DB::Properties::kDBStats);
|
||||
assert(db_property_info != nullptr);
|
||||
|
||||
bool tmp1 = false;
|
||||
bool tmp2 = false;
|
||||
DBPropertyType cf_property_type =
|
||||
GetPropertyType(DB::Properties::kCFStats, &tmp1, &tmp2);
|
||||
DBPropertyType db_property_type =
|
||||
GetPropertyType(DB::Properties::kDBStats, &tmp1, &tmp2);
|
||||
std::string stats;
|
||||
{
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
for (auto cfd : *versions_->GetColumnFamilySet()) {
|
||||
cfd->internal_stats()->GetStringProperty(
|
||||
*cf_property_info, DB::Properties::kCFStats, &stats);
|
||||
cfd->internal_stats()->GetStringProperty(cf_property_type,
|
||||
DB::Properties::kCFStats,
|
||||
&stats);
|
||||
}
|
||||
default_cf_internal_stats_->GetStringProperty(
|
||||
*db_property_info, DB::Properties::kDBStats, &stats);
|
||||
default_cf_internal_stats_->GetStringProperty(db_property_type,
|
||||
DB::Properties::kDBStats,
|
||||
&stats);
|
||||
}
|
||||
Log(InfoLogLevel::WARN_LEVEL,
|
||||
db_options_.info_log, "------- DUMPING STATS -------");
|
||||
@@ -792,8 +782,8 @@ void DBImpl::PurgeObsoleteFiles(const JobContext& state) {
|
||||
}
|
||||
#endif // !ROCKSDB_LITE
|
||||
Status file_deletion_status;
|
||||
if (type == kTableFile) {
|
||||
file_deletion_status = DeleteSSTFile(&db_options_, fname, path_id);
|
||||
if (type == kTableFile && path_id == 0) {
|
||||
file_deletion_status = DeleteOrMoveToTrash(&db_options_, fname);
|
||||
} else {
|
||||
file_deletion_status = env_->DeleteFile(fname);
|
||||
}
|
||||
@@ -1515,14 +1505,6 @@ Status DBImpl::FlushMemTableToOutputFile(
|
||||
// may temporarily unlock and lock the mutex.
|
||||
NotifyOnFlushCompleted(cfd, &file_meta, mutable_cf_options,
|
||||
job_context->job_id, flush_job.GetTableProperties());
|
||||
auto sfm =
|
||||
static_cast<SstFileManagerImpl*>(db_options_.sst_file_manager.get());
|
||||
if (sfm) {
|
||||
// Notify sst_file_manager that a new file was added
|
||||
std::string file_path = MakeTableFileName(db_options_.db_paths[0].path,
|
||||
file_meta.fd.GetNumber());
|
||||
sfm->OnAddFile(file_path);
|
||||
}
|
||||
}
|
||||
#endif // ROCKSDB_LITE
|
||||
return s;
|
||||
@@ -1814,9 +1796,6 @@ Status DBImpl::CompactFilesImpl(
|
||||
std::vector<SequenceNumber> snapshot_seqs =
|
||||
snapshots_.GetAll(&earliest_write_conflict_snapshot);
|
||||
|
||||
auto pending_outputs_inserted_elem =
|
||||
CaptureCurrentFileNumberInPendingOutputs();
|
||||
|
||||
assert(is_snapshot_supported_ || snapshots_.empty());
|
||||
CompactionJob compaction_job(
|
||||
job_context->job_id, c.get(), db_options_, env_options_, versions_.get(),
|
||||
@@ -1844,8 +1823,6 @@ Status DBImpl::CompactFilesImpl(
|
||||
TEST_SYNC_POINT("CompactFilesImpl:0");
|
||||
TEST_SYNC_POINT("CompactFilesImpl:1");
|
||||
compaction_job.Run();
|
||||
TEST_SYNC_POINT("CompactFilesImpl:2");
|
||||
TEST_SYNC_POINT("CompactFilesImpl:3");
|
||||
mutex_.Lock();
|
||||
|
||||
Status status = compaction_job.Install(*c->mutable_cf_options(), &mutex_);
|
||||
@@ -1854,8 +1831,7 @@ Status DBImpl::CompactFilesImpl(
|
||||
c->column_family_data(), job_context, *c->mutable_cf_options());
|
||||
}
|
||||
c->ReleaseCompactionFiles(s);
|
||||
|
||||
ReleaseFileNumberFromPendingOutputs(pending_outputs_inserted_elem);
|
||||
c.reset();
|
||||
|
||||
if (status.ok()) {
|
||||
// Done
|
||||
@@ -1871,8 +1847,6 @@ Status DBImpl::CompactFilesImpl(
|
||||
}
|
||||
}
|
||||
|
||||
c.reset();
|
||||
|
||||
bg_compaction_scheduled_--;
|
||||
if (bg_compaction_scheduled_ == 0) {
|
||||
bg_cv_.SignalAll();
|
||||
@@ -2462,14 +2436,12 @@ void DBImpl::MaybeScheduleFlushOrCompaction() {
|
||||
env_->Schedule(&DBImpl::BGWorkFlush, this, Env::Priority::HIGH, this);
|
||||
}
|
||||
|
||||
auto bg_compactions_allowed = BGCompactionsAllowed();
|
||||
|
||||
// special case -- if max_background_flushes == 0, then schedule flush on a
|
||||
// compaction thread
|
||||
if (db_options_.max_background_flushes == 0) {
|
||||
while (unscheduled_flushes_ > 0 &&
|
||||
bg_flush_scheduled_ + bg_compaction_scheduled_ <
|
||||
bg_compactions_allowed) {
|
||||
db_options_.max_background_compactions) {
|
||||
unscheduled_flushes_--;
|
||||
bg_flush_scheduled_++;
|
||||
env_->Schedule(&DBImpl::BGWorkFlush, this, Env::Priority::LOW, this);
|
||||
@@ -2482,7 +2454,7 @@ void DBImpl::MaybeScheduleFlushOrCompaction() {
|
||||
return;
|
||||
}
|
||||
|
||||
while (bg_compaction_scheduled_ < bg_compactions_allowed &&
|
||||
while (bg_compaction_scheduled_ < db_options_.max_background_compactions &&
|
||||
unscheduled_compactions_ > 0) {
|
||||
CompactionArg* ca = new CompactionArg;
|
||||
ca->db = this;
|
||||
@@ -2494,14 +2466,6 @@ void DBImpl::MaybeScheduleFlushOrCompaction() {
|
||||
}
|
||||
}
|
||||
|
||||
int DBImpl::BGCompactionsAllowed() const {
|
||||
if (write_controller_.NeedSpeedupCompaction()) {
|
||||
return db_options_.max_background_compactions;
|
||||
} else {
|
||||
return db_options_.base_background_compactions;
|
||||
}
|
||||
}
|
||||
|
||||
void DBImpl::AddToCompactionQueue(ColumnFamilyData* cfd) {
|
||||
assert(!cfd->pending_compaction());
|
||||
cfd->Ref();
|
||||
@@ -2614,10 +2578,10 @@ Status DBImpl::BackgroundFlush(bool* made_progress, JobContext* job_context,
|
||||
LogToBuffer(
|
||||
log_buffer,
|
||||
"Calling FlushMemTableToOutputFile with column "
|
||||
"family [%s], flush slots available %d, compaction slots allowed %d, "
|
||||
"compaction slots scheduled %d",
|
||||
cfd->GetName().c_str(), db_options_.max_background_flushes,
|
||||
bg_flush_scheduled_, BGCompactionsAllowed() - bg_compaction_scheduled_);
|
||||
"family [%s], flush slots available %d, compaction slots available %d",
|
||||
cfd->GetName().c_str(),
|
||||
db_options_.max_background_flushes - bg_flush_scheduled_,
|
||||
db_options_.max_background_compactions - bg_compaction_scheduled_);
|
||||
status = FlushMemTableToOutputFile(cfd, mutable_cf_options, made_progress,
|
||||
job_context, log_buffer);
|
||||
if (cfd->Unref()) {
|
||||
@@ -2930,9 +2894,7 @@ Status DBImpl::BackgroundCompaction(bool* made_progress,
|
||||
TEST_SYNC_POINT("DBImpl::BackgroundCompaction:TrivialMove");
|
||||
// Instrument for event update
|
||||
// TODO(yhchiang): add op details for showing trivial-move.
|
||||
ThreadStatusUtil::SetColumnFamily(
|
||||
c->column_family_data(), c->column_family_data()->ioptions()->env,
|
||||
c->column_family_data()->options()->enable_thread_tracking);
|
||||
ThreadStatusUtil::SetColumnFamily(c->column_family_data());
|
||||
ThreadStatusUtil::SetThreadOperation(ThreadStatus::OP_COMPACTION);
|
||||
|
||||
compaction_job_stats.num_input_files = c->num_input_files(0);
|
||||
@@ -3315,19 +3277,13 @@ Status DBImpl::GetImpl(const ReadOptions& read_options,
|
||||
LookupKey lkey(key, snapshot);
|
||||
PERF_TIMER_STOP(get_snapshot_time);
|
||||
|
||||
bool skip_memtable =
|
||||
(read_options.read_tier == kPersistedTier && has_unpersisted_data_);
|
||||
bool done = false;
|
||||
if (!skip_memtable) {
|
||||
if (sv->mem->Get(lkey, value, &s, &merge_context)) {
|
||||
done = true;
|
||||
RecordTick(stats_, MEMTABLE_HIT);
|
||||
} else if (sv->imm->Get(lkey, value, &s, &merge_context)) {
|
||||
done = true;
|
||||
RecordTick(stats_, MEMTABLE_HIT);
|
||||
}
|
||||
}
|
||||
if (!done) {
|
||||
if (sv->mem->Get(lkey, value, &s, &merge_context)) {
|
||||
// Done
|
||||
RecordTick(stats_, MEMTABLE_HIT);
|
||||
} else if (sv->imm->Get(lkey, value, &s, &merge_context)) {
|
||||
// Done
|
||||
RecordTick(stats_, MEMTABLE_HIT);
|
||||
} else {
|
||||
PERF_TIMER_GUARD(get_from_output_files_time);
|
||||
sv->current->Get(read_options, lkey, value, &s, &merge_context,
|
||||
value_found);
|
||||
@@ -3341,7 +3297,6 @@ Status DBImpl::GetImpl(const ReadOptions& read_options,
|
||||
|
||||
RecordTick(stats_, NUMBER_KEYS_READ);
|
||||
RecordTick(stats_, BYTES_READ, value->size());
|
||||
MeasureTime(stats_, BYTES_PER_READ, value->size());
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -3412,23 +3367,14 @@ std::vector<Status> DBImpl::MultiGet(
|
||||
assert(mgd_iter != multiget_cf_data.end());
|
||||
auto mgd = mgd_iter->second;
|
||||
auto super_version = mgd->super_version;
|
||||
bool skip_memtable =
|
||||
(read_options.read_tier == kPersistedTier && has_unpersisted_data_);
|
||||
bool done = false;
|
||||
if (!skip_memtable) {
|
||||
if (super_version->mem->Get(lkey, value, &s, &merge_context)) {
|
||||
done = true;
|
||||
// TODO(?): RecordTick(stats_, MEMTABLE_HIT)?
|
||||
} else if (super_version->imm->Get(lkey, value, &s, &merge_context)) {
|
||||
done = true;
|
||||
// TODO(?): RecordTick(stats_, MEMTABLE_HIT)?
|
||||
}
|
||||
}
|
||||
if (!done) {
|
||||
if (super_version->mem->Get(lkey, value, &s, &merge_context)) {
|
||||
// Done
|
||||
} else if (super_version->imm->Get(lkey, value, &s, &merge_context)) {
|
||||
// Done
|
||||
} else {
|
||||
PERF_TIMER_GUARD(get_from_output_files_time);
|
||||
super_version->current->Get(read_options, lkey, value, &s,
|
||||
&merge_context);
|
||||
// TODO(?): RecordTick(stats_, MEMTABLE_MISS)?
|
||||
}
|
||||
|
||||
if (s.ok()) {
|
||||
@@ -3461,7 +3407,6 @@ std::vector<Status> DBImpl::MultiGet(
|
||||
RecordTick(stats_, NUMBER_MULTIGET_CALLS);
|
||||
RecordTick(stats_, NUMBER_MULTIGET_KEYS_READ, num_keys);
|
||||
RecordTick(stats_, NUMBER_MULTIGET_BYTES_READ, bytes_read);
|
||||
MeasureTime(stats_, BYTES_PER_MULTIGET, bytes_read);
|
||||
PERF_TIMER_STOP(get_post_process_time);
|
||||
|
||||
return stat_list;
|
||||
@@ -3554,9 +3499,6 @@ Status DBImpl::AddFile(ColumnFamilyHandle* column_family,
|
||||
auto cfh = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family);
|
||||
ColumnFamilyData* cfd = cfh->cfd();
|
||||
|
||||
if (file_info->num_entries == 0) {
|
||||
return Status::InvalidArgument("File contain no entries");
|
||||
}
|
||||
if (file_info->version != 1) {
|
||||
return Status::InvalidArgument("Generated table version is not supported");
|
||||
}
|
||||
@@ -3867,10 +3809,6 @@ bool DBImpl::KeyMayExist(const ReadOptions& read_options,
|
||||
|
||||
Iterator* DBImpl::NewIterator(const ReadOptions& read_options,
|
||||
ColumnFamilyHandle* column_family) {
|
||||
if (read_options.read_tier == kPersistedTier) {
|
||||
return NewErrorIterator(Status::NotSupported(
|
||||
"ReadTier::kPersistedData is not yet supported in iterators."));
|
||||
}
|
||||
auto cfh = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family);
|
||||
auto cfd = cfh->cfd();
|
||||
|
||||
@@ -3977,10 +3915,6 @@ Status DBImpl::NewIterators(
|
||||
const ReadOptions& read_options,
|
||||
const std::vector<ColumnFamilyHandle*>& column_families,
|
||||
std::vector<Iterator*>* iterators) {
|
||||
if (read_options.read_tier == kPersistedTier) {
|
||||
return Status::NotSupported(
|
||||
"ReadTier::kPersistedData is not yet supported in iterators.");
|
||||
}
|
||||
iterators->clear();
|
||||
iterators->reserve(column_families.size());
|
||||
XFUNC_TEST("", "managed_new", managed_new1, xf_manage_new,
|
||||
@@ -4356,11 +4290,10 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
|
||||
// Record statistics
|
||||
RecordTick(stats_, NUMBER_KEYS_WRITTEN, total_count);
|
||||
RecordTick(stats_, BYTES_WRITTEN, total_byte_size);
|
||||
MeasureTime(stats_, BYTES_PER_WRITE, total_byte_size);
|
||||
PERF_TIMER_STOP(write_pre_and_post_process_time);
|
||||
|
||||
if (write_options.disableWAL) {
|
||||
has_unpersisted_data_ = true;
|
||||
flush_on_destroy_ = true;
|
||||
}
|
||||
|
||||
uint64_t log_size = 0;
|
||||
@@ -4732,51 +4665,53 @@ const DBOptions& DBImpl::GetDBOptions() const { return db_options_; }
|
||||
|
||||
bool DBImpl::GetProperty(ColumnFamilyHandle* column_family,
|
||||
const Slice& property, std::string* value) {
|
||||
const DBPropertyInfo* property_info = GetPropertyInfo(property);
|
||||
bool is_int_property = false;
|
||||
bool need_out_of_mutex = false;
|
||||
DBPropertyType property_type =
|
||||
GetPropertyType(property, &is_int_property, &need_out_of_mutex);
|
||||
|
||||
value->clear();
|
||||
auto cfd = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family)->cfd();
|
||||
if (property_info == nullptr) {
|
||||
return false;
|
||||
} else if (property_info->handle_int) {
|
||||
if (is_int_property) {
|
||||
uint64_t int_value;
|
||||
bool ret_value =
|
||||
GetIntPropertyInternal(cfd, *property_info, false, &int_value);
|
||||
bool ret_value = GetIntPropertyInternal(
|
||||
cfd, property_type, need_out_of_mutex, false, &int_value);
|
||||
if (ret_value) {
|
||||
*value = ToString(int_value);
|
||||
}
|
||||
return ret_value;
|
||||
} else if (property_info->handle_string) {
|
||||
} else {
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
return cfd->internal_stats()->GetStringProperty(*property_info, property,
|
||||
return cfd->internal_stats()->GetStringProperty(property_type, property,
|
||||
value);
|
||||
}
|
||||
// Shouldn't reach here since exactly one of handle_string and handle_int
|
||||
// should be non-nullptr.
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DBImpl::GetIntProperty(ColumnFamilyHandle* column_family,
|
||||
const Slice& property, uint64_t* value) {
|
||||
const DBPropertyInfo* property_info = GetPropertyInfo(property);
|
||||
if (property_info == nullptr || property_info->handle_int == nullptr) {
|
||||
bool is_int_property = false;
|
||||
bool need_out_of_mutex = false;
|
||||
DBPropertyType property_type =
|
||||
GetPropertyType(property, &is_int_property, &need_out_of_mutex);
|
||||
if (!is_int_property) {
|
||||
return false;
|
||||
}
|
||||
auto cfd = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family)->cfd();
|
||||
return GetIntPropertyInternal(cfd, *property_info, false, value);
|
||||
return GetIntPropertyInternal(cfd, property_type, need_out_of_mutex, false,
|
||||
value);
|
||||
}
|
||||
|
||||
bool DBImpl::GetIntPropertyInternal(ColumnFamilyData* cfd,
|
||||
const DBPropertyInfo& property_info,
|
||||
bool is_locked, uint64_t* value) {
|
||||
assert(property_info.handle_int != nullptr);
|
||||
if (!property_info.need_out_of_mutex) {
|
||||
DBPropertyType property_type,
|
||||
bool need_out_of_mutex, bool is_locked,
|
||||
uint64_t* value) {
|
||||
if (!need_out_of_mutex) {
|
||||
if (is_locked) {
|
||||
mutex_.AssertHeld();
|
||||
return cfd->internal_stats()->GetIntProperty(property_info, value, this);
|
||||
return cfd->internal_stats()->GetIntProperty(property_type, value, this);
|
||||
} else {
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
return cfd->internal_stats()->GetIntProperty(property_info, value, this);
|
||||
return cfd->internal_stats()->GetIntProperty(property_type, value, this);
|
||||
}
|
||||
} else {
|
||||
SuperVersion* sv = nullptr;
|
||||
@@ -4787,7 +4722,7 @@ bool DBImpl::GetIntPropertyInternal(ColumnFamilyData* cfd,
|
||||
}
|
||||
|
||||
bool ret = cfd->internal_stats()->GetIntPropertyOutOfMutex(
|
||||
property_info, sv->current, value);
|
||||
property_type, sv->current, value);
|
||||
|
||||
if (!is_locked) {
|
||||
ReturnAndCleanupSuperVersion(cfd, sv);
|
||||
@@ -4799,8 +4734,11 @@ bool DBImpl::GetIntPropertyInternal(ColumnFamilyData* cfd,
|
||||
|
||||
bool DBImpl::GetAggregatedIntProperty(const Slice& property,
|
||||
uint64_t* aggregated_value) {
|
||||
const DBPropertyInfo* property_info = GetPropertyInfo(property);
|
||||
if (property_info == nullptr || property_info->handle_int == nullptr) {
|
||||
bool need_out_of_mutex;
|
||||
bool is_int_property;
|
||||
DBPropertyType property_type =
|
||||
GetPropertyType(property, &is_int_property, &need_out_of_mutex);
|
||||
if (!is_int_property) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4810,7 +4748,8 @@ bool DBImpl::GetAggregatedIntProperty(const Slice& property,
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
uint64_t value;
|
||||
for (auto* cfd : *versions_->GetColumnFamilySet()) {
|
||||
if (GetIntPropertyInternal(cfd, *property_info, true, &value)) {
|
||||
if (GetIntPropertyInternal(cfd, property_type, need_out_of_mutex, true,
|
||||
&value)) {
|
||||
sum += value;
|
||||
} else {
|
||||
return false;
|
||||
@@ -5462,25 +5401,6 @@ Status DB::Open(const DBOptions& db_options, const std::string& dbname,
|
||||
}
|
||||
impl->mutex_.Unlock();
|
||||
|
||||
auto sfm = static_cast<SstFileManagerImpl*>(
|
||||
impl->db_options_.sst_file_manager.get());
|
||||
if (s.ok() && sfm) {
|
||||
// Notify SstFileManager about all sst files that already exist in
|
||||
// db_paths[0] when the DB is opened.
|
||||
auto& db_path = impl->db_options_.db_paths[0];
|
||||
std::vector<std::string> existing_files;
|
||||
impl->db_options_.env->GetChildren(db_path.path, &existing_files);
|
||||
for (auto& file_name : existing_files) {
|
||||
uint64_t file_number;
|
||||
FileType file_type;
|
||||
std::string file_path = db_path.path + "/" + file_name;
|
||||
if (ParseFileName(file_name, &file_number, &file_type) &&
|
||||
file_type == kTableFile) {
|
||||
sfm->OnAddFile(file_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s.ok()) {
|
||||
Log(InfoLogLevel::INFO_LEVEL, impl->db_options_.info_log, "DB pointer %p",
|
||||
impl);
|
||||
@@ -5540,7 +5460,7 @@ Status DestroyDB(const std::string& dbname, const Options& options) {
|
||||
if (type == kMetaDatabase) {
|
||||
del = DestroyDB(path_to_delete, options);
|
||||
} else if (type == kTableFile) {
|
||||
del = DeleteSSTFile(&options, path_to_delete, 0);
|
||||
del = DeleteOrMoveToTrash(&options, path_to_delete);
|
||||
} else {
|
||||
del = env->DeleteFile(path_to_delete);
|
||||
}
|
||||
@@ -5556,9 +5476,13 @@ Status DestroyDB(const std::string& dbname, const Options& options) {
|
||||
for (size_t i = 0; i < filenames.size(); i++) {
|
||||
if (ParseFileName(filenames[i], &number, &type) &&
|
||||
type == kTableFile) { // Lock file will be deleted at end
|
||||
Status del;
|
||||
std::string table_path = db_path.path + "/" + filenames[i];
|
||||
Status del = DeleteSSTFile(&options, table_path,
|
||||
static_cast<uint32_t>(path_id));
|
||||
if (path_id == 0) {
|
||||
del = DeleteOrMoveToTrash(&options, table_path);
|
||||
} else {
|
||||
del = env->DeleteFile(table_path);
|
||||
}
|
||||
if (result.ok() && !del.ok()) {
|
||||
result = del;
|
||||
}
|
||||
@@ -5713,8 +5637,7 @@ Status DBImpl::RenameTempFileToOptionsFile(const std::string& file_name) {
|
||||
void DBImpl::NewThreadStatusCfInfo(
|
||||
ColumnFamilyData* cfd) const {
|
||||
if (db_options_.enable_thread_tracking) {
|
||||
ThreadStatusUtil::NewColumnFamilyInfo(this, cfd, cfd->GetName(),
|
||||
cfd->ioptions()->env);
|
||||
ThreadStatusUtil::NewColumnFamilyInfo(this, cfd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-10
@@ -347,10 +347,6 @@ class DBImpl : public DB {
|
||||
|
||||
#endif // NDEBUG
|
||||
|
||||
// Return maximum background compaction alowed to be scheduled based on
|
||||
// compaction status.
|
||||
int BGCompactionsAllowed() const;
|
||||
|
||||
// Returns the list of live files in 'live' and the list
|
||||
// of all files in the filesystem in 'candidate_files'.
|
||||
// If force == false and the last call was less than
|
||||
@@ -822,10 +818,7 @@ class DBImpl : public DB {
|
||||
// they're unique
|
||||
std::atomic<int> next_job_id_;
|
||||
|
||||
// A flag indicating whether the current rocksdb database has any
|
||||
// data that is not yet persisted into either WAL or SST file.
|
||||
// Used when disableWAL is true.
|
||||
bool has_unpersisted_data_;
|
||||
bool flush_on_destroy_; // Used when disableWAL is true.
|
||||
|
||||
static const int KEEP_LOG_FILE_NUM = 1000;
|
||||
// MSVC version 1800 still does not have constexpr for ::max()
|
||||
@@ -896,8 +889,9 @@ class DBImpl : public DB {
|
||||
bool* value_found = nullptr);
|
||||
|
||||
bool GetIntPropertyInternal(ColumnFamilyData* cfd,
|
||||
const DBPropertyInfo& property_info,
|
||||
bool is_locked, uint64_t* value);
|
||||
DBPropertyType property_type,
|
||||
bool need_out_of_mutex, bool is_locked,
|
||||
uint64_t* value);
|
||||
|
||||
bool HasPendingManualCompaction();
|
||||
bool HasExclusiveManualCompaction();
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
+1168
-438
File diff suppressed because it is too large.
Load diff
+54
-81
@@ -73,69 +73,64 @@ DBTestBase::~DBTestBase() {
|
||||
delete env_;
|
||||
}
|
||||
|
||||
bool DBTestBase::ShouldSkipOptions(int option_config, int skip_mask) {
|
||||
#ifdef ROCKSDB_LITE
|
||||
// These options are not supported in ROCKSDB_LITE
|
||||
if (option_config == kHashSkipList ||
|
||||
option_config == kPlainTableFirstBytePrefix ||
|
||||
option_config == kPlainTableCappedPrefix ||
|
||||
option_config == kPlainTableCappedPrefixNonMmap ||
|
||||
option_config == kPlainTableAllBytesPrefix ||
|
||||
option_config == kVectorRep || option_config == kHashLinkList ||
|
||||
option_config == kHashCuckoo || option_config == kUniversalCompaction ||
|
||||
option_config == kUniversalCompactionMultiLevel ||
|
||||
option_config == kUniversalSubcompactions ||
|
||||
option_config == kFIFOCompaction ||
|
||||
option_config == kConcurrentSkipList) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((skip_mask & kSkipDeletesFilterFirst) &&
|
||||
option_config == kDeletesFilterFirst) {
|
||||
return true;
|
||||
}
|
||||
if ((skip_mask & kSkipUniversalCompaction) &&
|
||||
(option_config == kUniversalCompaction ||
|
||||
option_config == kUniversalCompactionMultiLevel)) {
|
||||
return true;
|
||||
}
|
||||
if ((skip_mask & kSkipMergePut) && option_config == kMergePut) {
|
||||
return true;
|
||||
}
|
||||
if ((skip_mask & kSkipNoSeekToLast) &&
|
||||
(option_config == kHashLinkList || option_config == kHashSkipList)) {
|
||||
return true;
|
||||
}
|
||||
if ((skip_mask & kSkipPlainTable) &&
|
||||
(option_config == kPlainTableAllBytesPrefix ||
|
||||
option_config == kPlainTableFirstBytePrefix ||
|
||||
option_config == kPlainTableCappedPrefix ||
|
||||
option_config == kPlainTableCappedPrefixNonMmap)) {
|
||||
return true;
|
||||
}
|
||||
if ((skip_mask & kSkipHashIndex) &&
|
||||
(option_config == kBlockBasedTableWithPrefixHashIndex ||
|
||||
option_config == kBlockBasedTableWithWholeKeyHashIndex)) {
|
||||
return true;
|
||||
}
|
||||
if ((skip_mask & kSkipHashCuckoo) && (option_config == kHashCuckoo)) {
|
||||
return true;
|
||||
}
|
||||
if ((skip_mask & kSkipFIFOCompaction) && option_config == kFIFOCompaction) {
|
||||
return true;
|
||||
}
|
||||
if ((skip_mask & kSkipMmapReads) && option_config == kWalDirAndMmapReads) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Switch to a fresh database with the next option configuration to
|
||||
// test. Return false if there are no more configurations to test.
|
||||
bool DBTestBase::ChangeOptions(int skip_mask) {
|
||||
for (option_config_++; option_config_ < kEnd; option_config_++) {
|
||||
if (ShouldSkipOptions(option_config_, skip_mask)) {
|
||||
#ifdef ROCKSDB_LITE
|
||||
// These options are not supported in ROCKSDB_LITE
|
||||
if (option_config_ == kHashSkipList ||
|
||||
option_config_ == kPlainTableFirstBytePrefix ||
|
||||
option_config_ == kPlainTableCappedPrefix ||
|
||||
option_config_ == kPlainTableCappedPrefixNonMmap ||
|
||||
option_config_ == kPlainTableAllBytesPrefix ||
|
||||
option_config_ == kVectorRep || option_config_ == kHashLinkList ||
|
||||
option_config_ == kHashCuckoo ||
|
||||
option_config_ == kUniversalCompaction ||
|
||||
option_config_ == kUniversalCompactionMultiLevel ||
|
||||
option_config_ == kUniversalSubcompactions ||
|
||||
option_config_ == kFIFOCompaction ||
|
||||
option_config_ == kConcurrentSkipList) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((skip_mask & kSkipDeletesFilterFirst) &&
|
||||
option_config_ == kDeletesFilterFirst) {
|
||||
continue;
|
||||
}
|
||||
if ((skip_mask & kSkipUniversalCompaction) &&
|
||||
(option_config_ == kUniversalCompaction ||
|
||||
option_config_ == kUniversalCompactionMultiLevel)) {
|
||||
continue;
|
||||
}
|
||||
if ((skip_mask & kSkipMergePut) && option_config_ == kMergePut) {
|
||||
continue;
|
||||
}
|
||||
if ((skip_mask & kSkipNoSeekToLast) &&
|
||||
(option_config_ == kHashLinkList || option_config_ == kHashSkipList)) {
|
||||
continue;
|
||||
}
|
||||
if ((skip_mask & kSkipPlainTable) &&
|
||||
(option_config_ == kPlainTableAllBytesPrefix ||
|
||||
option_config_ == kPlainTableFirstBytePrefix ||
|
||||
option_config_ == kPlainTableCappedPrefix ||
|
||||
option_config_ == kPlainTableCappedPrefixNonMmap)) {
|
||||
continue;
|
||||
}
|
||||
if ((skip_mask & kSkipHashIndex) &&
|
||||
(option_config_ == kBlockBasedTableWithPrefixHashIndex ||
|
||||
option_config_ == kBlockBasedTableWithWholeKeyHashIndex)) {
|
||||
continue;
|
||||
}
|
||||
if ((skip_mask & kSkipHashCuckoo) && (option_config_ == kHashCuckoo)) {
|
||||
continue;
|
||||
}
|
||||
if ((skip_mask & kSkipFIFOCompaction) &&
|
||||
option_config_ == kFIFOCompaction) {
|
||||
continue;
|
||||
}
|
||||
if ((skip_mask & kSkipMmapReads) && option_config_ == kWalDirAndMmapReads) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
@@ -339,10 +334,6 @@ Options DBTestBase::CurrentOptions(
|
||||
options.prefix_extractor.reset(NewNoopTransform());
|
||||
break;
|
||||
}
|
||||
case kBlockBasedTableWithIndexRestartInterval: {
|
||||
table_options.index_block_restart_interval = 8;
|
||||
break;
|
||||
}
|
||||
case kOptimizeFiltersForHits: {
|
||||
options.optimize_filters_for_hits = true;
|
||||
set_block_based_table_factory = true;
|
||||
@@ -1015,22 +1006,4 @@ void DBTestBase::CopyFile(const std::string& source,
|
||||
ASSERT_OK(destfile->Close());
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, uint64_t> DBTestBase::GetAllSSTFiles() {
|
||||
std::unordered_map<std::string, uint64_t> res;
|
||||
|
||||
std::vector<std::string> files;
|
||||
env_->GetChildren(dbname_, &files);
|
||||
for (auto& file_name : files) {
|
||||
uint64_t number;
|
||||
FileType type;
|
||||
std::string file_path = dbname_ + "/" + file_name;
|
||||
if (ParseFileName(file_name, &number, &type) && type == kTableFile) {
|
||||
uint64_t file_size = 0;
|
||||
env_->GetFileSize(file_path, &file_size);
|
||||
res[file_path] = file_size;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
+1
-6
@@ -19,7 +19,6 @@
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
@@ -28,6 +27,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "db/db_impl.h"
|
||||
#include "db/db_test_util.h"
|
||||
#include "db/dbformat.h"
|
||||
#include "db/filename.h"
|
||||
#include "memtable/hash_linklist_rep.h"
|
||||
@@ -529,7 +529,6 @@ class DBTestBase : public testing::Test {
|
||||
kEnd = 31,
|
||||
kLevelSubcompactions = 31,
|
||||
kUniversalSubcompactions = 32,
|
||||
kBlockBasedTableWithIndexRestartInterval = 33,
|
||||
};
|
||||
int option_config_;
|
||||
|
||||
@@ -575,8 +574,6 @@ class DBTestBase : public testing::Test {
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
static bool ShouldSkipOptions(int option_config, int skip_mask = kNoSkip);
|
||||
|
||||
// Switch to a fresh database with the next option configuration to
|
||||
// test. Return false if there are no more configurations to test.
|
||||
bool ChangeOptions(int skip_mask = kNoSkip);
|
||||
@@ -753,8 +750,6 @@ class DBTestBase : public testing::Test {
|
||||
|
||||
void CopyFile(const std::string& source, const std::string& destination,
|
||||
uint64_t size = 0);
|
||||
|
||||
std::unordered_map<std::string, uint64_t> GetAllSSTFiles();
|
||||
};
|
||||
|
||||
} // namespace rocksdb
|
||||
@@ -187,16 +187,14 @@ TEST_P(DBTestUniversalCompaction, OptimizeFiltersForHits) {
|
||||
env_->Schedule(&test::SleepingBackgroundTask::DoSleepTask, &sleeping_task_low,
|
||||
Env::Priority::LOW);
|
||||
|
||||
Put("", "");
|
||||
for (int num = 0; num < options.level0_file_num_compaction_trigger; num++) {
|
||||
Put(Key(num * 10), "val");
|
||||
if (num) {
|
||||
dbfull()->TEST_WaitForFlushMemTable();
|
||||
}
|
||||
Put(Key(30 + num * 10), "val");
|
||||
Put(Key(60 + num * 10), "val");
|
||||
|
||||
dbfull()->TEST_WaitForFlushMemTable();
|
||||
}
|
||||
Put("", "");
|
||||
dbfull()->TEST_WaitForFlushMemTable();
|
||||
|
||||
// Query set of non existing keys
|
||||
for (int i = 5; i < 90; i += 10) {
|
||||
@@ -207,13 +205,6 @@ TEST_P(DBTestUniversalCompaction, OptimizeFiltersForHits) {
|
||||
ASSERT_GT(TestGetTickerCount(options, BLOOM_FILTER_USEFUL), 0);
|
||||
auto prev_counter = TestGetTickerCount(options, BLOOM_FILTER_USEFUL);
|
||||
|
||||
// Make sure bloom filter is used for all but the last L0 file when looking
|
||||
// up a non-existent key that's in the range of all L0 files.
|
||||
ASSERT_EQ(Get(Key(35)), "NOT_FOUND");
|
||||
ASSERT_EQ(prev_counter + NumTableFilesAtLevel(0) - 1,
|
||||
TestGetTickerCount(options, BLOOM_FILTER_USEFUL));
|
||||
prev_counter = TestGetTickerCount(options, BLOOM_FILTER_USEFUL);
|
||||
|
||||
// Unblock compaction and wait it for happening.
|
||||
sleeping_task_low.WakeUp();
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
|
||||
+1
-3
@@ -94,8 +94,7 @@ FlushJob::~FlushJob() {
|
||||
}
|
||||
|
||||
void FlushJob::ReportStartedFlush() {
|
||||
ThreadStatusUtil::SetColumnFamily(cfd_, cfd_->ioptions()->env,
|
||||
cfd_->options()->enable_thread_tracking);
|
||||
ThreadStatusUtil::SetColumnFamily(cfd_);
|
||||
ThreadStatusUtil::SetThreadOperation(ThreadStatus::OP_FLUSH);
|
||||
ThreadStatusUtil::SetThreadOperationProperty(
|
||||
ThreadStatus::COMPACTION_JOB_ID,
|
||||
@@ -271,7 +270,6 @@ Status FlushJob::WriteLevel0Table(const autovector<MemTable*>& mems,
|
||||
if (!db_options_.disableDataSync && output_file_directory_ != nullptr) {
|
||||
output_file_directory_->Fsync();
|
||||
}
|
||||
TEST_SYNC_POINT("FlushJob::WriteLevel0Table");
|
||||
db_mutex_->Lock();
|
||||
}
|
||||
base->Unref();
|
||||
|
||||
+285
-366
@@ -15,7 +15,6 @@
|
||||
#include <inttypes.h>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "db/column_family.h"
|
||||
|
||||
@@ -82,21 +81,7 @@ void PrintLevelStats(char* buf, size_t len, const std::string& name,
|
||||
stats.count == 0 ? 0 : stats.micros / kMicrosInSec / stats.count,
|
||||
num_input_records.c_str(), num_dropped_records.c_str());
|
||||
}
|
||||
|
||||
// Assumes that trailing numbers represent an optional argument. This requires
|
||||
// property names to not end with numbers.
|
||||
std::pair<Slice, Slice> GetPropertyNameAndArg(const Slice& property) {
|
||||
Slice name = property, arg = property;
|
||||
size_t sfx_len = 0;
|
||||
while (sfx_len < property.size() &&
|
||||
isdigit(property[property.size() - sfx_len - 1])) {
|
||||
++sfx_len;
|
||||
}
|
||||
name.remove_suffix(sfx_len);
|
||||
arg.remove_prefix(property.size() - sfx_len);
|
||||
return {name, arg};
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
static const std::string rocksdb_prefix = "rocksdb.";
|
||||
|
||||
@@ -114,8 +99,9 @@ static const std::string compaction_pending = "compaction-pending";
|
||||
static const std::string background_errors = "background-errors";
|
||||
static const std::string cur_size_active_mem_table =
|
||||
"cur-size-active-mem-table";
|
||||
static const std::string cur_size_all_mem_tables = "cur-size-all-mem-tables";
|
||||
static const std::string size_all_mem_tables = "size-all-mem-tables";
|
||||
static const std::string cur_size_unflushed_mem_tables =
|
||||
"cur-size-all-mem-tables";
|
||||
static const std::string cur_size_all_mem_tables = "size-all-mem-tables";
|
||||
static const std::string num_entries_active_mem_table =
|
||||
"num-entries-active-mem-table";
|
||||
static const std::string num_entries_imm_mem_tables =
|
||||
@@ -150,11 +136,8 @@ const std::string DB::Properties::kStats = rocksdb_prefix + allstats;
|
||||
const std::string DB::Properties::kSSTables = rocksdb_prefix + sstables;
|
||||
const std::string DB::Properties::kCFStats = rocksdb_prefix + cfstats;
|
||||
const std::string DB::Properties::kDBStats = rocksdb_prefix + dbstats;
|
||||
const std::string DB::Properties::kLevelStats = rocksdb_prefix + levelstats;
|
||||
const std::string DB::Properties::kNumImmutableMemTable =
|
||||
rocksdb_prefix + num_immutable_mem_table;
|
||||
const std::string DB::Properties::kNumImmutableMemTableFlushed =
|
||||
rocksdb_prefix + num_immutable_mem_table_flushed;
|
||||
const std::string DB::Properties::kMemTableFlushPending =
|
||||
rocksdb_prefix + mem_table_flush_pending;
|
||||
const std::string DB::Properties::kCompactionPending =
|
||||
@@ -168,9 +151,9 @@ const std::string DB::Properties::kBackgroundErrors =
|
||||
const std::string DB::Properties::kCurSizeActiveMemTable =
|
||||
rocksdb_prefix + cur_size_active_mem_table;
|
||||
const std::string DB::Properties::kCurSizeAllMemTables =
|
||||
rocksdb_prefix + cur_size_all_mem_tables;
|
||||
rocksdb_prefix + cur_size_unflushed_mem_tables;
|
||||
const std::string DB::Properties::kSizeAllMemTables =
|
||||
rocksdb_prefix + size_all_mem_tables;
|
||||
rocksdb_prefix + cur_size_all_mem_tables;
|
||||
const std::string DB::Properties::kNumEntriesActiveMemTable =
|
||||
rocksdb_prefix + num_entries_active_mem_table;
|
||||
const std::string DB::Properties::kNumEntriesImmMemTables =
|
||||
@@ -195,7 +178,6 @@ const std::string DB::Properties::kEstimateLiveDataSize =
|
||||
rocksdb_prefix + estimate_live_data_size;
|
||||
const std::string DB::Properties::kTotalSstFilesSize =
|
||||
rocksdb_prefix + total_sst_files_size;
|
||||
const std::string DB::Properties::kBaseLevel = rocksdb_prefix + base_level;
|
||||
const std::string DB::Properties::kEstimatePendingCompactionBytes =
|
||||
rocksdb_prefix + estimate_pending_comp_bytes;
|
||||
const std::string DB::Properties::kAggregatedTableProperties =
|
||||
@@ -203,360 +185,294 @@ const std::string DB::Properties::kAggregatedTableProperties =
|
||||
const std::string DB::Properties::kAggregatedTablePropertiesAtLevel =
|
||||
rocksdb_prefix + aggregated_table_properties_at_level;
|
||||
|
||||
const std::unordered_map<std::string,
|
||||
DBPropertyInfo> InternalStats::ppt_name_to_info = {
|
||||
{DB::Properties::kNumFilesAtLevelPrefix,
|
||||
{false, &InternalStats::HandleNumFilesAtLevel, nullptr}},
|
||||
{DB::Properties::kLevelStats,
|
||||
{false, &InternalStats::HandleLevelStats, nullptr}},
|
||||
{DB::Properties::kStats, {false, &InternalStats::HandleStats, nullptr}},
|
||||
{DB::Properties::kCFStats, {false, &InternalStats::HandleCFStats, nullptr}},
|
||||
{DB::Properties::kDBStats, {false, &InternalStats::HandleDBStats, nullptr}},
|
||||
{DB::Properties::kSSTables,
|
||||
{false, &InternalStats::HandleSsTables, nullptr}},
|
||||
{DB::Properties::kAggregatedTableProperties,
|
||||
{false, &InternalStats::HandleAggregatedTableProperties, nullptr}},
|
||||
{DB::Properties::kAggregatedTablePropertiesAtLevel,
|
||||
{false, &InternalStats::HandleAggregatedTablePropertiesAtLevel, nullptr}},
|
||||
{DB::Properties::kNumImmutableMemTable,
|
||||
{false, nullptr, &InternalStats::HandleNumImmutableMemTable}},
|
||||
{DB::Properties::kNumImmutableMemTableFlushed,
|
||||
{false, nullptr, &InternalStats::HandleNumImmutableMemTableFlushed}},
|
||||
{DB::Properties::kMemTableFlushPending,
|
||||
{false, nullptr, &InternalStats::HandleMemTableFlushPending}},
|
||||
{DB::Properties::kCompactionPending,
|
||||
{false, nullptr, &InternalStats::HandleCompactionPending}},
|
||||
{DB::Properties::kBackgroundErrors,
|
||||
{false, nullptr, &InternalStats::HandleBackgroundErrors}},
|
||||
{DB::Properties::kCurSizeActiveMemTable,
|
||||
{false, nullptr, &InternalStats::HandleCurSizeActiveMemTable}},
|
||||
{DB::Properties::kCurSizeAllMemTables,
|
||||
{false, nullptr, &InternalStats::HandleCurSizeAllMemTables}},
|
||||
{DB::Properties::kSizeAllMemTables,
|
||||
{false, nullptr, &InternalStats::HandleSizeAllMemTables}},
|
||||
{DB::Properties::kNumEntriesActiveMemTable,
|
||||
{false, nullptr, &InternalStats::HandleNumEntriesActiveMemTable}},
|
||||
{DB::Properties::kNumEntriesImmMemTables,
|
||||
{false, nullptr, &InternalStats::HandleNumEntriesImmMemTables}},
|
||||
{DB::Properties::kNumDeletesActiveMemTable,
|
||||
{false, nullptr, &InternalStats::HandleNumDeletesActiveMemTable}},
|
||||
{DB::Properties::kNumDeletesImmMemTables,
|
||||
{false, nullptr, &InternalStats::HandleNumDeletesImmMemTables}},
|
||||
{DB::Properties::kEstimateNumKeys,
|
||||
{false, nullptr, &InternalStats::HandleEstimateNumKeys}},
|
||||
{DB::Properties::kEstimateTableReadersMem,
|
||||
{true, nullptr, &InternalStats::HandleEstimateTableReadersMem}},
|
||||
{DB::Properties::kIsFileDeletionsEnabled,
|
||||
{false, nullptr, &InternalStats::HandleIsFileDeletionsEnabled}},
|
||||
{DB::Properties::kNumSnapshots,
|
||||
{false, nullptr, &InternalStats::HandleNumSnapshots}},
|
||||
{DB::Properties::kOldestSnapshotTime,
|
||||
{false, nullptr, &InternalStats::HandleOldestSnapshotTime}},
|
||||
{DB::Properties::kNumLiveVersions,
|
||||
{false, nullptr, &InternalStats::HandleNumLiveVersions}},
|
||||
{DB::Properties::kEstimateLiveDataSize,
|
||||
{true, nullptr, &InternalStats::HandleEstimateLiveDataSize}},
|
||||
{DB::Properties::kBaseLevel,
|
||||
{false, nullptr, &InternalStats::HandleBaseLevel}},
|
||||
{DB::Properties::kTotalSstFilesSize,
|
||||
{false, nullptr, &InternalStats::HandleTotalSstFilesSize}},
|
||||
{DB::Properties::kEstimatePendingCompactionBytes,
|
||||
{false, nullptr, &InternalStats::HandleEstimatePendingCompactionBytes}},
|
||||
{DB::Properties::kNumRunningFlushes,
|
||||
{false, nullptr, &InternalStats::HandleNumRunningFlushes}},
|
||||
{DB::Properties::kNumRunningCompactions,
|
||||
{false, nullptr, &InternalStats::HandleNumRunningCompactions}},
|
||||
};
|
||||
|
||||
const DBPropertyInfo* GetPropertyInfo(const Slice& property) {
|
||||
std::string ppt_name = GetPropertyNameAndArg(property).first.ToString();
|
||||
auto ppt_info_iter = InternalStats::ppt_name_to_info.find(ppt_name);
|
||||
if (ppt_info_iter == InternalStats::ppt_name_to_info.end()) {
|
||||
return nullptr;
|
||||
DBPropertyType GetPropertyType(const Slice& property, bool* is_int_property,
|
||||
bool* need_out_of_mutex) {
|
||||
assert(is_int_property != nullptr);
|
||||
assert(need_out_of_mutex != nullptr);
|
||||
Slice in = property;
|
||||
Slice prefix(rocksdb_prefix);
|
||||
*need_out_of_mutex = false;
|
||||
*is_int_property = false;
|
||||
if (!in.starts_with(prefix)) {
|
||||
return kUnknown;
|
||||
}
|
||||
return &ppt_info_iter->second;
|
||||
in.remove_prefix(prefix.size());
|
||||
|
||||
if (in.starts_with(num_files_at_level_prefix)) {
|
||||
return kNumFilesAtLevel;
|
||||
} else if (in == levelstats) {
|
||||
return kLevelStats;
|
||||
} else if (in == allstats) {
|
||||
return kStats;
|
||||
} else if (in == cfstats) {
|
||||
return kCFStats;
|
||||
} else if (in == dbstats) {
|
||||
return kDBStats;
|
||||
} else if (in == sstables) {
|
||||
return kSsTables;
|
||||
} else if (in == aggregated_table_properties) {
|
||||
return kAggregatedTableProperties;
|
||||
} else if (in.starts_with(aggregated_table_properties_at_level)) {
|
||||
return kAggregatedTablePropertiesAtLevel;
|
||||
}
|
||||
|
||||
*is_int_property = true;
|
||||
if (in == num_immutable_mem_table) {
|
||||
return kNumImmutableMemTable;
|
||||
} else if (in == num_immutable_mem_table_flushed) {
|
||||
return kNumImmutableMemTableFlushed;
|
||||
} else if (in == mem_table_flush_pending) {
|
||||
return kMemtableFlushPending;
|
||||
} else if (in == compaction_pending) {
|
||||
return kCompactionPending;
|
||||
} else if (in == background_errors) {
|
||||
return kBackgroundErrors;
|
||||
} else if (in == cur_size_active_mem_table) {
|
||||
return kCurSizeActiveMemTable;
|
||||
} else if (in == cur_size_unflushed_mem_tables) {
|
||||
return kCurSizeAllMemTables;
|
||||
} else if (in == cur_size_all_mem_tables) {
|
||||
return kSizeAllMemTables;
|
||||
} else if (in == num_entries_active_mem_table) {
|
||||
return kNumEntriesInMutableMemtable;
|
||||
} else if (in == num_entries_imm_mem_tables) {
|
||||
return kNumEntriesInImmutableMemtable;
|
||||
} else if (in == num_deletes_active_mem_table) {
|
||||
return kNumDeletesInMutableMemtable;
|
||||
} else if (in == num_deletes_imm_mem_tables) {
|
||||
return kNumDeletesInImmutableMemtable;
|
||||
} else if (in == estimate_num_keys) {
|
||||
return kEstimatedNumKeys;
|
||||
} else if (in == estimate_table_readers_mem) {
|
||||
*need_out_of_mutex = true;
|
||||
return kEstimatedUsageByTableReaders;
|
||||
} else if (in == is_file_deletions_enabled) {
|
||||
return kIsFileDeletionEnabled;
|
||||
} else if (in == num_snapshots) {
|
||||
return kNumSnapshots;
|
||||
} else if (in == oldest_snapshot_time) {
|
||||
return kOldestSnapshotTime;
|
||||
} else if (in == num_live_versions) {
|
||||
return kNumLiveVersions;
|
||||
} else if (in == estimate_live_data_size) {
|
||||
*need_out_of_mutex = true;
|
||||
return kEstimateLiveDataSize;
|
||||
} else if (in == base_level) {
|
||||
return kBaseLevel;
|
||||
} else if (in == total_sst_files_size) {
|
||||
return kTotalSstFilesSize;
|
||||
} else if (in == estimate_pending_comp_bytes) {
|
||||
return kEstimatePendingCompactionBytes;
|
||||
} else if (in == num_running_flushes) {
|
||||
return kNumRunningFlushes;
|
||||
} else if (in == num_running_compactions) {
|
||||
return kNumRunningCompactions;
|
||||
}
|
||||
return kUnknown;
|
||||
}
|
||||
|
||||
bool InternalStats::GetStringProperty(const DBPropertyInfo& property_info,
|
||||
bool InternalStats::GetIntPropertyOutOfMutex(DBPropertyType property_type,
|
||||
Version* version,
|
||||
uint64_t* value) const {
|
||||
assert(value != nullptr);
|
||||
const auto* vstorage = cfd_->current()->storage_info();
|
||||
|
||||
switch (property_type) {
|
||||
case kEstimatedUsageByTableReaders:
|
||||
*value = (version == nullptr) ?
|
||||
0 : version->GetMemoryUsageByTableReaders();
|
||||
return true;
|
||||
case kEstimateLiveDataSize:
|
||||
*value = vstorage->EstimateLiveDataSize();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool InternalStats::GetStringProperty(DBPropertyType property_type,
|
||||
const Slice& property,
|
||||
std::string* value) {
|
||||
assert(value != nullptr);
|
||||
assert(property_info.handle_string != nullptr);
|
||||
Slice arg = GetPropertyNameAndArg(property).second;
|
||||
return (this->*(property_info.handle_string))(value, arg);
|
||||
}
|
||||
|
||||
bool InternalStats::GetIntProperty(const DBPropertyInfo& property_info,
|
||||
uint64_t* value, DBImpl* db) {
|
||||
assert(value != nullptr);
|
||||
assert(property_info.handle_int != nullptr &&
|
||||
!property_info.need_out_of_mutex);
|
||||
db->mutex_.AssertHeld();
|
||||
return (this->*(property_info.handle_int))(value, db, nullptr /* version */);
|
||||
}
|
||||
|
||||
bool InternalStats::GetIntPropertyOutOfMutex(
|
||||
const DBPropertyInfo& property_info, Version* version, uint64_t* value) {
|
||||
assert(value != nullptr);
|
||||
assert(property_info.handle_int != nullptr &&
|
||||
property_info.need_out_of_mutex);
|
||||
return (this->*(property_info.handle_int))(value, nullptr /* db */, version);
|
||||
}
|
||||
|
||||
bool InternalStats::HandleNumFilesAtLevel(std::string* value, Slice suffix) {
|
||||
uint64_t level;
|
||||
const auto* vstorage = cfd_->current()->storage_info();
|
||||
bool ok = ConsumeDecimalNumber(&suffix, &level) && suffix.empty();
|
||||
if (!ok || static_cast<int>(level) >= number_levels_) {
|
||||
return false;
|
||||
} else {
|
||||
char buf[100];
|
||||
snprintf(buf, sizeof(buf), "%d",
|
||||
vstorage->NumLevelFiles(static_cast<int>(level)));
|
||||
*value = buf;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool InternalStats::HandleLevelStats(std::string* value, Slice suffix) {
|
||||
char buf[1000];
|
||||
const auto* vstorage = cfd_->current()->storage_info();
|
||||
snprintf(buf, sizeof(buf),
|
||||
"Level Files Size(MB)\n"
|
||||
"--------------------\n");
|
||||
value->append(buf);
|
||||
|
||||
for (int level = 0; level < number_levels_; level++) {
|
||||
snprintf(buf, sizeof(buf), "%3d %8d %8.0f\n", level,
|
||||
vstorage->NumLevelFiles(level),
|
||||
vstorage->NumLevelBytes(level) / kMB);
|
||||
value->append(buf);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleStats(std::string* value, Slice suffix) {
|
||||
if (!HandleCFStats(value, suffix)) {
|
||||
return false;
|
||||
}
|
||||
if (!HandleDBStats(value, suffix)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleCFStats(std::string* value, Slice suffix) {
|
||||
DumpCFStats(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleDBStats(std::string* value, Slice suffix) {
|
||||
DumpDBStats(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleSsTables(std::string* value, Slice suffix) {
|
||||
auto* current = cfd_->current();
|
||||
*value = current->DebugString();
|
||||
return true;
|
||||
}
|
||||
const auto* vstorage = current->storage_info();
|
||||
Slice in = property;
|
||||
|
||||
bool InternalStats::HandleAggregatedTableProperties(std::string* value,
|
||||
Slice suffix) {
|
||||
std::shared_ptr<const TableProperties> tp;
|
||||
auto s = cfd_->current()->GetAggregatedTableProperties(&tp);
|
||||
if (!s.ok()) {
|
||||
return false;
|
||||
switch (property_type) {
|
||||
case kNumFilesAtLevel: {
|
||||
in.remove_prefix(strlen("rocksdb.num-files-at-level"));
|
||||
uint64_t level;
|
||||
bool ok = ConsumeDecimalNumber(&in, &level) && in.empty();
|
||||
if (!ok || (int)level >= number_levels_) {
|
||||
return false;
|
||||
} else {
|
||||
char buf[100];
|
||||
snprintf(buf, sizeof(buf), "%d",
|
||||
vstorage->NumLevelFiles(static_cast<int>(level)));
|
||||
*value = buf;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
case kLevelStats: {
|
||||
char buf[1000];
|
||||
snprintf(buf, sizeof(buf),
|
||||
"Level Files Size(MB)\n"
|
||||
"--------------------\n");
|
||||
value->append(buf);
|
||||
|
||||
for (int level = 0; level < number_levels_; level++) {
|
||||
snprintf(buf, sizeof(buf), "%3d %8d %8.0f\n", level,
|
||||
vstorage->NumLevelFiles(level),
|
||||
vstorage->NumLevelBytes(level) / kMB);
|
||||
value->append(buf);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case kStats: {
|
||||
if (!GetStringProperty(kCFStats, DB::Properties::kCFStats, value)) {
|
||||
return false;
|
||||
}
|
||||
if (!GetStringProperty(kDBStats, DB::Properties::kDBStats, value)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case kCFStats: {
|
||||
DumpCFStats(value);
|
||||
return true;
|
||||
}
|
||||
case kDBStats: {
|
||||
DumpDBStats(value);
|
||||
return true;
|
||||
}
|
||||
case kSsTables:
|
||||
*value = current->DebugString();
|
||||
return true;
|
||||
case kAggregatedTableProperties: {
|
||||
std::shared_ptr<const TableProperties> tp;
|
||||
auto s = cfd_->current()->GetAggregatedTableProperties(&tp);
|
||||
if (!s.ok()) {
|
||||
return false;
|
||||
}
|
||||
*value = tp->ToString();
|
||||
return true;
|
||||
}
|
||||
case kAggregatedTablePropertiesAtLevel: {
|
||||
in.remove_prefix(
|
||||
DB::Properties::kAggregatedTablePropertiesAtLevel.length());
|
||||
uint64_t level;
|
||||
bool ok = ConsumeDecimalNumber(&in, &level) && in.empty();
|
||||
if (!ok || static_cast<int>(level) >= number_levels_) {
|
||||
return false;
|
||||
}
|
||||
std::shared_ptr<const TableProperties> tp;
|
||||
auto s = cfd_->current()->GetAggregatedTableProperties(
|
||||
&tp, static_cast<int>(level));
|
||||
if (!s.ok()) {
|
||||
return false;
|
||||
}
|
||||
*value = tp->ToString();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
*value = tp->ToString();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleAggregatedTablePropertiesAtLevel(std::string* value,
|
||||
Slice suffix) {
|
||||
uint64_t level;
|
||||
bool ok = ConsumeDecimalNumber(&suffix, &level) && suffix.empty();
|
||||
if (!ok || static_cast<int>(level) >= number_levels_) {
|
||||
return false;
|
||||
bool InternalStats::GetIntProperty(DBPropertyType property_type,
|
||||
uint64_t* value, DBImpl* db) const {
|
||||
db->mutex_.AssertHeld();
|
||||
const auto* vstorage = cfd_->current()->storage_info();
|
||||
|
||||
switch (property_type) {
|
||||
case kNumImmutableMemTable:
|
||||
*value = cfd_->imm()->NumNotFlushed();
|
||||
return true;
|
||||
case kNumImmutableMemTableFlushed:
|
||||
*value = cfd_->imm()->NumFlushed();
|
||||
return true;
|
||||
case kMemtableFlushPending:
|
||||
// Return number of mem tables that are ready to flush (made immutable)
|
||||
*value = (cfd_->imm()->IsFlushPending() ? 1 : 0);
|
||||
return true;
|
||||
case kNumRunningFlushes:
|
||||
*value = db->num_running_flushes();
|
||||
return true;
|
||||
case kCompactionPending:
|
||||
// 1 if the system already determines at least one compaction is needed.
|
||||
// 0 otherwise,
|
||||
*value = (cfd_->compaction_picker()->NeedsCompaction(vstorage) ? 1 : 0);
|
||||
return true;
|
||||
case kNumRunningCompactions:
|
||||
*value = db->num_running_compactions_;
|
||||
return true;
|
||||
case kBackgroundErrors:
|
||||
// Accumulated number of errors in background flushes or compactions.
|
||||
*value = GetBackgroundErrorCount();
|
||||
return true;
|
||||
case kCurSizeActiveMemTable:
|
||||
// Current size of the active memtable
|
||||
*value = cfd_->mem()->ApproximateMemoryUsage();
|
||||
return true;
|
||||
case kCurSizeAllMemTables:
|
||||
// Current size of the active memtable + immutable memtables
|
||||
*value = cfd_->mem()->ApproximateMemoryUsage() +
|
||||
cfd_->imm()->ApproximateUnflushedMemTablesMemoryUsage();
|
||||
return true;
|
||||
case kSizeAllMemTables:
|
||||
*value = cfd_->mem()->ApproximateMemoryUsage() +
|
||||
cfd_->imm()->ApproximateMemoryUsage();
|
||||
return true;
|
||||
case kNumEntriesInMutableMemtable:
|
||||
// Current number of entires in the active memtable
|
||||
*value = cfd_->mem()->num_entries();
|
||||
return true;
|
||||
case kNumEntriesInImmutableMemtable:
|
||||
// Current number of entries in the immutable memtables
|
||||
*value = cfd_->imm()->current()->GetTotalNumEntries();
|
||||
return true;
|
||||
case kNumDeletesInMutableMemtable:
|
||||
// Current number of entires in the active memtable
|
||||
*value = cfd_->mem()->num_deletes();
|
||||
return true;
|
||||
case kNumDeletesInImmutableMemtable:
|
||||
// Current number of entries in the immutable memtables
|
||||
*value = cfd_->imm()->current()->GetTotalNumDeletes();
|
||||
return true;
|
||||
case kEstimatedNumKeys:
|
||||
// Estimate number of entries in the column family:
|
||||
// Use estimated entries in tables + total entries in memtables.
|
||||
*value = cfd_->mem()->num_entries() +
|
||||
cfd_->imm()->current()->GetTotalNumEntries() -
|
||||
(cfd_->mem()->num_deletes() +
|
||||
cfd_->imm()->current()->GetTotalNumDeletes()) *
|
||||
2 +
|
||||
vstorage->GetEstimatedActiveKeys();
|
||||
return true;
|
||||
case kNumSnapshots:
|
||||
*value = db->snapshots().count();
|
||||
return true;
|
||||
case kOldestSnapshotTime:
|
||||
*value = static_cast<uint64_t>(db->snapshots().GetOldestSnapshotTime());
|
||||
return true;
|
||||
case kNumLiveVersions:
|
||||
*value = cfd_->GetNumLiveVersions();
|
||||
return true;
|
||||
case kIsFileDeletionEnabled:
|
||||
*value = db->IsFileDeletionsEnabled();
|
||||
return true;
|
||||
case kBaseLevel:
|
||||
*value = vstorage->base_level();
|
||||
return true;
|
||||
case kTotalSstFilesSize:
|
||||
*value = cfd_->GetTotalSstFilesSize();
|
||||
return true;
|
||||
case kEstimatePendingCompactionBytes:
|
||||
*value = vstorage->estimated_compaction_needed_bytes();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
std::shared_ptr<const TableProperties> tp;
|
||||
auto s = cfd_->current()->GetAggregatedTableProperties(
|
||||
&tp, static_cast<int>(level));
|
||||
if (!s.ok()) {
|
||||
return false;
|
||||
}
|
||||
*value = tp->ToString();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleNumImmutableMemTable(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
*value = cfd_->imm()->NumNotFlushed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleNumImmutableMemTableFlushed(uint64_t* value,
|
||||
DBImpl* db,
|
||||
Version* version) {
|
||||
*value = cfd_->imm()->NumFlushed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleMemTableFlushPending(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
// Return number of mem tables that are ready to flush (made immutable)
|
||||
*value = (cfd_->imm()->IsFlushPending() ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleNumRunningFlushes(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
*value = db->num_running_flushes();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleCompactionPending(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
// 1 if the system already determines at least one compaction is needed.
|
||||
// 0 otherwise,
|
||||
const auto* vstorage = cfd_->current()->storage_info();
|
||||
*value = (cfd_->compaction_picker()->NeedsCompaction(vstorage) ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleNumRunningCompactions(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
*value = db->num_running_compactions_;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleBackgroundErrors(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
// Accumulated number of errors in background flushes or compactions.
|
||||
*value = GetBackgroundErrorCount();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleCurSizeActiveMemTable(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
// Current size of the active memtable
|
||||
*value = cfd_->mem()->ApproximateMemoryUsage();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleCurSizeAllMemTables(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
// Current size of the active memtable + immutable memtables
|
||||
*value = cfd_->mem()->ApproximateMemoryUsage() +
|
||||
cfd_->imm()->ApproximateUnflushedMemTablesMemoryUsage();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleSizeAllMemTables(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
*value = cfd_->mem()->ApproximateMemoryUsage() +
|
||||
cfd_->imm()->ApproximateMemoryUsage();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleNumEntriesActiveMemTable(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
// Current number of entires in the active memtable
|
||||
*value = cfd_->mem()->num_entries();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleNumEntriesImmMemTables(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
// Current number of entries in the immutable memtables
|
||||
*value = cfd_->imm()->current()->GetTotalNumEntries();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleNumDeletesActiveMemTable(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
// Current number of entires in the active memtable
|
||||
*value = cfd_->mem()->num_deletes();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleNumDeletesImmMemTables(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
// Current number of entries in the immutable memtables
|
||||
*value = cfd_->imm()->current()->GetTotalNumDeletes();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleEstimateNumKeys(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
// Estimate number of entries in the column family:
|
||||
// Use estimated entries in tables + total entries in memtables.
|
||||
const auto* vstorage = cfd_->current()->storage_info();
|
||||
*value = cfd_->mem()->num_entries() +
|
||||
cfd_->imm()->current()->GetTotalNumEntries() -
|
||||
(cfd_->mem()->num_deletes() +
|
||||
cfd_->imm()->current()->GetTotalNumDeletes()) *
|
||||
2 +
|
||||
vstorage->GetEstimatedActiveKeys();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleNumSnapshots(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
*value = db->snapshots().count();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleOldestSnapshotTime(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
*value = static_cast<uint64_t>(db->snapshots().GetOldestSnapshotTime());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleNumLiveVersions(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
*value = cfd_->GetNumLiveVersions();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleIsFileDeletionsEnabled(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
*value = db->IsFileDeletionsEnabled();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleBaseLevel(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
const auto* vstorage = cfd_->current()->storage_info();
|
||||
*value = vstorage->base_level();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleTotalSstFilesSize(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
*value = cfd_->GetTotalSstFilesSize();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleEstimatePendingCompactionBytes(uint64_t* value,
|
||||
DBImpl* db,
|
||||
Version* version) {
|
||||
const auto* vstorage = cfd_->current()->storage_info();
|
||||
*value = vstorage->estimated_compaction_needed_bytes();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleEstimateTableReadersMem(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
*value = (version == nullptr) ? 0 : version->GetMemoryUsageByTableReaders();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InternalStats::HandleEstimateLiveDataSize(uint64_t* value, DBImpl* db,
|
||||
Version* version) {
|
||||
const auto* vstorage = cfd_->current()->storage_info();
|
||||
*value = vstorage->EstimateLiveDataSize();
|
||||
return true;
|
||||
}
|
||||
|
||||
void InternalStats::DumpDBStats(std::string* value) {
|
||||
@@ -841,7 +757,10 @@ void InternalStats::DumpCFStats(std::string* value) {
|
||||
|
||||
#else
|
||||
|
||||
const DBPropertyInfo* GetPropertyInfo(const Slice& property) { return nullptr; }
|
||||
DBPropertyType GetPropertyType(const Slice& property, bool* is_int_property,
|
||||
bool* need_out_of_mutex) {
|
||||
return kUnknown;
|
||||
}
|
||||
|
||||
#endif // !ROCKSDB_LITE
|
||||
|
||||
|
||||
+67
-91
@@ -21,29 +21,63 @@ namespace rocksdb {
|
||||
class MemTableList;
|
||||
class DBImpl;
|
||||
|
||||
// Config for retrieving a property's value.
|
||||
struct DBPropertyInfo {
|
||||
bool need_out_of_mutex;
|
||||
|
||||
// gcc had an internal error for initializing union of pointer-to-member-
|
||||
// functions. Workaround is to populate exactly one of the following function
|
||||
// pointers with a non-nullptr value.
|
||||
|
||||
// @param value Value-result argument for storing the property's string value
|
||||
// @param suffix Argument portion of the property. For example, suffix would
|
||||
// be "5" for the property "rocksdb.num-files-at-level5". So far, only
|
||||
// certain string properties take an argument.
|
||||
bool (InternalStats::*handle_string)(std::string* value, Slice suffix);
|
||||
|
||||
// @param value Value-result argument for storing the property's uint64 value
|
||||
// @param db Many of the int properties rely on DBImpl methods.
|
||||
// @param version Version is needed in case the property is retrieved without
|
||||
// holding db mutex, which is only supported for int properties.
|
||||
bool (InternalStats::*handle_int)(uint64_t* value, DBImpl* db,
|
||||
Version* version);
|
||||
// IMPORTANT: If you add a new property here, also add it to the list in
|
||||
// include/rocksdb/db.h
|
||||
enum DBPropertyType : uint32_t {
|
||||
kUnknown,
|
||||
kNumFilesAtLevel, // Number of files at a specific level
|
||||
kLevelStats, // Return number of files and total sizes of each level
|
||||
kCFStats, // Return general statitistics of CF
|
||||
kDBStats, // Return general statitistics of DB
|
||||
kStats, // Return general statitistics of both DB and CF
|
||||
kSsTables, // Return a human readable string of current SST files
|
||||
kStartIntTypes, // ---- Dummy value to indicate the start of integer values
|
||||
kNumImmutableMemTable, // Return number of immutable mem tables that
|
||||
// have not been flushed.
|
||||
kNumImmutableMemTableFlushed, // Return number of immutable mem tables
|
||||
// in memory that have already been flushed
|
||||
kMemtableFlushPending, // Return 1 if mem table flushing is pending,
|
||||
// otherwise 0.
|
||||
kNumRunningFlushes, // Return the number of currently running flushes.
|
||||
kCompactionPending, // Return 1 if a compaction is pending. Otherwise 0.
|
||||
kNumRunningCompactions, // Return the number of currently running
|
||||
// compactions.
|
||||
kBackgroundErrors, // Return accumulated background errors encountered.
|
||||
kCurSizeActiveMemTable, // Return current size of the active memtable
|
||||
kCurSizeAllMemTables, // Return current size of unflushed
|
||||
// (active + immutable) memtables
|
||||
kSizeAllMemTables, // Return current size of all (active + immutable
|
||||
// + pinned) memtables
|
||||
kNumEntriesInMutableMemtable, // Return number of deletes in the mutable
|
||||
// memtable.
|
||||
kNumEntriesInImmutableMemtable, // Return sum of number of entries in all
|
||||
// the immutable mem tables.
|
||||
kNumDeletesInMutableMemtable, // Return number of deletion entries in the
|
||||
// mutable memtable.
|
||||
kNumDeletesInImmutableMemtable, // Return the total number of deletion
|
||||
// entries in all the immutable mem tables.
|
||||
kEstimatedNumKeys, // Estimated total number of keys in the database.
|
||||
kEstimatedUsageByTableReaders, // Estimated memory by table readers.
|
||||
kIsFileDeletionEnabled, // Equals disable_delete_obsolete_files_,
|
||||
// 0 means file deletions enabled
|
||||
kNumSnapshots, // Number of snapshots in the system
|
||||
kOldestSnapshotTime, // Unix timestamp of the first snapshot
|
||||
kNumLiveVersions,
|
||||
kEstimateLiveDataSize, // Estimated amount of live data in bytes
|
||||
kTotalSstFilesSize, // Total size of all sst files.
|
||||
kBaseLevel, // The level that L0 data is compacted to
|
||||
kEstimatePendingCompactionBytes, // Estimated bytes to compaction
|
||||
kAggregatedTableProperties, // Return a string that contains the aggregated
|
||||
// table properties.
|
||||
kAggregatedTablePropertiesAtLevel, // Return a string that contains the
|
||||
// aggregated
|
||||
// table properties at the specified level.
|
||||
};
|
||||
|
||||
extern const DBPropertyInfo* GetPropertyInfo(const Slice& property);
|
||||
extern DBPropertyType GetPropertyType(const Slice& property,
|
||||
bool* is_int_property,
|
||||
bool* need_out_of_mutex);
|
||||
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
class InternalStats {
|
||||
@@ -214,18 +248,14 @@ class InternalStats {
|
||||
|
||||
uint64_t BumpAndGetBackgroundErrorCount() { return ++bg_error_count_; }
|
||||
|
||||
bool GetStringProperty(const DBPropertyInfo& property_info,
|
||||
const Slice& property, std::string* value);
|
||||
bool GetStringProperty(DBPropertyType property_type, const Slice& property,
|
||||
std::string* value);
|
||||
|
||||
bool GetIntProperty(const DBPropertyInfo& property_info, uint64_t* value,
|
||||
DBImpl* db);
|
||||
bool GetIntProperty(DBPropertyType property_type, uint64_t* value,
|
||||
DBImpl* db) const;
|
||||
|
||||
bool GetIntPropertyOutOfMutex(const DBPropertyInfo& property_info,
|
||||
Version* version, uint64_t* value);
|
||||
|
||||
// Store a mapping from the user-facing DB::Properties string to our
|
||||
// DBPropertyInfo struct used internally for retrieving properties.
|
||||
static const std::unordered_map<std::string, DBPropertyInfo> ppt_name_to_info;
|
||||
bool GetIntPropertyOutOfMutex(DBPropertyType property_type, Version* version,
|
||||
uint64_t* value) const;
|
||||
|
||||
private:
|
||||
void DumpDBStats(std::string* value);
|
||||
@@ -291,54 +321,6 @@ class InternalStats {
|
||||
seconds_up(0) {}
|
||||
} db_stats_snapshot_;
|
||||
|
||||
// Handler functions for getting property values. They use "value" as a value-
|
||||
// result argument, and return true upon successfully setting "value".
|
||||
bool HandleNumFilesAtLevel(std::string* value, Slice suffix);
|
||||
bool HandleLevelStats(std::string* value, Slice suffix);
|
||||
bool HandleStats(std::string* value, Slice suffix);
|
||||
bool HandleCFStats(std::string* value, Slice suffix);
|
||||
bool HandleDBStats(std::string* value, Slice suffix);
|
||||
bool HandleSsTables(std::string* value, Slice suffix);
|
||||
bool HandleAggregatedTableProperties(std::string* value, Slice suffix);
|
||||
bool HandleAggregatedTablePropertiesAtLevel(std::string* value, Slice suffix);
|
||||
bool HandleNumImmutableMemTable(uint64_t* value, DBImpl* db,
|
||||
Version* version);
|
||||
bool HandleNumImmutableMemTableFlushed(uint64_t* value, DBImpl* db,
|
||||
Version* version);
|
||||
bool HandleMemTableFlushPending(uint64_t* value, DBImpl* db,
|
||||
Version* version);
|
||||
bool HandleNumRunningFlushes(uint64_t* value, DBImpl* db, Version* version);
|
||||
bool HandleCompactionPending(uint64_t* value, DBImpl* db, Version* version);
|
||||
bool HandleNumRunningCompactions(uint64_t* value, DBImpl* db,
|
||||
Version* version);
|
||||
bool HandleBackgroundErrors(uint64_t* value, DBImpl* db, Version* version);
|
||||
bool HandleCurSizeActiveMemTable(uint64_t* value, DBImpl* db,
|
||||
Version* version);
|
||||
bool HandleCurSizeAllMemTables(uint64_t* value, DBImpl* db, Version* version);
|
||||
bool HandleSizeAllMemTables(uint64_t* value, DBImpl* db, Version* version);
|
||||
bool HandleNumEntriesActiveMemTable(uint64_t* value, DBImpl* db,
|
||||
Version* version);
|
||||
bool HandleNumEntriesImmMemTables(uint64_t* value, DBImpl* db,
|
||||
Version* version);
|
||||
bool HandleNumDeletesActiveMemTable(uint64_t* value, DBImpl* db,
|
||||
Version* version);
|
||||
bool HandleNumDeletesImmMemTables(uint64_t* value, DBImpl* db,
|
||||
Version* version);
|
||||
bool HandleEstimateNumKeys(uint64_t* value, DBImpl* db, Version* version);
|
||||
bool HandleNumSnapshots(uint64_t* value, DBImpl* db, Version* version);
|
||||
bool HandleOldestSnapshotTime(uint64_t* value, DBImpl* db, Version* version);
|
||||
bool HandleNumLiveVersions(uint64_t* value, DBImpl* db, Version* version);
|
||||
bool HandleIsFileDeletionsEnabled(uint64_t* value, DBImpl* db,
|
||||
Version* version);
|
||||
bool HandleBaseLevel(uint64_t* value, DBImpl* db, Version* version);
|
||||
bool HandleTotalSstFilesSize(uint64_t* value, DBImpl* db, Version* version);
|
||||
bool HandleEstimatePendingCompactionBytes(uint64_t* value, DBImpl* db,
|
||||
Version* version);
|
||||
bool HandleEstimateTableReadersMem(uint64_t* value, DBImpl* db,
|
||||
Version* version);
|
||||
bool HandleEstimateLiveDataSize(uint64_t* value, DBImpl* db,
|
||||
Version* version);
|
||||
|
||||
// Total number of background errors encountered. Every time a flush task
|
||||
// or compaction task fails, this counter is incremented. The failure can
|
||||
// be caused by any possible reason, including file system errors, out of
|
||||
@@ -420,20 +402,14 @@ class InternalStats {
|
||||
|
||||
uint64_t BumpAndGetBackgroundErrorCount() { return 0; }
|
||||
|
||||
bool GetStringProperty(const DBPropertyInfo& property_info,
|
||||
const Slice& property, std::string* value) {
|
||||
return false;
|
||||
}
|
||||
bool GetStringProperty(DBPropertyType property_type, const Slice& property,
|
||||
std::string* value) { return false; }
|
||||
|
||||
bool GetIntProperty(const DBPropertyInfo& property_info, uint64_t* value,
|
||||
DBImpl* db) const {
|
||||
return false;
|
||||
}
|
||||
bool GetIntProperty(DBPropertyType property_type, uint64_t* value,
|
||||
DBImpl* db) const { return false; }
|
||||
|
||||
bool GetIntPropertyOutOfMutex(const DBPropertyInfo& property_info,
|
||||
Version* version, uint64_t* value) const {
|
||||
return false;
|
||||
}
|
||||
bool GetIntPropertyOutOfMutex(DBPropertyType property_type, Version* version,
|
||||
uint64_t* value) const { return false; }
|
||||
};
|
||||
#endif // !ROCKSDB_LITE
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
|
||||
#include "db/managed_iterator.h"
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@@ -15,7 +13,7 @@
|
||||
#include "db/db_impl.h"
|
||||
#include "db/db_iter.h"
|
||||
#include "db/dbformat.h"
|
||||
#include "db/xfunc_test_points.h"
|
||||
#include "db/managed_iterator.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "rocksdb/slice.h"
|
||||
#include "rocksdb/slice_transform.h"
|
||||
|
||||
+6
-23
@@ -13,7 +13,6 @@
|
||||
#include "rocksdb/slice_transform.h"
|
||||
#include "rocksdb/memtablerep.h"
|
||||
#include "util/histogram.h"
|
||||
#include "util/instrumented_mutex.h"
|
||||
#include "util/stop_watch.h"
|
||||
#include "util/testharness.h"
|
||||
#include "util/thread_status_util.h"
|
||||
@@ -544,31 +543,28 @@ TEST_F(PerfContextTest, SeekKeyComparison) {
|
||||
}
|
||||
|
||||
TEST_F(PerfContextTest, DBMutexLockCounter) {
|
||||
SetPerfLevel(kEnableTime);
|
||||
int stats_code[] = {0, static_cast<int>(DB_MUTEX_WAIT_MICROS)};
|
||||
for (PerfLevel perf_level :
|
||||
{PerfLevel::kEnableTimeExceptForMutex, PerfLevel::kEnableTime}) {
|
||||
for (int c = 0; c < 2; ++c) {
|
||||
for (int c = 0; c < 2; ++c) {
|
||||
InstrumentedMutex mutex(nullptr, Env::Default(), stats_code[c]);
|
||||
mutex.Lock();
|
||||
std::thread child_thread([&] {
|
||||
SetPerfLevel(perf_level);
|
||||
SetPerfLevel(kEnableTime);
|
||||
perf_context.Reset();
|
||||
ASSERT_EQ(perf_context.db_mutex_lock_nanos, 0);
|
||||
mutex.Lock();
|
||||
mutex.Unlock();
|
||||
if (perf_level == PerfLevel::kEnableTimeExceptForMutex ||
|
||||
stats_code[c] != DB_MUTEX_WAIT_MICROS) {
|
||||
ASSERT_EQ(perf_context.db_mutex_lock_nanos, 0);
|
||||
} else {
|
||||
if (stats_code[c] == DB_MUTEX_WAIT_MICROS) {
|
||||
// increment the counter only when it's a DB Mutex
|
||||
ASSERT_GT(perf_context.db_mutex_lock_nanos, 0);
|
||||
} else {
|
||||
ASSERT_EQ(perf_context.db_mutex_lock_nanos, 0);
|
||||
}
|
||||
});
|
||||
Env::Default()->SleepForMicroseconds(100);
|
||||
mutex.Unlock();
|
||||
child_thread.join();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PerfContextTest, FalseDBMutexWait) {
|
||||
@@ -589,19 +585,6 @@ TEST_F(PerfContextTest, FalseDBMutexWait) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PerfContextTest, ToString) {
|
||||
perf_context.Reset();
|
||||
perf_context.block_read_count = 12345;
|
||||
|
||||
std::string zero_included = perf_context.ToString();
|
||||
ASSERT_NE(std::string::npos, zero_included.find("= 0"));
|
||||
ASSERT_NE(std::string::npos, zero_included.find("= 12345"));
|
||||
|
||||
std::string zero_excluded = perf_context.ToString(true);
|
||||
ASSERT_EQ(std::string::npos, zero_excluded.find("= 0"));
|
||||
ASSERT_NE(std::string::npos, zero_excluded.find("= 12345"));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
+1
-1
@@ -273,7 +273,7 @@ Status TableCache::Get(const ReadOptions& options,
|
||||
if (handle != nullptr) {
|
||||
ReleaseHandle(handle);
|
||||
}
|
||||
} else if (options.read_tier == kBlockCacheTier && s.IsIncomplete()) {
|
||||
} else if (options.read_tier && s.IsIncomplete()) {
|
||||
// Couldn't find Table in cache but treat as kFound if no_io set
|
||||
get_context->MarkKeyMayExist();
|
||||
return Status::OK();
|
||||
|
||||
+74
-22
@@ -84,11 +84,15 @@ int FindFileInRange(const InternalKeyComparator& icmp,
|
||||
// are MergeInProgress).
|
||||
class FilePicker {
|
||||
public:
|
||||
FilePicker(std::vector<FileMetaData*>* files, const Slice& user_key,
|
||||
const Slice& ikey, autovector<LevelFilesBrief>* file_levels,
|
||||
unsigned int num_levels, FileIndexer* file_indexer,
|
||||
const Comparator* user_comparator,
|
||||
const InternalKeyComparator* internal_comparator)
|
||||
FilePicker(
|
||||
std::vector<FileMetaData*>* files,
|
||||
const Slice& user_key,
|
||||
const Slice& ikey,
|
||||
autovector<LevelFilesBrief>* file_levels,
|
||||
unsigned int num_levels,
|
||||
FileIndexer* file_indexer,
|
||||
const Comparator* user_comparator,
|
||||
const InternalKeyComparator* internal_comparator)
|
||||
: num_levels_(num_levels),
|
||||
curr_level_(-1),
|
||||
hit_file_level_(-1),
|
||||
@@ -98,7 +102,6 @@ class FilePicker {
|
||||
files_(files),
|
||||
#endif
|
||||
level_files_brief_(file_levels),
|
||||
is_hit_file_last_in_level_(false),
|
||||
user_key_(user_key),
|
||||
ikey_(ikey),
|
||||
file_indexer_(file_indexer),
|
||||
@@ -123,8 +126,6 @@ class FilePicker {
|
||||
// Loops over all files in current level.
|
||||
FdWithKeyRange* f = &curr_file_level_->files[curr_index_in_curr_level_];
|
||||
hit_file_level_ = curr_level_;
|
||||
is_hit_file_last_in_level_ =
|
||||
curr_index_in_curr_level_ == curr_file_level_->num_files - 1;
|
||||
int cmp_largest = -1;
|
||||
|
||||
// Do key range filtering of files or/and fractional cascading if:
|
||||
@@ -208,10 +209,6 @@ class FilePicker {
|
||||
// for GET_HIT_L0, GET_HIT_L1 & GET_HIT_L2_AND_UP counts
|
||||
unsigned int GetHitFileLevel() { return hit_file_level_; }
|
||||
|
||||
// Returns true if the most recent "hit file" (i.e., one returned by
|
||||
// GetNextFile()) is at the last index in its level.
|
||||
bool IsHitFileLastInLevel() { return is_hit_file_last_in_level_; }
|
||||
|
||||
private:
|
||||
unsigned int num_levels_;
|
||||
unsigned int curr_level_;
|
||||
@@ -223,7 +220,6 @@ class FilePicker {
|
||||
#endif
|
||||
autovector<LevelFilesBrief>* level_files_brief_;
|
||||
bool search_ended_;
|
||||
bool is_hit_file_last_in_level_;
|
||||
LevelFilesBrief* curr_file_level_;
|
||||
unsigned int curr_index_in_curr_level_;
|
||||
unsigned int start_index_in_curr_level_;
|
||||
@@ -762,7 +758,7 @@ uint64_t VersionStorageInfo::GetEstimatedActiveKeys() const {
|
||||
|
||||
if (current_num_samples_ < file_count) {
|
||||
// casting to avoid overflowing
|
||||
return
|
||||
return
|
||||
static_cast<uint64_t>(
|
||||
(est * static_cast<double>(file_count) / current_num_samples_)
|
||||
);
|
||||
@@ -907,8 +903,7 @@ void Version::Get(const ReadOptions& read_options, const LookupKey& k,
|
||||
*status = table_cache_->Get(
|
||||
read_options, *internal_comparator(), f->fd, ikey, &get_context,
|
||||
cfd_->internal_stats()->GetFileReadHist(fp.GetHitFileLevel()),
|
||||
IsFilterSkipped(static_cast<int>(fp.GetHitFileLevel()),
|
||||
fp.IsHitFileLastInLevel()));
|
||||
IsFilterSkipped(static_cast<int>(fp.GetHitFileLevel())));
|
||||
// TODO: examine the behavior for corrupted key
|
||||
if (!status->ok()) {
|
||||
return;
|
||||
@@ -965,11 +960,10 @@ void Version::Get(const ReadOptions& read_options, const LookupKey& k,
|
||||
}
|
||||
}
|
||||
|
||||
bool Version::IsFilterSkipped(int level, bool is_file_last_in_level) {
|
||||
bool Version::IsFilterSkipped(int level) {
|
||||
// Reaching the bottom level implies misses at all upper levels, so we'll
|
||||
// skip checking the filters when we predict a hit.
|
||||
return cfd_->ioptions()->optimize_filters_for_hits &&
|
||||
(level > 0 || is_file_last_in_level) &&
|
||||
return cfd_->ioptions()->optimize_filters_for_hits && level > 0 &&
|
||||
level == storage_info_.num_non_empty_levels() - 1;
|
||||
}
|
||||
|
||||
@@ -2199,6 +2193,27 @@ Status VersionSet::LogAndApply(ColumnFamilyData* column_family_data,
|
||||
if (!s.ok()) {
|
||||
Log(InfoLogLevel::ERROR_LEVEL, db_options_->info_log,
|
||||
"MANIFEST write: %s\n", s.ToString().c_str());
|
||||
bool all_records_in = true;
|
||||
for (auto& e : batch_edits) {
|
||||
std::string record;
|
||||
if (!e->EncodeTo(&record)) {
|
||||
s = Status::Corruption(
|
||||
"Unable to Encode VersionEdit:" + e->DebugString(true));
|
||||
all_records_in = false;
|
||||
break;
|
||||
}
|
||||
if (!ManifestContains(pending_manifest_file_number_, record)) {
|
||||
all_records_in = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (all_records_in) {
|
||||
Log(InfoLogLevel::WARN_LEVEL, db_options_->info_log,
|
||||
"MANIFEST contains log record despite error; advancing to new "
|
||||
"version to prevent mismatch between in-memory and logged state"
|
||||
" If paranoid is set, then the db is now in readonly mode.");
|
||||
s = Status::OK();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2224,7 +2239,6 @@ Status VersionSet::LogAndApply(ColumnFamilyData* column_family_data,
|
||||
}
|
||||
|
||||
if (edit->is_column_family_drop_) {
|
||||
TEST_SYNC_POINT("VersionSet::LogAndApply::ColumnFamilyDrop:0");
|
||||
TEST_SYNC_POINT("VersionSet::LogAndApply::ColumnFamilyDrop:1");
|
||||
TEST_SYNC_POINT("VersionSet::LogAndApply::ColumnFamilyDrop:2");
|
||||
}
|
||||
@@ -2268,8 +2282,7 @@ Status VersionSet::LogAndApply(ColumnFamilyData* column_family_data,
|
||||
Log(InfoLogLevel::ERROR_LEVEL, db_options_->info_log,
|
||||
"Error in committing version %lu to [%s]",
|
||||
(unsigned long)v->GetVersionNumber(),
|
||||
column_family_data ? column_family_data->GetName().c_str()
|
||||
: "<null>");
|
||||
column_family_data->GetName().c_str());
|
||||
delete v;
|
||||
if (new_descriptor_log) {
|
||||
Log(InfoLogLevel::INFO_LEVEL, db_options_->info_log,
|
||||
@@ -3053,6 +3066,45 @@ Status VersionSet::WriteSnapshot(log::Writer* log) {
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
// Opens the mainfest file and reads all records
|
||||
// till it finds the record we are looking for.
|
||||
bool VersionSet::ManifestContains(uint64_t manifest_file_num,
|
||||
const std::string& record) const {
|
||||
std::string fname = DescriptorFileName(dbname_, manifest_file_num);
|
||||
Log(InfoLogLevel::INFO_LEVEL, db_options_->info_log,
|
||||
"ManifestContains: checking %s\n", fname.c_str());
|
||||
|
||||
unique_ptr<SequentialFileReader> file_reader;
|
||||
Status s;
|
||||
{
|
||||
unique_ptr<SequentialFile> file;
|
||||
s = env_->NewSequentialFile(fname, &file, env_options_);
|
||||
if (!s.ok()) {
|
||||
Log(InfoLogLevel::INFO_LEVEL, db_options_->info_log,
|
||||
"ManifestContains: %s\n", s.ToString().c_str());
|
||||
Log(InfoLogLevel::INFO_LEVEL, db_options_->info_log,
|
||||
"ManifestContains: is unable to reopen the manifest file %s",
|
||||
fname.c_str());
|
||||
return false;
|
||||
}
|
||||
file_reader.reset(new SequentialFileReader(std::move(file)));
|
||||
}
|
||||
log::Reader reader(NULL, std::move(file_reader), nullptr,
|
||||
true /*checksum*/, 0, 0);
|
||||
Slice r;
|
||||
std::string scratch;
|
||||
bool result = false;
|
||||
while (reader.ReadRecord(&r, &scratch)) {
|
||||
if (r == Slice(record)) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Log(InfoLogLevel::INFO_LEVEL, db_options_->info_log,
|
||||
"ManifestContains: result = %d\n", result ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO(aekmekji): in CompactionJob::GenSubcompactionBoundaries(), this
|
||||
// function is called repeatedly with consecutive pairs of slices. For example
|
||||
// if the slice list is [a, b, c, d] this function is called with arguments
|
||||
|
||||
+4
-1
@@ -530,7 +530,7 @@ class Version {
|
||||
// checked during read operations. In certain cases (trivial move or preload),
|
||||
// the filter block may already be cached, but we still do not access it such
|
||||
// that it eventually expires from the cache.
|
||||
bool IsFilterSkipped(int level, bool is_file_last_in_level = false);
|
||||
bool IsFilterSkipped(int level);
|
||||
|
||||
// The helper function of UpdateAccumulatedStats, which may fill the missing
|
||||
// fields of file_mata from its associated TableProperties.
|
||||
@@ -731,6 +731,9 @@ class VersionSet {
|
||||
|
||||
void AppendVersion(ColumnFamilyData* column_family_data, Version* v);
|
||||
|
||||
bool ManifestContains(uint64_t manifest_file_number,
|
||||
const std::string& record) const;
|
||||
|
||||
ColumnFamilyData* CreateColumnFamily(const ColumnFamilyOptions& cf_options,
|
||||
VersionEdit* edit);
|
||||
|
||||
|
||||
@@ -308,120 +308,6 @@ TEST_F(WriteBatchTest, Blob) {
|
||||
handler.seen);
|
||||
}
|
||||
|
||||
// It requires more than 30GB of memory to run the test. With single memory
|
||||
// allocation of more than 30GB.
|
||||
// Not all platform can run it. Also it runs a long time. So disable it.
|
||||
TEST_F(WriteBatchTest, DISABLED_ManyUpdates) {
|
||||
// Insert key and value of 3GB and push total batch size to 12GB.
|
||||
static const size_t kKeyValueSize = 4u;
|
||||
static const uint32_t kNumUpdates = 3 << 30;
|
||||
std::string raw(kKeyValueSize, 'A');
|
||||
WriteBatch batch(kNumUpdates * (4 + kKeyValueSize * 2) + 1024u);
|
||||
char c = 'A';
|
||||
for (uint32_t i = 0; i < kNumUpdates; i++) {
|
||||
if (c > 'Z') {
|
||||
c = 'A';
|
||||
}
|
||||
raw[0] = c;
|
||||
raw[raw.length() - 1] = c;
|
||||
c++;
|
||||
batch.Put(raw, raw);
|
||||
}
|
||||
|
||||
ASSERT_EQ(kNumUpdates, batch.Count());
|
||||
|
||||
struct NoopHandler : public WriteBatch::Handler {
|
||||
uint32_t num_seen = 0;
|
||||
char expected_char = 'A';
|
||||
virtual Status PutCF(uint32_t column_family_id, const Slice& key,
|
||||
const Slice& value) override {
|
||||
EXPECT_EQ(kKeyValueSize, key.size());
|
||||
EXPECT_EQ(kKeyValueSize, value.size());
|
||||
EXPECT_EQ(expected_char, key[0]);
|
||||
EXPECT_EQ(expected_char, value[0]);
|
||||
EXPECT_EQ(expected_char, key[kKeyValueSize - 1]);
|
||||
EXPECT_EQ(expected_char, value[kKeyValueSize - 1]);
|
||||
expected_char++;
|
||||
if (expected_char > 'Z') {
|
||||
expected_char = 'A';
|
||||
}
|
||||
++num_seen;
|
||||
return Status::OK();
|
||||
}
|
||||
virtual Status DeleteCF(uint32_t column_family_id,
|
||||
const Slice& key) override {
|
||||
EXPECT_TRUE(false);
|
||||
return Status::OK();
|
||||
}
|
||||
virtual Status SingleDeleteCF(uint32_t column_family_id,
|
||||
const Slice& key) override {
|
||||
EXPECT_TRUE(false);
|
||||
return Status::OK();
|
||||
}
|
||||
virtual Status MergeCF(uint32_t column_family_id, const Slice& key,
|
||||
const Slice& value) override {
|
||||
EXPECT_TRUE(false);
|
||||
return Status::OK();
|
||||
}
|
||||
virtual void LogData(const Slice& blob) override { EXPECT_TRUE(false); }
|
||||
virtual bool Continue() override { return num_seen < kNumUpdates; }
|
||||
} handler;
|
||||
|
||||
batch.Iterate(&handler);
|
||||
ASSERT_EQ(kNumUpdates, handler.num_seen);
|
||||
}
|
||||
|
||||
// The test requires more than 18GB memory to run it, with single memory
|
||||
// allocation of more than 12GB. Not all the platform can run it. So disable it.
|
||||
TEST_F(WriteBatchTest, DISABLED_LargeKeyValue) {
|
||||
// Insert key and value of 3GB and push total batch size to 12GB.
|
||||
static const size_t kKeyValueSize = 3221225472u;
|
||||
std::string raw(kKeyValueSize, 'A');
|
||||
WriteBatch batch(12884901888u + 1024u);
|
||||
for (char i = 0; i < 2; i++) {
|
||||
raw[0] = 'A' + i;
|
||||
raw[raw.length() - 1] = 'A' - i;
|
||||
batch.Put(raw, raw);
|
||||
}
|
||||
|
||||
ASSERT_EQ(2, batch.Count());
|
||||
|
||||
struct NoopHandler : public WriteBatch::Handler {
|
||||
int num_seen = 0;
|
||||
virtual Status PutCF(uint32_t column_family_id, const Slice& key,
|
||||
const Slice& value) override {
|
||||
EXPECT_EQ(kKeyValueSize, key.size());
|
||||
EXPECT_EQ(kKeyValueSize, value.size());
|
||||
EXPECT_EQ('A' + num_seen, key[0]);
|
||||
EXPECT_EQ('A' + num_seen, value[0]);
|
||||
EXPECT_EQ('A' - num_seen, key[kKeyValueSize - 1]);
|
||||
EXPECT_EQ('A' - num_seen, value[kKeyValueSize - 1]);
|
||||
++num_seen;
|
||||
return Status::OK();
|
||||
}
|
||||
virtual Status DeleteCF(uint32_t column_family_id,
|
||||
const Slice& key) override {
|
||||
EXPECT_TRUE(false);
|
||||
return Status::OK();
|
||||
}
|
||||
virtual Status SingleDeleteCF(uint32_t column_family_id,
|
||||
const Slice& key) override {
|
||||
EXPECT_TRUE(false);
|
||||
return Status::OK();
|
||||
}
|
||||
virtual Status MergeCF(uint32_t column_family_id, const Slice& key,
|
||||
const Slice& value) override {
|
||||
EXPECT_TRUE(false);
|
||||
return Status::OK();
|
||||
}
|
||||
virtual void LogData(const Slice& blob) override { EXPECT_TRUE(false); }
|
||||
virtual bool Continue() override { return num_seen < 2; }
|
||||
} handler;
|
||||
|
||||
batch.Iterate(&handler);
|
||||
ASSERT_EQ(2, handler.num_seen);
|
||||
}
|
||||
|
||||
TEST_F(WriteBatchTest, Continue) {
|
||||
WriteBatch batch;
|
||||
|
||||
|
||||
@@ -26,13 +26,6 @@ std::unique_ptr<WriteControllerToken> WriteController::GetDelayToken(
|
||||
return std::unique_ptr<WriteControllerToken>(new DelayWriteToken(this));
|
||||
}
|
||||
|
||||
std::unique_ptr<WriteControllerToken>
|
||||
WriteController::GetCompactionPressureToken() {
|
||||
++total_compaction_pressure_;
|
||||
return std::unique_ptr<WriteControllerToken>(
|
||||
new CompactionPressureToken(this));
|
||||
}
|
||||
|
||||
bool WriteController::IsStopped() const { return total_stopped_ > 0; }
|
||||
// This is inside DB mutex, so we can't sleep and need to minimize
|
||||
// frequency to get time.
|
||||
@@ -113,9 +106,4 @@ DelayWriteToken::~DelayWriteToken() {
|
||||
assert(controller_->total_delayed_ >= 0);
|
||||
}
|
||||
|
||||
CompactionPressureToken::~CompactionPressureToken() {
|
||||
controller_->total_compaction_pressure_--;
|
||||
assert(controller_->total_compaction_pressure_ >= 0);
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
+1
-17
@@ -23,7 +23,6 @@ class WriteController {
|
||||
explicit WriteController(uint64_t _delayed_write_rate = 1024u * 1024u * 32u)
|
||||
: total_stopped_(0),
|
||||
total_delayed_(0),
|
||||
total_compaction_pressure_(0),
|
||||
bytes_left_(0),
|
||||
last_refill_time_(0) {
|
||||
set_delayed_write_rate(_delayed_write_rate);
|
||||
@@ -39,16 +38,10 @@ class WriteController {
|
||||
// which returns number of microseconds to sleep.
|
||||
std::unique_ptr<WriteControllerToken> GetDelayToken(
|
||||
uint64_t delayed_write_rate);
|
||||
// When an actor (column family) requests a moderate token, compaction
|
||||
// threads will be increased
|
||||
std::unique_ptr<WriteControllerToken> GetCompactionPressureToken();
|
||||
|
||||
// these three metods are querying the state of the WriteController
|
||||
// these two metods are querying the state of the WriteController
|
||||
bool IsStopped() const;
|
||||
bool NeedsDelay() const { return total_delayed_ > 0; }
|
||||
bool NeedSpeedupCompaction() const {
|
||||
return IsStopped() || NeedsDelay() || total_compaction_pressure_ > 0;
|
||||
}
|
||||
// return how many microseconds the caller needs to sleep after the call
|
||||
// num_bytes: how many number of bytes to put into the DB.
|
||||
// Prerequisite: DB mutex held.
|
||||
@@ -66,11 +59,9 @@ class WriteController {
|
||||
friend class WriteControllerToken;
|
||||
friend class StopWriteToken;
|
||||
friend class DelayWriteToken;
|
||||
friend class CompactionPressureToken;
|
||||
|
||||
int total_stopped_;
|
||||
int total_delayed_;
|
||||
int total_compaction_pressure_;
|
||||
uint64_t bytes_left_;
|
||||
uint64_t last_refill_time_;
|
||||
uint64_t delayed_write_rate_;
|
||||
@@ -105,11 +96,4 @@ class DelayWriteToken : public WriteControllerToken {
|
||||
virtual ~DelayWriteToken();
|
||||
};
|
||||
|
||||
class CompactionPressureToken : public WriteControllerToken {
|
||||
public:
|
||||
explicit CompactionPressureToken(WriteController* controller)
|
||||
: WriteControllerToken(controller) {}
|
||||
virtual ~CompactionPressureToken();
|
||||
};
|
||||
|
||||
} // namespace rocksdb
|
||||
@@ -1,145 +0,0 @@
|
||||
// Copyright (c) 2016, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
#include "db/xfunc_test_points.h"
|
||||
#include "util/xfunc.h"
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
#ifdef XFUNC
|
||||
|
||||
void xf_manage_release(ManagedIterator* iter) {
|
||||
if (!(XFuncPoint::GetSkip() & kSkipNoPrefix)) {
|
||||
iter->ReleaseIter(false);
|
||||
}
|
||||
}
|
||||
|
||||
void xf_manage_create(ManagedIterator* iter) { iter->SetDropOld(false); }
|
||||
|
||||
void xf_manage_new(DBImpl* db, ReadOptions* read_options,
|
||||
bool is_snapshot_supported) {
|
||||
if ((!XFuncPoint::Check("managed_xftest_dropold") &&
|
||||
(!XFuncPoint::Check("managed_xftest_release"))) ||
|
||||
(!read_options->managed)) {
|
||||
return;
|
||||
}
|
||||
if ((!read_options->tailing) && (read_options->snapshot == nullptr) &&
|
||||
(!is_snapshot_supported)) {
|
||||
read_options->managed = false;
|
||||
return;
|
||||
}
|
||||
if (db->GetOptions().prefix_extractor != nullptr) {
|
||||
if (strcmp(db->GetOptions().table_factory.get()->Name(), "PlainTable")) {
|
||||
if (!(XFuncPoint::GetSkip() & kSkipNoPrefix)) {
|
||||
read_options->total_order_seek = true;
|
||||
}
|
||||
} else {
|
||||
read_options->managed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class XFTransactionWriteHandler : public WriteBatch::Handler {
|
||||
public:
|
||||
Transaction* txn_;
|
||||
DBImpl* db_impl_;
|
||||
|
||||
XFTransactionWriteHandler(Transaction* txn, DBImpl* db_impl)
|
||||
: txn_(txn), db_impl_(db_impl) {}
|
||||
|
||||
virtual Status PutCF(uint32_t column_family_id, const Slice& key,
|
||||
const Slice& value) override {
|
||||
InstrumentedMutexLock l(&db_impl_->mutex_);
|
||||
|
||||
ColumnFamilyHandle* cfh = db_impl_->GetColumnFamilyHandle(column_family_id);
|
||||
if (cfh == nullptr) {
|
||||
return Status::InvalidArgument(
|
||||
"XFUNC test could not find column family "
|
||||
"handle for id ",
|
||||
ToString(column_family_id));
|
||||
}
|
||||
|
||||
txn_->Put(cfh, key, value);
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
virtual Status MergeCF(uint32_t column_family_id, const Slice& key,
|
||||
const Slice& value) override {
|
||||
InstrumentedMutexLock l(&db_impl_->mutex_);
|
||||
|
||||
ColumnFamilyHandle* cfh = db_impl_->GetColumnFamilyHandle(column_family_id);
|
||||
if (cfh == nullptr) {
|
||||
return Status::InvalidArgument(
|
||||
"XFUNC test could not find column family "
|
||||
"handle for id ",
|
||||
ToString(column_family_id));
|
||||
}
|
||||
|
||||
txn_->Merge(cfh, key, value);
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
virtual Status DeleteCF(uint32_t column_family_id,
|
||||
const Slice& key) override {
|
||||
InstrumentedMutexLock l(&db_impl_->mutex_);
|
||||
|
||||
ColumnFamilyHandle* cfh = db_impl_->GetColumnFamilyHandle(column_family_id);
|
||||
if (cfh == nullptr) {
|
||||
return Status::InvalidArgument(
|
||||
"XFUNC test could not find column family "
|
||||
"handle for id ",
|
||||
ToString(column_family_id));
|
||||
}
|
||||
|
||||
txn_->Delete(cfh, key);
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
virtual void LogData(const Slice& blob) override { txn_->PutLogData(blob); }
|
||||
};
|
||||
|
||||
// Whenever DBImpl::Write is called, create a transaction and do the write via
|
||||
// the transaction.
|
||||
void xf_transaction_write(const WriteOptions& write_options,
|
||||
const DBOptions& db_options, WriteBatch* my_batch,
|
||||
WriteCallback* callback, DBImpl* db_impl, Status* s,
|
||||
bool* write_attempted) {
|
||||
if (callback != nullptr) {
|
||||
// We may already be in a transaction, don't force a transaction
|
||||
*write_attempted = false;
|
||||
return;
|
||||
}
|
||||
|
||||
OptimisticTransactionDB* txn_db = new OptimisticTransactionDB(db_impl);
|
||||
Transaction* txn = Transaction::BeginTransaction(txn_db, write_options);
|
||||
|
||||
XFTransactionWriteHandler handler(txn, db_impl);
|
||||
*s = my_batch->Iterate(&handler);
|
||||
|
||||
if (!s->ok()) {
|
||||
Log(InfoLogLevel::ERROR_LEVEL, db_options.info_log,
|
||||
"XFUNC test could not iterate batch. status: $s\n",
|
||||
s->ToString().c_str());
|
||||
}
|
||||
|
||||
*s = txn->Commit();
|
||||
|
||||
if (!s->ok()) {
|
||||
Log(InfoLogLevel::ERROR_LEVEL, db_options.info_log,
|
||||
"XFUNC test could not commit transaction. status: $s\n",
|
||||
s->ToString().c_str());
|
||||
}
|
||||
|
||||
*write_attempted = true;
|
||||
delete txn;
|
||||
delete txn_db;
|
||||
}
|
||||
|
||||
#endif // XFUNC
|
||||
|
||||
} // namespace rocksdb
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright (c) 2016, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "db/db_impl.h"
|
||||
#include "db/managed_iterator.h"
|
||||
#include "db/write_callback.h"
|
||||
#include "rocksdb/options.h"
|
||||
#include "rocksdb/write_batch.h"
|
||||
#include "util/xfunc.h"
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
#ifdef XFUNC
|
||||
|
||||
// DB-specific test points for the cross-functional test framework (see
|
||||
// util/xfunc.h).
|
||||
void xf_manage_release(ManagedIterator* iter);
|
||||
void xf_manage_create(ManagedIterator* iter);
|
||||
void xf_manage_new(DBImpl* db, ReadOptions* readoptions,
|
||||
bool is_snapshot_supported);
|
||||
void xf_transaction_write(const WriteOptions& write_options,
|
||||
const DBOptions& db_options,
|
||||
class WriteBatch* my_batch,
|
||||
class WriteCallback* callback, DBImpl* db_impl,
|
||||
Status* success, bool* write_attempted);
|
||||
|
||||
#endif // XFUNC
|
||||
|
||||
} // namespace rocksdb
|
||||
+52
-117
@@ -327,157 +327,92 @@ class DB {
|
||||
// use "snapshot" after this call.
|
||||
virtual void ReleaseSnapshot(const Snapshot* snapshot) = 0;
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
// Contains all valid property arguments for GetProperty().
|
||||
// DB implementations can export properties about their state
|
||||
// via this method. If "property" is a valid property understood by this
|
||||
// DB implementation, fills "*value" with its current value and returns
|
||||
// true. Otherwise returns false.
|
||||
//
|
||||
// NOTE: Property names cannot end in numbers since those are interpreted as
|
||||
// arguments, e.g., see kNumFilesAtLevelPrefix.
|
||||
//
|
||||
// Valid property names include:
|
||||
//
|
||||
// "rocksdb.num-files-at-level<N>" - return the number of files at level <N>,
|
||||
// where <N> is an ASCII representation of a level number (e.g. "0").
|
||||
// "rocksdb.stats" - returns a multi-line string that describes statistics
|
||||
// about the internal operation of the DB.
|
||||
// "rocksdb.sstables" - returns a multi-line string that describes all
|
||||
// of the sstables that make up the db contents.
|
||||
// "rocksdb.cfstats"
|
||||
// "rocksdb.dbstats"
|
||||
// "rocksdb.num-immutable-mem-table"
|
||||
// "rocksdb.mem-table-flush-pending"
|
||||
// "rocksdb.compaction-pending" - 1 if at least one compaction is pending
|
||||
// "rocksdb.background-errors" - accumulated number of background errors
|
||||
// "rocksdb.cur-size-active-mem-table"
|
||||
// "rocksdb.size-all-mem-tables"
|
||||
// "rocksdb.num-entries-active-mem-table"
|
||||
// "rocksdb.num-entries-imm-mem-tables"
|
||||
// "rocksdb.num-deletes-active-mem-table"
|
||||
// "rocksdb.num-deletes-imm-mem-tables"
|
||||
// "rocksdb.estimate-num-keys" - estimated keys in the column family
|
||||
// "rocksdb.estimate-table-readers-mem" - estimated memory used for reding
|
||||
// SST tables, that is not counted as a part of block cache.
|
||||
// "rocksdb.is-file-deletions-enabled"
|
||||
// "rocksdb.num-snapshots"
|
||||
// "rocksdb.oldest-snapshot-time"
|
||||
// "rocksdb.num-live-versions" - `version` is an internal data structure.
|
||||
// See version_set.h for details. More live versions often mean more SST
|
||||
// files are held from being deleted, by iterators or unfinished
|
||||
// compactions.
|
||||
// "rocksdb.estimate-live-data-size"
|
||||
// "rocksdb.total-sst-files-size" - total size of all used sst files, this
|
||||
// may slow down online queries if there are too many files.
|
||||
// "rocksdb.base-level"
|
||||
// "rocksdb.estimate-pending-compaction-bytes" - estimated total number of
|
||||
// bytes compaction needs to rewrite the data to get all levels down
|
||||
// to under target size. Not valid for other compactions than
|
||||
// level-based.
|
||||
// "rocksdb.aggregated-table-properties" - returns a string representation
|
||||
// of the aggregated table properties of the target column family.
|
||||
// "rocksdb.aggregated-table-properties-at-level<N>", same as the previous
|
||||
// one but only returns the aggregated table properties of the specified
|
||||
// level "N" at the target column family.
|
||||
// "rocksdb.num-running-compactions" - the number of currently running
|
||||
// compacitons.
|
||||
// "rocksdb.num-running-flushes" - the number of currently running flushes.
|
||||
#ifndef ROCKSDB_LITE
|
||||
struct Properties {
|
||||
// "rocksdb.num-files-at-level<N>" - returns string containing the number
|
||||
// of files at level <N>, where <N> is an ASCII representation of a
|
||||
// level number (e.g., "0").
|
||||
static const std::string kNumFilesAtLevelPrefix;
|
||||
|
||||
// "rocksdb.stats" - returns a multi-line string containing the data
|
||||
// described by kCFStats followed by the data described by kDBStats.
|
||||
static const std::string kStats;
|
||||
|
||||
// "rocksdb.sstables" - returns a multi-line string summarizing current
|
||||
// SST files.
|
||||
static const std::string kSSTables;
|
||||
|
||||
// "rocksdb.cfstats" - returns a multi-line string with general column
|
||||
// family stats per-level over db's lifetime ("L<n>"), aggregated over
|
||||
// db's lifetime ("Sum"), and aggregated over the interval since the
|
||||
// last retrieval ("Int").
|
||||
static const std::string kCFStats;
|
||||
|
||||
// "rocksdb.dbstats" - returns a multi-line string with general database
|
||||
// stats, both cumulative (over the db's lifetime) and interval (since
|
||||
// the last retrieval of kDBStats).
|
||||
static const std::string kDBStats;
|
||||
|
||||
// "rocksdb.levelstats" - returns multi-line string containing the number
|
||||
// of files per level and total size of each level (MB).
|
||||
static const std::string kLevelStats;
|
||||
|
||||
// "rocksdb.num-immutable-mem-table" - returns number of immutable
|
||||
// memtables that have not yet been flushed.
|
||||
static const std::string kNumImmutableMemTable;
|
||||
|
||||
// "rocksdb.num-immutable-mem-table-flushed" - returns number of immutable
|
||||
// memtables that have already been flushed.
|
||||
static const std::string kNumImmutableMemTableFlushed;
|
||||
|
||||
// "rocksdb.mem-table-flush-pending" - returns 1 if a memtable flush is
|
||||
// pending; otherwise, returns 0.
|
||||
static const std::string kMemTableFlushPending;
|
||||
|
||||
// "rocksdb.num-running-flushes" - returns the number of currently running
|
||||
// flushes.
|
||||
static const std::string kNumRunningFlushes;
|
||||
|
||||
// "rocksdb.compaction-pending" - returns 1 if at least one compaction is
|
||||
// pending; otherwise, returns 0.
|
||||
static const std::string kCompactionPending;
|
||||
|
||||
// "rocksdb.num-running-compactions" - returns the number of currently
|
||||
// running compactions.
|
||||
static const std::string kNumRunningCompactions;
|
||||
|
||||
// "rocksdb.background-errors" - returns accumulated number of background
|
||||
// errors.
|
||||
static const std::string kBackgroundErrors;
|
||||
|
||||
// "rocksdb.cur-size-active-mem-table" - returns approximate size of active
|
||||
// memtable (bytes).
|
||||
static const std::string kCurSizeActiveMemTable;
|
||||
|
||||
// "rocksdb.cur-size-all-mem-tables" - returns approximate size of active
|
||||
// and unflushed immutable memtables (bytes).
|
||||
static const std::string kCurSizeAllMemTables;
|
||||
|
||||
// "rocksdb.size-all-mem-tables" - returns approximate size of active,
|
||||
// unflushed immutable, and pinned immutable memtables (bytes).
|
||||
static const std::string kSizeAllMemTables;
|
||||
|
||||
// "rocksdb.num-entries-active-mem-table" - returns total number of entries
|
||||
// in the active memtable.
|
||||
static const std::string kNumEntriesActiveMemTable;
|
||||
|
||||
// "rocksdb.num-entries-imm-mem-tables" - returns total number of entries
|
||||
// in the unflushed immutable memtables.
|
||||
static const std::string kNumEntriesImmMemTables;
|
||||
|
||||
// "rocksdb.num-deletes-active-mem-table" - returns total number of delete
|
||||
// entries in the active memtable.
|
||||
static const std::string kNumDeletesActiveMemTable;
|
||||
|
||||
// "rocksdb.num-deletes-imm-mem-tables" - returns total number of delete
|
||||
// entries in the unflushed immutable memtables.
|
||||
static const std::string kNumDeletesImmMemTables;
|
||||
|
||||
// "rocksdb.estimate-num-keys" - returns estimated number of total keys in
|
||||
// the active and unflushed immutable memtables.
|
||||
static const std::string kEstimateNumKeys;
|
||||
|
||||
// "rocksdb.estimate-table-readers-mem" - returns estimated memory used for
|
||||
// reading SST tables, excluding memory used in block cache (e.g.,
|
||||
// filter and index blocks).
|
||||
static const std::string kEstimateTableReadersMem;
|
||||
|
||||
// "rocksdb.is-file-deletions-enabled" - returns 0 if deletion of obsolete
|
||||
// files is enabled; otherwise, returns a non-zero number.
|
||||
static const std::string kIsFileDeletionsEnabled;
|
||||
|
||||
// "rocksdb.num-snapshots" - returns number of unreleased snapshots of the
|
||||
// database.
|
||||
static const std::string kNumSnapshots;
|
||||
|
||||
// "rocksdb.oldest-snapshot-time" - returns number representing unix
|
||||
// timestamp of oldest unreleased snapshot.
|
||||
static const std::string kOldestSnapshotTime;
|
||||
|
||||
// "rocksdb.num-live-versions" - returns number of live versions. `Version`
|
||||
// is an internal data structure. See version_set.h for details. More
|
||||
// live versions often mean more SST files are held from being deleted,
|
||||
// by iterators or unfinished compactions.
|
||||
static const std::string kNumLiveVersions;
|
||||
|
||||
// "rocksdb.estimate-live-data-size" - returns an estimate of the amount of
|
||||
// live data in bytes.
|
||||
static const std::string kEstimateLiveDataSize;
|
||||
|
||||
// "rocksdb.total-sst-files-size" - returns total size (bytes) of all SST
|
||||
// files.
|
||||
// WARNING: may slow down online queries if there are too many files.
|
||||
static const std::string kTotalSstFilesSize;
|
||||
|
||||
// "rocksdb.base-level" - returns number of level to which L0 data will be
|
||||
// compacted.
|
||||
static const std::string kBaseLevel;
|
||||
|
||||
// "rocksdb.estimate-pending-compaction-bytes" - returns estimated total
|
||||
// number of bytes compaction needs to rewrite to get all levels down
|
||||
// to under target size. Not valid for other compactions than level-
|
||||
// based.
|
||||
static const std::string kEstimatePendingCompactionBytes;
|
||||
|
||||
// "rocksdb.aggregated-table-properties" - returns a string representation
|
||||
// of the aggregated table properties of the target column family.
|
||||
static const std::string kAggregatedTableProperties;
|
||||
|
||||
// "rocksdb.aggregated-table-properties-at-level<N>", same as the previous
|
||||
// one but only returns the aggregated table properties of the
|
||||
// specified level "N" at the target column family.
|
||||
static const std::string kAggregatedTablePropertiesAtLevel;
|
||||
};
|
||||
#endif /* ROCKSDB_LITE */
|
||||
|
||||
// DB implementations can export properties about their state via this method.
|
||||
// If "property" is a valid property understood by this DB implementation (see
|
||||
// Properties struct above for valid options), fills "*value" with its current
|
||||
// value and returns true. Otherwise, returns false.
|
||||
virtual bool GetProperty(ColumnFamilyHandle* column_family,
|
||||
const Slice& property, std::string* value) = 0;
|
||||
virtual bool GetProperty(const Slice& property, std::string* value) {
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2015, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "rocksdb/status.h"
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
class Env;
|
||||
class Logger;
|
||||
|
||||
// DeleteScheduler allow the DB to enforce a rate limit on file deletion,
|
||||
// Instead of deleteing files immediately, files are moved to trash_dir
|
||||
// and deleted in a background thread that apply sleep penlty between deletes
|
||||
// if they are happening in a rate faster than rate_bytes_per_sec,
|
||||
//
|
||||
// Rate limiting can be turned off by setting rate_bytes_per_sec = 0, In this
|
||||
// case DeleteScheduler will delete files immediately.
|
||||
class DeleteScheduler {
|
||||
public:
|
||||
virtual ~DeleteScheduler() {}
|
||||
|
||||
// Return delete rate limit in bytes per second
|
||||
virtual int64_t GetRateBytesPerSecond() = 0;
|
||||
|
||||
// Move file to trash directory and schedule it's deletion
|
||||
virtual Status DeleteFile(const std::string& fname) = 0;
|
||||
|
||||
// Return a map containing errors that happened in the background thread
|
||||
// file_path => error status
|
||||
virtual std::map<std::string, Status> GetBackgroundErrors() = 0;
|
||||
|
||||
// Wait for all files being deleteing in the background to finish or for
|
||||
// destructor to be called.
|
||||
virtual void WaitForEmptyTrash() = 0;
|
||||
};
|
||||
|
||||
// Create a new DeleteScheduler that can be shared among multiple RocksDB
|
||||
// instances to control the file deletion rate.
|
||||
//
|
||||
// @env: Pointer to Env object, please see "rocksdb/env.h".
|
||||
// @trash_dir: Path to the directory where deleted files will be moved into
|
||||
// to be deleted in a background thread while applying rate limiting. If this
|
||||
// directory dont exist, it will be created. This directory should not be
|
||||
// used by any other process or any other DeleteScheduler.
|
||||
// @rate_bytes_per_sec: How many bytes should be deleted per second, If this
|
||||
// value is set to 1024 (1 Kb / sec) and we deleted a file of size 4 Kb
|
||||
// in 1 second, we will wait for another 3 seconds before we delete other
|
||||
// files, Set to 0 to disable rate limiting.
|
||||
// @info_log: If not nullptr, info_log will be used to log errors.
|
||||
// @delete_exisitng_trash: If set to true, the newly created DeleteScheduler
|
||||
// will delete files that already exist in trash_dir.
|
||||
// @status: If not nullptr, status will contain any errors that happened during
|
||||
// creating the missing trash_dir or deleting existing files in trash.
|
||||
extern DeleteScheduler* NewDeleteScheduler(
|
||||
Env* env, const std::string& trash_dir, int64_t rate_bytes_per_sec,
|
||||
std::shared_ptr<Logger> info_log = nullptr,
|
||||
bool delete_exisitng_trash = true, Status* status = nullptr);
|
||||
|
||||
} // namespace rocksdb
|
||||
@@ -5,8 +5,6 @@
|
||||
#ifndef ROCKSDB_LITE
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "rocksdb/db.h"
|
||||
#include "rocksdb/options.h"
|
||||
|
||||
namespace rocksdb {
|
||||
@@ -30,10 +28,8 @@ struct LDBOptions {
|
||||
|
||||
class LDBTool {
|
||||
public:
|
||||
void Run(
|
||||
int argc, char** argv, Options db_options = Options(),
|
||||
const LDBOptions& ldb_options = LDBOptions(),
|
||||
const std::vector<ColumnFamilyDescriptor>* column_families = nullptr);
|
||||
void Run(int argc, char** argv, Options db_options= Options(),
|
||||
const LDBOptions& ldb_options = LDBOptions());
|
||||
};
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
@@ -33,7 +33,6 @@ class CompactionFilterFactory;
|
||||
class Comparator;
|
||||
class Env;
|
||||
enum InfoLogLevel : unsigned char;
|
||||
class SstFileManager;
|
||||
class FilterPolicy;
|
||||
class Logger;
|
||||
class MergeOperator;
|
||||
@@ -42,6 +41,7 @@ class TableFactory;
|
||||
class MemTableRepFactory;
|
||||
class TablePropertiesCollectorFactory;
|
||||
class RateLimiter;
|
||||
class DeleteScheduler;
|
||||
class Slice;
|
||||
class SliceTransform;
|
||||
class Statistics;
|
||||
@@ -830,12 +830,12 @@ struct DBOptions {
|
||||
// Default: nullptr
|
||||
std::shared_ptr<RateLimiter> rate_limiter;
|
||||
|
||||
// Use to track SST files and control their file deletion rate, can be used
|
||||
// among multiple RocksDB instances, sst_file_manager only track and throttle
|
||||
// deletes of SST files in first db_path (db_name if db_paths is empty), other
|
||||
// files and other db_paths wont be tracked or affected by sst_file_manager.
|
||||
// Default: nullptr
|
||||
std::shared_ptr<SstFileManager> sst_file_manager;
|
||||
// Use to control files deletion rate, can be used among multiple
|
||||
// RocksDB instances. delete_scheduler is only used to delete table files that
|
||||
// need to be deleted from the first db_path (db_name if db_paths is empty),
|
||||
// other files types and other db_paths wont be affected by delete_scheduler.
|
||||
// Default: nullptr (disabled)
|
||||
std::shared_ptr<DeleteScheduler> delete_scheduler;
|
||||
|
||||
// Any internal progress/error information generated by the db will
|
||||
// be written to info_log if it is non-nullptr, or to a file stored
|
||||
@@ -933,19 +933,8 @@ struct DBOptions {
|
||||
// regardless of this setting
|
||||
uint64_t delete_obsolete_files_period_micros;
|
||||
|
||||
// Suggested number of concurrent background compaction jobs, submitted to
|
||||
// the default LOW priority thread pool.
|
||||
//
|
||||
// Default: max_background_compactions
|
||||
int base_background_compactions;
|
||||
|
||||
// Maximum number of concurrent background compaction jobs, submitted to
|
||||
// the default LOW priority thread pool.
|
||||
// We first try to schedule compactions based on
|
||||
// `base_background_compactions`. If the compaction cannot catch up , we
|
||||
// will increase number of compaction threads up to
|
||||
// `max_background_compactions`.
|
||||
//
|
||||
// If you're increasing this, also consider increasing number of threads in
|
||||
// LOW priority thread pool. For more information, see
|
||||
// Env::SetBackgroundThreads
|
||||
@@ -1121,9 +1110,6 @@ struct DBOptions {
|
||||
// This option is currently honored only on Windows
|
||||
//
|
||||
// Default: 1 Mb
|
||||
//
|
||||
// Special value: 0 - means do not maintain per instance buffer. Allocate
|
||||
// per request buffer and avoid locking.
|
||||
size_t random_access_max_buffer_size;
|
||||
|
||||
// This is the maximum buffer size that is used by WritableFileWriter.
|
||||
@@ -1294,12 +1280,8 @@ struct Options : public DBOptions, public ColumnFamilyOptions {
|
||||
// the block cache. It will not page in data from the OS cache or data that
|
||||
// resides in storage.
|
||||
enum ReadTier {
|
||||
kReadAllTier = 0x0, // data in memtable, block cache, OS cache or storage
|
||||
kBlockCacheTier = 0x1, // data in memtable or block cache
|
||||
kPersistedTier = 0x2 // persisted data. When WAL is disabled, this option
|
||||
// will skip data in memtable.
|
||||
// Note that this ReadTier currently only supports
|
||||
// Get and MultiGet and does not support iterators.
|
||||
kReadAllTier = 0x0, // data in memtable, block cache, OS cache or storage
|
||||
kBlockCacheTier = 0x1 // data in memtable or block cache
|
||||
};
|
||||
|
||||
// Options that control read operations
|
||||
|
||||
@@ -21,7 +21,7 @@ struct PerfContext {
|
||||
|
||||
void Reset(); // reset all performance counters to zero
|
||||
|
||||
std::string ToString(bool exclude_zero_counters = false) const;
|
||||
std::string ToString() const;
|
||||
|
||||
uint64_t user_key_comparison_count; // total number of user key comparisons
|
||||
uint64_t block_cache_hit_count; // total number of block cache hits
|
||||
|
||||
@@ -14,11 +14,9 @@ namespace rocksdb {
|
||||
// How much perf stats to collect. Affects perf_context and iostats_context.
|
||||
|
||||
enum PerfLevel {
|
||||
kDisable = 0, // disable perf stats
|
||||
kEnableCount = 1, // enable only count stats
|
||||
kEnableTimeExceptForMutex = 2, // Other than count stats, also enable time
|
||||
// stats except for mutexes
|
||||
kEnableTime = 3 // enable count and time stats
|
||||
kDisable = 0, // disable perf stats
|
||||
kEnableCount = 1, // enable only count stats
|
||||
kEnableTime = 2 // enable time stats too
|
||||
};
|
||||
|
||||
// set the perf stats level for current thread
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
// Copyright (c) 2015, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "rocksdb/status.h"
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
class Env;
|
||||
class Logger;
|
||||
|
||||
// SstFileManager is used to track SST files in the DB and control there
|
||||
// deletion rate.
|
||||
// All SstFileManager public functions are thread-safe.
|
||||
class SstFileManager {
|
||||
public:
|
||||
virtual ~SstFileManager() {}
|
||||
|
||||
// Return the total size of all tracked files.
|
||||
// thread-safe
|
||||
virtual uint64_t GetTotalSize() = 0;
|
||||
|
||||
// Return a map containing all tracked files and there corresponding sizes.
|
||||
// thread-safe
|
||||
virtual std::unordered_map<std::string, uint64_t> GetTrackedFiles() = 0;
|
||||
|
||||
// Return delete rate limit in bytes per second.
|
||||
// thread-safe
|
||||
virtual int64_t GetDeleteRateBytesPerSecond() = 0;
|
||||
};
|
||||
|
||||
// Create a new SstFileManager that can be shared among multiple RocksDB
|
||||
// instances to track SST file and control there deletion rate.
|
||||
//
|
||||
// @param env: Pointer to Env object, please see "rocksdb/env.h".
|
||||
// @param info_log: If not nullptr, info_log will be used to log errors.
|
||||
//
|
||||
// == Deletion rate limiting specific arguments ==
|
||||
// @param trash_dir: Path to the directory where deleted files will be moved
|
||||
// to be deleted in a background thread while applying rate limiting. If this
|
||||
// directory dont exist, it will be created. This directory should not be
|
||||
// used by any other process or any other SstFileManager, Set to "" to
|
||||
// disable deletion rate limiting.
|
||||
// @param rate_bytes_per_sec: How many bytes should be deleted per second, If
|
||||
// this value is set to 1024 (1 Kb / sec) and we deleted a file of size 4 Kb
|
||||
// in 1 second, we will wait for another 3 seconds before we delete other
|
||||
// files, Set to 0 to disable deletion rate limiting.
|
||||
// @param delete_exisitng_trash: If set to true, the newly created
|
||||
// SstFileManager will delete files that already exist in trash_dir.
|
||||
// @param status: If not nullptr, status will contain any errors that happened
|
||||
// during creating the missing trash_dir or deleting existing files in trash.
|
||||
extern SstFileManager* NewSstFileManager(
|
||||
Env* env, std::shared_ptr<Logger> info_log = nullptr,
|
||||
std::string trash_dir = "", int64_t rate_bytes_per_sec = 0,
|
||||
bool delete_exisitng_trash = true, Status* status = nullptr);
|
||||
|
||||
} // namespace rocksdb
|
||||
@@ -109,7 +109,6 @@ enum Tickers : uint32_t {
|
||||
// Writer has to wait for compaction or flush to finish.
|
||||
STALL_MICROS,
|
||||
// The wait time for db mutex.
|
||||
// Disabled by default. To enable it set stats level to kAll
|
||||
DB_MUTEX_WAIT_MICROS,
|
||||
RATE_LIMIT_DELAY_MILLIS,
|
||||
NO_ITERATORS, // number of iterators currently open
|
||||
@@ -280,10 +279,6 @@ enum Histograms : uint32_t {
|
||||
SST_READ_MICROS,
|
||||
// The number of subcompactions actually scheduled during a compaction
|
||||
NUM_SUBCOMPACTIONS_SCHEDULED,
|
||||
// Value size distribution in each operation
|
||||
BYTES_PER_READ,
|
||||
BYTES_PER_WRITE,
|
||||
BYTES_PER_MULTIGET,
|
||||
HISTOGRAM_ENUM_MAX, // TODO(ldemailly): enforce HistogramsNameMap match
|
||||
};
|
||||
|
||||
@@ -311,9 +306,6 @@ const std::vector<std::pair<Histograms, std::string>> HistogramsNameMap = {
|
||||
{WRITE_STALL, "rocksdb.db.write.stall"},
|
||||
{SST_READ_MICROS, "rocksdb.sst.read.micros"},
|
||||
{NUM_SUBCOMPACTIONS_SCHEDULED, "rocksdb.num.subcompactions.scheduled"},
|
||||
{BYTES_PER_READ, "rocksdb.bytes.per.read"},
|
||||
{BYTES_PER_WRITE, "rocksdb.bytes.per.write"},
|
||||
{BYTES_PER_MULTIGET, "rocksdb.bytes.per.multiget"},
|
||||
};
|
||||
|
||||
struct HistogramData {
|
||||
@@ -324,16 +316,6 @@ struct HistogramData {
|
||||
double standard_deviation;
|
||||
};
|
||||
|
||||
enum StatsLevel {
|
||||
// Collect all stats except the counters requiring to get time inside the
|
||||
// mutex lock.
|
||||
kExceptTimeForMutex,
|
||||
// Collect all stats, including measuring duration of mutex operations.
|
||||
// If getting time is expensive on the platform to run, it can
|
||||
// reduce scalability to more threads, especialy for writes.
|
||||
kAll,
|
||||
};
|
||||
|
||||
// Analyze the performance of a db
|
||||
class Statistics {
|
||||
public:
|
||||
@@ -357,8 +339,6 @@ class Statistics {
|
||||
virtual bool HistEnabledForType(uint32_t type) const {
|
||||
return type < HISTOGRAM_ENUM_MAX;
|
||||
}
|
||||
|
||||
StatsLevel stats_level_ = kExceptTimeForMutex;
|
||||
};
|
||||
|
||||
// Create a concrete DBStatistics object
|
||||
|
||||
@@ -120,9 +120,6 @@ struct BlockBasedTableOptions {
|
||||
// value will be silently overwritten with 1.
|
||||
int block_restart_interval = 16;
|
||||
|
||||
// Same as block_restart_interval but used for the index block.
|
||||
int index_block_restart_interval = 1;
|
||||
|
||||
// Use delta encoding to compress keys in blocks.
|
||||
// Iterator::PinData() requires this option to be disabled.
|
||||
//
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#define ROCKSDB_MAJOR 4
|
||||
#define ROCKSDB_MINOR 5
|
||||
#define ROCKSDB_MINOR 4
|
||||
#define ROCKSDB_PATCH 1
|
||||
|
||||
// Do not use these. We made the mistake of declaring macros starting with
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
set(JNI_NATIVE_SOURCES
|
||||
rocksjni/backupenginejni.cc
|
||||
rocksjni/backupablejni.cc
|
||||
rocksjni/checkpoint.cc
|
||||
rocksjni/columnfamilyhandle.cc
|
||||
rocksjni/compaction_filter.cc
|
||||
rocksjni/comparator.cc
|
||||
rocksjni/comparatorjnicallback.cc
|
||||
rocksjni/env.cc
|
||||
rocksjni/filter.cc
|
||||
rocksjni/iterator.cc
|
||||
rocksjni/loggerjnicallback.cc
|
||||
rocksjni/memtablejni.cc
|
||||
rocksjni/merge_operator.cc
|
||||
rocksjni/options.cc
|
||||
rocksjni/ratelimiterjni.cc
|
||||
rocksjni/remove_emptyvalue_compactionfilterjni.cc
|
||||
rocksjni/restorejni.cc
|
||||
rocksjni/rocksjni.cc
|
||||
rocksjni/slice.cc
|
||||
rocksjni/snapshot.cc
|
||||
rocksjni/statistics.cc
|
||||
rocksjni/table.cc
|
||||
rocksjni/transaction_log.cc
|
||||
rocksjni/ttl.cc
|
||||
rocksjni/write_batch.cc
|
||||
rocksjni/writebatchhandlerjnicallback.cc
|
||||
rocksjni/write_batch_with_index.cc
|
||||
rocksjni/write_batch_test.cc
|
||||
)
|
||||
|
||||
set(NATIVE_JAVA_CLASSES
|
||||
org.rocksdb.AbstractCompactionFilter
|
||||
org.rocksdb.AbstractComparator
|
||||
org.rocksdb.AbstractSlice
|
||||
org.rocksdb.BackupEngine
|
||||
org.rocksdb.BackupableDB
|
||||
org.rocksdb.BackupableDBOptions
|
||||
org.rocksdb.BlockBasedTableConfig
|
||||
org.rocksdb.BloomFilter
|
||||
org.rocksdb.Checkpoint
|
||||
org.rocksdb.ColumnFamilyHandle
|
||||
org.rocksdb.ColumnFamilyOptions
|
||||
org.rocksdb.Comparator
|
||||
org.rocksdb.ComparatorOptions
|
||||
org.rocksdb.DBOptions
|
||||
org.rocksdb.DirectComparator
|
||||
org.rocksdb.DirectSlice
|
||||
org.rocksdb.Env
|
||||
org.rocksdb.FlushOptions
|
||||
org.rocksdb.Filter
|
||||
org.rocksdb.GenericRateLimiterConfig
|
||||
org.rocksdb.HashLinkedListMemTableConfig
|
||||
org.rocksdb.HashSkipListMemTableConfig
|
||||
org.rocksdb.Logger
|
||||
org.rocksdb.MergeOperator
|
||||
org.rocksdb.Options
|
||||
org.rocksdb.PlainTableConfig
|
||||
org.rocksdb.ReadOptions
|
||||
org.rocksdb.RemoveEmptyValueCompactionFilter
|
||||
org.rocksdb.RestoreBackupableDB
|
||||
org.rocksdb.RestoreOptions
|
||||
org.rocksdb.RocksDB
|
||||
org.rocksdb.RocksEnv
|
||||
org.rocksdb.RocksIterator
|
||||
org.rocksdb.RocksMemEnv
|
||||
org.rocksdb.SkipListMemTableConfig
|
||||
org.rocksdb.Slice
|
||||
org.rocksdb.Statistics
|
||||
org.rocksdb.TransactionLogIterator
|
||||
org.rocksdb.TtlDB
|
||||
org.rocksdb.VectorMemTableConfig
|
||||
org.rocksdb.Snapshot
|
||||
org.rocksdb.StringAppendOperator
|
||||
org.rocksdb.WriteBatch
|
||||
org.rocksdb.WriteBatch.Handler
|
||||
org.rocksdb.WriteOptions
|
||||
org.rocksdb.WriteBatchWithIndex
|
||||
org.rocksdb.WBWIRocksIterator
|
||||
org.rocksdb.WriteBatchTest
|
||||
org.rocksdb.WriteBatchTestInternalHelper
|
||||
)
|
||||
|
||||
include_directories($ENV{JAVA_HOME}/include)
|
||||
include_directories($ENV{JAVA_HOME}/include/win32)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/java)
|
||||
|
||||
set(JAVA_TEST_LIBDIR ${PROJECT_SOURCE_DIR}/java/test-libs)
|
||||
set(JAVA_TMP_JAR ${JAVA_TEST_LIBDIR}/tmp.jar)
|
||||
set(JAVA_JUNIT_JAR ${JAVA_TEST_LIBDIR}/junit-4.12.jar)
|
||||
set(JAVA_HAMCR_JAR ${JAVA_TEST_LIBDIR}/hamcrest-core-1.3.jar)
|
||||
set(JAVA_MOCKITO_JAR ${JAVA_TEST_LIBDIR}/mockito-all-1.10.19.jar)
|
||||
set(JAVA_CGLIB_JAR ${JAVA_TEST_LIBDIR}/cglib-2.2.2.jar)
|
||||
set(JAVA_ASSERTJ_JAR ${JAVA_TEST_LIBDIR}/assertj-core-1.7.1.jar)
|
||||
set(JAVA_TESTCLASSPATH "${JAVA_JUNIT_JAR}\;${JAVA_HAMCR_JAR}\;${JAVA_MOCKITO_JAR}\;${JAVA_CGLIB_JAR}\;${JAVA_ASSERTJ_JAR}")
|
||||
|
||||
if(NOT EXISTS ${PROJECT_SOURCE_DIR}/java/classes)
|
||||
execute_process(COMMAND mkdir ${PROJECT_SOURCE_DIR}/java/classes)
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS ${JAVA_TEST_LIBDIR})
|
||||
execute_process(COMMAND mkdir ${JAVA_TEST_LIBDIR})
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS ${JAVA_JUNIT_JAR})
|
||||
message("Downloading ${JAVA_JUNIT_JAR}")
|
||||
file(DOWNLOAD http://search.maven.org/remotecontent?filepath=junit/junit/4.12/junit-4.12.jar ${JAVA_TMP_JAR} STATUS downloadStatus)
|
||||
list(GET downloadStatus 0 error_code)
|
||||
if(NOT error_code EQUAL 0)
|
||||
message(FATAL_ERROR "Failed downloading ${JAVA_JUNIT_JAR}")
|
||||
endif()
|
||||
file(RENAME ${JAVA_TMP_JAR} ${JAVA_JUNIT_JAR})
|
||||
endif()
|
||||
if(NOT EXISTS ${JAVA_HAMCR_JAR})
|
||||
message("Downloading ${JAVA_HAMCR_JAR}")
|
||||
file(DOWNLOAD http://search.maven.org/remotecontent?filepath=org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar ${JAVA_TMP_JAR} STATUS downloadStatus)
|
||||
list(GET downloadStatus 0 error_code)
|
||||
if(NOT error_code EQUAL 0)
|
||||
message(FATAL_ERROR "Failed downloading ${JAVA_HAMCR_JAR}")
|
||||
endif()
|
||||
file(RENAME ${JAVA_TMP_JAR} ${JAVA_HAMCR_JAR})
|
||||
endif()
|
||||
if(NOT EXISTS ${JAVA_MOCKITO_JAR})
|
||||
message("Downloading ${JAVA_MOCKITO_JAR}")
|
||||
file(DOWNLOAD http://search.maven.org/remotecontent?filepath=org/mockito/mockito-all/1.10.19/mockito-all-1.10.19.jar ${JAVA_TMP_JAR} STATUS downloadStatus)
|
||||
list(GET downloadStatus 0 error_code)
|
||||
if(NOT error_code EQUAL 0)
|
||||
message(FATAL_ERROR "Failed downloading ${JAVA_MOCKITO_JAR}")
|
||||
endif()
|
||||
file(RENAME ${JAVA_TMP_JAR} ${JAVA_MOCKITO_JAR})
|
||||
endif()
|
||||
if(NOT EXISTS ${JAVA_CGLIB_JAR})
|
||||
message("Downloading ${JAVA_CGLIB_JAR}")
|
||||
file(DOWNLOAD http://search.maven.org/remotecontent?filepath=cglib/cglib/2.2.2/cglib-2.2.2.jar ${JAVA_TMP_JAR} STATUS downloadStatus)
|
||||
list(GET downloadStatus 0 error_code)
|
||||
if(NOT error_code EQUAL 0)
|
||||
message(FATAL_ERROR "Failed downloading ${JAVA_CGLIB_JAR}")
|
||||
endif()
|
||||
file(RENAME ${JAVA_TMP_JAR} ${JAVA_CGLIB_JAR})
|
||||
endif()
|
||||
if(NOT EXISTS ${JAVA_ASSERTJ_JAR})
|
||||
message("Downloading ${JAVA_ASSERTJ_JAR}")
|
||||
file(DOWNLOAD http://central.maven.org/maven2/org/assertj/assertj-core/1.7.1/assertj-core-1.7.1.jar ${JAVA_TMP_JAR} STATUS downloadStatus)
|
||||
list(GET downloadStatus 0 error_code)
|
||||
if(NOT error_code EQUAL 0)
|
||||
message(FATAL_ERROR "Failed downloading ${JAVA_ASSERTJ_JAR}")
|
||||
endif()
|
||||
file(RENAME ${JAVA_TMP_JAR} ${JAVA_ASSERTJ_JAR})
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND javac -cp ${JAVA_TESTCLASSPATH} -d ${PROJECT_SOURCE_DIR}/java/classes ${PROJECT_SOURCE_DIR}/java/src/main/java/org/rocksdb/util/*.java ${PROJECT_SOURCE_DIR}/java/src/main/java/org/rocksdb/*.java ${PROJECT_SOURCE_DIR}/java/src/test/java/org/rocksdb/*.java)
|
||||
execute_process(COMMAND javah -cp ${PROJECT_SOURCE_DIR}/java/classes -d ${PROJECT_SOURCE_DIR}/java/include -jni ${NATIVE_JAVA_CLASSES})
|
||||
add_library(rocksdbjni${ARTIFACT_SUFFIX} SHARED ${JNI_NATIVE_SOURCES})
|
||||
set_target_properties(rocksdbjni${ARTIFACT_SUFFIX} PROPERTIES COMPILE_FLAGS "/Fd${CMAKE_CFG_INTDIR}/rocksdbjni${ARTIFACT_SUFFIX}.pdb")
|
||||
target_link_libraries(rocksdbjni${ARTIFACT_SUFFIX} rocksdblib${ARTIFACT_SUFFIX} ${LIBS})
|
||||
@@ -99,7 +99,6 @@ JAVA_TESTS = org.rocksdb.BackupableDBOptionsTest\
|
||||
org.rocksdb.StatisticsCollectorTest\
|
||||
org.rocksdb.WriteBatchHandlerTest\
|
||||
org.rocksdb.WriteBatchTest\
|
||||
org.rocksdb.WriteBatchThreadedTest\
|
||||
org.rocksdb.WriteOptionsTest\
|
||||
org.rocksdb.WriteBatchWithIndexTest
|
||||
|
||||
|
||||
@@ -103,14 +103,20 @@ jintArray Java_org_rocksdb_BackupableDB_getCorruptedBackups(
|
||||
reinterpret_cast<rocksdb::BackupableDB*>(jhandle)->
|
||||
GetCorruptedBackups(&backup_ids);
|
||||
// store backupids in int array
|
||||
std::vector<jint> int_backup_ids(backup_ids.begin(), backup_ids.end());
|
||||
const std::vector<rocksdb::BackupID>::size_type
|
||||
kIdSize = backup_ids.size();
|
||||
int int_backup_ids[kIdSize];
|
||||
for (std::vector<rocksdb::BackupID>::size_type i = 0;
|
||||
i != kIdSize; i++) {
|
||||
int_backup_ids[i] = backup_ids[i];
|
||||
}
|
||||
// Store ints in java array
|
||||
jintArray ret_backup_ids;
|
||||
// Its ok to loose precision here (64->32)
|
||||
jsize ret_backup_ids_size = static_cast<jsize>(backup_ids.size());
|
||||
jsize ret_backup_ids_size = static_cast<jsize>(kIdSize);
|
||||
ret_backup_ids = env->NewIntArray(ret_backup_ids_size);
|
||||
env->SetIntArrayRegion(ret_backup_ids, 0, ret_backup_ids_size,
|
||||
int_backup_ids.data());
|
||||
int_backup_ids);
|
||||
return ret_backup_ids;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,14 +81,20 @@ jintArray Java_org_rocksdb_BackupEngine_getCorruptedBackups(
|
||||
std::vector<rocksdb::BackupID> backup_ids;
|
||||
backup_engine->GetCorruptedBackups(&backup_ids);
|
||||
// store backupids in int array
|
||||
std::vector<jint> int_backup_ids(backup_ids.begin(), backup_ids.end());
|
||||
const std::vector<rocksdb::BackupID>::size_type
|
||||
kIdSize = backup_ids.size();
|
||||
int int_backup_ids[kIdSize];
|
||||
for (std::vector<rocksdb::BackupID>::size_type i = 0;
|
||||
i != kIdSize; i++) {
|
||||
int_backup_ids[i] = backup_ids[i];
|
||||
}
|
||||
// Store ints in java array
|
||||
jintArray ret_backup_ids;
|
||||
// Its ok to loose precision here (64->32)
|
||||
jsize ret_backup_ids_size = static_cast<jsize>(backup_ids.size());
|
||||
jsize ret_backup_ids_size = static_cast<jsize>(kIdSize);
|
||||
ret_backup_ids = env->NewIntArray(ret_backup_ids_size);
|
||||
env->SetIntArrayRegion(ret_backup_ids, 0, ret_backup_ids_size,
|
||||
int_backup_ids.data());
|
||||
int_backup_ids);
|
||||
return ret_backup_ids;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
#include <strings.h>
|
||||
#include <memory>
|
||||
|
||||
#include "include/org_rocksdb_Options.h"
|
||||
@@ -1179,7 +1180,7 @@ jbyte Java_org_rocksdb_Options_compactionStyle(
|
||||
void Java_org_rocksdb_Options_setMaxTableFilesSizeFIFO(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle, jlong jmax_table_files_size) {
|
||||
reinterpret_cast<rocksdb::Options*>(jhandle)->compaction_options_fifo.max_table_files_size =
|
||||
static_cast<uint64_t>(jmax_table_files_size);
|
||||
static_cast<long>(jmax_table_files_size);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2338,7 +2339,7 @@ jbyte Java_org_rocksdb_ColumnFamilyOptions_compactionStyle(
|
||||
void Java_org_rocksdb_ColumnFamilyOptions_setMaxTableFilesSizeFIFO(
|
||||
JNIEnv* env, jobject jobj, jlong jhandle, jlong jmax_table_files_size) {
|
||||
reinterpret_cast<rocksdb::ColumnFamilyOptions*>(jhandle)->compaction_options_fifo.max_table_files_size =
|
||||
static_cast<uint64_t>(jmax_table_files_size);
|
||||
static_cast<long>(jmax_table_files_size);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -24,11 +24,6 @@
|
||||
#include "rocksjni/loggerjnicallback.h"
|
||||
#include "rocksjni/writebatchhandlerjnicallback.h"
|
||||
|
||||
// Remove macro on windows
|
||||
#ifdef DELETE
|
||||
#undef DELETE
|
||||
#endif
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
// Detect if jlong overflows size_t
|
||||
|
||||
@@ -156,14 +156,21 @@ jintArray Java_org_rocksdb_RestoreBackupableDB_getCorruptedBackups(
|
||||
reinterpret_cast<rocksdb::RestoreBackupableDB*>(jhandle)->
|
||||
GetCorruptedBackups(&backup_ids);
|
||||
// store backupids in int array
|
||||
std::vector<jint> int_backup_ids(backup_ids.begin(), backup_ids.end());
|
||||
const std::vector<rocksdb::BackupID>::size_type
|
||||
kIdSize = backup_ids.size();
|
||||
|
||||
int int_backup_ids[kIdSize];
|
||||
for (std::vector<rocksdb::BackupID>::size_type i = 0;
|
||||
i != kIdSize; i++) {
|
||||
int_backup_ids[i] = backup_ids[i];
|
||||
}
|
||||
// Store ints in java array
|
||||
jintArray ret_backup_ids;
|
||||
// Its ok to loose precision here (64->32)
|
||||
jsize ret_backup_ids_size = static_cast<jsize>(backup_ids.size());
|
||||
jsize ret_backup_ids_size = static_cast<jsize>(kIdSize);
|
||||
ret_backup_ids = env->NewIntArray(ret_backup_ids_size);
|
||||
env->SetIntArrayRegion(ret_backup_ids, 0, ret_backup_ids_size,
|
||||
int_backup_ids.data());
|
||||
int_backup_ids);
|
||||
return ret_backup_ids;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "include/org_rocksdb_RocksDB.h"
|
||||
#include "rocksdb/db.h"
|
||||
@@ -20,10 +19,6 @@
|
||||
#include "rocksdb/types.h"
|
||||
#include "rocksjni/portal.h"
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// rocksdb::DB::Open
|
||||
|
||||
@@ -693,8 +688,8 @@ jint rocksdb_get_helper(
|
||||
return kStatusError;
|
||||
}
|
||||
|
||||
jint cvalue_len = static_cast<jint>(cvalue.size());
|
||||
jint length = std::min(jentry_value_len, cvalue_len);
|
||||
int cvalue_len = static_cast<int>(cvalue.size());
|
||||
int length = std::min(jentry_value_len, cvalue_len);
|
||||
|
||||
env->SetByteArrayRegion(
|
||||
jentry_value, 0, length,
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* Signature: (IJ)J
|
||||
*/
|
||||
jlong Java_org_rocksdb_Statistics_getTickerCount0(
|
||||
JNIEnv* env, jobject jobj, jint tickerType, jlong handle) {
|
||||
JNIEnv* env, jobject jobj, int tickerType, jlong handle) {
|
||||
auto st = reinterpret_cast<rocksdb::Statistics*>(handle);
|
||||
assert(st != nullptr);
|
||||
|
||||
@@ -33,7 +33,7 @@ jlong Java_org_rocksdb_Statistics_getTickerCount0(
|
||||
* Signature: (IJ)Lorg/rocksdb/HistogramData;
|
||||
*/
|
||||
jobject Java_org_rocksdb_Statistics_geHistogramData0(
|
||||
JNIEnv* env, jobject jobj, jint histogramType, jlong handle) {
|
||||
JNIEnv* env, jobject jobj, int histogramType, jlong handle) {
|
||||
auto st = reinterpret_cast<rocksdb::Statistics*>(handle);
|
||||
assert(st != nullptr);
|
||||
|
||||
|
||||
@@ -60,8 +60,7 @@ jbyteArray Java_org_rocksdb_WriteBatchTest_getContents(
|
||||
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||
rocksdb::ParsedInternalKey ikey;
|
||||
memset(reinterpret_cast<void*>(&ikey), 0, sizeof(ikey));
|
||||
bool parsed = rocksdb::ParseInternalKey(iter->key(), &ikey);
|
||||
assert(parsed);
|
||||
assert(rocksdb::ParseInternalKey(iter->key(), &ikey));
|
||||
switch (ikey.type) {
|
||||
case rocksdb::kTypeValue:
|
||||
state.append("Put(");
|
||||
|
||||
@@ -19,7 +19,7 @@ public class NativeLibraryLoader {
|
||||
private static final String jniLibraryName = Environment.getJniLibraryName("rocksdb");
|
||||
private static final String jniLibraryFileName = Environment.getJniLibraryFileName("rocksdb");
|
||||
private static final String tempFilePrefix = "librocksdbjni";
|
||||
private static final String tempFileSuffix = Environment.getJniLibraryExtension();
|
||||
private static final String tempFileSuffix = "." + Environment.getJniLibraryExtension();
|
||||
|
||||
/**
|
||||
* Get a reference to the NativeLibraryLoader
|
||||
@@ -75,43 +75,37 @@ public class NativeLibraryLoader {
|
||||
void loadLibraryFromJar(final String tmpDir)
|
||||
throws IOException {
|
||||
if (!initialized) {
|
||||
System.load(loadLibraryFromJarToTemp(tmpDir).getAbsolutePath());
|
||||
final File temp;
|
||||
if (tmpDir == null || tmpDir.equals("")) {
|
||||
temp = File.createTempFile(tempFilePrefix, tempFileSuffix);
|
||||
} else {
|
||||
temp = new File(tmpDir, jniLibraryFileName);
|
||||
if (!temp.createNewFile()) {
|
||||
throw new RuntimeException("File: " + temp.getAbsolutePath()
|
||||
+ " could not be created.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!temp.exists()) {
|
||||
throw new RuntimeException("File " + temp.getAbsolutePath() + " does not exist.");
|
||||
} else {
|
||||
temp.deleteOnExit();
|
||||
}
|
||||
|
||||
// attempt to copy the library from the Jar file to the temp destination
|
||||
try (final InputStream is = getClass().getClassLoader().
|
||||
getResourceAsStream(jniLibraryFileName)) {
|
||||
if (is == null) {
|
||||
throw new RuntimeException(jniLibraryFileName + " was not found inside JAR.");
|
||||
} else {
|
||||
Files.copy(is, temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
|
||||
System.load(temp.getAbsolutePath());
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
File loadLibraryFromJarToTemp(final String tmpDir)
|
||||
throws IOException {
|
||||
final File temp;
|
||||
if (tmpDir == null || tmpDir.isEmpty()) {
|
||||
temp = File.createTempFile(tempFilePrefix, tempFileSuffix);
|
||||
} else {
|
||||
temp = new File(tmpDir, jniLibraryFileName);
|
||||
if (!temp.createNewFile()) {
|
||||
throw new RuntimeException("File: " + temp.getAbsolutePath()
|
||||
+ " could not be created.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!temp.exists()) {
|
||||
throw new RuntimeException("File " + temp.getAbsolutePath() + " does not exist.");
|
||||
} else {
|
||||
temp.deleteOnExit();
|
||||
}
|
||||
|
||||
// attempt to copy the library from the Jar file to the temp destination
|
||||
try (final InputStream is = getClass().getClassLoader().
|
||||
getResourceAsStream(jniLibraryFileName)) {
|
||||
if (is == null) {
|
||||
throw new RuntimeException(jniLibraryFileName + " was not found inside JAR.");
|
||||
} else {
|
||||
Files.copy(is, temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to disallow instantiation
|
||||
*/
|
||||
|
||||
@@ -18,10 +18,6 @@ public class Environment {
|
||||
OS.contains("aix"));
|
||||
}
|
||||
|
||||
public static boolean isSolaris() {
|
||||
return OS.contains("sunos");
|
||||
}
|
||||
|
||||
public static boolean is64Bit() {
|
||||
return (ARCH.indexOf("64") > 0);
|
||||
}
|
||||
@@ -40,10 +36,6 @@ public class Environment {
|
||||
return String.format("%sjni-linux%s", name, arch);
|
||||
} else if (isMac()) {
|
||||
return String.format("%sjni-osx", name);
|
||||
} else if (isSolaris()) {
|
||||
return String.format("%sjni-solaris%d", name, is64Bit() ? 64 : 32);
|
||||
} else if (isWindows() && is64Bit()) {
|
||||
return String.format("%sjni-win64", name);
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@@ -53,20 +45,15 @@ public class Environment {
|
||||
}
|
||||
|
||||
private static String appendLibOsSuffix(final String libraryFileName, final boolean shared) {
|
||||
if (isUnix() || isSolaris()) {
|
||||
if (isUnix()) {
|
||||
return libraryFileName + ".so";
|
||||
} else if (isMac()) {
|
||||
return libraryFileName + (shared ? ".dylib" : ".jnilib");
|
||||
} else if (isWindows()) {
|
||||
return libraryFileName + ".dll";
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public static String getJniLibraryExtension() {
|
||||
if (isWindows()) {
|
||||
return ".dll";
|
||||
}
|
||||
return (isMac()) ? ".jnilib" : ".so";
|
||||
}
|
||||
}
|
||||
@@ -5,18 +5,18 @@
|
||||
|
||||
package org.rocksdb;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class BackupableDBOptionsTest {
|
||||
|
||||
private final static String ARBITRARY_PATH = System.getProperty("java.io.tmpdir");
|
||||
private final static String ARBITRARY_PATH = "/tmp";
|
||||
|
||||
@ClassRule
|
||||
public static final RocksMemoryResource rocksMemoryResource =
|
||||
|
||||
@@ -4,7 +4,6 @@ import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.rocksdb.util.Environment;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -114,7 +113,7 @@ public class InfoLogLevelTest {
|
||||
* @throws IOException if file is not found.
|
||||
*/
|
||||
private String getLogContentsWithoutHeader() throws IOException {
|
||||
final String separator = Environment.isWindows() ? "\n" : System.getProperty("line.separator");
|
||||
final String separator = System.getProperty("line.separator");
|
||||
final String[] lines = new String(readAllBytes(get(
|
||||
dbFolder.getRoot().getAbsolutePath()+ "/LOG"))).split(separator);
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public class NativeLibraryLoaderTest {
|
||||
|
||||
@Test
|
||||
public void tempFolder() throws IOException {
|
||||
NativeLibraryLoader.getInstance().loadLibraryFromJarToTemp(
|
||||
NativeLibraryLoader.getInstance().loadLibraryFromJar(
|
||||
temporaryFolder.getRoot().getAbsolutePath());
|
||||
Path path = Paths.get(temporaryFolder.getRoot().getAbsolutePath(),
|
||||
Environment.getJniLibraryFileName("rocksdb"));
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
// Copyright (c) 2016, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
package org.rocksdb;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameter;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class WriteBatchThreadedTest {
|
||||
|
||||
@Parameters(name = "WriteBatchThreadedTest(threadCount={0})")
|
||||
public static Iterable<Integer> data() {
|
||||
return Arrays.asList(new Integer[]{1, 10, 50, 100});
|
||||
}
|
||||
|
||||
@Parameter
|
||||
public int threadCount;
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder dbFolder = new TemporaryFolder();
|
||||
|
||||
RocksDB db;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
RocksDB.loadLibrary();
|
||||
final Options options = new Options()
|
||||
.setCreateIfMissing(true)
|
||||
.setIncreaseParallelism(32);
|
||||
db = RocksDB.open(options, dbFolder.getRoot().getAbsolutePath());
|
||||
assert (db != null);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (db != null) {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void threadedWrites() throws InterruptedException, ExecutionException {
|
||||
final List<Callable<Void>> callables = new ArrayList<>();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
final int offset = i * 100;
|
||||
callables.add(new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws RocksDBException {
|
||||
final WriteBatch wb = new WriteBatch();
|
||||
for (int i = offset; i < offset + 100; i++) {
|
||||
wb.put(ByteBuffer.allocate(4).putInt(i).array(),
|
||||
"parallel rocks test".getBytes());
|
||||
}
|
||||
db.write(new WriteOptions(), wb);
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//submit the callables
|
||||
final ExecutorService executorService =
|
||||
Executors.newFixedThreadPool(threadCount);
|
||||
try {
|
||||
final ExecutorCompletionService<Void> completionService =
|
||||
new ExecutorCompletionService<>(executorService);
|
||||
final Set<Future<Void>> futures = new HashSet<>();
|
||||
for (final Callable<Void> callable : callables) {
|
||||
futures.add(completionService.submit(callable));
|
||||
}
|
||||
|
||||
while (futures.size() > 0) {
|
||||
final Future<Void> future = completionService.take();
|
||||
futures.remove(future);
|
||||
|
||||
try {
|
||||
future.get();
|
||||
} catch (final ExecutionException e) {
|
||||
for (final Future<Void> f : futures) {
|
||||
f.cancel(true);
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
executorService.shutdown();
|
||||
executorService.awaitTermination(10, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,22 +117,16 @@ public class EnvironmentTest {
|
||||
assertThat(Environment.isWindows()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void win64() {
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void failWinJniLibraryName(){
|
||||
setEnvironmentClassFields("win", "x64");
|
||||
assertThat(Environment.isWindows()).isTrue();
|
||||
assertThat(Environment.getJniLibraryExtension()).
|
||||
isEqualTo(".dll");
|
||||
assertThat(Environment.getJniLibraryFileName("rocksdb")).
|
||||
isEqualTo("librocksdbjni-win64.dll");
|
||||
assertThat(Environment.getSharedLibraryFileName("rocksdb")).
|
||||
isEqualTo("librocksdbjni.dll");
|
||||
Environment.getJniLibraryFileName("rocksdb");
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void win32(){
|
||||
setEnvironmentClassFields("win", "32");
|
||||
Environment.getJniLibraryFileName("rocksdb");
|
||||
public void failWinSharedLibrary(){
|
||||
setEnvironmentClassFields("win", "x64");
|
||||
Environment.getSharedLibraryFileName("rocksdb");
|
||||
}
|
||||
|
||||
private void setEnvironmentClassFields(String osName,
|
||||
|
||||
+60
-108
@@ -766,18 +766,6 @@ class WinRandomAccessFile : public RandomAccessFile {
|
||||
return read;
|
||||
}
|
||||
|
||||
void CalculateReadParameters(uint64_t offset, size_t bytes_requested,
|
||||
size_t& actual_bytes_toread,
|
||||
uint64_t& first_page_start) const {
|
||||
|
||||
const size_t alignment = buffer_.Alignment();
|
||||
|
||||
first_page_start = TruncateToPageBoundary(alignment, offset);
|
||||
const uint64_t last_page_start =
|
||||
TruncateToPageBoundary(alignment, offset + bytes_requested - 1);
|
||||
actual_bytes_toread = (last_page_start - first_page_start) + alignment;
|
||||
}
|
||||
|
||||
public:
|
||||
WinRandomAccessFile(const std::string& fname, HANDLE hFile, size_t alignment,
|
||||
const EnvOptions& options)
|
||||
@@ -809,87 +797,66 @@ class WinRandomAccessFile : public RandomAccessFile {
|
||||
|
||||
virtual Status Read(uint64_t offset, size_t n, Slice* result,
|
||||
char* scratch) const override {
|
||||
|
||||
Status s;
|
||||
SSIZE_T r = -1;
|
||||
size_t left = n;
|
||||
char* dest = scratch;
|
||||
|
||||
if (n == 0) {
|
||||
*result = Slice(scratch, 0);
|
||||
return s;
|
||||
}
|
||||
|
||||
// When in unbuffered mode we need to do the following changes:
|
||||
// - use our own aligned buffer
|
||||
// - always read at the offset of that is a multiple of alignment
|
||||
if (!use_os_buffer_) {
|
||||
std::unique_lock<std::mutex> lock(buffer_mut_);
|
||||
|
||||
uint64_t first_page_start = 0;
|
||||
size_t actual_bytes_toread = 0;
|
||||
size_t bytes_requested = left;
|
||||
|
||||
if (!read_ahead_ && random_access_max_buffer_size_ == 0) {
|
||||
CalculateReadParameters(offset, bytes_requested, actual_bytes_toread,
|
||||
first_page_start);
|
||||
|
||||
assert(actual_bytes_toread > 0);
|
||||
|
||||
r = ReadIntoOneShotBuffer(offset, first_page_start,
|
||||
actual_bytes_toread, left, dest);
|
||||
} else {
|
||||
|
||||
std::unique_lock<std::mutex> lock(buffer_mut_);
|
||||
|
||||
// Let's see if at least some of the requested data is already
|
||||
// in the buffer
|
||||
if (offset >= buffered_start_ &&
|
||||
// Let's see if at least some of the requested data is already
|
||||
// in the buffer
|
||||
if (offset >= buffered_start_ &&
|
||||
offset < (buffered_start_ + buffer_.CurrentSize())) {
|
||||
size_t buffer_offset = offset - buffered_start_;
|
||||
r = buffer_.Read(dest, buffer_offset, left);
|
||||
assert(r >= 0);
|
||||
size_t buffer_offset = offset - buffered_start_;
|
||||
r = buffer_.Read(dest, buffer_offset, left);
|
||||
assert(r >= 0);
|
||||
|
||||
left -= size_t(r);
|
||||
offset += r;
|
||||
dest += r;
|
||||
left -= size_t(r);
|
||||
offset += r;
|
||||
dest += r;
|
||||
}
|
||||
|
||||
// Still some left or none was buffered
|
||||
if (left > 0) {
|
||||
// Figure out the start/end offset for reading and amount to read
|
||||
const size_t alignment = buffer_.Alignment();
|
||||
const size_t first_page_start =
|
||||
TruncateToPageBoundary(alignment, offset);
|
||||
|
||||
size_t bytes_requested = left;
|
||||
if (read_ahead_ && bytes_requested < compaction_readahead_size_) {
|
||||
bytes_requested = compaction_readahead_size_;
|
||||
}
|
||||
|
||||
// Still some left or none was buffered
|
||||
if (left > 0) {
|
||||
// Figure out the start/end offset for reading and amount to read
|
||||
bytes_requested = left;
|
||||
const size_t last_page_start =
|
||||
TruncateToPageBoundary(alignment, offset + bytes_requested - 1);
|
||||
const size_t actual_bytes_toread =
|
||||
(last_page_start - first_page_start) + alignment;
|
||||
|
||||
if (read_ahead_ && bytes_requested < compaction_readahead_size_) {
|
||||
bytes_requested = compaction_readahead_size_;
|
||||
}
|
||||
|
||||
CalculateReadParameters(offset, bytes_requested, actual_bytes_toread,
|
||||
first_page_start);
|
||||
|
||||
assert(actual_bytes_toread > 0);
|
||||
|
||||
if (buffer_.Capacity() < actual_bytes_toread) {
|
||||
// If we are in read-ahead mode or the requested size
|
||||
// exceeds max buffer size then use one-shot
|
||||
// big buffer otherwise reallocate main buffer
|
||||
if (read_ahead_ ||
|
||||
if (buffer_.Capacity() < actual_bytes_toread) {
|
||||
// If we are in read-ahead mode or the requested size
|
||||
// exceeds max buffer size then use one-shot
|
||||
// big buffer otherwise reallocate main buffer
|
||||
if (read_ahead_ ||
|
||||
(actual_bytes_toread > random_access_max_buffer_size_)) {
|
||||
// Unlock the mutex since we are not using instance buffer
|
||||
lock.unlock();
|
||||
r = ReadIntoOneShotBuffer(offset, first_page_start,
|
||||
actual_bytes_toread, left, dest);
|
||||
}
|
||||
else {
|
||||
buffer_.AllocateNewBuffer(actual_bytes_toread);
|
||||
r = ReadIntoInstanceBuffer(offset, first_page_start,
|
||||
actual_bytes_toread, left, dest);
|
||||
}
|
||||
}
|
||||
else {
|
||||
buffer_.Clear();
|
||||
// Unlock the mutex since we are not using instance buffer
|
||||
lock.unlock();
|
||||
r = ReadIntoOneShotBuffer(offset, first_page_start,
|
||||
actual_bytes_toread, left, dest);
|
||||
} else {
|
||||
buffer_.AllocateNewBuffer(actual_bytes_toread);
|
||||
r = ReadIntoInstanceBuffer(offset, first_page_start,
|
||||
actual_bytes_toread, left, dest);
|
||||
actual_bytes_toread, left, dest);
|
||||
}
|
||||
} else {
|
||||
buffer_.Clear();
|
||||
r = ReadIntoInstanceBuffer(offset, first_page_start,
|
||||
actual_bytes_toread, left, dest);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1138,8 +1105,6 @@ void WinthreadCall(const char* label, std::error_code result) {
|
||||
}
|
||||
}
|
||||
|
||||
typedef VOID(WINAPI * FnGetSystemTimePreciseAsFileTime)(LPFILETIME);
|
||||
|
||||
class WinEnv : public Env {
|
||||
public:
|
||||
WinEnv();
|
||||
@@ -1678,29 +1643,25 @@ class WinEnv : public Env {
|
||||
}
|
||||
|
||||
virtual uint64_t NowMicros() override {
|
||||
if (GetSystemTimePreciseAsFileTime_ != NULL) {
|
||||
// all std::chrono clocks on windows proved to return
|
||||
// values that may repeat that is not good enough for some uses.
|
||||
const int64_t c_UnixEpochStartTicks = 116444736000000000i64;
|
||||
const int64_t c_FtToMicroSec = 10;
|
||||
// all std::chrono clocks on windows proved to return
|
||||
// values that may repeat that is not good enough for some uses.
|
||||
const int64_t c_UnixEpochStartTicks = 116444736000000000i64;
|
||||
const int64_t c_FtToMicroSec = 10;
|
||||
|
||||
// This interface needs to return system time and not
|
||||
// just any microseconds because it is often used as an argument
|
||||
// to TimedWait() on condition variable
|
||||
FILETIME ftSystemTime;
|
||||
GetSystemTimePreciseAsFileTime_(&ftSystemTime);
|
||||
// This interface needs to return system time and not
|
||||
// just any microseconds because it is often used as an argument
|
||||
// to TimedWait() on condition variable
|
||||
FILETIME ftSystemTime;
|
||||
GetSystemTimePreciseAsFileTime(&ftSystemTime);
|
||||
|
||||
LARGE_INTEGER li;
|
||||
li.LowPart = ftSystemTime.dwLowDateTime;
|
||||
li.HighPart = ftSystemTime.dwHighDateTime;
|
||||
// Subtract unix epoch start
|
||||
li.QuadPart -= c_UnixEpochStartTicks;
|
||||
// Convert to microsecs
|
||||
li.QuadPart /= c_FtToMicroSec;
|
||||
return li.QuadPart;
|
||||
}
|
||||
using namespace std::chrono;
|
||||
return duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
|
||||
LARGE_INTEGER li;
|
||||
li.LowPart = ftSystemTime.dwLowDateTime;
|
||||
li.HighPart = ftSystemTime.dwHighDateTime;
|
||||
// Subtract unix epoch start
|
||||
li.QuadPart -= c_UnixEpochStartTicks;
|
||||
// Convert to microsecs
|
||||
li.QuadPart /= c_FtToMicroSec;
|
||||
return li.QuadPart;
|
||||
}
|
||||
|
||||
virtual uint64_t NowNanos() override {
|
||||
@@ -2110,7 +2071,6 @@ class WinEnv : public Env {
|
||||
std::vector<ThreadPool> thread_pools_;
|
||||
mutable std::mutex mu_;
|
||||
std::vector<std::thread> threads_to_join_;
|
||||
FnGetSystemTimePreciseAsFileTime GetSystemTimePreciseAsFileTime_;
|
||||
};
|
||||
|
||||
WinEnv::WinEnv()
|
||||
@@ -2119,15 +2079,7 @@ WinEnv::WinEnv()
|
||||
page_size_(4 * 1012),
|
||||
allocation_granularity_(page_size_),
|
||||
perf_counter_frequency_(0),
|
||||
thread_pools_(Priority::TOTAL),
|
||||
GetSystemTimePreciseAsFileTime_(NULL) {
|
||||
|
||||
HMODULE module = GetModuleHandle("kernel32.dll");
|
||||
if (module != NULL) {
|
||||
GetSystemTimePreciseAsFileTime_ = (FnGetSystemTimePreciseAsFileTime)GetProcAddress(
|
||||
module, "GetSystemTimePreciseAsFileTime");
|
||||
}
|
||||
|
||||
thread_pools_(Priority::TOTAL) {
|
||||
SYSTEM_INFO sinfo;
|
||||
GetSystemInfo(&sinfo);
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# These are the sources from which librocksdb.a is built:
|
||||
LIB_SOURCES = \
|
||||
db/auto_roll_logger.cc \
|
||||
db/builder.cc \
|
||||
db/c.cc \
|
||||
db/column_family.cc \
|
||||
@@ -16,7 +15,6 @@ LIB_SOURCES = \
|
||||
db/db_impl_debug.cc \
|
||||
db/db_impl_readonly.cc \
|
||||
db/db_impl_experimental.cc \
|
||||
db/db_info_dumper.cc \
|
||||
db/db_iter.cc \
|
||||
db/experimental.cc \
|
||||
db/event_helpers.cc \
|
||||
@@ -48,12 +46,9 @@ LIB_SOURCES = \
|
||||
db/write_batch_base.cc \
|
||||
db/write_controller.cc \
|
||||
db/write_thread.cc \
|
||||
db/xfunc_test_points.cc \
|
||||
memtable/hash_cuckoo_rep.cc \
|
||||
memtable/hash_linklist_rep.cc \
|
||||
memtable/hash_skiplist_rep.cc \
|
||||
memtable/skiplistrep.cc \
|
||||
memtable/vectorrep.cc \
|
||||
port/stack_trace.cc \
|
||||
port/port_posix.cc \
|
||||
table/adaptive_table_factory.cc \
|
||||
@@ -86,6 +81,7 @@ LIB_SOURCES = \
|
||||
table/two_level_iterator.cc \
|
||||
tools/dump/db_dump_tool.cc \
|
||||
util/arena.cc \
|
||||
util/auto_roll_logger.cc \
|
||||
util/bloom.cc \
|
||||
util/build_version.cc \
|
||||
util/cache.cc \
|
||||
@@ -94,14 +90,14 @@ LIB_SOURCES = \
|
||||
util/compaction_job_stats_impl.cc \
|
||||
util/concurrent_arena.cc \
|
||||
util/crc32c.cc \
|
||||
util/delete_scheduler.cc \
|
||||
util/db_info_dumper.cc \
|
||||
util/delete_scheduler_impl.cc \
|
||||
util/dynamic_bloom.cc \
|
||||
util/env.cc \
|
||||
util/env_hdfs.cc \
|
||||
util/env_posix.cc \
|
||||
util/io_posix.cc \
|
||||
util/thread_posix.cc \
|
||||
util/sst_file_manager_impl.cc \
|
||||
util/file_util.cc \
|
||||
util/file_reader_writer.cc \
|
||||
util/filter_policy.cc \
|
||||
@@ -155,6 +151,7 @@ LIB_SOURCES = \
|
||||
util/perf_level.cc \
|
||||
util/random.cc \
|
||||
util/rate_limiter.cc \
|
||||
util/skiplistrep.cc \
|
||||
util/slice.cc \
|
||||
util/statistics.cc \
|
||||
util/status.cc \
|
||||
@@ -167,6 +164,7 @@ LIB_SOURCES = \
|
||||
util/thread_status_updater_debug.cc \
|
||||
util/thread_status_util.cc \
|
||||
util/thread_status_util_debug.cc \
|
||||
util/vectorrep.cc \
|
||||
util/xfunc.cc \
|
||||
util/xxhash.cc \
|
||||
|
||||
@@ -181,7 +179,6 @@ MOCK_SOURCES = \
|
||||
|
||||
TEST_BENCH_SOURCES = \
|
||||
third-party/gtest-1.7.0/fused-src/gtest/gtest-all.cc \
|
||||
db/auto_roll_logger_test.cc \
|
||||
db/column_family_test.cc \
|
||||
db/compaction_job_test.cc \
|
||||
db/compaction_job_stats_test.cc \
|
||||
@@ -209,6 +206,7 @@ TEST_BENCH_SOURCES = \
|
||||
db/flush_job_test.cc \
|
||||
db/inlineskiplist_test.cc \
|
||||
db/listener_test.cc \
|
||||
db/log_and_apply_bench.cc \
|
||||
db/log_test.cc \
|
||||
db/manual_compaction_test.cc \
|
||||
db/memtablerep_bench.cc \
|
||||
@@ -241,7 +239,10 @@ TEST_BENCH_SOURCES = \
|
||||
tools/reduce_levels_test.cc \
|
||||
tools/sst_dump_test.cc \
|
||||
util/arena_test.cc \
|
||||
util/auto_roll_logger_test.cc \
|
||||
util/autovector_test.cc \
|
||||
util/benchharness.cc \
|
||||
util/benchharness_test.cc \
|
||||
util/bloom_test.cc \
|
||||
util/cache_bench.cc \
|
||||
util/cache_test.cc \
|
||||
@@ -258,7 +259,7 @@ TEST_BENCH_SOURCES = \
|
||||
utilities/geodb/geodb_test.cc \
|
||||
utilities/memory/memory_test.cc \
|
||||
utilities/merge_operators/string_append/stringappend_test.cc \
|
||||
utilities/options/options_util_test.cc \
|
||||
utilities/options_util_test.cc \
|
||||
utilities/redis/redis_lists_test.cc \
|
||||
utilities/spatialdb/spatial_db_test.cc \
|
||||
utilities/table_properties_collectors/compact_on_deletion_collector_test.cc \
|
||||
|
||||
@@ -113,17 +113,15 @@ class IndexBuilder {
|
||||
//
|
||||
// Optimizations:
|
||||
// 1. Made block's `block_restart_interval` to be 1, which will avoid linear
|
||||
// search when doing index lookup (can be disabled by setting
|
||||
// index_block_restart_interval).
|
||||
// search when doing index lookup.
|
||||
// 2. Shorten the key length for index block. Other than honestly using the
|
||||
// last key in the data block as the index key, we instead find a shortest
|
||||
// substitute key that serves the same function.
|
||||
class ShortenedIndexBuilder : public IndexBuilder {
|
||||
public:
|
||||
explicit ShortenedIndexBuilder(const Comparator* comparator,
|
||||
int index_block_restart_interval)
|
||||
explicit ShortenedIndexBuilder(const Comparator* comparator)
|
||||
: IndexBuilder(comparator),
|
||||
index_block_builder_(index_block_restart_interval) {}
|
||||
index_block_builder_(1 /* block_restart_interval == 1 */) {}
|
||||
|
||||
virtual void AddIndexEntry(std::string* last_key_in_current_block,
|
||||
const Slice* first_key_in_next_block,
|
||||
@@ -180,10 +178,9 @@ class ShortenedIndexBuilder : public IndexBuilder {
|
||||
class HashIndexBuilder : public IndexBuilder {
|
||||
public:
|
||||
explicit HashIndexBuilder(const Comparator* comparator,
|
||||
const SliceTransform* hash_key_extractor,
|
||||
int index_block_restart_interval)
|
||||
const SliceTransform* hash_key_extractor)
|
||||
: IndexBuilder(comparator),
|
||||
primary_index_builder_(comparator, index_block_restart_interval),
|
||||
primary_index_builder_(comparator),
|
||||
hash_key_extractor_(hash_key_extractor) {}
|
||||
|
||||
virtual void AddIndexEntry(std::string* last_key_in_current_block,
|
||||
@@ -269,16 +266,13 @@ namespace {
|
||||
|
||||
// Create a index builder based on its type.
|
||||
IndexBuilder* CreateIndexBuilder(IndexType type, const Comparator* comparator,
|
||||
const SliceTransform* prefix_extractor,
|
||||
int index_block_restart_interval) {
|
||||
const SliceTransform* prefix_extractor) {
|
||||
switch (type) {
|
||||
case BlockBasedTableOptions::kBinarySearch: {
|
||||
return new ShortenedIndexBuilder(comparator,
|
||||
index_block_restart_interval);
|
||||
return new ShortenedIndexBuilder(comparator);
|
||||
}
|
||||
case BlockBasedTableOptions::kHashSearch: {
|
||||
return new HashIndexBuilder(comparator, prefix_extractor,
|
||||
index_block_restart_interval);
|
||||
return new HashIndexBuilder(comparator, prefix_extractor);
|
||||
}
|
||||
default: {
|
||||
assert(!"Do not recognize the index type ");
|
||||
@@ -490,10 +484,9 @@ struct BlockBasedTableBuilder::Rep {
|
||||
data_block(table_options.block_restart_interval,
|
||||
table_options.use_delta_encoding),
|
||||
internal_prefix_transform(_ioptions.prefix_extractor),
|
||||
index_builder(
|
||||
CreateIndexBuilder(table_options.index_type, &internal_comparator,
|
||||
&this->internal_prefix_transform,
|
||||
table_options.index_block_restart_interval)),
|
||||
index_builder(CreateIndexBuilder(table_options.index_type,
|
||||
&internal_comparator,
|
||||
&this->internal_prefix_transform)),
|
||||
compression_type(_compression_type),
|
||||
compression_opts(_compression_opts),
|
||||
filter_block(skip_filters ? nullptr : CreateFilterBlockBuilder(
|
||||
|
||||
@@ -42,9 +42,6 @@ BlockBasedTableFactory::BlockBasedTableFactory(
|
||||
if (table_options_.block_restart_interval < 1) {
|
||||
table_options_.block_restart_interval = 1;
|
||||
}
|
||||
if (table_options_.index_block_restart_interval < 1) {
|
||||
table_options_.index_block_restart_interval = 1;
|
||||
}
|
||||
}
|
||||
|
||||
Status BlockBasedTableFactory::NewTableReader(
|
||||
@@ -153,9 +150,6 @@ std::string BlockBasedTableFactory::GetPrintableTableOptions() const {
|
||||
snprintf(buffer, kBufferSize, " block_restart_interval: %d\n",
|
||||
table_options_.block_restart_interval);
|
||||
ret.append(buffer);
|
||||
snprintf(buffer, kBufferSize, " index_block_restart_interval: %d\n",
|
||||
table_options_.index_block_restart_interval);
|
||||
ret.append(buffer);
|
||||
snprintf(buffer, kBufferSize, " filter_policy: %s\n",
|
||||
table_options_.filter_policy == nullptr ?
|
||||
"nullptr" : table_options_.filter_policy->Name());
|
||||
|
||||
@@ -1255,8 +1255,7 @@ Status BlockBasedTable::Get(const ReadOptions& read_options, const Slice& key,
|
||||
BlockIter biter;
|
||||
NewDataBlockIterator(rep_, read_options, iiter.value(), &biter);
|
||||
|
||||
if (read_options.read_tier == kBlockCacheTier &&
|
||||
biter.status().IsIncomplete()) {
|
||||
if (read_options.read_tier && biter.status().IsIncomplete()) {
|
||||
// couldn't get block from block_cache
|
||||
// Update Saver.state to Found because we are only looking for whether
|
||||
// we can guarantee the key is not there when "no_io" is set
|
||||
|
||||
@@ -163,9 +163,6 @@ Status SstFileWriter::Finish(ExternalSstFileInfo* file_info) {
|
||||
if (!r->builder) {
|
||||
return Status::InvalidArgument("File is not opened");
|
||||
}
|
||||
if (r->file_info.num_entries == 0) {
|
||||
return Status::InvalidArgument("Cannot create sst file with no entries");
|
||||
}
|
||||
|
||||
Status s = r->builder->Finish();
|
||||
if (s.ok()) {
|
||||
|
||||
@@ -637,7 +637,6 @@ class HarnessTest : public testing::Test {
|
||||
new FlushBlockBySizePolicyFactory());
|
||||
table_options_.block_size = 256;
|
||||
table_options_.block_restart_interval = args.restart_interval;
|
||||
table_options_.index_block_restart_interval = args.restart_interval;
|
||||
table_options_.format_version = args.format_version;
|
||||
options_.table_factory.reset(
|
||||
new BlockBasedTableFactory(table_options_));
|
||||
@@ -2283,67 +2282,6 @@ TEST_F(HarnessTest, FooterTests) {
|
||||
}
|
||||
}
|
||||
|
||||
class IndexBlockRestartIntervalTest
|
||||
: public BlockBasedTableTest,
|
||||
public ::testing::WithParamInterface<int> {
|
||||
public:
|
||||
static std::vector<int> GetRestartValues() { return {-1, 0, 1, 8, 16, 32}; }
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
IndexBlockRestartIntervalTest, IndexBlockRestartIntervalTest,
|
||||
::testing::ValuesIn(IndexBlockRestartIntervalTest::GetRestartValues()));
|
||||
|
||||
TEST_P(IndexBlockRestartIntervalTest, IndexBlockRestartInterval) {
|
||||
const int kKeysInTable = 10000;
|
||||
const int kKeySize = 100;
|
||||
const int kValSize = 500;
|
||||
|
||||
int index_block_restart_interval = GetParam();
|
||||
|
||||
Options options;
|
||||
BlockBasedTableOptions table_options;
|
||||
table_options.block_size = 64; // small block size to get big index block
|
||||
table_options.index_block_restart_interval = index_block_restart_interval;
|
||||
options.table_factory.reset(new BlockBasedTableFactory(table_options));
|
||||
|
||||
TableConstructor c(BytewiseComparator());
|
||||
static Random rnd(301);
|
||||
for (int i = 0; i < kKeysInTable; i++) {
|
||||
InternalKey k(RandomString(&rnd, kKeySize), 0, kTypeValue);
|
||||
c.Add(k.Encode().ToString(), RandomString(&rnd, kValSize));
|
||||
}
|
||||
|
||||
std::vector<std::string> keys;
|
||||
stl_wrappers::KVMap kvmap;
|
||||
std::unique_ptr<InternalKeyComparator> comparator(
|
||||
new InternalKeyComparator(BytewiseComparator()));
|
||||
const ImmutableCFOptions ioptions(options);
|
||||
c.Finish(options, ioptions, table_options, *comparator, &keys, &kvmap);
|
||||
auto reader = c.GetTableReader();
|
||||
|
||||
std::unique_ptr<InternalIterator> db_iter(reader->NewIterator(ReadOptions()));
|
||||
|
||||
// Test point lookup
|
||||
for (auto& kv : kvmap) {
|
||||
db_iter->Seek(kv.first);
|
||||
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_OK(db_iter->status());
|
||||
ASSERT_EQ(db_iter->key(), kv.first);
|
||||
ASSERT_EQ(db_iter->value(), kv.second);
|
||||
}
|
||||
|
||||
// Test iterating
|
||||
auto kv_iter = kvmap.begin();
|
||||
for (db_iter->SeekToFirst(); db_iter->Valid(); db_iter->Next()) {
|
||||
ASSERT_EQ(db_iter->key(), kv_iter->first);
|
||||
ASSERT_EQ(db_iter->value(), kv_iter->second);
|
||||
kv_iter++;
|
||||
}
|
||||
ASSERT_EQ(kv_iter, kvmap.end());
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
+8
-30
@@ -109,10 +109,6 @@ function summarize_result {
|
||||
test_name=$2
|
||||
bench_name=$3
|
||||
|
||||
# Note that this function assumes that the benchmark executes long enough so
|
||||
# that "Compaction Stats" is written to stdout at least once. If it won't
|
||||
# happen then empty output from grep when searching for "Sum" will cause
|
||||
# syntax errors.
|
||||
uptime=$( grep ^Uptime\(secs $test_out | tail -1 | awk '{ printf "%.0f", $2 }' )
|
||||
stall_time=$( grep "^Cumulative stall" $test_out | tail -1 | awk '{ print $3 }' )
|
||||
stall_pct=$( grep "^Cumulative stall" $test_out| tail -1 | awk '{ print $5 }' )
|
||||
@@ -163,22 +159,8 @@ function run_bulkload {
|
||||
}
|
||||
|
||||
function run_fillseq {
|
||||
# This runs with a vector memtable. WAL can be either disabled or enabled
|
||||
# depending on the input parameter (1 for disabled, 0 for enabled). The main
|
||||
# benefit behind disabling WAL is to make loading faster. It is still crash
|
||||
# safe and the client can discover where to restart a load after a crash. I
|
||||
# think this is a good way to load.
|
||||
|
||||
# Make sure that we'll have unique names for all the files so that data won't
|
||||
# be overwritten.
|
||||
if [ $1 == 1 ]; then
|
||||
log_file_name=$output_dir/benchmark_fillseq.wal_disabled.v${value_size}.log
|
||||
test_name=fillseq.wal_disabled.v${value_size}
|
||||
else
|
||||
log_file_name=$output_dir/benchmark_fillseq.wal_enabled.v${value_size}.log
|
||||
test_name=fillseq.wal_enabled.v${value_size}
|
||||
fi
|
||||
|
||||
# This runs with a vector memtable and the WAL disabled to load faster. It is still crash safe and the
|
||||
# client can discover where to restart a load after a crash. I think this is a good way to load.
|
||||
echo "Loading $num_keys keys sequentially"
|
||||
cmd="./db_bench --benchmarks=fillseq \
|
||||
--use_existing_db=0 \
|
||||
@@ -187,14 +169,12 @@ function run_fillseq {
|
||||
--min_level_to_compress=0 \
|
||||
--threads=1 \
|
||||
--memtablerep=vector \
|
||||
--disable_wal=$1 \
|
||||
--disable_wal=1 \
|
||||
--seed=$( date +%s ) \
|
||||
2>&1 | tee -a $log_file_name"
|
||||
echo $cmd | tee $log_file_name
|
||||
2>&1 | tee -a $output_dir/benchmark_fillseq.v${value_size}.log"
|
||||
echo $cmd | tee $output_dir/benchmark_fillseq.v${value_size}.log
|
||||
eval $cmd
|
||||
|
||||
# The constant "fillseq" which we pass to db_bench is the benchmark name.
|
||||
summarize_result $log_file_name $test_name fillseq
|
||||
summarize_result $output_dir/benchmark_fillseq.v${value_size}.log fillseq.v${value_size} fillseq
|
||||
}
|
||||
|
||||
function run_change {
|
||||
@@ -330,10 +310,8 @@ for job in ${jobs[@]}; do
|
||||
start=$(now)
|
||||
if [ $job = bulkload ]; then
|
||||
run_bulkload
|
||||
elif [ $job = fillseq_disable_wal ]; then
|
||||
run_fillseq 1
|
||||
elif [ $job = fillseq_enable_wal ]; then
|
||||
run_fillseq 0
|
||||
elif [ $job = fillseq ]; then
|
||||
run_fillseq
|
||||
elif [ $job = overwrite ]; then
|
||||
run_change overwrite
|
||||
elif [ $job = updaterandom ]; then
|
||||
|
||||
+5
-15
@@ -86,7 +86,6 @@ simple_default_params = {
|
||||
"disable_data_sync": 0,
|
||||
"disable_wal": 0,
|
||||
"filter_deletes": lambda: random.randint(0, 1),
|
||||
"allow_concurrent_memtable_write": lambda: random.randint(0, 1),
|
||||
"iterpercent": 10,
|
||||
"max_background_compactions": 1,
|
||||
"max_bytes_for_level_base": 67108864,
|
||||
@@ -128,15 +127,6 @@ whitebox_simple_default_params = {
|
||||
}
|
||||
|
||||
|
||||
def finalize_and_sanitize(src_params):
|
||||
dest_params = dict([(k, v() if callable(v) else v)
|
||||
for (k, v) in src_params.items()])
|
||||
# --allow_concurrent_memtable_write with --filter_deletes is not supported.
|
||||
if dest_params.get("allow_concurrent_memtable_write", 1) == 1:
|
||||
dest_params["filter_deletes"] = 0
|
||||
return dest_params
|
||||
|
||||
|
||||
def gen_cmd_params(args):
|
||||
params = {}
|
||||
|
||||
@@ -162,8 +152,8 @@ def gen_cmd_params(args):
|
||||
|
||||
def gen_cmd(params):
|
||||
cmd = './db_stress ' + ' '.join(
|
||||
'--{0}={1}'.format(k, v)
|
||||
for k, v in finalize_and_sanitize(params).items()
|
||||
'--{0}={1}'.format(k, v() if callable(v) else v)
|
||||
for k, v in params.items()
|
||||
if k not in set(['test_type', 'simple', 'duration', 'interval'])
|
||||
and v is not None)
|
||||
return cmd
|
||||
@@ -247,7 +237,7 @@ def whitebox_crash_main(args):
|
||||
|
||||
total_check_mode = 4
|
||||
check_mode = 0
|
||||
kill_random_test = 888887
|
||||
kill_random_test = 97
|
||||
kill_mode = 0
|
||||
|
||||
while time.time() < exit_time:
|
||||
@@ -266,13 +256,13 @@ def whitebox_crash_main(args):
|
||||
})
|
||||
elif kill_mode == 1:
|
||||
additional_opts.update({
|
||||
"kill_random_test": (kill_random_test / 10 + 1),
|
||||
"kill_random_test": (kill_random_test / 2 + 1),
|
||||
"kill_prefix_blacklist": "WritableFileWriter::Append,"
|
||||
+ "WritableFileWriter::WriteBuffered",
|
||||
})
|
||||
elif kill_mode == 2:
|
||||
additional_opts.update({
|
||||
"kill_random_test": (kill_random_test / 5000 + 1),
|
||||
"kill_random_test": (kill_random_test / 4 + 1),
|
||||
"kill_prefix_blacklist": "WritableFileWriter::Append,"
|
||||
"WritableFileWriter::WriteBuffered,"
|
||||
"PosixMmapFile::Allocate,WritableFileWriter::Flush",
|
||||
|
||||
@@ -230,13 +230,6 @@ DEFINE_int64(cache_size, 2LL * KB * KB * KB,
|
||||
DEFINE_uint64(subcompactions, 1,
|
||||
"Maximum number of subcompactions to divide L0-L1 compactions "
|
||||
"into.");
|
||||
|
||||
DEFINE_bool(allow_concurrent_memtable_write, true,
|
||||
"Allow multi-writers to update mem tables in parallel.");
|
||||
|
||||
DEFINE_bool(enable_write_thread_adaptive_yield, true,
|
||||
"Use a yielding spin loop for brief writer thread waits.");
|
||||
|
||||
static const bool FLAGS_subcompactions_dummy __attribute__((unused)) =
|
||||
RegisterFlagValidator(&FLAGS_subcompactions, &ValidateUint32Range);
|
||||
|
||||
@@ -2004,10 +1997,6 @@ class StressTest {
|
||||
options_.filter_deletes = FLAGS_filter_deletes;
|
||||
options_.inplace_update_support = FLAGS_in_place_update;
|
||||
options_.max_subcompactions = static_cast<uint32_t>(FLAGS_subcompactions);
|
||||
options_.allow_concurrent_memtable_write =
|
||||
FLAGS_allow_concurrent_memtable_write;
|
||||
options_.enable_write_thread_adaptive_yield =
|
||||
FLAGS_enable_write_thread_adaptive_yield;
|
||||
if ((FLAGS_prefix_size == 0) == (FLAGS_rep_factory == kHashSkipList)) {
|
||||
fprintf(stderr,
|
||||
"prefix_size should be non-zero iff memtablerep == prefix_hash\n");
|
||||
|
||||
+29
-94
@@ -44,7 +44,6 @@ const string LDBCommand::ARG_PATH = "path";
|
||||
const string LDBCommand::ARG_HEX = "hex";
|
||||
const string LDBCommand::ARG_KEY_HEX = "key_hex";
|
||||
const string LDBCommand::ARG_VALUE_HEX = "value_hex";
|
||||
const string LDBCommand::ARG_CF_NAME = "column_family";
|
||||
const string LDBCommand::ARG_TTL = "ttl";
|
||||
const string LDBCommand::ARG_TTL_START = "start_time";
|
||||
const string LDBCommand::ARG_TTL_END = "end_time";
|
||||
@@ -73,14 +72,16 @@ void DumpSstFile(std::string filename, bool output_hex, bool show_properties);
|
||||
};
|
||||
|
||||
LDBCommand* LDBCommand::InitFromCmdLineArgs(
|
||||
int argc, char** argv, const Options& options,
|
||||
const LDBOptions& ldb_options,
|
||||
const std::vector<ColumnFamilyDescriptor>* column_families) {
|
||||
int argc,
|
||||
char** argv,
|
||||
const Options& options,
|
||||
const LDBOptions& ldb_options
|
||||
) {
|
||||
vector<string> args;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
args.push_back(argv[i]);
|
||||
}
|
||||
return InitFromCmdLineArgs(args, options, ldb_options, column_families);
|
||||
return InitFromCmdLineArgs(args, options, ldb_options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,9 +95,10 @@ LDBCommand* LDBCommand::InitFromCmdLineArgs(
|
||||
* Returns nullptr if the command-line cannot be parsed.
|
||||
*/
|
||||
LDBCommand* LDBCommand::InitFromCmdLineArgs(
|
||||
const vector<string>& args, const Options& options,
|
||||
const LDBOptions& ldb_options,
|
||||
const std::vector<ColumnFamilyDescriptor>* column_families) {
|
||||
const vector<string>& args,
|
||||
const Options& options,
|
||||
const LDBOptions& ldb_options
|
||||
) {
|
||||
// --x=y command line arguments are added as x->y map entries.
|
||||
map<string, string> option_map;
|
||||
|
||||
@@ -182,8 +184,6 @@ LDBCommand* LDBCommand::SelectCommand(
|
||||
return new ManifestDumpCommand(cmdParams, option_map, flags);
|
||||
} else if (cmd == ListColumnFamiliesCommand::Name()) {
|
||||
return new ListColumnFamiliesCommand(cmdParams, option_map, flags);
|
||||
} else if (cmd == CreateColumnFamilyCommand::Name()) {
|
||||
return new CreateColumnFamilyCommand(cmdParams, option_map, flags);
|
||||
} else if (cmd == DBFileDumperCommand::Name()) {
|
||||
return new DBFileDumperCommand(cmdParams, option_map, flags);
|
||||
} else if (cmd == InternalDumpCommand::Name()) {
|
||||
@@ -450,10 +450,6 @@ void CompactorCommand::Help(string& ret) {
|
||||
}
|
||||
|
||||
void CompactorCommand::DoCommand() {
|
||||
if (!db_) {
|
||||
assert(GetExecuteState().IsFailed());
|
||||
return;
|
||||
}
|
||||
|
||||
Slice* begin = nullptr;
|
||||
Slice* end = nullptr;
|
||||
@@ -517,7 +513,6 @@ Options DBLoaderCommand::PrepareOptionsForOpenDB() {
|
||||
|
||||
void DBLoaderCommand::DoCommand() {
|
||||
if (!db_) {
|
||||
assert(GetExecuteState().IsFailed());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -532,7 +527,7 @@ void DBLoaderCommand::DoCommand() {
|
||||
string key;
|
||||
string value;
|
||||
if (ParseKeyValue(line, &key, &value, is_key_hex_, is_value_hex_)) {
|
||||
db_->Put(write_options, GetCfHandle(), Slice(key), Slice(value));
|
||||
db_->Put(write_options, Slice(key), Slice(value));
|
||||
} else if (0 == line.find("Keys in range:")) {
|
||||
// ignore this line
|
||||
} else if (0 == line.find("Created bg thread 0x")) {
|
||||
@@ -546,7 +541,7 @@ void DBLoaderCommand::DoCommand() {
|
||||
cout << "Warning: " << bad_lines << " bad lines ignored." << endl;
|
||||
}
|
||||
if (compact_) {
|
||||
db_->CompactRange(CompactRangeOptions(), GetCfHandle(), nullptr, nullptr);
|
||||
db_->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -701,38 +696,6 @@ void ListColumnFamiliesCommand::DoCommand() {
|
||||
}
|
||||
}
|
||||
|
||||
void CreateColumnFamilyCommand::Help(string& ret) {
|
||||
ret.append(" ");
|
||||
ret.append(CreateColumnFamilyCommand::Name());
|
||||
ret.append(" --db=<db_path> <new_column_family_name>");
|
||||
ret.append("\n");
|
||||
}
|
||||
|
||||
CreateColumnFamilyCommand::CreateColumnFamilyCommand(
|
||||
const vector<string>& params, const map<string, string>& options,
|
||||
const vector<string>& flags)
|
||||
: LDBCommand(options, flags, true, {ARG_DB}) {
|
||||
if (params.size() != 1) {
|
||||
exec_state_ = LDBCommandExecuteResult::Failed(
|
||||
"new column family name must be specified");
|
||||
} else {
|
||||
new_cf_name_ = params[0];
|
||||
}
|
||||
}
|
||||
|
||||
void CreateColumnFamilyCommand::DoCommand() {
|
||||
ColumnFamilyHandle* new_cf_handle;
|
||||
Status st = db_->CreateColumnFamily(options_, new_cf_name_, &new_cf_handle);
|
||||
if (st.ok()) {
|
||||
fprintf(stdout, "OK\n");
|
||||
} else {
|
||||
exec_state_ = LDBCommandExecuteResult::Failed(
|
||||
"Fail to create new column family: " + st.ToString());
|
||||
}
|
||||
delete new_cf_handle;
|
||||
CloseDB();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
@@ -837,13 +800,12 @@ void InternalDumpCommand::Help(string& ret) {
|
||||
|
||||
void InternalDumpCommand::DoCommand() {
|
||||
if (!db_) {
|
||||
assert(GetExecuteState().IsFailed());
|
||||
return;
|
||||
}
|
||||
|
||||
if (print_stats_) {
|
||||
string stats;
|
||||
if (db_->GetProperty(GetCfHandle(), "rocksdb.stats", &stats)) {
|
||||
if (db_->GetProperty("rocksdb.stats", &stats)) {
|
||||
fprintf(stdout, "%s\n", stats.c_str());
|
||||
}
|
||||
}
|
||||
@@ -1088,7 +1050,7 @@ void DBDumperCommand::DoDumpCommand() {
|
||||
}
|
||||
|
||||
// Setup key iterator
|
||||
Iterator* iter = db_->NewIterator(ReadOptions(), GetCfHandle());
|
||||
Iterator* iter = db_->NewIterator(ReadOptions());
|
||||
Status st = iter->status();
|
||||
if (!st.ok()) {
|
||||
exec_state_ =
|
||||
@@ -1323,7 +1285,7 @@ void ReduceDBLevelsCommand::DoCommand() {
|
||||
}
|
||||
// Compact the whole DB to put all files to the highest level.
|
||||
fprintf(stdout, "Compacting the db...\n");
|
||||
db_->CompactRange(CompactRangeOptions(), GetCfHandle(), nullptr, nullptr);
|
||||
db_->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
||||
CloseDB();
|
||||
|
||||
EnvOptions soptions;
|
||||
@@ -1415,9 +1377,8 @@ void ChangeCompactionStyleCommand::DoCommand() {
|
||||
// print db stats before we have made any change
|
||||
std::string property;
|
||||
std::string files_per_level;
|
||||
for (int i = 0; i < db_->NumberLevels(GetCfHandle()); i++) {
|
||||
db_->GetProperty(GetCfHandle(),
|
||||
"rocksdb.num-files-at-level" + NumberToString(i),
|
||||
for (int i = 0; i < db_->NumberLevels(); i++) {
|
||||
db_->GetProperty("rocksdb.num-files-at-level" + NumberToString(i),
|
||||
&property);
|
||||
|
||||
// format print string
|
||||
@@ -1432,14 +1393,13 @@ void ChangeCompactionStyleCommand::DoCommand() {
|
||||
CompactRangeOptions compact_options;
|
||||
compact_options.change_level = true;
|
||||
compact_options.target_level = 0;
|
||||
db_->CompactRange(compact_options, GetCfHandle(), nullptr, nullptr);
|
||||
db_->CompactRange(compact_options, nullptr, nullptr);
|
||||
|
||||
// verify compaction result
|
||||
files_per_level = "";
|
||||
int num_files = 0;
|
||||
for (int i = 0; i < db_->NumberLevels(); i++) {
|
||||
db_->GetProperty(GetCfHandle(),
|
||||
"rocksdb.num-files-at-level" + NumberToString(i),
|
||||
db_->GetProperty("rocksdb.num-files-at-level" + NumberToString(i),
|
||||
&property);
|
||||
|
||||
// format print string
|
||||
@@ -1662,12 +1622,8 @@ void GetCommand::Help(string& ret) {
|
||||
}
|
||||
|
||||
void GetCommand::DoCommand() {
|
||||
if (!db_) {
|
||||
assert(GetExecuteState().IsFailed());
|
||||
return;
|
||||
}
|
||||
string value;
|
||||
Status st = db_->Get(ReadOptions(), GetCfHandle(), key_, &value);
|
||||
Status st = db_->Get(ReadOptions(), key_, &value);
|
||||
if (st.ok()) {
|
||||
fprintf(stdout, "%s\n",
|
||||
(is_value_hex_ ? StringToHex(value) : value).c_str());
|
||||
@@ -1714,14 +1670,11 @@ void ApproxSizeCommand::Help(string& ret) {
|
||||
}
|
||||
|
||||
void ApproxSizeCommand::DoCommand() {
|
||||
if (!db_) {
|
||||
assert(GetExecuteState().IsFailed());
|
||||
return;
|
||||
}
|
||||
|
||||
Range ranges[1];
|
||||
ranges[0] = Range(start_key_, end_key_);
|
||||
uint64_t sizes[1];
|
||||
db_->GetApproximateSizes(GetCfHandle(), ranges, 1, sizes);
|
||||
db_->GetApproximateSizes(ranges, 1, sizes);
|
||||
fprintf(stdout, "%lu\n", (unsigned long)sizes[0]);
|
||||
/* Weird that GetApproximateSizes() returns void, although documentation
|
||||
* says that it returns a Status object.
|
||||
@@ -1765,15 +1718,11 @@ void BatchPutCommand::Help(string& ret) {
|
||||
}
|
||||
|
||||
void BatchPutCommand::DoCommand() {
|
||||
if (!db_) {
|
||||
assert(GetExecuteState().IsFailed());
|
||||
return;
|
||||
}
|
||||
WriteBatch batch;
|
||||
|
||||
for (vector<pair<string, string>>::const_iterator itr
|
||||
= key_values_.begin(); itr != key_values_.end(); ++itr) {
|
||||
batch.Put(GetCfHandle(), itr->first, itr->second);
|
||||
batch.Put(itr->first, itr->second);
|
||||
}
|
||||
Status st = db_->Write(WriteOptions(), &batch);
|
||||
if (st.ok()) {
|
||||
@@ -1849,13 +1798,9 @@ void ScanCommand::Help(string& ret) {
|
||||
}
|
||||
|
||||
void ScanCommand::DoCommand() {
|
||||
if (!db_) {
|
||||
assert(GetExecuteState().IsFailed());
|
||||
return;
|
||||
}
|
||||
|
||||
int num_keys_scanned = 0;
|
||||
Iterator* it = db_->NewIterator(ReadOptions(), GetCfHandle());
|
||||
Iterator* it = db_->NewIterator(ReadOptions());
|
||||
if (start_key_specified_) {
|
||||
it->Seek(start_key_);
|
||||
} else {
|
||||
@@ -1951,11 +1896,7 @@ void DeleteCommand::Help(string& ret) {
|
||||
}
|
||||
|
||||
void DeleteCommand::DoCommand() {
|
||||
if (!db_) {
|
||||
assert(GetExecuteState().IsFailed());
|
||||
return;
|
||||
}
|
||||
Status st = db_->Delete(WriteOptions(), GetCfHandle(), key_);
|
||||
Status st = db_->Delete(WriteOptions(), key_);
|
||||
if (st.ok()) {
|
||||
fprintf(stdout, "OK\n");
|
||||
} else {
|
||||
@@ -1996,11 +1937,7 @@ void PutCommand::Help(string& ret) {
|
||||
}
|
||||
|
||||
void PutCommand::DoCommand() {
|
||||
if (!db_) {
|
||||
assert(GetExecuteState().IsFailed());
|
||||
return;
|
||||
}
|
||||
Status st = db_->Put(WriteOptions(), GetCfHandle(), key_, value_);
|
||||
Status st = db_->Put(WriteOptions(), key_, value_);
|
||||
if (st.ok()) {
|
||||
fprintf(stdout, "OK\n");
|
||||
} else {
|
||||
@@ -2041,7 +1978,6 @@ void DBQuerierCommand::Help(string& ret) {
|
||||
|
||||
void DBQuerierCommand::DoCommand() {
|
||||
if (!db_) {
|
||||
assert(GetExecuteState().IsFailed());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2075,17 +2011,17 @@ void DBQuerierCommand::DoCommand() {
|
||||
"delete <key>\n");
|
||||
} else if (cmd == DELETE_CMD && tokens.size() == 2) {
|
||||
key = (is_key_hex_ ? HexToString(tokens[1]) : tokens[1]);
|
||||
db_->Delete(write_options, GetCfHandle(), Slice(key));
|
||||
db_->Delete(write_options, Slice(key));
|
||||
fprintf(stdout, "Successfully deleted %s\n", tokens[1].c_str());
|
||||
} else if (cmd == PUT_CMD && tokens.size() == 3) {
|
||||
key = (is_key_hex_ ? HexToString(tokens[1]) : tokens[1]);
|
||||
value = (is_value_hex_ ? HexToString(tokens[2]) : tokens[2]);
|
||||
db_->Put(write_options, GetCfHandle(), Slice(key), Slice(value));
|
||||
db_->Put(write_options, Slice(key), Slice(value));
|
||||
fprintf(stdout, "Successfully put %s %s\n",
|
||||
tokens[1].c_str(), tokens[2].c_str());
|
||||
} else if (cmd == GET_CMD && tokens.size() == 2) {
|
||||
key = (is_key_hex_ ? HexToString(tokens[1]) : tokens[1]);
|
||||
if (db_->Get(read_options, GetCfHandle(), Slice(key), &value).ok()) {
|
||||
if (db_->Get(read_options, Slice(key), &value).ok()) {
|
||||
fprintf(stdout, "%s\n", PrintKeyValue(key, value,
|
||||
is_key_hex_, is_value_hex_).c_str());
|
||||
} else {
|
||||
@@ -2189,7 +2125,6 @@ void DBFileDumperCommand::Help(string& ret) {
|
||||
|
||||
void DBFileDumperCommand::DoCommand() {
|
||||
if (!db_) {
|
||||
assert(GetExecuteState().IsFailed());
|
||||
return;
|
||||
}
|
||||
Status s;
|
||||
|
||||
+20
-121
@@ -44,7 +44,6 @@ public:
|
||||
static const string ARG_HEX;
|
||||
static const string ARG_KEY_HEX;
|
||||
static const string ARG_VALUE_HEX;
|
||||
static const string ARG_CF_NAME;
|
||||
static const string ARG_TTL;
|
||||
static const string ARG_TTL_START;
|
||||
static const string ARG_TTL_END;
|
||||
@@ -63,14 +62,17 @@ public:
|
||||
static const string ARG_CREATE_IF_MISSING;
|
||||
|
||||
static LDBCommand* InitFromCmdLineArgs(
|
||||
const vector<string>& args, const Options& options,
|
||||
const LDBOptions& ldb_options,
|
||||
const std::vector<ColumnFamilyDescriptor>* column_families);
|
||||
const vector<string>& args,
|
||||
const Options& options,
|
||||
const LDBOptions& ldb_options
|
||||
);
|
||||
|
||||
static LDBCommand* InitFromCmdLineArgs(
|
||||
int argc, char** argv, const Options& options,
|
||||
const LDBOptions& ldb_options,
|
||||
const std::vector<ColumnFamilyDescriptor>* column_families);
|
||||
int argc,
|
||||
char** argv,
|
||||
const Options& options,
|
||||
const LDBOptions& ldb_options
|
||||
);
|
||||
|
||||
bool ValidateCmdLineOptions();
|
||||
|
||||
@@ -80,15 +82,6 @@ public:
|
||||
options_ = options;
|
||||
}
|
||||
|
||||
virtual void SetColumnFamilies(
|
||||
const std::vector<ColumnFamilyDescriptor>* column_families) {
|
||||
if (column_families != nullptr) {
|
||||
column_families_ = *column_families;
|
||||
} else {
|
||||
column_families_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void SetLDBOptions(const LDBOptions& ldb_options) {
|
||||
ldb_options_ = ldb_options;
|
||||
}
|
||||
@@ -97,7 +90,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual ~LDBCommand() { CloseDB(); }
|
||||
virtual ~LDBCommand() {
|
||||
delete db_;
|
||||
db_ = nullptr;
|
||||
}
|
||||
|
||||
/* Run the command, and return the execute result. */
|
||||
void Run() {
|
||||
@@ -185,10 +181,8 @@ protected:
|
||||
|
||||
LDBCommandExecuteResult exec_state_;
|
||||
string db_path_;
|
||||
string column_family_name_;
|
||||
DB* db_;
|
||||
DBWithTTL* db_ttl_;
|
||||
std::map<std::string, ColumnFamilyHandle*> cf_handles_;
|
||||
|
||||
/**
|
||||
* true implies that this command can work if the db is opened in read-only
|
||||
@@ -241,13 +235,6 @@ protected:
|
||||
db_path_ = itr->second;
|
||||
}
|
||||
|
||||
itr = options.find(ARG_CF_NAME);
|
||||
if (itr != options.end()) {
|
||||
column_family_name_ = itr->second;
|
||||
} else {
|
||||
column_family_name_ = kDefaultColumnFamilyName;
|
||||
}
|
||||
|
||||
is_key_hex_ = IsKeyHex(options, flags);
|
||||
is_value_hex_ = IsValueHex(options, flags);
|
||||
is_db_ttl_ = IsFlagPresent(flags, ARG_TTL);
|
||||
@@ -261,75 +248,21 @@ protected:
|
||||
}
|
||||
// Open the DB.
|
||||
Status st;
|
||||
std::vector<ColumnFamilyHandle*> handles_opened;
|
||||
if (is_db_ttl_) {
|
||||
// ldb doesn't yet support TTL DB with multiple column families
|
||||
if (!column_family_name_.empty() || !column_families_.empty()) {
|
||||
exec_state_ = LDBCommandExecuteResult::Failed(
|
||||
"ldb doesn't support TTL DB with multiple column families");
|
||||
}
|
||||
if (is_read_only_) {
|
||||
st = DBWithTTL::Open(opt, db_path_, &db_ttl_, 0, true);
|
||||
} else {
|
||||
st = DBWithTTL::Open(opt, db_path_, &db_ttl_);
|
||||
}
|
||||
db_ = db_ttl_;
|
||||
} else if (is_read_only_) {
|
||||
st = DB::OpenForReadOnly(opt, db_path_, &db_);
|
||||
} else {
|
||||
if (column_families_.empty()) {
|
||||
// Try to figure out column family lists
|
||||
std::vector<std::string> cf_list;
|
||||
st = DB::ListColumnFamilies(DBOptions(), db_path_, &cf_list);
|
||||
// There is possible the DB doesn't exist yet, for "create if not
|
||||
// "existing case". The failure is ignored here. We rely on DB::Open()
|
||||
// to give us the correct error message for problem with opening
|
||||
// existing DB.
|
||||
if (st.ok() && cf_list.size() > 1) {
|
||||
// Ignore single column family DB.
|
||||
for (auto cf_name : cf_list) {
|
||||
column_families_.emplace_back(cf_name, opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_read_only_) {
|
||||
if (column_families_.empty()) {
|
||||
st = DB::OpenForReadOnly(opt, db_path_, &db_);
|
||||
} else {
|
||||
st = DB::OpenForReadOnly(opt, db_path_, column_families_,
|
||||
&handles_opened, &db_);
|
||||
}
|
||||
} else {
|
||||
if (column_families_.empty()) {
|
||||
st = DB::Open(opt, db_path_, &db_);
|
||||
} else {
|
||||
st = DB::Open(opt, db_path_, column_families_, &handles_opened, &db_);
|
||||
}
|
||||
}
|
||||
st = DB::Open(opt, db_path_, &db_);
|
||||
}
|
||||
if (!st.ok()) {
|
||||
string msg = st.ToString();
|
||||
exec_state_ = LDBCommandExecuteResult::Failed(msg);
|
||||
} else if (!handles_opened.empty()) {
|
||||
assert(handles_opened.size() == column_families_.size());
|
||||
bool found_cf_name = false;
|
||||
for (size_t i = 0; i < handles_opened.size(); i++) {
|
||||
cf_handles_[column_families_[i].name] = handles_opened[i];
|
||||
if (column_family_name_ == column_families_[i].name) {
|
||||
found_cf_name = true;
|
||||
}
|
||||
}
|
||||
if (!found_cf_name) {
|
||||
exec_state_ = LDBCommandExecuteResult::Failed(
|
||||
"Non-existing column family " + column_family_name_);
|
||||
CloseDB();
|
||||
}
|
||||
} else {
|
||||
// We successfully opened DB in single column family mode.
|
||||
assert(column_families_.empty());
|
||||
if (column_family_name_ != kDefaultColumnFamilyName) {
|
||||
exec_state_ = LDBCommandExecuteResult::Failed(
|
||||
"Non-existing column family " + column_family_name_);
|
||||
CloseDB();
|
||||
}
|
||||
}
|
||||
|
||||
options_ = opt;
|
||||
@@ -337,27 +270,11 @@ protected:
|
||||
|
||||
void CloseDB () {
|
||||
if (db_ != nullptr) {
|
||||
for (auto& pair : cf_handles_) {
|
||||
delete pair.second;
|
||||
}
|
||||
delete db_;
|
||||
db_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ColumnFamilyHandle* GetCfHandle() {
|
||||
if (!cf_handles_.empty()) {
|
||||
auto it = cf_handles_.find(column_family_name_);
|
||||
if (it == cf_handles_.end()) {
|
||||
exec_state_ = LDBCommandExecuteResult::Failed(
|
||||
"Cannot find column family " + column_family_name_);
|
||||
} else {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
return db_->DefaultColumnFamily();
|
||||
}
|
||||
|
||||
static string PrintKeyValue(const string& key, const string& value,
|
||||
bool is_key_hex, bool is_value_hex) {
|
||||
string result;
|
||||
@@ -393,10 +310,10 @@ protected:
|
||||
* passed in.
|
||||
*/
|
||||
static vector<string> BuildCmdLineOptions(vector<string> options) {
|
||||
vector<string> ret = {ARG_DB, ARG_BLOOM_BITS, ARG_BLOCK_SIZE,
|
||||
ARG_AUTO_COMPACTION, ARG_COMPRESSION_TYPE,
|
||||
ARG_WRITE_BUFFER_SIZE, ARG_FILE_SIZE,
|
||||
ARG_FIX_PREFIX_LEN, ARG_CF_NAME};
|
||||
vector<string> ret = {ARG_DB, ARG_BLOOM_BITS,
|
||||
ARG_BLOCK_SIZE, ARG_AUTO_COMPACTION,
|
||||
ARG_COMPRESSION_TYPE, ARG_WRITE_BUFFER_SIZE,
|
||||
ARG_FILE_SIZE, ARG_FIX_PREFIX_LEN};
|
||||
ret.insert(ret.end(), options.begin(), options.end());
|
||||
return ret;
|
||||
}
|
||||
@@ -408,7 +325,6 @@ protected:
|
||||
const string& option, string* value);
|
||||
|
||||
Options options_;
|
||||
std::vector<ColumnFamilyDescriptor> column_families_;
|
||||
LDBOptions ldb_options_;
|
||||
|
||||
private:
|
||||
@@ -652,23 +568,6 @@ class ListColumnFamiliesCommand : public LDBCommand {
|
||||
string dbname_;
|
||||
};
|
||||
|
||||
class CreateColumnFamilyCommand : public LDBCommand {
|
||||
public:
|
||||
static string Name() { return "create_column_family"; }
|
||||
|
||||
CreateColumnFamilyCommand(const vector<string>& params,
|
||||
const map<string, string>& options,
|
||||
const vector<string>& flags);
|
||||
|
||||
static void Help(string& ret);
|
||||
virtual void DoCommand() override;
|
||||
|
||||
virtual bool NoDBOpen() override { return false; }
|
||||
|
||||
private:
|
||||
string new_cf_name_;
|
||||
};
|
||||
|
||||
class ReduceDBLevelsCommand : public LDBCommand {
|
||||
public:
|
||||
static string Name() { return "reduce_levels"; }
|
||||
|
||||
+1
-30
@@ -503,36 +503,7 @@ class LDBTestCase(unittest.TestCase):
|
||||
# Test on empty path.
|
||||
self.assertRunFAILFull(cmd % "")
|
||||
|
||||
def testColumnFamilies(self):
|
||||
print "Running testColumnFamilies..."
|
||||
dbPath = os.path.join(self.TMP_DIR, self.DB_NAME)
|
||||
self.assertRunOK("put cf1_1 1 --create_if_missing", "OK")
|
||||
self.assertRunOK("put cf1_2 2 --create_if_missing", "OK")
|
||||
self.assertRunOK("put cf1_3 3", "OK")
|
||||
# Given non-default column family to single CF DB.
|
||||
self.assertRunFAIL("get cf1_1 --column_family=two")
|
||||
self.assertRunOK("create_column_family two", "OK")
|
||||
self.assertRunOK("put cf2_1 1 --create_if_missing --column_family=two",
|
||||
"OK")
|
||||
self.assertRunOK("put cf2_2 2 --create_if_missing --column_family=two",
|
||||
"OK")
|
||||
self.assertRunOK("delete cf1_2", "OK")
|
||||
self.assertRunOK("create_column_family three", "OK")
|
||||
self.assertRunOK("delete cf2_2 --column_family=two", "OK")
|
||||
self.assertRunOK(
|
||||
"put cf3_1 3 --create_if_missing --column_family=three",
|
||||
"OK")
|
||||
self.assertRunOK("get cf1_1 --column_family=default", "1")
|
||||
self.assertRunOK("dump --column_family=two",
|
||||
"cf2_1 ==> 1\nKeys in range: 1")
|
||||
self.assertRunOK("dump",
|
||||
"cf1_1 ==> 1\ncf1_3 ==> 3\nKeys in range: 2")
|
||||
self.assertRunOK("get cf2_1 --column_family=two",
|
||||
"1")
|
||||
self.assertRunOK("get cf3_1 --column_family=three",
|
||||
"3")
|
||||
# non-existing column family.
|
||||
self.assertRunFAIL("get cf3_1 --column_family=four")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
+7
-13
@@ -30,10 +30,6 @@ public:
|
||||
" : Values are input/output as hex\n");
|
||||
ret.append(" --" + LDBCommand::ARG_HEX +
|
||||
" : Both keys and values are input/output as hex\n");
|
||||
ret.append(
|
||||
" --" + LDBCommand::ARG_CF_NAME +
|
||||
" : name of the column family to operate on. default: default column "
|
||||
"family\n");
|
||||
ret.append("\n");
|
||||
|
||||
ret.append("The following optional parameters control the database "
|
||||
@@ -81,16 +77,15 @@ public:
|
||||
fprintf(stderr, "%s\n", ret.c_str());
|
||||
}
|
||||
|
||||
static void RunCommand(
|
||||
int argc, char** argv, Options options, const LDBOptions& ldb_options,
|
||||
const std::vector<ColumnFamilyDescriptor>* column_families) {
|
||||
static void RunCommand(int argc, char** argv, Options options,
|
||||
const LDBOptions& ldb_options) {
|
||||
if (argc <= 2) {
|
||||
PrintHelp(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
LDBCommand* cmdObj = LDBCommand::InitFromCmdLineArgs(
|
||||
argc, argv, options, ldb_options, column_families);
|
||||
LDBCommand* cmdObj = LDBCommand::InitFromCmdLineArgs(argc, argv, options,
|
||||
ldb_options);
|
||||
if (cmdObj == nullptr) {
|
||||
fprintf(stderr, "Unknown command\n");
|
||||
PrintHelp(argv[0]);
|
||||
@@ -111,11 +106,10 @@ public:
|
||||
|
||||
};
|
||||
|
||||
|
||||
void LDBTool::Run(int argc, char** argv, Options options,
|
||||
const LDBOptions& ldb_options,
|
||||
const std::vector<ColumnFamilyDescriptor>* column_families) {
|
||||
LDBCommandRunner::RunCommand(argc, argv, options, ldb_options,
|
||||
column_families);
|
||||
const LDBOptions& ldb_options) {
|
||||
LDBCommandRunner::RunCommand(argc, argv, options, ldb_options);
|
||||
}
|
||||
} // namespace rocksdb
|
||||
|
||||
|
||||
@@ -92,8 +92,8 @@ Status ReduceLevelTest::OpenDB(bool create_if_missing, int num_levels) {
|
||||
bool ReduceLevelTest::ReduceLevels(int target_level) {
|
||||
std::vector<std::string> args = rocksdb::ReduceDBLevelsCommand::PrepareArgs(
|
||||
dbname_, target_level, false);
|
||||
LDBCommand* level_reducer =
|
||||
LDBCommand::InitFromCmdLineArgs(args, Options(), LDBOptions(), nullptr);
|
||||
LDBCommand* level_reducer = LDBCommand::InitFromCmdLineArgs(
|
||||
args, Options(), LDBOptions());
|
||||
level_reducer->Run();
|
||||
bool is_succeed = level_reducer->GetExecuteState().IsSucceed();
|
||||
delete level_reducer;
|
||||
|
||||
+43
-105
@@ -22,7 +22,6 @@
|
||||
# test and the tests are listed below.
|
||||
#
|
||||
# The environment variables are also optional. The variables are:
|
||||
#
|
||||
# NKEYS - number of key/value pairs to load
|
||||
# BG_MBWRITEPERSEC - write rate limit in MB/second for tests in which
|
||||
# there is one thread doing writes and stats are
|
||||
@@ -55,10 +54,6 @@
|
||||
# SAVE_SETUP - saves a copy of the database at the end of step 1 to
|
||||
# $DATA_DIR.bak. When LOG_DIR != DATA_DIR then it is copied
|
||||
# to $LOG_DIR.bak.
|
||||
# SKIP_LOW_PRI_TESTS - skip some of the tests which aren't crucial for getting
|
||||
# actionable benchmarking data (look for keywords "bulkload",
|
||||
# "sync=1", and "while merging").
|
||||
#
|
||||
|
||||
# Size constants
|
||||
K=1024
|
||||
@@ -94,14 +89,6 @@ wal_dir=${LOG_DIR:-"/tmp/rocksdb/"}
|
||||
do_setup=${DO_SETUP:-1}
|
||||
save_setup=${SAVE_SETUP:-0}
|
||||
|
||||
# By default we'll run all the tests. Set this to skip a set of tests which
|
||||
# aren't critical for getting key metrics.
|
||||
skip_low_pri_tests=${SKIP_LOW_PRI_TESTS:-0}
|
||||
|
||||
if [[ $skip_low_pri_tests == 1 ]]; then
|
||||
echo "Skipping some non-critical tests because SKIP_LOW_PRI_TESTS is set."
|
||||
fi
|
||||
|
||||
output_dir="/tmp/output"
|
||||
|
||||
ARGS="\
|
||||
@@ -129,25 +116,16 @@ echo -e "ops/sec\tmb/sec\tSize-GB\tL0_GB\tSum_GB\tW-Amp\tW-MB/s\tusec/op\tp50\tp
|
||||
if [[ $do_setup != 0 ]]; then
|
||||
echo Doing setup
|
||||
|
||||
if [[ $skip_low_pri_tests != 1 ]]; then
|
||||
# Test 1: bulk load
|
||||
env $ARGS ./tools/benchmark.sh bulkload
|
||||
fi
|
||||
# Test 1: bulk load
|
||||
env $ARGS ./tools/benchmark.sh bulkload
|
||||
|
||||
# Test 2a: sequential fill with large values to get peak ingest
|
||||
# adjust NUM_KEYS given the use of larger values
|
||||
env $ARGS BLOCK_SIZE=$((1 * M)) VALUE_SIZE=$((32 * K)) NUM_KEYS=$(( num_keys / 64 )) \
|
||||
./tools/benchmark.sh fillseq_disable_wal
|
||||
./tools/benchmark.sh fillseq
|
||||
|
||||
# Test 2b: sequential fill with the configured value size
|
||||
env $ARGS ./tools/benchmark.sh fillseq_disable_wal
|
||||
|
||||
# Test 2c: same as 2a, but with WAL being enabled.
|
||||
env $ARGS BLOCK_SIZE=$((1 * M)) VALUE_SIZE=$((32 * K)) NUM_KEYS=$(( num_keys / 64 )) \
|
||||
./tools/benchmark.sh fillseq_enable_wal
|
||||
|
||||
# Test 2d: same as 2b, but with WAL being enabled.
|
||||
env $ARGS ./tools/benchmark.sh fillseq_enable_wal
|
||||
env $ARGS ./tools/benchmark.sh fillseq
|
||||
|
||||
# Test 3: single-threaded overwrite
|
||||
env $ARGS NUM_THREADS=1 DB_BENCH_NO_SYNC=1 ./tools/benchmark.sh overwrite
|
||||
@@ -210,20 +188,16 @@ for num_thr in "${nthreads[@]}" ; do
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$fg_mbwps \
|
||||
DB_BENCH_NO_SYNC=1 ./tools/benchmark.sh overwrite
|
||||
|
||||
if [[ $skip_low_pri_tests != 1 ]]; then
|
||||
# Test 8: overwrite with sync=1
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$fg_mbwps \
|
||||
./tools/benchmark.sh overwrite
|
||||
fi
|
||||
# Test 8: overwrite with sync=1
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$fg_mbwps \
|
||||
./tools/benchmark.sh overwrite
|
||||
|
||||
# Test 9: random update with sync=0
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr DB_BENCH_NO_SYNC=1 \
|
||||
./tools/benchmark.sh updaterandom
|
||||
|
||||
if [[ $skip_low_pri_tests != 1 ]]; then
|
||||
# Test 10: random update with sync=1
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr ./tools/benchmark.sh updaterandom
|
||||
fi
|
||||
# Test 10: random update with sync=1
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr ./tools/benchmark.sh updaterandom
|
||||
|
||||
# Test 11: random read while writing
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$bg_mbwps \
|
||||
@@ -245,109 +219,73 @@ for num_thr in "${nthreads[@]}" ; do
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$fg_mbwps \
|
||||
DB_BENCH_NO_SYNC=1 ./tools/benchmark.sh mergerandom
|
||||
|
||||
if [[ $skip_low_pri_tests != 1 ]]; then
|
||||
# Test 15: random merge with sync=1
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$fg_mbwps \
|
||||
./tools/benchmark.sh mergerandom
|
||||
# Test 15: random merge with sync=1
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$fg_mbwps \
|
||||
./tools/benchmark.sh mergerandom
|
||||
|
||||
# Test 16: random read while merging
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$bg_mbwps \
|
||||
DB_BENCH_NO_SYNC=1 ./tools/benchmark.sh readwhilemerging
|
||||
# Test 16: random read while merging
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$bg_mbwps \
|
||||
DB_BENCH_NO_SYNC=1 ./tools/benchmark.sh readwhilemerging
|
||||
|
||||
# Test 17: range scan while merging
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$bg_mbwps \
|
||||
DB_BENCH_NO_SYNC=1 NUM_NEXTS_PER_SEEK=$nps ./tools/benchmark.sh fwdrangewhilemerging
|
||||
# Test 17: range scan while merging
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$bg_mbwps \
|
||||
DB_BENCH_NO_SYNC=1 NUM_NEXTS_PER_SEEK=$nps ./tools/benchmark.sh fwdrangewhilemerging
|
||||
|
||||
# Test 18: reverse range scan while merging
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$bg_mbwps \
|
||||
DB_BENCH_NO_SYNC=1 NUM_NEXTS_PER_SEEK=$nps ./tools/benchmark.sh revrangewhilemerging
|
||||
fi
|
||||
# Test 18: reverse range scan while merging
|
||||
env $ARGS DURATION=$duration NUM_THREADS=$num_thr MB_WRITE_PER_SEC=$bg_mbwps \
|
||||
DB_BENCH_NO_SYNC=1 NUM_NEXTS_PER_SEEK=$nps ./tools/benchmark.sh revrangewhilemerging
|
||||
done
|
||||
|
||||
if [[ $skip_low_pri_tests != 1 ]]; then
|
||||
echo bulkload > $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep bulkload $output_dir/report.txt >> $output_dir/report2.txt
|
||||
fi
|
||||
|
||||
echo fillseq_wal_disabled >> $output_dir/report2.txt
|
||||
echo bulkload > $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep fillseq.wal_disabled $output_dir/report.txt >> $output_dir/report2.txt
|
||||
|
||||
echo fillseq_wal_enabled >> $output_dir/report2.txt
|
||||
grep bulkload $output_dir/report.txt >> $output_dir/report2.txt
|
||||
echo fillseq >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep fillseq.wal_enabled $output_dir/report.txt >> $output_dir/report2.txt
|
||||
|
||||
grep fillseq $output_dir/report.txt >> $output_dir/report2.txt
|
||||
echo overwrite sync=0 >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep overwrite $output_dir/report.txt | grep \.s0 >> $output_dir/report2.txt
|
||||
|
||||
if [[ $skip_low_pri_tests != 1 ]]; then
|
||||
echo overwrite sync=1 >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep overwrite $output_dir/report.txt | grep \.s1 >> $output_dir/report2.txt
|
||||
fi
|
||||
|
||||
echo overwrite sync=1 >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep overwrite $output_dir/report.txt | grep \.s1 >> $output_dir/report2.txt
|
||||
echo updaterandom sync=0 >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep updaterandom $output_dir/report.txt | grep \.s0 >> $output_dir/report2.txt
|
||||
|
||||
if [[ $skip_low_pri_tests != 1 ]]; then
|
||||
echo updaterandom sync=1 >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep updaterandom $output_dir/report.txt | grep \.s1 >> $output_dir/report2.txt
|
||||
fi
|
||||
|
||||
echo updaterandom sync=1 >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep updaterandom $output_dir/report.txt | grep \.s1 >> $output_dir/report2.txt
|
||||
echo mergerandom sync=0 >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep mergerandom $output_dir/report.txt | grep \.s0 >> $output_dir/report2.txt
|
||||
|
||||
if [[ $skip_low_pri_tests != 1 ]]; then
|
||||
echo mergerandom sync=1 >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep mergerandom $output_dir/report.txt | grep \.s1 >> $output_dir/report2.txt
|
||||
fi
|
||||
|
||||
echo mergerandom sync=1 >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep mergerandom $output_dir/report.txt | grep \.s1 >> $output_dir/report2.txt
|
||||
echo readrandom >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep readrandom $output_dir/report.txt >> $output_dir/report2.txt
|
||||
|
||||
echo fwdrange >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep fwdrange\.t $output_dir/report.txt >> $output_dir/report2.txt
|
||||
|
||||
echo revrange >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep revrange\.t $output_dir/report.txt >> $output_dir/report2.txt
|
||||
|
||||
echo readwhile >> $output_dir/report2.txt >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep readwhilewriting $output_dir/report.txt >> $output_dir/report2.txt
|
||||
|
||||
if [[ $skip_low_pri_tests != 1 ]]; then
|
||||
echo readwhile >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep readwhilemerging $output_dir/report.txt >> $output_dir/report2.txt
|
||||
fi
|
||||
|
||||
echo readwhile >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep readwhilemerging $output_dir/report.txt >> $output_dir/report2.txt
|
||||
echo fwdreadwhilewriting >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep fwdrangewhilewriting $output_dir/report.txt >> $output_dir/report2.txt
|
||||
|
||||
if [[ $skip_low_pri_tests != 1 ]]; then
|
||||
echo fwdreadwhilemerging >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep fwdrangewhilemerg $output_dir/report.txt >> $output_dir/report2.txt
|
||||
fi
|
||||
|
||||
echo fwdreadwhilemerging >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep fwdrangewhilemerg $output_dir/report.txt >> $output_dir/report2.txt
|
||||
echo revreadwhilewriting >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep revrangewhilewriting $output_dir/report.txt >> $output_dir/report2.txt
|
||||
|
||||
if [[ $skip_low_pri_tests != 1 ]]; then
|
||||
echo revreadwhilemerging >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep revrangewhilemerg $output_dir/report.txt >> $output_dir/report2.txt
|
||||
fi
|
||||
echo revreadwhilemerging >> $output_dir/report2.txt
|
||||
head -1 $output_dir/report.txt >> $output_dir/report2.txt
|
||||
grep revrangewhilemerg $output_dir/report.txt >> $output_dir/report2.txt
|
||||
|
||||
cat $output_dir/report2.txt
|
||||
@@ -3,7 +3,7 @@
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
//
|
||||
#include "db/auto_roll_logger.h"
|
||||
#include "util/auto_roll_logger.h"
|
||||
#include "util/mutexlock.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -12,9 +12,7 @@ namespace rocksdb {
|
||||
|
||||
// -- AutoRollLogger
|
||||
Status AutoRollLogger::ResetLogger() {
|
||||
TEST_SYNC_POINT("AutoRollLogger::ResetLogger:BeforeNewLogger");
|
||||
status_ = env_->NewLogger(log_fname_, &logger_);
|
||||
TEST_SYNC_POINT("AutoRollLogger::ResetLogger:AfterNewLogger");
|
||||
|
||||
if (!status_.ok()) {
|
||||
return status_;
|
||||
@@ -34,16 +32,8 @@ Status AutoRollLogger::ResetLogger() {
|
||||
}
|
||||
|
||||
void AutoRollLogger::RollLogFile() {
|
||||
// This function is called when log is rotating. Two rotations
|
||||
// can happen quickly (NowMicro returns same value). To not overwrite
|
||||
// previous log file we increment by one micro second and try again.
|
||||
uint64_t now = env_->NowMicros();
|
||||
std::string old_fname;
|
||||
do {
|
||||
old_fname = OldInfoLogFileName(
|
||||
dbname_, now, db_absolute_path_, db_log_dir_);
|
||||
now++;
|
||||
} while (env_->FileExists(old_fname).ok());
|
||||
std::string old_fname = OldInfoLogFileName(
|
||||
dbname_, env_->NowMicros(), db_absolute_path_, db_log_dir_);
|
||||
env_->RenameFile(log_fname_, old_fname);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "db/filename.h"
|
||||
#include "port/port.h"
|
||||
#include "port/util_logger.h"
|
||||
#include "util/sync_point.h"
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
@@ -54,26 +53,11 @@ class AutoRollLogger : public Logger {
|
||||
return status_;
|
||||
}
|
||||
|
||||
size_t GetLogFileSize() const override {
|
||||
std::shared_ptr<Logger> logger;
|
||||
{
|
||||
MutexLock l(&mutex_);
|
||||
// pin down the current logger_ instance before releasing the mutex.
|
||||
logger = logger_;
|
||||
}
|
||||
return logger->GetLogFileSize();
|
||||
}
|
||||
size_t GetLogFileSize() const override { return logger_->GetLogFileSize(); }
|
||||
|
||||
void Flush() override {
|
||||
std::shared_ptr<Logger> logger;
|
||||
{
|
||||
MutexLock l(&mutex_);
|
||||
// pin down the current logger_ instance before releasing the mutex.
|
||||
logger = logger_;
|
||||
}
|
||||
TEST_SYNC_POINT("AutoRollLogger::Flush:PinnedLogger");
|
||||
if (logger) {
|
||||
logger->Flush();
|
||||
if (logger_) {
|
||||
logger_->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +101,7 @@ class AutoRollLogger : public Logger {
|
||||
uint64_t ctime_;
|
||||
uint64_t cached_now_access_count;
|
||||
uint64_t call_NowMicros_every_N_records_;
|
||||
mutable port::Mutex mutex_;
|
||||
port::Mutex mutex_;
|
||||
};
|
||||
|
||||
// Facade to craete logger automatically
|
||||
@@ -4,17 +4,14 @@
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
//
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include "db/auto_roll_logger.h"
|
||||
#include "port/port.h"
|
||||
#include "util/sync_point.h"
|
||||
#include "util/testharness.h"
|
||||
#include "util/auto_roll_logger.h"
|
||||
#include "rocksdb/db.h"
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
@@ -263,60 +260,7 @@ TEST_F(AutoRollLoggerTest, CreateLoggerFromOptions) {
|
||||
auto_roll_logger, options.log_file_time_to_roll,
|
||||
kSampleMessage + ":CreateLoggerFromOptions - both");
|
||||
}
|
||||
|
||||
TEST_F(AutoRollLoggerTest, LogFlushWhileRolling) {
|
||||
DBOptions options;
|
||||
shared_ptr<Logger> logger;
|
||||
|
||||
InitTestDb();
|
||||
options.max_log_file_size = 1024 * 5;
|
||||
ASSERT_OK(CreateLoggerFromOptions(kTestDir, options, &logger));
|
||||
AutoRollLogger* auto_roll_logger =
|
||||
dynamic_cast<AutoRollLogger*>(logger.get());
|
||||
ASSERT_TRUE(auto_roll_logger);
|
||||
std::thread flush_thread;
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->LoadDependency({
|
||||
// Need to pin the old logger before beginning the roll, as rolling grabs
|
||||
// the mutex, which would prevent us from accessing the old logger.
|
||||
{"AutoRollLogger::Flush:PinnedLogger",
|
||||
"AutoRollLoggerTest::LogFlushWhileRolling:PreRollAndPostThreadInit"},
|
||||
// Need to finish the flush thread init before this callback because the
|
||||
// callback accesses flush_thread.get_id() in order to apply certain sync
|
||||
// points only to the flush thread.
|
||||
{"AutoRollLoggerTest::LogFlushWhileRolling:PreRollAndPostThreadInit",
|
||||
"AutoRollLoggerTest::LogFlushWhileRolling:FlushCallbackBegin"},
|
||||
// Need to reset logger at this point in Flush() to exercise a race
|
||||
// condition case, which is executing the flush with the pinned (old)
|
||||
// logger after the roll has cut over to a new logger.
|
||||
{"AutoRollLoggerTest::LogFlushWhileRolling:FlushCallback1",
|
||||
"AutoRollLogger::ResetLogger:BeforeNewLogger"},
|
||||
{"AutoRollLogger::ResetLogger:AfterNewLogger",
|
||||
"AutoRollLoggerTest::LogFlushWhileRolling:FlushCallback2"},
|
||||
});
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"PosixLogger::Flush:BeginCallback", [&](void* arg) {
|
||||
TEST_SYNC_POINT(
|
||||
"AutoRollLoggerTest::LogFlushWhileRolling:FlushCallbackBegin");
|
||||
if (std::this_thread::get_id() == flush_thread.get_id()) {
|
||||
TEST_SYNC_POINT(
|
||||
"AutoRollLoggerTest::LogFlushWhileRolling:FlushCallback1");
|
||||
TEST_SYNC_POINT(
|
||||
"AutoRollLoggerTest::LogFlushWhileRolling:FlushCallback2");
|
||||
}
|
||||
});
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
flush_thread = std::thread([&]() { auto_roll_logger->Flush(); });
|
||||
TEST_SYNC_POINT(
|
||||
"AutoRollLoggerTest::LogFlushWhileRolling:PreRollAndPostThreadInit");
|
||||
RollLogFileBySizeTest(auto_roll_logger, options.max_log_file_size,
|
||||
kSampleMessage + ":LogFlushWhileRolling");
|
||||
flush_thread.join();
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
}
|
||||
|
||||
#endif // OS_WIN
|
||||
#endif
|
||||
|
||||
TEST_F(AutoRollLoggerTest, InfoLogLevel) {
|
||||
InitTestDb();
|
||||
@@ -7,8 +7,6 @@
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif
|
||||
|
||||
#include "db/db_info_dumper.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
@@ -18,6 +16,7 @@
|
||||
#include "db/filename.h"
|
||||
#include "rocksdb/options.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "util/db_info_dumper.h"
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
File renamed without changes.
@@ -3,40 +3,38 @@
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
#include "util/delete_scheduler.h"
|
||||
#include "util/delete_scheduler_impl.h"
|
||||
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "port/port.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "util/sst_file_manager_impl.h"
|
||||
#include "util/mutexlock.h"
|
||||
#include "util/sync_point.h"
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
DeleteScheduler::DeleteScheduler(Env* env, const std::string& trash_dir,
|
||||
int64_t rate_bytes_per_sec, Logger* info_log,
|
||||
SstFileManagerImpl* sst_file_manager)
|
||||
DeleteSchedulerImpl::DeleteSchedulerImpl(Env* env, const std::string& trash_dir,
|
||||
int64_t rate_bytes_per_sec,
|
||||
std::shared_ptr<Logger> info_log)
|
||||
: env_(env),
|
||||
trash_dir_(trash_dir),
|
||||
rate_bytes_per_sec_(rate_bytes_per_sec),
|
||||
pending_files_(0),
|
||||
closing_(false),
|
||||
cv_(&mu_),
|
||||
info_log_(info_log),
|
||||
sst_file_manager_(sst_file_manager) {
|
||||
if (rate_bytes_per_sec_ <= 0) {
|
||||
info_log_(info_log) {
|
||||
if (rate_bytes_per_sec_ == 0) {
|
||||
// Rate limiting is disabled
|
||||
bg_thread_.reset();
|
||||
} else {
|
||||
bg_thread_.reset(
|
||||
new std::thread(&DeleteScheduler::BackgroundEmptyTrash, this));
|
||||
new std::thread(&DeleteSchedulerImpl::BackgroundEmptyTrash, this));
|
||||
}
|
||||
}
|
||||
|
||||
DeleteScheduler::~DeleteScheduler() {
|
||||
DeleteSchedulerImpl::~DeleteSchedulerImpl() {
|
||||
{
|
||||
MutexLock l(&mu_);
|
||||
closing_ = true;
|
||||
@@ -47,29 +45,20 @@ DeleteScheduler::~DeleteScheduler() {
|
||||
}
|
||||
}
|
||||
|
||||
Status DeleteScheduler::DeleteFile(const std::string& file_path) {
|
||||
Status s;
|
||||
if (rate_bytes_per_sec_ <= 0) {
|
||||
Status DeleteSchedulerImpl::DeleteFile(const std::string& file_path) {
|
||||
if (rate_bytes_per_sec_ == 0) {
|
||||
// Rate limiting is disabled
|
||||
s = env_->DeleteFile(file_path);
|
||||
if (s.ok() && sst_file_manager_) {
|
||||
sst_file_manager_->OnDeleteFile(file_path);
|
||||
}
|
||||
return s;
|
||||
return env_->DeleteFile(file_path);
|
||||
}
|
||||
|
||||
// Move file to trash
|
||||
std::string path_in_trash;
|
||||
s = MoveToTrash(file_path, &path_in_trash);
|
||||
Status s = MoveToTrash(file_path, &path_in_trash);
|
||||
if (!s.ok()) {
|
||||
Log(InfoLogLevel::ERROR_LEVEL, info_log_,
|
||||
"Failed to move %s to trash directory (%s)", file_path.c_str(),
|
||||
trash_dir_.c_str());
|
||||
s = env_->DeleteFile(file_path);
|
||||
if (s.ok() && sst_file_manager_) {
|
||||
sst_file_manager_->OnDeleteFile(file_path);
|
||||
}
|
||||
return s;
|
||||
return env_->DeleteFile(file_path);
|
||||
}
|
||||
|
||||
// Add file to delete queue
|
||||
@@ -84,13 +73,13 @@ Status DeleteScheduler::DeleteFile(const std::string& file_path) {
|
||||
return s;
|
||||
}
|
||||
|
||||
std::map<std::string, Status> DeleteScheduler::GetBackgroundErrors() {
|
||||
std::map<std::string, Status> DeleteSchedulerImpl::GetBackgroundErrors() {
|
||||
MutexLock l(&mu_);
|
||||
return bg_errors_;
|
||||
}
|
||||
|
||||
Status DeleteScheduler::MoveToTrash(const std::string& file_path,
|
||||
std::string* path_in_trash) {
|
||||
Status DeleteSchedulerImpl::MoveToTrash(const std::string& file_path,
|
||||
std::string* path_in_trash) {
|
||||
Status s;
|
||||
// Figure out the name of the file in trash folder
|
||||
size_t idx = file_path.rfind("/");
|
||||
@@ -123,14 +112,11 @@ Status DeleteScheduler::MoveToTrash(const std::string& file_path,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (s.ok() && sst_file_manager_) {
|
||||
sst_file_manager_->OnMoveFile(file_path, *path_in_trash);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void DeleteScheduler::BackgroundEmptyTrash() {
|
||||
TEST_SYNC_POINT("DeleteScheduler::BackgroundEmptyTrash");
|
||||
void DeleteSchedulerImpl::BackgroundEmptyTrash() {
|
||||
TEST_SYNC_POINT("DeleteSchedulerImpl::BackgroundEmptyTrash");
|
||||
|
||||
while (true) {
|
||||
MutexLock l(&mu_);
|
||||
@@ -165,7 +151,7 @@ void DeleteScheduler::BackgroundEmptyTrash() {
|
||||
uint64_t total_penlty =
|
||||
((total_deleted_bytes * kMicrosInSecond) / rate_bytes_per_sec_);
|
||||
while (!closing_ && !cv_.TimedWait(start_time + total_penlty)) {}
|
||||
TEST_SYNC_POINT_CALLBACK("DeleteScheduler::BackgroundEmptyTrash:Wait",
|
||||
TEST_SYNC_POINT_CALLBACK("DeleteSchedulerImpl::BackgroundEmptyTrash:Wait",
|
||||
&total_penlty);
|
||||
|
||||
pending_files_--;
|
||||
@@ -178,12 +164,12 @@ void DeleteScheduler::BackgroundEmptyTrash() {
|
||||
}
|
||||
}
|
||||
|
||||
Status DeleteScheduler::DeleteTrashFile(const std::string& path_in_trash,
|
||||
uint64_t* deleted_bytes) {
|
||||
Status DeleteSchedulerImpl::DeleteTrashFile(const std::string& path_in_trash,
|
||||
uint64_t* deleted_bytes) {
|
||||
uint64_t file_size;
|
||||
Status s = env_->GetFileSize(path_in_trash, &file_size);
|
||||
if (s.ok()) {
|
||||
TEST_SYNC_POINT("DeleteScheduler::DeleteTrashFile:DeleteFile");
|
||||
TEST_SYNC_POINT("DeleteSchedulerImpl::DeleteTrashFile:DeleteFile");
|
||||
s = env_->DeleteFile(path_in_trash);
|
||||
}
|
||||
|
||||
@@ -195,19 +181,51 @@ Status DeleteScheduler::DeleteTrashFile(const std::string& path_in_trash,
|
||||
*deleted_bytes = 0;
|
||||
} else {
|
||||
*deleted_bytes = file_size;
|
||||
if (sst_file_manager_) {
|
||||
sst_file_manager_->OnDeleteFile(path_in_trash);
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void DeleteScheduler::WaitForEmptyTrash() {
|
||||
void DeleteSchedulerImpl::WaitForEmptyTrash() {
|
||||
MutexLock l(&mu_);
|
||||
while (pending_files_ > 0 && !closing_) {
|
||||
cv_.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
DeleteScheduler* NewDeleteScheduler(Env* env, const std::string& trash_dir,
|
||||
int64_t rate_bytes_per_sec,
|
||||
std::shared_ptr<Logger> info_log,
|
||||
bool delete_exisitng_trash,
|
||||
Status* status) {
|
||||
DeleteScheduler* res =
|
||||
new DeleteSchedulerImpl(env, trash_dir, rate_bytes_per_sec, info_log);
|
||||
|
||||
Status s;
|
||||
if (trash_dir != "") {
|
||||
s = env->CreateDirIfMissing(trash_dir);
|
||||
if (s.ok() && delete_exisitng_trash) {
|
||||
std::vector<std::string> files_in_trash;
|
||||
s = env->GetChildren(trash_dir, &files_in_trash);
|
||||
if (s.ok()) {
|
||||
for (const std::string& trash_file : files_in_trash) {
|
||||
if (trash_file == "." || trash_file == "..") {
|
||||
continue;
|
||||
}
|
||||
Status file_delete = res->DeleteFile(trash_dir + "/" + trash_file);
|
||||
if (s.ok() && !file_delete.ok()) {
|
||||
s = file_delete;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (status) {
|
||||
*status = s;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
@@ -12,28 +12,21 @@
|
||||
|
||||
#include "port/port.h"
|
||||
|
||||
#include "rocksdb/delete_scheduler.h"
|
||||
#include "rocksdb/status.h"
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
class Env;
|
||||
class Logger;
|
||||
class SstFileManagerImpl;
|
||||
|
||||
// DeleteScheduler allows the DB to enforce a rate limit on file deletion,
|
||||
// Instead of deleteing files immediately, files are moved to trash_dir
|
||||
// and deleted in a background thread that apply sleep penlty between deletes
|
||||
// if they are happening in a rate faster than rate_bytes_per_sec,
|
||||
//
|
||||
// Rate limiting can be turned off by setting rate_bytes_per_sec = 0, In this
|
||||
// case DeleteScheduler will delete files immediately.
|
||||
class DeleteScheduler {
|
||||
class DeleteSchedulerImpl : public DeleteScheduler {
|
||||
public:
|
||||
DeleteScheduler(Env* env, const std::string& trash_dir,
|
||||
int64_t rate_bytes_per_sec, Logger* info_log,
|
||||
SstFileManagerImpl* sst_file_manager);
|
||||
DeleteSchedulerImpl(Env* env, const std::string& trash_dir,
|
||||
int64_t rate_bytes_per_sec,
|
||||
std::shared_ptr<Logger> info_log);
|
||||
|
||||
~DeleteScheduler();
|
||||
~DeleteSchedulerImpl();
|
||||
|
||||
// Return delete rate limit in bytes per second
|
||||
int64_t GetRateBytesPerSecond() { return rate_bytes_per_sec_; }
|
||||
@@ -70,7 +63,7 @@ class DeleteScheduler {
|
||||
int32_t pending_files_;
|
||||
// Errors that happened in BackgroundEmptyTrash (file_path => error)
|
||||
std::map<std::string, Status> bg_errors_;
|
||||
// Set to true in ~DeleteScheduler() to force BackgroundEmptyTrash to stop
|
||||
// Set to true in ~DeleteSchedulerImpl() to force BackgroundEmptyTrash to stop
|
||||
bool closing_;
|
||||
// Condition variable signaled in these conditions
|
||||
// - pending_files_ value change from 0 => 1
|
||||
@@ -81,8 +74,7 @@ class DeleteScheduler {
|
||||
std::unique_ptr<std::thread> bg_thread_;
|
||||
// Mutex to protect threads from file name conflicts
|
||||
port::Mutex file_move_mu_;
|
||||
Logger* info_log_;
|
||||
SstFileManagerImpl* sst_file_manager_;
|
||||
std::shared_ptr<Logger> info_log_;
|
||||
static const uint64_t kMicrosInSecond = 1000 * 1000LL;
|
||||
};
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "rocksdb/delete_scheduler.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "rocksdb/options.h"
|
||||
#include "util/delete_scheduler.h"
|
||||
#include "util/string_util.h"
|
||||
#include "util/sync_point.h"
|
||||
#include "util/testharness.h"
|
||||
@@ -74,12 +74,6 @@ class DeleteSchedulerTest : public testing::Test {
|
||||
return file_path;
|
||||
}
|
||||
|
||||
void NewDeleteScheduler() {
|
||||
ASSERT_OK(env_->CreateDirIfMissing(trash_dir_));
|
||||
delete_scheduler_.reset(new DeleteScheduler(
|
||||
env_, trash_dir_, rate_bytes_per_sec_, nullptr, nullptr));
|
||||
}
|
||||
|
||||
Env* env_;
|
||||
std::string dummy_files_dir_;
|
||||
std::string trash_dir_;
|
||||
@@ -90,19 +84,19 @@ class DeleteSchedulerTest : public testing::Test {
|
||||
// Test the basic functionality of DeleteScheduler (Rate Limiting).
|
||||
// 1- Create 100 dummy files
|
||||
// 2- Delete the 100 dummy files using DeleteScheduler
|
||||
// --- Hold DeleteScheduler::BackgroundEmptyTrash ---
|
||||
// --- Hold DeleteSchedulerImpl::BackgroundEmptyTrash ---
|
||||
// 3- Wait for DeleteScheduler to delete all files in trash
|
||||
// 4- Verify that BackgroundEmptyTrash used to correct penlties for the files
|
||||
// 5- Make sure that all created files were completely deleted
|
||||
TEST_F(DeleteSchedulerTest, BasicRateLimiting) {
|
||||
rocksdb::SyncPoint::GetInstance()->LoadDependency({
|
||||
{"DeleteSchedulerTest::BasicRateLimiting:1",
|
||||
"DeleteScheduler::BackgroundEmptyTrash"},
|
||||
"DeleteSchedulerImpl::BackgroundEmptyTrash"},
|
||||
});
|
||||
|
||||
std::vector<uint64_t> penalties;
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"DeleteScheduler::BackgroundEmptyTrash:Wait",
|
||||
"DeleteSchedulerImpl::BackgroundEmptyTrash:Wait",
|
||||
[&](void* arg) { penalties.push_back(*(static_cast<int*>(arg))); });
|
||||
|
||||
int num_files = 100; // 100 files
|
||||
@@ -116,7 +110,8 @@ TEST_F(DeleteSchedulerTest, BasicRateLimiting) {
|
||||
|
||||
DestroyAndCreateDir(dummy_files_dir_);
|
||||
rate_bytes_per_sec_ = delete_kbs_per_sec[t] * 1024;
|
||||
NewDeleteScheduler();
|
||||
delete_scheduler_.reset(
|
||||
NewDeleteScheduler(env_, trash_dir_, rate_bytes_per_sec_));
|
||||
|
||||
// Create 100 dummy files, every file is 1 Kb
|
||||
std::vector<std::string> generated_files;
|
||||
@@ -157,19 +152,19 @@ TEST_F(DeleteSchedulerTest, BasicRateLimiting) {
|
||||
// Same as the BasicRateLimiting test but delete files in multiple threads.
|
||||
// 1- Create 100 dummy files
|
||||
// 2- Delete the 100 dummy files using DeleteScheduler using 10 threads
|
||||
// --- Hold DeleteScheduler::BackgroundEmptyTrash ---
|
||||
// --- Hold DeleteSchedulerImpl::BackgroundEmptyTrash ---
|
||||
// 3- Wait for DeleteScheduler to delete all files in queue
|
||||
// 4- Verify that BackgroundEmptyTrash used to correct penlties for the files
|
||||
// 5- Make sure that all created files were completely deleted
|
||||
TEST_F(DeleteSchedulerTest, RateLimitingMultiThreaded) {
|
||||
rocksdb::SyncPoint::GetInstance()->LoadDependency({
|
||||
{"DeleteSchedulerTest::RateLimitingMultiThreaded:1",
|
||||
"DeleteScheduler::BackgroundEmptyTrash"},
|
||||
"DeleteSchedulerImpl::BackgroundEmptyTrash"},
|
||||
});
|
||||
|
||||
std::vector<uint64_t> penalties;
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"DeleteScheduler::BackgroundEmptyTrash:Wait",
|
||||
"DeleteSchedulerImpl::BackgroundEmptyTrash:Wait",
|
||||
[&](void* arg) { penalties.push_back(*(static_cast<int*>(arg))); });
|
||||
|
||||
int thread_cnt = 10;
|
||||
@@ -184,7 +179,8 @@ TEST_F(DeleteSchedulerTest, RateLimitingMultiThreaded) {
|
||||
|
||||
DestroyAndCreateDir(dummy_files_dir_);
|
||||
rate_bytes_per_sec_ = delete_kbs_per_sec[t] * 1024;
|
||||
NewDeleteScheduler();
|
||||
delete_scheduler_.reset(
|
||||
NewDeleteScheduler(env_, trash_dir_, rate_bytes_per_sec_));
|
||||
|
||||
// Create 100 dummy files, every file is 1 Kb
|
||||
std::vector<std::string> generated_files;
|
||||
@@ -243,13 +239,12 @@ TEST_F(DeleteSchedulerTest, RateLimitingMultiThreaded) {
|
||||
TEST_F(DeleteSchedulerTest, DisableRateLimiting) {
|
||||
int bg_delete_file = 0;
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"DeleteScheduler::DeleteTrashFile:DeleteFile",
|
||||
"DeleteSchedulerImpl::DeleteTrashFile:DeleteFile",
|
||||
[&](void* arg) { bg_delete_file++; });
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
rate_bytes_per_sec_ = 0;
|
||||
NewDeleteScheduler();
|
||||
delete_scheduler_.reset(NewDeleteScheduler(env_, "", 0));
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
// Every file we delete will be deleted immediately
|
||||
@@ -269,17 +264,18 @@ TEST_F(DeleteSchedulerTest, DisableRateLimiting) {
|
||||
// 1- Create 10 files with the same name "conflict.data"
|
||||
// 2- Delete the 10 files using DeleteScheduler
|
||||
// 3- Make sure that trash directory contain 10 files ("conflict.data" x 10)
|
||||
// --- Hold DeleteScheduler::BackgroundEmptyTrash ---
|
||||
// --- Hold DeleteSchedulerImpl::BackgroundEmptyTrash ---
|
||||
// 4- Make sure that files are deleted from trash
|
||||
TEST_F(DeleteSchedulerTest, ConflictNames) {
|
||||
rocksdb::SyncPoint::GetInstance()->LoadDependency({
|
||||
{"DeleteSchedulerTest::ConflictNames:1",
|
||||
"DeleteScheduler::BackgroundEmptyTrash"},
|
||||
"DeleteSchedulerImpl::BackgroundEmptyTrash"},
|
||||
});
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
rate_bytes_per_sec_ = 1024 * 1024; // 1 Mb/sec
|
||||
NewDeleteScheduler();
|
||||
delete_scheduler_.reset(
|
||||
NewDeleteScheduler(env_, trash_dir_, rate_bytes_per_sec_));
|
||||
|
||||
// Create "conflict.data" and move it to trash 10 times
|
||||
for (int i = 0; i < 10; i++) {
|
||||
@@ -304,18 +300,19 @@ TEST_F(DeleteSchedulerTest, ConflictNames) {
|
||||
// 1- Create 10 dummy files
|
||||
// 2- Delete the 10 files using DeleteScheduler (move them to trsah)
|
||||
// 3- Delete the 10 files directly (using env_->DeleteFile)
|
||||
// --- Hold DeleteScheduler::BackgroundEmptyTrash ---
|
||||
// --- Hold DeleteSchedulerImpl::BackgroundEmptyTrash ---
|
||||
// 4- Make sure that DeleteScheduler failed to delete the 10 files and
|
||||
// reported 10 background errors
|
||||
TEST_F(DeleteSchedulerTest, BackgroundError) {
|
||||
rocksdb::SyncPoint::GetInstance()->LoadDependency({
|
||||
{"DeleteSchedulerTest::BackgroundError:1",
|
||||
"DeleteScheduler::BackgroundEmptyTrash"},
|
||||
"DeleteSchedulerImpl::BackgroundEmptyTrash"},
|
||||
});
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
rate_bytes_per_sec_ = 1024 * 1024; // 1 Mb/sec
|
||||
NewDeleteScheduler();
|
||||
delete_scheduler_.reset(
|
||||
NewDeleteScheduler(env_, trash_dir_, rate_bytes_per_sec_));
|
||||
|
||||
// Generate 10 dummy files and move them to trash
|
||||
for (int i = 0; i < 10; i++) {
|
||||
@@ -342,6 +339,32 @@ TEST_F(DeleteSchedulerTest, BackgroundError) {
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
}
|
||||
|
||||
// 1- Create 10 files in trash
|
||||
// 2- Create a DeleteScheduler with delete_exisitng_trash = true
|
||||
// 3- Wait for DeleteScheduler to delete all files in queue
|
||||
// 4- Make sure that all files in trash directory were deleted
|
||||
TEST_F(DeleteSchedulerTest, TrashWithExistingFiles) {
|
||||
std::vector<std::string> dummy_files;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
std::string file_name = "data_" + ToString(i) + ".data";
|
||||
std::string trash_path = trash_dir_ + "/" + file_name;
|
||||
env_->RenameFile(NewDummyFile(file_name), trash_path);
|
||||
}
|
||||
ASSERT_EQ(CountFilesInDir(trash_dir_), 10);
|
||||
|
||||
Status s;
|
||||
rate_bytes_per_sec_ = 1024 * 1024; // 1 Mb/sec
|
||||
delete_scheduler_.reset(NewDeleteScheduler(
|
||||
env_, trash_dir_, rate_bytes_per_sec_, nullptr, true, &s));
|
||||
ASSERT_OK(s);
|
||||
|
||||
delete_scheduler_->WaitForEmptyTrash();
|
||||
ASSERT_EQ(CountFilesInDir(trash_dir_), 0);
|
||||
|
||||
auto bg_errors = delete_scheduler_->GetBackgroundErrors();
|
||||
ASSERT_EQ(bg_errors.size(), 0);
|
||||
}
|
||||
|
||||
// 1- Create 10 dummy files
|
||||
// 2- Delete 10 dummy files using DeleteScheduler
|
||||
// 3- Wait for DeleteScheduler to delete all files in queue
|
||||
@@ -350,12 +373,13 @@ TEST_F(DeleteSchedulerTest, BackgroundError) {
|
||||
TEST_F(DeleteSchedulerTest, StartBGEmptyTrashMultipleTimes) {
|
||||
int bg_delete_file = 0;
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"DeleteScheduler::DeleteTrashFile:DeleteFile",
|
||||
"DeleteSchedulerImpl::DeleteTrashFile:DeleteFile",
|
||||
[&](void* arg) { bg_delete_file++; });
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
rate_bytes_per_sec_ = 1024 * 1024; // 1 MB / sec
|
||||
NewDeleteScheduler();
|
||||
delete_scheduler_.reset(
|
||||
NewDeleteScheduler(env_, trash_dir_, rate_bytes_per_sec_));
|
||||
|
||||
// Move files to trash, wait for empty trash, start again
|
||||
for (int run = 1; run <= 5; run++) {
|
||||
@@ -385,12 +409,13 @@ TEST_F(DeleteSchedulerTest, StartBGEmptyTrashMultipleTimes) {
|
||||
TEST_F(DeleteSchedulerTest, DestructorWithNonEmptyQueue) {
|
||||
int bg_delete_file = 0;
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"DeleteScheduler::DeleteTrashFile:DeleteFile",
|
||||
"DeleteSchedulerImpl::DeleteTrashFile:DeleteFile",
|
||||
[&](void* arg) { bg_delete_file++; });
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
rate_bytes_per_sec_ = 1; // 1 Byte / sec
|
||||
NewDeleteScheduler();
|
||||
delete_scheduler_.reset(
|
||||
NewDeleteScheduler(env_, trash_dir_, rate_bytes_per_sec_));
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
std::string file_name = "data_" + ToString(i) + ".data";
|
||||
@@ -414,12 +439,13 @@ TEST_F(DeleteSchedulerTest, DestructorWithNonEmptyQueue) {
|
||||
TEST_F(DeleteSchedulerTest, MoveToTrashError) {
|
||||
int bg_delete_file = 0;
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"DeleteScheduler::DeleteTrashFile:DeleteFile",
|
||||
"DeleteSchedulerImpl::DeleteTrashFile:DeleteFile",
|
||||
[&](void* arg) { bg_delete_file++; });
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
rate_bytes_per_sec_ = 1024; // 1 Kb / sec
|
||||
NewDeleteScheduler();
|
||||
delete_scheduler_.reset(
|
||||
NewDeleteScheduler(env_, trash_dir_, rate_bytes_per_sec_));
|
||||
|
||||
// We will delete the trash directory, that mean that DeleteScheduler wont
|
||||
// be able to move files to trash and will delete files them immediately.
|
||||
@@ -434,6 +460,7 @@ TEST_F(DeleteSchedulerTest, MoveToTrashError) {
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
@@ -46,7 +46,6 @@
|
||||
#include "util/iostats_context_imp.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/posix_logger.h"
|
||||
#include "util/random.h"
|
||||
#include "util/string_util.h"
|
||||
#include "util/sync_point.h"
|
||||
#include "util/thread_local.h"
|
||||
@@ -132,7 +131,6 @@ class PosixEnv : public Env {
|
||||
// All threads must be joined before the deletion of
|
||||
// thread_status_updater_.
|
||||
delete thread_status_updater_;
|
||||
TEST_SYNC_POINT("PosixEnv::~PosixEnv():End");
|
||||
}
|
||||
|
||||
void SetFD_CLOEXEC(int fd, const EnvOptions* options) {
|
||||
|
||||
+7
-9
@@ -8,9 +8,10 @@
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include "rocksdb/delete_scheduler.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "rocksdb/options.h"
|
||||
#include "util/sst_file_manager_impl.h"
|
||||
#include "db/filename.h"
|
||||
#include "util/file_reader_writer.h"
|
||||
|
||||
namespace rocksdb {
|
||||
@@ -66,15 +67,12 @@ Status CopyFile(Env* env, const std::string& source,
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status DeleteSSTFile(const DBOptions* db_options, const std::string& fname,
|
||||
uint32_t path_id) {
|
||||
// TODO(tec): support sst_file_manager for multiple path_ids
|
||||
auto sfm =
|
||||
static_cast<SstFileManagerImpl*>(db_options->sst_file_manager.get());
|
||||
if (sfm && path_id == 0) {
|
||||
return sfm->ScheduleFileDeletion(fname);
|
||||
} else {
|
||||
Status DeleteOrMoveToTrash(const DBOptions* db_options,
|
||||
const std::string& fname) {
|
||||
if (db_options->delete_scheduler == nullptr) {
|
||||
return db_options->env->DeleteFile(fname);
|
||||
} else {
|
||||
return db_options->delete_scheduler->DeleteFile(fname);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@ namespace rocksdb {
|
||||
extern Status CopyFile(Env* env, const std::string& source,
|
||||
const std::string& destination, uint64_t size = 0);
|
||||
|
||||
extern Status DeleteSSTFile(const DBOptions* db_options,
|
||||
const std::string& fname, uint32_t path_id);
|
||||
extern Status DeleteOrMoveToTrash(const DBOptions* db_options,
|
||||
const std::string& fname);
|
||||
|
||||
} // namespace rocksdb
|
||||
@@ -8,18 +8,11 @@
|
||||
#include "util/thread_status_util.h"
|
||||
|
||||
namespace rocksdb {
|
||||
namespace {
|
||||
bool ShouldReportToStats(Env* env, Statistics* stats) {
|
||||
return env != nullptr && stats != nullptr &&
|
||||
stats->stats_level_ != kExceptTimeForMutex;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void InstrumentedMutex::Lock() {
|
||||
PERF_CONDITIONAL_TIMER_FOR_MUTEX_GUARD(db_mutex_lock_nanos,
|
||||
stats_code_ == DB_MUTEX_WAIT_MICROS);
|
||||
PERF_CONDITIONAL_TIMER_GUARD(db_mutex_lock_nanos,
|
||||
stats_code_ == DB_MUTEX_WAIT_MICROS);
|
||||
uint64_t wait_time_micros = 0;
|
||||
if (ShouldReportToStats(env_, stats_)) {
|
||||
if (env_ != nullptr && stats_ != nullptr) {
|
||||
{
|
||||
StopWatch sw(env_, nullptr, 0, &wait_time_micros);
|
||||
LockInternal();
|
||||
@@ -38,10 +31,10 @@ void InstrumentedMutex::LockInternal() {
|
||||
}
|
||||
|
||||
void InstrumentedCondVar::Wait() {
|
||||
PERF_CONDITIONAL_TIMER_FOR_MUTEX_GUARD(db_condition_wait_nanos,
|
||||
stats_code_ == DB_MUTEX_WAIT_MICROS);
|
||||
PERF_CONDITIONAL_TIMER_GUARD(db_condition_wait_nanos,
|
||||
stats_code_ == DB_MUTEX_WAIT_MICROS);
|
||||
uint64_t wait_time_micros = 0;
|
||||
if (ShouldReportToStats(env_, stats_)) {
|
||||
if (env_ != nullptr && stats_ != nullptr) {
|
||||
{
|
||||
StopWatch sw(env_, nullptr, 0, &wait_time_micros);
|
||||
WaitInternal();
|
||||
@@ -60,11 +53,11 @@ void InstrumentedCondVar::WaitInternal() {
|
||||
}
|
||||
|
||||
bool InstrumentedCondVar::TimedWait(uint64_t abs_time_us) {
|
||||
PERF_CONDITIONAL_TIMER_FOR_MUTEX_GUARD(db_condition_wait_nanos,
|
||||
stats_code_ == DB_MUTEX_WAIT_MICROS);
|
||||
PERF_CONDITIONAL_TIMER_GUARD(db_condition_wait_nanos,
|
||||
stats_code_ == DB_MUTEX_WAIT_MICROS);
|
||||
uint64_t wait_time_micros = 0;
|
||||
bool result = false;
|
||||
if (ShouldReportToStats(env_, stats_)) {
|
||||
if (env_ != nullptr && stats_ != nullptr) {
|
||||
{
|
||||
StopWatch sw(env_, nullptr, 0, &wait_time_micros);
|
||||
result = TimedWaitInternal(abs_time_us);
|
||||
|
||||
+5
-12
@@ -31,21 +31,14 @@ void IOStatsContext::Reset() {
|
||||
logger_nanos = 0;
|
||||
}
|
||||
|
||||
#define IOSTATS_CONTEXT_OUTPUT(counter) #counter << " = " << counter << ", "
|
||||
#define OUTPUT(counter) #counter << " = " << counter << ", "
|
||||
|
||||
std::string IOStatsContext::ToString() const {
|
||||
std::ostringstream ss;
|
||||
ss << IOSTATS_CONTEXT_OUTPUT(thread_pool_id)
|
||||
<< IOSTATS_CONTEXT_OUTPUT(bytes_read)
|
||||
<< IOSTATS_CONTEXT_OUTPUT(bytes_written)
|
||||
<< IOSTATS_CONTEXT_OUTPUT(open_nanos)
|
||||
<< IOSTATS_CONTEXT_OUTPUT(allocate_nanos)
|
||||
<< IOSTATS_CONTEXT_OUTPUT(write_nanos)
|
||||
<< IOSTATS_CONTEXT_OUTPUT(read_nanos)
|
||||
<< IOSTATS_CONTEXT_OUTPUT(range_sync_nanos)
|
||||
<< IOSTATS_CONTEXT_OUTPUT(fsync_nanos)
|
||||
<< IOSTATS_CONTEXT_OUTPUT(prepare_write_nanos)
|
||||
<< IOSTATS_CONTEXT_OUTPUT(logger_nanos);
|
||||
ss << OUTPUT(thread_pool_id) << OUTPUT(bytes_read) << OUTPUT(bytes_written)
|
||||
<< OUTPUT(open_nanos) << OUTPUT(allocate_nanos) << OUTPUT(write_nanos)
|
||||
<< OUTPUT(read_nanos) << OUTPUT(range_sync_nanos) << OUTPUT(fsync_nanos)
|
||||
<< OUTPUT(prepare_write_nanos) << OUTPUT(logger_nanos);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
|
||||
#include "db/db_impl.h"
|
||||
#include "rocksdb/db.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "util/testharness.h"
|
||||
@@ -182,6 +183,58 @@ TEST_F(MemEnvTest, LargeWrite) {
|
||||
delete [] scratch;
|
||||
}
|
||||
|
||||
TEST_F(MemEnvTest, DBTest) {
|
||||
Options options;
|
||||
options.create_if_missing = true;
|
||||
options.env = env_;
|
||||
DB* db;
|
||||
|
||||
const Slice keys[] = {Slice("aaa"), Slice("bbb"), Slice("ccc")};
|
||||
const Slice vals[] = {Slice("foo"), Slice("bar"), Slice("baz")};
|
||||
|
||||
ASSERT_OK(DB::Open(options, "/dir/db", &db));
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
ASSERT_OK(db->Put(WriteOptions(), keys[i], vals[i]));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
std::string res;
|
||||
ASSERT_OK(db->Get(ReadOptions(), keys[i], &res));
|
||||
ASSERT_TRUE(res == vals[i]);
|
||||
}
|
||||
|
||||
Iterator* iterator = db->NewIterator(ReadOptions());
|
||||
iterator->SeekToFirst();
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
ASSERT_TRUE(iterator->Valid());
|
||||
ASSERT_TRUE(keys[i] == iterator->key());
|
||||
ASSERT_TRUE(vals[i] == iterator->value());
|
||||
iterator->Next();
|
||||
}
|
||||
ASSERT_TRUE(!iterator->Valid());
|
||||
delete iterator;
|
||||
|
||||
DBImpl* dbi = reinterpret_cast<DBImpl*>(db);
|
||||
ASSERT_OK(dbi->TEST_FlushMemTable());
|
||||
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
std::string res;
|
||||
ASSERT_OK(db->Get(ReadOptions(), keys[i], &res));
|
||||
ASSERT_TRUE(res == vals[i]);
|
||||
}
|
||||
|
||||
delete db;
|
||||
|
||||
options.create_if_missing = false;
|
||||
ASSERT_OK(DB::Open(options, "/dir/db", &db));
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
std::string res;
|
||||
ASSERT_OK(db->Get(ReadOptions(), keys[i], &res));
|
||||
ASSERT_TRUE(res == vals[i]);
|
||||
}
|
||||
delete db;
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "util/mock_env.h"
|
||||
#include "db/db_impl.h"
|
||||
#include "rocksdb/db.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "util/testharness.h"
|
||||
@@ -220,6 +221,52 @@ TEST_F(MockEnvTest, Corrupt) {
|
||||
ASSERT_NE(result.compare(kCorrupted), 0);
|
||||
}
|
||||
|
||||
TEST_F(MockEnvTest, DBTest) {
|
||||
Options options;
|
||||
options.create_if_missing = true;
|
||||
options.env = env_;
|
||||
DB* db;
|
||||
|
||||
const Slice keys[] = {Slice("aaa"), Slice("bbb"), Slice("ccc")};
|
||||
const Slice vals[] = {Slice("foo"), Slice("bar"), Slice("baz")};
|
||||
|
||||
ASSERT_OK(DB::Open(options, "/dir/db", &db));
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
ASSERT_OK(db->Put(WriteOptions(), keys[i], vals[i]));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
std::string res;
|
||||
ASSERT_OK(db->Get(ReadOptions(), keys[i], &res));
|
||||
ASSERT_TRUE(res == vals[i]);
|
||||
}
|
||||
|
||||
Iterator* iterator = db->NewIterator(ReadOptions());
|
||||
iterator->SeekToFirst();
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
ASSERT_TRUE(iterator->Valid());
|
||||
ASSERT_TRUE(keys[i] == iterator->key());
|
||||
ASSERT_TRUE(vals[i] == iterator->value());
|
||||
iterator->Next();
|
||||
}
|
||||
ASSERT_TRUE(!iterator->Valid());
|
||||
delete iterator;
|
||||
|
||||
// TEST_FlushMemTable() is not supported in ROCKSDB_LITE
|
||||
#ifndef ROCKSDB_LITE
|
||||
DBImpl* dbi = reinterpret_cast<DBImpl*>(db);
|
||||
ASSERT_OK(dbi->TEST_FlushMemTable());
|
||||
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
std::string res;
|
||||
ASSERT_OK(db->Get(ReadOptions(), keys[i], &res));
|
||||
ASSERT_TRUE(res == vals[i]);
|
||||
}
|
||||
#endif // ROCKSDB_LITE
|
||||
|
||||
delete db;
|
||||
}
|
||||
|
||||
TEST_F(MockEnvTest, FakeSleeping) {
|
||||
int64_t now = 0;
|
||||
auto s = env_->GetCurrentTime(&now);
|
||||
|
||||
+6
-11
@@ -17,11 +17,12 @@
|
||||
#include <inttypes.h>
|
||||
#include <limits>
|
||||
|
||||
#include "db/writebuffer.h"
|
||||
#include "rocksdb/cache.h"
|
||||
#include "rocksdb/compaction_filter.h"
|
||||
#include "rocksdb/comparator.h"
|
||||
#include "rocksdb/delete_scheduler.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "rocksdb/sst_file_manager.h"
|
||||
#include "rocksdb/memtablerep.h"
|
||||
#include "rocksdb/merge_operator.h"
|
||||
#include "rocksdb/slice.h"
|
||||
@@ -213,7 +214,7 @@ DBOptions::DBOptions()
|
||||
paranoid_checks(true),
|
||||
env(Env::Default()),
|
||||
rate_limiter(nullptr),
|
||||
sst_file_manager(nullptr),
|
||||
delete_scheduler(nullptr),
|
||||
info_log(nullptr),
|
||||
#ifdef NDEBUG
|
||||
info_log_level(INFO_LEVEL),
|
||||
@@ -229,7 +230,6 @@ DBOptions::DBOptions()
|
||||
db_log_dir(""),
|
||||
wal_dir(""),
|
||||
delete_obsolete_files_period_micros(6ULL * 60 * 60 * 1000000),
|
||||
base_background_compactions(-1),
|
||||
max_background_compactions(1),
|
||||
max_subcompactions(1),
|
||||
max_background_flushes(1),
|
||||
@@ -282,7 +282,7 @@ DBOptions::DBOptions(const Options& options)
|
||||
paranoid_checks(options.paranoid_checks),
|
||||
env(options.env),
|
||||
rate_limiter(options.rate_limiter),
|
||||
sst_file_manager(options.sst_file_manager),
|
||||
delete_scheduler(options.delete_scheduler),
|
||||
info_log(options.info_log),
|
||||
info_log_level(options.info_log_level),
|
||||
max_open_files(options.max_open_files),
|
||||
@@ -296,7 +296,6 @@ DBOptions::DBOptions(const Options& options)
|
||||
wal_dir(options.wal_dir),
|
||||
delete_obsolete_files_period_micros(
|
||||
options.delete_obsolete_files_period_micros),
|
||||
base_background_compactions(options.base_background_compactions),
|
||||
max_background_compactions(options.max_background_compactions),
|
||||
max_subcompactions(options.max_subcompactions),
|
||||
max_background_flushes(options.max_background_flushes),
|
||||
@@ -385,8 +384,6 @@ void DBOptions::Dump(Logger* log) const {
|
||||
table_cache_numshardbits);
|
||||
Header(log, " Options.delete_obsolete_files_period_micros: %" PRIu64,
|
||||
delete_obsolete_files_period_micros);
|
||||
Header(log, " Options.base_background_compactions: %d",
|
||||
base_background_compactions);
|
||||
Header(log, " Options.max_background_compactions: %d",
|
||||
max_background_compactions);
|
||||
Header(log, " Options.max_subcompactions: %" PRIu32,
|
||||
@@ -437,9 +434,8 @@ void DBOptions::Dump(Logger* log) const {
|
||||
use_adaptive_mutex);
|
||||
Header(log, " Options.rate_limiter: %p",
|
||||
rate_limiter.get());
|
||||
Header(
|
||||
log, " Options.sst_file_manager.rate_bytes_per_sec: %" PRIi64,
|
||||
sst_file_manager ? sst_file_manager->GetDeleteRateBytesPerSecond() : 0);
|
||||
Header(log, " Options.delete_scheduler.rate_bytes_per_sec: %" PRIi64,
|
||||
delete_scheduler ? delete_scheduler->GetRateBytesPerSecond() : 0);
|
||||
Header(log, " Options.bytes_per_sync: %" PRIu64,
|
||||
bytes_per_sync);
|
||||
Header(log, " Options.wal_bytes_per_sync: %" PRIu64,
|
||||
@@ -656,7 +652,6 @@ Options::PrepareForBulkLoad()
|
||||
// to L1. This is helpful so that all files that are
|
||||
// input to the manual compaction are all at L0.
|
||||
max_background_compactions = 2;
|
||||
base_background_compactions = 2;
|
||||
|
||||
// The compaction would create large files in L1.
|
||||
target_file_size_base = 256 * 1024 * 1024;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
#include <math.h>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include "rocksdb/options.h"
|
||||
|
||||
@@ -27,7 +26,7 @@ CompactionStyle PickCompactionStyle(size_t write_buffer_size,
|
||||
// Otherwise, calculate a score based on threshold and expected value of
|
||||
// two styles, weighing reads 4X important than writes.
|
||||
int expected_levels = static_cast<int>(ceil(
|
||||
std::log(target_db_size / write_buffer_size) / std::log(kBytesForLevelMultiplier)));
|
||||
::log(target_db_size / write_buffer_size) / ::log(kBytesForLevelMultiplier)));
|
||||
|
||||
int expected_max_files_universal =
|
||||
static_cast<int>(ceil(log2(target_db_size / write_buffer_size)));
|
||||
@@ -118,8 +117,8 @@ void OptimizeForLevel(int read_amplification_threshold,
|
||||
int write_amplification_threshold,
|
||||
uint64_t target_db_size, Options* options) {
|
||||
int expected_levels_one_level0_file =
|
||||
static_cast<int>(ceil(std::log(target_db_size / options->write_buffer_size) /
|
||||
std::log(kBytesForLevelMultiplier)));
|
||||
static_cast<int>(ceil(::log(target_db_size / options->write_buffer_size) /
|
||||
::log(kBytesForLevelMultiplier)));
|
||||
|
||||
int level0_stop_writes_trigger =
|
||||
read_amplification_threshold - expected_levels_one_level0_file;
|
||||
|
||||
@@ -208,7 +208,7 @@ static std::unordered_map<std::string, OptionTypeInfo> db_options_type_info = {
|
||||
{offsetof(struct DBOptions, random_access_max_buffer_size),
|
||||
OptionType::kSizeT, OptionVerificationType::kNormal}},
|
||||
{"writable_file_max_buffer_size",
|
||||
{offsetof(struct DBOptions, writable_file_max_buffer_size),
|
||||
{offsetof(struct DBOptions, writable_file_max_buffer_size),
|
||||
OptionType::kSizeT, OptionVerificationType::kNormal}},
|
||||
{"use_adaptive_mutex",
|
||||
{offsetof(struct DBOptions, use_adaptive_mutex), OptionType::kBoolean,
|
||||
@@ -219,9 +219,6 @@ static std::unordered_map<std::string, OptionTypeInfo> db_options_type_info = {
|
||||
{"max_background_compactions",
|
||||
{offsetof(struct DBOptions, max_background_compactions), OptionType::kInt,
|
||||
OptionVerificationType::kNormal}},
|
||||
{"base_background_compactions",
|
||||
{offsetof(struct DBOptions, base_background_compactions), OptionType::kInt,
|
||||
OptionVerificationType::kNormal}},
|
||||
{"max_background_flushes",
|
||||
{offsetof(struct DBOptions, max_background_flushes), OptionType::kInt,
|
||||
OptionVerificationType::kNormal}},
|
||||
@@ -486,9 +483,6 @@ static std::unordered_map<std::string,
|
||||
{"block_restart_interval",
|
||||
{offsetof(struct BlockBasedTableOptions, block_restart_interval),
|
||||
OptionType::kInt, OptionVerificationType::kNormal}},
|
||||
{"index_block_restart_interval",
|
||||
{offsetof(struct BlockBasedTableOptions, index_block_restart_interval),
|
||||
OptionType::kInt, OptionVerificationType::kNormal}},
|
||||
{"filter_policy",
|
||||
{offsetof(struct BlockBasedTableOptions, filter_policy),
|
||||
OptionType::kFilterPolicy, OptionVerificationType::kByName}},
|
||||
@@ -496,7 +490,7 @@ static std::unordered_map<std::string,
|
||||
{offsetof(struct BlockBasedTableOptions, whole_key_filtering),
|
||||
OptionType::kBoolean, OptionVerificationType::kNormal}},
|
||||
{"skip_table_builder_flush",
|
||||
{offsetof(struct BlockBasedTableOptions, skip_table_builder_flush),
|
||||
{offsetof(struct BlockBasedTableOptions, skip_table_builder_flush),
|
||||
OptionType::kBoolean, OptionVerificationType::kNormal}},
|
||||
{"format_version",
|
||||
{offsetof(struct BlockBasedTableOptions, format_version),
|
||||
|
||||
Loaded 100 of 131 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user