mirror of
https://github.com/facebook/rocksdb.git
synced 2026-11-06 11:02:36 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9adcef7ef8 | ||
|
|
664ad1c001 | ||
|
|
0400fb91e6 | ||
|
|
dd81eae663 | ||
|
|
61720850f6 | ||
|
|
e86f6eea0a | ||
|
|
b1845f43e7 | ||
|
|
958b4c9117 | ||
|
|
385412b6c0 | ||
|
|
e38e83169a | ||
|
|
f2a0fa2640 | ||
|
|
5de4fff167 | ||
|
|
9f33284d23 | ||
|
|
fb6f3b6771 | ||
|
|
b4242884d8 | ||
|
|
96687f030c | ||
|
|
3327adcc72 | ||
|
|
f63f26f842 | ||
|
|
46e923f671 | ||
|
|
b623dca531 | ||
|
|
6189230202 | ||
|
|
10a12b2a6f | ||
|
|
915c90ec0e | ||
|
|
b27c79a010 | ||
|
|
70f7fc3250 | ||
|
|
2955407c3a | ||
|
|
6e0597951e | ||
|
|
8c1f5c254f | ||
|
|
0ccaba2a05 | ||
|
|
4646cd45c4 | ||
|
|
2d6abcade4 | ||
|
|
0b129d1f7d | ||
|
|
58ef1ca899 | ||
|
|
13712712de | ||
|
|
ab8129ab8a | ||
|
|
87f35fbd3e | ||
|
|
9e58371114 | ||
|
|
1d4dc5eb22 | ||
|
|
b54951489c | ||
|
|
e8727ff6e0 | ||
|
|
a6e1cf9d20 | ||
|
|
ded1d5a1af | ||
|
|
dc0bbf78f7 | ||
|
|
b634fd7162 | ||
|
|
22f277e034 | ||
|
|
7e62c5d67a | ||
|
|
2014cdf2d0 | ||
|
|
459e00b365 | ||
|
|
49412d93e2 | ||
|
|
5a8e732594 | ||
|
|
f2e68d2bec | ||
|
|
b07369836e | ||
|
|
f3dc93bcf1 | ||
|
|
30a6d4e3ed | ||
|
|
6d29d8b3fa | ||
|
|
1530f38baa | ||
|
|
2b621c1f83 | ||
|
|
71acb4c122 | ||
|
|
ebbce5b10d | ||
|
|
fa586740e3 | ||
|
|
4623a5521f | ||
|
|
6df24fcffc | ||
|
|
8a1c34903c | ||
|
|
48fc484950 | ||
|
|
1265ed7abb | ||
|
|
95c5e2dc6e | ||
|
|
8d7edd5908 | ||
|
|
b6f6b73a9c |
No files matched your search
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"project_id" : "rocksdb",
|
||||
"conduit_uri" : "https://phabricator.fb.com/api/",
|
||||
"copyright_holder" : "Facebook",
|
||||
"load" : [
|
||||
"arcanist_util"
|
||||
],
|
||||
"lint.engine" : "FacebookFbcodeLintEngine",
|
||||
"lint.engine.single.linter" : "FbcodeCppLinter",
|
||||
"unit.engine" : "FacebookFbcodeUnitTestEngine",
|
||||
"arcanist_configuration" : "FacebookArcanistConfiguration",
|
||||
"base" : "git:HEAD^, hg:.^",
|
||||
"git.default-relative-commit" : "HEAD^",
|
||||
"git:arc.feature.start.default" : "origin/master",
|
||||
"arc.feature.start.default" : "master",
|
||||
"history.immutable" : false
|
||||
}
|
||||
+2
-3
@@ -31,7 +31,6 @@ build/
|
||||
ldb
|
||||
manifest_dump
|
||||
sst_dump
|
||||
blob_dump
|
||||
column_aware_encoding_exp
|
||||
util/build_version.cc
|
||||
build_tools/VALGRIND_LOGS/
|
||||
@@ -39,9 +38,9 @@ coverage/COVERAGE_REPORT
|
||||
.gdbhistory
|
||||
.gdb_history
|
||||
package/
|
||||
.phutil_module_cache
|
||||
unity.a
|
||||
tags
|
||||
etags
|
||||
rocksdb_dump
|
||||
rocksdb_undump
|
||||
db_test2
|
||||
@@ -60,7 +59,7 @@ rocksdb.h
|
||||
unity.cc
|
||||
java/crossbuild/.vagrant
|
||||
.vagrant/
|
||||
java/**/*.asc
|
||||
java/**.asc
|
||||
java/javadoc
|
||||
|
||||
scan_build_report/
|
||||
|
||||
+25
-34
@@ -7,7 +7,6 @@ os:
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
osx_image: xcode8.3
|
||||
jdk:
|
||||
- oraclejdk7
|
||||
cache:
|
||||
@@ -16,55 +15,47 @@ cache:
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages: ['zlib1g-dev', 'libbz2-dev', 'libsnappy-dev', 'curl', 'libgflags-dev', 'mingw-w64']
|
||||
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6']
|
||||
packages: ['clang-3.6' , 'g++-6', 'zlib1g-dev', 'libbz2-dev', 'libsnappy-dev', 'curl', 'libgflags-dev']
|
||||
env:
|
||||
- TEST_GROUP=platform_dependent # 16-18 minutes
|
||||
- TEST_GROUP=1 # 33-35 minutes
|
||||
- TEST_GROUP=2 # 30-32 minutes
|
||||
- TEST_GROUP=platform_dependent1
|
||||
- TEST_GROUP=platform_dependent2
|
||||
- TEST_GROUP=platform_dependent3
|
||||
- TEST_GROUP=1
|
||||
- TEST_GROUP=2
|
||||
# Run java tests
|
||||
- JOB_NAME=java_test # 4-11 minutes
|
||||
- JOB_NAME=java_test
|
||||
# Build ROCKSDB_LITE
|
||||
- JOB_NAME=lite_build # 3-4 minutes
|
||||
- JOB_NAME=lite_build
|
||||
# Build examples
|
||||
- JOB_NAME=examples # 5-7 minutes
|
||||
- JOB_NAME=cmake # 3-5 minutes
|
||||
- JOB_NAME=cmake-mingw # 3 minutes
|
||||
- JOB_NAME=examples
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
- os: osx
|
||||
env: TEST_GROUP=1
|
||||
- os: osx
|
||||
env: TEST_GROUP=2
|
||||
- os : osx
|
||||
env: JOB_NAME=cmake-mingw
|
||||
- os : linux
|
||||
compiler: clang
|
||||
- os : osx
|
||||
compiler: gcc
|
||||
|
||||
# https://docs.travis-ci.com/user/caching/#ccache-cache
|
||||
install:
|
||||
- if [ "${TRAVIS_OS_NAME}" == osx ]; then
|
||||
brew install ccache;
|
||||
PATH=$PATH:/usr/local/opt/ccache/libexec;
|
||||
fi
|
||||
|
||||
before_script:
|
||||
# Increase the maximum number of open file descriptors, since some tests use
|
||||
# more FDs than the default limit.
|
||||
- ulimit -n 8192
|
||||
- if [[ "${TRAVIS_OS_NAME}" == 'linux' && "${CXX}" == 'clang++' ]]; then CXX=clang++-3.6; fi
|
||||
# test one linux g++ build with g++-6
|
||||
- if [[ "${TRAVIS_OS_NAME}" == 'linux' && "${CXX}" == 'g++' && "${JOB_NAME}" == 'unittests' ]]; then CXX=g++-6; fi
|
||||
# Limit the maximum number of open file descriptors to 8192
|
||||
- ulimit -n 8192 || true
|
||||
|
||||
script:
|
||||
- ${CXX} --version
|
||||
- if [ "${TEST_GROUP}" == 'platform_dependent' ]; then ccache -C && OPT=-DTRAVIS V=1 ROCKSDBTESTS_END=db_block_cache_test make -j4 all_but_some_tests check_some; fi
|
||||
- if [ "${TEST_GROUP}" == '1' ]; then OPT=-DTRAVIS V=1 ROCKSDBTESTS_START=db_block_cache_test ROCKSDBTESTS_END=comparator_db_test make -j4 check_some; fi
|
||||
- if [ "${TEST_GROUP}" == '2' ]; then OPT=-DTRAVIS V=1 ROCKSDBTESTS_START=comparator_db_test make -j4 check_some; fi
|
||||
- if [ "${JOB_NAME}" == 'java_test' ]; then OPT=-DTRAVIS V=1 make clean jclean && make rocksdbjava jtest; fi
|
||||
- if [ "${JOB_NAME}" == 'lite_build' ]; then OPT="-DTRAVIS -DROCKSDB_LITE" V=1 make -j4 static_lib tools; fi
|
||||
- if [ "${JOB_NAME}" == 'examples' ]; then OPT=-DTRAVIS V=1 make -j4 static_lib; cd examples; make -j4; fi
|
||||
- if [ "${JOB_NAME}" == 'cmake' ]; then mkdir build && cd build && cmake .. && make -j4 rocksdb; fi
|
||||
- if [ "${JOB_NAME}" == 'cmake-mingw' ]; then mkdir build && cd build && cmake .. -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ -DCMAKE_SYSTEM_NAME=Windows && make -j4 rocksdb; fi
|
||||
- if [[ "${TEST_GROUP}" == 'platform_dependent1' ]]; then OPT=-DTRAVIS V=1 ROCKSDBTESTS_END=external_sst_file_basic_test make -j4 check_some; fi
|
||||
- if [[ "${TEST_GROUP}" == 'platform_dependent2' ]]; then OPT=-DTRAVIS V=1 ROCKSDBTESTS_START=external_sst_file_basic_test ROCKSDBTESTS_END=checkpoint_test make -j4 check_some; fi
|
||||
- if [[ "${TEST_GROUP}" == 'platform_dependent3' ]]; then OPT=-DTRAVIS V=1 ROCKSDBTESTS_START=checkpoint_test ROCKSDBTESTS_END=db_block_cache_test make -j4 check_some; fi
|
||||
- if [[ "${TEST_GROUP}" == '1' ]]; then OPT=-DTRAVIS V=1 ROCKSDBTESTS_START=db_block_cache_test ROCKSDBTESTS_END=comparator_db_test make -j4 check_some; fi
|
||||
- if [[ "${TEST_GROUP}" == '2' ]]; then OPT=-DTRAVIS V=1 ROCKSDBTESTS_START=comparator_db_test make -j4 check_some; fi
|
||||
- if [[ "${JOB_NAME}" == 'java_test' ]]; then OPT=-DTRAVIS V=1 make clean jclean rocksdbjava jtest; fi
|
||||
- if [[ "${JOB_NAME}" == 'lite_build' ]]; then OPT="-DTRAVIS -DROCKSDB_LITE" V=1 make -j4 static_lib; fi
|
||||
- if [[ "${JOB_NAME}" == 'examples' ]]; then OPT=-DTRAVIS V=1 make -j4 static_lib; cd examples; make -j4; fi
|
||||
notifications:
|
||||
email:
|
||||
- leveldb@fb.com
|
||||
|
||||
+114
-272
@@ -41,10 +41,10 @@ endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/")
|
||||
|
||||
option(WITH_JEMALLOC "build with JeMalloc" OFF)
|
||||
if(MSVC)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/thirdparty.inc)
|
||||
else()
|
||||
option(WITH_JEMALLOC "build with JeMalloc" OFF)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
# FreeBSD has jemaloc as default malloc
|
||||
# but it does not have all the jemalloc files in include/...
|
||||
@@ -55,8 +55,7 @@ else()
|
||||
add_definitions(-DROCKSDB_JEMALLOC -DJEMALLOC_NO_DEMANGLE)
|
||||
include_directories(${JEMALLOC_INCLUDE_DIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endif()
|
||||
option(WITH_SNAPPY "build with SNAPPY" OFF)
|
||||
if(WITH_SNAPPY)
|
||||
find_package(snappy REQUIRED)
|
||||
@@ -64,43 +63,11 @@ else()
|
||||
include_directories(${SNAPPY_INCLUDE_DIR})
|
||||
list(APPEND THIRDPARTY_LIBS ${SNAPPY_LIBRARIES})
|
||||
endif()
|
||||
|
||||
option(WITH_ZLIB "build with zlib" OFF)
|
||||
if(WITH_ZLIB)
|
||||
find_package(zlib REQUIRED)
|
||||
add_definitions(-DZLIB)
|
||||
include_directories(${ZLIB_INCLUDE_DIR})
|
||||
list(APPEND THIRDPARTY_LIBS ${ZLIB_LIBRARIES})
|
||||
endif()
|
||||
|
||||
option(WITH_BZ2 "build with bzip2" OFF)
|
||||
if(WITH_BZ2)
|
||||
find_package(bzip2 REQUIRED)
|
||||
add_definitions(-DBZIP2)
|
||||
include_directories(${BZIP2_INCLUDE_DIR})
|
||||
list(APPEND THIRDPARTY_LIBS ${BZIP2_LIBRARIES})
|
||||
endif()
|
||||
|
||||
option(WITH_LZ4 "build with lz4" OFF)
|
||||
if(WITH_LZ4)
|
||||
find_package(lz4 REQUIRED)
|
||||
add_definitions(-DLZ4)
|
||||
include_directories(${LZ4_INCLUDE_DIR})
|
||||
list(APPEND THIRDPARTY_LIBS ${LZ4_LIBRARIES})
|
||||
endif()
|
||||
|
||||
option(WITH_ZSTD "build with zstd" OFF)
|
||||
if(WITH_ZSTD)
|
||||
find_package(zstd REQUIRED)
|
||||
add_definitions(-DZSTD)
|
||||
include_directories(${ZSTD_INCLUDE_DIR})
|
||||
list(APPEND THIRDPARTY_LIBS ${ZSTD_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
execute_process(COMMAND powershell -noprofile -Command "Get-Date -format MM_dd_yyyy" OUTPUT_VARIABLE DATE)
|
||||
execute_process(COMMAND powershell -noprofile -Command "Get-Date -format HH:mm:ss" OUTPUT_VARIABLE TIME)
|
||||
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}")
|
||||
string(REGEX REPLACE "(..):(.....).*" " \\1:\\2" TIME "${TIME}")
|
||||
set(GIT_DATE_TIME "${DATE} ${TIME}")
|
||||
@@ -139,12 +106,14 @@ if(NOT WIN32)
|
||||
string(STRIP "${ROCKSDB_VERSION_MAJOR}" ROCKSDB_VERSION_MAJOR)
|
||||
endif()
|
||||
|
||||
option(WITH_MD_LIBRARY "build with MD" ON)
|
||||
if(WIN32 AND MSVC)
|
||||
if(WITH_MD_LIBRARY)
|
||||
set(RUNTIME_LIBRARY "MD")
|
||||
else()
|
||||
set(RUNTIME_LIBRARY "MT")
|
||||
if(WIN32)
|
||||
option(WITH_AVX2 "build with AVX2" ON)
|
||||
if(WITH_AVX2)
|
||||
if(MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX2")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx2")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -164,7 +133,7 @@ else()
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer")
|
||||
include(CheckCXXCompilerFlag)
|
||||
CHECK_CXX_COMPILER_FLAG("-momit-leaf-frame-pointer" HAVE_OMIT_LEAF_FRAME_POINTER)
|
||||
if(HAVE_OMIT_LEAF_FRAME_POINTER)
|
||||
@@ -173,49 +142,6 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(PORTABLE "build a portable binary" OFF)
|
||||
option(FORCE_SSE42 "force building with SSE4.2, even when PORTABLE=ON" OFF)
|
||||
if(PORTABLE)
|
||||
# MSVC does not need a separate compiler flag to enable SSE4.2; if nmmintrin.h
|
||||
# is available, it is available by default.
|
||||
if(FORCE_SSE42 AND NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.2")
|
||||
endif()
|
||||
else()
|
||||
if(MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX2")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
include(CheckCXXSourceCompiles)
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
#include <cstdint>
|
||||
#include <nmmintrin.h>
|
||||
int main() {
|
||||
volatile uint32_t x = _mm_crc32_u32(0, 0);
|
||||
}
|
||||
" HAVE_SSE42)
|
||||
if(HAVE_SSE42)
|
||||
add_definitions(-DHAVE_SSE42)
|
||||
elseif(FORCE_SSE42)
|
||||
message(FATAL_ERROR "FORCE_SSE42=ON but unable to compile with SSE4.2 enabled")
|
||||
endif()
|
||||
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
#if defined(_MSC_VER) && !defined(__thread)
|
||||
#define __thread __declspec(thread)
|
||||
#endif
|
||||
int main() {
|
||||
static __thread int tls;
|
||||
}
|
||||
" HAVE_THREAD_LOCAL)
|
||||
if(HAVE_THREAD_LOCAL)
|
||||
add_definitions(-DROCKSDB_SUPPORT_THREAD_LOCAL)
|
||||
endif()
|
||||
|
||||
option(FAIL_ON_WARNINGS "Treat compile warnings as errors" ON)
|
||||
if(FAIL_ON_WARNINGS)
|
||||
if(MSVC)
|
||||
@@ -227,6 +153,7 @@ endif()
|
||||
|
||||
option(WITH_ASAN "build with ASAN" OFF)
|
||||
if(WITH_ASAN)
|
||||
add_definitions(-DROCKSDB_TSAN_RUN)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
|
||||
@@ -238,6 +165,7 @@ endif()
|
||||
option(WITH_TSAN "build with TSAN" OFF)
|
||||
if(WITH_TSAN)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread -pie")
|
||||
add_definitions(-DROCKSDB_TSAN_RUN)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -fPIC")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread -fPIC")
|
||||
if(WITH_JEMALLOC)
|
||||
@@ -247,7 +175,6 @@ endif()
|
||||
|
||||
option(WITH_UBSAN "build with UBSAN" OFF)
|
||||
if(WITH_UBSAN)
|
||||
add_definitions(-DROCKSDB_UBSAN_RUN)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined")
|
||||
@@ -268,11 +195,11 @@ endif()
|
||||
if(MSVC)
|
||||
if((${OPTIMIZE_DEBUG} EQUAL 1))
|
||||
message(STATUS "Debug optimization is enabled")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "/Oxt /${RUNTIME_LIBRARY}d")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "/Oxt /MDd")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /RTC1 /Gm /${RUNTIME_LIBRARY}d")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /RTC1 /Gm /MDd")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oxt /Zp8 /Gm- /Gy /${RUNTIME_LIBRARY}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oxt /Zp8 /Gm- /Gy /MD")
|
||||
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG")
|
||||
@@ -325,7 +252,6 @@ endif()
|
||||
option(WITH_FALLOCATE "build with fallocate" ON)
|
||||
|
||||
if(WITH_FALLOCATE)
|
||||
set(CMAKE_REQUIRED_FLAGS ${CMAKE_C_FLAGS})
|
||||
include(CheckCSourceCompiles)
|
||||
CHECK_C_SOURCE_COMPILES("
|
||||
#include <fcntl.h>
|
||||
@@ -391,7 +317,6 @@ set(SOURCES
|
||||
db/internal_stats.cc
|
||||
db/log_reader.cc
|
||||
db/log_writer.cc
|
||||
db/malloc_stats.cc
|
||||
db/managed_iterator.cc
|
||||
db/memtable.cc
|
||||
db/memtable_list.cc
|
||||
@@ -413,16 +338,14 @@ set(SOURCES
|
||||
db/write_thread.cc
|
||||
env/env.cc
|
||||
env/env_chroot.cc
|
||||
env/env_encryption.cc
|
||||
env/env_hdfs.cc
|
||||
env/mock_env.cc
|
||||
memtable/alloc_tracker.cc
|
||||
env/memenv.cc
|
||||
memtable/hash_cuckoo_rep.cc
|
||||
memtable/hash_linklist_rep.cc
|
||||
memtable/hash_skiplist_rep.cc
|
||||
memtable/memtable_allocator.cc
|
||||
memtable/skiplistrep.cc
|
||||
memtable/vectorrep.cc
|
||||
memtable/write_buffer_manager.cc
|
||||
monitoring/histogram.cc
|
||||
monitoring/histogram_windowing.cc
|
||||
monitoring/instrumented_mutex.cc
|
||||
@@ -510,22 +433,17 @@ set(SOURCES
|
||||
utilities/backupable/backupable_db.cc
|
||||
utilities/blob_db/blob_db.cc
|
||||
utilities/blob_db/blob_db_impl.cc
|
||||
utilities/blob_db/blob_dump_tool.cc
|
||||
utilities/blob_db/blob_db_options_impl.cc
|
||||
utilities/blob_db/blob_file.cc
|
||||
utilities/blob_db/blob_log_reader.cc
|
||||
utilities/blob_db/blob_log_writer.cc
|
||||
utilities/blob_db/blob_log_format.cc
|
||||
utilities/blob_db/ttl_extractor.cc
|
||||
utilities/cassandra/cassandra_compaction_filter.cc
|
||||
utilities/cassandra/format.cc
|
||||
utilities/cassandra/merge_operator.cc
|
||||
utilities/checkpoint/checkpoint_impl.cc
|
||||
utilities/checkpoint/checkpoint.cc
|
||||
utilities/col_buf_decoder.cc
|
||||
utilities/col_buf_encoder.cc
|
||||
utilities/column_aware_encoding_util.cc
|
||||
utilities/compaction_filters/remove_emptyvalue_compactionfilter.cc
|
||||
utilities/date_tiered/date_tiered_db_impl.cc
|
||||
utilities/debug.cc
|
||||
utilities/document/document_db.cc
|
||||
utilities/document/json_document.cc
|
||||
utilities/document/json_document_builder.cc
|
||||
@@ -552,14 +470,13 @@ set(SOURCES
|
||||
utilities/spatialdb/spatial_db.cc
|
||||
utilities/table_properties_collectors/compact_on_deletion_collector.cc
|
||||
utilities/transactions/optimistic_transaction_db_impl.cc
|
||||
utilities/transactions/optimistic_transaction.cc
|
||||
utilities/transactions/optimistic_transaction_impl.cc
|
||||
utilities/transactions/transaction_base.cc
|
||||
utilities/transactions/pessimistic_transaction_db.cc
|
||||
utilities/transactions/transaction_db_impl.cc
|
||||
utilities/transactions/transaction_db_mutex_impl.cc
|
||||
utilities/transactions/pessimistic_transaction.cc
|
||||
utilities/transactions/transaction_impl.cc
|
||||
utilities/transactions/transaction_lock_mgr.cc
|
||||
utilities/transactions/transaction_util.cc
|
||||
utilities/transactions/write_prepared_txn.cc
|
||||
utilities/ttl/db_ttl_impl.cc
|
||||
utilities/write_batch_with_index/write_batch_with_index.cc
|
||||
utilities/write_batch_with_index/write_batch_with_index_internal.cc
|
||||
@@ -574,12 +491,6 @@ if(WIN32)
|
||||
port/win/win_logger.cc
|
||||
port/win/win_thread.cc
|
||||
port/win/xpress_win.cc)
|
||||
|
||||
if(WITH_JEMALLOC)
|
||||
list(APPEND SOURCES
|
||||
port/win/win_jemalloc.cc)
|
||||
endif()
|
||||
|
||||
else()
|
||||
list(APPEND SOURCES
|
||||
port/port_posix.cc
|
||||
@@ -587,14 +498,16 @@ else()
|
||||
env/io_posix.cc)
|
||||
endif()
|
||||
|
||||
set(ROCKSDB_STATIC_LIB rocksdb${ARTIFACT_SUFFIX})
|
||||
set(ROCKSDB_SHARED_LIB rocksdb-shared${ARTIFACT_SUFFIX})
|
||||
set(ROCKSDB_IMPORT_LIB ${ROCKSDB_SHARED_LIB})
|
||||
if(WIN32)
|
||||
set(SYSTEM_LIBS ${SYSTEM_LIBS} Shlwapi.lib Rpcrt4.lib)
|
||||
set(ROCKSDB_STATIC_LIB rocksdblib${ARTIFACT_SUFFIX})
|
||||
set(ROCKSDB_IMPORT_LIB rocksdb${ARTIFACT_SUFFIX})
|
||||
set(LIBS ${ROCKSDB_STATIC_LIB} ${THIRDPARTY_LIBS} ${SYSTEM_LIBS})
|
||||
else()
|
||||
set(SYSTEM_LIBS ${CMAKE_THREAD_LIBS_INIT})
|
||||
set(SYSTEM_LIBS ${CMAKE_THREAD_LIBS_INIT} rt)
|
||||
set(ROCKSDB_STATIC_LIB rocksdb${ARTIFACT_SUFFIX})
|
||||
set(ROCKSDB_SHARED_LIB rocksdb-shared)
|
||||
set(ROCKSDB_IMPORT_LIB ${ROCKSDB_SHARED_LIB})
|
||||
set(LIBS ${ROCKSDB_SHARED_LIB} ${THIRDPARTY_LIBS} ${SYSTEM_LIBS})
|
||||
|
||||
add_library(${ROCKSDB_SHARED_LIB} SHARED ${SOURCES})
|
||||
@@ -641,72 +554,7 @@ else()
|
||||
message(STATUS "JNI library is disabled")
|
||||
endif()
|
||||
|
||||
# Installation and packaging
|
||||
if(WIN32)
|
||||
option(ROCKSDB_INSTALL_ON_WINDOWS "Enable install target on Windows" OFF)
|
||||
endif()
|
||||
if(NOT WIN32 OR ROCKSDB_INSTALL_ON_WINDOWS)
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
# Change default installation prefix on Linux to /usr
|
||||
set(CMAKE_INSTALL_PREFIX /usr CACHE PATH "Install path prefix, prepended onto install directories." FORCE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
set(package_config_destination ${CMAKE_INSTALL_LIBDIR}/cmake/rocksdb)
|
||||
|
||||
configure_package_config_file(
|
||||
${CMAKE_SOURCE_DIR}/cmake/RocksDBConfig.cmake.in RocksDBConfig.cmake
|
||||
INSTALL_DESTINATION ${package_config_destination}
|
||||
)
|
||||
|
||||
write_basic_package_version_file(
|
||||
RocksDBConfigVersion.cmake
|
||||
VERSION ${ROCKSDB_VERSION}
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
|
||||
install(DIRECTORY include/rocksdb COMPONENT devel DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
|
||||
install(
|
||||
TARGETS ${ROCKSDB_STATIC_LIB}
|
||||
EXPORT RocksDBTargets
|
||||
COMPONENT devel
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS ${ROCKSDB_SHARED_LIB}
|
||||
EXPORT RocksDBTargets
|
||||
COMPONENT runtime
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
)
|
||||
|
||||
install(
|
||||
EXPORT RocksDBTargets
|
||||
COMPONENT devel
|
||||
DESTINATION ${package_config_destination}
|
||||
NAMESPACE RocksDB::
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/RocksDBConfig.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/RocksDBConfigVersion.cmake
|
||||
COMPONENT devel
|
||||
DESTINATION ${package_config_destination}
|
||||
)
|
||||
endif()
|
||||
|
||||
option(WITH_TESTS "build with tests" ON)
|
||||
if(WITH_TESTS)
|
||||
set(TESTS
|
||||
set(TESTS
|
||||
cache/cache_test.cc
|
||||
cache/lru_cache_test.cc
|
||||
db/column_family_test.cc
|
||||
@@ -719,7 +567,6 @@ if(WITH_TESTS)
|
||||
db/corruption_test.cc
|
||||
db/cuckoo_table_db_test.cc
|
||||
db/db_basic_test.cc
|
||||
db/db_blob_index_test.cc
|
||||
db/db_block_cache_test.cc
|
||||
db/db_bloom_filter_test.cc
|
||||
db/db_compaction_filter_test.cc
|
||||
@@ -744,7 +591,6 @@ if(WITH_TESTS)
|
||||
db/db_test2.cc
|
||||
db/db_universal_compaction_test.cc
|
||||
db/db_wal_test.cc
|
||||
db/db_write_test.cc
|
||||
db/dbformat_test.cc
|
||||
db/deletefile_test.cc
|
||||
db/external_sst_file_basic_test.cc
|
||||
@@ -777,7 +623,6 @@ if(WITH_TESTS)
|
||||
env/mock_env_test.cc
|
||||
memtable/inlineskiplist_test.cc
|
||||
memtable/skiplist_test.cc
|
||||
memtable/write_buffer_manager_test.cc
|
||||
monitoring/histogram_test.cc
|
||||
monitoring/iostats_context_test.cc
|
||||
monitoring/statistics_test.cc
|
||||
@@ -785,7 +630,6 @@ if(WITH_TESTS)
|
||||
options/options_test.cc
|
||||
table/block_based_filter_block_test.cc
|
||||
table/block_test.cc
|
||||
table/cleanable_test.cc
|
||||
table/cuckoo_table_builder_test.cc
|
||||
table/cuckoo_table_reader_test.cc
|
||||
table/full_filter_block_test.cc
|
||||
@@ -805,7 +649,6 @@ if(WITH_TESTS)
|
||||
util/event_logger_test.cc
|
||||
util/file_reader_writer_test.cc
|
||||
util/filelock_test.cc
|
||||
util/hash_test.cc
|
||||
util/heap_test.cc
|
||||
util/rate_limiter_test.cc
|
||||
util/slice_transform_test.cc
|
||||
@@ -813,11 +656,6 @@ if(WITH_TESTS)
|
||||
util/thread_list_test.cc
|
||||
util/thread_local_test.cc
|
||||
utilities/backupable/backupable_db_test.cc
|
||||
utilities/blob_db/blob_db_test.cc
|
||||
utilities/cassandra/cassandra_functional_test.cc
|
||||
utilities/cassandra/cassandra_format_test.cc
|
||||
utilities/cassandra/cassandra_row_merge_test.cc
|
||||
utilities/cassandra/cassandra_serialize_test.cc
|
||||
utilities/checkpoint/checkpoint_test.cc
|
||||
utilities/column_aware_encoding_test.cc
|
||||
utilities/date_tiered/date_tiered_test.cc
|
||||
@@ -834,94 +672,98 @@ if(WITH_TESTS)
|
||||
utilities/persistent_cache/persistent_cache_test.cc
|
||||
utilities/redis/redis_lists_test.cc
|
||||
utilities/spatialdb/spatial_db_test.cc
|
||||
utilities/simulator_cache/sim_cache_test.cc
|
||||
utilities/table_properties_collectors/compact_on_deletion_collector_test.cc
|
||||
utilities/transactions/optimistic_transaction_test.cc
|
||||
utilities/transactions/transaction_test.cc
|
||||
utilities/ttl/ttl_test.cc
|
||||
utilities/write_batch_with_index/write_batch_with_index_test.cc
|
||||
)
|
||||
if(WITH_LIBRADOS)
|
||||
list(APPEND TESTS utilities/env_librados_test.cc)
|
||||
endif()
|
||||
)
|
||||
if(WITH_LIBRADOS)
|
||||
list(APPEND TESTS utilities/env_librados_test.cc)
|
||||
endif()
|
||||
|
||||
set(BENCHMARKS
|
||||
cache/cache_bench.cc
|
||||
memtable/memtablerep_bench.cc
|
||||
tools/db_bench.cc
|
||||
table/table_reader_bench.cc
|
||||
utilities/column_aware_encoding_exp.cc
|
||||
utilities/persistent_cache/hash_table_bench.cc)
|
||||
add_library(testharness OBJECT util/testharness.cc)
|
||||
foreach(sourcefile ${BENCHMARKS})
|
||||
set(BENCHMARKS
|
||||
cache/cache_bench.cc
|
||||
memtable/memtablerep_bench.cc
|
||||
tools/db_bench.cc
|
||||
table/table_reader_bench.cc
|
||||
utilities/column_aware_encoding_exp.cc
|
||||
utilities/persistent_cache/hash_table_bench.cc)
|
||||
add_library(testharness OBJECT util/testharness.cc)
|
||||
foreach(sourcefile ${BENCHMARKS})
|
||||
get_filename_component(exename ${sourcefile} NAME_WE)
|
||||
add_executable(${exename}${ARTIFACT_SUFFIX} ${sourcefile}
|
||||
$<TARGET_OBJECTS:testharness>)
|
||||
target_link_libraries(${exename}${ARTIFACT_SUFFIX} gtest ${LIBS})
|
||||
endforeach(sourcefile ${BENCHMARKS})
|
||||
|
||||
# For test util library that is build only in DEBUG mode
|
||||
# and linked to tests. Add test only code that is not #ifdefed for Release here.
|
||||
set(TESTUTIL_SOURCE
|
||||
db/db_test_util.cc
|
||||
env/mock_env.cc
|
||||
monitoring/thread_status_updater_debug.cc
|
||||
table/mock_table.cc
|
||||
util/fault_injection_test_env.cc
|
||||
)
|
||||
# test utilities are only build in debug
|
||||
enable_testing()
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
|
||||
set(TESTUTILLIB testutillib${ARTIFACT_SUFFIX})
|
||||
add_library(${TESTUTILLIB} STATIC ${TESTUTIL_SOURCE})
|
||||
if(MSVC)
|
||||
set_target_properties(${TESTUTILLIB} PROPERTIES COMPILE_FLAGS "/Fd${CMAKE_CFG_INTDIR}/testutillib${ARTIFACT_SUFFIX}.pdb")
|
||||
endif()
|
||||
set_target_properties(${TESTUTILLIB}
|
||||
PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD_RELEASE 1
|
||||
EXCLUDE_FROM_DEFAULT_BUILD_MINRELEASE 1
|
||||
EXCLUDE_FROM_DEFAULT_BUILD_RELWITHDEBINFO 1
|
||||
)
|
||||
|
||||
# Tests are excluded from Release builds
|
||||
set(TEST_EXES ${TESTS})
|
||||
|
||||
foreach(sourcefile ${TEST_EXES})
|
||||
get_filename_component(exename ${sourcefile} NAME_WE)
|
||||
add_executable(${exename}${ARTIFACT_SUFFIX} ${sourcefile}
|
||||
$<TARGET_OBJECTS:testharness>)
|
||||
target_link_libraries(${exename}${ARTIFACT_SUFFIX} gtest ${LIBS})
|
||||
endforeach(sourcefile ${BENCHMARKS})
|
||||
|
||||
# For test util library that is build only in DEBUG mode
|
||||
# and linked to tests. Add test only code that is not #ifdefed for Release here.
|
||||
set(TESTUTIL_SOURCE
|
||||
db/db_test_util.cc
|
||||
monitoring/thread_status_updater_debug.cc
|
||||
table/mock_table.cc
|
||||
util/fault_injection_test_env.cc
|
||||
utilities/cassandra/test_utils.cc
|
||||
)
|
||||
# test utilities are only build in debug
|
||||
enable_testing()
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
|
||||
set(TESTUTILLIB testutillib${ARTIFACT_SUFFIX})
|
||||
add_library(${TESTUTILLIB} STATIC ${TESTUTIL_SOURCE})
|
||||
if(MSVC)
|
||||
set_target_properties(${TESTUTILLIB} PROPERTIES COMPILE_FLAGS "/Fd${CMAKE_CFG_INTDIR}/testutillib${ARTIFACT_SUFFIX}.pdb")
|
||||
endif()
|
||||
set_target_properties(${TESTUTILLIB}
|
||||
PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD_RELEASE 1
|
||||
EXCLUDE_FROM_DEFAULT_BUILD_MINRELEASE 1
|
||||
EXCLUDE_FROM_DEFAULT_BUILD_RELWITHDEBINFO 1
|
||||
)
|
||||
|
||||
# Tests are excluded from Release builds
|
||||
set(TEST_EXES ${TESTS})
|
||||
|
||||
foreach(sourcefile ${TEST_EXES})
|
||||
get_filename_component(exename ${sourcefile} NAME_WE)
|
||||
add_executable(${exename}${ARTIFACT_SUFFIX} ${sourcefile}
|
||||
$<TARGET_OBJECTS:testharness>)
|
||||
set_target_properties(${exename}${ARTIFACT_SUFFIX}
|
||||
PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD_RELEASE 1
|
||||
EXCLUDE_FROM_DEFAULT_BUILD_MINRELEASE 1
|
||||
EXCLUDE_FROM_DEFAULT_BUILD_RELWITHDEBINFO 1
|
||||
)
|
||||
target_link_libraries(${exename}${ARTIFACT_SUFFIX} testutillib${ARTIFACT_SUFFIX} gtest ${LIBS})
|
||||
if(NOT "${exename}" MATCHES "db_sanity_test")
|
||||
add_test(NAME ${exename} COMMAND ${exename}${ARTIFACT_SUFFIX})
|
||||
add_dependencies(check ${exename}${ARTIFACT_SUFFIX})
|
||||
endif()
|
||||
endforeach(sourcefile ${TEST_EXES})
|
||||
|
||||
# C executables must link to a shared object
|
||||
set(C_TESTS db/c_test.c)
|
||||
set(C_TEST_EXES ${C_TESTS})
|
||||
|
||||
foreach(sourcefile ${C_TEST_EXES})
|
||||
string(REPLACE ".c" "" exename ${sourcefile})
|
||||
string(REGEX REPLACE "^((.+)/)+" "" exename ${exename})
|
||||
add_executable(${exename}${ARTIFACT_SUFFIX} ${sourcefile})
|
||||
set_target_properties(${exename}${ARTIFACT_SUFFIX}
|
||||
PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD_RELEASE 1
|
||||
EXCLUDE_FROM_DEFAULT_BUILD_MINRELEASE 1
|
||||
EXCLUDE_FROM_DEFAULT_BUILD_RELWITHDEBINFO 1
|
||||
)
|
||||
target_link_libraries(${exename}${ARTIFACT_SUFFIX} ${ROCKSDB_IMPORT_LIB} testutillib${ARTIFACT_SUFFIX})
|
||||
set_target_properties(${exename}${ARTIFACT_SUFFIX}
|
||||
PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD_RELEASE 1
|
||||
EXCLUDE_FROM_DEFAULT_BUILD_MINRELEASE 1
|
||||
EXCLUDE_FROM_DEFAULT_BUILD_RELWITHDEBINFO 1
|
||||
)
|
||||
target_link_libraries(${exename}${ARTIFACT_SUFFIX} testutillib${ARTIFACT_SUFFIX} gtest ${LIBS})
|
||||
if(NOT "${exename}" MATCHES "db_sanity_test")
|
||||
add_test(NAME ${exename} COMMAND ${exename}${ARTIFACT_SUFFIX})
|
||||
add_dependencies(check ${exename}${ARTIFACT_SUFFIX})
|
||||
endforeach(sourcefile ${C_TEST_EXES})
|
||||
endif()
|
||||
endif()
|
||||
endforeach(sourcefile ${TEST_EXES})
|
||||
|
||||
option(WITH_TOOLS "build with tools" ON)
|
||||
if(WITH_TOOLS)
|
||||
add_subdirectory(tools)
|
||||
# C executables must link to a shared object
|
||||
set(C_TESTS db/c_test.c)
|
||||
set(C_TEST_EXES ${C_TESTS})
|
||||
|
||||
foreach(sourcefile ${C_TEST_EXES})
|
||||
string(REPLACE ".c" "" exename ${sourcefile})
|
||||
string(REGEX REPLACE "^((.+)/)+" "" exename ${exename})
|
||||
add_executable(${exename}${ARTIFACT_SUFFIX} ${sourcefile})
|
||||
set_target_properties(${exename}${ARTIFACT_SUFFIX}
|
||||
PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD_RELEASE 1
|
||||
EXCLUDE_FROM_DEFAULT_BUILD_MINRELEASE 1
|
||||
EXCLUDE_FROM_DEFAULT_BUILD_RELWITHDEBINFO 1
|
||||
)
|
||||
target_link_libraries(${exename}${ARTIFACT_SUFFIX} ${ROCKSDB_IMPORT_LIB} testutillib${ARTIFACT_SUFFIX})
|
||||
add_test(NAME ${exename} COMMAND ${exename}${ARTIFACT_SUFFIX})
|
||||
add_dependencies(check ${exename}${ARTIFACT_SUFFIX})
|
||||
endforeach(sourcefile ${C_TEST_EXES})
|
||||
add_subdirectory(tools)
|
||||
|
||||
# Installation and packaging for Linux
|
||||
if(NOT WIN32)
|
||||
install(TARGETS ${ROCKSDB_STATIC_LIB} COMPONENT devel ARCHIVE DESTINATION lib64)
|
||||
install(TARGETS ${ROCKSDB_SHARED_LIB} COMPONENT runtime DESTINATION lib64)
|
||||
install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/rocksdb/"
|
||||
COMPONENT devel
|
||||
DESTINATION include/rocksdb)
|
||||
set(CMAKE_INSTALL_PREFIX /usr)
|
||||
endif()
|
||||
@@ -1,8 +1,5 @@
|
||||
# RocksDB default options change log
|
||||
## Unreleased
|
||||
* delayed_write_rate takes the rate given by rate_limiter if not specified.
|
||||
|
||||
## 5.2
|
||||
* Change the default of delayed slowdown value to 16MB/s and further increase the L0 stop condition to 36 files.
|
||||
|
||||
## 5.0 (11/17/2016)
|
||||
|
||||
+45
-73
@@ -1,93 +1,64 @@
|
||||
# Rocksdb Change Log
|
||||
## 5.8.8 (12/6/2017)
|
||||
## 5.4.12 (08/21/2017)
|
||||
* Statistics::Reset() to reset user stats.
|
||||
|
||||
## 5.4.11 (08/17/2017)
|
||||
### Bug Fixes
|
||||
* Fix possible corruption to LSM structure when `DeleteFilesInRange()` deletes a subset of files spanned by a `DeleteRange()` marker.
|
||||
* Fix a bug in PosixWritableFile::Close()
|
||||
|
||||
## 5.8.7 (11/28/2017)
|
||||
## 5.4.10 (08/12/2017)
|
||||
### Bug Fixes
|
||||
* Fix IOError on WAL write doesn't propagate to write group follower
|
||||
|
||||
## 5.8.6 (11/20/2017)
|
||||
### Bug Fixes
|
||||
* Fixed aligned_alloc issues with Windows.
|
||||
|
||||
## 5.8.1 (10/23/2017)
|
||||
### New Features
|
||||
* Add a new db property "rocksdb.estimate-oldest-key-time" to return oldest data timestamp. The property is available only for FIFO compaction with compaction_options_fifo.allow_compaction = false.
|
||||
|
||||
## 5.8.0 (08/30/2017)
|
||||
### Public API Change
|
||||
* Users of `Statistics::getHistogramString()` will see fewer histogram buckets and different bucket endpoints.
|
||||
* `Slice::compare` and BytewiseComparator `Compare` no longer accept `Slice`s containing nullptr.
|
||||
* `Transaction::Get` and `Transaction::GetForUpdate` variants with `PinnableSlice` added.
|
||||
|
||||
### New Features
|
||||
* Add Iterator::Refresh(), which allows users to update the iterator state so that they can avoid some initialization costs of recreating iterators.
|
||||
* Replace dynamic_cast<> (except unit test) so people can choose to build with RTTI off. With make, release mode is by default built with -fno-rtti and debug mode is built without it. Users can override it by setting USE_RTTI=0 or 1.
|
||||
* Universal compactions including the bottom level can be executed in a dedicated thread pool. This alleviates head-of-line blocking in the compaction queue, which cause write stalling, particularly in multi-instance use cases. Users can enable this feature via `Env::SetBackgroundThreads(N, Env::Priority::BOTTOM)`, where `N > 0`.
|
||||
* Allow merge operator to be called even with a single merge operand during compactions, by appropriately overriding `MergeOperator::AllowSingleOperand`.
|
||||
* Add `DB::VerifyChecksum()`, which verifies the checksums in all SST files in a running DB.
|
||||
* Block-based table support for disabling checksums by setting `BlockBasedTableOptions::checksum = kNoChecksum`.
|
||||
|
||||
### Bug Fixes
|
||||
* Fix wrong latencies in `rocksdb.db.get.micros`, `rocksdb.db.write.micros`, and `rocksdb.sst.read.micros`.
|
||||
* Fix incorrect dropping of deletions during intra-L0 compaction.
|
||||
* Fix transient reappearance of keys covered by range deletions when memtable prefix bloom filter is enabled.
|
||||
* Fix potentially wrong file smallest key when range deletions separated by snapshot are written together.
|
||||
|
||||
## 5.7.0 (07/13/2017)
|
||||
### Public API Change
|
||||
* DB property "rocksdb.sstables" now prints keys in hex form.
|
||||
## 5.4.9 (07/20/2017)
|
||||
* Change license to Apache + GPLv2
|
||||
|
||||
### New Features
|
||||
* Measure estimated number of reads per file. The information can be accessed through DB::GetColumnFamilyMetaData or "rocksdb.sstables" DB property.
|
||||
* RateLimiter support for throttling background reads, or throttling the sum of background reads and writes. This can give more predictable I/O usage when compaction reads more data than it writes, e.g., due to lots of deletions.
|
||||
* [Experimental] FIFO compaction with TTL support. It can be enabled by setting CompactionOptionsFIFO.ttl > 0.
|
||||
* Introduce `EventListener::OnBackgroundError()` callback. Users can implement it to be notified of errors causing the DB to enter read-only mode, and optionally override them.
|
||||
* Partitioned Index/Filters exiting the experimental mode. To enable partitioned indexes set index_type to kTwoLevelIndexSearch and to further enable partitioned filters set partition_filters to true. To configure the partition size set metadata_block_size.
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
* Fix discarding empty compaction output files when `DeleteRange()` is used together with subcompactions.
|
||||
|
||||
## 5.6.0 (06/06/2017)
|
||||
### Public API Change
|
||||
* Scheduling flushes and compactions in the same thread pool is no longer supported by setting `max_background_flushes=0`. Instead, users can achieve this by configuring their high-pri thread pool to have zero threads.
|
||||
* Replace `Options::max_background_flushes`, `Options::max_background_compactions`, and `Options::base_background_compactions` all with `Options::max_background_jobs`, which automatically decides how many threads to allocate towards flush/compaction.
|
||||
* options.delayed_write_rate by default take the value of options.rate_limiter rate.
|
||||
* Replace global variable `IOStatsContext iostats_context` with `IOStatsContext* get_iostats_context()`; replace global variable `PerfContext perf_context` with `PerfContext* get_perf_context()`.
|
||||
|
||||
### New Features
|
||||
* Change ticker/histogram statistics implementations to use core-local storage. This improves aggregation speed compared to our previous thread-local approach, particularly for applications with many threads.
|
||||
* Users can pass a cache object to write buffer manager, so that they can cap memory usage for memtable and block cache using one single limit.
|
||||
* Flush will be triggered when 7/8 of the limit introduced by write_buffer_manager or db_write_buffer_size is triggered, so that the hard threshold is hard to hit.
|
||||
* Introduce WriteOptions.low_pri. If it is true, low priority writes will be throttled if the compaction is behind.
|
||||
* `DB::IngestExternalFile()` now supports ingesting files into a database containing range deletions.
|
||||
## 5.4.8 (07/13/2017)
|
||||
No change from 5.4.7.
|
||||
|
||||
## 5.4.7 (06/28/2017)
|
||||
### Bug Fixes
|
||||
* Shouldn't ignore return value of fsync() in flush.
|
||||
|
||||
## 5.5.0 (05/17/2017)
|
||||
## 5.4.6 (05/30/2017)
|
||||
### Bug Fixes
|
||||
* Fix db_bench with lite build.
|
||||
|
||||
## 5.4.5 (05/19/2017)
|
||||
### Bug Fixes
|
||||
* Facility for cross-building RocksJava using Docker.
|
||||
* Build and link with ZStd when creating the static RocksJava build.
|
||||
* Fix snprintf's usage to be cross-platform.
|
||||
* Fix build error with blob DB.
|
||||
* Fix readamp test type inconsistency.
|
||||
|
||||
## 5.4.4 (05/11/2017)
|
||||
### New Features
|
||||
* FIFO compaction to support Intra L0 compaction too with CompactionOptionsFIFO.allow_compaction=true.
|
||||
* DB::ResetStats() to reset internal stats.
|
||||
* Statistics::Reset() to reset user stats.
|
||||
* ldb add option --try_load_options, which will open DB with its own option file.
|
||||
* Introduce WriteBatch::PopSavePoint to pop the most recent save point explicitly.
|
||||
* Support dynamically change `max_open_files` option via SetDBOptions()
|
||||
* Added DB::CreateColumnFamilie() and DB::DropColumnFamilies() to bulk create/drop column families.
|
||||
* Add debugging function `GetAllKeyVersions` to see internal versions of a range of keys.
|
||||
* Support file ingestion with universal compaction style
|
||||
* Support file ingestion behind with option `allow_ingest_behind`
|
||||
* New option enable_pipelined_write which may improve write throughput in case writing from multiple threads and WAL enabled.
|
||||
|
||||
### Bug Fixes
|
||||
* Fix the bug that Direct I/O uses direct reads for non-SST file
|
||||
* Fix a manual / auto compaction data race.
|
||||
* Fix CentOS 5 cross-building of RocksJava.
|
||||
|
||||
## 5.4.3 (05/10/2017)
|
||||
### Bug Fixes
|
||||
* Fix memory alignment with logical sector size.
|
||||
* Fix alignment in ReadaheadRandomAccessFile.
|
||||
* Fix bias with read amplification stats (READ_AMP_ESTIMATE_USEFUL_BYTES and READ_AMP_TOTAL_READ_BYTES).
|
||||
|
||||
## 5.4.2 (05/08/2017)
|
||||
### Bug Fixes
|
||||
* Fix huge fallocate calls fail and make XFS unhappy.
|
||||
|
||||
## 5.4.1 (05/02/2017)
|
||||
### Bug Fxies
|
||||
* Fix WriteBatchWithIndex address use after scope error.
|
||||
* Fix WritableFile buffer size in direct IO.
|
||||
* Add prefetch to PosixRandomAccessFile in buffered io.
|
||||
* Fix PinnableSlice access invalid address when row cache is enabled.
|
||||
|
||||
## 5.4.0 (04/11/2017)
|
||||
### Public API Change
|
||||
* random_access_max_buffer_size no longer has any effect
|
||||
* Removed Env::EnableReadAhead(), Env::ShouldForwardRawRequest()
|
||||
* Support dynamically change `stats_dump_period_sec` option via SetDBOptions().
|
||||
* Added ReadOptions::max_skippable_internal_keys to set a threshold to fail a request as incomplete when too many keys are being skipped when using iterators.
|
||||
* DB::Get in place of std::string accepts PinnableSlice, which avoids the extra memcpy of value to std::string in most of cases.
|
||||
@@ -100,6 +71,7 @@
|
||||
* Memtable flush can be avoided during checkpoint creation if total log file size is smaller than a threshold specified by the user.
|
||||
* Introduce level-based L0->L0 compactions to reduce file count, so write delays are incurred less often.
|
||||
* (Experimental) Partitioning filters which creates an index on the partitions. The feature can be enabled by setting partition_filters when using kFullFilter. Currently the feature also requires two-level indexing to be enabled. Number of partitions is the same as the number of partitions for indexes, which is controlled by metadata_block_size.
|
||||
* DB::ResetStats() to reset internal stats.
|
||||
|
||||
## 5.3.0 (03/08/2017)
|
||||
### Public API Change
|
||||
@@ -326,7 +298,7 @@
|
||||
* Added a new way to report QPS from db_bench (check out --report_file and --report_interval_seconds)
|
||||
* Added a cache for individual rows. See DBOptions::row_cache for more info.
|
||||
* Several new features on EventListener (see include/rocksdb/listener.h):
|
||||
- OnCompationCompleted() now returns per-compaction job statistics, defined in include/rocksdb/compaction_job_stats.h.
|
||||
- OnCompationCompleted() now returns per-compaciton job statistics, defined in include/rocksdb/compaction_job_stats.h.
|
||||
- Added OnTableFileCreated() and OnTableFileDeleted().
|
||||
* Add compaction_options_universal.enable_trivial_move to true, to allow trivial move while performing universal compaction. Trivial move will happen only when all the input files are non overlapping.
|
||||
|
||||
|
||||
+14
-50
@@ -21,18 +21,15 @@ 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). SSE4.2 will thus be enabled automatically if your
|
||||
CPU supports it. To print a warning if your CPU does not support SSE4.2, build with
|
||||
`USE_SSE=1 make static_lib` or, if using CMake, `cmake -DFORCE_SSE42=ON`. If you want
|
||||
to build a portable binary, add `PORTABLE=1` before your make commands, like this:
|
||||
`PORTABLE=1 make static_lib`.
|
||||
(-march=native or the equivalent). If you want to build a portable binary, add 'PORTABLE=1' before
|
||||
your make commands, like this: `PORTABLE=1 make static_lib`. If you want to build a binary that
|
||||
makes use of SSE4, add 'USE_SSE=1' before your make commands, like this: `USE_SSE=1 make static_lib`.
|
||||
|
||||
## Dependencies
|
||||
|
||||
* You can link RocksDB with following compression libraries:
|
||||
- [zlib](http://www.zlib.net/) - a library for data compression.
|
||||
- [bzip2](http://www.bzip.org/) - a library for data compression.
|
||||
- [lz4](https://github.com/lz4/lz4) - a library for extremely fast data compression.
|
||||
- [snappy](http://google.github.io/snappy/) - a library for fast
|
||||
data compression.
|
||||
- [zstandard](http://www.zstd.net) - Fast real-time compression
|
||||
@@ -54,7 +51,6 @@ to build a portable binary, add `PORTABLE=1` before your make commands, like thi
|
||||
`sudo apt-get install libsnappy-dev`.
|
||||
* Install zlib. Try: `sudo apt-get install zlib1g-dev`.
|
||||
* Install bzip2: `sudo apt-get install libbz2-dev`.
|
||||
* Install lz4: `sudo apt-get install liblz4-dev`.
|
||||
* Install zstandard: `sudo apt-get install libzstd-dev`.
|
||||
|
||||
* **Linux - CentOS / RHEL**
|
||||
@@ -67,29 +63,26 @@ to build a portable binary, add `PORTABLE=1` before your make commands, like thi
|
||||
git checkout v2.0
|
||||
./configure && make && sudo make install
|
||||
|
||||
**Notice**: Once installed, please add the include path for gflags to your `CPATH` environment variable and the
|
||||
lib path to `LIBRARY_PATH`. If installed with default settings, the include path will be `/usr/local/include`
|
||||
and the lib path will be `/usr/local/lib`.
|
||||
**Notice**: Once installed, please add the include path for gflags to your CPATH env var and the
|
||||
lib path to LIBRARY_PATH. If installed with default settings, the lib will be /usr/local/lib
|
||||
and the include path will be /usr/local/include.
|
||||
|
||||
* Install snappy:
|
||||
|
||||
sudo yum install snappy snappy-devel
|
||||
wget https://github.com/google/snappy/releases/download/1.1.4/snappy-1.1.4.tar.gz
|
||||
tar -xzvf snappy-1.1.4.tar.gz
|
||||
cd snappy-1.1.4
|
||||
./configure && make && sudo make install
|
||||
|
||||
* Install zlib:
|
||||
|
||||
sudo yum install zlib zlib-devel
|
||||
sudo yum install zlib
|
||||
sudo yum install zlib-devel
|
||||
|
||||
* Install bzip2:
|
||||
|
||||
sudo yum install bzip2 bzip2-devel
|
||||
|
||||
* Install lz4:
|
||||
|
||||
sudo yum install lz4-devel
|
||||
|
||||
* Install ASAN (optional for debugging):
|
||||
|
||||
sudo yum install libasan
|
||||
sudo yum install bzip2
|
||||
sudo yum install bzip2-devel
|
||||
|
||||
* Install zstandard:
|
||||
|
||||
@@ -113,32 +106,3 @@ to build a portable binary, add `PORTABLE=1` before your make commands, like thi
|
||||
* **Windows**:
|
||||
* For building with MS Visual Studio 13 you will need Update 4 installed.
|
||||
* Read and follow the instructions at CMakeLists.txt
|
||||
* Or install via [vcpkg](https://github.com/microsoft/vcpkg)
|
||||
* run `vcpkg install rocksdb`
|
||||
|
||||
* **AIX 6.1**
|
||||
* Install AIX Toolbox rpms with gcc
|
||||
* Use these environment variables:
|
||||
|
||||
export PORTABLE=1
|
||||
export CC=gcc
|
||||
export AR="ar -X64"
|
||||
export EXTRA_ARFLAGS=-X64
|
||||
export EXTRA_CFLAGS=-maix64
|
||||
export EXTRA_CXXFLAGS=-maix64
|
||||
export PLATFORM_LDFLAGS="-static-libstdc++ -static-libgcc"
|
||||
export LIBPATH=/opt/freeware/lib
|
||||
export JAVA_HOME=/usr/java8_64
|
||||
export PATH=/opt/freeware/bin:$PATH
|
||||
|
||||
* **Solaris Sparc**
|
||||
* Install GCC 4.8.2 and higher.
|
||||
* Use these environment variables:
|
||||
|
||||
export CC=gcc
|
||||
export EXTRA_CFLAGS=-m64
|
||||
export EXTRA_CXXFLAGS=-m64
|
||||
export EXTRA_LDFLAGS=-m64
|
||||
export PORTABLE=1
|
||||
export PLATFORM_LDFLAGS="-static-libstdc++ -static-libgcc"
|
||||
|
||||
@@ -9,8 +9,5 @@ This is the list of all known third-party language bindings for RocksDB. If some
|
||||
* Haskell - https://hackage.haskell.org/package/rocksdb-haskell
|
||||
* PHP - https://github.com/Photonios/rocksdb-php
|
||||
* C# - https://github.com/warrenfalk/rocksdb-sharp
|
||||
* Rust
|
||||
* https://github.com/spacejam/rust-rocksdb
|
||||
* https://github.com/bh1xuw/rust-rocks
|
||||
* Rust - https://github.com/spacejam/rust-rocksdb
|
||||
* D programming language - https://github.com/b1naryth1ef/rocksdb
|
||||
* Erlang - https://gitlab.com/barrel-db/erlang-rocksdb
|
||||
@@ -14,8 +14,7 @@ CFLAGS += ${EXTRA_CFLAGS}
|
||||
CXXFLAGS += ${EXTRA_CXXFLAGS}
|
||||
LDFLAGS += $(EXTRA_LDFLAGS)
|
||||
MACHINE ?= $(shell uname -m)
|
||||
ARFLAGS = ${EXTRA_ARFLAGS} rs
|
||||
STRIPFLAGS = -S -x
|
||||
ARFLAGS = rs
|
||||
|
||||
# Transform parallel LOG output into something more readable.
|
||||
perl_command = perl -n \
|
||||
@@ -101,19 +100,7 @@ endif
|
||||
ifeq ($(DEBUG_LEVEL),0)
|
||||
OPT += -DNDEBUG
|
||||
DISABLE_WARNING_AS_ERROR=1
|
||||
|
||||
ifneq ($(USE_RTTI), 1)
|
||||
CXXFLAGS += -fno-rtti
|
||||
else
|
||||
CXXFLAGS += -DROCKSDB_USE_RTTI
|
||||
endif
|
||||
else
|
||||
ifneq ($(USE_RTTI), 0)
|
||||
CXXFLAGS += -DROCKSDB_USE_RTTI
|
||||
else
|
||||
CXXFLAGS += -fno-rtti
|
||||
endif
|
||||
|
||||
$(warning Warning: Compiling in debug mode. Don't use the resulting binary in production)
|
||||
endif
|
||||
|
||||
@@ -167,9 +154,7 @@ missing_make_config_paths := $(shell \
|
||||
$(foreach path, $(missing_make_config_paths), \
|
||||
$(warning Warning: $(path) dont exist))
|
||||
|
||||
ifeq ($(PLATFORM), OS_AIX)
|
||||
# no debug info
|
||||
else ifneq ($(PLATFORM), IOS)
|
||||
ifneq ($(PLATFORM), IOS)
|
||||
CFLAGS += -g
|
||||
CXXFLAGS += -g
|
||||
else
|
||||
@@ -177,11 +162,6 @@ else
|
||||
OPT += -DNDEBUG
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), OS_AIX)
|
||||
ARFLAGS = -X64 rs
|
||||
STRIPFLAGS = -X64 -x
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), OS_SOLARIS)
|
||||
PLATFORM_CXXFLAGS += -D _GLIBCXX_USE_C99
|
||||
endif
|
||||
@@ -204,9 +184,9 @@ endif
|
||||
# TSAN doesn't work well with jemalloc. If we're compiling with TSAN, we should use regular malloc.
|
||||
ifdef COMPILE_WITH_TSAN
|
||||
DISABLE_JEMALLOC=1
|
||||
EXEC_LDFLAGS += -fsanitize=thread
|
||||
PLATFORM_CCFLAGS += -fsanitize=thread -fPIC
|
||||
PLATFORM_CXXFLAGS += -fsanitize=thread -fPIC
|
||||
EXEC_LDFLAGS += -fsanitize=thread -pie
|
||||
PLATFORM_CCFLAGS += -fsanitize=thread -fPIC -DROCKSDB_TSAN_RUN
|
||||
PLATFORM_CXXFLAGS += -fsanitize=thread -fPIC -DROCKSDB_TSAN_RUN
|
||||
# Turn off -pg when enabling TSAN testing, because that induces
|
||||
# a link failure. TODO: find the root cause
|
||||
PROFILING_FLAGS =
|
||||
@@ -214,17 +194,12 @@ ifdef COMPILE_WITH_TSAN
|
||||
LUA_PATH =
|
||||
endif
|
||||
|
||||
# AIX doesn't work with -pg
|
||||
ifeq ($(PLATFORM), OS_AIX)
|
||||
PROFILING_FLAGS =
|
||||
endif
|
||||
|
||||
# USAN doesn't work well with jemalloc. If we're compiling with USAN, we should use regular malloc.
|
||||
ifdef COMPILE_WITH_UBSAN
|
||||
DISABLE_JEMALLOC=1
|
||||
EXEC_LDFLAGS += -fsanitize=undefined
|
||||
PLATFORM_CCFLAGS += -fsanitize=undefined -DROCKSDB_UBSAN_RUN
|
||||
PLATFORM_CXXFLAGS += -fsanitize=undefined -DROCKSDB_UBSAN_RUN
|
||||
PLATFORM_CCFLAGS += -fsanitize=undefined
|
||||
PLATFORM_CXXFLAGS += -fsanitize=undefined
|
||||
endif
|
||||
|
||||
ifndef DISABLE_JEMALLOC
|
||||
@@ -232,10 +207,6 @@ ifndef DISABLE_JEMALLOC
|
||||
PLATFORM_CXXFLAGS += -DROCKSDB_JEMALLOC -DJEMALLOC_NO_DEMANGLE
|
||||
PLATFORM_CCFLAGS += -DROCKSDB_JEMALLOC -DJEMALLOC_NO_DEMANGLE
|
||||
endif
|
||||
ifdef WITH_JEMALLOC_FLAG
|
||||
PLATFORM_LDFLAGS += -ljemalloc
|
||||
JAVA_LDFLAGS += -ljemalloc
|
||||
endif
|
||||
EXEC_LDFLAGS := $(JEMALLOC_LIB) $(EXEC_LDFLAGS)
|
||||
PLATFORM_CXXFLAGS += $(JEMALLOC_INCLUDE)
|
||||
PLATFORM_CCFLAGS += $(JEMALLOC_INCLUDE)
|
||||
@@ -244,14 +215,8 @@ endif
|
||||
export GTEST_THROW_ON_FAILURE=1
|
||||
export GTEST_HAS_EXCEPTIONS=1
|
||||
GTEST_DIR = ./third-party/gtest-1.7.0/fused-src
|
||||
# AIX: pre-defined system headers are surrounded by an extern "C" block
|
||||
ifeq ($(PLATFORM), OS_AIX)
|
||||
PLATFORM_CCFLAGS += -I$(GTEST_DIR)
|
||||
PLATFORM_CXXFLAGS += -I$(GTEST_DIR)
|
||||
else
|
||||
PLATFORM_CCFLAGS += -isystem $(GTEST_DIR)
|
||||
PLATFORM_CXXFLAGS += -isystem $(GTEST_DIR)
|
||||
endif
|
||||
PLATFORM_CCFLAGS += -isystem $(GTEST_DIR)
|
||||
PLATFORM_CXXFLAGS += -isystem $(GTEST_DIR)
|
||||
|
||||
# This (the first rule) must depend on "all".
|
||||
default: all
|
||||
@@ -259,11 +224,6 @@ default: all
|
||||
WARNING_FLAGS = -W -Wextra -Wall -Wsign-compare -Wshadow \
|
||||
-Wno-unused-parameter
|
||||
|
||||
ifndef DISABLE_WARNING_AS_ERROR
|
||||
WARNING_FLAGS += -Werror
|
||||
endif
|
||||
|
||||
|
||||
ifdef LUA_PATH
|
||||
|
||||
ifndef LUA_INCLUDE
|
||||
@@ -296,9 +256,6 @@ CXXFLAGS += $(WARNING_FLAGS) -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT) -Woverl
|
||||
|
||||
LDFLAGS += $(PLATFORM_LDFLAGS)
|
||||
|
||||
# If NO_UPDATE_BUILD_VERSION is set we don't update util/build_version.cc, but
|
||||
# the file needs to already exist or else the build will fail
|
||||
ifndef NO_UPDATE_BUILD_VERSION
|
||||
date := $(shell date +%F)
|
||||
ifdef FORCE_GIT_SHA
|
||||
git_sha := $(FORCE_GIT_SHA)
|
||||
@@ -312,6 +269,7 @@ gen_build_version = sed -e s/@@GIT_SHA@@/$(git_sha)/ -e s/@@GIT_DATE_TIME@@/$(da
|
||||
# as a regular source file as part of the compilation process.
|
||||
# One can run "strings executable_filename | grep _build_" to find
|
||||
# the version of the source that we used to build the executable file.
|
||||
CLEAN_FILES += util/build_version.cc:
|
||||
FORCE:
|
||||
util/build_version.cc: FORCE
|
||||
$(AM_V_GEN)rm -f $@-t
|
||||
@@ -319,7 +277,6 @@ util/build_version.cc: FORCE
|
||||
$(AM_V_at)if test -f $@; then \
|
||||
cmp -s $@-t $@ && rm -f $@-t || mv -f $@-t $@; \
|
||||
else mv -f $@-t $@; fi
|
||||
endif
|
||||
|
||||
LIBOBJECTS = $(LIB_SOURCES:.cc=.o)
|
||||
LIBOBJECTS += $(TOOL_LIB_SOURCES:.cc=.o)
|
||||
@@ -339,7 +296,6 @@ EXPOBJECTS = $(EXP_LIB_SOURCES:.cc=.o) $(LIBOBJECTS) $(TESTUTIL)
|
||||
|
||||
TESTS = \
|
||||
db_basic_test \
|
||||
db_encryption_test \
|
||||
db_test2 \
|
||||
external_sst_file_basic_test \
|
||||
auto_roll_logger_test \
|
||||
@@ -352,7 +308,6 @@ TESTS = \
|
||||
inlineskiplist_test \
|
||||
env_basic_test \
|
||||
env_test \
|
||||
hash_test \
|
||||
thread_local_test \
|
||||
rate_limiter_test \
|
||||
perf_context_test \
|
||||
@@ -360,7 +315,6 @@ TESTS = \
|
||||
db_wal_test \
|
||||
db_block_cache_test \
|
||||
db_test \
|
||||
db_blob_index_test \
|
||||
db_bloom_filter_test \
|
||||
db_iter_test \
|
||||
db_log_iter_test \
|
||||
@@ -381,9 +335,7 @@ TESTS = \
|
||||
db_properties_test \
|
||||
db_table_properties_test \
|
||||
db_statistics_test \
|
||||
db_write_test \
|
||||
autovector_test \
|
||||
blob_db_test \
|
||||
cleanable_test \
|
||||
column_family_test \
|
||||
table_properties_collector_test \
|
||||
@@ -419,12 +371,7 @@ TESTS = \
|
||||
external_sst_file_test \
|
||||
prefix_test \
|
||||
skiplist_test \
|
||||
write_buffer_manager_test \
|
||||
stringappend_test \
|
||||
cassandra_format_test \
|
||||
cassandra_functional_test \
|
||||
cassandra_row_merge_test \
|
||||
cassandra_serialize_test \
|
||||
ttl_test \
|
||||
date_tiered_test \
|
||||
backupable_db_test \
|
||||
@@ -511,8 +458,7 @@ TOOLS = \
|
||||
ldb \
|
||||
db_repl_stress \
|
||||
rocksdb_dump \
|
||||
rocksdb_undump \
|
||||
blob_dump \
|
||||
rocksdb_undump
|
||||
|
||||
TEST_LIBS = \
|
||||
librocksdb_env_basic_test.a
|
||||
@@ -573,14 +519,9 @@ $(SHARED3): $(SHARED4)
|
||||
ln -fs $(SHARED4) $(SHARED3)
|
||||
endif
|
||||
|
||||
shared_libobjects = $(patsubst %,shared-objects/%,$(LIBOBJECTS))
|
||||
CLEAN_FILES += shared-objects
|
||||
|
||||
$(shared_libobjects): shared-objects/%.o: %.cc
|
||||
$(AM_V_CC)mkdir -p $(@D) && $(CXX) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) -c $< -o $@
|
||||
|
||||
$(SHARED4): $(shared_libobjects)
|
||||
$(CXX) $(PLATFORM_SHARED_LDFLAGS)$(SHARED3) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) $(shared_libobjects) $(LDFLAGS) -o $@
|
||||
$(SHARED4):
|
||||
$(CXX) $(PLATFORM_SHARED_LDFLAGS)$(SHARED3) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) $(LIB_SOURCES) $(TOOL_LIB_SOURCES) \
|
||||
$(LDFLAGS) -o $@
|
||||
|
||||
endif # PLATFORM_SHARED_EXT
|
||||
|
||||
@@ -592,8 +533,6 @@ endif # PLATFORM_SHARED_EXT
|
||||
|
||||
all: $(LIBRARY) $(BENCHMARKS) tools tools_lib test_libs $(TESTS)
|
||||
|
||||
all_but_some_tests: $(LIBRARY) $(BENCHMARKS) tools tools_lib test_libs $(SUBSET)
|
||||
|
||||
static_lib: $(LIBRARY)
|
||||
|
||||
shared_lib: $(SHARED)
|
||||
@@ -623,8 +562,7 @@ ifneq (,$(filter check parallel_check,$(MAKECMDGOALS)),)
|
||||
# and create a randomly-named rocksdb.XXXX directory therein.
|
||||
# We'll use that directory in the "make check" rules.
|
||||
ifeq ($(TMPD),)
|
||||
TMPDIR := $(shell echo $${TMPDIR:-/tmp})
|
||||
TMPD := $(shell f=/dev/shm; test -k $$f || f=$(TMPDIR); \
|
||||
TMPD := $(shell f=/dev/shm; test -k $$f || f=/tmp; \
|
||||
perl -le 'use File::Temp "tempdir";' \
|
||||
-e 'print tempdir("'$$f'/rocksdb.XXXX", CLEANUP => 0)')
|
||||
endif
|
||||
@@ -779,12 +717,10 @@ check: all
|
||||
echo "===== Running $$t"; ./$$t || exit 1; done; \
|
||||
fi
|
||||
rm -rf $(TMPD)
|
||||
ifneq ($(PLATFORM), OS_AIX)
|
||||
ifeq ($(filter -DROCKSDB_LITE,$(OPT)),)
|
||||
python tools/ldb_test.py
|
||||
sh tools/rocksdb_dump_test.sh
|
||||
endif
|
||||
endif
|
||||
|
||||
# TODO add ldb_tests
|
||||
check_some: $(SUBSET)
|
||||
@@ -797,8 +733,8 @@ ldb_tests: ldb
|
||||
crash_test: whitebox_crash_test blackbox_crash_test
|
||||
|
||||
blackbox_crash_test: db_stress
|
||||
python -u tools/db_crashtest.py --simple blackbox $(CRASH_TEST_EXT_ARGS)
|
||||
python -u tools/db_crashtest.py blackbox $(CRASH_TEST_EXT_ARGS)
|
||||
python -u tools/db_crashtest.py --simple blackbox
|
||||
python -u tools/db_crashtest.py blackbox
|
||||
|
||||
ifeq ($(CRASH_TEST_KILL_ODD),)
|
||||
CRASH_TEST_KILL_ODD=888887
|
||||
@@ -806,9 +742,9 @@ endif
|
||||
|
||||
whitebox_crash_test: db_stress
|
||||
python -u tools/db_crashtest.py --simple whitebox --random_kill_odd \
|
||||
$(CRASH_TEST_KILL_ODD) $(CRASH_TEST_EXT_ARGS)
|
||||
$(CRASH_TEST_KILL_ODD)
|
||||
python -u tools/db_crashtest.py whitebox --random_kill_odd \
|
||||
$(CRASH_TEST_KILL_ODD) $(CRASH_TEST_EXT_ARGS)
|
||||
$(CRASH_TEST_KILL_ODD)
|
||||
|
||||
asan_check:
|
||||
$(MAKE) clean
|
||||
@@ -930,13 +866,12 @@ clean:
|
||||
rm -rf $(CLEAN_FILES) ios-x86 ios-arm scan_build_report
|
||||
find . -name "*.[oda]" -exec rm -f {} \;
|
||||
find . -type f -regex ".*\.\(\(gcda\)\|\(gcno\)\)" -exec rm {} \;
|
||||
rm -rf bzip2* snappy* zlib* lz4* zstd*
|
||||
rm -rf bzip2* snappy* zlib* lz4*
|
||||
cd java; $(MAKE) clean
|
||||
|
||||
tags:
|
||||
ctags * -R
|
||||
cscope -b `find . -name '*.cc'` `find . -name '*.h'` `find . -name '*.c'`
|
||||
ctags -e -R -o etags *
|
||||
|
||||
format:
|
||||
build_tools/format-diff.sh
|
||||
@@ -1010,27 +945,12 @@ cache_test: cache/cache_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
coding_test: util/coding_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
hash_test: util/hash_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
option_change_migration_test: utilities/option_change_migration/option_change_migration_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
stringappend_test: utilities/merge_operators/string_append/stringappend_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
cassandra_format_test: utilities/cassandra/cassandra_format_test.o utilities/cassandra/test_utils.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
cassandra_functional_test: utilities/cassandra/cassandra_functional_test.o utilities/cassandra/test_utils.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
cassandra_row_merge_test: utilities/cassandra/cassandra_row_merge_test.o utilities/cassandra/test_utils.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
cassandra_serialize_test: utilities/cassandra/cassandra_serialize_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
redis_test: utilities/redis/redis_lists_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
@@ -1055,18 +975,12 @@ slice_transform_test: util/slice_transform_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
db_basic_test: db/db_basic_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
db_encryption_test: db/db_encryption_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
db_test: db/db_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
db_test2: db/db_test2.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
db_blob_index_test: db/db_blob_index_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
db_block_cache_test: db/db_block_cache_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
@@ -1112,9 +1026,6 @@ db_sst_test: db/db_sst_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
db_statistics_test: db/db_statistics_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
db_write_test: db/db_write_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
external_sst_file_basic_test: db/external_sst_file_basic_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
@@ -1270,9 +1181,6 @@ inlineskiplist_test: memtable/inlineskiplist_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
skiplist_test: memtable/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
write_buffer_manager_test: memtable/write_buffer_manager_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
version_edit_test: db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
@@ -1399,9 +1307,6 @@ transaction_test: utilities/transactions/transaction_test.o $(LIBOBJECTS) $(TEST
|
||||
sst_dump: tools/sst_dump.o $(LIBOBJECTS)
|
||||
$(AM_LINK)
|
||||
|
||||
blob_dump: tools/blob_dump.o $(LIBOBJECTS)
|
||||
$(AM_LINK)
|
||||
|
||||
column_aware_encoding_exp: utilities/column_aware_encoding_exp.o $(EXPOBJECTS)
|
||||
$(AM_LINK)
|
||||
|
||||
@@ -1432,9 +1337,6 @@ lua_test: utilities/lua/rocks_lua_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTH
|
||||
range_del_aggregator_test: db/range_del_aggregator_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
blob_db_test: utilities/blob_db/blob_db_test.o $(LIBOBJECTS) $(TESTHARNESS)
|
||||
$(AM_LINK)
|
||||
|
||||
#-------------------------------------------------
|
||||
# make install related stuff
|
||||
INSTALL_PATH ?= /usr/local
|
||||
@@ -1494,18 +1396,14 @@ ROCKSDB_JAVADOCS_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PA
|
||||
ROCKSDB_SOURCES_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-sources.jar
|
||||
SHA256_CMD = sha256sum
|
||||
|
||||
ZLIB_VER ?= 1.2.11
|
||||
ZLIB_SHA256 ?= c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1
|
||||
ZLIB_DOWNLOAD_BASE ?= http://zlib.net
|
||||
BZIP2_VER ?= 1.0.6
|
||||
BZIP2_SHA256 ?= a2848f34fcd5d6cf47def00461fcb528a0484d8edef8208d6d2e2909dc61d9cd
|
||||
BZIP2_DOWNLOAD_BASE ?= http://www.bzip.org
|
||||
SNAPPY_VER ?= 1.1.4
|
||||
SNAPPY_SHA256 ?= 134bfe122fd25599bb807bb8130e7ba6d9bdb851e0b16efcb83ac4f5d0b70057
|
||||
SNAPPY_DOWNLOAD_BASE ?= https://github.com/google/snappy/releases/download
|
||||
LZ4_VER ?= 1.7.5
|
||||
LZ4_SHA256 ?= 0190cacd63022ccb86f44fa5041dc6c3804407ad61550ca21c382827319e7e7e
|
||||
LZ4_DOWNLOAD_BASE ?= https://github.com/lz4/lz4/archive
|
||||
ZLIB_VER = 1.2.11
|
||||
ZLIB_SHA256 = c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1
|
||||
BZIP2_VER = 1.0.6
|
||||
BZIP2_SHA256 = a2848f34fcd5d6cf47def00461fcb528a0484d8edef8208d6d2e2909dc61d9cd
|
||||
SNAPPY_VER = 1.1.4
|
||||
SNAPPY_SHA256 = 134bfe122fd25599bb807bb8130e7ba6d9bdb851e0b16efcb83ac4f5d0b70057
|
||||
LZ4_VER = 1.7.5
|
||||
LZ4_SHA256 = 0190cacd63022ccb86f44fa5041dc6c3804407ad61550ca21c382827319e7e7e
|
||||
ZSTD_VER ?= 1.2.0
|
||||
ZSTD_SHA256 ?= 4a7e4593a3638276ca7f2a09dc4f38e674d8317bbea51626393ca73fc047cbfb
|
||||
ZSTD_DOWNLOAD_BASE ?= https://github.com/facebook/zstd/archive
|
||||
@@ -1531,53 +1429,47 @@ ifeq ($(PLATFORM), OS_SOLARIS)
|
||||
JAVA_INCLUDE = -I$(JAVA_HOME)/include/ -I$(JAVA_HOME)/include/solaris
|
||||
SHA256_CMD = digest -a sha256
|
||||
endif
|
||||
ifeq ($(PLATFORM), OS_AIX)
|
||||
JAVA_INCLUDE = -I$(JAVA_HOME)/include/ -I$(JAVA_HOME)/include/aix
|
||||
ROCKSDBJNILIB = librocksdbjni-aix.so
|
||||
EXTRACT_SOURCES = gunzip < TAR_GZ | tar xvf -
|
||||
SNAPPY_MAKE_TARGET = libsnappy.la
|
||||
endif
|
||||
|
||||
libz.a:
|
||||
-rm -rf zlib-$(ZLIB_VER)
|
||||
curl -O -L ${ZLIB_DOWNLOAD_BASE}/zlib-$(ZLIB_VER).tar.gz
|
||||
curl -O -L http://zlib.net/zlib-$(ZLIB_VER).tar.gz
|
||||
ZLIB_SHA256_ACTUAL=`$(SHA256_CMD) zlib-$(ZLIB_VER).tar.gz | cut -d ' ' -f 1`; \
|
||||
if [ "$(ZLIB_SHA256)" != "$$ZLIB_SHA256_ACTUAL" ]; then \
|
||||
echo zlib-$(ZLIB_VER).tar.gz checksum mismatch, expected=\"$(ZLIB_SHA256)\" actual=\"$$ZLIB_SHA256_ACTUAL\"; \
|
||||
exit 1; \
|
||||
fi
|
||||
tar xvzf zlib-$(ZLIB_VER).tar.gz
|
||||
cd zlib-$(ZLIB_VER) && CFLAGS='-fPIC ${EXTRA_CFLAGS}' LDFLAGS='${EXTRA_LDFLAGS}' ./configure --static && make
|
||||
cd zlib-$(ZLIB_VER) && CFLAGS='-fPIC' ./configure --static && make
|
||||
cp zlib-$(ZLIB_VER)/libz.a .
|
||||
|
||||
libbz2.a:
|
||||
-rm -rf bzip2-$(BZIP2_VER)
|
||||
curl -O -L ${BZIP2_DOWNLOAD_BASE}/$(BZIP2_VER)/bzip2-$(BZIP2_VER).tar.gz
|
||||
curl -O -L http://www.bzip.org/$(BZIP2_VER)/bzip2-$(BZIP2_VER).tar.gz
|
||||
BZIP2_SHA256_ACTUAL=`$(SHA256_CMD) bzip2-$(BZIP2_VER).tar.gz | cut -d ' ' -f 1`; \
|
||||
if [ "$(BZIP2_SHA256)" != "$$BZIP2_SHA256_ACTUAL" ]; then \
|
||||
echo bzip2-$(BZIP2_VER).tar.gz checksum mismatch, expected=\"$(BZIP2_SHA256)\" actual=\"$$BZIP2_SHA256_ACTUAL\"; \
|
||||
exit 1; \
|
||||
fi
|
||||
tar xvzf bzip2-$(BZIP2_VER).tar.gz
|
||||
cd bzip2-$(BZIP2_VER) && make CFLAGS='-fPIC -O2 -g -D_FILE_OFFSET_BITS=64 ${EXTRA_CFLAGS}' AR='ar ${EXTRA_ARFLAGS}'
|
||||
cd bzip2-$(BZIP2_VER) && make CFLAGS='-fPIC -O2 -g -D_FILE_OFFSET_BITS=64'
|
||||
cp bzip2-$(BZIP2_VER)/libbz2.a .
|
||||
|
||||
libsnappy.a:
|
||||
-rm -rf snappy-$(SNAPPY_VER)
|
||||
curl -O -L ${SNAPPY_DOWNLOAD_BASE}/$(SNAPPY_VER)/snappy-$(SNAPPY_VER).tar.gz
|
||||
curl -O -L https://github.com/google/snappy/releases/download/$(SNAPPY_VER)/snappy-$(SNAPPY_VER).tar.gz
|
||||
SNAPPY_SHA256_ACTUAL=`$(SHA256_CMD) snappy-$(SNAPPY_VER).tar.gz | cut -d ' ' -f 1`; \
|
||||
if [ "$(SNAPPY_SHA256)" != "$$SNAPPY_SHA256_ACTUAL" ]; then \
|
||||
echo snappy-$(SNAPPY_VER).tar.gz checksum mismatch, expected=\"$(SNAPPY_SHA256)\" actual=\"$$SNAPPY_SHA256_ACTUAL\"; \
|
||||
exit 1; \
|
||||
fi
|
||||
tar xvzf snappy-$(SNAPPY_VER).tar.gz
|
||||
cd snappy-$(SNAPPY_VER) && CFLAGS='${EXTRA_CFLAGS}' CXXFLAGS='${EXTRA_CXXFLAGS}' LDFLAGS='${EXTRA_LDFLAGS}' ./configure --with-pic --enable-static --disable-shared
|
||||
cd snappy-$(SNAPPY_VER) && make ${SNAPPY_MAKE_TARGET}
|
||||
cd snappy-$(SNAPPY_VER) && ./configure --with-pic --enable-static
|
||||
cd snappy-$(SNAPPY_VER) && make
|
||||
cp snappy-$(SNAPPY_VER)/.libs/libsnappy.a .
|
||||
|
||||
liblz4.a:
|
||||
-rm -rf lz4-$(LZ4_VER)
|
||||
curl -O -L ${LZ4_DOWNLOAD_BASE}/v$(LZ4_VER).tar.gz
|
||||
curl -O -L https://github.com/lz4/lz4/archive/v$(LZ4_VER).tar.gz
|
||||
mv v$(LZ4_VER).tar.gz lz4-$(LZ4_VER).tar.gz
|
||||
LZ4_SHA256_ACTUAL=`$(SHA256_CMD) lz4-$(LZ4_VER).tar.gz | cut -d ' ' -f 1`; \
|
||||
if [ "$(LZ4_SHA256)" != "$$LZ4_SHA256_ACTUAL" ]; then \
|
||||
@@ -1585,7 +1477,7 @@ liblz4.a:
|
||||
exit 1; \
|
||||
fi
|
||||
tar xvzf lz4-$(LZ4_VER).tar.gz
|
||||
cd lz4-$(LZ4_VER)/lib && make CFLAGS='-fPIC -O2 ${EXTRA_CFLAGS}' all
|
||||
cd lz4-$(LZ4_VER)/lib && make CFLAGS='-fPIC' all
|
||||
cp lz4-$(LZ4_VER)/lib/liblz4.a .
|
||||
|
||||
libzstd.a:
|
||||
@@ -1622,7 +1514,7 @@ rocksdbjavastatic: $(java_static_libobjects)
|
||||
-o ./java/target/$(ROCKSDBJNILIB) $(JNI_NATIVE_SOURCES) \
|
||||
$(java_static_libobjects) $(COVERAGEFLAGS) \
|
||||
$(JAVA_COMPRESSIONS) $(JAVA_STATIC_LDFLAGS)
|
||||
cd java/target;strip $(STRIPFLAGS) $(ROCKSDBJNILIB)
|
||||
cd java/target;strip -S -x $(ROCKSDBJNILIB)
|
||||
cd java;jar -cf target/$(ROCKSDB_JAR) HISTORY*.md
|
||||
cd java/target;jar -uf $(ROCKSDB_JAR) $(ROCKSDBJNILIB)
|
||||
cd java/target/classes;jar -uf ../$(ROCKSDB_JAR) org/rocksdb/*.class org/rocksdb/util/*.class
|
||||
@@ -1638,12 +1530,12 @@ rocksdbjavastaticrelease: rocksdbjavastatic
|
||||
rocksdbjavastaticreleasedocker: rocksdbjavastatic
|
||||
DOCKER_LINUX_X64_CONTAINER=`docker ps -aqf name=rocksdb_linux_x64-be`; \
|
||||
if [ -z "$$DOCKER_LINUX_X64_CONTAINER" ]; then \
|
||||
docker container create --attach stdin --attach stdout --attach stderr --volume `pwd`:/rocksdb-host --name rocksdb_linux_x64-be evolvedbinary/rocksjava:centos6_x64-be /rocksdb-host/java/crossbuild/docker-build-linux-centos.sh; \
|
||||
docker container create --attach stdin --attach stdout --attach stderr --volume `pwd`:/rocksdb-host --name rocksdb_linux_x64-be evolvedbinary/rocksjava:centos5_x64-be /rocksdb-host/java/crossbuild/docker-build-linux-centos.sh; \
|
||||
fi
|
||||
docker start -a rocksdb_linux_x64-be
|
||||
DOCKER_LINUX_X86_CONTAINER=`docker ps -aqf name=rocksdb_linux_x86-be`; \
|
||||
if [ -z "$$DOCKER_LINUX_X86_CONTAINER" ]; then \
|
||||
docker container create --attach stdin --attach stdout --attach stderr --volume `pwd`:/rocksdb-host --name rocksdb_linux_x86-be evolvedbinary/rocksjava:centos6_x86-be /rocksdb-host/java/crossbuild/docker-build-linux-centos.sh; \
|
||||
docker container create --attach stdin --attach stdout --attach stderr --volume `pwd`:/rocksdb-host --name rocksdb_linux_x86-be evolvedbinary/rocksjava:centos5_x86-be /rocksdb-host/java/crossbuild/docker-build-linux-centos.sh; \
|
||||
fi
|
||||
docker start -a rocksdb_linux_x86-be
|
||||
cd java;jar -cf target/$(ROCKSDB_JAR_ALL) HISTORY*.md
|
||||
|
||||
@@ -1,21 +1,15 @@
|
||||
|
||||
import os
|
||||
|
||||
TARGETS_PATH = os.path.dirname(__file__)
|
||||
REPO_PATH = TARGETS_PATH[(TARGETS_PATH.find('fbcode/') + len('fbcode/')):] + "/"
|
||||
REPO_PATH = "internal_repo_rocksdb/repo/"
|
||||
BUCK_BINS = "buck-out/gen/" + REPO_PATH
|
||||
TEST_RUNNER = REPO_PATH + "buckifier/rocks_test_runner.sh"
|
||||
rocksdb_compiler_flags = [
|
||||
"-msse",
|
||||
"-msse4.2",
|
||||
"-fno-builtin-memcmp",
|
||||
"-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",
|
||||
"-DOS_LINUX",
|
||||
"-DROCKSDB_UBSAN_RUN",
|
||||
# Flags to enable libs we include
|
||||
"-DSNAPPY",
|
||||
"-DZLIB",
|
||||
@@ -37,7 +31,7 @@ rocksdb_external_deps = [
|
||||
('lz4', None, 'lz4'),
|
||||
('zstd', None),
|
||||
('tbb', None),
|
||||
("numa", None, "numa"),
|
||||
("numa", "2.0.8", "numa"),
|
||||
("googletest", None, "gtest"),
|
||||
]
|
||||
|
||||
@@ -47,10 +41,6 @@ rocksdb_preprocessor_flags = [
|
||||
"-I" + REPO_PATH,
|
||||
]
|
||||
|
||||
rocksdb_arch_preprocessor_flags = {
|
||||
"x86_64": ["-DHAVE_SSE42"],
|
||||
}
|
||||
|
||||
cpp_library(
|
||||
name = "rocksdb_lib",
|
||||
headers = AutoHeaders.RECURSIVE_GLOB,
|
||||
@@ -90,7 +80,6 @@ cpp_library(
|
||||
"db/internal_stats.cc",
|
||||
"db/log_reader.cc",
|
||||
"db/log_writer.cc",
|
||||
"db/malloc_stats.cc",
|
||||
"db/managed_iterator.cc",
|
||||
"db/memtable.cc",
|
||||
"db/memtable_list.cc",
|
||||
@@ -112,18 +101,16 @@ cpp_library(
|
||||
"db/write_thread.cc",
|
||||
"env/env.cc",
|
||||
"env/env_chroot.cc",
|
||||
"env/env_encryption.cc",
|
||||
"env/env_hdfs.cc",
|
||||
"env/env_posix.cc",
|
||||
"env/io_posix.cc",
|
||||
"env/mock_env.cc",
|
||||
"memtable/alloc_tracker.cc",
|
||||
"env/memenv.cc",
|
||||
"memtable/hash_cuckoo_rep.cc",
|
||||
"memtable/hash_linklist_rep.cc",
|
||||
"memtable/hash_skiplist_rep.cc",
|
||||
"memtable/memtable_allocator.cc",
|
||||
"memtable/skiplistrep.cc",
|
||||
"memtable/vectorrep.cc",
|
||||
"memtable/write_buffer_manager.cc",
|
||||
"monitoring/histogram.cc",
|
||||
"monitoring/histogram_windowing.cc",
|
||||
"monitoring/instrumented_mutex.cc",
|
||||
@@ -209,19 +196,15 @@ cpp_library(
|
||||
"utilities/backupable/backupable_db.cc",
|
||||
"utilities/blob_db/blob_db.cc",
|
||||
"utilities/blob_db/blob_db_impl.cc",
|
||||
"utilities/blob_db/blob_db_options_impl.cc",
|
||||
"utilities/blob_db/blob_file.cc",
|
||||
"utilities/blob_db/blob_log_reader.cc",
|
||||
"utilities/blob_db/blob_log_writer.cc",
|
||||
"utilities/blob_db/blob_log_format.cc",
|
||||
"utilities/blob_db/ttl_extractor.cc",
|
||||
"utilities/cassandra/cassandra_compaction_filter.cc",
|
||||
"utilities/cassandra/format.cc",
|
||||
"utilities/cassandra/merge_operator.cc",
|
||||
"utilities/checkpoint/checkpoint_impl.cc",
|
||||
"utilities/checkpoint/checkpoint.cc",
|
||||
"utilities/compaction_filters/remove_emptyvalue_compactionfilter.cc",
|
||||
"utilities/convenience/info_log_finder.cc",
|
||||
"utilities/date_tiered/date_tiered_db_impl.cc",
|
||||
"utilities/debug.cc",
|
||||
"utilities/document/document_db.cc",
|
||||
"utilities/document/json_document.cc",
|
||||
"utilities/document/json_document_builder.cc",
|
||||
@@ -248,25 +231,22 @@ cpp_library(
|
||||
"utilities/spatialdb/spatial_db.cc",
|
||||
"utilities/table_properties_collectors/compact_on_deletion_collector.cc",
|
||||
"utilities/transactions/optimistic_transaction_db_impl.cc",
|
||||
"utilities/transactions/optimistic_transaction.cc",
|
||||
"utilities/transactions/optimistic_transaction_impl.cc",
|
||||
"utilities/transactions/transaction_base.cc",
|
||||
"utilities/transactions/pessimistic_transaction_db.cc",
|
||||
"utilities/transactions/transaction_db_impl.cc",
|
||||
"utilities/transactions/transaction_db_mutex_impl.cc",
|
||||
"utilities/transactions/pessimistic_transaction.cc",
|
||||
"utilities/transactions/transaction_impl.cc",
|
||||
"utilities/transactions/transaction_lock_mgr.cc",
|
||||
"utilities/transactions/transaction_util.cc",
|
||||
"utilities/transactions/write_prepared_txn.cc",
|
||||
"utilities/ttl/db_ttl_impl.cc",
|
||||
"utilities/write_batch_with_index/write_batch_with_index.cc",
|
||||
"utilities/write_batch_with_index/write_batch_with_index_internal.cc",
|
||||
"tools/ldb_cmd.cc",
|
||||
"tools/ldb_tool.cc",
|
||||
"tools/sst_dump_tool.cc",
|
||||
"utilities/blob_db/blob_dump_tool.cc",
|
||||
],
|
||||
deps = [],
|
||||
preprocessor_flags = rocksdb_preprocessor_flags,
|
||||
arch_preprocessor_flags = rocksdb_arch_preprocessor_flags,
|
||||
compiler_flags = rocksdb_compiler_flags,
|
||||
external_deps = rocksdb_external_deps,
|
||||
)
|
||||
@@ -275,19 +255,18 @@ cpp_library(
|
||||
name = "rocksdb_test_lib",
|
||||
headers = AutoHeaders.RECURSIVE_GLOB,
|
||||
srcs = [
|
||||
"env/mock_env.cc",
|
||||
"table/mock_table.cc",
|
||||
"util/fault_injection_test_env.cc",
|
||||
"util/testharness.cc",
|
||||
"util/testutil.cc",
|
||||
"db/db_test_util.cc",
|
||||
"utilities/cassandra/test_utils.cc",
|
||||
"utilities/col_buf_encoder.cc",
|
||||
"utilities/col_buf_decoder.cc",
|
||||
"utilities/column_aware_encoding_util.cc",
|
||||
],
|
||||
deps = [":rocksdb_lib"],
|
||||
preprocessor_flags = rocksdb_preprocessor_flags,
|
||||
arch_preprocessor_flags = rocksdb_arch_preprocessor_flags,
|
||||
compiler_flags = rocksdb_compiler_flags,
|
||||
external_deps = rocksdb_external_deps,
|
||||
)
|
||||
@@ -301,7 +280,6 @@ cpp_library(
|
||||
],
|
||||
deps = [":rocksdb_lib"],
|
||||
preprocessor_flags = rocksdb_preprocessor_flags,
|
||||
arch_preprocessor_flags = rocksdb_arch_preprocessor_flags,
|
||||
compiler_flags = rocksdb_compiler_flags,
|
||||
external_deps = rocksdb_external_deps,
|
||||
)
|
||||
@@ -312,189 +290,167 @@ cpp_library(
|
||||
srcs = ["env/env_basic_test.cc"],
|
||||
deps = [":rocksdb_test_lib"],
|
||||
preprocessor_flags = rocksdb_preprocessor_flags,
|
||||
arch_preprocessor_flags = rocksdb_arch_preprocessor_flags,
|
||||
compiler_flags = rocksdb_compiler_flags,
|
||||
external_deps = rocksdb_external_deps,
|
||||
)
|
||||
|
||||
# [test_name, test_src, test_type]
|
||||
ROCKS_TESTS = [['arena_test', 'util/arena_test.cc', 'serial'],
|
||||
['auto_roll_logger_test', 'util/auto_roll_logger_test.cc', 'serial'],
|
||||
['autovector_test', 'util/autovector_test.cc', 'serial'],
|
||||
['backupable_db_test',
|
||||
'utilities/backupable/backupable_db_test.cc',
|
||||
'parallel'],
|
||||
['blob_db_test', 'utilities/blob_db/blob_db_test.cc', 'serial'],
|
||||
['block_based_filter_block_test',
|
||||
'table/block_based_filter_block_test.cc',
|
||||
'serial'],
|
||||
['block_test', 'table/block_test.cc', 'serial'],
|
||||
['bloom_test', 'util/bloom_test.cc', 'serial'],
|
||||
['c_test', 'db/c_test.c', 'serial'],
|
||||
ROCKS_TESTS = [['merger_test', 'table/merger_test.cc', 'serial'],
|
||||
['cache_test', 'cache/cache_test.cc', 'serial'],
|
||||
['cassandra_format_test',
|
||||
'utilities/cassandra/cassandra_format_test.cc',
|
||||
'serial'],
|
||||
['cassandra_functional_test',
|
||||
'utilities/cassandra/cassandra_functional_test.cc',
|
||||
'serial'],
|
||||
['cassandra_row_merge_test',
|
||||
'utilities/cassandra/cassandra_row_merge_test.cc',
|
||||
'serial'],
|
||||
['cassandra_serialize_test',
|
||||
'utilities/cassandra/cassandra_serialize_test.cc',
|
||||
'serial'],
|
||||
['checkpoint_test', 'utilities/checkpoint/checkpoint_test.cc', 'serial'],
|
||||
['cleanable_test', 'table/cleanable_test.cc', 'serial'],
|
||||
['coding_test', 'util/coding_test.cc', 'serial'],
|
||||
['column_aware_encoding_test',
|
||||
'utilities/column_aware_encoding_test.cc',
|
||||
'serial'],
|
||||
['column_family_test', 'db/column_family_test.cc', 'serial'],
|
||||
['compact_files_test', 'db/compact_files_test.cc', 'serial'],
|
||||
['compact_on_deletion_collector_test',
|
||||
'utilities/table_properties_collectors/compact_on_deletion_collector_test.cc',
|
||||
'serial'],
|
||||
['compaction_iterator_test', 'db/compaction_iterator_test.cc', 'serial'],
|
||||
['compaction_job_stats_test', 'db/compaction_job_stats_test.cc', 'serial'],
|
||||
['compaction_job_test', 'db/compaction_job_test.cc', 'serial'],
|
||||
['compaction_picker_test', 'db/compaction_picker_test.cc', 'serial'],
|
||||
['comparator_db_test', 'db/comparator_db_test.cc', 'serial'],
|
||||
['corruption_test', 'db/corruption_test.cc', 'serial'],
|
||||
['crc32c_test', 'util/crc32c_test.cc', 'serial'],
|
||||
['cuckoo_table_builder_test', 'table/cuckoo_table_builder_test.cc', 'serial'],
|
||||
['cuckoo_table_db_test', 'db/cuckoo_table_db_test.cc', 'serial'],
|
||||
['cuckoo_table_reader_test', 'table/cuckoo_table_reader_test.cc', 'serial'],
|
||||
['date_tiered_test', 'utilities/date_tiered/date_tiered_test.cc', 'serial'],
|
||||
['db_basic_test', 'db/db_basic_test.cc', 'serial'],
|
||||
['db_blob_index_test', 'db/db_blob_index_test.cc', 'serial'],
|
||||
['db_block_cache_test', 'db/db_block_cache_test.cc', 'serial'],
|
||||
['db_bloom_filter_test', 'db/db_bloom_filter_test.cc', 'serial'],
|
||||
['db_compaction_filter_test', 'db/db_compaction_filter_test.cc', 'parallel'],
|
||||
['db_compaction_test', 'db/db_compaction_test.cc', 'parallel'],
|
||||
['db_dynamic_level_test', 'db/db_dynamic_level_test.cc', 'serial'],
|
||||
['db_encryption_test', 'db/db_encryption_test.cc', 'serial'],
|
||||
['db_flush_test', 'db/db_flush_test.cc', 'serial'],
|
||||
['db_inplace_update_test', 'db/db_inplace_update_test.cc', 'serial'],
|
||||
['db_io_failure_test', 'db/db_io_failure_test.cc', 'serial'],
|
||||
['db_iter_test', 'db/db_iter_test.cc', 'serial'],
|
||||
['db_iterator_test', 'db/db_iterator_test.cc', 'serial'],
|
||||
['db_log_iter_test', 'db/db_log_iter_test.cc', 'serial'],
|
||||
['db_memtable_test', 'db/db_memtable_test.cc', 'serial'],
|
||||
['db_merge_operator_test', 'db/db_merge_operator_test.cc', 'serial'],
|
||||
['db_options_test', 'db/db_options_test.cc', 'serial'],
|
||||
['db_properties_test', 'db/db_properties_test.cc', 'serial'],
|
||||
['db_range_del_test', 'db/db_range_del_test.cc', 'serial'],
|
||||
['db_sst_test', 'db/db_sst_test.cc', 'parallel'],
|
||||
['db_statistics_test', 'db/db_statistics_test.cc', 'serial'],
|
||||
['db_table_properties_test', 'db/db_table_properties_test.cc', 'serial'],
|
||||
['db_tailing_iter_test', 'db/db_tailing_iter_test.cc', 'serial'],
|
||||
['db_test', 'db/db_test.cc', 'parallel'],
|
||||
['db_test2', 'db/db_test2.cc', 'serial'],
|
||||
['db_universal_compaction_test',
|
||||
'db/db_universal_compaction_test.cc',
|
||||
'parallel'],
|
||||
['db_wal_test', 'db/db_wal_test.cc', 'parallel'],
|
||||
['db_write_test', 'db/db_write_test.cc', 'serial'],
|
||||
['dbformat_test', 'db/dbformat_test.cc', 'serial'],
|
||||
['delete_scheduler_test', 'util/delete_scheduler_test.cc', 'serial'],
|
||||
['deletefile_test', 'db/deletefile_test.cc', 'serial'],
|
||||
['document_db_test', 'utilities/document/document_db_test.cc', 'serial'],
|
||||
['dynamic_bloom_test', 'util/dynamic_bloom_test.cc', 'serial'],
|
||||
['env_basic_test', 'env/env_basic_test.cc', 'serial'],
|
||||
['env_test', 'env/env_test.cc', 'serial'],
|
||||
['env_timed_test', 'utilities/env_timed_test.cc', 'serial'],
|
||||
['event_logger_test', 'util/event_logger_test.cc', 'serial'],
|
||||
['external_sst_file_basic_test',
|
||||
'db/external_sst_file_basic_test.cc',
|
||||
'serial'],
|
||||
['external_sst_file_test', 'db/external_sst_file_test.cc', 'parallel'],
|
||||
['fault_injection_test', 'db/fault_injection_test.cc', 'parallel'],
|
||||
['file_indexer_test', 'db/file_indexer_test.cc', 'serial'],
|
||||
['file_reader_writer_test', 'util/file_reader_writer_test.cc', 'serial'],
|
||||
['filelock_test', 'util/filelock_test.cc', 'serial'],
|
||||
['filename_test', 'db/filename_test.cc', 'serial'],
|
||||
['flush_job_test', 'db/flush_job_test.cc', 'serial'],
|
||||
['full_filter_block_test', 'table/full_filter_block_test.cc', 'serial'],
|
||||
['geodb_test', 'utilities/geodb/geodb_test.cc', 'serial'],
|
||||
['hash_table_test',
|
||||
'utilities/persistent_cache/hash_table_test.cc',
|
||||
'serial'],
|
||||
['hash_test', 'util/hash_test.cc', 'serial'],
|
||||
['heap_test', 'util/heap_test.cc', 'serial'],
|
||||
['histogram_test', 'monitoring/histogram_test.cc', 'serial'],
|
||||
['inlineskiplist_test', 'memtable/inlineskiplist_test.cc', 'parallel'],
|
||||
['iostats_context_test', 'monitoring/iostats_context_test.cc', 'serial'],
|
||||
['json_document_test', 'utilities/document/json_document_test.cc', 'serial'],
|
||||
['ldb_cmd_test', 'tools/ldb_cmd_test.cc', 'serial'],
|
||||
['listener_test', 'db/listener_test.cc', 'serial'],
|
||||
['log_test', 'db/log_test.cc', 'serial'],
|
||||
['lru_cache_test', 'cache/lru_cache_test.cc', 'serial'],
|
||||
['manual_compaction_test', 'db/manual_compaction_test.cc', 'parallel'],
|
||||
['memory_test', 'utilities/memory/memory_test.cc', 'serial'],
|
||||
['memtable_list_test', 'db/memtable_list_test.cc', 'serial'],
|
||||
['merge_helper_test', 'db/merge_helper_test.cc', 'serial'],
|
||||
['merge_test', 'db/merge_test.cc', 'serial'],
|
||||
['merger_test', 'table/merger_test.cc', 'serial'],
|
||||
['mock_env_test', 'env/mock_env_test.cc', 'serial'],
|
||||
['object_registry_test', 'utilities/object_registry_test.cc', 'serial'],
|
||||
['optimistic_transaction_test',
|
||||
'utilities/transactions/optimistic_transaction_test.cc',
|
||||
'serial'],
|
||||
['option_change_migration_test',
|
||||
'utilities/option_change_migration/option_change_migration_test.cc',
|
||||
'serial'],
|
||||
['options_file_test', 'db/options_file_test.cc', 'serial'],
|
||||
['options_settable_test', 'options/options_settable_test.cc', 'serial'],
|
||||
['options_test', 'options/options_test.cc', 'serial'],
|
||||
['options_util_test', 'utilities/options/options_util_test.cc', 'serial'],
|
||||
['partitioned_filter_block_test',
|
||||
'table/partitioned_filter_block_test.cc',
|
||||
'serial'],
|
||||
['perf_context_test', 'db/perf_context_test.cc', 'serial'],
|
||||
['persistent_cache_test',
|
||||
'utilities/persistent_cache/persistent_cache_test.cc',
|
||||
'parallel'],
|
||||
['plain_table_db_test', 'db/plain_table_db_test.cc', 'serial'],
|
||||
['prefix_test', 'db/prefix_test.cc', 'serial'],
|
||||
['range_del_aggregator_test', 'db/range_del_aggregator_test.cc', 'serial'],
|
||||
['rate_limiter_test', 'util/rate_limiter_test.cc', 'serial'],
|
||||
['reduce_levels_test', 'tools/reduce_levels_test.cc', 'serial'],
|
||||
['repair_test', 'db/repair_test.cc', 'serial'],
|
||||
['sim_cache_test', 'utilities/simulator_cache/sim_cache_test.cc', 'serial'],
|
||||
['skiplist_test', 'memtable/skiplist_test.cc', 'serial'],
|
||||
['slice_transform_test', 'util/slice_transform_test.cc', 'serial'],
|
||||
['spatial_db_test', 'utilities/spatialdb/spatial_db_test.cc', 'serial'],
|
||||
['sst_dump_test', 'tools/sst_dump_test.cc', 'serial'],
|
||||
['statistics_test', 'monitoring/statistics_test.cc', 'serial'],
|
||||
['stringappend_test',
|
||||
'utilities/merge_operators/string_append/stringappend_test.cc',
|
||||
'serial'],
|
||||
['compaction_picker_test', 'db/compaction_picker_test.cc', 'serial'],
|
||||
['corruption_test', 'db/corruption_test.cc', 'serial'],
|
||||
['thread_list_test', 'util/thread_list_test.cc', 'serial'],
|
||||
['table_properties_collector_test',
|
||||
'db/table_properties_collector_test.cc',
|
||||
'serial'],
|
||||
['table_test', 'table/table_test.cc', 'parallel'],
|
||||
['thread_list_test', 'util/thread_list_test.cc', 'serial'],
|
||||
['thread_local_test', 'util/thread_local_test.cc', 'serial'],
|
||||
['timer_queue_test', 'util/timer_queue_test.cc', 'serial'],
|
||||
['transaction_test', 'utilities/transactions/transaction_test.cc', 'serial'],
|
||||
['ttl_test', 'utilities/ttl/ttl_test.cc', 'serial'],
|
||||
['util_merge_operators_test',
|
||||
'utilities/util_merge_operators_test.cc',
|
||||
['document_db_test', 'utilities/document/document_db_test.cc', 'serial'],
|
||||
['event_logger_test', 'util/event_logger_test.cc', 'serial'],
|
||||
['coding_test', 'util/coding_test.cc', 'serial'],
|
||||
['statistics_test', 'monitoring/statistics_test.cc', 'serial'],
|
||||
['options_settable_test', 'options/options_settable_test.cc', 'serial'],
|
||||
['sst_dump_test', 'tools/sst_dump_test.cc', 'serial'],
|
||||
['column_aware_encoding_test',
|
||||
'utilities/column_aware_encoding_test.cc',
|
||||
'serial'],
|
||||
['version_builder_test', 'db/version_builder_test.cc', 'serial'],
|
||||
['version_edit_test', 'db/version_edit_test.cc', 'serial'],
|
||||
['db_iterator_test', 'db/db_iterator_test.cc', 'serial'],
|
||||
['db_sst_test', 'db/db_sst_test.cc', 'parallel'],
|
||||
['geodb_test', 'utilities/geodb/geodb_test.cc', 'serial'],
|
||||
['listener_test', 'db/listener_test.cc', 'serial'],
|
||||
['write_callback_test', 'db/write_callback_test.cc', 'serial'],
|
||||
['version_set_test', 'db/version_set_test.cc', 'serial'],
|
||||
['wal_manager_test', 'db/wal_manager_test.cc', 'serial'],
|
||||
['write_batch_test', 'db/write_batch_test.cc', 'serial'],
|
||||
['full_filter_block_test', 'table/full_filter_block_test.cc', 'serial'],
|
||||
['cleanable_test', 'table/cleanable_test.cc', 'serial'],
|
||||
['checkpoint_test', 'utilities/checkpoint/checkpoint_test.cc', 'serial'],
|
||||
['compact_files_test', 'db/compact_files_test.cc', 'serial'],
|
||||
['db_options_test', 'db/db_options_test.cc', 'serial'],
|
||||
['object_registry_test', 'utilities/object_registry_test.cc', 'serial'],
|
||||
['auto_roll_logger_test', 'util/auto_roll_logger_test.cc', 'serial'],
|
||||
['dbformat_test', 'db/dbformat_test.cc', 'serial'],
|
||||
['write_batch_with_index_test',
|
||||
'utilities/write_batch_with_index/write_batch_with_index_test.cc',
|
||||
'serial'],
|
||||
['write_buffer_manager_test',
|
||||
'memtable/write_buffer_manager_test.cc',
|
||||
['json_document_test', 'utilities/document/json_document_test.cc', 'serial'],
|
||||
['file_reader_writer_test', 'util/file_reader_writer_test.cc', 'serial'],
|
||||
['repair_test', 'db/repair_test.cc', 'serial'],
|
||||
['persistent_cache_test',
|
||||
'utilities/persistent_cache/persistent_cache_test.cc',
|
||||
'parallel'],
|
||||
['db_bloom_filter_test', 'db/db_bloom_filter_test.cc', 'serial'],
|
||||
['external_sst_file_basic_test',
|
||||
'db/external_sst_file_basic_test.cc',
|
||||
'serial'],
|
||||
['write_callback_test', 'db/write_callback_test.cc', 'serial'],
|
||||
['write_controller_test', 'db/write_controller_test.cc', 'serial']]
|
||||
['options_test', 'options/options_test.cc', 'serial'],
|
||||
['perf_context_test', 'db/perf_context_test.cc', 'serial'],
|
||||
['db_block_cache_test', 'db/db_block_cache_test.cc', 'serial'],
|
||||
['heap_test', 'util/heap_test.cc', 'serial'],
|
||||
['db_test2', 'db/db_test2.cc', 'serial'],
|
||||
['filelock_test', 'util/filelock_test.cc', 'serial'],
|
||||
['write_controller_test', 'db/write_controller_test.cc', 'serial'],
|
||||
['compaction_iterator_test', 'db/compaction_iterator_test.cc', 'serial'],
|
||||
['spatial_db_test', 'utilities/spatialdb/spatial_db_test.cc', 'serial'],
|
||||
['c_test', 'db/c_test.c', 'serial'],
|
||||
['range_del_aggregator_test', 'db/range_del_aggregator_test.cc', 'serial'],
|
||||
['date_tiered_test', 'utilities/date_tiered/date_tiered_test.cc', 'serial'],
|
||||
['ldb_cmd_test', 'tools/ldb_cmd_test.cc', 'serial'],
|
||||
['db_test', 'db/db_test.cc', 'parallel'],
|
||||
['block_based_filter_block_test',
|
||||
'table/block_based_filter_block_test.cc',
|
||||
'serial'],
|
||||
['merge_test', 'db/merge_test.cc', 'serial'],
|
||||
['bloom_test', 'util/bloom_test.cc', 'serial'],
|
||||
['block_test', 'table/block_test.cc', 'serial'],
|
||||
['cuckoo_table_builder_test', 'table/cuckoo_table_builder_test.cc', 'serial'],
|
||||
['backupable_db_test',
|
||||
'utilities/backupable/backupable_db_test.cc',
|
||||
'parallel'],
|
||||
['db_flush_test', 'db/db_flush_test.cc', 'serial'],
|
||||
['filename_test', 'db/filename_test.cc', 'serial'],
|
||||
['cuckoo_table_reader_test', 'table/cuckoo_table_reader_test.cc', 'serial'],
|
||||
['slice_transform_test', 'util/slice_transform_test.cc', 'serial'],
|
||||
['cuckoo_table_db_test', 'db/cuckoo_table_db_test.cc', 'serial'],
|
||||
['inlineskiplist_test', 'memtable/inlineskiplist_test.cc', 'parallel'],
|
||||
['optimistic_transaction_test',
|
||||
'utilities/transactions/optimistic_transaction_test.cc',
|
||||
'serial'],
|
||||
['hash_table_test',
|
||||
'utilities/persistent_cache/hash_table_test.cc',
|
||||
'serial'],
|
||||
['db_dynamic_level_test', 'db/db_dynamic_level_test.cc', 'serial'],
|
||||
['option_change_migration_test',
|
||||
'utilities/option_change_migration/option_change_migration_test.cc',
|
||||
'serial'],
|
||||
['db_inplace_update_test', 'db/db_inplace_update_test.cc', 'serial'],
|
||||
['autovector_test', 'util/autovector_test.cc', 'serial'],
|
||||
['db_iter_test', 'db/db_iter_test.cc', 'serial'],
|
||||
['flush_job_test', 'db/flush_job_test.cc', 'serial'],
|
||||
['wal_manager_test', 'db/wal_manager_test.cc', 'serial'],
|
||||
['write_batch_test', 'db/write_batch_test.cc', 'serial'],
|
||||
['crc32c_test', 'util/crc32c_test.cc', 'serial'],
|
||||
['rate_limiter_test', 'util/rate_limiter_test.cc', 'serial'],
|
||||
['external_sst_file_test', 'db/external_sst_file_test.cc', 'parallel'],
|
||||
['compaction_job_test', 'db/compaction_job_test.cc', 'serial'],
|
||||
['mock_env_test', 'env/mock_env_test.cc', 'serial'],
|
||||
['db_table_properties_test', 'db/db_table_properties_test.cc', 'serial'],
|
||||
['db_compaction_test', 'db/db_compaction_test.cc', 'parallel'],
|
||||
['arena_test', 'util/arena_test.cc', 'serial'],
|
||||
['stringappend_test',
|
||||
'utilities/merge_operators/string_append/stringappend_test.cc',
|
||||
'serial'],
|
||||
['reduce_levels_test', 'tools/reduce_levels_test.cc', 'serial'],
|
||||
['prefix_test', 'db/prefix_test.cc', 'serial'],
|
||||
['ttl_test', 'utilities/ttl/ttl_test.cc', 'serial'],
|
||||
['merge_helper_test', 'db/merge_helper_test.cc', 'serial'],
|
||||
['file_indexer_test', 'db/file_indexer_test.cc', 'serial'],
|
||||
['memory_test', 'utilities/memory/memory_test.cc', 'serial'],
|
||||
['log_test', 'db/log_test.cc', 'serial'],
|
||||
['env_timed_test', 'utilities/env_timed_test.cc', 'serial'],
|
||||
['deletefile_test', 'db/deletefile_test.cc', 'serial'],
|
||||
['partitioned_filter_block_test',
|
||||
'table/partitioned_filter_block_test.cc',
|
||||
'serial'],
|
||||
['comparator_db_test', 'db/comparator_db_test.cc', 'serial'],
|
||||
['compaction_job_stats_test', 'db/compaction_job_stats_test.cc', 'serial'],
|
||||
['thread_local_test', 'util/thread_local_test.cc', 'serial'],
|
||||
['version_builder_test', 'db/version_builder_test.cc', 'serial'],
|
||||
['db_range_del_test', 'db/db_range_del_test.cc', 'serial'],
|
||||
['table_test', 'table/table_test.cc', 'parallel'],
|
||||
['db_tailing_iter_test', 'db/db_tailing_iter_test.cc', 'serial'],
|
||||
['db_compaction_filter_test', 'db/db_compaction_filter_test.cc', 'parallel'],
|
||||
['options_util_test', 'utilities/options/options_util_test.cc', 'serial'],
|
||||
['dynamic_bloom_test', 'util/dynamic_bloom_test.cc', 'serial'],
|
||||
['db_basic_test', 'db/db_basic_test.cc', 'serial'],
|
||||
['db_merge_operator_test', 'db/db_merge_operator_test.cc', 'serial'],
|
||||
['manual_compaction_test', 'db/manual_compaction_test.cc', 'parallel'],
|
||||
['delete_scheduler_test', 'util/delete_scheduler_test.cc', 'serial'],
|
||||
['transaction_test', 'utilities/transactions/transaction_test.cc', 'serial'],
|
||||
['db_io_failure_test', 'db/db_io_failure_test.cc', 'serial'],
|
||||
['db_log_iter_test', 'db/db_log_iter_test.cc', 'serial'],
|
||||
['compact_on_deletion_collector_test',
|
||||
'utilities/table_properties_collectors/compact_on_deletion_collector_test.cc',
|
||||
'serial'],
|
||||
['env_test', 'env/env_test.cc', 'serial'],
|
||||
['db_wal_test', 'db/db_wal_test.cc', 'parallel'],
|
||||
['sim_cache_test', 'utilities/simulator_cache/sim_cache_test.cc', 'serial'],
|
||||
['db_memtable_test', 'db/db_memtable_test.cc', 'serial'],
|
||||
['db_universal_compaction_test',
|
||||
'db/db_universal_compaction_test.cc',
|
||||
'parallel'],
|
||||
['histogram_test', 'monitoring/histogram_test.cc', 'serial'],
|
||||
['util_merge_operators_test',
|
||||
'utilities/util_merge_operators_test.cc',
|
||||
'serial'],
|
||||
['fault_injection_test', 'db/fault_injection_test.cc', 'parallel'],
|
||||
['env_basic_test', 'env/env_basic_test.cc', 'serial'],
|
||||
['iostats_context_test', 'monitoring/iostats_context_test.cc', 'serial'],
|
||||
['memtable_list_test', 'db/memtable_list_test.cc', 'serial'],
|
||||
['column_family_test', 'db/column_family_test.cc', 'serial'],
|
||||
['db_properties_test', 'db/db_properties_test.cc', 'serial'],
|
||||
['version_edit_test', 'db/version_edit_test.cc', 'serial'],
|
||||
['skiplist_test', 'memtable/skiplist_test.cc', 'serial'],
|
||||
['lru_cache_test', 'cache/lru_cache_test.cc', 'serial'],
|
||||
['plain_table_db_test', 'db/plain_table_db_test.cc', 'serial'],
|
||||
['db_statistics_test', 'db/db_statistics_test.cc', 'serial']]
|
||||
|
||||
|
||||
# Generate a test rule for each entry in ROCKS_TESTS
|
||||
@@ -509,7 +465,6 @@ for test_cfg in ROCKS_TESTS:
|
||||
srcs = [test_cc],
|
||||
deps = [":rocksdb_test_lib"],
|
||||
preprocessor_flags = rocksdb_preprocessor_flags,
|
||||
arch_preprocessor_flags = rocksdb_arch_preprocessor_flags,
|
||||
compiler_flags = rocksdb_compiler_flags,
|
||||
external_deps = rocksdb_external_deps,
|
||||
)
|
||||
@@ -520,15 +475,3 @@ for test_cfg in ROCKS_TESTS:
|
||||
deps = [":" + test_bin],
|
||||
command = [TEST_RUNNER, BUCK_BINS + test_bin]
|
||||
)
|
||||
|
||||
custom_unittest(
|
||||
name = "make_rocksdbjavastatic",
|
||||
type = "simple",
|
||||
command = ["internal_repo_rocksdb/make_rocksdbjavastatic.sh"],
|
||||
)
|
||||
|
||||
custom_unittest(
|
||||
name = "make_rocksdb_lite_release",
|
||||
type = "simple",
|
||||
command = ["internal_repo_rocksdb/make_rocksdb_lite_release.sh"],
|
||||
)
|
||||
@@ -76,10 +76,7 @@ quasardb uses a heavily tuned RocksDB as its persistence layer.
|
||||
[Dgraph](https://github.com/dgraph-io/dgraph) is an open-source, scalable, distributed, low latency, high throughput Graph database .They use RocksDB to store state locally on a machine.
|
||||
|
||||
## Uber
|
||||
[Uber](http://eng.uber.com/cherami/) uses RocksDB as a durable and scalable task queue.
|
||||
[Uber](http://eng.uber.com/cherami/) uses RocksDB as a durable and and scalable task queue.
|
||||
|
||||
## 360 Pika
|
||||
[360](http://www.360.cn/) [Pika](https://github.com/Qihoo360/pika) is a nosql compatible with redis. With the huge amount of data stored, redis may suffer for a capacity bottleneck, and pika was born for solving it. It has widely been widely used in many company
|
||||
|
||||
## LzLabs
|
||||
LzLabs is using RocksDB as a storage engine in their multi-database distributed framework to store application configuration and user data.
|
||||
+1
-1
@@ -3,7 +3,7 @@ image: Visual Studio 2015
|
||||
before_build:
|
||||
- md %APPVEYOR_BUILD_FOLDER%\build
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\build
|
||||
- cmake -G "Visual Studio 14 2015 Win64" -DOPTDBG=1 -DXPRESS=1 -DPORTABLE=1 ..
|
||||
- cmake -G "Visual Studio 14 2015 Win64" -DOPTDBG=1 -DXPRESS=1 ..
|
||||
- cd ..
|
||||
build:
|
||||
project: build\rocksdb.sln
|
||||
|
||||
@@ -84,7 +84,7 @@ def get_tests(repo_path):
|
||||
else:
|
||||
# we consumed all the parallel tests
|
||||
break
|
||||
|
||||
|
||||
return tests
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ def generate_targets(repo_path):
|
||||
[":rocksdb_lib"])
|
||||
|
||||
# test for every test we found in the Makefile
|
||||
for test in sorted(tests):
|
||||
for test in tests:
|
||||
match_src = [src for src in cc_files if ("/%s.c" % test) in src]
|
||||
if len(match_src) == 0:
|
||||
print(ColorString.warning("Cannot find .cc file for %s" % test))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
# Create a tmp directory for the test to use
|
||||
TEST_DIR=$(mktemp -d /dev/shm/fbcode_rocksdb_XXXXXXX)
|
||||
TEST_TMPDIR="$TEST_DIR" $@ && rm -rf "$TEST_DIR"
|
||||
@@ -2,22 +2,17 @@ from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
rocksdb_target_header = """
|
||||
import os
|
||||
|
||||
TARGETS_PATH = os.path.dirname(__file__)
|
||||
REPO_PATH = "rocksdb/src/"
|
||||
rocksdb_target_header = """REPO_PATH = "internal_repo_rocksdb/repo/"
|
||||
BUCK_BINS = "buck-out/gen/" + REPO_PATH
|
||||
TEST_RUNNER = REPO_PATH + "buckifier/rocks_test_runner.sh"
|
||||
rocksdb_compiler_flags = [
|
||||
"-msse",
|
||||
"-msse4.2",
|
||||
"-fno-builtin-memcmp",
|
||||
"-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",
|
||||
"-DOS_LINUX",
|
||||
# Flags to enable libs we include
|
||||
"-DSNAPPY",
|
||||
@@ -40,7 +35,7 @@ rocksdb_external_deps = [
|
||||
('lz4', None, 'lz4'),
|
||||
('zstd', None),
|
||||
('tbb', None),
|
||||
("numa", None, "numa"),
|
||||
("numa", "2.0.8", "numa"),
|
||||
("googletest", None, "gtest"),
|
||||
]
|
||||
|
||||
@@ -49,10 +44,6 @@ rocksdb_preprocessor_flags = [
|
||||
"-I" + REPO_PATH + "include/",
|
||||
"-I" + REPO_PATH,
|
||||
]
|
||||
|
||||
rocksdb_arch_preprocessor_flags = {
|
||||
"x86_64": ["-DHAVE_SSE42"],
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
@@ -63,7 +54,6 @@ cpp_library(
|
||||
srcs = [%s],
|
||||
deps = [%s],
|
||||
preprocessor_flags = rocksdb_preprocessor_flags,
|
||||
arch_preprocessor_flags = rocksdb_arch_preprocessor_flags,
|
||||
compiler_flags = rocksdb_compiler_flags,
|
||||
external_deps = rocksdb_external_deps,
|
||||
)
|
||||
@@ -75,7 +65,6 @@ cpp_binary(
|
||||
srcs = [%s],
|
||||
deps = [%s],
|
||||
preprocessor_flags = rocksdb_preprocessor_flags,
|
||||
arch_preprocessor_flags = rocksdb_arch_preprocessor_flags,
|
||||
compiler_flags = rocksdb_compiler_flags,
|
||||
external_deps = rocksdb_external_deps,
|
||||
)
|
||||
@@ -98,7 +87,6 @@ for test_cfg in ROCKS_TESTS:
|
||||
srcs = [test_cc],
|
||||
deps = [":rocksdb_test_lib"],
|
||||
preprocessor_flags = rocksdb_preprocessor_flags,
|
||||
arch_preprocessor_flags = rocksdb_arch_preprocessor_flags,
|
||||
compiler_flags = rocksdb_compiler_flags,
|
||||
external_deps = rocksdb_external_deps,
|
||||
)
|
||||
|
||||
@@ -1,377 +0,0 @@
|
||||
<?php
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
|
||||
// Name of the environment variables which need to be set by the entity which
|
||||
// triggers continuous runs so that code at the end of the file gets executed
|
||||
// and Sandcastle run starts.
|
||||
define("ENV_POST_RECEIVE_HOOK", "POST_RECEIVE_HOOK");
|
||||
define("ENV_HTTPS_APP_VALUE", "HTTPS_APP_VALUE");
|
||||
define("ENV_HTTPS_TOKEN_VALUE", "HTTPS_TOKEN_VALUE");
|
||||
|
||||
define("PRIMARY_TOKEN_FILE", '/home/krad/.sandcastle');
|
||||
define("CONT_RUN_ALIAS", "leveldb");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
/* Run tests in sandcastle */
|
||||
function postURL($diffID, $url) {
|
||||
assert(strlen($diffID) > 0);
|
||||
assert(is_numeric($diffID));
|
||||
assert(strlen($url) > 0);
|
||||
|
||||
$cmd_args = array(
|
||||
'diff_id' => (int)$diffID,
|
||||
'name' => sprintf(
|
||||
'click here for sandcastle tests for D%d',
|
||||
(int)$diffID
|
||||
),
|
||||
'link' => $url
|
||||
);
|
||||
$cmd = 'echo ' . escapeshellarg(json_encode($cmd_args))
|
||||
. ' | arc call-conduit differential.updateunitresults';
|
||||
|
||||
shell_exec($cmd);
|
||||
}
|
||||
|
||||
function buildUpdateTestStatusCmd($diffID, $test, $status) {
|
||||
assert(strlen($diffID) > 0);
|
||||
assert(is_numeric($diffID));
|
||||
assert(strlen($test) > 0);
|
||||
assert(strlen($status) > 0);
|
||||
|
||||
$cmd_args = array(
|
||||
'diff_id' => (int)$diffID,
|
||||
'name' => $test,
|
||||
'result' => $status
|
||||
);
|
||||
|
||||
$cmd = 'echo ' . escapeshellarg(json_encode($cmd_args))
|
||||
. ' | arc call-conduit differential.updateunitresults';
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
function updateTestStatus($diffID, $test) {
|
||||
assert(strlen($diffID) > 0);
|
||||
assert(is_numeric($diffID));
|
||||
assert(strlen($test) > 0);
|
||||
|
||||
shell_exec(buildUpdateTestStatusCmd($diffID, $test, "waiting"));
|
||||
}
|
||||
|
||||
function getSteps($applyDiff, $diffID, $username, $test) {
|
||||
assert(strlen($username) > 0);
|
||||
assert(strlen($test) > 0);
|
||||
|
||||
if ($applyDiff) {
|
||||
assert(strlen($diffID) > 0);
|
||||
assert(is_numeric($diffID));
|
||||
|
||||
$arcrc_content = (PHP_OS == "Darwin" ?
|
||||
exec("cat ~/.arcrc | gzip -f | base64") :
|
||||
exec("cat ~/.arcrc | gzip -f | base64 -w0"));
|
||||
assert(strlen($arcrc_content) > 0);
|
||||
|
||||
// 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 " . escapeshellarg($arcrc_content) . " | base64 --decode"
|
||||
. " | gzip -d > ~/.arcrc",
|
||||
"user" => "root"
|
||||
);
|
||||
|
||||
// arc demands certain permission on its config.
|
||||
// also fix the sticky bit issue in sandcastle
|
||||
$fix_permission = array(
|
||||
"name" => "Fix environment",
|
||||
"shell" => "chmod 600 ~/.arcrc && chmod +t /dev/shm",
|
||||
"user" => "root"
|
||||
);
|
||||
|
||||
// Construct the steps in the order of execution.
|
||||
$steps[] = $setup;
|
||||
$steps[] = $fix_permission;
|
||||
}
|
||||
|
||||
// fbcode is a sub-repo. We cannot patch until we add it to ignore otherwise
|
||||
// Git thinks it is an uncommited change.
|
||||
$fix_git_ignore = array(
|
||||
"name" => "Fix git ignore",
|
||||
"shell" => "echo fbcode >> .git/info/exclude",
|
||||
"user" => "root"
|
||||
);
|
||||
|
||||
// This fixes "FATAL: ThreadSanitizer can not mmap the shadow memory"
|
||||
// Source:
|
||||
// https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual#FAQ
|
||||
$fix_kernel_issue = array(
|
||||
"name" => "Fix kernel issue with tsan",
|
||||
"shell" => "echo 2 >/proc/sys/kernel/randomize_va_space",
|
||||
"user" => "root"
|
||||
);
|
||||
|
||||
$steps[] = $fix_git_ignore;
|
||||
$steps[] = $fix_kernel_issue;
|
||||
|
||||
// This will be the command used to execute particular type of tests.
|
||||
$cmd = "";
|
||||
|
||||
if ($applyDiff) {
|
||||
// Patch the code (keep your fingures crossed).
|
||||
$patch = array(
|
||||
"name" => "Patch " . $diffID,
|
||||
"shell" => "arc --arcrc-file ~/.arcrc "
|
||||
. "patch --nocommit --diff " . escapeshellarg($diffID),
|
||||
"user" => "root"
|
||||
);
|
||||
|
||||
$steps[] = $patch;
|
||||
|
||||
updateTestStatus($diffID, $test);
|
||||
$cmd = buildUpdateTestStatusCmd($diffID, $test, "running") . "; ";
|
||||
}
|
||||
|
||||
// Run the actual command.
|
||||
$cmd = $cmd . "J=$(nproc) ./build_tools/precommit_checker.py " .
|
||||
escapeshellarg($test) . "; exit_code=$?; ";
|
||||
|
||||
if ($applyDiff) {
|
||||
$cmd = $cmd . "([[ \$exit_code -eq 0 ]] &&"
|
||||
. buildUpdateTestStatusCmd($diffID, $test, "pass") . ")"
|
||||
. "||" . buildUpdateTestStatusCmd($diffID, $test, "fail")
|
||||
. "; ";
|
||||
}
|
||||
|
||||
// shell command to sort the tests based on exit code and print
|
||||
// the output of the log files.
|
||||
$cat_sorted_logs = "
|
||||
while read code log_file;
|
||||
do echo \"################ cat \$log_file [exit_code : \$code] ################\";
|
||||
cat \$log_file;
|
||||
done < <(tail -n +2 LOG | sort -k7,7n -k4,4gr | awk '{print \$7,\$NF}')";
|
||||
|
||||
// Shell command to cat all log files
|
||||
$cat_all_logs = "for f in `ls t/!(run-*)`; do echo \$f;cat \$f; done";
|
||||
|
||||
// If LOG file exist use it to cat log files sorted by exit code, otherwise
|
||||
// cat everything
|
||||
$logs_cmd = "if [ -f LOG ]; then {$cat_sorted_logs}; else {$cat_all_logs}; fi";
|
||||
|
||||
$cmd = $cmd . " cat /tmp/precommit-check.log"
|
||||
. "; shopt -s extglob; {$logs_cmd}"
|
||||
. "; shopt -u extglob; [[ \$exit_code -eq 0 ]]";
|
||||
assert(strlen($cmd) > 0);
|
||||
|
||||
$run_test = array(
|
||||
"name" => "Run " . $test,
|
||||
"shell" => $cmd,
|
||||
"user" => "root",
|
||||
"parser" => "python build_tools/error_filter.py " . escapeshellarg($test),
|
||||
);
|
||||
|
||||
$steps[] = $run_test;
|
||||
|
||||
if ($applyDiff) {
|
||||
// Clean up the user arc config we are using.
|
||||
$cleanup = array(
|
||||
"name" => "Arc cleanup",
|
||||
"shell" => "rm -f ~/.arcrc",
|
||||
"user" => "root"
|
||||
);
|
||||
|
||||
$steps[] = $cleanup;
|
||||
}
|
||||
|
||||
assert(count($steps) > 0);
|
||||
return $steps;
|
||||
}
|
||||
|
||||
function getSandcastleConfig() {
|
||||
$sandcastle_config = array();
|
||||
|
||||
$cwd = getcwd();
|
||||
$cwd_token_file = "{$cwd}/.sandcastle";
|
||||
// This is a case when we're executed from a continuous run. Fetch the values
|
||||
// from the environment.
|
||||
if (getenv(ENV_POST_RECEIVE_HOOK)) {
|
||||
$sandcastle_config[0] = getenv(ENV_HTTPS_APP_VALUE);
|
||||
$sandcastle_config[1] = getenv(ENV_HTTPS_TOKEN_VALUE);
|
||||
} else {
|
||||
// This is a typical `[p]arc diff` case. Fetch the values from the specific
|
||||
// configuration files.
|
||||
for ($i = 0; $i < 50; $i++) {
|
||||
if (file_exists(PRIMARY_TOKEN_FILE) ||
|
||||
file_exists($cwd_token_file)) {
|
||||
break;
|
||||
}
|
||||
// If we failed to fetch the tokens, sleep for 0.2 second and try again
|
||||
usleep(200000);
|
||||
}
|
||||
assert(file_exists(PRIMARY_TOKEN_FILE) ||
|
||||
file_exists($cwd_token_file));
|
||||
|
||||
// Try the primary location first, followed by a secondary.
|
||||
if (file_exists(PRIMARY_TOKEN_FILE)) {
|
||||
$cmd = 'cat ' . PRIMARY_TOKEN_FILE;
|
||||
} else {
|
||||
$cmd = 'cat ' . escapeshellarg($cwd_token_file);
|
||||
}
|
||||
|
||||
assert(strlen($cmd) > 0);
|
||||
$sandcastle_config = explode(':', rtrim(shell_exec($cmd)));
|
||||
}
|
||||
|
||||
// In this case be very explicit about the implications.
|
||||
if (count($sandcastle_config) != 2) {
|
||||
echo "Sandcastle configuration files don't contain valid information " .
|
||||
"or the necessary environment variables aren't defined. Unable " .
|
||||
"to validate the code changes.";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert(strlen($sandcastle_config[0]) > 0);
|
||||
assert(strlen($sandcastle_config[1]) > 0);
|
||||
assert(count($sandcastle_config) > 0);
|
||||
|
||||
return $sandcastle_config;
|
||||
}
|
||||
|
||||
// This function can be called either from `[p]arc diff` command or during
|
||||
// the Git post-receive hook.
|
||||
function startTestsInSandcastle($applyDiff, $workflow, $diffID) {
|
||||
// Default options don't terminate on failure, but that's what we want. In
|
||||
// the current case we use assertions intentionally as "terminate on failure
|
||||
// invariants".
|
||||
assert_options(ASSERT_BAIL, true);
|
||||
|
||||
// In case of a diff we'll send notificatios to the author. Else it'll go to
|
||||
// the entire team because failures indicate that build quality has regressed.
|
||||
$username = $applyDiff ? exec("whoami") : CONT_RUN_ALIAS;
|
||||
assert(strlen($username) > 0);
|
||||
|
||||
if ($applyDiff) {
|
||||
assert($workflow);
|
||||
assert(strlen($diffID) > 0);
|
||||
assert(is_numeric($diffID));
|
||||
}
|
||||
|
||||
// List of tests we want to run in Sandcastle.
|
||||
$tests = array("unit", "unit_non_shm", "unit_481", "clang_unit", "tsan",
|
||||
"asan", "lite_test", "valgrind", "release", "release_481",
|
||||
"clang_release", "clang_analyze", "code_cov",
|
||||
"java_build", "no_compression", "unity", "ubsan");
|
||||
|
||||
$send_email_template = array(
|
||||
'type' => 'email',
|
||||
'triggers' => array('fail'),
|
||||
'emails' => array($username . '@fb.com'),
|
||||
);
|
||||
|
||||
// Construct a job definition for each test and add it to the master plan.
|
||||
foreach ($tests as $test) {
|
||||
$stepName = "RocksDB diff " . $diffID . " test " . $test;
|
||||
|
||||
if (!$applyDiff) {
|
||||
$stepName = "RocksDB continuous integration test " . $test;
|
||||
}
|
||||
|
||||
$arg[] = array(
|
||||
"name" => $stepName,
|
||||
"report" => array($send_email_template),
|
||||
"steps" => getSteps($applyDiff, $diffID, $username, $test)
|
||||
);
|
||||
}
|
||||
|
||||
// We cannot submit the parallel execution master plan to Sandcastle and
|
||||
// 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 the job definitions? Otherwise we run over the max
|
||||
// string size.
|
||||
$cmd = "echo " . base64_encode(json_encode($arg))
|
||||
. (PHP_OS == "Darwin" ?
|
||||
" | gzip -f | base64" :
|
||||
" | gzip -f | base64 -w0");
|
||||
assert(strlen($cmd) > 0);
|
||||
|
||||
$arg_encoded = shell_exec($cmd);
|
||||
assert(strlen($arg_encoded) > 0);
|
||||
|
||||
$runName = "Run diff " . $diffID . "for user " . $username;
|
||||
|
||||
if (!$applyDiff) {
|
||||
$runName = "RocksDB continuous integration build and test run";
|
||||
}
|
||||
|
||||
$command = array(
|
||||
"name" => $runName,
|
||||
"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/create';
|
||||
|
||||
$job = array(
|
||||
'command' => 'SandcastleUniversalCommand',
|
||||
'args' => $command,
|
||||
'capabilities' => array(
|
||||
'vcs' => 'rocksdb-int-git',
|
||||
'type' => 'lego',
|
||||
),
|
||||
'hash' => 'origin/master',
|
||||
'user' => $username,
|
||||
'alias' => 'rocksdb-precommit',
|
||||
'tags' => array('rocksdb'),
|
||||
'description' => 'Rocksdb precommit job',
|
||||
);
|
||||
|
||||
// Fetch the configuration necessary to submit a successful HTTPS request.
|
||||
$sandcastle_config = getSandcastleConfig();
|
||||
|
||||
$app = $sandcastle_config[0];
|
||||
$token = $sandcastle_config[1];
|
||||
|
||||
$cmd = 'curl -s -k '
|
||||
. ' -F app=' . escapeshellarg($app)
|
||||
. ' -F token=' . escapeshellarg($token)
|
||||
. ' -F job=' . escapeshellarg(json_encode($job))
|
||||
.' ' . escapeshellarg($url);
|
||||
|
||||
$output = shell_exec($cmd);
|
||||
assert(strlen($output) > 0);
|
||||
|
||||
// Extract Sandcastle URL from the response.
|
||||
preg_match('/url": "(.+)"/', $output, $sandcastle_url);
|
||||
|
||||
assert(count($sandcastle_url) > 0, "Unable to submit Sandcastle request.");
|
||||
assert(strlen($sandcastle_url[1]) > 0, "Unable to extract Sandcastle URL.");
|
||||
|
||||
if ($applyDiff) {
|
||||
echo "\nSandcastle URL: " . $sandcastle_url[1] . "\n";
|
||||
// Ask Phabricator to display it on the diff UI.
|
||||
postURL($diffID, $sandcastle_url[1]);
|
||||
} else {
|
||||
echo "Continuous integration started Sandcastle tests. You can look at ";
|
||||
echo "the progress at:\n" . $sandcastle_url[1] . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Continuous run cript will set the environment variable and based on that
|
||||
// we'll trigger the execution of tests in Sandcastle. In that case we don't
|
||||
// need to apply any diffs and there's no associated workflow either.
|
||||
if (getenv(ENV_POST_RECEIVE_HOOK)) {
|
||||
startTestsInSandcastle(
|
||||
false /* $applyDiff */,
|
||||
NULL /* $workflow */,
|
||||
NULL /* $diffID */);
|
||||
}
|
||||
@@ -51,14 +51,7 @@ if [ -z "$ROCKSDB_NO_FBCODE" -a -d /mnt/gvfs/third-party ]; then
|
||||
FBCODE_BUILD="true"
|
||||
# If we're compiling with TSAN we need pic build
|
||||
PIC_BUILD=$COMPILE_WITH_TSAN
|
||||
if [ -n "$ROCKSDB_FBCODE_BUILD_WITH_481" ]; then
|
||||
# we need this to build with MySQL. Don't use for other purposes.
|
||||
source "$PWD/build_tools/fbcode_config4.8.1.sh"
|
||||
elif [ -n "$ROCKSDB_FBCODE_BUILD_WITH_5xx" ]; then
|
||||
source "$PWD/build_tools/fbcode_config.sh"
|
||||
else
|
||||
source "$PWD/build_tools/fbcode_config_platform007.sh"
|
||||
fi
|
||||
source "$PWD/build_tools/fbcode_config.sh"
|
||||
fi
|
||||
|
||||
# Delete existing output, if it exists
|
||||
@@ -130,17 +123,10 @@ case "$TARGET_OS" in
|
||||
;;
|
||||
SunOS)
|
||||
PLATFORM=OS_SOLARIS
|
||||
COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp -D_REENTRANT -DOS_SOLARIS -m64"
|
||||
PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lpthread -lrt -static-libstdc++ -static-libgcc -m64"
|
||||
COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp -D_REENTRANT -DOS_SOLARIS"
|
||||
PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -lpthread -lrt"
|
||||
# PORT_FILES=port/sunos/sunos_specific.cc
|
||||
;;
|
||||
AIX)
|
||||
PLATFORM=OS_AIX
|
||||
CC=gcc
|
||||
COMMON_FLAGS="$COMMON_FLAGS -maix64 -pthread -fno-builtin-memcmp -D_REENTRANT -DOS_AIX -D__STDC_FORMAT_MACROS"
|
||||
PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -pthread -lpthread -lrt -maix64 -static-libstdc++ -static-libgcc"
|
||||
# PORT_FILES=port/aix/aix_specific.cc
|
||||
;;
|
||||
FreeBSD)
|
||||
PLATFORM=OS_FREEBSD
|
||||
COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp -D_REENTRANT -DOS_FREEBSD"
|
||||
@@ -319,11 +305,9 @@ EOF
|
||||
# Test whether jemalloc is available
|
||||
if echo 'int main() {}' | $CXX $CFLAGS -x c++ - -o /dev/null -ljemalloc \
|
||||
2>/dev/null; then
|
||||
# This will enable some preprocessor identifiers in the Makefile
|
||||
PLATFORM_LDFLAGS="$PLATFORM_LDFLAGS -ljemalloc"
|
||||
JAVA_LDFLAGS="$JAVA_LDFLAGS -ljemalloc"
|
||||
JEMALLOC=1
|
||||
# JEMALLOC can be enabled either using the flag (like here) or by
|
||||
# providing direct link to the jemalloc library
|
||||
WITH_JEMALLOC_FLAG=1
|
||||
else
|
||||
# jemalloc is not available. Let's try tcmalloc
|
||||
if echo 'int main() {}' | $CXX $CFLAGS -x c++ - -o /dev/null \
|
||||
@@ -393,29 +377,6 @@ EOF
|
||||
if [ "$?" = 0 ]; then
|
||||
PROFILING_FLAGS=-pg
|
||||
fi
|
||||
|
||||
# Test whether sync_file_range is supported for compatibility with an old glibc
|
||||
$CXX $CFLAGS -x c++ - -o /dev/null 2>/dev/null <<EOF
|
||||
#include <fcntl.h>
|
||||
int main() {
|
||||
int fd = open("/dev/null", 0);
|
||||
sync_file_range(fd, 0, 1024, SYNC_FILE_RANGE_WRITE);
|
||||
}
|
||||
EOF
|
||||
if [ "$?" = 0 ]; then
|
||||
COMMON_FLAGS="$COMMON_FLAGS -DROCKSDB_RANGESYNC_PRESENT"
|
||||
fi
|
||||
|
||||
# Test whether sched_getcpu is supported
|
||||
$CXX $CFLAGS -x c++ - -o /dev/null 2>/dev/null <<EOF
|
||||
#include <sched.h>
|
||||
int main() {
|
||||
int cpuid = sched_getcpu();
|
||||
}
|
||||
EOF
|
||||
if [ "$?" = 0 ]; then
|
||||
COMMON_FLAGS="$COMMON_FLAGS -DROCKSDB_SCHED_GETCPU_PRESENT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# TODO(tec): Fix -Wshorten-64-to-32 errors on FreeBSD and enable the warning.
|
||||
@@ -446,8 +407,14 @@ if test "$USE_HDFS"; then
|
||||
JAVA_LDFLAGS="$JAVA_LDFLAGS $HDFS_LDFLAGS"
|
||||
fi
|
||||
|
||||
if [ "$TARGET_OS" = FreeBSD -a "$TARGET_ARCHITECTURE" = i386 ]; then
|
||||
# Intel SSE instructions breaks compilation on FreeBSD i386
|
||||
unset USE_SSE
|
||||
fi
|
||||
|
||||
if test "$USE_SSE"; then
|
||||
COMMON_FLAGS="$COMMON_FLAGS -msse4.2"
|
||||
# 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
|
||||
@@ -455,41 +422,11 @@ elif test -z "$PORTABLE"; then
|
||||
COMMON_FLAGS="$COMMON_FLAGS -mcpu=$POWER -mtune=$POWER "
|
||||
elif test -n "`echo $TARGET_ARCHITECTURE | grep ^s390x`"; then
|
||||
COMMON_FLAGS="$COMMON_FLAGS -march=z10 "
|
||||
elif [ "$TARGET_OS" != AIX ] && [ "$TARGET_OS" != SunOS ]; then
|
||||
else
|
||||
COMMON_FLAGS="$COMMON_FLAGS -march=native "
|
||||
fi
|
||||
fi
|
||||
|
||||
$CXX $PLATFORM_CXXFLAGS $COMMON_FLAGS -x c++ - -o /dev/null 2>/dev/null <<EOF
|
||||
#include <cstdint>
|
||||
#include <nmmintrin.h>
|
||||
int main() {
|
||||
volatile uint32_t x = _mm_crc32_u32(0, 0);
|
||||
}
|
||||
EOF
|
||||
if [ "$?" = 0 ]; then
|
||||
COMMON_FLAGS="$COMMON_FLAGS -DHAVE_SSE42"
|
||||
elif test "$USE_SSE"; then
|
||||
echo "warning: USE_SSE specified but compiler could not use SSE intrinsics, disabling"
|
||||
fi
|
||||
|
||||
# iOS doesn't support thread-local storage, but this check would erroneously
|
||||
# succeed because the cross-compiler flags are added by the Makefile, not this
|
||||
# script.
|
||||
if [ "$PLATFORM" != IOS ]; then
|
||||
$CXX $COMMON_FLAGS -x c++ - -o /dev/null 2>/dev/null <<EOF
|
||||
#if defined(_MSC_VER) && !defined(__thread)
|
||||
#define __thread __declspec(thread)
|
||||
#endif
|
||||
int main() {
|
||||
static __thread int tls;
|
||||
}
|
||||
EOF
|
||||
if [ "$?" = 0 ]; then
|
||||
COMMON_FLAGS="$COMMON_FLAGS -DROCKSDB_SUPPORT_THREAD_LOCAL"
|
||||
fi
|
||||
fi
|
||||
|
||||
PLATFORM_CCFLAGS="$PLATFORM_CCFLAGS $COMMON_FLAGS"
|
||||
PLATFORM_CXXFLAGS="$PLATFORM_CXXFLAGS $COMMON_FLAGS"
|
||||
|
||||
@@ -521,14 +458,7 @@ echo "ROCKSDB_PATCH=$ROCKSDB_PATCH" >> "$OUTPUT"
|
||||
echo "CLANG_SCAN_BUILD=$CLANG_SCAN_BUILD" >> "$OUTPUT"
|
||||
echo "CLANG_ANALYZER=$CLANG_ANALYZER" >> "$OUTPUT"
|
||||
echo "PROFILING_FLAGS=$PROFILING_FLAGS" >> "$OUTPUT"
|
||||
# This will enable some related identifiers for the preprocessor
|
||||
if test -n "$JEMALLOC"; then
|
||||
echo "JEMALLOC=1" >> "$OUTPUT"
|
||||
fi
|
||||
# Indicates that jemalloc should be enabled using -ljemalloc flag
|
||||
# The alternative is to porvide a direct link to the library via JEMALLOC_LIB
|
||||
# and JEMALLOC_INCLUDE
|
||||
if test -n "$WITH_JEMALLOC_FLAG"; then
|
||||
echo "WITH_JEMALLOC_FLAG=$WITH_JEMALLOC_FLAG" >> "$OUTPUT"
|
||||
fi
|
||||
echo "LUA_PATH=$LUA_PATH" >> "$OUTPUT"
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2016, Facebook. All rights reserved.
|
||||
#
|
||||
@@ -67,7 +67,7 @@ function update_repo_status {
|
||||
#
|
||||
|
||||
# Path to the determinator from the root of the RocksDB repo.
|
||||
CONTRUN_DETERMINATOR=./build_tools/RocksDBCommonHelper.php
|
||||
CONTRUN_DETERMINATOR=./arcanist_util/config/RocksDBCommonHelper.php
|
||||
|
||||
# Value of the previous commit.
|
||||
PREV_COMMIT=
|
||||
|
||||
+19
-18
@@ -1,18 +1,19 @@
|
||||
GCC_BASE=/mnt/gvfs/third-party2/gcc/2928bb3ed95bf64f5b388ee88c30dc74710c3b35/5.x/centos6-native/f4950a1
|
||||
CLANG_BASE=/mnt/gvfs/third-party2/llvm-fb/a5fea028cb7ba43498976e1f8054b0b2e790c295/stable/centos6-native/6aaf4de
|
||||
LIBGCC_BASE=/mnt/gvfs/third-party2/libgcc/7a9099f6587ee4378c0b1fa32bb8934019d30ca4/5.x/gcc-5-glibc-2.23/339d858
|
||||
GLIBC_BASE=/mnt/gvfs/third-party2/glibc/3b7c6469854dfc7832a1c3cc5b86919a84e5f865/2.23/gcc-5-glibc-2.23/ca1d1c0
|
||||
SNAPPY_BASE=/mnt/gvfs/third-party2/snappy/8c38a4c1e52b4c2cc8a9cdc31b9c947ed7dbfcb4/1.1.3/gcc-5-glibc-2.23/9bc6787
|
||||
ZLIB_BASE=/mnt/gvfs/third-party2/zlib/d7861abe6f0e27ab98c9303b95a662f0e4cdedb5/1.2.8/gcc-5-glibc-2.23/9bc6787
|
||||
BZIP2_BASE=/mnt/gvfs/third-party2/bzip2/740325875f6729f42d28deaa2147b0854f3a347e/1.0.6/gcc-5-glibc-2.23/9bc6787
|
||||
LZ4_BASE=/mnt/gvfs/third-party2/lz4/0815d59804160c96caac5f27ca004f51af893dc6/r131/gcc-5-glibc-2.23/9bc6787
|
||||
ZSTD_BASE=/mnt/gvfs/third-party2/zstd/c15a4f5f619a2930478d01e2e34dc1e0652b0873/1.1.4/gcc-5-glibc-2.23/03859b5
|
||||
GFLAGS_BASE=/mnt/gvfs/third-party2/gflags/f905a5e1032fb30c05db3d3752319857388c0c49/2.2.0/gcc-5-glibc-2.23/9bc6787
|
||||
JEMALLOC_BASE=/mnt/gvfs/third-party2/jemalloc/8d60633d822a2a55849c73db24e74a25e52b71db/master/gcc-5-glibc-2.23/1c32b4b
|
||||
NUMA_BASE=/mnt/gvfs/third-party2/numa/17c514c4d102a25ca15f4558be564eeed76f4b6a/2.0.8/gcc-5-glibc-2.23/9bc6787
|
||||
LIBUNWIND_BASE=/mnt/gvfs/third-party2/libunwind/8db74270cd6d0212ac92d69e7fc7beefe617d772/trunk/gcc-5-glibc-2.23/b1847cb
|
||||
TBB_BASE=/mnt/gvfs/third-party2/tbb/9d9a554877d0c5bef330fe818ab7178806dd316a/4.0_update2/gcc-5-glibc-2.23/9bc6787
|
||||
KERNEL_HEADERS_BASE=/mnt/gvfs/third-party2/kernel-headers/90c9734afc5579c9d1db529fa788d09f97763b85/4.0.9-36_fbk5_2933_gd092e3f/gcc-5-glibc-2.23/da39a3e
|
||||
BINUTILS_BASE=/mnt/gvfs/third-party2/binutils/9e829389ef61b92c62de8748c80169aaf25ce1f0/2.26.1/centos6-native/da39a3e
|
||||
VALGRIND_BASE=/mnt/gvfs/third-party2/valgrind/d7f4d4d86674a57668e3a96f76f0e17dd0eb8765/3.11.0/gcc-5-glibc-2.23/9bc6787
|
||||
LUA_BASE=/mnt/gvfs/third-party2/lua/61e4abf5813bbc39bc4f548757ccfcadde175a48/5.2.3/gcc-5-glibc-2.23/65372bd
|
||||
# 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
|
||||
@@ -1,18 +0,0 @@
|
||||
GCC_BASE=/mnt/gvfs/third-party2/gcc/6e8e715624fd15256a7970073387793dfcf79b46/7.x/centos7-native/b2ef2b6
|
||||
CLANG_BASE=/mnt/gvfs/third-party2/llvm-fb/ef37e1faa1c29782abfac1ae65a291b9b7966f6d/stable/centos7-native/c9f9104
|
||||
LIBGCC_BASE=/mnt/gvfs/third-party2/libgcc/c67031f0f739ac61575a061518d6ef5038f99f90/7.x/platform007/5620abc
|
||||
GLIBC_BASE=/mnt/gvfs/third-party2/glibc/60d6f124a78798b73944f5ba87c2306ae3460153/2.26/platform007/f259413
|
||||
SNAPPY_BASE=/mnt/gvfs/third-party2/snappy/7f9bdaada18f59bc27ec2b0871eb8a6144343aef/1.1.3/platform007/ca4da3d
|
||||
ZLIB_BASE=/mnt/gvfs/third-party2/zlib/22c2d65676fb7c23cfa797c4f6937f38b026f3cf/1.2.8/platform007/ca4da3d
|
||||
BZIP2_BASE=/mnt/gvfs/third-party2/bzip2/dc49a21c5fceec6456a7a28a94dcd16690af1337/1.0.6/platform007/ca4da3d
|
||||
LZ4_BASE=/mnt/gvfs/third-party2/lz4/907b498203d297947f3bb70b9466f47e100f1873/r131/platform007/ca4da3d
|
||||
ZSTD_BASE=/mnt/gvfs/third-party2/zstd/3ee276cbacfad3074e3f07bf826ac47f06970f4e/1.3.5/platform007/15a3614
|
||||
GFLAGS_BASE=/mnt/gvfs/third-party2/gflags/0b9929d2588991c65a57168bf88aff2db87c5d48/2.2.0/platform007/ca4da3d
|
||||
JEMALLOC_BASE=/mnt/gvfs/third-party2/jemalloc/9c910d36d6235cc40e8ff559358f1833452300ca/master/platform007/5b0f53e
|
||||
NUMA_BASE=/mnt/gvfs/third-party2/numa/9cbf2460284c669ed19c3ccb200a71f7dd7e53c7/2.0.11/platform007/ca4da3d
|
||||
LIBUNWIND_BASE=/mnt/gvfs/third-party2/libunwind/bf3d7497fe4e6d007354f0adffa16ce3003f8338/1.3/platform007/6f3e0a9
|
||||
TBB_BASE=/mnt/gvfs/third-party2/tbb/ff4e0b093534704d8abab678a4fd7f5ea7b094c7/2018_U5/platform007/ca4da3d
|
||||
KERNEL_HEADERS_BASE=/mnt/gvfs/third-party2/kernel-headers/b5c4a61a5c483ba24722005ae07895971a2ac707/fb/platform007/da39a3e
|
||||
BINUTILS_BASE=/mnt/gvfs/third-party2/binutils/92ff90349e2f43ea0a8246d8b1cf17b6869013e3/2.29.1/centos7-native/da39a3e
|
||||
VALGRIND_BASE=/mnt/gvfs/third-party2/valgrind/f3f697a28122e6bcd513273dd9c1ff23852fc59f/3.13.0/platform007/ca4da3d
|
||||
LUA_BASE=/mnt/gvfs/third-party2/lua/f0cd714433206d5139df61659eb7b28b1dea6683/5.3.4/platform007/5007832
|
||||
@@ -1,2 +1,2 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
docker run -v $PWD:/rocks -w /rocks buildpack-deps make
|
||||
@@ -13,7 +13,7 @@ source "$BASEDIR/dependencies.sh"
|
||||
CFLAGS=""
|
||||
|
||||
# libgcc
|
||||
LIBGCC_INCLUDE="$LIBGCC_BASE/include"
|
||||
LIBGCC_INCLUDE="$LIBGCC_BASE/include/c++/7.3.0"
|
||||
LIBGCC_LIBS=" -L $LIBGCC_BASE/lib"
|
||||
|
||||
# glibc
|
||||
@@ -43,12 +43,16 @@ if test -z $PIC_BUILD; then
|
||||
LZ4_INCLUDE=" -I $LZ4_BASE/include/"
|
||||
LZ4_LIBS=" $LZ4_BASE/lib/liblz4.a"
|
||||
CFLAGS+=" -DLZ4"
|
||||
|
||||
ZSTD_INCLUDE=" -I $ZSTD_BASE/include/"
|
||||
ZSTD_LIBS=" $ZSTD_BASE/lib/libzstd.a"
|
||||
CFLAGS+=" -DZSTD"
|
||||
fi
|
||||
|
||||
ZSTD_INCLUDE=" -I $ZSTD_BASE/include/"
|
||||
if test -z $PIC_BUILD; then
|
||||
ZSTD_LIBS=" $ZSTD_BASE/lib/libzstd.a"
|
||||
else
|
||||
ZSTD_LIBS=" $ZSTD_BASE/lib/libzstd_pic.a"
|
||||
fi
|
||||
CFLAGS+=" -DZSTD"
|
||||
|
||||
# location of gflags headers and libraries
|
||||
GFLAGS_INCLUDE=" -I $GFLAGS_BASE/include/"
|
||||
if test -z $PIC_BUILD; then
|
||||
@@ -104,8 +108,8 @@ if [ -z "$USE_CLANG" ]; then
|
||||
CXX="$GCC_BASE/bin/g++"
|
||||
|
||||
CFLAGS+=" -B$BINUTILS/gold"
|
||||
CFLAGS+=" -isystem $GLIBC_INCLUDE"
|
||||
CFLAGS+=" -isystem $LIBGCC_INCLUDE"
|
||||
CFLAGS+=" -isystem $GLIBC_INCLUDE"
|
||||
JEMALLOC=1
|
||||
else
|
||||
# clang
|
||||
@@ -116,8 +120,8 @@ else
|
||||
KERNEL_HEADERS_INCLUDE="$KERNEL_HEADERS_BASE/include"
|
||||
|
||||
CFLAGS+=" -B$BINUTILS/gold -nostdinc -nostdlib"
|
||||
CFLAGS+=" -isystem $LIBGCC_BASE/include/c++/5.x "
|
||||
CFLAGS+=" -isystem $LIBGCC_BASE/include/c++/5.x/x86_64-facebook-linux "
|
||||
CFLAGS+=" -isystem $LIBGCC_BASE/include/c++/7.x "
|
||||
CFLAGS+=" -isystem $LIBGCC_BASE/include/c++/7.x/x86_64-facebook-linux "
|
||||
CFLAGS+=" -isystem $GLIBC_INCLUDE"
|
||||
CFLAGS+=" -isystem $LIBGCC_INCLUDE"
|
||||
CFLAGS+=" -isystem $CLANG_INCLUDE"
|
||||
@@ -133,9 +137,9 @@ 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/gcc-5-glibc-2.23/lib/ld.so"
|
||||
EXEC_LDFLAGS+=" -Wl,--dynamic-linker,/usr/local/fbcode/platform007/lib/ld.so"
|
||||
EXEC_LDFLAGS+=" $LIBUNWIND"
|
||||
EXEC_LDFLAGS+=" -Wl,-rpath=/usr/local/fbcode/gcc-5-glibc-2.23/lib"
|
||||
EXEC_LDFLAGS+=" -Wl,-rpath=/usr/local/fbcode/platform007/lib"
|
||||
# required by libtbb
|
||||
EXEC_LDFLAGS+=" -ldl"
|
||||
|
||||
@@ -145,12 +149,4 @@ EXEC_LDFLAGS_SHARED="$SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GF
|
||||
|
||||
VALGRIND_VER="$VALGRIND_BASE/bin/"
|
||||
|
||||
LUA_PATH="$LUA_BASE"
|
||||
|
||||
if test -z $PIC_BUILD; then
|
||||
LUA_LIB=" $LUA_PATH/lib/liblua.a"
|
||||
else
|
||||
LUA_LIB=" $LUA_PATH/lib/liblua_pic.a"
|
||||
fi
|
||||
|
||||
export CC CXX AR CFLAGS CXXFLAGS EXEC_LDFLAGS EXEC_LDFLAGS_SHARED VALGRIND_VER JEMALLOC_LIB JEMALLOC_INCLUDE CLANG_ANALYZER CLANG_SCAN_BUILD LUA_PATH LUA_LIB
|
||||
export CC CXX AR CFLAGS CXXFLAGS EXEC_LDFLAGS EXEC_LDFLAGS_SHARED VALGRIND_VER JEMALLOC_LIB JEMALLOC_INCLUDE CLANG_ANALYZER CLANG_SCAN_BUILD
|
||||
@@ -93,7 +93,7 @@ else
|
||||
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"
|
||||
CFLAGS+=" -DSNAPPY -DGFLAGS=google -DZLIB -DBZIP2 -DLZ4 -DZSTD -DNUMA -DTBB"
|
||||
CXXFLAGS+=" $CFLAGS"
|
||||
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Set environment variables so that we can compile rocksdb using
|
||||
# fbcode settings. It uses the latest g++ and clang compilers and also
|
||||
# uses jemalloc
|
||||
# Environment variables that change the behavior of this script:
|
||||
# PIC_BUILD -- if true, it will only take pic versions of libraries from fbcode. libraries that don't have pic variant will not be included
|
||||
|
||||
|
||||
BASEDIR=`dirname $BASH_SOURCE`
|
||||
source "$BASEDIR/dependencies_platform007.sh"
|
||||
|
||||
CFLAGS=""
|
||||
|
||||
# libgcc
|
||||
LIBGCC_INCLUDE="$LIBGCC_BASE/include/c++/7.3.0"
|
||||
LIBGCC_LIBS=" -L $LIBGCC_BASE/lib"
|
||||
|
||||
# glibc
|
||||
GLIBC_INCLUDE="$GLIBC_BASE/include"
|
||||
GLIBC_LIBS=" -L $GLIBC_BASE/lib"
|
||||
|
||||
# snappy
|
||||
SNAPPY_INCLUDE=" -I $SNAPPY_BASE/include/"
|
||||
if test -z $PIC_BUILD; then
|
||||
SNAPPY_LIBS=" $SNAPPY_BASE/lib/libsnappy.a"
|
||||
else
|
||||
SNAPPY_LIBS=" $SNAPPY_BASE/lib/libsnappy_pic.a"
|
||||
fi
|
||||
CFLAGS+=" -DSNAPPY"
|
||||
|
||||
if test -z $PIC_BUILD; then
|
||||
# location of zlib headers and libraries
|
||||
ZLIB_INCLUDE=" -I $ZLIB_BASE/include/"
|
||||
ZLIB_LIBS=" $ZLIB_BASE/lib/libz.a"
|
||||
CFLAGS+=" -DZLIB"
|
||||
|
||||
# location of bzip headers and libraries
|
||||
BZIP_INCLUDE=" -I $BZIP2_BASE/include/"
|
||||
BZIP_LIBS=" $BZIP2_BASE/lib/libbz2.a"
|
||||
CFLAGS+=" -DBZIP2"
|
||||
|
||||
LZ4_INCLUDE=" -I $LZ4_BASE/include/"
|
||||
LZ4_LIBS=" $LZ4_BASE/lib/liblz4.a"
|
||||
CFLAGS+=" -DLZ4"
|
||||
fi
|
||||
|
||||
ZSTD_INCLUDE=" -I $ZSTD_BASE/include/"
|
||||
if test -z $PIC_BUILD; then
|
||||
ZSTD_LIBS=" $ZSTD_BASE/lib/libzstd.a"
|
||||
else
|
||||
ZSTD_LIBS=" $ZSTD_BASE/lib/libzstd_pic.a"
|
||||
fi
|
||||
CFLAGS+=" -DZSTD"
|
||||
|
||||
# location of gflags headers and libraries
|
||||
GFLAGS_INCLUDE=" -I $GFLAGS_BASE/include/"
|
||||
if test -z $PIC_BUILD; then
|
||||
GFLAGS_LIBS=" $GFLAGS_BASE/lib/libgflags.a"
|
||||
else
|
||||
GFLAGS_LIBS=" $GFLAGS_BASE/lib/libgflags_pic.a"
|
||||
fi
|
||||
CFLAGS+=" -DGFLAGS=gflags"
|
||||
|
||||
# location of jemalloc
|
||||
JEMALLOC_INCLUDE=" -I $JEMALLOC_BASE/include/"
|
||||
JEMALLOC_LIB=" $JEMALLOC_BASE/lib/libjemalloc.a"
|
||||
|
||||
if test -z $PIC_BUILD; then
|
||||
# location of numa
|
||||
NUMA_INCLUDE=" -I $NUMA_BASE/include/"
|
||||
NUMA_LIB=" $NUMA_BASE/lib/libnuma.a"
|
||||
CFLAGS+=" -DNUMA"
|
||||
|
||||
# location of libunwind
|
||||
LIBUNWIND="$LIBUNWIND_BASE/lib/libunwind.a"
|
||||
fi
|
||||
|
||||
# location of TBB
|
||||
TBB_INCLUDE=" -isystem $TBB_BASE/include/"
|
||||
if test -z $PIC_BUILD; then
|
||||
TBB_LIBS="$TBB_BASE/lib/libtbb.a"
|
||||
else
|
||||
TBB_LIBS="$TBB_BASE/lib/libtbb_pic.a"
|
||||
fi
|
||||
CFLAGS+=" -DTBB"
|
||||
|
||||
# use Intel SSE support for checksum calculations
|
||||
export USE_SSE=1
|
||||
export PORTABLE=1
|
||||
|
||||
BINUTILS="$BINUTILS_BASE/bin"
|
||||
AR="$BINUTILS/ar"
|
||||
|
||||
DEPS_INCLUDE="$SNAPPY_INCLUDE $ZLIB_INCLUDE $BZIP_INCLUDE $LZ4_INCLUDE $ZSTD_INCLUDE $GFLAGS_INCLUDE $NUMA_INCLUDE $TBB_INCLUDE"
|
||||
|
||||
STDLIBS="-L $GCC_BASE/lib64"
|
||||
|
||||
CLANG_BIN="$CLANG_BASE/bin"
|
||||
CLANG_LIB="$CLANG_BASE/lib"
|
||||
CLANG_SRC="$CLANG_BASE/../../src"
|
||||
|
||||
CLANG_ANALYZER="$CLANG_BIN/clang++"
|
||||
CLANG_SCAN_BUILD="$CLANG_SRC/llvm/tools/clang/tools/scan-build/bin/scan-build"
|
||||
|
||||
if [ -z "$USE_CLANG" ]; then
|
||||
# gcc
|
||||
CC="$GCC_BASE/bin/gcc"
|
||||
CXX="$GCC_BASE/bin/g++"
|
||||
|
||||
CFLAGS+=" -B$BINUTILS/gold"
|
||||
CFLAGS+=" -isystem $LIBGCC_INCLUDE"
|
||||
CFLAGS+=" -isystem $GLIBC_INCLUDE"
|
||||
JEMALLOC=1
|
||||
else
|
||||
# clang
|
||||
CLANG_INCLUDE="$CLANG_LIB/clang/stable/include"
|
||||
CC="$CLANG_BIN/clang"
|
||||
CXX="$CLANG_BIN/clang++"
|
||||
|
||||
KERNEL_HEADERS_INCLUDE="$KERNEL_HEADERS_BASE/include"
|
||||
|
||||
CFLAGS+=" -B$BINUTILS/gold -nostdinc -nostdlib"
|
||||
CFLAGS+=" -isystem $LIBGCC_BASE/include/c++/7.x "
|
||||
CFLAGS+=" -isystem $LIBGCC_BASE/include/c++/7.x/x86_64-facebook-linux "
|
||||
CFLAGS+=" -isystem $GLIBC_INCLUDE"
|
||||
CFLAGS+=" -isystem $LIBGCC_INCLUDE"
|
||||
CFLAGS+=" -isystem $CLANG_INCLUDE"
|
||||
CFLAGS+=" -isystem $KERNEL_HEADERS_INCLUDE/linux "
|
||||
CFLAGS+=" -isystem $KERNEL_HEADERS_INCLUDE "
|
||||
CFLAGS+=" -Wno-expansion-to-defined "
|
||||
CXXFLAGS="-nostdinc++"
|
||||
fi
|
||||
|
||||
CFLAGS+=" $DEPS_INCLUDE"
|
||||
CFLAGS+=" -DROCKSDB_PLATFORM_POSIX -DROCKSDB_LIB_IO_POSIX -DROCKSDB_FALLOCATE_PRESENT -DROCKSDB_MALLOC_USABLE_SIZE -DROCKSDB_RANGESYNC_PRESENT -DROCKSDB_SCHED_GETCPU_PRESENT -DROCKSDB_SUPPORT_THREAD_LOCAL -DHAVE_SSE42"
|
||||
CXXFLAGS+=" $CFLAGS"
|
||||
|
||||
EXEC_LDFLAGS=" $SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GFLAGS_LIBS $NUMA_LIB $TBB_LIBS"
|
||||
EXEC_LDFLAGS+=" -B$BINUTILS/gold"
|
||||
EXEC_LDFLAGS+=" -Wl,--dynamic-linker,/usr/local/fbcode/platform007/lib/ld.so"
|
||||
EXEC_LDFLAGS+=" $LIBUNWIND"
|
||||
EXEC_LDFLAGS+=" -Wl,-rpath=/usr/local/fbcode/platform007/lib"
|
||||
# required by libtbb
|
||||
EXEC_LDFLAGS+=" -ldl"
|
||||
|
||||
PLATFORM_LDFLAGS="$LIBGCC_LIBS $GLIBC_LIBS $STDLIBS -lgcc -lstdc++"
|
||||
|
||||
EXEC_LDFLAGS_SHARED="$SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GFLAGS_LIBS $TBB_LIBS"
|
||||
|
||||
VALGRIND_VER="$VALGRIND_BASE/bin/"
|
||||
|
||||
# lua not supported because it's on track for deprecation, I think
|
||||
LUA_PATH=
|
||||
LUA_LIB=
|
||||
|
||||
export CC CXX AR CFLAGS CXXFLAGS EXEC_LDFLAGS EXEC_LDFLAGS_SHARED VALGRIND_VER JEMALLOC_LIB JEMALLOC_INCLUDE CLANG_ANALYZER CLANG_SCAN_BUILD LUA_PATH LUA_LIB
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
# If clang_format_diff.py command is not specfied, we assume we are able to
|
||||
# access directly without any path.
|
||||
if [ -z $CLANG_FORMAT_DIFF ]
|
||||
|
||||
@@ -99,18 +99,6 @@ function main() {
|
||||
|
||||
make static_lib
|
||||
make install INSTALL_PATH=package
|
||||
|
||||
cd package
|
||||
|
||||
LIB_DIR=lib
|
||||
if [[ -z "$ARCH" ]]; then
|
||||
ARCH=$(getconf LONG_BIT)
|
||||
fi
|
||||
if [[ ("$FPM_OUTPUT" = "rpm") && ($ARCH -eq 64) ]]; then
|
||||
mv lib lib64
|
||||
LIB_DIR=lib64
|
||||
fi
|
||||
|
||||
fpm \
|
||||
-s dir \
|
||||
-t $FPM_OUTPUT \
|
||||
@@ -122,7 +110,7 @@ function main() {
|
||||
--license BSD \
|
||||
--vendor Facebook \
|
||||
--description "RocksDB is an embeddable persistent key-value store for fast storage." \
|
||||
include $LIB_DIR
|
||||
package
|
||||
}
|
||||
|
||||
main $@
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
# This script is executed by Sandcastle
|
||||
# to determine next steps to run
|
||||
|
||||
@@ -85,9 +85,8 @@ NON_SHM="TMPD=/tmp/rocksdb_test_tmp"
|
||||
GCC_481="ROCKSDB_FBCODE_BUILD_WITH_481=1"
|
||||
ASAN="COMPILE_WITH_ASAN=1"
|
||||
CLANG="USE_CLANG=1"
|
||||
# in gcc-5 there are known problems with TSAN like https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71090.
|
||||
# using platform007 gives us gcc-8 or higher which has that bug fixed.
|
||||
TSAN="ROCKSDB_FBCODE_BUILD_WITH_PLATFORM007=1 COMPILE_WITH_TSAN=1"
|
||||
LITE="OPT=\"-DROCKSDB_LITE -g\""
|
||||
TSAN="COMPILE_WITH_TSAN=1"
|
||||
UBSAN="COMPILE_WITH_UBSAN=1"
|
||||
DISABLE_JEMALLOC="DISABLE_JEMALLOC=1"
|
||||
HTTP_PROXY="https_proxy=http://fwdproxy.29.prn1:8080 http_proxy=http://fwdproxy.29.prn1:8080 ftp_proxy=http://fwdproxy.29.prn1:8080"
|
||||
@@ -131,6 +130,35 @@ DISABLE_COMMANDS="[
|
||||
}
|
||||
]"
|
||||
|
||||
#
|
||||
# RocksDB unit test in parallel
|
||||
# Currently we always have noise in our parallel runs. This job is to help
|
||||
# manage the noise
|
||||
#
|
||||
PARALLEL_UNIT_TEST_COMMANDS="[
|
||||
{
|
||||
'name':'Rocksdb Parallel Unit Test',
|
||||
'oncall':'$ONCALL',
|
||||
'steps': [
|
||||
$CLEANUP_ENV,
|
||||
{
|
||||
'name':'Build and test RocksDB debug version',
|
||||
'shell':'$DEBUG make -j$(nproc) all && $SHM make check > /dev/null 2>&1 || $CONTRUN_NAME=punit_check $TASK_CREATION_TOOL || cat t/log-*',
|
||||
'user':'root',
|
||||
$PARSER
|
||||
},
|
||||
$CLEANUP_ENV,
|
||||
{
|
||||
'name':'Build and test RocksDB debug version under gcc-4.8.1',
|
||||
'shell':'$GCC_481 $DEBUG make -j$(nproc) all && $SHM make check > /dev/null 2>&1 || $CONTRUN_NAME=punit_check_gcc481 $TASK_CREATION_TOOL || cat t/log-*',
|
||||
'user':'root',
|
||||
$PARSER
|
||||
},
|
||||
],
|
||||
$REPORT
|
||||
}
|
||||
]"
|
||||
|
||||
#
|
||||
# RocksDB unit test
|
||||
#
|
||||
@@ -344,7 +372,27 @@ LITE_BUILD_COMMANDS="[
|
||||
$CLEANUP_ENV,
|
||||
{
|
||||
'name':'Build RocksDB debug version',
|
||||
'shell':'$LITE make J=1 all check || $CONTRUN_NAME=lite $TASK_CREATION_TOOL',
|
||||
'shell':'$LITE make J=1 static_lib || $CONTRUN_NAME=lite_static_lib $TASK_CREATION_TOOL',
|
||||
'user':'root',
|
||||
$PARSER
|
||||
},
|
||||
],
|
||||
$REPORT
|
||||
}
|
||||
]"
|
||||
|
||||
#
|
||||
# RocksDB lite tests
|
||||
#
|
||||
LITE_UNIT_TEST_COMMANDS="[
|
||||
{
|
||||
'name':'Rocksdb Lite Unit Test',
|
||||
'oncall':'$ONCALL',
|
||||
'steps': [
|
||||
$CLEANUP_ENV,
|
||||
{
|
||||
'name':'Build RocksDB debug version',
|
||||
'shell':'$SHM $LITE make J=1 check || $CONTRUN_NAME=lite_check $TASK_CREATION_TOOL',
|
||||
'user':'root',
|
||||
$PARSER
|
||||
},
|
||||
@@ -545,7 +593,7 @@ TSAN_CRASH_TEST_COMMANDS="[
|
||||
{
|
||||
'name':'Compile and run',
|
||||
'timeout': 86400,
|
||||
'shell':'set -o pipefail && $SHM $DEBUG $TSAN CRASH_TEST_KILL_ODD=1887 CRASH_TEST_EXT_ARGS=--log2_keys_per_lock=22 make J=1 crash_test || $CONTRUN_NAME=tsan_crash_test $TASK_CREATION_TOOL',
|
||||
'shell':'set -o pipefail && $SHM $DEBUG $TSAN CRASH_TEST_KILL_ODD=1887 make J=1 crash_test || $CONTRUN_NAME=tsan_crash_test $TASK_CREATION_TOOL',
|
||||
'user':'root',
|
||||
$PARSER
|
||||
},
|
||||
@@ -564,7 +612,39 @@ run_format_compatible()
|
||||
rm -rf /dev/shm/rocksdb
|
||||
mkdir /dev/shm/rocksdb
|
||||
|
||||
tools/check_format_compatible.sh
|
||||
echo '
|
||||
if [ -e "build_tools/build_detect_platform" ]
|
||||
then
|
||||
sed "s/tcmalloc/nothingnothingnothing/g" build_tools/build_detect_platform > $TEST_TMPDIR/temp_build_file
|
||||
rm -rf build_tools/build_detect_platform
|
||||
cp $TEST_TMPDIR/temp_build_file build_tools/build_detect_platform
|
||||
chmod +x build_tools/build_detect_platform
|
||||
fi
|
||||
|
||||
if [ -e "build_detect_platform" ]
|
||||
then
|
||||
sed "s/tcmalloc/nothingnothingnothing/g" build_detect_platform > $TEST_TMPDIR/temp_build_file
|
||||
rm -rf build_detect_platform
|
||||
cp $TEST_TMPDIR/temp_build_file build_detect_platform
|
||||
chmod +x build_detect_platform
|
||||
fi
|
||||
|
||||
make ldb -j32
|
||||
|
||||
if [ -e "build_detect_platform" ]
|
||||
then
|
||||
git checkout -- build_detect_platform
|
||||
fi
|
||||
|
||||
if [ -e "build_tools/build_detect_platform" ]
|
||||
then
|
||||
git checkout -- build_tools/build_detect_platform
|
||||
fi
|
||||
' > temp_build_ldb.sh
|
||||
|
||||
sed "s/make ldb -j32/source temp_build_ldb.sh/g" tools/check_format_compatible.sh > tools/temp_check_format_compatible.sh
|
||||
chmod +x tools/temp_check_format_compatible.sh
|
||||
tools/temp_check_format_compatible.sh
|
||||
}
|
||||
|
||||
FORMAT_COMPATIBLE_COMMANDS="[
|
||||
@@ -696,6 +776,9 @@ JAVA_BUILD_TEST_COMMANDS="[
|
||||
|
||||
|
||||
case $1 in
|
||||
punit)
|
||||
echo $PARALLEL_UNIT_TEST_COMMANDS
|
||||
;;
|
||||
unit)
|
||||
echo $UNIT_TEST_COMMANDS
|
||||
;;
|
||||
@@ -729,6 +812,9 @@ case $1 in
|
||||
lite)
|
||||
echo $LITE_BUILD_COMMANDS
|
||||
;;
|
||||
lite_test)
|
||||
echo $LITE_UNIT_TEST_COMMANDS
|
||||
;;
|
||||
stress_crash)
|
||||
echo $STRESS_CRASH_TEST_COMMANDS
|
||||
;;
|
||||
|
||||
@@ -276,7 +276,7 @@ if($RunAll) {
|
||||
continue
|
||||
}
|
||||
|
||||
if($RunOnly.Contains($bare_name)) {
|
||||
if($RunOnly.Contains($e)) {
|
||||
MakeAndAdd -token $e -HashTable $TestExes
|
||||
} else {
|
||||
$ListOfSuites += $bare_name
|
||||
@@ -333,7 +333,7 @@ function RunJobs($Suites, $TestCmds, [int]$ConcurrencyVal)
|
||||
$Cases = @{}
|
||||
|
||||
if($Suites.Count -gt 0) {
|
||||
# Will the first one
|
||||
# Will teh first one
|
||||
ForEach($e in $Suites.Keys) {
|
||||
$exe_name = $e
|
||||
$Cases = $Suites[$e]
|
||||
|
||||
@@ -53,46 +53,7 @@ function get_lib_base()
|
||||
}
|
||||
|
||||
###########################################################
|
||||
# platform007 dependencies #
|
||||
###########################################################
|
||||
|
||||
OUTPUT="$BASEDIR/dependencies_platform007.sh"
|
||||
|
||||
rm -f "$OUTPUT"
|
||||
touch "$OUTPUT"
|
||||
|
||||
echo "Writing dependencies to $OUTPUT"
|
||||
|
||||
# Compilers locations
|
||||
GCC_BASE=`readlink -f $TP2_LATEST/gcc/7.x/centos7-native/*/`
|
||||
CLANG_BASE=`readlink -f $TP2_LATEST/llvm-fb/stable/centos7-native/*/`
|
||||
|
||||
log_variable GCC_BASE
|
||||
log_variable CLANG_BASE
|
||||
|
||||
# Libraries locations
|
||||
get_lib_base libgcc 7.x platform007
|
||||
get_lib_base glibc 2.26 platform007
|
||||
get_lib_base snappy LATEST platform007
|
||||
get_lib_base zlib LATEST platform007
|
||||
get_lib_base bzip2 LATEST platform007
|
||||
get_lib_base lz4 LATEST platform007
|
||||
get_lib_base zstd LATEST platform007
|
||||
get_lib_base gflags LATEST platform007
|
||||
get_lib_base jemalloc LATEST platform007
|
||||
get_lib_base numa LATEST platform007
|
||||
get_lib_base libunwind LATEST platform007
|
||||
get_lib_base tbb LATEST platform007
|
||||
|
||||
get_lib_base kernel-headers fb platform007
|
||||
get_lib_base binutils LATEST centos7-native
|
||||
get_lib_base valgrind LATEST platform007
|
||||
get_lib_base lua 5.3.4 platform007
|
||||
|
||||
git diff $OUTPUT
|
||||
|
||||
###########################################################
|
||||
# 5.x dependencies #
|
||||
# 4.9.x dependencies #
|
||||
###########################################################
|
||||
|
||||
OUTPUT="$BASEDIR/dependencies.sh"
|
||||
@@ -103,16 +64,16 @@ touch "$OUTPUT"
|
||||
echo "Writing dependencies to $OUTPUT"
|
||||
|
||||
# Compilers locations
|
||||
GCC_BASE=`readlink -f $TP2_LATEST/gcc/5.x/centos6-native/*/`
|
||||
GCC_BASE=`readlink -f $TP2_LATEST/gcc/4.9.x/centos6-native/*/`
|
||||
CLANG_BASE=`readlink -f $TP2_LATEST/llvm-fb/stable/centos6-native/*/`
|
||||
|
||||
log_variable GCC_BASE
|
||||
log_variable CLANG_BASE
|
||||
|
||||
# Libraries locations
|
||||
get_lib_base libgcc 5.x
|
||||
get_lib_base glibc 2.23
|
||||
get_lib_base snappy LATEST gcc-5-glibc-2.23
|
||||
get_lib_base libgcc 4.9.x
|
||||
get_lib_base glibc 2.20
|
||||
get_lib_base snappy LATEST gcc-4.9-glibc-2.20
|
||||
get_lib_base zlib LATEST
|
||||
get_lib_base bzip2 LATEST
|
||||
get_lib_base lz4 LATEST
|
||||
@@ -121,12 +82,12 @@ get_lib_base gflags LATEST
|
||||
get_lib_base jemalloc LATEST
|
||||
get_lib_base numa LATEST
|
||||
get_lib_base libunwind LATEST
|
||||
get_lib_base tbb 4.0_update2 gcc-5-glibc-2.23
|
||||
get_lib_base tbb 4.0_update2 gcc-4.9-glibc-2.20
|
||||
|
||||
get_lib_base kernel-headers LATEST
|
||||
get_lib_base binutils LATEST centos6-native
|
||||
get_lib_base valgrind 3.10.0 gcc-5-glibc-2.23
|
||||
get_lib_base lua 5.2.3 gcc-5-glibc-2.23
|
||||
get_lib_base valgrind 3.10.0 gcc-4.9-glibc-2.20
|
||||
get_lib_base lua 5.2.3 gcc-4.9-glibc-2.20
|
||||
|
||||
git diff $OUTPUT
|
||||
|
||||
|
||||
Vendored
-31
@@ -475,37 +475,6 @@ void deleter(const Slice& key, void* value) {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST_P(CacheTest, ReleaseAndErase) {
|
||||
std::shared_ptr<Cache> cache = NewCache(5, 0, false);
|
||||
Cache::Handle* handle;
|
||||
Status s = cache->Insert(EncodeKey(100), EncodeValue(100), 1,
|
||||
&CacheTest::Deleter, &handle);
|
||||
ASSERT_TRUE(s.ok());
|
||||
ASSERT_EQ(5U, cache->GetCapacity());
|
||||
ASSERT_EQ(1U, cache->GetUsage());
|
||||
ASSERT_EQ(0U, deleted_keys_.size());
|
||||
auto erased = cache->Release(handle, true);
|
||||
ASSERT_TRUE(erased);
|
||||
// This tests that deleter has been called
|
||||
ASSERT_EQ(1U, deleted_keys_.size());
|
||||
}
|
||||
|
||||
TEST_P(CacheTest, ReleaseWithoutErase) {
|
||||
std::shared_ptr<Cache> cache = NewCache(5, 0, false);
|
||||
Cache::Handle* handle;
|
||||
Status s = cache->Insert(EncodeKey(100), EncodeValue(100), 1,
|
||||
&CacheTest::Deleter, &handle);
|
||||
ASSERT_TRUE(s.ok());
|
||||
ASSERT_EQ(5U, cache->GetCapacity());
|
||||
ASSERT_EQ(1U, cache->GetUsage());
|
||||
ASSERT_EQ(0U, deleted_keys_.size());
|
||||
auto erased = cache->Release(handle);
|
||||
ASSERT_FALSE(erased);
|
||||
// This tests that deleter is not called. When cache has free capacity it is
|
||||
// not expected to immediately erase the released items.
|
||||
ASSERT_EQ(0U, deleted_keys_.size());
|
||||
}
|
||||
|
||||
TEST_P(CacheTest, SetCapacity) {
|
||||
// test1: increase capacity
|
||||
// lets create a cache with capacity 5,
|
||||
|
||||
Vendored
+17
-39
@@ -26,12 +26,8 @@ std::shared_ptr<Cache> NewClockCache(size_t capacity, int num_shard_bits,
|
||||
#include <assert.h>
|
||||
#include <atomic>
|
||||
#include <deque>
|
||||
#include <limits>
|
||||
|
||||
// "tbb/concurrent_hash_map.h" requires RTTI if exception is enabled.
|
||||
// Disable it so users can chooose to disable RTTI.
|
||||
#ifndef ROCKSDB_USE_RTTI
|
||||
#define TBB_USE_EXCEPTIONS 0
|
||||
#endif
|
||||
#include "tbb/concurrent_hash_map.h"
|
||||
|
||||
#include "cache/sharded_cache.h"
|
||||
@@ -256,11 +252,8 @@ class ClockCacheShard : public CacheShard {
|
||||
//
|
||||
// Not necessary to hold mutex_ before being called.
|
||||
virtual bool Ref(Cache::Handle* handle) override;
|
||||
virtual bool Release(Cache::Handle* handle,
|
||||
bool force_erase = false) override;
|
||||
virtual void Release(Cache::Handle* handle) override;
|
||||
virtual void Erase(const Slice& key, uint32_t hash) override;
|
||||
bool EraseAndConfirm(const Slice& key, uint32_t hash,
|
||||
CleanupContext* context);
|
||||
virtual size_t GetUsage() const override;
|
||||
virtual size_t GetPinnedUsage() const override;
|
||||
virtual void EraseUnRefEntries() override;
|
||||
@@ -281,17 +274,13 @@ class ClockCacheShard : public CacheShard {
|
||||
// Decrease reference count of the entry. If this decreases the count to 0,
|
||||
// recycle the entry. If set_usage is true, also set the usage bit.
|
||||
//
|
||||
// returns true if a value is erased.
|
||||
//
|
||||
// Not necessary to hold mutex_ before being called.
|
||||
bool Unref(CacheHandle* handle, bool set_usage, CleanupContext* context);
|
||||
void Unref(CacheHandle* handle, bool set_usage, CleanupContext* context);
|
||||
|
||||
// Unset in-cache bit of the entry. Recycle the handle if necessary.
|
||||
//
|
||||
// returns true if a value is erased.
|
||||
//
|
||||
// Has to hold mutex_ before being called.
|
||||
bool UnsetInCache(CacheHandle* handle, CleanupContext* context);
|
||||
void UnsetInCache(CacheHandle* handle, CleanupContext* context);
|
||||
|
||||
// Put the handle back to recycle_ list, and put the value associated with
|
||||
// it into to-be-deleted list. It doesn't cleanup the key as it might be
|
||||
@@ -443,7 +432,7 @@ bool ClockCacheShard::Ref(Cache::Handle* h) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ClockCacheShard::Unref(CacheHandle* handle, bool set_usage,
|
||||
void ClockCacheShard::Unref(CacheHandle* handle, bool set_usage,
|
||||
CleanupContext* context) {
|
||||
if (set_usage) {
|
||||
handle->flags.fetch_or(kUsageBit, std::memory_order_relaxed);
|
||||
@@ -462,10 +451,9 @@ bool ClockCacheShard::Unref(CacheHandle* handle, bool set_usage,
|
||||
RecycleHandle(handle, context);
|
||||
}
|
||||
}
|
||||
return context->to_delete_value.size();
|
||||
}
|
||||
|
||||
bool ClockCacheShard::UnsetInCache(CacheHandle* handle,
|
||||
void ClockCacheShard::UnsetInCache(CacheHandle* handle,
|
||||
CleanupContext* context) {
|
||||
mutex_.AssertHeld();
|
||||
// Use acquire-release semantics as previous operations on the cache entry
|
||||
@@ -477,7 +465,6 @@ bool ClockCacheShard::UnsetInCache(CacheHandle* handle,
|
||||
if (InCache(flags) && CountRefs(flags) == 0) {
|
||||
RecycleHandle(handle, context);
|
||||
}
|
||||
return context->to_delete_value.size();
|
||||
}
|
||||
|
||||
bool ClockCacheShard::TryEvict(CacheHandle* handle, CleanupContext* context) {
|
||||
@@ -631,34 +618,25 @@ Cache::Handle* ClockCacheShard::Lookup(const Slice& key, uint32_t hash) {
|
||||
return reinterpret_cast<Cache::Handle*>(handle);
|
||||
}
|
||||
|
||||
bool ClockCacheShard::Release(Cache::Handle* h, bool force_erase) {
|
||||
void ClockCacheShard::Release(Cache::Handle* h) {
|
||||
CleanupContext context;
|
||||
CacheHandle* handle = reinterpret_cast<CacheHandle*>(h);
|
||||
bool erased = Unref(handle, true, &context);
|
||||
if (force_erase && !erased) {
|
||||
erased = EraseAndConfirm(handle->key, handle->hash, &context);
|
||||
}
|
||||
Unref(handle, true, &context);
|
||||
Cleanup(context);
|
||||
return erased;
|
||||
}
|
||||
|
||||
void ClockCacheShard::Erase(const Slice& key, uint32_t hash) {
|
||||
CleanupContext context;
|
||||
EraseAndConfirm(key, hash, &context);
|
||||
Cleanup(context);
|
||||
}
|
||||
|
||||
bool ClockCacheShard::EraseAndConfirm(const Slice& key, uint32_t hash,
|
||||
CleanupContext* context) {
|
||||
MutexLock l(&mutex_);
|
||||
HashTable::accessor accessor;
|
||||
bool erased = false;
|
||||
if (table_.find(accessor, CacheKey(key, hash))) {
|
||||
CacheHandle* handle = accessor->second;
|
||||
table_.erase(accessor);
|
||||
erased = UnsetInCache(handle, context);
|
||||
{
|
||||
MutexLock l(&mutex_);
|
||||
HashTable::accessor accessor;
|
||||
if (table_.find(accessor, CacheKey(key, hash))) {
|
||||
CacheHandle* handle = accessor->second;
|
||||
table_.erase(accessor);
|
||||
UnsetInCache(handle, &context);
|
||||
}
|
||||
}
|
||||
return erased;
|
||||
Cleanup(context);
|
||||
}
|
||||
|
||||
void ClockCacheShard::EraseUnRefEntries() {
|
||||
|
||||
Vendored
+10
-50
@@ -22,7 +22,7 @@
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
LRUHandleTable::LRUHandleTable() : list_(nullptr), length_(0), elems_(0) {
|
||||
LRUHandleTable::LRUHandleTable() : length_(0), elems_(0), list_(nullptr) {
|
||||
Resize();
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ void LRUHandleTable::Resize() {
|
||||
}
|
||||
|
||||
LRUCacheShard::LRUCacheShard()
|
||||
: high_pri_pool_usage_(0), usage_(0), lru_usage_(0) {
|
||||
: usage_(0), lru_usage_(0), high_pri_pool_usage_(0) {
|
||||
// Make empty circular linked list
|
||||
lru_.next = &lru_;
|
||||
lru_.prev = &lru_;
|
||||
@@ -157,16 +157,6 @@ void LRUCacheShard::TEST_GetLRUList(LRUHandle** lru, LRUHandle** lru_low_pri) {
|
||||
*lru_low_pri = lru_low_pri_;
|
||||
}
|
||||
|
||||
size_t LRUCacheShard::TEST_GetLRUSize() {
|
||||
LRUHandle* lru_handle = lru_.next;
|
||||
size_t lru_size = 0;
|
||||
while (lru_handle != &lru_) {
|
||||
lru_size++;
|
||||
lru_handle = lru_handle->next;
|
||||
}
|
||||
return lru_size;
|
||||
}
|
||||
|
||||
void LRUCacheShard::LRU_Remove(LRUHandle* e) {
|
||||
assert(e->next != nullptr);
|
||||
assert(e->prev != nullptr);
|
||||
@@ -233,22 +223,6 @@ void LRUCacheShard::EvictFromLRU(size_t charge,
|
||||
}
|
||||
}
|
||||
|
||||
void* LRUCacheShard::operator new(size_t size) {
|
||||
return port::cacheline_aligned_alloc(size);
|
||||
}
|
||||
|
||||
void* LRUCacheShard::operator new[](size_t size) {
|
||||
return port::cacheline_aligned_alloc(size);
|
||||
}
|
||||
|
||||
void LRUCacheShard::operator delete(void *memblock) {
|
||||
port::cacheline_aligned_free(memblock);
|
||||
}
|
||||
|
||||
void LRUCacheShard::operator delete[](void* memblock) {
|
||||
port::cacheline_aligned_free(memblock);
|
||||
}
|
||||
|
||||
void LRUCacheShard::SetCapacity(size_t capacity) {
|
||||
autovector<LRUHandle*> last_reference_list;
|
||||
{
|
||||
@@ -299,9 +273,9 @@ void LRUCacheShard::SetHighPriorityPoolRatio(double high_pri_pool_ratio) {
|
||||
MaintainPoolSize();
|
||||
}
|
||||
|
||||
bool LRUCacheShard::Release(Cache::Handle* handle, bool force_erase) {
|
||||
void LRUCacheShard::Release(Cache::Handle* handle) {
|
||||
if (handle == nullptr) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
LRUHandle* e = reinterpret_cast<LRUHandle*>(handle);
|
||||
bool last_reference = false;
|
||||
@@ -313,10 +287,10 @@ bool LRUCacheShard::Release(Cache::Handle* handle, bool force_erase) {
|
||||
}
|
||||
if (e->refs == 1 && e->InCache()) {
|
||||
// The item is still in cache, and nobody else holds a reference to it
|
||||
if (usage_ > capacity_ || force_erase) {
|
||||
if (usage_ > capacity_) {
|
||||
// the cache is full
|
||||
// The LRU list must be empty since the cache is full
|
||||
assert(!(usage_ > capacity_) || lru_.next == &lru_);
|
||||
assert(lru_.next == &lru_);
|
||||
// take this opportunity and remove the item
|
||||
table_.Remove(e->key(), e->hash);
|
||||
e->SetInCache(false);
|
||||
@@ -334,7 +308,6 @@ bool LRUCacheShard::Release(Cache::Handle* handle, bool force_erase) {
|
||||
if (last_reference) {
|
||||
e->Free();
|
||||
}
|
||||
return last_reference;
|
||||
}
|
||||
|
||||
Status LRUCacheShard::Insert(const Slice& key, uint32_t hash, void* value,
|
||||
@@ -464,11 +437,11 @@ std::string LRUCacheShard::GetPrintableOptions() const {
|
||||
LRUCache::LRUCache(size_t capacity, int num_shard_bits,
|
||||
bool strict_capacity_limit, double high_pri_pool_ratio)
|
||||
: ShardedCache(capacity, num_shard_bits, strict_capacity_limit) {
|
||||
num_shards_ = 1 << num_shard_bits;
|
||||
shards_ = new LRUCacheShard[num_shards_];
|
||||
int num_shards = 1 << num_shard_bits;
|
||||
shards_ = new LRUCacheShard[num_shards];
|
||||
SetCapacity(capacity);
|
||||
SetStrictCapacityLimit(strict_capacity_limit);
|
||||
for (int i = 0; i < num_shards_; i++) {
|
||||
for (int i = 0; i < num_shards; i++) {
|
||||
shards_[i].SetHighPriorityPoolRatio(high_pri_pool_ratio);
|
||||
}
|
||||
}
|
||||
@@ -495,20 +468,7 @@ uint32_t LRUCache::GetHash(Handle* handle) const {
|
||||
return reinterpret_cast<const LRUHandle*>(handle)->hash;
|
||||
}
|
||||
|
||||
void LRUCache::DisownData() {
|
||||
// Do not drop data if compile with ASAN to suppress leak warning.
|
||||
#ifndef __SANITIZE_ADDRESS__
|
||||
shards_ = nullptr;
|
||||
#endif // !__SANITIZE_ADDRESS__
|
||||
}
|
||||
|
||||
size_t LRUCache::TEST_GetLRUSize() {
|
||||
size_t lru_size_of_all_shards = 0;
|
||||
for (int i = 0; i < num_shards_; i++) {
|
||||
lru_size_of_all_shards += shards_[i].TEST_GetLRUSize();
|
||||
}
|
||||
return lru_size_of_all_shards;
|
||||
}
|
||||
void LRUCache::DisownData() { shards_ = nullptr; }
|
||||
|
||||
std::shared_ptr<Cache> NewLRUCache(size_t capacity, int num_shard_bits,
|
||||
bool strict_capacity_limit,
|
||||
|
||||
Vendored
+14
-43
@@ -148,13 +148,13 @@ class LRUHandleTable {
|
||||
|
||||
// The table consists of an array of buckets where each bucket is
|
||||
// a linked list of cache entries that hash into the bucket.
|
||||
LRUHandle** list_;
|
||||
uint32_t length_;
|
||||
uint32_t elems_;
|
||||
LRUHandle** list_;
|
||||
};
|
||||
|
||||
// A single shard of sharded cache.
|
||||
class ALIGN_AS(CACHE_LINE_SIZE) LRUCacheShard : public CacheShard {
|
||||
class LRUCacheShard : public CacheShard {
|
||||
public:
|
||||
LRUCacheShard();
|
||||
virtual ~LRUCacheShard();
|
||||
@@ -178,8 +178,7 @@ class ALIGN_AS(CACHE_LINE_SIZE) LRUCacheShard : public CacheShard {
|
||||
Cache::Priority priority) override;
|
||||
virtual Cache::Handle* Lookup(const Slice& key, uint32_t hash) override;
|
||||
virtual bool Ref(Cache::Handle* handle) override;
|
||||
virtual bool Release(Cache::Handle* handle,
|
||||
bool force_erase = false) override;
|
||||
virtual void Release(Cache::Handle* handle) override;
|
||||
virtual void Erase(const Slice& key, uint32_t hash) override;
|
||||
|
||||
// Although in some platforms the update of size_t is atomic, to make sure
|
||||
@@ -198,19 +197,6 @@ class ALIGN_AS(CACHE_LINE_SIZE) LRUCacheShard : public CacheShard {
|
||||
|
||||
void TEST_GetLRUList(LRUHandle** lru, LRUHandle** lru_low_pri);
|
||||
|
||||
// Retrieves number of elements in LRU, for unit test purpose only
|
||||
// not threadsafe
|
||||
size_t TEST_GetLRUSize();
|
||||
|
||||
// Overloading to aligned it to cache line size
|
||||
void* operator new(size_t);
|
||||
|
||||
void* operator new[](size_t);
|
||||
|
||||
void operator delete(void *);
|
||||
|
||||
void operator delete[](void*);
|
||||
|
||||
private:
|
||||
void LRU_Remove(LRUHandle* e);
|
||||
void LRU_Insert(LRUHandle* e);
|
||||
@@ -232,6 +218,12 @@ class ALIGN_AS(CACHE_LINE_SIZE) LRUCacheShard : public CacheShard {
|
||||
// Initialized before use.
|
||||
size_t capacity_;
|
||||
|
||||
// Memory size for entries residing in the cache
|
||||
size_t usage_;
|
||||
|
||||
// Memory size for entries residing only in the LRU list
|
||||
size_t lru_usage_;
|
||||
|
||||
// Memory size for entries in high-pri pool.
|
||||
size_t high_pri_pool_usage_;
|
||||
|
||||
@@ -245,6 +237,11 @@ class ALIGN_AS(CACHE_LINE_SIZE) LRUCacheShard : public CacheShard {
|
||||
// Remember the value to avoid recomputing each time.
|
||||
double high_pri_pool_capacity_;
|
||||
|
||||
// mutex_ protects the following state.
|
||||
// We don't count mutex_ as the cache's internal state so semantically we
|
||||
// don't mind mutex_ invoking the non-const actions.
|
||||
mutable port::Mutex mutex_;
|
||||
|
||||
// Dummy head of LRU list.
|
||||
// lru.prev is newest entry, lru.next is oldest entry.
|
||||
// LRU contains items which can be evicted, ie reference only by cache
|
||||
@@ -253,29 +250,7 @@ class ALIGN_AS(CACHE_LINE_SIZE) LRUCacheShard : public CacheShard {
|
||||
// Pointer to head of low-pri pool in LRU list.
|
||||
LRUHandle* lru_low_pri_;
|
||||
|
||||
// ------------^^^^^^^^^^^^^-----------
|
||||
// Not frequently modified data members
|
||||
// ------------------------------------
|
||||
//
|
||||
// We separate data members that are updated frequently from the ones that
|
||||
// are not frequently updated so that they don't share the same cache line
|
||||
// which will lead into false cache sharing
|
||||
//
|
||||
// ------------------------------------
|
||||
// Frequently modified data members
|
||||
// ------------vvvvvvvvvvvvv-----------
|
||||
LRUHandleTable table_;
|
||||
|
||||
// Memory size for entries residing in the cache
|
||||
size_t usage_;
|
||||
|
||||
// Memory size for entries residing only in the LRU list
|
||||
size_t lru_usage_;
|
||||
|
||||
// mutex_ protects the following state.
|
||||
// We don't count mutex_ as the cache's internal state so semantically we
|
||||
// don't mind mutex_ invoking the non-const actions.
|
||||
mutable port::Mutex mutex_;
|
||||
};
|
||||
|
||||
class LRUCache : public ShardedCache {
|
||||
@@ -291,12 +266,8 @@ class LRUCache : public ShardedCache {
|
||||
virtual uint32_t GetHash(Handle* handle) const override;
|
||||
virtual void DisownData() override;
|
||||
|
||||
// Retrieves number of elements in LRU, for unit test purpose only
|
||||
size_t TEST_GetLRUSize();
|
||||
|
||||
private:
|
||||
LRUCacheShard* shards_;
|
||||
int num_shards_ = 0;
|
||||
};
|
||||
|
||||
} // namespace rocksdb
|
||||
Vendored
+1
-10
@@ -17,16 +17,7 @@ class LRUCacheTest : public testing::Test {
|
||||
~LRUCacheTest() {}
|
||||
|
||||
void NewCache(size_t capacity, double high_pri_pool_ratio = 0.0) {
|
||||
cache_.reset(
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4316) // We've validated the alignment with the new operators
|
||||
#endif
|
||||
new LRUCacheShard()
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
);
|
||||
cache_.reset(new LRUCacheShard());
|
||||
cache_->SetCapacity(capacity);
|
||||
cache_->SetStrictCapacityLimit(false);
|
||||
cache_->SetHighPriorityPoolRatio(high_pri_pool_ratio);
|
||||
|
||||
Vendored
+2
-2
@@ -63,9 +63,9 @@ bool ShardedCache::Ref(Handle* handle) {
|
||||
return GetShard(Shard(hash))->Ref(handle);
|
||||
}
|
||||
|
||||
bool ShardedCache::Release(Handle* handle, bool force_erase) {
|
||||
void ShardedCache::Release(Handle* handle) {
|
||||
uint32_t hash = GetHash(handle);
|
||||
return GetShard(Shard(hash))->Release(handle, force_erase);
|
||||
GetShard(Shard(hash))->Release(handle);
|
||||
}
|
||||
|
||||
void ShardedCache::Erase(const Slice& key) {
|
||||
|
||||
Vendored
+2
-2
@@ -30,7 +30,7 @@ class CacheShard {
|
||||
Cache::Handle** handle, Cache::Priority priority) = 0;
|
||||
virtual Cache::Handle* Lookup(const Slice& key, uint32_t hash) = 0;
|
||||
virtual bool Ref(Cache::Handle* handle) = 0;
|
||||
virtual bool Release(Cache::Handle* handle, bool force_erase = false) = 0;
|
||||
virtual void Release(Cache::Handle* handle) = 0;
|
||||
virtual void Erase(const Slice& key, uint32_t hash) = 0;
|
||||
virtual void SetCapacity(size_t capacity) = 0;
|
||||
virtual void SetStrictCapacityLimit(bool strict_capacity_limit) = 0;
|
||||
@@ -65,7 +65,7 @@ class ShardedCache : public Cache {
|
||||
Handle** handle, Priority priority) override;
|
||||
virtual Handle* Lookup(const Slice& key, Statistics* stats) override;
|
||||
virtual bool Ref(Handle* handle) override;
|
||||
virtual bool Release(Handle* handle, bool force_erase = false) override;
|
||||
virtual void Release(Handle* handle) override;
|
||||
virtual void Erase(const Slice& key) override;
|
||||
virtual uint64_t NewId() override;
|
||||
virtual size_t GetCapacity() const override;
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
@PACKAGE_INIT@
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/RocksDBTargets.cmake")
|
||||
check_required_components(RocksDB)
|
||||
@@ -1,21 +0,0 @@
|
||||
# - Find Bzip2
|
||||
# Find the bzip2 compression library and includes
|
||||
#
|
||||
# BZIP2_INCLUDE_DIR - where to find bzlib.h, etc.
|
||||
# BZIP2_LIBRARIES - List of libraries when using bzip2.
|
||||
# BZIP2_FOUND - True if bzip2 found.
|
||||
|
||||
find_path(BZIP2_INCLUDE_DIR
|
||||
NAMES bzlib.h
|
||||
HINTS ${BZIP2_ROOT_DIR}/include)
|
||||
|
||||
find_library(BZIP2_LIBRARIES
|
||||
NAMES bz2
|
||||
HINTS ${BZIP2_ROOT_DIR}/lib)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(bzip2 DEFAULT_MSG BZIP2_LIBRARIES BZIP2_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(
|
||||
BZIP2_LIBRARIES
|
||||
BZIP2_INCLUDE_DIR)
|
||||
@@ -1,21 +0,0 @@
|
||||
# - Find Lz4
|
||||
# Find the lz4 compression library and includes
|
||||
#
|
||||
# LZ4_INCLUDE_DIR - where to find lz4.h, etc.
|
||||
# LZ4_LIBRARIES - List of libraries when using lz4.
|
||||
# LZ4_FOUND - True if lz4 found.
|
||||
|
||||
find_path(LZ4_INCLUDE_DIR
|
||||
NAMES lz4.h
|
||||
HINTS ${LZ4_ROOT_DIR}/include)
|
||||
|
||||
find_library(LZ4_LIBRARIES
|
||||
NAMES lz4
|
||||
HINTS ${LZ4_ROOT_DIR}/lib)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(lz4 DEFAULT_MSG LZ4_LIBRARIES LZ4_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(
|
||||
LZ4_LIBRARIES
|
||||
LZ4_INCLUDE_DIR)
|
||||
@@ -1,21 +0,0 @@
|
||||
# - Find zlib
|
||||
# Find the zlib compression library and includes
|
||||
#
|
||||
# ZLIB_INCLUDE_DIR - where to find zlib.h, etc.
|
||||
# ZLIB_LIBRARIES - List of libraries when using zlib.
|
||||
# ZLIB_FOUND - True if zlib found.
|
||||
|
||||
find_path(ZLIB_INCLUDE_DIR
|
||||
NAMES zlib.h
|
||||
HINTS ${ZLIB_ROOT_DIR}/include)
|
||||
|
||||
find_library(ZLIB_LIBRARIES
|
||||
NAMES z
|
||||
HINTS ${ZLIB_ROOT_DIR}/lib)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(zlib DEFAULT_MSG ZLIB_LIBRARIES ZLIB_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(
|
||||
ZLIB_LIBRARIES
|
||||
ZLIB_INCLUDE_DIR)
|
||||
@@ -1,21 +0,0 @@
|
||||
# - Find zstd
|
||||
# Find the zstd compression library and includes
|
||||
#
|
||||
# ZSTD_INCLUDE_DIR - where to find zstd.h, etc.
|
||||
# ZSTD_LIBRARIES - List of libraries when using zstd.
|
||||
# ZSTD_FOUND - True if zstd found.
|
||||
|
||||
find_path(ZSTD_INCLUDE_DIR
|
||||
NAMES zstd.h
|
||||
HINTS ${ZSTD_ROOT_DIR}/include)
|
||||
|
||||
find_library(ZSTD_LIBRARIES
|
||||
NAMES zstd
|
||||
HINTS ${ZSTD_ROOT_DIR}/lib)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(zstd DEFAULT_MSG ZSTD_LIBRARIES ZSTD_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(
|
||||
ZSTD_LIBRARIES
|
||||
ZSTD_INCLUDE_DIR)
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
|
||||
# Exit on error.
|
||||
set -e
|
||||
|
||||
+10
-11
@@ -45,17 +45,17 @@ TableBuilder* NewTableBuilder(
|
||||
int_tbl_prop_collector_factories,
|
||||
uint32_t column_family_id, const std::string& column_family_name,
|
||||
WritableFileWriter* file, const CompressionType compression_type,
|
||||
const CompressionOptions& compression_opts, int level,
|
||||
const std::string* compression_dict, const bool skip_filters,
|
||||
const uint64_t creation_time, const uint64_t oldest_key_time) {
|
||||
const CompressionOptions& compression_opts,
|
||||
int level,
|
||||
const std::string* compression_dict, const bool skip_filters) {
|
||||
assert((column_family_id ==
|
||||
TablePropertiesCollectorFactory::Context::kUnknownColumnFamily) ==
|
||||
column_family_name.empty());
|
||||
return ioptions.table_factory->NewTableBuilder(
|
||||
TableBuilderOptions(
|
||||
ioptions, internal_comparator, int_tbl_prop_collector_factories,
|
||||
compression_type, compression_opts, compression_dict, skip_filters,
|
||||
column_family_name, level, creation_time, oldest_key_time),
|
||||
TableBuilderOptions(ioptions, internal_comparator,
|
||||
int_tbl_prop_collector_factories, compression_type,
|
||||
compression_opts, compression_dict, skip_filters,
|
||||
column_family_name, level),
|
||||
column_family_id, file);
|
||||
}
|
||||
|
||||
@@ -74,8 +74,7 @@ Status BuildTable(
|
||||
const CompressionOptions& compression_opts, bool paranoid_file_checks,
|
||||
InternalStats* internal_stats, TableFileCreationReason reason,
|
||||
EventLogger* event_logger, int job_id, const Env::IOPriority io_priority,
|
||||
TableProperties* table_properties, int level, const uint64_t creation_time,
|
||||
const uint64_t oldest_key_time) {
|
||||
TableProperties* table_properties, int level) {
|
||||
assert((column_family_id ==
|
||||
TablePropertiesCollectorFactory::Context::kUnknownColumnFamily) ==
|
||||
column_family_name.empty());
|
||||
@@ -120,11 +119,11 @@ Status BuildTable(
|
||||
|
||||
file_writer.reset(new WritableFileWriter(std::move(file), env_options,
|
||||
ioptions.statistics));
|
||||
|
||||
builder = NewTableBuilder(
|
||||
ioptions, internal_comparator, int_tbl_prop_collector_factories,
|
||||
column_family_id, column_family_name, file_writer.get(), compression,
|
||||
compression_opts, level, nullptr /* compression_dict */,
|
||||
false /* skip_filters */, creation_time, oldest_key_time);
|
||||
compression_opts, level);
|
||||
}
|
||||
|
||||
MergeHelper merge(env, internal_comparator.user_comparator(),
|
||||
|
||||
+4
-5
@@ -48,10 +48,10 @@ TableBuilder* NewTableBuilder(
|
||||
int_tbl_prop_collector_factories,
|
||||
uint32_t column_family_id, const std::string& column_family_name,
|
||||
WritableFileWriter* file, const CompressionType compression_type,
|
||||
const CompressionOptions& compression_opts, int level,
|
||||
const CompressionOptions& compression_opts,
|
||||
int level,
|
||||
const std::string* compression_dict = nullptr,
|
||||
const bool skip_filters = false, const uint64_t creation_time = 0,
|
||||
const uint64_t oldest_key_time = 0);
|
||||
const bool skip_filters = false);
|
||||
|
||||
// Build a Table file from the contents of *iter. The generated file
|
||||
// will be named according to number specified in meta. On success, the rest of
|
||||
@@ -77,7 +77,6 @@ extern Status BuildTable(
|
||||
InternalStats* internal_stats, TableFileCreationReason reason,
|
||||
EventLogger* event_logger = nullptr, int job_id = 0,
|
||||
const Env::IOPriority io_priority = Env::IO_HIGH,
|
||||
TableProperties* table_properties = nullptr, int level = -1,
|
||||
const uint64_t creation_time = 0, const uint64_t oldest_key_time = 0);
|
||||
TableProperties* table_properties = nullptr, int level = -1);
|
||||
|
||||
} // namespace rocksdb
|
||||
@@ -34,10 +34,6 @@
|
||||
#include "rocksdb/utilities/backupable_db.h"
|
||||
#include "rocksdb/utilities/write_batch_with_index.h"
|
||||
#include "utilities/merge_operators.h"
|
||||
#include "rocksdb/utilities/transaction.h"
|
||||
#include "rocksdb/utilities/transaction_db.h"
|
||||
#include "rocksdb/utilities/optimistic_transaction_db.h"
|
||||
#include "rocksdb/utilities/checkpoint.h"
|
||||
|
||||
using rocksdb::BytewiseComparator;
|
||||
using rocksdb::Cache;
|
||||
@@ -53,7 +49,6 @@ using rocksdb::CompressionType;
|
||||
using rocksdb::WALRecoveryMode;
|
||||
using rocksdb::DB;
|
||||
using rocksdb::DBOptions;
|
||||
using rocksdb::DbPath;
|
||||
using rocksdb::Env;
|
||||
using rocksdb::EnvOptions;
|
||||
using rocksdb::InfoLogLevel;
|
||||
@@ -92,14 +87,6 @@ using rocksdb::RestoreOptions;
|
||||
using rocksdb::CompactRangeOptions;
|
||||
using rocksdb::RateLimiter;
|
||||
using rocksdb::NewGenericRateLimiter;
|
||||
using rocksdb::PinnableSlice;
|
||||
using rocksdb::TransactionDBOptions;
|
||||
using rocksdb::TransactionDB;
|
||||
using rocksdb::TransactionOptions;
|
||||
using rocksdb::OptimisticTransactionDB;
|
||||
using rocksdb::OptimisticTransactionOptions;
|
||||
using rocksdb::Transaction;
|
||||
using rocksdb::Checkpoint;
|
||||
|
||||
using std::shared_ptr;
|
||||
|
||||
@@ -138,30 +125,6 @@ struct rocksdb_envoptions_t { EnvOptions rep; };
|
||||
struct rocksdb_ingestexternalfileoptions_t { IngestExternalFileOptions rep; };
|
||||
struct rocksdb_sstfilewriter_t { SstFileWriter* rep; };
|
||||
struct rocksdb_ratelimiter_t { RateLimiter* rep; };
|
||||
struct rocksdb_pinnableslice_t {
|
||||
PinnableSlice rep;
|
||||
};
|
||||
struct rocksdb_transactiondb_options_t {
|
||||
TransactionDBOptions rep;
|
||||
};
|
||||
struct rocksdb_transactiondb_t {
|
||||
TransactionDB* rep;
|
||||
};
|
||||
struct rocksdb_transaction_options_t {
|
||||
TransactionOptions rep;
|
||||
};
|
||||
struct rocksdb_transaction_t {
|
||||
Transaction* rep;
|
||||
};
|
||||
struct rocksdb_checkpoint_t {
|
||||
Checkpoint* rep;
|
||||
};
|
||||
struct rocksdb_optimistictransactiondb_t {
|
||||
OptimisticTransactionDB* rep;
|
||||
};
|
||||
struct rocksdb_optimistictransaction_options_t {
|
||||
OptimisticTransactionOptions rep;
|
||||
};
|
||||
|
||||
struct rocksdb_compactionfiltercontext_t {
|
||||
CompactionFilter::Context rep;
|
||||
@@ -392,10 +355,6 @@ struct rocksdb_mergeoperator_t : public MergeOperator {
|
||||
}
|
||||
};
|
||||
|
||||
struct rocksdb_dbpath_t {
|
||||
DbPath rep;
|
||||
};
|
||||
|
||||
struct rocksdb_env_t {
|
||||
Env* rep;
|
||||
bool is_default;
|
||||
@@ -578,29 +537,6 @@ void rocksdb_backup_engine_close(rocksdb_backup_engine_t* be) {
|
||||
delete be;
|
||||
}
|
||||
|
||||
rocksdb_checkpoint_t* rocksdb_checkpoint_object_create(rocksdb_t* db,
|
||||
char** errptr) {
|
||||
Checkpoint* checkpoint;
|
||||
if (SaveError(errptr, Checkpoint::Create(db->rep, &checkpoint))) {
|
||||
return nullptr;
|
||||
}
|
||||
rocksdb_checkpoint_t* result = new rocksdb_checkpoint_t;
|
||||
result->rep = checkpoint;
|
||||
return result;
|
||||
}
|
||||
|
||||
void rocksdb_checkpoint_create(rocksdb_checkpoint_t* checkpoint,
|
||||
const char* checkpoint_dir,
|
||||
uint64_t log_size_for_flush, char** errptr) {
|
||||
SaveError(errptr, checkpoint->rep->CreateCheckpoint(
|
||||
std::string(checkpoint_dir), log_size_for_flush));
|
||||
}
|
||||
|
||||
void rocksdb_checkpoint_object_destroy(rocksdb_checkpoint_t* checkpoint) {
|
||||
delete checkpoint->rep;
|
||||
delete checkpoint;
|
||||
}
|
||||
|
||||
void rocksdb_close(rocksdb_t* db) {
|
||||
delete db->rep;
|
||||
delete db;
|
||||
@@ -1386,24 +1322,23 @@ void rocksdb_writebatch_put_log_data(
|
||||
b->rep.PutLogData(Slice(blob, len));
|
||||
}
|
||||
|
||||
class H : public WriteBatch::Handler {
|
||||
public:
|
||||
void* state_;
|
||||
void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen);
|
||||
void (*deleted_)(void*, const char* k, size_t klen);
|
||||
virtual void Put(const Slice& key, const Slice& value) override {
|
||||
(*put_)(state_, key.data(), key.size(), value.data(), value.size());
|
||||
}
|
||||
virtual void Delete(const Slice& key) override {
|
||||
(*deleted_)(state_, key.data(), key.size());
|
||||
}
|
||||
};
|
||||
|
||||
void rocksdb_writebatch_iterate(
|
||||
rocksdb_writebatch_t* b,
|
||||
void* state,
|
||||
void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen),
|
||||
void (*deleted)(void*, const char* k, size_t klen)) {
|
||||
class H : public WriteBatch::Handler {
|
||||
public:
|
||||
void* state_;
|
||||
void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen);
|
||||
void (*deleted_)(void*, const char* k, size_t klen);
|
||||
virtual void Put(const Slice& key, const Slice& value) override {
|
||||
(*put_)(state_, key.data(), key.size(), value.data(), value.size());
|
||||
}
|
||||
virtual void Delete(const Slice& key) override {
|
||||
(*deleted_)(state_, key.data(), key.size());
|
||||
}
|
||||
};
|
||||
H handler;
|
||||
handler.state_ = state;
|
||||
handler.put_ = put;
|
||||
@@ -1425,10 +1360,6 @@ void rocksdb_writebatch_rollback_to_save_point(rocksdb_writebatch_t* b,
|
||||
SaveError(errptr, b->rep.RollbackToSavePoint());
|
||||
}
|
||||
|
||||
void rocksdb_writebatch_pop_save_point(rocksdb_writebatch_t* b, char** errptr) {
|
||||
SaveError(errptr, b->rep.PopSavePoint());
|
||||
}
|
||||
|
||||
rocksdb_writebatch_wi_t* rocksdb_writebatch_wi_create(size_t reserved_bytes, unsigned char overwrite_key) {
|
||||
rocksdb_writebatch_wi_t* b = new rocksdb_writebatch_wi_t;
|
||||
b->rep = new WriteBatchWithIndex(BytewiseComparator(), reserved_bytes, overwrite_key);
|
||||
@@ -1648,6 +1579,18 @@ void rocksdb_writebatch_wi_iterate(
|
||||
void* state,
|
||||
void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen),
|
||||
void (*deleted)(void*, const char* k, size_t klen)) {
|
||||
class H : public WriteBatch::Handler {
|
||||
public:
|
||||
void* state_;
|
||||
void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen);
|
||||
void (*deleted_)(void*, const char* k, size_t klen);
|
||||
virtual void Put(const Slice& key, const Slice& value) override {
|
||||
(*put_)(state_, key.data(), key.size(), value.data(), value.size());
|
||||
}
|
||||
virtual void Delete(const Slice& key) override {
|
||||
(*deleted_)(state_, key.data(), key.size());
|
||||
}
|
||||
};
|
||||
H handler;
|
||||
handler.state_ = state;
|
||||
handler.put_ = put;
|
||||
@@ -2012,16 +1955,6 @@ void rocksdb_options_set_paranoid_checks(
|
||||
opt->rep.paranoid_checks = v;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_db_paths(rocksdb_options_t* opt,
|
||||
const rocksdb_dbpath_t** dbpath_values,
|
||||
size_t num_paths) {
|
||||
std::vector<DbPath> db_paths(num_paths);
|
||||
for (size_t i = 0; i < num_paths; ++i) {
|
||||
db_paths[i] = dbpath_values[i]->rep;
|
||||
}
|
||||
opt->rep.db_paths = db_paths;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_env(rocksdb_options_t* opt, rocksdb_env_t* env) {
|
||||
opt->rep.env = (env ? env->rep : nullptr);
|
||||
}
|
||||
@@ -2050,10 +1983,6 @@ void rocksdb_options_set_max_open_files(rocksdb_options_t* opt, int n) {
|
||||
opt->rep.max_open_files = n;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_max_file_opening_threads(rocksdb_options_t* opt, int n) {
|
||||
opt->rep.max_file_opening_threads = n;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_max_total_wal_size(rocksdb_options_t* opt, uint64_t n) {
|
||||
opt->rep.max_total_wal_size = n;
|
||||
}
|
||||
@@ -2100,10 +2029,6 @@ void rocksdb_options_enable_statistics(rocksdb_options_t* opt) {
|
||||
opt->rep.statistics = rocksdb::CreateDBStatistics();
|
||||
}
|
||||
|
||||
void rocksdb_options_set_skip_stats_update_on_db_open(rocksdb_options_t* opt, unsigned char val) {
|
||||
opt->rep.skip_stats_update_on_db_open = val;
|
||||
}
|
||||
|
||||
void rocksdb_options_set_num_levels(rocksdb_options_t* opt, int n) {
|
||||
opt->rep.num_levels = n;
|
||||
}
|
||||
@@ -2806,17 +2731,6 @@ size_t rocksdb_cache_get_pinned_usage(rocksdb_cache_t* cache) {
|
||||
return cache->rep->GetPinnedUsage();
|
||||
}
|
||||
|
||||
rocksdb_dbpath_t* rocksdb_dbpath_create(const char* path, uint64_t target_size) {
|
||||
rocksdb_dbpath_t* result = new rocksdb_dbpath_t;
|
||||
result->rep.path = std::string(path);
|
||||
result->rep.target_size = target_size;
|
||||
return result;
|
||||
}
|
||||
|
||||
void rocksdb_dbpath_destroy(rocksdb_dbpath_t* dbpath) {
|
||||
delete dbpath;
|
||||
}
|
||||
|
||||
rocksdb_env_t* rocksdb_create_default_env() {
|
||||
rocksdb_env_t* result = new rocksdb_env_t;
|
||||
result->rep = Env::Default();
|
||||
@@ -2878,26 +2792,7 @@ void rocksdb_sstfilewriter_open(rocksdb_sstfilewriter_t* writer,
|
||||
void rocksdb_sstfilewriter_add(rocksdb_sstfilewriter_t* writer, const char* key,
|
||||
size_t keylen, const char* val, size_t vallen,
|
||||
char** errptr) {
|
||||
SaveError(errptr, writer->rep->Put(Slice(key, keylen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_sstfilewriter_put(rocksdb_sstfilewriter_t* writer, const char* key,
|
||||
size_t keylen, const char* val, size_t vallen,
|
||||
char** errptr) {
|
||||
SaveError(errptr, writer->rep->Put(Slice(key, keylen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_sstfilewriter_merge(rocksdb_sstfilewriter_t* writer,
|
||||
const char* key, size_t keylen,
|
||||
const char* val, size_t vallen,
|
||||
char** errptr) {
|
||||
SaveError(errptr, writer->rep->Merge(Slice(key, keylen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_sstfilewriter_delete(rocksdb_sstfilewriter_t* writer,
|
||||
const char* key, size_t keylen,
|
||||
char** errptr) {
|
||||
SaveError(errptr, writer->rep->Delete(Slice(key, keylen)));
|
||||
SaveError(errptr, writer->rep->Add(Slice(key, keylen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
void rocksdb_sstfilewriter_finish(rocksdb_sstfilewriter_t* writer,
|
||||
@@ -2994,21 +2889,20 @@ void rocksdb_slicetransform_destroy(rocksdb_slicetransform_t* st) {
|
||||
delete st;
|
||||
}
|
||||
|
||||
struct Wrapper : public rocksdb_slicetransform_t {
|
||||
const SliceTransform* rep_;
|
||||
~Wrapper() { delete rep_; }
|
||||
const char* Name() const override { return rep_->Name(); }
|
||||
Slice Transform(const Slice& src) const override {
|
||||
return rep_->Transform(src);
|
||||
}
|
||||
bool InDomain(const Slice& src) const override {
|
||||
return rep_->InDomain(src);
|
||||
}
|
||||
bool InRange(const Slice& src) const override { return rep_->InRange(src); }
|
||||
static void DoNothing(void*) { }
|
||||
};
|
||||
|
||||
rocksdb_slicetransform_t* rocksdb_slicetransform_create_fixed_prefix(size_t prefixLen) {
|
||||
struct Wrapper : public rocksdb_slicetransform_t {
|
||||
const SliceTransform* rep_;
|
||||
~Wrapper() { delete rep_; }
|
||||
const char* Name() const override { return rep_->Name(); }
|
||||
Slice Transform(const Slice& src) const override {
|
||||
return rep_->Transform(src);
|
||||
}
|
||||
bool InDomain(const Slice& src) const override {
|
||||
return rep_->InDomain(src);
|
||||
}
|
||||
bool InRange(const Slice& src) const override { return rep_->InRange(src); }
|
||||
static void DoNothing(void*) { }
|
||||
};
|
||||
Wrapper* wrapper = new Wrapper;
|
||||
wrapper->rep_ = rocksdb::NewFixedPrefixTransform(prefixLen);
|
||||
wrapper->state_ = nullptr;
|
||||
@@ -3017,6 +2911,19 @@ rocksdb_slicetransform_t* rocksdb_slicetransform_create_fixed_prefix(size_t pref
|
||||
}
|
||||
|
||||
rocksdb_slicetransform_t* rocksdb_slicetransform_create_noop() {
|
||||
struct Wrapper : public rocksdb_slicetransform_t {
|
||||
const SliceTransform* rep_;
|
||||
~Wrapper() { delete rep_; }
|
||||
const char* Name() const override { return rep_->Name(); }
|
||||
Slice Transform(const Slice& src) const override {
|
||||
return rep_->Transform(src);
|
||||
}
|
||||
bool InDomain(const Slice& src) const override {
|
||||
return rep_->InDomain(src);
|
||||
}
|
||||
bool InRange(const Slice& src) const override { return rep_->InRange(src); }
|
||||
static void DoNothing(void*) { }
|
||||
};
|
||||
Wrapper* wrapper = new Wrapper;
|
||||
wrapper->rep_ = rocksdb::NewNoopTransform();
|
||||
wrapper->state_ = nullptr;
|
||||
@@ -3173,467 +3080,8 @@ void rocksdb_delete_file_in_range_cf(
|
||||
(limit_key ? (b = Slice(limit_key, limit_key_len), &b) : nullptr)));
|
||||
}
|
||||
|
||||
rocksdb_transactiondb_options_t* rocksdb_transactiondb_options_create() {
|
||||
return new rocksdb_transactiondb_options_t;
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_options_destroy(rocksdb_transactiondb_options_t* opt){
|
||||
delete opt;
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_options_set_max_num_locks(
|
||||
rocksdb_transactiondb_options_t* opt, int64_t max_num_locks) {
|
||||
opt->rep.max_num_locks = max_num_locks;
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_options_set_num_stripes(
|
||||
rocksdb_transactiondb_options_t* opt, size_t num_stripes) {
|
||||
opt->rep.num_stripes = num_stripes;
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_options_set_transaction_lock_timeout(
|
||||
rocksdb_transactiondb_options_t* opt, int64_t txn_lock_timeout) {
|
||||
opt->rep.transaction_lock_timeout = txn_lock_timeout;
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_options_set_default_lock_timeout(
|
||||
rocksdb_transactiondb_options_t* opt, int64_t default_lock_timeout) {
|
||||
opt->rep.default_lock_timeout = default_lock_timeout;
|
||||
}
|
||||
|
||||
rocksdb_transaction_options_t* rocksdb_transaction_options_create() {
|
||||
return new rocksdb_transaction_options_t;
|
||||
}
|
||||
|
||||
void rocksdb_transaction_options_destroy(rocksdb_transaction_options_t* opt) {
|
||||
delete opt;
|
||||
}
|
||||
|
||||
void rocksdb_transaction_options_set_set_snapshot(
|
||||
rocksdb_transaction_options_t* opt, unsigned char v) {
|
||||
opt->rep.set_snapshot = v;
|
||||
}
|
||||
|
||||
void rocksdb_transaction_options_set_deadlock_detect(
|
||||
rocksdb_transaction_options_t* opt, unsigned char v) {
|
||||
opt->rep.deadlock_detect = v;
|
||||
}
|
||||
|
||||
void rocksdb_transaction_options_set_lock_timeout(
|
||||
rocksdb_transaction_options_t* opt, int64_t lock_timeout) {
|
||||
opt->rep.lock_timeout = lock_timeout;
|
||||
}
|
||||
|
||||
void rocksdb_transaction_options_set_expiration(
|
||||
rocksdb_transaction_options_t* opt, int64_t expiration) {
|
||||
opt->rep.expiration = expiration;
|
||||
}
|
||||
|
||||
void rocksdb_transaction_options_set_deadlock_detect_depth(
|
||||
rocksdb_transaction_options_t* opt, int64_t depth) {
|
||||
opt->rep.deadlock_detect_depth = depth;
|
||||
}
|
||||
|
||||
void rocksdb_transaction_options_set_max_write_batch_size(
|
||||
rocksdb_transaction_options_t* opt, size_t size) {
|
||||
opt->rep.max_write_batch_size = size;
|
||||
}
|
||||
|
||||
rocksdb_optimistictransaction_options_t*
|
||||
rocksdb_optimistictransaction_options_create() {
|
||||
return new rocksdb_optimistictransaction_options_t;
|
||||
}
|
||||
|
||||
void rocksdb_optimistictransaction_options_destroy(
|
||||
rocksdb_optimistictransaction_options_t* opt) {
|
||||
delete opt;
|
||||
}
|
||||
|
||||
void rocksdb_optimistictransaction_options_set_set_snapshot(
|
||||
rocksdb_optimistictransaction_options_t* opt, unsigned char v) {
|
||||
opt->rep.set_snapshot = v;
|
||||
}
|
||||
|
||||
rocksdb_column_family_handle_t* rocksdb_transactiondb_create_column_family(
|
||||
rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_options_t* column_family_options,
|
||||
const char* column_family_name, char** errptr) {
|
||||
rocksdb_column_family_handle_t* handle = new rocksdb_column_family_handle_t;
|
||||
SaveError(errptr, txn_db->rep->CreateColumnFamily(
|
||||
ColumnFamilyOptions(column_family_options->rep),
|
||||
std::string(column_family_name), &(handle->rep)));
|
||||
return handle;
|
||||
}
|
||||
|
||||
rocksdb_transactiondb_t* rocksdb_transactiondb_open(
|
||||
const rocksdb_options_t* options,
|
||||
const rocksdb_transactiondb_options_t* txn_db_options, const char* name,
|
||||
char** errptr) {
|
||||
TransactionDB* txn_db;
|
||||
if (SaveError(errptr, TransactionDB::Open(options->rep, txn_db_options->rep,
|
||||
std::string(name), &txn_db))) {
|
||||
return nullptr;
|
||||
}
|
||||
rocksdb_transactiondb_t* result = new rocksdb_transactiondb_t;
|
||||
result->rep = txn_db;
|
||||
return result;
|
||||
}
|
||||
|
||||
const rocksdb_snapshot_t* rocksdb_transactiondb_create_snapshot(
|
||||
rocksdb_transactiondb_t* txn_db) {
|
||||
rocksdb_snapshot_t* result = new rocksdb_snapshot_t;
|
||||
result->rep = txn_db->rep->GetSnapshot();
|
||||
return result;
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_release_snapshot(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_snapshot_t* snapshot) {
|
||||
txn_db->rep->ReleaseSnapshot(snapshot->rep);
|
||||
delete snapshot;
|
||||
}
|
||||
|
||||
rocksdb_transaction_t* rocksdb_transaction_begin(
|
||||
rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_writeoptions_t* write_options,
|
||||
const rocksdb_transaction_options_t* txn_options,
|
||||
rocksdb_transaction_t* old_txn) {
|
||||
if (old_txn == nullptr) {
|
||||
rocksdb_transaction_t* result = new rocksdb_transaction_t;
|
||||
result->rep = txn_db->rep->BeginTransaction(write_options->rep,
|
||||
txn_options->rep, nullptr);
|
||||
return result;
|
||||
}
|
||||
old_txn->rep = txn_db->rep->BeginTransaction(write_options->rep,
|
||||
txn_options->rep, old_txn->rep);
|
||||
return old_txn;
|
||||
}
|
||||
|
||||
void rocksdb_transaction_commit(rocksdb_transaction_t* txn, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Commit());
|
||||
}
|
||||
|
||||
void rocksdb_transaction_rollback(rocksdb_transaction_t* txn, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Rollback());
|
||||
}
|
||||
|
||||
void rocksdb_transaction_destroy(rocksdb_transaction_t* txn) {
|
||||
delete txn->rep;
|
||||
delete txn;
|
||||
}
|
||||
|
||||
const rocksdb_snapshot_t* rocksdb_transaction_get_snapshot(
|
||||
rocksdb_transaction_t* txn) {
|
||||
rocksdb_snapshot_t* result = new rocksdb_snapshot_t;
|
||||
result->rep = txn->rep->GetSnapshot();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Read a key inside a transaction
|
||||
char* rocksdb_transaction_get(rocksdb_transaction_t* txn,
|
||||
const rocksdb_readoptions_t* options,
|
||||
const char* key, size_t klen, size_t* vlen,
|
||||
char** errptr) {
|
||||
char* result = nullptr;
|
||||
std::string tmp;
|
||||
Status s = txn->rep->Get(options->rep, Slice(key, klen), &tmp);
|
||||
if (s.ok()) {
|
||||
*vlen = tmp.size();
|
||||
result = CopyString(tmp);
|
||||
} else {
|
||||
*vlen = 0;
|
||||
if (!s.IsNotFound()) {
|
||||
SaveError(errptr, s);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
char* rocksdb_transaction_get_cf(rocksdb_transaction_t* txn,
|
||||
const rocksdb_readoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, size_t* vlen,
|
||||
char** errptr) {
|
||||
char* result = nullptr;
|
||||
std::string tmp;
|
||||
Status s =
|
||||
txn->rep->Get(options->rep, column_family->rep, Slice(key, klen), &tmp);
|
||||
if (s.ok()) {
|
||||
*vlen = tmp.size();
|
||||
result = CopyString(tmp);
|
||||
} else {
|
||||
*vlen = 0;
|
||||
if (!s.IsNotFound()) {
|
||||
SaveError(errptr, s);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Read a key inside a transaction
|
||||
char* rocksdb_transaction_get_for_update(rocksdb_transaction_t* txn,
|
||||
const rocksdb_readoptions_t* options,
|
||||
const char* key, size_t klen,
|
||||
size_t* vlen, unsigned char exclusive,
|
||||
char** errptr) {
|
||||
char* result = nullptr;
|
||||
std::string tmp;
|
||||
Status s =
|
||||
txn->rep->GetForUpdate(options->rep, Slice(key, klen), &tmp, exclusive);
|
||||
if (s.ok()) {
|
||||
*vlen = tmp.size();
|
||||
result = CopyString(tmp);
|
||||
} else {
|
||||
*vlen = 0;
|
||||
if (!s.IsNotFound()) {
|
||||
SaveError(errptr, s);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Read a key outside a transaction
|
||||
char* rocksdb_transactiondb_get(
|
||||
rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_readoptions_t* options,
|
||||
const char* key, size_t klen,
|
||||
size_t* vlen,
|
||||
char** errptr){
|
||||
char* result = nullptr;
|
||||
std::string tmp;
|
||||
Status s = txn_db->rep->Get(options->rep, Slice(key, klen), &tmp);
|
||||
if (s.ok()) {
|
||||
*vlen = tmp.size();
|
||||
result = CopyString(tmp);
|
||||
} else {
|
||||
*vlen = 0;
|
||||
if (!s.IsNotFound()) {
|
||||
SaveError(errptr, s);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
char* rocksdb_transactiondb_get_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_readoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, size_t* vallen, char** errptr) {
|
||||
char* result = nullptr;
|
||||
std::string tmp;
|
||||
Status s = txn_db->rep->Get(options->rep, column_family->rep,
|
||||
Slice(key, keylen), &tmp);
|
||||
if (s.ok()) {
|
||||
*vallen = tmp.size();
|
||||
result = CopyString(tmp);
|
||||
} else {
|
||||
*vallen = 0;
|
||||
if (!s.IsNotFound()) {
|
||||
SaveError(errptr, s);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Put a key inside a transaction
|
||||
void rocksdb_transaction_put(rocksdb_transaction_t* txn, const char* key,
|
||||
size_t klen, const char* val, size_t vlen,
|
||||
char** errptr) {
|
||||
SaveError(errptr, txn->rep->Put(Slice(key, klen), Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_put_cf(rocksdb_transaction_t* txn,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, const char* val,
|
||||
size_t vlen, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Put(column_family->rep, Slice(key, klen),
|
||||
Slice(val, vlen)));
|
||||
}
|
||||
|
||||
// Put a key outside a transaction
|
||||
void rocksdb_transactiondb_put(rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t klen, const char* val,
|
||||
size_t vlen, char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Put(options->rep, Slice(key, klen),
|
||||
Slice(val, vlen)));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_put_cf(rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t keylen,
|
||||
const char* val, size_t vallen,
|
||||
char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Put(options->rep, column_family->rep,
|
||||
Slice(key, keylen), Slice(val, vallen)));
|
||||
}
|
||||
|
||||
// Write batch into transaction db
|
||||
void rocksdb_transactiondb_write(
|
||||
rocksdb_transactiondb_t* db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
rocksdb_writebatch_t* batch,
|
||||
char** errptr) {
|
||||
SaveError(errptr, db->rep->Write(options->rep, &batch->rep));
|
||||
}
|
||||
|
||||
// Merge a key inside a transaction
|
||||
void rocksdb_transaction_merge(rocksdb_transaction_t* txn, const char* key,
|
||||
size_t klen, const char* val, size_t vlen,
|
||||
char** errptr) {
|
||||
SaveError(errptr, txn->rep->Merge(Slice(key, klen), Slice(val, vlen)));
|
||||
}
|
||||
|
||||
// Merge a key outside a transaction
|
||||
void rocksdb_transactiondb_merge(rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t klen, const char* val,
|
||||
size_t vlen, char** errptr) {
|
||||
SaveError(errptr,
|
||||
txn_db->rep->Merge(options->rep, Slice(key, klen), Slice(val, vlen)));
|
||||
}
|
||||
|
||||
// Delete a key inside a transaction
|
||||
void rocksdb_transaction_delete(rocksdb_transaction_t* txn, const char* key,
|
||||
size_t klen, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Delete(Slice(key, klen)));
|
||||
}
|
||||
|
||||
void rocksdb_transaction_delete_cf(
|
||||
rocksdb_transaction_t* txn, rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, size_t klen, char** errptr) {
|
||||
SaveError(errptr, txn->rep->Delete(column_family->rep, Slice(key, klen)));
|
||||
}
|
||||
|
||||
// Delete a key outside a transaction
|
||||
void rocksdb_transactiondb_delete(rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_writeoptions_t* options,
|
||||
const char* key, size_t klen, char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Delete(options->rep, Slice(key, klen)));
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_delete_cf(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_writeoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, char** errptr) {
|
||||
SaveError(errptr, txn_db->rep->Delete(options->rep, column_family->rep,
|
||||
Slice(key, keylen)));
|
||||
}
|
||||
|
||||
// Create an iterator inside a transaction
|
||||
rocksdb_iterator_t* rocksdb_transaction_create_iterator(
|
||||
rocksdb_transaction_t* txn, const rocksdb_readoptions_t* options) {
|
||||
rocksdb_iterator_t* result = new rocksdb_iterator_t;
|
||||
result->rep = txn->rep->GetIterator(options->rep);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Create an iterator outside a transaction
|
||||
rocksdb_iterator_t* rocksdb_transactiondb_create_iterator(
|
||||
rocksdb_transactiondb_t* txn_db, const rocksdb_readoptions_t* options) {
|
||||
rocksdb_iterator_t* result = new rocksdb_iterator_t;
|
||||
result->rep = txn_db->rep->NewIterator(options->rep);
|
||||
return result;
|
||||
}
|
||||
|
||||
void rocksdb_transactiondb_close(rocksdb_transactiondb_t* txn_db) {
|
||||
delete txn_db->rep;
|
||||
delete txn_db;
|
||||
}
|
||||
|
||||
rocksdb_checkpoint_t* rocksdb_transactiondb_checkpoint_object_create(
|
||||
rocksdb_transactiondb_t* txn_db, char** errptr) {
|
||||
Checkpoint* checkpoint;
|
||||
if (SaveError(errptr, Checkpoint::Create(txn_db->rep, &checkpoint))) {
|
||||
return nullptr;
|
||||
}
|
||||
rocksdb_checkpoint_t* result = new rocksdb_checkpoint_t;
|
||||
result->rep = checkpoint;
|
||||
return result;
|
||||
}
|
||||
|
||||
rocksdb_optimistictransactiondb_t* rocksdb_optimistictransactiondb_open(
|
||||
const rocksdb_options_t* options, const char* name,
|
||||
char** errptr) {
|
||||
OptimisticTransactionDB* otxn_db;
|
||||
if (SaveError(errptr, OptimisticTransactionDB::Open(
|
||||
options->rep, std::string(name), &otxn_db))) {
|
||||
return nullptr;
|
||||
}
|
||||
rocksdb_optimistictransactiondb_t* result =
|
||||
new rocksdb_optimistictransactiondb_t;
|
||||
result->rep = otxn_db;
|
||||
return result;
|
||||
}
|
||||
|
||||
rocksdb_transaction_t* rocksdb_optimistictransaction_begin(
|
||||
rocksdb_optimistictransactiondb_t* otxn_db,
|
||||
const rocksdb_writeoptions_t* write_options,
|
||||
const rocksdb_optimistictransaction_options_t* otxn_options,
|
||||
rocksdb_transaction_t* old_txn) {
|
||||
if (old_txn == nullptr) {
|
||||
rocksdb_transaction_t* result = new rocksdb_transaction_t;
|
||||
result->rep = otxn_db->rep->BeginTransaction(write_options->rep,
|
||||
otxn_options->rep, nullptr);
|
||||
return result;
|
||||
}
|
||||
old_txn->rep = otxn_db->rep->BeginTransaction(
|
||||
write_options->rep, otxn_options->rep, old_txn->rep);
|
||||
return old_txn;
|
||||
}
|
||||
|
||||
void rocksdb_optimistictransactiondb_close(
|
||||
rocksdb_optimistictransactiondb_t* otxn_db) {
|
||||
delete otxn_db->rep;
|
||||
delete otxn_db;
|
||||
}
|
||||
|
||||
void rocksdb_free(void* ptr) { free(ptr); }
|
||||
|
||||
rocksdb_pinnableslice_t* rocksdb_get_pinned(
|
||||
rocksdb_t* db, const rocksdb_readoptions_t* options, const char* key,
|
||||
size_t keylen, char** errptr) {
|
||||
rocksdb_pinnableslice_t* v = new (rocksdb_pinnableslice_t);
|
||||
Status s = db->rep->Get(options->rep, db->rep->DefaultColumnFamily(),
|
||||
Slice(key, keylen), &v->rep);
|
||||
if (!s.ok()) {
|
||||
delete (v);
|
||||
if (!s.IsNotFound()) {
|
||||
SaveError(errptr, s);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
rocksdb_pinnableslice_t* rocksdb_get_pinned_cf(
|
||||
rocksdb_t* db, const rocksdb_readoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family, const char* key,
|
||||
size_t keylen, char** errptr) {
|
||||
rocksdb_pinnableslice_t* v = new (rocksdb_pinnableslice_t);
|
||||
Status s = db->rep->Get(options->rep, column_family->rep, Slice(key, keylen),
|
||||
&v->rep);
|
||||
if (!s.ok()) {
|
||||
delete v;
|
||||
if (!s.IsNotFound()) {
|
||||
SaveError(errptr, s);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
void rocksdb_pinnableslice_destroy(rocksdb_pinnableslice_t* v) { delete v; }
|
||||
|
||||
const char* rocksdb_pinnableslice_value(const rocksdb_pinnableslice_t* v,
|
||||
size_t* vlen) {
|
||||
if (!v) {
|
||||
*vlen = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*vlen = v->rep.size();
|
||||
return v->rep.data();
|
||||
}
|
||||
} // end extern "C"
|
||||
|
||||
#endif // !ROCKSDB_LITE
|
||||
+11
-268
@@ -20,7 +20,7 @@
|
||||
// Can not use port/port.h macros as this is a c file
|
||||
#ifdef OS_WIN
|
||||
|
||||
#include <windows.h>
|
||||
#include <Windows.h>
|
||||
|
||||
#define snprintf _snprintf
|
||||
|
||||
@@ -40,8 +40,6 @@ const char* phase = "";
|
||||
static char dbname[200];
|
||||
static char sstfilename[200];
|
||||
static char dbbackupname[200];
|
||||
static char dbcheckpointname[200];
|
||||
static char dbpathname[200];
|
||||
|
||||
static void StartPhase(const char* name) {
|
||||
fprintf(stderr, "=== Test %s\n", name);
|
||||
@@ -128,32 +126,6 @@ static void CheckGetCF(
|
||||
Free(&val);
|
||||
}
|
||||
|
||||
static void CheckPinGet(rocksdb_t* db, const rocksdb_readoptions_t* options,
|
||||
const char* key, const char* expected) {
|
||||
char* err = NULL;
|
||||
size_t val_len;
|
||||
const char* val;
|
||||
rocksdb_pinnableslice_t* p;
|
||||
p = rocksdb_get_pinned(db, options, key, strlen(key), &err);
|
||||
CheckNoError(err);
|
||||
val = rocksdb_pinnableslice_value(p, &val_len);
|
||||
CheckEqual(expected, val, val_len);
|
||||
rocksdb_pinnableslice_destroy(p);
|
||||
}
|
||||
|
||||
static void CheckPinGetCF(rocksdb_t* db, const rocksdb_readoptions_t* options,
|
||||
rocksdb_column_family_handle_t* handle,
|
||||
const char* key, const char* expected) {
|
||||
char* err = NULL;
|
||||
size_t val_len;
|
||||
const char* val;
|
||||
rocksdb_pinnableslice_t* p;
|
||||
p = rocksdb_get_pinned_cf(db, options, handle, key, strlen(key), &err);
|
||||
CheckNoError(err);
|
||||
val = rocksdb_pinnableslice_value(p, &val_len);
|
||||
CheckEqual(expected, val, val_len);
|
||||
rocksdb_pinnableslice_destroy(p);
|
||||
}
|
||||
|
||||
static void CheckIter(rocksdb_iterator_t* iter,
|
||||
const char* key, const char* val) {
|
||||
@@ -320,53 +292,10 @@ static char* MergeOperatorPartialMerge(
|
||||
return result;
|
||||
}
|
||||
|
||||
static void CheckTxnGet(
|
||||
rocksdb_transaction_t* txn,
|
||||
const rocksdb_readoptions_t* options,
|
||||
const char* key,
|
||||
const char* expected) {
|
||||
char* err = NULL;
|
||||
size_t val_len;
|
||||
char* val;
|
||||
val = rocksdb_transaction_get(txn, options, key, strlen(key), &val_len, &err);
|
||||
CheckNoError(err);
|
||||
CheckEqual(expected, val, val_len);
|
||||
Free(&val);
|
||||
}
|
||||
|
||||
static void CheckTxnDBGet(
|
||||
rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_readoptions_t* options,
|
||||
const char* key,
|
||||
const char* expected) {
|
||||
char* err = NULL;
|
||||
size_t val_len;
|
||||
char* val;
|
||||
val = rocksdb_transactiondb_get(txn_db, options, key, strlen(key), &val_len, &err);
|
||||
CheckNoError(err);
|
||||
CheckEqual(expected, val, val_len);
|
||||
Free(&val);
|
||||
}
|
||||
|
||||
static void CheckTxnDBGetCF(rocksdb_transactiondb_t* txn_db,
|
||||
const rocksdb_readoptions_t* options,
|
||||
rocksdb_column_family_handle_t* column_family,
|
||||
const char* key, const char* expected) {
|
||||
char* err = NULL;
|
||||
size_t val_len;
|
||||
char* val;
|
||||
val = rocksdb_transactiondb_get_cf(txn_db, options, column_family, key,
|
||||
strlen(key), &val_len, &err);
|
||||
CheckNoError(err);
|
||||
CheckEqual(expected, val, val_len);
|
||||
Free(&val);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
rocksdb_t* db;
|
||||
rocksdb_comparator_t* cmp;
|
||||
rocksdb_cache_t* cache;
|
||||
rocksdb_dbpath_t *dbpath;
|
||||
rocksdb_env_t* env;
|
||||
rocksdb_options_t* options;
|
||||
rocksdb_compactoptions_t* coptions;
|
||||
@@ -374,10 +303,6 @@ int main(int argc, char** argv) {
|
||||
rocksdb_readoptions_t* roptions;
|
||||
rocksdb_writeoptions_t* woptions;
|
||||
rocksdb_ratelimiter_t* rate_limiter;
|
||||
rocksdb_transactiondb_t* txn_db;
|
||||
rocksdb_transactiondb_options_t* txn_db_options;
|
||||
rocksdb_transaction_t* txn;
|
||||
rocksdb_transaction_options_t* txn_options;
|
||||
char* err = NULL;
|
||||
int run = -1;
|
||||
|
||||
@@ -391,24 +316,13 @@ int main(int argc, char** argv) {
|
||||
GetTempDir(),
|
||||
((int) geteuid()));
|
||||
|
||||
snprintf(dbcheckpointname, sizeof(dbcheckpointname),
|
||||
"%s/rocksdb_c_test-%d-checkpoint",
|
||||
GetTempDir(),
|
||||
((int) geteuid()));
|
||||
|
||||
snprintf(sstfilename, sizeof(sstfilename),
|
||||
"%s/rocksdb_c_test-%d-sst",
|
||||
GetTempDir(),
|
||||
((int)geteuid()));
|
||||
|
||||
snprintf(dbpathname, sizeof(dbpathname),
|
||||
"%s/rocksdb_c_test-%d-dbpath",
|
||||
GetTempDir(),
|
||||
((int) geteuid()));
|
||||
|
||||
StartPhase("create_objects");
|
||||
cmp = rocksdb_comparator_create(NULL, CmpDestroy, CmpCompare, CmpName);
|
||||
dbpath = rocksdb_dbpath_create(dbpathname, 1024 * 1024);
|
||||
env = rocksdb_create_default_env();
|
||||
cache = rocksdb_cache_create_lru(100000);
|
||||
|
||||
@@ -517,36 +431,6 @@ int main(int argc, char** argv) {
|
||||
rocksdb_backup_engine_close(be);
|
||||
}
|
||||
|
||||
StartPhase("checkpoint");
|
||||
{
|
||||
rocksdb_destroy_db(options, dbcheckpointname, &err);
|
||||
CheckNoError(err);
|
||||
|
||||
rocksdb_checkpoint_t* checkpoint = rocksdb_checkpoint_object_create(db, &err);
|
||||
CheckNoError(err);
|
||||
|
||||
rocksdb_checkpoint_create(checkpoint, dbcheckpointname, 0, &err);
|
||||
CheckNoError(err);
|
||||
|
||||
// start a new database from the checkpoint
|
||||
rocksdb_close(db);
|
||||
rocksdb_options_set_error_if_exists(options, 0);
|
||||
db = rocksdb_open(options, dbcheckpointname, &err);
|
||||
CheckNoError(err);
|
||||
|
||||
CheckGet(db, roptions, "foo", "hello");
|
||||
|
||||
rocksdb_checkpoint_object_destroy(checkpoint);
|
||||
|
||||
rocksdb_close(db);
|
||||
rocksdb_destroy_db(options, dbcheckpointname, &err);
|
||||
CheckNoError(err);
|
||||
|
||||
db = rocksdb_open(options, dbname, &err);
|
||||
CheckNoError(err);
|
||||
rocksdb_options_set_error_if_exists(options, 1);
|
||||
}
|
||||
|
||||
StartPhase("compactall");
|
||||
rocksdb_compact_range(db, NULL, 0, NULL, 0);
|
||||
CheckGet(db, roptions, "foo", "hello");
|
||||
@@ -591,11 +475,11 @@ int main(int argc, char** argv) {
|
||||
unlink(sstfilename);
|
||||
rocksdb_sstfilewriter_open(writer, sstfilename, &err);
|
||||
CheckNoError(err);
|
||||
rocksdb_sstfilewriter_put(writer, "sstk1", 5, "v1", 2, &err);
|
||||
rocksdb_sstfilewriter_add(writer, "sstk1", 5, "v1", 2, &err);
|
||||
CheckNoError(err);
|
||||
rocksdb_sstfilewriter_put(writer, "sstk2", 5, "v2", 2, &err);
|
||||
rocksdb_sstfilewriter_add(writer, "sstk2", 5, "v2", 2, &err);
|
||||
CheckNoError(err);
|
||||
rocksdb_sstfilewriter_put(writer, "sstk3", 5, "v3", 2, &err);
|
||||
rocksdb_sstfilewriter_add(writer, "sstk3", 5, "v3", 2, &err);
|
||||
CheckNoError(err);
|
||||
rocksdb_sstfilewriter_finish(writer, &err);
|
||||
CheckNoError(err);
|
||||
@@ -612,11 +496,11 @@ int main(int argc, char** argv) {
|
||||
unlink(sstfilename);
|
||||
rocksdb_sstfilewriter_open(writer, sstfilename, &err);
|
||||
CheckNoError(err);
|
||||
rocksdb_sstfilewriter_put(writer, "sstk2", 5, "v4", 2, &err);
|
||||
rocksdb_sstfilewriter_add(writer, "sstk2", 5, "v4", 2, &err);
|
||||
CheckNoError(err);
|
||||
rocksdb_sstfilewriter_put(writer, "sstk22", 6, "v5", 2, &err);
|
||||
rocksdb_sstfilewriter_add(writer, "sstk22", 6, "v5", 2, &err);
|
||||
CheckNoError(err);
|
||||
rocksdb_sstfilewriter_put(writer, "sstk3", 5, "v6", 2, &err);
|
||||
rocksdb_sstfilewriter_add(writer, "sstk3", 5, "v6", 2, &err);
|
||||
CheckNoError(err);
|
||||
rocksdb_sstfilewriter_finish(writer, &err);
|
||||
CheckNoError(err);
|
||||
@@ -703,13 +587,10 @@ int main(int argc, char** argv) {
|
||||
{
|
||||
rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
|
||||
rocksdb_writebatch_set_save_point(wb);
|
||||
rocksdb_writebatch_set_save_point(wb);
|
||||
const char* k_list[2] = {"z", "ap"};
|
||||
const size_t k_sizes[2] = {1, 2};
|
||||
const char* v_list[3] = {"x", "y", "z"};
|
||||
const size_t v_sizes[3] = {1, 1, 1};
|
||||
rocksdb_writebatch_pop_save_point(wb, &err);
|
||||
CheckNoError(err);
|
||||
rocksdb_writebatch_putv(wb, 2, k_list, k_sizes, 3, v_list, v_sizes);
|
||||
rocksdb_writebatch_rollback_to_save_point(wb, &err);
|
||||
CheckNoError(err);
|
||||
@@ -905,13 +786,6 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
StartPhase("pin_get");
|
||||
{
|
||||
CheckPinGet(db, roptions, "box", "c");
|
||||
CheckPinGet(db, roptions, "foo", "hello");
|
||||
CheckPinGet(db, roptions, "notfound", NULL);
|
||||
}
|
||||
|
||||
StartPhase("approximate_sizes");
|
||||
{
|
||||
int i;
|
||||
@@ -1123,13 +997,11 @@ int main(int argc, char** argv) {
|
||||
CheckNoError(err);
|
||||
|
||||
CheckGetCF(db, roptions, handles[1], "foo", "hello");
|
||||
CheckPinGetCF(db, roptions, handles[1], "foo", "hello");
|
||||
|
||||
rocksdb_delete_cf(db, woptions, handles[1], "foo", 3, &err);
|
||||
CheckNoError(err);
|
||||
|
||||
CheckGetCF(db, roptions, handles[1], "foo", NULL);
|
||||
CheckPinGetCF(db, roptions, handles[1], "foo", NULL);
|
||||
|
||||
rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
|
||||
rocksdb_writebatch_put_cf(wb, handles[1], "baz", 3, "a", 1);
|
||||
@@ -1142,9 +1014,6 @@ int main(int argc, char** argv) {
|
||||
CheckGetCF(db, roptions, handles[1], "baz", NULL);
|
||||
CheckGetCF(db, roptions, handles[1], "bar", NULL);
|
||||
CheckGetCF(db, roptions, handles[1], "box", "c");
|
||||
CheckPinGetCF(db, roptions, handles[1], "baz", NULL);
|
||||
CheckPinGetCF(db, roptions, handles[1], "bar", NULL);
|
||||
CheckPinGetCF(db, roptions, handles[1], "box", "c");
|
||||
rocksdb_writebatch_destroy(wb);
|
||||
|
||||
const char* keys[3] = { "box", "box", "barfooxx" };
|
||||
@@ -1356,127 +1225,14 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
StartPhase("transactions");
|
||||
{
|
||||
rocksdb_close(db);
|
||||
rocksdb_destroy_db(options, dbname, &err);
|
||||
CheckNoError(err);
|
||||
|
||||
// open a TransactionDB
|
||||
txn_db_options = rocksdb_transactiondb_options_create();
|
||||
txn_options = rocksdb_transaction_options_create();
|
||||
rocksdb_options_set_create_if_missing(options, 1);
|
||||
txn_db = rocksdb_transactiondb_open(options, txn_db_options, dbname, &err);
|
||||
CheckNoError(err);
|
||||
|
||||
// put outside a transaction
|
||||
rocksdb_transactiondb_put(txn_db, woptions, "foo", 3, "hello", 5, &err);
|
||||
CheckNoError(err);
|
||||
CheckTxnDBGet(txn_db, roptions, "foo", "hello");
|
||||
|
||||
// delete from outside transaction
|
||||
rocksdb_transactiondb_delete(txn_db, woptions, "foo", 3, &err);
|
||||
CheckNoError(err);
|
||||
CheckTxnDBGet(txn_db, roptions, "foo", NULL);
|
||||
|
||||
// write batch into TransactionDB
|
||||
rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
|
||||
rocksdb_writebatch_put(wb, "foo", 3, "a", 1);
|
||||
rocksdb_writebatch_clear(wb);
|
||||
rocksdb_writebatch_put(wb, "bar", 3, "b", 1);
|
||||
rocksdb_writebatch_put(wb, "box", 3, "c", 1);
|
||||
rocksdb_writebatch_delete(wb, "bar", 3);
|
||||
rocksdb_transactiondb_write(txn_db, woptions, wb, &err);
|
||||
rocksdb_writebatch_destroy(wb);
|
||||
CheckTxnDBGet(txn_db, roptions, "box", "c");
|
||||
CheckNoError(err);
|
||||
|
||||
// begin a transaction
|
||||
txn = rocksdb_transaction_begin(txn_db, woptions, txn_options, NULL);
|
||||
// put
|
||||
rocksdb_transaction_put(txn, "foo", 3, "hello", 5, &err);
|
||||
CheckNoError(err);
|
||||
CheckTxnGet(txn, roptions, "foo", "hello");
|
||||
// delete
|
||||
rocksdb_transaction_delete(txn, "foo", 3, &err);
|
||||
CheckNoError(err);
|
||||
CheckTxnGet(txn, roptions, "foo", NULL);
|
||||
|
||||
rocksdb_transaction_put(txn, "foo", 3, "hello", 5, &err);
|
||||
CheckNoError(err);
|
||||
|
||||
// read from outside transaction, before commit
|
||||
CheckTxnDBGet(txn_db, roptions, "foo", NULL);
|
||||
|
||||
// commit
|
||||
rocksdb_transaction_commit(txn, &err);
|
||||
CheckNoError(err);
|
||||
|
||||
// read from outside transaction, after commit
|
||||
CheckTxnDBGet(txn_db, roptions, "foo", "hello");
|
||||
|
||||
// reuse old transaction
|
||||
txn = rocksdb_transaction_begin(txn_db, woptions, txn_options, txn);
|
||||
|
||||
// snapshot
|
||||
const rocksdb_snapshot_t* snapshot;
|
||||
snapshot = rocksdb_transactiondb_create_snapshot(txn_db);
|
||||
rocksdb_readoptions_set_snapshot(roptions, snapshot);
|
||||
|
||||
rocksdb_transactiondb_put(txn_db, woptions, "foo", 3, "hey", 3, &err);
|
||||
CheckNoError(err);
|
||||
|
||||
CheckTxnDBGet(txn_db, roptions, "foo", "hello");
|
||||
rocksdb_readoptions_set_snapshot(roptions, NULL);
|
||||
rocksdb_transactiondb_release_snapshot(txn_db, snapshot);
|
||||
CheckTxnDBGet(txn_db, roptions, "foo", "hey");
|
||||
|
||||
// iterate
|
||||
rocksdb_transaction_put(txn, "bar", 3, "hi", 2, &err);
|
||||
rocksdb_iterator_t* iter = rocksdb_transaction_create_iterator(txn, roptions);
|
||||
CheckCondition(!rocksdb_iter_valid(iter));
|
||||
rocksdb_iter_seek_to_first(iter);
|
||||
CheckCondition(rocksdb_iter_valid(iter));
|
||||
CheckIter(iter, "bar", "hi");
|
||||
rocksdb_iter_get_error(iter, &err);
|
||||
CheckNoError(err);
|
||||
rocksdb_iter_destroy(iter);
|
||||
|
||||
// rollback
|
||||
rocksdb_transaction_rollback(txn, &err);
|
||||
CheckNoError(err);
|
||||
CheckTxnDBGet(txn_db, roptions, "bar", NULL);
|
||||
|
||||
// Column families.
|
||||
rocksdb_column_family_handle_t* cfh;
|
||||
cfh = rocksdb_transactiondb_create_column_family(txn_db, options,
|
||||
"txn_db_cf", &err);
|
||||
CheckNoError(err);
|
||||
|
||||
rocksdb_transactiondb_put_cf(txn_db, woptions, cfh, "cf_foo", 6, "cf_hello",
|
||||
8, &err);
|
||||
CheckNoError(err);
|
||||
CheckTxnDBGetCF(txn_db, roptions, cfh, "cf_foo", "cf_hello");
|
||||
|
||||
rocksdb_transactiondb_delete_cf(txn_db, woptions, cfh, "cf_foo", 6, &err);
|
||||
CheckNoError(err);
|
||||
CheckTxnDBGetCF(txn_db, roptions, cfh, "cf_foo", NULL);
|
||||
|
||||
rocksdb_column_family_handle_destroy(cfh);
|
||||
|
||||
// close and destroy
|
||||
rocksdb_transaction_destroy(txn);
|
||||
rocksdb_transactiondb_close(txn_db);
|
||||
rocksdb_destroy_db(options, dbname, &err);
|
||||
CheckNoError(err);
|
||||
rocksdb_transaction_options_destroy(txn_options);
|
||||
rocksdb_transactiondb_options_destroy(txn_db_options);
|
||||
}
|
||||
|
||||
// Simple sanity check that setting memtable rep works.
|
||||
StartPhase("memtable_reps");
|
||||
{
|
||||
// Create database with vector memtable.
|
||||
rocksdb_close(db);
|
||||
rocksdb_destroy_db(options, dbname, &err);
|
||||
CheckNoError(err);
|
||||
|
||||
rocksdb_options_set_memtable_vector_rep(options);
|
||||
db = rocksdb_open(options, dbname, &err);
|
||||
CheckNoError(err);
|
||||
@@ -1491,18 +1247,6 @@ int main(int argc, char** argv) {
|
||||
CheckNoError(err);
|
||||
}
|
||||
|
||||
// Simple sanity check that options setting db_paths work.
|
||||
StartPhase("open_db_paths");
|
||||
{
|
||||
rocksdb_close(db);
|
||||
rocksdb_destroy_db(options, dbname, &err);
|
||||
|
||||
const rocksdb_dbpath_t* paths[1] = {dbpath};
|
||||
rocksdb_options_set_db_paths(options, paths, 1);
|
||||
db = rocksdb_open(options, dbname, &err);
|
||||
CheckNoError(err);
|
||||
}
|
||||
|
||||
StartPhase("cleanup");
|
||||
rocksdb_close(db);
|
||||
rocksdb_options_destroy(options);
|
||||
@@ -1512,7 +1256,6 @@ int main(int argc, char** argv) {
|
||||
rocksdb_compactoptions_destroy(coptions);
|
||||
rocksdb_cache_destroy(cache);
|
||||
rocksdb_comparator_destroy(cmp);
|
||||
rocksdb_dbpath_destroy(dbpath);
|
||||
rocksdb_env_destroy(env);
|
||||
|
||||
fprintf(stderr, "PASS\n");
|
||||
|
||||
+8
-26
@@ -170,12 +170,6 @@ ColumnFamilyOptions SanitizeOptions(const ImmutableDBOptions& db_options,
|
||||
result.num_levels < 2) {
|
||||
result.num_levels = 2;
|
||||
}
|
||||
|
||||
if (result.compaction_style == kCompactionStyleUniversal &&
|
||||
db_options.allow_ingest_behind && result.num_levels < 3) {
|
||||
result.num_levels = 3;
|
||||
}
|
||||
|
||||
if (result.max_write_buffer_number < 2) {
|
||||
result.max_write_buffer_number = 2;
|
||||
}
|
||||
@@ -202,6 +196,7 @@ ColumnFamilyOptions SanitizeOptions(const ImmutableDBOptions& db_options,
|
||||
result.num_levels = 1;
|
||||
// since we delete level0 files in FIFO compaction when there are too many
|
||||
// of them, these options don't really mean anything
|
||||
result.level0_file_num_compaction_trigger = std::numeric_limits<int>::max();
|
||||
result.level0_slowdown_writes_trigger = std::numeric_limits<int>::max();
|
||||
result.level0_stop_writes_trigger = std::numeric_limits<int>::max();
|
||||
}
|
||||
@@ -347,14 +342,13 @@ ColumnFamilyData::ColumnFamilyData(
|
||||
dummy_versions_(_dummy_versions),
|
||||
current_(nullptr),
|
||||
refs_(0),
|
||||
initialized_(false),
|
||||
dropped_(false),
|
||||
internal_comparator_(cf_options.comparator),
|
||||
initial_cf_options_(SanitizeOptions(db_options, cf_options)),
|
||||
ioptions_(db_options, initial_cf_options_),
|
||||
mutable_cf_options_(initial_cf_options_),
|
||||
is_delete_range_supported_(
|
||||
cf_options.table_factory->IsDeleteRangeSupported()),
|
||||
is_delete_range_supported_(strcmp(cf_options.table_factory->Name(),
|
||||
BlockBasedTableFactory().Name()) == 0),
|
||||
write_buffer_manager_(write_buffer_manager),
|
||||
mem_(nullptr),
|
||||
imm_(ioptions_.min_write_buffer_number_to_merge,
|
||||
@@ -550,7 +544,7 @@ std::unique_ptr<WriteControllerToken> SetupDelay(
|
||||
// If DB just falled into the stop condition, we need to further reduce
|
||||
// the write rate to avoid the stop condition.
|
||||
if (penalize_stop) {
|
||||
// Penalize the near stop or stop condition by more aggressive slowdown.
|
||||
// Penalize the near stop or stop condition by more agressive slowdown.
|
||||
// This is to provide the long term slowdown increase signal.
|
||||
// The penalty is more than the reward of recovering to the normal
|
||||
// condition.
|
||||
@@ -728,7 +722,7 @@ void ColumnFamilyData::RecalculateWriteStallConditions(
|
||||
mutable_cf_options.level0_slowdown_writes_trigger)) {
|
||||
write_controller_token_ =
|
||||
write_controller->GetCompactionPressureToken();
|
||||
ROCKS_LOG_INFO(
|
||||
ROCKS_LOG_WARN(
|
||||
ioptions_.info_log,
|
||||
"[%s] Increasing compaction threads because we have %d level-0 "
|
||||
"files ",
|
||||
@@ -742,7 +736,7 @@ void ColumnFamilyData::RecalculateWriteStallConditions(
|
||||
write_controller_token_ =
|
||||
write_controller->GetCompactionPressureToken();
|
||||
if (mutable_cf_options.soft_pending_compaction_bytes_limit > 0) {
|
||||
ROCKS_LOG_INFO(
|
||||
ROCKS_LOG_WARN(
|
||||
ioptions_.info_log,
|
||||
"[%s] Increasing compaction threads because of estimated pending "
|
||||
"compaction "
|
||||
@@ -759,12 +753,6 @@ void ColumnFamilyData::RecalculateWriteStallConditions(
|
||||
uint64_t write_rate = write_controller->delayed_write_rate();
|
||||
write_controller->set_delayed_write_rate(static_cast<uint64_t>(
|
||||
static_cast<double>(write_rate) * kDelayRecoverSlowdownRatio));
|
||||
// Set the low pri limit to be 1/4 the delayed write rate.
|
||||
// Note we don't reset this value even after delay condition is relased.
|
||||
// Low-pri rate will continue to apply if there is a compaction
|
||||
// pressure.
|
||||
write_controller->low_pri_rate_limiter()->SetBytesPerSecond(write_rate /
|
||||
4);
|
||||
}
|
||||
}
|
||||
prev_compaction_needed_bytes_ = compaction_needed_bytes;
|
||||
@@ -789,8 +777,9 @@ uint64_t ColumnFamilyData::GetTotalSstFilesSize() const {
|
||||
|
||||
MemTable* ColumnFamilyData::ConstructNewMemtable(
|
||||
const MutableCFOptions& mutable_cf_options, SequenceNumber earliest_seq) {
|
||||
assert(current_ != nullptr);
|
||||
return new MemTable(internal_comparator_, ioptions_, mutable_cf_options,
|
||||
write_buffer_manager_, earliest_seq, id_);
|
||||
write_buffer_manager_, earliest_seq);
|
||||
}
|
||||
|
||||
void ColumnFamilyData::CreateNewMemtable(
|
||||
@@ -930,13 +919,6 @@ SuperVersion* ColumnFamilyData::InstallSuperVersion(
|
||||
super_version_ = new_superversion;
|
||||
++super_version_number_;
|
||||
super_version_->version_number = super_version_number_;
|
||||
if (old_superversion != nullptr) {
|
||||
if (old_superversion->mutable_cf_options.write_buffer_size !=
|
||||
mutable_cf_options.write_buffer_size) {
|
||||
mem_->UpdateWriteBufferSize(mutable_cf_options.write_buffer_size);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset SuperVersions cached in thread local storage
|
||||
ResetThreadLocalSuperVersions();
|
||||
|
||||
|
||||
@@ -333,10 +333,6 @@ class ColumnFamilyData {
|
||||
void RecalculateWriteStallConditions(
|
||||
const MutableCFOptions& mutable_cf_options);
|
||||
|
||||
void set_initialized() { initialized_.store(true); }
|
||||
|
||||
bool initialized() const { return initialized_.load(); }
|
||||
|
||||
private:
|
||||
friend class ColumnFamilySet;
|
||||
ColumnFamilyData(uint32_t id, const std::string& name,
|
||||
@@ -353,7 +349,6 @@ class ColumnFamilyData {
|
||||
Version* current_; // == dummy_versions->prev_
|
||||
|
||||
std::atomic<int> refs_; // outstanding references to ColumnFamilyData
|
||||
std::atomic<bool> initialized_;
|
||||
bool dropped_; // true if client dropped it
|
||||
|
||||
const InternalKeyComparator internal_comparator_;
|
||||
|
||||
+30
-59
@@ -54,7 +54,7 @@ class EnvCounter : public EnvWrapper {
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<int> num_new_writable_file_;
|
||||
int num_new_writable_file_;
|
||||
};
|
||||
|
||||
class ColumnFamilyTest : public testing::Test {
|
||||
@@ -302,7 +302,6 @@ class ColumnFamilyTest : public testing::Test {
|
||||
ASSERT_OK(Put(cf, key, RandomString(&rnd_, key_value_size - 10)));
|
||||
}
|
||||
}
|
||||
db_->FlushWAL(false);
|
||||
}
|
||||
|
||||
#ifndef ROCKSDB_LITE // TEST functions in DB are not supported in lite
|
||||
@@ -521,30 +520,6 @@ TEST_F(ColumnFamilyTest, DontReuseColumnFamilyID) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
TEST_F(ColumnFamilyTest, CreateCFRaceWithGetAggProperty) {
|
||||
Open();
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->LoadDependency(
|
||||
{{"DBImpl::WriteOptionsFile:1",
|
||||
"ColumnFamilyTest.CreateCFRaceWithGetAggProperty:1"},
|
||||
{"ColumnFamilyTest.CreateCFRaceWithGetAggProperty:2",
|
||||
"DBImpl::WriteOptionsFile:2"}});
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
rocksdb::port::Thread thread([&] { CreateColumnFamilies({"one"}); });
|
||||
|
||||
TEST_SYNC_POINT("ColumnFamilyTest.CreateCFRaceWithGetAggProperty:1");
|
||||
uint64_t pv;
|
||||
db_->GetAggregatedIntProperty(DB::Properties::kEstimateTableReadersMem, &pv);
|
||||
TEST_SYNC_POINT("ColumnFamilyTest.CreateCFRaceWithGetAggProperty:2");
|
||||
|
||||
thread.join();
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
}
|
||||
#endif // !ROCKSDB_LITE
|
||||
|
||||
class FlushEmptyCFTestWithParam : public ColumnFamilyTest,
|
||||
public testing::WithParamInterface<bool> {
|
||||
public:
|
||||
@@ -582,7 +557,6 @@ TEST_P(FlushEmptyCFTestWithParam, FlushEmptyCFTest) {
|
||||
Flush(0);
|
||||
ASSERT_OK(Put(1, "bar", "v3")); // seqID 4
|
||||
ASSERT_OK(Put(1, "foo", "v4")); // seqID 5
|
||||
db_->FlushWAL(false);
|
||||
|
||||
// Preserve file system state up to here to simulate a crash condition.
|
||||
fault_env->SetFilesystemActive(false);
|
||||
@@ -645,7 +619,6 @@ TEST_P(FlushEmptyCFTestWithParam, FlushEmptyCFTest2) {
|
||||
// Write to log file D
|
||||
ASSERT_OK(Put(1, "bar", "v4")); // seqID 7
|
||||
ASSERT_OK(Put(1, "bar", "v5")); // seqID 8
|
||||
db_->FlushWAL(false);
|
||||
// Preserve file system state up to here to simulate a crash condition.
|
||||
fault_env->SetFilesystemActive(false);
|
||||
std::vector<std::string> names;
|
||||
@@ -1406,6 +1379,7 @@ TEST_F(ColumnFamilyTest, AutomaticAndManualCompactions) {
|
||||
ColumnFamilyOptions default_cf, one, two;
|
||||
db_options_.max_open_files = 20; // only 10 files in file cache
|
||||
db_options_.max_background_compactions = 3;
|
||||
db_options_.base_background_compactions = 3;
|
||||
|
||||
default_cf.compaction_style = kCompactionStyleLevel;
|
||||
default_cf.num_levels = 3;
|
||||
@@ -1429,9 +1403,6 @@ TEST_F(ColumnFamilyTest, AutomaticAndManualCompactions) {
|
||||
two.write_buffer_size = 100000;
|
||||
|
||||
Reopen({default_cf, one, two});
|
||||
// make sure all background compaction jobs can be scheduled
|
||||
auto stop_token =
|
||||
dbfull()->TEST_write_controler().GetCompactionPressureToken();
|
||||
|
||||
bool cf_1_1 = true;
|
||||
rocksdb::SyncPoint::GetInstance()->LoadDependency(
|
||||
@@ -1491,6 +1462,7 @@ TEST_F(ColumnFamilyTest, AutomaticAndManualCompactions) {
|
||||
ASSERT_NE("NOT_FOUND", Get(1, *key_iter));
|
||||
key_iter++;
|
||||
}
|
||||
Close();
|
||||
}
|
||||
|
||||
TEST_F(ColumnFamilyTest, ManualAndAutomaticCompactions) {
|
||||
@@ -1499,6 +1471,7 @@ TEST_F(ColumnFamilyTest, ManualAndAutomaticCompactions) {
|
||||
ColumnFamilyOptions default_cf, one, two;
|
||||
db_options_.max_open_files = 20; // only 10 files in file cache
|
||||
db_options_.max_background_compactions = 3;
|
||||
db_options_.base_background_compactions = 3;
|
||||
|
||||
default_cf.compaction_style = kCompactionStyleLevel;
|
||||
default_cf.num_levels = 3;
|
||||
@@ -1522,9 +1495,6 @@ TEST_F(ColumnFamilyTest, ManualAndAutomaticCompactions) {
|
||||
two.write_buffer_size = 100000;
|
||||
|
||||
Reopen({default_cf, one, two});
|
||||
// make sure all background compaction jobs can be scheduled
|
||||
auto stop_token =
|
||||
dbfull()->TEST_write_controler().GetCompactionPressureToken();
|
||||
|
||||
// SETUP column family "one" -- universal style
|
||||
for (int i = 0; i < one.level0_file_num_compaction_trigger - 2; ++i) {
|
||||
@@ -1587,6 +1557,7 @@ TEST_F(ColumnFamilyTest, ManualAndAutomaticCompactions) {
|
||||
ASSERT_NE("NOT_FOUND", Get(1, *key_iter));
|
||||
key_iter++;
|
||||
}
|
||||
Close();
|
||||
}
|
||||
|
||||
TEST_F(ColumnFamilyTest, SameCFManualManualCompactions) {
|
||||
@@ -1595,6 +1566,7 @@ TEST_F(ColumnFamilyTest, SameCFManualManualCompactions) {
|
||||
ColumnFamilyOptions default_cf, one;
|
||||
db_options_.max_open_files = 20; // only 10 files in file cache
|
||||
db_options_.max_background_compactions = 3;
|
||||
db_options_.base_background_compactions = 3;
|
||||
|
||||
default_cf.compaction_style = kCompactionStyleLevel;
|
||||
default_cf.num_levels = 3;
|
||||
@@ -1613,9 +1585,6 @@ TEST_F(ColumnFamilyTest, SameCFManualManualCompactions) {
|
||||
one.write_buffer_size = 120000;
|
||||
|
||||
Reopen({default_cf, one});
|
||||
// make sure all background compaction jobs can be scheduled
|
||||
auto stop_token =
|
||||
dbfull()->TEST_write_controler().GetCompactionPressureToken();
|
||||
|
||||
// SETUP column family "one" -- universal style
|
||||
for (int i = 0; i < one.level0_file_num_compaction_trigger - 2; ++i) {
|
||||
@@ -1686,6 +1655,7 @@ TEST_F(ColumnFamilyTest, SameCFManualManualCompactions) {
|
||||
ASSERT_NE("NOT_FOUND", Get(1, *key_iter));
|
||||
key_iter++;
|
||||
}
|
||||
Close();
|
||||
}
|
||||
|
||||
TEST_F(ColumnFamilyTest, SameCFManualAutomaticCompactions) {
|
||||
@@ -1694,6 +1664,7 @@ TEST_F(ColumnFamilyTest, SameCFManualAutomaticCompactions) {
|
||||
ColumnFamilyOptions default_cf, one;
|
||||
db_options_.max_open_files = 20; // only 10 files in file cache
|
||||
db_options_.max_background_compactions = 3;
|
||||
db_options_.base_background_compactions = 3;
|
||||
|
||||
default_cf.compaction_style = kCompactionStyleLevel;
|
||||
default_cf.num_levels = 3;
|
||||
@@ -1712,9 +1683,6 @@ TEST_F(ColumnFamilyTest, SameCFManualAutomaticCompactions) {
|
||||
one.write_buffer_size = 120000;
|
||||
|
||||
Reopen({default_cf, one});
|
||||
// make sure all background compaction jobs can be scheduled
|
||||
auto stop_token =
|
||||
dbfull()->TEST_write_controler().GetCompactionPressureToken();
|
||||
|
||||
// SETUP column family "one" -- universal style
|
||||
for (int i = 0; i < one.level0_file_num_compaction_trigger - 2; ++i) {
|
||||
@@ -1776,6 +1744,7 @@ TEST_F(ColumnFamilyTest, SameCFManualAutomaticCompactions) {
|
||||
ASSERT_NE("NOT_FOUND", Get(1, *key_iter));
|
||||
key_iter++;
|
||||
}
|
||||
Close();
|
||||
}
|
||||
|
||||
TEST_F(ColumnFamilyTest, SameCFManualAutomaticCompactionsLevel) {
|
||||
@@ -1784,6 +1753,7 @@ TEST_F(ColumnFamilyTest, SameCFManualAutomaticCompactionsLevel) {
|
||||
ColumnFamilyOptions default_cf, one;
|
||||
db_options_.max_open_files = 20; // only 10 files in file cache
|
||||
db_options_.max_background_compactions = 3;
|
||||
db_options_.base_background_compactions = 3;
|
||||
|
||||
default_cf.compaction_style = kCompactionStyleLevel;
|
||||
default_cf.num_levels = 3;
|
||||
@@ -1802,9 +1772,6 @@ TEST_F(ColumnFamilyTest, SameCFManualAutomaticCompactionsLevel) {
|
||||
one.write_buffer_size = 120000;
|
||||
|
||||
Reopen({default_cf, one});
|
||||
// make sure all background compaction jobs can be scheduled
|
||||
auto stop_token =
|
||||
dbfull()->TEST_write_controler().GetCompactionPressureToken();
|
||||
|
||||
// SETUP column family "one" -- level style
|
||||
for (int i = 0; i < one.level0_file_num_compaction_trigger - 2; ++i) {
|
||||
@@ -1866,6 +1833,7 @@ TEST_F(ColumnFamilyTest, SameCFManualAutomaticCompactionsLevel) {
|
||||
ASSERT_NE("NOT_FOUND", Get(1, *key_iter));
|
||||
key_iter++;
|
||||
}
|
||||
Close();
|
||||
}
|
||||
|
||||
// This test checks for automatic getting a conflict if there is a
|
||||
@@ -1881,6 +1849,7 @@ TEST_F(ColumnFamilyTest, SameCFManualAutomaticConflict) {
|
||||
ColumnFamilyOptions default_cf, one;
|
||||
db_options_.max_open_files = 20; // only 10 files in file cache
|
||||
db_options_.max_background_compactions = 3;
|
||||
db_options_.base_background_compactions = 3;
|
||||
|
||||
default_cf.compaction_style = kCompactionStyleLevel;
|
||||
default_cf.num_levels = 3;
|
||||
@@ -1899,9 +1868,6 @@ TEST_F(ColumnFamilyTest, SameCFManualAutomaticConflict) {
|
||||
one.write_buffer_size = 120000;
|
||||
|
||||
Reopen({default_cf, one});
|
||||
// make sure all background compaction jobs can be scheduled
|
||||
auto stop_token =
|
||||
dbfull()->TEST_write_controler().GetCompactionPressureToken();
|
||||
|
||||
// SETUP column family "one" -- universal style
|
||||
for (int i = 0; i < one.level0_file_num_compaction_trigger - 2; ++i) {
|
||||
@@ -1986,6 +1952,8 @@ TEST_F(ColumnFamilyTest, SameCFManualAutomaticConflict) {
|
||||
ASSERT_NE("NOT_FOUND", Get(1, *key_iter));
|
||||
key_iter++;
|
||||
}
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
// In this test, we generate enough files to trigger automatic compactions.
|
||||
@@ -2000,6 +1968,7 @@ TEST_F(ColumnFamilyTest, SameCFAutomaticManualCompactions) {
|
||||
ColumnFamilyOptions default_cf, one;
|
||||
db_options_.max_open_files = 20; // only 10 files in file cache
|
||||
db_options_.max_background_compactions = 3;
|
||||
db_options_.base_background_compactions = 3;
|
||||
|
||||
default_cf.compaction_style = kCompactionStyleLevel;
|
||||
default_cf.num_levels = 3;
|
||||
@@ -2018,9 +1987,6 @@ TEST_F(ColumnFamilyTest, SameCFAutomaticManualCompactions) {
|
||||
one.write_buffer_size = 120000;
|
||||
|
||||
Reopen({default_cf, one});
|
||||
// make sure all background compaction jobs can be scheduled
|
||||
auto stop_token =
|
||||
dbfull()->TEST_write_controler().GetCompactionPressureToken();
|
||||
|
||||
bool cf_1_1 = true;
|
||||
bool cf_1_2 = true;
|
||||
@@ -2075,6 +2041,8 @@ TEST_F(ColumnFamilyTest, SameCFAutomaticManualCompactions) {
|
||||
ASSERT_NE("NOT_FOUND", Get(1, *key_iter));
|
||||
key_iter++;
|
||||
}
|
||||
|
||||
Close();
|
||||
}
|
||||
#endif // !ROCKSDB_LITE
|
||||
|
||||
@@ -2527,6 +2495,7 @@ TEST_F(ColumnFamilyTest, CreateAndDropRace) {
|
||||
TEST_F(ColumnFamilyTest, WriteStallSingleColumnFamily) {
|
||||
const uint64_t kBaseRate = 800000u;
|
||||
db_options_.delayed_write_rate = kBaseRate;
|
||||
db_options_.base_background_compactions = 2;
|
||||
db_options_.max_background_compactions = 6;
|
||||
|
||||
Open({"default"});
|
||||
@@ -2707,6 +2676,7 @@ TEST_F(ColumnFamilyTest, WriteStallSingleColumnFamily) {
|
||||
}
|
||||
|
||||
TEST_F(ColumnFamilyTest, CompactionSpeedupSingleColumnFamily) {
|
||||
db_options_.base_background_compactions = 2;
|
||||
db_options_.max_background_compactions = 6;
|
||||
Open({"default"});
|
||||
ColumnFamilyData* cfd =
|
||||
@@ -2726,7 +2696,7 @@ TEST_F(ColumnFamilyTest, CompactionSpeedupSingleColumnFamily) {
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(40);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(50);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
@@ -2738,11 +2708,11 @@ TEST_F(ColumnFamilyTest, CompactionSpeedupSingleColumnFamily) {
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(45);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(7);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(9);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
@@ -2750,7 +2720,7 @@ TEST_F(ColumnFamilyTest, CompactionSpeedupSingleColumnFamily) {
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(6);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
// Speed up threshold = min(4 * 2, 4 + (12 - 4)/4) = 6
|
||||
mutable_cf_options.level0_file_num_compaction_trigger = 4;
|
||||
@@ -2759,7 +2729,7 @@ TEST_F(ColumnFamilyTest, CompactionSpeedupSingleColumnFamily) {
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(5);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(7);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
@@ -2767,7 +2737,7 @@ TEST_F(ColumnFamilyTest, CompactionSpeedupSingleColumnFamily) {
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(3);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
|
||||
}
|
||||
|
||||
TEST_F(ColumnFamilyTest, WriteStallTwoColumnFamilies) {
|
||||
@@ -2846,6 +2816,7 @@ TEST_F(ColumnFamilyTest, WriteStallTwoColumnFamilies) {
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -2873,11 +2844,11 @@ TEST_F(ColumnFamilyTest, CompactionSpeedupTwoColumnFamilies) {
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(40);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage->TEST_set_estimated_compaction_needed_bytes(60);
|
||||
cfd1->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(6, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
@@ -2895,7 +2866,7 @@ TEST_F(ColumnFamilyTest, CompactionSpeedupTwoColumnFamilies) {
|
||||
|
||||
vstorage1->TEST_set_estimated_compaction_needed_bytes(3);
|
||||
cfd1->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(9);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
@@ -2907,7 +2878,7 @@ TEST_F(ColumnFamilyTest, CompactionSpeedupTwoColumnFamilies) {
|
||||
|
||||
vstorage->set_l0_delay_trigger_count(0);
|
||||
cfd->RecalculateWriteStallConditions(mutable_cf_options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
|
||||
}
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
|
||||
+24
-38
@@ -169,7 +169,6 @@ Compaction::Compaction(VersionStorageInfo* vstorage,
|
||||
bottommost_level_(IsBottommostLevel(output_level_, vstorage, inputs_)),
|
||||
is_full_compaction_(IsFullCompaction(vstorage, inputs_)),
|
||||
is_manual_compaction_(_manual_compaction),
|
||||
is_trivial_move_(false),
|
||||
compaction_reason_(_compaction_reason) {
|
||||
MarkFilesBeingCompacted(true);
|
||||
if (is_manual_compaction_) {
|
||||
@@ -284,32 +283,32 @@ bool Compaction::KeyNotExistsBeyondOutputLevel(
|
||||
assert(input_version_ != nullptr);
|
||||
assert(level_ptrs != nullptr);
|
||||
assert(level_ptrs->size() == static_cast<size_t>(number_levels_));
|
||||
if (cfd_->ioptions()->compaction_style == kCompactionStyleLevel) {
|
||||
if (output_level_ == 0) {
|
||||
return false;
|
||||
}
|
||||
// Maybe use binary search to find right entry instead of linear search?
|
||||
const Comparator* user_cmp = cfd_->user_comparator();
|
||||
for (int lvl = output_level_ + 1; lvl < number_levels_; lvl++) {
|
||||
const std::vector<FileMetaData*>& files =
|
||||
input_vstorage_->LevelFiles(lvl);
|
||||
for (; level_ptrs->at(lvl) < files.size(); level_ptrs->at(lvl)++) {
|
||||
auto* f = files[level_ptrs->at(lvl)];
|
||||
if (user_cmp->Compare(user_key, f->largest.user_key()) <= 0) {
|
||||
// We've advanced far enough
|
||||
if (user_cmp->Compare(user_key, f->smallest.user_key()) >= 0) {
|
||||
// Key falls in this file's range, so definitely
|
||||
// exists beyond output level
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
assert(cfd_->ioptions()->compaction_style != kCompactionStyleFIFO);
|
||||
if (cfd_->ioptions()->compaction_style == kCompactionStyleUniversal) {
|
||||
return bottommost_level_;
|
||||
}
|
||||
if (cfd_->ioptions()->compaction_style == kCompactionStyleLevel &&
|
||||
output_level_ == 0) {
|
||||
return false;
|
||||
}
|
||||
// Maybe use binary search to find right entry instead of linear search?
|
||||
const Comparator* user_cmp = cfd_->user_comparator();
|
||||
for (int lvl = output_level_ + 1; lvl < number_levels_; lvl++) {
|
||||
const std::vector<FileMetaData*>& files = input_vstorage_->LevelFiles(lvl);
|
||||
for (; level_ptrs->at(lvl) < files.size(); level_ptrs->at(lvl)++) {
|
||||
auto* f = files[level_ptrs->at(lvl)];
|
||||
if (user_cmp->Compare(user_key, f->largest.user_key()) <= 0) {
|
||||
// We've advanced far enough
|
||||
if (user_cmp->Compare(user_key, f->smallest.user_key()) >= 0) {
|
||||
// Key falls in this file's range, so definitely
|
||||
// exists beyond output level
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Mark (or clear) each file that is being compacted
|
||||
@@ -464,17 +463,4 @@ bool Compaction::ShouldFormSubcompactions() const {
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t Compaction::MaxInputFileCreationTime() const {
|
||||
uint64_t max_creation_time = 0;
|
||||
for (const auto& file : inputs_[0].files) {
|
||||
if (file->fd.table_reader != nullptr &&
|
||||
file->fd.table_reader->GetTableProperties() != nullptr) {
|
||||
uint64_t creation_time =
|
||||
file->fd.table_reader->GetTableProperties()->creation_time;
|
||||
max_creation_time = std::max(max_creation_time, creation_time);
|
||||
}
|
||||
}
|
||||
return max_creation_time;
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
+1
-4
@@ -99,8 +99,7 @@ class Compaction {
|
||||
// input level.
|
||||
// REQUIREMENT: "compaction_input_level" must be >= 0 and
|
||||
// < "input_levels()"
|
||||
const std::vector<FileMetaData*>* inputs(
|
||||
size_t compaction_input_level) const {
|
||||
const std::vector<FileMetaData*>* inputs(size_t compaction_input_level) {
|
||||
assert(compaction_input_level < inputs_.size());
|
||||
return &inputs_[compaction_input_level].files;
|
||||
}
|
||||
@@ -241,8 +240,6 @@ class Compaction {
|
||||
|
||||
uint64_t max_compaction_bytes() const { return max_compaction_bytes_; }
|
||||
|
||||
uint64_t MaxInputFileCreationTime() const;
|
||||
|
||||
private:
|
||||
// mark (or clear) all files that are being compacted
|
||||
void MarkFilesBeingCompacted(bool mark_as_compacted);
|
||||
|
||||
@@ -16,8 +16,6 @@ struct CompactionIterationStats {
|
||||
int64_t num_record_drop_obsolete = 0;
|
||||
int64_t num_record_drop_range_del = 0;
|
||||
int64_t num_range_del_drop_obsolete = 0;
|
||||
// Deletions obsoleted before bottom level due to file gap optimization.
|
||||
int64_t num_optimized_del_drop_obsolete = 0;
|
||||
uint64_t total_filter_time = 0;
|
||||
|
||||
// Input statistics
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
|
||||
#include "db/compaction_iterator.h"
|
||||
#include "rocksdb/listener.h"
|
||||
#include "table/internal_iterator.h"
|
||||
|
||||
namespace rocksdb {
|
||||
@@ -25,8 +24,6 @@ CompactionEventListener::CompactionListenerValueType fromInternalValueType(
|
||||
kSingleDelete;
|
||||
case kTypeRangeDeletion:
|
||||
return CompactionEventListener::CompactionListenerValueType::kRangeDelete;
|
||||
case kTypeBlobIndex:
|
||||
return CompactionEventListener::CompactionListenerValueType::kBlobIndex;
|
||||
default:
|
||||
assert(false);
|
||||
return CompactionEventListener::CompactionListenerValueType::kInvalid;
|
||||
@@ -69,9 +66,7 @@ CompactionIterator::CompactionIterator(
|
||||
range_del_agg_(range_del_agg),
|
||||
compaction_(std::move(compaction)),
|
||||
compaction_filter_(compaction_filter),
|
||||
#ifndef ROCKSDB_LITE
|
||||
compaction_listener_(compaction_listener),
|
||||
#endif // ROCKSDB_LITE
|
||||
shutting_down_(shutting_down),
|
||||
ignore_snapshots_(false),
|
||||
merge_out_iter_(merge_helper_) {
|
||||
@@ -85,7 +80,7 @@ CompactionIterator::CompactionIterator(
|
||||
if (snapshots_->size() == 0) {
|
||||
// optimize for fast path if there are no snapshots
|
||||
visible_at_tip_ = true;
|
||||
earliest_snapshot_ = kMaxSequenceNumber;
|
||||
earliest_snapshot_ = last_sequence;
|
||||
latest_snapshot_ = 0;
|
||||
} else {
|
||||
visible_at_tip_ = false;
|
||||
@@ -113,7 +108,6 @@ void CompactionIterator::ResetRecordCounts() {
|
||||
iter_stats_.num_record_drop_obsolete = 0;
|
||||
iter_stats_.num_record_drop_range_del = 0;
|
||||
iter_stats_.num_range_del_drop_obsolete = 0;
|
||||
iter_stats_.num_optimized_del_drop_obsolete = 0;
|
||||
}
|
||||
|
||||
void CompactionIterator::SeekToFirst() {
|
||||
@@ -230,8 +224,7 @@ void CompactionIterator::NextFromInput() {
|
||||
#endif // ROCKSDB_LITE
|
||||
|
||||
// apply the compaction filter to the first occurrence of the user key
|
||||
if (compaction_filter_ != nullptr &&
|
||||
(ikey_.type == kTypeValue || ikey_.type == kTypeBlobIndex) &&
|
||||
if (compaction_filter_ != nullptr && ikey_.type == kTypeValue &&
|
||||
(visible_at_tip_ || ikey_.sequence > latest_snapshot_ ||
|
||||
ignore_snapshots_)) {
|
||||
// If the user has specified a compaction filter and the sequence
|
||||
@@ -241,13 +234,11 @@ void CompactionIterator::NextFromInput() {
|
||||
CompactionFilter::Decision filter;
|
||||
compaction_filter_value_.clear();
|
||||
compaction_filter_skip_until_.Clear();
|
||||
CompactionFilter::ValueType value_type =
|
||||
ikey_.type == kTypeValue ? CompactionFilter::ValueType::kValue
|
||||
: CompactionFilter::ValueType::kBlobIndex;
|
||||
{
|
||||
StopWatchNano timer(env_, true);
|
||||
filter = compaction_filter_->FilterV2(
|
||||
compaction_->level(), ikey_.user_key, value_type, value_,
|
||||
compaction_->level(), ikey_.user_key,
|
||||
CompactionFilter::ValueType::kValue, value_,
|
||||
&compaction_filter_value_, compaction_filter_skip_until_.rep());
|
||||
iter_stats_.total_filter_time +=
|
||||
env_ != nullptr ? timer.ElapsedNanos() : 0;
|
||||
@@ -432,9 +423,6 @@ void CompactionIterator::NextFromInput() {
|
||||
// Can compact out this SingleDelete.
|
||||
++iter_stats_.num_record_drop_obsolete;
|
||||
++iter_stats_.num_single_del_fallthru;
|
||||
if (!bottommost_level_) {
|
||||
++iter_stats_.num_optimized_del_drop_obsolete;
|
||||
}
|
||||
} else {
|
||||
// Output SingleDelete
|
||||
valid_ = true;
|
||||
@@ -476,9 +464,6 @@ void CompactionIterator::NextFromInput() {
|
||||
// Note: Dropping this Delete will not affect TransactionDB
|
||||
// write-conflict checking since it is earlier than any snapshot.
|
||||
++iter_stats_.num_record_drop_obsolete;
|
||||
if (!bottommost_level_) {
|
||||
++iter_stats_.num_optimized_del_drop_obsolete;
|
||||
}
|
||||
input_->Next();
|
||||
} else if (ikey_.type == kTypeMerge) {
|
||||
if (!merge_helper_->HasOperator()) {
|
||||
@@ -558,8 +543,7 @@ void CompactionIterator::PrepareOutput() {
|
||||
|
||||
// This is safe for TransactionDB write-conflict checking since transactions
|
||||
// only care about sequence number larger than any active snapshots.
|
||||
if ((compaction_ != nullptr && !compaction_->allow_ingest_behind()) &&
|
||||
bottommost_level_ && valid_ && ikey_.sequence <= earliest_snapshot_ &&
|
||||
if (bottommost_level_ && valid_ && ikey_.sequence < earliest_snapshot_ &&
|
||||
ikey_.type != kTypeMerge &&
|
||||
!cmp_->Equal(compaction_->GetLargestUserKey(), ikey_.user_key)) {
|
||||
assert(ikey_.type != kTypeDeletion && ikey_.type != kTypeSingleDeletion);
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "db/merge_helper.h"
|
||||
#include "db/pinned_iterators_manager.h"
|
||||
#include "db/range_del_aggregator.h"
|
||||
#include "options/cf_options.h"
|
||||
#include "rocksdb/compaction_filter.h"
|
||||
|
||||
namespace rocksdb {
|
||||
@@ -45,9 +44,6 @@ class CompactionIterator {
|
||||
virtual Slice GetLargestUserKey() const {
|
||||
return compaction_->GetLargestUserKey();
|
||||
}
|
||||
virtual bool allow_ingest_behind() const {
|
||||
return compaction_->immutable_cf_options()->allow_ingest_behind;
|
||||
}
|
||||
|
||||
protected:
|
||||
CompactionProxy() = default;
|
||||
@@ -130,9 +126,7 @@ class CompactionIterator {
|
||||
RangeDelAggregator* range_del_agg_;
|
||||
std::unique_ptr<CompactionProxy> compaction_;
|
||||
const CompactionFilter* compaction_filter_;
|
||||
#ifndef ROCKSDB_LITE
|
||||
CompactionEventListener* compaction_listener_;
|
||||
#endif // ROCKSDB_LITE
|
||||
const std::atomic<bool>* shutting_down_;
|
||||
bool bottommost_level_;
|
||||
bool valid_ = false;
|
||||
|
||||
@@ -154,7 +154,6 @@ class FakeCompaction : public CompactionIterator::CompactionProxy {
|
||||
virtual Slice GetLargestUserKey() const {
|
||||
return "\xff\xff\xff\xff\xff\xff\xff\xff\xff";
|
||||
}
|
||||
virtual bool allow_ingest_behind() const { return false; }
|
||||
|
||||
bool key_not_exists_beyond_output_level = false;
|
||||
};
|
||||
@@ -455,111 +454,6 @@ TEST_F(CompactionIteratorTest, ShuttingDownInMerge) {
|
||||
EXPECT_EQ(2, filter.last_seen.load());
|
||||
}
|
||||
|
||||
TEST_F(CompactionIteratorTest, SingleMergeOperand) {
|
||||
class Filter : public CompactionFilter {
|
||||
virtual Decision FilterV2(int level, const Slice& key, ValueType t,
|
||||
const Slice& existing_value,
|
||||
std::string* new_value,
|
||||
std::string* skip_until) const override {
|
||||
std::string k = key.ToString();
|
||||
std::string v = existing_value.ToString();
|
||||
|
||||
// See InitIterators() call below for the sequence of keys and their
|
||||
// filtering decisions. Here we closely assert that compaction filter is
|
||||
// called with the expected keys and only them, and with the right values.
|
||||
if (k == "a") {
|
||||
EXPECT_EQ(ValueType::kMergeOperand, t);
|
||||
EXPECT_EQ("av1", v);
|
||||
return Decision::kKeep;
|
||||
} else if (k == "b") {
|
||||
EXPECT_EQ(ValueType::kMergeOperand, t);
|
||||
return Decision::kKeep;
|
||||
} else if (k == "c") {
|
||||
return Decision::kKeep;
|
||||
}
|
||||
|
||||
ADD_FAILURE();
|
||||
return Decision::kKeep;
|
||||
}
|
||||
|
||||
const char* Name() const override {
|
||||
return "CompactionIteratorTest.SingleMergeOperand::Filter";
|
||||
}
|
||||
};
|
||||
|
||||
class SingleMergeOp : public MergeOperator {
|
||||
public:
|
||||
bool FullMergeV2(const MergeOperationInput& merge_in,
|
||||
MergeOperationOutput* merge_out) const override {
|
||||
// See InitIterators() call below for why "c" is the only key for which
|
||||
// FullMergeV2 should be called.
|
||||
EXPECT_EQ("c", merge_in.key.ToString());
|
||||
|
||||
std::string temp_value;
|
||||
if (merge_in.existing_value != nullptr) {
|
||||
temp_value = merge_in.existing_value->ToString();
|
||||
}
|
||||
|
||||
for (auto& operand : merge_in.operand_list) {
|
||||
temp_value.append(operand.ToString());
|
||||
}
|
||||
merge_out->new_value = temp_value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PartialMergeMulti(const Slice& key,
|
||||
const std::deque<Slice>& operand_list,
|
||||
std::string* new_value,
|
||||
Logger* logger) const override {
|
||||
std::string string_key = key.ToString();
|
||||
EXPECT_TRUE(string_key == "a" || string_key == "b");
|
||||
|
||||
if (string_key == "a") {
|
||||
EXPECT_EQ(1, operand_list.size());
|
||||
} else if (string_key == "b") {
|
||||
EXPECT_EQ(2, operand_list.size());
|
||||
}
|
||||
|
||||
std::string temp_value;
|
||||
for (auto& operand : operand_list) {
|
||||
temp_value.append(operand.ToString());
|
||||
}
|
||||
swap(temp_value, *new_value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* Name() const override {
|
||||
return "CompactionIteratorTest SingleMergeOp";
|
||||
}
|
||||
|
||||
bool AllowSingleOperand() const override { return true; }
|
||||
};
|
||||
|
||||
SingleMergeOp merge_op;
|
||||
Filter filter;
|
||||
InitIterators(
|
||||
// a should invoke PartialMergeMulti with a single merge operand.
|
||||
{test::KeyStr("a", 50, kTypeMerge),
|
||||
// b should invoke PartialMergeMulti with two operands.
|
||||
test::KeyStr("b", 70, kTypeMerge), test::KeyStr("b", 60, kTypeMerge),
|
||||
// c should invoke FullMerge due to kTypeValue at the beginning.
|
||||
test::KeyStr("c", 90, kTypeMerge), test::KeyStr("c", 80, kTypeValue)},
|
||||
{"av1", "bv2", "bv1", "cv2", "cv1"}, {}, {}, kMaxSequenceNumber,
|
||||
&merge_op, &filter);
|
||||
|
||||
c_iter_->SeekToFirst();
|
||||
ASSERT_TRUE(c_iter_->Valid());
|
||||
ASSERT_EQ(test::KeyStr("a", 50, kTypeMerge), c_iter_->key().ToString());
|
||||
ASSERT_EQ("av1", c_iter_->value().ToString());
|
||||
c_iter_->Next();
|
||||
ASSERT_TRUE(c_iter_->Valid());
|
||||
ASSERT_EQ("bv1bv2", c_iter_->value().ToString());
|
||||
c_iter_->Next();
|
||||
ASSERT_EQ("cv1cv2", c_iter_->value().ToString());
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
+13
-59
@@ -594,9 +594,6 @@ Status CompactionJob::Install(const MutableCFOptions& mutable_cf_options) {
|
||||
|
||||
double read_write_amp = 0.0;
|
||||
double write_amp = 0.0;
|
||||
double bytes_read_per_sec = 0;
|
||||
double bytes_written_per_sec = 0;
|
||||
|
||||
if (stats.bytes_read_non_output_levels > 0) {
|
||||
read_write_amp = (stats.bytes_written + stats.bytes_read_output_level +
|
||||
stats.bytes_read_non_output_levels) /
|
||||
@@ -604,22 +601,17 @@ Status CompactionJob::Install(const MutableCFOptions& mutable_cf_options) {
|
||||
write_amp = stats.bytes_written /
|
||||
static_cast<double>(stats.bytes_read_non_output_levels);
|
||||
}
|
||||
if (stats.micros > 0) {
|
||||
bytes_read_per_sec =
|
||||
(stats.bytes_read_non_output_levels + stats.bytes_read_output_level) /
|
||||
static_cast<double>(stats.micros);
|
||||
bytes_written_per_sec =
|
||||
stats.bytes_written / static_cast<double>(stats.micros);
|
||||
}
|
||||
|
||||
ROCKS_LOG_BUFFER(
|
||||
log_buffer_,
|
||||
"[%s] compacted to: %s, MB/sec: %.1f rd, %.1f wr, level %d, "
|
||||
"files in(%d, %d) out(%d) "
|
||||
"MB in(%.1f, %.1f) out(%.1f), read-write-amplify(%.1f) "
|
||||
"write-amplify(%.1f) %s, records in: %d, records dropped: %d\n",
|
||||
cfd->GetName().c_str(), vstorage->LevelSummary(&tmp), bytes_read_per_sec,
|
||||
bytes_written_per_sec, compact_->compaction->output_level(),
|
||||
cfd->GetName().c_str(), vstorage->LevelSummary(&tmp),
|
||||
(stats.bytes_read_non_output_levels + stats.bytes_read_output_level) /
|
||||
static_cast<double>(stats.micros),
|
||||
stats.bytes_written / static_cast<double>(stats.micros),
|
||||
compact_->compaction->output_level(),
|
||||
stats.num_input_files_in_non_output_levels,
|
||||
stats.num_input_files_in_output_level, stats.num_output_files,
|
||||
stats.bytes_read_non_output_levels / 1048576.0,
|
||||
@@ -1014,10 +1006,6 @@ void CompactionJob::RecordDroppedKeys(
|
||||
RecordTick(stats_, COMPACTION_RANGE_DEL_DROP_OBSOLETE,
|
||||
c_iter_stats.num_range_del_drop_obsolete);
|
||||
}
|
||||
if (c_iter_stats.num_optimized_del_drop_obsolete > 0) {
|
||||
RecordTick(stats_, COMPACTION_OPTIMIZED_DEL_DROP_OBSOLETE,
|
||||
c_iter_stats.num_optimized_del_drop_obsolete);
|
||||
}
|
||||
}
|
||||
|
||||
Status CompactionJob::FinishCompactionOutputFile(
|
||||
@@ -1035,6 +1023,7 @@ Status CompactionJob::FinishCompactionOutputFile(
|
||||
uint64_t output_number = sub_compact->current_output()->meta.fd.GetNumber();
|
||||
assert(output_number != 0);
|
||||
|
||||
TableProperties table_properties;
|
||||
// Check for iterator errors
|
||||
Status s = input_status;
|
||||
auto meta = &sub_compact->current_output()->meta;
|
||||
@@ -1090,23 +1079,6 @@ Status CompactionJob::FinishCompactionOutputFile(
|
||||
}
|
||||
sub_compact->outfile.reset();
|
||||
|
||||
if (s.ok() && current_entries == 0) {
|
||||
// If there is nothing to output, no necessary to generate a sst file.
|
||||
// This happens when the output level is bottom level, at the same time
|
||||
// the sub_compact output nothing.
|
||||
std::string fname = TableFileName(
|
||||
db_options_.db_paths, meta->fd.GetNumber(), meta->fd.GetPathId());
|
||||
env_->DeleteFile(fname);
|
||||
|
||||
// Also need to remove the file from outputs, or it will be added to the
|
||||
// VersionEdit.
|
||||
assert(!sub_compact->outputs.empty());
|
||||
sub_compact->outputs.pop_back();
|
||||
sub_compact->builder.reset();
|
||||
sub_compact->current_output_file_size = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
ColumnFamilyData* cfd = sub_compact->compaction->column_family_data();
|
||||
TableProperties tp;
|
||||
if (s.ok() && current_entries > 0) {
|
||||
@@ -1159,22 +1131,12 @@ Status CompactionJob::FinishCompactionOutputFile(
|
||||
meta->fd.GetPathId());
|
||||
sfm->OnAddFile(fn);
|
||||
if (sfm->IsMaxAllowedSpaceReached()) {
|
||||
// TODO(ajkr): should we return OK() if max space was reached by the final
|
||||
// compaction output file (similarly to how flush works when full)?
|
||||
s = Status::IOError("Max allowed space was reached");
|
||||
TEST_SYNC_POINT(
|
||||
"CompactionJob::FinishCompactionOutputFile:"
|
||||
"MaxAllowedSpaceReached");
|
||||
InstrumentedMutexLock l(db_mutex_);
|
||||
if (db_bg_error_->ok()) {
|
||||
Status new_bg_error = s;
|
||||
// may temporarily unlock and lock the mutex.
|
||||
EventHelpers::NotifyOnBackgroundError(
|
||||
cfd->ioptions()->listeners, BackgroundErrorReason::kCompaction,
|
||||
&new_bg_error, db_mutex_);
|
||||
if (!new_bg_error.ok()) {
|
||||
*db_bg_error_ = new_bg_error;
|
||||
}
|
||||
s = Status::IOError("Max allowed space was reached");
|
||||
*db_bg_error_ = s;
|
||||
TEST_SYNC_POINT(
|
||||
"CompactionJob::FinishCompactionOutputFile:MaxAllowedSpaceReached");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1289,22 +1251,14 @@ Status CompactionJob::OpenCompactionOutputFile(
|
||||
// data is going to be found
|
||||
bool skip_filters =
|
||||
cfd->ioptions()->optimize_filters_for_hits && bottommost_level_;
|
||||
|
||||
uint64_t output_file_creation_time =
|
||||
sub_compact->compaction->MaxInputFileCreationTime();
|
||||
if (output_file_creation_time == 0) {
|
||||
int64_t _current_time = 0;
|
||||
db_options_.env->GetCurrentTime(&_current_time); // ignore error
|
||||
output_file_creation_time = static_cast<uint64_t>(_current_time);
|
||||
}
|
||||
|
||||
sub_compact->builder.reset(NewTableBuilder(
|
||||
*cfd->ioptions(), cfd->internal_comparator(),
|
||||
cfd->int_tbl_prop_collector_factories(), cfd->GetID(), cfd->GetName(),
|
||||
sub_compact->outfile.get(), sub_compact->compaction->output_compression(),
|
||||
cfd->ioptions()->compression_opts,
|
||||
sub_compact->compaction->output_level(), &sub_compact->compression_dict,
|
||||
skip_filters, output_file_creation_time));
|
||||
sub_compact->compaction->output_level(),
|
||||
&sub_compact->compression_dict,
|
||||
skip_filters));
|
||||
LogFlush(db_options_.info_log);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -654,6 +654,7 @@ TEST_P(CompactionJobStatsTest, CompactionJobStatsTest) {
|
||||
Options options;
|
||||
options.listeners.emplace_back(stats_checker);
|
||||
options.create_if_missing = true;
|
||||
options.max_background_flushes = 0;
|
||||
// just enough setting to hold off auto-compaction.
|
||||
options.level0_file_num_compaction_trigger = kTestScale + 1;
|
||||
options.num_levels = 3;
|
||||
@@ -875,6 +876,7 @@ TEST_P(CompactionJobStatsTest, DeletionStatsTest) {
|
||||
Options options;
|
||||
options.listeners.emplace_back(stats_checker);
|
||||
options.create_if_missing = true;
|
||||
options.max_background_flushes = 0;
|
||||
options.level0_file_num_compaction_trigger = kTestScale+1;
|
||||
options.num_levels = 3;
|
||||
options.compression = kNoCompression;
|
||||
|
||||
@@ -142,7 +142,6 @@ class CompactionJobTest : public testing::Test {
|
||||
}
|
||||
|
||||
void SetLastSequence(const SequenceNumber sequence_number) {
|
||||
versions_->SetLastToBeWrittenSequence(sequence_number + 1);
|
||||
versions_->SetLastSequence(sequence_number + 1);
|
||||
}
|
||||
|
||||
@@ -338,24 +337,6 @@ TEST_F(CompactionJobTest, SimpleDeletion) {
|
||||
RunCompaction({files}, expected_results);
|
||||
}
|
||||
|
||||
TEST_F(CompactionJobTest, OutputNothing) {
|
||||
NewDB();
|
||||
|
||||
auto file1 = mock::MakeMockFile({{KeyStr("a", 1U, kTypeValue), "val"}});
|
||||
|
||||
AddMockFile(file1);
|
||||
|
||||
auto file2 = mock::MakeMockFile({{KeyStr("a", 2U, kTypeDeletion), ""}});
|
||||
|
||||
AddMockFile(file2);
|
||||
|
||||
auto expected_results = mock::MakeMockFile();
|
||||
|
||||
SetLastSequence(4U);
|
||||
auto files = cfd_->current()->storage_info()->LevelFiles(0);
|
||||
RunCompaction({files}, expected_results);
|
||||
}
|
||||
|
||||
TEST_F(CompactionJobTest, SimpleOverwrite) {
|
||||
NewDB();
|
||||
|
||||
|
||||
+65
-194
@@ -36,39 +36,6 @@ uint64_t TotalCompensatedFileSize(const std::vector<FileMetaData*>& files) {
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
bool FindIntraL0Compaction(const std::vector<FileMetaData*>& level_files,
|
||||
size_t min_files_to_compact,
|
||||
uint64_t max_compact_bytes_per_del_file,
|
||||
CompactionInputFiles* comp_inputs) {
|
||||
size_t compact_bytes = level_files[0]->fd.file_size;
|
||||
size_t compact_bytes_per_del_file = port::kMaxSizet;
|
||||
// compaction range will be [0, span_len).
|
||||
size_t span_len;
|
||||
// pull in files until the amount of compaction work per deleted file begins
|
||||
// increasing.
|
||||
size_t new_compact_bytes_per_del_file = 0;
|
||||
for (span_len = 1; span_len < level_files.size(); ++span_len) {
|
||||
compact_bytes += level_files[span_len]->fd.file_size;
|
||||
new_compact_bytes_per_del_file = compact_bytes / span_len;
|
||||
if (level_files[span_len]->being_compacted ||
|
||||
new_compact_bytes_per_del_file > compact_bytes_per_del_file) {
|
||||
break;
|
||||
}
|
||||
compact_bytes_per_del_file = new_compact_bytes_per_del_file;
|
||||
}
|
||||
|
||||
if (span_len >= min_files_to_compact &&
|
||||
new_compact_bytes_per_del_file < max_compact_bytes_per_del_file) {
|
||||
assert(comp_inputs != nullptr);
|
||||
comp_inputs->level = 0;
|
||||
for (size_t i = 0; i < span_len; ++i) {
|
||||
comp_inputs->files.push_back(level_files[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
// Determine compression type, based on user options, level of the output
|
||||
@@ -234,6 +201,11 @@ bool CompactionPicker::ExpandInputsToCleanCut(const std::string& cf_name,
|
||||
// If, after the expansion, there are files that are already under
|
||||
// compaction, then we must drop/cancel this compaction.
|
||||
if (AreFilesInCompaction(inputs->files)) {
|
||||
ROCKS_LOG_WARN(
|
||||
ioptions_.info_log,
|
||||
"[%s] ExpandWhileOverlapping() failure because some of the necessary"
|
||||
" compaction input files are currently being compacted.",
|
||||
cf_name.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -522,11 +494,7 @@ Compaction* CompactionPicker::CompactRange(
|
||||
// files together to the last level.
|
||||
assert(vstorage->num_levels() > 1);
|
||||
// DBImpl::CompactRange() set output level to be the last level
|
||||
if (ioptions_.allow_ingest_behind) {
|
||||
assert(output_level == vstorage->num_levels() - 2);
|
||||
} else {
|
||||
assert(output_level == vstorage->num_levels() - 1);
|
||||
}
|
||||
assert(output_level == vstorage->num_levels() - 1);
|
||||
// DBImpl::RunManualCompaction will make full range for universal compaction
|
||||
assert(begin == nullptr);
|
||||
assert(end == nullptr);
|
||||
@@ -1101,7 +1069,11 @@ void LevelCompactionBuilder::SetupInitialFiles() {
|
||||
}
|
||||
output_level_ =
|
||||
(start_level_ == 0) ? vstorage_->base_level() : start_level_ + 1;
|
||||
if (PickFileToCompact()) {
|
||||
if (PickFileToCompact() &&
|
||||
compaction_picker_->ExpandInputsToCleanCut(cf_name_, vstorage_,
|
||||
&start_level_inputs_) &&
|
||||
!compaction_picker_->FilesRangeOverlapWithCompaction(
|
||||
{start_level_inputs_}, output_level_)) {
|
||||
// found the compaction!
|
||||
if (start_level_ == 0) {
|
||||
// L0 score = `num L0 files` / `level0_file_num_compaction_trigger`
|
||||
@@ -1323,10 +1295,12 @@ bool LevelCompactionBuilder::PickFileToCompact() {
|
||||
const std::vector<FileMetaData*>& level_files =
|
||||
vstorage_->LevelFiles(start_level_);
|
||||
|
||||
unsigned int cmp_idx;
|
||||
for (cmp_idx = vstorage_->NextCompactionIndex(start_level_);
|
||||
cmp_idx < file_size.size(); cmp_idx++) {
|
||||
int index = file_size[cmp_idx];
|
||||
// record the first file that is not yet compacted
|
||||
int nextIndex = -1;
|
||||
|
||||
for (unsigned int i = vstorage_->NextCompactionIndex(start_level_);
|
||||
i < file_size.size(); i++) {
|
||||
int index = file_size[i];
|
||||
auto* f = level_files[index];
|
||||
|
||||
// do not pick a file to compact if it is being compacted
|
||||
@@ -1335,42 +1309,27 @@ bool LevelCompactionBuilder::PickFileToCompact() {
|
||||
continue;
|
||||
}
|
||||
|
||||
start_level_inputs_.files.push_back(f);
|
||||
start_level_inputs_.level = start_level_;
|
||||
if (!compaction_picker_->ExpandInputsToCleanCut(cf_name_, vstorage_,
|
||||
&start_level_inputs_) ||
|
||||
compaction_picker_->FilesRangeOverlapWithCompaction(
|
||||
{start_level_inputs_}, output_level_)) {
|
||||
// A locked (pending compaction) input-level file was pulled in due to
|
||||
// user-key overlap.
|
||||
start_level_inputs_.clear();
|
||||
continue;
|
||||
// remember the startIndex for the next call to PickCompaction
|
||||
if (nextIndex == -1) {
|
||||
nextIndex = i;
|
||||
}
|
||||
|
||||
// Now that input level is fully expanded, we check whether any output files
|
||||
// are locked due to pending compaction.
|
||||
//
|
||||
// Note we rely on ExpandInputsToCleanCut() to tell us whether any output-
|
||||
// level files are locked, not just the extra ones pulled in for user-key
|
||||
// overlap.
|
||||
InternalKey smallest, largest;
|
||||
compaction_picker_->GetRange(start_level_inputs_, &smallest, &largest);
|
||||
CompactionInputFiles output_level_inputs;
|
||||
output_level_inputs.level = output_level_;
|
||||
vstorage_->GetOverlappingInputs(output_level_, &smallest, &largest,
|
||||
&output_level_inputs.files);
|
||||
if (!output_level_inputs.empty() &&
|
||||
!compaction_picker_->ExpandInputsToCleanCut(cf_name_, vstorage_,
|
||||
&output_level_inputs)) {
|
||||
start_level_inputs_.clear();
|
||||
// Do not pick this file if its parents at level+1 are being compacted.
|
||||
// Maybe we can avoid redoing this work in SetupOtherInputs
|
||||
parent_index_ = -1;
|
||||
if (compaction_picker_->IsRangeInCompaction(vstorage_, &f->smallest,
|
||||
&f->largest, output_level_,
|
||||
&parent_index_)) {
|
||||
continue;
|
||||
}
|
||||
start_level_inputs_.files.push_back(f);
|
||||
start_level_inputs_.level = start_level_;
|
||||
base_index_ = index;
|
||||
break;
|
||||
}
|
||||
|
||||
// store where to start the iteration in the next call to PickCompaction
|
||||
vstorage_->SetNextCompactionIndex(start_level_, cmp_idx);
|
||||
vstorage_->SetNextCompactionIndex(start_level_, nextIndex);
|
||||
|
||||
return start_level_inputs_.size() > 0;
|
||||
}
|
||||
@@ -1387,8 +1346,31 @@ bool LevelCompactionBuilder::PickIntraL0Compaction() {
|
||||
// resort to L0->L0 compaction yet.
|
||||
return false;
|
||||
}
|
||||
return FindIntraL0Compaction(level_files, kMinFilesForIntraL0Compaction,
|
||||
port::kMaxUint64, &start_level_inputs_);
|
||||
|
||||
size_t compact_bytes = level_files[0]->fd.file_size;
|
||||
size_t compact_bytes_per_del_file = port::kMaxSizet;
|
||||
// compaction range will be [0, span_len).
|
||||
size_t span_len;
|
||||
// pull in files until the amount of compaction work per deleted file begins
|
||||
// increasing.
|
||||
for (span_len = 1; span_len < level_files.size(); ++span_len) {
|
||||
compact_bytes += level_files[span_len]->fd.file_size;
|
||||
size_t new_compact_bytes_per_del_file = compact_bytes / span_len;
|
||||
if (level_files[span_len]->being_compacted ||
|
||||
new_compact_bytes_per_del_file > compact_bytes_per_del_file) {
|
||||
break;
|
||||
}
|
||||
compact_bytes_per_del_file = new_compact_bytes_per_del_file;
|
||||
}
|
||||
|
||||
if (span_len >= kMinFilesForIntraL0Compaction) {
|
||||
start_level_inputs_.level = 0;
|
||||
for (size_t i = 0; i < span_len; ++i) {
|
||||
start_level_inputs_.files.push_back(level_files[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -1407,114 +1389,20 @@ bool FIFOCompactionPicker::NeedsCompaction(
|
||||
return vstorage->CompactionScore(kLevel0) >= 1;
|
||||
}
|
||||
|
||||
namespace {
|
||||
uint64_t GetTotalFilesSize(
|
||||
const std::vector<FileMetaData*>& files) {
|
||||
Compaction* FIFOCompactionPicker::PickCompaction(
|
||||
const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
|
||||
VersionStorageInfo* vstorage, LogBuffer* log_buffer) {
|
||||
assert(vstorage->num_levels() == 1);
|
||||
const int kLevel0 = 0;
|
||||
const std::vector<FileMetaData*>& level_files = vstorage->LevelFiles(kLevel0);
|
||||
uint64_t total_size = 0;
|
||||
for (const auto& f : files) {
|
||||
total_size += f->fd.file_size;
|
||||
for (const auto& file : level_files) {
|
||||
total_size += file->fd.file_size;
|
||||
}
|
||||
return total_size;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
Compaction* FIFOCompactionPicker::PickTTLCompaction(
|
||||
const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
|
||||
VersionStorageInfo* vstorage, LogBuffer* log_buffer) {
|
||||
assert(ioptions_.compaction_options_fifo.ttl > 0);
|
||||
|
||||
const int kLevel0 = 0;
|
||||
const std::vector<FileMetaData*>& level_files = vstorage->LevelFiles(kLevel0);
|
||||
uint64_t total_size = GetTotalFilesSize(level_files);
|
||||
|
||||
int64_t _current_time;
|
||||
auto status = ioptions_.env->GetCurrentTime(&_current_time);
|
||||
if (!status.ok()) {
|
||||
ROCKS_LOG_BUFFER(log_buffer,
|
||||
"[%s] FIFO compaction: Couldn't get current time: %s. "
|
||||
"Not doing compactions based on TTL. ",
|
||||
cf_name.c_str(), status.ToString().c_str());
|
||||
return nullptr;
|
||||
}
|
||||
const uint64_t current_time = static_cast<uint64_t>(_current_time);
|
||||
|
||||
std::vector<CompactionInputFiles> inputs;
|
||||
inputs.emplace_back();
|
||||
inputs[0].level = 0;
|
||||
|
||||
// avoid underflow
|
||||
if (current_time > ioptions_.compaction_options_fifo.ttl) {
|
||||
for (auto ritr = level_files.rbegin(); ritr != level_files.rend(); ++ritr) {
|
||||
auto f = *ritr;
|
||||
if (f->fd.table_reader != nullptr &&
|
||||
f->fd.table_reader->GetTableProperties() != nullptr) {
|
||||
auto creation_time =
|
||||
f->fd.table_reader->GetTableProperties()->creation_time;
|
||||
if (creation_time == 0 ||
|
||||
creation_time >=
|
||||
(current_time - ioptions_.compaction_options_fifo.ttl)) {
|
||||
break;
|
||||
}
|
||||
total_size -= f->compensated_file_size;
|
||||
inputs[0].files.push_back(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return a nullptr and proceed to size-based FIFO compaction if:
|
||||
// 1. there are no files older than ttl OR
|
||||
// 2. there are a few files older than ttl, but deleting them will not bring
|
||||
// the total size to be less than max_table_files_size threshold.
|
||||
if (inputs[0].files.empty() ||
|
||||
total_size > ioptions_.compaction_options_fifo.max_table_files_size) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (const auto& f : inputs[0].files) {
|
||||
ROCKS_LOG_BUFFER(log_buffer,
|
||||
"[%s] FIFO compaction: picking file %" PRIu64
|
||||
" with creation time %" PRIu64 " for deletion",
|
||||
cf_name.c_str(), f->fd.GetNumber(),
|
||||
f->fd.table_reader->GetTableProperties()->creation_time);
|
||||
}
|
||||
|
||||
Compaction* c = new Compaction(
|
||||
vstorage, ioptions_, mutable_cf_options, std::move(inputs), 0, 0, 0, 0,
|
||||
kNoCompression, {}, /* is manual */ false, vstorage->CompactionScore(0),
|
||||
/* is deletion compaction */ true, CompactionReason::kFIFOTtl);
|
||||
return c;
|
||||
}
|
||||
|
||||
Compaction* FIFOCompactionPicker::PickSizeCompaction(
|
||||
const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
|
||||
VersionStorageInfo* vstorage, LogBuffer* log_buffer) {
|
||||
const int kLevel0 = 0;
|
||||
const std::vector<FileMetaData*>& level_files = vstorage->LevelFiles(kLevel0);
|
||||
uint64_t total_size = GetTotalFilesSize(level_files);
|
||||
|
||||
if (total_size <= ioptions_.compaction_options_fifo.max_table_files_size ||
|
||||
level_files.size() == 0) {
|
||||
// total size not exceeded
|
||||
if (ioptions_.compaction_options_fifo.allow_compaction &&
|
||||
level_files.size() > 0) {
|
||||
CompactionInputFiles comp_inputs;
|
||||
if (FindIntraL0Compaction(
|
||||
level_files,
|
||||
mutable_cf_options
|
||||
.level0_file_num_compaction_trigger /* min_files_to_compact */,
|
||||
mutable_cf_options.write_buffer_size, &comp_inputs)) {
|
||||
Compaction* c = new Compaction(
|
||||
vstorage, ioptions_, mutable_cf_options, {comp_inputs}, 0,
|
||||
16 * 1024 * 1024 /* output file size limit */,
|
||||
0 /* max compaction bytes, not applicable */,
|
||||
0 /* output path ID */, mutable_cf_options.compression, {},
|
||||
/* is manual */ false, vstorage->CompactionScore(0),
|
||||
/* is deletion compaction */ false,
|
||||
CompactionReason::kFIFOReduceNumFiles);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
ROCKS_LOG_BUFFER(log_buffer,
|
||||
"[%s] FIFO compaction: nothing to do. Total size %" PRIu64
|
||||
", max size %" PRIu64 "\n",
|
||||
@@ -1535,41 +1423,24 @@ Compaction* FIFOCompactionPicker::PickSizeCompaction(
|
||||
std::vector<CompactionInputFiles> inputs;
|
||||
inputs.emplace_back();
|
||||
inputs[0].level = 0;
|
||||
|
||||
// delete old files (FIFO)
|
||||
for (auto ritr = level_files.rbegin(); ritr != level_files.rend(); ++ritr) {
|
||||
auto f = *ritr;
|
||||
total_size -= f->compensated_file_size;
|
||||
inputs[0].files.push_back(f);
|
||||
char tmp_fsize[16];
|
||||
AppendHumanBytes(f->fd.GetFileSize(), tmp_fsize, sizeof(tmp_fsize));
|
||||
ROCKS_LOG_BUFFER(log_buffer,
|
||||
"[%s] FIFO compaction: picking file %" PRIu64
|
||||
" with size %s for deletion",
|
||||
ROCKS_LOG_BUFFER(log_buffer, "[%s] FIFO compaction: picking file %" PRIu64
|
||||
" with size %s for deletion",
|
||||
cf_name.c_str(), f->fd.GetNumber(), tmp_fsize);
|
||||
if (total_size <= ioptions_.compaction_options_fifo.max_table_files_size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Compaction* c = new Compaction(
|
||||
vstorage, ioptions_, mutable_cf_options, std::move(inputs), 0, 0, 0, 0,
|
||||
kNoCompression, {}, /* is manual */ false, vstorage->CompactionScore(0),
|
||||
/* is deletion compaction */ true, CompactionReason::kFIFOMaxSize);
|
||||
return c;
|
||||
}
|
||||
|
||||
Compaction* FIFOCompactionPicker::PickCompaction(
|
||||
const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
|
||||
VersionStorageInfo* vstorage, LogBuffer* log_buffer) {
|
||||
assert(vstorage->num_levels() == 1);
|
||||
|
||||
Compaction* c = nullptr;
|
||||
if (ioptions_.compaction_options_fifo.ttl > 0) {
|
||||
c = PickTTLCompaction(cf_name, mutable_cf_options, vstorage, log_buffer);
|
||||
}
|
||||
if (c == nullptr) {
|
||||
c = PickSizeCompaction(cf_name, mutable_cf_options, vstorage, log_buffer);
|
||||
}
|
||||
RegisterCompaction(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -242,17 +242,6 @@ class FIFOCompactionPicker : public CompactionPicker {
|
||||
|
||||
virtual bool NeedsCompaction(
|
||||
const VersionStorageInfo* vstorage) const override;
|
||||
|
||||
private:
|
||||
Compaction* PickTTLCompaction(const std::string& cf_name,
|
||||
const MutableCFOptions& mutable_cf_options,
|
||||
VersionStorageInfo* version,
|
||||
LogBuffer* log_buffer);
|
||||
|
||||
Compaction* PickSizeCompaction(const std::string& cf_name,
|
||||
const MutableCFOptions& mutable_cf_options,
|
||||
VersionStorageInfo* version,
|
||||
LogBuffer* log_buffer);
|
||||
};
|
||||
|
||||
class NullCompactionPicker : public CompactionPicker {
|
||||
|
||||
@@ -400,35 +400,6 @@ TEST_F(CompactionPickerTest, NeedsCompactionUniversal) {
|
||||
vstorage_->CompactionScore(0) >= 1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(CompactionPickerTest, CompactionUniversalIngestBehindReservedLevel) {
|
||||
const uint64_t kFileSize = 100000;
|
||||
NewVersionStorage(1, kCompactionStyleUniversal);
|
||||
ioptions_.allow_ingest_behind = true;
|
||||
ioptions_.num_levels = 3;
|
||||
UniversalCompactionPicker universal_compaction_picker(ioptions_, &icmp_);
|
||||
// must return false when there's no files.
|
||||
ASSERT_EQ(universal_compaction_picker.NeedsCompaction(vstorage_.get()),
|
||||
false);
|
||||
|
||||
NewVersionStorage(3, kCompactionStyleUniversal);
|
||||
|
||||
Add(0, 1U, "150", "200", kFileSize, 0, 500, 550);
|
||||
Add(0, 2U, "201", "250", kFileSize, 0, 401, 450);
|
||||
Add(0, 4U, "260", "300", kFileSize, 0, 260, 300);
|
||||
Add(1, 5U, "100", "151", kFileSize, 0, 200, 251);
|
||||
Add(1, 3U, "301", "350", kFileSize, 0, 101, 150);
|
||||
Add(2, 6U, "120", "200", kFileSize, 0, 20, 100);
|
||||
|
||||
UpdateVersionStorageInfo();
|
||||
|
||||
std::unique_ptr<Compaction> compaction(
|
||||
universal_compaction_picker.PickCompaction(
|
||||
cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
|
||||
|
||||
// output level should be the one above the bottom-most
|
||||
ASSERT_EQ(1, compaction->output_level());
|
||||
}
|
||||
// Tests if the files can be trivially moved in multi level
|
||||
// universal compaction when allow_trivial_move option is set
|
||||
// In this test as the input files overlaps, they cannot
|
||||
@@ -512,7 +483,7 @@ TEST_F(CompactionPickerTest, NeedsCompactionFIFO) {
|
||||
kFileSize, 0, i * 100, i * 100 + 99);
|
||||
current_size += kFileSize;
|
||||
UpdateVersionStorageInfo();
|
||||
ASSERT_EQ(fifo_compaction_picker.NeedsCompaction(vstorage_.get()),
|
||||
ASSERT_EQ(level_compaction_picker.NeedsCompaction(vstorage_.get()),
|
||||
vstorage_->CompactionScore(0) >= 1);
|
||||
}
|
||||
}
|
||||
@@ -852,80 +823,6 @@ TEST_F(CompactionPickerTest, OverlappingUserKeys9) {
|
||||
ASSERT_EQ(8U, compaction->input(1, 1)->fd.GetNumber());
|
||||
}
|
||||
|
||||
TEST_F(CompactionPickerTest, OverlappingUserKeys10) {
|
||||
// Locked file encountered when pulling in extra input-level files with same
|
||||
// user keys. Verify we pick the next-best file from the same input level.
|
||||
NewVersionStorage(6, kCompactionStyleLevel);
|
||||
mutable_cf_options_.max_compaction_bytes = 100000000000u;
|
||||
|
||||
// file_number 2U is largest and thus first choice. But it overlaps with
|
||||
// file_number 1U which is being compacted. So instead we pick the next-
|
||||
// biggest file, 3U, which is eligible for compaction.
|
||||
Add(1 /* level */, 1U /* file_number */, "100" /* smallest */,
|
||||
"150" /* largest */, 1U /* file_size */);
|
||||
file_map_[1U].first->being_compacted = true;
|
||||
Add(1 /* level */, 2U /* file_number */, "150" /* smallest */,
|
||||
"200" /* largest */, 1000000000U /* file_size */, 0 /* smallest_seq */,
|
||||
0 /* largest_seq */);
|
||||
Add(1 /* level */, 3U /* file_number */, "201" /* smallest */,
|
||||
"250" /* largest */, 900000000U /* file_size */);
|
||||
Add(2 /* level */, 4U /* file_number */, "100" /* smallest */,
|
||||
"150" /* largest */, 1U /* file_size */);
|
||||
Add(2 /* level */, 5U /* file_number */, "151" /* smallest */,
|
||||
"200" /* largest */, 1U /* file_size */);
|
||||
Add(2 /* level */, 6U /* file_number */, "201" /* smallest */,
|
||||
"250" /* largest */, 1U /* file_size */);
|
||||
|
||||
UpdateVersionStorageInfo();
|
||||
|
||||
std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
|
||||
cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
|
||||
ASSERT_TRUE(compaction.get() != nullptr);
|
||||
ASSERT_EQ(2U, compaction->num_input_levels());
|
||||
ASSERT_EQ(1U, compaction->num_input_files(0));
|
||||
ASSERT_EQ(1U, compaction->num_input_files(1));
|
||||
ASSERT_EQ(3U, compaction->input(0, 0)->fd.GetNumber());
|
||||
ASSERT_EQ(6U, compaction->input(1, 0)->fd.GetNumber());
|
||||
}
|
||||
|
||||
TEST_F(CompactionPickerTest, OverlappingUserKeys11) {
|
||||
// Locked file encountered when pulling in extra output-level files with same
|
||||
// user keys. Expected to skip that compaction and pick the next-best choice.
|
||||
NewVersionStorage(6, kCompactionStyleLevel);
|
||||
mutable_cf_options_.max_compaction_bytes = 100000000000u;
|
||||
|
||||
// score(L1) = 3.7
|
||||
// score(L2) = 1.85
|
||||
// There is no eligible file in L1 to compact since both candidates pull in
|
||||
// file_number 5U, which overlaps with a file pending compaction (6U). The
|
||||
// first eligible compaction is from L2->L3.
|
||||
Add(1 /* level */, 2U /* file_number */, "151" /* smallest */,
|
||||
"200" /* largest */, 1000000000U /* file_size */);
|
||||
Add(1 /* level */, 3U /* file_number */, "201" /* smallest */,
|
||||
"250" /* largest */, 1U /* file_size */);
|
||||
Add(2 /* level */, 4U /* file_number */, "100" /* smallest */,
|
||||
"149" /* largest */, 5000000000U /* file_size */);
|
||||
Add(2 /* level */, 5U /* file_number */, "150" /* smallest */,
|
||||
"201" /* largest */, 1U /* file_size */);
|
||||
Add(2 /* level */, 6U /* file_number */, "201" /* smallest */,
|
||||
"249" /* largest */, 1U /* file_size */, 0 /* smallest_seq */,
|
||||
0 /* largest_seq */);
|
||||
file_map_[6U].first->being_compacted = true;
|
||||
Add(3 /* level */, 7U /* file_number */, "100" /* smallest */,
|
||||
"149" /* largest */, 1U /* file_size */);
|
||||
|
||||
UpdateVersionStorageInfo();
|
||||
|
||||
std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
|
||||
cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
|
||||
ASSERT_TRUE(compaction.get() != nullptr);
|
||||
ASSERT_EQ(2U, compaction->num_input_levels());
|
||||
ASSERT_EQ(1U, compaction->num_input_files(0));
|
||||
ASSERT_EQ(1U, compaction->num_input_files(1));
|
||||
ASSERT_EQ(4U, compaction->input(0, 0)->fd.GetNumber());
|
||||
ASSERT_EQ(7U, compaction->input(1, 0)->fd.GetNumber());
|
||||
}
|
||||
|
||||
TEST_F(CompactionPickerTest, NotScheduleL1IfL0WithHigherPri1) {
|
||||
NewVersionStorage(6, kCompactionStyleLevel);
|
||||
mutable_cf_options_.level0_file_num_compaction_trigger = 2;
|
||||
@@ -1024,7 +921,7 @@ TEST_F(CompactionPickerTest, NotScheduleL1IfL0WithHigherPri3) {
|
||||
TEST_F(CompactionPickerTest, EstimateCompactionBytesNeeded1) {
|
||||
int num_levels = ioptions_.num_levels;
|
||||
ioptions_.level_compaction_dynamic_level_bytes = false;
|
||||
mutable_cf_options_.level0_file_num_compaction_trigger = 4;
|
||||
mutable_cf_options_.level0_file_num_compaction_trigger = 3;
|
||||
mutable_cf_options_.max_bytes_for_level_base = 1000;
|
||||
mutable_cf_options_.max_bytes_for_level_multiplier = 10;
|
||||
NewVersionStorage(num_levels, kCompactionStyleLevel);
|
||||
@@ -1114,8 +1011,7 @@ TEST_F(CompactionPickerTest, EstimateCompactionBytesNeededDynamicLevel) {
|
||||
|
||||
// Set Last level size 50000
|
||||
// num_levels - 1 target 5000
|
||||
// num_levels - 2 is base level with target 1000 (rounded up to
|
||||
// max_bytes_for_level_base).
|
||||
// num_levels - 2 is base level with taret 500
|
||||
Add(num_levels - 1, 10U, "400", "500", 50000);
|
||||
|
||||
Add(0, 1U, "150", "200", 200);
|
||||
@@ -1124,16 +1020,16 @@ TEST_F(CompactionPickerTest, EstimateCompactionBytesNeededDynamicLevel) {
|
||||
Add(0, 5U, "150", "200", 200);
|
||||
Add(0, 6U, "150", "200", 200);
|
||||
// num_levels - 3 is over target by 100 + 1000
|
||||
Add(num_levels - 3, 7U, "400", "500", 550);
|
||||
Add(num_levels - 3, 8U, "600", "700", 550);
|
||||
Add(num_levels - 3, 7U, "400", "500", 300);
|
||||
Add(num_levels - 3, 8U, "600", "700", 300);
|
||||
// num_levels - 2 is over target by 1100 + 200
|
||||
Add(num_levels - 2, 9U, "150", "200", 5200);
|
||||
|
||||
UpdateVersionStorageInfo();
|
||||
|
||||
// Merging to the second last level: (5200 / 2100 + 1) * 1100
|
||||
// Merging to the second last level: (5200 / 1600 + 1) * 1100
|
||||
// Merging to the last level: (50000 / 6300 + 1) * 1300
|
||||
ASSERT_EQ(2100u + 3823u + 11617u,
|
||||
ASSERT_EQ(1600u + 4675u + 11617u,
|
||||
vstorage_->estimated_compaction_needed_bytes());
|
||||
}
|
||||
|
||||
@@ -1390,49 +1286,6 @@ TEST_F(CompactionPickerTest, IsTrivialMoveOff) {
|
||||
ASSERT_FALSE(compaction->IsTrivialMove());
|
||||
}
|
||||
|
||||
TEST_F(CompactionPickerTest, CacheNextCompactionIndex) {
|
||||
NewVersionStorage(6, kCompactionStyleLevel);
|
||||
mutable_cf_options_.max_compaction_bytes = 100000000000u;
|
||||
|
||||
Add(1 /* level */, 1U /* file_number */, "100" /* smallest */,
|
||||
"149" /* largest */, 1000000000U /* file_size */);
|
||||
file_map_[1U].first->being_compacted = true;
|
||||
Add(1 /* level */, 2U /* file_number */, "150" /* smallest */,
|
||||
"199" /* largest */, 900000000U /* file_size */);
|
||||
Add(1 /* level */, 3U /* file_number */, "200" /* smallest */,
|
||||
"249" /* largest */, 800000000U /* file_size */);
|
||||
Add(1 /* level */, 4U /* file_number */, "250" /* smallest */,
|
||||
"299" /* largest */, 700000000U /* file_size */);
|
||||
Add(2 /* level */, 5U /* file_number */, "150" /* smallest */,
|
||||
"199" /* largest */, 1U /* file_size */);
|
||||
file_map_[5U].first->being_compacted = true;
|
||||
|
||||
UpdateVersionStorageInfo();
|
||||
|
||||
std::unique_ptr<Compaction> compaction(level_compaction_picker.PickCompaction(
|
||||
cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
|
||||
ASSERT_TRUE(compaction.get() != nullptr);
|
||||
ASSERT_EQ(1U, compaction->num_input_levels());
|
||||
ASSERT_EQ(1U, compaction->num_input_files(0));
|
||||
ASSERT_EQ(0U, compaction->num_input_files(1));
|
||||
ASSERT_EQ(3U, compaction->input(0, 0)->fd.GetNumber());
|
||||
ASSERT_EQ(2, vstorage_->NextCompactionIndex(1 /* level */));
|
||||
|
||||
compaction.reset(level_compaction_picker.PickCompaction(
|
||||
cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
|
||||
ASSERT_TRUE(compaction.get() != nullptr);
|
||||
ASSERT_EQ(1U, compaction->num_input_levels());
|
||||
ASSERT_EQ(1U, compaction->num_input_files(0));
|
||||
ASSERT_EQ(0U, compaction->num_input_files(1));
|
||||
ASSERT_EQ(4U, compaction->input(0, 0)->fd.GetNumber());
|
||||
ASSERT_EQ(3, vstorage_->NextCompactionIndex(1 /* level */));
|
||||
|
||||
compaction.reset(level_compaction_picker.PickCompaction(
|
||||
cf_name_, mutable_cf_options_, vstorage_.get(), &log_buffer_));
|
||||
ASSERT_TRUE(compaction.get() == nullptr);
|
||||
ASSERT_EQ(4, vstorage_->NextCompactionIndex(1 /* level */));
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
@@ -342,6 +342,8 @@ Compaction* UniversalCompactionPicker::PickCompaction(
|
||||
assert(f->smallest_seqno <= f->largest_seqno);
|
||||
if (is_first) {
|
||||
is_first = false;
|
||||
} else {
|
||||
assert(prev_smallest_seqno > f->largest_seqno);
|
||||
}
|
||||
prev_smallest_seqno = f->smallest_seqno;
|
||||
}
|
||||
@@ -373,7 +375,6 @@ Compaction* UniversalCompactionPicker::PickCompaction(
|
||||
c->inputs(0)->size());
|
||||
|
||||
RegisterCompaction(c);
|
||||
vstorage->ComputeCompactionScore(ioptions_, mutable_cf_options);
|
||||
|
||||
TEST_SYNC_POINT_CALLBACK("UniversalCompactionPicker::PickCompaction:Return",
|
||||
c);
|
||||
@@ -567,13 +568,6 @@ Compaction* UniversalCompactionPicker::PickCompactionToReduceSortedRuns(
|
||||
output_level = sorted_runs[first_index_after].level - 1;
|
||||
}
|
||||
|
||||
// last level is reserved for the files ingested behind
|
||||
if (ioptions_.allow_ingest_behind &&
|
||||
(output_level == vstorage->num_levels() - 1)) {
|
||||
assert(output_level > 1);
|
||||
output_level--;
|
||||
}
|
||||
|
||||
std::vector<CompactionInputFiles> inputs(vstorage->num_levels());
|
||||
for (size_t i = 0; i < inputs.size(); ++i) {
|
||||
inputs[i].level = start_level + static_cast<int>(i);
|
||||
@@ -620,7 +614,7 @@ Compaction* UniversalCompactionPicker::PickCompactionToReduceSizeAmp(
|
||||
const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
|
||||
VersionStorageInfo* vstorage, double score,
|
||||
const std::vector<SortedRun>& sorted_runs, LogBuffer* log_buffer) {
|
||||
// percentage flexibility while reducing size amplification
|
||||
// percentage flexibilty while reducing size amplification
|
||||
uint64_t ratio =
|
||||
ioptions_.compaction_options_universal.max_size_amplification_percent;
|
||||
|
||||
@@ -725,20 +719,13 @@ Compaction* UniversalCompactionPicker::PickCompactionToReduceSizeAmp(
|
||||
cf_name.c_str(), file_num_buf);
|
||||
}
|
||||
|
||||
// output files at the bottom most level, unless it's reserved
|
||||
int output_level = vstorage->num_levels() - 1;
|
||||
// last level is reserved for the files ingested behind
|
||||
if (ioptions_.allow_ingest_behind) {
|
||||
assert(output_level > 1);
|
||||
output_level--;
|
||||
}
|
||||
|
||||
return new Compaction(
|
||||
vstorage, ioptions_, mutable_cf_options, std::move(inputs),
|
||||
output_level, mutable_cf_options.MaxFileSizeForLevel(output_level),
|
||||
vstorage->num_levels() - 1,
|
||||
mutable_cf_options.MaxFileSizeForLevel(vstorage->num_levels() - 1),
|
||||
/* max_grandparent_overlap_bytes */ LLONG_MAX, path_id,
|
||||
GetCompressionType(ioptions_, vstorage, mutable_cf_options,
|
||||
output_level, 1),
|
||||
vstorage->num_levels() - 1, 1),
|
||||
/* grandparents */ {}, /* is manual */ false, score,
|
||||
false /* deletion_compaction */,
|
||||
CompactionReason::kUniversalSizeAmplification);
|
||||
|
||||
+2
-33
@@ -9,50 +9,19 @@
|
||||
#include "rocksdb/convenience.h"
|
||||
|
||||
#include "db/db_impl.h"
|
||||
#include "util/cast_util.h"
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
void CancelAllBackgroundWork(DB* db, bool wait) {
|
||||
(static_cast_with_check<DBImpl, DB>(db->GetRootDB()))
|
||||
->CancelAllBackgroundWork(wait);
|
||||
(dynamic_cast<DBImpl*>(db))->CancelAllBackgroundWork(wait);
|
||||
}
|
||||
|
||||
Status DeleteFilesInRange(DB* db, ColumnFamilyHandle* column_family,
|
||||
const Slice* begin, const Slice* end) {
|
||||
return (static_cast_with_check<DBImpl, DB>(db->GetRootDB()))
|
||||
return (dynamic_cast<DBImpl*>(db))
|
||||
->DeleteFilesInRange(column_family, begin, end);
|
||||
}
|
||||
|
||||
Status VerifySstFileChecksum(const Options& options,
|
||||
const EnvOptions& env_options,
|
||||
const std::string& file_path) {
|
||||
unique_ptr<RandomAccessFile> file;
|
||||
uint64_t file_size;
|
||||
InternalKeyComparator internal_comparator(options.comparator);
|
||||
ImmutableCFOptions ioptions(options);
|
||||
|
||||
Status s = ioptions.env->NewRandomAccessFile(file_path, &file, env_options);
|
||||
if (s.ok()) {
|
||||
s = ioptions.env->GetFileSize(file_path, &file_size);
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
unique_ptr<TableReader> table_reader;
|
||||
std::unique_ptr<RandomAccessFileReader> file_reader(
|
||||
new RandomAccessFileReader(std::move(file), file_path));
|
||||
s = ioptions.table_factory->NewTableReader(
|
||||
TableReaderOptions(ioptions, env_options, internal_comparator,
|
||||
false /* skip_filters */, -1 /* level */),
|
||||
std::move(file_reader), file_size, &table_reader,
|
||||
false /* prefetch_index_and_filter_in_cache */);
|
||||
if (!s.ok()) {
|
||||
return s;
|
||||
}
|
||||
s = table_reader->VerifyChecksum();
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // ROCKSDB_LITE
|
||||
+2
-13
@@ -20,7 +20,6 @@
|
||||
#include "db/log_format.h"
|
||||
#include "db/version_set.h"
|
||||
#include "rocksdb/cache.h"
|
||||
#include "rocksdb/convenience.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "rocksdb/table.h"
|
||||
#include "rocksdb/write_batch.h"
|
||||
@@ -153,7 +152,7 @@ class CorruptionTest : public testing::Test {
|
||||
struct stat sbuf;
|
||||
if (stat(fname.c_str(), &sbuf) != 0) {
|
||||
const char* msg = strerror(errno);
|
||||
FAIL() << fname << ": " << msg;
|
||||
ASSERT_TRUE(false) << fname << ": " << msg;
|
||||
}
|
||||
|
||||
if (offset < 0) {
|
||||
@@ -180,9 +179,6 @@ class CorruptionTest : public testing::Test {
|
||||
}
|
||||
s = WriteStringToFile(Env::Default(), contents, fname);
|
||||
ASSERT_TRUE(s.ok()) << s.ToString();
|
||||
Options options;
|
||||
EnvOptions env_options;
|
||||
ASSERT_NOK(VerifySstFileChecksum(options, env_options, fname));
|
||||
}
|
||||
|
||||
void Corrupt(FileType filetype, int offset, int bytes_to_corrupt) {
|
||||
@@ -217,7 +213,7 @@ class CorruptionTest : public testing::Test {
|
||||
return;
|
||||
}
|
||||
}
|
||||
FAIL() << "no file found at level";
|
||||
ASSERT_TRUE(false) << "no file found at level";
|
||||
}
|
||||
|
||||
|
||||
@@ -316,7 +312,6 @@ TEST_F(CorruptionTest, TableFile) {
|
||||
|
||||
Corrupt(kTableFile, 100, 1);
|
||||
Check(99, 99);
|
||||
ASSERT_NOK(dbi->VerifyChecksum());
|
||||
}
|
||||
|
||||
TEST_F(CorruptionTest, TableFileIndexData) {
|
||||
@@ -332,11 +327,9 @@ TEST_F(CorruptionTest, TableFileIndexData) {
|
||||
// corrupt an index block of an entire file
|
||||
Corrupt(kTableFile, -2000, 500);
|
||||
Reopen();
|
||||
dbi = reinterpret_cast<DBImpl*>(db_);
|
||||
// one full file should be readable, since only one was corrupted
|
||||
// the other file should be fully non-readable, since index was corrupted
|
||||
Check(5000, 5000);
|
||||
ASSERT_NOK(dbi->VerifyChecksum());
|
||||
}
|
||||
|
||||
TEST_F(CorruptionTest, MissingDescriptor) {
|
||||
@@ -396,12 +389,10 @@ TEST_F(CorruptionTest, CompactionInputError) {
|
||||
|
||||
Corrupt(kTableFile, 100, 1);
|
||||
Check(9, 9);
|
||||
ASSERT_NOK(dbi->VerifyChecksum());
|
||||
|
||||
// Force compactions by writing lots of values
|
||||
Build(10000);
|
||||
Check(10000, 10000);
|
||||
ASSERT_NOK(dbi->VerifyChecksum());
|
||||
}
|
||||
|
||||
TEST_F(CorruptionTest, CompactionInputErrorParanoid) {
|
||||
@@ -433,7 +424,6 @@ TEST_F(CorruptionTest, CompactionInputErrorParanoid) {
|
||||
|
||||
CorruptTableFileAtLevel(0, 100, 1);
|
||||
Check(9, 9);
|
||||
ASSERT_NOK(dbi->VerifyChecksum());
|
||||
|
||||
// Write must eventually fail because of corrupted table
|
||||
Status s;
|
||||
@@ -455,7 +445,6 @@ TEST_F(CorruptionTest, UnrelatedKeys) {
|
||||
DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
|
||||
dbi->TEST_FlushMemTable();
|
||||
Corrupt(kTableFile, 100, 1);
|
||||
ASSERT_NOK(dbi->VerifyChecksum());
|
||||
|
||||
std::string tmp1, tmp2;
|
||||
ASSERT_OK(db_->Put(WriteOptions(), Key(1000, &tmp1), Value(1000, &tmp2)));
|
||||
|
||||
@@ -320,14 +320,8 @@ TEST_F(CuckooTableDBTest, AdaptiveTable) {
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (rocksdb::port::kLittleEndian) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "SKIPPED as Cuckoo table doesn't support Big Endian\n");
|
||||
return 0;
|
||||
}
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
+33
-37
@@ -175,8 +175,6 @@ TEST_F(DBBasicTest, LevelLimitReopen) {
|
||||
int i = 0;
|
||||
while (NumTableFilesAtLevel(2, 1) == 0) {
|
||||
ASSERT_OK(Put(1, Key(i++), value));
|
||||
dbfull()->TEST_WaitForFlushMemTable();
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
}
|
||||
|
||||
options.num_levels = 1;
|
||||
@@ -360,15 +358,15 @@ TEST_F(DBBasicTest, FLUSH) {
|
||||
WriteOptions writeOpt = WriteOptions();
|
||||
writeOpt.disableWAL = true;
|
||||
SetPerfLevel(kEnableTime);
|
||||
;
|
||||
ASSERT_OK(dbfull()->Put(writeOpt, handles_[1], "foo", "v1"));
|
||||
// this will now also flush the last 2 writes
|
||||
ASSERT_OK(Flush(1));
|
||||
ASSERT_OK(dbfull()->Put(writeOpt, handles_[1], "bar", "v1"));
|
||||
|
||||
get_perf_context()->Reset();
|
||||
perf_context.Reset();
|
||||
Get(1, "foo");
|
||||
ASSERT_TRUE((int)get_perf_context()->get_from_output_files_time > 0);
|
||||
ASSERT_EQ(2, (int)get_perf_context()->get_read_bytes);
|
||||
ASSERT_TRUE((int)perf_context.get_from_output_files_time > 0);
|
||||
|
||||
ReopenWithColumnFamilies({"default", "pikachu"}, CurrentOptions());
|
||||
ASSERT_EQ("v1", Get(1, "foo"));
|
||||
@@ -381,9 +379,9 @@ TEST_F(DBBasicTest, FLUSH) {
|
||||
|
||||
ReopenWithColumnFamilies({"default", "pikachu"}, CurrentOptions());
|
||||
ASSERT_EQ("v2", Get(1, "bar"));
|
||||
get_perf_context()->Reset();
|
||||
perf_context.Reset();
|
||||
ASSERT_EQ("v2", Get(1, "foo"));
|
||||
ASSERT_TRUE((int)get_perf_context()->get_from_output_files_time > 0);
|
||||
ASSERT_TRUE((int)perf_context.get_from_output_files_time > 0);
|
||||
|
||||
writeOpt.disableWAL = false;
|
||||
ASSERT_OK(dbfull()->Put(writeOpt, handles_[1], "bar", "v3"));
|
||||
@@ -725,7 +723,6 @@ TEST_F(DBBasicTest, FlushOneColumnFamily) {
|
||||
TEST_F(DBBasicTest, MultiGetSimple) {
|
||||
do {
|
||||
CreateAndReopenWithCF({"pikachu"}, CurrentOptions());
|
||||
SetPerfLevel(kEnableCount);
|
||||
ASSERT_OK(Put(1, "k1", "v1"));
|
||||
ASSERT_OK(Put(1, "k2", "v2"));
|
||||
ASSERT_OK(Put(1, "k3", "v3"));
|
||||
@@ -739,15 +736,12 @@ TEST_F(DBBasicTest, MultiGetSimple) {
|
||||
std::vector<std::string> values(20, "Temporary data to be overwritten");
|
||||
std::vector<ColumnFamilyHandle*> cfs(keys.size(), handles_[1]);
|
||||
|
||||
get_perf_context()->Reset();
|
||||
std::vector<Status> s = db_->MultiGet(ReadOptions(), cfs, keys, &values);
|
||||
ASSERT_EQ(values.size(), keys.size());
|
||||
ASSERT_EQ(values[0], "v1");
|
||||
ASSERT_EQ(values[1], "v2");
|
||||
ASSERT_EQ(values[2], "v3");
|
||||
ASSERT_EQ(values[4], "v5");
|
||||
// four kv pairs * two bytes per value
|
||||
ASSERT_EQ(8, (int)get_perf_context()->multiget_read_bytes);
|
||||
|
||||
ASSERT_OK(s[0]);
|
||||
ASSERT_OK(s[1]);
|
||||
@@ -755,7 +749,6 @@ TEST_F(DBBasicTest, MultiGetSimple) {
|
||||
ASSERT_TRUE(s[3].IsNotFound());
|
||||
ASSERT_OK(s[4]);
|
||||
ASSERT_TRUE(s[5].IsNotFound());
|
||||
SetPerfLevel(kDisable);
|
||||
} while (ChangeCompactOptions());
|
||||
}
|
||||
|
||||
@@ -792,30 +785,36 @@ TEST_F(DBBasicTest, MultiGetEmpty) {
|
||||
TEST_F(DBBasicTest, ChecksumTest) {
|
||||
BlockBasedTableOptions table_options;
|
||||
Options options = CurrentOptions();
|
||||
// change when new checksum type added
|
||||
int max_checksum = static_cast<int>(kxxHash);
|
||||
const int kNumPerFile = 2;
|
||||
|
||||
// generate one table with each type of checksum
|
||||
for (int i = 0; i <= max_checksum; ++i) {
|
||||
table_options.checksum = static_cast<ChecksumType>(i);
|
||||
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
|
||||
Reopen(options);
|
||||
for (int j = 0; j < kNumPerFile; ++j) {
|
||||
ASSERT_OK(Put(Key(i * kNumPerFile + j), Key(i * kNumPerFile + j)));
|
||||
}
|
||||
ASSERT_OK(Flush());
|
||||
}
|
||||
table_options.checksum = kCRC32c;
|
||||
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
|
||||
Reopen(options);
|
||||
ASSERT_OK(Put("a", "b"));
|
||||
ASSERT_OK(Put("c", "d"));
|
||||
ASSERT_OK(Flush()); // table with crc checksum
|
||||
|
||||
// verify data with each type of checksum
|
||||
for (int i = 0; i <= kxxHash; ++i) {
|
||||
table_options.checksum = static_cast<ChecksumType>(i);
|
||||
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
|
||||
Reopen(options);
|
||||
for (int j = 0; j < (max_checksum + 1) * kNumPerFile; ++j) {
|
||||
ASSERT_EQ(Key(j), Get(Key(j)));
|
||||
}
|
||||
}
|
||||
table_options.checksum = kxxHash;
|
||||
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
|
||||
Reopen(options);
|
||||
ASSERT_OK(Put("e", "f"));
|
||||
ASSERT_OK(Put("g", "h"));
|
||||
ASSERT_OK(Flush()); // table with xxhash checksum
|
||||
|
||||
table_options.checksum = kCRC32c;
|
||||
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
|
||||
Reopen(options);
|
||||
ASSERT_EQ("b", Get("a"));
|
||||
ASSERT_EQ("d", Get("c"));
|
||||
ASSERT_EQ("f", Get("e"));
|
||||
ASSERT_EQ("h", Get("g"));
|
||||
|
||||
table_options.checksum = kCRC32c;
|
||||
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
|
||||
Reopen(options);
|
||||
ASSERT_EQ("b", Get("a"));
|
||||
ASSERT_EQ("d", Get("c"));
|
||||
ASSERT_EQ("f", Get("e"));
|
||||
ASSERT_EQ("h", Get("g"));
|
||||
}
|
||||
|
||||
// On Windows you can have either memory mapped file or a file
|
||||
@@ -823,9 +822,6 @@ TEST_F(DBBasicTest, ChecksumTest) {
|
||||
// sense to run
|
||||
#ifndef OS_WIN
|
||||
TEST_F(DBBasicTest, MmapAndBufferOptions) {
|
||||
if (!IsMemoryMappedAccessSupported()) {
|
||||
return;
|
||||
}
|
||||
Options options = CurrentOptions();
|
||||
|
||||
options.use_direct_reads = true;
|
||||
|
||||
@@ -1,409 +0,0 @@
|
||||
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
//
|
||||
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "db/column_family.h"
|
||||
#include "db/db_iter.h"
|
||||
#include "db/db_test_util.h"
|
||||
#include "db/dbformat.h"
|
||||
#include "db/write_batch_internal.h"
|
||||
#include "port/port.h"
|
||||
#include "port/stack_trace.h"
|
||||
#include "util/string_util.h"
|
||||
#include "utilities/merge_operators.h"
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
// kTypeBlobIndex is a value type used by BlobDB only. The base rocksdb
|
||||
// should accept the value type on write, and report not supported value
|
||||
// for reads, unless caller request for it explicitly. The base rocksdb
|
||||
// doesn't understand format of actual blob index (the value).
|
||||
class DBBlobIndexTest : public DBTestBase {
|
||||
public:
|
||||
enum Tier {
|
||||
kMemtable = 0,
|
||||
kImmutableMemtables = 1,
|
||||
kL0SstFile = 2,
|
||||
kLnSstFile = 3,
|
||||
};
|
||||
const std::vector<Tier> kAllTiers = {Tier::kMemtable,
|
||||
Tier::kImmutableMemtables,
|
||||
Tier::kL0SstFile, Tier::kLnSstFile};
|
||||
|
||||
DBBlobIndexTest() : DBTestBase("/db_blob_index_test") {}
|
||||
|
||||
ColumnFamilyHandle* cfh() { return dbfull()->DefaultColumnFamily(); }
|
||||
|
||||
ColumnFamilyData* cfd() {
|
||||
return reinterpret_cast<ColumnFamilyHandleImpl*>(cfh())->cfd();
|
||||
}
|
||||
|
||||
Status PutBlobIndex(WriteBatch* batch, const Slice& key,
|
||||
const Slice& blob_index) {
|
||||
return WriteBatchInternal::PutBlobIndex(batch, cfd()->GetID(), key,
|
||||
blob_index);
|
||||
}
|
||||
|
||||
Status Write(WriteBatch* batch) {
|
||||
return dbfull()->Write(WriteOptions(), batch);
|
||||
}
|
||||
|
||||
std::string GetImpl(const Slice& key, bool* is_blob_index = nullptr,
|
||||
const Snapshot* snapshot = nullptr) {
|
||||
ReadOptions read_options;
|
||||
read_options.snapshot = snapshot;
|
||||
PinnableSlice value;
|
||||
auto s = dbfull()->GetImpl(read_options, cfh(), key, &value,
|
||||
nullptr /*value_found*/, is_blob_index);
|
||||
if (s.IsNotFound()) {
|
||||
return "NOT_FOUND";
|
||||
}
|
||||
if (s.IsNotSupported()) {
|
||||
return "NOT_SUPPORTED";
|
||||
}
|
||||
if (!s.ok()) {
|
||||
return s.ToString();
|
||||
}
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
std::string GetBlobIndex(const Slice& key,
|
||||
const Snapshot* snapshot = nullptr) {
|
||||
bool is_blob_index = false;
|
||||
std::string value = GetImpl(key, &is_blob_index, snapshot);
|
||||
if (!is_blob_index) {
|
||||
return "NOT_BLOB";
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
ArenaWrappedDBIter* GetBlobIterator() {
|
||||
return dbfull()->NewIteratorImpl(ReadOptions(), cfd(),
|
||||
dbfull()->GetLatestSequenceNumber(),
|
||||
true /*allow_blob*/);
|
||||
}
|
||||
|
||||
Options GetTestOptions() {
|
||||
Options options;
|
||||
options.create_if_missing = true;
|
||||
options.num_levels = 2;
|
||||
options.disable_auto_compactions = true;
|
||||
// Disable auto flushes.
|
||||
options.max_write_buffer_number = 10;
|
||||
options.min_write_buffer_number_to_merge = 10;
|
||||
options.merge_operator = MergeOperators::CreateStringAppendOperator();
|
||||
return options;
|
||||
}
|
||||
|
||||
void MoveDataTo(Tier tier) {
|
||||
switch (tier) {
|
||||
case Tier::kMemtable:
|
||||
break;
|
||||
case Tier::kImmutableMemtables:
|
||||
ASSERT_OK(dbfull()->TEST_SwitchMemtable());
|
||||
break;
|
||||
case Tier::kL0SstFile:
|
||||
ASSERT_OK(Flush());
|
||||
break;
|
||||
case Tier::kLnSstFile:
|
||||
ASSERT_OK(Flush());
|
||||
ASSERT_OK(Put("a", "dummy"));
|
||||
ASSERT_OK(Put("z", "dummy"));
|
||||
ASSERT_OK(Flush());
|
||||
ASSERT_OK(
|
||||
dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||
#ifndef ROCKSDB_LITE
|
||||
ASSERT_EQ("0,1", FilesPerLevel());
|
||||
#endif // !ROCKSDB_LITE
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Should be able to write kTypeBlobIndex to memtables and SST files.
|
||||
TEST_F(DBBlobIndexTest, Write) {
|
||||
for (auto tier : kAllTiers) {
|
||||
DestroyAndReopen(GetTestOptions());
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
std::string index = ToString(i);
|
||||
WriteBatch batch;
|
||||
ASSERT_OK(PutBlobIndex(&batch, "key" + index, "blob" + index));
|
||||
ASSERT_OK(Write(&batch));
|
||||
}
|
||||
MoveDataTo(tier);
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
std::string index = ToString(i);
|
||||
ASSERT_EQ("blob" + index, GetBlobIndex("key" + index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get should be able to return blob index if is_blob_index is provided,
|
||||
// otherwise return Status::NotSupported status.
|
||||
TEST_F(DBBlobIndexTest, Get) {
|
||||
for (auto tier : kAllTiers) {
|
||||
DestroyAndReopen(GetTestOptions());
|
||||
WriteBatch batch;
|
||||
ASSERT_OK(batch.Put("key", "value"));
|
||||
ASSERT_OK(PutBlobIndex(&batch, "blob_key", "blob_index"));
|
||||
ASSERT_OK(Write(&batch));
|
||||
MoveDataTo(tier);
|
||||
// Verify normal value
|
||||
bool is_blob_index = false;
|
||||
PinnableSlice value;
|
||||
ASSERT_EQ("value", Get("key"));
|
||||
ASSERT_EQ("value", GetImpl("key"));
|
||||
ASSERT_EQ("value", GetImpl("key", &is_blob_index));
|
||||
ASSERT_FALSE(is_blob_index);
|
||||
// Verify blob index
|
||||
ASSERT_TRUE(Get("blob_key", &value).IsNotSupported());
|
||||
ASSERT_EQ("NOT_SUPPORTED", GetImpl("blob_key"));
|
||||
ASSERT_EQ("blob_index", GetImpl("blob_key", &is_blob_index));
|
||||
ASSERT_TRUE(is_blob_index);
|
||||
}
|
||||
}
|
||||
|
||||
// Get should NOT return Status::NotSupported if blob index is updated with
|
||||
// a normal value.
|
||||
TEST_F(DBBlobIndexTest, Updated) {
|
||||
for (auto tier : kAllTiers) {
|
||||
DestroyAndReopen(GetTestOptions());
|
||||
WriteBatch batch;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
ASSERT_OK(PutBlobIndex(&batch, "key" + ToString(i), "blob_index"));
|
||||
}
|
||||
ASSERT_OK(Write(&batch));
|
||||
// Avoid blob values from being purged.
|
||||
const Snapshot* snapshot = dbfull()->GetSnapshot();
|
||||
ASSERT_OK(Put("key1", "new_value"));
|
||||
ASSERT_OK(Merge("key2", "a"));
|
||||
ASSERT_OK(Merge("key2", "b"));
|
||||
ASSERT_OK(Merge("key2", "c"));
|
||||
ASSERT_OK(Delete("key3"));
|
||||
ASSERT_OK(SingleDelete("key4"));
|
||||
ASSERT_OK(Delete("key5"));
|
||||
ASSERT_OK(Merge("key5", "a"));
|
||||
ASSERT_OK(Merge("key5", "b"));
|
||||
ASSERT_OK(Merge("key5", "c"));
|
||||
ASSERT_OK(dbfull()->DeleteRange(WriteOptions(), cfh(), "key6", "key9"));
|
||||
MoveDataTo(tier);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
ASSERT_EQ("blob_index", GetBlobIndex("key" + ToString(i), snapshot));
|
||||
}
|
||||
ASSERT_EQ("new_value", Get("key1"));
|
||||
ASSERT_EQ("NOT_SUPPORTED", GetImpl("key2"));
|
||||
ASSERT_EQ("NOT_FOUND", Get("key3"));
|
||||
ASSERT_EQ("NOT_FOUND", Get("key4"));
|
||||
ASSERT_EQ("a,b,c", GetImpl("key5"));
|
||||
for (int i = 6; i < 9; i++) {
|
||||
ASSERT_EQ("NOT_FOUND", Get("key" + ToString(i)));
|
||||
}
|
||||
ASSERT_EQ("blob_index", GetBlobIndex("key9"));
|
||||
dbfull()->ReleaseSnapshot(snapshot);
|
||||
}
|
||||
}
|
||||
|
||||
// Iterator should get blob value if allow_blob flag is set,
|
||||
// otherwise return Status::NotSupported status.
|
||||
TEST_F(DBBlobIndexTest, Iterate) {
|
||||
const std::vector<std::vector<ValueType>> data = {
|
||||
/*00*/ {kTypeValue},
|
||||
/*01*/ {kTypeBlobIndex},
|
||||
/*02*/ {kTypeValue},
|
||||
/*03*/ {kTypeBlobIndex, kTypeValue},
|
||||
/*04*/ {kTypeValue},
|
||||
/*05*/ {kTypeValue, kTypeBlobIndex},
|
||||
/*06*/ {kTypeValue},
|
||||
/*07*/ {kTypeDeletion, kTypeBlobIndex},
|
||||
/*08*/ {kTypeValue},
|
||||
/*09*/ {kTypeSingleDeletion, kTypeBlobIndex},
|
||||
/*10*/ {kTypeValue},
|
||||
/*11*/ {kTypeMerge, kTypeMerge, kTypeMerge, kTypeBlobIndex},
|
||||
/*12*/ {kTypeValue},
|
||||
/*13*/
|
||||
{kTypeMerge, kTypeMerge, kTypeMerge, kTypeDeletion, kTypeBlobIndex},
|
||||
/*14*/ {kTypeValue},
|
||||
/*15*/ {kTypeBlobIndex},
|
||||
/*16*/ {kTypeValue},
|
||||
};
|
||||
|
||||
auto get_key = [](int index) {
|
||||
char buf[20];
|
||||
snprintf(buf, sizeof(buf), "%02d", index);
|
||||
return "key" + std::string(buf);
|
||||
};
|
||||
|
||||
auto get_value = [&](int index, int version) {
|
||||
return get_key(index) + "_value" + ToString(version);
|
||||
};
|
||||
|
||||
auto check_iterator = [&](Iterator* iterator, Status::Code expected_status,
|
||||
const Slice& expected_value) {
|
||||
ASSERT_EQ(expected_status, iterator->status().code());
|
||||
if (expected_status == Status::kOk) {
|
||||
ASSERT_TRUE(iterator->Valid());
|
||||
ASSERT_EQ(expected_value, iterator->value());
|
||||
} else {
|
||||
ASSERT_FALSE(iterator->Valid());
|
||||
}
|
||||
};
|
||||
|
||||
auto create_normal_iterator = [&]() -> Iterator* {
|
||||
return dbfull()->NewIterator(ReadOptions());
|
||||
};
|
||||
|
||||
auto create_blob_iterator = [&]() -> Iterator* { return GetBlobIterator(); };
|
||||
|
||||
auto check_is_blob = [&](bool is_blob) {
|
||||
return [is_blob](Iterator* iterator) {
|
||||
ASSERT_EQ(is_blob,
|
||||
reinterpret_cast<ArenaWrappedDBIter*>(iterator)->IsBlob());
|
||||
};
|
||||
};
|
||||
|
||||
auto verify = [&](int index, Status::Code expected_status,
|
||||
const Slice& forward_value, const Slice& backward_value,
|
||||
std::function<Iterator*()> create_iterator,
|
||||
std::function<void(Iterator*)> extra_check = nullptr) {
|
||||
// Seek
|
||||
auto* iterator = create_iterator();
|
||||
ASSERT_OK(iterator->Refresh());
|
||||
iterator->Seek(get_key(index));
|
||||
check_iterator(iterator, expected_status, forward_value);
|
||||
if (extra_check) {
|
||||
extra_check(iterator);
|
||||
}
|
||||
delete iterator;
|
||||
|
||||
// Next
|
||||
iterator = create_iterator();
|
||||
ASSERT_OK(iterator->Refresh());
|
||||
iterator->Seek(get_key(index - 1));
|
||||
ASSERT_TRUE(iterator->Valid());
|
||||
iterator->Next();
|
||||
check_iterator(iterator, expected_status, forward_value);
|
||||
if (extra_check) {
|
||||
extra_check(iterator);
|
||||
}
|
||||
delete iterator;
|
||||
|
||||
// SeekForPrev
|
||||
iterator = create_iterator();
|
||||
ASSERT_OK(iterator->Refresh());
|
||||
iterator->SeekForPrev(get_key(index));
|
||||
check_iterator(iterator, expected_status, backward_value);
|
||||
if (extra_check) {
|
||||
extra_check(iterator);
|
||||
}
|
||||
delete iterator;
|
||||
|
||||
// Prev
|
||||
iterator = create_iterator();
|
||||
iterator->Seek(get_key(index + 1));
|
||||
ASSERT_TRUE(iterator->Valid());
|
||||
iterator->Prev();
|
||||
check_iterator(iterator, expected_status, backward_value);
|
||||
if (extra_check) {
|
||||
extra_check(iterator);
|
||||
}
|
||||
delete iterator;
|
||||
};
|
||||
|
||||
for (auto tier : {Tier::kMemtable} /*kAllTiers*/) {
|
||||
// Avoid values from being purged.
|
||||
std::vector<const Snapshot*> snapshots;
|
||||
DestroyAndReopen(GetTestOptions());
|
||||
|
||||
// fill data
|
||||
for (int i = 0; i < static_cast<int>(data.size()); i++) {
|
||||
for (int j = static_cast<int>(data[i].size()) - 1; j >= 0; j--) {
|
||||
std::string key = get_key(i);
|
||||
std::string value = get_value(i, j);
|
||||
WriteBatch batch;
|
||||
switch (data[i][j]) {
|
||||
case kTypeValue:
|
||||
ASSERT_OK(Put(key, value));
|
||||
break;
|
||||
case kTypeDeletion:
|
||||
ASSERT_OK(Delete(key));
|
||||
break;
|
||||
case kTypeSingleDeletion:
|
||||
ASSERT_OK(SingleDelete(key));
|
||||
break;
|
||||
case kTypeMerge:
|
||||
ASSERT_OK(Merge(key, value));
|
||||
break;
|
||||
case kTypeBlobIndex:
|
||||
ASSERT_OK(PutBlobIndex(&batch, key, value));
|
||||
ASSERT_OK(Write(&batch));
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
};
|
||||
}
|
||||
snapshots.push_back(dbfull()->GetSnapshot());
|
||||
}
|
||||
ASSERT_OK(
|
||||
dbfull()->DeleteRange(WriteOptions(), cfh(), get_key(15), get_key(16)));
|
||||
snapshots.push_back(dbfull()->GetSnapshot());
|
||||
MoveDataTo(tier);
|
||||
|
||||
// Normal iterator
|
||||
verify(1, Status::kNotSupported, "", "", create_normal_iterator);
|
||||
verify(3, Status::kNotSupported, "", "", create_normal_iterator);
|
||||
verify(5, Status::kOk, get_value(5, 0), get_value(5, 0),
|
||||
create_normal_iterator);
|
||||
verify(7, Status::kOk, get_value(8, 0), get_value(6, 0),
|
||||
create_normal_iterator);
|
||||
verify(9, Status::kOk, get_value(10, 0), get_value(8, 0),
|
||||
create_normal_iterator);
|
||||
verify(11, Status::kNotSupported, "", "", create_normal_iterator);
|
||||
verify(13, Status::kOk,
|
||||
get_value(13, 2) + "," + get_value(13, 1) + "," + get_value(13, 0),
|
||||
get_value(13, 2) + "," + get_value(13, 1) + "," + get_value(13, 0),
|
||||
create_normal_iterator);
|
||||
verify(15, Status::kOk, get_value(16, 0), get_value(14, 0),
|
||||
create_normal_iterator);
|
||||
|
||||
// Iterator with blob support
|
||||
verify(1, Status::kOk, get_value(1, 0), get_value(1, 0),
|
||||
create_blob_iterator, check_is_blob(true));
|
||||
verify(3, Status::kOk, get_value(3, 0), get_value(3, 0),
|
||||
create_blob_iterator, check_is_blob(true));
|
||||
verify(5, Status::kOk, get_value(5, 0), get_value(5, 0),
|
||||
create_blob_iterator, check_is_blob(false));
|
||||
verify(7, Status::kOk, get_value(8, 0), get_value(6, 0),
|
||||
create_blob_iterator, check_is_blob(false));
|
||||
verify(9, Status::kOk, get_value(10, 0), get_value(8, 0),
|
||||
create_blob_iterator, check_is_blob(false));
|
||||
verify(11, Status::kNotSupported, "", "", create_blob_iterator);
|
||||
verify(13, Status::kOk,
|
||||
get_value(13, 2) + "," + get_value(13, 1) + "," + get_value(13, 0),
|
||||
get_value(13, 2) + "," + get_value(13, 1) + "," + get_value(13, 0),
|
||||
create_blob_iterator, check_is_blob(false));
|
||||
verify(15, Status::kOk, get_value(16, 0), get_value(14, 0),
|
||||
create_blob_iterator, check_is_blob(false));
|
||||
|
||||
for (auto* snapshot : snapshots) {
|
||||
dbfull()->ReleaseSnapshot(snapshot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
rocksdb::port::InstallStackTraceHandler();
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -497,7 +497,7 @@ TEST_F(DBBlockCacheTest, CompressedCache) {
|
||||
options.compression = kNoCompression;
|
||||
break;
|
||||
default:
|
||||
FAIL();
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
CreateAndReopenWithCF({"pikachu"}, options);
|
||||
// default column family doesn't have block cache
|
||||
@@ -560,7 +560,7 @@ TEST_F(DBBlockCacheTest, CompressedCache) {
|
||||
ASSERT_EQ(TestGetTickerCount(options, BLOCK_CACHE_COMPRESSED_HIT), 0);
|
||||
break;
|
||||
default:
|
||||
FAIL();
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
|
||||
options.create_if_missing = true;
|
||||
|
||||
+42
-25
@@ -686,12 +686,12 @@ class BloomStatsTestWithParam
|
||||
}
|
||||
options_.env = env_;
|
||||
|
||||
get_perf_context()->Reset();
|
||||
perf_context.Reset();
|
||||
DestroyAndReopen(options_);
|
||||
}
|
||||
|
||||
~BloomStatsTestWithParam() {
|
||||
get_perf_context()->Reset();
|
||||
perf_context.Reset();
|
||||
Destroy(options_);
|
||||
}
|
||||
|
||||
@@ -724,33 +724,33 @@ TEST_P(BloomStatsTestWithParam, BloomStatsTest) {
|
||||
|
||||
// check memtable bloom stats
|
||||
ASSERT_EQ(value1, Get(key1));
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_memtable_hit_count);
|
||||
ASSERT_EQ(1, perf_context.bloom_memtable_hit_count);
|
||||
ASSERT_EQ(value3, Get(key3));
|
||||
ASSERT_EQ(2, get_perf_context()->bloom_memtable_hit_count);
|
||||
ASSERT_EQ(0, get_perf_context()->bloom_memtable_miss_count);
|
||||
ASSERT_EQ(2, perf_context.bloom_memtable_hit_count);
|
||||
ASSERT_EQ(0, perf_context.bloom_memtable_miss_count);
|
||||
|
||||
ASSERT_EQ("NOT_FOUND", Get(key2));
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_memtable_miss_count);
|
||||
ASSERT_EQ(2, get_perf_context()->bloom_memtable_hit_count);
|
||||
ASSERT_EQ(1, perf_context.bloom_memtable_miss_count);
|
||||
ASSERT_EQ(2, perf_context.bloom_memtable_hit_count);
|
||||
|
||||
// sanity checks
|
||||
ASSERT_EQ(0, get_perf_context()->bloom_sst_hit_count);
|
||||
ASSERT_EQ(0, get_perf_context()->bloom_sst_miss_count);
|
||||
ASSERT_EQ(0, perf_context.bloom_sst_hit_count);
|
||||
ASSERT_EQ(0, perf_context.bloom_sst_miss_count);
|
||||
|
||||
Flush();
|
||||
|
||||
// sanity checks
|
||||
ASSERT_EQ(0, get_perf_context()->bloom_sst_hit_count);
|
||||
ASSERT_EQ(0, get_perf_context()->bloom_sst_miss_count);
|
||||
ASSERT_EQ(0, perf_context.bloom_sst_hit_count);
|
||||
ASSERT_EQ(0, perf_context.bloom_sst_miss_count);
|
||||
|
||||
// check SST bloom stats
|
||||
ASSERT_EQ(value1, Get(key1));
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_sst_hit_count);
|
||||
ASSERT_EQ(1, perf_context.bloom_sst_hit_count);
|
||||
ASSERT_EQ(value3, Get(key3));
|
||||
ASSERT_EQ(2, get_perf_context()->bloom_sst_hit_count);
|
||||
ASSERT_EQ(2, perf_context.bloom_sst_hit_count);
|
||||
|
||||
ASSERT_EQ("NOT_FOUND", Get(key2));
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_sst_miss_count);
|
||||
ASSERT_EQ(1, perf_context.bloom_sst_miss_count);
|
||||
}
|
||||
|
||||
// Same scenario as in BloomStatsTest but using an iterator
|
||||
@@ -771,21 +771,21 @@ TEST_P(BloomStatsTestWithParam, BloomStatsTestWithIter) {
|
||||
ASSERT_OK(iter->status());
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(value1, iter->value().ToString());
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_memtable_hit_count);
|
||||
ASSERT_EQ(0, get_perf_context()->bloom_memtable_miss_count);
|
||||
ASSERT_EQ(1, perf_context.bloom_memtable_hit_count);
|
||||
ASSERT_EQ(0, perf_context.bloom_memtable_miss_count);
|
||||
|
||||
iter->Seek(key3);
|
||||
ASSERT_OK(iter->status());
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(value3, iter->value().ToString());
|
||||
ASSERT_EQ(2, get_perf_context()->bloom_memtable_hit_count);
|
||||
ASSERT_EQ(0, get_perf_context()->bloom_memtable_miss_count);
|
||||
ASSERT_EQ(2, perf_context.bloom_memtable_hit_count);
|
||||
ASSERT_EQ(0, perf_context.bloom_memtable_miss_count);
|
||||
|
||||
iter->Seek(key2);
|
||||
ASSERT_OK(iter->status());
|
||||
ASSERT_TRUE(!iter->Valid());
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_memtable_miss_count);
|
||||
ASSERT_EQ(2, get_perf_context()->bloom_memtable_hit_count);
|
||||
ASSERT_EQ(1, perf_context.bloom_memtable_miss_count);
|
||||
ASSERT_EQ(2, perf_context.bloom_memtable_hit_count);
|
||||
|
||||
Flush();
|
||||
|
||||
@@ -796,19 +796,36 @@ TEST_P(BloomStatsTestWithParam, BloomStatsTestWithIter) {
|
||||
ASSERT_OK(iter->status());
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(value1, iter->value().ToString());
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_sst_hit_count);
|
||||
if (partition_filters_) {
|
||||
ASSERT_EQ(0, perf_context.bloom_sst_hit_count); // no_io
|
||||
ASSERT_EQ(0, perf_context.bloom_sst_miss_count); // no_io
|
||||
} else {
|
||||
ASSERT_EQ(1, perf_context.bloom_sst_hit_count);
|
||||
}
|
||||
|
||||
iter->Seek(key3);
|
||||
ASSERT_OK(iter->status());
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(value3, iter->value().ToString());
|
||||
ASSERT_EQ(2, get_perf_context()->bloom_sst_hit_count);
|
||||
if (partition_filters_) {
|
||||
ASSERT_EQ(0, perf_context.bloom_sst_hit_count); // no_io
|
||||
ASSERT_EQ(0, perf_context.bloom_sst_miss_count); // no_io
|
||||
} else {
|
||||
ASSERT_EQ(2, perf_context.bloom_sst_hit_count);
|
||||
}
|
||||
|
||||
iter->Seek(key2);
|
||||
ASSERT_OK(iter->status());
|
||||
ASSERT_TRUE(!iter->Valid());
|
||||
ASSERT_EQ(1, get_perf_context()->bloom_sst_miss_count);
|
||||
ASSERT_EQ(2, get_perf_context()->bloom_sst_hit_count);
|
||||
if (partition_filters_) {
|
||||
// iter is still valid since filter did not reject the key2
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(0, perf_context.bloom_sst_hit_count); // no_io
|
||||
ASSERT_EQ(0, perf_context.bloom_sst_miss_count); // no_io
|
||||
} else {
|
||||
ASSERT_TRUE(!iter->Valid());
|
||||
ASSERT_EQ(1, perf_context.bloom_sst_miss_count);
|
||||
ASSERT_EQ(2, perf_context.bloom_sst_hit_count);
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(BloomStatsTestWithParam, BloomStatsTestWithParam,
|
||||
|
||||
@@ -626,7 +626,7 @@ TEST_F(DBTestCompactionFilter, CompactionFilterContextManual) {
|
||||
iter->Next();
|
||||
}
|
||||
ASSERT_EQ(total, 700);
|
||||
ASSERT_EQ(count, 1);
|
||||
ASSERT_EQ(count, 2);
|
||||
}
|
||||
}
|
||||
#endif // ROCKSDB_LITE
|
||||
@@ -778,7 +778,7 @@ TEST_F(DBTestCompactionFilter, SkipUntil) {
|
||||
|
||||
cfilter_skips = 0;
|
||||
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||
// Number of skips in tables: 2, 3, 3, 3.
|
||||
// Numberof skips in tables: 2, 3, 3, 3.
|
||||
ASSERT_EQ(11, cfilter_skips);
|
||||
|
||||
for (int table = 0; table < 4; ++table) {
|
||||
@@ -799,43 +799,6 @@ TEST_F(DBTestCompactionFilter, SkipUntil) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DBTestCompactionFilter, SkipUntilWithBloomFilter) {
|
||||
BlockBasedTableOptions table_options;
|
||||
table_options.whole_key_filtering = false;
|
||||
table_options.filter_policy.reset(NewBloomFilterPolicy(100, false));
|
||||
|
||||
Options options = CurrentOptions();
|
||||
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
|
||||
options.prefix_extractor.reset(NewCappedPrefixTransform(9));
|
||||
options.compaction_filter_factory = std::make_shared<SkipEvenFilterFactory>();
|
||||
options.disable_auto_compactions = true;
|
||||
options.create_if_missing = true;
|
||||
DestroyAndReopen(options);
|
||||
|
||||
Put("0000000010", "v10");
|
||||
Put("0000000020", "v20"); // skipped
|
||||
Put("0000000050", "v50");
|
||||
Flush();
|
||||
|
||||
cfilter_skips = 0;
|
||||
EXPECT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||
EXPECT_EQ(1, cfilter_skips);
|
||||
|
||||
Status s;
|
||||
std::string val;
|
||||
|
||||
s = db_->Get(ReadOptions(), "0000000010", &val);
|
||||
ASSERT_OK(s);
|
||||
EXPECT_EQ("v10", val);
|
||||
|
||||
s = db_->Get(ReadOptions(), "0000000020", &val);
|
||||
EXPECT_TRUE(s.IsNotFound());
|
||||
|
||||
s = db_->Get(ReadOptions(), "0000000050", &val);
|
||||
ASSERT_OK(s);
|
||||
EXPECT_EQ("v50", val);
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
+7
-100
@@ -519,6 +519,7 @@ TEST_F(DBCompactionTest, BGCompactionsAllowed) {
|
||||
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));
|
||||
|
||||
@@ -1192,8 +1193,7 @@ TEST_P(DBCompactionTestWithParam, ManualCompactionPartial) {
|
||||
}
|
||||
}
|
||||
|
||||
// Disable as the test is flaky.
|
||||
TEST_F(DBCompactionTest, DISABLED_ManualPartialFill) {
|
||||
TEST_F(DBCompactionTest, ManualPartialFill) {
|
||||
int32_t trivial_move = 0;
|
||||
int32_t non_trivial_move = 0;
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
@@ -1227,9 +1227,6 @@ TEST_F(DBCompactionTest, DISABLED_ManualPartialFill) {
|
||||
options.max_background_compactions = 3;
|
||||
|
||||
DestroyAndReopen(options);
|
||||
// make sure all background compaction jobs can be scheduled
|
||||
auto stop_token =
|
||||
dbfull()->TEST_write_controler().GetCompactionPressureToken();
|
||||
int32_t value_size = 10 * 1024; // 10 KB
|
||||
|
||||
// Add 2 non-overlapping files
|
||||
@@ -1439,60 +1436,6 @@ TEST_F(DBCompactionTest, DeleteFileRange) {
|
||||
ASSERT_GT(old_num_files, new_num_files);
|
||||
}
|
||||
|
||||
TEST_F(DBCompactionTest, DeleteFileRangeFileEndpointsOverlapBug) {
|
||||
// regression test for #2833: groups of files whose user-keys overlap at the
|
||||
// endpoints could be split by `DeleteFilesInRange`. This caused old data to
|
||||
// reappear, either because a new version of the key was removed, or a range
|
||||
// deletion was partially dropped. It could also cause non-overlapping
|
||||
// invariant to be violated if the files dropped by DeleteFilesInRange were
|
||||
// a subset of files that a range deletion spans.
|
||||
const int kNumL0Files = 2;
|
||||
const int kValSize = 8 << 10; // 8KB
|
||||
Options options = CurrentOptions();
|
||||
options.level0_file_num_compaction_trigger = kNumL0Files;
|
||||
options.target_file_size_base = 1 << 10; // 1KB
|
||||
DestroyAndReopen(options);
|
||||
|
||||
// The snapshot prevents key 1 from having its old version dropped. The low
|
||||
// `target_file_size_base` ensures two keys will be in each output file.
|
||||
const Snapshot* snapshot = nullptr;
|
||||
Random rnd(301);
|
||||
// The value indicates which flush the key belonged to, which is enough
|
||||
// for us to determine the keys' relative ages. After L0 flushes finish,
|
||||
// files look like:
|
||||
//
|
||||
// File 0: 0 -> vals[0], 1 -> vals[0]
|
||||
// File 1: 1 -> vals[1], 2 -> vals[1]
|
||||
//
|
||||
// Then L0->L1 compaction happens, which outputs keys as follows:
|
||||
//
|
||||
// File 0: 0 -> vals[0], 1 -> vals[1]
|
||||
// File 1: 1 -> vals[0], 2 -> vals[1]
|
||||
//
|
||||
// DeleteFilesInRange shouldn't be allowed to drop just file 0, as that
|
||||
// would cause `1 -> vals[0]` (an older key) to reappear.
|
||||
std::string vals[kNumL0Files];
|
||||
for (int i = 0; i < kNumL0Files; ++i) {
|
||||
vals[i] = RandomString(&rnd, kValSize);
|
||||
Put(Key(i), vals[i]);
|
||||
Put(Key(i + 1), vals[i]);
|
||||
Flush();
|
||||
if (i == 0) {
|
||||
snapshot = db_->GetSnapshot();
|
||||
}
|
||||
}
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
|
||||
// Verify `DeleteFilesInRange` can't drop only file 0 which would cause
|
||||
// "1 -> vals[0]" to reappear.
|
||||
Slice begin = Key(0);
|
||||
Slice end = Key(1);
|
||||
ASSERT_OK(DeleteFilesInRange(db_, db_->DefaultColumnFamily(), &begin, &end));
|
||||
ASSERT_EQ(vals[1], Get(Key(1)));
|
||||
|
||||
db_->ReleaseSnapshot(snapshot);
|
||||
}
|
||||
|
||||
TEST_P(DBCompactionTestWithParam, TrivialMoveToLastLevelWithFiles) {
|
||||
int32_t trivial_move = 0;
|
||||
int32_t non_trivial_move = 0;
|
||||
@@ -1971,7 +1914,7 @@ TEST_F(DBCompactionTest, ManualAutoRace) {
|
||||
|
||||
// The auto compaction is scheduled but waited until here
|
||||
TEST_SYNC_POINT("DBCompactionTest::ManualAutoRace:1");
|
||||
// The auto compaction will wait until the manual compaction is registerd
|
||||
// The auto compaction will wait until the the manual compaction is registerd
|
||||
// before processing so that it will be cancelled.
|
||||
dbfull()->CompactRange(CompactRangeOptions(), handles_[1], nullptr, nullptr);
|
||||
ASSERT_EQ("0,1", FilesPerLevel(1));
|
||||
@@ -2031,6 +1974,7 @@ TEST_P(DBCompactionTestWithParam, ManualCompaction) {
|
||||
|
||||
if (iter == 0) {
|
||||
options = CurrentOptions();
|
||||
options.max_background_flushes = 0;
|
||||
options.num_levels = 3;
|
||||
options.create_if_missing = true;
|
||||
options.statistics = rocksdb::CreateDBStatistics();
|
||||
@@ -2476,12 +2420,15 @@ TEST_F(DBCompactionTest, SanitizeCompactionOptionsTest) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -2738,46 +2685,6 @@ TEST_P(DBCompactionTestWithParam, IntraL0CompactionDoesNotObsoleteDeletions) {
|
||||
ASSERT_TRUE(db_->Get(roptions, Key(0), &result).IsNotFound());
|
||||
}
|
||||
|
||||
TEST_F(DBCompactionTest, OptimizedDeletionObsoleting) {
|
||||
// Deletions can be dropped when compacted to non-last level if they fall
|
||||
// outside the lower-level files' key-ranges.
|
||||
const int kNumL0Files = 4;
|
||||
Options options = CurrentOptions();
|
||||
options.level0_file_num_compaction_trigger = kNumL0Files;
|
||||
options.statistics = rocksdb::CreateDBStatistics();
|
||||
DestroyAndReopen(options);
|
||||
|
||||
// put key 1 and 3 in separate L1, L2 files.
|
||||
// So key 0, 2, and 4+ fall outside these levels' key-ranges.
|
||||
for (int level = 2; level >= 1; --level) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
Put(Key(2 * i + 1), "val");
|
||||
Flush();
|
||||
}
|
||||
MoveFilesToLevel(level);
|
||||
ASSERT_EQ(2, NumTableFilesAtLevel(level));
|
||||
}
|
||||
|
||||
// Delete keys in range [1, 4]. These L0 files will be compacted with L1:
|
||||
// - Tombstones for keys 2 and 4 can be dropped early.
|
||||
// - Tombstones for keys 1 and 3 must be kept due to L2 files' key-ranges.
|
||||
for (int i = 0; i < kNumL0Files; ++i) {
|
||||
Put(Key(0), "val"); // sentinel to prevent trivial move
|
||||
Delete(Key(i + 1));
|
||||
Flush();
|
||||
}
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
|
||||
for (int i = 0; i < kNumL0Files; ++i) {
|
||||
std::string value;
|
||||
ASSERT_TRUE(db_->Get(ReadOptions(), Key(i + 1), &value).IsNotFound());
|
||||
}
|
||||
ASSERT_EQ(2, options.statistics->getTickerCount(
|
||||
COMPACTION_OPTIMIZED_DEL_DROP_OBSOLETE));
|
||||
ASSERT_EQ(2,
|
||||
options.statistics->getTickerCount(COMPACTION_KEY_DROP_OBSOLETE));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(DBCompactionTestWithParam, DBCompactionTestWithParam,
|
||||
::testing::Values(std::make_tuple(1, true),
|
||||
std::make_tuple(1, false),
|
||||
|
||||
@@ -57,6 +57,7 @@ TEST_F(DBTestDynamicLevel, DynamicLevelMaxBytesBase) {
|
||||
Options options;
|
||||
options.env = env.get();
|
||||
options.create_if_missing = true;
|
||||
options.db_write_buffer_size = 2048;
|
||||
options.write_buffer_size = 2048;
|
||||
options.max_write_buffer_number = 2;
|
||||
options.level0_file_num_compaction_trigger = 2;
|
||||
@@ -126,6 +127,7 @@ TEST_F(DBTestDynamicLevel, DynamicLevelMaxBytesBase2) {
|
||||
|
||||
Options options = CurrentOptions();
|
||||
options.create_if_missing = true;
|
||||
options.db_write_buffer_size = 204800;
|
||||
options.write_buffer_size = 20480;
|
||||
options.max_write_buffer_number = 2;
|
||||
options.level0_file_num_compaction_trigger = 2;
|
||||
@@ -282,6 +284,7 @@ TEST_F(DBTestDynamicLevel, DynamicLevelMaxBytesCompactRange) {
|
||||
|
||||
Options options = CurrentOptions();
|
||||
options.create_if_missing = true;
|
||||
options.db_write_buffer_size = 2048;
|
||||
options.write_buffer_size = 2048;
|
||||
options.max_write_buffer_number = 2;
|
||||
options.level0_file_num_compaction_trigger = 2;
|
||||
@@ -359,6 +362,7 @@ TEST_F(DBTestDynamicLevel, DynamicLevelMaxBytesCompactRange) {
|
||||
TEST_F(DBTestDynamicLevel, DynamicLevelMaxBytesBaseInc) {
|
||||
Options options = CurrentOptions();
|
||||
options.create_if_missing = true;
|
||||
options.db_write_buffer_size = 2048;
|
||||
options.write_buffer_size = 2048;
|
||||
options.max_write_buffer_number = 2;
|
||||
options.level0_file_num_compaction_trigger = 2;
|
||||
@@ -371,7 +375,6 @@ TEST_F(DBTestDynamicLevel, DynamicLevelMaxBytesBaseInc) {
|
||||
options.soft_rate_limit = 1.1;
|
||||
options.max_background_compactions = 2;
|
||||
options.num_levels = 5;
|
||||
options.max_compaction_bytes = 100000000;
|
||||
|
||||
DestroyAndReopen(options);
|
||||
|
||||
@@ -411,6 +414,7 @@ TEST_F(DBTestDynamicLevel, DISABLED_MigrateToDynamicLevelMaxBytesBase) {
|
||||
|
||||
Options options;
|
||||
options.create_if_missing = true;
|
||||
options.db_write_buffer_size = 2048;
|
||||
options.write_buffer_size = 2048;
|
||||
options.max_write_buffer_number = 8;
|
||||
options.level0_file_num_compaction_trigger = 4;
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
//
|
||||
#include "db/db_test_util.h"
|
||||
#include "port/stack_trace.h"
|
||||
#include "rocksdb/perf_context.h"
|
||||
#if !defined(ROCKSDB_LITE)
|
||||
#include "util/sync_point.h"
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
class DBEncryptionTest : public DBTestBase {
|
||||
public:
|
||||
DBEncryptionTest() : DBTestBase("/db_encryption_test") {}
|
||||
};
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
|
||||
TEST_F(DBEncryptionTest, CheckEncrypted) {
|
||||
ASSERT_OK(Put("foo567", "v1.fetdq"));
|
||||
ASSERT_OK(Put("bar123", "v2.dfgkjdfghsd"));
|
||||
Close();
|
||||
|
||||
// Open all files and look for the values we've put in there.
|
||||
// They should not be found if encrypted, otherwise
|
||||
// they should be found.
|
||||
std::vector<std::string> fileNames;
|
||||
auto status = env_->GetChildren(dbname_, &fileNames);
|
||||
ASSERT_OK(status);
|
||||
|
||||
auto defaultEnv = Env::Default();
|
||||
int hits = 0;
|
||||
for (auto it = fileNames.begin() ; it != fileNames.end(); ++it) {
|
||||
if ((*it == "..") || (*it == ".")) {
|
||||
continue;
|
||||
}
|
||||
auto filePath = dbname_ + "/" + *it;
|
||||
unique_ptr<SequentialFile> seqFile;
|
||||
auto envOptions = EnvOptions(CurrentOptions());
|
||||
status = defaultEnv->NewSequentialFile(filePath, &seqFile, envOptions);
|
||||
ASSERT_OK(status);
|
||||
|
||||
uint64_t fileSize;
|
||||
status = defaultEnv->GetFileSize(filePath, &fileSize);
|
||||
ASSERT_OK(status);
|
||||
|
||||
std::string scratch;
|
||||
scratch.reserve(fileSize);
|
||||
Slice data;
|
||||
status = seqFile->Read(fileSize, &data, (char*)scratch.data());
|
||||
ASSERT_OK(status);
|
||||
|
||||
if (data.ToString().find("foo567") != std::string::npos) {
|
||||
hits++;
|
||||
//std::cout << "Hit in " << filePath << "\n";
|
||||
}
|
||||
if (data.ToString().find("v1.fetdq") != std::string::npos) {
|
||||
hits++;
|
||||
//std::cout << "Hit in " << filePath << "\n";
|
||||
}
|
||||
if (data.ToString().find("bar123") != std::string::npos) {
|
||||
hits++;
|
||||
//std::cout << "Hit in " << filePath << "\n";
|
||||
}
|
||||
if (data.ToString().find("v2.dfgkjdfghsd") != std::string::npos) {
|
||||
hits++;
|
||||
//std::cout << "Hit in " << filePath << "\n";
|
||||
}
|
||||
if (data.ToString().find("dfgk") != std::string::npos) {
|
||||
hits++;
|
||||
//std::cout << "Hit in " << filePath << "\n";
|
||||
}
|
||||
}
|
||||
if (encrypted_env_) {
|
||||
ASSERT_EQ(hits, 0);
|
||||
} else {
|
||||
ASSERT_GE(hits, 4);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ROCKSDB_LITE
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
rocksdb::port::InstallStackTraceHandler();
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -89,43 +89,6 @@ TEST_F(DBFlushTest, SyncFail) {
|
||||
Destroy(options);
|
||||
}
|
||||
|
||||
TEST_F(DBFlushTest, FlushInLowPriThreadPool) {
|
||||
// Verify setting an empty high-pri (flush) thread pool causes flushes to be
|
||||
// scheduled in the low-pri (compaction) thread pool.
|
||||
Options options = CurrentOptions();
|
||||
options.level0_file_num_compaction_trigger = 4;
|
||||
options.memtable_factory.reset(new SpecialSkipListFactory(1));
|
||||
Reopen(options);
|
||||
env_->SetBackgroundThreads(0, Env::HIGH);
|
||||
|
||||
std::thread::id tid;
|
||||
int num_flushes = 0, num_compactions = 0;
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"DBImpl::BGWorkFlush", [&](void* arg) {
|
||||
if (tid == std::thread::id()) {
|
||||
tid = std::this_thread::get_id();
|
||||
} else {
|
||||
ASSERT_EQ(tid, std::this_thread::get_id());
|
||||
}
|
||||
++num_flushes;
|
||||
});
|
||||
SyncPoint::GetInstance()->SetCallBack(
|
||||
"DBImpl::BGWorkCompaction", [&](void* arg) {
|
||||
ASSERT_EQ(tid, std::this_thread::get_id());
|
||||
++num_compactions;
|
||||
});
|
||||
SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
ASSERT_OK(Put("key", "val"));
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
ASSERT_OK(Put("key", "val"));
|
||||
dbfull()->TEST_WaitForFlushMemTable();
|
||||
}
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
ASSERT_EQ(4, num_flushes);
|
||||
ASSERT_EQ(1, num_compactions);
|
||||
}
|
||||
|
||||
TEST_P(DBFlushDirectIOTest, DirectIO) {
|
||||
Options options;
|
||||
options.create_if_missing = true;
|
||||
|
||||
+168
-245
@@ -16,6 +16,9 @@
|
||||
#ifdef OS_SOLARIS
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
#ifdef ROCKSDB_JEMALLOC
|
||||
#include "jemalloc/jemalloc.h"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
@@ -41,7 +44,6 @@
|
||||
#include "db/job_context.h"
|
||||
#include "db/log_reader.h"
|
||||
#include "db/log_writer.h"
|
||||
#include "db/malloc_stats.h"
|
||||
#include "db/managed_iterator.h"
|
||||
#include "db/memtable.h"
|
||||
#include "db/memtable_list.h"
|
||||
@@ -67,7 +69,6 @@
|
||||
#include "port/port.h"
|
||||
#include "rocksdb/cache.h"
|
||||
#include "rocksdb/compaction_filter.h"
|
||||
#include "rocksdb/convenience.h"
|
||||
#include "rocksdb/db.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "rocksdb/merge_operator.h"
|
||||
@@ -81,7 +82,6 @@
|
||||
#include "table/merging_iterator.h"
|
||||
#include "table/table_builder.h"
|
||||
#include "table/two_level_iterator.h"
|
||||
#include "tools/sst_dump_tool_imp.h"
|
||||
#include "util/auto_roll_logger.h"
|
||||
#include "util/autovector.h"
|
||||
#include "util/build_version.h"
|
||||
@@ -134,8 +134,6 @@ void DumpSupportInfo(Logger* logger) {
|
||||
ROCKS_LOG_HEADER(logger, "Fast CRC32 supported: %d",
|
||||
crc32c::IsFastCrc32Supported());
|
||||
}
|
||||
|
||||
int64_t kDefaultLowPriThrottledRate = 2 * 1024 * 1024;
|
||||
} // namespace
|
||||
|
||||
DBImpl::DBImpl(const DBOptions& options, const std::string& dbname)
|
||||
@@ -159,18 +157,14 @@ DBImpl::DBImpl(const DBOptions& options, const std::string& dbname)
|
||||
max_total_in_memory_state_(0),
|
||||
is_snapshot_supported_(true),
|
||||
write_buffer_manager_(immutable_db_options_.write_buffer_manager.get()),
|
||||
write_thread_(immutable_db_options_),
|
||||
nonmem_write_thread_(immutable_db_options_),
|
||||
write_thread_(immutable_db_options_.enable_write_thread_adaptive_yield
|
||||
? immutable_db_options_.write_thread_max_yield_usec
|
||||
: 0,
|
||||
immutable_db_options_.write_thread_slow_yield_usec),
|
||||
write_controller_(mutable_db_options_.delayed_write_rate),
|
||||
// Use delayed_write_rate as a base line to determine the initial
|
||||
// low pri write rate limit. It may be adjusted later.
|
||||
low_pri_write_rate_limiter_(NewGenericRateLimiter(std::min(
|
||||
static_cast<int64_t>(mutable_db_options_.delayed_write_rate / 8),
|
||||
kDefaultLowPriThrottledRate))),
|
||||
last_batch_group_size_(0),
|
||||
unscheduled_flushes_(0),
|
||||
unscheduled_compactions_(0),
|
||||
bg_bottom_compaction_scheduled_(0),
|
||||
bg_compaction_scheduled_(0),
|
||||
num_running_compactions_(0),
|
||||
bg_flush_scheduled_(0),
|
||||
@@ -191,16 +185,14 @@ DBImpl::DBImpl(const DBOptions& options, const std::string& dbname)
|
||||
bg_work_paused_(0),
|
||||
bg_compaction_paused_(0),
|
||||
refitting_level_(false),
|
||||
opened_successfully_(false),
|
||||
concurrent_prepare_(options.concurrent_prepare),
|
||||
manual_wal_flush_(options.manual_wal_flush) {
|
||||
opened_successfully_(false) {
|
||||
env_->GetAbsolutePath(dbname, &db_absolute_path_);
|
||||
|
||||
// Reserve ten files or so for other uses and give the rest to TableCache.
|
||||
// Give a large number for setting of "infinite" open files.
|
||||
const int table_cache_size = (mutable_db_options_.max_open_files == -1)
|
||||
? TableCache::kInfiniteCapacity
|
||||
: mutable_db_options_.max_open_files - 10;
|
||||
const int table_cache_size = (immutable_db_options_.max_open_files == -1)
|
||||
? 4194304
|
||||
: immutable_db_options_.max_open_files - 10;
|
||||
table_cache_ = NewLRUCache(table_cache_size,
|
||||
immutable_db_options_.table_cache_numshardbits);
|
||||
|
||||
@@ -228,7 +220,7 @@ void DBImpl::CancelAllBackgroundWork(bool wait) {
|
||||
has_unpersisted_data_.load(std::memory_order_relaxed) &&
|
||||
!mutable_db_options_.avoid_flush_during_shutdown) {
|
||||
for (auto cfd : *versions_->GetColumnFamilySet()) {
|
||||
if (!cfd->IsDropped() && cfd->initialized() && !cfd->mem()->IsEmpty()) {
|
||||
if (!cfd->IsDropped() && !cfd->mem()->IsEmpty()) {
|
||||
cfd->Ref();
|
||||
mutex_.Unlock();
|
||||
FlushMemTable(cfd, FlushOptions());
|
||||
@@ -245,8 +237,7 @@ void DBImpl::CancelAllBackgroundWork(bool wait) {
|
||||
return;
|
||||
}
|
||||
// Wait for background work to finish
|
||||
while (bg_bottom_compaction_scheduled_ || bg_compaction_scheduled_ ||
|
||||
bg_flush_scheduled_) {
|
||||
while (bg_compaction_scheduled_ || bg_flush_scheduled_) {
|
||||
bg_cv_.Wait();
|
||||
}
|
||||
}
|
||||
@@ -256,18 +247,15 @@ DBImpl::~DBImpl() {
|
||||
// marker. After this we do a variant of the waiting and unschedule work
|
||||
// (to consider: moving all the waiting into CancelAllBackgroundWork(true))
|
||||
CancelAllBackgroundWork(false);
|
||||
int bottom_compactions_unscheduled =
|
||||
env_->UnSchedule(this, Env::Priority::BOTTOM);
|
||||
int compactions_unscheduled = env_->UnSchedule(this, Env::Priority::LOW);
|
||||
int flushes_unscheduled = env_->UnSchedule(this, Env::Priority::HIGH);
|
||||
mutex_.Lock();
|
||||
bg_bottom_compaction_scheduled_ -= bottom_compactions_unscheduled;
|
||||
bg_compaction_scheduled_ -= compactions_unscheduled;
|
||||
bg_flush_scheduled_ -= flushes_unscheduled;
|
||||
|
||||
// Wait for background work to finish
|
||||
while (bg_bottom_compaction_scheduled_ || bg_compaction_scheduled_ ||
|
||||
bg_flush_scheduled_ || bg_purge_scheduled_) {
|
||||
while (bg_compaction_scheduled_ || bg_flush_scheduled_ ||
|
||||
bg_purge_scheduled_) {
|
||||
TEST_SYNC_POINT("DBImpl::~DBImpl:WaitJob");
|
||||
bg_cv_.Wait();
|
||||
}
|
||||
@@ -383,6 +371,39 @@ void DBImpl::PrintStatistics() {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
#ifdef ROCKSDB_JEMALLOC
|
||||
typedef struct {
|
||||
char* cur;
|
||||
char* end;
|
||||
} MallocStatus;
|
||||
|
||||
static void GetJemallocStatus(void* mstat_arg, const char* status) {
|
||||
MallocStatus* mstat = reinterpret_cast<MallocStatus*>(mstat_arg);
|
||||
size_t status_len = status ? strlen(status) : 0;
|
||||
size_t buf_size = (size_t)(mstat->end - mstat->cur);
|
||||
if (!status_len || status_len > buf_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(mstat->cur, buf_size, "%s", status);
|
||||
mstat->cur += status_len;
|
||||
}
|
||||
#endif // ROCKSDB_JEMALLOC
|
||||
|
||||
static void DumpMallocStats(std::string* stats) {
|
||||
#ifdef ROCKSDB_JEMALLOC
|
||||
MallocStatus mstat;
|
||||
const unsigned int kMallocStatusLen = 1000000;
|
||||
std::unique_ptr<char[]> buf{new char[kMallocStatusLen + 1]};
|
||||
mstat.cur = buf.get();
|
||||
mstat.end = buf.get() + kMallocStatusLen;
|
||||
je_malloc_stats_print(GetJemallocStatus, &mstat, "");
|
||||
stats->append(buf.get());
|
||||
#endif // ROCKSDB_JEMALLOC
|
||||
}
|
||||
#endif // !ROCKSDB_LITE
|
||||
|
||||
void DBImpl::MaybeDumpStats() {
|
||||
mutex_.Lock();
|
||||
unsigned int stats_dump_period_sec =
|
||||
@@ -414,17 +435,12 @@ void DBImpl::MaybeDumpStats() {
|
||||
default_cf_internal_stats_->GetStringProperty(
|
||||
*db_property_info, DB::Properties::kDBStats, &stats);
|
||||
for (auto cfd : *versions_->GetColumnFamilySet()) {
|
||||
if (cfd->initialized()) {
|
||||
cfd->internal_stats()->GetStringProperty(
|
||||
*cf_property_info, DB::Properties::kCFStatsNoFileHistogram,
|
||||
&stats);
|
||||
}
|
||||
cfd->internal_stats()->GetStringProperty(
|
||||
*cf_property_info, DB::Properties::kCFStatsNoFileHistogram, &stats);
|
||||
}
|
||||
for (auto cfd : *versions_->GetColumnFamilySet()) {
|
||||
if (cfd->initialized()) {
|
||||
cfd->internal_stats()->GetStringProperty(
|
||||
*cf_property_info, DB::Properties::kCFFileHistogram, &stats);
|
||||
}
|
||||
cfd->internal_stats()->GetStringProperty(
|
||||
*cf_property_info, DB::Properties::kCFFileHistogram, &stats);
|
||||
}
|
||||
}
|
||||
ROCKS_LOG_WARN(immutable_db_options_.info_log,
|
||||
@@ -555,9 +571,6 @@ Status DBImpl::SetDBOptions(
|
||||
}
|
||||
|
||||
write_controller_.set_max_delayed_write_rate(new_options.delayed_write_rate);
|
||||
table_cache_.get()->SetCapacity(new_options.max_open_files == -1
|
||||
? TableCache::kInfiniteCapacity
|
||||
: new_options.max_open_files - 10);
|
||||
|
||||
mutable_db_options_ = new_options;
|
||||
|
||||
@@ -620,26 +633,6 @@ int DBImpl::FindMinimumEmptyLevelFitting(ColumnFamilyData* cfd,
|
||||
return minimum_level;
|
||||
}
|
||||
|
||||
Status DBImpl::FlushWAL(bool sync) {
|
||||
{
|
||||
// We need to lock log_write_mutex_ since logs_ might change concurrently
|
||||
InstrumentedMutexLock wl(&log_write_mutex_);
|
||||
log::Writer* cur_log_writer = logs_.back().writer;
|
||||
auto s = cur_log_writer->WriteBuffer();
|
||||
if (!s.ok()) {
|
||||
ROCKS_LOG_ERROR(immutable_db_options_.info_log, "WAL flush error %s",
|
||||
s.ToString().c_str());
|
||||
}
|
||||
if (!sync) {
|
||||
ROCKS_LOG_DEBUG(immutable_db_options_.info_log, "FlushWAL sync=false");
|
||||
return s;
|
||||
}
|
||||
}
|
||||
// sync = true
|
||||
ROCKS_LOG_DEBUG(immutable_db_options_.info_log, "FlushWAL sync=true");
|
||||
return SyncWAL();
|
||||
}
|
||||
|
||||
Status DBImpl::SyncWAL() {
|
||||
autovector<log::Writer*, 1> logs_to_sync;
|
||||
bool need_log_dir_sync;
|
||||
@@ -678,7 +671,6 @@ Status DBImpl::SyncWAL() {
|
||||
need_log_dir_sync = !log_dir_synced_;
|
||||
}
|
||||
|
||||
TEST_SYNC_POINT("DBWALTest::SyncWALNotWaitWrite:1");
|
||||
RecordTick(stats_, WAL_FILE_SYNCED);
|
||||
Status status;
|
||||
for (log::Writer* log : logs_to_sync) {
|
||||
@@ -690,7 +682,6 @@ Status DBImpl::SyncWAL() {
|
||||
if (status.ok() && need_log_dir_sync) {
|
||||
status = directories_.GetWalDir()->Fsync();
|
||||
}
|
||||
TEST_SYNC_POINT("DBWALTest::SyncWALNotWaitWrite:2");
|
||||
|
||||
TEST_SYNC_POINT("DBImpl::SyncWAL:BeforeMarkLogsSynced:1");
|
||||
{
|
||||
@@ -909,8 +900,7 @@ Status DBImpl::Get(const ReadOptions& read_options,
|
||||
|
||||
Status DBImpl::GetImpl(const ReadOptions& read_options,
|
||||
ColumnFamilyHandle* column_family, const Slice& key,
|
||||
PinnableSlice* pinnable_val, bool* value_found,
|
||||
bool* is_blob_index) {
|
||||
PinnableSlice* pinnable_val, bool* value_found) {
|
||||
assert(pinnable_val != nullptr);
|
||||
StopWatch sw(env_, stats_, DB_GET);
|
||||
PERF_TIMER_GUARD(get_snapshot_time);
|
||||
@@ -960,13 +950,13 @@ Status DBImpl::GetImpl(const ReadOptions& read_options,
|
||||
bool done = false;
|
||||
if (!skip_memtable) {
|
||||
if (sv->mem->Get(lkey, pinnable_val->GetSelf(), &s, &merge_context,
|
||||
&range_del_agg, read_options, is_blob_index)) {
|
||||
&range_del_agg, read_options)) {
|
||||
done = true;
|
||||
pinnable_val->PinSelf();
|
||||
RecordTick(stats_, MEMTABLE_HIT);
|
||||
} else if ((s.ok() || s.IsMergeInProgress()) &&
|
||||
sv->imm->Get(lkey, pinnable_val->GetSelf(), &s, &merge_context,
|
||||
&range_del_agg, read_options, is_blob_index)) {
|
||||
&range_del_agg, read_options)) {
|
||||
done = true;
|
||||
pinnable_val->PinSelf();
|
||||
RecordTick(stats_, MEMTABLE_HIT);
|
||||
@@ -978,8 +968,7 @@ Status DBImpl::GetImpl(const ReadOptions& read_options,
|
||||
if (!done) {
|
||||
PERF_TIMER_GUARD(get_from_output_files_time);
|
||||
sv->current->Get(read_options, lkey, pinnable_val, &s, &merge_context,
|
||||
&range_del_agg, value_found, nullptr, nullptr,
|
||||
is_blob_index);
|
||||
&range_del_agg, value_found);
|
||||
RecordTick(stats_, MEMTABLE_MISS);
|
||||
}
|
||||
|
||||
@@ -992,7 +981,6 @@ Status DBImpl::GetImpl(const ReadOptions& read_options,
|
||||
size_t size = pinnable_val->size();
|
||||
RecordTick(stats_, BYTES_READ, size);
|
||||
MeasureTime(stats_, BYTES_PER_READ, size);
|
||||
PERF_COUNTER_ADD(get_read_bytes, size);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -1120,7 +1108,6 @@ std::vector<Status> DBImpl::MultiGet(
|
||||
RecordTick(stats_, NUMBER_MULTIGET_KEYS_READ, num_keys);
|
||||
RecordTick(stats_, NUMBER_MULTIGET_BYTES_READ, bytes_read);
|
||||
MeasureTime(stats_, BYTES_PER_MULTIGET, bytes_read);
|
||||
PERF_COUNTER_ADD(multiget_read_bytes, bytes_read);
|
||||
PERF_TIMER_STOP(get_post_process_time);
|
||||
|
||||
return stat_list;
|
||||
@@ -1247,8 +1234,6 @@ Status DBImpl::CreateColumnFamilyImpl(const ColumnFamilyOptions& cf_options,
|
||||
is_snapshot_supported_ = false;
|
||||
}
|
||||
|
||||
cfd->set_initialized();
|
||||
|
||||
*handle = new ColumnFamilyHandleImpl(cfd, this, &mutex_);
|
||||
ROCKS_LOG_INFO(immutable_db_options_.info_log,
|
||||
"Created column family [%s] (ID %u)",
|
||||
@@ -1326,11 +1311,6 @@ Status DBImpl::DropColumnFamilyImpl(ColumnFamilyHandle* column_family) {
|
||||
&edit, &mutex_);
|
||||
write_thread_.ExitUnbatched(&w);
|
||||
}
|
||||
if (s.ok()) {
|
||||
auto* mutable_cf_options = cfd->GetLatestMutableCFOptions();
|
||||
max_total_in_memory_state_ -= mutable_cf_options->write_buffer_size *
|
||||
mutable_cf_options->max_write_buffer_number;
|
||||
}
|
||||
|
||||
if (!cf_support_snapshot) {
|
||||
// Dropped Column Family doesn't support snapshot. Need to recalculate
|
||||
@@ -1352,6 +1332,9 @@ Status DBImpl::DropColumnFamilyImpl(ColumnFamilyHandle* column_family) {
|
||||
// later inside db_mutex.
|
||||
EraseThreadStatusCfInfo(cfd);
|
||||
assert(cfd->IsDropped());
|
||||
auto* mutable_cf_options = cfd->GetLatestMutableCFOptions();
|
||||
max_total_in_memory_state_ -= mutable_cf_options->write_buffer_size *
|
||||
mutable_cf_options->max_write_buffer_number;
|
||||
ROCKS_LOG_INFO(immutable_db_options_.info_log,
|
||||
"Dropped column family with id %u\n", cfd->GetID());
|
||||
} else {
|
||||
@@ -1415,83 +1398,77 @@ Iterator* DBImpl::NewIterator(const ReadOptions& read_options,
|
||||
return NewDBIterator(
|
||||
env_, read_options, *cfd->ioptions(), cfd->user_comparator(), iter,
|
||||
kMaxSequenceNumber,
|
||||
sv->mutable_cf_options.max_sequential_skip_in_iterations);
|
||||
sv->mutable_cf_options.max_sequential_skip_in_iterations,
|
||||
sv->version_number);
|
||||
#endif
|
||||
} else {
|
||||
SequenceNumber latest_snapshot = versions_->LastSequence();
|
||||
SuperVersion* sv = cfd->GetReferencedSuperVersion(&mutex_);
|
||||
|
||||
auto snapshot =
|
||||
read_options.snapshot != nullptr
|
||||
? reinterpret_cast<const SnapshotImpl*>(read_options.snapshot)
|
||||
->number_
|
||||
? reinterpret_cast<const SnapshotImpl*>(
|
||||
read_options.snapshot)->number_
|
||||
: latest_snapshot;
|
||||
return NewIteratorImpl(read_options, cfd, snapshot);
|
||||
|
||||
// Try to generate a DB iterator tree in continuous memory area to be
|
||||
// cache friendly. Here is an example of result:
|
||||
// +-------------------------------+
|
||||
// | |
|
||||
// | ArenaWrappedDBIter |
|
||||
// | + |
|
||||
// | +---> Inner Iterator ------------+
|
||||
// | | | |
|
||||
// | | +-- -- -- -- -- -- -- --+ |
|
||||
// | +--- | Arena | |
|
||||
// | | | |
|
||||
// | Allocated Memory: | |
|
||||
// | | +-------------------+ |
|
||||
// | | | DBIter | <---+
|
||||
// | | + |
|
||||
// | | | +-> iter_ ------------+
|
||||
// | | | | |
|
||||
// | | +-------------------+ |
|
||||
// | | | MergingIterator | <---+
|
||||
// | | + |
|
||||
// | | | +->child iter1 ------------+
|
||||
// | | | | | |
|
||||
// | | +->child iter2 ----------+ |
|
||||
// | | | | | | |
|
||||
// | | | +->child iter3 --------+ | |
|
||||
// | | | | | |
|
||||
// | | +-------------------+ | | |
|
||||
// | | | Iterator1 | <--------+
|
||||
// | | +-------------------+ | |
|
||||
// | | | Iterator2 | <------+
|
||||
// | | +-------------------+ |
|
||||
// | | | Iterator3 | <----+
|
||||
// | | +-------------------+
|
||||
// | | |
|
||||
// +-------+-----------------------+
|
||||
//
|
||||
// ArenaWrappedDBIter inlines an arena area where all the iterators in
|
||||
// the iterator tree are allocated in the order of being accessed when
|
||||
// querying.
|
||||
// Laying out the iterators in the order of being accessed makes it more
|
||||
// likely that any iterator pointer is close to the iterator it points to so
|
||||
// that they are likely to be in the same cache line and/or page.
|
||||
ArenaWrappedDBIter* db_iter = NewArenaWrappedDbIterator(
|
||||
env_, read_options, *cfd->ioptions(), cfd->user_comparator(), snapshot,
|
||||
sv->mutable_cf_options.max_sequential_skip_in_iterations,
|
||||
sv->version_number);
|
||||
|
||||
InternalIterator* internal_iter =
|
||||
NewInternalIterator(read_options, cfd, sv, db_iter->GetArena(),
|
||||
db_iter->GetRangeDelAggregator());
|
||||
db_iter->SetIterUnderDBIter(internal_iter);
|
||||
|
||||
return db_iter;
|
||||
}
|
||||
// To stop compiler from complaining
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ArenaWrappedDBIter* DBImpl::NewIteratorImpl(const ReadOptions& read_options,
|
||||
ColumnFamilyData* cfd,
|
||||
SequenceNumber snapshot,
|
||||
bool allow_blob) {
|
||||
SuperVersion* sv = cfd->GetReferencedSuperVersion(&mutex_);
|
||||
|
||||
// Try to generate a DB iterator tree in continuous memory area to be
|
||||
// cache friendly. Here is an example of result:
|
||||
// +-------------------------------+
|
||||
// | |
|
||||
// | ArenaWrappedDBIter |
|
||||
// | + |
|
||||
// | +---> Inner Iterator ------------+
|
||||
// | | | |
|
||||
// | | +-- -- -- -- -- -- -- --+ |
|
||||
// | +--- | Arena | |
|
||||
// | | | |
|
||||
// | Allocated Memory: | |
|
||||
// | | +-------------------+ |
|
||||
// | | | DBIter | <---+
|
||||
// | | + |
|
||||
// | | | +-> iter_ ------------+
|
||||
// | | | | |
|
||||
// | | +-------------------+ |
|
||||
// | | | MergingIterator | <---+
|
||||
// | | + |
|
||||
// | | | +->child iter1 ------------+
|
||||
// | | | | | |
|
||||
// | | +->child iter2 ----------+ |
|
||||
// | | | | | | |
|
||||
// | | | +->child iter3 --------+ | |
|
||||
// | | | | | |
|
||||
// | | +-------------------+ | | |
|
||||
// | | | Iterator1 | <--------+
|
||||
// | | +-------------------+ | |
|
||||
// | | | Iterator2 | <------+
|
||||
// | | +-------------------+ |
|
||||
// | | | Iterator3 | <----+
|
||||
// | | +-------------------+
|
||||
// | | |
|
||||
// +-------+-----------------------+
|
||||
//
|
||||
// ArenaWrappedDBIter inlines an arena area where all the iterators in
|
||||
// the iterator tree are allocated in the order of being accessed when
|
||||
// querying.
|
||||
// Laying out the iterators in the order of being accessed makes it more
|
||||
// likely that any iterator pointer is close to the iterator it points to so
|
||||
// that they are likely to be in the same cache line and/or page.
|
||||
ArenaWrappedDBIter* db_iter = NewArenaWrappedDbIterator(
|
||||
env_, read_options, *cfd->ioptions(), snapshot,
|
||||
sv->mutable_cf_options.max_sequential_skip_in_iterations,
|
||||
sv->version_number, ((read_options.snapshot != nullptr) ? nullptr : this),
|
||||
cfd, allow_blob);
|
||||
|
||||
InternalIterator* internal_iter =
|
||||
NewInternalIterator(read_options, cfd, sv, db_iter->GetArena(),
|
||||
db_iter->GetRangeDelAggregator());
|
||||
db_iter->SetIterUnderDBIter(internal_iter);
|
||||
|
||||
return db_iter;
|
||||
}
|
||||
|
||||
Status DBImpl::NewIterators(
|
||||
const ReadOptions& read_options,
|
||||
const std::vector<ColumnFamilyHandle*>& column_families,
|
||||
@@ -1530,21 +1507,33 @@ Status DBImpl::NewIterators(
|
||||
iterators->push_back(NewDBIterator(
|
||||
env_, read_options, *cfd->ioptions(), cfd->user_comparator(), iter,
|
||||
kMaxSequenceNumber,
|
||||
sv->mutable_cf_options.max_sequential_skip_in_iterations));
|
||||
sv->mutable_cf_options.max_sequential_skip_in_iterations,
|
||||
sv->version_number));
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
SequenceNumber latest_snapshot = versions_->LastSequence();
|
||||
auto snapshot =
|
||||
read_options.snapshot != nullptr
|
||||
? reinterpret_cast<const SnapshotImpl*>(read_options.snapshot)
|
||||
->number_
|
||||
: latest_snapshot;
|
||||
|
||||
for (size_t i = 0; i < column_families.size(); ++i) {
|
||||
auto* cfd = reinterpret_cast<ColumnFamilyHandleImpl*>(
|
||||
column_families[i])->cfd();
|
||||
iterators->push_back(NewIteratorImpl(read_options, cfd, snapshot));
|
||||
SuperVersion* sv = cfd->GetReferencedSuperVersion(&mutex_);
|
||||
|
||||
auto snapshot =
|
||||
read_options.snapshot != nullptr
|
||||
? reinterpret_cast<const SnapshotImpl*>(
|
||||
read_options.snapshot)->number_
|
||||
: latest_snapshot;
|
||||
|
||||
ArenaWrappedDBIter* db_iter = NewArenaWrappedDbIterator(
|
||||
env_, read_options, *cfd->ioptions(), cfd->user_comparator(),
|
||||
snapshot, sv->mutable_cf_options.max_sequential_skip_in_iterations,
|
||||
sv->version_number);
|
||||
InternalIterator* internal_iter =
|
||||
NewInternalIterator(read_options, cfd, sv, db_iter->GetArena(),
|
||||
db_iter->GetRangeDelAggregator());
|
||||
db_iter->SetIterUnderDBIter(internal_iter);
|
||||
iterators->push_back(db_iter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1583,10 +1572,12 @@ void DBImpl::ReleaseSnapshot(const Snapshot* s) {
|
||||
delete casted_s;
|
||||
}
|
||||
|
||||
bool DBImpl::HasActiveSnapshotInRange(SequenceNumber lower_bound,
|
||||
SequenceNumber upper_bound) {
|
||||
bool DBImpl::HasActiveSnapshotLaterThanSN(SequenceNumber sn) {
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
return snapshots_.HasSnapshotInRange(lower_bound, upper_bound);
|
||||
if (snapshots_.empty()) {
|
||||
return false;
|
||||
}
|
||||
return (snapshots_.newest()->GetSequenceNumber() > sn);
|
||||
}
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
@@ -1744,9 +1735,7 @@ bool DBImpl::GetIntPropertyInternal(ColumnFamilyData* cfd,
|
||||
Status DBImpl::ResetStats() {
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
for (auto* cfd : *versions_->GetColumnFamilySet()) {
|
||||
if (cfd->initialized()) {
|
||||
cfd->internal_stats()->Clear();
|
||||
}
|
||||
cfd->internal_stats()->Clear();
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
@@ -1765,9 +1754,6 @@ bool DBImpl::GetAggregatedIntProperty(const Slice& property,
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
uint64_t value;
|
||||
for (auto* cfd : *versions_->GetColumnFamilySet()) {
|
||||
if (!cfd->initialized()) {
|
||||
continue;
|
||||
}
|
||||
if (GetIntPropertyInternal(cfd, *property_info, true, &value)) {
|
||||
sum += value;
|
||||
} else {
|
||||
@@ -2062,19 +2048,25 @@ Status DBImpl::DeleteFilesInRange(ColumnFamilyHandle* column_family,
|
||||
end_key = &end_storage;
|
||||
}
|
||||
|
||||
vstorage->GetCleanInputsWithinInterval(i, begin_key, end_key,
|
||||
&level_files, -1 /* hint_index */,
|
||||
nullptr /* file_index */);
|
||||
vstorage->GetOverlappingInputs(i, begin_key, end_key, &level_files, -1,
|
||||
nullptr, false);
|
||||
FileMetaData* level_file;
|
||||
for (uint32_t j = 0; j < level_files.size(); j++) {
|
||||
level_file = level_files[j];
|
||||
if (level_file->being_compacted) {
|
||||
continue;
|
||||
if (((begin == nullptr) ||
|
||||
(cfd->internal_comparator().user_comparator()->Compare(
|
||||
level_file->smallest.user_key(), *begin) >= 0)) &&
|
||||
((end == nullptr) ||
|
||||
(cfd->internal_comparator().user_comparator()->Compare(
|
||||
level_file->largest.user_key(), *end) <= 0))) {
|
||||
if (level_file->being_compacted) {
|
||||
continue;
|
||||
}
|
||||
edit.SetColumnFamily(cfd->GetID());
|
||||
edit.DeleteFile(i, level_file->fd.GetNumber());
|
||||
deleted_files.push_back(level_file);
|
||||
level_file->being_compacted = true;
|
||||
}
|
||||
edit.SetColumnFamily(cfd->GetID());
|
||||
edit.DeleteFile(i, level_file->fd.GetNumber());
|
||||
deleted_files.push_back(level_file);
|
||||
level_file->being_compacted = true;
|
||||
}
|
||||
}
|
||||
if (edit.GetDeletedFiles().empty()) {
|
||||
@@ -2292,7 +2284,7 @@ Status DestroyDB(const std::string& dbname, const Options& options) {
|
||||
// Delete log files in the WAL dir
|
||||
for (const auto& file : walDirFiles) {
|
||||
if (ParseFileName(file, &number, &type) && type == kLogFile) {
|
||||
Status del = env->DeleteFile(LogFileName(soptions.wal_dir, number));
|
||||
Status del = env->DeleteFile(soptions.wal_dir + "/" + file);
|
||||
if (result.ok() && !del.ok()) {
|
||||
result = del;
|
||||
}
|
||||
@@ -2354,9 +2346,6 @@ Status DBImpl::WriteOptionsFile(bool need_mutex_lock,
|
||||
BuildDBOptions(immutable_db_options_, mutable_db_options_);
|
||||
mutex_.Unlock();
|
||||
|
||||
TEST_SYNC_POINT("DBImpl::WriteOptionsFile:1");
|
||||
TEST_SYNC_POINT("DBImpl::WriteOptionsFile:2");
|
||||
|
||||
std::string file_name =
|
||||
TempOptionsFileName(GetName(), versions_->NewFileNumber());
|
||||
Status s =
|
||||
@@ -2492,7 +2481,7 @@ void DBImpl::EraseThreadStatusDbInfo() const {
|
||||
// A global method that can dump out the build version
|
||||
void DumpRocksDBBuildVersion(Logger * log) {
|
||||
#if !defined(IOS_CROSS_COMPILE)
|
||||
// if we compile with Xcode, we don't run build_detect_version, so we don't
|
||||
// if we compile with Xcode, we don't run build_detect_vesion, so we don't
|
||||
// generate util/build_version.cc
|
||||
ROCKS_LOG_HEADER(log, "RocksDB version: %d.%d.%d\n", ROCKSDB_MAJOR,
|
||||
ROCKSDB_MINOR, ROCKSDB_PATCH);
|
||||
@@ -2520,8 +2509,7 @@ SequenceNumber DBImpl::GetEarliestMemTableSequenceNumber(SuperVersion* sv,
|
||||
#ifndef ROCKSDB_LITE
|
||||
Status DBImpl::GetLatestSequenceForKey(SuperVersion* sv, const Slice& key,
|
||||
bool cache_only, SequenceNumber* seq,
|
||||
bool* found_record_for_key,
|
||||
bool* is_blob_index) {
|
||||
bool* found_record_for_key) {
|
||||
Status s;
|
||||
MergeContext merge_context;
|
||||
RangeDelAggregator range_del_agg(sv->mem->GetInternalKeyComparator(),
|
||||
@@ -2536,7 +2524,7 @@ Status DBImpl::GetLatestSequenceForKey(SuperVersion* sv, const Slice& key,
|
||||
|
||||
// Check if there is a record for this key in the latest memtable
|
||||
sv->mem->Get(lkey, nullptr, &s, &merge_context, &range_del_agg, seq,
|
||||
read_options, is_blob_index);
|
||||
read_options);
|
||||
|
||||
if (!(s.ok() || s.IsNotFound() || s.IsMergeInProgress())) {
|
||||
// unexpected error reading memtable.
|
||||
@@ -2555,7 +2543,7 @@ Status DBImpl::GetLatestSequenceForKey(SuperVersion* sv, const Slice& key,
|
||||
|
||||
// Check if there is a record for this key in the immutable memtables
|
||||
sv->imm->Get(lkey, nullptr, &s, &merge_context, &range_del_agg, seq,
|
||||
read_options, is_blob_index);
|
||||
read_options);
|
||||
|
||||
if (!(s.ok() || s.IsNotFound() || s.IsMergeInProgress())) {
|
||||
// unexpected error reading memtable.
|
||||
@@ -2574,7 +2562,7 @@ Status DBImpl::GetLatestSequenceForKey(SuperVersion* sv, const Slice& key,
|
||||
|
||||
// Check if there is a record for this key in the immutable memtables
|
||||
sv->imm->GetFromHistory(lkey, nullptr, &s, &merge_context, &range_del_agg,
|
||||
seq, read_options, is_blob_index);
|
||||
seq, read_options);
|
||||
|
||||
if (!(s.ok() || s.IsNotFound() || s.IsMergeInProgress())) {
|
||||
// unexpected error reading memtable.
|
||||
@@ -2598,7 +2586,7 @@ Status DBImpl::GetLatestSequenceForKey(SuperVersion* sv, const Slice& key,
|
||||
// Check tables
|
||||
sv->current->Get(read_options, lkey, nullptr, &s, &merge_context,
|
||||
&range_del_agg, nullptr /* value_found */,
|
||||
found_record_for_key, seq, is_blob_index);
|
||||
found_record_for_key, seq);
|
||||
|
||||
if (!(s.ok() || s.IsNotFound() || s.IsMergeInProgress())) {
|
||||
// unexpected error reading SST files
|
||||
@@ -2621,15 +2609,6 @@ Status DBImpl::IngestExternalFile(
|
||||
auto cfh = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family);
|
||||
auto cfd = cfh->cfd();
|
||||
|
||||
// Ingest should immediately fail if ingest_behind is requested,
|
||||
// but the DB doesn't support it.
|
||||
if (ingestion_options.ingest_behind) {
|
||||
if (!immutable_db_options_.allow_ingest_behind) {
|
||||
return Status::InvalidArgument(
|
||||
"Can't ingest_behind file in DB with allow_ingest_behind=false");
|
||||
}
|
||||
}
|
||||
|
||||
ExternalSstFileIngestionJob ingestion_job(env_, versions_.get(), cfd,
|
||||
immutable_db_options_, env_options_,
|
||||
&snapshots_, ingestion_options);
|
||||
@@ -2657,13 +2636,9 @@ Status DBImpl::IngestExternalFile(
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
TEST_SYNC_POINT("DBImpl::AddFile:MutexLock");
|
||||
|
||||
// Stop writes to the DB by entering both write threads
|
||||
// Stop writes to the DB
|
||||
WriteThread::Writer w;
|
||||
write_thread_.EnterUnbatched(&w, &mutex_);
|
||||
WriteThread::Writer nonmem_w;
|
||||
if (concurrent_prepare_) {
|
||||
nonmem_write_thread_.EnterUnbatched(&nonmem_w, &mutex_);
|
||||
}
|
||||
|
||||
num_running_ingest_file_++;
|
||||
|
||||
@@ -2677,8 +2652,7 @@ Status DBImpl::IngestExternalFile(
|
||||
if (status.ok()) {
|
||||
bool need_flush = false;
|
||||
status = ingestion_job.NeedsFlush(&need_flush);
|
||||
TEST_SYNC_POINT_CALLBACK("DBImpl::IngestExternalFile:NeedFlush",
|
||||
&need_flush);
|
||||
|
||||
if (status.ok() && need_flush) {
|
||||
mutex_.Unlock();
|
||||
status = FlushMemTable(cfd, FlushOptions(), true /* writes_stopped */);
|
||||
@@ -2704,9 +2678,6 @@ Status DBImpl::IngestExternalFile(
|
||||
}
|
||||
|
||||
// Resume writes to the DB
|
||||
if (concurrent_prepare_) {
|
||||
nonmem_write_thread_.ExitUnbatched(&nonmem_w);
|
||||
}
|
||||
write_thread_.ExitUnbatched(&w);
|
||||
|
||||
// Update stats
|
||||
@@ -2735,54 +2706,6 @@ Status DBImpl::IngestExternalFile(
|
||||
return status;
|
||||
}
|
||||
|
||||
Status DBImpl::VerifyChecksum() {
|
||||
Status s;
|
||||
Options options;
|
||||
EnvOptions env_options;
|
||||
std::vector<ColumnFamilyData*> cfd_list;
|
||||
{
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
for (auto cfd : *versions_->GetColumnFamilySet()) {
|
||||
if (!cfd->IsDropped() && cfd->initialized()) {
|
||||
cfd->Ref();
|
||||
cfd_list.push_back(cfd);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<SuperVersion*> sv_list;
|
||||
for (auto cfd : cfd_list) {
|
||||
sv_list.push_back(cfd->GetReferencedSuperVersion(&mutex_));
|
||||
}
|
||||
for (auto& sv : sv_list) {
|
||||
VersionStorageInfo* vstorage = sv->current->storage_info();
|
||||
for (int i = 0; i < vstorage->num_non_empty_levels() && s.ok(); i++) {
|
||||
for (size_t j = 0; j < vstorage->LevelFilesBrief(i).num_files && s.ok();
|
||||
j++) {
|
||||
const auto& fd = vstorage->LevelFilesBrief(i).files[j].fd;
|
||||
std::string fname = TableFileName(immutable_db_options_.db_paths,
|
||||
fd.GetNumber(), fd.GetPathId());
|
||||
s = rocksdb::VerifySstFileChecksum(options, env_options, fname);
|
||||
}
|
||||
}
|
||||
if (!s.ok()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
for (auto sv : sv_list) {
|
||||
if (sv && sv->Unref()) {
|
||||
sv->Cleanup();
|
||||
delete sv;
|
||||
}
|
||||
}
|
||||
for (auto cfd : cfd_list) {
|
||||
cfd->Unref();
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void DBImpl::NotifyOnExternalFileIngested(
|
||||
ColumnFamilyData* cfd, const ExternalSstFileIngestionJob& ingestion_job) {
|
||||
#ifndef ROCKSDB_LITE
|
||||
|
||||
+50
-167
@@ -52,7 +52,6 @@
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
class ArenaWrappedDBIter;
|
||||
class MemTable;
|
||||
class TableCache;
|
||||
class Version;
|
||||
@@ -94,13 +93,6 @@ class DBImpl : public DB {
|
||||
virtual Status Get(const ReadOptions& options,
|
||||
ColumnFamilyHandle* column_family, const Slice& key,
|
||||
PinnableSlice* value) override;
|
||||
|
||||
// Function that Get and KeyMayExist call with no_io true or false
|
||||
// Note: 'value_found' from KeyMayExist propagates here
|
||||
Status GetImpl(const ReadOptions& options, ColumnFamilyHandle* column_family,
|
||||
const Slice& key, PinnableSlice* value,
|
||||
bool* value_found = nullptr, bool* is_blob_index = nullptr);
|
||||
|
||||
using DB::MultiGet;
|
||||
virtual std::vector<Status> MultiGet(
|
||||
const ReadOptions& options,
|
||||
@@ -131,7 +123,6 @@ class DBImpl : public DB {
|
||||
ColumnFamilyHandle* column_family, const Slice& key,
|
||||
std::string* value,
|
||||
bool* value_found = nullptr) override;
|
||||
|
||||
using DB::NewIterator;
|
||||
virtual Iterator* NewIterator(const ReadOptions& options,
|
||||
ColumnFamilyHandle* column_family) override;
|
||||
@@ -139,11 +130,6 @@ class DBImpl : public DB {
|
||||
const ReadOptions& options,
|
||||
const std::vector<ColumnFamilyHandle*>& column_families,
|
||||
std::vector<Iterator*>* iterators) override;
|
||||
ArenaWrappedDBIter* NewIteratorImpl(const ReadOptions& options,
|
||||
ColumnFamilyData* cfd,
|
||||
SequenceNumber snapshot,
|
||||
bool allow_blob = false);
|
||||
|
||||
virtual const Snapshot* GetSnapshot() override;
|
||||
virtual void ReleaseSnapshot(const Snapshot* snapshot) override;
|
||||
using DB::GetProperty;
|
||||
@@ -211,14 +197,11 @@ class DBImpl : public DB {
|
||||
using DB::Flush;
|
||||
virtual Status Flush(const FlushOptions& options,
|
||||
ColumnFamilyHandle* column_family) override;
|
||||
virtual Status FlushWAL(bool sync) override;
|
||||
virtual Status SyncWAL() override;
|
||||
|
||||
virtual SequenceNumber GetLatestSequenceNumber() const override;
|
||||
|
||||
// Whether there is an active snapshot in range [lower_bound, upper_bound).
|
||||
bool HasActiveSnapshotInRange(SequenceNumber lower_bound,
|
||||
SequenceNumber upper_bound);
|
||||
bool HasActiveSnapshotLaterThanSN(SequenceNumber sn);
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
using DB::ResetStats;
|
||||
@@ -251,11 +234,11 @@ class DBImpl : public DB {
|
||||
ColumnFamilyHandle* column_family,
|
||||
ColumnFamilyMetaData* metadata) override;
|
||||
|
||||
// experimental API
|
||||
Status SuggestCompactRange(ColumnFamilyHandle* column_family,
|
||||
const Slice* begin, const Slice* end) override;
|
||||
const Slice* begin, const Slice* end);
|
||||
|
||||
Status PromoteL0(ColumnFamilyHandle* column_family,
|
||||
int target_level) override;
|
||||
Status PromoteL0(ColumnFamilyHandle* column_family, int target_level);
|
||||
|
||||
// Similar to Write() but will call the callback once on the single write
|
||||
// thread to determine whether it is safe to perform the write.
|
||||
@@ -301,8 +284,7 @@ class DBImpl : public DB {
|
||||
// TODO(andrewkr): this API need to be aware of range deletion operations
|
||||
Status GetLatestSequenceForKey(SuperVersion* sv, const Slice& key,
|
||||
bool cache_only, SequenceNumber* seq,
|
||||
bool* found_record_for_key,
|
||||
bool* is_blob_index = nullptr);
|
||||
bool* found_record_for_key);
|
||||
|
||||
using DB::IngestExternalFile;
|
||||
virtual Status IngestExternalFile(
|
||||
@@ -310,8 +292,6 @@ class DBImpl : public DB {
|
||||
const std::vector<std::string>& external_files,
|
||||
const IngestExternalFileOptions& ingestion_options) override;
|
||||
|
||||
virtual Status VerifyChecksum() override;
|
||||
|
||||
#endif // ROCKSDB_LITE
|
||||
|
||||
// Similar to GetSnapshot(), but also lets the db know that this snapshot
|
||||
@@ -358,8 +338,6 @@ class DBImpl : public DB {
|
||||
return alive_log_files_.begin()->getting_flushed;
|
||||
}
|
||||
|
||||
Status TEST_SwitchMemtable(ColumnFamilyData* cfd = nullptr);
|
||||
|
||||
// Force current memtable contents to be flushed.
|
||||
Status TEST_FlushMemTable(bool wait = true,
|
||||
ColumnFamilyHandle* cfh = nullptr);
|
||||
@@ -409,9 +387,9 @@ class DBImpl : public DB {
|
||||
Status TEST_GetAllImmutableCFOptions(
|
||||
std::unordered_map<std::string, const ImmutableCFOptions*>* iopts_map);
|
||||
|
||||
// Return the lastest MutableCFOptions of a column family
|
||||
// Return the lastest MutableCFOptions of of a column family
|
||||
Status TEST_GetLatestMutableCFOptions(ColumnFamilyHandle* column_family,
|
||||
MutableCFOptions* mutable_cf_options);
|
||||
MutableCFOptions* mutable_cf_opitons);
|
||||
|
||||
Cache* TEST_table_cache() { return table_cache_.get(); }
|
||||
|
||||
@@ -421,21 +399,12 @@ class DBImpl : public DB {
|
||||
uint64_t TEST_FindMinPrepLogReferencedByMemTable();
|
||||
|
||||
int TEST_BGCompactionsAllowed() const;
|
||||
int TEST_BGFlushesAllowed() const;
|
||||
|
||||
#endif // NDEBUG
|
||||
|
||||
struct BGJobLimits {
|
||||
int max_flushes;
|
||||
int max_compactions;
|
||||
};
|
||||
// Returns maximum background flushes and compactions allowed to be scheduled
|
||||
BGJobLimits GetBGJobLimits() const;
|
||||
// Need a static version that can be called during SanitizeOptions().
|
||||
static BGJobLimits GetBGJobLimits(int max_background_flushes,
|
||||
int max_background_compactions,
|
||||
int max_background_jobs,
|
||||
bool parallelize_compactions);
|
||||
// Return maximum background compaction allowed to be scheduled based on
|
||||
// compaction status.
|
||||
int BGCompactionsAllowed() const;
|
||||
|
||||
// move logs pending closing from job_context to the DB queue and
|
||||
// schedule a purge
|
||||
@@ -515,12 +484,6 @@ class DBImpl : public DB {
|
||||
|
||||
const WriteController& write_controller() { return write_controller_; }
|
||||
|
||||
InternalIterator* NewInternalIterator(const ReadOptions&,
|
||||
ColumnFamilyData* cfd,
|
||||
SuperVersion* super_version,
|
||||
Arena* arena,
|
||||
RangeDelAggregator* range_del_agg);
|
||||
|
||||
// hollow transactions shell used for recovery.
|
||||
// these will then be passed to TransactionDB so that
|
||||
// locks can be reacquired before writing can resume.
|
||||
@@ -579,7 +542,6 @@ class DBImpl : public DB {
|
||||
void AddToLogsToFreeQueue(log::Writer* log_writer) {
|
||||
logs_to_free_queue_.push_back(log_writer);
|
||||
}
|
||||
InstrumentedMutex* mutex() { return &mutex_; }
|
||||
|
||||
Status NewDB();
|
||||
|
||||
@@ -594,6 +556,12 @@ class DBImpl : public DB {
|
||||
std::unordered_map<std::string, RecoveredTransaction*>
|
||||
recovered_transactions_;
|
||||
|
||||
InternalIterator* NewInternalIterator(const ReadOptions&,
|
||||
ColumnFamilyData* cfd,
|
||||
SuperVersion* super_version,
|
||||
Arena* arena,
|
||||
RangeDelAggregator* range_del_agg);
|
||||
|
||||
// Except in DB::Open(), WriteOptionsFile can only be called when:
|
||||
// Persist options to options file.
|
||||
// If need_mutex_lock = false, the method will lock DB mutex.
|
||||
@@ -635,18 +603,7 @@ class DBImpl : public DB {
|
||||
Status WriteImpl(const WriteOptions& options, WriteBatch* updates,
|
||||
WriteCallback* callback = nullptr,
|
||||
uint64_t* log_used = nullptr, uint64_t log_ref = 0,
|
||||
bool disable_memtable = false, uint64_t* seq_used = nullptr);
|
||||
|
||||
Status PipelinedWriteImpl(const WriteOptions& options, WriteBatch* updates,
|
||||
WriteCallback* callback = nullptr,
|
||||
uint64_t* log_used = nullptr, uint64_t log_ref = 0,
|
||||
bool disable_memtable = false,
|
||||
uint64_t* seq_used = nullptr);
|
||||
|
||||
Status WriteImplWALOnly(const WriteOptions& options, WriteBatch* updates,
|
||||
WriteCallback* callback = nullptr,
|
||||
uint64_t* log_used = nullptr, uint64_t log_ref = 0,
|
||||
uint64_t* seq_used = nullptr);
|
||||
bool disable_memtable = false);
|
||||
|
||||
uint64_t FindMinLogContainingOutstandingPrep();
|
||||
uint64_t FindMinPrepLogReferencedByMemTable();
|
||||
@@ -654,18 +611,14 @@ class DBImpl : public DB {
|
||||
private:
|
||||
friend class DB;
|
||||
friend class InternalStats;
|
||||
friend class PessimisticTransaction;
|
||||
friend class WriteCommittedTxn;
|
||||
friend class WritePreparedTxn;
|
||||
friend class TransactionImpl;
|
||||
#ifndef ROCKSDB_LITE
|
||||
friend class ForwardIterator;
|
||||
#endif
|
||||
friend struct SuperVersion;
|
||||
friend class CompactedDBImpl;
|
||||
#ifndef NDEBUG
|
||||
friend class DBTest2_ReadCallbackTest_Test;
|
||||
friend class XFTransactionWriteHandler;
|
||||
friend class DBBlobIndexTest;
|
||||
#endif
|
||||
struct CompactionState;
|
||||
|
||||
@@ -683,7 +636,6 @@ class DBImpl : public DB {
|
||||
}
|
||||
};
|
||||
|
||||
struct PrepickedCompaction;
|
||||
struct PurgeFileInfo;
|
||||
|
||||
// Recover the descriptor from persistent storage. May do a significant
|
||||
@@ -754,9 +706,6 @@ class DBImpl : public DB {
|
||||
// `num_bytes` going through.
|
||||
Status DelayWrite(uint64_t num_bytes, const WriteOptions& write_options);
|
||||
|
||||
Status ThrottleLowPriWritesIfNeeded(const WriteOptions& write_options,
|
||||
WriteBatch* my_batch);
|
||||
|
||||
Status ScheduleFlushes(WriteContext* context);
|
||||
|
||||
Status SwitchMemtable(ColumnFamilyData* cfd, WriteContext* context);
|
||||
@@ -775,29 +724,12 @@ class DBImpl : public DB {
|
||||
Status HandleWriteBufferFull(WriteContext* write_context);
|
||||
|
||||
// REQUIRES: mutex locked
|
||||
Status PreprocessWrite(const WriteOptions& write_options, bool* need_log_sync,
|
||||
WriteContext* write_context);
|
||||
Status PreprocessWrite(const WriteOptions& write_options, bool need_log_sync,
|
||||
bool* logs_getting_syned, WriteContext* write_context);
|
||||
|
||||
WriteBatch* MergeBatch(const WriteThread::WriteGroup& write_group,
|
||||
WriteBatch* tmp_batch, size_t* write_with_wal);
|
||||
|
||||
Status WriteToWAL(const WriteBatch& merged_batch, log::Writer* log_writer,
|
||||
uint64_t* log_used, uint64_t* log_size);
|
||||
|
||||
Status WriteToWAL(const WriteThread::WriteGroup& write_group,
|
||||
log::Writer* log_writer, uint64_t* log_used,
|
||||
bool need_log_sync, bool need_log_dir_sync,
|
||||
SequenceNumber sequence);
|
||||
|
||||
Status ConcurrentWriteToWAL(const WriteThread::WriteGroup& write_group,
|
||||
uint64_t* log_used, SequenceNumber* last_sequence,
|
||||
int total_count);
|
||||
|
||||
// Used by WriteImpl to update bg_error_ if paranoid check is enabled.
|
||||
void WriteCallbackStatusCheck(const Status& status);
|
||||
|
||||
// Used by WriteImpl to update bg_error_ in case of memtable insert error.
|
||||
void MemTableInsertStatusCheck(const Status& memtable_insert_status);
|
||||
Status WriteToWAL(const autovector<WriteThread::Writer*>& write_group,
|
||||
log::Writer* log_writer, bool need_log_sync,
|
||||
bool need_log_dir_sync, SequenceNumber sequence);
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
|
||||
@@ -825,19 +757,14 @@ class DBImpl : public DB {
|
||||
void SchedulePendingPurge(std::string fname, FileType type, uint64_t number,
|
||||
uint32_t path_id, int job_id);
|
||||
static void BGWorkCompaction(void* arg);
|
||||
// Runs a pre-chosen universal compaction involving bottom level in a
|
||||
// separate, bottom-pri thread pool.
|
||||
static void BGWorkBottomCompaction(void* arg);
|
||||
static void BGWorkFlush(void* db);
|
||||
static void BGWorkPurge(void* arg);
|
||||
static void UnscheduleCallback(void* arg);
|
||||
void BackgroundCallCompaction(PrepickedCompaction* prepicked_compaction,
|
||||
Env::Priority bg_thread_pri);
|
||||
void BackgroundCallCompaction(void* arg);
|
||||
void BackgroundCallFlush();
|
||||
void BackgroundCallPurge();
|
||||
Status BackgroundCompaction(bool* madeProgress, JobContext* job_context,
|
||||
LogBuffer* log_buffer,
|
||||
PrepickedCompaction* prepicked_compaction);
|
||||
LogBuffer* log_buffer, void* m = 0);
|
||||
Status BackgroundFlush(bool* madeProgress, JobContext* job_context,
|
||||
LogBuffer* log_buffer);
|
||||
|
||||
@@ -875,16 +802,11 @@ class DBImpl : public DB {
|
||||
// Lock over the persistent DB state. Non-nullptr iff successfully acquired.
|
||||
FileLock* db_lock_;
|
||||
|
||||
// In addition to mutex_, log_write_mutex_ protected writes to logs_ and
|
||||
// logfile_number_. With concurrent_prepare it also protects alive_log_files_,
|
||||
// and log_empty_. Refer to the definition of each variable below for more
|
||||
// details.
|
||||
InstrumentedMutex log_write_mutex_;
|
||||
// The mutex for options file related operations.
|
||||
// NOTE: should never acquire options_file_mutex_ and mutex_ at the
|
||||
// same time.
|
||||
InstrumentedMutex options_files_mutex_;
|
||||
// State below is protected by mutex_
|
||||
// With concurrent_prepare enabled, some of the variables that accessed during
|
||||
// WriteToWAL need different synchronization: log_empty_, alive_log_files_,
|
||||
// logs_, logfile_number_. Refer to the definition of each variable below for
|
||||
// more description.
|
||||
mutable InstrumentedMutex mutex_;
|
||||
|
||||
std::atomic<bool> shutting_down_;
|
||||
@@ -898,20 +820,10 @@ class DBImpl : public DB {
|
||||
// * whenever there is an error in background purge, flush or compaction
|
||||
// * whenever num_running_ingest_file_ goes to 0.
|
||||
InstrumentedCondVar bg_cv_;
|
||||
// Writes are protected by locking both mutex_ and log_write_mutex_, and reads
|
||||
// must be under either mutex_ or log_write_mutex_. Since after ::Open,
|
||||
// logfile_number_ is currently updated only in write_thread_, it can be read
|
||||
// from the same write_thread_ without any locks.
|
||||
uint64_t logfile_number_;
|
||||
std::deque<uint64_t>
|
||||
log_recycle_files; // a list of log files that we can recycle
|
||||
bool log_dir_synced_;
|
||||
// Without concurrent_prepare, read and writes to log_empty_ are protected by
|
||||
// mutex_. Since it is currently updated/read only in write_thread_, it can be
|
||||
// accessed from the same write_thread_ without any locks. With
|
||||
// concurrent_prepare writes, where it can be updated in different threads,
|
||||
// read and writes are protected by log_write_mutex_ instead. This is to avoid
|
||||
// expesnive mutex_ lock during WAL write, which update log_empty_.
|
||||
bool log_empty_;
|
||||
ColumnFamilyHandleImpl* default_cf_handle_;
|
||||
InternalStats* default_cf_internal_stats_;
|
||||
@@ -946,26 +858,14 @@ class DBImpl : public DB {
|
||||
// true for some prefix of logs_
|
||||
bool getting_synced = false;
|
||||
};
|
||||
// Without concurrent_prepare, read and writes to alive_log_files_ are
|
||||
// protected by mutex_. However since back() is never popped, and push_back()
|
||||
// is done only from write_thread_, the same thread can access the item
|
||||
// reffered by back() without mutex_. With concurrent_prepare_, writes
|
||||
// are protected by locking both mutex_ and log_write_mutex_, and reads must
|
||||
// be under either mutex_ or log_write_mutex_.
|
||||
std::deque<LogFileNumberSize> alive_log_files_;
|
||||
// Log files that aren't fully synced, and the current log file.
|
||||
// Synchronization:
|
||||
// - push_back() is done from write_thread_ with locked mutex_ and
|
||||
// log_write_mutex_
|
||||
// - pop_front() is done from any thread with locked mutex_ and
|
||||
// log_write_mutex_
|
||||
// - reads are done with either locked mutex_ or log_write_mutex_
|
||||
// - push_back() is done from write thread with locked mutex_,
|
||||
// - pop_front() is done from any thread with locked mutex_,
|
||||
// - back() and items with getting_synced=true are not popped,
|
||||
// - The same thread that sets getting_synced=true will reset it.
|
||||
// - it follows that the object referred by back() can be safely read from
|
||||
// the write_thread_ without using mutex
|
||||
// - it follows that the items with getting_synced=true can be safely read
|
||||
// from the same thread that has set getting_synced=true
|
||||
// - it follows that write thread with unlocked mutex_ can safely access
|
||||
// back() and items with getting_synced=true.
|
||||
std::deque<LogWriterNumber> logs_;
|
||||
// Signaled when getting_synced becomes false for some of the logs_.
|
||||
InstrumentedCondVar log_sync_cv_;
|
||||
@@ -1014,19 +914,13 @@ class DBImpl : public DB {
|
||||
WriteBufferManager* write_buffer_manager_;
|
||||
|
||||
WriteThread write_thread_;
|
||||
|
||||
WriteBatch tmp_batch_;
|
||||
// The write thread when the writers have no memtable write. This will be used
|
||||
// in 2PC to batch the prepares separately from the serial commit.
|
||||
WriteThread nonmem_write_thread_;
|
||||
|
||||
WriteController write_controller_;
|
||||
|
||||
unique_ptr<RateLimiter> low_pri_write_rate_limiter_;
|
||||
|
||||
// Size of the last batch group. In slowdown mode, next write needs to
|
||||
// sleep if it uses up the quota.
|
||||
// Note: This is to protect memtable and compaction. If the batch only writes
|
||||
// to the WAL its size need not to be included in this.
|
||||
uint64_t last_batch_group_size_;
|
||||
|
||||
FlushScheduler flush_scheduler_;
|
||||
@@ -1090,10 +984,6 @@ class DBImpl : public DB {
|
||||
int unscheduled_flushes_;
|
||||
int unscheduled_compactions_;
|
||||
|
||||
// count how many background compactions are running or have been scheduled in
|
||||
// the BOTTOM pool
|
||||
int bg_bottom_compaction_scheduled_;
|
||||
|
||||
// count how many background compactions are running or have been scheduled
|
||||
int bg_compaction_scheduled_;
|
||||
|
||||
@@ -1110,7 +1000,7 @@ class DBImpl : public DB {
|
||||
int bg_purge_scheduled_;
|
||||
|
||||
// Information for a manual compaction
|
||||
struct ManualCompactionState {
|
||||
struct ManualCompaction {
|
||||
ColumnFamilyData* cfd;
|
||||
int input_level;
|
||||
int output_level;
|
||||
@@ -1126,21 +1016,13 @@ class DBImpl : public DB {
|
||||
InternalKey* manual_end; // how far we are compacting
|
||||
InternalKey tmp_storage; // Used to keep track of compaction progress
|
||||
InternalKey tmp_storage1; // Used to keep track of compaction progress
|
||||
};
|
||||
struct PrepickedCompaction {
|
||||
// background compaction takes ownership of `compaction`.
|
||||
Compaction* compaction;
|
||||
// caller retains ownership of `manual_compaction_state` as it is reused
|
||||
// across background compactions.
|
||||
ManualCompactionState* manual_compaction_state; // nullptr if non-manual
|
||||
};
|
||||
std::deque<ManualCompactionState*> manual_compaction_dequeue_;
|
||||
std::deque<ManualCompaction*> manual_compaction_dequeue_;
|
||||
|
||||
struct CompactionArg {
|
||||
// caller retains ownership of `db`.
|
||||
DBImpl* db;
|
||||
// background compaction takes ownership of `prepicked_compaction`.
|
||||
PrepickedCompaction* prepicked_compaction;
|
||||
ManualCompaction* m;
|
||||
};
|
||||
|
||||
// Have we encountered a background error in paranoid mode?
|
||||
@@ -1210,7 +1092,7 @@ class DBImpl : public DB {
|
||||
// Indicate DB was opened successfully
|
||||
bool opened_successfully_;
|
||||
|
||||
// minimum log number still containing prepared data.
|
||||
// minmum log number still containing prepared data.
|
||||
// this is used by FindObsoleteFiles to determine which
|
||||
// flushed logs we must keep around because they still
|
||||
// contain prepared data which has not been flushed or rolled back
|
||||
@@ -1223,7 +1105,7 @@ class DBImpl : public DB {
|
||||
// to prepared_section_completed_ which maps LOG -> instance_count
|
||||
// since a log could contain multiple prepared sections
|
||||
//
|
||||
// when trying to determine the minimum log still active we first
|
||||
// when trying to determine the minmum log still active we first
|
||||
// consult min_log_with_prep_. while that root value maps to
|
||||
// a value > 0 in prepared_section_completed_ we decrement the
|
||||
// instance_count for that log and pop the root value in
|
||||
@@ -1262,24 +1144,25 @@ class DBImpl : public DB {
|
||||
|
||||
#endif // ROCKSDB_LITE
|
||||
|
||||
// Function that Get and KeyMayExist call with no_io true or false
|
||||
// Note: 'value_found' from KeyMayExist propagates here
|
||||
Status GetImpl(const ReadOptions& options, ColumnFamilyHandle* column_family,
|
||||
const Slice& key, PinnableSlice* value,
|
||||
bool* value_found = nullptr);
|
||||
|
||||
bool GetIntPropertyInternal(ColumnFamilyData* cfd,
|
||||
const DBPropertyInfo& property_info,
|
||||
bool is_locked, uint64_t* value);
|
||||
|
||||
bool HasPendingManualCompaction();
|
||||
bool HasExclusiveManualCompaction();
|
||||
void AddManualCompaction(ManualCompactionState* m);
|
||||
void RemoveManualCompaction(ManualCompactionState* m);
|
||||
bool ShouldntRunManualCompaction(ManualCompactionState* m);
|
||||
void AddManualCompaction(ManualCompaction* m);
|
||||
void RemoveManualCompaction(ManualCompaction* m);
|
||||
bool ShouldntRunManualCompaction(ManualCompaction* m);
|
||||
bool HaveManualCompaction(ColumnFamilyData* cfd);
|
||||
bool MCOverlap(ManualCompactionState* m, ManualCompactionState* m1);
|
||||
bool MCOverlap(ManualCompaction* m, ManualCompaction* m1);
|
||||
|
||||
size_t GetWalPreallocateBlockSize(uint64_t write_buffer_size) const;
|
||||
|
||||
// When set, we use a seprate queue for writes that dont write to memtable. In
|
||||
// 2PC these are the writes at Prepare phase.
|
||||
const bool concurrent_prepare_;
|
||||
const bool manual_wal_flush_;
|
||||
};
|
||||
|
||||
extern Options SanitizeOptions(const std::string& db,
|
||||
@@ -1290,7 +1173,7 @@ extern DBOptions SanitizeOptions(const std::string& db, const DBOptions& src);
|
||||
extern CompressionType GetCompressionFlush(
|
||||
const ImmutableCFOptions& ioptions,
|
||||
const MutableCFOptions& mutable_cf_options);
|
||||
|
||||
|
||||
// Fix user-supplied options to be reasonable
|
||||
template <class T, class V>
|
||||
static void ClipToRange(T* ptr, V minvalue, V maxvalue) {
|
||||
|
||||
+72
-197
@@ -14,7 +14,6 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "db/builder.h"
|
||||
#include "db/event_helpers.h"
|
||||
#include "monitoring/iostats_context_imp.h"
|
||||
#include "monitoring/perf_context_imp.h"
|
||||
#include "monitoring/thread_status_updater.h"
|
||||
@@ -60,14 +59,7 @@ Status DBImpl::SyncClosedLogs(JobContext* job_context) {
|
||||
// "number < current_log_number".
|
||||
MarkLogsSynced(current_log_number - 1, true, s);
|
||||
if (!s.ok()) {
|
||||
Status new_bg_error = s;
|
||||
// may temporarily unlock and lock the mutex.
|
||||
EventHelpers::NotifyOnBackgroundError(immutable_db_options_.listeners,
|
||||
BackgroundErrorReason::kFlush,
|
||||
&new_bg_error, &mutex_);
|
||||
if (!new_bg_error.ok()) {
|
||||
bg_error_ = new_bg_error;
|
||||
}
|
||||
bg_error_ = s;
|
||||
TEST_SYNC_POINT("DBImpl::SyncClosedLogs:Failed");
|
||||
return s;
|
||||
}
|
||||
@@ -142,16 +134,9 @@ Status DBImpl::FlushMemTableToOutputFile(
|
||||
|
||||
if (!s.ok() && !s.IsShutdownInProgress() &&
|
||||
immutable_db_options_.paranoid_checks && bg_error_.ok()) {
|
||||
Status new_bg_error = s;
|
||||
// may temporarily unlock and lock the mutex.
|
||||
EventHelpers::NotifyOnBackgroundError(immutable_db_options_.listeners,
|
||||
BackgroundErrorReason::kFlush,
|
||||
&new_bg_error, &mutex_);
|
||||
if (!new_bg_error.ok()) {
|
||||
// if a bad error happened (not ShutdownInProgress), paranoid_checks is
|
||||
// true, and the error isn't handled by callback, mark DB read-only
|
||||
bg_error_ = new_bg_error;
|
||||
}
|
||||
// if a bad error happened (not ShutdownInProgress) and paranoid_checks is
|
||||
// true, mark DB read-only
|
||||
bg_error_ = s;
|
||||
}
|
||||
if (s.ok()) {
|
||||
#ifndef ROCKSDB_LITE
|
||||
@@ -166,17 +151,10 @@ Status DBImpl::FlushMemTableToOutputFile(
|
||||
immutable_db_options_.db_paths[0].path, file_meta.fd.GetNumber());
|
||||
sfm->OnAddFile(file_path);
|
||||
if (sfm->IsMaxAllowedSpaceReached() && bg_error_.ok()) {
|
||||
Status new_bg_error = Status::IOError("Max allowed space was reached");
|
||||
bg_error_ = Status::IOError("Max allowed space was reached");
|
||||
TEST_SYNC_POINT_CALLBACK(
|
||||
"DBImpl::FlushMemTableToOutputFile:MaxAllowedSpaceReached",
|
||||
&new_bg_error);
|
||||
// may temporarily unlock and lock the mutex.
|
||||
EventHelpers::NotifyOnBackgroundError(immutable_db_options_.listeners,
|
||||
BackgroundErrorReason::kFlush,
|
||||
&new_bg_error, &mutex_);
|
||||
if (!new_bg_error.ok()) {
|
||||
bg_error_ = new_bg_error;
|
||||
}
|
||||
&bg_error_);
|
||||
}
|
||||
}
|
||||
#endif // ROCKSDB_LITE
|
||||
@@ -304,14 +282,10 @@ Status DBImpl::CompactRange(const CompactRangeOptions& options,
|
||||
if (cfd->ioptions()->compaction_style == kCompactionStyleUniversal &&
|
||||
cfd->NumberLevels() > 1) {
|
||||
// Always compact all files together.
|
||||
final_output_level = cfd->NumberLevels() - 1;
|
||||
// if bottom most level is reserved
|
||||
if (immutable_db_options_.allow_ingest_behind) {
|
||||
final_output_level--;
|
||||
}
|
||||
s = RunManualCompaction(cfd, ColumnFamilyData::kCompactAllLevels,
|
||||
final_output_level, options.target_path_id,
|
||||
cfd->NumberLevels() - 1, options.target_path_id,
|
||||
begin, end, exclusive);
|
||||
final_output_level = cfd->NumberLevels() - 1;
|
||||
} else {
|
||||
for (int level = 0; level <= max_level_with_files; level++) {
|
||||
int output_level;
|
||||
@@ -587,14 +561,7 @@ Status DBImpl::CompactFilesImpl(
|
||||
c->column_family_data()->GetName().c_str(),
|
||||
job_context->job_id, status.ToString().c_str());
|
||||
if (immutable_db_options_.paranoid_checks && bg_error_.ok()) {
|
||||
Status new_bg_error = status;
|
||||
// may temporarily unlock and lock the mutex.
|
||||
EventHelpers::NotifyOnBackgroundError(immutable_db_options_.listeners,
|
||||
BackgroundErrorReason::kCompaction,
|
||||
&new_bg_error, &mutex_);
|
||||
if (!new_bg_error.ok()) {
|
||||
bg_error_ = new_bg_error;
|
||||
}
|
||||
bg_error_ = status;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -612,8 +579,7 @@ Status DBImpl::CompactFilesImpl(
|
||||
Status DBImpl::PauseBackgroundWork() {
|
||||
InstrumentedMutexLock guard_lock(&mutex_);
|
||||
bg_compaction_paused_++;
|
||||
while (bg_bottom_compaction_scheduled_ > 0 || bg_compaction_scheduled_ > 0 ||
|
||||
bg_flush_scheduled_ > 0) {
|
||||
while (bg_compaction_scheduled_ > 0 || bg_flush_scheduled_ > 0) {
|
||||
bg_cv_.Wait();
|
||||
}
|
||||
bg_work_paused_++;
|
||||
@@ -809,7 +775,7 @@ Status DBImpl::RunManualCompaction(ColumnFamilyData* cfd, int input_level,
|
||||
|
||||
bool scheduled = false;
|
||||
bool manual_conflict = false;
|
||||
ManualCompactionState manual;
|
||||
ManualCompaction manual;
|
||||
manual.cfd = cfd;
|
||||
manual.input_level = input_level;
|
||||
manual.output_level = output_level;
|
||||
@@ -859,8 +825,7 @@ Status DBImpl::RunManualCompaction(ColumnFamilyData* cfd, int input_level,
|
||||
AddManualCompaction(&manual);
|
||||
TEST_SYNC_POINT_CALLBACK("DBImpl::RunManualCompaction:NotScheduled", &mutex_);
|
||||
if (exclusive) {
|
||||
while (bg_bottom_compaction_scheduled_ > 0 ||
|
||||
bg_compaction_scheduled_ > 0) {
|
||||
while (bg_compaction_scheduled_ > 0) {
|
||||
TEST_SYNC_POINT("DBImpl::RunManualCompaction:WaitScheduled");
|
||||
ROCKS_LOG_INFO(
|
||||
immutable_db_options_.info_log,
|
||||
@@ -880,14 +845,14 @@ Status DBImpl::RunManualCompaction(ColumnFamilyData* cfd, int input_level,
|
||||
while (!manual.done) {
|
||||
assert(HasPendingManualCompaction());
|
||||
manual_conflict = false;
|
||||
Compaction* compaction;
|
||||
if (ShouldntRunManualCompaction(&manual) || (manual.in_progress == true) ||
|
||||
scheduled ||
|
||||
((manual.manual_end = &manual.tmp_storage1) &&
|
||||
((compaction = manual.cfd->CompactRange(
|
||||
*manual.cfd->GetLatestMutableCFOptions(), manual.input_level,
|
||||
manual.output_level, manual.output_path_id, manual.begin,
|
||||
manual.end, &manual.manual_end, &manual_conflict)) == nullptr) &&
|
||||
((manual.manual_end = &manual.tmp_storage1)&&(
|
||||
(manual.compaction = manual.cfd->CompactRange(
|
||||
*manual.cfd->GetLatestMutableCFOptions(), manual.input_level,
|
||||
manual.output_level, manual.output_path_id, manual.begin,
|
||||
manual.end, &manual.manual_end, &manual_conflict)) ==
|
||||
nullptr) &&
|
||||
manual_conflict)) {
|
||||
// exclusive manual compactions should not see a conflict during
|
||||
// CompactRange
|
||||
@@ -900,16 +865,14 @@ Status DBImpl::RunManualCompaction(ColumnFamilyData* cfd, int input_level,
|
||||
manual.incomplete = false;
|
||||
}
|
||||
} else if (!scheduled) {
|
||||
if (compaction == nullptr) {
|
||||
if (manual.compaction == nullptr) {
|
||||
manual.done = true;
|
||||
bg_cv_.SignalAll();
|
||||
continue;
|
||||
}
|
||||
ca = new CompactionArg;
|
||||
ca->db = this;
|
||||
ca->prepicked_compaction = new PrepickedCompaction;
|
||||
ca->prepicked_compaction->manual_compaction_state = &manual;
|
||||
ca->prepicked_compaction->compaction = compaction;
|
||||
ca->m = &manual;
|
||||
manual.incomplete = false;
|
||||
bg_compaction_scheduled_++;
|
||||
env_->Schedule(&DBImpl::BGWorkCompaction, ca, Env::Priority::LOW, this,
|
||||
@@ -1014,22 +977,22 @@ void DBImpl::MaybeScheduleFlushOrCompaction() {
|
||||
// DB is being deleted; no more background compactions
|
||||
return;
|
||||
}
|
||||
auto bg_job_limits = GetBGJobLimits();
|
||||
bool is_flush_pool_empty =
|
||||
env_->GetBackgroundThreads(Env::Priority::HIGH) == 0;
|
||||
while (!is_flush_pool_empty && unscheduled_flushes_ > 0 &&
|
||||
bg_flush_scheduled_ < bg_job_limits.max_flushes) {
|
||||
|
||||
while (unscheduled_flushes_ > 0 &&
|
||||
bg_flush_scheduled_ < immutable_db_options_.max_background_flushes) {
|
||||
unscheduled_flushes_--;
|
||||
bg_flush_scheduled_++;
|
||||
env_->Schedule(&DBImpl::BGWorkFlush, this, Env::Priority::HIGH, this);
|
||||
}
|
||||
|
||||
// special case -- if high-pri (flush) thread pool is empty, then schedule
|
||||
// flushes in low-pri (compaction) thread pool.
|
||||
if (is_flush_pool_empty) {
|
||||
auto bg_compactions_allowed = BGCompactionsAllowed();
|
||||
|
||||
// special case -- if max_background_flushes == 0, then schedule flush on a
|
||||
// compaction thread
|
||||
if (immutable_db_options_.max_background_flushes == 0) {
|
||||
while (unscheduled_flushes_ > 0 &&
|
||||
bg_flush_scheduled_ + bg_compaction_scheduled_ <
|
||||
bg_job_limits.max_flushes) {
|
||||
bg_compactions_allowed) {
|
||||
unscheduled_flushes_--;
|
||||
bg_flush_scheduled_++;
|
||||
env_->Schedule(&DBImpl::BGWorkFlush, this, Env::Priority::LOW, this);
|
||||
@@ -1047,11 +1010,11 @@ void DBImpl::MaybeScheduleFlushOrCompaction() {
|
||||
return;
|
||||
}
|
||||
|
||||
while (bg_compaction_scheduled_ < bg_job_limits.max_compactions &&
|
||||
while (bg_compaction_scheduled_ < bg_compactions_allowed &&
|
||||
unscheduled_compactions_ > 0) {
|
||||
CompactionArg* ca = new CompactionArg;
|
||||
ca->db = this;
|
||||
ca->prepicked_compaction = nullptr;
|
||||
ca->m = nullptr;
|
||||
bg_compaction_scheduled_++;
|
||||
unscheduled_compactions_--;
|
||||
env_->Schedule(&DBImpl::BGWorkCompaction, ca, Env::Priority::LOW, this,
|
||||
@@ -1059,35 +1022,13 @@ void DBImpl::MaybeScheduleFlushOrCompaction() {
|
||||
}
|
||||
}
|
||||
|
||||
DBImpl::BGJobLimits DBImpl::GetBGJobLimits() const {
|
||||
int DBImpl::BGCompactionsAllowed() const {
|
||||
mutex_.AssertHeld();
|
||||
return GetBGJobLimits(immutable_db_options_.max_background_flushes,
|
||||
mutable_db_options_.max_background_compactions,
|
||||
mutable_db_options_.max_background_jobs,
|
||||
write_controller_.NeedSpeedupCompaction());
|
||||
}
|
||||
|
||||
DBImpl::BGJobLimits DBImpl::GetBGJobLimits(int max_background_flushes,
|
||||
int max_background_compactions,
|
||||
int max_background_jobs,
|
||||
bool parallelize_compactions) {
|
||||
BGJobLimits res;
|
||||
if (max_background_flushes == -1 && max_background_compactions == -1) {
|
||||
// for our first stab implementing max_background_jobs, simply allocate a
|
||||
// quarter of the threads to flushes.
|
||||
res.max_flushes = std::max(1, max_background_jobs / 4);
|
||||
res.max_compactions = std::max(1, max_background_jobs - res.max_flushes);
|
||||
if (write_controller_.NeedSpeedupCompaction()) {
|
||||
return mutable_db_options_.max_background_compactions;
|
||||
} else {
|
||||
// compatibility code in case users haven't migrated to max_background_jobs,
|
||||
// which automatically computes flush/compaction limits
|
||||
res.max_flushes = std::max(1, max_background_flushes);
|
||||
res.max_compactions = std::max(1, max_background_compactions);
|
||||
return mutable_db_options_.base_background_compactions;
|
||||
}
|
||||
if (!parallelize_compactions) {
|
||||
// throttle background compactions until we deem necessary
|
||||
res.max_compactions = 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void DBImpl::AddToCompactionQueue(ColumnFamilyData* cfd) {
|
||||
@@ -1156,23 +1097,7 @@ void DBImpl::BGWorkCompaction(void* arg) {
|
||||
delete reinterpret_cast<CompactionArg*>(arg);
|
||||
IOSTATS_SET_THREAD_POOL_ID(Env::Priority::LOW);
|
||||
TEST_SYNC_POINT("DBImpl::BGWorkCompaction");
|
||||
auto prepicked_compaction =
|
||||
static_cast<PrepickedCompaction*>(ca.prepicked_compaction);
|
||||
reinterpret_cast<DBImpl*>(ca.db)->BackgroundCallCompaction(
|
||||
prepicked_compaction, Env::Priority::LOW);
|
||||
delete prepicked_compaction;
|
||||
}
|
||||
|
||||
void DBImpl::BGWorkBottomCompaction(void* arg) {
|
||||
CompactionArg ca = *(static_cast<CompactionArg*>(arg));
|
||||
delete static_cast<CompactionArg*>(arg);
|
||||
IOSTATS_SET_THREAD_POOL_ID(Env::Priority::BOTTOM);
|
||||
TEST_SYNC_POINT("DBImpl::BGWorkBottomCompaction");
|
||||
auto* prepicked_compaction = ca.prepicked_compaction;
|
||||
assert(prepicked_compaction && prepicked_compaction->compaction &&
|
||||
!prepicked_compaction->manual_compaction_state);
|
||||
ca.db->BackgroundCallCompaction(prepicked_compaction, Env::Priority::BOTTOM);
|
||||
delete prepicked_compaction;
|
||||
reinterpret_cast<DBImpl*>(ca.db)->BackgroundCallCompaction(ca.m);
|
||||
}
|
||||
|
||||
void DBImpl::BGWorkPurge(void* db) {
|
||||
@@ -1185,11 +1110,8 @@ void DBImpl::BGWorkPurge(void* db) {
|
||||
void DBImpl::UnscheduleCallback(void* arg) {
|
||||
CompactionArg ca = *(reinterpret_cast<CompactionArg*>(arg));
|
||||
delete reinterpret_cast<CompactionArg*>(arg);
|
||||
if (ca.prepicked_compaction != nullptr) {
|
||||
if (ca.prepicked_compaction->compaction != nullptr) {
|
||||
delete ca.prepicked_compaction->compaction;
|
||||
}
|
||||
delete ca.prepicked_compaction;
|
||||
if ((ca.m != nullptr) && (ca.m->compaction != nullptr)) {
|
||||
delete ca.m->compaction;
|
||||
}
|
||||
TEST_SYNC_POINT("DBImpl::UnscheduleCallback");
|
||||
}
|
||||
@@ -1228,15 +1150,13 @@ Status DBImpl::BackgroundFlush(bool* made_progress, JobContext* job_context,
|
||||
if (cfd != nullptr) {
|
||||
const MutableCFOptions mutable_cf_options =
|
||||
*cfd->GetLatestMutableCFOptions();
|
||||
auto bg_job_limits = GetBGJobLimits();
|
||||
ROCKS_LOG_BUFFER(
|
||||
log_buffer,
|
||||
"Calling FlushMemTableToOutputFile with column "
|
||||
"family [%s], flush slots available %d, compaction slots available %d, "
|
||||
"flush slots scheduled %d, compaction slots scheduled %d",
|
||||
cfd->GetName().c_str(), bg_job_limits.max_flushes,
|
||||
bg_job_limits.max_compactions, bg_flush_scheduled_,
|
||||
bg_compaction_scheduled_);
|
||||
"family [%s], flush slots available %d, compaction slots allowed %d, "
|
||||
"compaction slots scheduled %d",
|
||||
cfd->GetName().c_str(), immutable_db_options_.max_background_flushes,
|
||||
bg_flush_scheduled_, BGCompactionsAllowed() - bg_compaction_scheduled_);
|
||||
status = FlushMemTableToOutputFile(cfd, mutable_cf_options, made_progress,
|
||||
job_context, log_buffer);
|
||||
if (cfd->Unref()) {
|
||||
@@ -1249,6 +1169,7 @@ Status DBImpl::BackgroundFlush(bool* made_progress, JobContext* job_context,
|
||||
void DBImpl::BackgroundCallFlush() {
|
||||
bool made_progress = false;
|
||||
JobContext job_context(next_job_id_.fetch_add(1), true);
|
||||
assert(bg_flush_scheduled_);
|
||||
|
||||
TEST_SYNC_POINT("DBImpl::BackgroundCallFlush:start");
|
||||
|
||||
@@ -1256,7 +1177,6 @@ void DBImpl::BackgroundCallFlush() {
|
||||
immutable_db_options_.info_log.get());
|
||||
{
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
assert(bg_flush_scheduled_);
|
||||
num_running_flushes_++;
|
||||
|
||||
auto pending_outputs_inserted_elem =
|
||||
@@ -1316,9 +1236,9 @@ void DBImpl::BackgroundCallFlush() {
|
||||
}
|
||||
}
|
||||
|
||||
void DBImpl::BackgroundCallCompaction(PrepickedCompaction* prepicked_compaction,
|
||||
Env::Priority bg_thread_pri) {
|
||||
void DBImpl::BackgroundCallCompaction(void* arg) {
|
||||
bool made_progress = false;
|
||||
ManualCompaction* m = reinterpret_cast<ManualCompaction*>(arg);
|
||||
JobContext job_context(next_job_id_.fetch_add(1), true);
|
||||
TEST_SYNC_POINT("BackgroundCallCompaction:0");
|
||||
MaybeDumpStats();
|
||||
@@ -1336,11 +1256,9 @@ void DBImpl::BackgroundCallCompaction(PrepickedCompaction* prepicked_compaction,
|
||||
auto pending_outputs_inserted_elem =
|
||||
CaptureCurrentFileNumberInPendingOutputs();
|
||||
|
||||
assert((bg_thread_pri == Env::Priority::BOTTOM &&
|
||||
bg_bottom_compaction_scheduled_) ||
|
||||
(bg_thread_pri == Env::Priority::LOW && bg_compaction_scheduled_));
|
||||
Status s = BackgroundCompaction(&made_progress, &job_context, &log_buffer,
|
||||
prepicked_compaction);
|
||||
assert(bg_compaction_scheduled_);
|
||||
Status s =
|
||||
BackgroundCompaction(&made_progress, &job_context, &log_buffer, m);
|
||||
TEST_SYNC_POINT("BackgroundCallCompaction:1");
|
||||
if (!s.ok() && !s.IsShutdownInProgress()) {
|
||||
// Wait a little bit before retrying background compaction in
|
||||
@@ -1386,24 +1304,17 @@ void DBImpl::BackgroundCallCompaction(PrepickedCompaction* prepicked_compaction,
|
||||
|
||||
assert(num_running_compactions_ > 0);
|
||||
num_running_compactions_--;
|
||||
if (bg_thread_pri == Env::Priority::LOW) {
|
||||
bg_compaction_scheduled_--;
|
||||
} else {
|
||||
assert(bg_thread_pri == Env::Priority::BOTTOM);
|
||||
bg_bottom_compaction_scheduled_--;
|
||||
}
|
||||
bg_compaction_scheduled_--;
|
||||
|
||||
versions_->GetColumnFamilySet()->FreeDeadColumnFamilies();
|
||||
|
||||
// See if there's more work to be done
|
||||
MaybeScheduleFlushOrCompaction();
|
||||
if (made_progress ||
|
||||
(bg_compaction_scheduled_ == 0 &&
|
||||
bg_bottom_compaction_scheduled_ == 0) ||
|
||||
if (made_progress || bg_compaction_scheduled_ == 0 ||
|
||||
HasPendingManualCompaction()) {
|
||||
// signal if
|
||||
// * made_progress -- need to wakeup DelayWrite
|
||||
// * bg_{bottom,}_compaction_scheduled_ == 0 -- need to wakeup ~DBImpl
|
||||
// * bg_compaction_scheduled_ == 0 -- need to wakeup ~DBImpl
|
||||
// * HasPendingManualCompaction -- need to wakeup RunManualCompaction
|
||||
// If none of this is true, there is no need to signal since nobody is
|
||||
// waiting for it
|
||||
@@ -1418,23 +1329,14 @@ void DBImpl::BackgroundCallCompaction(PrepickedCompaction* prepicked_compaction,
|
||||
|
||||
Status DBImpl::BackgroundCompaction(bool* made_progress,
|
||||
JobContext* job_context,
|
||||
LogBuffer* log_buffer,
|
||||
PrepickedCompaction* prepicked_compaction) {
|
||||
ManualCompactionState* manual_compaction =
|
||||
prepicked_compaction == nullptr
|
||||
? nullptr
|
||||
: prepicked_compaction->manual_compaction_state;
|
||||
LogBuffer* log_buffer, void* arg) {
|
||||
ManualCompaction* manual_compaction =
|
||||
reinterpret_cast<ManualCompaction*>(arg);
|
||||
*made_progress = false;
|
||||
mutex_.AssertHeld();
|
||||
TEST_SYNC_POINT("DBImpl::BackgroundCompaction:Start");
|
||||
|
||||
bool is_manual = (manual_compaction != nullptr);
|
||||
unique_ptr<Compaction> c;
|
||||
if (prepicked_compaction != nullptr &&
|
||||
prepicked_compaction->compaction != nullptr) {
|
||||
c.reset(prepicked_compaction->compaction);
|
||||
}
|
||||
bool is_prepicked = is_manual || c;
|
||||
|
||||
// (manual_compaction->in_progress == false);
|
||||
bool trivial_move_disallowed =
|
||||
@@ -1451,6 +1353,7 @@ Status DBImpl::BackgroundCompaction(bool* made_progress,
|
||||
manual_compaction->status = status;
|
||||
manual_compaction->done = true;
|
||||
manual_compaction->in_progress = false;
|
||||
delete manual_compaction->compaction;
|
||||
manual_compaction = nullptr;
|
||||
}
|
||||
return status;
|
||||
@@ -1461,11 +1364,13 @@ Status DBImpl::BackgroundCompaction(bool* made_progress,
|
||||
manual_compaction->in_progress = true;
|
||||
}
|
||||
|
||||
unique_ptr<Compaction> c;
|
||||
// InternalKey manual_end_storage;
|
||||
// InternalKey* manual_end = &manual_end_storage;
|
||||
if (is_manual) {
|
||||
ManualCompactionState* m = manual_compaction;
|
||||
ManualCompaction* m = manual_compaction;
|
||||
assert(m->in_progress);
|
||||
c.reset(std::move(m->compaction));
|
||||
if (!c) {
|
||||
m->done = true;
|
||||
m->manual_end = nullptr;
|
||||
@@ -1487,12 +1392,12 @@ Status DBImpl::BackgroundCompaction(bool* made_progress,
|
||||
? "(end)"
|
||||
: m->manual_end->DebugString().c_str()));
|
||||
}
|
||||
} else if (!is_prepicked && !compaction_queue_.empty()) {
|
||||
} else if (!compaction_queue_.empty()) {
|
||||
if (HaveManualCompaction(compaction_queue_.front())) {
|
||||
// Can't compact right now, but try again later
|
||||
TEST_SYNC_POINT("DBImpl::BackgroundCompaction()::Conflict");
|
||||
|
||||
// Stay in the compaction queue.
|
||||
// Stay in the compaciton queue.
|
||||
unscheduled_compactions_++;
|
||||
|
||||
return Status::OK();
|
||||
@@ -1639,28 +1544,6 @@ Status DBImpl::BackgroundCompaction(bool* made_progress,
|
||||
|
||||
// Clear Instrument
|
||||
ThreadStatusUtil::ResetThreadStatus();
|
||||
} else if (c->column_family_data()->ioptions()->compaction_style ==
|
||||
kCompactionStyleUniversal &&
|
||||
!is_prepicked && c->output_level() > 0 &&
|
||||
c->output_level() ==
|
||||
c->column_family_data()
|
||||
->current()
|
||||
->storage_info()
|
||||
->MaxOutputLevel(
|
||||
immutable_db_options_.allow_ingest_behind) &&
|
||||
env_->GetBackgroundThreads(Env::Priority::BOTTOM) > 0) {
|
||||
// Forward universal compactions involving last level to the bottom pool
|
||||
// if it exists, such that long-running compactions can't block short-
|
||||
// lived ones, like L0->L0s.
|
||||
TEST_SYNC_POINT("DBImpl::BackgroundCompaction:ForwardToBottomPriPool");
|
||||
CompactionArg* ca = new CompactionArg;
|
||||
ca->db = this;
|
||||
ca->prepicked_compaction = new PrepickedCompaction;
|
||||
ca->prepicked_compaction->compaction = c.release();
|
||||
ca->prepicked_compaction->manual_compaction_state = nullptr;
|
||||
++bg_bottom_compaction_scheduled_;
|
||||
env_->Schedule(&DBImpl::BGWorkBottomCompaction, ca, Env::Priority::BOTTOM,
|
||||
this, &DBImpl::UnscheduleCallback);
|
||||
} else {
|
||||
int output_level __attribute__((unused)) = c->output_level();
|
||||
TEST_SYNC_POINT_CALLBACK("DBImpl::BackgroundCompaction:NonTrivial",
|
||||
@@ -1712,19 +1595,12 @@ Status DBImpl::BackgroundCompaction(bool* made_progress,
|
||||
ROCKS_LOG_WARN(immutable_db_options_.info_log, "Compaction error: %s",
|
||||
status.ToString().c_str());
|
||||
if (immutable_db_options_.paranoid_checks && bg_error_.ok()) {
|
||||
Status new_bg_error = status;
|
||||
// may temporarily unlock and lock the mutex.
|
||||
EventHelpers::NotifyOnBackgroundError(immutable_db_options_.listeners,
|
||||
BackgroundErrorReason::kCompaction,
|
||||
&new_bg_error, &mutex_);
|
||||
if (!new_bg_error.ok()) {
|
||||
bg_error_ = new_bg_error;
|
||||
}
|
||||
bg_error_ = status;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_manual) {
|
||||
ManualCompactionState* m = manual_compaction;
|
||||
ManualCompaction* m = manual_compaction;
|
||||
if (!status.ok()) {
|
||||
m->status = status;
|
||||
m->done = true;
|
||||
@@ -1767,13 +1643,13 @@ bool DBImpl::HasPendingManualCompaction() {
|
||||
return (!manual_compaction_dequeue_.empty());
|
||||
}
|
||||
|
||||
void DBImpl::AddManualCompaction(DBImpl::ManualCompactionState* m) {
|
||||
void DBImpl::AddManualCompaction(DBImpl::ManualCompaction* m) {
|
||||
manual_compaction_dequeue_.push_back(m);
|
||||
}
|
||||
|
||||
void DBImpl::RemoveManualCompaction(DBImpl::ManualCompactionState* m) {
|
||||
void DBImpl::RemoveManualCompaction(DBImpl::ManualCompaction* m) {
|
||||
// Remove from queue
|
||||
std::deque<ManualCompactionState*>::iterator it =
|
||||
std::deque<ManualCompaction*>::iterator it =
|
||||
manual_compaction_dequeue_.begin();
|
||||
while (it != manual_compaction_dequeue_.end()) {
|
||||
if (m == (*it)) {
|
||||
@@ -1786,17 +1662,16 @@ void DBImpl::RemoveManualCompaction(DBImpl::ManualCompactionState* m) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool DBImpl::ShouldntRunManualCompaction(ManualCompactionState* m) {
|
||||
bool DBImpl::ShouldntRunManualCompaction(ManualCompaction* m) {
|
||||
if (num_running_ingest_file_ > 0) {
|
||||
// We need to wait for other IngestExternalFile() calls to finish
|
||||
// before running a manual compaction.
|
||||
return true;
|
||||
}
|
||||
if (m->exclusive) {
|
||||
return (bg_bottom_compaction_scheduled_ > 0 ||
|
||||
bg_compaction_scheduled_ > 0);
|
||||
return (bg_compaction_scheduled_ > 0);
|
||||
}
|
||||
std::deque<ManualCompactionState*>::iterator it =
|
||||
std::deque<ManualCompaction*>::iterator it =
|
||||
manual_compaction_dequeue_.begin();
|
||||
bool seen = false;
|
||||
while (it != manual_compaction_dequeue_.end()) {
|
||||
@@ -1817,7 +1692,7 @@ bool DBImpl::ShouldntRunManualCompaction(ManualCompactionState* m) {
|
||||
|
||||
bool DBImpl::HaveManualCompaction(ColumnFamilyData* cfd) {
|
||||
// Remove from priority queue
|
||||
std::deque<ManualCompactionState*>::iterator it =
|
||||
std::deque<ManualCompaction*>::iterator it =
|
||||
manual_compaction_dequeue_.begin();
|
||||
while (it != manual_compaction_dequeue_.end()) {
|
||||
if ((*it)->exclusive) {
|
||||
@@ -1825,7 +1700,7 @@ bool DBImpl::HaveManualCompaction(ColumnFamilyData* cfd) {
|
||||
}
|
||||
if ((cfd == (*it)->cfd) && (!((*it)->in_progress || (*it)->done))) {
|
||||
// Allow automatic compaction if manual compaction is
|
||||
// in progress
|
||||
// is in progress
|
||||
return true;
|
||||
}
|
||||
it++;
|
||||
@@ -1835,7 +1710,7 @@ bool DBImpl::HaveManualCompaction(ColumnFamilyData* cfd) {
|
||||
|
||||
bool DBImpl::HasExclusiveManualCompaction() {
|
||||
// Remove from priority queue
|
||||
std::deque<ManualCompactionState*>::iterator it =
|
||||
std::deque<ManualCompaction*>::iterator it =
|
||||
manual_compaction_dequeue_.begin();
|
||||
while (it != manual_compaction_dequeue_.end()) {
|
||||
if ((*it)->exclusive) {
|
||||
@@ -1846,7 +1721,7 @@ bool DBImpl::HasExclusiveManualCompaction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DBImpl::MCOverlap(ManualCompactionState* m, ManualCompactionState* m1) {
|
||||
bool DBImpl::MCOverlap(ManualCompaction* m, ManualCompaction* m1) {
|
||||
if ((m->exclusive) || (m1->exclusive)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
+2
-18
@@ -80,15 +80,6 @@ Status DBImpl::TEST_CompactRange(int level, const Slice* begin,
|
||||
disallow_trivial_move);
|
||||
}
|
||||
|
||||
Status DBImpl::TEST_SwitchMemtable(ColumnFamilyData* cfd) {
|
||||
WriteContext write_context;
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
if (cfd == nullptr) {
|
||||
cfd = default_cf_handle_->cfd();
|
||||
}
|
||||
return SwitchMemtable(cfd, &write_context);
|
||||
}
|
||||
|
||||
Status DBImpl::TEST_FlushMemTable(bool wait, ColumnFamilyHandle* cfh) {
|
||||
FlushOptions fo;
|
||||
fo.wait = wait;
|
||||
@@ -121,9 +112,7 @@ Status DBImpl::TEST_WaitForCompact() {
|
||||
// OR flush to finish.
|
||||
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
while ((bg_bottom_compaction_scheduled_ || bg_compaction_scheduled_ ||
|
||||
bg_flush_scheduled_) &&
|
||||
bg_error_.ok()) {
|
||||
while ((bg_compaction_scheduled_ || bg_flush_scheduled_) && bg_error_.ok()) {
|
||||
bg_cv_.Wait();
|
||||
}
|
||||
return bg_error_;
|
||||
@@ -197,12 +186,7 @@ Status DBImpl::TEST_GetLatestMutableCFOptions(
|
||||
|
||||
int DBImpl::TEST_BGCompactionsAllowed() const {
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
return GetBGJobLimits().max_compactions;
|
||||
}
|
||||
|
||||
int DBImpl::TEST_BGFlushesAllowed() const {
|
||||
InstrumentedMutexLock l(&mutex_);
|
||||
return GetBGJobLimits().max_flushes;
|
||||
return BGCompactionsAllowed();
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
+1
-13
@@ -250,13 +250,7 @@ void DBImpl::FindObsoleteFiles(JobContext* job_context, bool force,
|
||||
}
|
||||
job_context->size_log_to_delete += earliest.size;
|
||||
total_log_size_ -= earliest.size;
|
||||
if (concurrent_prepare_) {
|
||||
log_write_mutex_.Lock();
|
||||
}
|
||||
alive_log_files_.pop_front();
|
||||
if (concurrent_prepare_) {
|
||||
log_write_mutex_.Unlock();
|
||||
}
|
||||
// Current log should always stay alive since it can't have
|
||||
// number < MinLogNumber().
|
||||
assert(alive_log_files_.size());
|
||||
@@ -269,10 +263,7 @@ void DBImpl::FindObsoleteFiles(JobContext* job_context, bool force,
|
||||
continue;
|
||||
}
|
||||
logs_to_free_.push_back(log.ReleaseWriter());
|
||||
{
|
||||
InstrumentedMutexLock wl(&log_write_mutex_);
|
||||
logs_.pop_front();
|
||||
}
|
||||
logs_.pop_front();
|
||||
}
|
||||
// Current log cannot be obsolete.
|
||||
assert(!logs_.empty());
|
||||
@@ -368,9 +359,6 @@ void DBImpl::PurgeObsoleteFiles(const JobContext& state, bool schedule_only) {
|
||||
candidate_files.emplace_back(
|
||||
MakeTableFileName(kDumbDbName, file->fd.GetNumber()),
|
||||
file->fd.GetPathId());
|
||||
if (file->table_reader_handle) {
|
||||
table_cache_->Release(file->table_reader_handle);
|
||||
}
|
||||
delete file;
|
||||
}
|
||||
|
||||
|
||||
+20
-65
@@ -16,8 +16,6 @@
|
||||
#include "db/builder.h"
|
||||
#include "options/options_helper.h"
|
||||
#include "rocksdb/wal_filter.h"
|
||||
#include "table/block_based_table_factory.h"
|
||||
#include "util/rate_limiter.h"
|
||||
#include "util/sst_file_manager_impl.h"
|
||||
#include "util/sync_point.h"
|
||||
|
||||
@@ -38,7 +36,7 @@ DBOptions SanitizeOptions(const std::string& dbname, const DBOptions& src) {
|
||||
if (result.max_open_files != -1) {
|
||||
int max_max_open_files = port::GetMaxOpenFiles();
|
||||
if (max_max_open_files == -1) {
|
||||
max_max_open_files = 0x400000;
|
||||
max_max_open_files = 1000000;
|
||||
}
|
||||
ClipToRange(&result.max_open_files, 20, max_max_open_files);
|
||||
}
|
||||
@@ -55,13 +53,15 @@ DBOptions SanitizeOptions(const std::string& dbname, const DBOptions& src) {
|
||||
result.write_buffer_manager.reset(
|
||||
new WriteBufferManager(result.db_write_buffer_size));
|
||||
}
|
||||
auto bg_job_limits = DBImpl::GetBGJobLimits(result.max_background_flushes,
|
||||
result.max_background_compactions,
|
||||
result.max_background_jobs,
|
||||
true /* parallelize_compactions */);
|
||||
result.env->IncBackgroundThreadsIfNeeded(bg_job_limits.max_compactions,
|
||||
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(bg_job_limits.max_flushes,
|
||||
result.env->IncBackgroundThreadsIfNeeded(src.max_background_flushes,
|
||||
Env::Priority::HIGH);
|
||||
|
||||
if (result.rate_limiter.get() != nullptr) {
|
||||
@@ -70,15 +70,6 @@ DBOptions SanitizeOptions(const std::string& dbname, const DBOptions& src) {
|
||||
}
|
||||
}
|
||||
|
||||
if (result.delayed_write_rate == 0) {
|
||||
if (result.rate_limiter.get() != nullptr) {
|
||||
result.delayed_write_rate = result.rate_limiter->GetBytesPerSecond();
|
||||
}
|
||||
if (result.delayed_write_rate == 0) {
|
||||
result.delayed_write_rate = 16 * 1024 * 1024;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.WAL_ttl_seconds > 0 || result.WAL_size_limit_MB > 0) {
|
||||
result.recycle_log_file_num = false;
|
||||
}
|
||||
@@ -163,19 +154,6 @@ static Status ValidateOptions(
|
||||
"universal and level compaction styles. ");
|
||||
}
|
||||
}
|
||||
if (cfd.options.compaction_options_fifo.ttl > 0) {
|
||||
if (db_options.max_open_files != -1) {
|
||||
return Status::NotSupported(
|
||||
"FIFO Compaction with TTL is only supported when files are always "
|
||||
"kept open (set max_open_files = -1). ");
|
||||
}
|
||||
if (cfd.options.table_factory->Name() !=
|
||||
BlockBasedTableFactory().Name()) {
|
||||
return Status::NotSupported(
|
||||
"FIFO Compaction with TTL is only supported in "
|
||||
"Block-Based Table format. ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (db_options.db_paths.size() > 4) {
|
||||
@@ -520,8 +498,7 @@ Status DBImpl::RecoverLogFiles(const std::vector<uint64_t>& log_numbers,
|
||||
unique_ptr<SequentialFileReader> file_reader;
|
||||
{
|
||||
unique_ptr<SequentialFile> file;
|
||||
status = env_->NewSequentialFile(fname, &file,
|
||||
env_->OptimizeForLogRead(env_options_));
|
||||
status = env_->NewSequentialFile(fname, &file, env_options_);
|
||||
if (!status.ok()) {
|
||||
MaybeIgnoreError(&status);
|
||||
if (!status.ok()) {
|
||||
@@ -737,7 +714,6 @@ Status DBImpl::RecoverLogFiles(const std::vector<uint64_t>& log_numbers,
|
||||
auto last_sequence = *next_sequence - 1;
|
||||
if ((*next_sequence != kMaxSequenceNumber) &&
|
||||
(versions_->LastSequence() <= last_sequence)) {
|
||||
versions_->SetLastToBeWrittenSequence(last_sequence);
|
||||
versions_->SetLastSequence(last_sequence);
|
||||
}
|
||||
}
|
||||
@@ -809,15 +785,9 @@ Status DBImpl::RecoverLogFiles(const std::vector<uint64_t>& log_numbers,
|
||||
if (data_seen && !flushed) {
|
||||
// Mark these as alive so they'll be considered for deletion later by
|
||||
// FindObsoleteFiles()
|
||||
if (concurrent_prepare_) {
|
||||
log_write_mutex_.Lock();
|
||||
}
|
||||
for (auto log_number : log_numbers) {
|
||||
alive_log_files_.push_back(LogFileNumberSize(log_number));
|
||||
}
|
||||
if (concurrent_prepare_) {
|
||||
log_write_mutex_.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
event_logger_.Log() << "job" << job_id << "event"
|
||||
@@ -851,11 +821,6 @@ Status DBImpl::WriteLevel0TableForRecovery(int job_id, ColumnFamilyData* cfd,
|
||||
*cfd->GetLatestMutableCFOptions();
|
||||
bool paranoid_file_checks =
|
||||
cfd->GetLatestMutableCFOptions()->paranoid_file_checks;
|
||||
|
||||
int64_t _current_time = 0;
|
||||
env_->GetCurrentTime(&_current_time); // ignore error
|
||||
const uint64_t current_time = static_cast<uint64_t>(_current_time);
|
||||
|
||||
{
|
||||
mutex_.Unlock();
|
||||
|
||||
@@ -875,8 +840,7 @@ Status DBImpl::WriteLevel0TableForRecovery(int job_id, ColumnFamilyData* cfd,
|
||||
GetCompressionFlush(*cfd->ioptions(), mutable_cf_options),
|
||||
cfd->ioptions()->compression_opts, paranoid_file_checks,
|
||||
cfd->internal_stats(), TableFileCreationReason::kRecovery,
|
||||
&event_logger_, job_id, Env::IO_HIGH, nullptr /* table_properties */,
|
||||
-1 /* level */, current_time);
|
||||
&event_logger_, job_id);
|
||||
LogFlush(immutable_db_options_.info_log);
|
||||
ROCKS_LOG_DEBUG(immutable_db_options_.info_log,
|
||||
"[%s] [WriteLevel0TableForRecovery]"
|
||||
@@ -925,7 +889,7 @@ Status DB::Open(const Options& options, const std::string& dbname, DB** dbptr) {
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
Status DB::Open(const DBOptions& db_options, const std::string& dbname,
|
||||
const std::vector<ColumnFamilyDescriptor>& column_families,
|
||||
std::vector<ColumnFamilyHandle*>* handles, DB** dbptr) {
|
||||
@@ -987,17 +951,14 @@ Status DB::Open(const DBOptions& db_options, const std::string& dbname,
|
||||
if (s.ok()) {
|
||||
lfile->SetPreallocationBlockSize(
|
||||
impl->GetWalPreallocateBlockSize(max_write_buffer_size));
|
||||
{
|
||||
InstrumentedMutexLock wl(&impl->log_write_mutex_);
|
||||
impl->logfile_number_ = new_log_number;
|
||||
unique_ptr<WritableFileWriter> file_writer(
|
||||
new WritableFileWriter(std::move(lfile), opt_env_options));
|
||||
impl->logs_.emplace_back(
|
||||
new_log_number,
|
||||
new log::Writer(
|
||||
std::move(file_writer), new_log_number,
|
||||
impl->immutable_db_options_.recycle_log_file_num > 0));
|
||||
}
|
||||
impl->logfile_number_ = new_log_number;
|
||||
unique_ptr<WritableFileWriter> file_writer(
|
||||
new WritableFileWriter(std::move(lfile), opt_env_options));
|
||||
impl->logs_.emplace_back(
|
||||
new_log_number,
|
||||
new log::Writer(
|
||||
std::move(file_writer), new_log_number,
|
||||
impl->immutable_db_options_.recycle_log_file_num > 0));
|
||||
|
||||
// set column family handles
|
||||
for (auto cf : column_families) {
|
||||
@@ -1031,14 +992,8 @@ Status DB::Open(const DBOptions& db_options, const std::string& dbname,
|
||||
delete impl->InstallSuperVersionAndScheduleWork(
|
||||
cfd, nullptr, *cfd->GetLatestMutableCFOptions());
|
||||
}
|
||||
if (impl->concurrent_prepare_) {
|
||||
impl->log_write_mutex_.Lock();
|
||||
}
|
||||
impl->alive_log_files_.push_back(
|
||||
DBImpl::LogFileNumberSize(impl->logfile_number_));
|
||||
if (impl->concurrent_prepare_) {
|
||||
impl->log_write_mutex_.Unlock();
|
||||
}
|
||||
impl->DeleteObsoleteFiles();
|
||||
s = impl->directories_.GetDbDir()->Fsync();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
|
||||
|
||||
#include "db/db_impl_readonly.h"
|
||||
|
||||
#include "db/compacted_db_impl.h"
|
||||
@@ -58,7 +59,7 @@ Iterator* DBImplReadOnly::NewIterator(const ReadOptions& read_options,
|
||||
SuperVersion* super_version = cfd->GetSuperVersion()->Ref();
|
||||
SequenceNumber latest_snapshot = versions_->LastSequence();
|
||||
auto db_iter = NewArenaWrappedDbIterator(
|
||||
env_, read_options, *cfd->ioptions(),
|
||||
env_, read_options, *cfd->ioptions(), cfd->user_comparator(),
|
||||
(read_options.snapshot != nullptr
|
||||
? reinterpret_cast<const SnapshotImpl*>(read_options.snapshot)
|
||||
->number_
|
||||
@@ -87,7 +88,7 @@ Status DBImplReadOnly::NewIterators(
|
||||
auto* cfd = reinterpret_cast<ColumnFamilyHandleImpl*>(cfh)->cfd();
|
||||
auto* sv = cfd->GetSuperVersion()->Ref();
|
||||
auto* db_iter = NewArenaWrappedDbIterator(
|
||||
env_, read_options, *cfd->ioptions(),
|
||||
env_, read_options, *cfd->ioptions(), cfd->user_comparator(),
|
||||
(read_options.snapshot != nullptr
|
||||
? reinterpret_cast<const SnapshotImpl*>(read_options.snapshot)
|
||||
->number_
|
||||
|
||||
+124
-553
@@ -12,7 +12,6 @@
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif
|
||||
#include <inttypes.h>
|
||||
#include "db/event_helpers.h"
|
||||
#include "monitoring/perf_context_imp.h"
|
||||
#include "options/options_helper.h"
|
||||
#include "util/sync_point.h"
|
||||
@@ -60,32 +59,12 @@ Status DBImpl::WriteWithCallback(const WriteOptions& write_options,
|
||||
Status DBImpl::WriteImpl(const WriteOptions& write_options,
|
||||
WriteBatch* my_batch, WriteCallback* callback,
|
||||
uint64_t* log_used, uint64_t log_ref,
|
||||
bool disable_memtable, uint64_t* seq_used) {
|
||||
bool disable_memtable) {
|
||||
if (my_batch == nullptr) {
|
||||
return Status::Corruption("Batch is nullptr!");
|
||||
}
|
||||
if (concurrent_prepare_ && immutable_db_options_.enable_pipelined_write) {
|
||||
return Status::NotSupported(
|
||||
"pipelined_writes is not compatible with concurrent prepares");
|
||||
}
|
||||
|
||||
Status status;
|
||||
if (write_options.low_pri) {
|
||||
status = ThrottleLowPriWritesIfNeeded(write_options, my_batch);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (concurrent_prepare_ && disable_memtable) {
|
||||
return WriteImplWALOnly(write_options, my_batch, callback, log_used,
|
||||
log_ref, seq_used);
|
||||
}
|
||||
|
||||
if (immutable_db_options_.enable_pipelined_write) {
|
||||
return PipelinedWriteImpl(write_options, my_batch, callback, log_used,
|
||||
log_ref, disable_memtable, seq_used);
|
||||
}
|
||||
|
||||
PERF_TIMER_GUARD(write_pre_and_post_process_time);
|
||||
WriteThread::Writer w(write_options, my_batch, callback, log_ref,
|
||||
@@ -98,25 +77,25 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
|
||||
StopWatch write_sw(env_, immutable_db_options_.statistics.get(), DB_WRITE);
|
||||
|
||||
write_thread_.JoinBatchGroup(&w);
|
||||
if (w.state == WriteThread::STATE_PARALLEL_MEMTABLE_WRITER) {
|
||||
if (w.state == WriteThread::STATE_PARALLEL_FOLLOWER) {
|
||||
// we are a non-leader in a parallel group
|
||||
PERF_TIMER_GUARD(write_memtable_time);
|
||||
|
||||
if (w.ShouldWriteToMemtable()) {
|
||||
ColumnFamilyMemTablesImpl column_family_memtables(
|
||||
versions_->GetColumnFamilySet());
|
||||
WriteBatchInternal::SetSequence(w.batch, w.sequence);
|
||||
w.status = WriteBatchInternal::InsertInto(
|
||||
&w, w.sequence, &column_family_memtables, &flush_scheduler_,
|
||||
&w, &column_family_memtables, &flush_scheduler_,
|
||||
write_options.ignore_missing_column_families, 0 /*log_number*/, this,
|
||||
true /*concurrent_memtable_writes*/);
|
||||
}
|
||||
|
||||
if (write_thread_.CompleteParallelMemTableWriter(&w)) {
|
||||
// we're responsible for exit batch group
|
||||
auto last_sequence = w.write_group->last_sequence;
|
||||
if (write_thread_.CompleteParallelWorker(&w)) {
|
||||
// we're responsible for early exit
|
||||
auto last_sequence = w.parallel_group->last_sequence;
|
||||
versions_->SetLastSequence(last_sequence);
|
||||
MemTableInsertStatusCheck(w.status);
|
||||
write_thread_.ExitAsBatchGroupFollower(&w);
|
||||
write_thread_.EarlyExitParallelGroup(&w);
|
||||
}
|
||||
assert(w.state == WriteThread::STATE_COMPLETED);
|
||||
// STATE_COMPLETED conditional below handles exit
|
||||
@@ -127,9 +106,6 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
|
||||
if (log_used != nullptr) {
|
||||
*log_used = w.log_used;
|
||||
}
|
||||
if (seq_used != nullptr) {
|
||||
*seq_used = w.sequence;
|
||||
}
|
||||
// write is complete and leader has updated sequence
|
||||
return w.FinalStatus();
|
||||
}
|
||||
@@ -141,24 +117,17 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
|
||||
// when it finds suitable, and finish them in the same write batch.
|
||||
// This is how a write job could be done by the other writer.
|
||||
WriteContext write_context;
|
||||
WriteThread::WriteGroup write_group;
|
||||
bool in_parallel_group = false;
|
||||
uint64_t last_sequence = kMaxSequenceNumber;
|
||||
if (!concurrent_prepare_) {
|
||||
last_sequence = versions_->LastSequence();
|
||||
}
|
||||
WriteThread::Writer* last_writer = &w; // Dummy intial value
|
||||
autovector<WriteThread::Writer*> write_group;
|
||||
bool logs_getting_synced = false;
|
||||
|
||||
mutex_.Lock();
|
||||
|
||||
bool need_log_sync = !write_options.disableWAL && write_options.sync;
|
||||
bool need_log_dir_sync = need_log_sync && !log_dir_synced_;
|
||||
if (!concurrent_prepare_ || !disable_memtable) {
|
||||
// With concurrent writes we do preprocess only in the write thread that
|
||||
// also does write to memtable to avoid sync issue on shared data structure
|
||||
// with the other thread
|
||||
status = PreprocessWrite(write_options, &need_log_sync, &write_context);
|
||||
}
|
||||
log::Writer* log_writer = logs_.back().writer;
|
||||
status = PreprocessWrite(write_options, need_log_sync, &logs_getting_synced,
|
||||
&write_context);
|
||||
log::Writer* cur_log_writer = logs_.back().writer;
|
||||
|
||||
mutex_.Unlock();
|
||||
|
||||
@@ -167,8 +136,9 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
|
||||
// and protects against concurrent loggers and concurrent writes
|
||||
// into memtables
|
||||
|
||||
bool exit_completed_early = false;
|
||||
last_batch_group_size_ =
|
||||
write_thread_.EnterAsBatchGroupLeader(&w, &write_group);
|
||||
write_thread_.EnterAsBatchGroupLeader(&w, &last_writer, &write_group);
|
||||
|
||||
if (status.ok()) {
|
||||
// Rules for when we can update the memtable concurrently
|
||||
@@ -183,39 +153,43 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
|
||||
// relax rules 2 if we could prevent write batches from referring
|
||||
// more than once to a particular key.
|
||||
bool parallel = immutable_db_options_.allow_concurrent_memtable_write &&
|
||||
write_group.size > 1;
|
||||
write_group.size() > 1;
|
||||
int total_count = 0;
|
||||
uint64_t total_byte_size = 0;
|
||||
for (auto* writer : write_group) {
|
||||
for (auto writer : write_group) {
|
||||
if (writer->CheckCallback(this)) {
|
||||
if (writer->ShouldWriteToMemtable()) {
|
||||
total_count += WriteBatchInternal::Count(writer->batch);
|
||||
parallel = parallel && !writer->batch->HasMerge();
|
||||
}
|
||||
|
||||
total_byte_size = WriteBatchInternal::AppendedByteSize(
|
||||
total_byte_size, WriteBatchInternal::ByteSize(writer->batch));
|
||||
if (writer->ShouldWriteToWAL()) {
|
||||
total_byte_size = WriteBatchInternal::AppendedByteSize(
|
||||
total_byte_size, WriteBatchInternal::ByteSize(writer->batch));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool concurrent_update = concurrent_prepare_;
|
||||
uint64_t last_sequence = versions_->LastSequence();
|
||||
const SequenceNumber current_sequence = last_sequence + 1;
|
||||
last_sequence += total_count;
|
||||
|
||||
// Update stats while we are an exclusive group leader, so we know
|
||||
// that nobody else can be writing to these particular stats.
|
||||
// We're optimistic, updating the stats before we successfully
|
||||
// commit. That lets us release our leader status early.
|
||||
// commit. That lets us release our leader status early in
|
||||
// some cases.
|
||||
auto stats = default_cf_internal_stats_;
|
||||
stats->AddDBStats(InternalStats::NUMBER_KEYS_WRITTEN, total_count,
|
||||
concurrent_update);
|
||||
stats->AddDBStats(InternalStats::NUMBER_KEYS_WRITTEN, total_count);
|
||||
RecordTick(stats_, NUMBER_KEYS_WRITTEN, total_count);
|
||||
stats->AddDBStats(InternalStats::BYTES_WRITTEN, total_byte_size,
|
||||
concurrent_update);
|
||||
stats->AddDBStats(InternalStats::BYTES_WRITTEN, total_byte_size);
|
||||
RecordTick(stats_, BYTES_WRITTEN, total_byte_size);
|
||||
stats->AddDBStats(InternalStats::WRITE_DONE_BY_SELF, 1, concurrent_update);
|
||||
stats->AddDBStats(InternalStats::WRITE_DONE_BY_SELF, 1);
|
||||
RecordTick(stats_, WRITE_DONE_BY_SELF);
|
||||
auto write_done_by_other = write_group.size - 1;
|
||||
auto write_done_by_other = write_group.size() - 1;
|
||||
if (write_done_by_other > 0) {
|
||||
stats->AddDBStats(InternalStats::WRITE_DONE_BY_OTHER, write_done_by_other,
|
||||
concurrent_update);
|
||||
stats->AddDBStats(InternalStats::WRITE_DONE_BY_OTHER,
|
||||
write_done_by_other);
|
||||
RecordTick(stats_, WRITE_DONE_BY_OTHER, write_done_by_other);
|
||||
}
|
||||
MeasureTime(stats_, BYTES_PER_WRITE, total_byte_size);
|
||||
@@ -226,49 +200,39 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
|
||||
|
||||
PERF_TIMER_STOP(write_pre_and_post_process_time);
|
||||
|
||||
if (!concurrent_prepare_) {
|
||||
if (status.ok() && !write_options.disableWAL) {
|
||||
PERF_TIMER_GUARD(write_wal_time);
|
||||
status = WriteToWAL(write_group, log_writer, log_used, need_log_sync,
|
||||
need_log_dir_sync, last_sequence + 1);
|
||||
}
|
||||
} else {
|
||||
if (status.ok() && !write_options.disableWAL) {
|
||||
PERF_TIMER_GUARD(write_wal_time);
|
||||
// LastToBeWrittenSequence is increased inside WriteToWAL under
|
||||
// wal_write_mutex_ to ensure ordered events in WAL
|
||||
status = ConcurrentWriteToWAL(write_group, log_used, &last_sequence,
|
||||
total_count);
|
||||
} else {
|
||||
// Otherwise we inc seq number for memtable writes
|
||||
last_sequence = versions_->FetchAddLastToBeWrittenSequence(total_count);
|
||||
if (status.ok() && !write_options.disableWAL) {
|
||||
PERF_TIMER_GUARD(write_wal_time);
|
||||
status = WriteToWAL(write_group, cur_log_writer, need_log_sync,
|
||||
need_log_dir_sync, current_sequence);
|
||||
if (log_used != nullptr) {
|
||||
*log_used = logfile_number_;
|
||||
}
|
||||
}
|
||||
assert(last_sequence != kMaxSequenceNumber);
|
||||
const SequenceNumber current_sequence = last_sequence + 1;
|
||||
last_sequence += total_count;
|
||||
|
||||
if (status.ok()) {
|
||||
PERF_TIMER_GUARD(write_memtable_time);
|
||||
|
||||
if (!parallel) {
|
||||
w.status = WriteBatchInternal::InsertInto(
|
||||
status = WriteBatchInternal::InsertInto(
|
||||
write_group, current_sequence, column_family_memtables_.get(),
|
||||
&flush_scheduler_, write_options.ignore_missing_column_families,
|
||||
0 /*recovery_log_number*/, this);
|
||||
} else {
|
||||
SequenceNumber next_sequence = current_sequence;
|
||||
for (auto* writer : write_group) {
|
||||
if (writer->ShouldWriteToMemtable()) {
|
||||
writer->sequence = next_sequence;
|
||||
next_sequence += WriteBatchInternal::Count(writer->batch);
|
||||
}
|
||||
|
||||
if (status.ok()) {
|
||||
// There were no write failures. Set leader's status
|
||||
// in case the write callback returned a non-ok status.
|
||||
status = w.FinalStatus();
|
||||
}
|
||||
write_group.last_sequence = last_sequence;
|
||||
write_group.running.store(static_cast<uint32_t>(write_group.size),
|
||||
std::memory_order_relaxed);
|
||||
write_thread_.LaunchParallelMemTableWriters(&write_group);
|
||||
in_parallel_group = true;
|
||||
|
||||
} else {
|
||||
WriteThread::ParallelGroup pg;
|
||||
pg.leader = &w;
|
||||
pg.last_writer = last_writer;
|
||||
pg.last_sequence = last_sequence;
|
||||
pg.early_exit_allowed = !need_log_sync;
|
||||
pg.running.store(static_cast<uint32_t>(write_group.size()),
|
||||
std::memory_order_relaxed);
|
||||
write_thread_.LaunchParallelFollowers(&pg, current_sequence);
|
||||
|
||||
// Each parallel follower is doing each own writes. The leader should
|
||||
// also do its own.
|
||||
@@ -276,329 +240,73 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
|
||||
ColumnFamilyMemTablesImpl column_family_memtables(
|
||||
versions_->GetColumnFamilySet());
|
||||
assert(w.sequence == current_sequence);
|
||||
WriteBatchInternal::SetSequence(w.batch, w.sequence);
|
||||
w.status = WriteBatchInternal::InsertInto(
|
||||
&w, w.sequence, &column_family_memtables, &flush_scheduler_,
|
||||
&w, &column_family_memtables, &flush_scheduler_,
|
||||
write_options.ignore_missing_column_families, 0 /*log_number*/,
|
||||
this, true /*concurrent_memtable_writes*/);
|
||||
}
|
||||
if (seq_used != nullptr) {
|
||||
*seq_used = w.sequence;
|
||||
|
||||
// CompleteParallelWorker returns true if this thread should
|
||||
// handle exit, false means somebody else did
|
||||
exit_completed_early = !write_thread_.CompleteParallelWorker(&w);
|
||||
status = w.FinalStatus();
|
||||
}
|
||||
|
||||
if (!exit_completed_early && w.status.ok()) {
|
||||
versions_->SetLastSequence(last_sequence);
|
||||
if (!need_log_sync) {
|
||||
write_thread_.ExitAsBatchGroupLeader(&w, last_writer, w.status);
|
||||
exit_completed_early = true;
|
||||
}
|
||||
}
|
||||
|
||||
// A non-OK status here indicates that the state implied by the
|
||||
// WAL has diverged from the in-memory state. This could be
|
||||
// because of a corrupt write_batch (very bad), or because the
|
||||
// client specified an invalid column family and didn't specify
|
||||
// ignore_missing_column_families.
|
||||
//
|
||||
// Is setting bg_error_ enough here? This will at least stop
|
||||
// compaction and fail any further writes.
|
||||
if (!status.ok() && !w.CallbackFailed()) {
|
||||
mutex_.Lock();
|
||||
if (bg_error_.ok()) {
|
||||
bg_error_ = status; // stop compaction & fail any further writes
|
||||
}
|
||||
mutex_.Unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
PERF_TIMER_START(write_pre_and_post_process_time);
|
||||
|
||||
if (!w.CallbackFailed()) {
|
||||
WriteCallbackStatusCheck(status);
|
||||
if (immutable_db_options_.paranoid_checks && !status.ok() &&
|
||||
!w.CallbackFailed() && !status.IsBusy() && !status.IsIncomplete()) {
|
||||
mutex_.Lock();
|
||||
if (bg_error_.ok()) {
|
||||
bg_error_ = status; // stop compaction & fail any further writes
|
||||
}
|
||||
mutex_.Unlock();
|
||||
}
|
||||
|
||||
if (need_log_sync) {
|
||||
if (logs_getting_synced) {
|
||||
mutex_.Lock();
|
||||
MarkLogsSynced(logfile_number_, need_log_dir_sync, status);
|
||||
mutex_.Unlock();
|
||||
// Requesting sync with concurrent_prepare_ is expected to be very rare. We
|
||||
// hance provide a simple implementation that is not necessarily efficient.
|
||||
if (concurrent_prepare_) {
|
||||
if (manual_wal_flush_) {
|
||||
status = FlushWAL(true);
|
||||
} else {
|
||||
status = SyncWAL();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool should_exit_batch_group = true;
|
||||
if (in_parallel_group) {
|
||||
// CompleteParallelWorker returns true if this thread should
|
||||
// handle exit, false means somebody else did
|
||||
should_exit_batch_group = write_thread_.CompleteParallelMemTableWriter(&w);
|
||||
}
|
||||
if (should_exit_batch_group) {
|
||||
if (status.ok()) {
|
||||
versions_->SetLastSequence(last_sequence);
|
||||
}
|
||||
MemTableInsertStatusCheck(w.status);
|
||||
write_thread_.ExitAsBatchGroupLeader(write_group, status);
|
||||
if (!exit_completed_early) {
|
||||
write_thread_.ExitAsBatchGroupLeader(&w, last_writer, w.status);
|
||||
}
|
||||
|
||||
if (status.ok()) {
|
||||
status = w.FinalStatus();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
Status DBImpl::PipelinedWriteImpl(const WriteOptions& write_options,
|
||||
WriteBatch* my_batch, WriteCallback* callback,
|
||||
uint64_t* log_used, uint64_t log_ref,
|
||||
bool disable_memtable, uint64_t* seq_used) {
|
||||
PERF_TIMER_GUARD(write_pre_and_post_process_time);
|
||||
StopWatch write_sw(env_, immutable_db_options_.statistics.get(), DB_WRITE);
|
||||
|
||||
WriteContext write_context;
|
||||
|
||||
WriteThread::Writer w(write_options, my_batch, callback, log_ref,
|
||||
disable_memtable);
|
||||
write_thread_.JoinBatchGroup(&w);
|
||||
if (w.state == WriteThread::STATE_GROUP_LEADER) {
|
||||
WriteThread::WriteGroup wal_write_group;
|
||||
if (w.callback && !w.callback->AllowWriteBatching()) {
|
||||
write_thread_.WaitForMemTableWriters();
|
||||
}
|
||||
mutex_.Lock();
|
||||
bool need_log_sync = !write_options.disableWAL && write_options.sync;
|
||||
bool need_log_dir_sync = need_log_sync && !log_dir_synced_;
|
||||
w.status = PreprocessWrite(write_options, &need_log_sync, &write_context);
|
||||
log::Writer* log_writer = logs_.back().writer;
|
||||
mutex_.Unlock();
|
||||
|
||||
// This can set non-OK status if callback fail.
|
||||
last_batch_group_size_ =
|
||||
write_thread_.EnterAsBatchGroupLeader(&w, &wal_write_group);
|
||||
const SequenceNumber current_sequence =
|
||||
write_thread_.UpdateLastSequence(versions_->LastSequence()) + 1;
|
||||
size_t total_count = 0;
|
||||
size_t total_byte_size = 0;
|
||||
|
||||
if (w.status.ok()) {
|
||||
SequenceNumber next_sequence = current_sequence;
|
||||
for (auto writer : wal_write_group) {
|
||||
if (writer->CheckCallback(this)) {
|
||||
if (writer->ShouldWriteToMemtable()) {
|
||||
writer->sequence = next_sequence;
|
||||
size_t count = WriteBatchInternal::Count(writer->batch);
|
||||
next_sequence += count;
|
||||
total_count += count;
|
||||
}
|
||||
total_byte_size = WriteBatchInternal::AppendedByteSize(
|
||||
total_byte_size, WriteBatchInternal::ByteSize(writer->batch));
|
||||
}
|
||||
}
|
||||
if (w.disable_wal) {
|
||||
has_unpersisted_data_.store(true, std::memory_order_relaxed);
|
||||
}
|
||||
write_thread_.UpdateLastSequence(current_sequence + total_count - 1);
|
||||
}
|
||||
|
||||
auto stats = default_cf_internal_stats_;
|
||||
stats->AddDBStats(InternalStats::NUMBER_KEYS_WRITTEN, total_count);
|
||||
RecordTick(stats_, NUMBER_KEYS_WRITTEN, total_count);
|
||||
stats->AddDBStats(InternalStats::BYTES_WRITTEN, total_byte_size);
|
||||
RecordTick(stats_, BYTES_WRITTEN, total_byte_size);
|
||||
|
||||
PERF_TIMER_STOP(write_pre_and_post_process_time);
|
||||
|
||||
if (w.ShouldWriteToWAL()) {
|
||||
PERF_TIMER_GUARD(write_wal_time);
|
||||
stats->AddDBStats(InternalStats::WRITE_DONE_BY_SELF, 1);
|
||||
RecordTick(stats_, WRITE_DONE_BY_SELF, 1);
|
||||
if (wal_write_group.size > 1) {
|
||||
stats->AddDBStats(InternalStats::WRITE_DONE_BY_OTHER,
|
||||
wal_write_group.size - 1);
|
||||
RecordTick(stats_, WRITE_DONE_BY_OTHER, wal_write_group.size - 1);
|
||||
}
|
||||
w.status = WriteToWAL(wal_write_group, log_writer, log_used,
|
||||
need_log_sync, need_log_dir_sync, current_sequence);
|
||||
}
|
||||
|
||||
if (!w.CallbackFailed()) {
|
||||
WriteCallbackStatusCheck(w.status);
|
||||
}
|
||||
|
||||
if (need_log_sync) {
|
||||
mutex_.Lock();
|
||||
MarkLogsSynced(logfile_number_, need_log_dir_sync, w.status);
|
||||
mutex_.Unlock();
|
||||
}
|
||||
|
||||
write_thread_.ExitAsBatchGroupLeader(wal_write_group, w.status);
|
||||
}
|
||||
|
||||
WriteThread::WriteGroup memtable_write_group;
|
||||
if (w.state == WriteThread::STATE_MEMTABLE_WRITER_LEADER) {
|
||||
PERF_TIMER_GUARD(write_memtable_time);
|
||||
assert(w.status.ok());
|
||||
write_thread_.EnterAsMemTableWriter(&w, &memtable_write_group);
|
||||
if (memtable_write_group.size > 1 &&
|
||||
immutable_db_options_.allow_concurrent_memtable_write) {
|
||||
write_thread_.LaunchParallelMemTableWriters(&memtable_write_group);
|
||||
} else {
|
||||
memtable_write_group.status = WriteBatchInternal::InsertInto(
|
||||
memtable_write_group, w.sequence, column_family_memtables_.get(),
|
||||
&flush_scheduler_, write_options.ignore_missing_column_families,
|
||||
0 /*log_number*/, this);
|
||||
versions_->SetLastSequence(memtable_write_group.last_sequence);
|
||||
write_thread_.ExitAsMemTableWriter(&w, memtable_write_group);
|
||||
}
|
||||
}
|
||||
|
||||
if (w.state == WriteThread::STATE_PARALLEL_MEMTABLE_WRITER) {
|
||||
assert(w.ShouldWriteToMemtable());
|
||||
ColumnFamilyMemTablesImpl column_family_memtables(
|
||||
versions_->GetColumnFamilySet());
|
||||
w.status = WriteBatchInternal::InsertInto(
|
||||
&w, w.sequence, &column_family_memtables, &flush_scheduler_,
|
||||
write_options.ignore_missing_column_families, 0 /*log_number*/, this,
|
||||
true /*concurrent_memtable_writes*/);
|
||||
if (write_thread_.CompleteParallelMemTableWriter(&w)) {
|
||||
MemTableInsertStatusCheck(w.status);
|
||||
versions_->SetLastSequence(w.write_group->last_sequence);
|
||||
write_thread_.ExitAsMemTableWriter(&w, *w.write_group);
|
||||
}
|
||||
}
|
||||
if (seq_used != nullptr) {
|
||||
*seq_used = w.sequence;
|
||||
}
|
||||
|
||||
assert(w.state == WriteThread::STATE_COMPLETED);
|
||||
return w.FinalStatus();
|
||||
}
|
||||
|
||||
Status DBImpl::WriteImplWALOnly(const WriteOptions& write_options,
|
||||
WriteBatch* my_batch, WriteCallback* callback,
|
||||
uint64_t* log_used, uint64_t log_ref,
|
||||
uint64_t* seq_used) {
|
||||
Status status;
|
||||
PERF_TIMER_GUARD(write_pre_and_post_process_time);
|
||||
WriteThread::Writer w(write_options, my_batch, callback, log_ref,
|
||||
true /* disable_memtable */);
|
||||
if (write_options.disableWAL) {
|
||||
return status;
|
||||
}
|
||||
RecordTick(stats_, WRITE_WITH_WAL);
|
||||
StopWatch write_sw(env_, immutable_db_options_.statistics.get(), DB_WRITE);
|
||||
|
||||
nonmem_write_thread_.JoinBatchGroup(&w);
|
||||
assert(w.state != WriteThread::STATE_PARALLEL_MEMTABLE_WRITER);
|
||||
if (w.state == WriteThread::STATE_COMPLETED) {
|
||||
if (log_used != nullptr) {
|
||||
*log_used = w.log_used;
|
||||
}
|
||||
if (seq_used != nullptr) {
|
||||
*seq_used = w.sequence;
|
||||
}
|
||||
return w.FinalStatus();
|
||||
}
|
||||
// else we are the leader of the write batch group
|
||||
assert(w.state == WriteThread::STATE_GROUP_LEADER);
|
||||
WriteContext write_context;
|
||||
WriteThread::WriteGroup write_group;
|
||||
uint64_t last_sequence;
|
||||
nonmem_write_thread_.EnterAsBatchGroupLeader(&w, &write_group);
|
||||
// Note: no need to update last_batch_group_size_ here since the batch writes
|
||||
// to WAL only
|
||||
|
||||
uint64_t total_byte_size = 0;
|
||||
for (auto* writer : write_group) {
|
||||
if (writer->CheckCallback(this)) {
|
||||
total_byte_size = WriteBatchInternal::AppendedByteSize(
|
||||
total_byte_size, WriteBatchInternal::ByteSize(writer->batch));
|
||||
}
|
||||
}
|
||||
|
||||
const bool concurrent_update = true;
|
||||
// Update stats while we are an exclusive group leader, so we know
|
||||
// that nobody else can be writing to these particular stats.
|
||||
// We're optimistic, updating the stats before we successfully
|
||||
// commit. That lets us release our leader status early.
|
||||
auto stats = default_cf_internal_stats_;
|
||||
stats->AddDBStats(InternalStats::BYTES_WRITTEN, total_byte_size,
|
||||
concurrent_update);
|
||||
RecordTick(stats_, BYTES_WRITTEN, total_byte_size);
|
||||
stats->AddDBStats(InternalStats::WRITE_DONE_BY_SELF, 1, concurrent_update);
|
||||
RecordTick(stats_, WRITE_DONE_BY_SELF);
|
||||
auto write_done_by_other = write_group.size - 1;
|
||||
if (write_done_by_other > 0) {
|
||||
stats->AddDBStats(InternalStats::WRITE_DONE_BY_OTHER, write_done_by_other,
|
||||
concurrent_update);
|
||||
RecordTick(stats_, WRITE_DONE_BY_OTHER, write_done_by_other);
|
||||
}
|
||||
MeasureTime(stats_, BYTES_PER_WRITE, total_byte_size);
|
||||
|
||||
PERF_TIMER_STOP(write_pre_and_post_process_time);
|
||||
|
||||
PERF_TIMER_GUARD(write_wal_time);
|
||||
// LastToBeWrittenSequence is increased inside WriteToWAL under
|
||||
// wal_write_mutex_ to ensure ordered events in WAL
|
||||
status = ConcurrentWriteToWAL(write_group, log_used, &last_sequence,
|
||||
0 /*total_count*/);
|
||||
auto curr_seq = last_sequence + 1;
|
||||
for (auto* writer : write_group) {
|
||||
if (writer->CheckCallback(this)) {
|
||||
writer->sequence = curr_seq;
|
||||
curr_seq += WriteBatchInternal::Count(writer->batch);
|
||||
}
|
||||
}
|
||||
if (status.ok() && write_options.sync) {
|
||||
// Requesting sync with concurrent_prepare_ is expected to be very rare. We
|
||||
// hance provide a simple implementation that is not necessarily efficient.
|
||||
if (manual_wal_flush_) {
|
||||
status = FlushWAL(true);
|
||||
} else {
|
||||
status = SyncWAL();
|
||||
}
|
||||
}
|
||||
PERF_TIMER_START(write_pre_and_post_process_time);
|
||||
|
||||
if (!w.CallbackFailed()) {
|
||||
WriteCallbackStatusCheck(status);
|
||||
}
|
||||
nonmem_write_thread_.ExitAsBatchGroupLeader(write_group, status);
|
||||
if (status.ok()) {
|
||||
status = w.FinalStatus();
|
||||
}
|
||||
if (seq_used != nullptr) {
|
||||
*seq_used = w.sequence;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void DBImpl::WriteCallbackStatusCheck(const Status& status) {
|
||||
// Is setting bg_error_ enough here? This will at least stop
|
||||
// compaction and fail any further writes.
|
||||
if (immutable_db_options_.paranoid_checks && !status.ok() &&
|
||||
!status.IsBusy() && !status.IsIncomplete()) {
|
||||
mutex_.Lock();
|
||||
if (bg_error_.ok()) {
|
||||
Status new_bg_error = status;
|
||||
// may temporarily unlock and lock the mutex.
|
||||
EventHelpers::NotifyOnBackgroundError(immutable_db_options_.listeners,
|
||||
BackgroundErrorReason::kWriteCallback,
|
||||
&new_bg_error, &mutex_);
|
||||
if (!new_bg_error.ok()) {
|
||||
bg_error_ = new_bg_error; // stop compaction & fail any further writes
|
||||
}
|
||||
}
|
||||
mutex_.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void DBImpl::MemTableInsertStatusCheck(const Status& status) {
|
||||
// A non-OK status here indicates that the state implied by the
|
||||
// WAL has diverged from the in-memory state. This could be
|
||||
// because of a corrupt write_batch (very bad), or because the
|
||||
// client specified an invalid column family and didn't specify
|
||||
// ignore_missing_column_families.
|
||||
if (!status.ok()) {
|
||||
mutex_.Lock();
|
||||
assert(bg_error_.ok());
|
||||
Status new_bg_error = status;
|
||||
// may temporarily unlock and lock the mutex.
|
||||
EventHelpers::NotifyOnBackgroundError(immutable_db_options_.listeners,
|
||||
BackgroundErrorReason::kMemTable,
|
||||
&new_bg_error, &mutex_);
|
||||
if (!new_bg_error.ok()) {
|
||||
bg_error_ = new_bg_error; // stop compaction & fail any further writes
|
||||
}
|
||||
mutex_.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
Status DBImpl::PreprocessWrite(const WriteOptions& write_options,
|
||||
bool* need_log_sync,
|
||||
bool need_log_sync, bool* logs_getting_synced,
|
||||
WriteContext* write_context) {
|
||||
mutex_.AssertHeld();
|
||||
assert(write_context != nullptr && need_log_sync != nullptr);
|
||||
assert(write_context != nullptr && logs_getting_synced != nullptr);
|
||||
Status status;
|
||||
|
||||
assert(!single_column_family_mode_ ||
|
||||
@@ -618,7 +326,7 @@ Status DBImpl::PreprocessWrite(const WriteOptions& write_options,
|
||||
}
|
||||
|
||||
if (UNLIKELY(status.ok() && !bg_error_.ok())) {
|
||||
return bg_error_;
|
||||
status = bg_error_;
|
||||
}
|
||||
|
||||
if (UNLIKELY(status.ok() && !flush_scheduler_.Empty())) {
|
||||
@@ -635,7 +343,7 @@ Status DBImpl::PreprocessWrite(const WriteOptions& write_options,
|
||||
status = DelayWrite(last_batch_group_size_, write_options);
|
||||
}
|
||||
|
||||
if (status.ok() && *need_log_sync) {
|
||||
if (status.ok() && need_log_sync) {
|
||||
// Wait until the parallel syncs are finished. Any sync process has to sync
|
||||
// the front log too so it is enough to check the status of front()
|
||||
// We do a while loop since log_sync_cv_ is signalled when any sync is
|
||||
@@ -655,84 +363,50 @@ Status DBImpl::PreprocessWrite(const WriteOptions& write_options,
|
||||
// actually write to the WAL
|
||||
log.getting_synced = true;
|
||||
}
|
||||
} else {
|
||||
*need_log_sync = false;
|
||||
*logs_getting_synced = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
WriteBatch* DBImpl::MergeBatch(const WriteThread::WriteGroup& write_group,
|
||||
WriteBatch* tmp_batch, size_t* write_with_wal) {
|
||||
assert(write_with_wal != nullptr);
|
||||
assert(tmp_batch != nullptr);
|
||||
Status DBImpl::WriteToWAL(const autovector<WriteThread::Writer*>& write_group,
|
||||
log::Writer* log_writer, bool need_log_sync,
|
||||
bool need_log_dir_sync, SequenceNumber sequence) {
|
||||
Status status;
|
||||
|
||||
WriteBatch* merged_batch = nullptr;
|
||||
*write_with_wal = 0;
|
||||
auto* leader = write_group.leader;
|
||||
if (write_group.size == 1 && leader->ShouldWriteToWAL() &&
|
||||
leader->batch->GetWalTerminationPoint().is_cleared()) {
|
||||
size_t write_with_wal = 0;
|
||||
if (write_group.size() == 1 && write_group[0]->ShouldWriteToWAL() &&
|
||||
write_group[0]->batch->GetWalTerminationPoint().is_cleared()) {
|
||||
// we simply write the first WriteBatch to WAL if the group only
|
||||
// contains one batch, that batch should be written to the WAL,
|
||||
// and the batch is not wanting to be truncated
|
||||
merged_batch = leader->batch;
|
||||
*write_with_wal = 1;
|
||||
merged_batch = write_group[0]->batch;
|
||||
write_group[0]->log_used = logfile_number_;
|
||||
write_with_wal = 1;
|
||||
} else {
|
||||
// WAL needs all of the batches flattened into a single batch.
|
||||
// We could avoid copying here with an iov-like AddRecord
|
||||
// interface
|
||||
merged_batch = tmp_batch;
|
||||
merged_batch = &tmp_batch_;
|
||||
for (auto writer : write_group) {
|
||||
if (writer->ShouldWriteToWAL()) {
|
||||
WriteBatchInternal::Append(merged_batch, writer->batch,
|
||||
/*WAL_only*/ true);
|
||||
(*write_with_wal)++;
|
||||
write_with_wal++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return merged_batch;
|
||||
}
|
||||
|
||||
// When concurrent_prepare_ is disabled, this function is called from the only
|
||||
// write thread. Otherwise this must be called holding log_write_mutex_.
|
||||
Status DBImpl::WriteToWAL(const WriteBatch& merged_batch,
|
||||
log::Writer* log_writer, uint64_t* log_used,
|
||||
uint64_t* log_size) {
|
||||
assert(log_size != nullptr);
|
||||
Slice log_entry = WriteBatchInternal::Contents(&merged_batch);
|
||||
*log_size = log_entry.size();
|
||||
Status status = log_writer->AddRecord(log_entry);
|
||||
if (log_used != nullptr) {
|
||||
*log_used = logfile_number_;
|
||||
}
|
||||
total_log_size_ += log_entry.size();
|
||||
// TODO(myabandeh): it might be unsafe to access alive_log_files_.back() here
|
||||
// since alive_log_files_ might be modified concurrently
|
||||
alive_log_files_.back().AddSize(log_entry.size());
|
||||
log_empty_ = false;
|
||||
return status;
|
||||
}
|
||||
|
||||
Status DBImpl::WriteToWAL(const WriteThread::WriteGroup& write_group,
|
||||
log::Writer* log_writer, uint64_t* log_used,
|
||||
bool need_log_sync, bool need_log_dir_sync,
|
||||
SequenceNumber sequence) {
|
||||
Status status;
|
||||
|
||||
size_t write_with_wal = 0;
|
||||
WriteBatch* merged_batch =
|
||||
MergeBatch(write_group, &tmp_batch_, &write_with_wal);
|
||||
if (merged_batch == write_group.leader->batch) {
|
||||
write_group.leader->log_used = logfile_number_;
|
||||
} else if (write_with_wal > 1) {
|
||||
for (auto writer : write_group) {
|
||||
writer->log_used = logfile_number_;
|
||||
}
|
||||
}
|
||||
|
||||
WriteBatchInternal::SetSequence(merged_batch, sequence);
|
||||
|
||||
uint64_t log_size;
|
||||
status = WriteToWAL(*merged_batch, log_writer, log_used, &log_size);
|
||||
Slice log_entry = WriteBatchInternal::Contents(merged_batch);
|
||||
status = log_writer->AddRecord(log_entry);
|
||||
total_log_size_ += log_entry.size();
|
||||
alive_log_files_.back().AddSize(log_entry.size());
|
||||
log_empty_ = false;
|
||||
uint64_t log_size = log_entry.size();
|
||||
|
||||
if (status.ok() && need_log_sync) {
|
||||
StopWatch sw(env_, stats_, WAL_FILE_SYNC_MICROS);
|
||||
@@ -774,48 +448,6 @@ Status DBImpl::WriteToWAL(const WriteThread::WriteGroup& write_group,
|
||||
return status;
|
||||
}
|
||||
|
||||
Status DBImpl::ConcurrentWriteToWAL(const WriteThread::WriteGroup& write_group,
|
||||
uint64_t* log_used,
|
||||
SequenceNumber* last_sequence,
|
||||
int total_count) {
|
||||
Status status;
|
||||
|
||||
WriteBatch tmp_batch;
|
||||
size_t write_with_wal = 0;
|
||||
WriteBatch* merged_batch =
|
||||
MergeBatch(write_group, &tmp_batch, &write_with_wal);
|
||||
|
||||
// We need to lock log_write_mutex_ since logs_ and alive_log_files might be
|
||||
// pushed back concurrently
|
||||
log_write_mutex_.Lock();
|
||||
if (merged_batch == write_group.leader->batch) {
|
||||
write_group.leader->log_used = logfile_number_;
|
||||
} else if (write_with_wal > 1) {
|
||||
for (auto writer : write_group) {
|
||||
writer->log_used = logfile_number_;
|
||||
}
|
||||
}
|
||||
*last_sequence = versions_->FetchAddLastToBeWrittenSequence(total_count);
|
||||
auto sequence = *last_sequence + 1;
|
||||
WriteBatchInternal::SetSequence(merged_batch, sequence);
|
||||
|
||||
log::Writer* log_writer = logs_.back().writer;
|
||||
uint64_t log_size;
|
||||
status = WriteToWAL(*merged_batch, log_writer, log_used, &log_size);
|
||||
log_write_mutex_.Unlock();
|
||||
|
||||
if (status.ok()) {
|
||||
const bool concurrent = true;
|
||||
auto stats = default_cf_internal_stats_;
|
||||
stats->AddDBStats(InternalStats::WAL_FILE_BYTES, log_size, concurrent);
|
||||
RecordTick(stats_, WAL_FILE_BYTES, log_size);
|
||||
stats->AddDBStats(InternalStats::WRITE_WITH_WAL, write_with_wal,
|
||||
concurrent);
|
||||
RecordTick(stats_, WRITE_WITH_WAL, write_with_wal);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
Status DBImpl::HandleWALFull(WriteContext* write_context) {
|
||||
mutex_.AssertHeld();
|
||||
assert(write_context != nullptr);
|
||||
@@ -980,35 +612,6 @@ Status DBImpl::DelayWrite(uint64_t num_bytes,
|
||||
return bg_error_;
|
||||
}
|
||||
|
||||
Status DBImpl::ThrottleLowPriWritesIfNeeded(const WriteOptions& write_options,
|
||||
WriteBatch* my_batch) {
|
||||
assert(write_options.low_pri);
|
||||
// This is called outside the DB mutex. Although it is safe to make the call,
|
||||
// the consistency condition is not guaranteed to hold. It's OK to live with
|
||||
// it in this case.
|
||||
// If we need to speed compaction, it means the compaction is left behind
|
||||
// and we start to limit low pri writes to a limit.
|
||||
if (write_controller_.NeedSpeedupCompaction()) {
|
||||
if (allow_2pc() && (my_batch->HasCommit() || my_batch->HasRollback())) {
|
||||
// For 2PC, we only rate limit prepare, not commit.
|
||||
return Status::OK();
|
||||
}
|
||||
if (write_options.no_slowdown) {
|
||||
return Status::Incomplete();
|
||||
} else {
|
||||
assert(my_batch != nullptr);
|
||||
// Rate limit those writes. The reason that we don't completely wait
|
||||
// is that in case the write is heavy, low pri writes may never have
|
||||
// a chance to run. Now we guarantee we are still slowly making
|
||||
// progress.
|
||||
write_controller_.low_pri_rate_limiter()->Request(
|
||||
my_batch->GetDataSize(), Env::IO_HIGH, nullptr /* stats */,
|
||||
RateLimiter::OpType::kWrite);
|
||||
}
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status DBImpl::ScheduleFlushes(WriteContext* context) {
|
||||
ColumnFamilyData* cfd;
|
||||
while ((cfd = flush_scheduler_.TakeNextColumnFamily()) != nullptr) {
|
||||
@@ -1043,33 +646,14 @@ void DBImpl::NotifyOnMemTableSealed(ColumnFamilyData* cfd,
|
||||
// REQUIRES: this thread is currently at the front of the writer queue
|
||||
Status DBImpl::SwitchMemtable(ColumnFamilyData* cfd, WriteContext* context) {
|
||||
mutex_.AssertHeld();
|
||||
WriteThread::Writer nonmem_w;
|
||||
if (concurrent_prepare_) {
|
||||
// SwitchMemtable is a rare event. To simply the reasoning, we make sure
|
||||
// that there is no concurrent thread writing to WAL.
|
||||
nonmem_write_thread_.EnterUnbatched(&nonmem_w, &mutex_);
|
||||
}
|
||||
|
||||
unique_ptr<WritableFile> lfile;
|
||||
log::Writer* new_log = nullptr;
|
||||
MemTable* new_mem = nullptr;
|
||||
|
||||
// In case of pipelined write is enabled, wait for all pending memtable
|
||||
// writers.
|
||||
if (immutable_db_options_.enable_pipelined_write) {
|
||||
write_thread_.WaitForMemTableWriters();
|
||||
}
|
||||
|
||||
// Attempt to switch to a new memtable and trigger flush of old.
|
||||
// Do this without holding the dbmutex lock.
|
||||
assert(versions_->prev_log_number() == 0);
|
||||
if (concurrent_prepare_) {
|
||||
log_write_mutex_.Lock();
|
||||
}
|
||||
bool creating_new_log = !log_empty_;
|
||||
if (concurrent_prepare_) {
|
||||
log_write_mutex_.Unlock();
|
||||
}
|
||||
uint64_t recycle_log_number = 0;
|
||||
if (creating_new_log && immutable_db_options_.recycle_log_file_num &&
|
||||
!log_recycle_files.empty()) {
|
||||
@@ -1081,7 +665,7 @@ Status DBImpl::SwitchMemtable(ColumnFamilyData* cfd, WriteContext* context) {
|
||||
SuperVersion* new_superversion = nullptr;
|
||||
const MutableCFOptions mutable_cf_options = *cfd->GetLatestMutableCFOptions();
|
||||
|
||||
// Set memtable_info for memtable sealed callback
|
||||
// Set current_memtble_info for memtable sealed callback
|
||||
#ifndef ROCKSDB_LITE
|
||||
MemTableInfo memtable_info;
|
||||
memtable_info.cf_name = cfd->GetName();
|
||||
@@ -1125,9 +709,9 @@ Status DBImpl::SwitchMemtable(ColumnFamilyData* cfd, WriteContext* context) {
|
||||
lfile->SetPreallocationBlockSize(preallocate_block_size);
|
||||
unique_ptr<WritableFileWriter> file_writer(
|
||||
new WritableFileWriter(std::move(lfile), opt_env_opt));
|
||||
new_log = new log::Writer(
|
||||
std::move(file_writer), new_log_number,
|
||||
immutable_db_options_.recycle_log_file_num > 0, manual_wal_flush_);
|
||||
new_log =
|
||||
new log::Writer(std::move(file_writer), new_log_number,
|
||||
immutable_db_options_.recycle_log_file_num > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1154,25 +738,15 @@ Status DBImpl::SwitchMemtable(ColumnFamilyData* cfd, WriteContext* context) {
|
||||
assert(creating_new_log);
|
||||
assert(!new_mem);
|
||||
assert(!new_log);
|
||||
if (concurrent_prepare_) {
|
||||
nonmem_write_thread_.ExitUnbatched(&nonmem_w);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
if (creating_new_log) {
|
||||
log_write_mutex_.Lock();
|
||||
logfile_number_ = new_log_number;
|
||||
assert(new_log != nullptr);
|
||||
log_empty_ = true;
|
||||
log_dir_synced_ = false;
|
||||
if (!logs_.empty()) {
|
||||
// Alway flush the buffer of the last log before switching to a new one
|
||||
log::Writer* cur_log_writer = logs_.back().writer;
|
||||
cur_log_writer->WriteBuffer();
|
||||
}
|
||||
logs_.emplace_back(logfile_number_, new_log);
|
||||
alive_log_files_.push_back(LogFileNumberSize(logfile_number_));
|
||||
log_write_mutex_.Unlock();
|
||||
}
|
||||
for (auto loop_cfd : *versions_->GetColumnFamilySet()) {
|
||||
// all this is just optimization to delete logs that
|
||||
@@ -1194,9 +768,6 @@ Status DBImpl::SwitchMemtable(ColumnFamilyData* cfd, WriteContext* context) {
|
||||
cfd->SetMemtable(new_mem);
|
||||
context->superversions_to_free_.push_back(InstallSuperVersionAndScheduleWork(
|
||||
cfd, new_superversion, mutable_cf_options));
|
||||
if (concurrent_prepare_) {
|
||||
nonmem_write_thread_.ExitUnbatched(&nonmem_w);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
+1
-309
@@ -204,6 +204,7 @@ TEST_F(DBIOFailureTest, ManifestWriteError) {
|
||||
ASSERT_EQ("bar2", Get("foo2"));
|
||||
}
|
||||
}
|
||||
#endif // ROCKSDB_LITE
|
||||
|
||||
TEST_F(DBIOFailureTest, PutFailsParanoid) {
|
||||
// Test the following:
|
||||
@@ -249,316 +250,7 @@ TEST_F(DBIOFailureTest, PutFailsParanoid) {
|
||||
// the next put should NOT fail
|
||||
ASSERT_TRUE(s.ok());
|
||||
}
|
||||
#if !(defined NDEBUG) || !defined(OS_WIN)
|
||||
TEST_F(DBIOFailureTest, FlushSstRangeSyncError) {
|
||||
Options options = CurrentOptions();
|
||||
options.env = env_;
|
||||
options.create_if_missing = true;
|
||||
options.error_if_exists = false;
|
||||
options.paranoid_checks = true;
|
||||
options.write_buffer_size = 256 * 1024 * 1024;
|
||||
options.writable_file_max_buffer_size = 128 * 1024;
|
||||
options.bytes_per_sync = 128 * 1024;
|
||||
options.level0_file_num_compaction_trigger = 4;
|
||||
options.memtable_factory.reset(new SpecialSkipListFactory(10));
|
||||
BlockBasedTableOptions table_options;
|
||||
table_options.filter_policy.reset(NewBloomFilterPolicy(10));
|
||||
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
|
||||
|
||||
DestroyAndReopen(options);
|
||||
CreateAndReopenWithCF({"pikachu"}, options);
|
||||
Status s;
|
||||
|
||||
std::atomic<int> range_sync_called(0);
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"SpecialEnv::SStableFile::RangeSync", [&](void* arg) {
|
||||
if (range_sync_called.fetch_add(1) == 0) {
|
||||
Status* st = static_cast<Status*>(arg);
|
||||
*st = Status::IOError("range sync dummy error");
|
||||
}
|
||||
});
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
Random rnd(301);
|
||||
std::string rnd_str =
|
||||
RandomString(&rnd, static_cast<int>(options.bytes_per_sync / 2));
|
||||
std::string rnd_str_512kb = RandomString(&rnd, 512 * 1024);
|
||||
|
||||
ASSERT_OK(Put(1, "foo", "bar"));
|
||||
// First 1MB doesn't get range synced
|
||||
ASSERT_OK(Put(1, "foo0_0", rnd_str_512kb));
|
||||
ASSERT_OK(Put(1, "foo0_1", rnd_str_512kb));
|
||||
ASSERT_OK(Put(1, "foo1_1", rnd_str));
|
||||
ASSERT_OK(Put(1, "foo1_2", rnd_str));
|
||||
ASSERT_OK(Put(1, "foo1_3", rnd_str));
|
||||
ASSERT_OK(Put(1, "foo2", "bar"));
|
||||
ASSERT_OK(Put(1, "foo3_1", rnd_str));
|
||||
ASSERT_OK(Put(1, "foo3_2", rnd_str));
|
||||
ASSERT_OK(Put(1, "foo3_3", rnd_str));
|
||||
ASSERT_OK(Put(1, "foo4", "bar"));
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[1]);
|
||||
|
||||
// Following writes should fail as flush failed.
|
||||
ASSERT_NOK(Put(1, "foo2", "bar3"));
|
||||
ASSERT_EQ("bar", Get(1, "foo"));
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
ASSERT_GE(1, range_sync_called.load());
|
||||
|
||||
ReopenWithColumnFamilies({"default", "pikachu"}, options);
|
||||
ASSERT_EQ("bar", Get(1, "foo"));
|
||||
}
|
||||
|
||||
TEST_F(DBIOFailureTest, CompactSstRangeSyncError) {
|
||||
Options options = CurrentOptions();
|
||||
options.env = env_;
|
||||
options.create_if_missing = true;
|
||||
options.error_if_exists = false;
|
||||
options.paranoid_checks = true;
|
||||
options.write_buffer_size = 256 * 1024 * 1024;
|
||||
options.writable_file_max_buffer_size = 128 * 1024;
|
||||
options.bytes_per_sync = 128 * 1024;
|
||||
options.level0_file_num_compaction_trigger = 2;
|
||||
options.target_file_size_base = 256 * 1024 * 1024;
|
||||
options.disable_auto_compactions = true;
|
||||
BlockBasedTableOptions table_options;
|
||||
table_options.filter_policy.reset(NewBloomFilterPolicy(10));
|
||||
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
|
||||
DestroyAndReopen(options);
|
||||
CreateAndReopenWithCF({"pikachu"}, options);
|
||||
Status s;
|
||||
|
||||
Random rnd(301);
|
||||
std::string rnd_str =
|
||||
RandomString(&rnd, static_cast<int>(options.bytes_per_sync / 2));
|
||||
std::string rnd_str_512kb = RandomString(&rnd, 512 * 1024);
|
||||
|
||||
ASSERT_OK(Put(1, "foo", "bar"));
|
||||
// First 1MB doesn't get range synced
|
||||
ASSERT_OK(Put(1, "foo0_0", rnd_str_512kb));
|
||||
ASSERT_OK(Put(1, "foo0_1", rnd_str_512kb));
|
||||
ASSERT_OK(Put(1, "foo1_1", rnd_str));
|
||||
ASSERT_OK(Put(1, "foo1_2", rnd_str));
|
||||
ASSERT_OK(Put(1, "foo1_3", rnd_str));
|
||||
Flush(1);
|
||||
ASSERT_OK(Put(1, "foo", "bar"));
|
||||
ASSERT_OK(Put(1, "foo3_1", rnd_str));
|
||||
ASSERT_OK(Put(1, "foo3_2", rnd_str));
|
||||
ASSERT_OK(Put(1, "foo3_3", rnd_str));
|
||||
ASSERT_OK(Put(1, "foo4", "bar"));
|
||||
Flush(1);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[1]);
|
||||
|
||||
std::atomic<int> range_sync_called(0);
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"SpecialEnv::SStableFile::RangeSync", [&](void* arg) {
|
||||
if (range_sync_called.fetch_add(1) == 0) {
|
||||
Status* st = static_cast<Status*>(arg);
|
||||
*st = Status::IOError("range sync dummy error");
|
||||
}
|
||||
});
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
ASSERT_OK(dbfull()->SetOptions(handles_[1],
|
||||
{
|
||||
{"disable_auto_compactions", "false"},
|
||||
}));
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
|
||||
// Following writes should fail as flush failed.
|
||||
ASSERT_NOK(Put(1, "foo2", "bar3"));
|
||||
ASSERT_EQ("bar", Get(1, "foo"));
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
ASSERT_GE(1, range_sync_called.load());
|
||||
|
||||
ReopenWithColumnFamilies({"default", "pikachu"}, options);
|
||||
ASSERT_EQ("bar", Get(1, "foo"));
|
||||
}
|
||||
|
||||
TEST_F(DBIOFailureTest, FlushSstCloseError) {
|
||||
Options options = CurrentOptions();
|
||||
options.env = env_;
|
||||
options.create_if_missing = true;
|
||||
options.error_if_exists = false;
|
||||
options.paranoid_checks = true;
|
||||
options.level0_file_num_compaction_trigger = 4;
|
||||
options.memtable_factory.reset(new SpecialSkipListFactory(2));
|
||||
|
||||
DestroyAndReopen(options);
|
||||
CreateAndReopenWithCF({"pikachu"}, options);
|
||||
Status s;
|
||||
std::atomic<int> close_called(0);
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"SpecialEnv::SStableFile::Close", [&](void* arg) {
|
||||
if (close_called.fetch_add(1) == 0) {
|
||||
Status* st = static_cast<Status*>(arg);
|
||||
*st = Status::IOError("close dummy error");
|
||||
}
|
||||
});
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
ASSERT_OK(Put(1, "foo", "bar"));
|
||||
ASSERT_OK(Put(1, "foo1", "bar1"));
|
||||
ASSERT_OK(Put(1, "foo", "bar2"));
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[1]);
|
||||
|
||||
// Following writes should fail as flush failed.
|
||||
ASSERT_NOK(Put(1, "foo2", "bar3"));
|
||||
ASSERT_EQ("bar2", Get(1, "foo"));
|
||||
ASSERT_EQ("bar1", Get(1, "foo1"));
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
|
||||
ReopenWithColumnFamilies({"default", "pikachu"}, options);
|
||||
ASSERT_EQ("bar2", Get(1, "foo"));
|
||||
ASSERT_EQ("bar1", Get(1, "foo1"));
|
||||
}
|
||||
|
||||
TEST_F(DBIOFailureTest, CompactionSstCloseError) {
|
||||
Options options = CurrentOptions();
|
||||
options.env = env_;
|
||||
options.create_if_missing = true;
|
||||
options.error_if_exists = false;
|
||||
options.paranoid_checks = true;
|
||||
options.level0_file_num_compaction_trigger = 2;
|
||||
options.disable_auto_compactions = true;
|
||||
|
||||
DestroyAndReopen(options);
|
||||
CreateAndReopenWithCF({"pikachu"}, options);
|
||||
Status s;
|
||||
|
||||
ASSERT_OK(Put(1, "foo", "bar"));
|
||||
ASSERT_OK(Put(1, "foo2", "bar"));
|
||||
Flush(1);
|
||||
ASSERT_OK(Put(1, "foo", "bar2"));
|
||||
ASSERT_OK(Put(1, "foo2", "bar"));
|
||||
Flush(1);
|
||||
ASSERT_OK(Put(1, "foo", "bar3"));
|
||||
ASSERT_OK(Put(1, "foo2", "bar"));
|
||||
Flush(1);
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
|
||||
std::atomic<int> close_called(0);
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"SpecialEnv::SStableFile::Close", [&](void* arg) {
|
||||
if (close_called.fetch_add(1) == 0) {
|
||||
Status* st = static_cast<Status*>(arg);
|
||||
*st = Status::IOError("close dummy error");
|
||||
}
|
||||
});
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
ASSERT_OK(dbfull()->SetOptions(handles_[1],
|
||||
{
|
||||
{"disable_auto_compactions", "false"},
|
||||
}));
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
|
||||
// Following writes should fail as compaction failed.
|
||||
ASSERT_NOK(Put(1, "foo2", "bar3"));
|
||||
ASSERT_EQ("bar3", Get(1, "foo"));
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
|
||||
ReopenWithColumnFamilies({"default", "pikachu"}, options);
|
||||
ASSERT_EQ("bar3", Get(1, "foo"));
|
||||
}
|
||||
|
||||
TEST_F(DBIOFailureTest, FlushSstSyncError) {
|
||||
Options options = CurrentOptions();
|
||||
options.env = env_;
|
||||
options.create_if_missing = true;
|
||||
options.error_if_exists = false;
|
||||
options.paranoid_checks = true;
|
||||
options.use_fsync = false;
|
||||
options.level0_file_num_compaction_trigger = 4;
|
||||
options.memtable_factory.reset(new SpecialSkipListFactory(2));
|
||||
|
||||
DestroyAndReopen(options);
|
||||
CreateAndReopenWithCF({"pikachu"}, options);
|
||||
Status s;
|
||||
std::atomic<int> sync_called(0);
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"SpecialEnv::SStableFile::Sync", [&](void* arg) {
|
||||
if (sync_called.fetch_add(1) == 0) {
|
||||
Status* st = static_cast<Status*>(arg);
|
||||
*st = Status::IOError("sync dummy error");
|
||||
}
|
||||
});
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
ASSERT_OK(Put(1, "foo", "bar"));
|
||||
ASSERT_OK(Put(1, "foo1", "bar1"));
|
||||
ASSERT_OK(Put(1, "foo", "bar2"));
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[1]);
|
||||
|
||||
// Following writes should fail as flush failed.
|
||||
ASSERT_NOK(Put(1, "foo2", "bar3"));
|
||||
ASSERT_EQ("bar2", Get(1, "foo"));
|
||||
ASSERT_EQ("bar1", Get(1, "foo1"));
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
|
||||
ReopenWithColumnFamilies({"default", "pikachu"}, options);
|
||||
ASSERT_EQ("bar2", Get(1, "foo"));
|
||||
ASSERT_EQ("bar1", Get(1, "foo1"));
|
||||
}
|
||||
|
||||
TEST_F(DBIOFailureTest, CompactionSstSyncError) {
|
||||
Options options = CurrentOptions();
|
||||
options.env = env_;
|
||||
options.create_if_missing = true;
|
||||
options.error_if_exists = false;
|
||||
options.paranoid_checks = true;
|
||||
options.level0_file_num_compaction_trigger = 2;
|
||||
options.disable_auto_compactions = true;
|
||||
options.use_fsync = false;
|
||||
|
||||
DestroyAndReopen(options);
|
||||
CreateAndReopenWithCF({"pikachu"}, options);
|
||||
Status s;
|
||||
|
||||
ASSERT_OK(Put(1, "foo", "bar"));
|
||||
ASSERT_OK(Put(1, "foo2", "bar"));
|
||||
Flush(1);
|
||||
ASSERT_OK(Put(1, "foo", "bar2"));
|
||||
ASSERT_OK(Put(1, "foo2", "bar"));
|
||||
Flush(1);
|
||||
ASSERT_OK(Put(1, "foo", "bar3"));
|
||||
ASSERT_OK(Put(1, "foo2", "bar"));
|
||||
Flush(1);
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
|
||||
std::atomic<int> sync_called(0);
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"SpecialEnv::SStableFile::Sync", [&](void* arg) {
|
||||
if (sync_called.fetch_add(1) == 0) {
|
||||
Status* st = static_cast<Status*>(arg);
|
||||
*st = Status::IOError("close dummy error");
|
||||
}
|
||||
});
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
ASSERT_OK(dbfull()->SetOptions(handles_[1],
|
||||
{
|
||||
{"disable_auto_compactions", "false"},
|
||||
}));
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
|
||||
// Following writes should fail as compaction failed.
|
||||
ASSERT_NOK(Put(1, "foo2", "bar3"));
|
||||
ASSERT_EQ("bar3", Get(1, "foo"));
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
|
||||
ReopenWithColumnFamilies({"default", "pikachu"}, options);
|
||||
ASSERT_EQ("bar3", Get(1, "foo"));
|
||||
}
|
||||
#endif // !(defined NDEBUG) || !defined(OS_WIN)
|
||||
#endif // ROCKSDB_LITE
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
+39
-147
@@ -8,6 +8,8 @@
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
|
||||
#include "db/db_iter.h"
|
||||
#include <stdexcept>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
|
||||
@@ -16,6 +18,7 @@
|
||||
#include "db/merge_helper.h"
|
||||
#include "db/pinned_iterators_manager.h"
|
||||
#include "monitoring/perf_context_imp.h"
|
||||
#include "port/port.h"
|
||||
#include "rocksdb/env.h"
|
||||
#include "rocksdb/iterator.h"
|
||||
#include "rocksdb/merge_operator.h"
|
||||
@@ -83,7 +86,6 @@ class DBIter: public Iterator {
|
||||
RecordTick(global_statistics, NUMBER_DB_PREV, prev_count_);
|
||||
RecordTick(global_statistics, NUMBER_DB_PREV_FOUND, prev_found_count_);
|
||||
RecordTick(global_statistics, ITER_BYTES_READ, bytes_read_);
|
||||
PERF_COUNTER_ADD(iter_read_bytes, bytes_read_);
|
||||
ResetCounters();
|
||||
}
|
||||
|
||||
@@ -99,12 +101,12 @@ class DBIter: public Iterator {
|
||||
uint64_t bytes_read_;
|
||||
};
|
||||
|
||||
DBIter(Env* _env, const ReadOptions& read_options,
|
||||
DBIter(Env* env, const ReadOptions& read_options,
|
||||
const ImmutableCFOptions& cf_options, const Comparator* cmp,
|
||||
InternalIterator* iter, SequenceNumber s, bool arena_mode,
|
||||
uint64_t max_sequential_skip_in_iterations, bool allow_blob)
|
||||
uint64_t max_sequential_skip_in_iterations, uint64_t version_number)
|
||||
: arena_mode_(arena_mode),
|
||||
env_(_env),
|
||||
env_(env),
|
||||
logger_(cf_options.info_log),
|
||||
user_comparator_(cmp),
|
||||
merge_operator_(cf_options.merge_operator),
|
||||
@@ -114,13 +116,13 @@ class DBIter: public Iterator {
|
||||
valid_(false),
|
||||
current_entry_is_merged_(false),
|
||||
statistics_(cf_options.statistics),
|
||||
version_number_(version_number),
|
||||
iterate_upper_bound_(read_options.iterate_upper_bound),
|
||||
prefix_same_as_start_(read_options.prefix_same_as_start),
|
||||
pin_thru_lifetime_(read_options.pin_data),
|
||||
total_order_seek_(read_options.total_order_seek),
|
||||
range_del_agg_(cf_options.internal_comparator, s,
|
||||
true /* collapse_deletions */),
|
||||
allow_blob_(allow_blob) {
|
||||
true /* collapse_deletions */) {
|
||||
RecordTick(statistics_, NO_ITERATORS);
|
||||
prefix_extractor_ = cf_options.prefix_extractor;
|
||||
max_skip_ = max_sequential_skip_in_iterations;
|
||||
@@ -178,10 +180,6 @@ class DBIter: public Iterator {
|
||||
return status_;
|
||||
}
|
||||
}
|
||||
bool IsBlob() const {
|
||||
assert(valid_ && (allow_blob_ || !is_blob_));
|
||||
return is_blob_;
|
||||
}
|
||||
|
||||
virtual Status GetProperty(std::string prop_name,
|
||||
std::string* prop) override {
|
||||
@@ -190,7 +188,10 @@ class DBIter: public Iterator {
|
||||
}
|
||||
if (prop_name == "rocksdb.iterator.super-version-number") {
|
||||
// First try to pass the value returned from inner iterator.
|
||||
return iter_->GetProperty(prop_name, prop);
|
||||
if (!iter_->GetProperty(prop_name, prop).ok()) {
|
||||
*prop = ToString(version_number_);
|
||||
}
|
||||
return Status::OK();
|
||||
} else if (prop_name == "rocksdb.iterator.is-key-pinned") {
|
||||
if (valid_) {
|
||||
*prop = (pin_thru_lifetime_ && saved_key_.IsKeyPinned()) ? "1" : "0";
|
||||
@@ -208,9 +209,6 @@ class DBIter: public Iterator {
|
||||
virtual void SeekForPrev(const Slice& target) override;
|
||||
virtual void SeekToFirst() override;
|
||||
virtual void SeekToLast() override;
|
||||
Env* env() { return env_; }
|
||||
void set_sequence(uint64_t s) { sequence_ = s; }
|
||||
void set_valid(bool v) { valid_ = v; }
|
||||
|
||||
private:
|
||||
void ReverseToForward();
|
||||
@@ -262,7 +260,7 @@ class DBIter: public Iterator {
|
||||
const Comparator* const user_comparator_;
|
||||
const MergeOperator* const merge_operator_;
|
||||
InternalIterator* iter_;
|
||||
SequenceNumber sequence_;
|
||||
SequenceNumber const sequence_;
|
||||
|
||||
Status status_;
|
||||
IterKey saved_key_;
|
||||
@@ -276,6 +274,7 @@ class DBIter: public Iterator {
|
||||
uint64_t max_skip_;
|
||||
uint64_t max_skippable_internal_keys_;
|
||||
uint64_t num_internal_keys_skipped_;
|
||||
uint64_t version_number_;
|
||||
const Slice* iterate_upper_bound_;
|
||||
IterKey prefix_start_buf_;
|
||||
Slice prefix_start_key_;
|
||||
@@ -289,8 +288,6 @@ class DBIter: public Iterator {
|
||||
RangeDelAggregator range_del_agg_;
|
||||
LocalStatistics local_stats_;
|
||||
PinnedIteratorsManager pinned_iters_mgr_;
|
||||
bool allow_blob_;
|
||||
bool is_blob_;
|
||||
|
||||
// No copying allowed
|
||||
DBIter(const DBIter&);
|
||||
@@ -380,8 +377,6 @@ void DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
|
||||
// - none of the above : saved_key_ can contain anything, it doesn't matter.
|
||||
uint64_t num_skipped = 0;
|
||||
|
||||
is_blob_ = false;
|
||||
|
||||
do {
|
||||
ParsedInternalKey ikey;
|
||||
|
||||
@@ -426,7 +421,6 @@ void DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
|
||||
PERF_COUNTER_ADD(internal_delete_skipped_count, 1);
|
||||
break;
|
||||
case kTypeValue:
|
||||
case kTypeBlobIndex:
|
||||
saved_key_.SetUserKey(
|
||||
ikey.user_key,
|
||||
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
|
||||
@@ -438,18 +432,6 @@ void DBIter::FindNextUserEntryInternal(bool skipping, bool prefix_check) {
|
||||
skipping = true;
|
||||
num_skipped = 0;
|
||||
PERF_COUNTER_ADD(internal_delete_skipped_count, 1);
|
||||
} else if (ikey.type == kTypeBlobIndex) {
|
||||
if (!allow_blob_) {
|
||||
ROCKS_LOG_ERROR(logger_, "Encounter unexpected blob index.");
|
||||
status_ = Status::NotSupported(
|
||||
"Encounter unexpected blob index. Please open DB with "
|
||||
"rocksdb::blob_db::BlobDB instead.");
|
||||
valid_ = false;
|
||||
} else {
|
||||
is_blob_ = true;
|
||||
valid_ = true;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
valid_ = true;
|
||||
return;
|
||||
@@ -578,7 +560,7 @@ void DBIter::MergeValuesNewToOld() {
|
||||
const Slice val = iter_->value();
|
||||
s = MergeHelper::TimedFullMerge(
|
||||
merge_operator_, ikey.user_key, &val, merge_context_.GetOperands(),
|
||||
&saved_value_, logger_, statistics_, env_, &pinned_value_, true);
|
||||
&saved_value_, logger_, statistics_, env_, &pinned_value_);
|
||||
if (!s.ok()) {
|
||||
status_ = s;
|
||||
}
|
||||
@@ -591,18 +573,6 @@ void DBIter::MergeValuesNewToOld() {
|
||||
merge_context_.PushOperand(iter_->value(),
|
||||
iter_->IsValuePinned() /* operand_pinned */);
|
||||
PERF_COUNTER_ADD(internal_merge_count, 1);
|
||||
} else if (kTypeBlobIndex == ikey.type) {
|
||||
if (!allow_blob_) {
|
||||
ROCKS_LOG_ERROR(logger_, "Encounter unexpected blob index.");
|
||||
status_ = Status::NotSupported(
|
||||
"Encounter unexpected blob index. Please open DB with "
|
||||
"rocksdb::blob_db::BlobDB instead.");
|
||||
} else {
|
||||
status_ =
|
||||
Status::NotSupported("Blob DB does not support merge operator.");
|
||||
}
|
||||
valid_ = false;
|
||||
return;
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
@@ -615,7 +585,7 @@ void DBIter::MergeValuesNewToOld() {
|
||||
s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetUserKey(),
|
||||
nullptr, merge_context_.GetOperands(),
|
||||
&saved_value_, logger_, statistics_, env_,
|
||||
&pinned_value_, true);
|
||||
&pinned_value_);
|
||||
if (!s.ok()) {
|
||||
status_ = s;
|
||||
}
|
||||
@@ -672,7 +642,6 @@ void DBIter::ReverseToBackward() {
|
||||
while (iter_->Valid() &&
|
||||
user_comparator_->Compare(ikey.user_key, saved_key_.GetUserKey()) >
|
||||
0) {
|
||||
assert(ikey.sequence != kMaxSequenceNumber);
|
||||
if (ikey.sequence > sequence_) {
|
||||
PERF_COUNTER_ADD(internal_recent_skipped_count, 1);
|
||||
} else {
|
||||
@@ -709,6 +678,7 @@ void DBIter::PrevInternal() {
|
||||
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
|
||||
|
||||
if (FindValueForCurrentKey()) {
|
||||
valid_ = true;
|
||||
if (!iter_->Valid()) {
|
||||
return;
|
||||
}
|
||||
@@ -775,7 +745,6 @@ bool DBIter::FindValueForCurrentKey() {
|
||||
last_key_entry_type = ikey.type;
|
||||
switch (last_key_entry_type) {
|
||||
case kTypeValue:
|
||||
case kTypeBlobIndex:
|
||||
if (range_del_agg_.ShouldDelete(
|
||||
ikey,
|
||||
RangeDelAggregator::RangePositioningMode::kBackwardTraversal)) {
|
||||
@@ -821,7 +790,6 @@ bool DBIter::FindValueForCurrentKey() {
|
||||
}
|
||||
|
||||
Status s;
|
||||
is_blob_ = false;
|
||||
switch (last_key_entry_type) {
|
||||
case kTypeDeletion:
|
||||
case kTypeSingleDeletion:
|
||||
@@ -836,41 +804,18 @@ bool DBIter::FindValueForCurrentKey() {
|
||||
s = MergeHelper::TimedFullMerge(
|
||||
merge_operator_, saved_key_.GetUserKey(), nullptr,
|
||||
merge_context_.GetOperands(), &saved_value_, logger_, statistics_,
|
||||
env_, &pinned_value_, true);
|
||||
} else if (last_not_merge_type == kTypeBlobIndex) {
|
||||
if (!allow_blob_) {
|
||||
ROCKS_LOG_ERROR(logger_, "Encounter unexpected blob index.");
|
||||
status_ = Status::NotSupported(
|
||||
"Encounter unexpected blob index. Please open DB with "
|
||||
"rocksdb::blob_db::BlobDB instead.");
|
||||
} else {
|
||||
status_ =
|
||||
Status::NotSupported("Blob DB does not support merge operator.");
|
||||
}
|
||||
valid_ = false;
|
||||
return true;
|
||||
env_, &pinned_value_);
|
||||
} else {
|
||||
assert(last_not_merge_type == kTypeValue);
|
||||
s = MergeHelper::TimedFullMerge(
|
||||
merge_operator_, saved_key_.GetUserKey(), &pinned_value_,
|
||||
merge_context_.GetOperands(), &saved_value_, logger_, statistics_,
|
||||
env_, &pinned_value_, true);
|
||||
env_, &pinned_value_);
|
||||
}
|
||||
break;
|
||||
case kTypeValue:
|
||||
// do nothing - we've already has value in saved_value_
|
||||
break;
|
||||
case kTypeBlobIndex:
|
||||
if (!allow_blob_) {
|
||||
ROCKS_LOG_ERROR(logger_, "Encounter unexpected blob index.");
|
||||
status_ = Status::NotSupported(
|
||||
"Encounter unexpected blob index. Please open DB with "
|
||||
"rocksdb::blob_db::BlobDB instead.");
|
||||
valid_ = false;
|
||||
return true;
|
||||
}
|
||||
is_blob_ = true;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
@@ -904,15 +849,7 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
||||
valid_ = false;
|
||||
return false;
|
||||
}
|
||||
if (ikey.type == kTypeBlobIndex && !allow_blob_) {
|
||||
ROCKS_LOG_ERROR(logger_, "Encounter unexpected blob index.");
|
||||
status_ = Status::NotSupported(
|
||||
"Encounter unexpected blob index. Please open DB with "
|
||||
"rocksdb::blob_db::BlobDB instead.");
|
||||
valid_ = false;
|
||||
return true;
|
||||
}
|
||||
if (ikey.type == kTypeValue || ikey.type == kTypeBlobIndex) {
|
||||
if (ikey.type == kTypeValue) {
|
||||
assert(iter_->IsValuePinned());
|
||||
pinned_value_ = iter_->value();
|
||||
valid_ = true;
|
||||
@@ -945,7 +882,7 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
||||
s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetUserKey(),
|
||||
nullptr, merge_context_.GetOperands(),
|
||||
&saved_value_, logger_, statistics_, env_,
|
||||
&pinned_value_, true);
|
||||
&pinned_value_);
|
||||
// Make iter_ valid and point to saved_key_
|
||||
if (!iter_->Valid() ||
|
||||
!user_comparator_->Equal(ikey.user_key, saved_key_.GetUserKey())) {
|
||||
@@ -963,7 +900,7 @@ bool DBIter::FindValueForCurrentKeyUsingSeek() {
|
||||
s = MergeHelper::TimedFullMerge(merge_operator_, saved_key_.GetUserKey(),
|
||||
&val, merge_context_.GetOperands(),
|
||||
&saved_value_, logger_, statistics_, env_,
|
||||
&pinned_value_, true);
|
||||
&pinned_value_);
|
||||
valid_ = true;
|
||||
if (!s.ok()) {
|
||||
status_ = s;
|
||||
@@ -1017,7 +954,6 @@ void DBIter::FindPrevUserKey() {
|
||||
++num_skipped;
|
||||
}
|
||||
}
|
||||
assert(ikey.sequence != kMaxSequenceNumber);
|
||||
if (ikey.sequence > sequence_) {
|
||||
PERF_COUNTER_ADD(internal_recent_skipped_count, 1);
|
||||
} else {
|
||||
@@ -1078,7 +1014,6 @@ void DBIter::Seek(const Slice& target) {
|
||||
if (valid_) {
|
||||
RecordTick(statistics_, NUMBER_DB_SEEK_FOUND);
|
||||
RecordTick(statistics_, ITER_BYTES_READ, key().size() + value().size());
|
||||
PERF_COUNTER_ADD(iter_read_bytes, key().size() + value().size());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1121,7 +1056,6 @@ void DBIter::SeekForPrev(const Slice& target) {
|
||||
if (valid_) {
|
||||
RecordTick(statistics_, NUMBER_DB_SEEK_FOUND);
|
||||
RecordTick(statistics_, ITER_BYTES_READ, key().size() + value().size());
|
||||
PERF_COUNTER_ADD(iter_read_bytes, key().size() + value().size());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1160,7 +1094,6 @@ void DBIter::SeekToFirst() {
|
||||
if (valid_) {
|
||||
RecordTick(statistics_, NUMBER_DB_SEEK_FOUND);
|
||||
RecordTick(statistics_, ITER_BYTES_READ, key().size() + value().size());
|
||||
PERF_COUNTER_ADD(iter_read_bytes, key().size() + value().size());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1208,7 +1141,6 @@ void DBIter::SeekToLast() {
|
||||
if (valid_) {
|
||||
RecordTick(statistics_, NUMBER_DB_SEEK_FOUND);
|
||||
RecordTick(statistics_, ITER_BYTES_READ, key().size() + value().size());
|
||||
PERF_COUNTER_ADD(iter_read_bytes, key().size() + value().size());
|
||||
}
|
||||
}
|
||||
if (valid_ && prefix_extractor_ && prefix_same_as_start_) {
|
||||
@@ -1224,15 +1156,17 @@ Iterator* NewDBIterator(Env* env, const ReadOptions& read_options,
|
||||
InternalIterator* internal_iter,
|
||||
const SequenceNumber& sequence,
|
||||
uint64_t max_sequential_skip_in_iterations,
|
||||
bool allow_blob) {
|
||||
uint64_t version_number) {
|
||||
DBIter* db_iter = new DBIter(
|
||||
env, read_options, cf_options, user_key_comparator, internal_iter,
|
||||
sequence, false, max_sequential_skip_in_iterations, allow_blob);
|
||||
sequence, false, max_sequential_skip_in_iterations, version_number);
|
||||
return db_iter;
|
||||
}
|
||||
|
||||
ArenaWrappedDBIter::~ArenaWrappedDBIter() { db_iter_->~DBIter(); }
|
||||
|
||||
void ArenaWrappedDBIter::SetDBIter(DBIter* iter) { db_iter_ = iter; }
|
||||
|
||||
RangeDelAggregator* ArenaWrappedDBIter::GetRangeDelAggregator() {
|
||||
return db_iter_->GetRangeDelAggregator();
|
||||
}
|
||||
@@ -1255,70 +1189,28 @@ inline void ArenaWrappedDBIter::Prev() { db_iter_->Prev(); }
|
||||
inline Slice ArenaWrappedDBIter::key() const { return db_iter_->key(); }
|
||||
inline Slice ArenaWrappedDBIter::value() const { return db_iter_->value(); }
|
||||
inline Status ArenaWrappedDBIter::status() const { return db_iter_->status(); }
|
||||
bool ArenaWrappedDBIter::IsBlob() const { return db_iter_->IsBlob(); }
|
||||
inline Status ArenaWrappedDBIter::GetProperty(std::string prop_name,
|
||||
std::string* prop) {
|
||||
if (prop_name == "rocksdb.iterator.super-version-number") {
|
||||
// First try to pass the value returned from inner iterator.
|
||||
if (!db_iter_->GetProperty(prop_name, prop).ok()) {
|
||||
*prop = ToString(sv_number_);
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
return db_iter_->GetProperty(prop_name, prop);
|
||||
}
|
||||
|
||||
void ArenaWrappedDBIter::Init(Env* env, const ReadOptions& read_options,
|
||||
const ImmutableCFOptions& cf_options,
|
||||
const SequenceNumber& sequence,
|
||||
uint64_t max_sequential_skip_in_iteration,
|
||||
uint64_t version_number, bool allow_blob) {
|
||||
auto mem = arena_.AllocateAligned(sizeof(DBIter));
|
||||
db_iter_ = new (mem)
|
||||
DBIter(env, read_options, cf_options, cf_options.user_comparator, nullptr,
|
||||
sequence, true, max_sequential_skip_in_iteration, allow_blob);
|
||||
sv_number_ = version_number;
|
||||
}
|
||||
|
||||
Status ArenaWrappedDBIter::Refresh() {
|
||||
if (cfd_ == nullptr || db_impl_ == nullptr) {
|
||||
return Status::NotSupported("Creating renew iterator is not allowed.");
|
||||
}
|
||||
assert(db_iter_ != nullptr);
|
||||
SequenceNumber latest_seq = db_impl_->GetLatestSequenceNumber();
|
||||
uint64_t cur_sv_number = cfd_->GetSuperVersionNumber();
|
||||
if (sv_number_ != cur_sv_number) {
|
||||
Env* env = db_iter_->env();
|
||||
db_iter_->~DBIter();
|
||||
arena_.~Arena();
|
||||
new (&arena_) Arena();
|
||||
|
||||
SuperVersion* sv = cfd_->GetReferencedSuperVersion(db_impl_->mutex());
|
||||
Init(env, read_options_, *(cfd_->ioptions()), latest_seq,
|
||||
sv->mutable_cf_options.max_sequential_skip_in_iterations,
|
||||
cur_sv_number, allow_blob_);
|
||||
|
||||
InternalIterator* internal_iter = db_impl_->NewInternalIterator(
|
||||
read_options_, cfd_, sv, &arena_, db_iter_->GetRangeDelAggregator());
|
||||
SetIterUnderDBIter(internal_iter);
|
||||
} else {
|
||||
db_iter_->set_sequence(latest_seq);
|
||||
db_iter_->set_valid(false);
|
||||
}
|
||||
return Status::OK();
|
||||
void ArenaWrappedDBIter::RegisterCleanup(CleanupFunction function, void* arg1,
|
||||
void* arg2) {
|
||||
db_iter_->RegisterCleanup(function, arg1, arg2);
|
||||
}
|
||||
|
||||
ArenaWrappedDBIter* NewArenaWrappedDbIterator(
|
||||
Env* env, const ReadOptions& read_options,
|
||||
const ImmutableCFOptions& cf_options, const SequenceNumber& sequence,
|
||||
uint64_t max_sequential_skip_in_iterations, uint64_t version_number,
|
||||
DBImpl* db_impl, ColumnFamilyData* cfd, bool allow_blob) {
|
||||
const ImmutableCFOptions& cf_options, const Comparator* user_key_comparator,
|
||||
const SequenceNumber& sequence, uint64_t max_sequential_skip_in_iterations,
|
||||
uint64_t version_number) {
|
||||
ArenaWrappedDBIter* iter = new ArenaWrappedDBIter();
|
||||
iter->Init(env, read_options, cf_options, sequence,
|
||||
max_sequential_skip_in_iterations, version_number, allow_blob);
|
||||
if (db_impl != nullptr && cfd != nullptr) {
|
||||
iter->StoreRefreshInfo(read_options, db_impl, cfd, allow_blob);
|
||||
}
|
||||
Arena* arena = iter->GetArena();
|
||||
auto mem = arena->AllocateAligned(sizeof(DBIter));
|
||||
DBIter* db_iter = new (mem)
|
||||
DBIter(env, read_options, cf_options, user_key_comparator, nullptr,
|
||||
sequence, true, max_sequential_skip_in_iterations, version_number);
|
||||
|
||||
iter->SetDBIter(db_iter);
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
+9
-29
@@ -10,7 +10,6 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include "db/db_impl.h"
|
||||
#include "db/dbformat.h"
|
||||
#include "db/range_del_aggregator.h"
|
||||
#include "options/cf_options.h"
|
||||
@@ -34,7 +33,7 @@ extern Iterator* NewDBIterator(Env* env, const ReadOptions& read_options,
|
||||
InternalIterator* internal_iter,
|
||||
const SequenceNumber& sequence,
|
||||
uint64_t max_sequential_skip_in_iterations,
|
||||
bool allow_blob = false);
|
||||
uint64_t version_number);
|
||||
|
||||
// A wrapper iterator which wraps DB Iterator and the arena, with which the DB
|
||||
// iterator is supposed be allocated. This class is used as an entry point of
|
||||
@@ -50,6 +49,10 @@ class ArenaWrappedDBIter : public Iterator {
|
||||
virtual Arena* GetArena() { return &arena_; }
|
||||
virtual RangeDelAggregator* GetRangeDelAggregator();
|
||||
|
||||
// Set the DB Iterator to be wrapped
|
||||
|
||||
virtual void SetDBIter(DBIter* iter);
|
||||
|
||||
// Set the internal iterator wrapped inside the DB Iterator. Usually it is
|
||||
// a merging iterator.
|
||||
virtual void SetIterUnderDBIter(InternalIterator* iter);
|
||||
@@ -63,43 +66,20 @@ class ArenaWrappedDBIter : public Iterator {
|
||||
virtual Slice key() const override;
|
||||
virtual Slice value() const override;
|
||||
virtual Status status() const override;
|
||||
virtual Status Refresh() override;
|
||||
bool IsBlob() const;
|
||||
|
||||
void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2);
|
||||
virtual Status GetProperty(std::string prop_name, std::string* prop) override;
|
||||
|
||||
void Init(Env* env, const ReadOptions& read_options,
|
||||
const ImmutableCFOptions& cf_options,
|
||||
const SequenceNumber& sequence,
|
||||
uint64_t max_sequential_skip_in_iterations, uint64_t version_number,
|
||||
bool allow_blob);
|
||||
|
||||
void StoreRefreshInfo(const ReadOptions& read_options, DBImpl* db_impl,
|
||||
ColumnFamilyData* cfd, bool allow_blob) {
|
||||
read_options_ = read_options;
|
||||
db_impl_ = db_impl;
|
||||
cfd_ = cfd;
|
||||
allow_blob_ = allow_blob;
|
||||
}
|
||||
|
||||
private:
|
||||
DBIter* db_iter_;
|
||||
Arena arena_;
|
||||
uint64_t sv_number_;
|
||||
ColumnFamilyData* cfd_ = nullptr;
|
||||
DBImpl* db_impl_ = nullptr;
|
||||
ReadOptions read_options_;
|
||||
bool allow_blob_ = false;
|
||||
};
|
||||
|
||||
// Generate the arena wrapped iterator class.
|
||||
// `db_impl` and `cfd` are used for reneweal. If left null, renewal will not
|
||||
// be supported.
|
||||
extern ArenaWrappedDBIter* NewArenaWrappedDbIterator(
|
||||
Env* env, const ReadOptions& read_options,
|
||||
const ImmutableCFOptions& cf_options, const SequenceNumber& sequence,
|
||||
uint64_t max_sequential_skip_in_iterations, uint64_t version_number,
|
||||
DBImpl* db_impl = nullptr, ColumnFamilyData* cfd = nullptr,
|
||||
bool allow_blob = false);
|
||||
const ImmutableCFOptions& cf_options, const Comparator* user_key_comparator,
|
||||
const SequenceNumber& sequence, uint64_t max_sequential_skip_in_iterations,
|
||||
uint64_t version_number);
|
||||
|
||||
} // namespace rocksdb
|
||||
+73
-73
@@ -193,7 +193,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
ReadOptions ro;
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -225,7 +225,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
ReadOptions ro;
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -251,7 +251,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -283,7 +283,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -318,7 +318,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(!db_iter->Valid());
|
||||
@@ -347,16 +347,16 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
7, options.max_sequential_skip_in_iterations));
|
||||
7, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
SetPerfLevel(kEnableCount);
|
||||
ASSERT_TRUE(GetPerfLevel() == kEnableCount);
|
||||
|
||||
get_perf_context()->Reset();
|
||||
perf_context.Reset();
|
||||
db_iter->SeekToLast();
|
||||
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(static_cast<int>(get_perf_context()->internal_key_skipped_count), 7);
|
||||
ASSERT_EQ(static_cast<int>(perf_context.internal_key_skipped_count), 7);
|
||||
ASSERT_EQ(db_iter->key().ToString(), "b");
|
||||
|
||||
SetPerfLevel(kDisable);
|
||||
@@ -384,7 +384,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
4, options.max_sequential_skip_in_iterations));
|
||||
4, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -409,7 +409,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(!db_iter->Valid());
|
||||
@@ -431,7 +431,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -466,16 +466,16 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
7, options.max_sequential_skip_in_iterations));
|
||||
7, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
SetPerfLevel(kEnableCount);
|
||||
ASSERT_TRUE(GetPerfLevel() == kEnableCount);
|
||||
|
||||
get_perf_context()->Reset();
|
||||
perf_context.Reset();
|
||||
db_iter->SeekToLast();
|
||||
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(static_cast<int>(get_perf_context()->internal_delete_skipped_count), 1);
|
||||
ASSERT_EQ(static_cast<int>(perf_context.internal_delete_skipped_count), 1);
|
||||
ASSERT_EQ(db_iter->key().ToString(), "b");
|
||||
|
||||
SetPerfLevel(kDisable);
|
||||
@@ -495,7 +495,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
ReadOptions ro;
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -537,7 +537,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
ReadOptions ro;
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
2, options.max_sequential_skip_in_iterations));
|
||||
2, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "b");
|
||||
@@ -568,7 +568,7 @@ TEST_F(DBIteratorTest, DBIteratorPrevNext) {
|
||||
ReadOptions ro;
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "c");
|
||||
@@ -597,7 +597,7 @@ TEST_F(DBIteratorTest, DBIteratorEmpty) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
0, options.max_sequential_skip_in_iterations));
|
||||
0, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(!db_iter->Valid());
|
||||
}
|
||||
@@ -608,7 +608,7 @@ TEST_F(DBIteratorTest, DBIteratorEmpty) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
0, options.max_sequential_skip_in_iterations));
|
||||
0, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(!db_iter->Valid());
|
||||
}
|
||||
@@ -630,7 +630,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkipCountSkips) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, ImmutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, 2, options.max_sequential_skip_in_iterations));
|
||||
internal_iter, 2, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "c");
|
||||
@@ -673,7 +673,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkip) {
|
||||
options.statistics = rocksdb::CreateDBStatistics();
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, cf_options, BytewiseComparator(), internal_iter, i + 2,
|
||||
options.max_sequential_skip_in_iterations));
|
||||
options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -708,7 +708,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkip) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, cf_options, BytewiseComparator(), internal_iter, i + 2,
|
||||
options.max_sequential_skip_in_iterations));
|
||||
options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -736,7 +736,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkip) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, cf_options, BytewiseComparator(), internal_iter, 202,
|
||||
options.max_sequential_skip_in_iterations));
|
||||
options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -768,7 +768,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkip) {
|
||||
internal_iter->Finish();
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, cf_options, BytewiseComparator(), internal_iter, i,
|
||||
options.max_sequential_skip_in_iterations));
|
||||
options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(!db_iter->Valid());
|
||||
|
||||
@@ -784,7 +784,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkip) {
|
||||
internal_iter->Finish();
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
200, options.max_sequential_skip_in_iterations));
|
||||
200, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "c");
|
||||
@@ -818,7 +818,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkip) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, cf_options, BytewiseComparator(), internal_iter, i + 2,
|
||||
options.max_sequential_skip_in_iterations));
|
||||
options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -852,7 +852,7 @@ TEST_F(DBIteratorTest, DBIteratorUseSkip) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, cf_options, BytewiseComparator(), internal_iter, i + 2,
|
||||
options.max_sequential_skip_in_iterations));
|
||||
options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -900,7 +900,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
ro.max_skippable_internal_keys = 0;
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -946,7 +946,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
ro.max_skippable_internal_keys = 2;
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -990,7 +990,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
ro.max_skippable_internal_keys = 2;
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1028,7 +1028,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
ro.max_skippable_internal_keys = 2;
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1063,7 +1063,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
ro.max_skippable_internal_keys = 2;
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1093,7 +1093,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
ro.max_skippable_internal_keys = 2;
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1130,7 +1130,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
ro.max_skippable_internal_keys = 2;
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1167,7 +1167,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
ro.max_skippable_internal_keys = i;
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, cf_options, BytewiseComparator(), internal_iter, 2 * i + 1,
|
||||
options.max_sequential_skip_in_iterations));
|
||||
options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1220,7 +1220,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipInternalKeys) {
|
||||
ro.max_skippable_internal_keys = i;
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, cf_options, BytewiseComparator(), internal_iter, 2 * i + 1,
|
||||
options.max_sequential_skip_in_iterations));
|
||||
options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -1258,7 +1258,7 @@ TEST_F(DBIteratorTest, DBIterator1) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, ImmutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, 1, options.max_sequential_skip_in_iterations));
|
||||
internal_iter, 1, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1285,7 +1285,7 @@ TEST_F(DBIteratorTest, DBIterator2) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, ImmutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, 0, options.max_sequential_skip_in_iterations));
|
||||
internal_iter, 0, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1309,7 +1309,7 @@ TEST_F(DBIteratorTest, DBIterator3) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, ImmutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, 2, options.max_sequential_skip_in_iterations));
|
||||
internal_iter, 2, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1333,7 +1333,7 @@ TEST_F(DBIteratorTest, DBIterator4) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, ImmutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, 4, options.max_sequential_skip_in_iterations));
|
||||
internal_iter, 4, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1365,7 +1365,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
0, options.max_sequential_skip_in_iterations));
|
||||
0, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1387,7 +1387,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
1, options.max_sequential_skip_in_iterations));
|
||||
1, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1409,7 +1409,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
2, options.max_sequential_skip_in_iterations));
|
||||
2, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1431,7 +1431,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
3, options.max_sequential_skip_in_iterations));
|
||||
3, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1453,7 +1453,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
4, options.max_sequential_skip_in_iterations));
|
||||
4, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1475,7 +1475,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
5, options.max_sequential_skip_in_iterations));
|
||||
5, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1497,7 +1497,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
6, options.max_sequential_skip_in_iterations));
|
||||
6, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1517,7 +1517,7 @@ TEST_F(DBIteratorTest, DBIterator5) {
|
||||
internal_iter->Finish();
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
10, options.max_sequential_skip_in_iterations));
|
||||
10, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->Seek("b");
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "b");
|
||||
@@ -1546,7 +1546,7 @@ TEST_F(DBIteratorTest, DBIterator6) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
0, options.max_sequential_skip_in_iterations));
|
||||
0, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1568,7 +1568,7 @@ TEST_F(DBIteratorTest, DBIterator6) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
1, options.max_sequential_skip_in_iterations));
|
||||
1, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1590,7 +1590,7 @@ TEST_F(DBIteratorTest, DBIterator6) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
2, options.max_sequential_skip_in_iterations));
|
||||
2, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1612,7 +1612,7 @@ TEST_F(DBIteratorTest, DBIterator6) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
3, options.max_sequential_skip_in_iterations));
|
||||
3, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(!db_iter->Valid());
|
||||
}
|
||||
@@ -1630,7 +1630,7 @@ TEST_F(DBIteratorTest, DBIterator6) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
4, options.max_sequential_skip_in_iterations));
|
||||
4, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1652,7 +1652,7 @@ TEST_F(DBIteratorTest, DBIterator6) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
5, options.max_sequential_skip_in_iterations));
|
||||
5, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1674,7 +1674,7 @@ TEST_F(DBIteratorTest, DBIterator6) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
6, options.max_sequential_skip_in_iterations));
|
||||
6, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1715,7 +1715,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
0, options.max_sequential_skip_in_iterations));
|
||||
0, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -1749,7 +1749,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
2, options.max_sequential_skip_in_iterations));
|
||||
2, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -1789,7 +1789,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
4, options.max_sequential_skip_in_iterations));
|
||||
4, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -1829,7 +1829,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
5, options.max_sequential_skip_in_iterations));
|
||||
5, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -1874,7 +1874,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
6, options.max_sequential_skip_in_iterations));
|
||||
6, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -1920,7 +1920,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
7, options.max_sequential_skip_in_iterations));
|
||||
7, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -1960,7 +1960,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
9, options.max_sequential_skip_in_iterations));
|
||||
9, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -2006,7 +2006,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
13, options.max_sequential_skip_in_iterations));
|
||||
13, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -2053,7 +2053,7 @@ TEST_F(DBIteratorTest, DBIterator7) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, cf_options, BytewiseComparator(), internal_iter,
|
||||
14, options.max_sequential_skip_in_iterations));
|
||||
14, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
|
||||
@@ -2083,7 +2083,7 @@ TEST_F(DBIteratorTest, DBIterator8) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, ImmutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, 10, options.max_sequential_skip_in_iterations));
|
||||
internal_iter, 10, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "b");
|
||||
@@ -2113,7 +2113,7 @@ TEST_F(DBIteratorTest, DBIterator9) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, ImmutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, 10, options.max_sequential_skip_in_iterations));
|
||||
internal_iter, 10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -2179,7 +2179,7 @@ TEST_F(DBIteratorTest, DBIterator10) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, ImmutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, 10, options.max_sequential_skip_in_iterations));
|
||||
internal_iter, 10, options.max_sequential_skip_in_iterations, 0));
|
||||
|
||||
db_iter->Seek("c");
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
@@ -2218,7 +2218,7 @@ TEST_F(DBIteratorTest, SeekToLastOccurrenceSeq0) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, ImmutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, 10, 0 /* force seek */));
|
||||
internal_iter, 10, 0 /* force seek */, 0));
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -2246,7 +2246,7 @@ TEST_F(DBIteratorTest, DBIterator11) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(NewDBIterator(
|
||||
env_, ro, ImmutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, 1, options.max_sequential_skip_in_iterations));
|
||||
internal_iter, 1, options.max_sequential_skip_in_iterations, 0));
|
||||
db_iter->SeekToFirst();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "a");
|
||||
@@ -2272,7 +2272,7 @@ TEST_F(DBIteratorTest, DBIterator12) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, ImmutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, 10, 0));
|
||||
internal_iter, 10, 0, 0));
|
||||
db_iter->SeekToLast();
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "c");
|
||||
@@ -2309,7 +2309,7 @@ TEST_F(DBIteratorTest, DBIterator13) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, ImmutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, 2, 3));
|
||||
internal_iter, 2, 3, 0));
|
||||
db_iter->Seek("b");
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), key);
|
||||
@@ -2337,7 +2337,7 @@ TEST_F(DBIteratorTest, DBIterator14) {
|
||||
|
||||
std::unique_ptr<Iterator> db_iter(
|
||||
NewDBIterator(env_, ro, ImmutableCFOptions(options), BytewiseComparator(),
|
||||
internal_iter, 4, 1));
|
||||
internal_iter, 4, 1, 0));
|
||||
db_iter->Seek("b");
|
||||
ASSERT_TRUE(db_iter->Valid());
|
||||
ASSERT_EQ(db_iter->key().ToString(), "b");
|
||||
@@ -2376,7 +2376,7 @@ class DBIterWithMergeIterTest : public testing::Test {
|
||||
db_iter_.reset(NewDBIterator(env_, ro_, ImmutableCFOptions(options_),
|
||||
BytewiseComparator(), merge_iter,
|
||||
8 /* read data earlier than seqId 8 */,
|
||||
3 /* max iterators before reseek */));
|
||||
3 /* max iterators before reseek */, 0));
|
||||
}
|
||||
|
||||
Env* env_;
|
||||
|
||||
+23
-93
@@ -972,11 +972,11 @@ TEST_F(DBIteratorTest, DBIteratorBoundTest) {
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(iter->key().compare(("b1")), 0);
|
||||
|
||||
get_perf_context()->Reset();
|
||||
perf_context.Reset();
|
||||
iter->Next();
|
||||
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(static_cast<int>(get_perf_context()->internal_delete_skipped_count), 2);
|
||||
ASSERT_EQ(static_cast<int>(perf_context.internal_delete_skipped_count), 2);
|
||||
|
||||
// now testing with iterate_bound
|
||||
Slice prefix("c");
|
||||
@@ -984,7 +984,7 @@ TEST_F(DBIteratorTest, DBIteratorBoundTest) {
|
||||
|
||||
iter.reset(db_->NewIterator(ro));
|
||||
|
||||
get_perf_context()->Reset();
|
||||
perf_context.Reset();
|
||||
|
||||
iter->Seek("b");
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
@@ -999,13 +999,12 @@ TEST_F(DBIteratorTest, DBIteratorBoundTest) {
|
||||
// even though the key is deleted
|
||||
// hence internal_delete_skipped_count should be 0
|
||||
ASSERT_TRUE(!iter->Valid());
|
||||
ASSERT_EQ(static_cast<int>(get_perf_context()->internal_delete_skipped_count), 0);
|
||||
ASSERT_EQ(static_cast<int>(perf_context.internal_delete_skipped_count), 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DBIteratorTest, DBIteratorBoundOptimizationTest) {
|
||||
int upper_bound_hits = 0;
|
||||
Options options = CurrentOptions();
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"BlockBasedTable::BlockEntryIteratorState::KeyReachedUpperBound",
|
||||
[&upper_bound_hits](void* arg) {
|
||||
@@ -1013,6 +1012,7 @@ TEST_F(DBIteratorTest, DBIteratorBoundOptimizationTest) {
|
||||
upper_bound_hits += (*static_cast<bool*>(arg) ? 1 : 0);
|
||||
});
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
Options options = CurrentOptions();
|
||||
options.env = env_;
|
||||
options.create_if_missing = true;
|
||||
options.prefix_extractor = nullptr;
|
||||
@@ -1719,15 +1719,12 @@ TEST_F(DBIteratorTest, IteratorWithLocalStatistics) {
|
||||
|
||||
std::vector<port::Thread> threads;
|
||||
std::function<void()> reader_func_next = [&]() {
|
||||
SetPerfLevel(kEnableCount);
|
||||
get_perf_context()->Reset();
|
||||
Iterator* iter = db_->NewIterator(ReadOptions());
|
||||
|
||||
iter->SeekToFirst();
|
||||
// Seek will bump ITER_BYTES_READ
|
||||
uint64_t bytes = 0;
|
||||
bytes += iter->key().size();
|
||||
bytes += iter->value().size();
|
||||
total_bytes += iter->key().size();
|
||||
total_bytes += iter->value().size();
|
||||
while (true) {
|
||||
iter->Next();
|
||||
total_next++;
|
||||
@@ -1736,25 +1733,20 @@ TEST_F(DBIteratorTest, IteratorWithLocalStatistics) {
|
||||
break;
|
||||
}
|
||||
total_next_found++;
|
||||
bytes += iter->key().size();
|
||||
bytes += iter->value().size();
|
||||
total_bytes += iter->key().size();
|
||||
total_bytes += iter->value().size();
|
||||
}
|
||||
|
||||
delete iter;
|
||||
ASSERT_EQ(bytes, get_perf_context()->iter_read_bytes);
|
||||
SetPerfLevel(kDisable);
|
||||
total_bytes += bytes;
|
||||
};
|
||||
|
||||
std::function<void()> reader_func_prev = [&]() {
|
||||
SetPerfLevel(kEnableCount);
|
||||
Iterator* iter = db_->NewIterator(ReadOptions());
|
||||
|
||||
iter->SeekToLast();
|
||||
// Seek will bump ITER_BYTES_READ
|
||||
uint64_t bytes = 0;
|
||||
bytes += iter->key().size();
|
||||
bytes += iter->value().size();
|
||||
total_bytes += iter->key().size();
|
||||
total_bytes += iter->value().size();
|
||||
while (true) {
|
||||
iter->Prev();
|
||||
total_prev++;
|
||||
@@ -1763,14 +1755,11 @@ TEST_F(DBIteratorTest, IteratorWithLocalStatistics) {
|
||||
break;
|
||||
}
|
||||
total_prev_found++;
|
||||
bytes += iter->key().size();
|
||||
bytes += iter->value().size();
|
||||
total_bytes += iter->key().size();
|
||||
total_bytes += iter->value().size();
|
||||
}
|
||||
|
||||
delete iter;
|
||||
ASSERT_EQ(bytes, get_perf_context()->iter_read_bytes);
|
||||
SetPerfLevel(kDisable);
|
||||
total_bytes += bytes;
|
||||
};
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
@@ -1897,7 +1886,7 @@ TEST_F(DBIteratorTest, DBIteratorSkipRecentDuplicatesTest) {
|
||||
#endif
|
||||
|
||||
// Seek iterator to a smaller key.
|
||||
get_perf_context()->Reset();
|
||||
perf_context.Reset();
|
||||
iter->Seek("a");
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
EXPECT_EQ("b", iter->key().ToString());
|
||||
@@ -1905,80 +1894,21 @@ TEST_F(DBIteratorTest, DBIteratorSkipRecentDuplicatesTest) {
|
||||
|
||||
// Check that the seek didn't do too much work.
|
||||
// Checks are not tight, just make sure that everything is well below 100.
|
||||
EXPECT_LT(get_perf_context()->internal_key_skipped_count, 4);
|
||||
EXPECT_LT(get_perf_context()->internal_recent_skipped_count, 8);
|
||||
EXPECT_LT(get_perf_context()->seek_on_memtable_count, 10);
|
||||
EXPECT_LT(get_perf_context()->next_on_memtable_count, 10);
|
||||
EXPECT_LT(get_perf_context()->prev_on_memtable_count, 10);
|
||||
EXPECT_LT(perf_context.internal_key_skipped_count, 4);
|
||||
EXPECT_LT(perf_context.internal_recent_skipped_count, 8);
|
||||
EXPECT_LT(perf_context.seek_on_memtable_count, 10);
|
||||
EXPECT_LT(perf_context.next_on_memtable_count, 10);
|
||||
EXPECT_LT(perf_context.prev_on_memtable_count, 10);
|
||||
|
||||
// Check that iterator did something like what we expect.
|
||||
EXPECT_EQ(get_perf_context()->internal_delete_skipped_count, 0);
|
||||
EXPECT_EQ(get_perf_context()->internal_merge_count, 0);
|
||||
EXPECT_GE(get_perf_context()->internal_recent_skipped_count, 2);
|
||||
EXPECT_GE(get_perf_context()->seek_on_memtable_count, 2);
|
||||
EXPECT_EQ(perf_context.internal_delete_skipped_count, 0);
|
||||
EXPECT_EQ(perf_context.internal_merge_count, 0);
|
||||
EXPECT_GE(perf_context.internal_recent_skipped_count, 2);
|
||||
EXPECT_GE(perf_context.seek_on_memtable_count, 2);
|
||||
EXPECT_EQ(1, options.statistics->getTickerCount(
|
||||
NUMBER_OF_RESEEKS_IN_ITERATION));
|
||||
}
|
||||
|
||||
TEST_F(DBIteratorTest, Refresh) {
|
||||
ASSERT_OK(Put("x", "y"));
|
||||
|
||||
std::unique_ptr<Iterator> iter(db_->NewIterator(ReadOptions()));
|
||||
iter->Seek(Slice("a"));
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(iter->key().compare(Slice("x")), 0);
|
||||
iter->Next();
|
||||
ASSERT_FALSE(iter->Valid());
|
||||
|
||||
ASSERT_OK(Put("c", "d"));
|
||||
|
||||
iter->Seek(Slice("a"));
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(iter->key().compare(Slice("x")), 0);
|
||||
iter->Next();
|
||||
ASSERT_FALSE(iter->Valid());
|
||||
|
||||
iter->Refresh();
|
||||
|
||||
iter->Seek(Slice("a"));
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(iter->key().compare(Slice("c")), 0);
|
||||
iter->Next();
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(iter->key().compare(Slice("x")), 0);
|
||||
iter->Next();
|
||||
ASSERT_FALSE(iter->Valid());
|
||||
|
||||
dbfull()->Flush(FlushOptions());
|
||||
|
||||
ASSERT_OK(Put("m", "n"));
|
||||
|
||||
iter->Seek(Slice("a"));
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(iter->key().compare(Slice("c")), 0);
|
||||
iter->Next();
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(iter->key().compare(Slice("x")), 0);
|
||||
iter->Next();
|
||||
ASSERT_FALSE(iter->Valid());
|
||||
|
||||
iter->Refresh();
|
||||
|
||||
iter->Seek(Slice("a"));
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(iter->key().compare(Slice("c")), 0);
|
||||
iter->Next();
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(iter->key().compare(Slice("m")), 0);
|
||||
iter->Next();
|
||||
ASSERT_TRUE(iter->Valid());
|
||||
ASSERT_EQ(iter->key().compare(Slice("x")), 0);
|
||||
iter->Next();
|
||||
ASSERT_FALSE(iter->Valid());
|
||||
|
||||
iter.reset();
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
@@ -116,7 +116,6 @@ TEST_F(DBTestXactLogIterator, TransactionLogIteratorRace) {
|
||||
dbfull()->Flush(FlushOptions());
|
||||
Put("key4", DummyString(1024));
|
||||
ASSERT_EQ(dbfull()->GetLatestSequenceNumber(), 4U);
|
||||
dbfull()->FlushWAL(false);
|
||||
|
||||
{
|
||||
auto iter = OpenTransactionLogIter(0);
|
||||
@@ -133,7 +132,6 @@ TEST_F(DBTestXactLogIterator, TransactionLogIteratorRace) {
|
||||
|
||||
// "key5" would be written in a new memtable and log
|
||||
Put("key5", DummyString(1024));
|
||||
dbfull()->FlushWAL(false);
|
||||
{
|
||||
// this iter would miss "key4" if not fixed
|
||||
auto iter = OpenTransactionLogIter(0);
|
||||
@@ -183,7 +181,6 @@ TEST_F(DBTestXactLogIterator, TransactionLogIteratorCorruptedLog) {
|
||||
Put("key"+ToString(i), DummyString(10));
|
||||
}
|
||||
dbfull()->Flush(FlushOptions());
|
||||
dbfull()->FlushWAL(false);
|
||||
// Corrupt this log to create a gap
|
||||
rocksdb::VectorLogPtr wal_files;
|
||||
ASSERT_OK(dbfull()->GetSortedWalFiles(wal_files));
|
||||
@@ -197,7 +194,6 @@ TEST_F(DBTestXactLogIterator, TransactionLogIteratorCorruptedLog) {
|
||||
|
||||
// Insert a new entry to a new log file
|
||||
Put("key1025", DummyString(10));
|
||||
dbfull()->FlushWAL(false);
|
||||
// Try to read from the beginning. Should stop before the gap and read less
|
||||
// than 1025 entries
|
||||
auto iter = OpenTransactionLogIter(0);
|
||||
|
||||
+2
-33
@@ -21,7 +21,7 @@ class DBMemTableTest : public DBTestBase {
|
||||
|
||||
class MockMemTableRep : public MemTableRep {
|
||||
public:
|
||||
explicit MockMemTableRep(Allocator* allocator, MemTableRep* rep)
|
||||
explicit MockMemTableRep(MemTableAllocator* allocator, MemTableRep* rep)
|
||||
: MemTableRep(allocator), rep_(rep), num_insert_with_hint_(0) {}
|
||||
|
||||
virtual KeyHandle Allocate(const size_t len, char** buf) override {
|
||||
@@ -72,7 +72,7 @@ class MockMemTableRep : public MemTableRep {
|
||||
class MockMemTableRepFactory : public MemTableRepFactory {
|
||||
public:
|
||||
virtual MemTableRep* CreateMemTableRep(const MemTableRep::KeyComparator& cmp,
|
||||
Allocator* allocator,
|
||||
MemTableAllocator* allocator,
|
||||
const SliceTransform* transform,
|
||||
Logger* logger) override {
|
||||
SkipListFactory factory;
|
||||
@@ -82,27 +82,14 @@ class MockMemTableRepFactory : public MemTableRepFactory {
|
||||
return mock_rep_;
|
||||
}
|
||||
|
||||
virtual MemTableRep* CreateMemTableRep(const MemTableRep::KeyComparator& cmp,
|
||||
Allocator* allocator,
|
||||
const SliceTransform* transform,
|
||||
Logger* logger,
|
||||
uint32_t column_family_id) override {
|
||||
last_column_family_id_ = column_family_id;
|
||||
return CreateMemTableRep(cmp, allocator, transform, logger);
|
||||
}
|
||||
|
||||
virtual const char* Name() const override { return "MockMemTableRepFactory"; }
|
||||
|
||||
MockMemTableRep* rep() { return mock_rep_; }
|
||||
|
||||
bool IsInsertConcurrentlySupported() const override { return false; }
|
||||
|
||||
uint32_t GetLastColumnFamilyId() { return last_column_family_id_; }
|
||||
|
||||
private:
|
||||
MockMemTableRep* mock_rep_;
|
||||
// workaround since there's no port::kMaxUint32 yet.
|
||||
uint32_t last_column_family_id_ = static_cast<uint32_t>(-1);
|
||||
};
|
||||
|
||||
class TestPrefixExtractor : public SliceTransform {
|
||||
@@ -168,24 +155,6 @@ TEST_F(DBMemTableTest, InsertWithHint) {
|
||||
ASSERT_EQ("vvv", Get("whitelisted"));
|
||||
}
|
||||
|
||||
TEST_F(DBMemTableTest, ColumnFamilyId) {
|
||||
// Verifies MemTableRepFactory is told the right column family id.
|
||||
Options options;
|
||||
options.allow_concurrent_memtable_write = false;
|
||||
options.create_if_missing = true;
|
||||
options.memtable_factory.reset(new MockMemTableRepFactory());
|
||||
DestroyAndReopen(options);
|
||||
CreateAndReopenWithCF({"pikachu"}, options);
|
||||
|
||||
for (int cf = 0; cf < 2; ++cf) {
|
||||
ASSERT_OK(Put(cf, "key", "val"));
|
||||
ASSERT_OK(Flush(cf));
|
||||
ASSERT_EQ(
|
||||
cf, static_cast<MockMemTableRepFactory*>(options.memtable_factory.get())
|
||||
->GetLastColumnFamilyId());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
@@ -18,6 +18,28 @@ class DBMergeOperatorTest : public DBTestBase {
|
||||
DBMergeOperatorTest() : DBTestBase("/db_merge_operator_test") {}
|
||||
};
|
||||
|
||||
// A test merge operator mimics put but also fails if one of merge operands is
|
||||
// "corrupted".
|
||||
class TestPutOperator : public MergeOperator {
|
||||
public:
|
||||
virtual bool FullMergeV2(const MergeOperationInput& merge_in,
|
||||
MergeOperationOutput* merge_out) const override {
|
||||
if (merge_in.existing_value != nullptr &&
|
||||
*(merge_in.existing_value) == "corrupted") {
|
||||
return false;
|
||||
}
|
||||
for (auto value : merge_in.operand_list) {
|
||||
if (value == "corrupted") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
merge_out->existing_operand = merge_in.operand_list.back();
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual const char* Name() const override { return "TestPutOperator"; }
|
||||
};
|
||||
|
||||
TEST_F(DBMergeOperatorTest, MergeErrorOnRead) {
|
||||
Options options;
|
||||
options.create_if_missing = true;
|
||||
|
||||
+4
-62
@@ -15,9 +15,7 @@
|
||||
#include "db/db_test_util.h"
|
||||
#include "options/options_helper.h"
|
||||
#include "port/stack_trace.h"
|
||||
#include "rocksdb/cache.h"
|
||||
#include "rocksdb/convenience.h"
|
||||
#include "rocksdb/rate_limiter.h"
|
||||
#include "util/random.h"
|
||||
#include "util/sync_point.h"
|
||||
#include "util/testutil.h"
|
||||
@@ -253,44 +251,18 @@ TEST_F(DBOptionsTest, SetOptionsMayTriggerCompaction) {
|
||||
TEST_F(DBOptionsTest, SetBackgroundCompactionThreads) {
|
||||
Options options;
|
||||
options.create_if_missing = true;
|
||||
options.base_background_compactions = 1; // default value
|
||||
options.max_background_compactions = 1; // default value
|
||||
options.env = env_;
|
||||
Reopen(options);
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
ASSERT_OK(dbfull()->SetDBOptions({{"max_background_compactions", "3"}}));
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
ASSERT_OK(dbfull()->SetDBOptions({{"base_background_compactions", "2"},
|
||||
{"max_background_compactions", "3"}}));
|
||||
ASSERT_EQ(2, dbfull()->TEST_BGCompactionsAllowed());
|
||||
auto stop_token = dbfull()->TEST_write_controler().GetStopToken();
|
||||
ASSERT_EQ(3, dbfull()->TEST_BGCompactionsAllowed());
|
||||
}
|
||||
|
||||
TEST_F(DBOptionsTest, SetBackgroundJobs) {
|
||||
Options options;
|
||||
options.create_if_missing = true;
|
||||
options.max_background_jobs = 8;
|
||||
options.env = env_;
|
||||
Reopen(options);
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (i > 0) {
|
||||
options.max_background_jobs = 12;
|
||||
ASSERT_OK(dbfull()->SetDBOptions(
|
||||
{{"max_background_jobs",
|
||||
std::to_string(options.max_background_jobs)}}));
|
||||
}
|
||||
|
||||
ASSERT_EQ(options.max_background_jobs / 4,
|
||||
dbfull()->TEST_BGFlushesAllowed());
|
||||
ASSERT_EQ(1, dbfull()->TEST_BGCompactionsAllowed());
|
||||
|
||||
auto stop_token = dbfull()->TEST_write_controler().GetStopToken();
|
||||
|
||||
ASSERT_EQ(options.max_background_jobs / 4,
|
||||
dbfull()->TEST_BGFlushesAllowed());
|
||||
ASSERT_EQ(3 * options.max_background_jobs / 4,
|
||||
dbfull()->TEST_BGCompactionsAllowed());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DBOptionsTest, AvoidFlushDuringShutdown) {
|
||||
Options options;
|
||||
options.create_if_missing = true;
|
||||
@@ -411,36 +383,6 @@ TEST_F(DBOptionsTest, DeleteObsoleteFilesPeriodChange) {
|
||||
Close();
|
||||
}
|
||||
|
||||
TEST_F(DBOptionsTest, MaxOpenFilesChange) {
|
||||
SpecialEnv env(env_);
|
||||
Options options;
|
||||
options.env = CurrentOptions().env;
|
||||
options.max_open_files = -1;
|
||||
|
||||
Reopen(options);
|
||||
|
||||
Cache* tc = dbfull()->TEST_table_cache();
|
||||
|
||||
ASSERT_EQ(-1, dbfull()->GetDBOptions().max_open_files);
|
||||
ASSERT_LT(2000, tc->GetCapacity());
|
||||
ASSERT_OK(dbfull()->SetDBOptions({{"max_open_files", "1024"}}));
|
||||
ASSERT_EQ(1024, dbfull()->GetDBOptions().max_open_files);
|
||||
// examine the table cache (actual size should be 1014)
|
||||
ASSERT_GT(1500, tc->GetCapacity());
|
||||
Close();
|
||||
}
|
||||
|
||||
TEST_F(DBOptionsTest, SanitizeDelayedWriteRate) {
|
||||
Options options;
|
||||
options.delayed_write_rate = 0;
|
||||
Reopen(options);
|
||||
ASSERT_EQ(16 * 1024 * 1024, dbfull()->GetDBOptions().delayed_write_rate);
|
||||
|
||||
options.rate_limiter.reset(NewGenericRateLimiter(31 * 1024 * 1024));
|
||||
Reopen(options);
|
||||
ASSERT_EQ(31 * 1024 * 1024, dbfull()->GetDBOptions().delayed_write_rate);
|
||||
}
|
||||
|
||||
#endif // ROCKSDB_LITE
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
+23
-94
@@ -533,9 +533,9 @@ TEST_F(DBPropertiesTest, NumImmutableMemTable) {
|
||||
ASSERT_TRUE(dbfull()->GetProperty(
|
||||
handles_[1], "rocksdb.num-entries-active-mem-table", &num));
|
||||
ASSERT_EQ(num, "1");
|
||||
get_perf_context()->Reset();
|
||||
perf_context.Reset();
|
||||
Get(1, "k1");
|
||||
ASSERT_EQ(1, static_cast<int>(get_perf_context()->get_from_memtable_count));
|
||||
ASSERT_EQ(1, static_cast<int>(perf_context.get_from_memtable_count));
|
||||
|
||||
ASSERT_OK(dbfull()->Put(writeOpt, handles_[1], "k2", big_value));
|
||||
ASSERT_TRUE(dbfull()->GetProperty(handles_[1],
|
||||
@@ -548,12 +548,12 @@ TEST_F(DBPropertiesTest, NumImmutableMemTable) {
|
||||
handles_[1], "rocksdb.num-entries-imm-mem-tables", &num));
|
||||
ASSERT_EQ(num, "1");
|
||||
|
||||
get_perf_context()->Reset();
|
||||
perf_context.Reset();
|
||||
Get(1, "k1");
|
||||
ASSERT_EQ(2, static_cast<int>(get_perf_context()->get_from_memtable_count));
|
||||
get_perf_context()->Reset();
|
||||
ASSERT_EQ(2, static_cast<int>(perf_context.get_from_memtable_count));
|
||||
perf_context.Reset();
|
||||
Get(1, "k2");
|
||||
ASSERT_EQ(1, static_cast<int>(get_perf_context()->get_from_memtable_count));
|
||||
ASSERT_EQ(1, static_cast<int>(perf_context.get_from_memtable_count));
|
||||
|
||||
ASSERT_OK(dbfull()->Put(writeOpt, handles_[1], "k3", big_value));
|
||||
ASSERT_TRUE(dbfull()->GetProperty(
|
||||
@@ -567,15 +567,15 @@ TEST_F(DBPropertiesTest, NumImmutableMemTable) {
|
||||
ASSERT_TRUE(dbfull()->GetProperty(
|
||||
handles_[1], "rocksdb.num-entries-imm-mem-tables", &num));
|
||||
ASSERT_EQ(num, "2");
|
||||
get_perf_context()->Reset();
|
||||
perf_context.Reset();
|
||||
Get(1, "k2");
|
||||
ASSERT_EQ(2, static_cast<int>(get_perf_context()->get_from_memtable_count));
|
||||
get_perf_context()->Reset();
|
||||
ASSERT_EQ(2, static_cast<int>(perf_context.get_from_memtable_count));
|
||||
perf_context.Reset();
|
||||
Get(1, "k3");
|
||||
ASSERT_EQ(1, static_cast<int>(get_perf_context()->get_from_memtable_count));
|
||||
get_perf_context()->Reset();
|
||||
ASSERT_EQ(1, static_cast<int>(perf_context.get_from_memtable_count));
|
||||
perf_context.Reset();
|
||||
Get(1, "k1");
|
||||
ASSERT_EQ(3, static_cast<int>(get_perf_context()->get_from_memtable_count));
|
||||
ASSERT_EQ(3, static_cast<int>(perf_context.get_from_memtable_count));
|
||||
|
||||
ASSERT_OK(Flush(1));
|
||||
ASSERT_TRUE(dbfull()->GetProperty(handles_[1],
|
||||
@@ -670,7 +670,7 @@ TEST_F(DBPropertiesTest, DISABLED_GetProperty) {
|
||||
ASSERT_EQ(num, "0");
|
||||
ASSERT_TRUE(dbfull()->GetProperty("rocksdb.estimate-num-keys", &num));
|
||||
ASSERT_EQ(num, "1");
|
||||
get_perf_context()->Reset();
|
||||
perf_context.Reset();
|
||||
|
||||
ASSERT_OK(dbfull()->Put(writeOpt, "k2", big_value));
|
||||
ASSERT_TRUE(dbfull()->GetProperty("rocksdb.num-immutable-mem-table", &num));
|
||||
@@ -913,7 +913,7 @@ TEST_F(DBPropertiesTest, EstimatePendingCompBytes) {
|
||||
Flush();
|
||||
ASSERT_TRUE(dbfull()->GetIntProperty(
|
||||
"rocksdb.estimate-pending-compaction-bytes", &int_num));
|
||||
ASSERT_GT(int_num, 0U);
|
||||
ASSERT_EQ(int_num, 0U);
|
||||
|
||||
ASSERT_OK(dbfull()->Put(writeOpt, "k3", big_value));
|
||||
Flush();
|
||||
@@ -940,6 +940,7 @@ TEST_F(DBPropertiesTest, EstimateCompressionRatio) {
|
||||
Options options = CurrentOptions();
|
||||
options.compression_per_level = {kNoCompression, kSnappyCompression};
|
||||
options.disable_auto_compactions = true;
|
||||
options.max_background_flushes = 0;
|
||||
options.num_levels = 2;
|
||||
Reopen(options);
|
||||
|
||||
@@ -1067,6 +1068,7 @@ class CountingDeleteTabPropCollectorFactory
|
||||
TEST_F(DBPropertiesTest, GetUserDefinedTableProperties) {
|
||||
Options options = CurrentOptions();
|
||||
options.level0_file_num_compaction_trigger = (1 << 30);
|
||||
options.max_background_flushes = 0;
|
||||
options.table_properties_collector_factories.resize(1);
|
||||
std::shared_ptr<CountingUserTblPropCollectorFactory> collector_factory =
|
||||
std::make_shared<CountingUserTblPropCollectorFactory>(0);
|
||||
@@ -1107,6 +1109,7 @@ TEST_F(DBPropertiesTest, GetUserDefinedTableProperties) {
|
||||
TEST_F(DBPropertiesTest, UserDefinedTablePropertiesContext) {
|
||||
Options options = CurrentOptions();
|
||||
options.level0_file_num_compaction_trigger = 3;
|
||||
options.max_background_flushes = 0;
|
||||
options.table_properties_collector_factories.resize(1);
|
||||
std::shared_ptr<CountingUserTblPropCollectorFactory> collector_factory =
|
||||
std::make_shared<CountingUserTblPropCollectorFactory>(1);
|
||||
@@ -1228,7 +1231,7 @@ TEST_F(DBPropertiesTest, TablePropertiesNeedCompactTest) {
|
||||
|
||||
{
|
||||
SetPerfLevel(kEnableCount);
|
||||
get_perf_context()->Reset();
|
||||
perf_context.Reset();
|
||||
int c = 0;
|
||||
std::unique_ptr<Iterator> iter(db_->NewIterator(ReadOptions()));
|
||||
iter->Seek(Key(kMaxKey - 100));
|
||||
@@ -1236,8 +1239,8 @@ TEST_F(DBPropertiesTest, TablePropertiesNeedCompactTest) {
|
||||
iter->Next();
|
||||
}
|
||||
ASSERT_EQ(c, 0);
|
||||
ASSERT_LT(get_perf_context()->internal_delete_skipped_count, 30u);
|
||||
ASSERT_LT(get_perf_context()->internal_key_skipped_count, 30u);
|
||||
ASSERT_LT(perf_context.internal_delete_skipped_count, 30u);
|
||||
ASSERT_LT(perf_context.internal_key_skipped_count, 30u);
|
||||
SetPerfLevel(kDisable);
|
||||
}
|
||||
}
|
||||
@@ -1284,16 +1287,16 @@ TEST_F(DBPropertiesTest, NeedCompactHintPersistentTest) {
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 0);
|
||||
{
|
||||
SetPerfLevel(kEnableCount);
|
||||
get_perf_context()->Reset();
|
||||
perf_context.Reset();
|
||||
int c = 0;
|
||||
std::unique_ptr<Iterator> iter(db_->NewIterator(ReadOptions()));
|
||||
for (iter->Seek(Key(0)); iter->Valid(); iter->Next()) {
|
||||
c++;
|
||||
}
|
||||
ASSERT_EQ(c, 2);
|
||||
ASSERT_EQ(get_perf_context()->internal_delete_skipped_count, 0);
|
||||
ASSERT_EQ(perf_context.internal_delete_skipped_count, 0);
|
||||
// We iterate every key twice. Is it a bug?
|
||||
ASSERT_LE(get_perf_context()->internal_key_skipped_count, 2);
|
||||
ASSERT_LE(perf_context.internal_key_skipped_count, 2);
|
||||
SetPerfLevel(kDisable);
|
||||
}
|
||||
}
|
||||
@@ -1309,80 +1312,6 @@ TEST_F(DBPropertiesTest, EstimateNumKeysUnderflow) {
|
||||
ASSERT_EQ(0, num_keys);
|
||||
}
|
||||
|
||||
TEST_F(DBPropertiesTest, EstimateOldestKeyTime) {
|
||||
std::unique_ptr<MockTimeEnv> mock_env(new MockTimeEnv(Env::Default()));
|
||||
uint64_t oldest_key_time = 0;
|
||||
Options options;
|
||||
options.env = mock_env.get();
|
||||
|
||||
// "rocksdb.estimate-oldest-key-time" only available to fifo compaction.
|
||||
mock_env->set_current_time(100);
|
||||
for (auto compaction : {kCompactionStyleLevel, kCompactionStyleUniversal,
|
||||
kCompactionStyleNone}) {
|
||||
options.compaction_style = compaction;
|
||||
options.create_if_missing = true;
|
||||
DestroyAndReopen(options);
|
||||
ASSERT_OK(Put("foo", "bar"));
|
||||
ASSERT_FALSE(dbfull()->GetIntProperty(
|
||||
DB::Properties::kEstimateOldestKeyTime, &oldest_key_time));
|
||||
}
|
||||
|
||||
options.compaction_style = kCompactionStyleFIFO;
|
||||
options.compaction_options_fifo.ttl = 300;
|
||||
options.compaction_options_fifo.allow_compaction = false;
|
||||
DestroyAndReopen(options);
|
||||
|
||||
mock_env->set_current_time(100);
|
||||
ASSERT_OK(Put("k1", "v1"));
|
||||
ASSERT_TRUE(dbfull()->GetIntProperty(DB::Properties::kEstimateOldestKeyTime,
|
||||
&oldest_key_time));
|
||||
ASSERT_EQ(100, oldest_key_time);
|
||||
ASSERT_OK(Flush());
|
||||
ASSERT_EQ("1", FilesPerLevel());
|
||||
ASSERT_TRUE(dbfull()->GetIntProperty(DB::Properties::kEstimateOldestKeyTime,
|
||||
&oldest_key_time));
|
||||
ASSERT_EQ(100, oldest_key_time);
|
||||
|
||||
mock_env->set_current_time(200);
|
||||
ASSERT_OK(Put("k2", "v2"));
|
||||
ASSERT_OK(Flush());
|
||||
ASSERT_EQ("2", FilesPerLevel());
|
||||
ASSERT_TRUE(dbfull()->GetIntProperty(DB::Properties::kEstimateOldestKeyTime,
|
||||
&oldest_key_time));
|
||||
ASSERT_EQ(100, oldest_key_time);
|
||||
|
||||
mock_env->set_current_time(300);
|
||||
ASSERT_OK(Put("k3", "v3"));
|
||||
ASSERT_OK(Flush());
|
||||
ASSERT_EQ("3", FilesPerLevel());
|
||||
ASSERT_TRUE(dbfull()->GetIntProperty(DB::Properties::kEstimateOldestKeyTime,
|
||||
&oldest_key_time));
|
||||
ASSERT_EQ(100, oldest_key_time);
|
||||
|
||||
mock_env->set_current_time(450);
|
||||
ASSERT_OK(dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||
ASSERT_EQ("2", FilesPerLevel());
|
||||
ASSERT_TRUE(dbfull()->GetIntProperty(DB::Properties::kEstimateOldestKeyTime,
|
||||
&oldest_key_time));
|
||||
ASSERT_EQ(200, oldest_key_time);
|
||||
|
||||
mock_env->set_current_time(550);
|
||||
ASSERT_OK(dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||
ASSERT_EQ("1", FilesPerLevel());
|
||||
ASSERT_TRUE(dbfull()->GetIntProperty(DB::Properties::kEstimateOldestKeyTime,
|
||||
&oldest_key_time));
|
||||
ASSERT_EQ(300, oldest_key_time);
|
||||
|
||||
mock_env->set_current_time(650);
|
||||
ASSERT_OK(dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr));
|
||||
ASSERT_EQ("", FilesPerLevel());
|
||||
ASSERT_FALSE(dbfull()->GetIntProperty(DB::Properties::kEstimateOldestKeyTime,
|
||||
&oldest_key_time));
|
||||
|
||||
// Close before mock_env destructs.
|
||||
Close();
|
||||
}
|
||||
|
||||
#endif // ROCKSDB_LITE
|
||||
} // namespace rocksdb
|
||||
|
||||
|
||||
@@ -27,9 +27,6 @@ class DBRangeDelTest : public DBTestBase {
|
||||
// ROCKSDB_LITE
|
||||
#ifndef ROCKSDB_LITE
|
||||
TEST_F(DBRangeDelTest, NonBlockBasedTableNotSupported) {
|
||||
if (!IsMemoryMappedAccessSupported()) {
|
||||
return;
|
||||
}
|
||||
Options opts = CurrentOptions();
|
||||
opts.table_factory.reset(new PlainTableFactory());
|
||||
opts.prefix_extractor.reset(NewNoopTransform());
|
||||
@@ -792,7 +789,6 @@ TEST_F(DBRangeDelTest, IteratorIgnoresRangeDeletions) {
|
||||
db_->ReleaseSnapshot(snapshot);
|
||||
}
|
||||
|
||||
#ifndef ROCKSDB_UBSAN_RUN
|
||||
TEST_F(DBRangeDelTest, TailingIteratorRangeTombstoneUnsupported) {
|
||||
db_->Put(WriteOptions(), "key", "val");
|
||||
// snapshot prevents key from being deleted during flush
|
||||
@@ -819,183 +815,6 @@ TEST_F(DBRangeDelTest, TailingIteratorRangeTombstoneUnsupported) {
|
||||
}
|
||||
db_->ReleaseSnapshot(snapshot);
|
||||
}
|
||||
|
||||
#endif // !ROCKSDB_UBSAN_RUN
|
||||
|
||||
TEST_F(DBRangeDelTest, SubcompactionHasEmptyDedicatedRangeDelFile) {
|
||||
const int kNumFiles = 2, kNumKeysPerFile = 4;
|
||||
Options options = CurrentOptions();
|
||||
options.compression = kNoCompression;
|
||||
options.disable_auto_compactions = true;
|
||||
options.level0_file_num_compaction_trigger = kNumFiles;
|
||||
options.max_subcompactions = 2;
|
||||
options.num_levels = 2;
|
||||
options.target_file_size_base = 4096;
|
||||
Reopen(options);
|
||||
|
||||
// need a L1 file for subcompaction to be triggered
|
||||
ASSERT_OK(
|
||||
db_->Put(WriteOptions(), db_->DefaultColumnFamily(), Key(0), "val"));
|
||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||
MoveFilesToLevel(1);
|
||||
|
||||
// put enough keys to fill up the first subcompaction, and later range-delete
|
||||
// them so that the first subcompaction outputs no key-values. In that case
|
||||
// it'll consider making an SST file dedicated to range deletions.
|
||||
for (int i = 0; i < kNumKeysPerFile; ++i) {
|
||||
ASSERT_OK(db_->Put(WriteOptions(), db_->DefaultColumnFamily(), Key(i),
|
||||
std::string(1024, 'a')));
|
||||
}
|
||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), Key(0),
|
||||
Key(kNumKeysPerFile)));
|
||||
|
||||
// the above range tombstone can be dropped, so that one alone won't cause a
|
||||
// dedicated file to be opened. We can make one protected by snapshot that
|
||||
// must be considered. Make its range outside the first subcompaction's range
|
||||
// to exercise the tricky part of the code.
|
||||
const Snapshot* snapshot = db_->GetSnapshot();
|
||||
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
|
||||
Key(kNumKeysPerFile + 1),
|
||||
Key(kNumKeysPerFile + 2)));
|
||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||
|
||||
ASSERT_EQ(kNumFiles, NumTableFilesAtLevel(0));
|
||||
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
||||
|
||||
db_->EnableAutoCompaction({db_->DefaultColumnFamily()});
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
db_->ReleaseSnapshot(snapshot);
|
||||
}
|
||||
|
||||
TEST_F(DBRangeDelTest, MemtableBloomFilter) {
|
||||
// regression test for #2743. the range delete tombstones in memtable should
|
||||
// be added even when Get() skips searching due to its prefix bloom filter
|
||||
const int kMemtableSize = 1 << 20; // 1MB
|
||||
const int kMemtablePrefixFilterSize = 1 << 13; // 8KB
|
||||
const int kNumKeys = 1000;
|
||||
const int kPrefixLen = 8;
|
||||
Options options = CurrentOptions();
|
||||
options.memtable_prefix_bloom_size_ratio =
|
||||
static_cast<double>(kMemtablePrefixFilterSize) / kMemtableSize;
|
||||
options.prefix_extractor.reset(rocksdb::NewFixedPrefixTransform(kPrefixLen));
|
||||
options.write_buffer_size = kMemtableSize;
|
||||
Reopen(options);
|
||||
|
||||
for (int i = 0; i < kNumKeys; ++i) {
|
||||
ASSERT_OK(Put(Key(i), "val"));
|
||||
}
|
||||
Flush();
|
||||
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), Key(0),
|
||||
Key(kNumKeys)));
|
||||
for (int i = 0; i < kNumKeys; ++i) {
|
||||
std::string value;
|
||||
ASSERT_TRUE(db_->Get(ReadOptions(), Key(i), &value).IsNotFound());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DBRangeDelTest, CompactionTreatsSplitInputLevelDeletionAtomically) {
|
||||
// make sure compaction treats files containing a split range deletion in the
|
||||
// input level as an atomic unit. I.e., compacting any input-level file(s)
|
||||
// containing a portion of the range deletion causes all other input-level
|
||||
// files containing portions of that same range deletion to be included in the
|
||||
// compaction.
|
||||
const int kNumFilesPerLevel = 4, kValueBytes = 4 << 10;
|
||||
Options options = CurrentOptions();
|
||||
options.compression = kNoCompression;
|
||||
options.level0_file_num_compaction_trigger = kNumFilesPerLevel;
|
||||
options.memtable_factory.reset(
|
||||
new SpecialSkipListFactory(2 /* num_entries_flush */));
|
||||
options.target_file_size_base = kValueBytes;
|
||||
// i == 0: CompactFiles
|
||||
// i == 1: CompactRange
|
||||
// i == 2: automatic compaction
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
DestroyAndReopen(options);
|
||||
|
||||
ASSERT_OK(Put(Key(0), ""));
|
||||
ASSERT_OK(db_->Flush(FlushOptions()));
|
||||
MoveFilesToLevel(2);
|
||||
ASSERT_EQ(1, NumTableFilesAtLevel(2));
|
||||
|
||||
// snapshot protects range tombstone from dropping due to becoming obsolete.
|
||||
const Snapshot* snapshot = db_->GetSnapshot();
|
||||
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), Key(0),
|
||||
Key(2 * kNumFilesPerLevel));
|
||||
|
||||
Random rnd(301);
|
||||
std::string value = RandomString(&rnd, kValueBytes);
|
||||
for (int j = 0; j < kNumFilesPerLevel; ++j) {
|
||||
// give files overlapping key-ranges to prevent trivial move
|
||||
ASSERT_OK(Put(Key(j), value));
|
||||
ASSERT_OK(Put(Key(2 * kNumFilesPerLevel - 1 - j), value));
|
||||
if (j > 0) {
|
||||
dbfull()->TEST_WaitForFlushMemTable();
|
||||
ASSERT_EQ(j, NumTableFilesAtLevel(0));
|
||||
}
|
||||
}
|
||||
// put extra key to trigger final flush
|
||||
ASSERT_OK(Put("", ""));
|
||||
dbfull()->TEST_WaitForFlushMemTable();
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
||||
ASSERT_EQ(kNumFilesPerLevel, NumTableFilesAtLevel(1));
|
||||
|
||||
ColumnFamilyMetaData meta;
|
||||
db_->GetColumnFamilyMetaData(&meta);
|
||||
if (i == 0) {
|
||||
ASSERT_OK(db_->CompactFiles(
|
||||
CompactionOptions(), {meta.levels[1].files[0].name}, 2 /* level */));
|
||||
} else if (i == 1) {
|
||||
auto begin_str = Key(0), end_str = Key(1);
|
||||
Slice begin = begin_str, end = end_str;
|
||||
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), &begin, &end));
|
||||
} else if (i == 2) {
|
||||
ASSERT_OK(db_->SetOptions(db_->DefaultColumnFamily(),
|
||||
{{"max_bytes_for_level_base", "10000"}}));
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
}
|
||||
ASSERT_EQ(0, NumTableFilesAtLevel(1));
|
||||
ASSERT_GT(NumTableFilesAtLevel(2), 0);
|
||||
|
||||
db_->ReleaseSnapshot(snapshot);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DBRangeDelTest, UnorderedTombstones) {
|
||||
// Regression test for #2752. Range delete tombstones between
|
||||
// different snapshot stripes are not stored in order, so the first
|
||||
// tombstone of each snapshot stripe should be checked as a smallest
|
||||
// candidate.
|
||||
Options options = CurrentOptions();
|
||||
DestroyAndReopen(options);
|
||||
|
||||
auto cf = db_->DefaultColumnFamily();
|
||||
|
||||
ASSERT_OK(db_->Put(WriteOptions(), cf, "a", "a"));
|
||||
ASSERT_OK(db_->Flush(FlushOptions(), cf));
|
||||
ASSERT_EQ(1, NumTableFilesAtLevel(0));
|
||||
ASSERT_OK(dbfull()->TEST_CompactRange(0, nullptr, nullptr));
|
||||
ASSERT_EQ(1, NumTableFilesAtLevel(1));
|
||||
|
||||
ASSERT_OK(db_->DeleteRange(WriteOptions(), cf, "b", "c"));
|
||||
// Hold a snapshot to separate these two delete ranges.
|
||||
auto snapshot = db_->GetSnapshot();
|
||||
ASSERT_OK(db_->DeleteRange(WriteOptions(), cf, "a", "b"));
|
||||
ASSERT_OK(db_->Flush(FlushOptions(), cf));
|
||||
db_->ReleaseSnapshot(snapshot);
|
||||
|
||||
std::vector<std::vector<FileMetaData>> files;
|
||||
dbfull()->TEST_GetFilesMetaData(cf, &files);
|
||||
ASSERT_EQ(1, files[0].size());
|
||||
ASSERT_EQ("a", files[0][0].smallest.user_key());
|
||||
ASSERT_EQ("c", files[0][0].largest.user_key());
|
||||
|
||||
std::string v;
|
||||
auto s = db_->Get(ReadOptions(), "a", &v);
|
||||
ASSERT_TRUE(s.IsNotFound());
|
||||
}
|
||||
|
||||
#endif // ROCKSDB_LITE
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
+8
-24
@@ -297,7 +297,7 @@ TEST_F(DBSSTTest, RateLimitedDelete) {
|
||||
std::vector<uint64_t> penalties;
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"DeleteScheduler::BackgroundEmptyTrash:Wait",
|
||||
[&](void* arg) { penalties.push_back(*(static_cast<uint64_t*>(arg))); });
|
||||
[&](void* arg) { penalties.push_back(*(static_cast<int*>(arg))); });
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"InstrumentedCondVar::TimedWaitInternal", [&](void* arg) {
|
||||
// Turn timed wait into a simulated sleep
|
||||
@@ -335,7 +335,6 @@ TEST_F(DBSSTTest, RateLimitedDelete) {
|
||||
ASSERT_OK(s);
|
||||
options.sst_file_manager->SetDeleteRateBytesPerSecond(rate_bytes_per_sec);
|
||||
auto sfm = static_cast<SstFileManagerImpl*>(options.sst_file_manager.get());
|
||||
sfm->delete_scheduler()->TEST_SetMaxTrashDBRatio(1.1);
|
||||
|
||||
ASSERT_OK(TryReopen(options));
|
||||
// Create 4 files in L0
|
||||
@@ -401,7 +400,6 @@ TEST_F(DBSSTTest, DeleteSchedulerMultipleDBPaths) {
|
||||
env_, nullptr, trash_dir, rate_bytes_per_sec, false, &s));
|
||||
ASSERT_OK(s);
|
||||
auto sfm = static_cast<SstFileManagerImpl*>(options.sst_file_manager.get());
|
||||
sfm->delete_scheduler()->TEST_SetMaxTrashDBRatio(1.1);
|
||||
|
||||
DestroyAndReopen(options);
|
||||
|
||||
@@ -456,14 +454,9 @@ TEST_F(DBSSTTest, DestroyDBWithRateLimitedDelete) {
|
||||
[&](void* arg) { bg_delete_file++; });
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
Status s;
|
||||
Options options = CurrentOptions();
|
||||
options.disable_auto_compactions = true;
|
||||
options.env = env_;
|
||||
std::string trash_dir = test::TmpDir(env_) + "/trash";
|
||||
options.sst_file_manager.reset(
|
||||
NewSstFileManager(env_, nullptr, trash_dir, 0, false, &s));
|
||||
ASSERT_OK(s);
|
||||
DestroyAndReopen(options);
|
||||
|
||||
// Create 4 files in L0
|
||||
@@ -476,12 +469,15 @@ TEST_F(DBSSTTest, DestroyDBWithRateLimitedDelete) {
|
||||
|
||||
// Close DB and destroy it using DeleteScheduler
|
||||
Close();
|
||||
std::string trash_dir = test::TmpDir(env_) + "/trash";
|
||||
int64_t rate_bytes_per_sec = 1024 * 1024; // 1 Mb / Sec
|
||||
Status s;
|
||||
options.sst_file_manager.reset(NewSstFileManager(
|
||||
env_, nullptr, trash_dir, rate_bytes_per_sec, false, &s));
|
||||
ASSERT_OK(s);
|
||||
ASSERT_OK(DestroyDB(dbname_, options));
|
||||
|
||||
auto sfm = static_cast<SstFileManagerImpl*>(options.sst_file_manager.get());
|
||||
|
||||
sfm->SetDeleteRateBytesPerSecond(1024 * 1024);
|
||||
sfm->delete_scheduler()->TEST_SetMaxTrashDBRatio(1.1);
|
||||
ASSERT_OK(DestroyDB(dbname_, options));
|
||||
sfm->WaitForEmptyTrash();
|
||||
// We have deleted the 4 sst files in the delete_scheduler
|
||||
ASSERT_EQ(bg_delete_file, 4);
|
||||
@@ -650,18 +646,9 @@ TEST_F(DBSSTTest, OpenDBWithInfiniteMaxOpenFiles) {
|
||||
}
|
||||
|
||||
TEST_F(DBSSTTest, GetTotalSstFilesSize) {
|
||||
// We don't propagate oldest-key-time table property on compaction and
|
||||
// just write 0 as default value. This affect the exact table size, since
|
||||
// we encode table properties as varint64. Force time to be 0 to work around
|
||||
// it. Should remove the workaround after we propagate the property on
|
||||
// compaction.
|
||||
std::unique_ptr<MockTimeEnv> mock_env(new MockTimeEnv(Env::Default()));
|
||||
mock_env->set_current_time(0);
|
||||
|
||||
Options options = CurrentOptions();
|
||||
options.disable_auto_compactions = true;
|
||||
options.compression = kNoCompression;
|
||||
options.env = mock_env.get();
|
||||
DestroyAndReopen(options);
|
||||
// Generate 5 files in L0
|
||||
for (int i = 0; i < 5; i++) {
|
||||
@@ -748,9 +735,6 @@ TEST_F(DBSSTTest, GetTotalSstFilesSize) {
|
||||
// Live SST files = 0
|
||||
// Total SST files = 0
|
||||
ASSERT_EQ(total_sst_files_size, 0);
|
||||
|
||||
// Close db before mock_env destruct.
|
||||
Close();
|
||||
}
|
||||
|
||||
TEST_F(DBSSTTest, GetTotalSstFilesSizeVersionsFilesShared) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under both the GPLv2 (found in the
|
||||
// COPYING file in the root directory) and Apache 2.0 License
|
||||
// (found in the LICENSE.Apache file in the root directory).
|
||||
// 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 <string>
|
||||
|
||||
|
||||
+26
-396
@@ -23,7 +23,6 @@
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#include "cache/lru_cache.h"
|
||||
#include "db/db_impl.h"
|
||||
#include "db/db_test_util.h"
|
||||
#include "db/dbformat.h"
|
||||
@@ -61,6 +60,7 @@
|
||||
#include "util/file_reader_writer.h"
|
||||
#include "util/filename.h"
|
||||
#include "util/hash.h"
|
||||
#include "util/logging.h"
|
||||
#include "util/mutexlock.h"
|
||||
#include "util/rate_limiter.h"
|
||||
#include "util/string_util.h"
|
||||
@@ -1439,6 +1439,7 @@ TEST_F(DBTest, UnremovableSingleDelete) {
|
||||
#ifndef ROCKSDB_LITE
|
||||
TEST_F(DBTest, DeletionMarkers1) {
|
||||
Options options = CurrentOptions();
|
||||
options.max_background_flushes = 0;
|
||||
CreateAndReopenWithCF({"pikachu"}, options);
|
||||
Put(1, "foo", "v1");
|
||||
ASSERT_OK(Flush(1));
|
||||
@@ -2235,10 +2236,6 @@ class ModelDB : public DB {
|
||||
return Status::NotSupported("Not implemented.");
|
||||
}
|
||||
|
||||
virtual Status VerifyChecksum() override {
|
||||
return Status::NotSupported("Not implemented.");
|
||||
}
|
||||
|
||||
using DB::GetPropertiesOfAllTables;
|
||||
virtual Status GetPropertiesOfAllTables(
|
||||
ColumnFamilyHandle* column_family,
|
||||
@@ -2768,345 +2765,13 @@ TEST_P(DBTestWithParam, FIFOCompactionTest) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DBTest, FIFOCompactionTestWithCompaction) {
|
||||
Options options;
|
||||
options.compaction_style = kCompactionStyleFIFO;
|
||||
options.write_buffer_size = 20 << 10; // 20K
|
||||
options.arena_block_size = 4096;
|
||||
options.compaction_options_fifo.max_table_files_size = 1500 << 10; // 1MB
|
||||
options.compaction_options_fifo.allow_compaction = true;
|
||||
options.level0_file_num_compaction_trigger = 6;
|
||||
options.compression = kNoCompression;
|
||||
options.create_if_missing = true;
|
||||
options = CurrentOptions(options);
|
||||
DestroyAndReopen(options);
|
||||
|
||||
Random rnd(301);
|
||||
for (int i = 0; i < 60; i++) {
|
||||
// Generate and flush a file about 20KB.
|
||||
for (int j = 0; j < 20; j++) {
|
||||
ASSERT_OK(Put(ToString(i * 20 + j), RandomString(&rnd, 980)));
|
||||
}
|
||||
Flush();
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
}
|
||||
// It should be compacted to 10 files.
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 10);
|
||||
|
||||
for (int i = 0; i < 60; i++) {
|
||||
// Generate and flush a file about 20KB.
|
||||
for (int j = 0; j < 20; j++) {
|
||||
ASSERT_OK(Put(ToString(i * 20 + j + 2000), RandomString(&rnd, 980)));
|
||||
}
|
||||
Flush();
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
}
|
||||
|
||||
// It should be compacted to no more than 20 files.
|
||||
ASSERT_GT(NumTableFilesAtLevel(0), 10);
|
||||
ASSERT_LT(NumTableFilesAtLevel(0), 18);
|
||||
// Size limit is still guaranteed.
|
||||
ASSERT_LE(SizeAtLevel(0),
|
||||
options.compaction_options_fifo.max_table_files_size);
|
||||
}
|
||||
|
||||
TEST_F(DBTest, FIFOCompactionStyleWithCompactionAndDelete) {
|
||||
Options options;
|
||||
options.compaction_style = kCompactionStyleFIFO;
|
||||
options.write_buffer_size = 20 << 10; // 20K
|
||||
options.arena_block_size = 4096;
|
||||
options.compaction_options_fifo.max_table_files_size = 1500 << 10; // 1MB
|
||||
options.compaction_options_fifo.allow_compaction = true;
|
||||
options.level0_file_num_compaction_trigger = 3;
|
||||
options.compression = kNoCompression;
|
||||
options.create_if_missing = true;
|
||||
options = CurrentOptions(options);
|
||||
DestroyAndReopen(options);
|
||||
|
||||
Random rnd(301);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// Each file contains a different key which will be dropped later.
|
||||
ASSERT_OK(Put("a" + ToString(i), RandomString(&rnd, 500)));
|
||||
ASSERT_OK(Put("key" + ToString(i), ""));
|
||||
ASSERT_OK(Put("z" + ToString(i), RandomString(&rnd, 500)));
|
||||
Flush();
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
}
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 1);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ASSERT_EQ("", Get("key" + ToString(i)));
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// Each file contains a different key which will be dropped later.
|
||||
ASSERT_OK(Put("a" + ToString(i), RandomString(&rnd, 500)));
|
||||
ASSERT_OK(Delete("key" + ToString(i)));
|
||||
ASSERT_OK(Put("z" + ToString(i), RandomString(&rnd, 500)));
|
||||
Flush();
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
}
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 2);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ASSERT_EQ("NOT_FOUND", Get("key" + ToString(i)));
|
||||
}
|
||||
}
|
||||
|
||||
// Check that FIFO-with-TTL is not supported with max_open_files != -1.
|
||||
TEST_F(DBTest, FIFOCompactionWithTTLAndMaxOpenFilesTest) {
|
||||
Options options;
|
||||
options.compaction_style = kCompactionStyleFIFO;
|
||||
options.create_if_missing = true;
|
||||
options.compaction_options_fifo.ttl = 600; // seconds
|
||||
|
||||
// Check that it is not supported with max_open_files != -1.
|
||||
options.max_open_files = 100;
|
||||
options = CurrentOptions(options);
|
||||
ASSERT_TRUE(TryReopen(options).IsNotSupported());
|
||||
|
||||
options.max_open_files = -1;
|
||||
ASSERT_OK(TryReopen(options));
|
||||
}
|
||||
|
||||
// Check that FIFO-with-TTL is supported only with BlockBasedTableFactory.
|
||||
TEST_F(DBTest, FIFOCompactionWithTTLAndVariousTableFormatsTest) {
|
||||
Options options;
|
||||
options.compaction_style = kCompactionStyleFIFO;
|
||||
options.create_if_missing = true;
|
||||
options.compaction_options_fifo.ttl = 600; // seconds
|
||||
|
||||
options = CurrentOptions(options);
|
||||
options.table_factory.reset(NewBlockBasedTableFactory());
|
||||
ASSERT_OK(TryReopen(options));
|
||||
|
||||
Destroy(options);
|
||||
options.table_factory.reset(NewPlainTableFactory());
|
||||
ASSERT_TRUE(TryReopen(options).IsNotSupported());
|
||||
|
||||
Destroy(options);
|
||||
options.table_factory.reset(NewCuckooTableFactory());
|
||||
ASSERT_TRUE(TryReopen(options).IsNotSupported());
|
||||
|
||||
Destroy(options);
|
||||
options.table_factory.reset(NewAdaptiveTableFactory());
|
||||
ASSERT_TRUE(TryReopen(options).IsNotSupported());
|
||||
}
|
||||
|
||||
TEST_F(DBTest, FIFOCompactionWithTTLTest) {
|
||||
Options options;
|
||||
options.compaction_style = kCompactionStyleFIFO;
|
||||
options.write_buffer_size = 10 << 10; // 10KB
|
||||
options.arena_block_size = 4096;
|
||||
options.compression = kNoCompression;
|
||||
options.create_if_missing = true;
|
||||
env_->time_elapse_only_sleep_ = false;
|
||||
options.env = env_;
|
||||
|
||||
// Test to make sure that all files with expired ttl are deleted on next
|
||||
// manual compaction.
|
||||
{
|
||||
env_->addon_time_.store(0);
|
||||
options.compaction_options_fifo.max_table_files_size = 150 << 10; // 150KB
|
||||
options.compaction_options_fifo.allow_compaction = false;
|
||||
options.compaction_options_fifo.ttl = 1 * 60 * 60 ; // 1 hour
|
||||
options = CurrentOptions(options);
|
||||
DestroyAndReopen(options);
|
||||
|
||||
Random rnd(301);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
// Generate and flush a file about 10KB.
|
||||
for (int j = 0; j < 10; j++) {
|
||||
ASSERT_OK(Put(ToString(i * 20 + j), RandomString(&rnd, 980)));
|
||||
}
|
||||
Flush();
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
}
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 10);
|
||||
|
||||
// Sleep for 2 hours -- which is much greater than TTL.
|
||||
// Note: Couldn't use SleepForMicroseconds because it takes an int instead
|
||||
// of uint64_t. Hence used addon_time_ directly.
|
||||
// env_->SleepForMicroseconds(2 * 60 * 60 * 1000 * 1000);
|
||||
env_->addon_time_.fetch_add(2 * 60 * 60);
|
||||
|
||||
// Since no flushes and compactions have run, the db should still be in
|
||||
// the same state even after considerable time has passed.
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 10);
|
||||
|
||||
dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr);
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 0);
|
||||
}
|
||||
|
||||
// Test to make sure that all files with expired ttl are deleted on next
|
||||
// automatic compaction.
|
||||
{
|
||||
options.compaction_options_fifo.max_table_files_size = 150 << 10; // 150KB
|
||||
options.compaction_options_fifo.allow_compaction = false;
|
||||
options.compaction_options_fifo.ttl = 1 * 60 * 60; // 1 hour
|
||||
options = CurrentOptions(options);
|
||||
DestroyAndReopen(options);
|
||||
|
||||
Random rnd(301);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
// Generate and flush a file about 10KB.
|
||||
for (int j = 0; j < 10; j++) {
|
||||
ASSERT_OK(Put(ToString(i * 20 + j), RandomString(&rnd, 980)));
|
||||
}
|
||||
Flush();
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
}
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 10);
|
||||
|
||||
// Sleep for 2 hours -- which is much greater than TTL.
|
||||
env_->addon_time_.fetch_add(2 * 60 * 60);
|
||||
// Just to make sure that we are in the same state even after sleeping.
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 10);
|
||||
|
||||
// Create 1 more file to trigger TTL compaction. The old files are dropped.
|
||||
for (int i = 0; i < 1; i++) {
|
||||
for (int j = 0; j < 10; j++) {
|
||||
ASSERT_OK(Put(ToString(i * 20 + j), RandomString(&rnd, 980)));
|
||||
}
|
||||
Flush();
|
||||
}
|
||||
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
// Only the new 10 files remain.
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 1);
|
||||
ASSERT_LE(SizeAtLevel(0),
|
||||
options.compaction_options_fifo.max_table_files_size);
|
||||
}
|
||||
|
||||
// Test that shows the fall back to size-based FIFO compaction if TTL-based
|
||||
// deletion doesn't move the total size to be less than max_table_files_size.
|
||||
{
|
||||
options.write_buffer_size = 10 << 10; // 10KB
|
||||
options.compaction_options_fifo.max_table_files_size = 150 << 10; // 150KB
|
||||
options.compaction_options_fifo.allow_compaction = false;
|
||||
options.compaction_options_fifo.ttl = 1 * 60 * 60; // 1 hour
|
||||
options = CurrentOptions(options);
|
||||
DestroyAndReopen(options);
|
||||
|
||||
Random rnd(301);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// Generate and flush a file about 10KB.
|
||||
for (int j = 0; j < 10; j++) {
|
||||
ASSERT_OK(Put(ToString(i * 20 + j), RandomString(&rnd, 980)));
|
||||
}
|
||||
Flush();
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
}
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 3);
|
||||
|
||||
// Sleep for 2 hours -- which is much greater than TTL.
|
||||
env_->addon_time_.fetch_add(2 * 60 * 60);
|
||||
// Just to make sure that we are in the same state even after sleeping.
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 3);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
for (int j = 0; j < 140; j++) {
|
||||
ASSERT_OK(Put(ToString(i * 20 + j), RandomString(&rnd, 980)));
|
||||
}
|
||||
Flush();
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
}
|
||||
// Size limit is still guaranteed.
|
||||
ASSERT_LE(SizeAtLevel(0),
|
||||
options.compaction_options_fifo.max_table_files_size);
|
||||
}
|
||||
|
||||
// Test with TTL + Intra-L0 compactions.
|
||||
{
|
||||
options.compaction_options_fifo.max_table_files_size = 150 << 10; // 150KB
|
||||
options.compaction_options_fifo.allow_compaction = true;
|
||||
options.compaction_options_fifo.ttl = 1 * 60 * 60; // 1 hour
|
||||
options.level0_file_num_compaction_trigger = 6;
|
||||
options = CurrentOptions(options);
|
||||
DestroyAndReopen(options);
|
||||
|
||||
Random rnd(301);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
// Generate and flush a file about 10KB.
|
||||
for (int j = 0; j < 10; j++) {
|
||||
ASSERT_OK(Put(ToString(i * 20 + j), RandomString(&rnd, 980)));
|
||||
}
|
||||
Flush();
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
}
|
||||
// With Intra-L0 compaction, out of 10 files, 6 files will be compacted to 1
|
||||
// (due to level0_file_num_compaction_trigger = 6).
|
||||
// So total files = 1 + remaining 4 = 5.
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 5);
|
||||
|
||||
// Sleep for 2 hours -- which is much greater than TTL.
|
||||
env_->addon_time_.fetch_add(2 * 60 * 60);
|
||||
// Just to make sure that we are in the same state even after sleeping.
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 5);
|
||||
|
||||
// Create 10 more files. The old 5 files are dropped as their ttl expired.
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int j = 0; j < 10; j++) {
|
||||
ASSERT_OK(Put(ToString(i * 20 + j), RandomString(&rnd, 980)));
|
||||
}
|
||||
Flush();
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
}
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 5);
|
||||
ASSERT_LE(SizeAtLevel(0),
|
||||
options.compaction_options_fifo.max_table_files_size);
|
||||
}
|
||||
|
||||
// Test with large TTL + Intra-L0 compactions.
|
||||
// Files dropped based on size, as ttl doesn't kick in.
|
||||
{
|
||||
options.write_buffer_size = 20 << 10; // 20K
|
||||
options.compaction_options_fifo.max_table_files_size = 1500 << 10; // 1.5MB
|
||||
options.compaction_options_fifo.allow_compaction = true;
|
||||
options.compaction_options_fifo.ttl = 1 * 60 * 60; // 1 hour
|
||||
options.level0_file_num_compaction_trigger = 6;
|
||||
options = CurrentOptions(options);
|
||||
DestroyAndReopen(options);
|
||||
|
||||
Random rnd(301);
|
||||
for (int i = 0; i < 60; i++) {
|
||||
// Generate and flush a file about 20KB.
|
||||
for (int j = 0; j < 20; j++) {
|
||||
ASSERT_OK(Put(ToString(i * 20 + j), RandomString(&rnd, 980)));
|
||||
}
|
||||
Flush();
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
}
|
||||
// It should be compacted to 10 files.
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 10);
|
||||
|
||||
for (int i = 0; i < 60; i++) {
|
||||
// Generate and flush a file about 20KB.
|
||||
for (int j = 0; j < 20; j++) {
|
||||
ASSERT_OK(Put(ToString(i * 20 + j + 2000), RandomString(&rnd, 980)));
|
||||
}
|
||||
Flush();
|
||||
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
||||
}
|
||||
|
||||
// It should be compacted to no more than 20 files.
|
||||
ASSERT_GT(NumTableFilesAtLevel(0), 10);
|
||||
ASSERT_LT(NumTableFilesAtLevel(0), 18);
|
||||
// Size limit is still guaranteed.
|
||||
ASSERT_LE(SizeAtLevel(0),
|
||||
options.compaction_options_fifo.max_table_files_size);
|
||||
}
|
||||
}
|
||||
#endif // ROCKSDB_LITE
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
/*
|
||||
* This test is not reliable enough as it heavily depends on disk behavior.
|
||||
* Disable as it is flaky.
|
||||
*/
|
||||
TEST_F(DBTest, DISABLED_RateLimitingTest) {
|
||||
TEST_F(DBTest, RateLimitingTest) {
|
||||
Options options = CurrentOptions();
|
||||
options.write_buffer_size = 1 << 20; // 1MB
|
||||
options.level0_file_num_compaction_trigger = 2;
|
||||
@@ -3347,23 +3012,11 @@ TEST_F(DBTest, DynamicMemtableOptions) {
|
||||
{"write_buffer_size", "131072"},
|
||||
}));
|
||||
|
||||
// The existing memtable inflated 64KB->128KB when we invoked SetOptions().
|
||||
// Write 192KB, we should have a 128KB L0 file and a memtable with 64KB data.
|
||||
gen_l0_kb(192);
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 1); // (A)
|
||||
ASSERT_LT(SizeAtLevel(0), k128KB + 2 * k5KB);
|
||||
ASSERT_GT(SizeAtLevel(0), k128KB - 4 * k5KB);
|
||||
|
||||
// Decrease buffer size below current usage
|
||||
ASSERT_OK(dbfull()->SetOptions({
|
||||
{"write_buffer_size", "65536"},
|
||||
}));
|
||||
// The existing memtable became eligible for flush when we reduced its
|
||||
// capacity to 64KB. Two keys need to be added to trigger flush: first causes
|
||||
// memtable to be marked full, second schedules the flush. Then we should have
|
||||
// a 128KB L0 file, a 64KB L0 file, and a memtable with just one key.
|
||||
gen_l0_kb(2);
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 2);
|
||||
// The existing memtable is still 64KB in size, after it becomes immutable,
|
||||
// the next memtable will be 128KB in size. Write 256KB total, we should
|
||||
// have a 64KB L0 file, a 128KB L0 file, and a memtable with 64KB data
|
||||
gen_l0_kb(256);
|
||||
ASSERT_EQ(NumTableFilesAtLevel(0), 2); // (A)
|
||||
ASSERT_LT(SizeAtLevel(0), k128KB + k64KB + 2 * k5KB);
|
||||
ASSERT_GT(SizeAtLevel(0), k128KB + k64KB - 4 * k5KB);
|
||||
|
||||
@@ -3377,9 +3030,9 @@ TEST_F(DBTest, DynamicMemtableOptions) {
|
||||
Env::Priority::LOW);
|
||||
// Start from scratch and disable compaction/flush. Flush can only happen
|
||||
// during compaction but trigger is pretty high
|
||||
options.max_background_flushes = 0;
|
||||
options.disable_auto_compactions = true;
|
||||
DestroyAndReopen(options);
|
||||
env_->SetBackgroundThreads(0, Env::HIGH);
|
||||
|
||||
// Put until writes are stopped, bounded by 256 puts. We should see stop at
|
||||
// ~128KB
|
||||
@@ -3656,6 +3309,7 @@ TEST_P(DBTestWithParam, ThreadStatusSingleCompaction) {
|
||||
|
||||
TEST_P(DBTestWithParam, PreShutdownManualCompaction) {
|
||||
Options options = CurrentOptions();
|
||||
options.max_background_flushes = 0;
|
||||
options.max_subcompactions = max_subcompactions_;
|
||||
CreateAndReopenWithCF({"pikachu"}, options);
|
||||
|
||||
@@ -3694,6 +3348,7 @@ TEST_P(DBTestWithParam, PreShutdownManualCompaction) {
|
||||
|
||||
if (iter == 0) {
|
||||
options = CurrentOptions();
|
||||
options.max_background_flushes = 0;
|
||||
options.num_levels = 3;
|
||||
options.create_if_missing = true;
|
||||
DestroyAndReopen(options);
|
||||
@@ -3704,6 +3359,7 @@ TEST_P(DBTestWithParam, PreShutdownManualCompaction) {
|
||||
|
||||
TEST_F(DBTest, PreShutdownFlush) {
|
||||
Options options = CurrentOptions();
|
||||
options.max_background_flushes = 0;
|
||||
CreateAndReopenWithCF({"pikachu"}, options);
|
||||
ASSERT_OK(Put(1, "key", "value"));
|
||||
CancelAllBackgroundWork(db_);
|
||||
@@ -3995,14 +3651,19 @@ TEST_F(DBTest, DynamicLevelCompressionPerLevel2) {
|
||||
Random rnd(301);
|
||||
Options options;
|
||||
options.create_if_missing = true;
|
||||
options.db_write_buffer_size = 6000000;
|
||||
options.write_buffer_size = 600000;
|
||||
options.db_write_buffer_size = 6000;
|
||||
options.write_buffer_size = 6000;
|
||||
options.max_write_buffer_number = 2;
|
||||
options.level0_file_num_compaction_trigger = 2;
|
||||
options.level0_slowdown_writes_trigger = 2;
|
||||
options.level0_stop_writes_trigger = 2;
|
||||
options.soft_pending_compaction_bytes_limit = 1024 * 1024;
|
||||
options.target_file_size_base = 20;
|
||||
|
||||
// Use file size to distinguish levels
|
||||
// L1: 10, L2: 20, L3 40, L4 80
|
||||
// L0 is less than 30
|
||||
options.target_file_size_base = 10;
|
||||
options.target_file_size_multiplier = 2;
|
||||
|
||||
options.level_compaction_dynamic_level_bytes = true;
|
||||
options.max_bytes_for_level_base = 200;
|
||||
@@ -4039,11 +3700,10 @@ TEST_F(DBTest, DynamicLevelCompressionPerLevel2) {
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
std::string value = RandomString(&rnd, 200);
|
||||
ASSERT_OK(Put(Key(keys[i]), value));
|
||||
if (i % 25 == 24) {
|
||||
Flush();
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
ASSERT_OK(Put(Key(keys[i]), RandomString(&rnd, 200)));
|
||||
|
||||
if (i % 25 == 0) {
|
||||
dbfull()->TEST_WaitForFlushMemTable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4084,8 +3744,7 @@ TEST_F(DBTest, DynamicLevelCompressionPerLevel2) {
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
for (int i = 101; i < 500; i++) {
|
||||
std::string value = RandomString(&rnd, 200);
|
||||
ASSERT_OK(Put(Key(keys[i]), value));
|
||||
ASSERT_OK(Put(Key(keys[i]), RandomString(&rnd, 200)));
|
||||
if (i % 100 == 99) {
|
||||
Flush();
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
@@ -5387,36 +5046,6 @@ TEST_F(DBTest, RowCache) {
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), 1);
|
||||
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), 1);
|
||||
}
|
||||
|
||||
TEST_F(DBTest, PinnableSliceAndRowCache) {
|
||||
Options options = CurrentOptions();
|
||||
options.statistics = rocksdb::CreateDBStatistics();
|
||||
options.row_cache = NewLRUCache(8192);
|
||||
DestroyAndReopen(options);
|
||||
|
||||
ASSERT_OK(Put("foo", "bar"));
|
||||
ASSERT_OK(Flush());
|
||||
|
||||
ASSERT_EQ(Get("foo"), "bar");
|
||||
ASSERT_EQ(
|
||||
reinterpret_cast<LRUCache*>(options.row_cache.get())->TEST_GetLRUSize(),
|
||||
1);
|
||||
|
||||
{
|
||||
PinnableSlice pin_slice;
|
||||
ASSERT_EQ(Get("foo", &pin_slice), Status::OK());
|
||||
ASSERT_EQ(pin_slice.ToString(), "bar");
|
||||
// Entry is already in cache, lookup will remove the element from lru
|
||||
ASSERT_EQ(
|
||||
reinterpret_cast<LRUCache*>(options.row_cache.get())->TEST_GetLRUSize(),
|
||||
0);
|
||||
}
|
||||
// After PinnableSlice destruction element is added back in LRU
|
||||
ASSERT_EQ(
|
||||
reinterpret_cast<LRUCache*>(options.row_cache.get())->TEST_GetLRUSize(),
|
||||
1);
|
||||
}
|
||||
|
||||
#endif // ROCKSDB_LITE
|
||||
|
||||
TEST_F(DBTest, DeletingOldWalAfterDrop) {
|
||||
@@ -5489,6 +5118,7 @@ TEST_F(DBTest, PauseBackgroundWorkTest) {
|
||||
// now it's done
|
||||
ASSERT_TRUE(done.load());
|
||||
}
|
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
+36
-267
@@ -165,48 +165,20 @@ TEST_F(DBTest2, MaxSuccessiveMergesChangeWithDBRecovery) {
|
||||
#ifndef ROCKSDB_LITE
|
||||
class DBTestSharedWriteBufferAcrossCFs
|
||||
: public DBTestBase,
|
||||
public testing::WithParamInterface<std::tuple<bool, bool>> {
|
||||
public testing::WithParamInterface<bool> {
|
||||
public:
|
||||
DBTestSharedWriteBufferAcrossCFs()
|
||||
: DBTestBase("/db_test_shared_write_buffer") {}
|
||||
void SetUp() override {
|
||||
use_old_interface_ = std::get<0>(GetParam());
|
||||
cost_cache_ = std::get<1>(GetParam());
|
||||
}
|
||||
void SetUp() override { use_old_interface_ = GetParam(); }
|
||||
bool use_old_interface_;
|
||||
bool cost_cache_;
|
||||
};
|
||||
|
||||
TEST_P(DBTestSharedWriteBufferAcrossCFs, SharedWriteBufferAcrossCFs) {
|
||||
Options options = CurrentOptions();
|
||||
options.arena_block_size = 4096;
|
||||
|
||||
// Avoid undeterministic value by malloc_usable_size();
|
||||
// Force arena block size to 1
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"Arena::Arena:0", [&](void* arg) {
|
||||
size_t* block_size = static_cast<size_t*>(arg);
|
||||
*block_size = 1;
|
||||
});
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"Arena::AllocateNewBlock:0", [&](void* arg) {
|
||||
std::pair<size_t*, size_t*>* pair =
|
||||
static_cast<std::pair<size_t*, size_t*>*>(arg);
|
||||
*std::get<0>(*pair) = *std::get<1>(*pair);
|
||||
});
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
// The total soft write buffer size is about 105000
|
||||
std::shared_ptr<Cache> cache = NewLRUCache(4 * 1024 * 1024, 2);
|
||||
ASSERT_LT(cache->GetUsage(), 1024 * 1024);
|
||||
|
||||
if (use_old_interface_) {
|
||||
options.db_write_buffer_size = 120000; // this is the real limit
|
||||
} else if (!cost_cache_) {
|
||||
options.write_buffer_manager.reset(new WriteBufferManager(114285));
|
||||
options.db_write_buffer_size = 100000; // this is the real limit
|
||||
} else {
|
||||
options.write_buffer_manager.reset(new WriteBufferManager(114285, cache));
|
||||
options.write_buffer_manager.reset(new WriteBufferManager(100000));
|
||||
}
|
||||
options.write_buffer_size = 500000; // this is never hit
|
||||
CreateAndReopenWithCF({"pikachu", "dobrynia", "nikitich"}, options);
|
||||
@@ -214,13 +186,6 @@ TEST_P(DBTestSharedWriteBufferAcrossCFs, SharedWriteBufferAcrossCFs) {
|
||||
WriteOptions wo;
|
||||
wo.disableWAL = true;
|
||||
|
||||
std::function<void()> wait_flush = [&]() {
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[0]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[1]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[2]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[3]);
|
||||
};
|
||||
|
||||
// Create some data and flush "default" and "nikitich" so that they
|
||||
// are newer CFs created.
|
||||
ASSERT_OK(Put(3, Key(1), DummyString(1), wo));
|
||||
@@ -234,20 +199,13 @@ TEST_P(DBTestSharedWriteBufferAcrossCFs, SharedWriteBufferAcrossCFs) {
|
||||
static_cast<uint64_t>(1));
|
||||
|
||||
ASSERT_OK(Put(3, Key(1), DummyString(30000), wo));
|
||||
if (cost_cache_) {
|
||||
ASSERT_GE(cache->GetUsage(), 1024 * 1024);
|
||||
ASSERT_LE(cache->GetUsage(), 2 * 1024 * 1024);
|
||||
}
|
||||
wait_flush();
|
||||
ASSERT_OK(Put(0, Key(1), DummyString(60000), wo));
|
||||
if (cost_cache_) {
|
||||
ASSERT_GE(cache->GetUsage(), 1024 * 1024);
|
||||
ASSERT_LE(cache->GetUsage(), 2 * 1024 * 1024);
|
||||
}
|
||||
wait_flush();
|
||||
ASSERT_OK(Put(2, Key(1), DummyString(1), wo));
|
||||
// No flush should trigger
|
||||
wait_flush();
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[0]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[1]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[2]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[3]);
|
||||
{
|
||||
ASSERT_EQ(GetNumberOfSstFilesForColumnFamily(db_, "default"),
|
||||
static_cast<uint64_t>(1));
|
||||
@@ -261,9 +219,11 @@ TEST_P(DBTestSharedWriteBufferAcrossCFs, SharedWriteBufferAcrossCFs) {
|
||||
|
||||
// Trigger a flush. Flushing "nikitich".
|
||||
ASSERT_OK(Put(3, Key(2), DummyString(30000), wo));
|
||||
wait_flush();
|
||||
ASSERT_OK(Put(0, Key(1), DummyString(1), wo));
|
||||
wait_flush();
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[0]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[1]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[2]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[3]);
|
||||
{
|
||||
ASSERT_EQ(GetNumberOfSstFilesForColumnFamily(db_, "default"),
|
||||
static_cast<uint64_t>(1));
|
||||
@@ -277,11 +237,12 @@ TEST_P(DBTestSharedWriteBufferAcrossCFs, SharedWriteBufferAcrossCFs) {
|
||||
|
||||
// Without hitting the threshold, no flush should trigger.
|
||||
ASSERT_OK(Put(2, Key(1), DummyString(30000), wo));
|
||||
wait_flush();
|
||||
ASSERT_OK(Put(2, Key(1), DummyString(1), wo));
|
||||
wait_flush();
|
||||
ASSERT_OK(Put(2, Key(1), DummyString(1), wo));
|
||||
wait_flush();
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[0]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[1]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[2]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[3]);
|
||||
{
|
||||
ASSERT_EQ(GetNumberOfSstFilesForColumnFamily(db_, "default"),
|
||||
static_cast<uint64_t>(1));
|
||||
@@ -296,15 +257,14 @@ TEST_P(DBTestSharedWriteBufferAcrossCFs, SharedWriteBufferAcrossCFs) {
|
||||
// Hit the write buffer limit again. "default"
|
||||
// will have been flushed.
|
||||
ASSERT_OK(Put(2, Key(2), DummyString(10000), wo));
|
||||
wait_flush();
|
||||
ASSERT_OK(Put(3, Key(1), DummyString(1), wo));
|
||||
wait_flush();
|
||||
ASSERT_OK(Put(0, Key(1), DummyString(1), wo));
|
||||
wait_flush();
|
||||
ASSERT_OK(Put(0, Key(1), DummyString(1), wo));
|
||||
wait_flush();
|
||||
ASSERT_OK(Put(0, Key(1), DummyString(1), wo));
|
||||
wait_flush();
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[0]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[1]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[2]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[3]);
|
||||
{
|
||||
ASSERT_EQ(GetNumberOfSstFilesForColumnFamily(db_, "default"),
|
||||
static_cast<uint64_t>(2));
|
||||
@@ -319,14 +279,13 @@ TEST_P(DBTestSharedWriteBufferAcrossCFs, SharedWriteBufferAcrossCFs) {
|
||||
// Trigger another flush. This time "dobrynia". "pikachu" should not
|
||||
// be flushed, althrough it was never flushed.
|
||||
ASSERT_OK(Put(1, Key(1), DummyString(1), wo));
|
||||
wait_flush();
|
||||
ASSERT_OK(Put(2, Key(1), DummyString(80000), wo));
|
||||
wait_flush();
|
||||
ASSERT_OK(Put(1, Key(1), DummyString(1), wo));
|
||||
wait_flush();
|
||||
ASSERT_OK(Put(2, Key(1), DummyString(1), wo));
|
||||
wait_flush();
|
||||
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[0]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[1]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[2]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[3]);
|
||||
{
|
||||
ASSERT_EQ(GetNumberOfSstFilesForColumnFamily(db_, "default"),
|
||||
static_cast<uint64_t>(2));
|
||||
@@ -337,45 +296,16 @@ TEST_P(DBTestSharedWriteBufferAcrossCFs, SharedWriteBufferAcrossCFs) {
|
||||
ASSERT_EQ(GetNumberOfSstFilesForColumnFamily(db_, "nikitich"),
|
||||
static_cast<uint64_t>(2));
|
||||
}
|
||||
if (cost_cache_) {
|
||||
ASSERT_GE(cache->GetUsage(), 1024 * 1024);
|
||||
Close();
|
||||
options.write_buffer_manager.reset();
|
||||
ASSERT_LT(cache->GetUsage(), 1024 * 1024);
|
||||
}
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(DBTestSharedWriteBufferAcrossCFs,
|
||||
DBTestSharedWriteBufferAcrossCFs,
|
||||
::testing::Values(std::make_tuple(true, false),
|
||||
std::make_tuple(false, false),
|
||||
std::make_tuple(false, true)));
|
||||
DBTestSharedWriteBufferAcrossCFs, ::testing::Bool());
|
||||
|
||||
TEST_F(DBTest2, SharedWriteBufferLimitAcrossDB) {
|
||||
std::string dbname2 = test::TmpDir(env_) + "/db_shared_wb_db2";
|
||||
Options options = CurrentOptions();
|
||||
options.arena_block_size = 4096;
|
||||
// Avoid undeterministic value by malloc_usable_size();
|
||||
// Force arena block size to 1
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"Arena::Arena:0", [&](void* arg) {
|
||||
size_t* block_size = static_cast<size_t*>(arg);
|
||||
*block_size = 1;
|
||||
});
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"Arena::AllocateNewBlock:0", [&](void* arg) {
|
||||
std::pair<size_t*, size_t*>* pair =
|
||||
static_cast<std::pair<size_t*, size_t*>*>(arg);
|
||||
*std::get<0>(*pair) = *std::get<1>(*pair);
|
||||
});
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
|
||||
options.write_buffer_size = 500000; // this is never hit
|
||||
// Use a write buffer total size so that the soft limit is about
|
||||
// 105000.
|
||||
options.write_buffer_manager.reset(new WriteBufferManager(120000));
|
||||
options.write_buffer_manager.reset(new WriteBufferManager(100000));
|
||||
CreateAndReopenWithCF({"cf1", "cf2"}, options);
|
||||
|
||||
ASSERT_OK(DestroyDB(dbname2, options));
|
||||
@@ -385,25 +315,17 @@ TEST_F(DBTest2, SharedWriteBufferLimitAcrossDB) {
|
||||
WriteOptions wo;
|
||||
wo.disableWAL = true;
|
||||
|
||||
std::function<void()> wait_flush = [&]() {
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[0]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[1]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[2]);
|
||||
static_cast<DBImpl*>(db2)->TEST_WaitForFlushMemTable();
|
||||
};
|
||||
|
||||
// Trigger a flush on cf2
|
||||
ASSERT_OK(Put(2, Key(1), DummyString(70000), wo));
|
||||
wait_flush();
|
||||
ASSERT_OK(Put(0, Key(1), DummyString(20000), wo));
|
||||
wait_flush();
|
||||
|
||||
// Insert to DB2
|
||||
ASSERT_OK(db2->Put(wo, Key(2), DummyString(20000)));
|
||||
wait_flush();
|
||||
|
||||
ASSERT_OK(Put(2, Key(1), DummyString(1), wo));
|
||||
wait_flush();
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[0]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[1]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[2]);
|
||||
static_cast<DBImpl*>(db2)->TEST_WaitForFlushMemTable();
|
||||
{
|
||||
ASSERT_EQ(GetNumberOfSstFilesForColumnFamily(db_, "default") +
|
||||
@@ -416,9 +338,10 @@ TEST_F(DBTest2, SharedWriteBufferLimitAcrossDB) {
|
||||
|
||||
// Triggering to flush another CF in DB1
|
||||
ASSERT_OK(db2->Put(wo, Key(2), DummyString(70000)));
|
||||
wait_flush();
|
||||
ASSERT_OK(Put(2, Key(1), DummyString(1), wo));
|
||||
wait_flush();
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[0]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[1]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[2]);
|
||||
{
|
||||
ASSERT_EQ(GetNumberOfSstFilesForColumnFamily(db_, "default"),
|
||||
static_cast<uint64_t>(1));
|
||||
@@ -432,9 +355,10 @@ TEST_F(DBTest2, SharedWriteBufferLimitAcrossDB) {
|
||||
|
||||
// Triggering flush in DB2.
|
||||
ASSERT_OK(db2->Put(wo, Key(3), DummyString(40000)));
|
||||
wait_flush();
|
||||
ASSERT_OK(db2->Put(wo, Key(1), DummyString(1)));
|
||||
wait_flush();
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[0]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[1]);
|
||||
dbfull()->TEST_WaitForFlushMemTable(handles_[2]);
|
||||
static_cast<DBImpl*>(db2)->TEST_WaitForFlushMemTable();
|
||||
{
|
||||
ASSERT_EQ(GetNumberOfSstFilesForColumnFamily(db_, "default"),
|
||||
@@ -449,8 +373,6 @@ TEST_F(DBTest2, SharedWriteBufferLimitAcrossDB) {
|
||||
|
||||
delete db2;
|
||||
ASSERT_OK(DestroyDB(dbname2, options));
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -1028,7 +950,6 @@ TEST_F(DBTest2, PresetCompressionDict) {
|
||||
const int kNumL0Files = 5;
|
||||
|
||||
Options options;
|
||||
options.env = CurrentOptions().env; // Make sure to use any custom env that the test is configured with.
|
||||
options.allow_concurrent_memtable_write = false;
|
||||
options.arena_block_size = kBlockSizeBytes;
|
||||
options.compaction_style = kCompactionStyleUniversal;
|
||||
@@ -1159,6 +1080,7 @@ TEST_F(DBTest2, CompressionOptions) {
|
||||
options.max_bytes_for_level_multiplier = 2;
|
||||
options.num_levels = 7;
|
||||
options.max_background_compactions = 1;
|
||||
options.base_background_compactions = 1;
|
||||
|
||||
CompactionCompressionListener* listener =
|
||||
new CompactionCompressionListener(&options);
|
||||
@@ -1235,9 +1157,6 @@ TEST_F(DBTest2, CompactionStall) {
|
||||
CompactionStallTestListener* listener = new CompactionStallTestListener();
|
||||
options.listeners.emplace_back(listener);
|
||||
DestroyAndReopen(options);
|
||||
// make sure all background compaction jobs can be scheduled
|
||||
auto stop_token =
|
||||
dbfull()->TEST_write_controler().GetCompactionPressureToken();
|
||||
|
||||
Random rnd(301);
|
||||
|
||||
@@ -1597,7 +1516,6 @@ class MockPersistentCache : public PersistentCache {
|
||||
const size_t max_size_ = 10 * 1024; // 10KiB
|
||||
};
|
||||
|
||||
#ifndef OS_SOLARIS // GetUniqueIdFromFile is not implemented
|
||||
TEST_F(DBTest2, PersistentCache) {
|
||||
int num_iter = 80;
|
||||
|
||||
@@ -1661,7 +1579,6 @@ TEST_F(DBTest2, PersistentCache) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // !OS_SOLARIS
|
||||
|
||||
namespace {
|
||||
void CountSyncPoint() {
|
||||
@@ -1799,7 +1716,6 @@ TEST_F(DBTest2, ReadAmpBitmap) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef OS_SOLARIS // GetUniqueIdFromFile is not implemented
|
||||
TEST_F(DBTest2, ReadAmpBitmapLiveInCacheAfterDBClose) {
|
||||
if (dbname_.find("dev/shm") != std::string::npos) {
|
||||
// /dev/shm dont support getting a unique file id, this mean that
|
||||
@@ -1895,7 +1811,6 @@ TEST_F(DBTest2, ReadAmpBitmapLiveInCacheAfterDBClose) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // !OS_SOLARIS
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
TEST_F(DBTest2, AutomaticCompactionOverlapManualCompaction) {
|
||||
@@ -2185,152 +2100,6 @@ TEST_F(DBTest2, MemtableOnlyIterator) {
|
||||
ASSERT_EQ(1, count);
|
||||
delete it;
|
||||
}
|
||||
|
||||
TEST_F(DBTest2, LowPriWrite) {
|
||||
Options options = CurrentOptions();
|
||||
// Compaction pressure should trigger since 6 files
|
||||
options.level0_file_num_compaction_trigger = 4;
|
||||
options.level0_slowdown_writes_trigger = 12;
|
||||
options.level0_stop_writes_trigger = 30;
|
||||
options.delayed_write_rate = 8 * 1024 * 1024;
|
||||
Reopen(options);
|
||||
|
||||
std::atomic<int> rate_limit_count(0);
|
||||
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"GenericRateLimiter::Request:1", [&](void* arg) {
|
||||
rate_limit_count.fetch_add(1);
|
||||
int64_t* rate_bytes_per_sec = static_cast<int64_t*>(arg);
|
||||
ASSERT_EQ(1024 * 1024, *rate_bytes_per_sec);
|
||||
});
|
||||
// Block compaction
|
||||
rocksdb::SyncPoint::GetInstance()->LoadDependency({
|
||||
{"DBTest.LowPriWrite:0", "DBImpl::BGWorkCompaction"},
|
||||
});
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
WriteOptions wo;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
wo.low_pri = false;
|
||||
Put("", "", wo);
|
||||
wo.low_pri = true;
|
||||
Put("", "", wo);
|
||||
Flush();
|
||||
}
|
||||
ASSERT_EQ(0, rate_limit_count.load());
|
||||
wo.low_pri = true;
|
||||
Put("", "", wo);
|
||||
ASSERT_EQ(1, rate_limit_count.load());
|
||||
wo.low_pri = false;
|
||||
Put("", "", wo);
|
||||
ASSERT_EQ(1, rate_limit_count.load());
|
||||
|
||||
TEST_SYNC_POINT("DBTest.LowPriWrite:0");
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
wo.low_pri = true;
|
||||
Put("", "", wo);
|
||||
ASSERT_EQ(1, rate_limit_count.load());
|
||||
wo.low_pri = false;
|
||||
Put("", "", wo);
|
||||
ASSERT_EQ(1, rate_limit_count.load());
|
||||
}
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
TEST_F(DBTest2, RateLimitedCompactionReads) {
|
||||
// compaction input has 512KB data
|
||||
const int kNumKeysPerFile = 128;
|
||||
const int kBytesPerKey = 1024;
|
||||
const int kNumL0Files = 4;
|
||||
|
||||
for (auto use_direct_io : {false, true}) {
|
||||
if (use_direct_io && !IsDirectIOSupported()) {
|
||||
continue;
|
||||
}
|
||||
Options options = CurrentOptions();
|
||||
options.compression = kNoCompression;
|
||||
options.level0_file_num_compaction_trigger = kNumL0Files;
|
||||
options.memtable_factory.reset(new SpecialSkipListFactory(kNumKeysPerFile));
|
||||
options.new_table_reader_for_compaction_inputs = true;
|
||||
// takes roughly one second, split into 100 x 10ms intervals. Each interval
|
||||
// permits 5.12KB, which is smaller than the block size, so this test
|
||||
// exercises the code for chunking reads.
|
||||
options.rate_limiter.reset(NewGenericRateLimiter(
|
||||
static_cast<int64_t>(kNumL0Files * kNumKeysPerFile *
|
||||
kBytesPerKey) /* rate_bytes_per_sec */,
|
||||
10 * 1000 /* refill_period_us */, 10 /* fairness */,
|
||||
RateLimiter::Mode::kReadsOnly));
|
||||
options.use_direct_io_for_flush_and_compaction = use_direct_io;
|
||||
BlockBasedTableOptions bbto;
|
||||
bbto.block_size = 16384;
|
||||
bbto.no_block_cache = true;
|
||||
options.table_factory.reset(new BlockBasedTableFactory(bbto));
|
||||
DestroyAndReopen(options);
|
||||
|
||||
for (int i = 0; i < kNumL0Files; ++i) {
|
||||
for (int j = 0; j <= kNumKeysPerFile; ++j) {
|
||||
ASSERT_OK(Put(Key(j), DummyString(kBytesPerKey)));
|
||||
}
|
||||
dbfull()->TEST_WaitForFlushMemTable();
|
||||
ASSERT_EQ(i + 1, NumTableFilesAtLevel(0));
|
||||
}
|
||||
dbfull()->TEST_WaitForCompact();
|
||||
ASSERT_EQ(0, NumTableFilesAtLevel(0));
|
||||
|
||||
ASSERT_EQ(0, options.rate_limiter->GetTotalBytesThrough(Env::IO_HIGH));
|
||||
// should be slightly above 512KB due to non-data blocks read. Arbitrarily
|
||||
// chose 1MB as the upper bound on the total bytes read.
|
||||
size_t rate_limited_bytes =
|
||||
options.rate_limiter->GetTotalBytesThrough(Env::IO_LOW);
|
||||
// Include the explict prefetch of the footer in direct I/O case.
|
||||
size_t direct_io_extra = use_direct_io ? 512 * 1024 : 0;
|
||||
ASSERT_GE(rate_limited_bytes,
|
||||
static_cast<size_t>(kNumKeysPerFile * kBytesPerKey * kNumL0Files +
|
||||
direct_io_extra));
|
||||
ASSERT_LT(
|
||||
rate_limited_bytes,
|
||||
static_cast<size_t>(2 * kNumKeysPerFile * kBytesPerKey * kNumL0Files +
|
||||
direct_io_extra));
|
||||
|
||||
Iterator* iter = db_->NewIterator(ReadOptions());
|
||||
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||
ASSERT_EQ(iter->value().ToString(), DummyString(kBytesPerKey));
|
||||
}
|
||||
delete iter;
|
||||
// bytes read for user iterator shouldn't count against the rate limit.
|
||||
ASSERT_EQ(rate_limited_bytes,
|
||||
static_cast<size_t>(
|
||||
options.rate_limiter->GetTotalBytesThrough(Env::IO_LOW)));
|
||||
}
|
||||
}
|
||||
#endif // ROCKSDB_LITE
|
||||
|
||||
// Make sure DB can be reopen with reduced number of levels, given no file
|
||||
// is on levels higher than the new num_levels.
|
||||
TEST_F(DBTest2, ReduceLevel) {
|
||||
Options options;
|
||||
options.disable_auto_compactions = true;
|
||||
options.num_levels = 7;
|
||||
Reopen(options);
|
||||
Put("foo", "bar");
|
||||
Flush();
|
||||
MoveFilesToLevel(6);
|
||||
#ifndef ROCKSDB_LITE
|
||||
ASSERT_EQ("0,0,0,0,0,0,1", FilesPerLevel());
|
||||
#endif // !ROCKSDB_LITE
|
||||
CompactRangeOptions compact_options;
|
||||
compact_options.change_level = true;
|
||||
compact_options.target_level = 1;
|
||||
dbfull()->CompactRange(compact_options, nullptr, nullptr);
|
||||
#ifndef ROCKSDB_LITE
|
||||
ASSERT_EQ("0,1", FilesPerLevel());
|
||||
#endif // !ROCKSDB_LITE
|
||||
options.num_levels = 3;
|
||||
Reopen(options);
|
||||
#ifndef ROCKSDB_LITE
|
||||
ASSERT_EQ("0,1", FilesPerLevel());
|
||||
#endif // !ROCKSDB_LITE
|
||||
}
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
+17
-90
@@ -9,7 +9,6 @@
|
||||
|
||||
#include "db/db_test_util.h"
|
||||
#include "db/forward_iterator.h"
|
||||
#include "rocksdb/env_encryption.h"
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
@@ -42,25 +41,11 @@ SpecialEnv::SpecialEnv(Env* base)
|
||||
non_writable_count_ = 0;
|
||||
table_write_callback_ = nullptr;
|
||||
}
|
||||
#ifndef ROCKSDB_LITE
|
||||
ROT13BlockCipher rot13Cipher_(16);
|
||||
#endif // ROCKSDB_LITE
|
||||
|
||||
DBTestBase::DBTestBase(const std::string path)
|
||||
: mem_env_(!getenv("MEM_ENV") ? nullptr : new MockEnv(Env::Default())),
|
||||
#ifndef ROCKSDB_LITE
|
||||
encrypted_env_(
|
||||
!getenv("ENCRYPTED_ENV")
|
||||
? nullptr
|
||||
: NewEncryptedEnv(mem_env_ ? mem_env_ : Env::Default(),
|
||||
new CTREncryptionProvider(rot13Cipher_))),
|
||||
#else
|
||||
encrypted_env_(nullptr),
|
||||
#endif // ROCKSDB_LITE
|
||||
env_(new SpecialEnv(encrypted_env_
|
||||
? encrypted_env_
|
||||
: (mem_env_ ? mem_env_ : Env::Default()))),
|
||||
option_config_(kDefault) {
|
||||
: option_config_(kDefault),
|
||||
mem_env_(!getenv("MEM_ENV") ? nullptr : new MockEnv(Env::Default())),
|
||||
env_(new SpecialEnv(mem_env_ ? mem_env_ : Env::Default())) {
|
||||
env_->SetBackgroundThreads(1, Env::LOW);
|
||||
env_->SetBackgroundThreads(1, Env::HIGH);
|
||||
dbname_ = test::TmpDir(env_) + path;
|
||||
@@ -260,44 +245,27 @@ bool DBTestBase::ChangeFilterOptions() {
|
||||
|
||||
// Return the current option configuration.
|
||||
Options DBTestBase::CurrentOptions(
|
||||
const anon::OptionsOverride& options_override) const {
|
||||
return GetOptions(option_config_, GetDefaultOptions(), options_override);
|
||||
}
|
||||
|
||||
Options DBTestBase::CurrentOptions(
|
||||
const Options& default_options,
|
||||
const anon::OptionsOverride& options_override) const {
|
||||
return GetOptions(option_config_, default_options, options_override);
|
||||
}
|
||||
|
||||
Options DBTestBase::GetDefaultOptions() {
|
||||
const anon::OptionsOverride& options_override) {
|
||||
Options options;
|
||||
options.write_buffer_size = 4090 * 4096;
|
||||
options.target_file_size_base = 2 * 1024 * 1024;
|
||||
options.max_bytes_for_level_base = 10 * 1024 * 1024;
|
||||
options.max_open_files = 5000;
|
||||
options.base_background_compactions = -1;
|
||||
options.wal_recovery_mode = WALRecoveryMode::kTolerateCorruptedTailRecords;
|
||||
options.compaction_pri = CompactionPri::kByCompensatedSize;
|
||||
return options;
|
||||
|
||||
return CurrentOptions(options, options_override);
|
||||
}
|
||||
|
||||
Options DBTestBase::GetOptions(
|
||||
int option_config, const Options& default_options,
|
||||
const anon::OptionsOverride& options_override) const {
|
||||
Options DBTestBase::CurrentOptions(
|
||||
const Options& defaultOptions,
|
||||
const anon::OptionsOverride& options_override) {
|
||||
// this redundant copy is to minimize code change w/o having lint error.
|
||||
Options options = default_options;
|
||||
Options options = defaultOptions;
|
||||
BlockBasedTableOptions table_options;
|
||||
bool set_block_based_table_factory = true;
|
||||
#if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(OS_SOLARIS) && \
|
||||
!defined(OS_AIX)
|
||||
rocksdb::SyncPoint::GetInstance()->ClearCallBack(
|
||||
"NewRandomAccessFile:O_DIRECT");
|
||||
rocksdb::SyncPoint::GetInstance()->ClearCallBack(
|
||||
"NewWritableFile:O_DIRECT");
|
||||
#endif
|
||||
|
||||
bool can_allow_mmap = IsMemoryMappedAccessSupported();
|
||||
switch (option_config) {
|
||||
switch (option_config_) {
|
||||
#ifndef ROCKSDB_LITE
|
||||
case kHashSkipList:
|
||||
options.prefix_extractor.reset(NewFixedPrefixTransform(1));
|
||||
@@ -307,14 +275,14 @@ Options DBTestBase::GetOptions(
|
||||
case kPlainTableFirstBytePrefix:
|
||||
options.table_factory.reset(new PlainTableFactory());
|
||||
options.prefix_extractor.reset(NewFixedPrefixTransform(1));
|
||||
options.allow_mmap_reads = can_allow_mmap;
|
||||
options.allow_mmap_reads = true;
|
||||
options.max_sequential_skip_in_iterations = 999999;
|
||||
set_block_based_table_factory = false;
|
||||
break;
|
||||
case kPlainTableCappedPrefix:
|
||||
options.table_factory.reset(new PlainTableFactory());
|
||||
options.prefix_extractor.reset(NewCappedPrefixTransform(8));
|
||||
options.allow_mmap_reads = can_allow_mmap;
|
||||
options.allow_mmap_reads = true;
|
||||
options.max_sequential_skip_in_iterations = 999999;
|
||||
set_block_based_table_factory = false;
|
||||
break;
|
||||
@@ -328,7 +296,7 @@ Options DBTestBase::GetOptions(
|
||||
case kPlainTableAllBytesPrefix:
|
||||
options.table_factory.reset(new PlainTableFactory());
|
||||
options.prefix_extractor.reset(NewNoopTransform());
|
||||
options.allow_mmap_reads = can_allow_mmap;
|
||||
options.allow_mmap_reads = true;
|
||||
options.max_sequential_skip_in_iterations = 999999;
|
||||
set_block_based_table_factory = false;
|
||||
break;
|
||||
@@ -380,7 +348,7 @@ Options DBTestBase::GetOptions(
|
||||
options.wal_dir = alternative_wal_dir_;
|
||||
// mmap reads should be orthogonal to WalDir setting, so we piggyback to
|
||||
// this option config to test mmap reads as well
|
||||
options.allow_mmap_reads = can_allow_mmap;
|
||||
options.allow_mmap_reads = true;
|
||||
break;
|
||||
case kManifestFileSize:
|
||||
options.max_manifest_file_size = 50; // 50 bytes
|
||||
@@ -400,7 +368,7 @@ Options DBTestBase::GetOptions(
|
||||
options.num_levels = 8;
|
||||
break;
|
||||
case kCompressedBlockCache:
|
||||
options.allow_mmap_writes = can_allow_mmap;
|
||||
options.allow_mmap_writes = true;
|
||||
table_options.block_cache_compressed = NewLRUCache(8 * 1024 * 1024);
|
||||
break;
|
||||
case kInfiniteMaxOpenFiles:
|
||||
@@ -461,36 +429,6 @@ Options DBTestBase::GetOptions(
|
||||
options.enable_write_thread_adaptive_yield = true;
|
||||
break;
|
||||
}
|
||||
case kDirectIO: {
|
||||
options.use_direct_reads = true;
|
||||
options.use_direct_io_for_flush_and_compaction = true;
|
||||
options.compaction_readahead_size = 2 * 1024 * 1024;
|
||||
#if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(OS_SOLARIS) && \
|
||||
!defined(OS_AIX)
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"NewWritableFile:O_DIRECT", [&](void* arg) {
|
||||
int* val = static_cast<int*>(arg);
|
||||
*val &= ~O_DIRECT;
|
||||
});
|
||||
rocksdb::SyncPoint::GetInstance()->SetCallBack(
|
||||
"NewRandomAccessFile:O_DIRECT", [&](void* arg) {
|
||||
int* val = static_cast<int*>(arg);
|
||||
*val &= ~O_DIRECT;
|
||||
});
|
||||
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case kPipelinedWrite: {
|
||||
options.enable_pipelined_write = true;
|
||||
break;
|
||||
}
|
||||
case kConcurrentWALWrites: {
|
||||
// This options optimize 2PC commit path
|
||||
options.concurrent_prepare = true;
|
||||
options.manual_wal_flush = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -614,10 +552,6 @@ bool DBTestBase::IsDirectIOSupported() {
|
||||
return s.ok();
|
||||
}
|
||||
|
||||
bool DBTestBase::IsMemoryMappedAccessSupported() const {
|
||||
return (!encrypted_env_);
|
||||
}
|
||||
|
||||
Status DBTestBase::Flush(int cf) {
|
||||
if (cf == 0) {
|
||||
return db_->Flush(FlushOptions());
|
||||
@@ -697,13 +631,6 @@ std::string DBTestBase::Get(int cf, const std::string& k,
|
||||
return result;
|
||||
}
|
||||
|
||||
Status DBTestBase::Get(const std::string& k, PinnableSlice* v) {
|
||||
ReadOptions options;
|
||||
options.verify_checksums = true;
|
||||
Status s = dbfull()->Get(options, dbfull()->DefaultColumnFamily(), k, v);
|
||||
return s;
|
||||
}
|
||||
|
||||
uint64_t DBTestBase::GetNumSnapshots() {
|
||||
uint64_t int_num;
|
||||
EXPECT_TRUE(dbfull()->GetIntProperty("rocksdb.num-snapshots", &int_num));
|
||||
|
||||
+22
-103
@@ -49,7 +49,10 @@
|
||||
#include "util/mutexlock.h"
|
||||
|
||||
#include "util/string_util.h"
|
||||
// SyncPoint is not supported in Released Windows Mode.
|
||||
#if !(defined NDEBUG) || !defined(OS_WIN)
|
||||
#include "util/sync_point.h"
|
||||
#endif // !(defined NDEBUG) || !defined(OS_WIN)
|
||||
#include "util/testharness.h"
|
||||
#include "util/testutil.h"
|
||||
#include "utilities/merge_operators.h"
|
||||
@@ -123,8 +126,8 @@ enum SkipPolicy { kSkipNone = 0, kSkipNoSnapshot = 1, kSkipNoPrefix = 2 };
|
||||
// A hacky skip list mem table that triggers flush after number of entries.
|
||||
class SpecialMemTableRep : public MemTableRep {
|
||||
public:
|
||||
explicit SpecialMemTableRep(Allocator* allocator, MemTableRep* memtable,
|
||||
int num_entries_flush)
|
||||
explicit SpecialMemTableRep(MemTableAllocator* allocator,
|
||||
MemTableRep* memtable, int num_entries_flush)
|
||||
: MemTableRep(allocator),
|
||||
memtable_(memtable),
|
||||
num_entries_flush_(num_entries_flush),
|
||||
@@ -184,9 +187,8 @@ class SpecialSkipListFactory : public MemTableRepFactory {
|
||||
explicit SpecialSkipListFactory(int num_entries_flush)
|
||||
: num_entries_flush_(num_entries_flush) {}
|
||||
|
||||
using MemTableRepFactory::CreateMemTableRep;
|
||||
virtual MemTableRep* CreateMemTableRep(
|
||||
const MemTableRep::KeyComparator& compare, Allocator* allocator,
|
||||
const MemTableRep::KeyComparator& compare, MemTableAllocator* allocator,
|
||||
const SliceTransform* transform, Logger* logger) override {
|
||||
return new SpecialMemTableRep(
|
||||
allocator, factory_.CreateMemTableRep(compare, allocator, transform, 0),
|
||||
@@ -247,13 +249,6 @@ class SpecialEnv : public EnvWrapper {
|
||||
}
|
||||
}
|
||||
Status Truncate(uint64_t size) override { return base_->Truncate(size); }
|
||||
Status RangeSync(uint64_t offset, uint64_t nbytes) override {
|
||||
Status s = base_->RangeSync(offset, nbytes);
|
||||
#if !(defined NDEBUG) || !defined(OS_WIN)
|
||||
TEST_SYNC_POINT_CALLBACK("SpecialEnv::SStableFile::RangeSync", &s);
|
||||
#endif // !(defined NDEBUG) || !defined(OS_WIN)
|
||||
return s;
|
||||
}
|
||||
Status Close() override {
|
||||
// SyncPoint is not supported in Released Windows Mode.
|
||||
#if !(defined NDEBUG) || !defined(OS_WIN)
|
||||
@@ -263,11 +258,7 @@ class SpecialEnv : public EnvWrapper {
|
||||
TEST_SYNC_POINT_CALLBACK("DBTestWritableFile.GetPreallocationStatus",
|
||||
&preallocation_size);
|
||||
#endif // !(defined NDEBUG) || !defined(OS_WIN)
|
||||
Status s = base_->Close();
|
||||
#if !(defined NDEBUG) || !defined(OS_WIN)
|
||||
TEST_SYNC_POINT_CALLBACK("SpecialEnv::SStableFile::Close", &s);
|
||||
#endif // !(defined NDEBUG) || !defined(OS_WIN)
|
||||
return s;
|
||||
return base_->Close();
|
||||
}
|
||||
Status Flush() override { return base_->Flush(); }
|
||||
Status Sync() override {
|
||||
@@ -275,11 +266,7 @@ class SpecialEnv : public EnvWrapper {
|
||||
while (env_->delay_sstable_sync_.load(std::memory_order_acquire)) {
|
||||
env_->SleepForMicroseconds(100000);
|
||||
}
|
||||
Status s = base_->Sync();
|
||||
#if !(defined NDEBUG) || !defined(OS_WIN)
|
||||
TEST_SYNC_POINT_CALLBACK("SpecialEnv::SStableFile::Sync", &s);
|
||||
#endif // !(defined NDEBUG) || !defined(OS_WIN)
|
||||
return s;
|
||||
return base_->Sync();
|
||||
}
|
||||
void SetIOPriority(Env::IOPriority pri) override {
|
||||
base_->SetIOPriority(pri);
|
||||
@@ -572,37 +559,6 @@ class SpecialEnv : public EnvWrapper {
|
||||
std::atomic<bool> is_wal_sync_thread_safe_{true};
|
||||
};
|
||||
|
||||
class MockTimeEnv : public EnvWrapper {
|
||||
public:
|
||||
explicit MockTimeEnv(Env* base) : EnvWrapper(base) {}
|
||||
|
||||
virtual Status GetCurrentTime(int64_t* time) override {
|
||||
assert(time != nullptr);
|
||||
assert(current_time_ <=
|
||||
static_cast<uint64_t>(std::numeric_limits<int64_t>::max()));
|
||||
*time = static_cast<int64_t>(current_time_);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
virtual uint64_t NowMicros() override {
|
||||
assert(current_time_ <= std::numeric_limits<uint64_t>::max() / 1000000);
|
||||
return current_time_ * 1000000;
|
||||
}
|
||||
|
||||
virtual uint64_t NowNanos() override {
|
||||
assert(current_time_ <= std::numeric_limits<uint64_t>::max() / 1000000000);
|
||||
return current_time_ * 1000000000;
|
||||
}
|
||||
|
||||
void set_current_time(uint64_t time) {
|
||||
assert(time >= current_time_);
|
||||
current_time_ = time;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t current_time_ = 0;
|
||||
};
|
||||
|
||||
#ifndef ROCKSDB_LITE
|
||||
class OnFileDeletionListener : public EventListener {
|
||||
public:
|
||||
@@ -630,32 +586,10 @@ class OnFileDeletionListener : public EventListener {
|
||||
};
|
||||
#endif
|
||||
|
||||
// A test merge operator mimics put but also fails if one of merge operands is
|
||||
// "corrupted".
|
||||
class TestPutOperator : public MergeOperator {
|
||||
public:
|
||||
virtual bool FullMergeV2(const MergeOperationInput& merge_in,
|
||||
MergeOperationOutput* merge_out) const override {
|
||||
if (merge_in.existing_value != nullptr &&
|
||||
*(merge_in.existing_value) == "corrupted") {
|
||||
return false;
|
||||
}
|
||||
for (auto value : merge_in.operand_list) {
|
||||
if (value == "corrupted") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
merge_out->existing_operand = merge_in.operand_list.back();
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual const char* Name() const override { return "TestPutOperator"; }
|
||||
};
|
||||
|
||||
class DBTestBase : public testing::Test {
|
||||
public:
|
||||
protected:
|
||||
// Sequence of option configurations to try
|
||||
enum OptionConfig : int {
|
||||
enum OptionConfig {
|
||||
kDefault = 0,
|
||||
kBlockBasedTableWithPrefixHashIndex = 1,
|
||||
kBlockBasedTableWithWholeKeyHashIndex = 2,
|
||||
@@ -686,28 +620,24 @@ class DBTestBase : public testing::Test {
|
||||
kRowCache = 27,
|
||||
kRecycleLogFiles = 28,
|
||||
kConcurrentSkipList = 29,
|
||||
kPipelinedWrite = 30,
|
||||
kConcurrentWALWrites = 31,
|
||||
kEnd = 32,
|
||||
kDirectIO = 33,
|
||||
kLevelSubcompactions = 34,
|
||||
kUniversalSubcompactions = 35,
|
||||
kBlockBasedTableWithIndexRestartInterval = 36,
|
||||
kBlockBasedTableWithPartitionedIndex = 37,
|
||||
kPartitionedFilterWithNewTableReaderForCompactions = 38,
|
||||
kEnd = 30,
|
||||
kLevelSubcompactions = 31,
|
||||
kUniversalSubcompactions = 32,
|
||||
kBlockBasedTableWithIndexRestartInterval = 33,
|
||||
kBlockBasedTableWithPartitionedIndex = 34,
|
||||
kPartitionedFilterWithNewTableReaderForCompactions = 35,
|
||||
};
|
||||
int option_config_;
|
||||
|
||||
public:
|
||||
std::string dbname_;
|
||||
std::string alternative_wal_dir_;
|
||||
std::string alternative_db_log_dir_;
|
||||
MockEnv* mem_env_;
|
||||
Env* encrypted_env_;
|
||||
SpecialEnv* env_;
|
||||
DB* db_;
|
||||
std::vector<ColumnFamilyHandle*> handles_;
|
||||
|
||||
int option_config_;
|
||||
Options last_options_;
|
||||
|
||||
// Skip some options, as they may not be applicable to a specific test.
|
||||
@@ -758,19 +688,12 @@ class DBTestBase : public testing::Test {
|
||||
bool ChangeFilterOptions();
|
||||
|
||||
// Return the current option configuration.
|
||||
Options CurrentOptions(const anon::OptionsOverride& options_override =
|
||||
anon::OptionsOverride()) const;
|
||||
Options CurrentOptions(
|
||||
const anon::OptionsOverride& options_override = anon::OptionsOverride());
|
||||
|
||||
Options CurrentOptions(const Options& default_options,
|
||||
const anon::OptionsOverride& options_override =
|
||||
anon::OptionsOverride()) const;
|
||||
|
||||
static Options GetDefaultOptions();
|
||||
|
||||
Options GetOptions(int option_config,
|
||||
const Options& default_options = GetDefaultOptions(),
|
||||
const anon::OptionsOverride& options_override =
|
||||
anon::OptionsOverride()) const;
|
||||
Options CurrentOptions(
|
||||
const Options& defaultOptions,
|
||||
const anon::OptionsOverride& options_override = anon::OptionsOverride());
|
||||
|
||||
DBImpl* dbfull() { return reinterpret_cast<DBImpl*>(db_); }
|
||||
|
||||
@@ -806,8 +729,6 @@ class DBTestBase : public testing::Test {
|
||||
|
||||
bool IsDirectIOSupported();
|
||||
|
||||
bool IsMemoryMappedAccessSupported() const;
|
||||
|
||||
Status Flush(int cf = 0);
|
||||
|
||||
Status Put(const Slice& k, const Slice& v, WriteOptions wo = WriteOptions());
|
||||
@@ -834,8 +755,6 @@ class DBTestBase : public testing::Test {
|
||||
std::string Get(int cf, const std::string& k,
|
||||
const Snapshot* snapshot = nullptr);
|
||||
|
||||
Status Get(const std::string& k, PinnableSlice* v);
|
||||
|
||||
uint64_t GetNumSnapshots();
|
||||
|
||||
uint64_t GetTimeOldestSnapshots();
|
||||
|
||||
Loaded 100 of 543 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user