merge upstream changes

main
Praveen Rao 9 years ago
commit 2938c5c137
  1. 2
      .travis.yml
  2. 21
      CMakeLists.txt
  3. 1
      HISTORY.md
  4. 1
      INSTALL.md
  5. 50
      Makefile
  6. 2
      build_tools/rocksdb-lego-determinator
  7. 10
      db/builder.cc
  8. 6
      db/builder.h
  9. 2
      db/column_family.cc
  10. 3
      db/compaction_iterator.cc
  11. 4
      db/compaction_iterator.h
  12. 22
      db/compaction_job.cc
  13. 2
      db/compaction_job.h
  14. 4
      db/compaction_job_stats_test.cc
  15. 13
      db/compaction_job_test.cc
  16. 3
      db/comparator_db_test.cc
  17. 33
      db/db_bench.cc
  18. 12
      db/db_compaction_filter_test.cc
  19. 7
      db/db_compaction_test.cc
  20. 6
      db/db_dynamic_level_test.cc
  21. 79
      db/db_impl.cc
  22. 48
      db/db_impl.h
  23. 21
      db/db_impl_debug.cc
  24. 19
      db/db_iter.cc
  25. 11
      db/db_iter.h
  26. 7
      db/db_iter_test.cc
  27. 6
      db/db_log_iter_test.cc
  28. 217
      db/db_table_properties_test.cc
  29. 6
      db/db_tailing_iter_test.cc
  30. 270
      db/db_test.cc
  31. 154
      db/db_test_util.cc
  32. 56
      db/db_test_util.h
  33. 6
      db/db_universal_compaction_test.cc
  34. 4
      db/filename.cc
  35. 2
      db/flush_job.cc
  36. 2
      db/flush_job.h
  37. 8
      db/forward_iterator.cc
  38. 16
      db/forward_iterator.h
  39. 16
      db/internal_stats.cc
  40. 11
      db/internal_stats.h
  41. 2
      db/listener_test.cc
  42. 0
      db/manual_compaction_test.cc
  43. 6
      db/memtable.cc
  44. 3
      db/memtable.h
  45. 4
      db/memtable_list.cc
  46. 3
      db/memtable_list.h
  47. 2
      db/memtablerep_bench.cc
  48. 4
      db/merge_helper.cc
  49. 4
      db/merge_helper.h
  50. 46
      db/perf_context_test.cc
  51. 4
      db/repair.cc
  52. 17
      db/table_cache.cc
  53. 11
      db/table_cache.h
  54. 71
      db/version_set.cc
  55. 21
      db/version_set.h
  56. 2
      db/write_batch_test.cc
  57. 14
      include/rocksdb/compaction_filter.h
  58. 22
      include/rocksdb/db.h
  59. 44
      include/rocksdb/iterator.h
  60. 32
      include/rocksdb/perf_context.h
  61. 7
      include/rocksdb/utilities/stackable_db.h
  62. 20
      include/rocksdb/utilities/transaction.h
  63. 2
      java/RELEASE.md
  64. 2
      java/crossbuild/Vagrantfile
  65. 4
      java/crossbuild/build-linux-centos.sh
  66. 2
      java/rocksjni/write_batch.cc
  67. 2
      java/rocksjni/write_batch_test.cc
  68. 6
      memtable/hash_cuckoo_rep.cc
  69. 3
      memtable/hash_cuckoo_rep.h
  70. 2
      memtable/hash_linklist_rep.cc
  71. 2
      memtable/hash_linklist_rep.h
  72. 2
      memtable/hash_skiplist_rep.cc
  73. 2
      memtable/hash_skiplist_rep.h
  74. 12
      memtable/stl_wrappers.h
  75. 2
      port/win/env_win.cc
  76. 7
      port/win/port_win.h
  77. 21
      src.mk
  78. 8
      table/block.cc
  79. 8
      table/block.h
  80. 72
      table/block_based_table_reader.cc
  81. 21
      table/block_based_table_reader.h
  82. 6
      table/block_hash_index.cc
  83. 7
      table/block_hash_index.h
  84. 3
      table/block_hash_index_test.cc
  85. 6
      table/block_test.cc
  86. 12
      table/cuckoo_table_reader.cc
  87. 4
      table/cuckoo_table_reader.h
  88. 4
      table/cuckoo_table_reader_test.cc
  89. 75
      table/internal_iterator.h
  90. 54
      table/iterator.cc
  91. 19
      table/iterator_wrapper.h
  92. 18
      table/merger.cc
  93. 12
      table/merger.h
  94. 6
      table/merger_test.cc
  95. 11
      table/meta_blocks.cc
  96. 5
      table/meta_blocks.h
  97. 3
      table/mock_table.cc
  98. 7
      table/mock_table.h
  99. 7
      table/plain_table_reader.cc
  100. 4
      table/plain_table_reader.h
  101. Some files were not shown because too many files have changed in this diff Show More

@ -34,7 +34,7 @@ before_script:
# as EnvPosixTest::AllocateTest expects within the Travis OpenVZ environment. # as EnvPosixTest::AllocateTest expects within the Travis OpenVZ environment.
script: script:
- if [[ "${TRAVIS_OS_NAME}" == 'linux' ]]; then OPT=-DTRAVIS CLANG_FORMAT_DIFF=/tmp/clang-format-diff.py make format || true; fi - if [[ "${TRAVIS_OS_NAME}" == 'linux' ]]; then OPT=-DTRAVIS CLANG_FORMAT_DIFF=/tmp/clang-format-diff.py make format || true; fi
- OPT=-DTRAVIS V=1 make -j4 check && OPT=-DTRAVIS V=1 make clean jclean rocksdbjava jtest - OPT=-DTRAVIS V=1 make -j4 check && OPT=-DTRAVIS V=1 make clean jclean rocksdbjava jtest && make clean && OPT="-DTRAVIS -DROCKSDB_LITE" V=1 make -j4 check
notifications: notifications:
email: email:

@ -31,7 +31,7 @@ string(REGEX REPLACE "(..)/(..)/..(..).*" "\\1/\\2/\\3" DATE ${DATE})
string(REGEX REPLACE "(..):(.....).*" " \\1:\\2" TIME ${TIME}) string(REGEX REPLACE "(..):(.....).*" " \\1:\\2" TIME ${TIME})
string(CONCAT GIT_DATE_TIME ${DATE} ${TIME}) string(CONCAT GIT_DATE_TIME ${DATE} ${TIME})
execute_process(COMMAND $ENV{COMSPEC} " /C git rev-parse HEAD 2>nil" OUTPUT_VARIABLE GIT_SHA) execute_process(COMMAND $ENV{COMSPEC} " /C git -C ${CMAKE_CURRENT_SOURCE_DIR} rev-parse HEAD" OUTPUT_VARIABLE GIT_SHA)
string(REGEX REPLACE "[^0-9a-f]+" "" GIT_SHA ${GIT_SHA}) string(REGEX REPLACE "[^0-9a-f]+" "" GIT_SHA ${GIT_SHA})
set(BUILD_VERSION_CC ${CMAKE_CURRENT_SOURCE_DIR}/util/build_version.cc) set(BUILD_VERSION_CC ${CMAKE_CURRENT_SOURCE_DIR}/util/build_version.cc)
@ -131,6 +131,9 @@ set(SOURCES
db/write_batch_base.cc db/write_batch_base.cc
db/write_controller.cc db/write_controller.cc
db/write_thread.cc db/write_thread.cc
memtable/hash_cuckoo_rep.cc
memtable/hash_linklist_rep.cc
memtable/hash_skiplist_rep.cc
port/stack_trace.cc port/stack_trace.cc
port/win/env_win.cc port/win/env_win.cc
port/win/port_win.cc port/win/port_win.cc
@ -164,6 +167,7 @@ set(SOURCES
table/plain_table_reader.cc table/plain_table_reader.cc
table/table_properties.cc table/table_properties.cc
table/two_level_iterator.cc table/two_level_iterator.cc
tools/sst_dump_tool.cc
tools/dump/db_dump_tool.cc tools/dump/db_dump_tool.cc
util/arena.cc util/arena.cc
util/auto_roll_logger.cc util/auto_roll_logger.cc
@ -184,14 +188,11 @@ set(SOURCES
util/file_reader_writer.cc util/file_reader_writer.cc
util/filter_policy.cc util/filter_policy.cc
util/hash.cc util/hash.cc
util/hash_cuckoo_rep.cc
util/hash_linklist_rep.cc
util/hash_skiplist_rep.cc
util/histogram.cc util/histogram.cc
util/instrumented_mutex.cc util/instrumented_mutex.cc
util/iostats_context.cc util/iostats_context.cc
util/ldb_cmd.cc tools/ldb_cmd.cc
util/ldb_tool.cc tools/ldb_tool.cc
util/logging.cc util/logging.cc
util/log_buffer.cc util/log_buffer.cc
util/memenv.cc util/memenv.cc
@ -207,7 +208,6 @@ set(SOURCES
util/rate_limiter.cc util/rate_limiter.cc
util/skiplistrep.cc util/skiplistrep.cc
util/slice.cc util/slice.cc
util/sst_dump_tool.cc
util/statistics.cc util/statistics.cc
util/status.cc util/status.cc
util/status_message.cc util/status_message.cc
@ -294,6 +294,7 @@ set(TESTS
db/db_universal_compaction_test.cc db/db_universal_compaction_test.cc
db/db_wal_test.cc db/db_wal_test.cc
db/db_tailing_iter_test.cc db/db_tailing_iter_test.cc
db/db_table_properties_test.cc
db/dbformat_test.cc db/dbformat_test.cc
db/deletefile_test.cc db/deletefile_test.cc
db/fault_injection_test.cc db/fault_injection_test.cc
@ -302,6 +303,7 @@ set(TESTS
db/flush_job_test.cc db/flush_job_test.cc
db/listener_test.cc db/listener_test.cc
db/log_test.cc db/log_test.cc
db/manual_compaction_test.cc
db/memtable_list_test.cc db/memtable_list_test.cc
db/merge_test.cc db/merge_test.cc
db/merge_helper_test.cc db/merge_helper_test.cc
@ -326,7 +328,9 @@ set(TESTS
table/merger_test.cc table/merger_test.cc
table/table_test.cc table/table_test.cc
tools/db_sanity_test.cc tools/db_sanity_test.cc
tools/ldb_cmd_test.cc
tools/reduce_levels_test.cc tools/reduce_levels_test.cc
tools/sst_dump_test.cc
util/arena_test.cc util/arena_test.cc
util/autovector_test.cc util/autovector_test.cc
util/auto_roll_logger_test.cc util/auto_roll_logger_test.cc
@ -341,14 +345,11 @@ set(TESTS
util/file_reader_writer_test.cc util/file_reader_writer_test.cc
util/heap_test.cc util/heap_test.cc
util/histogram_test.cc util/histogram_test.cc
util/ldb_cmd_test.cc
util/manual_compaction_test.cc
util/memenv_test.cc util/memenv_test.cc
util/mock_env_test.cc util/mock_env_test.cc
util/options_test.cc util/options_test.cc
util/rate_limiter_test.cc util/rate_limiter_test.cc
util/slice_transform_test.cc util/slice_transform_test.cc
util/sst_dump_test.cc
util/thread_list_test.cc util/thread_list_test.cc
util/thread_local_test.cc util/thread_local_test.cc
utilities/backupable/backupable_db_test.cc utilities/backupable/backupable_db_test.cc

@ -5,6 +5,7 @@
* CompactionFilter::Context includes information of Column Family ID * CompactionFilter::Context includes information of Column Family ID
* The need-compaction hint given by TablePropertiesCollector::NeedCompact() will be persistent and recoverable after DB recovery. This introduces a breaking format change. If you use this experimental feature, including NewCompactOnDeletionCollectorFactory() in the new version, you may not be able to directly downgrade the DB back to version 4.0 or lower. * The need-compaction hint given by TablePropertiesCollector::NeedCompact() will be persistent and recoverable after DB recovery. This introduces a breaking format change. If you use this experimental feature, including NewCompactOnDeletionCollectorFactory() in the new version, you may not be able to directly downgrade the DB back to version 4.0 or lower.
* TablePropertiesCollectorFactory::CreateTablePropertiesCollector() now takes an option Context, containing the information of column family ID for the file being written. * TablePropertiesCollectorFactory::CreateTablePropertiesCollector() now takes an option Context, containing the information of column family ID for the file being written.
* Remove DefaultCompactionFilterFactory.
## 4.1.0 (10/8/2015) ## 4.1.0 (10/8/2015)
### New Features ### New Features

@ -87,4 +87,5 @@ your make commands, like this: `PORTABLE=1 make static_lib`
* Run: `TARGET_OS=IOS make static_lib`. When building the project which uses rocksdb iOS library, make sure to define two important pre-processing macros: `ROCKSDB_LITE` and `IOS_CROSS_COMPILE`. * Run: `TARGET_OS=IOS make static_lib`. When building the project which uses rocksdb iOS library, make sure to define two important pre-processing macros: `ROCKSDB_LITE` and `IOS_CROSS_COMPILE`.
* **Windows**: * **Windows**:
* For building with MS Visual Studio 13 you will need Update 4 installed.
* Read and follow the instructions at CMakeLists.txt * Read and follow the instructions at CMakeLists.txt

@ -33,7 +33,9 @@ quoted_perl_command = $(subst ','\'',$(perl_command))
# with debug level 0. To compile with level 0, run `make shared_lib`, # with debug level 0. To compile with level 0, run `make shared_lib`,
# `make install-shared`, `make static_lib`, `make install-static` or # `make install-shared`, `make static_lib`, `make install-static` or
# `make install` # `make install`
DEBUG_LEVEL=1
# Set the default DEBUG_LEVEL to 1
DEBUG_LEVEL?=1
ifeq ($(MAKECMDGOALS),dbg) ifeq ($(MAKECMDGOALS),dbg)
DEBUG_LEVEL=2 DEBUG_LEVEL=2
@ -230,6 +232,7 @@ TESTS = \
db_tailing_iter_test \ db_tailing_iter_test \
db_universal_compaction_test \ db_universal_compaction_test \
db_wal_test \ db_wal_test \
db_table_properties_test \
block_hash_index_test \ block_hash_index_test \
autovector_test \ autovector_test \
column_family_test \ column_family_test \
@ -550,8 +553,10 @@ check: all
echo "===== Running $$t"; ./$$t || exit 1; done; \ echo "===== Running $$t"; ./$$t || exit 1; done; \
fi fi
rm -rf $(TMPD) rm -rf $(TMPD)
ifeq ($(filter -DROCKSDB_LITE,$(OPT)),)
python tools/ldb_test.py python tools/ldb_test.py
sh tools/rocksdb_dump_test.sh sh tools/rocksdb_dump_test.sh
endif
check_some: $(SUBSET) ldb_tests check_some: $(SUBSET) ldb_tests
for t in $(SUBSET); do echo "===== Running $$t"; ./$$t || exit 1; done for t in $(SUBSET); do echo "===== Running $$t"; ./$$t || exit 1; done
@ -563,12 +568,12 @@ ldb_tests: ldb
crash_test: whitebox_crash_test blackbox_crash_test crash_test: whitebox_crash_test blackbox_crash_test
blackbox_crash_test: db_stress blackbox_crash_test: db_stress
python -u tools/db_crashtest.py -s python -u tools/db_crashtest.py --simple blackbox
python -u tools/db_crashtest.py python -u tools/db_crashtest.py blackbox
whitebox_crash_test: db_stress whitebox_crash_test: db_stress
python -u tools/db_crashtest2.py -s python -u tools/db_crashtest.py --simple whitebox
python -u tools/db_crashtest2.py python -u tools/db_crashtest.py whitebox
asan_check: asan_check:
$(MAKE) clean $(MAKE) clean
@ -739,6 +744,9 @@ db_universal_compaction_test: db/db_universal_compaction_test.o db/db_test_util.
db_wal_test: db/db_wal_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS) db_wal_test: db/db_wal_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
$(AM_LINK) $(AM_LINK)
db_table_properties_test: db/db_table_properties_test.o db/db_test_util.o $(LIBOBJECTS) $(TESTHARNESS)
$(AM_LINK)
log_write_bench: util/log_write_bench.o $(LIBOBJECTS) $(TESTHARNESS) log_write_bench: util/log_write_bench.o $(LIBOBJECTS) $(TESTHARNESS)
$(AM_LINK) $(pg) $(AM_LINK) $(pg)
@ -904,7 +912,7 @@ options_test: util/options_test.o $(LIBOBJECTS) $(TESTHARNESS)
event_logger_test: util/event_logger_test.o $(LIBOBJECTS) $(TESTHARNESS) event_logger_test: util/event_logger_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(AM_LINK) $(AM_LINK)
sst_dump_test: util/sst_dump_test.o $(LIBOBJECTS) $(TESTHARNESS) sst_dump_test: tools/sst_dump_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(AM_LINK) $(AM_LINK)
memenv_test : util/memenv_test.o $(LIBOBJECTS) $(TESTHARNESS) memenv_test : util/memenv_test.o $(LIBOBJECTS) $(TESTHARNESS)
@ -916,7 +924,7 @@ optimistic_transaction_test: utilities/transactions/optimistic_transaction_test.
mock_env_test : util/mock_env_test.o $(LIBOBJECTS) $(TESTHARNESS) mock_env_test : util/mock_env_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(AM_LINK) $(AM_LINK)
manual_compaction_test: util/manual_compaction_test.o $(LIBOBJECTS) $(TESTHARNESS) manual_compaction_test: db/manual_compaction_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(AM_LINK) $(AM_LINK)
filelock_test: util/filelock_test.o $(LIBOBJECTS) $(TESTHARNESS) filelock_test: util/filelock_test.o $(LIBOBJECTS) $(TESTHARNESS)
@ -940,7 +948,7 @@ transaction_test: utilities/transactions/transaction_test.o $(LIBOBJECTS) $(TEST
sst_dump: tools/sst_dump.o $(LIBOBJECTS) sst_dump: tools/sst_dump.o $(LIBOBJECTS)
$(AM_LINK) $(AM_LINK)
ldb_cmd_test: util/ldb_cmd_test.o $(LIBOBJECTS) $(TESTHARNESS) ldb_cmd_test: tools/ldb_cmd_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(AM_LINK) $(AM_LINK)
ldb: tools/ldb.o $(LIBOBJECTS) ldb: tools/ldb.o $(LIBOBJECTS)
@ -1035,19 +1043,22 @@ liblz4.a:
cd lz4-r127/lib && make CFLAGS='-fPIC' all cd lz4-r127/lib && make CFLAGS='-fPIC' all
cp lz4-r127/lib/liblz4.a . cp lz4-r127/lib/liblz4.a .
# A version of each $(LIBOBJECTS) compiled with -fPIC # A version of each $(LIBOBJECTS) compiled with -fPIC and a fixed set of static compression libraries
java_libobjects = $(patsubst %,jl/%,$(LIBOBJECTS)) java_static_libobjects = $(patsubst %,jls/%,$(LIBOBJECTS))
CLEAN_FILES += jl CLEAN_FILES += jls
$(java_libobjects): jl/%.o: %.cc JAVA_STATIC_FLAGS = -DZLIB -DBZIP2 -DSNAPPY -DLZ4
$(AM_V_CC)mkdir -p $(@D) && $(CXX) $(CXXFLAGS) -fPIC -c $< -o $@ $(COVERAGEFLAGS) JAVA_STATIC_INCLUDES = -I./zlib-1.2.8 -I./bzip2-1.0.6 -I./snappy-1.1.1 -I./lz4-r127/lib
rocksdbjavastatic: $(java_libobjects) libz.a libbz2.a libsnappy.a liblz4.a $(java_static_libobjects): jls/%.o: %.cc libz.a libbz2.a libsnappy.a liblz4.a
$(AM_V_CC)mkdir -p $(@D) && $(CXX) $(CXXFLAGS) $(JAVA_STATIC_FLAGS) $(JAVA_STATIC_INCLUDES) -fPIC -c $< -o $@ $(COVERAGEFLAGS)
rocksdbjavastatic: $(java_static_libobjects)
cd java;$(MAKE) javalib; cd java;$(MAKE) javalib;
rm -f ./java/target/$(ROCKSDBJNILIB) rm -f ./java/target/$(ROCKSDBJNILIB)
$(CXX) $(CXXFLAGS) -I./java/. $(JAVA_INCLUDE) -shared -fPIC \ $(CXX) $(CXXFLAGS) -I./java/. $(JAVA_INCLUDE) -shared -fPIC \
-o ./java/target/$(ROCKSDBJNILIB) $(JNI_NATIVE_SOURCES) \ -o ./java/target/$(ROCKSDBJNILIB) $(JNI_NATIVE_SOURCES) \
$(java_libobjects) $(COVERAGEFLAGS) \ $(java_static_libobjects) $(COVERAGEFLAGS) \
libz.a libbz2.a libsnappy.a liblz4.a $(JAVA_STATIC_LDFLAGS) libz.a libbz2.a libsnappy.a liblz4.a $(JAVA_STATIC_LDFLAGS)
cd java/target;strip -S -x $(ROCKSDBJNILIB) cd java/target;strip -S -x $(ROCKSDBJNILIB)
cd java;jar -cf target/$(ROCKSDB_JAR) HISTORY*.md cd java;jar -cf target/$(ROCKSDB_JAR) HISTORY*.md
@ -1059,7 +1070,7 @@ rocksdbjavastatic: $(java_libobjects) libz.a libbz2.a libsnappy.a liblz4.a
rocksdbjavastaticrelease: rocksdbjavastatic rocksdbjavastaticrelease: rocksdbjavastatic
cd java/crossbuild && vagrant destroy -f && vagrant up linux32 && vagrant halt linux32 && vagrant up linux64 && vagrant halt linux64 cd java/crossbuild && vagrant destroy -f && vagrant up linux32 && vagrant halt linux32 && vagrant up linux64 && vagrant halt linux64
cd java;jar -cf target/$(ROCKSDB_JAR_ALL) HISTORY*.md cd java;jar -cf target/$(ROCKSDB_JAR_ALL) HISTORY*.md
cd java;jar -uf target/$(ROCKSDB_JAR_ALL) librocksdbjni-*.so librocksdbjni-*.jnilib cd java/target;jar -uf $(ROCKSDB_JAR_ALL) librocksdbjni-*.so librocksdbjni-*.jnilib
cd java/target/classes;jar -uf ../$(ROCKSDB_JAR_ALL) org/rocksdb/*.class org/rocksdb/util/*.class cd java/target/classes;jar -uf ../$(ROCKSDB_JAR_ALL) org/rocksdb/*.class org/rocksdb/util/*.class
rocksdbjavastaticpublish: rocksdbjavastaticrelease rocksdbjavastaticpublish: rocksdbjavastaticrelease
@ -1070,6 +1081,13 @@ rocksdbjavastaticpublish: rocksdbjavastaticrelease
mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-osx.jar -Dclassifier=osx mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-osx.jar -Dclassifier=osx
mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH).jar mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH).jar
# A version of each $(LIBOBJECTS) compiled with -fPIC
java_libobjects = $(patsubst %,jl/%,$(LIBOBJECTS))
CLEAN_FILES += jl
$(java_libobjects): jl/%.o: %.cc
$(AM_V_CC)mkdir -p $(@D) && $(CXX) $(CXXFLAGS) -fPIC -c $< -o $@ $(COVERAGEFLAGS)
rocksdbjava: $(java_libobjects) rocksdbjava: $(java_libobjects)
$(AM_V_GEN)cd java;$(MAKE) javalib; $(AM_V_GEN)cd java;$(MAKE) javalib;
$(AM_V_at)rm -f ./java/target/$(ROCKSDBJNILIB) $(AM_V_at)rm -f ./java/target/$(ROCKSDBJNILIB)

@ -388,6 +388,8 @@ TSAN_CRASH_TEST_COMMANDS="[
} }
]" ]"
TSAN_CRASH_TEST_COMMANDS=$DISABLE_COMMANDS
# #
# RocksDB format compatible # RocksDB format compatible
# #

@ -26,6 +26,7 @@
#include "rocksdb/options.h" #include "rocksdb/options.h"
#include "rocksdb/table.h" #include "rocksdb/table.h"
#include "table/block_based_table_builder.h" #include "table/block_based_table_builder.h"
#include "table/internal_iterator.h"
#include "util/file_reader_writer.h" #include "util/file_reader_writer.h"
#include "util/iostats_context_imp.h" #include "util/iostats_context_imp.h"
#include "util/stop_watch.h" #include "util/stop_watch.h"
@ -52,8 +53,9 @@ TableBuilder* NewTableBuilder(
Status BuildTable( Status BuildTable(
const std::string& dbname, Env* env, const ImmutableCFOptions& ioptions, const std::string& dbname, Env* env, const ImmutableCFOptions& ioptions,
const EnvOptions& env_options, TableCache* table_cache, Iterator* iter, const EnvOptions& env_options, TableCache* table_cache,
FileMetaData* meta, const InternalKeyComparator& internal_comparator, InternalIterator* iter, FileMetaData* meta,
const InternalKeyComparator& internal_comparator,
const std::vector<std::unique_ptr<IntTblPropCollectorFactory>>* const std::vector<std::unique_ptr<IntTblPropCollectorFactory>>*
int_tbl_prop_collector_factories, int_tbl_prop_collector_factories,
uint32_t column_family_id, std::vector<SequenceNumber> snapshots, uint32_t column_family_id, std::vector<SequenceNumber> snapshots,
@ -74,7 +76,7 @@ Status BuildTable(
unique_ptr<WritableFileWriter> file_writer; unique_ptr<WritableFileWriter> file_writer;
{ {
unique_ptr<WritableFile> file; unique_ptr<WritableFile> file;
s = env->NewWritableFile(fname, &file, env_options); s = NewWritableFile(env, fname, &file, env_options);
if (!s.ok()) { if (!s.ok()) {
return s; return s;
} }
@ -141,7 +143,7 @@ Status BuildTable(
if (s.ok() && !empty) { if (s.ok() && !empty) {
// Verify that the table is usable // Verify that the table is usable
std::unique_ptr<Iterator> it(table_cache->NewIterator( std::unique_ptr<InternalIterator> it(table_cache->NewIterator(
ReadOptions(), env_options, internal_comparator, meta->fd, nullptr, ReadOptions(), env_options, internal_comparator, meta->fd, nullptr,
(internal_stats == nullptr) ? nullptr (internal_stats == nullptr) ? nullptr
: internal_stats->GetFileReadHist(0), : internal_stats->GetFileReadHist(0),

@ -31,6 +31,7 @@ class VersionEdit;
class TableBuilder; class TableBuilder;
class WritableFileWriter; class WritableFileWriter;
class InternalStats; class InternalStats;
class InternalIterator;
TableBuilder* NewTableBuilder( TableBuilder* NewTableBuilder(
const ImmutableCFOptions& options, const ImmutableCFOptions& options,
@ -49,8 +50,9 @@ TableBuilder* NewTableBuilder(
// zero, and no Table file will be produced. // zero, and no Table file will be produced.
extern Status BuildTable( extern Status BuildTable(
const std::string& dbname, Env* env, const ImmutableCFOptions& options, const std::string& dbname, Env* env, const ImmutableCFOptions& options,
const EnvOptions& env_options, TableCache* table_cache, Iterator* iter, const EnvOptions& env_options, TableCache* table_cache,
FileMetaData* meta, const InternalKeyComparator& internal_comparator, InternalIterator* iter, FileMetaData* meta,
const InternalKeyComparator& internal_comparator,
const std::vector<std::unique_ptr<IntTblPropCollectorFactory>>* const std::vector<std::unique_ptr<IntTblPropCollectorFactory>>*
int_tbl_prop_collector_factories, int_tbl_prop_collector_factories,
uint32_t column_family_id, std::vector<SequenceNumber> snapshots, uint32_t column_family_id, std::vector<SequenceNumber> snapshots,

@ -27,9 +27,9 @@
#include "db/version_set.h" #include "db/version_set.h"
#include "db/write_controller.h" #include "db/write_controller.h"
#include "db/writebuffer.h" #include "db/writebuffer.h"
#include "memtable/hash_skiplist_rep.h"
#include "util/autovector.h" #include "util/autovector.h"
#include "util/compression.h" #include "util/compression.h"
#include "util/hash_skiplist_rep.h"
#include "util/options_helper.h" #include "util/options_helper.h"
#include "util/thread_status_util.h" #include "util/thread_status_util.h"
#include "util/xfunc.h" #include "util/xfunc.h"

@ -6,11 +6,12 @@
// of patent rights can be found in the PATENTS file in the same directory. // of patent rights can be found in the PATENTS file in the same directory.
#include "db/compaction_iterator.h" #include "db/compaction_iterator.h"
#include "table/internal_iterator.h"
namespace rocksdb { namespace rocksdb {
CompactionIterator::CompactionIterator( CompactionIterator::CompactionIterator(
Iterator* input, const Comparator* cmp, MergeHelper* merge_helper, InternalIterator* input, const Comparator* cmp, MergeHelper* merge_helper,
SequenceNumber last_sequence, std::vector<SequenceNumber>* snapshots, SequenceNumber last_sequence, std::vector<SequenceNumber>* snapshots,
Env* env, bool expect_valid_internal_key, Compaction* compaction, Env* env, bool expect_valid_internal_key, Compaction* compaction,
const CompactionFilter* compaction_filter, LogBuffer* log_buffer) const CompactionFilter* compaction_filter, LogBuffer* log_buffer)

@ -37,7 +37,7 @@ struct CompactionIteratorStats {
class CompactionIterator { class CompactionIterator {
public: public:
CompactionIterator(Iterator* input, const Comparator* cmp, CompactionIterator(InternalIterator* input, const Comparator* cmp,
MergeHelper* merge_helper, SequenceNumber last_sequence, MergeHelper* merge_helper, SequenceNumber last_sequence,
std::vector<SequenceNumber>* snapshots, Env* env, std::vector<SequenceNumber>* snapshots, Env* env,
bool expect_valid_internal_key, bool expect_valid_internal_key,
@ -84,7 +84,7 @@ class CompactionIterator {
inline SequenceNumber findEarliestVisibleSnapshot( inline SequenceNumber findEarliestVisibleSnapshot(
SequenceNumber in, SequenceNumber* prev_snapshot); SequenceNumber in, SequenceNumber* prev_snapshot);
Iterator* input_; InternalIterator* input_;
const Comparator* cmp_; const Comparator* cmp_;
MergeHelper* merge_helper_; MergeHelper* merge_helper_;
const std::vector<SequenceNumber>* snapshots_; const std::vector<SequenceNumber>* snapshots_;

@ -585,7 +585,7 @@ Status CompactionJob::Install(const MutableCFOptions& mutable_cf_options,
void CompactionJob::ProcessKeyValueCompaction(SubcompactionState* sub_compact) { void CompactionJob::ProcessKeyValueCompaction(SubcompactionState* sub_compact) {
assert(sub_compact != nullptr); assert(sub_compact != nullptr);
std::unique_ptr<Iterator> input( std::unique_ptr<InternalIterator> input(
versions_->MakeInputIterator(sub_compact->compaction)); versions_->MakeInputIterator(sub_compact->compaction));
AutoThreadOperationStageUpdater stage_updater( AutoThreadOperationStageUpdater stage_updater(
@ -601,10 +601,10 @@ void CompactionJob::ProcessKeyValueCompaction(SubcompactionState* sub_compact) {
if (measure_io_stats_) { if (measure_io_stats_) {
prev_perf_level = GetPerfLevel(); prev_perf_level = GetPerfLevel();
SetPerfLevel(PerfLevel::kEnableTime); SetPerfLevel(PerfLevel::kEnableTime);
prev_write_nanos = iostats_context.write_nanos; prev_write_nanos = IOSTATS(write_nanos);
prev_fsync_nanos = iostats_context.fsync_nanos; prev_fsync_nanos = IOSTATS(fsync_nanos);
prev_range_sync_nanos = iostats_context.range_sync_nanos; prev_range_sync_nanos = IOSTATS(range_sync_nanos);
prev_prepare_write_nanos = iostats_context.prepare_write_nanos; prev_prepare_write_nanos = IOSTATS(prepare_write_nanos);
} }
ColumnFamilyData* cfd = sub_compact->compaction->column_family_data(); ColumnFamilyData* cfd = sub_compact->compaction->column_family_data();
@ -728,13 +728,13 @@ void CompactionJob::ProcessKeyValueCompaction(SubcompactionState* sub_compact) {
if (measure_io_stats_) { if (measure_io_stats_) {
sub_compact->compaction_job_stats.file_write_nanos += sub_compact->compaction_job_stats.file_write_nanos +=
iostats_context.write_nanos - prev_write_nanos; IOSTATS(write_nanos) - prev_write_nanos;
sub_compact->compaction_job_stats.file_fsync_nanos += sub_compact->compaction_job_stats.file_fsync_nanos +=
iostats_context.fsync_nanos - prev_fsync_nanos; IOSTATS(fsync_nanos) - prev_fsync_nanos;
sub_compact->compaction_job_stats.file_range_sync_nanos += sub_compact->compaction_job_stats.file_range_sync_nanos +=
iostats_context.range_sync_nanos - prev_range_sync_nanos; IOSTATS(range_sync_nanos) - prev_range_sync_nanos;
sub_compact->compaction_job_stats.file_prepare_write_nanos += sub_compact->compaction_job_stats.file_prepare_write_nanos +=
iostats_context.prepare_write_nanos - prev_prepare_write_nanos; IOSTATS(prepare_write_nanos) - prev_prepare_write_nanos;
if (prev_perf_level != PerfLevel::kEnableTime) { if (prev_perf_level != PerfLevel::kEnableTime) {
SetPerfLevel(prev_perf_level); SetPerfLevel(prev_perf_level);
} }
@ -811,7 +811,7 @@ Status CompactionJob::FinishCompactionOutputFile(
if (s.ok() && current_entries > 0) { if (s.ok() && current_entries > 0) {
// Verify that the table is usable // Verify that the table is usable
ColumnFamilyData* cfd = sub_compact->compaction->column_family_data(); ColumnFamilyData* cfd = sub_compact->compaction->column_family_data();
Iterator* iter = cfd->table_cache()->NewIterator( InternalIterator* iter = cfd->table_cache()->NewIterator(
ReadOptions(), env_options_, cfd->internal_comparator(), meta->fd, ReadOptions(), env_options_, cfd->internal_comparator(), meta->fd,
nullptr, cfd->internal_stats()->GetFileReadHist( nullptr, cfd->internal_stats()->GetFileReadHist(
compact_->compaction->output_level()), compact_->compaction->output_level()),
@ -911,7 +911,7 @@ Status CompactionJob::OpenCompactionOutputFile(
unique_ptr<WritableFile> writable_file; unique_ptr<WritableFile> writable_file;
std::string fname = TableFileName(db_options_.db_paths, file_number, std::string fname = TableFileName(db_options_.db_paths, file_number,
sub_compact->compaction->output_path_id()); sub_compact->compaction->output_path_id());
Status s = env_->NewWritableFile(fname, &writable_file, env_options_); Status s = NewWritableFile(env_, fname, &writable_file, env_options_);
if (!s.ok()) { if (!s.ok()) {
Log(InfoLogLevel::ERROR_LEVEL, db_options_.info_log, Log(InfoLogLevel::ERROR_LEVEL, db_options_.info_log,
"[%s] [JOB %d] OpenCompactionOutputFiles for table #%" PRIu64 "[%s] [JOB %d] OpenCompactionOutputFiles for table #%" PRIu64

@ -35,9 +35,9 @@
#include "rocksdb/env.h" #include "rocksdb/env.h"
#include "rocksdb/memtablerep.h" #include "rocksdb/memtablerep.h"
#include "rocksdb/transaction_log.h" #include "rocksdb/transaction_log.h"
#include "table/scoped_arena_iterator.h"
#include "util/autovector.h" #include "util/autovector.h"
#include "util/event_logger.h" #include "util/event_logger.h"
#include "util/scoped_arena_iterator.h"
#include "util/stop_watch.h" #include "util/stop_watch.h"
#include "util/thread_local.h" #include "util/thread_local.h"

@ -27,6 +27,7 @@
#include "db/job_context.h" #include "db/job_context.h"
#include "db/version_set.h" #include "db/version_set.h"
#include "db/write_batch_internal.h" #include "db/write_batch_internal.h"
#include "memtable/hash_linklist_rep.h"
#include "port/stack_trace.h" #include "port/stack_trace.h"
#include "rocksdb/cache.h" #include "rocksdb/cache.h"
#include "rocksdb/compaction_filter.h" #include "rocksdb/compaction_filter.h"
@ -47,14 +48,13 @@
#include "table/block_based_table_factory.h" #include "table/block_based_table_factory.h"
#include "table/mock_table.h" #include "table/mock_table.h"
#include "table/plain_table_factory.h" #include "table/plain_table_factory.h"
#include "table/scoped_arena_iterator.h"
#include "util/compression.h" #include "util/compression.h"
#include "util/hash.h" #include "util/hash.h"
#include "util/hash_linklist_rep.h"
#include "util/logging.h" #include "util/logging.h"
#include "util/mock_env.h" #include "util/mock_env.h"
#include "util/mutexlock.h" #include "util/mutexlock.h"
#include "util/rate_limiter.h" #include "util/rate_limiter.h"
#include "util/scoped_arena_iterator.h"
#include "util/statistics.h" #include "util/statistics.h"
#include "util/string_util.h" #include "util/string_util.h"
#include "util/sync_point.h" #include "util/sync_point.h"

@ -3,6 +3,8 @@
// LICENSE file in the root directory of this source tree. An additional grant // 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. // of patent rights can be found in the PATENTS file in the same directory.
#ifndef ROCKSDB_LITE
#include <algorithm> #include <algorithm>
#include <map> #include <map>
#include <string> #include <string>
@ -695,3 +697,14 @@ int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
} }
#else
#include <stdio.h>
int main(int argc, char** argv) {
fprintf(stderr,
"SKIPPED as CompactionJobStats is not supported in ROCKSDB_LITE\n");
return 0;
}
#endif // ROCKSDB_LITE

@ -7,10 +7,11 @@
#include <map> #include <map>
#include <string> #include <string>
#include "memtable/stl_wrappers.h"
#include "rocksdb/db.h" #include "rocksdb/db.h"
#include "rocksdb/env.h" #include "rocksdb/env.h"
#include "util/hash.h" #include "util/hash.h"
#include "util/stl_wrappers.h" #include "util/kv_map.h"
#include "util/string_util.h" #include "util/string_util.h"
#include "util/testharness.h" #include "util/testharness.h"
#include "util/testutil.h" #include "util/testutil.h"

@ -486,6 +486,7 @@ DEFINE_int32(deletepercent, 2, "Percentage of deletes out of reads/writes/"
DEFINE_uint64(delete_obsolete_files_period_micros, 0, DEFINE_uint64(delete_obsolete_files_period_micros, 0,
"Ignored. Left here for backward compatibility"); "Ignored. Left here for backward compatibility");
#ifndef ROCKSDB_LITE
DEFINE_bool(optimistic_transaction_db, false, DEFINE_bool(optimistic_transaction_db, false,
"Open a OptimisticTransactionDB instance. " "Open a OptimisticTransactionDB instance. "
"Required for randomtransaction benchmark."); "Required for randomtransaction benchmark.");
@ -509,6 +510,7 @@ DEFINE_int32(transaction_sleep, 0,
DEFINE_uint64(transaction_lock_timeout, 100, DEFINE_uint64(transaction_lock_timeout, 100,
"If using a transaction_db, specifies the lock wait timeout in" "If using a transaction_db, specifies the lock wait timeout in"
" milliseconds before failing a transaction waiting on a lock"); " milliseconds before failing a transaction waiting on a lock");
#endif // ROCKSDB_LITE
DEFINE_bool(compaction_measure_io_stats, false, DEFINE_bool(compaction_measure_io_stats, false,
"Measure times spents on I/Os while in compactions. "); "Measure times spents on I/Os while in compactions. ");
@ -645,7 +647,9 @@ DEFINE_int32(max_grandparent_overlap_factor, 10, "Control maximum bytes of "
"overlaps in grandparent (i.e., level+2) before we stop building a" "overlaps in grandparent (i.e., level+2) before we stop building a"
" single file in a level->level+1 compaction."); " single file in a level->level+1 compaction.");
#ifndef ROCKSDB_LITE
DEFINE_bool(readonly, false, "Run read only benchmarks."); DEFINE_bool(readonly, false, "Run read only benchmarks.");
#endif // ROCKSDB_LITE
DEFINE_bool(disable_auto_compactions, false, "Do not auto trigger compactions"); DEFINE_bool(disable_auto_compactions, false, "Do not auto trigger compactions");
@ -983,7 +987,9 @@ static void AppendWithSpace(std::string* str, Slice msg) {
struct DBWithColumnFamilies { struct DBWithColumnFamilies {
std::vector<ColumnFamilyHandle*> cfh; std::vector<ColumnFamilyHandle*> cfh;
DB* db; DB* db;
#ifndef ROCKSDB_LITE
OptimisticTransactionDB* opt_txn_db; OptimisticTransactionDB* opt_txn_db;
#endif // ROCKSDB_LITE
std::atomic<size_t> num_created; // Need to be updated after all the std::atomic<size_t> num_created; // Need to be updated after all the
// new entries in cfh are set. // new entries in cfh are set.
size_t num_hot; // Number of column families to be queried at each moment. size_t num_hot; // Number of column families to be queried at each moment.
@ -991,7 +997,12 @@ struct DBWithColumnFamilies {
// Column families will be created and used to be queried. // Column families will be created and used to be queried.
port::Mutex create_cf_mutex; // Only one thread can execute CreateNewCf() port::Mutex create_cf_mutex; // Only one thread can execute CreateNewCf()
DBWithColumnFamilies() : db(nullptr), opt_txn_db(nullptr) { DBWithColumnFamilies()
: db(nullptr)
#ifndef ROCKSDB_LITE
, opt_txn_db(nullptr)
#endif // ROCKSDB_LITE
{
cfh.clear(); cfh.clear();
num_created = 0; num_created = 0;
num_hot = 0; num_hot = 0;
@ -1000,7 +1011,9 @@ struct DBWithColumnFamilies {
DBWithColumnFamilies(const DBWithColumnFamilies& other) DBWithColumnFamilies(const DBWithColumnFamilies& other)
: cfh(other.cfh), : cfh(other.cfh),
db(other.db), db(other.db),
#ifndef ROCKSDB_LITE
opt_txn_db(other.opt_txn_db), opt_txn_db(other.opt_txn_db),
#endif // ROCKSDB_LITE
num_created(other.num_created.load()), num_created(other.num_created.load()),
num_hot(other.num_hot) {} num_hot(other.num_hot) {}
@ -1008,13 +1021,18 @@ struct DBWithColumnFamilies {
std::for_each(cfh.begin(), cfh.end(), std::for_each(cfh.begin(), cfh.end(),
[](ColumnFamilyHandle* cfhi) { delete cfhi; }); [](ColumnFamilyHandle* cfhi) { delete cfhi; });
cfh.clear(); cfh.clear();
#ifndef ROCKSDB_LITE
if (opt_txn_db) { if (opt_txn_db) {
delete opt_txn_db; delete opt_txn_db;
opt_txn_db = nullptr; opt_txn_db = nullptr;
} else { } else {
delete db; delete db;
db = nullptr;
} }
#else
delete db;
db = nullptr; db = nullptr;
#endif // ROCKSDB_LITE
} }
ColumnFamilyHandle* GetCfh(int64_t rand_num) { ColumnFamilyHandle* GetCfh(int64_t rand_num) {
@ -1940,9 +1958,11 @@ class Benchmark {
method = &Benchmark::Compress; method = &Benchmark::Compress;
} else if (name == "uncompress") { } else if (name == "uncompress") {
method = &Benchmark::Uncompress; method = &Benchmark::Uncompress;
#ifndef ROCKSDB_LITE
} else if (name == "randomtransaction") { } else if (name == "randomtransaction") {
method = &Benchmark::RandomTransaction; method = &Benchmark::RandomTransaction;
post_process_method = &Benchmark::RandomTransactionVerify; post_process_method = &Benchmark::RandomTransactionVerify;
#endif // ROCKSDB_LITE
} else if (name == "randomreplacekeys") { } else if (name == "randomreplacekeys") {
fresh_db = true; fresh_db = true;
method = &Benchmark::RandomReplaceKeys; method = &Benchmark::RandomReplaceKeys;
@ -2518,10 +2538,12 @@ class Benchmark {
NewGenericRateLimiter(FLAGS_rate_limiter_bytes_per_sec)); NewGenericRateLimiter(FLAGS_rate_limiter_bytes_per_sec));
} }
#ifndef ROCKSDB_LITE
if (FLAGS_readonly && FLAGS_transaction_db) { if (FLAGS_readonly && FLAGS_transaction_db) {
fprintf(stderr, "Cannot use readonly flag with transaction_db\n"); fprintf(stderr, "Cannot use readonly flag with transaction_db\n");
exit(1); exit(1);
} }
#endif // ROCKSDB_LITE
if (FLAGS_num_multi_db <= 1) { if (FLAGS_num_multi_db <= 1) {
OpenDb(options, FLAGS_db, &db_); OpenDb(options, FLAGS_db, &db_);
@ -2554,6 +2576,7 @@ class Benchmark {
column_families.push_back(ColumnFamilyDescriptor( column_families.push_back(ColumnFamilyDescriptor(
ColumnFamilyName(i), ColumnFamilyOptions(options))); ColumnFamilyName(i), ColumnFamilyOptions(options)));
} }
#ifndef ROCKSDB_LITE
if (FLAGS_readonly) { if (FLAGS_readonly) {
s = DB::OpenForReadOnly(options, db_name, column_families, s = DB::OpenForReadOnly(options, db_name, column_families,
&db->cfh, &db->db); &db->cfh, &db->db);
@ -2574,9 +2597,13 @@ class Benchmark {
} else { } else {
s = DB::Open(options, db_name, column_families, &db->cfh, &db->db); s = DB::Open(options, db_name, column_families, &db->cfh, &db->db);
} }
#else
s = DB::Open(options, db_name, column_families, &db->cfh, &db->db);
#endif // ROCKSDB_LITE
db->cfh.resize(FLAGS_num_column_families); db->cfh.resize(FLAGS_num_column_families);
db->num_created = num_hot; db->num_created = num_hot;
db->num_hot = num_hot; db->num_hot = num_hot;
#ifndef ROCKSDB_LITE
} else if (FLAGS_readonly) { } else if (FLAGS_readonly) {
s = DB::OpenForReadOnly(options, db_name, &db->db); s = DB::OpenForReadOnly(options, db_name, &db->db);
} else if (FLAGS_optimistic_transaction_db) { } else if (FLAGS_optimistic_transaction_db) {
@ -2591,7 +2618,7 @@ class Benchmark {
if (s.ok()) { if (s.ok()) {
db->db = ptr; db->db = ptr;
} }
#endif // ROCKSDB_LITE
} else { } else {
s = DB::Open(options, db_name, &db->db); s = DB::Open(options, db_name, &db->db);
} }
@ -3636,6 +3663,7 @@ class Benchmark {
} }
} }
#ifndef ROCKSDB_LITE
// This benchmark stress tests Transactions. For a given --duration (or // This benchmark stress tests Transactions. For a given --duration (or
// total number of --writes, a Transaction will perform a read-modify-write // total number of --writes, a Transaction will perform a read-modify-write
// to increment the value of a key in each of N(--transaction-sets) sets of // to increment the value of a key in each of N(--transaction-sets) sets of
@ -3868,6 +3896,7 @@ class Benchmark {
fprintf(stdout, "RandomTransactionVerify Success!\n"); fprintf(stdout, "RandomTransactionVerify Success!\n");
} }
#endif // ROCKSDB_LITE
// Writes and deletes random keys without overwriting keys. // Writes and deletes random keys without overwriting keys.
// //

@ -186,6 +186,7 @@ class ChangeFilterFactory : public CompactionFilterFactory {
virtual const char* Name() const override { return "ChangeFilterFactory"; } virtual const char* Name() const override { return "ChangeFilterFactory"; }
}; };
#ifndef ROCKSDB_LITE
TEST_F(DBTestCompactionFilter, CompactionFilter) { TEST_F(DBTestCompactionFilter, CompactionFilter) {
Options options = CurrentOptions(); Options options = CurrentOptions();
options.max_open_files = -1; options.max_open_files = -1;
@ -228,7 +229,7 @@ TEST_F(DBTestCompactionFilter, CompactionFilter) {
Arena arena; Arena arena;
{ {
ScopedArenaIterator iter( ScopedArenaIterator iter(
dbfull()->TEST_NewInternalIterator(&arena, handles_[1])); dbfull()->NewInternalIterator(&arena, handles_[1]));
iter->SeekToFirst(); iter->SeekToFirst();
ASSERT_OK(iter->status()); ASSERT_OK(iter->status());
while (iter->Valid()) { while (iter->Valid()) {
@ -316,7 +317,7 @@ TEST_F(DBTestCompactionFilter, CompactionFilter) {
count = 0; count = 0;
{ {
ScopedArenaIterator iter( ScopedArenaIterator iter(
dbfull()->TEST_NewInternalIterator(&arena, handles_[1])); dbfull()->NewInternalIterator(&arena, handles_[1]));
iter->SeekToFirst(); iter->SeekToFirst();
ASSERT_OK(iter->status()); ASSERT_OK(iter->status());
while (iter->Valid()) { while (iter->Valid()) {
@ -362,6 +363,7 @@ TEST_F(DBTestCompactionFilter, CompactionFilterDeletesAll) {
delete itr; delete itr;
} }
#endif // ROCKSDB_LITE
TEST_F(DBTestCompactionFilter, CompactionFilterWithValueChange) { TEST_F(DBTestCompactionFilter, CompactionFilterWithValueChange) {
do { do {
@ -493,6 +495,7 @@ TEST_F(DBTestCompactionFilter, CompactionFilterWithMergeOperator) {
ASSERT_EQ(newvalue, four); ASSERT_EQ(newvalue, four);
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTestCompactionFilter, CompactionFilterContextManual) { TEST_F(DBTestCompactionFilter, CompactionFilterContextManual) {
KeepFilterFactory* filter = new KeepFilterFactory(true, true); KeepFilterFactory* filter = new KeepFilterFactory(true, true);
@ -533,7 +536,7 @@ TEST_F(DBTestCompactionFilter, CompactionFilterContextManual) {
int count = 0; int count = 0;
int total = 0; int total = 0;
Arena arena; Arena arena;
ScopedArenaIterator iter(dbfull()->TEST_NewInternalIterator(&arena)); ScopedArenaIterator iter(dbfull()->NewInternalIterator(&arena));
iter->SeekToFirst(); iter->SeekToFirst();
ASSERT_OK(iter->status()); ASSERT_OK(iter->status());
while (iter->Valid()) { while (iter->Valid()) {
@ -550,6 +553,7 @@ TEST_F(DBTestCompactionFilter, CompactionFilterContextManual) {
ASSERT_EQ(count, 1); ASSERT_EQ(count, 1);
} }
} }
#endif // ROCKSDB_LITE
TEST_F(DBTestCompactionFilter, CompactionFilterContextCfId) { TEST_F(DBTestCompactionFilter, CompactionFilterContextCfId) {
KeepFilterFactory* filter = new KeepFilterFactory(false, true); KeepFilterFactory* filter = new KeepFilterFactory(false, true);
@ -580,6 +584,7 @@ TEST_F(DBTestCompactionFilter, CompactionFilterContextCfId) {
ASSERT_TRUE(filter->compaction_filter_created()); ASSERT_TRUE(filter->compaction_filter_created());
} }
#ifndef ROCKSDB_LITE
// Compaction filters should only be applied to records that are newer than the // Compaction filters should only be applied to records that are newer than the
// latest snapshot. This test inserts records and applies a delete filter. // latest snapshot. This test inserts records and applies a delete filter.
TEST_F(DBTestCompactionFilter, CompactionFilterSnapshot) { TEST_F(DBTestCompactionFilter, CompactionFilterSnapshot) {
@ -615,6 +620,7 @@ TEST_F(DBTestCompactionFilter, CompactionFilterSnapshot) {
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr)); ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
ASSERT_EQ(0U, CountLiveFiles()); ASSERT_EQ(0U, CountLiveFiles());
} }
#endif // ROCKSDB_LITE
} // namespace rocksdb } // namespace rocksdb

@ -14,8 +14,7 @@
namespace rocksdb { namespace rocksdb {
// SYNC_POINT is not supported in released Windows mode. // SYNC_POINT is not supported in released Windows mode.
#if !(defined NDEBUG) || !defined(OS_WIN) #if (!(defined NDEBUG) || !defined(OS_WIN)) && !defined(ROCKSDB_LITE)
class DBCompactionTest : public DBTestBase { class DBCompactionTest : public DBTestBase {
public: public:
@ -1844,11 +1843,11 @@ TEST_P(DBCompactionTestWithParam, ForceBottommostLevelCompaction) {
INSTANTIATE_TEST_CASE_P(DBCompactionTestWithParam, DBCompactionTestWithParam, INSTANTIATE_TEST_CASE_P(DBCompactionTestWithParam, DBCompactionTestWithParam,
::testing::Values(1, 4)); ::testing::Values(1, 4));
#endif // !(defined NDEBUG) || !defined(OS_WIN) #endif // (!(defined NDEBUG) || !defined(OS_WIN)) && !defined(ROCKSDB_LITE)
} // namespace rocksdb } // namespace rocksdb
int main(int argc, char** argv) { int main(int argc, char** argv) {
#if !(defined NDEBUG) || !defined(OS_WIN) #if (!(defined NDEBUG) || !defined(OS_WIN)) && !defined(ROCKSDB_LITE)
rocksdb::port::InstallStackTraceHandler(); rocksdb::port::InstallStackTraceHandler();
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();

@ -10,7 +10,7 @@
// Introduction of SyncPoint effectively disabled building and running this test // Introduction of SyncPoint effectively disabled building and running this test
// in Release build. // in Release build.
// which is a pity, it is a good test // which is a pity, it is a good test
#if !(defined NDEBUG) || !defined(OS_WIN) #if (!(defined NDEBUG) || !defined(OS_WIN)) && !defined(ROCKSDB_LITE)
#include "db/db_test_util.h" #include "db/db_test_util.h"
#include "port/stack_trace.h" #include "port/stack_trace.h"
@ -484,10 +484,10 @@ TEST_F(DBTestDynamicLevel, MigrateToDynamicLevelMaxBytesBase) {
} }
} // namespace rocksdb } // namespace rocksdb
#endif // !(defined NDEBUG) || !defined(OS_WIN) #endif // (!(defined NDEBUG) || !defined(OS_WIN)) && !defined(ROCKSDB_LITE)
int main(int argc, char** argv) { int main(int argc, char** argv) {
#if !(defined NDEBUG) || !defined(OS_WIN) #if (!(defined NDEBUG) || !defined(OS_WIN)) && !defined(ROCKSDB_LITE)
rocksdb::port::InstallStackTraceHandler(); rocksdb::port::InstallStackTraceHandler();
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();

@ -50,6 +50,8 @@
#include "db/write_batch_internal.h" #include "db/write_batch_internal.h"
#include "db/write_callback.h" #include "db/write_callback.h"
#include "db/writebuffer.h" #include "db/writebuffer.h"
#include "memtable/hash_linklist_rep.h"
#include "memtable/hash_skiplist_rep.h"
#include "port/likely.h" #include "port/likely.h"
#include "port/port.h" #include "port/port.h"
#include "rocksdb/cache.h" #include "rocksdb/cache.h"
@ -78,8 +80,6 @@
#include "util/db_info_dumper.h" #include "util/db_info_dumper.h"
#include "util/file_reader_writer.h" #include "util/file_reader_writer.h"
#include "util/file_util.h" #include "util/file_util.h"
#include "util/hash_linklist_rep.h"
#include "util/hash_skiplist_rep.h"
#include "util/iostats_context_imp.h" #include "util/iostats_context_imp.h"
#include "util/log_buffer.h" #include "util/log_buffer.h"
#include "util/logging.h" #include "util/logging.h"
@ -246,8 +246,10 @@ DBImpl::DBImpl(const DBOptions& options, const std::string& dbname)
unscheduled_flushes_(0), unscheduled_flushes_(0),
unscheduled_compactions_(0), unscheduled_compactions_(0),
bg_compaction_scheduled_(0), bg_compaction_scheduled_(0),
num_running_compactions_(0),
bg_manual_only_(0), bg_manual_only_(0),
bg_flush_scheduled_(0), bg_flush_scheduled_(0),
num_running_flushes_(0),
manual_compaction_(nullptr), manual_compaction_(nullptr),
disable_delete_obsolete_files_(0), disable_delete_obsolete_files_(0),
delete_obsolete_files_next_run_( delete_obsolete_files_next_run_(
@ -408,7 +410,7 @@ Status DBImpl::NewDB() {
{ {
unique_ptr<WritableFile> file; unique_ptr<WritableFile> file;
EnvOptions env_options = env_->OptimizeForManifestWrite(env_options_); EnvOptions env_options = env_->OptimizeForManifestWrite(env_options_);
s = env_->NewWritableFile(manifest, &file, env_options); s = NewWritableFile(env_, manifest, &file, env_options);
if (!s.ok()) { if (!s.ok()) {
return s; return s;
} }
@ -2236,6 +2238,23 @@ Status DBImpl::RunManualCompaction(ColumnFamilyData* cfd, int input_level,
return manual.status; return manual.status;
} }
InternalIterator* DBImpl::NewInternalIterator(
Arena* arena, ColumnFamilyHandle* column_family) {
ColumnFamilyData* cfd;
if (column_family == nullptr) {
cfd = default_cf_handle_->cfd();
} else {
auto cfh = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family);
cfd = cfh->cfd();
}
mutex_.Lock();
SuperVersion* super_version = cfd->GetSuperVersion()->Ref();
mutex_.Unlock();
ReadOptions roptions;
return NewInternalIterator(roptions, cfd, super_version, arena);
}
Status DBImpl::FlushMemTable(ColumnFamilyData* cfd, Status DBImpl::FlushMemTable(ColumnFamilyData* cfd,
const FlushOptions& flush_options) { const FlushOptions& flush_options) {
Status s; Status s;
@ -2455,6 +2474,7 @@ void DBImpl::BackgroundCallFlush() {
LogBuffer log_buffer(InfoLogLevel::INFO_LEVEL, db_options_.info_log.get()); LogBuffer log_buffer(InfoLogLevel::INFO_LEVEL, db_options_.info_log.get());
{ {
InstrumentedMutexLock l(&mutex_); InstrumentedMutexLock l(&mutex_);
num_running_flushes_++;
auto pending_outputs_inserted_elem = auto pending_outputs_inserted_elem =
CaptureCurrentFileNumberInPendingOutputs(); CaptureCurrentFileNumberInPendingOutputs();
@ -2500,6 +2520,8 @@ void DBImpl::BackgroundCallFlush() {
mutex_.Lock(); mutex_.Lock();
} }
assert(num_running_flushes_ > 0);
num_running_flushes_--;
bg_flush_scheduled_--; bg_flush_scheduled_--;
// See if there's more work to be done // See if there's more work to be done
MaybeScheduleFlushOrCompaction(); MaybeScheduleFlushOrCompaction();
@ -2520,6 +2542,7 @@ void DBImpl::BackgroundCallCompaction() {
LogBuffer log_buffer(InfoLogLevel::INFO_LEVEL, db_options_.info_log.get()); LogBuffer log_buffer(InfoLogLevel::INFO_LEVEL, db_options_.info_log.get());
{ {
InstrumentedMutexLock l(&mutex_); InstrumentedMutexLock l(&mutex_);
num_running_compactions_++;
auto pending_outputs_inserted_elem = auto pending_outputs_inserted_elem =
CaptureCurrentFileNumberInPendingOutputs(); CaptureCurrentFileNumberInPendingOutputs();
@ -2568,6 +2591,8 @@ void DBImpl::BackgroundCallCompaction() {
mutex_.Lock(); mutex_.Lock();
} }
assert(num_running_compactions_ > 0);
num_running_compactions_--;
bg_compaction_scheduled_--; bg_compaction_scheduled_--;
versions_->GetColumnFamilySet()->FreeDeadColumnFamilies(); versions_->GetColumnFamilySet()->FreeDeadColumnFamilies();
@ -2913,11 +2938,11 @@ static void CleanupIteratorState(void* arg1, void* arg2) {
} }
} // namespace } // namespace
Iterator* DBImpl::NewInternalIterator(const ReadOptions& read_options, InternalIterator* DBImpl::NewInternalIterator(const ReadOptions& read_options,
ColumnFamilyData* cfd, ColumnFamilyData* cfd,
SuperVersion* super_version, SuperVersion* super_version,
Arena* arena) { Arena* arena) {
Iterator* internal_iter; InternalIterator* internal_iter;
assert(arena != nullptr); assert(arena != nullptr);
// Need to create internal iterator from the arena. // Need to create internal iterator from the arena.
MergeIteratorBuilder merge_iter_builder(&cfd->internal_comparator(), arena); MergeIteratorBuilder merge_iter_builder(&cfd->internal_comparator(), arena);
@ -3216,7 +3241,8 @@ Status DBImpl::AddFile(ColumnFamilyHandle* column_family,
file_info.num_entries = table_reader->GetTableProperties()->num_entries; file_info.num_entries = table_reader->GetTableProperties()->num_entries;
ParsedInternalKey key; ParsedInternalKey key;
std::unique_ptr<Iterator> iter(table_reader->NewIterator(ReadOptions())); std::unique_ptr<InternalIterator> iter(
table_reader->NewIterator(ReadOptions()));
// Get first (smallest) key from file // Get first (smallest) key from file
iter->SeekToFirst(); iter->SeekToFirst();
@ -3616,7 +3642,7 @@ Iterator* DBImpl::NewIterator(const ReadOptions& read_options,
snapshot, sv->mutable_cf_options.max_sequential_skip_in_iterations, snapshot, sv->mutable_cf_options.max_sequential_skip_in_iterations,
read_options.iterate_upper_bound); read_options.iterate_upper_bound);
Iterator* internal_iter = InternalIterator* internal_iter =
NewInternalIterator(read_options, cfd, sv, db_iter->GetArena()); NewInternalIterator(read_options, cfd, sv, db_iter->GetArena());
db_iter->SetIterUnderDBIter(internal_iter); db_iter->SetIterUnderDBIter(internal_iter);
@ -3683,8 +3709,8 @@ Status DBImpl::NewIterators(
ArenaWrappedDBIter* db_iter = NewArenaWrappedDbIterator( ArenaWrappedDBIter* db_iter = NewArenaWrappedDbIterator(
env_, *cfd->ioptions(), cfd->user_comparator(), snapshot, env_, *cfd->ioptions(), cfd->user_comparator(), snapshot,
sv->mutable_cf_options.max_sequential_skip_in_iterations); sv->mutable_cf_options.max_sequential_skip_in_iterations);
Iterator* internal_iter = NewInternalIterator( InternalIterator* internal_iter =
read_options, cfd, sv, db_iter->GetArena()); NewInternalIterator(read_options, cfd, sv, db_iter->GetArena());
db_iter->SetIterUnderDBIter(internal_iter); db_iter->SetIterUnderDBIter(internal_iter);
iterators->push_back(db_iter); iterators->push_back(db_iter);
} }
@ -4124,9 +4150,9 @@ Status DBImpl::SwitchMemtable(ColumnFamilyData* cfd, WriteContext* context) {
if (creating_new_log) { if (creating_new_log) {
EnvOptions opt_env_opt = EnvOptions opt_env_opt =
env_->OptimizeForLogWrite(env_options_, db_options_); env_->OptimizeForLogWrite(env_options_, db_options_);
s = env_->NewWritableFile( s = NewWritableFile(env_,
LogFileName(db_options_.wal_dir, new_log_number), &lfile, LogFileName(db_options_.wal_dir, new_log_number),
opt_env_opt); &lfile, opt_env_opt);
if (s.ok()) { if (s.ok()) {
// Our final size should be less than write_buffer_size // Our final size should be less than write_buffer_size
// (compression, etc) but err on the side of caution. // (compression, etc) but err on the side of caution.
@ -4203,6 +4229,29 @@ Status DBImpl::GetPropertiesOfAllTables(ColumnFamilyHandle* column_family,
return s; return s;
} }
Status DBImpl::GetPropertiesOfTablesInRange(ColumnFamilyHandle* column_family,
const Range* range, std::size_t n,
TablePropertiesCollection* props) {
auto cfh = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family);
auto cfd = cfh->cfd();
// Increment the ref count
mutex_.Lock();
auto version = cfd->current();
version->Ref();
mutex_.Unlock();
auto s = version->GetPropertiesOfTablesInRange(range, n, props);
// Decrement the ref count
mutex_.Lock();
version->Unref();
mutex_.Unlock();
return s;
}
#endif // ROCKSDB_LITE #endif // ROCKSDB_LITE
const std::string& DBImpl::GetName() const { const std::string& DBImpl::GetName() const {
@ -4742,9 +4791,9 @@ Status DB::Open(const DBOptions& db_options, const std::string& dbname,
EnvOptions soptions(db_options); EnvOptions soptions(db_options);
EnvOptions opt_env_options = EnvOptions opt_env_options =
impl->db_options_.env->OptimizeForLogWrite(soptions, impl->db_options_); impl->db_options_.env->OptimizeForLogWrite(soptions, impl->db_options_);
s = impl->db_options_.env->NewWritableFile( s = NewWritableFile(impl->db_options_.env,
LogFileName(impl->db_options_.wal_dir, new_log_number), &lfile, LogFileName(impl->db_options_.wal_dir, new_log_number),
opt_env_options); &lfile, opt_env_options);
if (s.ok()) { if (s.ok()) {
lfile->SetPreallocationBlockSize(1.1 * max_write_buffer_size); lfile->SetPreallocationBlockSize(1.1 * max_write_buffer_size);
impl->logfile_number_ = new_log_number; impl->logfile_number_ = new_log_number;

@ -36,11 +36,11 @@
#include "rocksdb/env.h" #include "rocksdb/env.h"
#include "rocksdb/memtablerep.h" #include "rocksdb/memtablerep.h"
#include "rocksdb/transaction_log.h" #include "rocksdb/transaction_log.h"
#include "table/scoped_arena_iterator.h"
#include "util/autovector.h" #include "util/autovector.h"
#include "util/event_logger.h" #include "util/event_logger.h"
#include "util/hash.h" #include "util/hash.h"
#include "util/instrumented_mutex.h" #include "util/instrumented_mutex.h"
#include "util/scoped_arena_iterator.h"
#include "util/stop_watch.h" #include "util/stop_watch.h"
#include "util/thread_local.h" #include "util/thread_local.h"
@ -248,7 +248,13 @@ class DBImpl : public DB {
const Slice* begin, const Slice* end, const Slice* begin, const Slice* end,
bool disallow_trivial_move = false); bool disallow_trivial_move = false);
#ifndef ROCKSDB_LITE // Return an internal iterator over the current state of the database.
// The keys of this iterator are internal keys (see format.h).
// The returned iterator should be deleted when no longer needed.
InternalIterator* NewInternalIterator(
Arena* arena, ColumnFamilyHandle* column_family = nullptr);
#ifndef NDEBUG
// Extra methods (for testing) that are not in the public DB interface // Extra methods (for testing) that are not in the public DB interface
// Implemented in db_impl_debug.cc // Implemented in db_impl_debug.cc
@ -266,12 +272,6 @@ class DBImpl : public DB {
// Wait for any compaction // Wait for any compaction
Status TEST_WaitForCompact(); Status TEST_WaitForCompact();
// Return an internal iterator over the current state of the database.
// The keys of this iterator are internal keys (see format.h).
// The returned iterator should be deleted when no longer needed.
Iterator* TEST_NewInternalIterator(
Arena* arena, ColumnFamilyHandle* column_family = nullptr);
// Return the maximum overlapping data (in bytes) at next level for any // Return the maximum overlapping data (in bytes) at next level for any
// file at a level >= 1. // file at a level >= 1.
int64_t TEST_MaxNextLevelOverlappingBytes(ColumnFamilyHandle* column_family = int64_t TEST_MaxNextLevelOverlappingBytes(ColumnFamilyHandle* column_family =
@ -305,7 +305,7 @@ class DBImpl : public DB {
uint64_t TEST_LogfileNumber(); uint64_t TEST_LogfileNumber();
#endif // ROCKSDB_LITE #endif // NDEBUG
// Returns the list of live files in 'live' and the list // Returns the list of live files in 'live' and the list
// of all files in the filesystem in 'candidate_files'. // of all files in the filesystem in 'candidate_files'.
@ -363,6 +363,20 @@ class DBImpl : public DB {
// Same as above, should called without mutex held and not on write thread. // Same as above, should called without mutex held and not on write thread.
ColumnFamilyHandle* GetColumnFamilyHandleUnlocked(uint32_t column_family_id); ColumnFamilyHandle* GetColumnFamilyHandleUnlocked(uint32_t column_family_id);
// Returns the number of currently running flushes.
// REQUIREMENT: mutex_ must be held when calling this function.
int num_running_flushes() {
mutex_.AssertHeld();
return num_running_flushes_;
}
// Returns the number of currently running compactions.
// REQUIREMENT: mutex_ must be held when calling this function.
int num_running_compactions() {
mutex_.AssertHeld();
return num_running_compactions_;
}
protected: protected:
Env* const env_; Env* const env_;
const std::string dbname_; const std::string dbname_;
@ -370,8 +384,10 @@ class DBImpl : public DB {
const DBOptions db_options_; const DBOptions db_options_;
Statistics* stats_; Statistics* stats_;
Iterator* NewInternalIterator(const ReadOptions&, ColumnFamilyData* cfd, InternalIterator* NewInternalIterator(const ReadOptions&,
SuperVersion* super_version, Arena* arena); ColumnFamilyData* cfd,
SuperVersion* super_version,
Arena* arena);
void NotifyOnFlushCompleted(ColumnFamilyData* cfd, FileMetaData* file_meta, void NotifyOnFlushCompleted(ColumnFamilyData* cfd, FileMetaData* file_meta,
const MutableCFOptions& mutable_cf_options, const MutableCFOptions& mutable_cf_options,
@ -685,6 +701,9 @@ class DBImpl : public DB {
// count how many background compactions are running or have been scheduled // count how many background compactions are running or have been scheduled
int bg_compaction_scheduled_; int bg_compaction_scheduled_;
// stores the number of compactions are currently running
int num_running_compactions_;
// If non-zero, MaybeScheduleFlushOrCompaction() will only schedule manual // If non-zero, MaybeScheduleFlushOrCompaction() will only schedule manual
// compactions (if manual_compaction_ is not null). This mechanism enables // compactions (if manual_compaction_ is not null). This mechanism enables
// manual compactions to wait until all other compactions are finished. // manual compactions to wait until all other compactions are finished.
@ -693,6 +712,9 @@ class DBImpl : public DB {
// number of background memtable flush jobs, submitted to the HIGH pool // number of background memtable flush jobs, submitted to the HIGH pool
int bg_flush_scheduled_; int bg_flush_scheduled_;
// stores the number of flushes are currently running
int num_running_flushes_;
// Information for a manual compaction // Information for a manual compaction
struct ManualCompaction { struct ManualCompaction {
ColumnFamilyData* cfd; ColumnFamilyData* cfd;
@ -788,6 +810,10 @@ class DBImpl : public DB {
virtual Status GetPropertiesOfAllTables(ColumnFamilyHandle* column_family, virtual Status GetPropertiesOfAllTables(ColumnFamilyHandle* column_family,
TablePropertiesCollection* props) TablePropertiesCollection* props)
override; override;
virtual Status GetPropertiesOfTablesInRange(
ColumnFamilyHandle* column_family, const Range* range, std::size_t n,
TablePropertiesCollection* props) override;
#endif // ROCKSDB_LITE #endif // ROCKSDB_LITE
// Function that Get and KeyMayExist call with no_io true or false // Function that Get and KeyMayExist call with no_io true or false

@ -7,7 +7,7 @@
// Use of this source code is governed by a BSD-style license that can be // 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. // found in the LICENSE file. See the AUTHORS file for names of contributors.
#ifndef ROCKSDB_LITE #ifndef NDEBUG
#include "db/db_impl.h" #include "db/db_impl.h"
#include "util/thread_status_updater.h" #include "util/thread_status_updater.h"
@ -19,23 +19,6 @@ uint64_t DBImpl::TEST_GetLevel0TotalSize() {
return default_cf_handle_->cfd()->current()->storage_info()->NumLevelBytes(0); return default_cf_handle_->cfd()->current()->storage_info()->NumLevelBytes(0);
} }
Iterator* DBImpl::TEST_NewInternalIterator(Arena* arena,
ColumnFamilyHandle* column_family) {
ColumnFamilyData* cfd;
if (column_family == nullptr) {
cfd = default_cf_handle_->cfd();
} else {
auto cfh = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family);
cfd = cfh->cfd();
}
mutex_.Lock();
SuperVersion* super_version = cfd->GetSuperVersion()->Ref();
mutex_.Unlock();
ReadOptions roptions;
return NewInternalIterator(roptions, cfd, super_version, arena);
}
int64_t DBImpl::TEST_MaxNextLevelOverlappingBytes( int64_t DBImpl::TEST_MaxNextLevelOverlappingBytes(
ColumnFamilyHandle* column_family) { ColumnFamilyHandle* column_family) {
ColumnFamilyData* cfd; ColumnFamilyData* cfd;
@ -153,4 +136,4 @@ uint64_t DBImpl::TEST_LogfileNumber() {
} }
} // namespace rocksdb } // namespace rocksdb
#endif // ROCKSDB_LITE #endif // NDEBUG

@ -15,11 +15,12 @@
#include "db/filename.h" #include "db/filename.h"
#include "db/dbformat.h" #include "db/dbformat.h"
#include "port/port.h"
#include "rocksdb/env.h" #include "rocksdb/env.h"
#include "rocksdb/options.h" #include "rocksdb/options.h"
#include "rocksdb/iterator.h" #include "rocksdb/iterator.h"
#include "rocksdb/merge_operator.h" #include "rocksdb/merge_operator.h"
#include "port/port.h" #include "table/internal_iterator.h"
#include "util/arena.h" #include "util/arena.h"
#include "util/logging.h" #include "util/logging.h"
#include "util/mutexlock.h" #include "util/mutexlock.h"
@ -58,9 +59,9 @@ class DBIter: public Iterator {
kReverse kReverse
}; };
DBIter(Env* env, const ImmutableCFOptions& ioptions, DBIter(Env* env, const ImmutableCFOptions& ioptions, const Comparator* cmp,
const Comparator* cmp, Iterator* iter, SequenceNumber s, InternalIterator* iter, SequenceNumber s, bool arena_mode,
bool arena_mode, uint64_t max_sequential_skip_in_iterations, uint64_t max_sequential_skip_in_iterations,
const Slice* iterate_upper_bound = nullptr) const Slice* iterate_upper_bound = nullptr)
: arena_mode_(arena_mode), : arena_mode_(arena_mode),
env_(env), env_(env),
@ -83,10 +84,10 @@ class DBIter: public Iterator {
if (!arena_mode_) { if (!arena_mode_) {
delete iter_; delete iter_;
} else { } else {
iter_->~Iterator(); iter_->~InternalIterator();
} }
} }
virtual void SetIter(Iterator* iter) { virtual void SetIter(InternalIterator* iter) {
assert(iter_ == nullptr); assert(iter_ == nullptr);
iter_ = iter; iter_ = iter;
} }
@ -142,7 +143,7 @@ class DBIter: public Iterator {
Logger* logger_; Logger* logger_;
const Comparator* const user_comparator_; const Comparator* const user_comparator_;
const MergeOperator* const user_merge_operator_; const MergeOperator* const user_merge_operator_;
Iterator* iter_; InternalIterator* iter_;
SequenceNumber const sequence_; SequenceNumber const sequence_;
Status status_; Status status_;
@ -744,7 +745,7 @@ void DBIter::SeekToLast() {
Iterator* NewDBIterator(Env* env, const ImmutableCFOptions& ioptions, Iterator* NewDBIterator(Env* env, const ImmutableCFOptions& ioptions,
const Comparator* user_key_comparator, const Comparator* user_key_comparator,
Iterator* internal_iter, InternalIterator* internal_iter,
const SequenceNumber& sequence, const SequenceNumber& sequence,
uint64_t max_sequential_skip_in_iterations, uint64_t max_sequential_skip_in_iterations,
const Slice* iterate_upper_bound) { const Slice* iterate_upper_bound) {
@ -757,7 +758,7 @@ ArenaWrappedDBIter::~ArenaWrappedDBIter() { db_iter_->~DBIter(); }
void ArenaWrappedDBIter::SetDBIter(DBIter* iter) { db_iter_ = iter; } void ArenaWrappedDBIter::SetDBIter(DBIter* iter) { db_iter_ = iter; }
void ArenaWrappedDBIter::SetIterUnderDBIter(Iterator* iter) { void ArenaWrappedDBIter::SetIterUnderDBIter(InternalIterator* iter) {
static_cast<DBIter*>(db_iter_)->SetIter(iter); static_cast<DBIter*>(db_iter_)->SetIter(iter);
} }

@ -10,6 +10,7 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include "rocksdb/db.h" #include "rocksdb/db.h"
#include "rocksdb/iterator.h"
#include "db/dbformat.h" #include "db/dbformat.h"
#include "util/arena.h" #include "util/arena.h"
#include "util/autovector.h" #include "util/autovector.h"
@ -18,15 +19,14 @@ namespace rocksdb {
class Arena; class Arena;
class DBIter; class DBIter;
class InternalIterator;
// Return a new iterator that converts internal keys (yielded by // Return a new iterator that converts internal keys (yielded by
// "*internal_iter") that were live at the specified "sequence" number // "*internal_iter") that were live at the specified "sequence" number
// into appropriate user keys. // into appropriate user keys.
extern Iterator* NewDBIterator( extern Iterator* NewDBIterator(Env* env, const ImmutableCFOptions& options,
Env* env,
const ImmutableCFOptions& options,
const Comparator* user_key_comparator, const Comparator* user_key_comparator,
Iterator* internal_iter, InternalIterator* internal_iter,
const SequenceNumber& sequence, const SequenceNumber& sequence,
uint64_t max_sequential_skip_in_iterations, uint64_t max_sequential_skip_in_iterations,
const Slice* iterate_upper_bound = nullptr); const Slice* iterate_upper_bound = nullptr);
@ -50,7 +50,7 @@ class ArenaWrappedDBIter : public Iterator {
// Set the internal iterator wrapped inside the DB Iterator. Usually it is // Set the internal iterator wrapped inside the DB Iterator. Usually it is
// a merging iterator. // a merging iterator.
virtual void SetIterUnderDBIter(Iterator* iter); virtual void SetIterUnderDBIter(InternalIterator* iter);
virtual bool Valid() const override; virtual bool Valid() const override;
virtual void SeekToFirst() override; virtual void SeekToFirst() override;
virtual void SeekToLast() override; virtual void SeekToLast() override;
@ -60,6 +60,7 @@ class ArenaWrappedDBIter : public Iterator {
virtual Slice key() const override; virtual Slice key() const override;
virtual Slice value() const override; virtual Slice value() const override;
virtual Status status() const override; virtual Status status() const override;
void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2); void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2);
private: private:

@ -29,7 +29,7 @@ static uint64_t TestGetTickerCount(const Options& options,
return options.statistics->getTickerCount(ticker_type); return options.statistics->getTickerCount(ticker_type);
} }
class TestIterator : public Iterator { class TestIterator : public InternalIterator {
public: public:
explicit TestIterator(const Comparator* comparator) explicit TestIterator(const Comparator* comparator)
: initialized_(false), : initialized_(false),
@ -1864,11 +1864,12 @@ class DBIterWithMergeIterTest : public testing::Test {
internal_iter2_->Add("d", kTypeValue, "7", 3u); internal_iter2_->Add("d", kTypeValue, "7", 3u);
internal_iter2_->Finish(); internal_iter2_->Finish();
std::vector<Iterator*> child_iters; std::vector<InternalIterator*> child_iters;
child_iters.push_back(internal_iter1_); child_iters.push_back(internal_iter1_);
child_iters.push_back(internal_iter2_); child_iters.push_back(internal_iter2_);
InternalKeyComparator icomp(BytewiseComparator()); InternalKeyComparator icomp(BytewiseComparator());
Iterator* merge_iter = NewMergingIterator(&icomp_, &child_iters[0], 2u); InternalIterator* merge_iter =
NewMergingIterator(&icomp_, &child_iters[0], 2u);
db_iter_.reset(NewDBIterator(env_, ImmutableCFOptions(options_), db_iter_.reset(NewDBIterator(env_, ImmutableCFOptions(options_),
BytewiseComparator(), merge_iter, BytewiseComparator(), merge_iter,

@ -10,7 +10,7 @@
// Introduction of SyncPoint effectively disabled building and running this test // Introduction of SyncPoint effectively disabled building and running this test
// in Release build. // in Release build.
// which is a pity, it is a good test // which is a pity, it is a good test
#if !(defined NDEBUG) || !defined(OS_WIN) #if (!(defined NDEBUG) || !defined(OS_WIN)) && !defined(ROCKSDB_LITE)
#include "db/db_test_util.h" #include "db/db_test_util.h"
#include "port/stack_trace.h" #include "port/stack_trace.h"
@ -277,10 +277,10 @@ TEST_F(DBTestXactLogIterator, TransactionLogIteratorBlobs) {
} }
} // namespace rocksdb } // namespace rocksdb
#endif // !(defined NDEBUG) || !defined(OS_WIN) #endif // (!(defined NDEBUG) || !defined(OS_WIN)) && !defined(ROCKSDB_LITE)
int main(int argc, char** argv) { int main(int argc, char** argv) {
#if !(defined NDEBUG) || !defined(OS_WIN) #if (!(defined NDEBUG) || !defined(OS_WIN)) && !defined(ROCKSDB_LITE)
rocksdb::port::InstallStackTraceHandler(); rocksdb::port::InstallStackTraceHandler();
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();

@ -0,0 +1,217 @@
// Copyright (c) 2013, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
// 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 <unordered_set>
#include <vector>
#include "db/db_test_util.h"
#include "port/stack_trace.h"
#include "rocksdb/db.h"
#include "util/testharness.h"
#include "util/testutil.h"
#ifndef ROCKSDB_LITE
namespace rocksdb {
// A helper function that ensures the table properties returned in
// `GetPropertiesOfAllTablesTest` is correct.
// This test assumes entries size is different for each of the tables.
namespace {
void VerifyTableProperties(DB* db, uint64_t expected_entries_size) {
TablePropertiesCollection props;
ASSERT_OK(db->GetPropertiesOfAllTables(&props));
ASSERT_EQ(4U, props.size());
std::unordered_set<uint64_t> unique_entries;
// Indirect test
uint64_t sum = 0;
for (const auto& item : props) {
unique_entries.insert(item.second->num_entries);
sum += item.second->num_entries;
}
ASSERT_EQ(props.size(), unique_entries.size());
ASSERT_EQ(expected_entries_size, sum);
}
} // namespace
class DBTablePropertiesTest : public DBTestBase {
public:
DBTablePropertiesTest() : DBTestBase("/db_table_properties_test") {}
TablePropertiesCollection TestGetPropertiesOfTablesInRange(
std::vector<Range> ranges, std::size_t* num_properties = nullptr,
std::size_t* num_files = nullptr);
};
TEST_F(DBTablePropertiesTest, GetPropertiesOfAllTablesTest) {
Options options = CurrentOptions();
options.level0_file_num_compaction_trigger = 8;
Reopen(options);
// Create 4 tables
for (int table = 0; table < 4; ++table) {
for (int i = 0; i < 10 + table; ++i) {
db_->Put(WriteOptions(), ToString(table * 100 + i), "val");
}
db_->Flush(FlushOptions());
}
// 1. Read table properties directly from file
Reopen(options);
VerifyTableProperties(db_, 10 + 11 + 12 + 13);
// 2. Put two tables to table cache and
Reopen(options);
// fetch key from 1st and 2nd table, which will internally place that table to
// the table cache.
for (int i = 0; i < 2; ++i) {
Get(ToString(i * 100 + 0));
}
VerifyTableProperties(db_, 10 + 11 + 12 + 13);
// 3. Put all tables to table cache
Reopen(options);
// fetch key from 1st and 2nd table, which will internally place that table to
// the table cache.
for (int i = 0; i < 4; ++i) {
Get(ToString(i * 100 + 0));
}
VerifyTableProperties(db_, 10 + 11 + 12 + 13);
}
TablePropertiesCollection
DBTablePropertiesTest::TestGetPropertiesOfTablesInRange(
std::vector<Range> ranges, std::size_t* num_properties,
std::size_t* num_files) {
// run the query
TablePropertiesCollection props;
EXPECT_OK(db_->GetPropertiesOfTablesInRange(
db_->DefaultColumnFamily(), &ranges[0], ranges.size(), &props));
// Make sure that we've received properties for those and for those files
// only which fall within requested ranges
std::vector<LiveFileMetaData> vmd;
db_->GetLiveFilesMetaData(&vmd);
for (auto md : vmd) {
std::string fn = md.db_path + md.name;
bool in_range = false;
for (auto r : ranges) {
// smallestkey < limit && largestkey >= start
if (r.limit.compare(md.smallestkey) >= 0 &&
r.start.compare(md.largestkey) <= 0) {
in_range = true;
EXPECT_GT(props.count(fn), 0);
}
}
if (!in_range) {
EXPECT_EQ(props.count(fn), 0);
}
}
if (num_properties) {
*num_properties = props.size();
}
if (num_files) {
*num_files = vmd.size();
}
return props;
}
TEST_F(DBTablePropertiesTest, GetPropertiesOfTablesInRange) {
// Fixed random sead
Random rnd(301);
Options options;
options.create_if_missing = true;
options.write_buffer_size = 4096;
options.max_write_buffer_number = 8;
options.level0_file_num_compaction_trigger = 2;
options.level0_slowdown_writes_trigger = 2;
options.level0_stop_writes_trigger = 4;
options.target_file_size_base = 2048;
options.max_bytes_for_level_base = 10240;
options.max_bytes_for_level_multiplier = 4;
options.soft_rate_limit = 1.1;
options.num_levels = 8;
DestroyAndReopen(options);
// build a decent LSM
for (int i = 0; i < 10000; i++) {
ASSERT_OK(Put(test::RandomKey(&rnd, 5), RandomString(&rnd, 102)));
}
Flush();
db_->PauseBackgroundWork();
// Ensure that we have at least L0, L1 and L2
ASSERT_GT(NumTableFilesAtLevel(0), 0);
ASSERT_GT(NumTableFilesAtLevel(1), 0);
ASSERT_GT(NumTableFilesAtLevel(2), 0);
// Query the largest range
std::size_t num_properties, num_files;
TestGetPropertiesOfTablesInRange(
{Range(test::RandomKey(&rnd, 5, test::RandomKeyType::SMALLEST),
test::RandomKey(&rnd, 5, test::RandomKeyType::LARGEST))},
&num_properties, &num_files);
ASSERT_EQ(num_properties, num_files);
// Query the empty range
TestGetPropertiesOfTablesInRange(
{Range(test::RandomKey(&rnd, 5, test::RandomKeyType::LARGEST),
test::RandomKey(&rnd, 5, test::RandomKeyType::SMALLEST))},
&num_properties, &num_files);
ASSERT_GT(num_files, 0);
ASSERT_EQ(num_properties, 0);
// Query the middle rangee
TestGetPropertiesOfTablesInRange(
{Range(test::RandomKey(&rnd, 5, test::RandomKeyType::MIDDLE),
test::RandomKey(&rnd, 5, test::RandomKeyType::LARGEST))},
&num_properties, &num_files);
ASSERT_GT(num_files, 0);
ASSERT_GT(num_files, num_properties);
ASSERT_GT(num_properties, 0);
// Query a bunch of random ranges
for (int j = 0; j < 100; j++) {
// create a bunch of ranges
std::vector<std::string> random_keys;
auto n = 2 * rnd.Uniform(50);
for (uint32_t i = 0; i < n; ++i) {
random_keys.push_back(test::RandomKey(&rnd, 5));
}
std::vector<Range> ranges;
auto it = random_keys.begin();
while (it != random_keys.end()) {
ranges.push_back(Range(*it, *(it + 1)));
it += 2;
}
TestGetPropertiesOfTablesInRange(std::move(ranges));
}
}
} // namespace rocksdb
#endif // ROCKSDB_LITE
int main(int argc, char** argv) {
#if !(defined NDEBUG) || !defined(OS_WIN)
rocksdb::port::InstallStackTraceHandler();
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
#else
return 0;
#endif
}

@ -10,7 +10,7 @@
// Introduction of SyncPoint effectively disabled building and running this test // Introduction of SyncPoint effectively disabled building and running this test
// in Release build. // in Release build.
// which is a pity, it is a good test // which is a pity, it is a good test
#if !(defined NDEBUG) || !defined(OS_WIN) #if (!(defined NDEBUG) || !defined(OS_WIN)) && !defined(ROCKSDB_LITE)
#include "db/db_test_util.h" #include "db/db_test_util.h"
#include "db/forward_iterator.h" #include "db/forward_iterator.h"
@ -646,10 +646,10 @@ TEST_F(DBTestTailingIterator, ManagedTailingIteratorSeekToSame) {
} // namespace rocksdb } // namespace rocksdb
#endif // !(defined NDEBUG) || !defined(OS_WIN) #endif // (!(defined NDEBUG) || !defined(OS_WIN)) && !defined(ROCKSDB_LITE)
int main(int argc, char** argv) { int main(int argc, char** argv) {
#if !(defined NDEBUG) || !defined(OS_WIN) #if (!(defined NDEBUG) || !defined(OS_WIN)) && !defined(ROCKSDB_LITE)
rocksdb::port::InstallStackTraceHandler(); rocksdb::port::InstallStackTraceHandler();
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();

@ -30,6 +30,7 @@
#include "db/job_context.h" #include "db/job_context.h"
#include "db/version_set.h" #include "db/version_set.h"
#include "db/write_batch_internal.h" #include "db/write_batch_internal.h"
#include "memtable/hash_linklist_rep.h"
#include "port/stack_trace.h" #include "port/stack_trace.h"
#include "rocksdb/cache.h" #include "rocksdb/cache.h"
#include "rocksdb/compaction_filter.h" #include "rocksdb/compaction_filter.h"
@ -55,9 +56,9 @@
#include "table/block_based_table_factory.h" #include "table/block_based_table_factory.h"
#include "table/mock_table.h" #include "table/mock_table.h"
#include "table/plain_table_factory.h" #include "table/plain_table_factory.h"
#include "table/scoped_arena_iterator.h"
#include "util/file_reader_writer.h" #include "util/file_reader_writer.h"
#include "util/hash.h" #include "util/hash.h"
#include "util/hash_linklist_rep.h"
#include "utilities/merge_operators.h" #include "utilities/merge_operators.h"
#include "util/logging.h" #include "util/logging.h"
#include "util/compression.h" #include "util/compression.h"
@ -65,7 +66,6 @@
#include "util/rate_limiter.h" #include "util/rate_limiter.h"
#include "util/statistics.h" #include "util/statistics.h"
#include "util/testharness.h" #include "util/testharness.h"
#include "util/scoped_arena_iterator.h"
#include "util/sync_point.h" #include "util/sync_point.h"
#include "util/testutil.h" #include "util/testutil.h"
#include "util/mock_env.h" #include "util/mock_env.h"
@ -79,29 +79,12 @@ static long TestGetTickerCount(const Options& options, Tickers ticker_type) {
return options.statistics->getTickerCount(ticker_type); return options.statistics->getTickerCount(ticker_type);
} }
#ifndef ROCKSDB_LITE
// A helper function that ensures the table properties returned in // A helper function that ensures the table properties returned in
// `GetPropertiesOfAllTablesTest` is correct. // `GetPropertiesOfAllTablesTest` is correct.
// This test assumes entries size is different for each of the tables. // This test assumes entries size is different for each of the tables.
namespace { namespace {
void VerifyTableProperties(DB* db, uint64_t expected_entries_size) {
TablePropertiesCollection props;
ASSERT_OK(db->GetPropertiesOfAllTables(&props));
ASSERT_EQ(4U, props.size());
std::unordered_set<uint64_t> unique_entries;
// Indirect test
uint64_t sum = 0;
for (const auto& item : props) {
unique_entries.insert(item.second->num_entries);
sum += item.second->num_entries;
}
ASSERT_EQ(props.size(), unique_entries.size());
ASSERT_EQ(expected_entries_size, sum);
}
uint64_t GetNumberOfSstFilesForColumnFamily(DB* db, uint64_t GetNumberOfSstFilesForColumnFamily(DB* db,
std::string column_family_name) { std::string column_family_name) {
std::vector<LiveFileMetaData> metadata; std::vector<LiveFileMetaData> metadata;
@ -114,6 +97,7 @@ uint64_t GetNumberOfSstFilesForColumnFamily(DB* db,
} }
} // namespace } // namespace
#endif // ROCKSDB_LITE
class DBTest : public DBTestBase { class DBTest : public DBTestBase {
public: public:
@ -132,46 +116,7 @@ class DBTestWithParam : public DBTest,
uint32_t max_subcompactions_; uint32_t max_subcompactions_;
}; };
class BloomStatsTestWithParam #ifndef ROCKSDB_LITE
: public DBTest,
public testing::WithParamInterface<std::tuple<bool, bool>> {
public:
BloomStatsTestWithParam() {
use_block_table_ = std::get<0>(GetParam());
use_block_based_builder_ = std::get<1>(GetParam());
options_.create_if_missing = true;
options_.prefix_extractor.reset(rocksdb::NewFixedPrefixTransform(4));
options_.memtable_prefix_bloom_bits = 8 * 1024;
if (use_block_table_) {
BlockBasedTableOptions table_options;
table_options.hash_index_allow_collision = false;
table_options.filter_policy.reset(
NewBloomFilterPolicy(10, use_block_based_builder_));
options_.table_factory.reset(NewBlockBasedTableFactory(table_options));
} else {
PlainTableOptions table_options;
options_.table_factory.reset(NewPlainTableFactory(table_options));
}
perf_context.Reset();
DestroyAndReopen(options_);
}
~BloomStatsTestWithParam() {
perf_context.Reset();
Destroy(options_);
}
// Required if inheriting from testing::WithParamInterface<>
static void SetUpTestCase() {}
static void TearDownTestCase() {}
bool use_block_table_;
bool use_block_based_builder_;
Options options_;
};
TEST_F(DBTest, Empty) { TEST_F(DBTest, Empty) {
do { do {
Options options; Options options;
@ -233,6 +178,7 @@ TEST_F(DBTest, Empty) {
ASSERT_EQ("0", num); ASSERT_EQ("0", num);
} while (ChangeOptions()); } while (ChangeOptions());
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, WriteEmptyBatch) { TEST_F(DBTest, WriteEmptyBatch) {
Options options; Options options;
@ -255,6 +201,7 @@ TEST_F(DBTest, WriteEmptyBatch) {
ASSERT_EQ("bar", Get(1, "foo")); ASSERT_EQ("bar", Get(1, "foo"));
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, ReadOnlyDB) { TEST_F(DBTest, ReadOnlyDB) {
ASSERT_OK(Put("foo", "v1")); ASSERT_OK(Put("foo", "v1"));
ASSERT_OK(Put("bar", "v2")); ASSERT_OK(Put("bar", "v2"));
@ -476,42 +423,6 @@ TEST_F(DBTest, ParanoidFileChecks) {
TestGetTickerCount(options, BLOCK_CACHE_ADD)); TestGetTickerCount(options, BLOCK_CACHE_ADD));
} }
TEST_F(DBTest, GetPropertiesOfAllTablesTest) {
Options options = CurrentOptions();
options.level0_file_num_compaction_trigger = 8;
Reopen(options);
// Create 4 tables
for (int table = 0; table < 4; ++table) {
for (int i = 0; i < 10 + table; ++i) {
db_->Put(WriteOptions(), ToString(table * 100 + i), "val");
}
db_->Flush(FlushOptions());
}
// 1. Read table properties directly from file
Reopen(options);
VerifyTableProperties(db_, 10 + 11 + 12 + 13);
// 2. Put two tables to table cache and
Reopen(options);
// fetch key from 1st and 2nd table, which will internally place that table to
// the table cache.
for (int i = 0; i < 2; ++i) {
Get(ToString(i * 100 + 0));
}
VerifyTableProperties(db_, 10 + 11 + 12 + 13);
// 3. Put all tables to table cache
Reopen(options);
// fetch key from 1st and 2nd table, which will internally place that table to
// the table cache.
for (int i = 0; i < 4; ++i) {
Get(ToString(i * 100 + 0));
}
VerifyTableProperties(db_, 10 + 11 + 12 + 13);
}
namespace { namespace {
void ResetTableProperties(TableProperties* tp) { void ResetTableProperties(TableProperties* tp) {
tp->data_size = 0; tp->data_size = 0;
@ -658,9 +569,10 @@ TEST_F(DBTest, ReadLatencyHistogramByLevel) {
DestroyAndReopen(options); DestroyAndReopen(options);
int key_index = 0; int key_index = 0;
Random rnd(301); Random rnd(301);
for (int num = 0; num < 7; num++) { for (int num = 0; num < 8; num++) {
Put("foo", "bar"); Put("foo", "bar");
GenerateNewFile(&rnd, &key_index); GenerateNewFile(&rnd, &key_index);
dbfull()->TEST_WaitForCompact();
} }
dbfull()->TEST_WaitForCompact(); dbfull()->TEST_WaitForCompact();
@ -668,7 +580,7 @@ TEST_F(DBTest, ReadLatencyHistogramByLevel) {
ASSERT_TRUE(dbfull()->GetProperty("rocksdb.dbstats", &prop)); ASSERT_TRUE(dbfull()->GetProperty("rocksdb.dbstats", &prop));
// Get() after flushes, See latency histogram tracked. // Get() after flushes, See latency histogram tracked.
for (int key = 0; key < 500; key++) { for (int key = 0; key < key_index; key++) {
Get(Key(key)); Get(Key(key));
} }
ASSERT_TRUE(dbfull()->GetProperty("rocksdb.dbstats", &prop)); ASSERT_TRUE(dbfull()->GetProperty("rocksdb.dbstats", &prop));
@ -679,7 +591,7 @@ TEST_F(DBTest, ReadLatencyHistogramByLevel) {
// Reopen and issue Get(). See thee latency tracked // Reopen and issue Get(). See thee latency tracked
Reopen(options); Reopen(options);
dbfull()->TEST_WaitForCompact(); dbfull()->TEST_WaitForCompact();
for (int key = 0; key < 500; key++) { for (int key = 0; key < key_index; key++) {
Get(Key(key)); Get(Key(key));
} }
ASSERT_TRUE(dbfull()->GetProperty("rocksdb.dbstats", &prop)); ASSERT_TRUE(dbfull()->GetProperty("rocksdb.dbstats", &prop));
@ -710,7 +622,7 @@ TEST_F(DBTest, ReadLatencyHistogramByLevel) {
ASSERT_NE(std::string::npos, prop.find("** Level 0 read latency histogram")); ASSERT_NE(std::string::npos, prop.find("** Level 0 read latency histogram"));
ASSERT_NE(std::string::npos, prop.find("** Level 1 read latency histogram")); ASSERT_NE(std::string::npos, prop.find("** Level 1 read latency histogram"));
ASSERT_EQ(std::string::npos, prop.find("** Level 2 read latency histogram")); ASSERT_EQ(std::string::npos, prop.find("** Level 2 read latency histogram"));
for (int key = 0; key < 500; key++) { for (int key = 0; key < key_index; key++) {
Get(Key(key)); Get(Key(key));
} }
ASSERT_TRUE(dbfull()->GetProperty("rocksdb.dbstats", &prop)); ASSERT_TRUE(dbfull()->GetProperty("rocksdb.dbstats", &prop));
@ -790,6 +702,7 @@ TEST_F(DBTest, AggregatedTablePropertiesAtLevel) {
} }
} }
} }
#endif // ROCKSDB_LITE
class CoutingUserTblPropCollector : public TablePropertiesCollector { class CoutingUserTblPropCollector : public TablePropertiesCollector {
public: public:
@ -842,6 +755,7 @@ class CoutingUserTblPropCollectorFactory
uint32_t num_created_; uint32_t num_created_;
}; };
#ifndef ROCKSDB_LITE
TEST_F(DBTest, GetUserDefinedTableProperties) { TEST_F(DBTest, GetUserDefinedTableProperties) {
Options options = CurrentOptions(); Options options = CurrentOptions();
options.level0_file_num_compaction_trigger = (1<<30); options.level0_file_num_compaction_trigger = (1<<30);
@ -881,6 +795,7 @@ TEST_F(DBTest, GetUserDefinedTableProperties) {
dbfull()->TEST_CompactRange(0, nullptr, nullptr); dbfull()->TEST_CompactRange(0, nullptr, nullptr);
ASSERT_GT(collector_factory->num_created_, 0); ASSERT_GT(collector_factory->num_created_, 0);
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, UserDefinedTablePropertiesContext) { TEST_F(DBTest, UserDefinedTablePropertiesContext) {
Options options = CurrentOptions(); Options options = CurrentOptions();
@ -943,6 +858,7 @@ TEST_F(DBTest, UserDefinedTablePropertiesContext) {
ASSERT_GT(collector_factory->num_created_, 0); ASSERT_GT(collector_factory->num_created_, 0);
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, LevelLimitReopen) { TEST_F(DBTest, LevelLimitReopen) {
Options options = CurrentOptions(); Options options = CurrentOptions();
CreateAndReopenWithCF({"pikachu"}, options); CreateAndReopenWithCF({"pikachu"}, options);
@ -964,6 +880,7 @@ TEST_F(DBTest, LevelLimitReopen) {
options.max_bytes_for_level_multiplier_additional.resize(10, 1); options.max_bytes_for_level_multiplier_additional.resize(10, 1);
ASSERT_OK(TryReopenWithColumnFamilies({"default", "pikachu"}, options)); ASSERT_OK(TryReopenWithColumnFamilies({"default", "pikachu"}, options));
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, PutDeleteGet) { TEST_F(DBTest, PutDeleteGet) {
do { do {
@ -1110,6 +1027,7 @@ TEST_F(DBTest, GetFromVersions) {
} while (ChangeOptions()); } while (ChangeOptions());
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, GetSnapshot) { TEST_F(DBTest, GetSnapshot) {
anon::OptionsOverride options_override; anon::OptionsOverride options_override;
options_override.skip_policy = kSkipNoSnapshot; options_override.skip_policy = kSkipNoSnapshot;
@ -1135,6 +1053,7 @@ TEST_F(DBTest, GetSnapshot) {
} }
} while (ChangeOptions()); } while (ChangeOptions());
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, GetLevel0Ordering) { TEST_F(DBTest, GetLevel0Ordering) {
do { do {
@ -1162,6 +1081,7 @@ TEST_F(DBTest, WrongLevel0Config) {
ASSERT_OK(DB::Open(options, dbname_, &db_)); ASSERT_OK(DB::Open(options, dbname_, &db_));
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, GetOrderedByLevels) { TEST_F(DBTest, GetOrderedByLevels) {
do { do {
CreateAndReopenWithCF({"pikachu"}, CurrentOptions()); CreateAndReopenWithCF({"pikachu"}, CurrentOptions());
@ -1233,6 +1153,7 @@ TEST_F(DBTest, GetEncountersEmptyLevel) {
ASSERT_EQ(NumTableFilesAtLevel(0, 1), 1); // XXX ASSERT_EQ(NumTableFilesAtLevel(0, 1), 1); // XXX
} while (ChangeOptions(kSkipUniversalCompaction | kSkipFIFOCompaction)); } while (ChangeOptions(kSkipUniversalCompaction | kSkipFIFOCompaction));
} }
#endif // ROCKSDB_LITE
// KeyMayExist can lead to a few false positives, but not false negatives. // KeyMayExist can lead to a few false positives, but not false negatives.
// To make test deterministic, use a much larger number of bits per key-20 than // To make test deterministic, use a much larger number of bits per key-20 than
@ -1365,6 +1286,7 @@ TEST_F(DBTest, NonBlockingIteration) {
kSkipMmapReads)); kSkipMmapReads));
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, ManagedNonBlockingIteration) { TEST_F(DBTest, ManagedNonBlockingIteration) {
do { do {
ReadOptions non_blocking_opts, regular_opts; ReadOptions non_blocking_opts, regular_opts;
@ -1429,6 +1351,7 @@ TEST_F(DBTest, ManagedNonBlockingIteration) {
} while (ChangeOptions(kSkipPlainTable | kSkipNoSeekToLast | kSkipHashCuckoo | } while (ChangeOptions(kSkipPlainTable | kSkipNoSeekToLast | kSkipHashCuckoo |
kSkipMmapReads)); kSkipMmapReads));
} }
#endif // ROCKSDB_LITE
// A delete is skipped for key if KeyMayExist(key) returns False // A delete is skipped for key if KeyMayExist(key) returns False
// Tests Writebatch consistency and proper delete behaviour // Tests Writebatch consistency and proper delete behaviour
@ -2333,6 +2256,7 @@ TEST_F(DBTest, FlushMultipleMemtable) {
} while (ChangeCompactOptions()); } while (ChangeCompactOptions());
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, NumImmutableMemTable) { TEST_F(DBTest, NumImmutableMemTable) {
do { do {
Options options = CurrentOptions(); Options options = CurrentOptions();
@ -2442,6 +2366,7 @@ TEST_F(DBTest, NumImmutableMemTable) {
ASSERT_TRUE(GetPerfLevel() == kDisable); ASSERT_TRUE(GetPerfLevel() == kDisable);
} while (ChangeCompactOptions()); } while (ChangeCompactOptions());
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, FlushEmptyColumnFamily) { TEST_F(DBTest, FlushEmptyColumnFamily) {
// Block flush thread and disable compaction thread // Block flush thread and disable compaction thread
@ -2487,6 +2412,7 @@ TEST_F(DBTest, FlushEmptyColumnFamily) {
sleeping_task_low.WaitUntilDone(); sleeping_task_low.WaitUntilDone();
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, GetProperty) { TEST_F(DBTest, GetProperty) {
// Set sizes to both background thread pool to be 1 and block them. // Set sizes to both background thread pool to be 1 and block them.
env_->SetBackgroundThreads(1, Env::HIGH); env_->SetBackgroundThreads(1, Env::HIGH);
@ -2792,6 +2718,7 @@ TEST_F(DBTest, EstimatePendingCompBytes) {
"rocksdb.estimate-pending-compaction-bytes", &int_num)); "rocksdb.estimate-pending-compaction-bytes", &int_num));
ASSERT_EQ(int_num, 0U); ASSERT_EQ(int_num, 0U);
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, FLUSH) { TEST_F(DBTest, FLUSH) {
do { do {
@ -2851,7 +2778,7 @@ TEST_F(DBTest, RecoveryWithEmptyLog) {
} while (ChangeOptions()); } while (ChangeOptions());
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, FlushSchedule) { TEST_F(DBTest, FlushSchedule) {
Options options = CurrentOptions(); Options options = CurrentOptions();
options.disable_auto_compactions = true; options.disable_auto_compactions = true;
@ -2892,7 +2819,7 @@ TEST_F(DBTest, FlushSchedule) {
ASSERT_LE(pikachu_tables, static_cast<uint64_t>(10)); ASSERT_LE(pikachu_tables, static_cast<uint64_t>(10));
ASSERT_GT(pikachu_tables, static_cast<uint64_t>(0)); ASSERT_GT(pikachu_tables, static_cast<uint64_t>(0));
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, ManifestRollOver) { TEST_F(DBTest, ManifestRollOver) {
do { do {
@ -2940,6 +2867,7 @@ TEST_F(DBTest, IdentityAcrossRestarts) {
} while (ChangeCompactOptions()); } while (ChangeCompactOptions());
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, RecoverWithLargeLog) { TEST_F(DBTest, RecoverWithLargeLog) {
do { do {
{ {
@ -2966,6 +2894,7 @@ TEST_F(DBTest, RecoverWithLargeLog) {
ASSERT_GT(NumTableFilesAtLevel(0, 1), 1); ASSERT_GT(NumTableFilesAtLevel(0, 1), 1);
} while (ChangeCompactOptions()); } while (ChangeCompactOptions());
} }
#endif // ROCKSDB_LITE
namespace { namespace {
class KeepFilter : public CompactionFilter { class KeepFilter : public CompactionFilter {
@ -3030,6 +2959,7 @@ class DelayFilterFactory : public CompactionFilterFactory {
}; };
} // namespace } // namespace
#ifndef ROCKSDB_LITE
TEST_F(DBTest, CompressedCache) { TEST_F(DBTest, CompressedCache) {
if (!Snappy_Supported()) { if (!Snappy_Supported()) {
return; return;
@ -3153,6 +3083,7 @@ static std::string CompressibleString(Random* rnd, int len) {
test::CompressibleString(rnd, 0.8, len, &r); test::CompressibleString(rnd, 0.8, len, &r);
return r; return r;
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, FailMoreDbPaths) { TEST_F(DBTest, FailMoreDbPaths) {
Options options = CurrentOptions(); Options options = CurrentOptions();
@ -3183,6 +3114,7 @@ void CheckColumnFamilyMeta(const ColumnFamilyMetaData& cf_meta) {
ASSERT_EQ(cf_meta.size, cf_size); ASSERT_EQ(cf_meta.size, cf_size);
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, ColumnFamilyMetaDataTest) { TEST_F(DBTest, ColumnFamilyMetaDataTest) {
Options options = CurrentOptions(); Options options = CurrentOptions();
options.create_if_missing = true; options.create_if_missing = true;
@ -3329,6 +3261,7 @@ TEST_F(DBTest, RepeatedWritesToSameKey) {
} }
} while (ChangeCompactOptions()); } while (ChangeCompactOptions());
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, SparseMerge) { TEST_F(DBTest, SparseMerge) {
do { do {
@ -3375,6 +3308,7 @@ TEST_F(DBTest, SparseMerge) {
} while (ChangeCompactOptions()); } while (ChangeCompactOptions());
} }
#ifndef ROCKSDB_LITE
static bool Between(uint64_t val, uint64_t low, uint64_t high) { static bool Between(uint64_t val, uint64_t low, uint64_t high) {
bool result = (val >= low) && (val <= high); bool result = (val >= low) && (val <= high);
if (!result) { if (!result) {
@ -3587,6 +3521,7 @@ TEST_F(DBTest, ApproximateSizes_MixOfSmallAndLarge) {
// ApproximateOffsetOf() is not yet implemented in plain table format. // ApproximateOffsetOf() is not yet implemented in plain table format.
} while (ChangeOptions(kSkipPlainTable)); } while (ChangeOptions(kSkipPlainTable));
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, IteratorPinsRef) { TEST_F(DBTest, IteratorPinsRef) {
do { do {
@ -3614,6 +3549,7 @@ TEST_F(DBTest, IteratorPinsRef) {
} while (ChangeCompactOptions()); } while (ChangeCompactOptions());
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, Snapshot) { TEST_F(DBTest, Snapshot) {
anon::OptionsOverride options_override; anon::OptionsOverride options_override;
options_override.skip_policy = kSkipNoSnapshot; options_override.skip_policy = kSkipNoSnapshot;
@ -3716,6 +3652,7 @@ TEST_F(DBTest, HiddenValuesAreRemoved) {
} while (ChangeOptions(kSkipUniversalCompaction | kSkipFIFOCompaction | } while (ChangeOptions(kSkipUniversalCompaction | kSkipFIFOCompaction |
kSkipPlainTable | kSkipHashCuckoo)); kSkipPlainTable | kSkipHashCuckoo));
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, CompactBetweenSnapshots) { TEST_F(DBTest, CompactBetweenSnapshots) {
anon::OptionsOverride options_override; anon::OptionsOverride options_override;
@ -3821,6 +3758,7 @@ TEST_F(DBTest, UnremovableSingleDelete) {
kSkipUniversalCompaction | kSkipMergePut)); kSkipUniversalCompaction | kSkipMergePut));
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, DeletionMarkers1) { TEST_F(DBTest, DeletionMarkers1) {
Options options = CurrentOptions(); Options options = CurrentOptions();
options.max_background_flushes = 0; options.max_background_flushes = 0;
@ -3930,6 +3868,7 @@ TEST_F(DBTest, OverlapInLevel0) {
ASSERT_EQ("NOT_FOUND", Get(1, "600")); ASSERT_EQ("NOT_FOUND", Get(1, "600"));
} while (ChangeOptions(kSkipUniversalCompaction | kSkipFIFOCompaction)); } while (ChangeOptions(kSkipUniversalCompaction | kSkipFIFOCompaction));
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, ComparatorCheck) { TEST_F(DBTest, ComparatorCheck) {
class NewComparator : public Comparator { class NewComparator : public Comparator {
@ -4122,6 +4061,7 @@ TEST_F(DBTest, DestroyDBMetaDatabase) {
ASSERT_TRUE(!(DB::Open(options, metametadbname, &db)).ok()); ASSERT_TRUE(!(DB::Open(options, metametadbname, &db)).ok());
} }
#ifndef ROCKSDB_LITE
// Check that number of files does not grow when writes are dropped // Check that number of files does not grow when writes are dropped
TEST_F(DBTest, DropWrites) { TEST_F(DBTest, DropWrites) {
do { do {
@ -4192,6 +4132,7 @@ TEST_F(DBTest, DropWritesFlush) {
env_->drop_writes_.store(false, std::memory_order_release); env_->drop_writes_.store(false, std::memory_order_release);
} while (ChangeCompactOptions()); } while (ChangeCompactOptions());
} }
#endif // ROCKSDB_LITE
// Check that CompactRange() returns failure if there is not enough space left // Check that CompactRange() returns failure if there is not enough space left
// on device // on device
@ -4241,6 +4182,7 @@ TEST_F(DBTest, NonWritableFileSystem) {
} while (ChangeCompactOptions()); } while (ChangeCompactOptions());
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, ManifestWriteError) { TEST_F(DBTest, ManifestWriteError) {
// Test for the following problem: // Test for the following problem:
// (a) Compaction produces file F // (a) Compaction produces file F
@ -4282,6 +4224,7 @@ TEST_F(DBTest, ManifestWriteError) {
ASSERT_EQ("bar", Get("foo")); ASSERT_EQ("bar", Get("foo"));
} }
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, PutFailsParanoid) { TEST_F(DBTest, PutFailsParanoid) {
// Test the following: // Test the following:
@ -4540,6 +4483,7 @@ TEST_F(DBTest, BloomFilterWrapper) {
ASSERT_EQ(2U * maxKey, policy->GetCounter()); ASSERT_EQ(2U * maxKey, policy->GetCounter());
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, SnapshotFiles) { TEST_F(DBTest, SnapshotFiles) {
do { do {
Options options = CurrentOptions(); Options options = CurrentOptions();
@ -4667,6 +4611,7 @@ TEST_F(DBTest, SnapshotFiles) {
dbfull()->DisableFileDeletions(); dbfull()->DisableFileDeletions();
} while (ChangeCompactOptions()); } while (ChangeCompactOptions());
} }
#endif
TEST_F(DBTest, CompactOnFlush) { TEST_F(DBTest, CompactOnFlush) {
anon::OptionsOverride options_override; anon::OptionsOverride options_override;
@ -4806,6 +4751,7 @@ TEST_F(DBTest, FlushOneColumnFamily) {
} }
} }
#ifndef ROCKSDB_LITE
// In https://reviews.facebook.net/D20661 we change // In https://reviews.facebook.net/D20661 we change
// recovery behavior: previously for each log file each column family // recovery behavior: previously for each log file each column family
// memtable was flushed, even it was empty. Now it's changed: // memtable was flushed, even it was empty. Now it's changed:
@ -5011,6 +4957,7 @@ TEST_F(DBTest, SharedWriteBuffer) {
static_cast<uint64_t>(4)); static_cast<uint64_t>(4));
} }
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, PurgeInfoLogs) { TEST_F(DBTest, PurgeInfoLogs) {
Options options = CurrentOptions(); Options options = CurrentOptions();
@ -5083,6 +5030,7 @@ TEST_F(DBTest, SyncMultipleLogs) {
ASSERT_OK(dbfull()->SyncWAL()); ASSERT_OK(dbfull()->SyncWAL());
} }
#ifndef ROCKSDB_LITE
// //
// Test WAL recovery for the various modes available // Test WAL recovery for the various modes available
// //
@ -5365,7 +5313,6 @@ TEST_F(DBTest, kSkipAnyCorruptedRecords) {
} }
} }
// Multi-threaded test: // Multi-threaded test:
namespace { namespace {
@ -5532,6 +5479,7 @@ TEST_P(MultiThreadedDBTest, MultiThreaded) {
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
MultiThreaded, MultiThreadedDBTest, MultiThreaded, MultiThreadedDBTest,
::testing::ValuesIn(MultiThreadedDBTest::GenerateOptionConfigs())); ::testing::ValuesIn(MultiThreadedDBTest::GenerateOptionConfigs()));
#endif // ROCKSDB_LITE
// Group commit test: // Group commit test:
namespace { namespace {
@ -5672,6 +5620,7 @@ class ModelDB: public DB {
return s; return s;
} }
#ifndef ROCKSDB_LITE
using DB::AddFile; using DB::AddFile;
virtual Status AddFile(ColumnFamilyHandle* column_family, virtual Status AddFile(ColumnFamilyHandle* column_family,
const ExternalSstFileInfo* file_path, const ExternalSstFileInfo* file_path,
@ -5691,6 +5640,13 @@ class ModelDB: public DB {
return Status(); return Status();
} }
virtual Status GetPropertiesOfTablesInRange(
ColumnFamilyHandle* column_family, const Range* range, std::size_t n,
TablePropertiesCollection* props) override {
return Status();
}
#endif // ROCKSDB_LITE
using DB::KeyMayExist; using DB::KeyMayExist;
virtual bool KeyMayExist(const ReadOptions& options, virtual bool KeyMayExist(const ReadOptions& options,
ColumnFamilyHandle* column_family, const Slice& key, ColumnFamilyHandle* column_family, const Slice& key,
@ -5834,7 +5790,9 @@ class ModelDB: public DB {
return Status::OK(); return Status::OK();
} }
#ifndef ROCKSDB_LITE
virtual Status DisableFileDeletions() override { return Status::OK(); } virtual Status DisableFileDeletions() override { return Status::OK(); }
virtual Status EnableFileDeletions(bool force) override { virtual Status EnableFileDeletions(bool force) override {
return Status::OK(); return Status::OK();
} }
@ -5849,11 +5807,6 @@ class ModelDB: public DB {
virtual Status DeleteFile(std::string name) override { return Status::OK(); } virtual Status DeleteFile(std::string name) override { return Status::OK(); }
virtual Status GetDbIdentity(std::string& identity) const override {
return Status::OK();
}
virtual SequenceNumber GetLatestSequenceNumber() const override { return 0; }
virtual Status GetUpdatesSince( virtual Status GetUpdatesSince(
rocksdb::SequenceNumber, unique_ptr<rocksdb::TransactionLogIterator>*, rocksdb::SequenceNumber, unique_ptr<rocksdb::TransactionLogIterator>*,
const TransactionLogIterator::ReadOptions& const TransactionLogIterator::ReadOptions&
@ -5861,13 +5814,20 @@ class ModelDB: public DB {
return Status::NotSupported("Not supported in Model DB"); return Status::NotSupported("Not supported in Model DB");
} }
virtual ColumnFamilyHandle* DefaultColumnFamily() const override {
return nullptr;
}
virtual void GetColumnFamilyMetaData( virtual void GetColumnFamilyMetaData(
ColumnFamilyHandle* column_family, ColumnFamilyHandle* column_family,
ColumnFamilyMetaData* metadata) override {} ColumnFamilyMetaData* metadata) override {}
#endif // ROCKSDB_LITE
virtual Status GetDbIdentity(std::string& identity) const override {
return Status::OK();
}
virtual SequenceNumber GetLatestSequenceNumber() const override { return 0; }
virtual ColumnFamilyHandle* DefaultColumnFamily() const override {
return nullptr;
}
private: private:
class ModelIter: public Iterator { class ModelIter: public Iterator {
@ -6128,6 +6088,7 @@ TEST_F(DBTest, MultiGetEmpty) {
} while (ChangeCompactOptions()); } while (ChangeCompactOptions());
} }
#ifndef ROCKSDB_LITE
namespace { namespace {
void PrefixScanInit(DBTest *dbtest) { void PrefixScanInit(DBTest *dbtest) {
char buf[100]; char buf[100];
@ -6230,6 +6191,7 @@ TEST_F(DBTest, PrefixScan) {
} // end of while } // end of while
XFUNC_TEST("", "dbtest_prefix", prefix_skip1, XFuncPoint::SetSkip, 0); XFUNC_TEST("", "dbtest_prefix", prefix_skip1, XFuncPoint::SetSkip, 0);
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, BlockBasedTablePrefixIndexTest) { TEST_F(DBTest, BlockBasedTablePrefixIndexTest) {
// create a DB with block prefix index // create a DB with block prefix index
@ -6291,6 +6253,7 @@ TEST_F(DBTest, ChecksumTest) {
ASSERT_EQ("h", Get("g")); ASSERT_EQ("h", Get("g"));
} }
#ifndef ROCKSDB_LITE
TEST_P(DBTestWithParam, FIFOCompactionTest) { TEST_P(DBTestWithParam, FIFOCompactionTest) {
for (int iter = 0; iter < 2; ++iter) { for (int iter = 0; iter < 2; ++iter) {
// first iteration -- auto compaction // first iteration -- auto compaction
@ -6330,6 +6293,7 @@ TEST_P(DBTestWithParam, FIFOCompactionTest) {
} }
} }
} }
#endif // ROCKSDB_LITE
// verify that we correctly deprecated timeout_hint_us // verify that we correctly deprecated timeout_hint_us
TEST_F(DBTest, SimpleWriteTimeoutTest) { TEST_F(DBTest, SimpleWriteTimeoutTest) {
@ -6340,6 +6304,7 @@ TEST_F(DBTest, SimpleWriteTimeoutTest) {
ASSERT_NOK(Put(Key(1), Key(1) + std::string(100, 'v'), write_opt)); ASSERT_NOK(Put(Key(1), Key(1) + std::string(100, 'v'), write_opt));
} }
#ifndef ROCKSDB_LITE
/* /*
* This test is not reliable enough as it heavily depends on disk behavior. * This test is not reliable enough as it heavily depends on disk behavior.
*/ */
@ -6432,6 +6397,7 @@ TEST_F(DBTest, TableOptionsSanitizeTest) {
options.prefix_extractor.reset(NewFixedPrefixTransform(1)); options.prefix_extractor.reset(NewFixedPrefixTransform(1));
ASSERT_OK(TryReopen(options)); ASSERT_OK(TryReopen(options));
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, SanitizeNumThreads) { TEST_F(DBTest, SanitizeNumThreads) {
for (int attempt = 0; attempt < 2; attempt++) { for (int attempt = 0; attempt < 2; attempt++) {
@ -6677,6 +6643,7 @@ TEST_F(DBTest, DisableDataSyncTest) {
} }
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, DynamicMemtableOptions) { TEST_F(DBTest, DynamicMemtableOptions) {
const uint64_t k64KB = 1 << 16; const uint64_t k64KB = 1 << 16;
const uint64_t k128KB = 1 << 17; const uint64_t k128KB = 1 << 17;
@ -6818,6 +6785,7 @@ TEST_F(DBTest, DynamicMemtableOptions) {
rocksdb::SyncPoint::GetInstance()->DisableProcessing(); rocksdb::SyncPoint::GetInstance()->DisableProcessing();
} }
#endif // ROCKSDB_LITE
#if ROCKSDB_USING_THREAD_STATUS #if ROCKSDB_USING_THREAD_STATUS
namespace { namespace {
@ -6926,6 +6894,10 @@ TEST_F(DBTest, ThreadStatusFlush) {
ASSERT_EQ("v1", Get(1, "foo")); ASSERT_EQ("v1", Get(1, "foo"));
VerifyOperationCount(env_, ThreadStatus::OP_FLUSH, 0); VerifyOperationCount(env_, ThreadStatus::OP_FLUSH, 0);
uint64_t num_running_flushes = 0;
db_->GetIntProperty(DB::Properties::kNumRunningFlushes, &num_running_flushes);
ASSERT_EQ(num_running_flushes, 0);
Put(1, "k1", std::string(100000, 'x')); // Fill memtable Put(1, "k1", std::string(100000, 'x')); // Fill memtable
Put(1, "k2", std::string(100000, 'y')); // Trigger flush Put(1, "k2", std::string(100000, 'y')); // Trigger flush
@ -6933,10 +6905,11 @@ TEST_F(DBTest, ThreadStatusFlush) {
// running when we perform VerifyOperationCount(). // running when we perform VerifyOperationCount().
TEST_SYNC_POINT("DBTest::ThreadStatusFlush:1"); TEST_SYNC_POINT("DBTest::ThreadStatusFlush:1");
VerifyOperationCount(env_, ThreadStatus::OP_FLUSH, 1); VerifyOperationCount(env_, ThreadStatus::OP_FLUSH, 1);
db_->GetIntProperty(DB::Properties::kNumRunningFlushes, &num_running_flushes);
ASSERT_EQ(num_running_flushes, 1);
// This second sync point is to ensure the flush job will not // This second sync point is to ensure the flush job will not
// be completed until we already perform VerifyOperationCount(). // be completed until we already perform VerifyOperationCount().
TEST_SYNC_POINT("DBTest::ThreadStatusFlush:2"); TEST_SYNC_POINT("DBTest::ThreadStatusFlush:2");
rocksdb::SyncPoint::GetInstance()->DisableProcessing(); rocksdb::SyncPoint::GetInstance()->DisableProcessing();
} }
@ -6981,6 +6954,10 @@ TEST_P(DBTestWithParam, ThreadStatusSingleCompaction) {
} }
// This makes sure a compaction won't be scheduled until // This makes sure a compaction won't be scheduled until
// we have done with the above Put Phase. // we have done with the above Put Phase.
uint64_t num_running_compactions = 0;
db_->GetIntProperty(DB::Properties::kNumRunningCompactions,
&num_running_compactions);
ASSERT_EQ(num_running_compactions, 0);
TEST_SYNC_POINT("DBTest::ThreadStatusSingleCompaction:0"); TEST_SYNC_POINT("DBTest::ThreadStatusSingleCompaction:0");
ASSERT_GE(NumTableFilesAtLevel(0), ASSERT_GE(NumTableFilesAtLevel(0),
options.level0_file_num_compaction_trigger); options.level0_file_num_compaction_trigger);
@ -6995,6 +6972,9 @@ TEST_P(DBTestWithParam, ThreadStatusSingleCompaction) {
// If thread tracking is not enabled, compaction count should be 0. // If thread tracking is not enabled, compaction count should be 0.
VerifyOperationCount(env_, ThreadStatus::OP_COMPACTION, 0); VerifyOperationCount(env_, ThreadStatus::OP_COMPACTION, 0);
} }
db_->GetIntProperty(DB::Properties::kNumRunningCompactions,
&num_running_compactions);
ASSERT_EQ(num_running_compactions, 1);
// TODO(yhchiang): adding assert to verify each compaction stage. // TODO(yhchiang): adding assert to verify each compaction stage.
TEST_SYNC_POINT("DBTest::ThreadStatusSingleCompaction:2"); TEST_SYNC_POINT("DBTest::ThreadStatusSingleCompaction:2");
@ -7243,6 +7223,7 @@ TEST_P(DBTestWithParam, PreShutdownCompactionMiddle) {
#endif // ROCKSDB_USING_THREAD_STATUS #endif // ROCKSDB_USING_THREAD_STATUS
#ifndef ROCKSDB_LITE
TEST_F(DBTest, FlushOnDestroy) { TEST_F(DBTest, FlushOnDestroy) {
WriteOptions wo; WriteOptions wo;
wo.disableWAL = true; wo.disableWAL = true;
@ -7696,6 +7677,7 @@ TEST_F(DBTest, DynamicCompactionOptions) {
rocksdb::SyncPoint::GetInstance()->DisableProcessing(); rocksdb::SyncPoint::GetInstance()->DisableProcessing();
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, FileCreationRandomFailure) { TEST_F(DBTest, FileCreationRandomFailure) {
Options options; Options options;
@ -7757,6 +7739,7 @@ TEST_F(DBTest, FileCreationRandomFailure) {
} }
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, DynamicMiscOptions) { TEST_F(DBTest, DynamicMiscOptions) {
// Test max_sequential_skip_in_iterations // Test max_sequential_skip_in_iterations
Options options; Options options;
@ -7806,6 +7789,7 @@ TEST_F(DBTest, DynamicMiscOptions) {
// No reseek // No reseek
assert_reseek_count(300, 1); assert_reseek_count(300, 1);
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, DontDeletePendingOutputs) { TEST_F(DBTest, DontDeletePendingOutputs) {
Options options; Options options;
@ -7839,6 +7823,7 @@ TEST_F(DBTest, DontDeletePendingOutputs) {
Compact("a", "b"); Compact("a", "b");
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, DontDeleteMovedFile) { TEST_F(DBTest, DontDeleteMovedFile) {
// This test triggers move compaction and verifies that the file is not // This test triggers move compaction and verifies that the file is not
// deleted when it's part of move compaction // deleted when it's part of move compaction
@ -7941,6 +7926,7 @@ TEST_F(DBTest, OptimizeFiltersForHits) {
ASSERT_EQ(Get(1, Key(i)), "val"); ASSERT_EQ(Get(1, Key(i)), "val");
} }
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, L0L1L2AndUpHitCounter) { TEST_F(DBTest, L0L1L2AndUpHitCounter) {
Options options = CurrentOptions(); Options options = CurrentOptions();
@ -8040,6 +8026,7 @@ TEST_F(DBTest, MutexWaitStats) {
ThreadStatus::STATE_MUTEX_WAIT, 0); ThreadStatus::STATE_MUTEX_WAIT, 0);
} }
#ifndef ROCKSDB_LITE
// This reproduces a bug where we don't delete a file because when it was // This reproduces a bug where we don't delete a file because when it was
// supposed to be deleted, it was blocked by pending_outputs // supposed to be deleted, it was blocked by pending_outputs
// Consider: // Consider:
@ -8135,6 +8122,7 @@ TEST_F(DBTest, DeleteObsoleteFilesPendingOutputs) {
ASSERT_EQ(Status::NotFound(), env_->FileExists(dbname_ + file_on_L2)); ASSERT_EQ(Status::NotFound(), env_->FileExists(dbname_ + file_on_L2));
listener->VerifyMatchedCount(1); listener->VerifyMatchedCount(1);
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, CloseSpeedup) { TEST_F(DBTest, CloseSpeedup) {
Options options = CurrentOptions(); Options options = CurrentOptions();
@ -8256,6 +8244,7 @@ TEST_F(DBTest, MergeTestTime) {
#endif // ROCKSDB_USING_THREAD_STATUS #endif // ROCKSDB_USING_THREAD_STATUS
} }
#ifndef ROCKSDB_LITE
TEST_P(DBTestWithParam, MergeCompactionTimeTest) { TEST_P(DBTestWithParam, MergeCompactionTimeTest) {
SetPerfLevel(kEnableTime); SetPerfLevel(kEnableTime);
Options options; Options options;
@ -8306,6 +8295,7 @@ TEST_P(DBTestWithParam, FilterCompactionTimeTest) {
ASSERT_NE(TestGetTickerCount(options, FILTER_OPERATION_TOTAL_TIME), 0); ASSERT_NE(TestGetTickerCount(options, FILTER_OPERATION_TOTAL_TIME), 0);
delete itr; delete itr;
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, TestLogCleanup) { TEST_F(DBTest, TestLogCleanup) {
Options options = CurrentOptions(); Options options = CurrentOptions();
@ -8322,6 +8312,7 @@ TEST_F(DBTest, TestLogCleanup) {
} }
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, EmptyCompactedDB) { TEST_F(DBTest, EmptyCompactedDB) {
Options options; Options options;
options.max_open_files = -1; options.max_open_files = -1;
@ -8332,6 +8323,7 @@ TEST_F(DBTest, EmptyCompactedDB) {
ASSERT_TRUE(s.IsNotSupported()); ASSERT_TRUE(s.IsNotSupported());
Close(); Close();
} }
#endif // ROCKSDB_LITE
class CountingDeleteTabPropCollector : public TablePropertiesCollector { class CountingDeleteTabPropCollector : public TablePropertiesCollector {
public: public:
@ -8373,6 +8365,7 @@ class CountingDeleteTabPropCollectorFactory
} }
}; };
#ifndef ROCKSDB_LITE
TEST_F(DBTest, TablePropertiesNeedCompactTest) { TEST_F(DBTest, TablePropertiesNeedCompactTest) {
Random rnd(301); Random rnd(301);
@ -8671,6 +8664,7 @@ TEST_F(DBTest, PromoteL0Failure) {
status = experimental::PromoteL0(db_, db_->DefaultColumnFamily()); status = experimental::PromoteL0(db_, db_->DefaultColumnFamily());
ASSERT_TRUE(status.IsInvalidArgument()); ASSERT_TRUE(status.IsInvalidArgument());
} }
#endif // ROCKSDB_LITE
// Github issue #596 // Github issue #596
TEST_F(DBTest, HugeNumberOfLevels) { TEST_F(DBTest, HugeNumberOfLevels) {
@ -8877,6 +8871,7 @@ TEST_F(DBTest, HardLimit) {
rocksdb::SyncPoint::GetInstance()->DisableProcessing(); rocksdb::SyncPoint::GetInstance()->DisableProcessing();
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, SoftLimit) { TEST_F(DBTest, SoftLimit) {
Options options; Options options;
options.env = env_; options.env = env_;
@ -8996,6 +8991,7 @@ TEST_F(DBTest, SoftLimit) {
ASSERT_EQ(sleep_count.load(), 0); ASSERT_EQ(sleep_count.load(), 0);
rocksdb::SyncPoint::GetInstance()->DisableProcessing(); rocksdb::SyncPoint::GetInstance()->DisableProcessing();
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, FailWhenCompressionNotSupportedTest) { TEST_F(DBTest, FailWhenCompressionNotSupportedTest) {
CompressionType compressions[] = {kZlibCompression, kBZip2Compression, CompressionType compressions[] = {kZlibCompression, kBZip2Compression,
@ -9017,6 +9013,7 @@ TEST_F(DBTest, FailWhenCompressionNotSupportedTest) {
} }
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, RowCache) { TEST_F(DBTest, RowCache) {
Options options = CurrentOptions(); Options options = CurrentOptions();
options.statistics = rocksdb::CreateDBStatistics(); options.statistics = rocksdb::CreateDBStatistics();
@ -9035,6 +9032,7 @@ TEST_F(DBTest, RowCache) {
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), 1); ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_HIT), 1);
ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), 1); ASSERT_EQ(TestGetTickerCount(options, ROW_CACHE_MISS), 1);
} }
#endif // ROCKSDB_LITE
// TODO(3.13): fix the issue of Seek() + Prev() which might not necessary // TODO(3.13): fix the issue of Seek() + Prev() which might not necessary
// return the biggest key which is smaller than the seek key. // return the biggest key which is smaller than the seek key.
@ -9095,6 +9093,7 @@ TEST_F(DBTest, DeletingOldWalAfterDrop) {
EXPECT_GT(lognum2, lognum1); EXPECT_GT(lognum2, lognum1);
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, RateLimitedDelete) { TEST_F(DBTest, RateLimitedDelete) {
rocksdb::SyncPoint::GetInstance()->LoadDependency({ rocksdb::SyncPoint::GetInstance()->LoadDependency({
{"DBTest::RateLimitedDelete:1", {"DBTest::RateLimitedDelete:1",
@ -9263,6 +9262,7 @@ TEST_F(DBTest, DestroyDBWithRateLimitedDelete) {
// We have deleted the 4 sst files in the delete_scheduler // We have deleted the 4 sst files in the delete_scheduler
ASSERT_EQ(bg_delete_file, 4); ASSERT_EQ(bg_delete_file, 4);
} }
#endif // ROCKSDB_LITE
TEST_F(DBTest, UnsupportedManualSync) { TEST_F(DBTest, UnsupportedManualSync) {
DestroyAndReopen(CurrentOptions()); DestroyAndReopen(CurrentOptions());
@ -9271,6 +9271,7 @@ TEST_F(DBTest, UnsupportedManualSync) {
ASSERT_TRUE(s.IsNotSupported()); ASSERT_TRUE(s.IsNotSupported());
} }
#ifndef ROCKSDB_LITE
TEST_F(DBTest, OpenDBWithInfiniteMaxOpenFiles) { TEST_F(DBTest, OpenDBWithInfiniteMaxOpenFiles) {
// Open DB with infinite max open files // Open DB with infinite max open files
// - First iteration use 1 thread to open files // - First iteration use 1 thread to open files
@ -9815,6 +9816,7 @@ TEST_F(DBTest, AddExternalSstFileMultiThreaded) {
} while (ChangeOptions(kSkipPlainTable | kSkipUniversalCompaction | } while (ChangeOptions(kSkipPlainTable | kSkipUniversalCompaction |
kSkipFIFOCompaction)); kSkipFIFOCompaction));
} }
#endif // ROCKSDB_LITE
// 1 Create some SST files by inserting K-V pairs into DB // 1 Create some SST files by inserting K-V pairs into DB
// 2 Close DB and change suffix from ".sst" to ".ldb" for every other SST file // 2 Close DB and change suffix from ".sst" to ".ldb" for every other SST file
@ -10222,6 +10224,47 @@ TEST_F(DBTest, WalFilterTestWithChangeBatch) {
} }
#endif // ROCKSDB_LITE #endif // ROCKSDB_LITE
#ifndef ROCKSDB_LITE
class BloomStatsTestWithParam
: public DBTest,
public testing::WithParamInterface<std::tuple<bool, bool>> {
public:
BloomStatsTestWithParam() {
use_block_table_ = std::get<0>(GetParam());
use_block_based_builder_ = std::get<1>(GetParam());
options_.create_if_missing = true;
options_.prefix_extractor.reset(rocksdb::NewFixedPrefixTransform(4));
options_.memtable_prefix_bloom_bits = 8 * 1024;
if (use_block_table_) {
BlockBasedTableOptions table_options;
table_options.hash_index_allow_collision = false;
table_options.filter_policy.reset(
NewBloomFilterPolicy(10, use_block_based_builder_));
options_.table_factory.reset(NewBlockBasedTableFactory(table_options));
} else {
PlainTableOptions table_options;
options_.table_factory.reset(NewPlainTableFactory(table_options));
}
perf_context.Reset();
DestroyAndReopen(options_);
}
~BloomStatsTestWithParam() {
perf_context.Reset();
Destroy(options_);
}
// Required if inheriting from testing::WithParamInterface<>
static void SetUpTestCase() {}
static void TearDownTestCase() {}
bool use_block_table_;
bool use_block_based_builder_;
Options options_;
};
// 1 Insert 2 K-V pairs into DB // 1 Insert 2 K-V pairs into DB
// 2 Call Get() for both keys - expext memtable bloom hit stat to be 2 // 2 Call Get() for both keys - expext memtable bloom hit stat to be 2
// 3 Call Get() for nonexisting key - expect memtable bloom miss stat to be 1 // 3 Call Get() for nonexisting key - expect memtable bloom miss stat to be 1
@ -10335,6 +10378,7 @@ INSTANTIATE_TEST_CASE_P(BloomStatsTestWithParam, BloomStatsTestWithParam,
::testing::Values(std::make_tuple(true, true), ::testing::Values(std::make_tuple(true, true),
std::make_tuple(true, false), std::make_tuple(true, false),
std::make_tuple(false, false))); std::make_tuple(false, false)));
#endif // ROCKSDB_LITE
} // namespace rocksdb } // namespace rocksdb
#endif #endif

@ -38,10 +38,9 @@ SpecialEnv::SpecialEnv(Env* base)
table_write_callback_ = nullptr; table_write_callback_ = nullptr;
} }
DBTestBase::DBTestBase(const std::string path)
DBTestBase::DBTestBase(const std::string path) : option_config_(kDefault), : option_config_(kDefault),
mem_env_(!getenv("MEM_ENV") ? nullptr : mem_env_(!getenv("MEM_ENV") ? nullptr : new MockEnv(Env::Default())),
new MockEnv(Env::Default())),
env_(new SpecialEnv(mem_env_ ? mem_env_ : Env::Default())) { env_(new SpecialEnv(mem_env_ ? mem_env_ : Env::Default())) {
env_->SetBackgroundThreads(1, Env::LOW); env_->SetBackgroundThreads(1, Env::LOW);
env_->SetBackgroundThreads(1, Env::HIGH); env_->SetBackgroundThreads(1, Env::HIGH);
@ -79,6 +78,23 @@ DBTestBase::~DBTestBase() {
// test. Return false if there are no more configurations to test. // test. Return false if there are no more configurations to test.
bool DBTestBase::ChangeOptions(int skip_mask) { bool DBTestBase::ChangeOptions(int skip_mask) {
for (option_config_++; option_config_ < kEnd; option_config_++) { for (option_config_++; option_config_ < kEnd; option_config_++) {
#ifdef ROCKSDB_LITE
// These options are not supported in ROCKSDB_LITE
if (option_config_ == kHashSkipList ||
option_config_ == kPlainTableFirstBytePrefix ||
option_config_ == kPlainTableCappedPrefix ||
option_config_ == kPlainTableCappedPrefixNonMmap ||
option_config_ == kPlainTableAllBytesPrefix ||
option_config_ == kVectorRep || option_config_ == kHashLinkList ||
option_config_ == kHashCuckoo ||
option_config_ == kUniversalCompaction ||
option_config_ == kUniversalCompactionMultiLevel ||
option_config_ == kUniversalSubcompactions ||
option_config_ == kFIFOCompaction) {
continue;
}
#endif
if ((skip_mask & kSkipDeletesFilterFirst) && if ((skip_mask & kSkipDeletesFilterFirst) &&
option_config_ == kDeletesFilterFirst) { option_config_ == kDeletesFilterFirst) {
continue; continue;
@ -92,8 +108,7 @@ bool DBTestBase::ChangeOptions(int skip_mask) {
continue; continue;
} }
if ((skip_mask & kSkipNoSeekToLast) && if ((skip_mask & kSkipNoSeekToLast) &&
(option_config_ == kHashLinkList || (option_config_ == kHashLinkList || option_config_ == kHashSkipList)) {
option_config_ == kHashSkipList)) {;
continue; continue;
} }
if ((skip_mask & kSkipPlainTable) && if ((skip_mask & kSkipPlainTable) &&
@ -115,8 +130,7 @@ bool DBTestBase::ChangeOptions(int skip_mask) {
option_config_ == kFIFOCompaction) { option_config_ == kFIFOCompaction) {
continue; continue;
} }
if ((skip_mask & kSkipMmapReads) && if ((skip_mask & kSkipMmapReads) && option_config_ == kWalDirAndMmapReads) {
option_config_ == kWalDirAndMmapReads) {
continue; continue;
} }
break; break;
@ -205,10 +219,10 @@ Options DBTestBase::CurrentOptions(
BlockBasedTableOptions table_options; BlockBasedTableOptions table_options;
bool set_block_based_table_factory = true; bool set_block_based_table_factory = true;
switch (option_config_) { switch (option_config_) {
#ifndef ROCKSDB_LITE
case kHashSkipList: case kHashSkipList:
options.prefix_extractor.reset(NewFixedPrefixTransform(1)); options.prefix_extractor.reset(NewFixedPrefixTransform(1));
options.memtable_factory.reset( options.memtable_factory.reset(NewHashSkipListRepFactory(16));
NewHashSkipListRepFactory(16));
break; break;
case kPlainTableFirstBytePrefix: case kPlainTableFirstBytePrefix:
options.table_factory.reset(new PlainTableFactory()); options.table_factory.reset(new PlainTableFactory());
@ -238,6 +252,19 @@ Options DBTestBase::CurrentOptions(
options.max_sequential_skip_in_iterations = 999999; options.max_sequential_skip_in_iterations = 999999;
set_block_based_table_factory = false; set_block_based_table_factory = false;
break; break;
case kVectorRep:
options.memtable_factory.reset(new VectorRepFactory(100));
break;
case kHashLinkList:
options.prefix_extractor.reset(NewFixedPrefixTransform(1));
options.memtable_factory.reset(
NewHashLinkListRepFactory(4, 0, 3, true, 4));
break;
case kHashCuckoo:
options.memtable_factory.reset(
NewHashCuckooRepFactory(options.write_buffer_size));
break;
#endif // ROCKSDB_LITE
case kMergePut: case kMergePut:
options.merge_operator = MergeOperators::CreatePutOperator(); options.merge_operator = MergeOperators::CreatePutOperator();
break; break;
@ -274,18 +301,6 @@ Options DBTestBase::CurrentOptions(
case kDeletesFilterFirst: case kDeletesFilterFirst:
options.filter_deletes = true; options.filter_deletes = true;
break; break;
case kVectorRep:
options.memtable_factory.reset(new VectorRepFactory(100));
break;
case kHashLinkList:
options.prefix_extractor.reset(NewFixedPrefixTransform(1));
options.memtable_factory.reset(
NewHashLinkListRepFactory(4, 0, 3, true, 4));
break;
case kHashCuckoo:
options.memtable_factory.reset(
NewHashCuckooRepFactory(options.write_buffer_size));
break;
case kUniversalCompaction: case kUniversalCompaction:
options.compaction_style = kCompactionStyleUniversal; options.compaction_style = kCompactionStyleUniversal;
options.num_levels = 1; options.num_levels = 1;
@ -383,8 +398,7 @@ void DBTestBase::ReopenWithColumnFamilies(const std::vector<std::string>& cfs,
} }
Status DBTestBase::TryReopenWithColumnFamilies( Status DBTestBase::TryReopenWithColumnFamilies(
const std::vector<std::string>& cfs, const std::vector<std::string>& cfs, const std::vector<Options>& options) {
const std::vector<Options>& options) {
Close(); Close();
EXPECT_EQ(cfs.size(), options.size()); EXPECT_EQ(cfs.size(), options.size());
std::vector<ColumnFamilyDescriptor> column_families; std::vector<ColumnFamilyDescriptor> column_families;
@ -396,8 +410,7 @@ Status DBTestBase::TryReopenWithColumnFamilies(
} }
Status DBTestBase::TryReopenWithColumnFamilies( Status DBTestBase::TryReopenWithColumnFamilies(
const std::vector<std::string>& cfs, const std::vector<std::string>& cfs, const Options& options) {
const Options& options) {
Close(); Close();
std::vector<Options> v_opts(cfs.size(), options); std::vector<Options> v_opts(cfs.size(), options);
return TryReopenWithColumnFamilies(cfs, v_opts); return TryReopenWithColumnFamilies(cfs, v_opts);
@ -552,9 +565,9 @@ std::string DBTestBase::AllEntriesFor(const Slice& user_key, int cf) {
Arena arena; Arena arena;
ScopedArenaIterator iter; ScopedArenaIterator iter;
if (cf == 0) { if (cf == 0) {
iter.set(dbfull()->TEST_NewInternalIterator(&arena)); iter.set(dbfull()->NewInternalIterator(&arena));
} else { } else {
iter.set(dbfull()->TEST_NewInternalIterator(&arena, handles_[cf])); iter.set(dbfull()->NewInternalIterator(&arena, handles_[cf]));
} }
InternalKey target(user_key, kMaxSequenceNumber, kTypeValue); InternalKey target(user_key, kMaxSequenceNumber, kTypeValue);
iter->Seek(target.Encode()); iter->Seek(target.Encode());
@ -605,6 +618,7 @@ std::string DBTestBase::AllEntriesFor(const Slice& user_key, int cf) {
return result; return result;
} }
#ifndef ROCKSDB_LITE
int DBTestBase::NumSortedRuns(int cf) { int DBTestBase::NumSortedRuns(int cf) {
ColumnFamilyMetaData cf_meta; ColumnFamilyMetaData cf_meta;
if (cf == 0) { if (cf == 0) {
@ -631,20 +645,6 @@ uint64_t DBTestBase::TotalSize(int cf) {
return cf_meta.size; return cf_meta.size;
} }
int DBTestBase::NumTableFilesAtLevel(int level, int cf) {
std::string property;
if (cf == 0) {
// default cfd
EXPECT_TRUE(db_->GetProperty(
"rocksdb.num-files-at-level" + NumberToString(level), &property));
} else {
EXPECT_TRUE(db_->GetProperty(
handles_[cf], "rocksdb.num-files-at-level" + NumberToString(level),
&property));
}
return atoi(property.c_str());
}
uint64_t DBTestBase::SizeAtLevel(int level) { uint64_t DBTestBase::SizeAtLevel(int level) {
std::vector<LiveFileMetaData> metadata; std::vector<LiveFileMetaData> metadata;
db_->GetLiveFilesMetaData(&metadata); db_->GetLiveFilesMetaData(&metadata);
@ -671,6 +671,27 @@ int DBTestBase::TotalLiveFiles(int cf) {
return num_files; return num_files;
} }
size_t DBTestBase::CountLiveFiles() {
std::vector<LiveFileMetaData> metadata;
db_->GetLiveFilesMetaData(&metadata);
return metadata.size();
}
#endif // ROCKSDB_LITE
int DBTestBase::NumTableFilesAtLevel(int level, int cf) {
std::string property;
if (cf == 0) {
// default cfd
EXPECT_TRUE(db_->GetProperty(
"rocksdb.num-files-at-level" + NumberToString(level), &property));
} else {
EXPECT_TRUE(db_->GetProperty(
handles_[cf], "rocksdb.num-files-at-level" + NumberToString(level),
&property));
}
return atoi(property.c_str());
}
int DBTestBase::TotalTableFiles(int cf, int levels) { int DBTestBase::TotalTableFiles(int cf, int levels) {
if (levels == -1) { if (levels == -1) {
levels = CurrentOptions().num_levels; levels = CurrentOptions().num_levels;
@ -713,12 +734,6 @@ size_t DBTestBase::CountFiles() {
return files.size() + logfiles.size(); return files.size() + logfiles.size();
} }
size_t DBTestBase::CountLiveFiles() {
std::vector<LiveFileMetaData> metadata;
db_->GetLiveFilesMetaData(&metadata);
return metadata.size();
}
uint64_t DBTestBase::Size(const Slice& start, const Slice& limit, int cf) { uint64_t DBTestBase::Size(const Slice& start, const Slice& limit, int cf) {
Range r(start, limit); Range r(start, limit);
uint64_t size; uint64_t size;
@ -748,8 +763,7 @@ void DBTestBase::Compact(const Slice& start, const Slice& limit) {
// Do n memtable compactions, each of which produces an sstable // Do n memtable compactions, each of which produces an sstable
// covering the range [small,large]. // covering the range [small,large].
void DBTestBase::MakeTables( void DBTestBase::MakeTables(int n, const std::string& small,
int n, const std::string& small,
const std::string& large, int cf) { const std::string& large, int cf) {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
ASSERT_OK(Put(cf, small, "begin")); ASSERT_OK(Put(cf, small, "begin"));
@ -761,8 +775,8 @@ void DBTestBase::MakeTables(
// Prevent pushing of new sstables into deeper levels by adding // Prevent pushing of new sstables into deeper levels by adding
// tables that cover a specified range to all levels. // tables that cover a specified range to all levels.
void DBTestBase::FillLevels( void DBTestBase::FillLevels(const std::string& smallest,
const std::string& smallest, const std::string& largest, int cf) { const std::string& largest, int cf) {
MakeTables(db_->NumberLevels(handles_[cf]), smallest, largest, cf); MakeTables(db_->NumberLevels(handles_[cf]), smallest, largest, cf);
} }
@ -888,9 +902,10 @@ void DBTestBase::VerifyIterLast(std::string expected_key, int cf) {
// sets newValue with delta // sets newValue with delta
// If previous value is not empty, // If previous value is not empty,
// updates previous value with 'b' string of previous value size - 1. // updates previous value with 'b' string of previous value size - 1.
UpdateStatus DBTestBase::updateInPlaceSmallerSize( UpdateStatus DBTestBase::updateInPlaceSmallerSize(char* prevValue,
char* prevValue, uint32_t* prevSize, uint32_t* prevSize,
Slice delta, std::string* newValue) { Slice delta,
std::string* newValue) {
if (prevValue == nullptr) { if (prevValue == nullptr) {
*newValue = std::string(delta.size(), 'c'); *newValue = std::string(delta.size(), 'c');
return UpdateStatus::UPDATED; return UpdateStatus::UPDATED;
@ -902,9 +917,10 @@ UpdateStatus DBTestBase::updateInPlaceSmallerSize(
} }
} }
UpdateStatus DBTestBase::updateInPlaceSmallerVarintSize( UpdateStatus DBTestBase::updateInPlaceSmallerVarintSize(char* prevValue,
char* prevValue, uint32_t* prevSize, uint32_t* prevSize,
Slice delta, std::string* newValue) { Slice delta,
std::string* newValue) {
if (prevValue == nullptr) { if (prevValue == nullptr) {
*newValue = std::string(delta.size(), 'c'); *newValue = std::string(delta.size(), 'c');
return UpdateStatus::UPDATED; return UpdateStatus::UPDATED;
@ -916,16 +932,17 @@ UpdateStatus DBTestBase::updateInPlaceSmallerVarintSize(
} }
} }
UpdateStatus DBTestBase::updateInPlaceLargerSize( UpdateStatus DBTestBase::updateInPlaceLargerSize(char* prevValue,
char* prevValue, uint32_t* prevSize, uint32_t* prevSize,
Slice delta, std::string* newValue) { Slice delta,
std::string* newValue) {
*newValue = std::string(delta.size(), 'c'); *newValue = std::string(delta.size(), 'c');
return UpdateStatus::UPDATED; return UpdateStatus::UPDATED;
} }
UpdateStatus DBTestBase::updateInPlaceNoAction( UpdateStatus DBTestBase::updateInPlaceNoAction(char* prevValue,
char* prevValue, uint32_t* prevSize, uint32_t* prevSize, Slice delta,
Slice delta, std::string* newValue) { std::string* newValue) {
return UpdateStatus::UPDATE_FAILED; return UpdateStatus::UPDATE_FAILED;
} }
@ -934,9 +951,9 @@ void DBTestBase::validateNumberOfEntries(int numValues, int cf) {
ScopedArenaIterator iter; ScopedArenaIterator iter;
Arena arena; Arena arena;
if (cf != 0) { if (cf != 0) {
iter.set(dbfull()->TEST_NewInternalIterator(&arena, handles_[cf])); iter.set(dbfull()->NewInternalIterator(&arena, handles_[cf]));
} else { } else {
iter.set(dbfull()->TEST_NewInternalIterator(&arena)); iter.set(dbfull()->NewInternalIterator(&arena));
} }
iter->SeekToFirst(); iter->SeekToFirst();
ASSERT_EQ(iter->status().ok(), true); ASSERT_EQ(iter->status().ok(), true);
@ -953,9 +970,8 @@ void DBTestBase::validateNumberOfEntries(int numValues, int cf) {
ASSERT_EQ(0, seq); ASSERT_EQ(0, seq);
} }
void DBTestBase::CopyFile( void DBTestBase::CopyFile(const std::string& source,
const std::string& source, const std::string& destination, const std::string& destination, uint64_t size) {
uint64_t size) {
const EnvOptions soptions; const EnvOptions soptions;
unique_ptr<SequentialFile> srcfile; unique_ptr<SequentialFile> srcfile;
ASSERT_OK(env_->NewSequentialFile(source, &srcfile, soptions)); ASSERT_OK(env_->NewSequentialFile(source, &srcfile, soptions));

@ -30,6 +30,7 @@
#include "db/db_test_util.h" #include "db/db_test_util.h"
#include "db/dbformat.h" #include "db/dbformat.h"
#include "db/filename.h" #include "db/filename.h"
#include "memtable/hash_linklist_rep.h"
#include "rocksdb/cache.h" #include "rocksdb/cache.h"
#include "rocksdb/compaction_filter.h" #include "rocksdb/compaction_filter.h"
#include "rocksdb/convenience.h" #include "rocksdb/convenience.h"
@ -43,11 +44,11 @@
#include "table/block_based_table_factory.h" #include "table/block_based_table_factory.h"
#include "table/mock_table.h" #include "table/mock_table.h"
#include "table/plain_table_factory.h" #include "table/plain_table_factory.h"
#include "table/scoped_arena_iterator.h"
#include "util/compression.h" #include "util/compression.h"
#include "util/hash_linklist_rep.h"
#include "util/mock_env.h" #include "util/mock_env.h"
#include "util/mutexlock.h" #include "util/mutexlock.h"
#include "util/scoped_arena_iterator.h"
#include "util/string_util.h" #include "util/string_util.h"
// SyncPoint is not supported in Released Windows Mode. // SyncPoint is not supported in Released Windows Mode.
#if !(defined NDEBUG) || !defined(OS_WIN) #if !(defined NDEBUG) || !defined(OS_WIN)
@ -131,9 +132,7 @@ class SpecialEnv : public EnvWrapper {
public: public:
SSTableFile(SpecialEnv* env, unique_ptr<WritableFile>&& base) SSTableFile(SpecialEnv* env, unique_ptr<WritableFile>&& base)
: env_(env), : env_(env), base_(std::move(base)) {}
base_(std::move(base)) {
}
Status Append(const Slice& data) override { Status Append(const Slice& data) override {
if (env_->table_write_callback_) { if (env_->table_write_callback_) {
(*env_->table_write_callback_)(); (*env_->table_write_callback_)();
@ -148,9 +147,7 @@ class SpecialEnv : public EnvWrapper {
return base_->Append(data); return base_->Append(data);
} }
} }
Status Truncate(uint64_t size) override { Status Truncate(uint64_t size) override { return base_->Truncate(size); }
return base_->Truncate(size);
}
Status Close() override { Status Close() override {
// SyncPoint is not supported in Released Windows Mode. // SyncPoint is not supported in Released Windows Mode.
#if !(defined NDEBUG) || !defined(OS_WIN) #if !(defined NDEBUG) || !defined(OS_WIN)
@ -283,8 +280,7 @@ class SpecialEnv : public EnvWrapper {
public: public:
CountingFile(unique_ptr<RandomAccessFile>&& target, CountingFile(unique_ptr<RandomAccessFile>&& target,
anon::AtomicCounter* counter) anon::AtomicCounter* counter)
: target_(std::move(target)), counter_(counter) { : target_(std::move(target)), counter_(counter) {}
}
virtual Status Read(uint64_t offset, size_t n, Slice* result, virtual Status Read(uint64_t offset, size_t n, Slice* result,
char* scratch) const override { char* scratch) const override {
counter_->Increment(); counter_->Increment();
@ -329,7 +325,6 @@ class SpecialEnv : public EnvWrapper {
return s; return s;
} }
virtual void SleepForMicroseconds(int micros) override { virtual void SleepForMicroseconds(int micros) override {
sleep_counter_.Increment(); sleep_counter_.Increment();
if (no_sleep_) { if (no_sleep_) {
@ -509,9 +504,7 @@ class DBTestBase : public testing::Test {
const Options& defaultOptions, const Options& defaultOptions,
const anon::OptionsOverride& options_override = anon::OptionsOverride()); const anon::OptionsOverride& options_override = anon::OptionsOverride());
DBImpl* dbfull() { DBImpl* dbfull() { return reinterpret_cast<DBImpl*>(db_); }
return reinterpret_cast<DBImpl*>(db_);
}
void CreateColumnFamilies(const std::vector<std::string>& cfs, void CreateColumnFamilies(const std::vector<std::string>& cfs,
const Options& options); const Options& options);
@ -525,8 +518,7 @@ class DBTestBase : public testing::Test {
void ReopenWithColumnFamilies(const std::vector<std::string>& cfs, void ReopenWithColumnFamilies(const std::vector<std::string>& cfs,
const Options& options); const Options& options);
Status TryReopenWithColumnFamilies( Status TryReopenWithColumnFamilies(const std::vector<std::string>& cfs,
const std::vector<std::string>& cfs,
const std::vector<Options>& options); const std::vector<Options>& options);
Status TryReopenWithColumnFamilies(const std::vector<std::string>& cfs, Status TryReopenWithColumnFamilies(const std::vector<std::string>& cfs,
@ -574,16 +566,20 @@ class DBTestBase : public testing::Test {
std::string AllEntriesFor(const Slice& user_key, int cf = 0); std::string AllEntriesFor(const Slice& user_key, int cf = 0);
#ifndef ROCKSDB_LITE
int NumSortedRuns(int cf = 0); int NumSortedRuns(int cf = 0);
uint64_t TotalSize(int cf = 0); uint64_t TotalSize(int cf = 0);
int NumTableFilesAtLevel(int level, int cf = 0);
uint64_t SizeAtLevel(int level); uint64_t SizeAtLevel(int level);
int TotalLiveFiles(int cf = 0); int TotalLiveFiles(int cf = 0);
size_t CountLiveFiles();
#endif // ROCKSDB_LITE
int NumTableFilesAtLevel(int level, int cf = 0);
int TotalTableFiles(int cf = 0, int levels = -1); int TotalTableFiles(int cf = 0, int levels = -1);
// Return spread of files per level // Return spread of files per level
@ -591,8 +587,6 @@ class DBTestBase : public testing::Test {
size_t CountFiles(); size_t CountFiles();
size_t CountLiveFiles();
uint64_t Size(const Slice& start, const Slice& limit, int cf = 0); uint64_t Size(const Slice& start, const Slice& limit, int cf = 0);
void Compact(int cf, const Slice& start, const Slice& limit, void Compact(int cf, const Slice& start, const Slice& limit,
@ -643,20 +637,20 @@ class DBTestBase : public testing::Test {
// sets newValue with delta // sets newValue with delta
// If previous value is not empty, // If previous value is not empty,
// updates previous value with 'b' string of previous value size - 1. // updates previous value with 'b' string of previous value size - 1.
static UpdateStatus updateInPlaceSmallerSize( static UpdateStatus updateInPlaceSmallerSize(char* prevValue,
char* prevValue, uint32_t* prevSize, uint32_t* prevSize, Slice delta,
Slice delta, std::string* newValue); std::string* newValue);
static UpdateStatus updateInPlaceSmallerVarintSize( static UpdateStatus updateInPlaceSmallerVarintSize(char* prevValue,
char* prevValue, uint32_t* prevSize, uint32_t* prevSize,
Slice delta, std::string* newValue); Slice delta,
std::string* newValue);
static UpdateStatus updateInPlaceLargerSize( static UpdateStatus updateInPlaceLargerSize(char* prevValue,
char* prevValue, uint32_t* prevSize, uint32_t* prevSize, Slice delta,
Slice delta, std::string* newValue); std::string* newValue);
static UpdateStatus updateInPlaceNoAction( static UpdateStatus updateInPlaceNoAction(char* prevValue, uint32_t* prevSize,
char* prevValue, uint32_t* prevSize,
Slice delta, std::string* newValue); Slice delta, std::string* newValue);
// Utility method to test InplaceUpdate // Utility method to test InplaceUpdate

@ -9,7 +9,7 @@
#include "db/db_test_util.h" #include "db/db_test_util.h"
#include "port/stack_trace.h" #include "port/stack_trace.h"
#if !(defined NDEBUG) || !defined(OS_WIN) #if (!(defined NDEBUG) || !defined(OS_WIN)) && !defined(ROCKSDB_LITE)
#include "util/sync_point.h" #include "util/sync_point.h"
namespace rocksdb { namespace rocksdb {
@ -1210,10 +1210,10 @@ INSTANTIATE_TEST_CASE_P(DBTestUniversalManualCompactionOutputPathId,
} // namespace rocksdb } // namespace rocksdb
#endif // !(defined NDEBUG) || !defined(OS_WIN) #endif // (!(defined NDEBUG) || !defined(OS_WIN)) && !defined(ROCKSDB_LITE)
int main(int argc, char** argv) { int main(int argc, char** argv) {
#if !(defined NDEBUG) || !defined(OS_WIN) #if (!(defined NDEBUG) || !defined(OS_WIN)) && !defined(ROCKSDB_LITE)
rocksdb::port::InstallStackTraceHandler(); rocksdb::port::InstallStackTraceHandler();
::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();

@ -21,6 +21,7 @@
#include "util/file_reader_writer.h" #include "util/file_reader_writer.h"
#include "util/logging.h" #include "util/logging.h"
#include "util/stop_watch.h" #include "util/stop_watch.h"
#include "util/sync_point.h"
namespace rocksdb { namespace rocksdb {
@ -322,7 +323,9 @@ Status SetCurrentFile(Env* env, const std::string& dbname,
std::string tmp = TempFileName(dbname, descriptor_number); std::string tmp = TempFileName(dbname, descriptor_number);
Status s = WriteStringToFile(env, contents.ToString() + "\n", tmp, true); Status s = WriteStringToFile(env, contents.ToString() + "\n", tmp, true);
if (s.ok()) { if (s.ok()) {
TEST_KILL_RANDOM("SetCurrentFile:0", rocksdb_kill_odds * REDUCE_ODDS2);
s = env->RenameFile(tmp, CurrentFileName(dbname)); s = env->RenameFile(tmp, CurrentFileName(dbname));
TEST_KILL_RANDOM("SetCurrentFile:1", rocksdb_kill_odds * REDUCE_ODDS2);
} }
if (s.ok()) { if (s.ok()) {
if (directory_to_fsync != nullptr) { if (directory_to_fsync != nullptr) {
@ -351,6 +354,7 @@ Status SetIdentityFile(Env* env, const std::string& dbname) {
Status SyncManifest(Env* env, const DBOptions* db_options, Status SyncManifest(Env* env, const DBOptions* db_options,
WritableFileWriter* file) { WritableFileWriter* file) {
TEST_KILL_RANDOM("SyncManifest:0", rocksdb_kill_odds * REDUCE_ODDS2);
if (db_options->disableDataSync) { if (db_options->disableDataSync) {
return Status::OK(); return Status::OK();
} else { } else {

@ -197,7 +197,7 @@ Status FlushJob::WriteLevel0Table(const autovector<MemTable*>& mems,
if (log_buffer_) { if (log_buffer_) {
log_buffer_->FlushBufferToLog(); log_buffer_->FlushBufferToLog();
} }
std::vector<Iterator*> memtables; std::vector<InternalIterator*> memtables;
ReadOptions ro; ReadOptions ro;
ro.total_order_seek = true; ro.total_order_seek = true;
Arena arena; Arena arena;

@ -27,12 +27,12 @@
#include "rocksdb/env.h" #include "rocksdb/env.h"
#include "rocksdb/memtablerep.h" #include "rocksdb/memtablerep.h"
#include "rocksdb/transaction_log.h" #include "rocksdb/transaction_log.h"
#include "table/scoped_arena_iterator.h"
#include "util/autovector.h" #include "util/autovector.h"
#include "util/event_logger.h" #include "util/event_logger.h"
#include "util/instrumented_mutex.h" #include "util/instrumented_mutex.h"
#include "util/stop_watch.h" #include "util/stop_watch.h"
#include "util/thread_local.h" #include "util/thread_local.h"
#include "util/scoped_arena_iterator.h"
#include "db/internal_stats.h" #include "db/internal_stats.h"
#include "db/write_controller.h" #include "db/write_controller.h"
#include "db/flush_scheduler.h" #include "db/flush_scheduler.h"

@ -28,7 +28,7 @@ namespace rocksdb {
// iter.SetFileIndex(file_index); // iter.SetFileIndex(file_index);
// iter.Seek(target); // iter.Seek(target);
// iter.Next() // iter.Next()
class LevelIterator : public Iterator { class LevelIterator : public InternalIterator {
public: public:
LevelIterator(const ColumnFamilyData* const cfd, LevelIterator(const ColumnFamilyData* const cfd,
const ReadOptions& read_options, const ReadOptions& read_options,
@ -113,7 +113,7 @@ class LevelIterator : public Iterator {
bool valid_; bool valid_;
uint32_t file_index_; uint32_t file_index_;
Status status_; Status status_;
std::unique_ptr<Iterator> file_iter_; std::unique_ptr<InternalIterator> file_iter_;
}; };
ForwardIterator::ForwardIterator(DBImpl* db, const ReadOptions& read_options, ForwardIterator::ForwardIterator(DBImpl* db, const ReadOptions& read_options,
@ -146,10 +146,10 @@ ForwardIterator::~ForwardIterator() {
void ForwardIterator::Cleanup(bool release_sv) { void ForwardIterator::Cleanup(bool release_sv) {
if (mutable_iter_ != nullptr) { if (mutable_iter_ != nullptr) {
mutable_iter_->~Iterator(); mutable_iter_->~InternalIterator();
} }
for (auto* m : imm_iters_) { for (auto* m : imm_iters_) {
m->~Iterator(); m->~InternalIterator();
} }
imm_iters_.clear(); imm_iters_.clear();
for (auto* f : l0_iters_) { for (auto* f : l0_iters_) {

@ -14,6 +14,7 @@
#include "rocksdb/iterator.h" #include "rocksdb/iterator.h"
#include "rocksdb/options.h" #include "rocksdb/options.h"
#include "db/dbformat.h" #include "db/dbformat.h"
#include "table/internal_iterator.h"
#include "util/arena.h" #include "util/arena.h"
namespace rocksdb { namespace rocksdb {
@ -30,15 +31,14 @@ class MinIterComparator {
explicit MinIterComparator(const Comparator* comparator) : explicit MinIterComparator(const Comparator* comparator) :
comparator_(comparator) {} comparator_(comparator) {}
bool operator()(Iterator* a, Iterator* b) { bool operator()(InternalIterator* a, InternalIterator* b) {
return comparator_->Compare(a->key(), b->key()) > 0; return comparator_->Compare(a->key(), b->key()) > 0;
} }
private: private:
const Comparator* comparator_; const Comparator* comparator_;
}; };
typedef std::priority_queue<Iterator*, typedef std::priority_queue<InternalIterator*, std::vector<InternalIterator*>,
std::vector<Iterator*>,
MinIterComparator> MinIterHeap; MinIterComparator> MinIterHeap;
/** /**
@ -48,7 +48,7 @@ typedef std::priority_queue<Iterator*,
* the iterator. At the current implementation, snapshot is taken at the * the iterator. At the current implementation, snapshot is taken at the
* time Seek() is called. The Next() followed do not see new values after. * time Seek() is called. The Next() followed do not see new values after.
*/ */
class ForwardIterator : public Iterator { class ForwardIterator : public InternalIterator {
public: public:
ForwardIterator(DBImpl* db, const ReadOptions& read_options, ForwardIterator(DBImpl* db, const ReadOptions& read_options,
ColumnFamilyData* cfd, SuperVersion* current_sv = nullptr); ColumnFamilyData* cfd, SuperVersion* current_sv = nullptr);
@ -94,11 +94,11 @@ class ForwardIterator : public Iterator {
MinIterHeap immutable_min_heap_; MinIterHeap immutable_min_heap_;
SuperVersion* sv_; SuperVersion* sv_;
Iterator* mutable_iter_; InternalIterator* mutable_iter_;
std::vector<Iterator*> imm_iters_; std::vector<InternalIterator*> imm_iters_;
std::vector<Iterator*> l0_iters_; std::vector<InternalIterator*> l0_iters_;
std::vector<LevelIterator*> level_iters_; std::vector<LevelIterator*> level_iters_;
Iterator* current_; InternalIterator* current_;
bool valid_; bool valid_;
// Internal iterator status; set only by one of the unsupported methods. // Internal iterator status; set only by one of the unsupported methods.

@ -130,6 +130,8 @@ static const std::string aggregated_table_properties =
"aggregated-table-properties"; "aggregated-table-properties";
static const std::string aggregated_table_properties_at_level = static const std::string aggregated_table_properties_at_level =
aggregated_table_properties + "-at-level"; aggregated_table_properties + "-at-level";
static const std::string num_running_compactions = "num-running-compactions";
static const std::string num_running_flushes = "num-running-flushes";
const std::string DB::Properties::kNumFilesAtLevelPrefix = const std::string DB::Properties::kNumFilesAtLevelPrefix =
rocksdb_prefix + num_files_at_level_prefix; rocksdb_prefix + num_files_at_level_prefix;
@ -143,6 +145,10 @@ const std::string DB::Properties::kMemTableFlushPending =
rocksdb_prefix + mem_table_flush_pending; rocksdb_prefix + mem_table_flush_pending;
const std::string DB::Properties::kCompactionPending = const std::string DB::Properties::kCompactionPending =
rocksdb_prefix + compaction_pending; rocksdb_prefix + compaction_pending;
const std::string DB::Properties::kNumRunningCompactions =
rocksdb_prefix + num_running_compactions;
const std::string DB::Properties::kNumRunningFlushes =
rocksdb_prefix + num_running_flushes;
const std::string DB::Properties::kBackgroundErrors = const std::string DB::Properties::kBackgroundErrors =
rocksdb_prefix + background_errors; rocksdb_prefix + background_errors;
const std::string DB::Properties::kCurSizeActiveMemTable = const std::string DB::Properties::kCurSizeActiveMemTable =
@ -260,6 +266,10 @@ DBPropertyType GetPropertyType(const Slice& property, bool* is_int_property,
return kTotalSstFilesSize; return kTotalSstFilesSize;
} else if (in == estimate_pending_comp_bytes) { } else if (in == estimate_pending_comp_bytes) {
return kEstimatePendingCompactionBytes; return kEstimatePendingCompactionBytes;
} else if (in == num_running_flushes) {
return kNumRunningFlushes;
} else if (in == num_running_compactions) {
return kNumRunningCompactions;
} }
return kUnknown; return kUnknown;
} }
@ -388,11 +398,17 @@ bool InternalStats::GetIntProperty(DBPropertyType property_type,
// Return number of mem tables that are ready to flush (made immutable) // Return number of mem tables that are ready to flush (made immutable)
*value = (cfd_->imm()->IsFlushPending() ? 1 : 0); *value = (cfd_->imm()->IsFlushPending() ? 1 : 0);
return true; return true;
case kNumRunningFlushes:
*value = db->num_running_flushes();
return true;
case kCompactionPending: case kCompactionPending:
// 1 if the system already determines at least one compaction is needed. // 1 if the system already determines at least one compaction is needed.
// 0 otherwise, // 0 otherwise,
*value = (cfd_->compaction_picker()->NeedsCompaction(vstorage) ? 1 : 0); *value = (cfd_->compaction_picker()->NeedsCompaction(vstorage) ? 1 : 0);
return true; return true;
case kNumRunningCompactions:
*value = db->num_running_compactions_;
return true;
case kBackgroundErrors: case kBackgroundErrors:
// Accumulated number of errors in background flushes or compactions. // Accumulated number of errors in background flushes or compactions.
*value = GetBackgroundErrorCount(); *value = GetBackgroundErrorCount();

@ -38,7 +38,10 @@ enum DBPropertyType : uint32_t {
// in memory that have already been flushed // in memory that have already been flushed
kMemtableFlushPending, // Return 1 if mem table flushing is pending, kMemtableFlushPending, // Return 1 if mem table flushing is pending,
// otherwise 0. // otherwise 0.
kNumRunningFlushes, // Return the number of currently running flushes.
kCompactionPending, // Return 1 if a compaction is pending. Otherwise 0. kCompactionPending, // Return 1 if a compaction is pending. Otherwise 0.
kNumRunningCompactions, // Return the number of currently running
// compactions.
kBackgroundErrors, // Return accumulated background errors encountered. kBackgroundErrors, // Return accumulated background errors encountered.
kCurSizeActiveMemTable, // Return current size of the active memtable kCurSizeActiveMemTable, // Return current size of the active memtable
kCurSizeAllMemTables, // Return current size of unflushed kCurSizeAllMemTables, // Return current size of unflushed
@ -49,10 +52,10 @@ enum DBPropertyType : uint32_t {
// memtable. // memtable.
kNumEntriesInImmutableMemtable, // Return sum of number of entries in all kNumEntriesInImmutableMemtable, // Return sum of number of entries in all
// the immutable mem tables. // the immutable mem tables.
kNumDeletesInMutableMemtable, // Return number of entries in the mutable kNumDeletesInMutableMemtable, // Return number of deletion entries in the
// memtable. // mutable memtable.
kNumDeletesInImmutableMemtable, // Return sum of number of deletes in all kNumDeletesInImmutableMemtable, // Return the total number of deletion
// the immutable mem tables. // entries in all the immutable mem tables.
kEstimatedNumKeys, // Estimated total number of keys in the database. kEstimatedNumKeys, // Estimated total number of keys in the database.
kEstimatedUsageByTableReaders, // Estimated memory by table readers. kEstimatedUsageByTableReaders, // Estimated memory by table readers.
kIsFileDeletionEnabled, // Equals disable_delete_obsolete_files_, kIsFileDeletionEnabled, // Equals disable_delete_obsolete_files_,

@ -8,6 +8,7 @@
#include "db/filename.h" #include "db/filename.h"
#include "db/version_set.h" #include "db/version_set.h"
#include "db/write_batch_internal.h" #include "db/write_batch_internal.h"
#include "memtable/hash_linklist_rep.h"
#include "rocksdb/cache.h" #include "rocksdb/cache.h"
#include "rocksdb/compaction_filter.h" #include "rocksdb/compaction_filter.h"
#include "rocksdb/db.h" #include "rocksdb/db.h"
@ -22,7 +23,6 @@
#include "table/block_based_table_factory.h" #include "table/block_based_table_factory.h"
#include "table/plain_table_factory.h" #include "table/plain_table_factory.h"
#include "util/hash.h" #include "util/hash.h"
#include "util/hash_linklist_rep.h"
#include "util/logging.h" #include "util/logging.h"
#include "util/mutexlock.h" #include "util/mutexlock.h"
#include "util/rate_limiter.h" #include "util/rate_limiter.h"

@ -21,6 +21,7 @@
#include "rocksdb/iterator.h" #include "rocksdb/iterator.h"
#include "rocksdb/merge_operator.h" #include "rocksdb/merge_operator.h"
#include "rocksdb/slice_transform.h" #include "rocksdb/slice_transform.h"
#include "table/internal_iterator.h"
#include "table/merger.h" #include "table/merger.h"
#include "util/arena.h" #include "util/arena.h"
#include "util/coding.h" #include "util/coding.h"
@ -202,7 +203,7 @@ const char* EncodeKey(std::string* scratch, const Slice& target) {
return scratch->data(); return scratch->data();
} }
class MemTableIterator: public Iterator { class MemTableIterator : public InternalIterator {
public: public:
MemTableIterator( MemTableIterator(
const MemTable& mem, const ReadOptions& read_options, Arena* arena) const MemTable& mem, const ReadOptions& read_options, Arena* arena)
@ -285,7 +286,8 @@ class MemTableIterator: public Iterator {
void operator=(const MemTableIterator&); void operator=(const MemTableIterator&);
}; };
Iterator* MemTable::NewIterator(const ReadOptions& read_options, Arena* arena) { InternalIterator* MemTable::NewIterator(const ReadOptions& read_options,
Arena* arena) {
assert(arena != nullptr); assert(arena != nullptr);
auto mem = arena->AllocateAligned(sizeof(MemTableIterator)); auto mem = arena->AllocateAligned(sizeof(MemTableIterator));
return new (mem) MemTableIterator(*this, read_options, arena); return new (mem) MemTableIterator(*this, read_options, arena);

@ -31,6 +31,7 @@ class Mutex;
class MemTableIterator; class MemTableIterator;
class MergeContext; class MergeContext;
class WriteBuffer; class WriteBuffer;
class InternalIterator;
struct MemTableOptions { struct MemTableOptions {
explicit MemTableOptions( explicit MemTableOptions(
@ -140,7 +141,7 @@ class MemTable {
// arena: If not null, the arena needs to be used to allocate the Iterator. // arena: If not null, the arena needs to be used to allocate the Iterator.
// Calling ~Iterator of the iterator will destroy all the states but // Calling ~Iterator of the iterator will destroy all the states but
// those allocated in arena. // those allocated in arena.
Iterator* NewIterator(const ReadOptions& read_options, Arena* arena); InternalIterator* NewIterator(const ReadOptions& read_options, Arena* arena);
// Add an entry into memtable that maps key to value at the // Add an entry into memtable that maps key to value at the
// specified sequence number and with the specified type. // specified sequence number and with the specified type.

@ -138,8 +138,8 @@ bool MemTableListVersion::GetFromList(std::list<MemTable*>* list,
return false; return false;
} }
void MemTableListVersion::AddIterators(const ReadOptions& options, void MemTableListVersion::AddIterators(
std::vector<Iterator*>* iterator_list, const ReadOptions& options, std::vector<InternalIterator*>* iterator_list,
Arena* arena) { Arena* arena) {
for (auto& m : memlist_) { for (auto& m : memlist_) {
iterator_list->push_back(m->NewIterator(options, arena)); iterator_list->push_back(m->NewIterator(options, arena));

@ -74,7 +74,8 @@ class MemTableListVersion {
} }
void AddIterators(const ReadOptions& options, void AddIterators(const ReadOptions& options,
std::vector<Iterator*>* iterator_list, Arena* arena); std::vector<InternalIterator*>* iterator_list,
Arena* arena);
void AddIterators(const ReadOptions& options, void AddIterators(const ReadOptions& options,
MergeIteratorBuilder* merge_iter_builder); MergeIteratorBuilder* merge_iter_builder);

@ -592,6 +592,7 @@ int main(int argc, char** argv) {
std::unique_ptr<rocksdb::MemTableRepFactory> factory; std::unique_ptr<rocksdb::MemTableRepFactory> factory;
if (FLAGS_memtablerep == "skiplist") { if (FLAGS_memtablerep == "skiplist") {
factory.reset(new rocksdb::SkipListFactory); factory.reset(new rocksdb::SkipListFactory);
#ifndef ROCKSDB_LITE
} else if (FLAGS_memtablerep == "vector") { } else if (FLAGS_memtablerep == "vector") {
factory.reset(new rocksdb::VectorRepFactory); factory.reset(new rocksdb::VectorRepFactory);
} else if (FLAGS_memtablerep == "hashskiplist") { } else if (FLAGS_memtablerep == "hashskiplist") {
@ -613,6 +614,7 @@ int main(int argc, char** argv) {
static_cast<uint32_t>(FLAGS_hash_function_count))); static_cast<uint32_t>(FLAGS_hash_function_count)));
options.prefix_extractor.reset( options.prefix_extractor.reset(
rocksdb::NewFixedPrefixTransform(FLAGS_prefix_length)); rocksdb::NewFixedPrefixTransform(FLAGS_prefix_length));
#endif // ROCKSDB_LITE
} else { } else {
fprintf(stdout, "Unknown memtablerep: %s\n", FLAGS_memtablerep.c_str()); fprintf(stdout, "Unknown memtablerep: %s\n", FLAGS_memtablerep.c_str());
exit(1); exit(1);

@ -12,6 +12,7 @@
#include "rocksdb/comparator.h" #include "rocksdb/comparator.h"
#include "rocksdb/db.h" #include "rocksdb/db.h"
#include "rocksdb/merge_operator.h" #include "rocksdb/merge_operator.h"
#include "table/internal_iterator.h"
#include "util/perf_context_imp.h" #include "util/perf_context_imp.h"
#include "util/statistics.h" #include "util/statistics.h"
@ -56,7 +57,8 @@ Status MergeHelper::TimedFullMerge(const Slice& key, const Slice* value,
// keys_ stores the list of keys encountered while merging. // keys_ stores the list of keys encountered while merging.
// operands_ stores the list of merge operands encountered while merging. // operands_ stores the list of merge operands encountered while merging.
// keys_[i] corresponds to operands_[i] for each i. // keys_[i] corresponds to operands_[i] for each i.
Status MergeHelper::MergeUntil(Iterator* iter, const SequenceNumber stop_before, Status MergeHelper::MergeUntil(InternalIterator* iter,
const SequenceNumber stop_before,
const bool at_bottom) { const bool at_bottom) {
// Get a copy of the internal key, before it's invalidated by iter->Next() // Get a copy of the internal key, before it's invalidated by iter->Next()
// Also maintain the list of merge operands seen. // Also maintain the list of merge operands seen.

@ -22,6 +22,7 @@ class Iterator;
class Logger; class Logger;
class MergeOperator; class MergeOperator;
class Statistics; class Statistics;
class InternalIterator;
class MergeHelper { class MergeHelper {
public: public:
@ -82,7 +83,8 @@ class MergeHelper {
// with asserts removed). // with asserts removed).
// //
// REQUIRED: The first key in the input is not corrupted. // REQUIRED: The first key in the input is not corrupted.
Status MergeUntil(Iterator* iter, const SequenceNumber stop_before = 0, Status MergeUntil(InternalIterator* iter,
const SequenceNumber stop_before = 0,
const bool at_bottom = false); const bool at_bottom = false);
// Filters a merge operand using the compaction filter specified // Filters a merge operand using the compaction filter specified

@ -5,6 +5,7 @@
// //
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <thread>
#include <vector> #include <vector>
#include "rocksdb/db.h" #include "rocksdb/db.h"
@ -444,6 +445,7 @@ void ProfileQueries(bool enabled_time = false) {
} }
} }
#ifndef ROCKSDB_LITE
TEST_F(PerfContextTest, KeyComparisonCount) { TEST_F(PerfContextTest, KeyComparisonCount) {
SetPerfLevel(kEnableCount); SetPerfLevel(kEnableCount);
ProfileQueries(); ProfileQueries();
@ -454,6 +456,7 @@ TEST_F(PerfContextTest, KeyComparisonCount) {
SetPerfLevel(kEnableTime); SetPerfLevel(kEnableTime);
ProfileQueries(true); ProfileQueries(true);
} }
#endif // ROCKSDB_LITE
// make perf_context_test // make perf_context_test
// export ROCKSDB_TESTS=PerfContextTest.SeekKeyComparison // export ROCKSDB_TESTS=PerfContextTest.SeekKeyComparison
@ -539,6 +542,49 @@ TEST_F(PerfContextTest, SeekKeyComparison) {
} }
} }
TEST_F(PerfContextTest, DBMutexLockCounter) {
SetPerfLevel(kEnableTime);
int stats_code[] = {0, static_cast<int>(DB_MUTEX_WAIT_MICROS)};
for (int c = 0; c < 2; ++c) {
InstrumentedMutex mutex(nullptr, Env::Default(), stats_code[c]);
mutex.Lock();
std::thread child_thread([&] {
SetPerfLevel(kEnableTime);
perf_context.Reset();
ASSERT_EQ(perf_context.db_mutex_lock_nanos, 0);
mutex.Lock();
mutex.Unlock();
if (stats_code[c] == DB_MUTEX_WAIT_MICROS) {
// increment the counter only when it's a DB Mutex
ASSERT_GT(perf_context.db_mutex_lock_nanos, 0);
} else {
ASSERT_EQ(perf_context.db_mutex_lock_nanos, 0);
}
});
Env::Default()->SleepForMicroseconds(100);
mutex.Unlock();
child_thread.join();
}
}
TEST_F(PerfContextTest, FalseDBMutexWait) {
SetPerfLevel(kEnableTime);
int stats_code[] = {0, static_cast<int>(DB_MUTEX_WAIT_MICROS)};
for (int c = 0; c < 2; ++c) {
InstrumentedMutex mutex(nullptr, Env::Default(), stats_code[c]);
InstrumentedCondVar lock(&mutex);
perf_context.Reset();
mutex.Lock();
lock.TimedWait(100);
mutex.Unlock();
if (stats_code[c] == static_cast<int>(DB_MUTEX_WAIT_MICROS)) {
// increment the counter only when it's a DB Mutex
ASSERT_GT(perf_context.db_condition_wait_nanos, 0);
} else {
ASSERT_EQ(perf_context.db_condition_wait_nanos, 0);
}
}
}
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {

@ -81,8 +81,8 @@
#include "rocksdb/env.h" #include "rocksdb/env.h"
#include "rocksdb/options.h" #include "rocksdb/options.h"
#include "rocksdb/immutable_options.h" #include "rocksdb/immutable_options.h"
#include "table/scoped_arena_iterator.h"
#include "util/file_reader_writer.h" #include "util/file_reader_writer.h"
#include "util/scoped_arena_iterator.h"
namespace rocksdb { namespace rocksdb {
@ -340,7 +340,7 @@ class Repairer {
t->meta.fd = FileDescriptor(t->meta.fd.GetNumber(), t->meta.fd.GetPathId(), t->meta.fd = FileDescriptor(t->meta.fd.GetNumber(), t->meta.fd.GetPathId(),
file_size); file_size);
if (status.ok()) { if (status.ok()) {
Iterator* iter = table_cache_->NewIterator( InternalIterator* iter = table_cache_->NewIterator(
ReadOptions(), env_options_, icmp_, t->meta.fd); ReadOptions(), env_options_, icmp_, t->meta.fd);
bool empty = true; bool empty = true;
ParsedInternalKey parsed; ParsedInternalKey parsed;

@ -14,6 +14,7 @@
#include "db/version_edit.h" #include "db/version_edit.h"
#include "rocksdb/statistics.h" #include "rocksdb/statistics.h"
#include "table/internal_iterator.h"
#include "table/iterator_wrapper.h" #include "table/iterator_wrapper.h"
#include "table/table_builder.h" #include "table/table_builder.h"
#include "table/table_reader.h" #include "table/table_reader.h"
@ -148,12 +149,10 @@ Status TableCache::FindTable(const EnvOptions& env_options,
return s; return s;
} }
Iterator* TableCache::NewIterator(const ReadOptions& options, InternalIterator* TableCache::NewIterator(
const EnvOptions& env_options, const ReadOptions& options, const EnvOptions& env_options,
const InternalKeyComparator& icomparator, const InternalKeyComparator& icomparator, const FileDescriptor& fd,
const FileDescriptor& fd, TableReader** table_reader_ptr, HistogramImpl* file_read_hist,
TableReader** table_reader_ptr,
HistogramImpl* file_read_hist,
bool for_compaction, Arena* arena) { bool for_compaction, Arena* arena) {
PERF_TIMER_GUARD(new_table_iterator_nanos); PERF_TIMER_GUARD(new_table_iterator_nanos);
@ -171,7 +170,7 @@ Iterator* TableCache::NewIterator(const ReadOptions& options,
env_options, icomparator, fd, /* sequential mode */ true, env_options, icomparator, fd, /* sequential mode */ true,
/* record stats */ false, nullptr, &table_reader_unique_ptr); /* record stats */ false, nullptr, &table_reader_unique_ptr);
if (!s.ok()) { if (!s.ok()) {
return NewErrorIterator(s, arena); return NewErrorInternalIterator(s, arena);
} }
table_reader = table_reader_unique_ptr.release(); table_reader = table_reader_unique_ptr.release();
} else { } else {
@ -182,13 +181,13 @@ Iterator* TableCache::NewIterator(const ReadOptions& options,
options.read_tier == kBlockCacheTier /* no_io */, options.read_tier == kBlockCacheTier /* no_io */,
!for_compaction /* record read_stats */, file_read_hist); !for_compaction /* record read_stats */, file_read_hist);
if (!s.ok()) { if (!s.ok()) {
return NewErrorIterator(s, arena); return NewErrorInternalIterator(s, arena);
} }
table_reader = GetTableReaderFromHandle(handle); table_reader = GetTableReaderFromHandle(handle);
} }
} }
Iterator* result = table_reader->NewIterator(options, arena); InternalIterator* result = table_reader->NewIterator(options, arena);
if (create_new_table_reader) { if (create_new_table_reader) {
assert(handle == nullptr); assert(handle == nullptr);

@ -29,6 +29,7 @@ class Arena;
struct FileDescriptor; struct FileDescriptor;
class GetContext; class GetContext;
class HistogramImpl; class HistogramImpl;
class InternalIterator;
class TableCache { class TableCache {
public: public:
@ -43,12 +44,12 @@ class TableCache {
// the returned iterator. The returned "*tableptr" object is owned by // the returned iterator. The returned "*tableptr" object is owned by
// the cache and should not be deleted, and is valid for as long as the // the cache and should not be deleted, and is valid for as long as the
// returned iterator is live. // returned iterator is live.
Iterator* NewIterator(const ReadOptions& options, const EnvOptions& toptions, InternalIterator* NewIterator(
const ReadOptions& options, const EnvOptions& toptions,
const InternalKeyComparator& internal_comparator, const InternalKeyComparator& internal_comparator,
const FileDescriptor& file_fd, const FileDescriptor& file_fd, TableReader** table_reader_ptr = nullptr,
TableReader** table_reader_ptr = nullptr, HistogramImpl* file_read_hist = nullptr, bool for_compaction = false,
HistogramImpl* file_read_hist = nullptr, Arena* arena = nullptr);
bool for_compaction = false, Arena* arena = nullptr);
// If a seek to internal key "k" in specified file finds an entry, // If a seek to internal key "k" in specified file finds an entry,
// call (*handle_result)(arg, found_key, found_value) repeatedly until // call (*handle_result)(arg, found_key, found_value) repeatedly until

@ -35,6 +35,7 @@
#include "db/writebuffer.h" #include "db/writebuffer.h"
#include "rocksdb/env.h" #include "rocksdb/env.h"
#include "rocksdb/merge_operator.h" #include "rocksdb/merge_operator.h"
#include "table/internal_iterator.h"
#include "table/table_reader.h" #include "table/table_reader.h"
#include "table/merger.h" #include "table/merger.h"
#include "table/two_level_iterator.h" #include "table/two_level_iterator.h"
@ -420,7 +421,7 @@ namespace {
// is the largest key that occurs in the file, and value() is an // is the largest key that occurs in the file, and value() is an
// 16-byte value containing the file number and file size, both // 16-byte value containing the file number and file size, both
// encoded using EncodeFixed64. // encoded using EncodeFixed64.
class LevelFileNumIterator : public Iterator { class LevelFileNumIterator : public InternalIterator {
public: public:
LevelFileNumIterator(const InternalKeyComparator& icmp, LevelFileNumIterator(const InternalKeyComparator& icmp,
const LevelFilesBrief* flevel) const LevelFilesBrief* flevel)
@ -488,9 +489,9 @@ class LevelFileIteratorState : public TwoLevelIteratorState {
file_read_hist_(file_read_hist), file_read_hist_(file_read_hist),
for_compaction_(for_compaction) {} for_compaction_(for_compaction) {}
Iterator* NewSecondaryIterator(const Slice& meta_handle) override { InternalIterator* NewSecondaryIterator(const Slice& meta_handle) override {
if (meta_handle.size() != sizeof(FileDescriptor)) { if (meta_handle.size() != sizeof(FileDescriptor)) {
return NewErrorIterator( return NewErrorInternalIterator(
Status::Corruption("FileReader invoked with unexpected value")); Status::Corruption("FileReader invoked with unexpected value"));
} else { } else {
const FileDescriptor* fd = const FileDescriptor* fd =
@ -541,7 +542,7 @@ class BaseReferencedVersionBuilder {
Status Version::GetTableProperties(std::shared_ptr<const TableProperties>* tp, Status Version::GetTableProperties(std::shared_ptr<const TableProperties>* tp,
const FileMetaData* file_meta, const FileMetaData* file_meta,
const std::string* fname) { const std::string* fname) const {
auto table_cache = cfd_->table_cache(); auto table_cache = cfd_->table_cache();
auto ioptions = cfd_->ioptions(); auto ioptions = cfd_->ioptions();
Status s = table_cache->GetTableProperties( Status s = table_cache->GetTableProperties(
@ -623,6 +624,38 @@ Status Version::GetPropertiesOfAllTables(TablePropertiesCollection* props,
return Status::OK(); return Status::OK();
} }
Status Version::GetPropertiesOfTablesInRange(
const Range* range, std::size_t n, TablePropertiesCollection* props) const {
for (int level = 0; level < storage_info_.num_non_empty_levels(); level++) {
for (decltype(n) i = 0; i < n; i++) {
// Convert user_key into a corresponding internal key.
InternalKey k1(range[i].start, kMaxSequenceNumber, kValueTypeForSeek);
InternalKey k2(range[i].limit, kMaxSequenceNumber, kValueTypeForSeek);
std::vector<FileMetaData*> files;
storage_info_.GetOverlappingInputs(level, &k1, &k2, &files, -1, nullptr,
false);
for (const auto& file_meta : files) {
auto fname =
TableFileName(vset_->db_options_->db_paths,
file_meta->fd.GetNumber(), file_meta->fd.GetPathId());
if (props->count(fname) == 0) {
// 1. If the table is already present in table cache, load table
// properties from there.
std::shared_ptr<const TableProperties> table_properties;
Status s = GetTableProperties(&table_properties, file_meta, &fname);
if (s.ok()) {
props->insert({fname, table_properties});
} else {
return s;
}
}
}
}
}
return Status::OK();
}
Status Version::GetAggregatedTableProperties( Status Version::GetAggregatedTableProperties(
std::shared_ptr<const TableProperties>* tp, int level) { std::shared_ptr<const TableProperties>* tp, int level) {
TablePropertiesCollection props; TablePropertiesCollection props;
@ -1064,7 +1097,7 @@ void VersionStorageInfo::EstimateCompactionBytesNeeded(
// We keep doing it to Level 2, 3, etc, until the last level and return the // We keep doing it to Level 2, 3, etc, until the last level and return the
// accumulated bytes. // accumulated bytes.
size_t bytes_compact_to_next_level = 0; uint64_t bytes_compact_to_next_level = 0;
// Level 0 // Level 0
bool level0_compact_triggered = false; bool level0_compact_triggered = false;
if (static_cast<int>(files_[0].size()) > if (static_cast<int>(files_[0].size()) >
@ -1080,7 +1113,7 @@ void VersionStorageInfo::EstimateCompactionBytesNeeded(
// Level 1 and up. // Level 1 and up.
for (int level = base_level(); level <= MaxInputLevel(); level++) { for (int level = base_level(); level <= MaxInputLevel(); level++) {
size_t level_size = 0; uint64_t level_size = 0;
for (auto* f : files_[level]) { for (auto* f : files_[level]) {
level_size += f->fd.GetFileSize(); level_size += f->fd.GetFileSize();
} }
@ -1091,7 +1124,7 @@ void VersionStorageInfo::EstimateCompactionBytesNeeded(
// Add size added by previous compaction // Add size added by previous compaction
level_size += bytes_compact_to_next_level; level_size += bytes_compact_to_next_level;
bytes_compact_to_next_level = 0; bytes_compact_to_next_level = 0;
size_t level_target = MaxBytesForLevel(level); uint64_t level_target = MaxBytesForLevel(level);
if (level_size > level_target) { if (level_size > level_target) {
bytes_compact_to_next_level = level_size - level_target; bytes_compact_to_next_level = level_size - level_target;
// Simplify to assume the actual compaction fan-out ratio is always // Simplify to assume the actual compaction fan-out ratio is always
@ -1405,7 +1438,8 @@ bool VersionStorageInfo::OverlapInLevel(int level,
// The file_index returns a pointer to any file in an overlapping range. // The file_index returns a pointer to any file in an overlapping range.
void VersionStorageInfo::GetOverlappingInputs( void VersionStorageInfo::GetOverlappingInputs(
int level, const InternalKey* begin, const InternalKey* end, int level, const InternalKey* begin, const InternalKey* end,
std::vector<FileMetaData*>* inputs, int hint_index, int* file_index) { std::vector<FileMetaData*>* inputs, int hint_index, int* file_index,
bool expand_range) const {
if (level >= num_non_empty_levels_) { if (level >= num_non_empty_levels_) {
// this level is empty, no overlapping inputs // this level is empty, no overlapping inputs
return; return;
@ -1438,7 +1472,7 @@ void VersionStorageInfo::GetOverlappingInputs(
// "f" is completely after specified range; skip it // "f" is completely after specified range; skip it
} else { } else {
inputs->push_back(files_[level][i-1]); inputs->push_back(files_[level][i-1]);
if (level == 0) { if (level == 0 && expand_range) {
// Level-0 files may overlap each other. So check if the newly // Level-0 files may overlap each other. So check if the newly
// added file has expanded the range. If so, restart search. // added file has expanded the range. If so, restart search.
if (begin != nullptr && user_cmp->Compare(file_start, user_begin) < 0) { if (begin != nullptr && user_cmp->Compare(file_start, user_begin) < 0) {
@ -1464,7 +1498,7 @@ void VersionStorageInfo::GetOverlappingInputs(
// forwards to find all overlapping files. // forwards to find all overlapping files.
void VersionStorageInfo::GetOverlappingInputsBinarySearch( void VersionStorageInfo::GetOverlappingInputsBinarySearch(
int level, const Slice& user_begin, const Slice& user_end, int level, const Slice& user_begin, const Slice& user_end,
std::vector<FileMetaData*>* inputs, int hint_index, int* file_index) { std::vector<FileMetaData*>* inputs, int hint_index, int* file_index) const {
assert(level > 0); assert(level > 0);
int min = 0; int min = 0;
int mid = 0; int mid = 0;
@ -1512,8 +1546,7 @@ void VersionStorageInfo::GetOverlappingInputsBinarySearch(
// Use FileLevel in searching, make it faster // Use FileLevel in searching, make it faster
void VersionStorageInfo::ExtendOverlappingInputs( void VersionStorageInfo::ExtendOverlappingInputs(
int level, const Slice& user_begin, const Slice& user_end, int level, const Slice& user_begin, const Slice& user_end,
std::vector<FileMetaData*>* inputs, unsigned int midIndex) { std::vector<FileMetaData*>* inputs, unsigned int midIndex) const {
const Comparator* user_cmp = user_comparator_; const Comparator* user_cmp = user_comparator_;
const FdWithKeyRange* files = level_files_brief_[level].files; const FdWithKeyRange* files = level_files_brief_[level].files;
#ifndef NDEBUG #ifndef NDEBUG
@ -2070,8 +2103,8 @@ Status VersionSet::LogAndApply(ColumnFamilyData* column_family_data,
"Creating manifest %" PRIu64 "\n", pending_manifest_file_number_); "Creating manifest %" PRIu64 "\n", pending_manifest_file_number_);
unique_ptr<WritableFile> descriptor_file; unique_ptr<WritableFile> descriptor_file;
EnvOptions opt_env_opts = env_->OptimizeForManifestWrite(env_options_); EnvOptions opt_env_opts = env_->OptimizeForManifestWrite(env_options_);
s = env_->NewWritableFile( s = NewWritableFile(
DescriptorFileName(dbname_, pending_manifest_file_number_), env_, DescriptorFileName(dbname_, pending_manifest_file_number_),
&descriptor_file, opt_env_opts); &descriptor_file, opt_env_opts);
if (s.ok()) { if (s.ok()) {
descriptor_file->SetPreallocationBlockSize( descriptor_file->SetPreallocationBlockSize(
@ -2098,6 +2131,8 @@ Status VersionSet::LogAndApply(ColumnFamilyData* column_family_data,
"Unable to Encode VersionEdit:" + e->DebugString(true)); "Unable to Encode VersionEdit:" + e->DebugString(true));
break; break;
} }
TEST_KILL_RANDOM("VersionSet::LogAndApply:BeforeAddRecord",
rocksdb_kill_odds * REDUCE_ODDS2);
s = descriptor_log_->AddRecord(record); s = descriptor_log_->AddRecord(record);
if (!s.ok()) { if (!s.ok()) {
break; break;
@ -3119,7 +3154,7 @@ uint64_t VersionSet::ApproximateSize(Version* v, const FdWithKeyRange& f,
// "key" falls in the range for this table. Add the // "key" falls in the range for this table. Add the
// approximate offset of "key" within the table. // approximate offset of "key" within the table.
TableReader* table_reader_ptr; TableReader* table_reader_ptr;
Iterator* iter = v->cfd_->table_cache()->NewIterator( InternalIterator* iter = v->cfd_->table_cache()->NewIterator(
ReadOptions(), env_options_, v->cfd_->internal_comparator(), f.fd, ReadOptions(), env_options_, v->cfd_->internal_comparator(), f.fd,
&table_reader_ptr); &table_reader_ptr);
if (table_reader_ptr != nullptr) { if (table_reader_ptr != nullptr) {
@ -3166,7 +3201,7 @@ void VersionSet::AddLiveFiles(std::vector<FileDescriptor>* live_list) {
} }
} }
Iterator* VersionSet::MakeInputIterator(Compaction* c) { InternalIterator* VersionSet::MakeInputIterator(Compaction* c) {
auto cfd = c->column_family_data(); auto cfd = c->column_family_data();
ReadOptions read_options; ReadOptions read_options;
read_options.verify_checksums = read_options.verify_checksums =
@ -3182,7 +3217,7 @@ Iterator* VersionSet::MakeInputIterator(Compaction* c) {
const size_t space = (c->level() == 0 ? c->input_levels(0)->num_files + const size_t space = (c->level() == 0 ? c->input_levels(0)->num_files +
c->num_input_levels() - 1 c->num_input_levels() - 1
: c->num_input_levels()); : c->num_input_levels());
Iterator** list = new Iterator* [space]; InternalIterator** list = new InternalIterator* [space];
size_t num = 0; size_t num = 0;
for (size_t which = 0; which < c->num_input_levels(); which++) { for (size_t which = 0; which < c->num_input_levels(); which++) {
if (c->input_levels(which)->num_files != 0) { if (c->input_levels(which)->num_files != 0) {
@ -3209,7 +3244,7 @@ Iterator* VersionSet::MakeInputIterator(Compaction* c) {
} }
} }
assert(num <= space); assert(num <= space);
Iterator* result = InternalIterator* result =
NewMergingIterator(&c->column_family_data()->internal_comparator(), list, NewMergingIterator(&c->column_family_data()->internal_comparator(), list,
static_cast<int>(num)); static_cast<int>(num));
delete[] list; delete[] list;

@ -48,7 +48,7 @@ class Writer;
} }
class Compaction; class Compaction;
class Iterator; class InternalIterator;
class LogBuffer; class LogBuffer;
class LookupKey; class LookupKey;
class MemTable; class MemTable;
@ -160,7 +160,10 @@ class VersionStorageInfo {
const InternalKey* end, // nullptr means after all keys const InternalKey* end, // nullptr means after all keys
std::vector<FileMetaData*>* inputs, std::vector<FileMetaData*>* inputs,
int hint_index = -1, // index of overlap file int hint_index = -1, // index of overlap file
int* file_index = nullptr); // return index of overlap file int* file_index = nullptr, // return index of overlap file
bool expand_range = true) // if set, returns files which overlap the
const; // range and overlap each other. If false,
// then just files intersecting the range
void GetOverlappingInputsBinarySearch( void GetOverlappingInputsBinarySearch(
int level, int level,
@ -168,14 +171,14 @@ class VersionStorageInfo {
const Slice& end, // nullptr means after all keys const Slice& end, // nullptr means after all keys
std::vector<FileMetaData*>* inputs, std::vector<FileMetaData*>* inputs,
int hint_index, // index of overlap file int hint_index, // index of overlap file
int* file_index); // return index of overlap file int* file_index) const; // return index of overlap file
void ExtendOverlappingInputs( void ExtendOverlappingInputs(
int level, int level,
const Slice& begin, // nullptr means before all keys const Slice& begin, // nullptr means before all keys
const Slice& end, // nullptr means after all keys const Slice& end, // nullptr means after all keys
std::vector<FileMetaData*>* inputs, std::vector<FileMetaData*>* inputs,
unsigned int index); // start extending from this index unsigned int index) const; // start extending from this index
// Returns true iff some file in the specified level overlaps // Returns true iff some file in the specified level overlaps
// some part of [*smallest_user_key,*largest_user_key]. // some part of [*smallest_user_key,*largest_user_key].
@ -456,15 +459,16 @@ class Version {
// file-name conversion. // file-name conversion.
Status GetTableProperties(std::shared_ptr<const TableProperties>* tp, Status GetTableProperties(std::shared_ptr<const TableProperties>* tp,
const FileMetaData* file_meta, const FileMetaData* file_meta,
const std::string* fname = nullptr); const std::string* fname = nullptr) const;
// REQUIRES: lock is held // REQUIRES: lock is held
// On success, *props will be populated with all SSTables' table properties. // On success, *props will be populated with all SSTables' table properties.
// The keys of `props` are the sst file name, the values of `props` are the // The keys of `props` are the sst file name, the values of `props` are the
// tables' propertis, represented as shared_ptr. // tables' propertis, represented as shared_ptr.
Status GetPropertiesOfAllTables(TablePropertiesCollection* props); Status GetPropertiesOfAllTables(TablePropertiesCollection* props);
Status GetPropertiesOfAllTables(TablePropertiesCollection* props, int level); Status GetPropertiesOfAllTables(TablePropertiesCollection* props, int level);
Status GetPropertiesOfTablesInRange(const Range* range, std::size_t n,
TablePropertiesCollection* props) const;
// REQUIRES: lock is held // REQUIRES: lock is held
// On success, "tp" will contains the aggregated table property amoug // On success, "tp" will contains the aggregated table property amoug
@ -502,7 +506,8 @@ class Version {
return storage_info_.user_comparator_; return storage_info_.user_comparator_;
} }
bool PrefixMayMatch(const ReadOptions& read_options, Iterator* level_iter, bool PrefixMayMatch(const ReadOptions& read_options,
InternalIterator* level_iter,
const Slice& internal_prefix) const; const Slice& internal_prefix) const;
// The helper function of UpdateAccumulatedStats, which may fill the missing // The helper function of UpdateAccumulatedStats, which may fill the missing
@ -643,7 +648,7 @@ class VersionSet {
// Create an iterator that reads over the compaction inputs for "*c". // Create an iterator that reads over the compaction inputs for "*c".
// The caller should delete the iterator when no longer needed. // The caller should delete the iterator when no longer needed.
Iterator* MakeInputIterator(Compaction* c); InternalIterator* MakeInputIterator(Compaction* c);
// Add all files listed in any live version to *live. // Add all files listed in any live version to *live.
void AddLiveFiles(std::vector<FileDescriptor>* live_list); void AddLiveFiles(std::vector<FileDescriptor>* live_list);

@ -17,10 +17,10 @@
#include "rocksdb/env.h" #include "rocksdb/env.h"
#include "rocksdb/memtablerep.h" #include "rocksdb/memtablerep.h"
#include "rocksdb/utilities/write_batch_with_index.h" #include "rocksdb/utilities/write_batch_with_index.h"
#include "table/scoped_arena_iterator.h"
#include "util/logging.h" #include "util/logging.h"
#include "util/string_util.h" #include "util/string_util.h"
#include "util/testharness.h" #include "util/testharness.h"
#include "util/scoped_arena_iterator.h"
namespace rocksdb { namespace rocksdb {

@ -116,20 +116,6 @@ class CompactionFilterFactory {
virtual const char* Name() const = 0; virtual const char* Name() const = 0;
}; };
// Default implementation of CompactionFilterFactory which does not
// return any filter
class DefaultCompactionFilterFactory : public CompactionFilterFactory {
public:
virtual std::unique_ptr<CompactionFilter> CreateCompactionFilter(
const CompactionFilter::Context& context) override {
return std::unique_ptr<CompactionFilter>(nullptr);
}
virtual const char* Name() const override {
return "DefaultCompactionFilterFactory";
}
};
} // namespace rocksdb } // namespace rocksdb
#endif // STORAGE_ROCKSDB_INCLUDE_COMPACTION_FILTER_H_ #endif // STORAGE_ROCKSDB_INCLUDE_COMPACTION_FILTER_H_

@ -340,18 +340,21 @@ class DB {
// files are held from being deleted, by iterators or unfinished // files are held from being deleted, by iterators or unfinished
// compactions. // compactions.
// "rocksdb.estimate-live-data-size" // "rocksdb.estimate-live-data-size"
// "rocksdb.total-sst-files-size" - total size of all used sst files, this may // "rocksdb.total-sst-files-size" - total size of all used sst files, this
// slow down online queries if there are too many files. // may slow down online queries if there are too many files.
// "rocksdb.base-level" // "rocksdb.base-level"
// "rocksdb.estimate-pending-compaction-bytes" - estimated total number of // "rocksdb.estimate-pending-compaction-bytes" - estimated total number of
// bytes compaction needs to rewrite the data to get all levels down // bytes compaction needs to rewrite the data to get all levels down
// to under target size. Not valid for other compactions than level-based. // to under target size. Not valid for other compactions than
// "rocksdb.aggregated-table-properties" - returns a string representation of // level-based.
// the aggregated table properties of the target column family. // "rocksdb.aggregated-table-properties" - returns a string representation
// of the aggregated table properties of the target column family.
// "rocksdb.aggregated-table-properties-at-level<N>", same as the previous // "rocksdb.aggregated-table-properties-at-level<N>", same as the previous
// one but only returns the aggregated table properties of the specified // one but only returns the aggregated table properties of the specified
// level "N" at the target column family. // level "N" at the target column family.
// replaced by the target level. // "rocksdb.num-running-compactions" - the number of currently running
// compacitons.
// "rocksdb.num-running-flushes" - the number of currently running flushes.
#ifndef ROCKSDB_LITE #ifndef ROCKSDB_LITE
struct Properties { struct Properties {
static const std::string kNumFilesAtLevelPrefix; static const std::string kNumFilesAtLevelPrefix;
@ -361,7 +364,9 @@ class DB {
static const std::string kDBStats; static const std::string kDBStats;
static const std::string kNumImmutableMemTable; static const std::string kNumImmutableMemTable;
static const std::string kMemTableFlushPending; static const std::string kMemTableFlushPending;
static const std::string kNumRunningFlushes;
static const std::string kCompactionPending; static const std::string kCompactionPending;
static const std::string kNumRunningCompactions;
static const std::string kBackgroundErrors; static const std::string kBackgroundErrors;
static const std::string kCurSizeActiveMemTable; static const std::string kCurSizeActiveMemTable;
static const std::string kCurSizeAllMemTables; static const std::string kCurSizeAllMemTables;
@ -414,6 +419,8 @@ class DB {
// "rocksdb.total-sst-files-size" // "rocksdb.total-sst-files-size"
// "rocksdb.base-level" // "rocksdb.base-level"
// "rocksdb.estimate-pending-compaction-bytes" // "rocksdb.estimate-pending-compaction-bytes"
// "rocksdb.num-running-compactions"
// "rocksdb.num-running-flushes"
virtual bool GetIntProperty(ColumnFamilyHandle* column_family, virtual bool GetIntProperty(ColumnFamilyHandle* column_family,
const Slice& property, uint64_t* value) = 0; const Slice& property, uint64_t* value) = 0;
virtual bool GetIntProperty(const Slice& property, uint64_t* value) { virtual bool GetIntProperty(const Slice& property, uint64_t* value) {
@ -709,6 +716,9 @@ class DB {
virtual Status GetPropertiesOfAllTables(TablePropertiesCollection* props) { virtual Status GetPropertiesOfAllTables(TablePropertiesCollection* props) {
return GetPropertiesOfAllTables(DefaultColumnFamily(), props); return GetPropertiesOfAllTables(DefaultColumnFamily(), props);
} }
virtual Status GetPropertiesOfTablesInRange(
ColumnFamilyHandle* column_family, const Range* range, std::size_t n,
TablePropertiesCollection* props) = 0;
#endif // ROCKSDB_LITE #endif // ROCKSDB_LITE
// Needed for StackableDB // Needed for StackableDB

@ -24,10 +24,32 @@
namespace rocksdb { namespace rocksdb {
class Iterator { class Cleanable {
public: public:
Iterator(); Cleanable();
virtual ~Iterator(); ~Cleanable();
// Clients are allowed to register function/arg1/arg2 triples that
// will be invoked when this iterator is destroyed.
//
// Note that unlike all of the preceding methods, this method is
// not abstract and therefore clients should not override it.
typedef void (*CleanupFunction)(void* arg1, void* arg2);
void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2);
protected:
struct Cleanup {
CleanupFunction function;
void* arg1;
void* arg2;
Cleanup* next;
};
Cleanup cleanup_;
};
class Iterator : public Cleanable {
public:
Iterator() {}
virtual ~Iterator() {}
// An iterator is either positioned at a key/value pair, or // An iterator is either positioned at a key/value pair, or
// not valid. This method returns true iff the iterator is valid. // not valid. This method returns true iff the iterator is valid.
@ -73,23 +95,7 @@ class Iterator {
// satisfied without doing some IO, then this returns Status::Incomplete(). // satisfied without doing some IO, then this returns Status::Incomplete().
virtual Status status() const = 0; virtual Status status() const = 0;
// Clients are allowed to register function/arg1/arg2 triples that
// will be invoked when this iterator is destroyed.
//
// Note that unlike all of the preceding methods, this method is
// not abstract and therefore clients should not override it.
typedef void (*CleanupFunction)(void* arg1, void* arg2);
void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2);
private: private:
struct Cleanup {
CleanupFunction function;
void* arg1;
void* arg2;
Cleanup* next;
};
Cleanup cleanup_;
// No copying allowed // No copying allowed
Iterator(const Iterator&); Iterator(const Iterator&);
void operator=(const Iterator&); void operator=(const Iterator&);

@ -27,42 +27,42 @@ struct PerfContext {
uint64_t block_cache_hit_count; // total number of block cache hits uint64_t block_cache_hit_count; // total number of block cache hits
uint64_t block_read_count; // total number of block reads (with IO) uint64_t block_read_count; // total number of block reads (with IO)
uint64_t block_read_byte; // total number of bytes from block reads uint64_t block_read_byte; // total number of bytes from block reads
uint64_t block_read_time; // total time spent on block reads uint64_t block_read_time; // total nanos spent on block reads
uint64_t block_checksum_time; // total time spent on block checksum uint64_t block_checksum_time; // total nanos spent on block checksum
uint64_t block_decompress_time; // total time spent on block decompression uint64_t block_decompress_time; // total nanos spent on block decompression
// total number of internal keys skipped over during iteration (overwritten or // total number of internal keys skipped over during iteration (overwritten or
// deleted, to be more specific, hidden by a put or delete of the same key) // deleted, to be more specific, hidden by a put or delete of the same key)
uint64_t internal_key_skipped_count; uint64_t internal_key_skipped_count;
// total number of deletes and single deletes skipped over during iteration // total number of deletes and single deletes skipped over during iteration
uint64_t internal_delete_skipped_count; uint64_t internal_delete_skipped_count;
uint64_t get_snapshot_time; // total time spent on getting snapshot uint64_t get_snapshot_time; // total nanos spent on getting snapshot
uint64_t get_from_memtable_time; // total time spent on querying memtables uint64_t get_from_memtable_time; // total nanos spent on querying memtables
uint64_t get_from_memtable_count; // number of mem tables queried uint64_t get_from_memtable_count; // number of mem tables queried
// total time spent after Get() finds a key // total nanos spent after Get() finds a key
uint64_t get_post_process_time; uint64_t get_post_process_time;
uint64_t get_from_output_files_time; // total time reading from output files uint64_t get_from_output_files_time; // total nanos reading from output files
// total time spent on seeking memtable // total nanos spent on seeking memtable
uint64_t seek_on_memtable_time; uint64_t seek_on_memtable_time;
// number of seeks issued on memtable // number of seeks issued on memtable
uint64_t seek_on_memtable_count; uint64_t seek_on_memtable_count;
// total time spent on seeking child iters // total nanos spent on seeking child iters
uint64_t seek_child_seek_time; uint64_t seek_child_seek_time;
// number of seek issued in child iterators // number of seek issued in child iterators
uint64_t seek_child_seek_count; uint64_t seek_child_seek_count;
uint64_t seek_min_heap_time; // total time spent on the merge heap uint64_t seek_min_heap_time; // total nanos spent on the merge heap
// total time spent on seeking the internal entries // total nanos spent on seeking the internal entries
uint64_t seek_internal_seek_time; uint64_t seek_internal_seek_time;
// total time spent on iterating internal entries to find the next user entry // total nanos spent on iterating internal entries to find the next user entry
uint64_t find_next_user_entry_time; uint64_t find_next_user_entry_time;
// total time spent on writing to WAL // total nanos spent on writing to WAL
uint64_t write_wal_time; uint64_t write_wal_time;
// total time spent on writing to mem tables // total nanos spent on writing to mem tables
uint64_t write_memtable_time; uint64_t write_memtable_time;
// total time spent on delaying write // total nanos spent on delaying write
uint64_t write_delay_time; uint64_t write_delay_time;
// total time spent on writing a record, excluding the above three times // total nanos spent on writing a record, excluding the above three times
uint64_t write_pre_and_post_process_time; uint64_t write_pre_and_post_process_time;
uint64_t db_mutex_lock_nanos; // time spent on acquiring DB mutex. uint64_t db_mutex_lock_nanos; // time spent on acquiring DB mutex.

@ -279,6 +279,13 @@ class StackableDB : public DB {
return db_->GetPropertiesOfAllTables(column_family, props); return db_->GetPropertiesOfAllTables(column_family, props);
} }
using DB::GetPropertiesOfTablesInRange;
virtual Status GetPropertiesOfTablesInRange(
ColumnFamilyHandle* column_family, const Range* range, std::size_t n,
TablePropertiesCollection* props) override {
return db_->GetPropertiesOfTablesInRange(column_family, range, n, props);
}
virtual Status GetUpdatesSince( virtual Status GetUpdatesSince(
SequenceNumber seq_number, unique_ptr<TransactionLogIterator>* iter, SequenceNumber seq_number, unique_ptr<TransactionLogIterator>* iter,
const TransactionLogIterator::ReadOptions& read_options) override { const TransactionLogIterator::ReadOptions& read_options) override {

@ -83,10 +83,22 @@ class Transaction {
// Returns the Snapshot created by the last call to SetSnapshot(). // Returns the Snapshot created by the last call to SetSnapshot().
// //
// REQUIRED: The returned Snapshot is only valid up until the next time // REQUIRED: The returned Snapshot is only valid up until the next time
// SetSnapshot()/SetSnapshotOnNextSavePoint() is called or the Transaction // SetSnapshot()/SetSnapshotOnNextSavePoint() is called, ClearSnapshot()
// is deleted. // is called, or the Transaction is deleted.
virtual const Snapshot* GetSnapshot() const = 0; virtual const Snapshot* GetSnapshot() const = 0;
// Clears the current snapshot (i.e. no snapshot will be 'set')
//
// This removes any snapshot that currently exists or is set to be created
// on the next update operation (SetSnapshotOnNextOperation).
//
// Calling ClearSnapshot() has no effect on keys written before this function
// has been called.
//
// If a reference to a snapshot was retrieved via GetSnapshot(), it will no
// longer be valid and should be discarded after a call to ClearSnapshot().
virtual void ClearSnapshot() = 0;
// Write all batched keys to the db atomically. // Write all batched keys to the db atomically.
// //
// Returns OK on success. // Returns OK on success.
@ -202,10 +214,6 @@ class Transaction {
// //
// The returned iterator is only valid until Commit(), Rollback(), or // The returned iterator is only valid until Commit(), Rollback(), or
// RollbackToSavePoint() is called. // RollbackToSavePoint() is called.
// NOTE: Transaction::Put/Merge/Delete will currently invalidate this iterator
// until
// the following issue is fixed:
// https://github.com/facebook/rocksdb/issues/616
virtual Iterator* GetIterator(const ReadOptions& read_options) = 0; virtual Iterator* GetIterator(const ReadOptions& read_options) = 0;
virtual Iterator* GetIterator(const ReadOptions& read_options, virtual Iterator* GetIterator(const ReadOptions& read_options,

@ -15,7 +15,7 @@ Once you have these items, run this make command from RocksDB's root source dire
This command will build RocksDB natively on OSX, and will then spin up two Vagrant Virtualbox Ubuntu images to build RocksDB for both 32-bit and 64-bit Linux. This command will build RocksDB natively on OSX, and will then spin up two Vagrant Virtualbox Ubuntu images to build RocksDB for both 32-bit and 64-bit Linux.
You can find all native binaries and JARs in the java directory upon completion: You can find all native binaries and JARs in the java/target directory upon completion:
librocksdbjni-linux32.so librocksdbjni-linux32.so
librocksdbjni-linux64.so librocksdbjni-linux64.so

@ -20,7 +20,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
end end
config.vm.provision :shell, path: "build-linux-centos.sh" config.vm.provision :shell, path: "build-linux-centos.sh"
config.vm.synced_folder "../", "/rocksdb-build" config.vm.synced_folder "../target", "/rocksdb-build"
config.vm.synced_folder "../..", "/rocksdb", type: "rsync" config.vm.synced_folder "../..", "/rocksdb", type: "rsync"
config.vm.boot_timeout = 1200 config.vm.boot_timeout = 1200
end end

@ -1,9 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# install all required packages for rocksdb that are available through yum # install all required packages for rocksdb that are available through yum
ARCH=$(uname -i) ARCH=$(uname -i)
sudo yum -y install openssl java-1.7.0-openjdk-devel.$ARCH zlib zlib-devel bzip2 bzip2-devel sudo yum -y install openssl java-1.7.0-openjdk-devel.$ARCH
sudo yum -y install epel-release-5-4.noarch
sudo yum -y install snappy snappy-devel
# install gcc/g++ 4.8.2 via CERN (http://linux.web.cern.ch/linux/devtoolset/) # install gcc/g++ 4.8.2 via CERN (http://linux.web.cern.ch/linux/devtoolset/)
sudo wget -O /etc/yum.repos.d/slc5-devtoolset.repo http://linuxsoft.cern.ch/cern/devtoolset/slc5-devtoolset.repo sudo wget -O /etc/yum.repos.d/slc5-devtoolset.repo http://linuxsoft.cern.ch/cern/devtoolset/slc5-devtoolset.repo

@ -20,8 +20,8 @@
#include "db/writebuffer.h" #include "db/writebuffer.h"
#include "rocksdb/env.h" #include "rocksdb/env.h"
#include "rocksdb/memtablerep.h" #include "rocksdb/memtablerep.h"
#include "table/scoped_arena_iterator.h"
#include "util/logging.h" #include "util/logging.h"
#include "util/scoped_arena_iterator.h"
#include "util/testharness.h" #include "util/testharness.h"
/* /*

@ -21,8 +21,8 @@
#include "rocksdb/status.h" #include "rocksdb/status.h"
#include "rocksdb/write_batch.h" #include "rocksdb/write_batch.h"
#include "rocksjni/portal.h" #include "rocksjni/portal.h"
#include "table/scoped_arena_iterator.h"
#include "util/logging.h" #include "util/logging.h"
#include "util/scoped_arena_iterator.h"
#include "util/testharness.h" #include "util/testharness.h"
/* /*

@ -5,8 +5,7 @@
// //
#ifndef ROCKSDB_LITE #ifndef ROCKSDB_LITE
#include "memtable/hash_cuckoo_rep.h"
#include "util/hash_cuckoo_rep.h"
#include <algorithm> #include <algorithm>
#include <atomic> #include <atomic>
@ -18,9 +17,10 @@
#include "db/memtable.h" #include "db/memtable.h"
#include "db/skiplist.h" #include "db/skiplist.h"
#include "memtable/stl_wrappers.h"
#include "port/port.h"
#include "rocksdb/memtablerep.h" #include "rocksdb/memtablerep.h"
#include "util/murmurhash.h" #include "util/murmurhash.h"
#include "util/stl_wrappers.h"
namespace rocksdb { namespace rocksdb {
namespace { namespace {

@ -6,8 +6,9 @@
// Use of this source code is governed by a BSD-style license that can be // 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. // found in the LICENSE file. See the AUTHORS file for names of contributors.
#ifndef ROCKSDB_LITE
#pragma once #pragma once
#ifndef ROCKSDB_LITE
#include "port/port.h"
#include "rocksdb/slice_transform.h" #include "rocksdb/slice_transform.h"
#include "rocksdb/memtablerep.h" #include "rocksdb/memtablerep.h"

@ -5,7 +5,7 @@
// //
#ifndef ROCKSDB_LITE #ifndef ROCKSDB_LITE
#include "util/hash_linklist_rep.h" #include "memtable/hash_linklist_rep.h"
#include <algorithm> #include <algorithm>
#include <atomic> #include <atomic>

@ -6,8 +6,8 @@
// Use of this source code is governed by a BSD-style license that can be // 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. // found in the LICENSE file. See the AUTHORS file for names of contributors.
#ifndef ROCKSDB_LITE
#pragma once #pragma once
#ifndef ROCKSDB_LITE
#include "rocksdb/slice_transform.h" #include "rocksdb/slice_transform.h"
#include "rocksdb/memtablerep.h" #include "rocksdb/memtablerep.h"

@ -5,7 +5,7 @@
// //
#ifndef ROCKSDB_LITE #ifndef ROCKSDB_LITE
#include "util/hash_skiplist_rep.h" #include "memtable/hash_skiplist_rep.h"
#include <atomic> #include <atomic>

@ -6,8 +6,8 @@
// Use of this source code is governed by a BSD-style license that can be // 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. // found in the LICENSE file. See the AUTHORS file for names of contributors.
#ifndef ROCKSDB_LITE
#pragma once #pragma once
#ifndef ROCKSDB_LITE
#include "rocksdb/slice_transform.h" #include "rocksdb/slice_transform.h"
#include "rocksdb/memtablerep.h" #include "rocksdb/memtablerep.h"

@ -30,17 +30,5 @@ struct Compare : private Base {
} }
}; };
struct LessOfComparator {
explicit LessOfComparator(const Comparator* c = BytewiseComparator())
: cmp(c) {}
bool operator()(const std::string& a, const std::string& b) const {
return cmp->Compare(Slice(a), Slice(b)) < 0;
}
const Comparator* cmp;
};
typedef std::map<std::string, std::string, LessOfComparator> KVMap;
} }
} }

@ -963,7 +963,7 @@ class WinWritableFile : public WritableFile {
virtual Status Allocate(off_t offset, off_t len) override { virtual Status Allocate(off_t offset, off_t len) override {
Status status; Status status;
TEST_KILL_RANDOM(rocksdb_kill_odds); TEST_KILL_RANDOM("WinWritableFile::Allocate", rocksdb_kill_odds);
// Make sure that we reserve an aligned amount of space // Make sure that we reserve an aligned amount of space
// since the reservation block size is driven outside so we want // since the reservation block size is driven outside so we want

@ -114,8 +114,11 @@ class CondVar;
class Mutex { class Mutex {
public: public:
/* implicit */ Mutex(bool adaptive = false) : locked_(false) { /* implicit */ Mutex(bool adaptive = false)
} #ifndef NDEBUG
: locked_(false)
#endif
{ }
~Mutex(); ~Mutex();

@ -46,6 +46,9 @@ LIB_SOURCES = \
db/write_batch_base.cc \ db/write_batch_base.cc \
db/write_controller.cc \ db/write_controller.cc \
db/write_thread.cc \ db/write_thread.cc \
memtable/hash_cuckoo_rep.cc \
memtable/hash_linklist_rep.cc \
memtable/hash_skiplist_rep.cc \
port/stack_trace.cc \ port/stack_trace.cc \
port/port_posix.cc \ port/port_posix.cc \
table/adaptive_table_factory.cc \ table/adaptive_table_factory.cc \
@ -96,9 +99,6 @@ LIB_SOURCES = \
util/file_reader_writer.cc \ util/file_reader_writer.cc \
util/filter_policy.cc \ util/filter_policy.cc \
util/hash.cc \ util/hash.cc \
util/hash_cuckoo_rep.cc \
util/hash_linklist_rep.cc \
util/hash_skiplist_rep.cc \
util/histogram.cc \ util/histogram.cc \
util/instrumented_mutex.cc \ util/instrumented_mutex.cc \
util/iostats_context.cc \ util/iostats_context.cc \
@ -161,9 +161,9 @@ LIB_SOURCES = \
util/xxhash.cc \ util/xxhash.cc \
TOOL_SOURCES = \ TOOL_SOURCES = \
util/ldb_cmd.cc \ tools/ldb_cmd.cc \
util/ldb_tool.cc \ tools/ldb_tool.cc \
util/sst_dump_tool.cc \ tools/sst_dump_tool.cc \
MOCK_SOURCES = \ MOCK_SOURCES = \
table/mock_table.cc \ table/mock_table.cc \
@ -190,6 +190,7 @@ TEST_BENCH_SOURCES = \
db/db_universal_compaction_test.cc \ db/db_universal_compaction_test.cc \
db/db_tailing_iter_test.cc \ db/db_tailing_iter_test.cc \
db/db_wal_test.cc \ db/db_wal_test.cc \
db/db_table_properties_test.cc \
db/deletefile_test.cc \ db/deletefile_test.cc \
db/fault_injection_test.cc \ db/fault_injection_test.cc \
db/file_indexer_test.cc \ db/file_indexer_test.cc \
@ -198,6 +199,7 @@ TEST_BENCH_SOURCES = \
db/listener_test.cc \ db/listener_test.cc \
db/log_and_apply_bench.cc \ db/log_and_apply_bench.cc \
db/log_test.cc \ db/log_test.cc \
db/manual_compaction_test.cc \
db/memtablerep_bench.cc \ db/memtablerep_bench.cc \
db/merge_test.cc \ db/merge_test.cc \
db/perf_context_test.cc \ db/perf_context_test.cc \
@ -223,7 +225,9 @@ TEST_BENCH_SOURCES = \
table/table_reader_bench.cc \ table/table_reader_bench.cc \
table/table_test.cc \ table/table_test.cc \
tools/db_sanity_test.cc \ tools/db_sanity_test.cc \
tools/ldb_cmd_test.cc \
tools/reduce_levels_test.cc \ tools/reduce_levels_test.cc \
tools/sst_dump_test.cc \
util/arena_test.cc \ util/arena_test.cc \
util/auto_roll_logger_test.cc \ util/auto_roll_logger_test.cc \
util/autovector_test.cc \ util/autovector_test.cc \
@ -252,19 +256,16 @@ TEST_BENCH_SOURCES = \
utilities/ttl/ttl_test.cc \ utilities/ttl/ttl_test.cc \
utilities/write_batch_with_index/write_batch_with_index_test.cc \ utilities/write_batch_with_index/write_batch_with_index_test.cc \
util/log_write_bench.cc \ util/log_write_bench.cc \
util/manual_compaction_test.cc \
util/memenv_test.cc \ util/memenv_test.cc \
util/mock_env_test.cc \ util/mock_env_test.cc \
util/options_test.cc \ util/options_test.cc \
util/event_logger_test.cc \ util/event_logger_test.cc \
util/rate_limiter_test.cc \ util/rate_limiter_test.cc \
util/slice_transform_test.cc \ util/slice_transform_test.cc \
util/sst_dump_test.cc \
util/testharness.cc \ util/testharness.cc \
util/testutil.cc \ util/testutil.cc \
util/thread_list_test.cc \ util/thread_list_test.cc \
util/thread_local_test.cc \ util/thread_local_test.cc
util/ldb_cmd_test.cc
JNI_NATIVE_SOURCES = \ JNI_NATIVE_SOURCES = \
java/rocksjni/backupenginejni.cc \ java/rocksjni/backupenginejni.cc \

@ -316,14 +316,14 @@ Block::Block(BlockContents&& contents)
} }
} }
Iterator* Block::NewIterator( InternalIterator* Block::NewIterator(const Comparator* cmp, BlockIter* iter,
const Comparator* cmp, BlockIter* iter, bool total_order_seek) { bool total_order_seek) {
if (size_ < 2*sizeof(uint32_t)) { if (size_ < 2*sizeof(uint32_t)) {
if (iter != nullptr) { if (iter != nullptr) {
iter->SetStatus(Status::Corruption("bad block contents")); iter->SetStatus(Status::Corruption("bad block contents"));
return iter; return iter;
} else { } else {
return NewErrorIterator(Status::Corruption("bad block contents")); return NewErrorInternalIterator(Status::Corruption("bad block contents"));
} }
} }
const uint32_t num_restarts = NumRestarts(); const uint32_t num_restarts = NumRestarts();
@ -332,7 +332,7 @@ Iterator* Block::NewIterator(
iter->SetStatus(Status::OK()); iter->SetStatus(Status::OK());
return iter; return iter;
} else { } else {
return NewEmptyIterator(); return NewEmptyInternalIterator();
} }
} else { } else {
BlockHashIndex* hash_index_ptr = BlockHashIndex* hash_index_ptr =

@ -19,6 +19,7 @@
#include "db/dbformat.h" #include "db/dbformat.h"
#include "table/block_prefix_index.h" #include "table/block_prefix_index.h"
#include "table/block_hash_index.h" #include "table/block_hash_index.h"
#include "table/internal_iterator.h"
#include "format.h" #include "format.h"
@ -66,8 +67,9 @@ class Block {
// If total_order_seek is true, hash_index_ and prefix_index_ are ignored. // If total_order_seek is true, hash_index_ and prefix_index_ are ignored.
// This option only applies for index block. For data block, hash_index_ // This option only applies for index block. For data block, hash_index_
// and prefix_index_ are null, so this option does not matter. // and prefix_index_ are null, so this option does not matter.
Iterator* NewIterator(const Comparator* comparator, InternalIterator* NewIterator(const Comparator* comparator,
BlockIter* iter = nullptr, bool total_order_seek = true); BlockIter* iter = nullptr,
bool total_order_seek = true);
void SetBlockHashIndex(BlockHashIndex* hash_index); void SetBlockHashIndex(BlockHashIndex* hash_index);
void SetBlockPrefixIndex(BlockPrefixIndex* prefix_index); void SetBlockPrefixIndex(BlockPrefixIndex* prefix_index);
@ -87,7 +89,7 @@ class Block {
void operator=(const Block&); void operator=(const Block&);
}; };
class BlockIter : public Iterator { class BlockIter : public InternalIterator {
public: public:
BlockIter() BlockIter()
: comparator_(nullptr), : comparator_(nullptr),

@ -32,6 +32,7 @@
#include "table/block_hash_index.h" #include "table/block_hash_index.h"
#include "table/block_prefix_index.h" #include "table/block_prefix_index.h"
#include "table/format.h" #include "table/format.h"
#include "table/internal_iterator.h"
#include "table/meta_blocks.h" #include "table/meta_blocks.h"
#include "table/two_level_iterator.h" #include "table/two_level_iterator.h"
#include "table/get_context.h" #include "table/get_context.h"
@ -146,8 +147,8 @@ class BlockBasedTable::IndexReader {
// Create an iterator for index access. // Create an iterator for index access.
// An iter is passed in, if it is not null, update this one and return it // An iter is passed in, if it is not null, update this one and return it
// If it is null, create a new Iterator // If it is null, create a new Iterator
virtual Iterator* NewIterator( virtual InternalIterator* NewIterator(BlockIter* iter = nullptr,
BlockIter* iter = nullptr, bool total_order_seek = true) = 0; bool total_order_seek = true) = 0;
// The size of the index. // The size of the index.
virtual size_t size() const = 0; virtual size_t size() const = 0;
@ -187,8 +188,8 @@ class BinarySearchIndexReader : public IndexReader {
return s; return s;
} }
virtual Iterator* NewIterator( virtual InternalIterator* NewIterator(BlockIter* iter = nullptr,
BlockIter* iter = nullptr, bool dont_care = true) override { bool dont_care = true) override {
return index_block_->NewIterator(comparator_, iter, true); return index_block_->NewIterator(comparator_, iter, true);
} }
@ -219,7 +220,8 @@ class HashIndexReader : public IndexReader {
const Footer& footer, RandomAccessFileReader* file, const Footer& footer, RandomAccessFileReader* file,
Env* env, const Comparator* comparator, Env* env, const Comparator* comparator,
const BlockHandle& index_handle, const BlockHandle& index_handle,
Iterator* meta_index_iter, IndexReader** index_reader, InternalIterator* meta_index_iter,
IndexReader** index_reader,
bool hash_index_allow_collision) { bool hash_index_allow_collision) {
std::unique_ptr<Block> index_block; std::unique_ptr<Block> index_block;
auto s = ReadBlockFromFile(file, footer, ReadOptions(), index_handle, auto s = ReadBlockFromFile(file, footer, ReadOptions(), index_handle,
@ -298,8 +300,8 @@ class HashIndexReader : public IndexReader {
return Status::OK(); return Status::OK();
} }
virtual Iterator* NewIterator( virtual InternalIterator* NewIterator(BlockIter* iter = nullptr,
BlockIter* iter = nullptr, bool total_order_seek = true) override { bool total_order_seek = true) override {
return index_block_->NewIterator(comparator_, iter, total_order_seek); return index_block_->NewIterator(comparator_, iter, total_order_seek);
} }
@ -512,7 +514,7 @@ Status BlockBasedTable::Open(const ImmutableCFOptions& ioptions,
// Read meta index // Read meta index
std::unique_ptr<Block> meta; std::unique_ptr<Block> meta;
std::unique_ptr<Iterator> meta_iter; std::unique_ptr<InternalIterator> meta_iter;
s = ReadMetaBlock(rep, &meta, &meta_iter); s = ReadMetaBlock(rep, &meta, &meta_iter);
if (!s.ok()) { if (!s.ok()) {
return s; return s;
@ -580,7 +582,8 @@ Status BlockBasedTable::Open(const ImmutableCFOptions& ioptions,
assert(table_options.block_cache != nullptr); assert(table_options.block_cache != nullptr);
// Hack: Call NewIndexIterator() to implicitly add index to the // Hack: Call NewIndexIterator() to implicitly add index to the
// block_cache // block_cache
unique_ptr<Iterator> iter(new_table->NewIndexIterator(ReadOptions())); unique_ptr<InternalIterator> iter(
new_table->NewIndexIterator(ReadOptions()));
s = iter->status(); s = iter->status();
if (s.ok()) { if (s.ok()) {
@ -652,10 +655,9 @@ size_t BlockBasedTable::ApproximateMemoryUsage() const {
// Load the meta-block from the file. On success, return the loaded meta block // Load the meta-block from the file. On success, return the loaded meta block
// and its iterator. // and its iterator.
Status BlockBasedTable::ReadMetaBlock( Status BlockBasedTable::ReadMetaBlock(Rep* rep,
Rep* rep,
std::unique_ptr<Block>* meta_block, std::unique_ptr<Block>* meta_block,
std::unique_ptr<Iterator>* iter) { std::unique_ptr<InternalIterator>* iter) {
// TODO(sanjay): Skip this if footer.metaindex_handle() size indicates // TODO(sanjay): Skip this if footer.metaindex_handle() size indicates
// it is an empty block. // it is an empty block.
// TODO: we never really verify check sum for meta index block // TODO: we never really verify check sum for meta index block
@ -898,8 +900,8 @@ BlockBasedTable::CachableEntry<FilterBlockReader> BlockBasedTable::GetFilter(
return { filter, cache_handle }; return { filter, cache_handle };
} }
Iterator* BlockBasedTable::NewIndexIterator(const ReadOptions& read_options, InternalIterator* BlockBasedTable::NewIndexIterator(
BlockIter* input_iter) { const ReadOptions& read_options, BlockIter* input_iter) {
// index reader has already been pre-populated. // index reader has already been pre-populated.
if (rep_->index_reader) { if (rep_->index_reader) {
return rep_->index_reader->NewIterator( return rep_->index_reader->NewIterator(
@ -922,7 +924,7 @@ Iterator* BlockBasedTable::NewIndexIterator(const ReadOptions& read_options,
input_iter->SetStatus(Status::Incomplete("no blocking io")); input_iter->SetStatus(Status::Incomplete("no blocking io"));
return input_iter; return input_iter;
} else { } else {
return NewErrorIterator(Status::Incomplete("no blocking io")); return NewErrorInternalIterator(Status::Incomplete("no blocking io"));
} }
} }
@ -942,7 +944,7 @@ Iterator* BlockBasedTable::NewIndexIterator(const ReadOptions& read_options,
input_iter->SetStatus(s); input_iter->SetStatus(s);
return input_iter; return input_iter;
} else { } else {
return NewErrorIterator(s); return NewErrorInternalIterator(s);
} }
} }
@ -965,8 +967,8 @@ Iterator* BlockBasedTable::NewIndexIterator(const ReadOptions& read_options,
// into an iterator over the contents of the corresponding block. // into an iterator over the contents of the corresponding block.
// If input_iter is null, new a iterator // If input_iter is null, new a iterator
// If input_iter is not null, update this iter and return it // If input_iter is not null, update this iter and return it
Iterator* BlockBasedTable::NewDataBlockIterator(Rep* rep, InternalIterator* BlockBasedTable::NewDataBlockIterator(
const ReadOptions& ro, const Slice& index_value, Rep* rep, const ReadOptions& ro, const Slice& index_value,
BlockIter* input_iter) { BlockIter* input_iter) {
PERF_TIMER_GUARD(new_table_block_iter_nanos); PERF_TIMER_GUARD(new_table_block_iter_nanos);
@ -987,7 +989,7 @@ Iterator* BlockBasedTable::NewDataBlockIterator(Rep* rep,
input_iter->SetStatus(s); input_iter->SetStatus(s);
return input_iter; return input_iter;
} else { } else {
return NewErrorIterator(s); return NewErrorInternalIterator(s);
} }
} }
@ -1040,7 +1042,7 @@ Iterator* BlockBasedTable::NewDataBlockIterator(Rep* rep,
input_iter->SetStatus(Status::Incomplete("no blocking io")); input_iter->SetStatus(Status::Incomplete("no blocking io"));
return input_iter; return input_iter;
} else { } else {
return NewErrorIterator(Status::Incomplete("no blocking io")); return NewErrorInternalIterator(Status::Incomplete("no blocking io"));
} }
} }
std::unique_ptr<Block> block_value; std::unique_ptr<Block> block_value;
@ -1051,7 +1053,7 @@ Iterator* BlockBasedTable::NewDataBlockIterator(Rep* rep,
} }
} }
Iterator* iter; InternalIterator* iter;
if (block.value != nullptr) { if (block.value != nullptr) {
iter = block.value->NewIterator(&rep->internal_comparator, input_iter); iter = block.value->NewIterator(&rep->internal_comparator, input_iter);
if (block.cache_handle != nullptr) { if (block.cache_handle != nullptr) {
@ -1065,7 +1067,7 @@ Iterator* BlockBasedTable::NewDataBlockIterator(Rep* rep,
input_iter->SetStatus(s); input_iter->SetStatus(s);
iter = input_iter; iter = input_iter;
} else { } else {
iter = NewErrorIterator(s); iter = NewErrorInternalIterator(s);
} }
} }
return iter; return iter;
@ -1080,7 +1082,7 @@ class BlockBasedTable::BlockEntryIteratorState : public TwoLevelIteratorState {
table_(table), table_(table),
read_options_(read_options) {} read_options_(read_options) {}
Iterator* NewSecondaryIterator(const Slice& index_value) override { InternalIterator* NewSecondaryIterator(const Slice& index_value) override {
return NewDataBlockIterator(table_->rep_, read_options_, index_value); return NewDataBlockIterator(table_->rep_, read_options_, index_value);
} }
@ -1138,7 +1140,7 @@ bool BlockBasedTable::PrefixMayMatch(const Slice& internal_key) {
// Then, try find it within each block // Then, try find it within each block
if (may_match) { if (may_match) {
unique_ptr<Iterator> iiter(NewIndexIterator(no_io_read_options)); unique_ptr<InternalIterator> iiter(NewIndexIterator(no_io_read_options));
iiter->Seek(internal_prefix); iiter->Seek(internal_prefix);
if (!iiter->Valid()) { if (!iiter->Valid()) {
@ -1184,7 +1186,7 @@ bool BlockBasedTable::PrefixMayMatch(const Slice& internal_key) {
return may_match; return may_match;
} }
Iterator* BlockBasedTable::NewIterator(const ReadOptions& read_options, InternalIterator* BlockBasedTable::NewIterator(const ReadOptions& read_options,
Arena* arena) { Arena* arena) {
return NewTwoLevelIterator(new BlockEntryIteratorState(this, read_options), return NewTwoLevelIterator(new BlockEntryIteratorState(this, read_options),
NewIndexIterator(read_options), arena); NewIndexIterator(read_options), arena);
@ -1326,7 +1328,7 @@ Status BlockBasedTable::Prefetch(const Slice* const begin,
bool BlockBasedTable::TEST_KeyInCache(const ReadOptions& options, bool BlockBasedTable::TEST_KeyInCache(const ReadOptions& options,
const Slice& key) { const Slice& key) {
std::unique_ptr<Iterator> iiter(NewIndexIterator(options)); std::unique_ptr<InternalIterator> iiter(NewIndexIterator(options));
iiter->Seek(key); iiter->Seek(key);
assert(iiter->Valid()); assert(iiter->Valid());
CachableEntry<Block> block; CachableEntry<Block> block;
@ -1361,8 +1363,8 @@ bool BlockBasedTable::TEST_KeyInCache(const ReadOptions& options,
// 3. options // 3. options
// 4. internal_comparator // 4. internal_comparator
// 5. index_type // 5. index_type
Status BlockBasedTable::CreateIndexReader(IndexReader** index_reader, Status BlockBasedTable::CreateIndexReader(
Iterator* preloaded_meta_index_iter) { IndexReader** index_reader, InternalIterator* preloaded_meta_index_iter) {
// Some old version of block-based tables don't have index type present in // Some old version of block-based tables don't have index type present in
// table properties. If that's the case we can safely use the kBinarySearch. // table properties. If that's the case we can safely use the kBinarySearch.
auto index_type_on_file = BlockBasedTableOptions::kBinarySearch; auto index_type_on_file = BlockBasedTableOptions::kBinarySearch;
@ -1396,7 +1398,7 @@ Status BlockBasedTable::CreateIndexReader(IndexReader** index_reader,
} }
case BlockBasedTableOptions::kHashSearch: { case BlockBasedTableOptions::kHashSearch: {
std::unique_ptr<Block> meta_guard; std::unique_ptr<Block> meta_guard;
std::unique_ptr<Iterator> meta_iter_guard; std::unique_ptr<InternalIterator> meta_iter_guard;
auto meta_index_iter = preloaded_meta_index_iter; auto meta_index_iter = preloaded_meta_index_iter;
if (meta_index_iter == nullptr) { if (meta_index_iter == nullptr) {
auto s = ReadMetaBlock(rep_, &meta_guard, &meta_iter_guard); auto s = ReadMetaBlock(rep_, &meta_guard, &meta_iter_guard);
@ -1430,7 +1432,7 @@ Status BlockBasedTable::CreateIndexReader(IndexReader** index_reader,
} }
uint64_t BlockBasedTable::ApproximateOffsetOf(const Slice& key) { uint64_t BlockBasedTable::ApproximateOffsetOf(const Slice& key) {
unique_ptr<Iterator> index_iter(NewIndexIterator(ReadOptions())); unique_ptr<InternalIterator> index_iter(NewIndexIterator(ReadOptions()));
index_iter->Seek(key); index_iter->Seek(key);
uint64_t result; uint64_t result;
@ -1484,7 +1486,7 @@ Status BlockBasedTable::DumpTable(WritableFile* out_file) {
"Metaindex Details:\n" "Metaindex Details:\n"
"--------------------------------------\n"); "--------------------------------------\n");
std::unique_ptr<Block> meta; std::unique_ptr<Block> meta;
std::unique_ptr<Iterator> meta_iter; std::unique_ptr<InternalIterator> meta_iter;
Status s = ReadMetaBlock(rep_, &meta, &meta_iter); Status s = ReadMetaBlock(rep_, &meta, &meta_iter);
if (s.ok()) { if (s.ok()) {
for (meta_iter->SeekToFirst(); meta_iter->Valid(); meta_iter->Next()) { for (meta_iter->SeekToFirst(); meta_iter->Valid(); meta_iter->Next()) {
@ -1567,7 +1569,8 @@ Status BlockBasedTable::DumpIndexBlock(WritableFile* out_file) {
"Index Details:\n" "Index Details:\n"
"--------------------------------------\n"); "--------------------------------------\n");
std::unique_ptr<Iterator> blockhandles_iter(NewIndexIterator(ReadOptions())); std::unique_ptr<InternalIterator> blockhandles_iter(
NewIndexIterator(ReadOptions()));
Status s = blockhandles_iter->status(); Status s = blockhandles_iter->status();
if (!s.ok()) { if (!s.ok()) {
out_file->Append("Can not read Index Block \n\n"); out_file->Append("Can not read Index Block \n\n");
@ -1608,7 +1611,8 @@ Status BlockBasedTable::DumpIndexBlock(WritableFile* out_file) {
} }
Status BlockBasedTable::DumpDataBlocks(WritableFile* out_file) { Status BlockBasedTable::DumpDataBlocks(WritableFile* out_file) {
std::unique_ptr<Iterator> blockhandles_iter(NewIndexIterator(ReadOptions())); std::unique_ptr<InternalIterator> blockhandles_iter(
NewIndexIterator(ReadOptions()));
Status s = blockhandles_iter->status(); Status s = blockhandles_iter->status();
if (!s.ok()) { if (!s.ok()) {
out_file->Append("Can not read Index Block \n\n"); out_file->Append("Can not read Index Block \n\n");
@ -1630,7 +1634,7 @@ Status BlockBasedTable::DumpDataBlocks(WritableFile* out_file) {
out_file->Append("\n"); out_file->Append("\n");
out_file->Append("--------------------------------------\n"); out_file->Append("--------------------------------------\n");
std::unique_ptr<Iterator> datablock_iter; std::unique_ptr<InternalIterator> datablock_iter;
datablock_iter.reset( datablock_iter.reset(
NewDataBlockIterator(rep_, ReadOptions(), blockhandles_iter->value())); NewDataBlockIterator(rep_, ReadOptions(), blockhandles_iter->value()));
s = datablock_iter->status(); s = datablock_iter->status();

@ -43,6 +43,7 @@ struct BlockBasedTableOptions;
struct EnvOptions; struct EnvOptions;
struct ReadOptions; struct ReadOptions;
class GetContext; class GetContext;
class InternalIterator;
using std::unique_ptr; using std::unique_ptr;
@ -79,7 +80,8 @@ class BlockBasedTable : public TableReader {
// Returns a new iterator over the table contents. // Returns a new iterator over the table contents.
// The result of NewIterator() is initially invalid (caller must // The result of NewIterator() is initially invalid (caller must
// call one of the Seek methods on the iterator before using it). // call one of the Seek methods on the iterator before using it).
Iterator* NewIterator(const ReadOptions&, Arena* arena = nullptr) override; InternalIterator* NewIterator(const ReadOptions&,
Arena* arena = nullptr) override;
Status Get(const ReadOptions& readOptions, const Slice& key, Status Get(const ReadOptions& readOptions, const Slice& key,
GetContext* get_context) override; GetContext* get_context) override;
@ -129,8 +131,8 @@ class BlockBasedTable : public TableReader {
class BlockEntryIteratorState; class BlockEntryIteratorState;
// input_iter: if it is not null, update this one and return it as Iterator // input_iter: if it is not null, update this one and return it as Iterator
static Iterator* NewDataBlockIterator(Rep* rep, const ReadOptions& ro, static InternalIterator* NewDataBlockIterator(
const Slice& index_value, Rep* rep, const ReadOptions& ro, const Slice& index_value,
BlockIter* input_iter = nullptr); BlockIter* input_iter = nullptr);
// For the following two functions: // For the following two functions:
@ -148,7 +150,7 @@ class BlockBasedTable : public TableReader {
// 2. index is not present in block cache. // 2. index is not present in block cache.
// 3. We disallowed any io to be performed, that is, read_options == // 3. We disallowed any io to be performed, that is, read_options ==
// kBlockCacheTier // kBlockCacheTier
Iterator* NewIndexIterator(const ReadOptions& read_options, InternalIterator* NewIndexIterator(const ReadOptions& read_options,
BlockIter* input_iter = nullptr); BlockIter* input_iter = nullptr);
// Read block cache from block caches (if set): block_cache and // Read block cache from block caches (if set): block_cache and
@ -186,17 +188,16 @@ class BlockBasedTable : public TableReader {
// Optionally, user can pass a preloaded meta_index_iter for the index that // Optionally, user can pass a preloaded meta_index_iter for the index that
// need to access extra meta blocks for index construction. This parameter // need to access extra meta blocks for index construction. This parameter
// helps avoid re-reading meta index block if caller already created one. // helps avoid re-reading meta index block if caller already created one.
Status CreateIndexReader(IndexReader** index_reader, Status CreateIndexReader(
Iterator* preloaded_meta_index_iter = nullptr); IndexReader** index_reader,
InternalIterator* preloaded_meta_index_iter = nullptr);
bool FullFilterKeyMayMatch(FilterBlockReader* filter, bool FullFilterKeyMayMatch(FilterBlockReader* filter,
const Slice& user_key) const; const Slice& user_key) const;
// Read the meta block from sst. // Read the meta block from sst.
static Status ReadMetaBlock( static Status ReadMetaBlock(Rep* rep, std::unique_ptr<Block>* meta_block,
Rep* rep, std::unique_ptr<InternalIterator>* iter);
std::unique_ptr<Block>* meta_block,
std::unique_ptr<Iterator>* iter);
// Create the filter from the filter block. // Create the filter from the filter block.
static FilterBlockReader* ReadFilter(Rep* rep, size_t* filter_size = nullptr); static FilterBlockReader* ReadFilter(Rep* rep, size_t* filter_size = nullptr);

@ -10,6 +10,7 @@
#include "rocksdb/comparator.h" #include "rocksdb/comparator.h"
#include "rocksdb/iterator.h" #include "rocksdb/iterator.h"
#include "rocksdb/slice_transform.h" #include "rocksdb/slice_transform.h"
#include "table/internal_iterator.h"
#include "util/coding.h" #include "util/coding.h"
namespace rocksdb { namespace rocksdb {
@ -53,8 +54,9 @@ Status CreateBlockHashIndex(const SliceTransform* hash_key_extractor,
} }
BlockHashIndex* CreateBlockHashIndexOnTheFly( BlockHashIndex* CreateBlockHashIndexOnTheFly(
Iterator* index_iter, Iterator* data_iter, const uint32_t num_restarts, InternalIterator* index_iter, InternalIterator* data_iter,
const Comparator* comparator, const SliceTransform* hash_key_extractor) { const uint32_t num_restarts, const Comparator* comparator,
const SliceTransform* hash_key_extractor) {
assert(hash_key_extractor); assert(hash_key_extractor);
auto hash_index = new BlockHashIndex( auto hash_index = new BlockHashIndex(
hash_key_extractor, hash_key_extractor,

@ -14,7 +14,7 @@
namespace rocksdb { namespace rocksdb {
class Comparator; class Comparator;
class Iterator; class InternalIterator;
class Slice; class Slice;
class SliceTransform; class SliceTransform;
@ -79,7 +79,8 @@ Status CreateBlockHashIndex(const SliceTransform* hash_key_extractor,
// @params hash_key_extractor: extract the hashable part of a given key. // @params hash_key_extractor: extract the hashable part of a given key.
// On error, nullptr will be returned. // On error, nullptr will be returned.
BlockHashIndex* CreateBlockHashIndexOnTheFly( BlockHashIndex* CreateBlockHashIndexOnTheFly(
Iterator* index_iter, Iterator* data_iter, const uint32_t num_restarts, InternalIterator* index_iter, InternalIterator* data_iter,
const Comparator* comparator, const SliceTransform* hash_key_extractor); const uint32_t num_restarts, const Comparator* comparator,
const SliceTransform* hash_key_extractor);
} // namespace rocksdb } // namespace rocksdb

@ -11,6 +11,7 @@
#include "rocksdb/iterator.h" #include "rocksdb/iterator.h"
#include "rocksdb/slice_transform.h" #include "rocksdb/slice_transform.h"
#include "table/block_hash_index.h" #include "table/block_hash_index.h"
#include "table/internal_iterator.h"
#include "util/testharness.h" #include "util/testharness.h"
#include "util/testutil.h" #include "util/testutil.h"
@ -18,7 +19,7 @@ namespace rocksdb {
typedef std::map<std::string, std::string> Data; typedef std::map<std::string, std::string> Data;
class MapIterator : public Iterator { class MapIterator : public InternalIterator {
public: public:
explicit MapIterator(const Data& data) : data_(data), pos_(data_.end()) {} explicit MapIterator(const Data& data) : data_(data), pos_(data_.end()) {}

@ -96,7 +96,7 @@ TEST_F(BlockTest, SimpleTest) {
// read contents of block sequentially // read contents of block sequentially
int count = 0; int count = 0;
Iterator* iter = reader.NewIterator(options.comparator); InternalIterator *iter = reader.NewIterator(options.comparator);
for (iter->SeekToFirst();iter->Valid(); count++, iter->Next()) { for (iter->SeekToFirst();iter->Valid(); count++, iter->Next()) {
// read kv from block // read kv from block
@ -170,10 +170,10 @@ void CheckBlockContents(BlockContents contents, const int max_key,
delete iter2; delete iter2;
} }
std::unique_ptr<Iterator> hash_iter( std::unique_ptr<InternalIterator> hash_iter(
reader1.NewIterator(BytewiseComparator(), nullptr, false)); reader1.NewIterator(BytewiseComparator(), nullptr, false));
std::unique_ptr<Iterator> regular_iter( std::unique_ptr<InternalIterator> regular_iter(
reader2.NewIterator(BytewiseComparator())); reader2.NewIterator(BytewiseComparator()));
// Seek existent keys // Seek existent keys

@ -17,6 +17,7 @@
#include <vector> #include <vector>
#include "rocksdb/iterator.h" #include "rocksdb/iterator.h"
#include "rocksdb/table.h" #include "rocksdb/table.h"
#include "table/internal_iterator.h"
#include "table/meta_blocks.h" #include "table/meta_blocks.h"
#include "table/cuckoo_table_factory.h" #include "table/cuckoo_table_factory.h"
#include "table/get_context.h" #include "table/get_context.h"
@ -173,7 +174,7 @@ void CuckooTableReader::Prepare(const Slice& key) {
} }
} }
class CuckooTableIterator : public Iterator { class CuckooTableIterator : public InternalIterator {
public: public:
explicit CuckooTableIterator(CuckooTableReader* reader); explicit CuckooTableIterator(CuckooTableReader* reader);
~CuckooTableIterator() {} ~CuckooTableIterator() {}
@ -348,16 +349,17 @@ Slice CuckooTableIterator::value() const {
return curr_value_; return curr_value_;
} }
extern Iterator* NewErrorIterator(const Status& status, Arena* arena); extern InternalIterator* NewErrorInternalIterator(const Status& status,
Arena* arena);
Iterator* CuckooTableReader::NewIterator( InternalIterator* CuckooTableReader::NewIterator(
const ReadOptions& read_options, Arena* arena) { const ReadOptions& read_options, Arena* arena) {
if (!status().ok()) { if (!status().ok()) {
return NewErrorIterator( return NewErrorInternalIterator(
Status::Corruption("CuckooTableReader status is not okay."), arena); Status::Corruption("CuckooTableReader status is not okay."), arena);
} }
if (read_options.total_order_seek) { if (read_options.total_order_seek) {
return NewErrorIterator( return NewErrorInternalIterator(
Status::InvalidArgument("total_order_seek is not supported."), arena); Status::InvalidArgument("total_order_seek is not supported."), arena);
} }
CuckooTableIterator* iter; CuckooTableIterator* iter;

@ -24,6 +24,7 @@ namespace rocksdb {
class Arena; class Arena;
class TableReader; class TableReader;
class InternalIterator;
class CuckooTableReader: public TableReader { class CuckooTableReader: public TableReader {
public: public:
@ -43,7 +44,8 @@ class CuckooTableReader: public TableReader {
Status Get(const ReadOptions& read_options, const Slice& key, Status Get(const ReadOptions& read_options, const Slice& key,
GetContext* get_context) override; GetContext* get_context) override;
Iterator* NewIterator(const ReadOptions&, Arena* arena = nullptr) override; InternalIterator* NewIterator(const ReadOptions&,
Arena* arena = nullptr) override;
void Prepare(const Slice& target) override; void Prepare(const Slice& target) override;
// Report an approximation of how much memory has been used. // Report an approximation of how much memory has been used.

@ -148,7 +148,7 @@ class CuckooReaderTest : public testing::Test {
CuckooTableReader reader(ioptions, std::move(file_reader), file_size, ucomp, CuckooTableReader reader(ioptions, std::move(file_reader), file_size, ucomp,
GetSliceHash); GetSliceHash);
ASSERT_OK(reader.status()); ASSERT_OK(reader.status());
Iterator* it = reader.NewIterator(ReadOptions(), nullptr); InternalIterator* it = reader.NewIterator(ReadOptions(), nullptr);
ASSERT_OK(it->status()); ASSERT_OK(it->status());
ASSERT_TRUE(!it->Valid()); ASSERT_TRUE(!it->Valid());
it->SeekToFirst(); it->SeekToFirst();
@ -196,7 +196,7 @@ class CuckooReaderTest : public testing::Test {
ASSERT_TRUE(keys[num_items/2] == it->key()); ASSERT_TRUE(keys[num_items/2] == it->key());
ASSERT_TRUE(values[num_items/2] == it->value()); ASSERT_TRUE(values[num_items/2] == it->value());
ASSERT_OK(it->status()); ASSERT_OK(it->status());
it->~Iterator(); it->~InternalIterator();
} }
std::vector<std::string> keys; std::vector<std::string> keys;

@ -0,0 +1,75 @@
// Copyright (c) 2013, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#pragma once
#include "rocksdb/iterator.h"
#include "rocksdb/status.h"
namespace rocksdb {
class InternalIterator : public Cleanable {
public:
InternalIterator() {}
virtual ~InternalIterator() {}
// An iterator is either positioned at a key/value pair, or
// not valid. This method returns true iff the iterator is valid.
virtual bool Valid() const = 0;
// Position at the first key in the source. The iterator is Valid()
// after this call iff the source is not empty.
virtual void SeekToFirst() = 0;
// Position at the last key in the source. The iterator is
// Valid() after this call iff the source is not empty.
virtual void SeekToLast() = 0;
// Position at the first key in the source that at or past target
// The iterator is Valid() after this call iff the source contains
// an entry that comes at or past target.
virtual void Seek(const Slice& target) = 0;
// Moves to the next entry in the source. After this call, Valid() is
// true iff the iterator was not positioned at the last entry in the source.
// REQUIRES: Valid()
virtual void Next() = 0;
// Moves to the previous entry in the source. After this call, Valid() is
// true iff the iterator was not positioned at the first entry in source.
// REQUIRES: Valid()
virtual void Prev() = 0;
// Return the key for the current entry. The underlying storage for
// the returned slice is valid only until the next modification of
// the iterator.
// REQUIRES: Valid()
virtual Slice key() const = 0;
// Return the value for the current entry. The underlying storage for
// the returned slice is valid only until the next modification of
// the iterator.
// REQUIRES: !AtEnd() && !AtStart()
virtual Slice value() const = 0;
// If an error has occurred, return it. Else return an ok status.
// If non-blocking IO is requested and this operation cannot be
// satisfied without doing some IO, then this returns Status::Incomplete().
virtual Status status() const = 0;
private:
// No copying allowed
InternalIterator(const InternalIterator&) = delete;
InternalIterator& operator=(const InternalIterator&) = delete;
};
// Return an empty iterator (yields nothing).
extern InternalIterator* NewEmptyInternalIterator();
// Return an empty iterator with the specified status.
extern InternalIterator* NewErrorInternalIterator(const Status& status);
} // namespace rocksdb

@ -8,17 +8,18 @@
// found in the LICENSE file. See the AUTHORS file for names of contributors. // found in the LICENSE file. See the AUTHORS file for names of contributors.
#include "rocksdb/iterator.h" #include "rocksdb/iterator.h"
#include "table/internal_iterator.h"
#include "table/iterator_wrapper.h" #include "table/iterator_wrapper.h"
#include "util/arena.h" #include "util/arena.h"
namespace rocksdb { namespace rocksdb {
Iterator::Iterator() { Cleanable::Cleanable() {
cleanup_.function = nullptr; cleanup_.function = nullptr;
cleanup_.next = nullptr; cleanup_.next = nullptr;
} }
Iterator::~Iterator() { Cleanable::~Cleanable() {
if (cleanup_.function != nullptr) { if (cleanup_.function != nullptr) {
(*cleanup_.function)(cleanup_.arg1, cleanup_.arg2); (*cleanup_.function)(cleanup_.arg1, cleanup_.arg2);
for (Cleanup* c = cleanup_.next; c != nullptr; ) { for (Cleanup* c = cleanup_.next; c != nullptr; ) {
@ -30,7 +31,7 @@ Iterator::~Iterator() {
} }
} }
void Iterator::RegisterCleanup(CleanupFunction func, void* arg1, void* arg2) { void Cleanable::RegisterCleanup(CleanupFunction func, void* arg1, void* arg2) {
assert(func != nullptr); assert(func != nullptr);
Cleanup* c; Cleanup* c;
if (cleanup_.function == nullptr) { if (cleanup_.function == nullptr) {
@ -68,31 +69,62 @@ class EmptyIterator : public Iterator {
private: private:
Status status_; Status status_;
}; };
class EmptyInternalIterator : public InternalIterator {
public:
explicit EmptyInternalIterator(const Status& s) : status_(s) {}
virtual bool Valid() const override { return false; }
virtual void Seek(const Slice& target) override {}
virtual void SeekToFirst() override {}
virtual void SeekToLast() override {}
virtual void Next() override { assert(false); }
virtual void Prev() override { assert(false); }
Slice key() const override {
assert(false);
return Slice();
}
Slice value() const override {
assert(false);
return Slice();
}
virtual Status status() const override { return status_; }
private:
Status status_;
};
} // namespace } // namespace
Iterator* NewEmptyIterator() { Iterator* NewEmptyIterator() {
return new EmptyIterator(Status::OK()); return new EmptyIterator(Status::OK());
} }
Iterator* NewEmptyIterator(Arena* arena) { Iterator* NewErrorIterator(const Status& status) {
return new EmptyIterator(status);
}
InternalIterator* NewEmptyInternalIterator() {
return new EmptyInternalIterator(Status::OK());
}
InternalIterator* NewEmptyInternalIterator(Arena* arena) {
if (arena == nullptr) { if (arena == nullptr) {
return NewEmptyIterator(); return NewEmptyInternalIterator();
} else { } else {
auto mem = arena->AllocateAligned(sizeof(EmptyIterator)); auto mem = arena->AllocateAligned(sizeof(EmptyIterator));
return new (mem) EmptyIterator(Status::OK()); return new (mem) EmptyInternalIterator(Status::OK());
} }
} }
Iterator* NewErrorIterator(const Status& status) { InternalIterator* NewErrorInternalIterator(const Status& status) {
return new EmptyIterator(status); return new EmptyInternalIterator(status);
} }
Iterator* NewErrorIterator(const Status& status, Arena* arena) { InternalIterator* NewErrorInternalIterator(const Status& status, Arena* arena) {
if (arena == nullptr) { if (arena == nullptr) {
return NewErrorIterator(status); return NewErrorInternalIterator(status);
} else { } else {
auto mem = arena->AllocateAligned(sizeof(EmptyIterator)); auto mem = arena->AllocateAligned(sizeof(EmptyIterator));
return new (mem) EmptyIterator(status); return new (mem) EmptyInternalIterator(status);
} }
} }

@ -9,7 +9,7 @@
#pragma once #pragma once
#include "rocksdb/iterator.h" #include "table/internal_iterator.h"
namespace rocksdb { namespace rocksdb {
@ -20,13 +20,15 @@ namespace rocksdb {
class IteratorWrapper { class IteratorWrapper {
public: public:
IteratorWrapper(): iter_(nullptr), valid_(false) { } IteratorWrapper(): iter_(nullptr), valid_(false) { }
explicit IteratorWrapper(Iterator* _iter) : iter_(nullptr) { Set(_iter); } explicit IteratorWrapper(InternalIterator* _iter) : iter_(nullptr) {
Set(_iter);
}
~IteratorWrapper() {} ~IteratorWrapper() {}
Iterator* iter() const { return iter_; } InternalIterator* iter() const { return iter_; }
// Takes ownership of "iter" and will delete it when destroyed, or // Takes ownership of "iter" and will delete it when destroyed, or
// when Set() is invoked again. // when Set() is invoked again.
void Set(Iterator* _iter) { void Set(InternalIterator* _iter) {
delete iter_; delete iter_;
iter_ = _iter; iter_ = _iter;
if (iter_ == nullptr) { if (iter_ == nullptr) {
@ -40,7 +42,7 @@ class IteratorWrapper {
if (!is_arena_mode) { if (!is_arena_mode) {
delete iter_; delete iter_;
} else { } else {
iter_->~Iterator(); iter_->~InternalIterator();
} }
} }
@ -64,16 +66,17 @@ class IteratorWrapper {
} }
} }
Iterator* iter_; InternalIterator* iter_;
bool valid_; bool valid_;
Slice key_; Slice key_;
}; };
class Arena; class Arena;
// Return an empty iterator (yields nothing) allocated from arena. // Return an empty iterator (yields nothing) allocated from arena.
extern Iterator* NewEmptyIterator(Arena* arena); extern InternalIterator* NewEmptyInternalIterator(Arena* arena);
// Return an empty iterator with the specified status, allocated arena. // Return an empty iterator with the specified status, allocated arena.
extern Iterator* NewErrorIterator(const Status& status, Arena* arena); extern InternalIterator* NewErrorInternalIterator(const Status& status,
Arena* arena);
} // namespace rocksdb } // namespace rocksdb

@ -14,6 +14,7 @@
#include "rocksdb/comparator.h" #include "rocksdb/comparator.h"
#include "rocksdb/iterator.h" #include "rocksdb/iterator.h"
#include "rocksdb/options.h" #include "rocksdb/options.h"
#include "table/internal_iterator.h"
#include "table/iter_heap.h" #include "table/iter_heap.h"
#include "table/iterator_wrapper.h" #include "table/iterator_wrapper.h"
#include "util/arena.h" #include "util/arena.h"
@ -32,10 +33,10 @@ typedef BinaryHeap<IteratorWrapper*, MinIteratorComparator> MergerMinIterHeap;
const size_t kNumIterReserve = 4; const size_t kNumIterReserve = 4;
class MergingIterator : public Iterator { class MergingIterator : public InternalIterator {
public: public:
MergingIterator(const Comparator* comparator, Iterator** children, int n, MergingIterator(const Comparator* comparator, InternalIterator** children,
bool is_arena_mode) int n, bool is_arena_mode)
: is_arena_mode_(is_arena_mode), : is_arena_mode_(is_arena_mode),
comparator_(comparator), comparator_(comparator),
current_(nullptr), current_(nullptr),
@ -53,7 +54,7 @@ class MergingIterator : public Iterator {
current_ = CurrentForward(); current_ = CurrentForward();
} }
virtual void AddIterator(Iterator* iter) { virtual void AddIterator(InternalIterator* iter) {
assert(direction_ == kForward); assert(direction_ == kForward);
children_.emplace_back(iter); children_.emplace_back(iter);
auto new_wrapper = children_.back(); auto new_wrapper = children_.back();
@ -288,11 +289,12 @@ void MergingIterator::InitMaxHeap() {
} }
} }
Iterator* NewMergingIterator(const Comparator* cmp, Iterator** list, int n, InternalIterator* NewMergingIterator(const Comparator* cmp,
InternalIterator** list, int n,
Arena* arena) { Arena* arena) {
assert(n >= 0); assert(n >= 0);
if (n == 0) { if (n == 0) {
return NewEmptyIterator(arena); return NewEmptyInternalIterator(arena);
} else if (n == 1) { } else if (n == 1) {
return list[0]; return list[0];
} else { } else {
@ -313,7 +315,7 @@ MergeIteratorBuilder::MergeIteratorBuilder(const Comparator* comparator,
merge_iter = new (mem) MergingIterator(comparator, nullptr, 0, true); merge_iter = new (mem) MergingIterator(comparator, nullptr, 0, true);
} }
void MergeIteratorBuilder::AddIterator(Iterator* iter) { void MergeIteratorBuilder::AddIterator(InternalIterator* iter) {
if (!use_merging_iter && first_iter != nullptr) { if (!use_merging_iter && first_iter != nullptr) {
merge_iter->AddIterator(first_iter); merge_iter->AddIterator(first_iter);
use_merging_iter = true; use_merging_iter = true;
@ -325,7 +327,7 @@ void MergeIteratorBuilder::AddIterator(Iterator* iter) {
} }
} }
Iterator* MergeIteratorBuilder::Finish() { InternalIterator* MergeIteratorBuilder::Finish() {
if (!use_merging_iter) { if (!use_merging_iter) {
return first_iter; return first_iter;
} else { } else {

@ -14,7 +14,7 @@
namespace rocksdb { namespace rocksdb {
class Comparator; class Comparator;
class Iterator; class InternalIterator;
class Env; class Env;
class Arena; class Arena;
@ -26,8 +26,8 @@ class Arena;
// key is present in K child iterators, it will be yielded K times. // key is present in K child iterators, it will be yielded K times.
// //
// REQUIRES: n >= 0 // REQUIRES: n >= 0
extern Iterator* NewMergingIterator(const Comparator* comparator, extern InternalIterator* NewMergingIterator(const Comparator* comparator,
Iterator** children, int n, InternalIterator** children, int n,
Arena* arena = nullptr); Arena* arena = nullptr);
class MergingIterator; class MergingIterator;
@ -41,18 +41,18 @@ class MergeIteratorBuilder {
~MergeIteratorBuilder() {} ~MergeIteratorBuilder() {}
// Add iter to the merging iterator. // Add iter to the merging iterator.
void AddIterator(Iterator* iter); void AddIterator(InternalIterator* iter);
// Get arena used to build the merging iterator. It is called one a child // Get arena used to build the merging iterator. It is called one a child
// iterator needs to be allocated. // iterator needs to be allocated.
Arena* GetArena() { return arena; } Arena* GetArena() { return arena; }
// Return the result merging iterator. // Return the result merging iterator.
Iterator* Finish(); InternalIterator* Finish();
private: private:
MergingIterator* merge_iter; MergingIterator* merge_iter;
Iterator* first_iter; InternalIterator* first_iter;
bool use_merging_iter; bool use_merging_iter;
Arena* arena; Arena* arena;
}; };

@ -88,7 +88,7 @@ class MergerTest : public testing::Test {
void Generate(size_t num_iterators, size_t strings_per_iterator, void Generate(size_t num_iterators, size_t strings_per_iterator,
int letters_per_string) { int letters_per_string) {
std::vector<Iterator*> small_iterators; std::vector<InternalIterator*> small_iterators;
for (size_t i = 0; i < num_iterators; ++i) { for (size_t i = 0; i < num_iterators; ++i) {
auto strings = GenerateStrings(strings_per_iterator, letters_per_string); auto strings = GenerateStrings(strings_per_iterator, letters_per_string);
small_iterators.push_back(new test::VectorIterator(strings)); small_iterators.push_back(new test::VectorIterator(strings));
@ -102,8 +102,8 @@ class MergerTest : public testing::Test {
} }
Random rnd_; Random rnd_;
std::unique_ptr<Iterator> merging_iterator_; std::unique_ptr<InternalIterator> merging_iterator_;
std::unique_ptr<Iterator> single_iterator_; std::unique_ptr<InternalIterator> single_iterator_;
std::vector<std::string> all_keys_; std::vector<std::string> all_keys_;
}; };

@ -12,6 +12,7 @@
#include "rocksdb/table_properties.h" #include "rocksdb/table_properties.h"
#include "table/block.h" #include "table/block.h"
#include "table/format.h" #include "table/format.h"
#include "table/internal_iterator.h"
#include "table/table_properties_internal.h" #include "table/table_properties_internal.h"
#include "util/coding.h" #include "util/coding.h"
@ -152,7 +153,7 @@ Status ReadProperties(const Slice& handle_value, RandomAccessFileReader* file,
} }
Block properties_block(std::move(block_contents)); Block properties_block(std::move(block_contents));
std::unique_ptr<Iterator> iter( std::unique_ptr<InternalIterator> iter(
properties_block.NewIterator(BytewiseComparator())); properties_block.NewIterator(BytewiseComparator()));
auto new_table_properties = new TableProperties(); auto new_table_properties = new TableProperties();
@ -237,7 +238,7 @@ Status ReadTableProperties(RandomAccessFileReader* file, uint64_t file_size,
return s; return s;
} }
Block metaindex_block(std::move(metaindex_contents)); Block metaindex_block(std::move(metaindex_contents));
std::unique_ptr<Iterator> meta_iter( std::unique_ptr<InternalIterator> meta_iter(
metaindex_block.NewIterator(BytewiseComparator())); metaindex_block.NewIterator(BytewiseComparator()));
// -- Read property block // -- Read property block
@ -258,7 +259,7 @@ Status ReadTableProperties(RandomAccessFileReader* file, uint64_t file_size,
return s; return s;
} }
Status FindMetaBlock(Iterator* meta_index_iter, Status FindMetaBlock(InternalIterator* meta_index_iter,
const std::string& meta_block_name, const std::string& meta_block_name,
BlockHandle* block_handle) { BlockHandle* block_handle) {
meta_index_iter->Seek(meta_block_name); meta_index_iter->Seek(meta_block_name);
@ -292,7 +293,7 @@ Status FindMetaBlock(RandomAccessFileReader* file, uint64_t file_size,
} }
Block metaindex_block(std::move(metaindex_contents)); Block metaindex_block(std::move(metaindex_contents));
std::unique_ptr<Iterator> meta_iter; std::unique_ptr<InternalIterator> meta_iter;
meta_iter.reset(metaindex_block.NewIterator(BytewiseComparator())); meta_iter.reset(metaindex_block.NewIterator(BytewiseComparator()));
return FindMetaBlock(meta_iter.get(), meta_block_name, block_handle); return FindMetaBlock(meta_iter.get(), meta_block_name, block_handle);
@ -323,7 +324,7 @@ Status ReadMetaBlock(RandomAccessFileReader* file, uint64_t file_size,
// Finding metablock // Finding metablock
Block metaindex_block(std::move(metaindex_contents)); Block metaindex_block(std::move(metaindex_contents));
std::unique_ptr<Iterator> meta_iter; std::unique_ptr<InternalIterator> meta_iter;
meta_iter.reset(metaindex_block.NewIterator(BytewiseComparator())); meta_iter.reset(metaindex_block.NewIterator(BytewiseComparator()));
BlockHandle block_handle; BlockHandle block_handle;

@ -11,12 +11,12 @@
#include "db/builder.h" #include "db/builder.h"
#include "db/table_properties_collector.h" #include "db/table_properties_collector.h"
#include "util/kv_map.h"
#include "rocksdb/comparator.h" #include "rocksdb/comparator.h"
#include "rocksdb/options.h" #include "rocksdb/options.h"
#include "rocksdb/slice.h" #include "rocksdb/slice.h"
#include "table/block_builder.h" #include "table/block_builder.h"
#include "table/format.h" #include "table/format.h"
#include "util/stl_wrappers.h"
namespace rocksdb { namespace rocksdb {
@ -27,6 +27,7 @@ class Footer;
class Logger; class Logger;
class RandomAccessFile; class RandomAccessFile;
struct TableProperties; struct TableProperties;
class InternalIterator;
class MetaIndexBuilder { class MetaIndexBuilder {
public: public:
@ -105,7 +106,7 @@ Status ReadTableProperties(RandomAccessFileReader* file, uint64_t file_size,
Logger* info_log, TableProperties** properties); Logger* info_log, TableProperties** properties);
// Find the meta block from the meta index block. // Find the meta block from the meta index block.
Status FindMetaBlock(Iterator* meta_index_iter, Status FindMetaBlock(InternalIterator* meta_index_iter,
const std::string& meta_block_name, const std::string& meta_block_name,
BlockHandle* block_handle); BlockHandle* block_handle);

@ -28,7 +28,8 @@ stl_wrappers::KVMap MakeMockFile(
return stl_wrappers::KVMap(l, stl_wrappers::LessOfComparator(&icmp_)); return stl_wrappers::KVMap(l, stl_wrappers::LessOfComparator(&icmp_));
} }
Iterator* MockTableReader::NewIterator(const ReadOptions&, Arena* arena) { InternalIterator* MockTableReader::NewIterator(const ReadOptions&,
Arena* arena) {
return new MockTableIterator(table_); return new MockTableIterator(table_);
} }

@ -14,13 +14,14 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include "util/kv_map.h"
#include "port/port.h" #include "port/port.h"
#include "rocksdb/comparator.h" #include "rocksdb/comparator.h"
#include "rocksdb/table.h" #include "rocksdb/table.h"
#include "table/internal_iterator.h"
#include "table/table_builder.h" #include "table/table_builder.h"
#include "table/table_reader.h" #include "table/table_reader.h"
#include "util/mutexlock.h" #include "util/mutexlock.h"
#include "util/stl_wrappers.h"
#include "util/testharness.h" #include "util/testharness.h"
#include "util/testutil.h" #include "util/testutil.h"
@ -39,7 +40,7 @@ class MockTableReader : public TableReader {
public: public:
explicit MockTableReader(const stl_wrappers::KVMap& table) : table_(table) {} explicit MockTableReader(const stl_wrappers::KVMap& table) : table_(table) {}
Iterator* NewIterator(const ReadOptions&, Arena* arena) override; InternalIterator* NewIterator(const ReadOptions&, Arena* arena) override;
Status Get(const ReadOptions&, const Slice& key, Status Get(const ReadOptions&, const Slice& key,
GetContext* get_context) override; GetContext* get_context) override;
@ -58,7 +59,7 @@ class MockTableReader : public TableReader {
const stl_wrappers::KVMap& table_; const stl_wrappers::KVMap& table_;
}; };
class MockTableIterator : public Iterator { class MockTableIterator : public InternalIterator {
public: public:
explicit MockTableIterator(const stl_wrappers::KVMap& table) : table_(table) { explicit MockTableIterator(const stl_wrappers::KVMap& table) : table_(table) {
itr_ = table_.end(); itr_ = table_.end();

@ -22,6 +22,7 @@
#include "table/bloom_block.h" #include "table/bloom_block.h"
#include "table/filter_block.h" #include "table/filter_block.h"
#include "table/format.h" #include "table/format.h"
#include "table/internal_iterator.h"
#include "table/meta_blocks.h" #include "table/meta_blocks.h"
#include "table/two_level_iterator.h" #include "table/two_level_iterator.h"
#include "table/plain_table_factory.h" #include "table/plain_table_factory.h"
@ -51,7 +52,7 @@ inline uint32_t GetFixed32Element(const char* base, size_t offset) {
} // namespace } // namespace
// Iterator to iterate IndexedTable // Iterator to iterate IndexedTable
class PlainTableIterator : public Iterator { class PlainTableIterator : public InternalIterator {
public: public:
explicit PlainTableIterator(PlainTableReader* table, bool use_prefix_seek); explicit PlainTableIterator(PlainTableReader* table, bool use_prefix_seek);
~PlainTableIterator(); ~PlainTableIterator();
@ -186,10 +187,10 @@ Status PlainTableReader::Open(const ImmutableCFOptions& ioptions,
void PlainTableReader::SetupForCompaction() { void PlainTableReader::SetupForCompaction() {
} }
Iterator* PlainTableReader::NewIterator(const ReadOptions& options, InternalIterator* PlainTableReader::NewIterator(const ReadOptions& options,
Arena* arena) { Arena* arena) {
if (options.total_order_seek && !IsTotalOrderMode()) { if (options.total_order_seek && !IsTotalOrderMode()) {
return NewErrorIterator( return NewErrorInternalIterator(
Status::InvalidArgument("total_order_seek not supported"), arena); Status::InvalidArgument("total_order_seek not supported"), arena);
} }
if (arena == nullptr) { if (arena == nullptr) {

@ -38,6 +38,7 @@ class TableReader;
class InternalKeyComparator; class InternalKeyComparator;
class PlainTableKeyDecoder; class PlainTableKeyDecoder;
class GetContext; class GetContext;
class InternalIterator;
using std::unique_ptr; using std::unique_ptr;
using std::unordered_map; using std::unordered_map;
@ -77,7 +78,8 @@ class PlainTableReader: public TableReader {
size_t index_sparseness, size_t huge_page_tlb_size, size_t index_sparseness, size_t huge_page_tlb_size,
bool full_scan_mode); bool full_scan_mode);
Iterator* NewIterator(const ReadOptions&, Arena* arena = nullptr) override; InternalIterator* NewIterator(const ReadOptions&,
Arena* arena = nullptr) override;
void Prepare(const Slice& target) override; void Prepare(const Slice& target) override;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save