@nxtedition/rocksdb 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1088) hide show
  1. package/CHANGELOG.md +294 -0
  2. package/LICENSE +21 -0
  3. package/README.md +102 -0
  4. package/UPGRADING.md +91 -0
  5. package/binding.cc +1276 -0
  6. package/binding.gyp +73 -0
  7. package/binding.js +1 -0
  8. package/chained-batch.js +44 -0
  9. package/deps/rocksdb/build_version.cc +4 -0
  10. package/deps/rocksdb/rocksdb/CMakeLists.txt +1356 -0
  11. package/deps/rocksdb/rocksdb/COPYING +339 -0
  12. package/deps/rocksdb/rocksdb/LICENSE.Apache +202 -0
  13. package/deps/rocksdb/rocksdb/LICENSE.leveldb +29 -0
  14. package/deps/rocksdb/rocksdb/Makefile +2521 -0
  15. package/deps/rocksdb/rocksdb/TARGETS +2100 -0
  16. package/deps/rocksdb/rocksdb/cache/cache.cc +63 -0
  17. package/deps/rocksdb/rocksdb/cache/cache_bench.cc +381 -0
  18. package/deps/rocksdb/rocksdb/cache/cache_helpers.h +114 -0
  19. package/deps/rocksdb/rocksdb/cache/cache_test.cc +775 -0
  20. package/deps/rocksdb/rocksdb/cache/clock_cache.cc +769 -0
  21. package/deps/rocksdb/rocksdb/cache/clock_cache.h +16 -0
  22. package/deps/rocksdb/rocksdb/cache/lru_cache.cc +574 -0
  23. package/deps/rocksdb/rocksdb/cache/lru_cache.h +339 -0
  24. package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +199 -0
  25. package/deps/rocksdb/rocksdb/cache/sharded_cache.cc +162 -0
  26. package/deps/rocksdb/rocksdb/cache/sharded_cache.h +111 -0
  27. package/deps/rocksdb/rocksdb/cmake/RocksDBConfig.cmake.in +54 -0
  28. package/deps/rocksdb/rocksdb/cmake/modules/CxxFlags.cmake +7 -0
  29. package/deps/rocksdb/rocksdb/cmake/modules/FindJeMalloc.cmake +29 -0
  30. package/deps/rocksdb/rocksdb/cmake/modules/FindNUMA.cmake +29 -0
  31. package/deps/rocksdb/rocksdb/cmake/modules/FindSnappy.cmake +29 -0
  32. package/deps/rocksdb/rocksdb/cmake/modules/FindTBB.cmake +33 -0
  33. package/deps/rocksdb/rocksdb/cmake/modules/Findgflags.cmake +29 -0
  34. package/deps/rocksdb/rocksdb/cmake/modules/Findlz4.cmake +29 -0
  35. package/deps/rocksdb/rocksdb/cmake/modules/Findzstd.cmake +29 -0
  36. package/deps/rocksdb/rocksdb/cmake/modules/ReadVersion.cmake +10 -0
  37. package/deps/rocksdb/rocksdb/db/arena_wrapped_db_iter.cc +108 -0
  38. package/deps/rocksdb/rocksdb/db/arena_wrapped_db_iter.h +115 -0
  39. package/deps/rocksdb/rocksdb/db/blob/blob_constants.h +16 -0
  40. package/deps/rocksdb/rocksdb/db/blob/blob_file_addition.cc +154 -0
  41. package/deps/rocksdb/rocksdb/db/blob/blob_file_addition.h +67 -0
  42. package/deps/rocksdb/rocksdb/db/blob/blob_file_addition_test.cc +206 -0
  43. package/deps/rocksdb/rocksdb/db/blob/blob_file_builder.cc +316 -0
  44. package/deps/rocksdb/rocksdb/db/blob/blob_file_builder.h +91 -0
  45. package/deps/rocksdb/rocksdb/db/blob/blob_file_builder_test.cc +660 -0
  46. package/deps/rocksdb/rocksdb/db/blob/blob_file_cache.cc +99 -0
  47. package/deps/rocksdb/rocksdb/db/blob/blob_file_cache.h +49 -0
  48. package/deps/rocksdb/rocksdb/db/blob/blob_file_cache_test.cc +268 -0
  49. package/deps/rocksdb/rocksdb/db/blob/blob_file_garbage.cc +134 -0
  50. package/deps/rocksdb/rocksdb/db/blob/blob_file_garbage.h +57 -0
  51. package/deps/rocksdb/rocksdb/db/blob/blob_file_garbage_test.cc +173 -0
  52. package/deps/rocksdb/rocksdb/db/blob/blob_file_meta.cc +55 -0
  53. package/deps/rocksdb/rocksdb/db/blob/blob_file_meta.h +164 -0
  54. package/deps/rocksdb/rocksdb/db/blob/blob_file_reader.cc +423 -0
  55. package/deps/rocksdb/rocksdb/db/blob/blob_file_reader.h +81 -0
  56. package/deps/rocksdb/rocksdb/db/blob/blob_file_reader_test.cc +771 -0
  57. package/deps/rocksdb/rocksdb/db/blob/blob_index.h +184 -0
  58. package/deps/rocksdb/rocksdb/db/blob/blob_log_format.cc +145 -0
  59. package/deps/rocksdb/rocksdb/db/blob/blob_log_format.h +148 -0
  60. package/deps/rocksdb/rocksdb/db/blob/blob_log_sequential_reader.cc +132 -0
  61. package/deps/rocksdb/rocksdb/db/blob/blob_log_sequential_reader.h +76 -0
  62. package/deps/rocksdb/rocksdb/db/blob/blob_log_writer.cc +168 -0
  63. package/deps/rocksdb/rocksdb/db/blob/blob_log_writer.h +83 -0
  64. package/deps/rocksdb/rocksdb/db/blob/db_blob_basic_test.cc +307 -0
  65. package/deps/rocksdb/rocksdb/db/blob/db_blob_index_test.cc +464 -0
  66. package/deps/rocksdb/rocksdb/db/builder.cc +358 -0
  67. package/deps/rocksdb/rocksdb/db/builder.h +95 -0
  68. package/deps/rocksdb/rocksdb/db/c.cc +5281 -0
  69. package/deps/rocksdb/rocksdb/db/c_test.c +2883 -0
  70. package/deps/rocksdb/rocksdb/db/column_family.cc +1602 -0
  71. package/deps/rocksdb/rocksdb/db/column_family.h +787 -0
  72. package/deps/rocksdb/rocksdb/db/column_family_test.cc +3427 -0
  73. package/deps/rocksdb/rocksdb/db/compact_files_test.cc +425 -0
  74. package/deps/rocksdb/rocksdb/db/compacted_db_impl.cc +169 -0
  75. package/deps/rocksdb/rocksdb/db/compacted_db_impl.h +118 -0
  76. package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +591 -0
  77. package/deps/rocksdb/rocksdb/db/compaction/compaction.h +389 -0
  78. package/deps/rocksdb/rocksdb/db/compaction/compaction_iteration_stats.h +37 -0
  79. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +1023 -0
  80. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.h +353 -0
  81. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator_test.cc +1254 -0
  82. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +1917 -0
  83. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +208 -0
  84. package/deps/rocksdb/rocksdb/db/compaction/compaction_job_stats_test.cc +1037 -0
  85. package/deps/rocksdb/rocksdb/db/compaction/compaction_job_test.cc +1224 -0
  86. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.cc +1135 -0
  87. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.h +318 -0
  88. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.cc +255 -0
  89. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.h +57 -0
  90. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_level.cc +510 -0
  91. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_level.h +33 -0
  92. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +2190 -0
  93. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +1103 -0
  94. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.h +32 -0
  95. package/deps/rocksdb/rocksdb/db/compaction/sst_partitioner.cc +44 -0
  96. package/deps/rocksdb/rocksdb/db/comparator_db_test.cc +660 -0
  97. package/deps/rocksdb/rocksdb/db/convenience.cc +78 -0
  98. package/deps/rocksdb/rocksdb/db/corruption_test.cc +921 -0
  99. package/deps/rocksdb/rocksdb/db/cuckoo_table_db_test.cc +359 -0
  100. package/deps/rocksdb/rocksdb/db/db_basic_test.cc +3820 -0
  101. package/deps/rocksdb/rocksdb/db/db_block_cache_test.cc +1058 -0
  102. package/deps/rocksdb/rocksdb/db/db_bloom_filter_test.cc +2128 -0
  103. package/deps/rocksdb/rocksdb/db/db_compaction_filter_test.cc +851 -0
  104. package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +6292 -0
  105. package/deps/rocksdb/rocksdb/db/db_dynamic_level_test.cc +509 -0
  106. package/deps/rocksdb/rocksdb/db/db_encryption_test.cc +130 -0
  107. package/deps/rocksdb/rocksdb/db/db_filesnapshot.cc +137 -0
  108. package/deps/rocksdb/rocksdb/db/db_flush_test.cc +1119 -0
  109. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +5057 -0
  110. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +2274 -0
  111. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +3421 -0
  112. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_debug.cc +298 -0
  113. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_experimental.cc +151 -0
  114. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_files.cc +967 -0
  115. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +1806 -0
  116. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_readonly.cc +270 -0
  117. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_readonly.h +146 -0
  118. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.cc +683 -0
  119. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.h +333 -0
  120. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_write.cc +2024 -0
  121. package/deps/rocksdb/rocksdb/db/db_impl/db_secondary_test.cc +932 -0
  122. package/deps/rocksdb/rocksdb/db/db_info_dumper.cc +137 -0
  123. package/deps/rocksdb/rocksdb/db/db_info_dumper.h +15 -0
  124. package/deps/rocksdb/rocksdb/db/db_inplace_update_test.cc +178 -0
  125. package/deps/rocksdb/rocksdb/db/db_io_failure_test.cc +592 -0
  126. package/deps/rocksdb/rocksdb/db/db_iter.cc +1493 -0
  127. package/deps/rocksdb/rocksdb/db/db_iter.h +390 -0
  128. package/deps/rocksdb/rocksdb/db/db_iter_stress_test.cc +657 -0
  129. package/deps/rocksdb/rocksdb/db/db_iter_test.cc +3268 -0
  130. package/deps/rocksdb/rocksdb/db/db_iterator_test.cc +3197 -0
  131. package/deps/rocksdb/rocksdb/db/db_log_iter_test.cc +299 -0
  132. package/deps/rocksdb/rocksdb/db/db_logical_block_size_cache_test.cc +513 -0
  133. package/deps/rocksdb/rocksdb/db/db_memtable_test.cc +329 -0
  134. package/deps/rocksdb/rocksdb/db/db_merge_operand_test.cc +241 -0
  135. package/deps/rocksdb/rocksdb/db/db_merge_operator_test.cc +671 -0
  136. package/deps/rocksdb/rocksdb/db/db_options_test.cc +1022 -0
  137. package/deps/rocksdb/rocksdb/db/db_properties_test.cc +1723 -0
  138. package/deps/rocksdb/rocksdb/db/db_range_del_test.cc +1694 -0
  139. package/deps/rocksdb/rocksdb/db/db_sst_test.cc +1261 -0
  140. package/deps/rocksdb/rocksdb/db/db_statistics_test.cc +164 -0
  141. package/deps/rocksdb/rocksdb/db/db_table_properties_test.cc +488 -0
  142. package/deps/rocksdb/rocksdb/db/db_tailing_iter_test.cc +567 -0
  143. package/deps/rocksdb/rocksdb/db/db_test.cc +6736 -0
  144. package/deps/rocksdb/rocksdb/db/db_test2.cc +5408 -0
  145. package/deps/rocksdb/rocksdb/db/db_test_util.cc +1633 -0
  146. package/deps/rocksdb/rocksdb/db/db_test_util.h +1194 -0
  147. package/deps/rocksdb/rocksdb/db/db_universal_compaction_test.cc +2235 -0
  148. package/deps/rocksdb/rocksdb/db/db_wal_test.cc +1780 -0
  149. package/deps/rocksdb/rocksdb/db/db_with_timestamp_basic_test.cc +2520 -0
  150. package/deps/rocksdb/rocksdb/db/db_with_timestamp_compaction_test.cc +119 -0
  151. package/deps/rocksdb/rocksdb/db/db_write_test.cc +465 -0
  152. package/deps/rocksdb/rocksdb/db/dbformat.cc +222 -0
  153. package/deps/rocksdb/rocksdb/db/dbformat.h +786 -0
  154. package/deps/rocksdb/rocksdb/db/dbformat_test.cc +206 -0
  155. package/deps/rocksdb/rocksdb/db/deletefile_test.cc +580 -0
  156. package/deps/rocksdb/rocksdb/db/error_handler.cc +726 -0
  157. package/deps/rocksdb/rocksdb/db/error_handler.h +117 -0
  158. package/deps/rocksdb/rocksdb/db/error_handler_fs_test.cc +2598 -0
  159. package/deps/rocksdb/rocksdb/db/event_helpers.cc +233 -0
  160. package/deps/rocksdb/rocksdb/db/event_helpers.h +57 -0
  161. package/deps/rocksdb/rocksdb/db/experimental.cc +50 -0
  162. package/deps/rocksdb/rocksdb/db/external_sst_file_basic_test.cc +1559 -0
  163. package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +910 -0
  164. package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.h +195 -0
  165. package/deps/rocksdb/rocksdb/db/external_sst_file_test.cc +2936 -0
  166. package/deps/rocksdb/rocksdb/db/fault_injection_test.cc +556 -0
  167. package/deps/rocksdb/rocksdb/db/file_indexer.cc +216 -0
  168. package/deps/rocksdb/rocksdb/db/file_indexer.h +142 -0
  169. package/deps/rocksdb/rocksdb/db/file_indexer_test.cc +350 -0
  170. package/deps/rocksdb/rocksdb/db/filename_test.cc +179 -0
  171. package/deps/rocksdb/rocksdb/db/flush_job.cc +514 -0
  172. package/deps/rocksdb/rocksdb/db/flush_job.h +169 -0
  173. package/deps/rocksdb/rocksdb/db/flush_job_test.cc +647 -0
  174. package/deps/rocksdb/rocksdb/db/flush_scheduler.cc +86 -0
  175. package/deps/rocksdb/rocksdb/db/flush_scheduler.h +54 -0
  176. package/deps/rocksdb/rocksdb/db/forward_iterator.cc +1023 -0
  177. package/deps/rocksdb/rocksdb/db/forward_iterator.h +163 -0
  178. package/deps/rocksdb/rocksdb/db/forward_iterator_bench.cc +377 -0
  179. package/deps/rocksdb/rocksdb/db/import_column_family_job.cc +282 -0
  180. package/deps/rocksdb/rocksdb/db/import_column_family_job.h +75 -0
  181. package/deps/rocksdb/rocksdb/db/import_column_family_test.cc +632 -0
  182. package/deps/rocksdb/rocksdb/db/internal_stats.cc +1461 -0
  183. package/deps/rocksdb/rocksdb/db/internal_stats.h +712 -0
  184. package/deps/rocksdb/rocksdb/db/job_context.h +226 -0
  185. package/deps/rocksdb/rocksdb/db/listener_test.cc +1118 -0
  186. package/deps/rocksdb/rocksdb/db/log_format.h +48 -0
  187. package/deps/rocksdb/rocksdb/db/log_reader.cc +654 -0
  188. package/deps/rocksdb/rocksdb/db/log_reader.h +192 -0
  189. package/deps/rocksdb/rocksdb/db/log_test.cc +901 -0
  190. package/deps/rocksdb/rocksdb/db/log_writer.cc +164 -0
  191. package/deps/rocksdb/rocksdb/db/log_writer.h +115 -0
  192. package/deps/rocksdb/rocksdb/db/logs_with_prep_tracker.cc +67 -0
  193. package/deps/rocksdb/rocksdb/db/logs_with_prep_tracker.h +63 -0
  194. package/deps/rocksdb/rocksdb/db/lookup_key.h +66 -0
  195. package/deps/rocksdb/rocksdb/db/malloc_stats.cc +54 -0
  196. package/deps/rocksdb/rocksdb/db/malloc_stats.h +24 -0
  197. package/deps/rocksdb/rocksdb/db/manual_compaction_test.cc +296 -0
  198. package/deps/rocksdb/rocksdb/db/memtable.cc +1169 -0
  199. package/deps/rocksdb/rocksdb/db/memtable.h +554 -0
  200. package/deps/rocksdb/rocksdb/db/memtable_list.cc +888 -0
  201. package/deps/rocksdb/rocksdb/db/memtable_list.h +438 -0
  202. package/deps/rocksdb/rocksdb/db/memtable_list_test.cc +935 -0
  203. package/deps/rocksdb/rocksdb/db/merge_context.h +134 -0
  204. package/deps/rocksdb/rocksdb/db/merge_helper.cc +421 -0
  205. package/deps/rocksdb/rocksdb/db/merge_helper.h +197 -0
  206. package/deps/rocksdb/rocksdb/db/merge_helper_test.cc +290 -0
  207. package/deps/rocksdb/rocksdb/db/merge_operator.cc +86 -0
  208. package/deps/rocksdb/rocksdb/db/merge_test.cc +608 -0
  209. package/deps/rocksdb/rocksdb/db/obsolete_files_test.cc +338 -0
  210. package/deps/rocksdb/rocksdb/db/options_file_test.cc +119 -0
  211. package/deps/rocksdb/rocksdb/db/output_validator.cc +30 -0
  212. package/deps/rocksdb/rocksdb/db/output_validator.h +47 -0
  213. package/deps/rocksdb/rocksdb/db/perf_context_test.cc +993 -0
  214. package/deps/rocksdb/rocksdb/db/periodic_work_scheduler.cc +113 -0
  215. package/deps/rocksdb/rocksdb/db/periodic_work_scheduler.h +76 -0
  216. package/deps/rocksdb/rocksdb/db/periodic_work_scheduler_test.cc +231 -0
  217. package/deps/rocksdb/rocksdb/db/pinned_iterators_manager.h +87 -0
  218. package/deps/rocksdb/rocksdb/db/plain_table_db_test.cc +1374 -0
  219. package/deps/rocksdb/rocksdb/db/pre_release_callback.h +38 -0
  220. package/deps/rocksdb/rocksdb/db/prefix_test.cc +910 -0
  221. package/deps/rocksdb/rocksdb/db/range_del_aggregator.cc +489 -0
  222. package/deps/rocksdb/rocksdb/db/range_del_aggregator.h +446 -0
  223. package/deps/rocksdb/rocksdb/db/range_del_aggregator_bench.cc +260 -0
  224. package/deps/rocksdb/rocksdb/db/range_del_aggregator_test.cc +709 -0
  225. package/deps/rocksdb/rocksdb/db/range_tombstone_fragmenter.cc +439 -0
  226. package/deps/rocksdb/rocksdb/db/range_tombstone_fragmenter.h +256 -0
  227. package/deps/rocksdb/rocksdb/db/range_tombstone_fragmenter_test.cc +552 -0
  228. package/deps/rocksdb/rocksdb/db/read_callback.h +53 -0
  229. package/deps/rocksdb/rocksdb/db/repair.cc +722 -0
  230. package/deps/rocksdb/rocksdb/db/repair_test.cc +390 -0
  231. package/deps/rocksdb/rocksdb/db/snapshot_checker.h +61 -0
  232. package/deps/rocksdb/rocksdb/db/snapshot_impl.cc +26 -0
  233. package/deps/rocksdb/rocksdb/db/snapshot_impl.h +167 -0
  234. package/deps/rocksdb/rocksdb/db/table_cache.cc +704 -0
  235. package/deps/rocksdb/rocksdb/db/table_cache.h +233 -0
  236. package/deps/rocksdb/rocksdb/db/table_properties_collector.cc +75 -0
  237. package/deps/rocksdb/rocksdb/db/table_properties_collector.h +107 -0
  238. package/deps/rocksdb/rocksdb/db/table_properties_collector_test.cc +517 -0
  239. package/deps/rocksdb/rocksdb/db/transaction_log_impl.cc +318 -0
  240. package/deps/rocksdb/rocksdb/db/transaction_log_impl.h +128 -0
  241. package/deps/rocksdb/rocksdb/db/trim_history_scheduler.cc +54 -0
  242. package/deps/rocksdb/rocksdb/db/trim_history_scheduler.h +44 -0
  243. package/deps/rocksdb/rocksdb/db/version_builder.cc +1078 -0
  244. package/deps/rocksdb/rocksdb/db/version_builder.h +69 -0
  245. package/deps/rocksdb/rocksdb/db/version_builder_test.cc +1551 -0
  246. package/deps/rocksdb/rocksdb/db/version_edit.cc +955 -0
  247. package/deps/rocksdb/rocksdb/db/version_edit.h +609 -0
  248. package/deps/rocksdb/rocksdb/db/version_edit_handler.cc +699 -0
  249. package/deps/rocksdb/rocksdb/db/version_edit_handler.h +252 -0
  250. package/deps/rocksdb/rocksdb/db/version_edit_test.cc +597 -0
  251. package/deps/rocksdb/rocksdb/db/version_set.cc +6333 -0
  252. package/deps/rocksdb/rocksdb/db/version_set.h +1485 -0
  253. package/deps/rocksdb/rocksdb/db/version_set_test.cc +3035 -0
  254. package/deps/rocksdb/rocksdb/db/wal_edit.cc +204 -0
  255. package/deps/rocksdb/rocksdb/db/wal_edit.h +166 -0
  256. package/deps/rocksdb/rocksdb/db/wal_edit_test.cc +214 -0
  257. package/deps/rocksdb/rocksdb/db/wal_manager.cc +517 -0
  258. package/deps/rocksdb/rocksdb/db/wal_manager.h +119 -0
  259. package/deps/rocksdb/rocksdb/db/wal_manager_test.cc +340 -0
  260. package/deps/rocksdb/rocksdb/db/write_batch.cc +2174 -0
  261. package/deps/rocksdb/rocksdb/db/write_batch_base.cc +94 -0
  262. package/deps/rocksdb/rocksdb/db/write_batch_internal.h +250 -0
  263. package/deps/rocksdb/rocksdb/db/write_batch_test.cc +907 -0
  264. package/deps/rocksdb/rocksdb/db/write_callback.h +27 -0
  265. package/deps/rocksdb/rocksdb/db/write_callback_test.cc +457 -0
  266. package/deps/rocksdb/rocksdb/db/write_controller.cc +128 -0
  267. package/deps/rocksdb/rocksdb/db/write_controller.h +144 -0
  268. package/deps/rocksdb/rocksdb/db/write_controller_test.cc +135 -0
  269. package/deps/rocksdb/rocksdb/db/write_thread.cc +796 -0
  270. package/deps/rocksdb/rocksdb/db/write_thread.h +433 -0
  271. package/deps/rocksdb/rocksdb/db_stress_tool/CMakeLists.txt +14 -0
  272. package/deps/rocksdb/rocksdb/db_stress_tool/batched_ops_stress.cc +341 -0
  273. package/deps/rocksdb/rocksdb/db_stress_tool/cf_consistency_stress.cc +520 -0
  274. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress.cc +23 -0
  275. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.cc +337 -0
  276. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +554 -0
  277. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_compaction_filter.h +79 -0
  278. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_driver.cc +173 -0
  279. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_driver.h +17 -0
  280. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_env_wrapper.h +38 -0
  281. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +763 -0
  282. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_listener.h +222 -0
  283. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_shared_state.cc +27 -0
  284. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_shared_state.h +428 -0
  285. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_stat.h +218 -0
  286. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_table_properties_collector.h +64 -0
  287. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +2430 -0
  288. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.h +237 -0
  289. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_tool.cc +343 -0
  290. package/deps/rocksdb/rocksdb/db_stress_tool/no_batched_ops_stress.cc +800 -0
  291. package/deps/rocksdb/rocksdb/env/composite_env_wrapper.h +920 -0
  292. package/deps/rocksdb/rocksdb/env/env.cc +733 -0
  293. package/deps/rocksdb/rocksdb/env/env_basic_test.cc +352 -0
  294. package/deps/rocksdb/rocksdb/env/env_chroot.cc +346 -0
  295. package/deps/rocksdb/rocksdb/env/env_chroot.h +22 -0
  296. package/deps/rocksdb/rocksdb/env/env_encryption.cc +1148 -0
  297. package/deps/rocksdb/rocksdb/env/env_encryption_ctr.h +137 -0
  298. package/deps/rocksdb/rocksdb/env/env_hdfs.cc +648 -0
  299. package/deps/rocksdb/rocksdb/env/env_posix.cc +514 -0
  300. package/deps/rocksdb/rocksdb/env/env_test.cc +2230 -0
  301. package/deps/rocksdb/rocksdb/env/file_system.cc +132 -0
  302. package/deps/rocksdb/rocksdb/env/file_system_tracer.cc +448 -0
  303. package/deps/rocksdb/rocksdb/env/file_system_tracer.h +415 -0
  304. package/deps/rocksdb/rocksdb/env/fs_posix.cc +1086 -0
  305. package/deps/rocksdb/rocksdb/env/io_posix.cc +1499 -0
  306. package/deps/rocksdb/rocksdb/env/io_posix.h +402 -0
  307. package/deps/rocksdb/rocksdb/env/io_posix_test.cc +140 -0
  308. package/deps/rocksdb/rocksdb/env/mock_env.cc +1066 -0
  309. package/deps/rocksdb/rocksdb/env/mock_env.h +41 -0
  310. package/deps/rocksdb/rocksdb/env/mock_env_test.cc +85 -0
  311. package/deps/rocksdb/rocksdb/file/delete_scheduler.cc +402 -0
  312. package/deps/rocksdb/rocksdb/file/delete_scheduler.h +150 -0
  313. package/deps/rocksdb/rocksdb/file/delete_scheduler_test.cc +717 -0
  314. package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.cc +156 -0
  315. package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.h +99 -0
  316. package/deps/rocksdb/rocksdb/file/file_util.cc +268 -0
  317. package/deps/rocksdb/rocksdb/file/file_util.h +96 -0
  318. package/deps/rocksdb/rocksdb/file/filename.cc +473 -0
  319. package/deps/rocksdb/rocksdb/file/filename.h +182 -0
  320. package/deps/rocksdb/rocksdb/file/prefetch_test.cc +188 -0
  321. package/deps/rocksdb/rocksdb/file/random_access_file_reader.cc +315 -0
  322. package/deps/rocksdb/rocksdb/file/random_access_file_reader.h +142 -0
  323. package/deps/rocksdb/rocksdb/file/random_access_file_reader_test.cc +482 -0
  324. package/deps/rocksdb/rocksdb/file/read_write_util.cc +67 -0
  325. package/deps/rocksdb/rocksdb/file/read_write_util.h +34 -0
  326. package/deps/rocksdb/rocksdb/file/readahead_raf.cc +169 -0
  327. package/deps/rocksdb/rocksdb/file/readahead_raf.h +29 -0
  328. package/deps/rocksdb/rocksdb/file/sequence_file_reader.cc +237 -0
  329. package/deps/rocksdb/rocksdb/file/sequence_file_reader.h +63 -0
  330. package/deps/rocksdb/rocksdb/file/sst_file_manager_impl.cc +552 -0
  331. package/deps/rocksdb/rocksdb/file/sst_file_manager_impl.h +203 -0
  332. package/deps/rocksdb/rocksdb/file/writable_file_writer.cc +523 -0
  333. package/deps/rocksdb/rocksdb/file/writable_file_writer.h +251 -0
  334. package/deps/rocksdb/rocksdb/hdfs/env_hdfs.h +386 -0
  335. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +839 -0
  336. package/deps/rocksdb/rocksdb/include/rocksdb/c.h +2218 -0
  337. package/deps/rocksdb/rocksdb/include/rocksdb/cache.h +294 -0
  338. package/deps/rocksdb/rocksdb/include/rocksdb/cleanable.h +71 -0
  339. package/deps/rocksdb/rocksdb/include/rocksdb/compaction_filter.h +214 -0
  340. package/deps/rocksdb/rocksdb/include/rocksdb/compaction_job_stats.h +98 -0
  341. package/deps/rocksdb/rocksdb/include/rocksdb/comparator.h +137 -0
  342. package/deps/rocksdb/rocksdb/include/rocksdb/compression_type.h +40 -0
  343. package/deps/rocksdb/rocksdb/include/rocksdb/concurrent_task_limiter.h +46 -0
  344. package/deps/rocksdb/rocksdb/include/rocksdb/configurable.h +359 -0
  345. package/deps/rocksdb/rocksdb/include/rocksdb/convenience.h +499 -0
  346. package/deps/rocksdb/rocksdb/include/rocksdb/customizable.h +138 -0
  347. package/deps/rocksdb/rocksdb/include/rocksdb/db.h +1697 -0
  348. package/deps/rocksdb/rocksdb/include/rocksdb/db_bench_tool.h +11 -0
  349. package/deps/rocksdb/rocksdb/include/rocksdb/db_dump_tool.h +45 -0
  350. package/deps/rocksdb/rocksdb/include/rocksdb/db_stress_tool.h +11 -0
  351. package/deps/rocksdb/rocksdb/include/rocksdb/env.h +1671 -0
  352. package/deps/rocksdb/rocksdb/include/rocksdb/env_encryption.h +405 -0
  353. package/deps/rocksdb/rocksdb/include/rocksdb/experimental.h +29 -0
  354. package/deps/rocksdb/rocksdb/include/rocksdb/file_checksum.h +129 -0
  355. package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +1472 -0
  356. package/deps/rocksdb/rocksdb/include/rocksdb/filter_policy.h +238 -0
  357. package/deps/rocksdb/rocksdb/include/rocksdb/flush_block_policy.h +61 -0
  358. package/deps/rocksdb/rocksdb/include/rocksdb/io_status.h +269 -0
  359. package/deps/rocksdb/rocksdb/include/rocksdb/iostats_context.h +56 -0
  360. package/deps/rocksdb/rocksdb/include/rocksdb/iterator.h +128 -0
  361. package/deps/rocksdb/rocksdb/include/rocksdb/ldb_tool.h +43 -0
  362. package/deps/rocksdb/rocksdb/include/rocksdb/listener.h +556 -0
  363. package/deps/rocksdb/rocksdb/include/rocksdb/memory_allocator.h +77 -0
  364. package/deps/rocksdb/rocksdb/include/rocksdb/memtablerep.h +385 -0
  365. package/deps/rocksdb/rocksdb/include/rocksdb/merge_operator.h +257 -0
  366. package/deps/rocksdb/rocksdb/include/rocksdb/metadata.h +155 -0
  367. package/deps/rocksdb/rocksdb/include/rocksdb/options.h +1702 -0
  368. package/deps/rocksdb/rocksdb/include/rocksdb/perf_context.h +237 -0
  369. package/deps/rocksdb/rocksdb/include/rocksdb/perf_level.h +35 -0
  370. package/deps/rocksdb/rocksdb/include/rocksdb/persistent_cache.h +73 -0
  371. package/deps/rocksdb/rocksdb/include/rocksdb/rate_limiter.h +139 -0
  372. package/deps/rocksdb/rocksdb/include/rocksdb/rocksdb_namespace.h +10 -0
  373. package/deps/rocksdb/rocksdb/include/rocksdb/slice.h +269 -0
  374. package/deps/rocksdb/rocksdb/include/rocksdb/slice_transform.h +103 -0
  375. package/deps/rocksdb/rocksdb/include/rocksdb/snapshot.h +48 -0
  376. package/deps/rocksdb/rocksdb/include/rocksdb/sst_dump_tool.h +19 -0
  377. package/deps/rocksdb/rocksdb/include/rocksdb/sst_file_manager.h +136 -0
  378. package/deps/rocksdb/rocksdb/include/rocksdb/sst_file_reader.h +47 -0
  379. package/deps/rocksdb/rocksdb/include/rocksdb/sst_file_writer.h +145 -0
  380. package/deps/rocksdb/rocksdb/include/rocksdb/sst_partitioner.h +135 -0
  381. package/deps/rocksdb/rocksdb/include/rocksdb/statistics.h +592 -0
  382. package/deps/rocksdb/rocksdb/include/rocksdb/stats_history.h +69 -0
  383. package/deps/rocksdb/rocksdb/include/rocksdb/status.h +608 -0
  384. package/deps/rocksdb/rocksdb/include/rocksdb/table.h +711 -0
  385. package/deps/rocksdb/rocksdb/include/rocksdb/table_properties.h +280 -0
  386. package/deps/rocksdb/rocksdb/include/rocksdb/thread_status.h +188 -0
  387. package/deps/rocksdb/rocksdb/include/rocksdb/threadpool.h +58 -0
  388. package/deps/rocksdb/rocksdb/include/rocksdb/trace_reader_writer.h +48 -0
  389. package/deps/rocksdb/rocksdb/include/rocksdb/transaction_log.h +121 -0
  390. package/deps/rocksdb/rocksdb/include/rocksdb/types.h +74 -0
  391. package/deps/rocksdb/rocksdb/include/rocksdb/universal_compaction.h +86 -0
  392. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/backupable_db.h +535 -0
  393. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/checkpoint.h +61 -0
  394. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/convenience.h +10 -0
  395. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/db_ttl.h +72 -0
  396. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/debug.h +49 -0
  397. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/env_librados.h +175 -0
  398. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/env_mirror.h +180 -0
  399. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/info_log_finder.h +19 -0
  400. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/ldb_cmd.h +288 -0
  401. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/ldb_cmd_execute_result.h +71 -0
  402. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/leveldb_options.h +145 -0
  403. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/lua/rocks_lua_custom_library.h +43 -0
  404. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/lua/rocks_lua_util.h +55 -0
  405. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/memory_util.h +50 -0
  406. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/object_registry.h +205 -0
  407. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/optimistic_transaction_db.h +100 -0
  408. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/option_change_migration.h +19 -0
  409. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/options_type.h +876 -0
  410. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/options_util.h +128 -0
  411. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/sim_cache.h +94 -0
  412. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +504 -0
  413. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/table_properties_collectors.h +95 -0
  414. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/transaction.h +626 -0
  415. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/transaction_db.h +432 -0
  416. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/transaction_db_mutex.h +92 -0
  417. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/utility_db.h +34 -0
  418. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/write_batch_with_index.h +279 -0
  419. package/deps/rocksdb/rocksdb/include/rocksdb/version.h +16 -0
  420. package/deps/rocksdb/rocksdb/include/rocksdb/wal_filter.h +102 -0
  421. package/deps/rocksdb/rocksdb/include/rocksdb/write_batch.h +377 -0
  422. package/deps/rocksdb/rocksdb/include/rocksdb/write_batch_base.h +127 -0
  423. package/deps/rocksdb/rocksdb/include/rocksdb/write_buffer_manager.h +106 -0
  424. package/deps/rocksdb/rocksdb/logging/auto_roll_logger.cc +300 -0
  425. package/deps/rocksdb/rocksdb/logging/auto_roll_logger.h +165 -0
  426. package/deps/rocksdb/rocksdb/logging/auto_roll_logger_test.cc +684 -0
  427. package/deps/rocksdb/rocksdb/logging/env_logger.h +165 -0
  428. package/deps/rocksdb/rocksdb/logging/env_logger_test.cc +162 -0
  429. package/deps/rocksdb/rocksdb/logging/event_logger.cc +70 -0
  430. package/deps/rocksdb/rocksdb/logging/event_logger.h +203 -0
  431. package/deps/rocksdb/rocksdb/logging/event_logger_test.cc +43 -0
  432. package/deps/rocksdb/rocksdb/logging/log_buffer.cc +92 -0
  433. package/deps/rocksdb/rocksdb/logging/log_buffer.h +56 -0
  434. package/deps/rocksdb/rocksdb/logging/logging.h +68 -0
  435. package/deps/rocksdb/rocksdb/logging/posix_logger.h +185 -0
  436. package/deps/rocksdb/rocksdb/memory/allocator.h +57 -0
  437. package/deps/rocksdb/rocksdb/memory/arena.cc +233 -0
  438. package/deps/rocksdb/rocksdb/memory/arena.h +141 -0
  439. package/deps/rocksdb/rocksdb/memory/arena_test.cc +204 -0
  440. package/deps/rocksdb/rocksdb/memory/concurrent_arena.cc +47 -0
  441. package/deps/rocksdb/rocksdb/memory/concurrent_arena.h +218 -0
  442. package/deps/rocksdb/rocksdb/memory/jemalloc_nodump_allocator.cc +206 -0
  443. package/deps/rocksdb/rocksdb/memory/jemalloc_nodump_allocator.h +78 -0
  444. package/deps/rocksdb/rocksdb/memory/memkind_kmem_allocator.cc +33 -0
  445. package/deps/rocksdb/rocksdb/memory/memkind_kmem_allocator.h +27 -0
  446. package/deps/rocksdb/rocksdb/memory/memkind_kmem_allocator_test.cc +102 -0
  447. package/deps/rocksdb/rocksdb/memory/memory_allocator.h +38 -0
  448. package/deps/rocksdb/rocksdb/memory/memory_usage.h +25 -0
  449. package/deps/rocksdb/rocksdb/memtable/alloc_tracker.cc +62 -0
  450. package/deps/rocksdb/rocksdb/memtable/hash_linklist_rep.cc +844 -0
  451. package/deps/rocksdb/rocksdb/memtable/hash_linklist_rep.h +49 -0
  452. package/deps/rocksdb/rocksdb/memtable/hash_skiplist_rep.cc +349 -0
  453. package/deps/rocksdb/rocksdb/memtable/hash_skiplist_rep.h +44 -0
  454. package/deps/rocksdb/rocksdb/memtable/inlineskiplist.h +997 -0
  455. package/deps/rocksdb/rocksdb/memtable/inlineskiplist_test.cc +663 -0
  456. package/deps/rocksdb/rocksdb/memtable/memtablerep_bench.cc +677 -0
  457. package/deps/rocksdb/rocksdb/memtable/skiplist.h +496 -0
  458. package/deps/rocksdb/rocksdb/memtable/skiplist_test.cc +388 -0
  459. package/deps/rocksdb/rocksdb/memtable/skiplistrep.cc +280 -0
  460. package/deps/rocksdb/rocksdb/memtable/stl_wrappers.h +33 -0
  461. package/deps/rocksdb/rocksdb/memtable/vectorrep.cc +301 -0
  462. package/deps/rocksdb/rocksdb/memtable/write_buffer_manager.cc +148 -0
  463. package/deps/rocksdb/rocksdb/memtable/write_buffer_manager_test.cc +203 -0
  464. package/deps/rocksdb/rocksdb/monitoring/file_read_sample.h +23 -0
  465. package/deps/rocksdb/rocksdb/monitoring/histogram.cc +287 -0
  466. package/deps/rocksdb/rocksdb/monitoring/histogram.h +149 -0
  467. package/deps/rocksdb/rocksdb/monitoring/histogram_test.cc +231 -0
  468. package/deps/rocksdb/rocksdb/monitoring/histogram_windowing.cc +200 -0
  469. package/deps/rocksdb/rocksdb/monitoring/histogram_windowing.h +84 -0
  470. package/deps/rocksdb/rocksdb/monitoring/in_memory_stats_history.cc +49 -0
  471. package/deps/rocksdb/rocksdb/monitoring/in_memory_stats_history.h +74 -0
  472. package/deps/rocksdb/rocksdb/monitoring/instrumented_mutex.cc +71 -0
  473. package/deps/rocksdb/rocksdb/monitoring/instrumented_mutex.h +98 -0
  474. package/deps/rocksdb/rocksdb/monitoring/iostats_context.cc +62 -0
  475. package/deps/rocksdb/rocksdb/monitoring/iostats_context_imp.h +60 -0
  476. package/deps/rocksdb/rocksdb/monitoring/iostats_context_test.cc +29 -0
  477. package/deps/rocksdb/rocksdb/monitoring/perf_context.cc +566 -0
  478. package/deps/rocksdb/rocksdb/monitoring/perf_context_imp.h +97 -0
  479. package/deps/rocksdb/rocksdb/monitoring/perf_level.cc +28 -0
  480. package/deps/rocksdb/rocksdb/monitoring/perf_level_imp.h +18 -0
  481. package/deps/rocksdb/rocksdb/monitoring/perf_step_timer.h +79 -0
  482. package/deps/rocksdb/rocksdb/monitoring/persistent_stats_history.cc +169 -0
  483. package/deps/rocksdb/rocksdb/monitoring/persistent_stats_history.h +83 -0
  484. package/deps/rocksdb/rocksdb/monitoring/statistics.cc +431 -0
  485. package/deps/rocksdb/rocksdb/monitoring/statistics.h +138 -0
  486. package/deps/rocksdb/rocksdb/monitoring/statistics_test.cc +47 -0
  487. package/deps/rocksdb/rocksdb/monitoring/stats_history_test.cc +652 -0
  488. package/deps/rocksdb/rocksdb/monitoring/thread_status_impl.cc +163 -0
  489. package/deps/rocksdb/rocksdb/monitoring/thread_status_updater.cc +314 -0
  490. package/deps/rocksdb/rocksdb/monitoring/thread_status_updater.h +233 -0
  491. package/deps/rocksdb/rocksdb/monitoring/thread_status_updater_debug.cc +43 -0
  492. package/deps/rocksdb/rocksdb/monitoring/thread_status_util.cc +206 -0
  493. package/deps/rocksdb/rocksdb/monitoring/thread_status_util.h +134 -0
  494. package/deps/rocksdb/rocksdb/monitoring/thread_status_util_debug.cc +32 -0
  495. package/deps/rocksdb/rocksdb/options/cf_options.cc +1026 -0
  496. package/deps/rocksdb/rocksdb/options/cf_options.h +308 -0
  497. package/deps/rocksdb/rocksdb/options/configurable.cc +681 -0
  498. package/deps/rocksdb/rocksdb/options/configurable_helper.h +251 -0
  499. package/deps/rocksdb/rocksdb/options/configurable_test.cc +757 -0
  500. package/deps/rocksdb/rocksdb/options/configurable_test.h +127 -0
  501. package/deps/rocksdb/rocksdb/options/customizable.cc +77 -0
  502. package/deps/rocksdb/rocksdb/options/customizable_helper.h +216 -0
  503. package/deps/rocksdb/rocksdb/options/customizable_test.cc +625 -0
  504. package/deps/rocksdb/rocksdb/options/db_options.cc +835 -0
  505. package/deps/rocksdb/rocksdb/options/db_options.h +126 -0
  506. package/deps/rocksdb/rocksdb/options/options.cc +664 -0
  507. package/deps/rocksdb/rocksdb/options/options_helper.cc +1391 -0
  508. package/deps/rocksdb/rocksdb/options/options_helper.h +118 -0
  509. package/deps/rocksdb/rocksdb/options/options_parser.cc +721 -0
  510. package/deps/rocksdb/rocksdb/options/options_parser.h +151 -0
  511. package/deps/rocksdb/rocksdb/options/options_settable_test.cc +583 -0
  512. package/deps/rocksdb/rocksdb/options/options_test.cc +3794 -0
  513. package/deps/rocksdb/rocksdb/port/jemalloc_helper.h +106 -0
  514. package/deps/rocksdb/rocksdb/port/lang.h +16 -0
  515. package/deps/rocksdb/rocksdb/port/likely.h +18 -0
  516. package/deps/rocksdb/rocksdb/port/malloc.h +17 -0
  517. package/deps/rocksdb/rocksdb/port/port.h +21 -0
  518. package/deps/rocksdb/rocksdb/port/port_dirent.h +44 -0
  519. package/deps/rocksdb/rocksdb/port/port_example.h +101 -0
  520. package/deps/rocksdb/rocksdb/port/port_posix.cc +266 -0
  521. package/deps/rocksdb/rocksdb/port/port_posix.h +223 -0
  522. package/deps/rocksdb/rocksdb/port/stack_trace.cc +179 -0
  523. package/deps/rocksdb/rocksdb/port/stack_trace.h +28 -0
  524. package/deps/rocksdb/rocksdb/port/sys_time.h +47 -0
  525. package/deps/rocksdb/rocksdb/port/util_logger.h +20 -0
  526. package/deps/rocksdb/rocksdb/port/win/env_default.cc +45 -0
  527. package/deps/rocksdb/rocksdb/port/win/env_win.cc +1449 -0
  528. package/deps/rocksdb/rocksdb/port/win/env_win.h +294 -0
  529. package/deps/rocksdb/rocksdb/port/win/io_win.cc +1084 -0
  530. package/deps/rocksdb/rocksdb/port/win/io_win.h +494 -0
  531. package/deps/rocksdb/rocksdb/port/win/port_win.cc +283 -0
  532. package/deps/rocksdb/rocksdb/port/win/port_win.h +411 -0
  533. package/deps/rocksdb/rocksdb/port/win/win_jemalloc.cc +79 -0
  534. package/deps/rocksdb/rocksdb/port/win/win_logger.cc +194 -0
  535. package/deps/rocksdb/rocksdb/port/win/win_logger.h +67 -0
  536. package/deps/rocksdb/rocksdb/port/win/win_thread.cc +183 -0
  537. package/deps/rocksdb/rocksdb/port/win/win_thread.h +122 -0
  538. package/deps/rocksdb/rocksdb/port/win/xpress_win.cc +221 -0
  539. package/deps/rocksdb/rocksdb/port/win/xpress_win.h +26 -0
  540. package/deps/rocksdb/rocksdb/port/xpress.h +17 -0
  541. package/deps/rocksdb/rocksdb/src.mk +631 -0
  542. package/deps/rocksdb/rocksdb/table/adaptive/adaptive_table_factory.cc +126 -0
  543. package/deps/rocksdb/rocksdb/table/adaptive/adaptive_table_factory.h +57 -0
  544. package/deps/rocksdb/rocksdb/table/block_based/binary_search_index_reader.cc +73 -0
  545. package/deps/rocksdb/rocksdb/table/block_based/binary_search_index_reader.h +48 -0
  546. package/deps/rocksdb/rocksdb/table/block_based/block.cc +1049 -0
  547. package/deps/rocksdb/rocksdb/table/block_based/block.h +720 -0
  548. package/deps/rocksdb/rocksdb/table/block_based/block_based_filter_block.cc +348 -0
  549. package/deps/rocksdb/rocksdb/table/block_based/block_based_filter_block.h +119 -0
  550. package/deps/rocksdb/rocksdb/table/block_based/block_based_filter_block_test.cc +434 -0
  551. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +1835 -0
  552. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.h +193 -0
  553. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.cc +839 -0
  554. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.h +95 -0
  555. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.cc +383 -0
  556. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.h +251 -0
  557. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +3563 -0
  558. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +681 -0
  559. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_impl.h +190 -0
  560. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_test.cc +347 -0
  561. package/deps/rocksdb/rocksdb/table/block_based/block_builder.cc +201 -0
  562. package/deps/rocksdb/rocksdb/table/block_based/block_builder.h +78 -0
  563. package/deps/rocksdb/rocksdb/table/block_based/block_prefetcher.cc +66 -0
  564. package/deps/rocksdb/rocksdb/table/block_based/block_prefetcher.h +32 -0
  565. package/deps/rocksdb/rocksdb/table/block_based/block_prefix_index.cc +232 -0
  566. package/deps/rocksdb/rocksdb/table/block_based/block_prefix_index.h +66 -0
  567. package/deps/rocksdb/rocksdb/table/block_based/block_test.cc +623 -0
  568. package/deps/rocksdb/rocksdb/table/block_based/block_type.h +30 -0
  569. package/deps/rocksdb/rocksdb/table/block_based/cachable_entry.h +220 -0
  570. package/deps/rocksdb/rocksdb/table/block_based/data_block_footer.cc +59 -0
  571. package/deps/rocksdb/rocksdb/table/block_based/data_block_footer.h +25 -0
  572. package/deps/rocksdb/rocksdb/table/block_based/data_block_hash_index.cc +93 -0
  573. package/deps/rocksdb/rocksdb/table/block_based/data_block_hash_index.h +136 -0
  574. package/deps/rocksdb/rocksdb/table/block_based/data_block_hash_index_test.cc +717 -0
  575. package/deps/rocksdb/rocksdb/table/block_based/filter_block.h +180 -0
  576. package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.cc +102 -0
  577. package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.h +55 -0
  578. package/deps/rocksdb/rocksdb/table/block_based/filter_policy.cc +1407 -0
  579. package/deps/rocksdb/rocksdb/table/block_based/filter_policy_internal.h +168 -0
  580. package/deps/rocksdb/rocksdb/table/block_based/flush_block_policy.cc +88 -0
  581. package/deps/rocksdb/rocksdb/table/block_based/flush_block_policy.h +41 -0
  582. package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.cc +344 -0
  583. package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.h +139 -0
  584. package/deps/rocksdb/rocksdb/table/block_based/full_filter_block_test.cc +333 -0
  585. package/deps/rocksdb/rocksdb/table/block_based/hash_index_reader.cc +147 -0
  586. package/deps/rocksdb/rocksdb/table/block_based/hash_index_reader.h +49 -0
  587. package/deps/rocksdb/rocksdb/table/block_based/index_builder.cc +248 -0
  588. package/deps/rocksdb/rocksdb/table/block_based/index_builder.h +444 -0
  589. package/deps/rocksdb/rocksdb/table/block_based/index_reader_common.cc +54 -0
  590. package/deps/rocksdb/rocksdb/table/block_based/index_reader_common.h +85 -0
  591. package/deps/rocksdb/rocksdb/table/block_based/mock_block_based_table.h +56 -0
  592. package/deps/rocksdb/rocksdb/table/block_based/parsed_full_filter_block.cc +22 -0
  593. package/deps/rocksdb/rocksdb/table/block_based/parsed_full_filter_block.h +40 -0
  594. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +521 -0
  595. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.h +144 -0
  596. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block_test.cc +424 -0
  597. package/deps/rocksdb/rocksdb/table/block_based/partitioned_index_iterator.cc +163 -0
  598. package/deps/rocksdb/rocksdb/table/block_based/partitioned_index_iterator.h +142 -0
  599. package/deps/rocksdb/rocksdb/table/block_based/partitioned_index_reader.cc +186 -0
  600. package/deps/rocksdb/rocksdb/table/block_based/partitioned_index_reader.h +51 -0
  601. package/deps/rocksdb/rocksdb/table/block_based/reader_common.cc +64 -0
  602. package/deps/rocksdb/rocksdb/table/block_based/reader_common.h +38 -0
  603. package/deps/rocksdb/rocksdb/table/block_based/uncompression_dict_reader.cc +120 -0
  604. package/deps/rocksdb/rocksdb/table/block_based/uncompression_dict_reader.h +59 -0
  605. package/deps/rocksdb/rocksdb/table/block_fetcher.cc +324 -0
  606. package/deps/rocksdb/rocksdb/table/block_fetcher.h +129 -0
  607. package/deps/rocksdb/rocksdb/table/block_fetcher_test.cc +534 -0
  608. package/deps/rocksdb/rocksdb/table/cleanable_test.cc +277 -0
  609. package/deps/rocksdb/rocksdb/table/cuckoo/cuckoo_table_builder.cc +543 -0
  610. package/deps/rocksdb/rocksdb/table/cuckoo/cuckoo_table_builder.h +136 -0
  611. package/deps/rocksdb/rocksdb/table/cuckoo/cuckoo_table_builder_test.cc +663 -0
  612. package/deps/rocksdb/rocksdb/table/cuckoo/cuckoo_table_factory.cc +107 -0
  613. package/deps/rocksdb/rocksdb/table/cuckoo/cuckoo_table_factory.h +81 -0
  614. package/deps/rocksdb/rocksdb/table/cuckoo/cuckoo_table_reader.cc +404 -0
  615. package/deps/rocksdb/rocksdb/table/cuckoo/cuckoo_table_reader.h +101 -0
  616. package/deps/rocksdb/rocksdb/table/cuckoo/cuckoo_table_reader_test.cc +585 -0
  617. package/deps/rocksdb/rocksdb/table/format.cc +422 -0
  618. package/deps/rocksdb/rocksdb/table/format.h +348 -0
  619. package/deps/rocksdb/rocksdb/table/get_context.cc +408 -0
  620. package/deps/rocksdb/rocksdb/table/get_context.h +212 -0
  621. package/deps/rocksdb/rocksdb/table/internal_iterator.h +205 -0
  622. package/deps/rocksdb/rocksdb/table/iter_heap.h +42 -0
  623. package/deps/rocksdb/rocksdb/table/iterator.cc +210 -0
  624. package/deps/rocksdb/rocksdb/table/iterator_wrapper.h +180 -0
  625. package/deps/rocksdb/rocksdb/table/merger_test.cc +180 -0
  626. package/deps/rocksdb/rocksdb/table/merging_iterator.cc +481 -0
  627. package/deps/rocksdb/rocksdb/table/merging_iterator.h +64 -0
  628. package/deps/rocksdb/rocksdb/table/meta_blocks.cc +541 -0
  629. package/deps/rocksdb/rocksdb/table/meta_blocks.h +154 -0
  630. package/deps/rocksdb/rocksdb/table/mock_table.cc +328 -0
  631. package/deps/rocksdb/rocksdb/table/mock_table.h +89 -0
  632. package/deps/rocksdb/rocksdb/table/multiget_context.h +282 -0
  633. package/deps/rocksdb/rocksdb/table/persistent_cache_helper.cc +116 -0
  634. package/deps/rocksdb/rocksdb/table/persistent_cache_helper.h +44 -0
  635. package/deps/rocksdb/rocksdb/table/persistent_cache_options.h +34 -0
  636. package/deps/rocksdb/rocksdb/table/plain/plain_table_bloom.cc +78 -0
  637. package/deps/rocksdb/rocksdb/table/plain/plain_table_bloom.h +135 -0
  638. package/deps/rocksdb/rocksdb/table/plain/plain_table_builder.cc +332 -0
  639. package/deps/rocksdb/rocksdb/table/plain/plain_table_builder.h +153 -0
  640. package/deps/rocksdb/rocksdb/table/plain/plain_table_factory.cc +263 -0
  641. package/deps/rocksdb/rocksdb/table/plain/plain_table_factory.h +182 -0
  642. package/deps/rocksdb/rocksdb/table/plain/plain_table_index.cc +211 -0
  643. package/deps/rocksdb/rocksdb/table/plain/plain_table_index.h +249 -0
  644. package/deps/rocksdb/rocksdb/table/plain/plain_table_key_coding.cc +506 -0
  645. package/deps/rocksdb/rocksdb/table/plain/plain_table_key_coding.h +201 -0
  646. package/deps/rocksdb/rocksdb/table/plain/plain_table_reader.cc +781 -0
  647. package/deps/rocksdb/rocksdb/table/plain/plain_table_reader.h +247 -0
  648. package/deps/rocksdb/rocksdb/table/scoped_arena_iterator.h +61 -0
  649. package/deps/rocksdb/rocksdb/table/sst_file_dumper.cc +502 -0
  650. package/deps/rocksdb/rocksdb/table/sst_file_dumper.h +96 -0
  651. package/deps/rocksdb/rocksdb/table/sst_file_reader.cc +98 -0
  652. package/deps/rocksdb/rocksdb/table/sst_file_reader_test.cc +228 -0
  653. package/deps/rocksdb/rocksdb/table/sst_file_writer.cc +340 -0
  654. package/deps/rocksdb/rocksdb/table/sst_file_writer_collectors.h +94 -0
  655. package/deps/rocksdb/rocksdb/table/table_builder.h +203 -0
  656. package/deps/rocksdb/rocksdb/table/table_factory.cc +38 -0
  657. package/deps/rocksdb/rocksdb/table/table_properties.cc +300 -0
  658. package/deps/rocksdb/rocksdb/table/table_properties_internal.h +30 -0
  659. package/deps/rocksdb/rocksdb/table/table_reader.h +147 -0
  660. package/deps/rocksdb/rocksdb/table/table_reader_bench.cc +347 -0
  661. package/deps/rocksdb/rocksdb/table/table_reader_caller.h +39 -0
  662. package/deps/rocksdb/rocksdb/table/table_test.cc +4769 -0
  663. package/deps/rocksdb/rocksdb/table/two_level_iterator.cc +215 -0
  664. package/deps/rocksdb/rocksdb/table/two_level_iterator.h +43 -0
  665. package/deps/rocksdb/rocksdb/test_util/mock_time_env.cc +38 -0
  666. package/deps/rocksdb/rocksdb/test_util/mock_time_env.h +74 -0
  667. package/deps/rocksdb/rocksdb/test_util/sync_point.cc +93 -0
  668. package/deps/rocksdb/rocksdb/test_util/sync_point.h +161 -0
  669. package/deps/rocksdb/rocksdb/test_util/sync_point_impl.cc +129 -0
  670. package/deps/rocksdb/rocksdb/test_util/sync_point_impl.h +74 -0
  671. package/deps/rocksdb/rocksdb/test_util/testharness.cc +56 -0
  672. package/deps/rocksdb/rocksdb/test_util/testharness.h +53 -0
  673. package/deps/rocksdb/rocksdb/test_util/testutil.cc +566 -0
  674. package/deps/rocksdb/rocksdb/test_util/testutil.h +887 -0
  675. package/deps/rocksdb/rocksdb/test_util/testutil_test.cc +43 -0
  676. package/deps/rocksdb/rocksdb/test_util/transaction_test_util.cc +388 -0
  677. package/deps/rocksdb/rocksdb/test_util/transaction_test_util.h +132 -0
  678. package/deps/rocksdb/rocksdb/third-party/folly/folly/CPortability.h +27 -0
  679. package/deps/rocksdb/rocksdb/third-party/folly/folly/ConstexprMath.h +45 -0
  680. package/deps/rocksdb/rocksdb/third-party/folly/folly/Indestructible.h +166 -0
  681. package/deps/rocksdb/rocksdb/third-party/folly/folly/Optional.h +570 -0
  682. package/deps/rocksdb/rocksdb/third-party/folly/folly/Portability.h +92 -0
  683. package/deps/rocksdb/rocksdb/third-party/folly/folly/ScopeGuard.h +54 -0
  684. package/deps/rocksdb/rocksdb/third-party/folly/folly/Traits.h +152 -0
  685. package/deps/rocksdb/rocksdb/third-party/folly/folly/Unit.h +59 -0
  686. package/deps/rocksdb/rocksdb/third-party/folly/folly/Utility.h +141 -0
  687. package/deps/rocksdb/rocksdb/third-party/folly/folly/chrono/Hardware.h +33 -0
  688. package/deps/rocksdb/rocksdb/third-party/folly/folly/container/Array.h +74 -0
  689. package/deps/rocksdb/rocksdb/third-party/folly/folly/detail/Futex-inl.h +117 -0
  690. package/deps/rocksdb/rocksdb/third-party/folly/folly/detail/Futex.cpp +263 -0
  691. package/deps/rocksdb/rocksdb/third-party/folly/folly/detail/Futex.h +96 -0
  692. package/deps/rocksdb/rocksdb/third-party/folly/folly/functional/Invoke.h +40 -0
  693. package/deps/rocksdb/rocksdb/third-party/folly/folly/hash/Hash.h +29 -0
  694. package/deps/rocksdb/rocksdb/third-party/folly/folly/lang/Align.h +144 -0
  695. package/deps/rocksdb/rocksdb/third-party/folly/folly/lang/Bits.h +30 -0
  696. package/deps/rocksdb/rocksdb/third-party/folly/folly/lang/Launder.h +51 -0
  697. package/deps/rocksdb/rocksdb/third-party/folly/folly/portability/Asm.h +28 -0
  698. package/deps/rocksdb/rocksdb/third-party/folly/folly/portability/SysSyscall.h +10 -0
  699. package/deps/rocksdb/rocksdb/third-party/folly/folly/portability/SysTypes.h +26 -0
  700. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/AtomicNotification-inl.h +138 -0
  701. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/AtomicNotification.cpp +23 -0
  702. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/AtomicNotification.h +57 -0
  703. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/AtomicUtil-inl.h +260 -0
  704. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/AtomicUtil.h +52 -0
  705. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/Baton.h +328 -0
  706. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/DistributedMutex-inl.h +1703 -0
  707. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/DistributedMutex.cpp +16 -0
  708. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/DistributedMutex.h +304 -0
  709. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/DistributedMutexSpecializations.h +39 -0
  710. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/ParkingLot.cpp +26 -0
  711. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/ParkingLot.h +318 -0
  712. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/WaitOptions.cpp +12 -0
  713. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/WaitOptions.h +57 -0
  714. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/detail/InlineFunctionRef.h +219 -0
  715. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/detail/ProxyLockable-inl.h +207 -0
  716. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/detail/ProxyLockable.h +164 -0
  717. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/detail/Sleeper.h +57 -0
  718. package/deps/rocksdb/rocksdb/third-party/folly/folly/synchronization/detail/Spin.h +77 -0
  719. package/deps/rocksdb/rocksdb/third-party/gcc/ppc-asm.h +390 -0
  720. package/deps/rocksdb/rocksdb/thirdparty.inc +268 -0
  721. package/deps/rocksdb/rocksdb/tools/CMakeLists.txt +30 -0
  722. package/deps/rocksdb/rocksdb/tools/blob_dump.cc +110 -0
  723. package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/__init__.py +2 -0
  724. package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_pysim.py +2000 -0
  725. package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_pysim.sh +156 -0
  726. package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_pysim_test.py +734 -0
  727. package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_trace_analyzer.cc +2307 -0
  728. package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_trace_analyzer.h +395 -0
  729. package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_trace_analyzer_plot.py +721 -0
  730. package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_trace_analyzer_test.cc +719 -0
  731. package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_trace_analyzer_tool.cc +25 -0
  732. package/deps/rocksdb/rocksdb/tools/db_bench.cc +21 -0
  733. package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +7416 -0
  734. package/deps/rocksdb/rocksdb/tools/db_bench_tool_test.cc +328 -0
  735. package/deps/rocksdb/rocksdb/tools/db_repl_stress.cc +130 -0
  736. package/deps/rocksdb/rocksdb/tools/db_sanity_test.cc +297 -0
  737. package/deps/rocksdb/rocksdb/tools/dump/db_dump_tool.cc +259 -0
  738. package/deps/rocksdb/rocksdb/tools/dump/rocksdb_dump.cc +63 -0
  739. package/deps/rocksdb/rocksdb/tools/dump/rocksdb_undump.cc +62 -0
  740. package/deps/rocksdb/rocksdb/tools/io_tracer_parser.cc +25 -0
  741. package/deps/rocksdb/rocksdb/tools/io_tracer_parser_test.cc +187 -0
  742. package/deps/rocksdb/rocksdb/tools/io_tracer_parser_tool.cc +120 -0
  743. package/deps/rocksdb/rocksdb/tools/io_tracer_parser_tool.h +40 -0
  744. package/deps/rocksdb/rocksdb/tools/ldb.cc +21 -0
  745. package/deps/rocksdb/rocksdb/tools/ldb_cmd.cc +3609 -0
  746. package/deps/rocksdb/rocksdb/tools/ldb_cmd_impl.h +665 -0
  747. package/deps/rocksdb/rocksdb/tools/ldb_cmd_test.cc +746 -0
  748. package/deps/rocksdb/rocksdb/tools/ldb_tool.cc +159 -0
  749. package/deps/rocksdb/rocksdb/tools/reduce_levels_test.cc +221 -0
  750. package/deps/rocksdb/rocksdb/tools/sst_dump.cc +20 -0
  751. package/deps/rocksdb/rocksdb/tools/sst_dump_test.cc +427 -0
  752. package/deps/rocksdb/rocksdb/tools/sst_dump_tool.cc +541 -0
  753. package/deps/rocksdb/rocksdb/tools/trace_analyzer.cc +25 -0
  754. package/deps/rocksdb/rocksdb/tools/trace_analyzer_test.cc +752 -0
  755. package/deps/rocksdb/rocksdb/tools/trace_analyzer_tool.cc +2001 -0
  756. package/deps/rocksdb/rocksdb/tools/trace_analyzer_tool.h +292 -0
  757. package/deps/rocksdb/rocksdb/tools/write_stress.cc +305 -0
  758. package/deps/rocksdb/rocksdb/trace_replay/block_cache_tracer.cc +496 -0
  759. package/deps/rocksdb/rocksdb/trace_replay/block_cache_tracer.h +294 -0
  760. package/deps/rocksdb/rocksdb/trace_replay/block_cache_tracer_test.cc +379 -0
  761. package/deps/rocksdb/rocksdb/trace_replay/io_tracer.cc +229 -0
  762. package/deps/rocksdb/rocksdb/trace_replay/io_tracer.h +174 -0
  763. package/deps/rocksdb/rocksdb/trace_replay/io_tracer_test.cc +215 -0
  764. package/deps/rocksdb/rocksdb/trace_replay/trace_replay.cc +491 -0
  765. package/deps/rocksdb/rocksdb/trace_replay/trace_replay.h +195 -0
  766. package/deps/rocksdb/rocksdb/util/aligned_buffer.h +255 -0
  767. package/deps/rocksdb/rocksdb/util/autovector.h +367 -0
  768. package/deps/rocksdb/rocksdb/util/autovector_test.cc +330 -0
  769. package/deps/rocksdb/rocksdb/util/bloom_impl.h +485 -0
  770. package/deps/rocksdb/rocksdb/util/bloom_test.cc +1191 -0
  771. package/deps/rocksdb/rocksdb/util/build_version.cc.in +5 -0
  772. package/deps/rocksdb/rocksdb/util/build_version.h +15 -0
  773. package/deps/rocksdb/rocksdb/util/cast_util.h +20 -0
  774. package/deps/rocksdb/rocksdb/util/channel.h +67 -0
  775. package/deps/rocksdb/rocksdb/util/coding.cc +89 -0
  776. package/deps/rocksdb/rocksdb/util/coding.h +419 -0
  777. package/deps/rocksdb/rocksdb/util/coding_lean.h +101 -0
  778. package/deps/rocksdb/rocksdb/util/coding_test.cc +217 -0
  779. package/deps/rocksdb/rocksdb/util/compaction_job_stats_impl.cc +92 -0
  780. package/deps/rocksdb/rocksdb/util/comparator.cc +219 -0
  781. package/deps/rocksdb/rocksdb/util/compression.h +1529 -0
  782. package/deps/rocksdb/rocksdb/util/compression_context_cache.cc +108 -0
  783. package/deps/rocksdb/rocksdb/util/compression_context_cache.h +47 -0
  784. package/deps/rocksdb/rocksdb/util/concurrent_task_limiter_impl.cc +67 -0
  785. package/deps/rocksdb/rocksdb/util/concurrent_task_limiter_impl.h +67 -0
  786. package/deps/rocksdb/rocksdb/util/core_local.h +83 -0
  787. package/deps/rocksdb/rocksdb/util/crc32c.cc +1283 -0
  788. package/deps/rocksdb/rocksdb/util/crc32c.h +51 -0
  789. package/deps/rocksdb/rocksdb/util/crc32c_arm64.cc +169 -0
  790. package/deps/rocksdb/rocksdb/util/crc32c_arm64.h +50 -0
  791. package/deps/rocksdb/rocksdb/util/crc32c_ppc.c +94 -0
  792. package/deps/rocksdb/rocksdb/util/crc32c_ppc.h +19 -0
  793. package/deps/rocksdb/rocksdb/util/crc32c_ppc_asm.S +756 -0
  794. package/deps/rocksdb/rocksdb/util/crc32c_ppc_constants.h +900 -0
  795. package/deps/rocksdb/rocksdb/util/crc32c_test.cc +180 -0
  796. package/deps/rocksdb/rocksdb/util/defer.h +52 -0
  797. package/deps/rocksdb/rocksdb/util/defer_test.cc +39 -0
  798. package/deps/rocksdb/rocksdb/util/duplicate_detector.h +68 -0
  799. package/deps/rocksdb/rocksdb/util/dynamic_bloom.cc +70 -0
  800. package/deps/rocksdb/rocksdb/util/dynamic_bloom.h +214 -0
  801. package/deps/rocksdb/rocksdb/util/dynamic_bloom_test.cc +323 -0
  802. package/deps/rocksdb/rocksdb/util/fastrange.h +112 -0
  803. package/deps/rocksdb/rocksdb/util/file_checksum_helper.cc +136 -0
  804. package/deps/rocksdb/rocksdb/util/file_checksum_helper.h +98 -0
  805. package/deps/rocksdb/rocksdb/util/file_reader_writer_test.cc +449 -0
  806. package/deps/rocksdb/rocksdb/util/filelock_test.cc +152 -0
  807. package/deps/rocksdb/rocksdb/util/filter_bench.cc +781 -0
  808. package/deps/rocksdb/rocksdb/util/gflags_compat.h +20 -0
  809. package/deps/rocksdb/rocksdb/util/hash.cc +83 -0
  810. package/deps/rocksdb/rocksdb/util/hash.h +107 -0
  811. package/deps/rocksdb/rocksdb/util/hash_map.h +67 -0
  812. package/deps/rocksdb/rocksdb/util/hash_test.cc +593 -0
  813. package/deps/rocksdb/rocksdb/util/heap.h +166 -0
  814. package/deps/rocksdb/rocksdb/util/heap_test.cc +139 -0
  815. package/deps/rocksdb/rocksdb/util/kv_map.h +33 -0
  816. package/deps/rocksdb/rocksdb/util/log_write_bench.cc +86 -0
  817. package/deps/rocksdb/rocksdb/util/math.h +186 -0
  818. package/deps/rocksdb/rocksdb/util/math128.h +298 -0
  819. package/deps/rocksdb/rocksdb/util/murmurhash.cc +191 -0
  820. package/deps/rocksdb/rocksdb/util/murmurhash.h +42 -0
  821. package/deps/rocksdb/rocksdb/util/mutexlock.h +186 -0
  822. package/deps/rocksdb/rocksdb/util/ppc-opcode.h +27 -0
  823. package/deps/rocksdb/rocksdb/util/random.cc +56 -0
  824. package/deps/rocksdb/rocksdb/util/random.h +186 -0
  825. package/deps/rocksdb/rocksdb/util/random_test.cc +105 -0
  826. package/deps/rocksdb/rocksdb/util/rate_limiter.cc +340 -0
  827. package/deps/rocksdb/rocksdb/util/rate_limiter.h +113 -0
  828. package/deps/rocksdb/rocksdb/util/rate_limiter_test.cc +251 -0
  829. package/deps/rocksdb/rocksdb/util/repeatable_thread.h +151 -0
  830. package/deps/rocksdb/rocksdb/util/repeatable_thread_test.cc +107 -0
  831. package/deps/rocksdb/rocksdb/util/ribbon_alg.h +1201 -0
  832. package/deps/rocksdb/rocksdb/util/ribbon_impl.h +1062 -0
  833. package/deps/rocksdb/rocksdb/util/ribbon_test.cc +931 -0
  834. package/deps/rocksdb/rocksdb/util/set_comparator.h +22 -0
  835. package/deps/rocksdb/rocksdb/util/slice.cc +243 -0
  836. package/deps/rocksdb/rocksdb/util/slice_test.cc +163 -0
  837. package/deps/rocksdb/rocksdb/util/slice_transform_test.cc +153 -0
  838. package/deps/rocksdb/rocksdb/util/status.cc +149 -0
  839. package/deps/rocksdb/rocksdb/util/stderr_logger.h +31 -0
  840. package/deps/rocksdb/rocksdb/util/stop_watch.h +118 -0
  841. package/deps/rocksdb/rocksdb/util/string_util.cc +422 -0
  842. package/deps/rocksdb/rocksdb/util/string_util.h +144 -0
  843. package/deps/rocksdb/rocksdb/util/thread_list_test.cc +354 -0
  844. package/deps/rocksdb/rocksdb/util/thread_local.cc +554 -0
  845. package/deps/rocksdb/rocksdb/util/thread_local.h +101 -0
  846. package/deps/rocksdb/rocksdb/util/thread_local_test.cc +583 -0
  847. package/deps/rocksdb/rocksdb/util/thread_operation.h +121 -0
  848. package/deps/rocksdb/rocksdb/util/threadpool_imp.cc +506 -0
  849. package/deps/rocksdb/rocksdb/util/threadpool_imp.h +112 -0
  850. package/deps/rocksdb/rocksdb/util/timer.h +331 -0
  851. package/deps/rocksdb/rocksdb/util/timer_queue.h +230 -0
  852. package/deps/rocksdb/rocksdb/util/timer_queue_test.cc +72 -0
  853. package/deps/rocksdb/rocksdb/util/timer_test.cc +399 -0
  854. package/deps/rocksdb/rocksdb/util/user_comparator_wrapper.h +80 -0
  855. package/deps/rocksdb/rocksdb/util/vector_iterator.h +101 -0
  856. package/deps/rocksdb/rocksdb/util/work_queue.h +148 -0
  857. package/deps/rocksdb/rocksdb/util/work_queue_test.cc +268 -0
  858. package/deps/rocksdb/rocksdb/util/xxh3p.h +1392 -0
  859. package/deps/rocksdb/rocksdb/util/xxhash.cc +1158 -0
  860. package/deps/rocksdb/rocksdb/util/xxhash.h +598 -0
  861. package/deps/rocksdb/rocksdb/utilities/backupable/backupable_db.cc +2354 -0
  862. package/deps/rocksdb/rocksdb/utilities/backupable/backupable_db_test.cc +2955 -0
  863. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_compaction_filter.cc +488 -0
  864. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_compaction_filter.h +199 -0
  865. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db.cc +112 -0
  866. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db.h +266 -0
  867. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_gc_stats.h +52 -0
  868. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_impl.cc +2167 -0
  869. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_impl.h +500 -0
  870. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_impl_filesnapshot.cc +113 -0
  871. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_iterator.h +147 -0
  872. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_listener.h +66 -0
  873. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_test.cc +2386 -0
  874. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_dump_tool.cc +281 -0
  875. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_dump_tool.h +58 -0
  876. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_file.cc +314 -0
  877. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_file.h +244 -0
  878. package/deps/rocksdb/rocksdb/utilities/cassandra/cassandra_compaction_filter.cc +47 -0
  879. package/deps/rocksdb/rocksdb/utilities/cassandra/cassandra_compaction_filter.h +42 -0
  880. package/deps/rocksdb/rocksdb/utilities/cassandra/cassandra_format_test.cc +375 -0
  881. package/deps/rocksdb/rocksdb/utilities/cassandra/cassandra_functional_test.cc +327 -0
  882. package/deps/rocksdb/rocksdb/utilities/cassandra/cassandra_row_merge_test.cc +114 -0
  883. package/deps/rocksdb/rocksdb/utilities/cassandra/cassandra_serialize_test.cc +187 -0
  884. package/deps/rocksdb/rocksdb/utilities/cassandra/format.cc +390 -0
  885. package/deps/rocksdb/rocksdb/utilities/cassandra/format.h +184 -0
  886. package/deps/rocksdb/rocksdb/utilities/cassandra/merge_operator.cc +67 -0
  887. package/deps/rocksdb/rocksdb/utilities/cassandra/merge_operator.h +44 -0
  888. package/deps/rocksdb/rocksdb/utilities/cassandra/serialize.h +75 -0
  889. package/deps/rocksdb/rocksdb/utilities/cassandra/test_utils.cc +72 -0
  890. package/deps/rocksdb/rocksdb/utilities/cassandra/test_utils.h +43 -0
  891. package/deps/rocksdb/rocksdb/utilities/checkpoint/checkpoint_impl.cc +588 -0
  892. package/deps/rocksdb/rocksdb/utilities/checkpoint/checkpoint_impl.h +82 -0
  893. package/deps/rocksdb/rocksdb/utilities/checkpoint/checkpoint_test.cc +821 -0
  894. package/deps/rocksdb/rocksdb/utilities/compaction_filters/layered_compaction_filter_base.h +37 -0
  895. package/deps/rocksdb/rocksdb/utilities/compaction_filters/remove_emptyvalue_compactionfilter.cc +29 -0
  896. package/deps/rocksdb/rocksdb/utilities/compaction_filters/remove_emptyvalue_compactionfilter.h +27 -0
  897. package/deps/rocksdb/rocksdb/utilities/convenience/info_log_finder.cc +25 -0
  898. package/deps/rocksdb/rocksdb/utilities/debug.cc +82 -0
  899. package/deps/rocksdb/rocksdb/utilities/env_librados.cc +1497 -0
  900. package/deps/rocksdb/rocksdb/utilities/env_librados_test.cc +1146 -0
  901. package/deps/rocksdb/rocksdb/utilities/env_mirror.cc +262 -0
  902. package/deps/rocksdb/rocksdb/utilities/env_mirror_test.cc +223 -0
  903. package/deps/rocksdb/rocksdb/utilities/env_timed.cc +145 -0
  904. package/deps/rocksdb/rocksdb/utilities/env_timed_test.cc +44 -0
  905. package/deps/rocksdb/rocksdb/utilities/fault_injection_env.cc +490 -0
  906. package/deps/rocksdb/rocksdb/utilities/fault_injection_env.h +242 -0
  907. package/deps/rocksdb/rocksdb/utilities/fault_injection_fs.cc +581 -0
  908. package/deps/rocksdb/rocksdb/utilities/fault_injection_fs.h +437 -0
  909. package/deps/rocksdb/rocksdb/utilities/leveldb_options/leveldb_options.cc +56 -0
  910. package/deps/rocksdb/rocksdb/utilities/memory/memory_test.cc +275 -0
  911. package/deps/rocksdb/rocksdb/utilities/memory/memory_util.cc +52 -0
  912. package/deps/rocksdb/rocksdb/utilities/merge_operators/bytesxor.cc +59 -0
  913. package/deps/rocksdb/rocksdb/utilities/merge_operators/bytesxor.h +39 -0
  914. package/deps/rocksdb/rocksdb/utilities/merge_operators/max.cc +77 -0
  915. package/deps/rocksdb/rocksdb/utilities/merge_operators/put.cc +83 -0
  916. package/deps/rocksdb/rocksdb/utilities/merge_operators/sortlist.cc +97 -0
  917. package/deps/rocksdb/rocksdb/utilities/merge_operators/sortlist.h +38 -0
  918. package/deps/rocksdb/rocksdb/utilities/merge_operators/string_append/stringappend.cc +59 -0
  919. package/deps/rocksdb/rocksdb/utilities/merge_operators/string_append/stringappend.h +31 -0
  920. package/deps/rocksdb/rocksdb/utilities/merge_operators/string_append/stringappend2.cc +117 -0
  921. package/deps/rocksdb/rocksdb/utilities/merge_operators/string_append/stringappend2.h +49 -0
  922. package/deps/rocksdb/rocksdb/utilities/merge_operators/string_append/stringappend_test.cc +598 -0
  923. package/deps/rocksdb/rocksdb/utilities/merge_operators/uint64add.cc +69 -0
  924. package/deps/rocksdb/rocksdb/utilities/merge_operators.h +55 -0
  925. package/deps/rocksdb/rocksdb/utilities/object_registry.cc +87 -0
  926. package/deps/rocksdb/rocksdb/utilities/object_registry_test.cc +174 -0
  927. package/deps/rocksdb/rocksdb/utilities/option_change_migration/option_change_migration.cc +168 -0
  928. package/deps/rocksdb/rocksdb/utilities/option_change_migration/option_change_migration_test.cc +431 -0
  929. package/deps/rocksdb/rocksdb/utilities/options/options_util.cc +159 -0
  930. package/deps/rocksdb/rocksdb/utilities/options/options_util_test.cc +655 -0
  931. package/deps/rocksdb/rocksdb/utilities/persistent_cache/block_cache_tier.cc +425 -0
  932. package/deps/rocksdb/rocksdb/utilities/persistent_cache/block_cache_tier.h +156 -0
  933. package/deps/rocksdb/rocksdb/utilities/persistent_cache/block_cache_tier_file.cc +609 -0
  934. package/deps/rocksdb/rocksdb/utilities/persistent_cache/block_cache_tier_file.h +296 -0
  935. package/deps/rocksdb/rocksdb/utilities/persistent_cache/block_cache_tier_file_buffer.h +127 -0
  936. package/deps/rocksdb/rocksdb/utilities/persistent_cache/block_cache_tier_metadata.cc +86 -0
  937. package/deps/rocksdb/rocksdb/utilities/persistent_cache/block_cache_tier_metadata.h +125 -0
  938. package/deps/rocksdb/rocksdb/utilities/persistent_cache/hash_table.h +238 -0
  939. package/deps/rocksdb/rocksdb/utilities/persistent_cache/hash_table_bench.cc +308 -0
  940. package/deps/rocksdb/rocksdb/utilities/persistent_cache/hash_table_evictable.h +168 -0
  941. package/deps/rocksdb/rocksdb/utilities/persistent_cache/hash_table_test.cc +160 -0
  942. package/deps/rocksdb/rocksdb/utilities/persistent_cache/lrulist.h +174 -0
  943. package/deps/rocksdb/rocksdb/utilities/persistent_cache/persistent_cache_bench.cc +360 -0
  944. package/deps/rocksdb/rocksdb/utilities/persistent_cache/persistent_cache_test.cc +456 -0
  945. package/deps/rocksdb/rocksdb/utilities/persistent_cache/persistent_cache_test.h +286 -0
  946. package/deps/rocksdb/rocksdb/utilities/persistent_cache/persistent_cache_tier.cc +167 -0
  947. package/deps/rocksdb/rocksdb/utilities/persistent_cache/persistent_cache_tier.h +339 -0
  948. package/deps/rocksdb/rocksdb/utilities/persistent_cache/persistent_cache_util.h +67 -0
  949. package/deps/rocksdb/rocksdb/utilities/persistent_cache/volatile_tier_impl.cc +140 -0
  950. package/deps/rocksdb/rocksdb/utilities/persistent_cache/volatile_tier_impl.h +142 -0
  951. package/deps/rocksdb/rocksdb/utilities/simulator_cache/cache_simulator.cc +285 -0
  952. package/deps/rocksdb/rocksdb/utilities/simulator_cache/cache_simulator.h +231 -0
  953. package/deps/rocksdb/rocksdb/utilities/simulator_cache/cache_simulator_test.cc +494 -0
  954. package/deps/rocksdb/rocksdb/utilities/simulator_cache/sim_cache.cc +356 -0
  955. package/deps/rocksdb/rocksdb/utilities/simulator_cache/sim_cache_test.cc +224 -0
  956. package/deps/rocksdb/rocksdb/utilities/table_properties_collectors/compact_on_deletion_collector.cc +122 -0
  957. package/deps/rocksdb/rocksdb/utilities/table_properties_collectors/compact_on_deletion_collector.h +72 -0
  958. package/deps/rocksdb/rocksdb/utilities/table_properties_collectors/compact_on_deletion_collector_test.cc +244 -0
  959. package/deps/rocksdb/rocksdb/utilities/trace/file_trace_reader_writer.cc +125 -0
  960. package/deps/rocksdb/rocksdb/utilities/trace/file_trace_reader_writer.h +48 -0
  961. package/deps/rocksdb/rocksdb/utilities/transactions/lock/lock_manager.cc +29 -0
  962. package/deps/rocksdb/rocksdb/utilities/transactions/lock/lock_manager.h +82 -0
  963. package/deps/rocksdb/rocksdb/utilities/transactions/lock/lock_tracker.h +209 -0
  964. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager.cc +720 -0
  965. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager.h +223 -0
  966. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager_test.cc +181 -0
  967. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager_test.h +319 -0
  968. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_tracker.cc +270 -0
  969. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_tracker.h +99 -0
  970. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_lock_manager.h +30 -0
  971. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_locking_test.cc +306 -0
  972. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/COPYING.AGPLv3 +661 -0
  973. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/COPYING.APACHEv2 +174 -0
  974. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/COPYING.GPLv2 +339 -0
  975. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/db.h +76 -0
  976. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/ft/comparator.h +138 -0
  977. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/ft/ft-status.h +102 -0
  978. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/concurrent_tree.cc +139 -0
  979. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/concurrent_tree.h +174 -0
  980. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/keyrange.cc +222 -0
  981. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/keyrange.h +141 -0
  982. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/lock_request.cc +525 -0
  983. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/lock_request.h +253 -0
  984. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/locktree.cc +1007 -0
  985. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/locktree.h +560 -0
  986. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/manager.cc +527 -0
  987. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/range_buffer.cc +265 -0
  988. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/range_buffer.h +178 -0
  989. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/treenode.cc +520 -0
  990. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/treenode.h +302 -0
  991. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/txnid_set.cc +120 -0
  992. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/txnid_set.h +92 -0
  993. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/wfg.cc +213 -0
  994. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/locktree/wfg.h +124 -0
  995. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/portability/memory.h +215 -0
  996. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/portability/toku_assert_subst.h +39 -0
  997. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/portability/toku_atomic.h +130 -0
  998. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/portability/toku_external_pthread.h +82 -0
  999. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/portability/toku_instrumentation.h +286 -0
  1000. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/portability/toku_portability.h +87 -0
  1001. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/portability/toku_pthread.h +520 -0
  1002. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/portability/toku_race_tools.h +179 -0
  1003. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/portability/toku_time.h +172 -0
  1004. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/portability/txn_subst.h +27 -0
  1005. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/standalone_port.cc +132 -0
  1006. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/util/dbt.cc +153 -0
  1007. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/util/dbt.h +98 -0
  1008. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/util/growable_array.h +144 -0
  1009. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/util/memarena.cc +201 -0
  1010. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/util/memarena.h +141 -0
  1011. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/util/omt.h +794 -0
  1012. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/util/omt_impl.h +1295 -0
  1013. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/util/partitioned_counter.h +165 -0
  1014. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/util/status.h +76 -0
  1015. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/range_tree_lock_manager.cc +479 -0
  1016. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/range_tree_lock_manager.h +130 -0
  1017. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/range_tree_lock_tracker.cc +156 -0
  1018. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/range_tree_lock_tracker.h +146 -0
  1019. package/deps/rocksdb/rocksdb/utilities/transactions/optimistic_transaction.cc +196 -0
  1020. package/deps/rocksdb/rocksdb/utilities/transactions/optimistic_transaction.h +101 -0
  1021. package/deps/rocksdb/rocksdb/utilities/transactions/optimistic_transaction_db_impl.cc +111 -0
  1022. package/deps/rocksdb/rocksdb/utilities/transactions/optimistic_transaction_db_impl.h +87 -0
  1023. package/deps/rocksdb/rocksdb/utilities/transactions/optimistic_transaction_test.cc +1418 -0
  1024. package/deps/rocksdb/rocksdb/utilities/transactions/pessimistic_transaction.cc +752 -0
  1025. package/deps/rocksdb/rocksdb/utilities/transactions/pessimistic_transaction.h +232 -0
  1026. package/deps/rocksdb/rocksdb/utilities/transactions/pessimistic_transaction_db.cc +628 -0
  1027. package/deps/rocksdb/rocksdb/utilities/transactions/pessimistic_transaction_db.h +228 -0
  1028. package/deps/rocksdb/rocksdb/utilities/transactions/snapshot_checker.cc +49 -0
  1029. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_base.cc +678 -0
  1030. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_base.h +373 -0
  1031. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_db_mutex_impl.cc +135 -0
  1032. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_db_mutex_impl.h +26 -0
  1033. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.cc +6350 -0
  1034. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.h +522 -0
  1035. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_util.cc +188 -0
  1036. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_util.h +80 -0
  1037. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_transaction_test.cc +3531 -0
  1038. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_txn.cc +483 -0
  1039. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_txn.h +119 -0
  1040. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_txn_db.cc +999 -0
  1041. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_txn_db.h +1109 -0
  1042. package/deps/rocksdb/rocksdb/utilities/transactions/write_unprepared_transaction_test.cc +786 -0
  1043. package/deps/rocksdb/rocksdb/utilities/transactions/write_unprepared_txn.cc +1039 -0
  1044. package/deps/rocksdb/rocksdb/utilities/transactions/write_unprepared_txn.h +341 -0
  1045. package/deps/rocksdb/rocksdb/utilities/transactions/write_unprepared_txn_db.cc +470 -0
  1046. package/deps/rocksdb/rocksdb/utilities/transactions/write_unprepared_txn_db.h +108 -0
  1047. package/deps/rocksdb/rocksdb/utilities/ttl/db_ttl_impl.cc +332 -0
  1048. package/deps/rocksdb/rocksdb/utilities/ttl/db_ttl_impl.h +353 -0
  1049. package/deps/rocksdb/rocksdb/utilities/ttl/ttl_test.cc +703 -0
  1050. package/deps/rocksdb/rocksdb/utilities/util_merge_operators_test.cc +99 -0
  1051. package/deps/rocksdb/rocksdb/utilities/write_batch_with_index/write_batch_with_index.cc +617 -0
  1052. package/deps/rocksdb/rocksdb/utilities/write_batch_with_index/write_batch_with_index_internal.cc +345 -0
  1053. package/deps/rocksdb/rocksdb/utilities/write_batch_with_index/write_batch_with_index_internal.h +569 -0
  1054. package/deps/rocksdb/rocksdb/utilities/write_batch_with_index/write_batch_with_index_test.cc +1867 -0
  1055. package/deps/rocksdb/rocksdb.gyp +475 -0
  1056. package/deps/snappy/freebsd/config.h +135 -0
  1057. package/deps/snappy/freebsd/snappy-stubs-public.h +100 -0
  1058. package/deps/snappy/linux/config.h +135 -0
  1059. package/deps/snappy/linux/snappy-stubs-public.h +100 -0
  1060. package/deps/snappy/mac/config.h +137 -0
  1061. package/deps/snappy/mac/snappy-stubs-public.h +100 -0
  1062. package/deps/snappy/openbsd/config.h +135 -0
  1063. package/deps/snappy/openbsd/snappy-stubs-public.h +100 -0
  1064. package/deps/snappy/snappy-1.1.7/COPYING +54 -0
  1065. package/deps/snappy/snappy-1.1.7/cmake/SnappyConfig.cmake +1 -0
  1066. package/deps/snappy/snappy-1.1.7/cmake/config.h.in +62 -0
  1067. package/deps/snappy/snappy-1.1.7/snappy-c.cc +90 -0
  1068. package/deps/snappy/snappy-1.1.7/snappy-c.h +138 -0
  1069. package/deps/snappy/snappy-1.1.7/snappy-internal.h +224 -0
  1070. package/deps/snappy/snappy-1.1.7/snappy-sinksource.cc +104 -0
  1071. package/deps/snappy/snappy-1.1.7/snappy-sinksource.h +182 -0
  1072. package/deps/snappy/snappy-1.1.7/snappy-stubs-internal.cc +42 -0
  1073. package/deps/snappy/snappy-1.1.7/snappy-stubs-internal.h +561 -0
  1074. package/deps/snappy/snappy-1.1.7/snappy-stubs-public.h.in +94 -0
  1075. package/deps/snappy/snappy-1.1.7/snappy-test.cc +612 -0
  1076. package/deps/snappy/snappy-1.1.7/snappy-test.h +573 -0
  1077. package/deps/snappy/snappy-1.1.7/snappy.cc +1515 -0
  1078. package/deps/snappy/snappy-1.1.7/snappy.h +203 -0
  1079. package/deps/snappy/snappy-1.1.7/snappy_unittest.cc +1410 -0
  1080. package/deps/snappy/snappy.gyp +90 -0
  1081. package/deps/snappy/solaris/config.h +135 -0
  1082. package/deps/snappy/solaris/snappy-stubs-public.h +100 -0
  1083. package/deps/snappy/win32/config.h +29 -0
  1084. package/deps/snappy/win32/snappy-stubs-public.h +100 -0
  1085. package/iterator.js +55 -0
  1086. package/leveldown.js +113 -0
  1087. package/package-lock.json +23687 -0
  1088. package/package.json +70 -0
@@ -0,0 +1,4769 @@
1
+ // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2
+ // This source code is licensed under both the GPLv2 (found in the
3
+ // COPYING file in the root directory) and Apache 2.0 License
4
+ // (found in the LICENSE.Apache file in the root directory).
5
+ //
6
+ // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7
+ // Use of this source code is governed by a BSD-style license that can be
8
+ // found in the LICENSE file. See the AUTHORS file for names of contributors.
9
+
10
+ #include <stdio.h>
11
+ #include <algorithm>
12
+ #include <iostream>
13
+ #include <map>
14
+ #include <memory>
15
+ #include <string>
16
+ #include <vector>
17
+
18
+ #include "block_fetcher.h"
19
+ #include "cache/lru_cache.h"
20
+ #include "db/dbformat.h"
21
+ #include "db/memtable.h"
22
+ #include "db/write_batch_internal.h"
23
+ #include "memtable/stl_wrappers.h"
24
+ #include "meta_blocks.h"
25
+ #include "monitoring/statistics.h"
26
+ #include "port/port.h"
27
+ #include "rocksdb/cache.h"
28
+ #include "rocksdb/db.h"
29
+ #include "rocksdb/env.h"
30
+ #include "rocksdb/file_checksum.h"
31
+ #include "rocksdb/file_system.h"
32
+ #include "rocksdb/iterator.h"
33
+ #include "rocksdb/memtablerep.h"
34
+ #include "rocksdb/perf_context.h"
35
+ #include "rocksdb/slice_transform.h"
36
+ #include "rocksdb/statistics.h"
37
+ #include "rocksdb/write_buffer_manager.h"
38
+ #include "table/block_based/block.h"
39
+ #include "table/block_based/block_based_table_builder.h"
40
+ #include "table/block_based/block_based_table_factory.h"
41
+ #include "table/block_based/block_based_table_reader.h"
42
+ #include "table/block_based/block_builder.h"
43
+ #include "table/block_based/flush_block_policy.h"
44
+ #include "table/format.h"
45
+ #include "table/get_context.h"
46
+ #include "table/internal_iterator.h"
47
+ #include "table/plain/plain_table_factory.h"
48
+ #include "table/scoped_arena_iterator.h"
49
+ #include "table/sst_file_writer_collectors.h"
50
+ #include "test_util/sync_point.h"
51
+ #include "test_util/testharness.h"
52
+ #include "test_util/testutil.h"
53
+ #include "util/compression.h"
54
+ #include "util/file_checksum_helper.h"
55
+ #include "util/random.h"
56
+ #include "util/string_util.h"
57
+ #include "utilities/merge_operators.h"
58
+
59
+ namespace ROCKSDB_NAMESPACE {
60
+
61
+ extern const uint64_t kLegacyBlockBasedTableMagicNumber;
62
+ extern const uint64_t kLegacyPlainTableMagicNumber;
63
+ extern const uint64_t kBlockBasedTableMagicNumber;
64
+ extern const uint64_t kPlainTableMagicNumber;
65
+
66
+ namespace {
67
+
68
+ const std::string kDummyValue(10000, 'o');
69
+
70
+ // DummyPropertiesCollector used to test BlockBasedTableProperties
71
+ class DummyPropertiesCollector : public TablePropertiesCollector {
72
+ public:
73
+ const char* Name() const override { return "DummyPropertiesCollector"; }
74
+
75
+ Status Finish(UserCollectedProperties* /*properties*/) override {
76
+ return Status::OK();
77
+ }
78
+
79
+ Status Add(const Slice& /*user_key*/, const Slice& /*value*/) override {
80
+ return Status::OK();
81
+ }
82
+
83
+ UserCollectedProperties GetReadableProperties() const override {
84
+ return UserCollectedProperties{};
85
+ }
86
+ };
87
+
88
+ class DummyPropertiesCollectorFactory1
89
+ : public TablePropertiesCollectorFactory {
90
+ public:
91
+ TablePropertiesCollector* CreateTablePropertiesCollector(
92
+ TablePropertiesCollectorFactory::Context /*context*/) override {
93
+ return new DummyPropertiesCollector();
94
+ }
95
+ const char* Name() const override {
96
+ return "DummyPropertiesCollectorFactory1";
97
+ }
98
+ };
99
+
100
+ class DummyPropertiesCollectorFactory2
101
+ : public TablePropertiesCollectorFactory {
102
+ public:
103
+ TablePropertiesCollector* CreateTablePropertiesCollector(
104
+ TablePropertiesCollectorFactory::Context /*context*/) override {
105
+ return new DummyPropertiesCollector();
106
+ }
107
+ const char* Name() const override {
108
+ return "DummyPropertiesCollectorFactory2";
109
+ }
110
+ };
111
+
112
+ // Return reverse of "key".
113
+ // Used to test non-lexicographic comparators.
114
+ std::string Reverse(const Slice& key) {
115
+ auto rev = key.ToString();
116
+ std::reverse(rev.begin(), rev.end());
117
+ return rev;
118
+ }
119
+
120
+ class ReverseKeyComparator : public Comparator {
121
+ public:
122
+ const char* Name() const override {
123
+ return "rocksdb.ReverseBytewiseComparator";
124
+ }
125
+
126
+ int Compare(const Slice& a, const Slice& b) const override {
127
+ return BytewiseComparator()->Compare(Reverse(a), Reverse(b));
128
+ }
129
+
130
+ void FindShortestSeparator(std::string* start,
131
+ const Slice& limit) const override {
132
+ std::string s = Reverse(*start);
133
+ std::string l = Reverse(limit);
134
+ BytewiseComparator()->FindShortestSeparator(&s, l);
135
+ *start = Reverse(s);
136
+ }
137
+
138
+ void FindShortSuccessor(std::string* key) const override {
139
+ std::string s = Reverse(*key);
140
+ BytewiseComparator()->FindShortSuccessor(&s);
141
+ *key = Reverse(s);
142
+ }
143
+ };
144
+
145
+ ReverseKeyComparator reverse_key_comparator;
146
+
147
+ void Increment(const Comparator* cmp, std::string* key) {
148
+ if (cmp == BytewiseComparator()) {
149
+ key->push_back('\0');
150
+ } else {
151
+ assert(cmp == &reverse_key_comparator);
152
+ std::string rev = Reverse(*key);
153
+ rev.push_back('\0');
154
+ *key = Reverse(rev);
155
+ }
156
+ }
157
+
158
+ } // namespace
159
+
160
+ // Helper class for tests to unify the interface between
161
+ // BlockBuilder/TableBuilder and Block/Table.
162
+ class Constructor {
163
+ public:
164
+ explicit Constructor(const Comparator* cmp)
165
+ : data_(stl_wrappers::LessOfComparator(cmp)) {}
166
+ virtual ~Constructor() { }
167
+
168
+ void Add(const std::string& key, const Slice& value) {
169
+ data_[key] = value.ToString();
170
+ }
171
+
172
+ // Finish constructing the data structure with all the keys that have
173
+ // been added so far. Returns the keys in sorted order in "*keys"
174
+ // and stores the key/value pairs in "*kvmap"
175
+ void Finish(const Options& options, const ImmutableCFOptions& ioptions,
176
+ const MutableCFOptions& moptions,
177
+ const BlockBasedTableOptions& table_options,
178
+ const InternalKeyComparator& internal_comparator,
179
+ std::vector<std::string>* keys, stl_wrappers::KVMap* kvmap) {
180
+ last_internal_key_ = &internal_comparator;
181
+ *kvmap = data_;
182
+ keys->clear();
183
+ for (const auto& kv : data_) {
184
+ keys->push_back(kv.first);
185
+ }
186
+ data_.clear();
187
+ Status s = FinishImpl(options, ioptions, moptions, table_options,
188
+ internal_comparator, *kvmap);
189
+ ASSERT_TRUE(s.ok()) << s.ToString();
190
+ }
191
+
192
+ // Construct the data structure from the data in "data"
193
+ virtual Status FinishImpl(const Options& options,
194
+ const ImmutableCFOptions& ioptions,
195
+ const MutableCFOptions& moptions,
196
+ const BlockBasedTableOptions& table_options,
197
+ const InternalKeyComparator& internal_comparator,
198
+ const stl_wrappers::KVMap& data) = 0;
199
+
200
+ virtual InternalIterator* NewIterator(
201
+ const SliceTransform* prefix_extractor = nullptr) const = 0;
202
+
203
+ virtual const stl_wrappers::KVMap& data() { return data_; }
204
+
205
+ virtual bool IsArenaMode() const { return false; }
206
+
207
+ virtual DB* db() const { return nullptr; } // Overridden in DBConstructor
208
+
209
+ virtual bool AnywayDeleteIterator() const { return false; }
210
+
211
+ protected:
212
+ const InternalKeyComparator* last_internal_key_;
213
+
214
+ private:
215
+ stl_wrappers::KVMap data_;
216
+ };
217
+
218
+ // A helper class that converts internal format keys into user keys
219
+ class KeyConvertingIterator : public InternalIterator {
220
+ public:
221
+ explicit KeyConvertingIterator(InternalIterator* iter,
222
+ bool arena_mode = false)
223
+ : iter_(iter), arena_mode_(arena_mode) {}
224
+ ~KeyConvertingIterator() override {
225
+ if (arena_mode_) {
226
+ iter_->~InternalIterator();
227
+ } else {
228
+ delete iter_;
229
+ }
230
+ }
231
+ bool Valid() const override { return iter_->Valid() && status_.ok(); }
232
+ void Seek(const Slice& target) override {
233
+ ParsedInternalKey ikey(target, kMaxSequenceNumber, kTypeValue);
234
+ std::string encoded;
235
+ AppendInternalKey(&encoded, ikey);
236
+ iter_->Seek(encoded);
237
+ }
238
+ void SeekForPrev(const Slice& target) override {
239
+ ParsedInternalKey ikey(target, kMaxSequenceNumber, kTypeValue);
240
+ std::string encoded;
241
+ AppendInternalKey(&encoded, ikey);
242
+ iter_->SeekForPrev(encoded);
243
+ }
244
+ void SeekToFirst() override { iter_->SeekToFirst(); }
245
+ void SeekToLast() override { iter_->SeekToLast(); }
246
+ void Next() override { iter_->Next(); }
247
+ void Prev() override { iter_->Prev(); }
248
+ IterBoundCheck UpperBoundCheckResult() override {
249
+ return iter_->UpperBoundCheckResult();
250
+ }
251
+
252
+ Slice key() const override {
253
+ assert(Valid());
254
+ ParsedInternalKey parsed_key;
255
+ Status pik_status =
256
+ ParseInternalKey(iter_->key(), &parsed_key, true /* log_err_key */);
257
+ if (!pik_status.ok()) {
258
+ status_ = pik_status;
259
+ return Slice(status_.getState());
260
+ }
261
+ return parsed_key.user_key;
262
+ }
263
+
264
+ Slice value() const override { return iter_->value(); }
265
+ Status status() const override {
266
+ return status_.ok() ? iter_->status() : status_;
267
+ }
268
+
269
+ private:
270
+ mutable Status status_;
271
+ InternalIterator* iter_;
272
+ bool arena_mode_;
273
+
274
+ // No copying allowed
275
+ KeyConvertingIterator(const KeyConvertingIterator&);
276
+ void operator=(const KeyConvertingIterator&);
277
+ };
278
+
279
+ // `BlockConstructor` APIs always accept/return user keys.
280
+ class BlockConstructor : public Constructor {
281
+ public:
282
+ explicit BlockConstructor(const Comparator* cmp)
283
+ : Constructor(cmp), comparator_(cmp), block_(nullptr) {}
284
+ ~BlockConstructor() override { delete block_; }
285
+ Status FinishImpl(const Options& /*options*/,
286
+ const ImmutableCFOptions& /*ioptions*/,
287
+ const MutableCFOptions& /*moptions*/,
288
+ const BlockBasedTableOptions& table_options,
289
+ const InternalKeyComparator& /*internal_comparator*/,
290
+ const stl_wrappers::KVMap& kv_map) override {
291
+ delete block_;
292
+ block_ = nullptr;
293
+ BlockBuilder builder(table_options.block_restart_interval);
294
+
295
+ for (const auto& kv : kv_map) {
296
+ // `DataBlockIter` assumes it reads only internal keys. `BlockConstructor`
297
+ // clients provide user keys, so we need to convert to internal key format
298
+ // before writing the data block.
299
+ ParsedInternalKey ikey(kv.first, kMaxSequenceNumber, kTypeValue);
300
+ std::string encoded;
301
+ AppendInternalKey(&encoded, ikey);
302
+ builder.Add(encoded, kv.second);
303
+ }
304
+ // Open the block
305
+ data_ = builder.Finish().ToString();
306
+ BlockContents contents;
307
+ contents.data = data_;
308
+ block_ = new Block(std::move(contents));
309
+ return Status::OK();
310
+ }
311
+ InternalIterator* NewIterator(
312
+ const SliceTransform* /*prefix_extractor*/) const override {
313
+ // `DataBlockIter` returns the internal keys it reads.
314
+ // `KeyConvertingIterator` converts them to user keys before they are
315
+ // exposed to the `BlockConstructor` clients.
316
+ return new KeyConvertingIterator(
317
+ block_->NewDataIterator(comparator_, kDisableGlobalSequenceNumber));
318
+ }
319
+
320
+ private:
321
+ const Comparator* comparator_;
322
+ std::string data_;
323
+ Block* block_;
324
+
325
+ BlockConstructor();
326
+ };
327
+
328
+ class TableConstructor : public Constructor {
329
+ public:
330
+ explicit TableConstructor(const Comparator* cmp,
331
+ bool convert_to_internal_key = false,
332
+ int level = -1, SequenceNumber largest_seqno = 0)
333
+ : Constructor(cmp),
334
+ largest_seqno_(largest_seqno),
335
+ convert_to_internal_key_(convert_to_internal_key),
336
+ level_(level) {
337
+ env_ = ROCKSDB_NAMESPACE::Env::Default();
338
+ }
339
+ ~TableConstructor() override { Reset(); }
340
+
341
+ Status FinishImpl(const Options& options, const ImmutableCFOptions& ioptions,
342
+ const MutableCFOptions& moptions,
343
+ const BlockBasedTableOptions& /*table_options*/,
344
+ const InternalKeyComparator& internal_comparator,
345
+ const stl_wrappers::KVMap& kv_map) override {
346
+ Reset();
347
+ soptions.use_mmap_reads = ioptions.allow_mmap_reads;
348
+ std::unique_ptr<FSWritableFile> sink(new test::StringSink());
349
+ file_writer_.reset(new WritableFileWriter(
350
+ std::move(sink), "" /* don't care */, FileOptions()));
351
+ std::unique_ptr<TableBuilder> builder;
352
+ std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
353
+ int_tbl_prop_collector_factories;
354
+
355
+ if (largest_seqno_ != 0) {
356
+ // Pretend that it's an external file written by SstFileWriter.
357
+ int_tbl_prop_collector_factories.emplace_back(
358
+ new SstFileWriterPropertiesCollectorFactory(2 /* version */,
359
+ 0 /* global_seqno*/));
360
+ }
361
+
362
+ std::string column_family_name;
363
+ builder.reset(ioptions.table_factory->NewTableBuilder(
364
+ TableBuilderOptions(ioptions, moptions, internal_comparator,
365
+ &int_tbl_prop_collector_factories,
366
+ options.compression, options.sample_for_compression,
367
+ options.compression_opts, false /* skip_filters */,
368
+ column_family_name, level_),
369
+ TablePropertiesCollectorFactory::Context::kUnknownColumnFamily,
370
+ file_writer_.get()));
371
+
372
+ for (const auto& kv : kv_map) {
373
+ if (convert_to_internal_key_) {
374
+ ParsedInternalKey ikey(kv.first, kMaxSequenceNumber, kTypeValue);
375
+ std::string encoded;
376
+ AppendInternalKey(&encoded, ikey);
377
+ builder->Add(encoded, kv.second);
378
+ } else {
379
+ builder->Add(kv.first, kv.second);
380
+ }
381
+ EXPECT_OK(builder->status());
382
+ }
383
+ Status s = builder->Finish();
384
+ EXPECT_OK(file_writer_->Flush());
385
+ EXPECT_TRUE(s.ok()) << s.ToString();
386
+
387
+ EXPECT_EQ(TEST_GetSink()->contents().size(), builder->FileSize());
388
+
389
+ // Open the table
390
+ uniq_id_ = cur_uniq_id_++;
391
+ std::unique_ptr<FSRandomAccessFile> source(new test::StringSource(
392
+ TEST_GetSink()->contents(), uniq_id_, ioptions.allow_mmap_reads));
393
+
394
+ file_reader_.reset(new RandomAccessFileReader(std::move(source), "test"));
395
+ const bool kSkipFilters = true;
396
+ const bool kImmortal = true;
397
+ return ioptions.table_factory->NewTableReader(
398
+ TableReaderOptions(ioptions, moptions.prefix_extractor.get(), soptions,
399
+ internal_comparator, !kSkipFilters, !kImmortal,
400
+ false, level_, largest_seqno_, &block_cache_tracer_,
401
+ moptions.write_buffer_size),
402
+ std::move(file_reader_), TEST_GetSink()->contents().size(),
403
+ &table_reader_);
404
+ }
405
+
406
+ InternalIterator* NewIterator(
407
+ const SliceTransform* prefix_extractor) const override {
408
+ InternalIterator* iter = table_reader_->NewIterator(
409
+ read_options_, prefix_extractor, /*arena=*/nullptr,
410
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized);
411
+ if (convert_to_internal_key_) {
412
+ return new KeyConvertingIterator(iter);
413
+ } else {
414
+ return iter;
415
+ }
416
+ }
417
+
418
+ uint64_t ApproximateOffsetOf(const Slice& key) const {
419
+ if (convert_to_internal_key_) {
420
+ InternalKey ikey(key, kMaxSequenceNumber, kTypeValue);
421
+ const Slice skey = ikey.Encode();
422
+ return table_reader_->ApproximateOffsetOf(
423
+ skey, TableReaderCaller::kUncategorized);
424
+ }
425
+ return table_reader_->ApproximateOffsetOf(
426
+ key, TableReaderCaller::kUncategorized);
427
+ }
428
+
429
+ virtual Status Reopen(const ImmutableCFOptions& ioptions,
430
+ const MutableCFOptions& moptions) {
431
+ std::unique_ptr<FSRandomAccessFile> source(new test::StringSource(
432
+ TEST_GetSink()->contents(), uniq_id_, ioptions.allow_mmap_reads));
433
+
434
+ file_reader_.reset(new RandomAccessFileReader(std::move(source), "test"));
435
+ return ioptions.table_factory->NewTableReader(
436
+ TableReaderOptions(ioptions, moptions.prefix_extractor.get(), soptions,
437
+ *last_internal_key_),
438
+ std::move(file_reader_), TEST_GetSink()->contents().size(),
439
+ &table_reader_);
440
+ }
441
+
442
+ virtual TableReader* GetTableReader() { return table_reader_.get(); }
443
+
444
+ bool AnywayDeleteIterator() const override {
445
+ return convert_to_internal_key_;
446
+ }
447
+
448
+ void ResetTableReader() { table_reader_.reset(); }
449
+
450
+ bool ConvertToInternalKey() { return convert_to_internal_key_; }
451
+
452
+ test::StringSink* TEST_GetSink() {
453
+ return static_cast<test::StringSink*>(file_writer_->writable_file());
454
+ }
455
+
456
+ BlockCacheTracer block_cache_tracer_;
457
+
458
+ private:
459
+ void Reset() {
460
+ uniq_id_ = 0;
461
+ table_reader_.reset();
462
+ file_writer_.reset();
463
+ file_reader_.reset();
464
+ }
465
+
466
+ const ReadOptions read_options_;
467
+ uint64_t uniq_id_;
468
+ std::unique_ptr<WritableFileWriter> file_writer_;
469
+ std::unique_ptr<RandomAccessFileReader> file_reader_;
470
+ std::unique_ptr<TableReader> table_reader_;
471
+ SequenceNumber largest_seqno_;
472
+ bool convert_to_internal_key_;
473
+ int level_;
474
+
475
+ TableConstructor();
476
+
477
+ static uint64_t cur_uniq_id_;
478
+ EnvOptions soptions;
479
+ Env* env_;
480
+ };
481
+ uint64_t TableConstructor::cur_uniq_id_ = 1;
482
+
483
+ class MemTableConstructor: public Constructor {
484
+ public:
485
+ explicit MemTableConstructor(const Comparator* cmp, WriteBufferManager* wb)
486
+ : Constructor(cmp),
487
+ internal_comparator_(cmp),
488
+ write_buffer_manager_(wb),
489
+ table_factory_(new SkipListFactory) {
490
+ options_.memtable_factory = table_factory_;
491
+ ImmutableCFOptions ioptions(options_);
492
+ memtable_ =
493
+ new MemTable(internal_comparator_, ioptions, MutableCFOptions(options_),
494
+ wb, kMaxSequenceNumber, 0 /* column_family_id */);
495
+ memtable_->Ref();
496
+ }
497
+ ~MemTableConstructor() override { delete memtable_->Unref(); }
498
+ Status FinishImpl(const Options&, const ImmutableCFOptions& ioptions,
499
+ const MutableCFOptions& /*moptions*/,
500
+ const BlockBasedTableOptions& /*table_options*/,
501
+ const InternalKeyComparator& /*internal_comparator*/,
502
+ const stl_wrappers::KVMap& kv_map) override {
503
+ delete memtable_->Unref();
504
+ ImmutableCFOptions mem_ioptions(ioptions);
505
+ memtable_ = new MemTable(internal_comparator_, mem_ioptions,
506
+ MutableCFOptions(options_), write_buffer_manager_,
507
+ kMaxSequenceNumber, 0 /* column_family_id */);
508
+ memtable_->Ref();
509
+ int seq = 1;
510
+ for (const auto& kv : kv_map) {
511
+ Status s = memtable_->Add(seq, kTypeValue, kv.first, kv.second);
512
+ if (!s.ok()) {
513
+ return s;
514
+ }
515
+ seq++;
516
+ }
517
+ return Status::OK();
518
+ }
519
+ InternalIterator* NewIterator(
520
+ const SliceTransform* /*prefix_extractor*/) const override {
521
+ return new KeyConvertingIterator(
522
+ memtable_->NewIterator(ReadOptions(), &arena_), true);
523
+ }
524
+
525
+ bool AnywayDeleteIterator() const override { return true; }
526
+
527
+ bool IsArenaMode() const override { return true; }
528
+
529
+ private:
530
+ mutable Arena arena_;
531
+ InternalKeyComparator internal_comparator_;
532
+ Options options_;
533
+ WriteBufferManager* write_buffer_manager_;
534
+ MemTable* memtable_;
535
+ std::shared_ptr<SkipListFactory> table_factory_;
536
+ };
537
+
538
+ class InternalIteratorFromIterator : public InternalIterator {
539
+ public:
540
+ explicit InternalIteratorFromIterator(Iterator* it) : it_(it) {}
541
+ bool Valid() const override { return it_->Valid(); }
542
+ void Seek(const Slice& target) override { it_->Seek(target); }
543
+ void SeekForPrev(const Slice& target) override { it_->SeekForPrev(target); }
544
+ void SeekToFirst() override { it_->SeekToFirst(); }
545
+ void SeekToLast() override { it_->SeekToLast(); }
546
+ void Next() override { it_->Next(); }
547
+ void Prev() override { it_->Prev(); }
548
+ Slice key() const override { return it_->key(); }
549
+ Slice value() const override { return it_->value(); }
550
+ Status status() const override { return it_->status(); }
551
+
552
+ private:
553
+ std::unique_ptr<Iterator> it_;
554
+ };
555
+
556
+ class DBConstructor: public Constructor {
557
+ public:
558
+ explicit DBConstructor(const Comparator* cmp)
559
+ : Constructor(cmp),
560
+ comparator_(cmp) {
561
+ db_ = nullptr;
562
+ NewDB();
563
+ }
564
+ ~DBConstructor() override { delete db_; }
565
+ Status FinishImpl(const Options& /*options*/,
566
+ const ImmutableCFOptions& /*ioptions*/,
567
+ const MutableCFOptions& /*moptions*/,
568
+ const BlockBasedTableOptions& /*table_options*/,
569
+ const InternalKeyComparator& /*internal_comparator*/,
570
+ const stl_wrappers::KVMap& kv_map) override {
571
+ delete db_;
572
+ db_ = nullptr;
573
+ NewDB();
574
+ for (const auto& kv : kv_map) {
575
+ WriteBatch batch;
576
+ EXPECT_OK(batch.Put(kv.first, kv.second));
577
+ EXPECT_TRUE(db_->Write(WriteOptions(), &batch).ok());
578
+ }
579
+ return Status::OK();
580
+ }
581
+
582
+ InternalIterator* NewIterator(
583
+ const SliceTransform* /*prefix_extractor*/) const override {
584
+ return new InternalIteratorFromIterator(db_->NewIterator(ReadOptions()));
585
+ }
586
+
587
+ DB* db() const override { return db_; }
588
+
589
+ private:
590
+ void NewDB() {
591
+ std::string name = test::PerThreadDBPath("table_testdb");
592
+
593
+ Options options;
594
+ options.comparator = comparator_;
595
+ Status status = DestroyDB(name, options);
596
+ ASSERT_TRUE(status.ok()) << status.ToString();
597
+
598
+ options.create_if_missing = true;
599
+ options.error_if_exists = true;
600
+ options.write_buffer_size = 10000; // Something small to force merging
601
+ status = DB::Open(options, name, &db_);
602
+ ASSERT_TRUE(status.ok()) << status.ToString();
603
+ }
604
+
605
+ const Comparator* comparator_;
606
+ DB* db_;
607
+ };
608
+
609
+ enum TestType {
610
+ BLOCK_BASED_TABLE_TEST,
611
+ #ifndef ROCKSDB_LITE
612
+ PLAIN_TABLE_SEMI_FIXED_PREFIX,
613
+ PLAIN_TABLE_FULL_STR_PREFIX,
614
+ PLAIN_TABLE_TOTAL_ORDER,
615
+ #endif // !ROCKSDB_LITE
616
+ BLOCK_TEST,
617
+ MEMTABLE_TEST,
618
+ DB_TEST
619
+ };
620
+
621
+ struct TestArgs {
622
+ TestType type;
623
+ bool reverse_compare;
624
+ int restart_interval;
625
+ CompressionType compression;
626
+ uint32_t compression_parallel_threads;
627
+ uint32_t format_version;
628
+ bool use_mmap;
629
+ };
630
+
631
+ std::ostream& operator<<(std::ostream& os, const TestArgs& args) {
632
+ os << "type: " << args.type << " reverse_compare: " << args.reverse_compare
633
+ << " restart_interval: " << args.restart_interval
634
+ << " compression: " << args.compression
635
+ << " compression_parallel_threads: " << args.compression_parallel_threads
636
+ << " format_version: " << args.format_version
637
+ << " use_mmap: " << args.use_mmap;
638
+
639
+ return os;
640
+ }
641
+
642
+ static std::vector<TestArgs> GenerateArgList() {
643
+ std::vector<TestArgs> test_args;
644
+ std::vector<TestType> test_types = {
645
+ BLOCK_BASED_TABLE_TEST,
646
+ #ifndef ROCKSDB_LITE
647
+ PLAIN_TABLE_SEMI_FIXED_PREFIX,
648
+ PLAIN_TABLE_FULL_STR_PREFIX,
649
+ PLAIN_TABLE_TOTAL_ORDER,
650
+ #endif // !ROCKSDB_LITE
651
+ BLOCK_TEST,
652
+ MEMTABLE_TEST, DB_TEST};
653
+ std::vector<bool> reverse_compare_types = {false, true};
654
+ std::vector<int> restart_intervals = {16, 1, 1024};
655
+ std::vector<uint32_t> compression_parallel_threads = {1, 4};
656
+
657
+ // Only add compression if it is supported
658
+ std::vector<std::pair<CompressionType, bool>> compression_types;
659
+ compression_types.emplace_back(kNoCompression, false);
660
+ if (Snappy_Supported()) {
661
+ compression_types.emplace_back(kSnappyCompression, false);
662
+ }
663
+ if (Zlib_Supported()) {
664
+ compression_types.emplace_back(kZlibCompression, false);
665
+ compression_types.emplace_back(kZlibCompression, true);
666
+ }
667
+ if (BZip2_Supported()) {
668
+ compression_types.emplace_back(kBZip2Compression, false);
669
+ compression_types.emplace_back(kBZip2Compression, true);
670
+ }
671
+ if (LZ4_Supported()) {
672
+ compression_types.emplace_back(kLZ4Compression, false);
673
+ compression_types.emplace_back(kLZ4Compression, true);
674
+ compression_types.emplace_back(kLZ4HCCompression, false);
675
+ compression_types.emplace_back(kLZ4HCCompression, true);
676
+ }
677
+ if (XPRESS_Supported()) {
678
+ compression_types.emplace_back(kXpressCompression, false);
679
+ compression_types.emplace_back(kXpressCompression, true);
680
+ }
681
+ if (ZSTD_Supported()) {
682
+ compression_types.emplace_back(kZSTD, false);
683
+ compression_types.emplace_back(kZSTD, true);
684
+ }
685
+
686
+ for (auto test_type : test_types) {
687
+ for (auto reverse_compare : reverse_compare_types) {
688
+ #ifndef ROCKSDB_LITE
689
+ if (test_type == PLAIN_TABLE_SEMI_FIXED_PREFIX ||
690
+ test_type == PLAIN_TABLE_FULL_STR_PREFIX ||
691
+ test_type == PLAIN_TABLE_TOTAL_ORDER) {
692
+ // Plain table doesn't use restart index or compression.
693
+ TestArgs one_arg;
694
+ one_arg.type = test_type;
695
+ one_arg.reverse_compare = reverse_compare;
696
+ one_arg.restart_interval = restart_intervals[0];
697
+ one_arg.compression = compression_types[0].first;
698
+ one_arg.compression_parallel_threads = 1;
699
+ one_arg.format_version = 0;
700
+ one_arg.use_mmap = true;
701
+ test_args.push_back(one_arg);
702
+ one_arg.use_mmap = false;
703
+ test_args.push_back(one_arg);
704
+ continue;
705
+ }
706
+ #endif // !ROCKSDB_LITE
707
+
708
+ for (auto restart_interval : restart_intervals) {
709
+ for (auto compression_type : compression_types) {
710
+ for (auto num_threads : compression_parallel_threads) {
711
+ TestArgs one_arg;
712
+ one_arg.type = test_type;
713
+ one_arg.reverse_compare = reverse_compare;
714
+ one_arg.restart_interval = restart_interval;
715
+ one_arg.compression = compression_type.first;
716
+ one_arg.compression_parallel_threads = num_threads;
717
+ one_arg.format_version = compression_type.second ? 2 : 1;
718
+ one_arg.use_mmap = false;
719
+ test_args.push_back(one_arg);
720
+ }
721
+ }
722
+ }
723
+ }
724
+ }
725
+ return test_args;
726
+ }
727
+
728
+ // In order to make all tests run for plain table format, including
729
+ // those operating on empty keys, create a new prefix transformer which
730
+ // return fixed prefix if the slice is not shorter than the prefix length,
731
+ // and the full slice if it is shorter.
732
+ class FixedOrLessPrefixTransform : public SliceTransform {
733
+ private:
734
+ const size_t prefix_len_;
735
+
736
+ public:
737
+ explicit FixedOrLessPrefixTransform(size_t prefix_len) :
738
+ prefix_len_(prefix_len) {
739
+ }
740
+
741
+ const char* Name() const override { return "rocksdb.FixedPrefix"; }
742
+
743
+ Slice Transform(const Slice& src) const override {
744
+ assert(InDomain(src));
745
+ if (src.size() < prefix_len_) {
746
+ return src;
747
+ }
748
+ return Slice(src.data(), prefix_len_);
749
+ }
750
+
751
+ bool InDomain(const Slice& /*src*/) const override { return true; }
752
+
753
+ bool InRange(const Slice& dst) const override {
754
+ return (dst.size() <= prefix_len_);
755
+ }
756
+ bool FullLengthEnabled(size_t* /*len*/) const override { return false; }
757
+ };
758
+
759
+ class HarnessTest : public testing::Test {
760
+ public:
761
+ explicit HarnessTest(const TestArgs& args)
762
+ : args_(args),
763
+ ioptions_(options_),
764
+ moptions_(options_),
765
+ write_buffer_(options_.db_write_buffer_size),
766
+ support_prev_(true),
767
+ only_support_prefix_seek_(false) {
768
+ options_.compression = args_.compression;
769
+ options_.compression_opts.parallel_threads =
770
+ args_.compression_parallel_threads;
771
+ // Use shorter block size for tests to exercise block boundary
772
+ // conditions more.
773
+ if (args_.reverse_compare) {
774
+ options_.comparator = &reverse_key_comparator;
775
+ }
776
+
777
+ internal_comparator_.reset(
778
+ new test::PlainInternalKeyComparator(options_.comparator));
779
+
780
+ options_.allow_mmap_reads = args_.use_mmap;
781
+ switch (args_.type) {
782
+ case BLOCK_BASED_TABLE_TEST:
783
+ table_options_.flush_block_policy_factory.reset(
784
+ new FlushBlockBySizePolicyFactory());
785
+ table_options_.block_size = 256;
786
+ table_options_.block_restart_interval = args_.restart_interval;
787
+ table_options_.index_block_restart_interval = args_.restart_interval;
788
+ table_options_.format_version = args_.format_version;
789
+ options_.table_factory.reset(
790
+ new BlockBasedTableFactory(table_options_));
791
+ constructor_.reset(new TableConstructor(
792
+ options_.comparator, true /* convert_to_internal_key_ */));
793
+ internal_comparator_.reset(
794
+ new InternalKeyComparator(options_.comparator));
795
+ break;
796
+ // Plain table is not supported in ROCKSDB_LITE
797
+ #ifndef ROCKSDB_LITE
798
+ case PLAIN_TABLE_SEMI_FIXED_PREFIX:
799
+ support_prev_ = false;
800
+ only_support_prefix_seek_ = true;
801
+ options_.prefix_extractor.reset(new FixedOrLessPrefixTransform(2));
802
+ options_.table_factory.reset(NewPlainTableFactory());
803
+ constructor_.reset(new TableConstructor(
804
+ options_.comparator, true /* convert_to_internal_key_ */));
805
+ internal_comparator_.reset(
806
+ new InternalKeyComparator(options_.comparator));
807
+ break;
808
+ case PLAIN_TABLE_FULL_STR_PREFIX:
809
+ support_prev_ = false;
810
+ only_support_prefix_seek_ = true;
811
+ options_.prefix_extractor.reset(NewNoopTransform());
812
+ options_.table_factory.reset(NewPlainTableFactory());
813
+ constructor_.reset(new TableConstructor(
814
+ options_.comparator, true /* convert_to_internal_key_ */));
815
+ internal_comparator_.reset(
816
+ new InternalKeyComparator(options_.comparator));
817
+ break;
818
+ case PLAIN_TABLE_TOTAL_ORDER:
819
+ support_prev_ = false;
820
+ only_support_prefix_seek_ = false;
821
+ options_.prefix_extractor = nullptr;
822
+
823
+ {
824
+ PlainTableOptions plain_table_options;
825
+ plain_table_options.user_key_len = kPlainTableVariableLength;
826
+ plain_table_options.bloom_bits_per_key = 0;
827
+ plain_table_options.hash_table_ratio = 0;
828
+
829
+ options_.table_factory.reset(
830
+ NewPlainTableFactory(plain_table_options));
831
+ }
832
+ constructor_.reset(new TableConstructor(
833
+ options_.comparator, true /* convert_to_internal_key_ */));
834
+ internal_comparator_.reset(
835
+ new InternalKeyComparator(options_.comparator));
836
+ break;
837
+ #endif // !ROCKSDB_LITE
838
+ case BLOCK_TEST:
839
+ table_options_.block_size = 256;
840
+ options_.table_factory.reset(
841
+ new BlockBasedTableFactory(table_options_));
842
+ constructor_.reset(new BlockConstructor(options_.comparator));
843
+ break;
844
+ case MEMTABLE_TEST:
845
+ table_options_.block_size = 256;
846
+ options_.table_factory.reset(
847
+ new BlockBasedTableFactory(table_options_));
848
+ constructor_.reset(
849
+ new MemTableConstructor(options_.comparator, &write_buffer_));
850
+ break;
851
+ case DB_TEST:
852
+ table_options_.block_size = 256;
853
+ options_.table_factory.reset(
854
+ new BlockBasedTableFactory(table_options_));
855
+ constructor_.reset(new DBConstructor(options_.comparator));
856
+ break;
857
+ }
858
+ ioptions_ = ImmutableCFOptions(options_);
859
+ moptions_ = MutableCFOptions(options_);
860
+ }
861
+
862
+ void Add(const std::string& key, const std::string& value) {
863
+ constructor_->Add(key, value);
864
+ }
865
+
866
+ void Test(Random* rnd) {
867
+ std::vector<std::string> keys;
868
+ stl_wrappers::KVMap data;
869
+ constructor_->Finish(options_, ioptions_, moptions_, table_options_,
870
+ *internal_comparator_, &keys, &data);
871
+
872
+ TestForwardScan(keys, data);
873
+ if (support_prev_) {
874
+ TestBackwardScan(keys, data);
875
+ }
876
+ TestRandomAccess(rnd, keys, data);
877
+ }
878
+
879
+ void TestForwardScan(const std::vector<std::string>& /*keys*/,
880
+ const stl_wrappers::KVMap& data) {
881
+ InternalIterator* iter = constructor_->NewIterator();
882
+ ASSERT_TRUE(!iter->Valid());
883
+ iter->SeekToFirst();
884
+ ASSERT_OK(iter->status());
885
+ for (stl_wrappers::KVMap::const_iterator model_iter = data.begin();
886
+ model_iter != data.end(); ++model_iter) {
887
+ ASSERT_EQ(ToString(data, model_iter), ToString(iter));
888
+ iter->Next();
889
+ ASSERT_OK(iter->status());
890
+ }
891
+ ASSERT_TRUE(!iter->Valid());
892
+ ASSERT_OK(iter->status());
893
+ if (constructor_->IsArenaMode() && !constructor_->AnywayDeleteIterator()) {
894
+ iter->~InternalIterator();
895
+ } else {
896
+ delete iter;
897
+ }
898
+ }
899
+
900
+ void TestBackwardScan(const std::vector<std::string>& /*keys*/,
901
+ const stl_wrappers::KVMap& data) {
902
+ InternalIterator* iter = constructor_->NewIterator();
903
+ ASSERT_TRUE(!iter->Valid());
904
+ iter->SeekToLast();
905
+ ASSERT_OK(iter->status());
906
+ for (stl_wrappers::KVMap::const_reverse_iterator model_iter = data.rbegin();
907
+ model_iter != data.rend(); ++model_iter) {
908
+ ASSERT_EQ(ToString(data, model_iter), ToString(iter));
909
+ iter->Prev();
910
+ ASSERT_OK(iter->status());
911
+ }
912
+ ASSERT_TRUE(!iter->Valid());
913
+ ASSERT_OK(iter->status());
914
+ if (constructor_->IsArenaMode() && !constructor_->AnywayDeleteIterator()) {
915
+ iter->~InternalIterator();
916
+ } else {
917
+ delete iter;
918
+ }
919
+ }
920
+
921
+ void TestRandomAccess(Random* rnd, const std::vector<std::string>& keys,
922
+ const stl_wrappers::KVMap& data) {
923
+ static const bool kVerbose = false;
924
+ InternalIterator* iter = constructor_->NewIterator();
925
+ ASSERT_TRUE(!iter->Valid());
926
+ stl_wrappers::KVMap::const_iterator model_iter = data.begin();
927
+ if (kVerbose) fprintf(stderr, "---\n");
928
+ for (int i = 0; i < 200; i++) {
929
+ const int toss = rnd->Uniform(support_prev_ ? 5 : 3);
930
+ switch (toss) {
931
+ case 0: {
932
+ if (iter->Valid()) {
933
+ if (kVerbose) fprintf(stderr, "Next\n");
934
+ iter->Next();
935
+ ASSERT_OK(iter->status());
936
+ ++model_iter;
937
+ ASSERT_EQ(ToString(data, model_iter), ToString(iter));
938
+ }
939
+ break;
940
+ }
941
+
942
+ case 1: {
943
+ if (kVerbose) fprintf(stderr, "SeekToFirst\n");
944
+ iter->SeekToFirst();
945
+ ASSERT_OK(iter->status());
946
+ model_iter = data.begin();
947
+ ASSERT_EQ(ToString(data, model_iter), ToString(iter));
948
+ break;
949
+ }
950
+
951
+ case 2: {
952
+ std::string key = PickRandomKey(rnd, keys);
953
+ model_iter = data.lower_bound(key);
954
+ if (kVerbose) fprintf(stderr, "Seek '%s'\n",
955
+ EscapeString(key).c_str());
956
+ iter->Seek(Slice(key));
957
+ ASSERT_OK(iter->status());
958
+ ASSERT_EQ(ToString(data, model_iter), ToString(iter));
959
+ break;
960
+ }
961
+
962
+ case 3: {
963
+ if (iter->Valid()) {
964
+ if (kVerbose) fprintf(stderr, "Prev\n");
965
+ iter->Prev();
966
+ ASSERT_OK(iter->status());
967
+ if (model_iter == data.begin()) {
968
+ model_iter = data.end(); // Wrap around to invalid value
969
+ } else {
970
+ --model_iter;
971
+ }
972
+ ASSERT_EQ(ToString(data, model_iter), ToString(iter));
973
+ }
974
+ break;
975
+ }
976
+
977
+ case 4: {
978
+ if (kVerbose) fprintf(stderr, "SeekToLast\n");
979
+ iter->SeekToLast();
980
+ ASSERT_OK(iter->status());
981
+ if (keys.empty()) {
982
+ model_iter = data.end();
983
+ } else {
984
+ std::string last = data.rbegin()->first;
985
+ model_iter = data.lower_bound(last);
986
+ }
987
+ ASSERT_EQ(ToString(data, model_iter), ToString(iter));
988
+ break;
989
+ }
990
+ }
991
+ }
992
+ if (constructor_->IsArenaMode() && !constructor_->AnywayDeleteIterator()) {
993
+ iter->~InternalIterator();
994
+ } else {
995
+ delete iter;
996
+ }
997
+ }
998
+
999
+ std::string ToString(const stl_wrappers::KVMap& data,
1000
+ const stl_wrappers::KVMap::const_iterator& it) {
1001
+ if (it == data.end()) {
1002
+ return "END";
1003
+ } else {
1004
+ return "'" + it->first + "->" + it->second + "'";
1005
+ }
1006
+ }
1007
+
1008
+ std::string ToString(const stl_wrappers::KVMap& data,
1009
+ const stl_wrappers::KVMap::const_reverse_iterator& it) {
1010
+ if (it == data.rend()) {
1011
+ return "END";
1012
+ } else {
1013
+ return "'" + it->first + "->" + it->second + "'";
1014
+ }
1015
+ }
1016
+
1017
+ std::string ToString(const InternalIterator* it) {
1018
+ if (!it->Valid()) {
1019
+ return "END";
1020
+ } else {
1021
+ return "'" + it->key().ToString() + "->" + it->value().ToString() + "'";
1022
+ }
1023
+ }
1024
+
1025
+ std::string PickRandomKey(Random* rnd, const std::vector<std::string>& keys) {
1026
+ if (keys.empty()) {
1027
+ return "foo";
1028
+ } else {
1029
+ const int index = rnd->Uniform(static_cast<int>(keys.size()));
1030
+ std::string result = keys[index];
1031
+ switch (rnd->Uniform(support_prev_ ? 3 : 1)) {
1032
+ case 0:
1033
+ // Return an existing key
1034
+ break;
1035
+ case 1: {
1036
+ // Attempt to return something smaller than an existing key
1037
+ if (result.size() > 0 && result[result.size() - 1] > '\0'
1038
+ && (!only_support_prefix_seek_
1039
+ || options_.prefix_extractor->Transform(result).size()
1040
+ < result.size())) {
1041
+ result[result.size() - 1]--;
1042
+ }
1043
+ break;
1044
+ }
1045
+ case 2: {
1046
+ // Return something larger than an existing key
1047
+ Increment(options_.comparator, &result);
1048
+ break;
1049
+ }
1050
+ }
1051
+ return result;
1052
+ }
1053
+ }
1054
+
1055
+ // Returns nullptr if not running against a DB
1056
+ DB* db() const { return constructor_->db(); }
1057
+
1058
+ private:
1059
+ TestArgs args_;
1060
+ Options options_;
1061
+ ImmutableCFOptions ioptions_;
1062
+ MutableCFOptions moptions_;
1063
+ BlockBasedTableOptions table_options_;
1064
+ std::unique_ptr<Constructor> constructor_;
1065
+ WriteBufferManager write_buffer_;
1066
+ bool support_prev_;
1067
+ bool only_support_prefix_seek_;
1068
+ std::shared_ptr<InternalKeyComparator> internal_comparator_;
1069
+ };
1070
+
1071
+ class ParameterizedHarnessTest : public HarnessTest,
1072
+ public testing::WithParamInterface<TestArgs> {
1073
+ public:
1074
+ ParameterizedHarnessTest() : HarnessTest(GetParam()) {}
1075
+ };
1076
+
1077
+ INSTANTIATE_TEST_CASE_P(TableTest, ParameterizedHarnessTest,
1078
+ ::testing::ValuesIn(GenerateArgList()));
1079
+
1080
+ class DBHarnessTest : public HarnessTest {
1081
+ public:
1082
+ DBHarnessTest()
1083
+ : HarnessTest(TestArgs{DB_TEST, /* reverse_compare */ false,
1084
+ /* restart_interval */ 16, kNoCompression,
1085
+ /* compression_parallel_threads */ 1,
1086
+ /* format_version */ 0, /* use_mmap */ false}) {}
1087
+ };
1088
+
1089
+ static bool Between(uint64_t val, uint64_t low, uint64_t high) {
1090
+ bool result = (val >= low) && (val <= high);
1091
+ if (!result) {
1092
+ fprintf(stderr, "Value %llu is not in range [%llu, %llu]\n",
1093
+ (unsigned long long)(val),
1094
+ (unsigned long long)(low),
1095
+ (unsigned long long)(high));
1096
+ }
1097
+ return result;
1098
+ }
1099
+
1100
+ // Tests against all kinds of tables
1101
+ class TableTest : public testing::Test {
1102
+ public:
1103
+ const InternalKeyComparator& GetPlainInternalComparator(
1104
+ const Comparator* comp) {
1105
+ if (!plain_internal_comparator) {
1106
+ plain_internal_comparator.reset(
1107
+ new test::PlainInternalKeyComparator(comp));
1108
+ }
1109
+ return *plain_internal_comparator;
1110
+ }
1111
+ void IndexTest(BlockBasedTableOptions table_options);
1112
+
1113
+ private:
1114
+ std::unique_ptr<InternalKeyComparator> plain_internal_comparator;
1115
+ };
1116
+
1117
+ class GeneralTableTest : public TableTest {};
1118
+ class BlockBasedTableTest
1119
+ : public TableTest,
1120
+ virtual public ::testing::WithParamInterface<uint32_t> {
1121
+ public:
1122
+ BlockBasedTableTest() : format_(GetParam()) {
1123
+ env_ = ROCKSDB_NAMESPACE::Env::Default();
1124
+ }
1125
+
1126
+ BlockBasedTableOptions GetBlockBasedTableOptions() {
1127
+ BlockBasedTableOptions options;
1128
+ options.format_version = format_;
1129
+ return options;
1130
+ }
1131
+
1132
+ void SetupTracingTest(TableConstructor* c) {
1133
+ test_path_ = test::PerThreadDBPath("block_based_table_tracing_test");
1134
+ EXPECT_OK(env_->CreateDir(test_path_));
1135
+ trace_file_path_ = test_path_ + "/block_cache_trace_file";
1136
+ TraceOptions trace_opt;
1137
+ std::unique_ptr<TraceWriter> trace_writer;
1138
+ EXPECT_OK(NewFileTraceWriter(env_, EnvOptions(), trace_file_path_,
1139
+ &trace_writer));
1140
+ // Always return Status::OK().
1141
+ assert(c->block_cache_tracer_
1142
+ .StartTrace(env_, trace_opt, std::move(trace_writer))
1143
+ .ok());
1144
+ {
1145
+ std::string user_key = "k01";
1146
+ InternalKey internal_key(user_key, 0, kTypeValue);
1147
+ std::string encoded_key = internal_key.Encode().ToString();
1148
+ c->Add(encoded_key, kDummyValue);
1149
+ }
1150
+ {
1151
+ std::string user_key = "k02";
1152
+ InternalKey internal_key(user_key, 0, kTypeValue);
1153
+ std::string encoded_key = internal_key.Encode().ToString();
1154
+ c->Add(encoded_key, kDummyValue);
1155
+ }
1156
+ }
1157
+
1158
+ void VerifyBlockAccessTrace(
1159
+ TableConstructor* c,
1160
+ const std::vector<BlockCacheTraceRecord>& expected_records) {
1161
+ c->block_cache_tracer_.EndTrace();
1162
+
1163
+ {
1164
+ std::unique_ptr<TraceReader> trace_reader;
1165
+ Status s =
1166
+ NewFileTraceReader(env_, EnvOptions(), trace_file_path_, &trace_reader);
1167
+ EXPECT_OK(s);
1168
+ BlockCacheTraceReader reader(std::move(trace_reader));
1169
+ BlockCacheTraceHeader header;
1170
+ EXPECT_OK(reader.ReadHeader(&header));
1171
+ uint32_t index = 0;
1172
+ while (s.ok()) {
1173
+ BlockCacheTraceRecord access;
1174
+ s = reader.ReadAccess(&access);
1175
+ if (!s.ok()) {
1176
+ break;
1177
+ }
1178
+ ASSERT_LT(index, expected_records.size());
1179
+ EXPECT_NE("", access.block_key);
1180
+ EXPECT_EQ(access.block_type, expected_records[index].block_type);
1181
+ EXPECT_GT(access.block_size, 0);
1182
+ EXPECT_EQ(access.caller, expected_records[index].caller);
1183
+ EXPECT_EQ(access.no_insert, expected_records[index].no_insert);
1184
+ EXPECT_EQ(access.is_cache_hit, expected_records[index].is_cache_hit);
1185
+ // Get
1186
+ if (access.caller == TableReaderCaller::kUserGet) {
1187
+ EXPECT_EQ(access.referenced_key,
1188
+ expected_records[index].referenced_key);
1189
+ EXPECT_EQ(access.get_id, expected_records[index].get_id);
1190
+ EXPECT_EQ(access.get_from_user_specified_snapshot,
1191
+ expected_records[index].get_from_user_specified_snapshot);
1192
+ if (access.block_type == TraceType::kBlockTraceDataBlock) {
1193
+ EXPECT_GT(access.referenced_data_size, 0);
1194
+ EXPECT_GT(access.num_keys_in_block, 0);
1195
+ EXPECT_EQ(access.referenced_key_exist_in_block,
1196
+ expected_records[index].referenced_key_exist_in_block);
1197
+ }
1198
+ } else {
1199
+ EXPECT_EQ(access.referenced_key, "");
1200
+ EXPECT_EQ(access.get_id, 0);
1201
+ EXPECT_TRUE(access.get_from_user_specified_snapshot == Boolean::kFalse);
1202
+ EXPECT_EQ(access.referenced_data_size, 0);
1203
+ EXPECT_EQ(access.num_keys_in_block, 0);
1204
+ EXPECT_TRUE(access.referenced_key_exist_in_block == Boolean::kFalse);
1205
+ }
1206
+ index++;
1207
+ }
1208
+ EXPECT_EQ(index, expected_records.size());
1209
+ }
1210
+ EXPECT_OK(env_->DeleteFile(trace_file_path_));
1211
+ EXPECT_OK(env_->DeleteDir(test_path_));
1212
+ }
1213
+
1214
+ protected:
1215
+ uint64_t IndexUncompressedHelper(bool indexCompress);
1216
+
1217
+ private:
1218
+ uint32_t format_;
1219
+ Env* env_;
1220
+ std::string trace_file_path_;
1221
+ std::string test_path_;
1222
+ };
1223
+ class PlainTableTest : public TableTest {};
1224
+ class TablePropertyTest : public testing::Test {};
1225
+ class BBTTailPrefetchTest : public TableTest {};
1226
+
1227
+ // The helper class to test the file checksum
1228
+ class FileChecksumTestHelper {
1229
+ public:
1230
+ FileChecksumTestHelper(bool convert_to_internal_key = false)
1231
+ : convert_to_internal_key_(convert_to_internal_key) {
1232
+ }
1233
+ ~FileChecksumTestHelper() {}
1234
+
1235
+ void CreateWriteableFile() {
1236
+ sink_ = new test::StringSink();
1237
+ std::unique_ptr<FSWritableFile> holder(sink_);
1238
+ file_writer_.reset(new WritableFileWriter(
1239
+ std::move(holder), "" /* don't care */, FileOptions()));
1240
+ }
1241
+
1242
+ void SetFileChecksumGenerator(FileChecksumGenerator* checksum_generator) {
1243
+ if (file_writer_ != nullptr) {
1244
+ file_writer_->TEST_SetFileChecksumGenerator(checksum_generator);
1245
+ } else {
1246
+ delete checksum_generator;
1247
+ }
1248
+ }
1249
+
1250
+ WritableFileWriter* GetFileWriter() { return file_writer_.get(); }
1251
+
1252
+ Status ResetTableBuilder(std::unique_ptr<TableBuilder>&& builder) {
1253
+ assert(builder != nullptr);
1254
+ table_builder_ = std::move(builder);
1255
+ return Status::OK();
1256
+ }
1257
+
1258
+ void AddKVtoKVMap(int num_entries) {
1259
+ Random rnd(test::RandomSeed());
1260
+ for (int i = 0; i < num_entries; i++) {
1261
+ std::string v = rnd.RandomString(100);
1262
+ kv_map_[test::RandomKey(&rnd, 20)] = v;
1263
+ }
1264
+ }
1265
+
1266
+ Status WriteKVAndFlushTable() {
1267
+ for (const auto& kv : kv_map_) {
1268
+ if (convert_to_internal_key_) {
1269
+ ParsedInternalKey ikey(kv.first, kMaxSequenceNumber, kTypeValue);
1270
+ std::string encoded;
1271
+ AppendInternalKey(&encoded, ikey);
1272
+ table_builder_->Add(encoded, kv.second);
1273
+ } else {
1274
+ table_builder_->Add(kv.first, kv.second);
1275
+ }
1276
+ EXPECT_TRUE(table_builder_->status().ok());
1277
+ }
1278
+ Status s = table_builder_->Finish();
1279
+ EXPECT_OK(file_writer_->Flush());
1280
+ EXPECT_OK(s);
1281
+
1282
+ EXPECT_EQ(sink_->contents().size(), table_builder_->FileSize());
1283
+ return s;
1284
+ }
1285
+
1286
+ std::string GetFileChecksum() {
1287
+ EXPECT_OK(file_writer_->Close());
1288
+ return table_builder_->GetFileChecksum();
1289
+ }
1290
+
1291
+ const char* GetFileChecksumFuncName() {
1292
+ return table_builder_->GetFileChecksumFuncName();
1293
+ }
1294
+
1295
+ Status CalculateFileChecksum(FileChecksumGenerator* file_checksum_generator,
1296
+ std::string* checksum) {
1297
+ assert(file_checksum_generator != nullptr);
1298
+ cur_uniq_id_ = checksum_uniq_id_++;
1299
+ test::StringSink* ss_rw =
1300
+ static_cast<test::StringSink*>(file_writer_->writable_file());
1301
+ std::unique_ptr<FSRandomAccessFile> source(
1302
+ new test::StringSource(ss_rw->contents()));
1303
+ file_reader_.reset(new RandomAccessFileReader(std::move(source), "test"));
1304
+
1305
+ std::unique_ptr<char[]> scratch(new char[2048]);
1306
+ Slice result;
1307
+ uint64_t offset = 0;
1308
+ Status s;
1309
+ s = file_reader_->Read(IOOptions(), offset, 2048, &result, scratch.get(),
1310
+ nullptr, false);
1311
+ if (!s.ok()) {
1312
+ return s;
1313
+ }
1314
+ while (result.size() != 0) {
1315
+ file_checksum_generator->Update(scratch.get(), result.size());
1316
+ offset += static_cast<uint64_t>(result.size());
1317
+ s = file_reader_->Read(IOOptions(), offset, 2048, &result, scratch.get(),
1318
+ nullptr, false);
1319
+ if (!s.ok()) {
1320
+ return s;
1321
+ }
1322
+ }
1323
+ EXPECT_EQ(offset, static_cast<uint64_t>(table_builder_->FileSize()));
1324
+ file_checksum_generator->Finalize();
1325
+ *checksum = file_checksum_generator->GetChecksum();
1326
+ return Status::OK();
1327
+ }
1328
+
1329
+ private:
1330
+ bool convert_to_internal_key_;
1331
+ uint64_t cur_uniq_id_;
1332
+ std::unique_ptr<WritableFileWriter> file_writer_;
1333
+ std::unique_ptr<RandomAccessFileReader> file_reader_;
1334
+ std::unique_ptr<TableBuilder> table_builder_;
1335
+ stl_wrappers::KVMap kv_map_;
1336
+ test::StringSink* sink_ = nullptr;
1337
+
1338
+ static uint64_t checksum_uniq_id_;
1339
+ };
1340
+
1341
+ uint64_t FileChecksumTestHelper::checksum_uniq_id_ = 1;
1342
+
1343
+ INSTANTIATE_TEST_CASE_P(FormatDef, BlockBasedTableTest,
1344
+ testing::Values(test::kDefaultFormatVersion));
1345
+ INSTANTIATE_TEST_CASE_P(FormatLatest, BlockBasedTableTest,
1346
+ testing::Values(test::kLatestFormatVersion));
1347
+
1348
+ // This test serves as the living tutorial for the prefix scan of user collected
1349
+ // properties.
1350
+ TEST_F(TablePropertyTest, PrefixScanTest) {
1351
+ UserCollectedProperties props{{"num.111.1", "1"},
1352
+ {"num.111.2", "2"},
1353
+ {"num.111.3", "3"},
1354
+ {"num.333.1", "1"},
1355
+ {"num.333.2", "2"},
1356
+ {"num.333.3", "3"},
1357
+ {"num.555.1", "1"},
1358
+ {"num.555.2", "2"},
1359
+ {"num.555.3", "3"}, };
1360
+
1361
+ // prefixes that exist
1362
+ for (const std::string& prefix : {"num.111", "num.333", "num.555"}) {
1363
+ int num = 0;
1364
+ for (auto pos = props.lower_bound(prefix);
1365
+ pos != props.end() &&
1366
+ pos->first.compare(0, prefix.size(), prefix) == 0;
1367
+ ++pos) {
1368
+ ++num;
1369
+ auto key = prefix + "." + ToString(num);
1370
+ ASSERT_EQ(key, pos->first);
1371
+ ASSERT_EQ(ToString(num), pos->second);
1372
+ }
1373
+ ASSERT_EQ(3, num);
1374
+ }
1375
+
1376
+ // prefixes that don't exist
1377
+ for (const std::string& prefix :
1378
+ {"num.000", "num.222", "num.444", "num.666"}) {
1379
+ auto pos = props.lower_bound(prefix);
1380
+ ASSERT_TRUE(pos == props.end() ||
1381
+ pos->first.compare(0, prefix.size(), prefix) != 0);
1382
+ }
1383
+ }
1384
+
1385
+ // This test include all the basic checks except those for index size and block
1386
+ // size, which will be conducted in separated unit tests.
1387
+ TEST_P(BlockBasedTableTest, BasicBlockBasedTableProperties) {
1388
+ TableConstructor c(BytewiseComparator(), true /* convert_to_internal_key_ */);
1389
+
1390
+ c.Add("a1", "val1");
1391
+ c.Add("b2", "val2");
1392
+ c.Add("c3", "val3");
1393
+ c.Add("d4", "val4");
1394
+ c.Add("e5", "val5");
1395
+ c.Add("f6", "val6");
1396
+ c.Add("g7", "val7");
1397
+ c.Add("h8", "val8");
1398
+ c.Add("j9", "val9");
1399
+ uint64_t diff_internal_user_bytes = 9 * 8; // 8 is seq size, 9 k-v totally
1400
+
1401
+ std::vector<std::string> keys;
1402
+ stl_wrappers::KVMap kvmap;
1403
+ Options options;
1404
+ options.compression = kNoCompression;
1405
+ options.statistics = CreateDBStatistics();
1406
+ options.statistics->set_stats_level(StatsLevel::kAll);
1407
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
1408
+ table_options.block_restart_interval = 1;
1409
+ options.table_factory.reset(NewBlockBasedTableFactory(table_options));
1410
+
1411
+ ImmutableCFOptions ioptions(options);
1412
+ MutableCFOptions moptions(options);
1413
+ ioptions.statistics = options.statistics.get();
1414
+ c.Finish(options, ioptions, moptions, table_options,
1415
+ GetPlainInternalComparator(options.comparator), &keys, &kvmap);
1416
+ ASSERT_EQ(options.statistics->getTickerCount(NUMBER_BLOCK_NOT_COMPRESSED), 0);
1417
+
1418
+ auto& props = *c.GetTableReader()->GetTableProperties();
1419
+ ASSERT_EQ(kvmap.size(), props.num_entries);
1420
+
1421
+ auto raw_key_size = kvmap.size() * 2ul;
1422
+ auto raw_value_size = kvmap.size() * 4ul;
1423
+
1424
+ ASSERT_EQ(raw_key_size + diff_internal_user_bytes, props.raw_key_size);
1425
+ ASSERT_EQ(raw_value_size, props.raw_value_size);
1426
+ ASSERT_EQ(1ul, props.num_data_blocks);
1427
+ ASSERT_EQ("", props.filter_policy_name); // no filter policy is used
1428
+
1429
+ // Verify data size.
1430
+ BlockBuilder block_builder(1);
1431
+ for (const auto& item : kvmap) {
1432
+ block_builder.Add(item.first, item.second);
1433
+ }
1434
+ Slice content = block_builder.Finish();
1435
+ ASSERT_EQ(content.size() + kBlockTrailerSize + diff_internal_user_bytes,
1436
+ props.data_size);
1437
+ c.ResetTableReader();
1438
+ }
1439
+
1440
+ #ifdef SNAPPY
1441
+ uint64_t BlockBasedTableTest::IndexUncompressedHelper(bool compressed) {
1442
+ TableConstructor c(BytewiseComparator(), true /* convert_to_internal_key_ */);
1443
+ constexpr size_t kNumKeys = 10000;
1444
+
1445
+ for (size_t k = 0; k < kNumKeys; ++k) {
1446
+ c.Add("key" + ToString(k), "val" + ToString(k));
1447
+ }
1448
+
1449
+ std::vector<std::string> keys;
1450
+ stl_wrappers::KVMap kvmap;
1451
+ Options options;
1452
+ options.compression = kSnappyCompression;
1453
+ options.statistics = CreateDBStatistics();
1454
+ options.statistics->set_stats_level(StatsLevel::kAll);
1455
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
1456
+ table_options.block_restart_interval = 1;
1457
+ table_options.enable_index_compression = compressed;
1458
+ options.table_factory.reset(NewBlockBasedTableFactory(table_options));
1459
+
1460
+ ImmutableCFOptions ioptions(options);
1461
+ MutableCFOptions moptions(options);
1462
+ ioptions.statistics = options.statistics.get();
1463
+ c.Finish(options, ioptions, moptions, table_options,
1464
+ GetPlainInternalComparator(options.comparator), &keys, &kvmap);
1465
+ c.ResetTableReader();
1466
+ return options.statistics->getTickerCount(NUMBER_BLOCK_COMPRESSED);
1467
+ }
1468
+ TEST_P(BlockBasedTableTest, IndexUncompressed) {
1469
+ uint64_t tbl1_compressed_cnt = IndexUncompressedHelper(true);
1470
+ uint64_t tbl2_compressed_cnt = IndexUncompressedHelper(false);
1471
+ // tbl1_compressed_cnt should include 1 index block
1472
+ EXPECT_EQ(tbl2_compressed_cnt + 1, tbl1_compressed_cnt);
1473
+ }
1474
+ #endif // SNAPPY
1475
+
1476
+ TEST_P(BlockBasedTableTest, BlockBasedTableProperties2) {
1477
+ TableConstructor c(&reverse_key_comparator);
1478
+ std::vector<std::string> keys;
1479
+ stl_wrappers::KVMap kvmap;
1480
+
1481
+ {
1482
+ Options options;
1483
+ options.compression = CompressionType::kNoCompression;
1484
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
1485
+ options.table_factory.reset(NewBlockBasedTableFactory(table_options));
1486
+
1487
+ const ImmutableCFOptions ioptions(options);
1488
+ const MutableCFOptions moptions(options);
1489
+ c.Finish(options, ioptions, moptions, table_options,
1490
+ GetPlainInternalComparator(options.comparator), &keys, &kvmap);
1491
+
1492
+ auto& props = *c.GetTableReader()->GetTableProperties();
1493
+
1494
+ // Default comparator
1495
+ ASSERT_EQ("leveldb.BytewiseComparator", props.comparator_name);
1496
+ // No merge operator
1497
+ ASSERT_EQ("nullptr", props.merge_operator_name);
1498
+ // No prefix extractor
1499
+ ASSERT_EQ("nullptr", props.prefix_extractor_name);
1500
+ // No property collectors
1501
+ ASSERT_EQ("[]", props.property_collectors_names);
1502
+ // No filter policy is used
1503
+ ASSERT_EQ("", props.filter_policy_name);
1504
+ // Compression type == that set:
1505
+ ASSERT_EQ("NoCompression", props.compression_name);
1506
+ c.ResetTableReader();
1507
+ }
1508
+
1509
+ {
1510
+ Options options;
1511
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
1512
+ options.table_factory.reset(NewBlockBasedTableFactory(table_options));
1513
+ options.comparator = &reverse_key_comparator;
1514
+ options.merge_operator = MergeOperators::CreateUInt64AddOperator();
1515
+ options.prefix_extractor.reset(NewNoopTransform());
1516
+ options.table_properties_collector_factories.emplace_back(
1517
+ new DummyPropertiesCollectorFactory1());
1518
+ options.table_properties_collector_factories.emplace_back(
1519
+ new DummyPropertiesCollectorFactory2());
1520
+
1521
+ const ImmutableCFOptions ioptions(options);
1522
+ const MutableCFOptions moptions(options);
1523
+ c.Finish(options, ioptions, moptions, table_options,
1524
+ GetPlainInternalComparator(options.comparator), &keys, &kvmap);
1525
+
1526
+ auto& props = *c.GetTableReader()->GetTableProperties();
1527
+
1528
+ ASSERT_EQ("rocksdb.ReverseBytewiseComparator", props.comparator_name);
1529
+ ASSERT_EQ("UInt64AddOperator", props.merge_operator_name);
1530
+ ASSERT_EQ("rocksdb.Noop", props.prefix_extractor_name);
1531
+ ASSERT_EQ(
1532
+ "[DummyPropertiesCollectorFactory1,DummyPropertiesCollectorFactory2]",
1533
+ props.property_collectors_names);
1534
+ ASSERT_EQ("", props.filter_policy_name); // no filter policy is used
1535
+ c.ResetTableReader();
1536
+ }
1537
+ }
1538
+
1539
+ TEST_P(BlockBasedTableTest, RangeDelBlock) {
1540
+ TableConstructor c(BytewiseComparator());
1541
+ std::vector<std::string> keys = {"1pika", "2chu"};
1542
+ std::vector<std::string> vals = {"p", "c"};
1543
+
1544
+ std::vector<RangeTombstone> expected_tombstones = {
1545
+ {"1pika", "2chu", 0},
1546
+ {"2chu", "c", 1},
1547
+ {"2chu", "c", 0},
1548
+ {"c", "p", 0},
1549
+ };
1550
+
1551
+ for (int i = 0; i < 2; i++) {
1552
+ RangeTombstone t(keys[i], vals[i], i);
1553
+ std::pair<InternalKey, Slice> p = t.Serialize();
1554
+ c.Add(p.first.Encode().ToString(), p.second);
1555
+ }
1556
+
1557
+ std::vector<std::string> sorted_keys;
1558
+ stl_wrappers::KVMap kvmap;
1559
+ Options options;
1560
+ options.compression = kNoCompression;
1561
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
1562
+ table_options.block_restart_interval = 1;
1563
+ options.table_factory.reset(NewBlockBasedTableFactory(table_options));
1564
+
1565
+ const ImmutableCFOptions ioptions(options);
1566
+ const MutableCFOptions moptions(options);
1567
+ std::unique_ptr<InternalKeyComparator> internal_cmp(
1568
+ new InternalKeyComparator(options.comparator));
1569
+ c.Finish(options, ioptions, moptions, table_options, *internal_cmp,
1570
+ &sorted_keys, &kvmap);
1571
+
1572
+ for (int j = 0; j < 2; ++j) {
1573
+ std::unique_ptr<InternalIterator> iter(
1574
+ c.GetTableReader()->NewRangeTombstoneIterator(ReadOptions()));
1575
+ if (j > 0) {
1576
+ // For second iteration, delete the table reader object and verify the
1577
+ // iterator can still access its metablock's range tombstones.
1578
+ c.ResetTableReader();
1579
+ }
1580
+ ASSERT_FALSE(iter->Valid());
1581
+ iter->SeekToFirst();
1582
+ ASSERT_TRUE(iter->Valid());
1583
+ for (size_t i = 0; i < expected_tombstones.size(); i++) {
1584
+ ASSERT_TRUE(iter->Valid());
1585
+ ParsedInternalKey parsed_key;
1586
+ ASSERT_OK(
1587
+ ParseInternalKey(iter->key(), &parsed_key, true /* log_err_key */));
1588
+ RangeTombstone t(parsed_key, iter->value());
1589
+ const auto& expected_t = expected_tombstones[i];
1590
+ ASSERT_EQ(t.start_key_, expected_t.start_key_);
1591
+ ASSERT_EQ(t.end_key_, expected_t.end_key_);
1592
+ ASSERT_EQ(t.seq_, expected_t.seq_);
1593
+ iter->Next();
1594
+ }
1595
+ ASSERT_TRUE(!iter->Valid());
1596
+ }
1597
+ }
1598
+
1599
+ TEST_P(BlockBasedTableTest, FilterPolicyNameProperties) {
1600
+ TableConstructor c(BytewiseComparator(), true /* convert_to_internal_key_ */);
1601
+ c.Add("a1", "val1");
1602
+ std::vector<std::string> keys;
1603
+ stl_wrappers::KVMap kvmap;
1604
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
1605
+ table_options.filter_policy.reset(NewBloomFilterPolicy(10));
1606
+ Options options;
1607
+ options.table_factory.reset(NewBlockBasedTableFactory(table_options));
1608
+
1609
+ const ImmutableCFOptions ioptions(options);
1610
+ const MutableCFOptions moptions(options);
1611
+ c.Finish(options, ioptions, moptions, table_options,
1612
+ GetPlainInternalComparator(options.comparator), &keys, &kvmap);
1613
+ auto& props = *c.GetTableReader()->GetTableProperties();
1614
+ ASSERT_EQ("rocksdb.BuiltinBloomFilter", props.filter_policy_name);
1615
+ c.ResetTableReader();
1616
+ }
1617
+
1618
+ //
1619
+ // BlockBasedTableTest::PrefetchTest
1620
+ //
1621
+ void AssertKeysInCache(BlockBasedTable* table_reader,
1622
+ const std::vector<std::string>& keys_in_cache,
1623
+ const std::vector<std::string>& keys_not_in_cache,
1624
+ bool convert = false) {
1625
+ if (convert) {
1626
+ for (auto key : keys_in_cache) {
1627
+ InternalKey ikey(key, kMaxSequenceNumber, kTypeValue);
1628
+ ASSERT_TRUE(table_reader->TEST_KeyInCache(ReadOptions(), ikey.Encode()));
1629
+ }
1630
+ for (auto key : keys_not_in_cache) {
1631
+ InternalKey ikey(key, kMaxSequenceNumber, kTypeValue);
1632
+ ASSERT_TRUE(!table_reader->TEST_KeyInCache(ReadOptions(), ikey.Encode()));
1633
+ }
1634
+ } else {
1635
+ for (auto key : keys_in_cache) {
1636
+ ASSERT_TRUE(table_reader->TEST_KeyInCache(ReadOptions(), key));
1637
+ }
1638
+ for (auto key : keys_not_in_cache) {
1639
+ ASSERT_TRUE(!table_reader->TEST_KeyInCache(ReadOptions(), key));
1640
+ }
1641
+ }
1642
+ }
1643
+
1644
+ void PrefetchRange(TableConstructor* c, Options* opt,
1645
+ BlockBasedTableOptions* table_options, const char* key_begin,
1646
+ const char* key_end,
1647
+ const std::vector<std::string>& keys_in_cache,
1648
+ const std::vector<std::string>& keys_not_in_cache,
1649
+ const Status expected_status = Status::OK()) {
1650
+ // reset the cache and reopen the table
1651
+ table_options->block_cache = NewLRUCache(16 * 1024 * 1024, 4);
1652
+ opt->table_factory.reset(NewBlockBasedTableFactory(*table_options));
1653
+ const ImmutableCFOptions ioptions2(*opt);
1654
+ const MutableCFOptions moptions(*opt);
1655
+ ASSERT_OK(c->Reopen(ioptions2, moptions));
1656
+
1657
+ // prefetch
1658
+ auto* table_reader = dynamic_cast<BlockBasedTable*>(c->GetTableReader());
1659
+ Status s;
1660
+ std::unique_ptr<Slice> begin, end;
1661
+ std::unique_ptr<InternalKey> i_begin, i_end;
1662
+ if (key_begin != nullptr) {
1663
+ if (c->ConvertToInternalKey()) {
1664
+ i_begin.reset(new InternalKey(key_begin, kMaxSequenceNumber, kTypeValue));
1665
+ begin.reset(new Slice(i_begin->Encode()));
1666
+ } else {
1667
+ begin.reset(new Slice(key_begin));
1668
+ }
1669
+ }
1670
+ if (key_end != nullptr) {
1671
+ if (c->ConvertToInternalKey()) {
1672
+ i_end.reset(new InternalKey(key_end, kMaxSequenceNumber, kTypeValue));
1673
+ end.reset(new Slice(i_end->Encode()));
1674
+ } else {
1675
+ end.reset(new Slice(key_end));
1676
+ }
1677
+ }
1678
+ s = table_reader->Prefetch(begin.get(), end.get());
1679
+
1680
+ ASSERT_TRUE(s.code() == expected_status.code());
1681
+
1682
+ // assert our expectation in cache warmup
1683
+ AssertKeysInCache(table_reader, keys_in_cache, keys_not_in_cache,
1684
+ c->ConvertToInternalKey());
1685
+ c->ResetTableReader();
1686
+ }
1687
+
1688
+ TEST_P(BlockBasedTableTest, PrefetchTest) {
1689
+ // The purpose of this test is to test the prefetching operation built into
1690
+ // BlockBasedTable.
1691
+ Options opt;
1692
+ std::unique_ptr<InternalKeyComparator> ikc;
1693
+ ikc.reset(new test::PlainInternalKeyComparator(opt.comparator));
1694
+ opt.compression = kNoCompression;
1695
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
1696
+ table_options.block_size = 1024;
1697
+ // big enough so we don't ever lose cached values.
1698
+ table_options.block_cache = NewLRUCache(16 * 1024 * 1024, 4);
1699
+ opt.table_factory.reset(NewBlockBasedTableFactory(table_options));
1700
+
1701
+ TableConstructor c(BytewiseComparator(), true /* convert_to_internal_key_ */);
1702
+ c.Add("k01", "hello");
1703
+ c.Add("k02", "hello2");
1704
+ c.Add("k03", std::string(10000, 'x'));
1705
+ c.Add("k04", std::string(200000, 'x'));
1706
+ c.Add("k05", std::string(300000, 'x'));
1707
+ c.Add("k06", "hello3");
1708
+ c.Add("k07", std::string(100000, 'x'));
1709
+ std::vector<std::string> keys;
1710
+ stl_wrappers::KVMap kvmap;
1711
+ const ImmutableCFOptions ioptions(opt);
1712
+ const MutableCFOptions moptions(opt);
1713
+ c.Finish(opt, ioptions, moptions, table_options, *ikc, &keys, &kvmap);
1714
+ c.ResetTableReader();
1715
+
1716
+ // We get the following data spread :
1717
+ //
1718
+ // Data block Index
1719
+ // ========================
1720
+ // [ k01 k02 k03 ] k03
1721
+ // [ k04 ] k04
1722
+ // [ k05 ] k05
1723
+ // [ k06 k07 ] k07
1724
+
1725
+
1726
+ // Simple
1727
+ PrefetchRange(&c, &opt, &table_options,
1728
+ /*key_range=*/"k01", "k05",
1729
+ /*keys_in_cache=*/{"k01", "k02", "k03", "k04", "k05"},
1730
+ /*keys_not_in_cache=*/{"k06", "k07"});
1731
+ PrefetchRange(&c, &opt, &table_options, "k01", "k01", {"k01", "k02", "k03"},
1732
+ {"k04", "k05", "k06", "k07"});
1733
+ // odd
1734
+ PrefetchRange(&c, &opt, &table_options, "a", "z",
1735
+ {"k01", "k02", "k03", "k04", "k05", "k06", "k07"}, {});
1736
+ PrefetchRange(&c, &opt, &table_options, "k00", "k00", {"k01", "k02", "k03"},
1737
+ {"k04", "k05", "k06", "k07"});
1738
+ // Edge cases
1739
+ PrefetchRange(&c, &opt, &table_options, "k00", "k06",
1740
+ {"k01", "k02", "k03", "k04", "k05", "k06", "k07"}, {});
1741
+ PrefetchRange(&c, &opt, &table_options, "k00", "zzz",
1742
+ {"k01", "k02", "k03", "k04", "k05", "k06", "k07"}, {});
1743
+ // null keys
1744
+ PrefetchRange(&c, &opt, &table_options, nullptr, nullptr,
1745
+ {"k01", "k02", "k03", "k04", "k05", "k06", "k07"}, {});
1746
+ PrefetchRange(&c, &opt, &table_options, "k04", nullptr,
1747
+ {"k04", "k05", "k06", "k07"}, {"k01", "k02", "k03"});
1748
+ PrefetchRange(&c, &opt, &table_options, nullptr, "k05",
1749
+ {"k01", "k02", "k03", "k04", "k05"}, {"k06", "k07"});
1750
+ // invalid
1751
+ PrefetchRange(&c, &opt, &table_options, "k06", "k00", {}, {},
1752
+ Status::InvalidArgument(Slice("k06 "), Slice("k07")));
1753
+ c.ResetTableReader();
1754
+ }
1755
+
1756
+ TEST_P(BlockBasedTableTest, TotalOrderSeekOnHashIndex) {
1757
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
1758
+ for (int i = 0; i <= 5; ++i) {
1759
+ Options options;
1760
+ // Make each key/value an individual block
1761
+ table_options.block_size = 64;
1762
+ switch (i) {
1763
+ case 0:
1764
+ // Binary search index
1765
+ table_options.index_type = BlockBasedTableOptions::kBinarySearch;
1766
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
1767
+ break;
1768
+ case 1:
1769
+ // Hash search index
1770
+ table_options.index_type = BlockBasedTableOptions::kHashSearch;
1771
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
1772
+ options.prefix_extractor.reset(NewFixedPrefixTransform(4));
1773
+ break;
1774
+ case 2:
1775
+ // Hash search index with hash_index_allow_collision
1776
+ table_options.index_type = BlockBasedTableOptions::kHashSearch;
1777
+ table_options.hash_index_allow_collision = true;
1778
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
1779
+ options.prefix_extractor.reset(NewFixedPrefixTransform(4));
1780
+ break;
1781
+ case 3:
1782
+ // Hash search index with filter policy
1783
+ table_options.index_type = BlockBasedTableOptions::kHashSearch;
1784
+ table_options.filter_policy.reset(NewBloomFilterPolicy(10));
1785
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
1786
+ options.prefix_extractor.reset(NewFixedPrefixTransform(4));
1787
+ break;
1788
+ case 4:
1789
+ // Two-level index
1790
+ table_options.index_type = BlockBasedTableOptions::kTwoLevelIndexSearch;
1791
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
1792
+ break;
1793
+ case 5:
1794
+ // Binary search with first key
1795
+ table_options.index_type =
1796
+ BlockBasedTableOptions::kBinarySearchWithFirstKey;
1797
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
1798
+ break;
1799
+ }
1800
+
1801
+ TableConstructor c(BytewiseComparator(),
1802
+ true /* convert_to_internal_key_ */);
1803
+ c.Add("aaaa1", std::string('a', 56));
1804
+ c.Add("bbaa1", std::string('a', 56));
1805
+ c.Add("cccc1", std::string('a', 56));
1806
+ c.Add("bbbb1", std::string('a', 56));
1807
+ c.Add("baaa1", std::string('a', 56));
1808
+ c.Add("abbb1", std::string('a', 56));
1809
+ c.Add("cccc2", std::string('a', 56));
1810
+ std::vector<std::string> keys;
1811
+ stl_wrappers::KVMap kvmap;
1812
+ const ImmutableCFOptions ioptions(options);
1813
+ const MutableCFOptions moptions(options);
1814
+ c.Finish(options, ioptions, moptions, table_options,
1815
+ GetPlainInternalComparator(options.comparator), &keys, &kvmap);
1816
+ auto props = c.GetTableReader()->GetTableProperties();
1817
+ ASSERT_EQ(7u, props->num_data_blocks);
1818
+ auto* reader = c.GetTableReader();
1819
+ ReadOptions ro;
1820
+ ro.total_order_seek = true;
1821
+ std::unique_ptr<InternalIterator> iter(reader->NewIterator(
1822
+ ro, moptions.prefix_extractor.get(), /*arena=*/nullptr,
1823
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
1824
+
1825
+ iter->Seek(InternalKey("b", 0, kTypeValue).Encode());
1826
+ ASSERT_OK(iter->status());
1827
+ ASSERT_TRUE(iter->Valid());
1828
+ ASSERT_EQ("baaa1", ExtractUserKey(iter->key()).ToString());
1829
+ iter->Next();
1830
+ ASSERT_OK(iter->status());
1831
+ ASSERT_TRUE(iter->Valid());
1832
+ ASSERT_EQ("bbaa1", ExtractUserKey(iter->key()).ToString());
1833
+
1834
+ iter->Seek(InternalKey("bb", 0, kTypeValue).Encode());
1835
+ ASSERT_OK(iter->status());
1836
+ ASSERT_TRUE(iter->Valid());
1837
+ ASSERT_EQ("bbaa1", ExtractUserKey(iter->key()).ToString());
1838
+ iter->Next();
1839
+ ASSERT_OK(iter->status());
1840
+ ASSERT_TRUE(iter->Valid());
1841
+ ASSERT_EQ("bbbb1", ExtractUserKey(iter->key()).ToString());
1842
+
1843
+ iter->Seek(InternalKey("bbb", 0, kTypeValue).Encode());
1844
+ ASSERT_OK(iter->status());
1845
+ ASSERT_TRUE(iter->Valid());
1846
+ ASSERT_EQ("bbbb1", ExtractUserKey(iter->key()).ToString());
1847
+ iter->Next();
1848
+ ASSERT_OK(iter->status());
1849
+ ASSERT_TRUE(iter->Valid());
1850
+ ASSERT_EQ("cccc1", ExtractUserKey(iter->key()).ToString());
1851
+ }
1852
+ }
1853
+
1854
+ TEST_P(BlockBasedTableTest, NoopTransformSeek) {
1855
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
1856
+ table_options.filter_policy.reset(NewBloomFilterPolicy(10));
1857
+
1858
+ Options options;
1859
+ options.comparator = BytewiseComparator();
1860
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
1861
+ options.prefix_extractor.reset(NewNoopTransform());
1862
+
1863
+ TableConstructor c(options.comparator);
1864
+ // To tickle the PrefixMayMatch bug it is important that the
1865
+ // user-key is a single byte so that the index key exactly matches
1866
+ // the user-key.
1867
+ InternalKey key("a", 1, kTypeValue);
1868
+ c.Add(key.Encode().ToString(), "b");
1869
+ std::vector<std::string> keys;
1870
+ stl_wrappers::KVMap kvmap;
1871
+ const ImmutableCFOptions ioptions(options);
1872
+ const MutableCFOptions moptions(options);
1873
+ const InternalKeyComparator internal_comparator(options.comparator);
1874
+ c.Finish(options, ioptions, moptions, table_options, internal_comparator,
1875
+ &keys, &kvmap);
1876
+
1877
+ auto* reader = c.GetTableReader();
1878
+ for (int i = 0; i < 2; ++i) {
1879
+ ReadOptions ro;
1880
+ ro.total_order_seek = (i == 0);
1881
+ std::unique_ptr<InternalIterator> iter(reader->NewIterator(
1882
+ ro, moptions.prefix_extractor.get(), /*arena=*/nullptr,
1883
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
1884
+
1885
+ iter->Seek(key.Encode());
1886
+ ASSERT_OK(iter->status());
1887
+ ASSERT_TRUE(iter->Valid());
1888
+ ASSERT_EQ("a", ExtractUserKey(iter->key()).ToString());
1889
+ }
1890
+ }
1891
+
1892
+ TEST_P(BlockBasedTableTest, SkipPrefixBloomFilter) {
1893
+ // if DB is opened with a prefix extractor of a different name,
1894
+ // prefix bloom is skipped when read the file
1895
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
1896
+ table_options.filter_policy.reset(NewBloomFilterPolicy(2));
1897
+ table_options.whole_key_filtering = false;
1898
+
1899
+ Options options;
1900
+ options.comparator = BytewiseComparator();
1901
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
1902
+ options.prefix_extractor.reset(NewFixedPrefixTransform(1));
1903
+
1904
+ TableConstructor c(options.comparator);
1905
+ InternalKey key("abcdefghijk", 1, kTypeValue);
1906
+ c.Add(key.Encode().ToString(), "test");
1907
+ std::vector<std::string> keys;
1908
+ stl_wrappers::KVMap kvmap;
1909
+ const ImmutableCFOptions ioptions(options);
1910
+ const MutableCFOptions moptions(options);
1911
+ const InternalKeyComparator internal_comparator(options.comparator);
1912
+ c.Finish(options, ioptions, moptions, table_options, internal_comparator,
1913
+ &keys, &kvmap);
1914
+ // TODO(Zhongyi): update test to use MutableCFOptions
1915
+ options.prefix_extractor.reset(NewFixedPrefixTransform(9));
1916
+ const ImmutableCFOptions new_ioptions(options);
1917
+ const MutableCFOptions new_moptions(options);
1918
+ ASSERT_OK(c.Reopen(new_ioptions, new_moptions));
1919
+ auto reader = c.GetTableReader();
1920
+ ReadOptions read_options;
1921
+ std::unique_ptr<InternalIterator> db_iter(reader->NewIterator(
1922
+ read_options, new_moptions.prefix_extractor.get(), /*arena=*/nullptr,
1923
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
1924
+
1925
+ // Test point lookup
1926
+ // only one kv
1927
+ for (auto& kv : kvmap) {
1928
+ db_iter->Seek(kv.first);
1929
+ ASSERT_TRUE(db_iter->Valid());
1930
+ ASSERT_OK(db_iter->status());
1931
+ ASSERT_EQ(db_iter->key(), kv.first);
1932
+ ASSERT_EQ(db_iter->value(), kv.second);
1933
+ }
1934
+ }
1935
+
1936
+ void AddInternalKey(TableConstructor* c, const std::string& prefix,
1937
+ std::string value = "v", int /*suffix_len*/ = 800) {
1938
+ static Random rnd(1023);
1939
+ InternalKey k(prefix + rnd.RandomString(800), 0, kTypeValue);
1940
+ c->Add(k.Encode().ToString(), value);
1941
+ }
1942
+
1943
+ void TableTest::IndexTest(BlockBasedTableOptions table_options) {
1944
+ TableConstructor c(BytewiseComparator());
1945
+
1946
+ // keys with prefix length 3, make sure the key/value is big enough to fill
1947
+ // one block
1948
+ AddInternalKey(&c, "0015");
1949
+ AddInternalKey(&c, "0035");
1950
+
1951
+ AddInternalKey(&c, "0054");
1952
+ AddInternalKey(&c, "0055");
1953
+
1954
+ AddInternalKey(&c, "0056");
1955
+ AddInternalKey(&c, "0057");
1956
+
1957
+ AddInternalKey(&c, "0058");
1958
+ AddInternalKey(&c, "0075");
1959
+
1960
+ AddInternalKey(&c, "0076");
1961
+ AddInternalKey(&c, "0095");
1962
+
1963
+ std::vector<std::string> keys;
1964
+ stl_wrappers::KVMap kvmap;
1965
+ Options options;
1966
+ options.prefix_extractor.reset(NewFixedPrefixTransform(3));
1967
+ table_options.block_size = 1700;
1968
+ table_options.block_cache = NewLRUCache(1024, 4);
1969
+ options.table_factory.reset(NewBlockBasedTableFactory(table_options));
1970
+
1971
+ std::unique_ptr<InternalKeyComparator> comparator(
1972
+ new InternalKeyComparator(BytewiseComparator()));
1973
+ const ImmutableCFOptions ioptions(options);
1974
+ const MutableCFOptions moptions(options);
1975
+ c.Finish(options, ioptions, moptions, table_options, *comparator, &keys,
1976
+ &kvmap);
1977
+ auto reader = c.GetTableReader();
1978
+
1979
+ auto props = reader->GetTableProperties();
1980
+ ASSERT_EQ(5u, props->num_data_blocks);
1981
+
1982
+ // TODO(Zhongyi): update test to use MutableCFOptions
1983
+ ReadOptions read_options;
1984
+ std::unique_ptr<InternalIterator> index_iter(reader->NewIterator(
1985
+ read_options, moptions.prefix_extractor.get(), /*arena=*/nullptr,
1986
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
1987
+
1988
+ // -- Find keys do not exist, but have common prefix.
1989
+ std::vector<std::string> prefixes = {"001", "003", "005", "007", "009"};
1990
+ std::vector<std::string> lower_bound = {
1991
+ keys[0], keys[1], keys[2], keys[7], keys[9],
1992
+ };
1993
+
1994
+ // find the lower bound of the prefix
1995
+ for (size_t i = 0; i < prefixes.size(); ++i) {
1996
+ index_iter->Seek(InternalKey(prefixes[i], 0, kTypeValue).Encode());
1997
+ ASSERT_OK(index_iter->status());
1998
+ ASSERT_TRUE(index_iter->Valid());
1999
+
2000
+ // seek the first element in the block
2001
+ ASSERT_EQ(lower_bound[i], index_iter->key().ToString());
2002
+ ASSERT_EQ("v", index_iter->value().ToString());
2003
+ }
2004
+
2005
+ // find the upper bound of prefixes
2006
+ std::vector<std::string> upper_bound = {keys[1], keys[2], keys[7], keys[9], };
2007
+
2008
+ // find existing keys
2009
+ for (const auto& item : kvmap) {
2010
+ auto ukey = ExtractUserKey(item.first).ToString();
2011
+ index_iter->Seek(ukey);
2012
+
2013
+ // ASSERT_OK(regular_iter->status());
2014
+ ASSERT_OK(index_iter->status());
2015
+
2016
+ // ASSERT_TRUE(regular_iter->Valid());
2017
+ ASSERT_TRUE(index_iter->Valid());
2018
+
2019
+ ASSERT_EQ(item.first, index_iter->key().ToString());
2020
+ ASSERT_EQ(item.second, index_iter->value().ToString());
2021
+ }
2022
+
2023
+ for (size_t i = 0; i < prefixes.size(); ++i) {
2024
+ // the key is greater than any existing keys.
2025
+ auto key = prefixes[i] + "9";
2026
+ index_iter->Seek(InternalKey(key, 0, kTypeValue).Encode());
2027
+
2028
+ ASSERT_TRUE(index_iter->status().ok() || index_iter->status().IsNotFound());
2029
+ ASSERT_TRUE(!index_iter->status().IsNotFound() || !index_iter->Valid());
2030
+ if (i == prefixes.size() - 1) {
2031
+ // last key
2032
+ ASSERT_TRUE(!index_iter->Valid());
2033
+ } else {
2034
+ ASSERT_TRUE(index_iter->Valid());
2035
+ // seek the first element in the block
2036
+ ASSERT_EQ(upper_bound[i], index_iter->key().ToString());
2037
+ ASSERT_EQ("v", index_iter->value().ToString());
2038
+ }
2039
+ }
2040
+
2041
+ // find keys with prefix that don't match any of the existing prefixes.
2042
+ std::vector<std::string> non_exist_prefixes = {"002", "004", "006", "008"};
2043
+ for (const auto& prefix : non_exist_prefixes) {
2044
+ index_iter->Seek(InternalKey(prefix, 0, kTypeValue).Encode());
2045
+ // regular_iter->Seek(prefix);
2046
+
2047
+ ASSERT_OK(index_iter->status());
2048
+ // Seek to non-existing prefixes should yield either invalid, or a
2049
+ // key with prefix greater than the target.
2050
+ if (index_iter->Valid()) {
2051
+ Slice ukey = ExtractUserKey(index_iter->key());
2052
+ Slice ukey_prefix = options.prefix_extractor->Transform(ukey);
2053
+ ASSERT_TRUE(BytewiseComparator()->Compare(prefix, ukey_prefix) < 0);
2054
+ }
2055
+ }
2056
+ for (const auto& prefix : non_exist_prefixes) {
2057
+ index_iter->SeekForPrev(InternalKey(prefix, 0, kTypeValue).Encode());
2058
+ // regular_iter->Seek(prefix);
2059
+
2060
+ ASSERT_OK(index_iter->status());
2061
+ // Seek to non-existing prefixes should yield either invalid, or a
2062
+ // key with prefix greater than the target.
2063
+ if (index_iter->Valid()) {
2064
+ Slice ukey = ExtractUserKey(index_iter->key());
2065
+ Slice ukey_prefix = options.prefix_extractor->Transform(ukey);
2066
+ ASSERT_TRUE(BytewiseComparator()->Compare(prefix, ukey_prefix) > 0);
2067
+ }
2068
+ }
2069
+
2070
+ {
2071
+ // Test reseek case. It should impact partitioned index more.
2072
+ ReadOptions ro;
2073
+ ro.total_order_seek = true;
2074
+ std::unique_ptr<InternalIterator> index_iter2(reader->NewIterator(
2075
+ ro, moptions.prefix_extractor.get(), /*arena=*/nullptr,
2076
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
2077
+
2078
+ // Things to cover in partitioned index:
2079
+ // 1. Both of Seek() and SeekToLast() has optimization to prevent
2080
+ // rereek leaf index block if it remains to the same one, and
2081
+ // they reuse the same variable.
2082
+ // 2. When Next() or Prev() is called, the block moves, so the
2083
+ // optimization should kick in only with the current one.
2084
+ index_iter2->Seek(InternalKey("0055", 0, kTypeValue).Encode());
2085
+ ASSERT_TRUE(index_iter2->Valid());
2086
+ ASSERT_EQ("0055", index_iter2->key().ToString().substr(0, 4));
2087
+
2088
+ index_iter2->SeekToLast();
2089
+ ASSERT_TRUE(index_iter2->Valid());
2090
+ ASSERT_EQ("0095", index_iter2->key().ToString().substr(0, 4));
2091
+
2092
+ index_iter2->Seek(InternalKey("0055", 0, kTypeValue).Encode());
2093
+ ASSERT_TRUE(index_iter2->Valid());
2094
+ ASSERT_EQ("0055", index_iter2->key().ToString().substr(0, 4));
2095
+
2096
+ index_iter2->SeekToLast();
2097
+ ASSERT_TRUE(index_iter2->Valid());
2098
+ ASSERT_EQ("0095", index_iter2->key().ToString().substr(0, 4));
2099
+ index_iter2->Prev();
2100
+ ASSERT_TRUE(index_iter2->Valid());
2101
+ index_iter2->Prev();
2102
+ ASSERT_TRUE(index_iter2->Valid());
2103
+ ASSERT_EQ("0075", index_iter2->key().ToString().substr(0, 4));
2104
+
2105
+ index_iter2->Seek(InternalKey("0095", 0, kTypeValue).Encode());
2106
+ ASSERT_TRUE(index_iter2->Valid());
2107
+ ASSERT_EQ("0095", index_iter2->key().ToString().substr(0, 4));
2108
+ index_iter2->Prev();
2109
+ ASSERT_TRUE(index_iter2->Valid());
2110
+ index_iter2->Prev();
2111
+ ASSERT_TRUE(index_iter2->Valid());
2112
+ ASSERT_EQ("0075", index_iter2->key().ToString().substr(0, 4));
2113
+
2114
+ index_iter2->SeekToLast();
2115
+ ASSERT_TRUE(index_iter2->Valid());
2116
+ ASSERT_EQ("0095", index_iter2->key().ToString().substr(0, 4));
2117
+
2118
+ index_iter2->Seek(InternalKey("0095", 0, kTypeValue).Encode());
2119
+ ASSERT_TRUE(index_iter2->Valid());
2120
+ ASSERT_EQ("0095", index_iter2->key().ToString().substr(0, 4));
2121
+
2122
+ index_iter2->Prev();
2123
+ ASSERT_TRUE(index_iter2->Valid());
2124
+ index_iter2->Prev();
2125
+ ASSERT_TRUE(index_iter2->Valid());
2126
+ ASSERT_EQ("0075", index_iter2->key().ToString().substr(0, 4));
2127
+
2128
+ index_iter2->Seek(InternalKey("0075", 0, kTypeValue).Encode());
2129
+ ASSERT_TRUE(index_iter2->Valid());
2130
+ ASSERT_EQ("0075", index_iter2->key().ToString().substr(0, 4));
2131
+
2132
+ index_iter2->Next();
2133
+ ASSERT_TRUE(index_iter2->Valid());
2134
+ index_iter2->Next();
2135
+ ASSERT_TRUE(index_iter2->Valid());
2136
+ ASSERT_EQ("0095", index_iter2->key().ToString().substr(0, 4));
2137
+
2138
+ index_iter2->SeekToLast();
2139
+ ASSERT_TRUE(index_iter2->Valid());
2140
+ ASSERT_EQ("0095", index_iter2->key().ToString().substr(0, 4));
2141
+ }
2142
+
2143
+ c.ResetTableReader();
2144
+ }
2145
+
2146
+ TEST_P(BlockBasedTableTest, BinaryIndexTest) {
2147
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
2148
+ table_options.index_type = BlockBasedTableOptions::kBinarySearch;
2149
+ IndexTest(table_options);
2150
+ }
2151
+
2152
+ TEST_P(BlockBasedTableTest, HashIndexTest) {
2153
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
2154
+ table_options.index_type = BlockBasedTableOptions::kHashSearch;
2155
+ IndexTest(table_options);
2156
+ }
2157
+
2158
+ TEST_P(BlockBasedTableTest, PartitionIndexTest) {
2159
+ const int max_index_keys = 5;
2160
+ const int est_max_index_key_value_size = 32;
2161
+ const int est_max_index_size = max_index_keys * est_max_index_key_value_size;
2162
+ for (int i = 1; i <= est_max_index_size + 1; i++) {
2163
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
2164
+ table_options.index_type = BlockBasedTableOptions::kTwoLevelIndexSearch;
2165
+ table_options.metadata_block_size = i;
2166
+ IndexTest(table_options);
2167
+ }
2168
+ }
2169
+
2170
+ TEST_P(BlockBasedTableTest, IndexSeekOptimizationIncomplete) {
2171
+ std::unique_ptr<InternalKeyComparator> comparator(
2172
+ new InternalKeyComparator(BytewiseComparator()));
2173
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
2174
+ Options options;
2175
+ options.table_factory.reset(NewBlockBasedTableFactory(table_options));
2176
+ const ImmutableCFOptions ioptions(options);
2177
+ const MutableCFOptions moptions(options);
2178
+
2179
+ TableConstructor c(BytewiseComparator());
2180
+ AddInternalKey(&c, "pika");
2181
+
2182
+ std::vector<std::string> keys;
2183
+ stl_wrappers::KVMap kvmap;
2184
+ c.Finish(options, ioptions, moptions, table_options, *comparator, &keys,
2185
+ &kvmap);
2186
+ ASSERT_EQ(1, keys.size());
2187
+
2188
+ auto reader = c.GetTableReader();
2189
+ ReadOptions ropt;
2190
+ ropt.read_tier = ReadTier::kBlockCacheTier;
2191
+ std::unique_ptr<InternalIterator> iter(reader->NewIterator(
2192
+ ropt, /*prefix_extractor=*/nullptr, /*arena=*/nullptr,
2193
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
2194
+
2195
+ auto ikey = [](Slice user_key) {
2196
+ return InternalKey(user_key, 0, kTypeValue).Encode().ToString();
2197
+ };
2198
+
2199
+ iter->Seek(ikey("pika"));
2200
+ ASSERT_FALSE(iter->Valid());
2201
+ ASSERT_TRUE(iter->status().IsIncomplete());
2202
+
2203
+ // This used to crash at some point.
2204
+ iter->Seek(ikey("pika"));
2205
+ ASSERT_FALSE(iter->Valid());
2206
+ ASSERT_TRUE(iter->status().IsIncomplete());
2207
+ }
2208
+
2209
+ TEST_P(BlockBasedTableTest, BinaryIndexWithFirstKey1) {
2210
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
2211
+ table_options.index_type = BlockBasedTableOptions::kBinarySearchWithFirstKey;
2212
+ IndexTest(table_options);
2213
+ }
2214
+
2215
+ class CustomFlushBlockPolicy : public FlushBlockPolicyFactory,
2216
+ public FlushBlockPolicy {
2217
+ public:
2218
+ explicit CustomFlushBlockPolicy(std::vector<int> keys_per_block)
2219
+ : keys_per_block_(keys_per_block) {}
2220
+
2221
+ const char* Name() const override { return "CustomFlushBlockPolicy"; }
2222
+
2223
+ FlushBlockPolicy* NewFlushBlockPolicy(const BlockBasedTableOptions&,
2224
+ const BlockBuilder&) const override {
2225
+ return new CustomFlushBlockPolicy(keys_per_block_);
2226
+ }
2227
+
2228
+ bool Update(const Slice&, const Slice&) override {
2229
+ if (keys_in_current_block_ >= keys_per_block_.at(current_block_idx_)) {
2230
+ ++current_block_idx_;
2231
+ keys_in_current_block_ = 1;
2232
+ return true;
2233
+ }
2234
+
2235
+ ++keys_in_current_block_;
2236
+ return false;
2237
+ }
2238
+
2239
+ std::vector<int> keys_per_block_;
2240
+
2241
+ int current_block_idx_ = 0;
2242
+ int keys_in_current_block_ = 0;
2243
+ };
2244
+
2245
+ TEST_P(BlockBasedTableTest, BinaryIndexWithFirstKey2) {
2246
+ for (int use_first_key = 0; use_first_key < 2; ++use_first_key) {
2247
+ SCOPED_TRACE("use_first_key = " + std::to_string(use_first_key));
2248
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
2249
+ table_options.index_type =
2250
+ use_first_key ? BlockBasedTableOptions::kBinarySearchWithFirstKey
2251
+ : BlockBasedTableOptions::kBinarySearch;
2252
+ table_options.block_cache = NewLRUCache(10000); // fits all blocks
2253
+ table_options.index_shortening =
2254
+ BlockBasedTableOptions::IndexShorteningMode::kNoShortening;
2255
+ table_options.flush_block_policy_factory =
2256
+ std::make_shared<CustomFlushBlockPolicy>(std::vector<int>{2, 1, 3, 2});
2257
+ Options options;
2258
+ options.table_factory.reset(NewBlockBasedTableFactory(table_options));
2259
+ options.statistics = CreateDBStatistics();
2260
+ Statistics* stats = options.statistics.get();
2261
+ std::unique_ptr<InternalKeyComparator> comparator(
2262
+ new InternalKeyComparator(BytewiseComparator()));
2263
+ const ImmutableCFOptions ioptions(options);
2264
+ const MutableCFOptions moptions(options);
2265
+
2266
+ TableConstructor c(BytewiseComparator());
2267
+
2268
+ // Block 0.
2269
+ AddInternalKey(&c, "aaaa", "v0");
2270
+ AddInternalKey(&c, "aaac", "v1");
2271
+
2272
+ // Block 1.
2273
+ AddInternalKey(&c, "aaca", "v2");
2274
+
2275
+ // Block 2.
2276
+ AddInternalKey(&c, "caaa", "v3");
2277
+ AddInternalKey(&c, "caac", "v4");
2278
+ AddInternalKey(&c, "caae", "v5");
2279
+
2280
+ // Block 3.
2281
+ AddInternalKey(&c, "ccaa", "v6");
2282
+ AddInternalKey(&c, "ccac", "v7");
2283
+
2284
+ // Write the file.
2285
+ std::vector<std::string> keys;
2286
+ stl_wrappers::KVMap kvmap;
2287
+ c.Finish(options, ioptions, moptions, table_options, *comparator, &keys,
2288
+ &kvmap);
2289
+ ASSERT_EQ(8, keys.size());
2290
+
2291
+ auto reader = c.GetTableReader();
2292
+ auto props = reader->GetTableProperties();
2293
+ ASSERT_EQ(4u, props->num_data_blocks);
2294
+ ReadOptions read_options;
2295
+ std::unique_ptr<InternalIterator> iter(reader->NewIterator(
2296
+ read_options, /*prefix_extractor=*/nullptr, /*arena=*/nullptr,
2297
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized,
2298
+ /*compaction_readahead_size=*/0, /*allow_unprepared_value=*/true));
2299
+
2300
+ // Shouldn't have read data blocks before iterator is seeked.
2301
+ EXPECT_EQ(0, stats->getTickerCount(BLOCK_CACHE_DATA_MISS));
2302
+ EXPECT_EQ(0, stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2303
+
2304
+ auto ikey = [](Slice user_key) {
2305
+ return InternalKey(user_key, 0, kTypeValue).Encode().ToString();
2306
+ };
2307
+
2308
+ // Seek to a key between blocks. If index contains first key, we shouldn't
2309
+ // read any data blocks until value is requested.
2310
+ iter->Seek(ikey("aaba"));
2311
+ ASSERT_TRUE(iter->Valid());
2312
+ EXPECT_EQ(keys[2], iter->key().ToString());
2313
+ EXPECT_EQ(use_first_key ? 0 : 1,
2314
+ stats->getTickerCount(BLOCK_CACHE_DATA_MISS));
2315
+ ASSERT_TRUE(iter->PrepareValue());
2316
+ EXPECT_EQ("v2", iter->value().ToString());
2317
+ EXPECT_EQ(1, stats->getTickerCount(BLOCK_CACHE_DATA_MISS));
2318
+ EXPECT_EQ(0, stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2319
+
2320
+ // Seek to the middle of a block. The block should be read right away.
2321
+ iter->Seek(ikey("caab"));
2322
+ ASSERT_TRUE(iter->Valid());
2323
+ EXPECT_EQ(keys[4], iter->key().ToString());
2324
+ EXPECT_EQ(2, stats->getTickerCount(BLOCK_CACHE_DATA_MISS));
2325
+ EXPECT_EQ(0, stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2326
+ ASSERT_TRUE(iter->PrepareValue());
2327
+ EXPECT_EQ("v4", iter->value().ToString());
2328
+ EXPECT_EQ(0, stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2329
+
2330
+ // Seek to just before the same block and don't access value.
2331
+ // The iterator should keep pinning the block contents.
2332
+ iter->Seek(ikey("baaa"));
2333
+ ASSERT_TRUE(iter->Valid());
2334
+ EXPECT_EQ(keys[3], iter->key().ToString());
2335
+ EXPECT_EQ(0, stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2336
+
2337
+ // Seek to the same block again to check that the block is still pinned.
2338
+ iter->Seek(ikey("caae"));
2339
+ ASSERT_TRUE(iter->Valid());
2340
+ EXPECT_EQ(keys[5], iter->key().ToString());
2341
+ EXPECT_EQ(0, stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2342
+ ASSERT_TRUE(iter->PrepareValue());
2343
+ EXPECT_EQ("v5", iter->value().ToString());
2344
+ EXPECT_EQ(2, stats->getTickerCount(BLOCK_CACHE_DATA_MISS));
2345
+ EXPECT_EQ(0, stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2346
+
2347
+ // Step forward and fall through to the next block. Don't access value.
2348
+ iter->Next();
2349
+ ASSERT_TRUE(iter->Valid());
2350
+ EXPECT_EQ(keys[6], iter->key().ToString());
2351
+ EXPECT_EQ(use_first_key ? 2 : 3,
2352
+ stats->getTickerCount(BLOCK_CACHE_DATA_MISS));
2353
+ EXPECT_EQ(0, stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2354
+
2355
+ // Step forward again. Block should be read.
2356
+ iter->Next();
2357
+ ASSERT_TRUE(iter->Valid());
2358
+ EXPECT_EQ(keys[7], iter->key().ToString());
2359
+ EXPECT_EQ(3, stats->getTickerCount(BLOCK_CACHE_DATA_MISS));
2360
+ ASSERT_TRUE(iter->PrepareValue());
2361
+ EXPECT_EQ("v7", iter->value().ToString());
2362
+ EXPECT_EQ(0, stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2363
+
2364
+ // Step forward and reach the end.
2365
+ iter->Next();
2366
+ EXPECT_FALSE(iter->Valid());
2367
+ EXPECT_EQ(3, stats->getTickerCount(BLOCK_CACHE_DATA_MISS));
2368
+ EXPECT_EQ(0, stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2369
+
2370
+ // Seek to a single-key block and step forward without accessing value.
2371
+ iter->Seek(ikey("aaca"));
2372
+ ASSERT_TRUE(iter->Valid());
2373
+ EXPECT_EQ(keys[2], iter->key().ToString());
2374
+ EXPECT_EQ(use_first_key ? 0 : 1,
2375
+ stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2376
+
2377
+ iter->Next();
2378
+ ASSERT_TRUE(iter->Valid());
2379
+ EXPECT_EQ(keys[3], iter->key().ToString());
2380
+ EXPECT_EQ(use_first_key ? 1 : 2,
2381
+ stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2382
+ ASSERT_TRUE(iter->PrepareValue());
2383
+ EXPECT_EQ("v3", iter->value().ToString());
2384
+ EXPECT_EQ(2, stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2385
+ EXPECT_EQ(3, stats->getTickerCount(BLOCK_CACHE_DATA_MISS));
2386
+
2387
+ // Seek between blocks and step back without accessing value.
2388
+ iter->Seek(ikey("aaca"));
2389
+ ASSERT_TRUE(iter->Valid());
2390
+ EXPECT_EQ(keys[2], iter->key().ToString());
2391
+ EXPECT_EQ(use_first_key ? 2 : 3,
2392
+ stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2393
+ EXPECT_EQ(3, stats->getTickerCount(BLOCK_CACHE_DATA_MISS));
2394
+
2395
+ iter->Prev();
2396
+ ASSERT_TRUE(iter->Valid());
2397
+ EXPECT_EQ(keys[1], iter->key().ToString());
2398
+ EXPECT_EQ(use_first_key ? 2 : 3,
2399
+ stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2400
+ // All blocks are in cache now, there'll be no more misses ever.
2401
+ EXPECT_EQ(4, stats->getTickerCount(BLOCK_CACHE_DATA_MISS));
2402
+ ASSERT_TRUE(iter->PrepareValue());
2403
+ EXPECT_EQ("v1", iter->value().ToString());
2404
+
2405
+ // Next into the next block again.
2406
+ iter->Next();
2407
+ ASSERT_TRUE(iter->Valid());
2408
+ EXPECT_EQ(keys[2], iter->key().ToString());
2409
+ EXPECT_EQ(use_first_key ? 2 : 4,
2410
+ stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2411
+
2412
+ // Seek to first and step back without accessing value.
2413
+ iter->SeekToFirst();
2414
+ ASSERT_TRUE(iter->Valid());
2415
+ EXPECT_EQ(keys[0], iter->key().ToString());
2416
+ EXPECT_EQ(use_first_key ? 2 : 5,
2417
+ stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2418
+
2419
+ iter->Prev();
2420
+ EXPECT_FALSE(iter->Valid());
2421
+ EXPECT_EQ(use_first_key ? 2 : 5,
2422
+ stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2423
+
2424
+ // Do some SeekForPrev() and SeekToLast() just to cover all methods.
2425
+ iter->SeekForPrev(ikey("caad"));
2426
+ ASSERT_TRUE(iter->Valid());
2427
+ EXPECT_EQ(keys[4], iter->key().ToString());
2428
+ EXPECT_EQ(use_first_key ? 3 : 6,
2429
+ stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2430
+ ASSERT_TRUE(iter->PrepareValue());
2431
+ EXPECT_EQ("v4", iter->value().ToString());
2432
+ EXPECT_EQ(use_first_key ? 3 : 6,
2433
+ stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2434
+
2435
+ iter->SeekToLast();
2436
+ ASSERT_TRUE(iter->Valid());
2437
+ EXPECT_EQ(keys[7], iter->key().ToString());
2438
+ EXPECT_EQ(use_first_key ? 4 : 7,
2439
+ stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2440
+ ASSERT_TRUE(iter->PrepareValue());
2441
+ EXPECT_EQ("v7", iter->value().ToString());
2442
+ EXPECT_EQ(use_first_key ? 4 : 7,
2443
+ stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2444
+
2445
+ EXPECT_EQ(4, stats->getTickerCount(BLOCK_CACHE_DATA_MISS));
2446
+
2447
+ c.ResetTableReader();
2448
+ }
2449
+ }
2450
+
2451
+ TEST_P(BlockBasedTableTest, BinaryIndexWithFirstKeyGlobalSeqno) {
2452
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
2453
+ table_options.index_type = BlockBasedTableOptions::kBinarySearchWithFirstKey;
2454
+ table_options.block_cache = NewLRUCache(10000);
2455
+ Options options;
2456
+ options.statistics = CreateDBStatistics();
2457
+ Statistics* stats = options.statistics.get();
2458
+ options.table_factory.reset(NewBlockBasedTableFactory(table_options));
2459
+ std::unique_ptr<InternalKeyComparator> comparator(
2460
+ new InternalKeyComparator(BytewiseComparator()));
2461
+ const ImmutableCFOptions ioptions(options);
2462
+ const MutableCFOptions moptions(options);
2463
+
2464
+ TableConstructor c(BytewiseComparator(), /* convert_to_internal_key */ false,
2465
+ /* level */ -1, /* largest_seqno */ 42);
2466
+
2467
+ c.Add(InternalKey("b", 0, kTypeValue).Encode().ToString(), "x");
2468
+ c.Add(InternalKey("c", 0, kTypeValue).Encode().ToString(), "y");
2469
+
2470
+ std::vector<std::string> keys;
2471
+ stl_wrappers::KVMap kvmap;
2472
+ c.Finish(options, ioptions, moptions, table_options, *comparator, &keys,
2473
+ &kvmap);
2474
+ ASSERT_EQ(2, keys.size());
2475
+
2476
+ auto reader = c.GetTableReader();
2477
+ auto props = reader->GetTableProperties();
2478
+ ASSERT_EQ(1u, props->num_data_blocks);
2479
+ ReadOptions read_options;
2480
+ std::unique_ptr<InternalIterator> iter(reader->NewIterator(
2481
+ read_options, /*prefix_extractor=*/nullptr, /*arena=*/nullptr,
2482
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized,
2483
+ /*compaction_readahead_size=*/0, /*allow_unprepared_value=*/true));
2484
+
2485
+ iter->Seek(InternalKey("a", 0, kTypeValue).Encode().ToString());
2486
+ ASSERT_TRUE(iter->Valid());
2487
+ EXPECT_EQ(InternalKey("b", 42, kTypeValue).Encode().ToString(),
2488
+ iter->key().ToString());
2489
+ EXPECT_NE(keys[0], iter->key().ToString());
2490
+ // Key should have been served from index, without reading data blocks.
2491
+ EXPECT_EQ(0, stats->getTickerCount(BLOCK_CACHE_DATA_MISS));
2492
+
2493
+ ASSERT_TRUE(iter->PrepareValue());
2494
+ EXPECT_EQ("x", iter->value().ToString());
2495
+ EXPECT_EQ(1, stats->getTickerCount(BLOCK_CACHE_DATA_MISS));
2496
+ EXPECT_EQ(0, stats->getTickerCount(BLOCK_CACHE_DATA_HIT));
2497
+ EXPECT_EQ(InternalKey("b", 42, kTypeValue).Encode().ToString(),
2498
+ iter->key().ToString());
2499
+
2500
+ c.ResetTableReader();
2501
+ }
2502
+
2503
+ // It's very hard to figure out the index block size of a block accurately.
2504
+ // To make sure we get the index size, we just make sure as key number
2505
+ // grows, the filter block size also grows.
2506
+ TEST_P(BlockBasedTableTest, IndexSizeStat) {
2507
+ uint64_t last_index_size = 0;
2508
+
2509
+ // we need to use random keys since the pure human readable texts
2510
+ // may be well compressed, resulting insignifcant change of index
2511
+ // block size.
2512
+ Random rnd(test::RandomSeed());
2513
+ std::vector<std::string> keys;
2514
+
2515
+ for (int i = 0; i < 100; ++i) {
2516
+ keys.push_back(rnd.RandomString(10000));
2517
+ }
2518
+
2519
+ // Each time we load one more key to the table. the table index block
2520
+ // size is expected to be larger than last time's.
2521
+ for (size_t i = 1; i < keys.size(); ++i) {
2522
+ TableConstructor c(BytewiseComparator(),
2523
+ true /* convert_to_internal_key_ */);
2524
+ for (size_t j = 0; j < i; ++j) {
2525
+ c.Add(keys[j], "val");
2526
+ }
2527
+
2528
+ std::vector<std::string> ks;
2529
+ stl_wrappers::KVMap kvmap;
2530
+ Options options;
2531
+ options.compression = kNoCompression;
2532
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
2533
+ table_options.block_restart_interval = 1;
2534
+ options.table_factory.reset(NewBlockBasedTableFactory(table_options));
2535
+
2536
+ const ImmutableCFOptions ioptions(options);
2537
+ const MutableCFOptions moptions(options);
2538
+ c.Finish(options, ioptions, moptions, table_options,
2539
+ GetPlainInternalComparator(options.comparator), &ks, &kvmap);
2540
+ auto index_size = c.GetTableReader()->GetTableProperties()->index_size;
2541
+ ASSERT_GT(index_size, last_index_size);
2542
+ last_index_size = index_size;
2543
+ c.ResetTableReader();
2544
+ }
2545
+ }
2546
+
2547
+ TEST_P(BlockBasedTableTest, NumBlockStat) {
2548
+ Random rnd(test::RandomSeed());
2549
+ TableConstructor c(BytewiseComparator(), true /* convert_to_internal_key_ */);
2550
+ Options options;
2551
+ options.compression = kNoCompression;
2552
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
2553
+ table_options.block_restart_interval = 1;
2554
+ table_options.block_size = 1000;
2555
+ options.table_factory.reset(NewBlockBasedTableFactory(table_options));
2556
+
2557
+ for (int i = 0; i < 10; ++i) {
2558
+ // the key/val are slightly smaller than block size, so that each block
2559
+ // holds roughly one key/value pair.
2560
+ c.Add(rnd.RandomString(900), "val");
2561
+ }
2562
+
2563
+ std::vector<std::string> ks;
2564
+ stl_wrappers::KVMap kvmap;
2565
+ const ImmutableCFOptions ioptions(options);
2566
+ const MutableCFOptions moptions(options);
2567
+ c.Finish(options, ioptions, moptions, table_options,
2568
+ GetPlainInternalComparator(options.comparator), &ks, &kvmap);
2569
+ ASSERT_EQ(kvmap.size(),
2570
+ c.GetTableReader()->GetTableProperties()->num_data_blocks);
2571
+ c.ResetTableReader();
2572
+ }
2573
+
2574
+ TEST_P(BlockBasedTableTest, TracingGetTest) {
2575
+ TableConstructor c(BytewiseComparator());
2576
+ Options options;
2577
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
2578
+ options.create_if_missing = true;
2579
+ table_options.block_cache = NewLRUCache(1024 * 1024, 0);
2580
+ table_options.cache_index_and_filter_blocks = true;
2581
+ table_options.filter_policy.reset(NewBloomFilterPolicy(10, true));
2582
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
2583
+ SetupTracingTest(&c);
2584
+ std::vector<std::string> keys;
2585
+ stl_wrappers::KVMap kvmap;
2586
+ ImmutableCFOptions ioptions(options);
2587
+ MutableCFOptions moptions(options);
2588
+ c.Finish(options, ioptions, moptions, table_options,
2589
+ GetPlainInternalComparator(options.comparator), &keys, &kvmap);
2590
+ std::string user_key = "k01";
2591
+ InternalKey internal_key(user_key, 0, kTypeValue);
2592
+ std::string encoded_key = internal_key.Encode().ToString();
2593
+ for (uint32_t i = 1; i <= 2; i++) {
2594
+ PinnableSlice value;
2595
+ GetContext get_context(options.comparator, nullptr, nullptr, nullptr,
2596
+ GetContext::kNotFound, user_key, &value, nullptr,
2597
+ nullptr, true, nullptr, nullptr, nullptr, nullptr,
2598
+ nullptr, nullptr, /*tracing_get_id=*/i);
2599
+ get_perf_context()->Reset();
2600
+ ASSERT_OK(c.GetTableReader()->Get(ReadOptions(), encoded_key, &get_context,
2601
+ moptions.prefix_extractor.get()));
2602
+ ASSERT_EQ(get_context.State(), GetContext::kFound);
2603
+ ASSERT_EQ(value.ToString(), kDummyValue);
2604
+ }
2605
+
2606
+ // Verify traces.
2607
+ std::vector<BlockCacheTraceRecord> expected_records;
2608
+ // The first two records should be prefetching index and filter blocks.
2609
+ BlockCacheTraceRecord record;
2610
+ record.block_type = TraceType::kBlockTraceIndexBlock;
2611
+ record.caller = TableReaderCaller::kPrefetch;
2612
+ record.is_cache_hit = Boolean::kFalse;
2613
+ record.no_insert = Boolean::kFalse;
2614
+ expected_records.push_back(record);
2615
+ record.block_type = TraceType::kBlockTraceFilterBlock;
2616
+ expected_records.push_back(record);
2617
+ // Then we should have three records for one index, one filter, and one data
2618
+ // block access.
2619
+ record.get_id = 1;
2620
+ record.block_type = TraceType::kBlockTraceIndexBlock;
2621
+ record.caller = TableReaderCaller::kUserGet;
2622
+ record.get_from_user_specified_snapshot = Boolean::kFalse;
2623
+ record.referenced_key = encoded_key;
2624
+ record.referenced_key_exist_in_block = Boolean::kTrue;
2625
+ record.is_cache_hit = Boolean::kTrue;
2626
+ expected_records.push_back(record);
2627
+ record.block_type = TraceType::kBlockTraceFilterBlock;
2628
+ expected_records.push_back(record);
2629
+ record.is_cache_hit = Boolean::kFalse;
2630
+ record.block_type = TraceType::kBlockTraceDataBlock;
2631
+ expected_records.push_back(record);
2632
+ // The second get should all observe cache hits.
2633
+ record.is_cache_hit = Boolean::kTrue;
2634
+ record.get_id = 2;
2635
+ record.block_type = TraceType::kBlockTraceIndexBlock;
2636
+ record.caller = TableReaderCaller::kUserGet;
2637
+ record.get_from_user_specified_snapshot = Boolean::kFalse;
2638
+ record.referenced_key = encoded_key;
2639
+ expected_records.push_back(record);
2640
+ record.block_type = TraceType::kBlockTraceFilterBlock;
2641
+ expected_records.push_back(record);
2642
+ record.block_type = TraceType::kBlockTraceDataBlock;
2643
+ expected_records.push_back(record);
2644
+ VerifyBlockAccessTrace(&c, expected_records);
2645
+ c.ResetTableReader();
2646
+ }
2647
+
2648
+ TEST_P(BlockBasedTableTest, TracingApproximateOffsetOfTest) {
2649
+ TableConstructor c(BytewiseComparator());
2650
+ Options options;
2651
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
2652
+ options.create_if_missing = true;
2653
+ table_options.block_cache = NewLRUCache(1024 * 1024, 0);
2654
+ table_options.cache_index_and_filter_blocks = true;
2655
+ table_options.filter_policy.reset(NewBloomFilterPolicy(10, true));
2656
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
2657
+ SetupTracingTest(&c);
2658
+ std::vector<std::string> keys;
2659
+ stl_wrappers::KVMap kvmap;
2660
+ ImmutableCFOptions ioptions(options);
2661
+ MutableCFOptions moptions(options);
2662
+ c.Finish(options, ioptions, moptions, table_options,
2663
+ GetPlainInternalComparator(options.comparator), &keys, &kvmap);
2664
+ for (uint32_t i = 1; i <= 2; i++) {
2665
+ std::string user_key = "k01";
2666
+ InternalKey internal_key(user_key, 0, kTypeValue);
2667
+ std::string encoded_key = internal_key.Encode().ToString();
2668
+ c.GetTableReader()->ApproximateOffsetOf(
2669
+ encoded_key, TableReaderCaller::kUserApproximateSize);
2670
+ }
2671
+ // Verify traces.
2672
+ std::vector<BlockCacheTraceRecord> expected_records;
2673
+ // The first two records should be prefetching index and filter blocks.
2674
+ BlockCacheTraceRecord record;
2675
+ record.block_type = TraceType::kBlockTraceIndexBlock;
2676
+ record.caller = TableReaderCaller::kPrefetch;
2677
+ record.is_cache_hit = Boolean::kFalse;
2678
+ record.no_insert = Boolean::kFalse;
2679
+ expected_records.push_back(record);
2680
+ record.block_type = TraceType::kBlockTraceFilterBlock;
2681
+ expected_records.push_back(record);
2682
+ // Then we should have two records for only index blocks.
2683
+ record.block_type = TraceType::kBlockTraceIndexBlock;
2684
+ record.caller = TableReaderCaller::kUserApproximateSize;
2685
+ record.is_cache_hit = Boolean::kTrue;
2686
+ expected_records.push_back(record);
2687
+ expected_records.push_back(record);
2688
+ VerifyBlockAccessTrace(&c, expected_records);
2689
+ c.ResetTableReader();
2690
+ }
2691
+
2692
+ TEST_P(BlockBasedTableTest, TracingIterator) {
2693
+ TableConstructor c(BytewiseComparator());
2694
+ Options options;
2695
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
2696
+ options.create_if_missing = true;
2697
+ table_options.block_cache = NewLRUCache(1024 * 1024, 0);
2698
+ table_options.cache_index_and_filter_blocks = true;
2699
+ table_options.filter_policy.reset(NewBloomFilterPolicy(10, true));
2700
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
2701
+ SetupTracingTest(&c);
2702
+ std::vector<std::string> keys;
2703
+ stl_wrappers::KVMap kvmap;
2704
+ ImmutableCFOptions ioptions(options);
2705
+ MutableCFOptions moptions(options);
2706
+ c.Finish(options, ioptions, moptions, table_options,
2707
+ GetPlainInternalComparator(options.comparator), &keys, &kvmap);
2708
+
2709
+ for (uint32_t i = 1; i <= 2; i++) {
2710
+ ReadOptions read_options;
2711
+ std::unique_ptr<InternalIterator> iter(c.GetTableReader()->NewIterator(
2712
+ read_options, moptions.prefix_extractor.get(), /*arena=*/nullptr,
2713
+ /*skip_filters=*/false, TableReaderCaller::kUserIterator));
2714
+ iter->SeekToFirst();
2715
+ while (iter->Valid()) {
2716
+ iter->key();
2717
+ iter->value();
2718
+ iter->Next();
2719
+ }
2720
+ ASSERT_OK(iter->status());
2721
+ iter.reset();
2722
+ }
2723
+
2724
+ // Verify traces.
2725
+ std::vector<BlockCacheTraceRecord> expected_records;
2726
+ // The first two records should be prefetching index and filter blocks.
2727
+ BlockCacheTraceRecord record;
2728
+ record.block_type = TraceType::kBlockTraceIndexBlock;
2729
+ record.caller = TableReaderCaller::kPrefetch;
2730
+ record.is_cache_hit = Boolean::kFalse;
2731
+ record.no_insert = Boolean::kFalse;
2732
+ expected_records.push_back(record);
2733
+ record.block_type = TraceType::kBlockTraceFilterBlock;
2734
+ expected_records.push_back(record);
2735
+ // Then we should have three records for index and two data block access.
2736
+ record.block_type = TraceType::kBlockTraceIndexBlock;
2737
+ record.caller = TableReaderCaller::kUserIterator;
2738
+ record.is_cache_hit = Boolean::kTrue;
2739
+ expected_records.push_back(record);
2740
+ record.block_type = TraceType::kBlockTraceDataBlock;
2741
+ record.is_cache_hit = Boolean::kFalse;
2742
+ expected_records.push_back(record);
2743
+ expected_records.push_back(record);
2744
+ // When we iterate this file for the second time, we should observe all cache
2745
+ // hits.
2746
+ record.block_type = TraceType::kBlockTraceIndexBlock;
2747
+ record.is_cache_hit = Boolean::kTrue;
2748
+ expected_records.push_back(record);
2749
+ record.block_type = TraceType::kBlockTraceDataBlock;
2750
+ expected_records.push_back(record);
2751
+ expected_records.push_back(record);
2752
+ VerifyBlockAccessTrace(&c, expected_records);
2753
+ c.ResetTableReader();
2754
+ }
2755
+
2756
+ // A simple tool that takes the snapshot of block cache statistics.
2757
+ class BlockCachePropertiesSnapshot {
2758
+ public:
2759
+ explicit BlockCachePropertiesSnapshot(Statistics* statistics) {
2760
+ block_cache_miss = statistics->getTickerCount(BLOCK_CACHE_MISS);
2761
+ block_cache_hit = statistics->getTickerCount(BLOCK_CACHE_HIT);
2762
+ index_block_cache_miss = statistics->getTickerCount(BLOCK_CACHE_INDEX_MISS);
2763
+ index_block_cache_hit = statistics->getTickerCount(BLOCK_CACHE_INDEX_HIT);
2764
+ data_block_cache_miss = statistics->getTickerCount(BLOCK_CACHE_DATA_MISS);
2765
+ data_block_cache_hit = statistics->getTickerCount(BLOCK_CACHE_DATA_HIT);
2766
+ filter_block_cache_miss =
2767
+ statistics->getTickerCount(BLOCK_CACHE_FILTER_MISS);
2768
+ filter_block_cache_hit = statistics->getTickerCount(BLOCK_CACHE_FILTER_HIT);
2769
+ block_cache_bytes_read = statistics->getTickerCount(BLOCK_CACHE_BYTES_READ);
2770
+ block_cache_bytes_write =
2771
+ statistics->getTickerCount(BLOCK_CACHE_BYTES_WRITE);
2772
+ }
2773
+
2774
+ void AssertIndexBlockStat(int64_t expected_index_block_cache_miss,
2775
+ int64_t expected_index_block_cache_hit) {
2776
+ ASSERT_EQ(expected_index_block_cache_miss, index_block_cache_miss);
2777
+ ASSERT_EQ(expected_index_block_cache_hit, index_block_cache_hit);
2778
+ }
2779
+
2780
+ void AssertFilterBlockStat(int64_t expected_filter_block_cache_miss,
2781
+ int64_t expected_filter_block_cache_hit) {
2782
+ ASSERT_EQ(expected_filter_block_cache_miss, filter_block_cache_miss);
2783
+ ASSERT_EQ(expected_filter_block_cache_hit, filter_block_cache_hit);
2784
+ }
2785
+
2786
+ // Check if the fetched props matches the expected ones.
2787
+ // TODO(kailiu) Use this only when you disabled filter policy!
2788
+ void AssertEqual(int64_t expected_index_block_cache_miss,
2789
+ int64_t expected_index_block_cache_hit,
2790
+ int64_t expected_data_block_cache_miss,
2791
+ int64_t expected_data_block_cache_hit) const {
2792
+ ASSERT_EQ(expected_index_block_cache_miss, index_block_cache_miss);
2793
+ ASSERT_EQ(expected_index_block_cache_hit, index_block_cache_hit);
2794
+ ASSERT_EQ(expected_data_block_cache_miss, data_block_cache_miss);
2795
+ ASSERT_EQ(expected_data_block_cache_hit, data_block_cache_hit);
2796
+ ASSERT_EQ(expected_index_block_cache_miss + expected_data_block_cache_miss,
2797
+ block_cache_miss);
2798
+ ASSERT_EQ(expected_index_block_cache_hit + expected_data_block_cache_hit,
2799
+ block_cache_hit);
2800
+ }
2801
+
2802
+ int64_t GetCacheBytesRead() { return block_cache_bytes_read; }
2803
+
2804
+ int64_t GetCacheBytesWrite() { return block_cache_bytes_write; }
2805
+
2806
+ private:
2807
+ int64_t block_cache_miss = 0;
2808
+ int64_t block_cache_hit = 0;
2809
+ int64_t index_block_cache_miss = 0;
2810
+ int64_t index_block_cache_hit = 0;
2811
+ int64_t data_block_cache_miss = 0;
2812
+ int64_t data_block_cache_hit = 0;
2813
+ int64_t filter_block_cache_miss = 0;
2814
+ int64_t filter_block_cache_hit = 0;
2815
+ int64_t block_cache_bytes_read = 0;
2816
+ int64_t block_cache_bytes_write = 0;
2817
+ };
2818
+
2819
+ // Make sure, by default, index/filter blocks were pre-loaded (meaning we won't
2820
+ // use block cache to store them).
2821
+ TEST_P(BlockBasedTableTest, BlockCacheDisabledTest) {
2822
+ Options options;
2823
+ options.create_if_missing = true;
2824
+ options.statistics = CreateDBStatistics();
2825
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
2826
+ table_options.block_cache = NewLRUCache(1024, 4);
2827
+ table_options.filter_policy.reset(NewBloomFilterPolicy(10));
2828
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
2829
+ std::vector<std::string> keys;
2830
+ stl_wrappers::KVMap kvmap;
2831
+
2832
+ TableConstructor c(BytewiseComparator(), true /* convert_to_internal_key_ */);
2833
+ c.Add("key", "value");
2834
+ const ImmutableCFOptions ioptions(options);
2835
+ const MutableCFOptions moptions(options);
2836
+ c.Finish(options, ioptions, moptions, table_options,
2837
+ GetPlainInternalComparator(options.comparator), &keys, &kvmap);
2838
+
2839
+ // preloading filter/index blocks is enabled.
2840
+ auto reader = dynamic_cast<BlockBasedTable*>(c.GetTableReader());
2841
+ ASSERT_FALSE(reader->TEST_FilterBlockInCache());
2842
+ ASSERT_FALSE(reader->TEST_IndexBlockInCache());
2843
+
2844
+ {
2845
+ // nothing happens in the beginning
2846
+ BlockCachePropertiesSnapshot props(options.statistics.get());
2847
+ props.AssertIndexBlockStat(0, 0);
2848
+ props.AssertFilterBlockStat(0, 0);
2849
+ }
2850
+
2851
+ {
2852
+ GetContext get_context(options.comparator, nullptr, nullptr, nullptr,
2853
+ GetContext::kNotFound, Slice(), nullptr, nullptr,
2854
+ nullptr, true, nullptr, nullptr);
2855
+ // a hack that just to trigger BlockBasedTable::GetFilter.
2856
+ ASSERT_OK(reader->Get(ReadOptions(), "non-exist-key", &get_context,
2857
+ moptions.prefix_extractor.get()));
2858
+ BlockCachePropertiesSnapshot props(options.statistics.get());
2859
+ props.AssertIndexBlockStat(0, 0);
2860
+ props.AssertFilterBlockStat(0, 0);
2861
+ }
2862
+ }
2863
+
2864
+ // Due to the difficulities of the intersaction between statistics, this test
2865
+ // only tests the case when "index block is put to block cache"
2866
+ TEST_P(BlockBasedTableTest, FilterBlockInBlockCache) {
2867
+ // -- Table construction
2868
+ Options options;
2869
+ options.create_if_missing = true;
2870
+ options.statistics = CreateDBStatistics();
2871
+
2872
+ // Enable the cache for index/filter blocks
2873
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
2874
+ LRUCacheOptions co;
2875
+ co.capacity = 2048;
2876
+ co.num_shard_bits = 2;
2877
+ co.metadata_charge_policy = kDontChargeCacheMetadata;
2878
+ table_options.block_cache = NewLRUCache(co);
2879
+ table_options.cache_index_and_filter_blocks = true;
2880
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
2881
+ std::vector<std::string> keys;
2882
+ stl_wrappers::KVMap kvmap;
2883
+
2884
+ TableConstructor c(BytewiseComparator(), true /* convert_to_internal_key_ */);
2885
+ c.Add("key", "value");
2886
+ const ImmutableCFOptions ioptions(options);
2887
+ const MutableCFOptions moptions(options);
2888
+ c.Finish(options, ioptions, moptions, table_options,
2889
+ GetPlainInternalComparator(options.comparator), &keys, &kvmap);
2890
+ // preloading filter/index blocks is prohibited.
2891
+ auto* reader = dynamic_cast<BlockBasedTable*>(c.GetTableReader());
2892
+ ASSERT_FALSE(reader->TEST_FilterBlockInCache());
2893
+ ASSERT_TRUE(reader->TEST_IndexBlockInCache());
2894
+
2895
+ // -- PART 1: Open with regular block cache.
2896
+ // Since block_cache is disabled, no cache activities will be involved.
2897
+ std::unique_ptr<InternalIterator> iter;
2898
+
2899
+ int64_t last_cache_bytes_read = 0;
2900
+ // At first, no block will be accessed.
2901
+ {
2902
+ BlockCachePropertiesSnapshot props(options.statistics.get());
2903
+ // index will be added to block cache.
2904
+ props.AssertEqual(1, // index block miss
2905
+ 0, 0, 0);
2906
+ ASSERT_EQ(props.GetCacheBytesRead(), 0);
2907
+ ASSERT_EQ(props.GetCacheBytesWrite(),
2908
+ static_cast<int64_t>(table_options.block_cache->GetUsage()));
2909
+ last_cache_bytes_read = props.GetCacheBytesRead();
2910
+ }
2911
+
2912
+ // Only index block will be accessed
2913
+ {
2914
+ iter.reset(c.NewIterator(moptions.prefix_extractor.get()));
2915
+ BlockCachePropertiesSnapshot props(options.statistics.get());
2916
+ // NOTE: to help better highlight the "detla" of each ticker, I use
2917
+ // <last_value> + <added_value> to indicate the increment of changed
2918
+ // value; other numbers remain the same.
2919
+ props.AssertEqual(1, 0 + 1, // index block hit
2920
+ 0, 0);
2921
+ // Cache hit, bytes read from cache should increase
2922
+ ASSERT_GT(props.GetCacheBytesRead(), last_cache_bytes_read);
2923
+ ASSERT_EQ(props.GetCacheBytesWrite(),
2924
+ static_cast<int64_t>(table_options.block_cache->GetUsage()));
2925
+ last_cache_bytes_read = props.GetCacheBytesRead();
2926
+ }
2927
+
2928
+ // Only data block will be accessed
2929
+ {
2930
+ iter->SeekToFirst();
2931
+ ASSERT_OK(iter->status());
2932
+ BlockCachePropertiesSnapshot props(options.statistics.get());
2933
+ props.AssertEqual(1, 1, 0 + 1, // data block miss
2934
+ 0);
2935
+ // Cache miss, Bytes read from cache should not change
2936
+ ASSERT_EQ(props.GetCacheBytesRead(), last_cache_bytes_read);
2937
+ ASSERT_EQ(props.GetCacheBytesWrite(),
2938
+ static_cast<int64_t>(table_options.block_cache->GetUsage()));
2939
+ last_cache_bytes_read = props.GetCacheBytesRead();
2940
+ }
2941
+
2942
+ // Data block will be in cache
2943
+ {
2944
+ iter.reset(c.NewIterator(moptions.prefix_extractor.get()));
2945
+ iter->SeekToFirst();
2946
+ ASSERT_OK(iter->status());
2947
+ BlockCachePropertiesSnapshot props(options.statistics.get());
2948
+ props.AssertEqual(1, 1 + 1, /* index block hit */
2949
+ 1, 0 + 1 /* data block hit */);
2950
+ // Cache hit, bytes read from cache should increase
2951
+ ASSERT_GT(props.GetCacheBytesRead(), last_cache_bytes_read);
2952
+ ASSERT_EQ(props.GetCacheBytesWrite(),
2953
+ static_cast<int64_t>(table_options.block_cache->GetUsage()));
2954
+ }
2955
+ // release the iterator so that the block cache can reset correctly.
2956
+ iter.reset();
2957
+
2958
+ c.ResetTableReader();
2959
+
2960
+ // -- PART 2: Open with very small block cache
2961
+ // In this test, no block will ever get hit since the block cache is
2962
+ // too small to fit even one entry.
2963
+ table_options.block_cache = NewLRUCache(1, 4);
2964
+ options.statistics = CreateDBStatistics();
2965
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
2966
+ const ImmutableCFOptions ioptions2(options);
2967
+ const MutableCFOptions moptions2(options);
2968
+ ASSERT_OK(c.Reopen(ioptions2, moptions2));
2969
+ {
2970
+ BlockCachePropertiesSnapshot props(options.statistics.get());
2971
+ props.AssertEqual(1, // index block miss
2972
+ 0, 0, 0);
2973
+ // Cache miss, Bytes read from cache should not change
2974
+ ASSERT_EQ(props.GetCacheBytesRead(), 0);
2975
+ }
2976
+
2977
+ {
2978
+ // Both index and data block get accessed.
2979
+ // It first cache index block then data block. But since the cache size
2980
+ // is only 1, index block will be purged after data block is inserted.
2981
+ iter.reset(c.NewIterator(moptions2.prefix_extractor.get()));
2982
+ BlockCachePropertiesSnapshot props(options.statistics.get());
2983
+ props.AssertEqual(1 + 1, // index block miss
2984
+ 0, 0, // data block miss
2985
+ 0);
2986
+ // Cache hit, bytes read from cache should increase
2987
+ ASSERT_EQ(props.GetCacheBytesRead(), 0);
2988
+ }
2989
+
2990
+ {
2991
+ // SeekToFirst() accesses data block. With similar reason, we expect data
2992
+ // block's cache miss.
2993
+ iter->SeekToFirst();
2994
+ ASSERT_OK(iter->status());
2995
+ BlockCachePropertiesSnapshot props(options.statistics.get());
2996
+ props.AssertEqual(2, 0, 0 + 1, // data block miss
2997
+ 0);
2998
+ // Cache miss, Bytes read from cache should not change
2999
+ ASSERT_EQ(props.GetCacheBytesRead(), 0);
3000
+ }
3001
+ iter.reset();
3002
+ c.ResetTableReader();
3003
+
3004
+ // -- PART 3: Open table with bloom filter enabled but not in SST file
3005
+ table_options.block_cache = NewLRUCache(4096, 4);
3006
+ table_options.cache_index_and_filter_blocks = false;
3007
+ options.table_factory.reset(NewBlockBasedTableFactory(table_options));
3008
+
3009
+ TableConstructor c3(BytewiseComparator());
3010
+ std::string user_key = "k01";
3011
+ InternalKey internal_key(user_key, 0, kTypeValue);
3012
+ c3.Add(internal_key.Encode().ToString(), "hello");
3013
+ ImmutableCFOptions ioptions3(options);
3014
+ MutableCFOptions moptions3(options);
3015
+ // Generate table without filter policy
3016
+ c3.Finish(options, ioptions3, moptions3, table_options,
3017
+ GetPlainInternalComparator(options.comparator), &keys, &kvmap);
3018
+ c3.ResetTableReader();
3019
+
3020
+ // Open table with filter policy
3021
+ table_options.filter_policy.reset(NewBloomFilterPolicy(1));
3022
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
3023
+ options.statistics = CreateDBStatistics();
3024
+ ImmutableCFOptions ioptions4(options);
3025
+ MutableCFOptions moptions4(options);
3026
+ ASSERT_OK(c3.Reopen(ioptions4, moptions4));
3027
+ reader = dynamic_cast<BlockBasedTable*>(c3.GetTableReader());
3028
+ ASSERT_FALSE(reader->TEST_FilterBlockInCache());
3029
+ PinnableSlice value;
3030
+ GetContext get_context(options.comparator, nullptr, nullptr, nullptr,
3031
+ GetContext::kNotFound, user_key, &value, nullptr,
3032
+ nullptr, true, nullptr, nullptr);
3033
+ ASSERT_OK(reader->Get(ReadOptions(), internal_key.Encode(), &get_context,
3034
+ moptions4.prefix_extractor.get()));
3035
+ ASSERT_STREQ(value.data(), "hello");
3036
+ BlockCachePropertiesSnapshot props(options.statistics.get());
3037
+ props.AssertFilterBlockStat(0, 0);
3038
+ c3.ResetTableReader();
3039
+ }
3040
+
3041
+ void ValidateBlockSizeDeviation(int value, int expected) {
3042
+ BlockBasedTableOptions table_options;
3043
+ table_options.block_size_deviation = value;
3044
+ BlockBasedTableFactory* factory = new BlockBasedTableFactory(table_options);
3045
+
3046
+ const BlockBasedTableOptions* normalized_table_options =
3047
+ factory->GetOptions<BlockBasedTableOptions>();
3048
+ ASSERT_EQ(normalized_table_options->block_size_deviation, expected);
3049
+
3050
+ delete factory;
3051
+ }
3052
+
3053
+ void ValidateBlockRestartInterval(int value, int expected) {
3054
+ BlockBasedTableOptions table_options;
3055
+ table_options.block_restart_interval = value;
3056
+ BlockBasedTableFactory* factory = new BlockBasedTableFactory(table_options);
3057
+
3058
+ const BlockBasedTableOptions* normalized_table_options =
3059
+ factory->GetOptions<BlockBasedTableOptions>();
3060
+ ASSERT_EQ(normalized_table_options->block_restart_interval, expected);
3061
+
3062
+ delete factory;
3063
+ }
3064
+
3065
+ TEST_P(BlockBasedTableTest, InvalidOptions) {
3066
+ // invalid values for block_size_deviation (<0 or >100) are silently set to 0
3067
+ ValidateBlockSizeDeviation(-10, 0);
3068
+ ValidateBlockSizeDeviation(-1, 0);
3069
+ ValidateBlockSizeDeviation(0, 0);
3070
+ ValidateBlockSizeDeviation(1, 1);
3071
+ ValidateBlockSizeDeviation(99, 99);
3072
+ ValidateBlockSizeDeviation(100, 100);
3073
+ ValidateBlockSizeDeviation(101, 0);
3074
+ ValidateBlockSizeDeviation(1000, 0);
3075
+
3076
+ // invalid values for block_restart_interval (<1) are silently set to 1
3077
+ ValidateBlockRestartInterval(-10, 1);
3078
+ ValidateBlockRestartInterval(-1, 1);
3079
+ ValidateBlockRestartInterval(0, 1);
3080
+ ValidateBlockRestartInterval(1, 1);
3081
+ ValidateBlockRestartInterval(2, 2);
3082
+ ValidateBlockRestartInterval(1000, 1000);
3083
+ }
3084
+
3085
+ TEST_P(BlockBasedTableTest, BlockReadCountTest) {
3086
+ // bloom_filter_type = 0 -- block-based filter
3087
+ // bloom_filter_type = 0 -- full filter
3088
+ for (int bloom_filter_type = 0; bloom_filter_type < 2; ++bloom_filter_type) {
3089
+ for (int index_and_filter_in_cache = 0; index_and_filter_in_cache < 2;
3090
+ ++index_and_filter_in_cache) {
3091
+ Options options;
3092
+ options.create_if_missing = true;
3093
+
3094
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
3095
+ table_options.block_cache = NewLRUCache(1, 0);
3096
+ table_options.cache_index_and_filter_blocks = index_and_filter_in_cache;
3097
+ table_options.filter_policy.reset(
3098
+ NewBloomFilterPolicy(10, bloom_filter_type == 0));
3099
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
3100
+ std::vector<std::string> keys;
3101
+ stl_wrappers::KVMap kvmap;
3102
+
3103
+ TableConstructor c(BytewiseComparator());
3104
+ std::string user_key = "k04";
3105
+ InternalKey internal_key(user_key, 0, kTypeValue);
3106
+ std::string encoded_key = internal_key.Encode().ToString();
3107
+ c.Add(encoded_key, "hello");
3108
+ ImmutableCFOptions ioptions(options);
3109
+ MutableCFOptions moptions(options);
3110
+ // Generate table with filter policy
3111
+ c.Finish(options, ioptions, moptions, table_options,
3112
+ GetPlainInternalComparator(options.comparator), &keys, &kvmap);
3113
+ auto reader = c.GetTableReader();
3114
+ PinnableSlice value;
3115
+ {
3116
+ GetContext get_context(options.comparator, nullptr, nullptr, nullptr,
3117
+ GetContext::kNotFound, user_key, &value, nullptr,
3118
+ nullptr, true, nullptr, nullptr);
3119
+ get_perf_context()->Reset();
3120
+ ASSERT_OK(reader->Get(ReadOptions(), encoded_key, &get_context,
3121
+ moptions.prefix_extractor.get()));
3122
+ if (index_and_filter_in_cache) {
3123
+ // data, index and filter block
3124
+ ASSERT_EQ(get_perf_context()->block_read_count, 3);
3125
+ ASSERT_EQ(get_perf_context()->index_block_read_count, 1);
3126
+ ASSERT_EQ(get_perf_context()->filter_block_read_count, 1);
3127
+ } else {
3128
+ // just the data block
3129
+ ASSERT_EQ(get_perf_context()->block_read_count, 1);
3130
+ }
3131
+ ASSERT_EQ(get_context.State(), GetContext::kFound);
3132
+ ASSERT_STREQ(value.data(), "hello");
3133
+ }
3134
+
3135
+ // Get non-existing key
3136
+ user_key = "does-not-exist";
3137
+ internal_key = InternalKey(user_key, 0, kTypeValue);
3138
+ encoded_key = internal_key.Encode().ToString();
3139
+
3140
+ value.Reset();
3141
+ {
3142
+ GetContext get_context(options.comparator, nullptr, nullptr, nullptr,
3143
+ GetContext::kNotFound, user_key, &value, nullptr,
3144
+ nullptr, true, nullptr, nullptr);
3145
+ get_perf_context()->Reset();
3146
+ ASSERT_OK(reader->Get(ReadOptions(), encoded_key, &get_context,
3147
+ moptions.prefix_extractor.get()));
3148
+ ASSERT_EQ(get_context.State(), GetContext::kNotFound);
3149
+ }
3150
+
3151
+ if (index_and_filter_in_cache) {
3152
+ if (bloom_filter_type == 0) {
3153
+ // with block-based, we read index and then the filter
3154
+ ASSERT_EQ(get_perf_context()->block_read_count, 2);
3155
+ ASSERT_EQ(get_perf_context()->index_block_read_count, 1);
3156
+ ASSERT_EQ(get_perf_context()->filter_block_read_count, 1);
3157
+ } else {
3158
+ // with full-filter, we read filter first and then we stop
3159
+ ASSERT_EQ(get_perf_context()->block_read_count, 1);
3160
+ ASSERT_EQ(get_perf_context()->filter_block_read_count, 1);
3161
+ }
3162
+ } else {
3163
+ // filter is already in memory and it figures out that the key doesn't
3164
+ // exist
3165
+ ASSERT_EQ(get_perf_context()->block_read_count, 0);
3166
+ }
3167
+ }
3168
+ }
3169
+ }
3170
+
3171
+ TEST_P(BlockBasedTableTest, BlockCacheLeak) {
3172
+ // Check that when we reopen a table we don't lose access to blocks already
3173
+ // in the cache. This test checks whether the Table actually makes use of the
3174
+ // unique ID from the file.
3175
+
3176
+ Options opt;
3177
+ std::unique_ptr<InternalKeyComparator> ikc;
3178
+ ikc.reset(new test::PlainInternalKeyComparator(opt.comparator));
3179
+ opt.compression = kNoCompression;
3180
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
3181
+ table_options.block_size = 1024;
3182
+ // big enough so we don't ever lose cached values.
3183
+ table_options.block_cache = NewLRUCache(16 * 1024 * 1024, 4);
3184
+ opt.table_factory.reset(NewBlockBasedTableFactory(table_options));
3185
+
3186
+ TableConstructor c(BytewiseComparator(), true /* convert_to_internal_key_ */);
3187
+ c.Add("k01", "hello");
3188
+ c.Add("k02", "hello2");
3189
+ c.Add("k03", std::string(10000, 'x'));
3190
+ c.Add("k04", std::string(200000, 'x'));
3191
+ c.Add("k05", std::string(300000, 'x'));
3192
+ c.Add("k06", "hello3");
3193
+ c.Add("k07", std::string(100000, 'x'));
3194
+ std::vector<std::string> keys;
3195
+ stl_wrappers::KVMap kvmap;
3196
+ const ImmutableCFOptions ioptions(opt);
3197
+ const MutableCFOptions moptions(opt);
3198
+ c.Finish(opt, ioptions, moptions, table_options, *ikc, &keys, &kvmap);
3199
+
3200
+ std::unique_ptr<InternalIterator> iter(
3201
+ c.NewIterator(moptions.prefix_extractor.get()));
3202
+ iter->SeekToFirst();
3203
+ while (iter->Valid()) {
3204
+ iter->key();
3205
+ iter->value();
3206
+ iter->Next();
3207
+ }
3208
+ ASSERT_OK(iter->status());
3209
+ iter.reset();
3210
+
3211
+ const ImmutableCFOptions ioptions1(opt);
3212
+ const MutableCFOptions moptions1(opt);
3213
+ ASSERT_OK(c.Reopen(ioptions1, moptions1));
3214
+ auto table_reader = dynamic_cast<BlockBasedTable*>(c.GetTableReader());
3215
+ for (const std::string& key : keys) {
3216
+ InternalKey ikey(key, kMaxSequenceNumber, kTypeValue);
3217
+ ASSERT_TRUE(table_reader->TEST_KeyInCache(ReadOptions(), ikey.Encode()));
3218
+ }
3219
+ c.ResetTableReader();
3220
+
3221
+ // rerun with different block cache
3222
+ table_options.block_cache = NewLRUCache(16 * 1024 * 1024, 4);
3223
+ opt.table_factory.reset(NewBlockBasedTableFactory(table_options));
3224
+ const ImmutableCFOptions ioptions2(opt);
3225
+ const MutableCFOptions moptions2(opt);
3226
+ ASSERT_OK(c.Reopen(ioptions2, moptions2));
3227
+ table_reader = dynamic_cast<BlockBasedTable*>(c.GetTableReader());
3228
+ for (const std::string& key : keys) {
3229
+ InternalKey ikey(key, kMaxSequenceNumber, kTypeValue);
3230
+ ASSERT_TRUE(!table_reader->TEST_KeyInCache(ReadOptions(), ikey.Encode()));
3231
+ }
3232
+ c.ResetTableReader();
3233
+ }
3234
+
3235
+ namespace {
3236
+ class CustomMemoryAllocator : public MemoryAllocator {
3237
+ public:
3238
+ const char* Name() const override { return "CustomMemoryAllocator"; }
3239
+
3240
+ void* Allocate(size_t size) override {
3241
+ ++numAllocations;
3242
+ auto ptr = new char[size + 16];
3243
+ memcpy(ptr, "memory_allocator_", 16); // mangle first 16 bytes
3244
+ return reinterpret_cast<void*>(ptr + 16);
3245
+ }
3246
+ void Deallocate(void* p) override {
3247
+ ++numDeallocations;
3248
+ char* ptr = reinterpret_cast<char*>(p) - 16;
3249
+ delete[] ptr;
3250
+ }
3251
+
3252
+ std::atomic<int> numAllocations;
3253
+ std::atomic<int> numDeallocations;
3254
+ };
3255
+ } // namespace
3256
+
3257
+ TEST_P(BlockBasedTableTest, MemoryAllocator) {
3258
+ auto custom_memory_allocator = std::make_shared<CustomMemoryAllocator>();
3259
+ {
3260
+ Options opt;
3261
+ std::unique_ptr<InternalKeyComparator> ikc;
3262
+ ikc.reset(new test::PlainInternalKeyComparator(opt.comparator));
3263
+ opt.compression = kNoCompression;
3264
+ BlockBasedTableOptions table_options;
3265
+ table_options.block_size = 1024;
3266
+ LRUCacheOptions lruOptions;
3267
+ lruOptions.memory_allocator = custom_memory_allocator;
3268
+ lruOptions.capacity = 16 * 1024 * 1024;
3269
+ lruOptions.num_shard_bits = 4;
3270
+ table_options.block_cache = NewLRUCache(std::move(lruOptions));
3271
+ opt.table_factory.reset(NewBlockBasedTableFactory(table_options));
3272
+
3273
+ TableConstructor c(BytewiseComparator(),
3274
+ true /* convert_to_internal_key_ */);
3275
+ c.Add("k01", "hello");
3276
+ c.Add("k02", "hello2");
3277
+ c.Add("k03", std::string(10000, 'x'));
3278
+ c.Add("k04", std::string(200000, 'x'));
3279
+ c.Add("k05", std::string(300000, 'x'));
3280
+ c.Add("k06", "hello3");
3281
+ c.Add("k07", std::string(100000, 'x'));
3282
+ std::vector<std::string> keys;
3283
+ stl_wrappers::KVMap kvmap;
3284
+ const ImmutableCFOptions ioptions(opt);
3285
+ const MutableCFOptions moptions(opt);
3286
+ c.Finish(opt, ioptions, moptions, table_options, *ikc, &keys, &kvmap);
3287
+
3288
+ std::unique_ptr<InternalIterator> iter(
3289
+ c.NewIterator(moptions.prefix_extractor.get()));
3290
+ iter->SeekToFirst();
3291
+ while (iter->Valid()) {
3292
+ iter->key();
3293
+ iter->value();
3294
+ iter->Next();
3295
+ }
3296
+ ASSERT_OK(iter->status());
3297
+ }
3298
+
3299
+ // out of scope, block cache should have been deleted, all allocations
3300
+ // deallocated
3301
+ EXPECT_EQ(custom_memory_allocator->numAllocations.load(),
3302
+ custom_memory_allocator->numDeallocations.load());
3303
+ // make sure that allocations actually happened through the cache allocator
3304
+ EXPECT_GT(custom_memory_allocator->numAllocations.load(), 0);
3305
+ }
3306
+
3307
+ // Test the file checksum of block based table
3308
+ TEST_P(BlockBasedTableTest, NoFileChecksum) {
3309
+ Options options;
3310
+ ImmutableCFOptions ioptions(options);
3311
+ MutableCFOptions moptions(options);
3312
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
3313
+ std::unique_ptr<InternalKeyComparator> comparator(
3314
+ new InternalKeyComparator(BytewiseComparator()));
3315
+ int level = 0;
3316
+ std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
3317
+ int_tbl_prop_collector_factories;
3318
+ std::string column_family_name;
3319
+
3320
+ FileChecksumTestHelper f(true);
3321
+ f.CreateWriteableFile();
3322
+ std::unique_ptr<TableBuilder> builder;
3323
+ builder.reset(ioptions.table_factory->NewTableBuilder(
3324
+ TableBuilderOptions(ioptions, moptions, *comparator,
3325
+ &int_tbl_prop_collector_factories,
3326
+ options.compression, options.sample_for_compression,
3327
+ options.compression_opts, false /* skip_filters */,
3328
+ column_family_name, level),
3329
+ TablePropertiesCollectorFactory::Context::kUnknownColumnFamily,
3330
+ f.GetFileWriter()));
3331
+ ASSERT_OK(f.ResetTableBuilder(std::move(builder)));
3332
+ f.AddKVtoKVMap(1000);
3333
+ ASSERT_OK(f.WriteKVAndFlushTable());
3334
+ ASSERT_STREQ(f.GetFileChecksumFuncName(), kUnknownFileChecksumFuncName);
3335
+ ASSERT_STREQ(f.GetFileChecksum().c_str(), kUnknownFileChecksum);
3336
+ }
3337
+
3338
+ TEST_P(BlockBasedTableTest, Crc32cFileChecksum) {
3339
+ FileChecksumGenCrc32cFactory* file_checksum_gen_factory =
3340
+ new FileChecksumGenCrc32cFactory();
3341
+ Options options;
3342
+ options.file_checksum_gen_factory.reset(file_checksum_gen_factory);
3343
+ ImmutableCFOptions ioptions(options);
3344
+ MutableCFOptions moptions(options);
3345
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
3346
+ std::unique_ptr<InternalKeyComparator> comparator(
3347
+ new InternalKeyComparator(BytewiseComparator()));
3348
+ int level = 0;
3349
+ std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
3350
+ int_tbl_prop_collector_factories;
3351
+ std::string column_family_name;
3352
+
3353
+ FileChecksumGenContext gen_context;
3354
+ gen_context.file_name = "db/tmp";
3355
+ std::unique_ptr<FileChecksumGenerator> checksum_crc32c_gen1 =
3356
+ options.file_checksum_gen_factory->CreateFileChecksumGenerator(
3357
+ gen_context);
3358
+ FileChecksumTestHelper f(true);
3359
+ f.CreateWriteableFile();
3360
+ f.SetFileChecksumGenerator(checksum_crc32c_gen1.release());
3361
+ std::unique_ptr<TableBuilder> builder;
3362
+ builder.reset(ioptions.table_factory->NewTableBuilder(
3363
+ TableBuilderOptions(ioptions, moptions, *comparator,
3364
+ &int_tbl_prop_collector_factories,
3365
+ options.compression, options.sample_for_compression,
3366
+ options.compression_opts, false /* skip_filters */,
3367
+ column_family_name, level),
3368
+ TablePropertiesCollectorFactory::Context::kUnknownColumnFamily,
3369
+ f.GetFileWriter()));
3370
+ ASSERT_OK(f.ResetTableBuilder(std::move(builder)));
3371
+ f.AddKVtoKVMap(1000);
3372
+ ASSERT_OK(f.WriteKVAndFlushTable());
3373
+ ASSERT_STREQ(f.GetFileChecksumFuncName(), "FileChecksumCrc32c");
3374
+
3375
+ std::unique_ptr<FileChecksumGenerator> checksum_crc32c_gen2 =
3376
+ options.file_checksum_gen_factory->CreateFileChecksumGenerator(
3377
+ gen_context);
3378
+ std::string checksum;
3379
+ ASSERT_OK(f.CalculateFileChecksum(checksum_crc32c_gen2.get(), &checksum));
3380
+ ASSERT_STREQ(f.GetFileChecksum().c_str(), checksum.c_str());
3381
+
3382
+ // Unit test the generator itself for schema stability
3383
+ std::unique_ptr<FileChecksumGenerator> checksum_crc32c_gen3 =
3384
+ options.file_checksum_gen_factory->CreateFileChecksumGenerator(
3385
+ gen_context);
3386
+ const char data[] = "here is some data";
3387
+ checksum_crc32c_gen3->Update(data, sizeof(data));
3388
+ checksum_crc32c_gen3->Finalize();
3389
+ checksum = checksum_crc32c_gen3->GetChecksum();
3390
+ ASSERT_STREQ(checksum.c_str(), "\345\245\277\110");
3391
+ }
3392
+
3393
+ // Plain table is not supported in ROCKSDB_LITE
3394
+ #ifndef ROCKSDB_LITE
3395
+ TEST_F(PlainTableTest, BasicPlainTableProperties) {
3396
+ PlainTableOptions plain_table_options;
3397
+ plain_table_options.user_key_len = 8;
3398
+ plain_table_options.bloom_bits_per_key = 8;
3399
+ plain_table_options.hash_table_ratio = 0;
3400
+
3401
+ PlainTableFactory factory(plain_table_options);
3402
+ std::unique_ptr<FSWritableFile> sink(new test::StringSink());
3403
+ std::unique_ptr<WritableFileWriter> file_writer(new WritableFileWriter(
3404
+ std::move(sink), "" /* don't care */, FileOptions()));
3405
+ Options options;
3406
+ const ImmutableCFOptions ioptions(options);
3407
+ const MutableCFOptions moptions(options);
3408
+ InternalKeyComparator ikc(options.comparator);
3409
+ std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
3410
+ int_tbl_prop_collector_factories;
3411
+ std::string column_family_name;
3412
+ int unknown_level = -1;
3413
+ std::unique_ptr<TableBuilder> builder(factory.NewTableBuilder(
3414
+ TableBuilderOptions(
3415
+ ioptions, moptions, ikc, &int_tbl_prop_collector_factories,
3416
+ kNoCompression, 0 /* sample_for_compression */, CompressionOptions(),
3417
+ false /* skip_filters */, column_family_name, unknown_level),
3418
+ TablePropertiesCollectorFactory::Context::kUnknownColumnFamily,
3419
+ file_writer.get()));
3420
+
3421
+ for (char c = 'a'; c <= 'z'; ++c) {
3422
+ std::string key(8, c);
3423
+ key.append("\1 "); // PlainTable expects internal key structure
3424
+ std::string value(28, c + 42);
3425
+ builder->Add(key, value);
3426
+ }
3427
+ ASSERT_OK(builder->Finish());
3428
+ ASSERT_OK(file_writer->Flush());
3429
+
3430
+ test::StringSink* ss =
3431
+ static_cast<test::StringSink*>(file_writer->writable_file());
3432
+ std::unique_ptr<FSRandomAccessFile> source(
3433
+ new test::StringSource(ss->contents(), 72242, true));
3434
+ std::unique_ptr<RandomAccessFileReader> file_reader(
3435
+ new RandomAccessFileReader(std::move(source), "test"));
3436
+
3437
+ TableProperties* props = nullptr;
3438
+ auto s = ReadTableProperties(file_reader.get(), ss->contents().size(),
3439
+ kPlainTableMagicNumber, ioptions,
3440
+ &props, true /* compression_type_missing */);
3441
+ std::unique_ptr<TableProperties> props_guard(props);
3442
+ ASSERT_OK(s);
3443
+
3444
+ ASSERT_EQ(0ul, props->index_size);
3445
+ ASSERT_EQ(0ul, props->filter_size);
3446
+ ASSERT_EQ(16ul * 26, props->raw_key_size);
3447
+ ASSERT_EQ(28ul * 26, props->raw_value_size);
3448
+ ASSERT_EQ(26ul, props->num_entries);
3449
+ ASSERT_EQ(1ul, props->num_data_blocks);
3450
+ }
3451
+
3452
+ TEST_F(PlainTableTest, NoFileChecksum) {
3453
+ PlainTableOptions plain_table_options;
3454
+ plain_table_options.user_key_len = 20;
3455
+ plain_table_options.bloom_bits_per_key = 8;
3456
+ plain_table_options.hash_table_ratio = 0;
3457
+ PlainTableFactory factory(plain_table_options);
3458
+
3459
+ Options options;
3460
+ const ImmutableCFOptions ioptions(options);
3461
+ const MutableCFOptions moptions(options);
3462
+ InternalKeyComparator ikc(options.comparator);
3463
+ std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
3464
+ int_tbl_prop_collector_factories;
3465
+ std::string column_family_name;
3466
+ int unknown_level = -1;
3467
+ FileChecksumTestHelper f(true);
3468
+ f.CreateWriteableFile();
3469
+
3470
+ std::unique_ptr<TableBuilder> builder(factory.NewTableBuilder(
3471
+ TableBuilderOptions(
3472
+ ioptions, moptions, ikc, &int_tbl_prop_collector_factories,
3473
+ kNoCompression, 0 /* sample_for_compression */, CompressionOptions(),
3474
+ false /* skip_filters */, column_family_name, unknown_level),
3475
+ TablePropertiesCollectorFactory::Context::kUnknownColumnFamily,
3476
+ f.GetFileWriter()));
3477
+ ASSERT_OK(f.ResetTableBuilder(std::move(builder)));
3478
+ f.AddKVtoKVMap(1000);
3479
+ ASSERT_OK(f.WriteKVAndFlushTable());
3480
+ ASSERT_STREQ(f.GetFileChecksumFuncName(), kUnknownFileChecksumFuncName);
3481
+ EXPECT_EQ(f.GetFileChecksum(), kUnknownFileChecksum);
3482
+ }
3483
+
3484
+ TEST_F(PlainTableTest, Crc32cFileChecksum) {
3485
+ PlainTableOptions plain_table_options;
3486
+ plain_table_options.user_key_len = 20;
3487
+ plain_table_options.bloom_bits_per_key = 8;
3488
+ plain_table_options.hash_table_ratio = 0;
3489
+ PlainTableFactory factory(plain_table_options);
3490
+
3491
+ FileChecksumGenCrc32cFactory* file_checksum_gen_factory =
3492
+ new FileChecksumGenCrc32cFactory();
3493
+ Options options;
3494
+ options.file_checksum_gen_factory.reset(file_checksum_gen_factory);
3495
+ const ImmutableCFOptions ioptions(options);
3496
+ const MutableCFOptions moptions(options);
3497
+ InternalKeyComparator ikc(options.comparator);
3498
+ std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
3499
+ int_tbl_prop_collector_factories;
3500
+ std::string column_family_name;
3501
+ int unknown_level = -1;
3502
+
3503
+ FileChecksumGenContext gen_context;
3504
+ gen_context.file_name = "db/tmp";
3505
+ std::unique_ptr<FileChecksumGenerator> checksum_crc32c_gen1 =
3506
+ options.file_checksum_gen_factory->CreateFileChecksumGenerator(
3507
+ gen_context);
3508
+ FileChecksumTestHelper f(true);
3509
+ f.CreateWriteableFile();
3510
+ f.SetFileChecksumGenerator(checksum_crc32c_gen1.release());
3511
+
3512
+ std::unique_ptr<TableBuilder> builder(factory.NewTableBuilder(
3513
+ TableBuilderOptions(
3514
+ ioptions, moptions, ikc, &int_tbl_prop_collector_factories,
3515
+ kNoCompression, 0 /* sample_for_compression */, CompressionOptions(),
3516
+ false /* skip_filters */, column_family_name, unknown_level),
3517
+ TablePropertiesCollectorFactory::Context::kUnknownColumnFamily,
3518
+ f.GetFileWriter()));
3519
+ ASSERT_OK(f.ResetTableBuilder(std::move(builder)));
3520
+ f.AddKVtoKVMap(1000);
3521
+ ASSERT_OK(f.WriteKVAndFlushTable());
3522
+ ASSERT_STREQ(f.GetFileChecksumFuncName(), "FileChecksumCrc32c");
3523
+
3524
+ std::unique_ptr<FileChecksumGenerator> checksum_crc32c_gen2 =
3525
+ options.file_checksum_gen_factory->CreateFileChecksumGenerator(
3526
+ gen_context);
3527
+ std::string checksum;
3528
+ ASSERT_OK(f.CalculateFileChecksum(checksum_crc32c_gen2.get(), &checksum));
3529
+ EXPECT_STREQ(f.GetFileChecksum().c_str(), checksum.c_str());
3530
+ }
3531
+
3532
+ #endif // !ROCKSDB_LITE
3533
+
3534
+ TEST_F(GeneralTableTest, ApproximateOffsetOfPlain) {
3535
+ TableConstructor c(BytewiseComparator(), true /* convert_to_internal_key_ */);
3536
+ c.Add("k01", "hello");
3537
+ c.Add("k02", "hello2");
3538
+ c.Add("k03", std::string(10000, 'x'));
3539
+ c.Add("k04", std::string(200000, 'x'));
3540
+ c.Add("k05", std::string(300000, 'x'));
3541
+ c.Add("k06", "hello3");
3542
+ c.Add("k07", std::string(100000, 'x'));
3543
+ std::vector<std::string> keys;
3544
+ stl_wrappers::KVMap kvmap;
3545
+ Options options;
3546
+ options.db_host_id = "";
3547
+ test::PlainInternalKeyComparator internal_comparator(options.comparator);
3548
+ options.compression = kNoCompression;
3549
+ BlockBasedTableOptions table_options;
3550
+ table_options.block_size = 1024;
3551
+ const ImmutableCFOptions ioptions(options);
3552
+ const MutableCFOptions moptions(options);
3553
+ c.Finish(options, ioptions, moptions, table_options, internal_comparator,
3554
+ &keys, &kvmap);
3555
+
3556
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("abc"), 0, 0));
3557
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01"), 0, 0));
3558
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01a"), 0, 0));
3559
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k02"), 0, 0));
3560
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k03"), 0, 0));
3561
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04"), 10000, 11000));
3562
+ // k04 and k05 will be in two consecutive blocks, the index is
3563
+ // an arbitrary slice between k04 and k05, either before or after k04a
3564
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04a"), 10000, 211000));
3565
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k05"), 210000, 211000));
3566
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k06"), 510000, 511000));
3567
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k07"), 510000, 511000));
3568
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("xyz"), 610000, 612000));
3569
+ c.ResetTableReader();
3570
+ }
3571
+
3572
+ static void DoCompressionTest(CompressionType comp) {
3573
+ Random rnd(301);
3574
+ TableConstructor c(BytewiseComparator(), true /* convert_to_internal_key_ */);
3575
+ std::string tmp;
3576
+ c.Add("k01", "hello");
3577
+ c.Add("k02", test::CompressibleString(&rnd, 0.25, 10000, &tmp));
3578
+ c.Add("k03", "hello3");
3579
+ c.Add("k04", test::CompressibleString(&rnd, 0.25, 10000, &tmp));
3580
+ std::vector<std::string> keys;
3581
+ stl_wrappers::KVMap kvmap;
3582
+ Options options;
3583
+ test::PlainInternalKeyComparator ikc(options.comparator);
3584
+ options.compression = comp;
3585
+ BlockBasedTableOptions table_options;
3586
+ table_options.block_size = 1024;
3587
+ const ImmutableCFOptions ioptions(options);
3588
+ const MutableCFOptions moptions(options);
3589
+ c.Finish(options, ioptions, moptions, table_options, ikc, &keys, &kvmap);
3590
+
3591
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("abc"), 0, 0));
3592
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01"), 0, 0));
3593
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k02"), 0, 0));
3594
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k03"), 2000, 3500));
3595
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04"), 2000, 3500));
3596
+ ASSERT_TRUE(Between(c.ApproximateOffsetOf("xyz"), 4000, 7000));
3597
+ c.ResetTableReader();
3598
+ }
3599
+
3600
+ TEST_F(GeneralTableTest, ApproximateOffsetOfCompressed) {
3601
+ std::vector<CompressionType> compression_state;
3602
+ if (!Snappy_Supported()) {
3603
+ fprintf(stderr, "skipping snappy compression tests\n");
3604
+ } else {
3605
+ compression_state.push_back(kSnappyCompression);
3606
+ }
3607
+
3608
+ if (!Zlib_Supported()) {
3609
+ fprintf(stderr, "skipping zlib compression tests\n");
3610
+ } else {
3611
+ compression_state.push_back(kZlibCompression);
3612
+ }
3613
+
3614
+ // TODO(kailiu) DoCompressionTest() doesn't work with BZip2.
3615
+ /*
3616
+ if (!BZip2_Supported()) {
3617
+ fprintf(stderr, "skipping bzip2 compression tests\n");
3618
+ } else {
3619
+ compression_state.push_back(kBZip2Compression);
3620
+ }
3621
+ */
3622
+
3623
+ if (!LZ4_Supported()) {
3624
+ fprintf(stderr, "skipping lz4 and lz4hc compression tests\n");
3625
+ } else {
3626
+ compression_state.push_back(kLZ4Compression);
3627
+ compression_state.push_back(kLZ4HCCompression);
3628
+ }
3629
+
3630
+ if (!XPRESS_Supported()) {
3631
+ fprintf(stderr, "skipping xpress and xpress compression tests\n");
3632
+ }
3633
+ else {
3634
+ compression_state.push_back(kXpressCompression);
3635
+ }
3636
+
3637
+ for (auto state : compression_state) {
3638
+ DoCompressionTest(state);
3639
+ }
3640
+ }
3641
+
3642
+ #ifndef ROCKSDB_VALGRIND_RUN
3643
+ TEST_P(ParameterizedHarnessTest, RandomizedHarnessTest) {
3644
+ Random rnd(test::RandomSeed() + 5);
3645
+ for (int num_entries = 0; num_entries < 2000;
3646
+ num_entries += (num_entries < 50 ? 1 : 200)) {
3647
+ for (int e = 0; e < num_entries; e++) {
3648
+ Add(test::RandomKey(&rnd, rnd.Skewed(4)),
3649
+ rnd.RandomString(rnd.Skewed(5)));
3650
+ }
3651
+ Test(&rnd);
3652
+ }
3653
+ }
3654
+
3655
+ #ifndef ROCKSDB_LITE
3656
+ TEST_F(DBHarnessTest, RandomizedLongDB) {
3657
+ Random rnd(test::RandomSeed());
3658
+ int num_entries = 100000;
3659
+ for (int e = 0; e < num_entries; e++) {
3660
+ std::string v;
3661
+ Add(test::RandomKey(&rnd, rnd.Skewed(4)), rnd.RandomString(rnd.Skewed(5)));
3662
+ }
3663
+ Test(&rnd);
3664
+
3665
+ // We must have created enough data to force merging
3666
+ int files = 0;
3667
+ for (int level = 0; level < db()->NumberLevels(); level++) {
3668
+ std::string value;
3669
+ char name[100];
3670
+ snprintf(name, sizeof(name), "rocksdb.num-files-at-level%d", level);
3671
+ ASSERT_TRUE(db()->GetProperty(name, &value));
3672
+ files += atoi(value.c_str());
3673
+ }
3674
+ ASSERT_GT(files, 0);
3675
+ }
3676
+ #endif // ROCKSDB_LITE
3677
+ #endif // ROCKSDB_VALGRIND_RUN
3678
+
3679
+ class MemTableTest : public testing::Test {
3680
+ public:
3681
+ MemTableTest() {
3682
+ InternalKeyComparator cmp(BytewiseComparator());
3683
+ auto table_factory = std::make_shared<SkipListFactory>();
3684
+ options_.memtable_factory = table_factory;
3685
+ ImmutableCFOptions ioptions(options_);
3686
+ wb_ = new WriteBufferManager(options_.db_write_buffer_size);
3687
+ memtable_ = new MemTable(cmp, ioptions, MutableCFOptions(options_), wb_,
3688
+ kMaxSequenceNumber, 0 /* column_family_id */);
3689
+ memtable_->Ref();
3690
+ }
3691
+
3692
+ ~MemTableTest() {
3693
+ delete memtable_->Unref();
3694
+ delete wb_;
3695
+ }
3696
+
3697
+ MemTable* GetMemTable() { return memtable_; }
3698
+
3699
+ private:
3700
+ MemTable* memtable_;
3701
+ Options options_;
3702
+ WriteBufferManager* wb_;
3703
+ };
3704
+
3705
+ TEST_F(MemTableTest, Simple) {
3706
+ WriteBatch batch;
3707
+ WriteBatchInternal::SetSequence(&batch, 100);
3708
+ ASSERT_OK(batch.Put(std::string("k1"), std::string("v1")));
3709
+ ASSERT_OK(batch.Put(std::string("k2"), std::string("v2")));
3710
+ ASSERT_OK(batch.Put(std::string("k3"), std::string("v3")));
3711
+ ASSERT_OK(batch.Put(std::string("largekey"), std::string("vlarge")));
3712
+ ASSERT_OK(batch.DeleteRange(std::string("chi"), std::string("xigua")));
3713
+ ASSERT_OK(batch.DeleteRange(std::string("begin"), std::string("end")));
3714
+ ColumnFamilyMemTablesDefault cf_mems_default(GetMemTable());
3715
+ ASSERT_TRUE(
3716
+ WriteBatchInternal::InsertInto(&batch, &cf_mems_default, nullptr, nullptr)
3717
+ .ok());
3718
+
3719
+ for (int i = 0; i < 2; ++i) {
3720
+ Arena arena;
3721
+ ScopedArenaIterator arena_iter_guard;
3722
+ std::unique_ptr<InternalIterator> iter_guard;
3723
+ InternalIterator* iter;
3724
+ if (i == 0) {
3725
+ iter = GetMemTable()->NewIterator(ReadOptions(), &arena);
3726
+ arena_iter_guard.set(iter);
3727
+ } else {
3728
+ iter = GetMemTable()->NewRangeTombstoneIterator(
3729
+ ReadOptions(), kMaxSequenceNumber /* read_seq */);
3730
+ iter_guard.reset(iter);
3731
+ }
3732
+ if (iter == nullptr) {
3733
+ continue;
3734
+ }
3735
+ iter->SeekToFirst();
3736
+ while (iter->Valid()) {
3737
+ fprintf(stderr, "key: '%s' -> '%s'\n", iter->key().ToString().c_str(),
3738
+ iter->value().ToString().c_str());
3739
+ iter->Next();
3740
+ }
3741
+ }
3742
+ }
3743
+
3744
+ // Test the empty key
3745
+ TEST_P(ParameterizedHarnessTest, SimpleEmptyKey) {
3746
+ Random rnd(test::RandomSeed() + 1);
3747
+ Add("", "v");
3748
+ Test(&rnd);
3749
+ }
3750
+
3751
+ TEST_P(ParameterizedHarnessTest, SimpleSingle) {
3752
+ Random rnd(test::RandomSeed() + 2);
3753
+ Add("abc", "v");
3754
+ Test(&rnd);
3755
+ }
3756
+
3757
+ TEST_P(ParameterizedHarnessTest, SimpleMulti) {
3758
+ Random rnd(test::RandomSeed() + 3);
3759
+ Add("abc", "v");
3760
+ Add("abcd", "v");
3761
+ Add("ac", "v2");
3762
+ Test(&rnd);
3763
+ }
3764
+
3765
+ TEST_P(ParameterizedHarnessTest, SimpleSpecialKey) {
3766
+ Random rnd(test::RandomSeed() + 4);
3767
+ Add("\xff\xff", "v3");
3768
+ Test(&rnd);
3769
+ }
3770
+
3771
+ TEST(TableTest, FooterTests) {
3772
+ {
3773
+ // upconvert legacy block based
3774
+ std::string encoded;
3775
+ Footer footer(kLegacyBlockBasedTableMagicNumber, 0);
3776
+ BlockHandle meta_index(10, 5), index(20, 15);
3777
+ footer.set_metaindex_handle(meta_index);
3778
+ footer.set_index_handle(index);
3779
+ footer.EncodeTo(&encoded);
3780
+ Footer decoded_footer;
3781
+ Slice encoded_slice(encoded);
3782
+ ASSERT_OK(decoded_footer.DecodeFrom(&encoded_slice));
3783
+ ASSERT_EQ(decoded_footer.table_magic_number(), kBlockBasedTableMagicNumber);
3784
+ ASSERT_EQ(decoded_footer.checksum(), kCRC32c);
3785
+ ASSERT_EQ(decoded_footer.metaindex_handle().offset(), meta_index.offset());
3786
+ ASSERT_EQ(decoded_footer.metaindex_handle().size(), meta_index.size());
3787
+ ASSERT_EQ(decoded_footer.index_handle().offset(), index.offset());
3788
+ ASSERT_EQ(decoded_footer.index_handle().size(), index.size());
3789
+ ASSERT_EQ(decoded_footer.version(), 0U);
3790
+ }
3791
+ {
3792
+ // xxhash block based
3793
+ std::string encoded;
3794
+ Footer footer(kBlockBasedTableMagicNumber, 1);
3795
+ BlockHandle meta_index(10, 5), index(20, 15);
3796
+ footer.set_metaindex_handle(meta_index);
3797
+ footer.set_index_handle(index);
3798
+ footer.set_checksum(kxxHash);
3799
+ footer.EncodeTo(&encoded);
3800
+ Footer decoded_footer;
3801
+ Slice encoded_slice(encoded);
3802
+ ASSERT_OK(decoded_footer.DecodeFrom(&encoded_slice));
3803
+ ASSERT_EQ(decoded_footer.table_magic_number(), kBlockBasedTableMagicNumber);
3804
+ ASSERT_EQ(decoded_footer.checksum(), kxxHash);
3805
+ ASSERT_EQ(decoded_footer.metaindex_handle().offset(), meta_index.offset());
3806
+ ASSERT_EQ(decoded_footer.metaindex_handle().size(), meta_index.size());
3807
+ ASSERT_EQ(decoded_footer.index_handle().offset(), index.offset());
3808
+ ASSERT_EQ(decoded_footer.index_handle().size(), index.size());
3809
+ ASSERT_EQ(decoded_footer.version(), 1U);
3810
+ }
3811
+ {
3812
+ // xxhash64 block based
3813
+ std::string encoded;
3814
+ Footer footer(kBlockBasedTableMagicNumber, 1);
3815
+ BlockHandle meta_index(10, 5), index(20, 15);
3816
+ footer.set_metaindex_handle(meta_index);
3817
+ footer.set_index_handle(index);
3818
+ footer.set_checksum(kxxHash64);
3819
+ footer.EncodeTo(&encoded);
3820
+ Footer decoded_footer;
3821
+ Slice encoded_slice(encoded);
3822
+ ASSERT_OK(decoded_footer.DecodeFrom(&encoded_slice));
3823
+ ASSERT_EQ(decoded_footer.table_magic_number(), kBlockBasedTableMagicNumber);
3824
+ ASSERT_EQ(decoded_footer.checksum(), kxxHash64);
3825
+ ASSERT_EQ(decoded_footer.metaindex_handle().offset(), meta_index.offset());
3826
+ ASSERT_EQ(decoded_footer.metaindex_handle().size(), meta_index.size());
3827
+ ASSERT_EQ(decoded_footer.index_handle().offset(), index.offset());
3828
+ ASSERT_EQ(decoded_footer.index_handle().size(), index.size());
3829
+ ASSERT_EQ(decoded_footer.version(), 1U);
3830
+ }
3831
+ // Plain table is not supported in ROCKSDB_LITE
3832
+ #ifndef ROCKSDB_LITE
3833
+ {
3834
+ // upconvert legacy plain table
3835
+ std::string encoded;
3836
+ Footer footer(kLegacyPlainTableMagicNumber, 0);
3837
+ BlockHandle meta_index(10, 5), index(20, 15);
3838
+ footer.set_metaindex_handle(meta_index);
3839
+ footer.set_index_handle(index);
3840
+ footer.EncodeTo(&encoded);
3841
+ Footer decoded_footer;
3842
+ Slice encoded_slice(encoded);
3843
+ ASSERT_OK(decoded_footer.DecodeFrom(&encoded_slice));
3844
+ ASSERT_EQ(decoded_footer.table_magic_number(), kPlainTableMagicNumber);
3845
+ ASSERT_EQ(decoded_footer.checksum(), kCRC32c);
3846
+ ASSERT_EQ(decoded_footer.metaindex_handle().offset(), meta_index.offset());
3847
+ ASSERT_EQ(decoded_footer.metaindex_handle().size(), meta_index.size());
3848
+ ASSERT_EQ(decoded_footer.index_handle().offset(), index.offset());
3849
+ ASSERT_EQ(decoded_footer.index_handle().size(), index.size());
3850
+ ASSERT_EQ(decoded_footer.version(), 0U);
3851
+ }
3852
+ {
3853
+ // xxhash block based
3854
+ std::string encoded;
3855
+ Footer footer(kPlainTableMagicNumber, 1);
3856
+ BlockHandle meta_index(10, 5), index(20, 15);
3857
+ footer.set_metaindex_handle(meta_index);
3858
+ footer.set_index_handle(index);
3859
+ footer.set_checksum(kxxHash);
3860
+ footer.EncodeTo(&encoded);
3861
+ Footer decoded_footer;
3862
+ Slice encoded_slice(encoded);
3863
+ ASSERT_OK(decoded_footer.DecodeFrom(&encoded_slice));
3864
+ ASSERT_EQ(decoded_footer.table_magic_number(), kPlainTableMagicNumber);
3865
+ ASSERT_EQ(decoded_footer.checksum(), kxxHash);
3866
+ ASSERT_EQ(decoded_footer.metaindex_handle().offset(), meta_index.offset());
3867
+ ASSERT_EQ(decoded_footer.metaindex_handle().size(), meta_index.size());
3868
+ ASSERT_EQ(decoded_footer.index_handle().offset(), index.offset());
3869
+ ASSERT_EQ(decoded_footer.index_handle().size(), index.size());
3870
+ ASSERT_EQ(decoded_footer.version(), 1U);
3871
+ }
3872
+ #endif // !ROCKSDB_LITE
3873
+ {
3874
+ // version == 2
3875
+ std::string encoded;
3876
+ Footer footer(kBlockBasedTableMagicNumber, 2);
3877
+ BlockHandle meta_index(10, 5), index(20, 15);
3878
+ footer.set_metaindex_handle(meta_index);
3879
+ footer.set_index_handle(index);
3880
+ footer.EncodeTo(&encoded);
3881
+ Footer decoded_footer;
3882
+ Slice encoded_slice(encoded);
3883
+ ASSERT_OK(decoded_footer.DecodeFrom(&encoded_slice));
3884
+ ASSERT_EQ(decoded_footer.table_magic_number(), kBlockBasedTableMagicNumber);
3885
+ ASSERT_EQ(decoded_footer.checksum(), kCRC32c);
3886
+ ASSERT_EQ(decoded_footer.metaindex_handle().offset(), meta_index.offset());
3887
+ ASSERT_EQ(decoded_footer.metaindex_handle().size(), meta_index.size());
3888
+ ASSERT_EQ(decoded_footer.index_handle().offset(), index.offset());
3889
+ ASSERT_EQ(decoded_footer.index_handle().size(), index.size());
3890
+ ASSERT_EQ(decoded_footer.version(), 2U);
3891
+ }
3892
+ }
3893
+
3894
+ class IndexBlockRestartIntervalTest
3895
+ : public TableTest,
3896
+ public ::testing::WithParamInterface<std::pair<int, bool>> {
3897
+ public:
3898
+ static std::vector<std::pair<int, bool>> GetRestartValues() {
3899
+ return {{-1, false}, {0, false}, {1, false}, {8, false},
3900
+ {16, false}, {32, false}, {-1, true}, {0, true},
3901
+ {1, true}, {8, true}, {16, true}, {32, true}};
3902
+ }
3903
+ };
3904
+
3905
+ INSTANTIATE_TEST_CASE_P(
3906
+ IndexBlockRestartIntervalTest, IndexBlockRestartIntervalTest,
3907
+ ::testing::ValuesIn(IndexBlockRestartIntervalTest::GetRestartValues()));
3908
+
3909
+ TEST_P(IndexBlockRestartIntervalTest, IndexBlockRestartInterval) {
3910
+ const int kKeysInTable = 10000;
3911
+ const int kKeySize = 100;
3912
+ const int kValSize = 500;
3913
+
3914
+ const int index_block_restart_interval = std::get<0>(GetParam());
3915
+ const bool value_delta_encoding = std::get<1>(GetParam());
3916
+
3917
+ Options options;
3918
+ BlockBasedTableOptions table_options;
3919
+ table_options.block_size = 64; // small block size to get big index block
3920
+ table_options.index_block_restart_interval = index_block_restart_interval;
3921
+ if (value_delta_encoding) {
3922
+ table_options.format_version = 4;
3923
+ }
3924
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
3925
+
3926
+ TableConstructor c(BytewiseComparator());
3927
+ static Random rnd(301);
3928
+ for (int i = 0; i < kKeysInTable; i++) {
3929
+ InternalKey k(rnd.RandomString(kKeySize), 0, kTypeValue);
3930
+ c.Add(k.Encode().ToString(), rnd.RandomString(kValSize));
3931
+ }
3932
+
3933
+ std::vector<std::string> keys;
3934
+ stl_wrappers::KVMap kvmap;
3935
+ std::unique_ptr<InternalKeyComparator> comparator(
3936
+ new InternalKeyComparator(BytewiseComparator()));
3937
+ const ImmutableCFOptions ioptions(options);
3938
+ const MutableCFOptions moptions(options);
3939
+ c.Finish(options, ioptions, moptions, table_options, *comparator, &keys,
3940
+ &kvmap);
3941
+ auto reader = c.GetTableReader();
3942
+
3943
+ ReadOptions read_options;
3944
+ std::unique_ptr<InternalIterator> db_iter(reader->NewIterator(
3945
+ read_options, moptions.prefix_extractor.get(), /*arena=*/nullptr,
3946
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
3947
+
3948
+ // Test point lookup
3949
+ for (auto& kv : kvmap) {
3950
+ db_iter->Seek(kv.first);
3951
+
3952
+ ASSERT_TRUE(db_iter->Valid());
3953
+ ASSERT_OK(db_iter->status());
3954
+ ASSERT_EQ(db_iter->key(), kv.first);
3955
+ ASSERT_EQ(db_iter->value(), kv.second);
3956
+ }
3957
+
3958
+ // Test iterating
3959
+ auto kv_iter = kvmap.begin();
3960
+ for (db_iter->SeekToFirst(); db_iter->Valid(); db_iter->Next()) {
3961
+ ASSERT_EQ(db_iter->key(), kv_iter->first);
3962
+ ASSERT_EQ(db_iter->value(), kv_iter->second);
3963
+ kv_iter++;
3964
+ }
3965
+ ASSERT_EQ(kv_iter, kvmap.end());
3966
+ c.ResetTableReader();
3967
+ }
3968
+
3969
+ class PrefixTest : public testing::Test {
3970
+ public:
3971
+ PrefixTest() : testing::Test() {}
3972
+ ~PrefixTest() override {}
3973
+ };
3974
+
3975
+ namespace {
3976
+ // A simple PrefixExtractor that only works for test PrefixAndWholeKeyTest
3977
+ class TestPrefixExtractor : public ROCKSDB_NAMESPACE::SliceTransform {
3978
+ public:
3979
+ ~TestPrefixExtractor() override{};
3980
+ const char* Name() const override { return "TestPrefixExtractor"; }
3981
+
3982
+ ROCKSDB_NAMESPACE::Slice Transform(
3983
+ const ROCKSDB_NAMESPACE::Slice& src) const override {
3984
+ assert(IsValid(src));
3985
+ return ROCKSDB_NAMESPACE::Slice(src.data(), 3);
3986
+ }
3987
+
3988
+ bool InDomain(const ROCKSDB_NAMESPACE::Slice& src) const override {
3989
+ assert(IsValid(src));
3990
+ return true;
3991
+ }
3992
+
3993
+ bool InRange(const ROCKSDB_NAMESPACE::Slice& /*dst*/) const override {
3994
+ return true;
3995
+ }
3996
+
3997
+ bool IsValid(const ROCKSDB_NAMESPACE::Slice& src) const {
3998
+ if (src.size() != 4) {
3999
+ return false;
4000
+ }
4001
+ if (src[0] != '[') {
4002
+ return false;
4003
+ }
4004
+ if (src[1] < '0' || src[1] > '9') {
4005
+ return false;
4006
+ }
4007
+ if (src[2] != ']') {
4008
+ return false;
4009
+ }
4010
+ if (src[3] < '0' || src[3] > '9') {
4011
+ return false;
4012
+ }
4013
+ return true;
4014
+ }
4015
+ };
4016
+ } // namespace
4017
+
4018
+ TEST_F(PrefixTest, PrefixAndWholeKeyTest) {
4019
+ ROCKSDB_NAMESPACE::Options options;
4020
+ options.compaction_style = ROCKSDB_NAMESPACE::kCompactionStyleUniversal;
4021
+ options.num_levels = 20;
4022
+ options.create_if_missing = true;
4023
+ options.optimize_filters_for_hits = false;
4024
+ options.target_file_size_base = 268435456;
4025
+ options.prefix_extractor = std::make_shared<TestPrefixExtractor>();
4026
+ ROCKSDB_NAMESPACE::BlockBasedTableOptions bbto;
4027
+ bbto.filter_policy.reset(ROCKSDB_NAMESPACE::NewBloomFilterPolicy(10));
4028
+ bbto.block_size = 262144;
4029
+ bbto.whole_key_filtering = true;
4030
+
4031
+ const std::string kDBPath = test::PerThreadDBPath("table_prefix_test");
4032
+ options.table_factory.reset(NewBlockBasedTableFactory(bbto));
4033
+ ASSERT_OK(DestroyDB(kDBPath, options));
4034
+ ROCKSDB_NAMESPACE::DB* db;
4035
+ ASSERT_OK(ROCKSDB_NAMESPACE::DB::Open(options, kDBPath, &db));
4036
+
4037
+ // Create a bunch of keys with 10 filters.
4038
+ for (int i = 0; i < 10; i++) {
4039
+ std::string prefix = "[" + std::to_string(i) + "]";
4040
+ for (int j = 0; j < 10; j++) {
4041
+ std::string key = prefix + std::to_string(j);
4042
+ ASSERT_OK(db->Put(ROCKSDB_NAMESPACE::WriteOptions(), key, "1"));
4043
+ }
4044
+ }
4045
+
4046
+ // Trigger compaction.
4047
+ ASSERT_OK(db->CompactRange(CompactRangeOptions(), nullptr, nullptr));
4048
+ delete db;
4049
+ // In the second round, turn whole_key_filtering off and expect
4050
+ // rocksdb still works.
4051
+ }
4052
+
4053
+ /*
4054
+ * Disable TableWithGlobalSeqno since RocksDB does not store global_seqno in
4055
+ * the SST file any more. Instead, RocksDB deduces global_seqno from the
4056
+ * MANIFEST while reading from an SST. Therefore, it's not possible to test the
4057
+ * functionality of global_seqno in a single, isolated unit test without the
4058
+ * involvement of Version, VersionSet, etc.
4059
+ */
4060
+ TEST_P(BlockBasedTableTest, DISABLED_TableWithGlobalSeqno) {
4061
+ BlockBasedTableOptions bbto = GetBlockBasedTableOptions();
4062
+ test::StringSink* sink = new test::StringSink();
4063
+ std::unique_ptr<FSWritableFile> holder(sink);
4064
+ std::unique_ptr<WritableFileWriter> file_writer(new WritableFileWriter(
4065
+ std::move(holder), "" /* don't care */, FileOptions()));
4066
+ Options options;
4067
+ options.table_factory.reset(NewBlockBasedTableFactory(bbto));
4068
+ const ImmutableCFOptions ioptions(options);
4069
+ const MutableCFOptions moptions(options);
4070
+ InternalKeyComparator ikc(options.comparator);
4071
+ std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
4072
+ int_tbl_prop_collector_factories;
4073
+ int_tbl_prop_collector_factories.emplace_back(
4074
+ new SstFileWriterPropertiesCollectorFactory(2 /* version */,
4075
+ 0 /* global_seqno*/));
4076
+ std::string column_family_name;
4077
+ std::unique_ptr<TableBuilder> builder(options.table_factory->NewTableBuilder(
4078
+ TableBuilderOptions(ioptions, moptions, ikc,
4079
+ &int_tbl_prop_collector_factories, kNoCompression,
4080
+ 0 /* sample_for_compression */, CompressionOptions(),
4081
+ false /* skip_filters */, column_family_name, -1),
4082
+ TablePropertiesCollectorFactory::Context::kUnknownColumnFamily,
4083
+ file_writer.get()));
4084
+
4085
+ for (char c = 'a'; c <= 'z'; ++c) {
4086
+ std::string key(8, c);
4087
+ std::string value = key;
4088
+ InternalKey ik(key, 0, kTypeValue);
4089
+
4090
+ builder->Add(ik.Encode(), value);
4091
+ }
4092
+ ASSERT_OK(builder->Finish());
4093
+ ASSERT_OK(file_writer->Flush());
4094
+
4095
+ test::RandomRWStringSink ss_rw(sink);
4096
+ uint32_t version;
4097
+ uint64_t global_seqno;
4098
+ uint64_t global_seqno_offset;
4099
+
4100
+ // Helper function to get version, global_seqno, global_seqno_offset
4101
+ std::function<void()> GetVersionAndGlobalSeqno = [&]() {
4102
+ std::unique_ptr<FSRandomAccessFile> source(
4103
+ new test::StringSource(ss_rw.contents(), 73342, true));
4104
+ std::unique_ptr<RandomAccessFileReader> file_reader(
4105
+ new RandomAccessFileReader(std::move(source), ""));
4106
+
4107
+ TableProperties* props = nullptr;
4108
+ ASSERT_OK(ReadTableProperties(file_reader.get(), ss_rw.contents().size(),
4109
+ kBlockBasedTableMagicNumber, ioptions,
4110
+ &props, true /* compression_type_missing */));
4111
+
4112
+ UserCollectedProperties user_props = props->user_collected_properties;
4113
+ version = DecodeFixed32(
4114
+ user_props[ExternalSstFilePropertyNames::kVersion].c_str());
4115
+ global_seqno = DecodeFixed64(
4116
+ user_props[ExternalSstFilePropertyNames::kGlobalSeqno].c_str());
4117
+ global_seqno_offset =
4118
+ props->properties_offsets[ExternalSstFilePropertyNames::kGlobalSeqno];
4119
+
4120
+ delete props;
4121
+ };
4122
+
4123
+ // Helper function to update the value of the global seqno in the file
4124
+ std::function<void(uint64_t)> SetGlobalSeqno = [&](uint64_t val) {
4125
+ std::string new_global_seqno;
4126
+ PutFixed64(&new_global_seqno, val);
4127
+
4128
+ ASSERT_OK(ss_rw.Write(global_seqno_offset, new_global_seqno, IOOptions(),
4129
+ nullptr));
4130
+ };
4131
+
4132
+ // Helper function to get the contents of the table InternalIterator
4133
+ std::unique_ptr<TableReader> table_reader;
4134
+ const ReadOptions read_options;
4135
+ std::function<InternalIterator*()> GetTableInternalIter = [&]() {
4136
+ std::unique_ptr<FSRandomAccessFile> source(
4137
+ new test::StringSource(ss_rw.contents(), 73342, true));
4138
+ std::unique_ptr<RandomAccessFileReader> file_reader(
4139
+ new RandomAccessFileReader(std::move(source), ""));
4140
+
4141
+ options.table_factory->NewTableReader(
4142
+ TableReaderOptions(ioptions, moptions.prefix_extractor.get(),
4143
+ EnvOptions(), ikc),
4144
+ std::move(file_reader), ss_rw.contents().size(), &table_reader);
4145
+
4146
+ return table_reader->NewIterator(
4147
+ read_options, moptions.prefix_extractor.get(), /*arena=*/nullptr,
4148
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized);
4149
+ };
4150
+
4151
+ GetVersionAndGlobalSeqno();
4152
+ ASSERT_EQ(2u, version);
4153
+ ASSERT_EQ(0u, global_seqno);
4154
+
4155
+ InternalIterator* iter = GetTableInternalIter();
4156
+ char current_c = 'a';
4157
+ for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
4158
+ ParsedInternalKey pik;
4159
+ ASSERT_OK(ParseInternalKey(iter->key(), &pik, true /* log_err_key */));
4160
+
4161
+ ASSERT_EQ(pik.type, ValueType::kTypeValue);
4162
+ ASSERT_EQ(pik.sequence, 0);
4163
+ ASSERT_EQ(pik.user_key, iter->value());
4164
+ ASSERT_EQ(pik.user_key.ToString(), std::string(8, current_c));
4165
+ current_c++;
4166
+ }
4167
+ ASSERT_EQ(current_c, 'z' + 1);
4168
+ delete iter;
4169
+
4170
+ // Update global sequence number to 10
4171
+ SetGlobalSeqno(10);
4172
+ GetVersionAndGlobalSeqno();
4173
+ ASSERT_EQ(2u, version);
4174
+ ASSERT_EQ(10u, global_seqno);
4175
+
4176
+ iter = GetTableInternalIter();
4177
+ current_c = 'a';
4178
+ for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
4179
+ ParsedInternalKey pik;
4180
+ ASSERT_OK(ParseInternalKey(iter->key(), &pik, true /* log_err_key */));
4181
+
4182
+ ASSERT_EQ(pik.type, ValueType::kTypeValue);
4183
+ ASSERT_EQ(pik.sequence, 10);
4184
+ ASSERT_EQ(pik.user_key, iter->value());
4185
+ ASSERT_EQ(pik.user_key.ToString(), std::string(8, current_c));
4186
+ current_c++;
4187
+ }
4188
+ ASSERT_EQ(current_c, 'z' + 1);
4189
+
4190
+ // Verify Seek
4191
+ for (char c = 'a'; c <= 'z'; c++) {
4192
+ std::string k = std::string(8, c);
4193
+ InternalKey ik(k, 10, kValueTypeForSeek);
4194
+ iter->Seek(ik.Encode());
4195
+ ASSERT_TRUE(iter->Valid());
4196
+
4197
+ ParsedInternalKey pik;
4198
+ ASSERT_OK(ParseInternalKey(iter->key(), &pik, true /* log_err_key */));
4199
+
4200
+ ASSERT_EQ(pik.type, ValueType::kTypeValue);
4201
+ ASSERT_EQ(pik.sequence, 10);
4202
+ ASSERT_EQ(pik.user_key.ToString(), k);
4203
+ ASSERT_EQ(iter->value().ToString(), k);
4204
+ }
4205
+ delete iter;
4206
+
4207
+ // Update global sequence number to 3
4208
+ SetGlobalSeqno(3);
4209
+ GetVersionAndGlobalSeqno();
4210
+ ASSERT_EQ(2u, version);
4211
+ ASSERT_EQ(3u, global_seqno);
4212
+
4213
+ iter = GetTableInternalIter();
4214
+ current_c = 'a';
4215
+ for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
4216
+ ParsedInternalKey pik;
4217
+ ASSERT_OK(ParseInternalKey(iter->key(), &pik, true /* log_err_key */));
4218
+
4219
+ ASSERT_EQ(pik.type, ValueType::kTypeValue);
4220
+ ASSERT_EQ(pik.sequence, 3);
4221
+ ASSERT_EQ(pik.user_key, iter->value());
4222
+ ASSERT_EQ(pik.user_key.ToString(), std::string(8, current_c));
4223
+ current_c++;
4224
+ }
4225
+ ASSERT_EQ(current_c, 'z' + 1);
4226
+
4227
+ // Verify Seek
4228
+ for (char c = 'a'; c <= 'z'; c++) {
4229
+ std::string k = std::string(8, c);
4230
+ // seqno=4 is less than 3 so we still should get our key
4231
+ InternalKey ik(k, 4, kValueTypeForSeek);
4232
+ iter->Seek(ik.Encode());
4233
+ ASSERT_TRUE(iter->Valid());
4234
+
4235
+ ParsedInternalKey pik;
4236
+ ASSERT_OK(ParseInternalKey(iter->key(), &pik, true /* log_err_key */));
4237
+
4238
+ ASSERT_EQ(pik.type, ValueType::kTypeValue);
4239
+ ASSERT_EQ(pik.sequence, 3);
4240
+ ASSERT_EQ(pik.user_key.ToString(), k);
4241
+ ASSERT_EQ(iter->value().ToString(), k);
4242
+ }
4243
+
4244
+ delete iter;
4245
+ }
4246
+
4247
+ TEST_P(BlockBasedTableTest, BlockAlignTest) {
4248
+ BlockBasedTableOptions bbto = GetBlockBasedTableOptions();
4249
+ bbto.block_align = true;
4250
+ test::StringSink* sink = new test::StringSink();
4251
+ std::unique_ptr<FSWritableFile> holder(sink);
4252
+ std::unique_ptr<WritableFileWriter> file_writer(new WritableFileWriter(
4253
+ std::move(holder), "" /* don't care */, FileOptions()));
4254
+ Options options;
4255
+ options.compression = kNoCompression;
4256
+ options.table_factory.reset(NewBlockBasedTableFactory(bbto));
4257
+ const ImmutableCFOptions ioptions(options);
4258
+ const MutableCFOptions moptions(options);
4259
+ InternalKeyComparator ikc(options.comparator);
4260
+ std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
4261
+ int_tbl_prop_collector_factories;
4262
+ std::string column_family_name;
4263
+ std::unique_ptr<TableBuilder> builder(options.table_factory->NewTableBuilder(
4264
+ TableBuilderOptions(ioptions, moptions, ikc,
4265
+ &int_tbl_prop_collector_factories, kNoCompression,
4266
+ 0 /* sample_for_compression */, CompressionOptions(),
4267
+ false /* skip_filters */, column_family_name, -1),
4268
+ TablePropertiesCollectorFactory::Context::kUnknownColumnFamily,
4269
+ file_writer.get()));
4270
+
4271
+ for (int i = 1; i <= 10000; ++i) {
4272
+ std::ostringstream ostr;
4273
+ ostr << std::setfill('0') << std::setw(5) << i;
4274
+ std::string key = ostr.str();
4275
+ std::string value = "val";
4276
+ InternalKey ik(key, 0, kTypeValue);
4277
+
4278
+ builder->Add(ik.Encode(), value);
4279
+ }
4280
+ ASSERT_OK(builder->Finish());
4281
+ ASSERT_OK(file_writer->Flush());
4282
+
4283
+ std::unique_ptr<FSRandomAccessFile> source(
4284
+ new test::StringSource(sink->contents(), 73342, false));
4285
+ std::unique_ptr<RandomAccessFileReader> file_reader(
4286
+ new RandomAccessFileReader(std::move(source), "test"));
4287
+ // Helper function to get version, global_seqno, global_seqno_offset
4288
+ std::function<void()> VerifyBlockAlignment = [&]() {
4289
+ TableProperties* props = nullptr;
4290
+ ASSERT_OK(ReadTableProperties(file_reader.get(), sink->contents().size(),
4291
+ kBlockBasedTableMagicNumber, ioptions, &props,
4292
+ true /* compression_type_missing */));
4293
+
4294
+ uint64_t data_block_size = props->data_size / props->num_data_blocks;
4295
+ ASSERT_EQ(data_block_size, 4096);
4296
+ ASSERT_EQ(props->data_size, data_block_size * props->num_data_blocks);
4297
+ delete props;
4298
+ };
4299
+
4300
+ VerifyBlockAlignment();
4301
+
4302
+ // The below block of code verifies that we can read back the keys. Set
4303
+ // block_align to false when creating the reader to ensure we can flip between
4304
+ // the two modes without any issues
4305
+ std::unique_ptr<TableReader> table_reader;
4306
+ bbto.block_align = false;
4307
+ Options options2;
4308
+ options2.table_factory.reset(NewBlockBasedTableFactory(bbto));
4309
+ ImmutableCFOptions ioptions2(options2);
4310
+ const MutableCFOptions moptions2(options2);
4311
+
4312
+ ASSERT_OK(ioptions.table_factory->NewTableReader(
4313
+ TableReaderOptions(ioptions2, moptions2.prefix_extractor.get(),
4314
+ EnvOptions(),
4315
+ GetPlainInternalComparator(options2.comparator)),
4316
+ std::move(file_reader), sink->contents().size(), &table_reader));
4317
+
4318
+ ReadOptions read_options;
4319
+ std::unique_ptr<InternalIterator> db_iter(table_reader->NewIterator(
4320
+ read_options, moptions2.prefix_extractor.get(), /*arena=*/nullptr,
4321
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
4322
+
4323
+ int expected_key = 1;
4324
+ for (db_iter->SeekToFirst(); db_iter->Valid(); db_iter->Next()) {
4325
+ std::ostringstream ostr;
4326
+ ostr << std::setfill('0') << std::setw(5) << expected_key++;
4327
+ std::string key = ostr.str();
4328
+ std::string value = "val";
4329
+
4330
+ ASSERT_OK(db_iter->status());
4331
+ ASSERT_EQ(ExtractUserKey(db_iter->key()).ToString(), key);
4332
+ ASSERT_EQ(db_iter->value().ToString(), value);
4333
+ }
4334
+ expected_key--;
4335
+ ASSERT_EQ(expected_key, 10000);
4336
+ table_reader.reset();
4337
+ }
4338
+
4339
+ TEST_P(BlockBasedTableTest, PropertiesBlockRestartPointTest) {
4340
+ BlockBasedTableOptions bbto = GetBlockBasedTableOptions();
4341
+ bbto.block_align = true;
4342
+ test::StringSink* sink = new test::StringSink();
4343
+ std::unique_ptr<FSWritableFile> holder(sink);
4344
+ std::unique_ptr<WritableFileWriter> file_writer(new WritableFileWriter(
4345
+ std::move(holder), "" /* don't care */, FileOptions()));
4346
+
4347
+ Options options;
4348
+ options.compression = kNoCompression;
4349
+ options.table_factory.reset(NewBlockBasedTableFactory(bbto));
4350
+
4351
+ const ImmutableCFOptions ioptions(options);
4352
+ const MutableCFOptions moptions(options);
4353
+ InternalKeyComparator ikc(options.comparator);
4354
+ std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
4355
+ int_tbl_prop_collector_factories;
4356
+ std::string column_family_name;
4357
+
4358
+ std::unique_ptr<TableBuilder> builder(options.table_factory->NewTableBuilder(
4359
+ TableBuilderOptions(ioptions, moptions, ikc,
4360
+ &int_tbl_prop_collector_factories, kNoCompression,
4361
+ 0 /* sample_for_compression */, CompressionOptions(),
4362
+ false /* skip_filters */, column_family_name, -1),
4363
+ TablePropertiesCollectorFactory::Context::kUnknownColumnFamily,
4364
+ file_writer.get()));
4365
+
4366
+ for (int i = 1; i <= 10000; ++i) {
4367
+ std::ostringstream ostr;
4368
+ ostr << std::setfill('0') << std::setw(5) << i;
4369
+ std::string key = ostr.str();
4370
+ std::string value = "val";
4371
+ InternalKey ik(key, 0, kTypeValue);
4372
+
4373
+ builder->Add(ik.Encode(), value);
4374
+ }
4375
+ ASSERT_OK(builder->Finish());
4376
+ ASSERT_OK(file_writer->Flush());
4377
+
4378
+ std::unique_ptr<FSRandomAccessFile> source(
4379
+ new test::StringSource(sink->contents(), 73342, true));
4380
+ std::unique_ptr<RandomAccessFileReader> file_reader(
4381
+ new RandomAccessFileReader(std::move(source), "test"));
4382
+
4383
+ {
4384
+ RandomAccessFileReader* file = file_reader.get();
4385
+ uint64_t file_size = sink->contents().size();
4386
+
4387
+ Footer footer;
4388
+ IOOptions opts;
4389
+ ASSERT_OK(ReadFooterFromFile(opts, file, nullptr /* prefetch_buffer */,
4390
+ file_size, &footer,
4391
+ kBlockBasedTableMagicNumber));
4392
+
4393
+ auto BlockFetchHelper = [&](const BlockHandle& handle, BlockType block_type,
4394
+ BlockContents* contents) {
4395
+ ReadOptions read_options;
4396
+ read_options.verify_checksums = false;
4397
+ PersistentCacheOptions cache_options;
4398
+
4399
+ BlockFetcher block_fetcher(
4400
+ file, nullptr /* prefetch_buffer */, footer, read_options, handle,
4401
+ contents, ioptions, false /* decompress */,
4402
+ false /*maybe_compressed*/, block_type,
4403
+ UncompressionDict::GetEmptyDict(), cache_options);
4404
+
4405
+ ASSERT_OK(block_fetcher.ReadBlockContents());
4406
+ };
4407
+
4408
+ // -- Read metaindex block
4409
+ auto metaindex_handle = footer.metaindex_handle();
4410
+ BlockContents metaindex_contents;
4411
+
4412
+ BlockFetchHelper(metaindex_handle, BlockType::kMetaIndex,
4413
+ &metaindex_contents);
4414
+ Block metaindex_block(std::move(metaindex_contents));
4415
+
4416
+ std::unique_ptr<InternalIterator> meta_iter(metaindex_block.NewDataIterator(
4417
+ BytewiseComparator(), kDisableGlobalSequenceNumber));
4418
+ bool found_properties_block = true;
4419
+ ASSERT_OK(SeekToPropertiesBlock(meta_iter.get(), &found_properties_block));
4420
+ ASSERT_TRUE(found_properties_block);
4421
+
4422
+ // -- Read properties block
4423
+ Slice v = meta_iter->value();
4424
+ BlockHandle properties_handle;
4425
+ ASSERT_OK(properties_handle.DecodeFrom(&v));
4426
+ BlockContents properties_contents;
4427
+
4428
+ BlockFetchHelper(properties_handle, BlockType::kProperties,
4429
+ &properties_contents);
4430
+ Block properties_block(std::move(properties_contents));
4431
+
4432
+ ASSERT_EQ(properties_block.NumRestarts(), 1u);
4433
+ }
4434
+ }
4435
+
4436
+ TEST_P(BlockBasedTableTest, PropertiesMetaBlockLast) {
4437
+ // The properties meta-block should come at the end since we always need to
4438
+ // read it when opening a file, unlike index/filter/other meta-blocks, which
4439
+ // are sometimes read depending on the user's configuration. This ordering
4440
+ // allows us to do a small readahead on the end of the file to read properties
4441
+ // and meta-index blocks with one I/O.
4442
+ TableConstructor c(BytewiseComparator(), true /* convert_to_internal_key_ */);
4443
+ c.Add("a1", "val1");
4444
+ c.Add("b2", "val2");
4445
+ c.Add("c3", "val3");
4446
+ c.Add("d4", "val4");
4447
+ c.Add("e5", "val5");
4448
+ c.Add("f6", "val6");
4449
+ c.Add("g7", "val7");
4450
+ c.Add("h8", "val8");
4451
+ c.Add("j9", "val9");
4452
+
4453
+ // write an SST file
4454
+ Options options;
4455
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
4456
+ table_options.filter_policy.reset(NewBloomFilterPolicy(
4457
+ 8 /* bits_per_key */, false /* use_block_based_filter */));
4458
+ options.table_factory.reset(NewBlockBasedTableFactory(table_options));
4459
+ ImmutableCFOptions ioptions(options);
4460
+ MutableCFOptions moptions(options);
4461
+ std::vector<std::string> keys;
4462
+ stl_wrappers::KVMap kvmap;
4463
+ c.Finish(options, ioptions, moptions, table_options,
4464
+ GetPlainInternalComparator(options.comparator), &keys, &kvmap);
4465
+
4466
+ // get file reader
4467
+ test::StringSink* table_sink = c.TEST_GetSink();
4468
+ std::unique_ptr<FSRandomAccessFile> source(new test::StringSource(
4469
+ table_sink->contents(), 0 /* unique_id */, false /* allow_mmap_reads */));
4470
+
4471
+ std::unique_ptr<RandomAccessFileReader> table_reader(
4472
+ new RandomAccessFileReader(std::move(source), "test"));
4473
+ size_t table_size = table_sink->contents().size();
4474
+
4475
+ // read footer
4476
+ Footer footer;
4477
+ IOOptions opts;
4478
+ ASSERT_OK(ReadFooterFromFile(opts, table_reader.get(),
4479
+ nullptr /* prefetch_buffer */, table_size,
4480
+ &footer, kBlockBasedTableMagicNumber));
4481
+
4482
+ // read metaindex
4483
+ auto metaindex_handle = footer.metaindex_handle();
4484
+ BlockContents metaindex_contents;
4485
+ PersistentCacheOptions pcache_opts;
4486
+ BlockFetcher block_fetcher(
4487
+ table_reader.get(), nullptr /* prefetch_buffer */, footer, ReadOptions(),
4488
+ metaindex_handle, &metaindex_contents, ioptions, false /* decompress */,
4489
+ false /*maybe_compressed*/, BlockType::kMetaIndex,
4490
+ UncompressionDict::GetEmptyDict(), pcache_opts,
4491
+ nullptr /*memory_allocator*/);
4492
+ ASSERT_OK(block_fetcher.ReadBlockContents());
4493
+ Block metaindex_block(std::move(metaindex_contents));
4494
+
4495
+ // verify properties block comes last
4496
+ std::unique_ptr<InternalIterator> metaindex_iter{
4497
+ metaindex_block.NewDataIterator(options.comparator,
4498
+ kDisableGlobalSequenceNumber)};
4499
+ uint64_t max_offset = 0;
4500
+ std::string key_at_max_offset;
4501
+ for (metaindex_iter->SeekToFirst(); metaindex_iter->Valid();
4502
+ metaindex_iter->Next()) {
4503
+ BlockHandle handle;
4504
+ Slice value = metaindex_iter->value();
4505
+ ASSERT_OK(handle.DecodeFrom(&value));
4506
+ if (handle.offset() > max_offset) {
4507
+ max_offset = handle.offset();
4508
+ key_at_max_offset = metaindex_iter->key().ToString();
4509
+ }
4510
+ }
4511
+ ASSERT_EQ(kPropertiesBlock, key_at_max_offset);
4512
+ // index handle is stored in footer rather than metaindex block, so need
4513
+ // separate logic to verify it comes before properties block.
4514
+ ASSERT_GT(max_offset, footer.index_handle().offset());
4515
+ c.ResetTableReader();
4516
+ }
4517
+
4518
+ TEST_P(BlockBasedTableTest, BadOptions) {
4519
+ ROCKSDB_NAMESPACE::Options options;
4520
+ options.compression = kNoCompression;
4521
+ BlockBasedTableOptions bbto = GetBlockBasedTableOptions();
4522
+ bbto.block_size = 4000;
4523
+ bbto.block_align = true;
4524
+
4525
+ const std::string kDBPath =
4526
+ test::PerThreadDBPath("block_based_table_bad_options_test");
4527
+ options.table_factory.reset(NewBlockBasedTableFactory(bbto));
4528
+ ASSERT_OK(DestroyDB(kDBPath, options));
4529
+ ROCKSDB_NAMESPACE::DB* db;
4530
+ ASSERT_NOK(ROCKSDB_NAMESPACE::DB::Open(options, kDBPath, &db));
4531
+
4532
+ bbto.block_size = 4096;
4533
+ options.compression = kSnappyCompression;
4534
+ options.table_factory.reset(NewBlockBasedTableFactory(bbto));
4535
+ ASSERT_NOK(ROCKSDB_NAMESPACE::DB::Open(options, kDBPath, &db));
4536
+ }
4537
+
4538
+ TEST_F(BBTTailPrefetchTest, TestTailPrefetchStats) {
4539
+ TailPrefetchStats tpstats;
4540
+ ASSERT_EQ(0, tpstats.GetSuggestedPrefetchSize());
4541
+ tpstats.RecordEffectiveSize(size_t{1000});
4542
+ tpstats.RecordEffectiveSize(size_t{1005});
4543
+ tpstats.RecordEffectiveSize(size_t{1002});
4544
+ ASSERT_EQ(1005, tpstats.GetSuggestedPrefetchSize());
4545
+
4546
+ // One single super large value shouldn't influence much
4547
+ tpstats.RecordEffectiveSize(size_t{1002000});
4548
+ tpstats.RecordEffectiveSize(size_t{999});
4549
+ ASSERT_LE(1005, tpstats.GetSuggestedPrefetchSize());
4550
+ ASSERT_GT(1200, tpstats.GetSuggestedPrefetchSize());
4551
+
4552
+ // Only history of 32 is kept
4553
+ for (int i = 0; i < 32; i++) {
4554
+ tpstats.RecordEffectiveSize(size_t{100});
4555
+ }
4556
+ ASSERT_EQ(100, tpstats.GetSuggestedPrefetchSize());
4557
+
4558
+ // 16 large values and 16 small values. The result should be closer
4559
+ // to the small value as the algorithm.
4560
+ for (int i = 0; i < 16; i++) {
4561
+ tpstats.RecordEffectiveSize(size_t{1000});
4562
+ }
4563
+ tpstats.RecordEffectiveSize(size_t{10});
4564
+ tpstats.RecordEffectiveSize(size_t{20});
4565
+ for (int i = 0; i < 6; i++) {
4566
+ tpstats.RecordEffectiveSize(size_t{100});
4567
+ }
4568
+ ASSERT_LE(80, tpstats.GetSuggestedPrefetchSize());
4569
+ ASSERT_GT(200, tpstats.GetSuggestedPrefetchSize());
4570
+ }
4571
+
4572
+ TEST_F(BBTTailPrefetchTest, FilePrefetchBufferMinOffset) {
4573
+ TailPrefetchStats tpstats;
4574
+ FilePrefetchBuffer buffer(nullptr, 0, 0, false, true);
4575
+ IOOptions opts;
4576
+ buffer.TryReadFromCache(opts, 500, 10, nullptr, nullptr);
4577
+ buffer.TryReadFromCache(opts, 480, 10, nullptr, nullptr);
4578
+ buffer.TryReadFromCache(opts, 490, 10, nullptr, nullptr);
4579
+ ASSERT_EQ(480, buffer.min_offset_read());
4580
+ }
4581
+
4582
+ TEST_P(BlockBasedTableTest, DataBlockHashIndex) {
4583
+ const int kNumKeys = 500;
4584
+ const int kKeySize = 8;
4585
+ const int kValSize = 40;
4586
+
4587
+ BlockBasedTableOptions table_options = GetBlockBasedTableOptions();
4588
+ table_options.data_block_index_type =
4589
+ BlockBasedTableOptions::kDataBlockBinaryAndHash;
4590
+
4591
+ Options options;
4592
+ options.comparator = BytewiseComparator();
4593
+
4594
+ options.table_factory.reset(new BlockBasedTableFactory(table_options));
4595
+
4596
+ TableConstructor c(options.comparator);
4597
+
4598
+ static Random rnd(1048);
4599
+ for (int i = 0; i < kNumKeys; i++) {
4600
+ // padding one "0" to mark existent keys.
4601
+ std::string random_key(rnd.RandomString(kKeySize - 1) + "1");
4602
+ InternalKey k(random_key, 0, kTypeValue);
4603
+ c.Add(k.Encode().ToString(), rnd.RandomString(kValSize));
4604
+ }
4605
+
4606
+ std::vector<std::string> keys;
4607
+ stl_wrappers::KVMap kvmap;
4608
+ const ImmutableCFOptions ioptions(options);
4609
+ const MutableCFOptions moptions(options);
4610
+ const InternalKeyComparator internal_comparator(options.comparator);
4611
+ c.Finish(options, ioptions, moptions, table_options, internal_comparator,
4612
+ &keys, &kvmap);
4613
+
4614
+ auto reader = c.GetTableReader();
4615
+
4616
+ std::unique_ptr<InternalIterator> seek_iter;
4617
+ ReadOptions read_options;
4618
+ seek_iter.reset(reader->NewIterator(
4619
+ read_options, moptions.prefix_extractor.get(), /*arena=*/nullptr,
4620
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
4621
+ for (int i = 0; i < 2; ++i) {
4622
+ ReadOptions ro;
4623
+ // for every kv, we seek using two method: Get() and Seek()
4624
+ // Get() will use the SuffixIndexHash in Block. For non-existent key it
4625
+ // will invalidate the iterator
4626
+ // Seek() will use the default BinarySeek() in Block. So for non-existent
4627
+ // key it will land at the closest key that is large than target.
4628
+
4629
+ // Search for existent keys
4630
+ for (auto& kv : kvmap) {
4631
+ if (i == 0) {
4632
+ // Search using Seek()
4633
+ seek_iter->Seek(kv.first);
4634
+ ASSERT_OK(seek_iter->status());
4635
+ ASSERT_TRUE(seek_iter->Valid());
4636
+ ASSERT_EQ(seek_iter->key(), kv.first);
4637
+ ASSERT_EQ(seek_iter->value(), kv.second);
4638
+ } else {
4639
+ // Search using Get()
4640
+ PinnableSlice value;
4641
+ std::string user_key = ExtractUserKey(kv.first).ToString();
4642
+ GetContext get_context(options.comparator, nullptr, nullptr, nullptr,
4643
+ GetContext::kNotFound, user_key, &value, nullptr,
4644
+ nullptr, true, nullptr, nullptr);
4645
+ ASSERT_OK(reader->Get(ro, kv.first, &get_context,
4646
+ moptions.prefix_extractor.get()));
4647
+ ASSERT_EQ(get_context.State(), GetContext::kFound);
4648
+ ASSERT_EQ(value, Slice(kv.second));
4649
+ value.Reset();
4650
+ }
4651
+ }
4652
+
4653
+ // Search for non-existent keys
4654
+ for (auto& kv : kvmap) {
4655
+ std::string user_key = ExtractUserKey(kv.first).ToString();
4656
+ user_key.back() = '0'; // make it non-existent key
4657
+ InternalKey internal_key(user_key, 0, kTypeValue);
4658
+ std::string encoded_key = internal_key.Encode().ToString();
4659
+ if (i == 0) { // Search using Seek()
4660
+ seek_iter->Seek(encoded_key);
4661
+ ASSERT_OK(seek_iter->status());
4662
+ if (seek_iter->Valid()) {
4663
+ ASSERT_TRUE(BytewiseComparator()->Compare(
4664
+ user_key, ExtractUserKey(seek_iter->key())) < 0);
4665
+ }
4666
+ } else { // Search using Get()
4667
+ PinnableSlice value;
4668
+ GetContext get_context(options.comparator, nullptr, nullptr, nullptr,
4669
+ GetContext::kNotFound, user_key, &value, nullptr,
4670
+ nullptr, true, nullptr, nullptr);
4671
+ ASSERT_OK(reader->Get(ro, encoded_key, &get_context,
4672
+ moptions.prefix_extractor.get()));
4673
+ ASSERT_EQ(get_context.State(), GetContext::kNotFound);
4674
+ value.Reset();
4675
+ }
4676
+ }
4677
+ }
4678
+ }
4679
+
4680
+ // BlockBasedTableIterator should invalidate itself and return
4681
+ // OutOfBound()=true immediately after Seek(), to allow LevelIterator
4682
+ // filter out corresponding level.
4683
+ TEST_P(BlockBasedTableTest, OutOfBoundOnSeek) {
4684
+ TableConstructor c(BytewiseComparator(), true /*convert_to_internal_key*/);
4685
+ c.Add("foo", "v1");
4686
+ std::vector<std::string> keys;
4687
+ stl_wrappers::KVMap kvmap;
4688
+ Options options;
4689
+ BlockBasedTableOptions table_opt(GetBlockBasedTableOptions());
4690
+ options.table_factory.reset(NewBlockBasedTableFactory(table_opt));
4691
+ const ImmutableCFOptions ioptions(options);
4692
+ const MutableCFOptions moptions(options);
4693
+ c.Finish(options, ioptions, moptions, table_opt,
4694
+ GetPlainInternalComparator(BytewiseComparator()), &keys, &kvmap);
4695
+ auto* reader = c.GetTableReader();
4696
+ ReadOptions read_opt;
4697
+ std::string upper_bound = "bar";
4698
+ Slice upper_bound_slice(upper_bound);
4699
+ read_opt.iterate_upper_bound = &upper_bound_slice;
4700
+ std::unique_ptr<InternalIterator> iter;
4701
+ iter.reset(new KeyConvertingIterator(reader->NewIterator(
4702
+ read_opt, /*prefix_extractor=*/nullptr, /*arena=*/nullptr,
4703
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized)));
4704
+ iter->SeekToFirst();
4705
+ ASSERT_FALSE(iter->Valid());
4706
+ ASSERT_OK(iter->status());
4707
+ ASSERT_TRUE(iter->UpperBoundCheckResult() == IterBoundCheck::kOutOfBound);
4708
+ iter.reset(new KeyConvertingIterator(reader->NewIterator(
4709
+ read_opt, /*prefix_extractor=*/nullptr, /*arena=*/nullptr,
4710
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized)));
4711
+ iter->Seek("foo");
4712
+ ASSERT_FALSE(iter->Valid());
4713
+ ASSERT_OK(iter->status());
4714
+ ASSERT_TRUE(iter->UpperBoundCheckResult() == IterBoundCheck::kOutOfBound);
4715
+ }
4716
+
4717
+ // BlockBasedTableIterator should invalidate itself and return
4718
+ // OutOfBound()=true after Next(), if it finds current index key is no smaller
4719
+ // than upper bound, unless it is pointing to the last data block.
4720
+ TEST_P(BlockBasedTableTest, OutOfBoundOnNext) {
4721
+ TableConstructor c(BytewiseComparator(), true /*convert_to_internal_key*/);
4722
+ c.Add("bar", "v");
4723
+ c.Add("foo", "v");
4724
+ std::vector<std::string> keys;
4725
+ stl_wrappers::KVMap kvmap;
4726
+ Options options;
4727
+ BlockBasedTableOptions table_opt(GetBlockBasedTableOptions());
4728
+ table_opt.flush_block_policy_factory =
4729
+ std::make_shared<FlushBlockEveryKeyPolicyFactory>();
4730
+ options.table_factory.reset(NewBlockBasedTableFactory(table_opt));
4731
+ const ImmutableCFOptions ioptions(options);
4732
+ const MutableCFOptions moptions(options);
4733
+ c.Finish(options, ioptions, moptions, table_opt,
4734
+ GetPlainInternalComparator(BytewiseComparator()), &keys, &kvmap);
4735
+ auto* reader = c.GetTableReader();
4736
+ ReadOptions read_opt;
4737
+ std::string ub1 = "bar_after";
4738
+ Slice ub_slice1(ub1);
4739
+ read_opt.iterate_upper_bound = &ub_slice1;
4740
+ std::unique_ptr<InternalIterator> iter;
4741
+ iter.reset(new KeyConvertingIterator(reader->NewIterator(
4742
+ read_opt, /*prefix_extractor=*/nullptr, /*arena=*/nullptr,
4743
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized)));
4744
+ iter->Seek("bar");
4745
+ ASSERT_TRUE(iter->Valid());
4746
+ ASSERT_EQ("bar", iter->key());
4747
+ iter->Next();
4748
+ ASSERT_FALSE(iter->Valid());
4749
+ ASSERT_TRUE(iter->UpperBoundCheckResult() == IterBoundCheck::kOutOfBound);
4750
+ std::string ub2 = "foo_after";
4751
+ Slice ub_slice2(ub2);
4752
+ read_opt.iterate_upper_bound = &ub_slice2;
4753
+ iter.reset(new KeyConvertingIterator(reader->NewIterator(
4754
+ read_opt, /*prefix_extractor=*/nullptr, /*arena=*/nullptr,
4755
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized)));
4756
+ iter->Seek("foo");
4757
+ ASSERT_TRUE(iter->Valid());
4758
+ ASSERT_EQ("foo", iter->key());
4759
+ iter->Next();
4760
+ ASSERT_FALSE(iter->Valid());
4761
+ ASSERT_FALSE(iter->UpperBoundCheckResult() == IterBoundCheck::kOutOfBound);
4762
+ }
4763
+
4764
+ } // namespace ROCKSDB_NAMESPACE
4765
+
4766
+ int main(int argc, char** argv) {
4767
+ ::testing::InitGoogleTest(&argc, argv);
4768
+ return RUN_ALL_TESTS();
4769
+ }