@nxtedition/rocksdb 15.4.1 → 16.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 (401) hide show
  1. package/binding.cc +70 -23
  2. package/deps/rocksdb/rocksdb/.clang-tidy +86 -0
  3. package/deps/rocksdb/rocksdb/BUCK +42 -0
  4. package/deps/rocksdb/rocksdb/CMakeLists.txt +11 -0
  5. package/deps/rocksdb/rocksdb/Makefile +59 -32
  6. package/deps/rocksdb/rocksdb/cache/cache.cc +0 -5
  7. package/deps/rocksdb/rocksdb/cache/cache_entry_stats.h +9 -9
  8. package/deps/rocksdb/rocksdb/cache/cache_key.cc +3 -3
  9. package/deps/rocksdb/rocksdb/cache/cache_key.h +5 -5
  10. package/deps/rocksdb/rocksdb/cache/cache_reservation_manager.h +16 -16
  11. package/deps/rocksdb/rocksdb/cache/cache_test.cc +1 -1
  12. package/deps/rocksdb/rocksdb/cache/clock_cache.cc +258 -294
  13. package/deps/rocksdb/rocksdb/cache/clock_cache.h +98 -49
  14. package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.cc +1 -5
  15. package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache_test.cc +2 -3
  16. package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +18 -18
  17. package/deps/rocksdb/rocksdb/crash_test.mk +5 -1
  18. package/deps/rocksdb/rocksdb/db/blob/blob_file_builder.cc +23 -22
  19. package/deps/rocksdb/rocksdb/db/blob/blob_file_builder.h +6 -1
  20. package/deps/rocksdb/rocksdb/db/blob/blob_file_builder_test.cc +14 -16
  21. package/deps/rocksdb/rocksdb/db/blob/blob_file_reader.cc +38 -26
  22. package/deps/rocksdb/rocksdb/db/blob/blob_file_reader.h +5 -1
  23. package/deps/rocksdb/rocksdb/db/blob/blob_file_reader_test.cc +101 -18
  24. package/deps/rocksdb/rocksdb/db/blob/blob_index.h +12 -0
  25. package/deps/rocksdb/rocksdb/db/blob/blob_source_test.cc +6 -9
  26. package/deps/rocksdb/rocksdb/db/builder.cc +23 -0
  27. package/deps/rocksdb/rocksdb/db/builder.h +7 -0
  28. package/deps/rocksdb/rocksdb/db/c.cc +373 -57
  29. package/deps/rocksdb/rocksdb/db/c_test.c +101 -1
  30. package/deps/rocksdb/rocksdb/db/column_family.cc +31 -3
  31. package/deps/rocksdb/rocksdb/db/column_family_test.cc +10 -13
  32. package/deps/rocksdb/rocksdb/db/compact_files_test.cc +35 -48
  33. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +13 -5
  34. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +201 -39
  35. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +15 -10
  36. package/deps/rocksdb/rocksdb/db/compaction/compaction_job_stats_test.cc +7 -7
  37. package/deps/rocksdb/rocksdb/db/compaction/compaction_job_test.cc +2 -455
  38. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +4 -2
  39. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.h +19 -0
  40. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.cc +72 -9
  41. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.h +12 -10
  42. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.cc +405 -83
  43. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.h +25 -1
  44. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_level.cc +23 -10
  45. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_level.h +1 -0
  46. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +1410 -106
  47. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +12 -5
  48. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.h +2 -1
  49. package/deps/rocksdb/rocksdb/db/compaction/compaction_service_job.cc +19 -10
  50. package/deps/rocksdb/rocksdb/db/compaction/compaction_service_test.cc +505 -45
  51. package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.cc +2 -2
  52. package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.h +9 -1
  53. package/deps/rocksdb/rocksdb/db/compaction/tiered_compaction_test.cc +4 -4
  54. package/deps/rocksdb/rocksdb/db/comparator_db_test.cc +7 -9
  55. package/deps/rocksdb/rocksdb/db/convenience.cc +4 -4
  56. package/deps/rocksdb/rocksdb/db/convenience_impl.h +2 -1
  57. package/deps/rocksdb/rocksdb/db/corruption_test.cc +60 -88
  58. package/deps/rocksdb/rocksdb/db/cuckoo_table_db_test.cc +10 -12
  59. package/deps/rocksdb/rocksdb/db/db_basic_test.cc +471 -40
  60. package/deps/rocksdb/rocksdb/db/db_block_cache_test.cc +116 -2
  61. package/deps/rocksdb/rocksdb/db/db_bloom_filter_test.cc +5 -15
  62. package/deps/rocksdb/rocksdb/db/db_compaction_abort_test.cc +993 -0
  63. package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +329 -29
  64. package/deps/rocksdb/rocksdb/db/db_flush_test.cc +155 -13
  65. package/deps/rocksdb/rocksdb/db/db_impl/compacted_db_impl.cc +54 -31
  66. package/deps/rocksdb/rocksdb/db/db_impl/compacted_db_impl.h +1 -0
  67. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +232 -70
  68. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +57 -9
  69. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +224 -31
  70. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_debug.cc +5 -0
  71. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_experimental.cc +4 -2
  72. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_files.cc +1 -1
  73. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_follower.cc +1 -0
  74. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +164 -8
  75. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_readonly.cc +6 -0
  76. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_readonly.h +5 -0
  77. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.cc +47 -35
  78. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.h +22 -9
  79. package/deps/rocksdb/rocksdb/db/db_iter.cc +9 -0
  80. package/deps/rocksdb/rocksdb/db/db_iterator_test.cc +371 -6
  81. package/deps/rocksdb/rocksdb/db/db_log_iter_test.cc +7 -5
  82. package/deps/rocksdb/rocksdb/db/db_logical_block_size_cache_test.cc +22 -23
  83. package/deps/rocksdb/rocksdb/db/db_memtable_test.cc +0 -2
  84. package/deps/rocksdb/rocksdb/db/db_merge_operator_test.cc +4 -4
  85. package/deps/rocksdb/rocksdb/db/db_options_test.cc +40 -0
  86. package/deps/rocksdb/rocksdb/db/db_properties_test.cc +32 -13
  87. package/deps/rocksdb/rocksdb/db/db_range_del_test.cc +1 -1
  88. package/deps/rocksdb/rocksdb/db/db_readonly_with_timestamp_test.cc +4 -4
  89. package/deps/rocksdb/rocksdb/db/db_secondary_test.cc +68 -15
  90. package/deps/rocksdb/rocksdb/db/db_sst_test.cc +1 -1
  91. package/deps/rocksdb/rocksdb/db/db_statistics_test.cc +2 -3
  92. package/deps/rocksdb/rocksdb/db/db_table_properties_test.cc +6 -21
  93. package/deps/rocksdb/rocksdb/db/db_test.cc +644 -128
  94. package/deps/rocksdb/rocksdb/db/db_test2.cc +198 -81
  95. package/deps/rocksdb/rocksdb/db/db_test_util.cc +35 -10
  96. package/deps/rocksdb/rocksdb/db/db_test_util.h +8 -2
  97. package/deps/rocksdb/rocksdb/db/db_wal_test.cc +36 -32
  98. package/deps/rocksdb/rocksdb/db/db_with_timestamp_basic_test.cc +11 -7
  99. package/deps/rocksdb/rocksdb/db/db_with_timestamp_compaction_test.cc +499 -0
  100. package/deps/rocksdb/rocksdb/db/db_write_buffer_manager_test.cc +284 -20
  101. package/deps/rocksdb/rocksdb/db/db_write_test.cc +3 -3
  102. package/deps/rocksdb/rocksdb/db/dbformat.h +0 -5
  103. package/deps/rocksdb/rocksdb/db/error_handler.cc +24 -0
  104. package/deps/rocksdb/rocksdb/db/error_handler_fs_test.cc +12 -14
  105. package/deps/rocksdb/rocksdb/db/experimental.cc +13 -10
  106. package/deps/rocksdb/rocksdb/db/external_sst_file_basic_test.cc +1 -1
  107. package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +22 -3
  108. package/deps/rocksdb/rocksdb/db/external_sst_file_test.cc +21 -15
  109. package/deps/rocksdb/rocksdb/db/fault_injection_test.cc +4 -6
  110. package/deps/rocksdb/rocksdb/db/flush_job.cc +11 -3
  111. package/deps/rocksdb/rocksdb/db/forward_iterator_bench.cc +5 -6
  112. package/deps/rocksdb/rocksdb/db/import_column_family_job.cc +4 -2
  113. package/deps/rocksdb/rocksdb/db/import_column_family_test.cc +17 -17
  114. package/deps/rocksdb/rocksdb/db/internal_stats.cc +13 -0
  115. package/deps/rocksdb/rocksdb/db/internal_stats.h +2 -0
  116. package/deps/rocksdb/rocksdb/db/listener_test.cc +154 -27
  117. package/deps/rocksdb/rocksdb/db/manual_compaction_test.cc +6 -6
  118. package/deps/rocksdb/rocksdb/db/memtable.cc +197 -51
  119. package/deps/rocksdb/rocksdb/db/memtable.h +6 -0
  120. package/deps/rocksdb/rocksdb/db/memtable_list_test.cc +3 -4
  121. package/deps/rocksdb/rocksdb/db/merge_test.cc +37 -35
  122. package/deps/rocksdb/rocksdb/db/obsolete_files_test.cc +2 -1
  123. package/deps/rocksdb/rocksdb/db/options_file_test.cc +4 -4
  124. package/deps/rocksdb/rocksdb/db/perf_context_test.cc +9 -11
  125. package/deps/rocksdb/rocksdb/db/periodic_task_scheduler.cc +10 -1
  126. package/deps/rocksdb/rocksdb/db/periodic_task_scheduler_test.cc +292 -15
  127. package/deps/rocksdb/rocksdb/db/plain_table_db_test.cc +10 -17
  128. package/deps/rocksdb/rocksdb/db/prefix_test.cc +6 -8
  129. package/deps/rocksdb/rocksdb/db/repair.cc +10 -10
  130. package/deps/rocksdb/rocksdb/db/seqno_time_test.cc +5 -5
  131. package/deps/rocksdb/rocksdb/db/table_cache.cc +142 -135
  132. package/deps/rocksdb/rocksdb/db/table_cache.h +30 -6
  133. package/deps/rocksdb/rocksdb/db/table_cache_sync_and_async.h +7 -7
  134. package/deps/rocksdb/rocksdb/db/version_builder.cc +11 -50
  135. package/deps/rocksdb/rocksdb/db/version_builder.h +2 -1
  136. package/deps/rocksdb/rocksdb/db/version_builder_test.cc +2 -1
  137. package/deps/rocksdb/rocksdb/db/version_edit.cc +51 -2
  138. package/deps/rocksdb/rocksdb/db/version_edit.h +91 -29
  139. package/deps/rocksdb/rocksdb/db/version_edit_handler.h +7 -7
  140. package/deps/rocksdb/rocksdb/db/version_set.cc +211 -50
  141. package/deps/rocksdb/rocksdb/db/version_set.h +40 -3
  142. package/deps/rocksdb/rocksdb/db/version_set_sync_and_async.h +5 -0
  143. package/deps/rocksdb/rocksdb/db/version_set_test.cc +294 -21
  144. package/deps/rocksdb/rocksdb/db/version_util.cc +96 -0
  145. package/deps/rocksdb/rocksdb/db/version_util.h +24 -0
  146. package/deps/rocksdb/rocksdb/db/wide/db_wide_basic_test.cc +5 -5
  147. package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization.cc +647 -31
  148. package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization.h +219 -1
  149. package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization_test.cc +549 -12
  150. package/deps/rocksdb/rocksdb/db/write_callback_test.cc +3 -3
  151. package/deps/rocksdb/rocksdb/db_stress_tool/cf_consistency_stress.cc +1 -1
  152. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.cc +19 -0
  153. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +21 -4
  154. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_env_wrapper.h +32 -0
  155. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +74 -22
  156. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_listener.h +9 -0
  157. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +143 -61
  158. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.h +15 -2
  159. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_tool.cc +76 -2
  160. package/deps/rocksdb/rocksdb/db_stress_tool/no_batched_ops_stress.cc +92 -72
  161. package/deps/rocksdb/rocksdb/env/env.cc +1 -0
  162. package/deps/rocksdb/rocksdb/env/env_test.cc +365 -2
  163. package/deps/rocksdb/rocksdb/env/fs_posix.cc +31 -30
  164. package/deps/rocksdb/rocksdb/env/io_posix.cc +8 -11
  165. package/deps/rocksdb/rocksdb/env/io_posix.h +30 -1
  166. package/deps/rocksdb/rocksdb/env/io_posix_test.cc +43 -0
  167. package/deps/rocksdb/rocksdb/file/delete_scheduler.cc +1 -1
  168. package/deps/rocksdb/rocksdb/file/delete_scheduler_test.cc +108 -0
  169. package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.cc +32 -4
  170. package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.h +4 -4
  171. package/deps/rocksdb/rocksdb/file/file_util.cc +8 -2
  172. package/deps/rocksdb/rocksdb/file/file_util.h +2 -1
  173. package/deps/rocksdb/rocksdb/file/prefetch_test.cc +331 -12
  174. package/deps/rocksdb/rocksdb/file/random_access_file_reader.cc +52 -35
  175. package/deps/rocksdb/rocksdb/folly.mk +22 -5
  176. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_cache.h +1 -1
  177. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_compression.h +100 -54
  178. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +67 -2
  179. package/deps/rocksdb/rocksdb/include/rocksdb/c.h +149 -13
  180. package/deps/rocksdb/rocksdb/include/rocksdb/cache.h +1 -12
  181. package/deps/rocksdb/rocksdb/include/rocksdb/db.h +78 -97
  182. package/deps/rocksdb/rocksdb/include/rocksdb/experimental.h +3 -3
  183. package/deps/rocksdb/rocksdb/include/rocksdb/external_table.h +2 -2
  184. package/deps/rocksdb/rocksdb/include/rocksdb/file_checksum.h +5 -0
  185. package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +17 -2
  186. package/deps/rocksdb/rocksdb/include/rocksdb/functor_wrapper.h +1 -1
  187. package/deps/rocksdb/rocksdb/include/rocksdb/io_dispatcher.h +358 -0
  188. package/deps/rocksdb/rocksdb/include/rocksdb/iostats_context.h +13 -0
  189. package/deps/rocksdb/rocksdb/include/rocksdb/listener.h +43 -0
  190. package/deps/rocksdb/rocksdb/include/rocksdb/memtablerep.h +20 -0
  191. package/deps/rocksdb/rocksdb/include/rocksdb/options.h +63 -21
  192. package/deps/rocksdb/rocksdb/include/rocksdb/perf_context.h +10 -1
  193. package/deps/rocksdb/rocksdb/include/rocksdb/rate_limiter.h +1 -1
  194. package/deps/rocksdb/rocksdb/include/rocksdb/slice_transform.h +2 -7
  195. package/deps/rocksdb/rocksdb/include/rocksdb/sst_file_reader.h +13 -0
  196. package/deps/rocksdb/rocksdb/include/rocksdb/sst_file_writer.h +3 -14
  197. package/deps/rocksdb/rocksdb/include/rocksdb/statistics.h +49 -9
  198. package/deps/rocksdb/rocksdb/include/rocksdb/status.h +8 -0
  199. package/deps/rocksdb/rocksdb/include/rocksdb/table.h +77 -6
  200. package/deps/rocksdb/rocksdb/include/rocksdb/table_properties.h +15 -0
  201. package/deps/rocksdb/rocksdb/include/rocksdb/tool_hooks.h +16 -10
  202. package/deps/rocksdb/rocksdb/include/rocksdb/unique_id.h +5 -5
  203. package/deps/rocksdb/rocksdb/include/rocksdb/universal_compaction.h +2 -4
  204. package/deps/rocksdb/rocksdb/include/rocksdb/user_defined_index.h +106 -46
  205. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/db_ttl.h +1 -1
  206. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/ldb_cmd.h +14 -1
  207. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/memory_util.h +5 -1
  208. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/optimistic_transaction_db.h +2 -1
  209. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +7 -9
  210. package/deps/rocksdb/rocksdb/include/rocksdb/version.h +2 -2
  211. package/deps/rocksdb/rocksdb/logging/auto_roll_logger_test.cc +1 -2
  212. package/deps/rocksdb/rocksdb/memory/memory_allocator_test.cc +2 -2
  213. package/deps/rocksdb/rocksdb/memtable/inlineskiplist.h +226 -8
  214. package/deps/rocksdb/rocksdb/memtable/inlineskiplist_test.cc +490 -0
  215. package/deps/rocksdb/rocksdb/memtable/skiplist.h +3 -3
  216. package/deps/rocksdb/rocksdb/memtable/skiplistrep.cc +11 -0
  217. package/deps/rocksdb/rocksdb/microbench/db_basic_bench.cc +4 -12
  218. package/deps/rocksdb/rocksdb/microbench/ribbon_bench.cc +5 -5
  219. package/deps/rocksdb/rocksdb/monitoring/file_read_sample.h +21 -4
  220. package/deps/rocksdb/rocksdb/monitoring/perf_context.cc +9 -3
  221. package/deps/rocksdb/rocksdb/monitoring/statistics.cc +21 -2
  222. package/deps/rocksdb/rocksdb/monitoring/stats_history_test.cc +2 -2
  223. package/deps/rocksdb/rocksdb/options/cf_options.cc +21 -1
  224. package/deps/rocksdb/rocksdb/options/cf_options.h +2 -0
  225. package/deps/rocksdb/rocksdb/options/customizable_test.cc +0 -2
  226. package/deps/rocksdb/rocksdb/options/db_options.cc +26 -5
  227. package/deps/rocksdb/rocksdb/options/db_options.h +3 -1
  228. package/deps/rocksdb/rocksdb/options/options.cc +5 -1
  229. package/deps/rocksdb/rocksdb/options/options_helper.cc +7 -2
  230. package/deps/rocksdb/rocksdb/options/options_settable_test.cc +109 -103
  231. package/deps/rocksdb/rocksdb/options/options_test.cc +14 -0
  232. package/deps/rocksdb/rocksdb/port/jemalloc_helper.h +15 -17
  233. package/deps/rocksdb/rocksdb/port/lang.h +4 -0
  234. package/deps/rocksdb/rocksdb/port/port_example.h +0 -23
  235. package/deps/rocksdb/rocksdb/port/stack_trace.cc +36 -0
  236. package/deps/rocksdb/rocksdb/port/stack_trace.h +9 -0
  237. package/deps/rocksdb/rocksdb/src.mk +12 -0
  238. package/deps/rocksdb/rocksdb/table/adaptive/adaptive_table_factory.cc +1 -2
  239. package/deps/rocksdb/rocksdb/table/block_based/binary_search_index_reader.cc +2 -1
  240. package/deps/rocksdb/rocksdb/table/block_based/block.cc +571 -292
  241. package/deps/rocksdb/rocksdb/table/block_based/block.h +143 -53
  242. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +154 -90
  243. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.h +5 -1
  244. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.cc +51 -14
  245. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.h +0 -2
  246. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.cc +147 -734
  247. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.h +30 -233
  248. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +178 -108
  249. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +13 -0
  250. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_impl.h +17 -4
  251. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_sync_and_async.h +5 -2
  252. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_test.cc +70 -0
  253. package/deps/rocksdb/rocksdb/table/block_based/block_builder.cc +168 -24
  254. package/deps/rocksdb/rocksdb/table/block_based/block_builder.h +25 -9
  255. package/deps/rocksdb/rocksdb/table/block_based/block_cache.cc +7 -4
  256. package/deps/rocksdb/rocksdb/table/block_based/block_cache.h +9 -2
  257. package/deps/rocksdb/rocksdb/table/block_based/block_test.cc +548 -169
  258. package/deps/rocksdb/rocksdb/table/block_based/block_type.h +30 -0
  259. package/deps/rocksdb/rocksdb/table/block_based/block_util.h +156 -0
  260. package/deps/rocksdb/rocksdb/table/block_based/data_block_footer.cc +73 -30
  261. package/deps/rocksdb/rocksdb/table/block_based/data_block_footer.h +74 -7
  262. package/deps/rocksdb/rocksdb/table/block_based/data_block_hash_index.h +1 -1
  263. package/deps/rocksdb/rocksdb/table/block_based/index_builder.cc +20 -14
  264. package/deps/rocksdb/rocksdb/table/block_based/index_builder.h +22 -12
  265. package/deps/rocksdb/rocksdb/table/block_based/mock_block_based_table.h +1 -1
  266. package/deps/rocksdb/rocksdb/table/block_based/multi_scan_index_iterator.cc +332 -0
  267. package/deps/rocksdb/rocksdb/table/block_based/multi_scan_index_iterator.h +133 -0
  268. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +4 -2
  269. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block_test.cc +1 -1
  270. package/deps/rocksdb/rocksdb/table/block_based/reader_common.cc +3 -2
  271. package/deps/rocksdb/rocksdb/table/block_based/reader_common.h +4 -1
  272. package/deps/rocksdb/rocksdb/table/block_based/uncompression_dict_reader.h +0 -1
  273. package/deps/rocksdb/rocksdb/table/block_based/user_defined_index_wrapper.h +126 -46
  274. package/deps/rocksdb/rocksdb/table/block_fetcher.cc +31 -3
  275. package/deps/rocksdb/rocksdb/table/block_fetcher_test.cc +1 -2
  276. package/deps/rocksdb/rocksdb/table/cleanable_test.cc +3 -1
  277. package/deps/rocksdb/rocksdb/table/external_table.cc +25 -4
  278. package/deps/rocksdb/rocksdb/table/format.cc +27 -15
  279. package/deps/rocksdb/rocksdb/table/format.h +41 -15
  280. package/deps/rocksdb/rocksdb/table/merging_iterator.cc +1 -0
  281. package/deps/rocksdb/rocksdb/table/meta_blocks.cc +22 -12
  282. package/deps/rocksdb/rocksdb/table/meta_blocks.h +0 -1
  283. package/deps/rocksdb/rocksdb/table/sst_file_dumper.cc +7 -21
  284. package/deps/rocksdb/rocksdb/table/sst_file_dumper.h +0 -1
  285. package/deps/rocksdb/rocksdb/table/sst_file_reader.cc +88 -13
  286. package/deps/rocksdb/rocksdb/table/sst_file_reader_test.cc +53 -42
  287. package/deps/rocksdb/rocksdb/table/sst_file_writer.cc +3 -12
  288. package/deps/rocksdb/rocksdb/table/table_builder.h +0 -4
  289. package/deps/rocksdb/rocksdb/table/table_properties.cc +18 -0
  290. package/deps/rocksdb/rocksdb/table/table_reader_bench.cc +2 -3
  291. package/deps/rocksdb/rocksdb/table/table_test.cc +848 -172
  292. package/deps/rocksdb/rocksdb/table/unique_id.cc +24 -20
  293. package/deps/rocksdb/rocksdb/table/unique_id_impl.h +8 -8
  294. package/deps/rocksdb/rocksdb/test_util/sync_point.h +5 -4
  295. package/deps/rocksdb/rocksdb/test_util/testutil.cc +2 -1
  296. package/deps/rocksdb/rocksdb/test_util/testutil.h +2 -2
  297. package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_trace_analyzer_test.cc +2 -1
  298. package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +238 -120
  299. package/deps/rocksdb/rocksdb/tools/db_repl_stress.cc +2 -2
  300. package/deps/rocksdb/rocksdb/tools/db_sanity_test.cc +2 -4
  301. package/deps/rocksdb/rocksdb/tools/dump/db_dump_tool.cc +4 -8
  302. package/deps/rocksdb/rocksdb/tools/dump/rocksdb_undump.cc +1 -1
  303. package/deps/rocksdb/rocksdb/tools/io_tracer_parser_test.cc +2 -3
  304. package/deps/rocksdb/rocksdb/tools/ldb_cmd.cc +82 -20
  305. package/deps/rocksdb/rocksdb/tools/ldb_cmd_test.cc +41 -47
  306. package/deps/rocksdb/rocksdb/tools/ldb_tool.cc +9 -0
  307. package/deps/rocksdb/rocksdb/tools/reduce_levels_test.cc +5 -6
  308. package/deps/rocksdb/rocksdb/tools/sst_dump_tool.cc +1 -1
  309. package/deps/rocksdb/rocksdb/tools/tool_hooks.cc +6 -5
  310. package/deps/rocksdb/rocksdb/tools/trace_analyzer_test.cc +4 -4
  311. package/deps/rocksdb/rocksdb/tools/write_stress.cc +1 -3
  312. package/deps/rocksdb/rocksdb/util/atomic.h +30 -23
  313. package/deps/rocksdb/rocksdb/util/auto_tune_compressor.cc +6 -7
  314. package/deps/rocksdb/rocksdb/util/auto_tune_compressor.h +3 -3
  315. package/deps/rocksdb/rocksdb/util/bit_fields.h +68 -46
  316. package/deps/rocksdb/rocksdb/util/bloom_impl.h +16 -16
  317. package/deps/rocksdb/rocksdb/util/coding.h +14 -27
  318. package/deps/rocksdb/rocksdb/util/compression.cc +365 -207
  319. package/deps/rocksdb/rocksdb/util/compression.h +16 -1298
  320. package/deps/rocksdb/rocksdb/util/compression_test.cc +347 -61
  321. package/deps/rocksdb/rocksdb/util/crc32c_arm64.cc +8 -9
  322. package/deps/rocksdb/rocksdb/util/crc32c_arm64.h +1 -1
  323. package/deps/rocksdb/rocksdb/util/crc32c_ppc.h +1 -1
  324. package/deps/rocksdb/rocksdb/util/dynamic_bloom_test.cc +3 -3
  325. package/deps/rocksdb/rocksdb/util/filter_bench.cc +18 -18
  326. package/deps/rocksdb/rocksdb/util/gflags_compat.h +3 -3
  327. package/deps/rocksdb/rocksdb/util/hash_test.cc +19 -7
  328. package/deps/rocksdb/rocksdb/util/io_dispatcher_imp.cc +1099 -0
  329. package/deps/rocksdb/rocksdb/util/io_dispatcher_imp.h +36 -0
  330. package/deps/rocksdb/rocksdb/util/io_dispatcher_test.cc +1919 -0
  331. package/deps/rocksdb/rocksdb/util/math.h +3 -1
  332. package/deps/rocksdb/rocksdb/util/mutexlock.h +19 -19
  333. package/deps/rocksdb/rocksdb/util/ribbon_alg.h +25 -25
  334. package/deps/rocksdb/rocksdb/util/simple_mixed_compressor.cc +5 -7
  335. package/deps/rocksdb/rocksdb/util/simple_mixed_compressor.h +4 -5
  336. package/deps/rocksdb/rocksdb/util/slice.cc +0 -10
  337. package/deps/rocksdb/rocksdb/util/slice_test.cc +35 -1
  338. package/deps/rocksdb/rocksdb/util/slice_transform_test.cc +5 -7
  339. package/deps/rocksdb/rocksdb/util/status.cc +3 -1
  340. package/deps/rocksdb/rocksdb/util/stop_watch.h +2 -0
  341. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine.cc +4 -1
  342. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +123 -78
  343. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_compaction_filter.cc +12 -93
  344. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_compaction_filter.h +1 -4
  345. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db.cc +0 -21
  346. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db.h +6 -48
  347. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_impl.cc +94 -307
  348. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_impl.h +12 -58
  349. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_impl_filesnapshot.cc +2 -8
  350. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_listener.h +2 -3
  351. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_test.cc +205 -811
  352. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_dump_tool.cc +18 -9
  353. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_file.cc +2 -7
  354. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_file.h +1 -9
  355. package/deps/rocksdb/rocksdb/utilities/cassandra/cassandra_functional_test.cc +17 -11
  356. package/deps/rocksdb/rocksdb/utilities/cassandra/test_utils.cc +1 -1
  357. package/deps/rocksdb/rocksdb/utilities/cassandra/test_utils.h +1 -1
  358. package/deps/rocksdb/rocksdb/utilities/checkpoint/checkpoint_impl.cc +1 -1
  359. package/deps/rocksdb/rocksdb/utilities/checkpoint/checkpoint_test.cc +68 -61
  360. package/deps/rocksdb/rocksdb/utilities/debug.cc +2 -1
  361. package/deps/rocksdb/rocksdb/utilities/fault_injection_fs.cc +105 -59
  362. package/deps/rocksdb/rocksdb/utilities/fault_injection_fs.h +274 -7
  363. package/deps/rocksdb/rocksdb/utilities/fault_injection_fs_test.cc +94 -0
  364. package/deps/rocksdb/rocksdb/utilities/memory/memory_test.cc +13 -17
  365. package/deps/rocksdb/rocksdb/utilities/memory/memory_util.cc +16 -3
  366. package/deps/rocksdb/rocksdb/utilities/merge_operators/string_append/stringappend_test.cc +25 -25
  367. package/deps/rocksdb/rocksdb/utilities/object_registry.cc +40 -40
  368. package/deps/rocksdb/rocksdb/utilities/option_change_migration/option_change_migration.cc +2 -5
  369. package/deps/rocksdb/rocksdb/utilities/options/options_util_test.cc +17 -19
  370. package/deps/rocksdb/rocksdb/utilities/persistent_cache/block_cache_tier_file.cc +2 -2
  371. package/deps/rocksdb/rocksdb/utilities/persistent_cache/block_cache_tier_file.h +2 -2
  372. package/deps/rocksdb/rocksdb/utilities/persistent_cache/volatile_tier_impl.cc +1 -1
  373. package/deps/rocksdb/rocksdb/utilities/transactions/optimistic_transaction_db_impl.cc +2 -2
  374. package/deps/rocksdb/rocksdb/utilities/transactions/optimistic_transaction_db_impl.h +4 -13
  375. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.cc +3 -3
  376. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.h +6 -0
  377. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_transaction_seqno_test.cc +431 -0
  378. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_transaction_test.cc +1 -2
  379. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_txn.h +91 -0
  380. package/deps/rocksdb/rocksdb/utilities/trie_index/bitvector.cc +562 -0
  381. package/deps/rocksdb/rocksdb/utilities/trie_index/bitvector.h +615 -0
  382. package/deps/rocksdb/rocksdb/utilities/trie_index/louds_trie.cc +2575 -0
  383. package/deps/rocksdb/rocksdb/utilities/trie_index/louds_trie.h +685 -0
  384. package/deps/rocksdb/rocksdb/utilities/trie_index/trie_index_db_test.cc +2843 -0
  385. package/deps/rocksdb/rocksdb/utilities/trie_index/trie_index_factory.cc +567 -0
  386. package/deps/rocksdb/rocksdb/utilities/trie_index/trie_index_factory.h +275 -0
  387. package/deps/rocksdb/rocksdb/utilities/trie_index/trie_index_test.cc +5183 -0
  388. package/deps/rocksdb/rocksdb/utilities/ttl/db_ttl_impl.cc +4 -3
  389. package/deps/rocksdb/rocksdb/utilities/ttl/db_ttl_impl.h +1 -1
  390. package/deps/rocksdb/rocksdb/utilities/ttl/ttl_test.cc +2 -2
  391. package/deps/rocksdb/rocksdb/utilities/write_batch_with_index/write_batch_with_index_internal.h +3 -3
  392. package/deps/rocksdb/rocksdb/utilities/write_batch_with_index/write_batch_with_index_test.cc +93 -88
  393. package/deps/rocksdb/rocksdb.gyp +7 -0
  394. package/index.js +70 -10
  395. package/iterator.js +25 -3
  396. package/max_rev_operator.h +9 -5
  397. package/package.json +1 -1
  398. package/prebuilds/darwin-arm64/@nxtedition+rocksdb.node +0 -0
  399. package/prebuilds/linux-x64/@nxtedition+rocksdb.node +0 -0
  400. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/lua/rocks_lua_custom_library.h +0 -43
  401. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/lua/rocks_lua_util.h +0 -55
@@ -25,6 +25,7 @@
25
25
  #include "rocksdb/table.h"
26
26
  #include "table/block_based/block_based_table_reader.h"
27
27
  #include "table/block_based/block_builder.h"
28
+ #include "table/block_based/data_block_footer.h"
28
29
  #include "table/format.h"
29
30
  #include "test_util/testharness.h"
30
31
  #include "test_util/testutil.h"
@@ -33,10 +34,10 @@
33
34
  namespace ROCKSDB_NAMESPACE {
34
35
 
35
36
  std::string GenerateInternalKey(int primary_key, int secondary_key,
36
- int padding_size, Random *rnd,
37
+ int padding_size, Random* rnd,
37
38
  size_t ts_sz = 0) {
38
39
  char buf[50];
39
- char *p = &buf[0];
40
+ char* p = &buf[0];
40
41
  snprintf(buf, sizeof(buf), "%6d%4d", primary_key, secondary_key);
41
42
  std::string k(p);
42
43
  if (padding_size) {
@@ -55,8 +56,8 @@ std::string GenerateInternalKey(int primary_key, int secondary_key,
55
56
  // Generate random key value pairs.
56
57
  // The generated key will be sorted. You can tune the parameters to generated
57
58
  // different kinds of test key/value pairs for different scenario.
58
- void GenerateRandomKVs(std::vector<std::string> *keys,
59
- std::vector<std::string> *values, const int from,
59
+ void GenerateRandomKVs(std::vector<std::string>* keys,
60
+ std::vector<std::string>* values, const int from,
60
61
  const int len, const int step = 1,
61
62
  const int padding_size = 0,
62
63
  const int keys_share_prefix = 1, size_t ts_sz = 0) {
@@ -75,13 +76,16 @@ void GenerateRandomKVs(std::vector<std::string> *keys,
75
76
  }
76
77
  }
77
78
 
78
- // Test Param 1): key use delta encoding.
79
- // Test Param 2): user-defined timestamp test mode.
80
- // Test Param 3): data block index type.
81
- class BlockTest : public testing::Test,
82
- public testing::WithParamInterface<
83
- std::tuple<bool, test::UserDefinedTimestampTestMode,
84
- BlockBasedTableOptions::DataBlockIndexType>> {
79
+ // Test Param 0): key use delta encoding.
80
+ // Test Param 1): user-defined timestamp test mode.
81
+ // Test Param 2): data block index type.
82
+ // Test Param 3): restart interval.
83
+ // Test Param 4): use separated KV storage.
84
+ class BlockTest
85
+ : public testing::Test,
86
+ public testing::WithParamInterface<std::tuple<
87
+ bool, test::UserDefinedTimestampTestMode,
88
+ BlockBasedTableOptions::DataBlockIndexType, uint32_t, bool>> {
85
89
  public:
86
90
  bool keyUseDeltaEncoding() const { return std::get<0>(GetParam()); }
87
91
  bool isUDTEnabled() const {
@@ -94,6 +98,10 @@ class BlockTest : public testing::Test,
94
98
  BlockBasedTableOptions::DataBlockIndexType dataBlockIndexType() const {
95
99
  return std::get<2>(GetParam());
96
100
  }
101
+
102
+ uint32_t getRestartInterval() const { return std::get<3>(GetParam()); }
103
+
104
+ bool useSeparatedKVStorage() const { return std::get<4>(GetParam()); }
97
105
  };
98
106
 
99
107
  // block test
@@ -110,11 +118,12 @@ TEST_P(BlockTest, SimpleTest) {
110
118
  BlockBasedTableOptions::DataBlockIndexType index_type =
111
119
  isUDTEnabled() ? BlockBasedTableOptions::kDataBlockBinarySearch
112
120
  : dataBlockIndexType();
113
- BlockBuilder builder(16, keyUseDeltaEncoding(),
114
- false /* use_value_delta_encoding */, index_type,
115
- 0.75 /* data_block_hash_table_util_ratio */, ts_sz,
116
- shouldPersistUDT(), false /* is_user_key */);
117
- int num_records = 100000;
121
+ BlockBuilder builder(
122
+ static_cast<int>(getRestartInterval()), keyUseDeltaEncoding(),
123
+ false /* use_value_delta_encoding */, index_type,
124
+ 0.75 /* data_block_hash_table_util_ratio */, ts_sz, shouldPersistUDT(),
125
+ false /* is_user_key */, useSeparatedKVStorage());
126
+ int num_records = 20;
118
127
 
119
128
  GenerateRandomKVs(&keys, &values, 0, num_records, 1 /* step */,
120
129
  0 /* padding_size */, 1 /* keys_share_prefix */, ts_sz);
@@ -129,11 +138,12 @@ TEST_P(BlockTest, SimpleTest) {
129
138
  // create block reader
130
139
  BlockContents contents;
131
140
  contents.data = rawblock;
132
- Block reader(std::move(contents));
141
+ Block reader(std::move(contents), 0 /* read_amp_bytes_per_bit */,
142
+ nullptr /* statistics */, getRestartInterval());
133
143
 
134
144
  // read contents of block sequentially
135
145
  int count = 0;
136
- InternalIterator *iter = reader.NewDataIterator(
146
+ InternalIterator* iter = reader.NewDataIterator(
137
147
  options.comparator, kDisableGlobalSequenceNumber, nullptr /* iter */,
138
148
  nullptr /* stats */, false /* block_contents_pinned */,
139
149
  shouldPersistUDT());
@@ -169,17 +179,18 @@ TEST_P(BlockTest, SimpleTest) {
169
179
 
170
180
  // return the block contents
171
181
  BlockContents GetBlockContents(
172
- std::unique_ptr<BlockBuilder> *builder,
173
- const std::vector<std::string> &keys,
174
- const std::vector<std::string> &values, bool key_use_delta_encoding,
182
+ std::unique_ptr<BlockBuilder>* builder,
183
+ const std::vector<std::string>& keys,
184
+ const std::vector<std::string>& values, bool key_use_delta_encoding,
175
185
  size_t ts_sz, bool should_persist_udt, const int /*prefix_group_size*/ = 1,
176
186
  BlockBasedTableOptions::DataBlockIndexType dblock_index_type =
177
- BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch) {
178
- builder->reset(
179
- new BlockBuilder(1 /* restart interval */, key_use_delta_encoding,
180
- false /* use_value_delta_encoding */, dblock_index_type,
181
- 0.75 /* data_block_hash_table_util_ratio */, ts_sz,
182
- should_persist_udt, false /* is_user_key */));
187
+ BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch,
188
+ bool use_separated_kv_storage = false, uint32_t restart_interval = 1) {
189
+ builder->reset(new BlockBuilder(
190
+ static_cast<int>(restart_interval), key_use_delta_encoding,
191
+ false /* use_value_delta_encoding */, dblock_index_type,
192
+ 0.75 /* data_block_hash_table_util_ratio */, ts_sz, should_persist_udt,
193
+ false /* is_user_key */, use_separated_kv_storage));
183
194
 
184
195
  // Add only half of the keys
185
196
  for (size_t i = 0; i < keys.size(); ++i) {
@@ -194,14 +205,17 @@ BlockContents GetBlockContents(
194
205
  }
195
206
 
196
207
  void CheckBlockContents(BlockContents contents, const int max_key,
197
- const std::vector<std::string> &keys,
198
- const std::vector<std::string> &values,
199
- bool is_udt_enabled, bool should_persist_udt) {
208
+ const std::vector<std::string>& keys,
209
+ const std::vector<std::string>& values,
210
+ bool is_udt_enabled, bool should_persist_udt,
211
+ uint32_t restart_interval) {
200
212
  const size_t prefix_size = 6;
201
213
  // create block reader
202
214
  BlockContents contents_ref(contents.data);
203
- Block reader1(std::move(contents));
204
- Block reader2(std::move(contents_ref));
215
+ Block reader1(std::move(contents), 0 /* read_amp_bytes_per_bit */,
216
+ nullptr /* statistics */, restart_interval);
217
+ Block reader2(std::move(contents_ref), 0 /* read_amp_bytes_per_bit */,
218
+ nullptr /* statistics */, restart_interval);
205
219
 
206
220
  std::unique_ptr<const SliceTransform> prefix_extractor(
207
221
  NewFixedPrefixTransform(prefix_size));
@@ -253,10 +267,11 @@ TEST_P(BlockTest, SimpleIndexHash) {
253
267
  1 /* prefix_group_size */,
254
268
  isUDTEnabled()
255
269
  ? BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch
256
- : dataBlockIndexType());
270
+ : dataBlockIndexType(),
271
+ useSeparatedKVStorage(), getRestartInterval());
257
272
 
258
273
  CheckBlockContents(std::move(contents), kMaxKey, keys, values, isUDTEnabled(),
259
- shouldPersistUDT());
274
+ shouldPersistUDT(), getRestartInterval());
260
275
  }
261
276
 
262
277
  TEST_P(BlockTest, IndexHashWithSharedPrefix) {
@@ -276,14 +291,15 @@ TEST_P(BlockTest, IndexHashWithSharedPrefix) {
276
291
  std::unique_ptr<BlockBuilder> builder;
277
292
 
278
293
  auto contents = GetBlockContents(
279
- &builder, keys, values, keyUseDeltaEncoding(), isUDTEnabled(),
280
- shouldPersistUDT(), kPrefixGroup,
294
+ &builder, keys, values, keyUseDeltaEncoding(), ts_sz, shouldPersistUDT(),
295
+ kPrefixGroup,
281
296
  isUDTEnabled()
282
297
  ? BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch
283
- : dataBlockIndexType());
298
+ : dataBlockIndexType(),
299
+ useSeparatedKVStorage(), getRestartInterval());
284
300
 
285
301
  CheckBlockContents(std::move(contents), kMaxKey, keys, values, isUDTEnabled(),
286
- shouldPersistUDT());
302
+ shouldPersistUDT(), getRestartInterval());
287
303
  }
288
304
 
289
305
  // Param 0: key use delta encoding
@@ -292,6 +308,8 @@ TEST_P(BlockTest, IndexHashWithSharedPrefix) {
292
308
  // compatible with `kDataBlockBinaryAndHash` data block index type because the
293
309
  // user comparator doesn't provide a `CanKeysWithDifferentByteContentsBeEqual`
294
310
  // override. This combination is disabled.
311
+ // Param 3: restart interval
312
+ // Param 4: use separated KV storage
295
313
  INSTANTIATE_TEST_CASE_P(
296
314
  P, BlockTest,
297
315
  ::testing::Combine(
@@ -299,7 +317,8 @@ INSTANTIATE_TEST_CASE_P(
299
317
  ::testing::Values(
300
318
  BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch,
301
319
  BlockBasedTableOptions::DataBlockIndexType::
302
- kDataBlockBinaryAndHash)));
320
+ kDataBlockBinaryAndHash),
321
+ ::testing::Values(1, 8, 16), ::testing::Bool()));
303
322
 
304
323
  // A slow and accurate version of BlockReadAmpBitmap that simply store
305
324
  // all the marked ranges in a set.
@@ -356,8 +375,8 @@ class BlockReadAmpBitmapSlowAndAccurate {
356
375
  TEST_F(BlockTest, BlockReadAmpBitmap) {
357
376
  uint32_t pin_offset = 0;
358
377
  SyncPoint::GetInstance()->SetCallBack(
359
- "BlockReadAmpBitmap:rnd", [&pin_offset](void *arg) {
360
- pin_offset = *(static_cast<uint32_t *>(arg));
378
+ "BlockReadAmpBitmap:rnd", [&pin_offset](void* arg) {
379
+ pin_offset = *(static_cast<uint32_t*>(arg));
361
380
  });
362
381
  SyncPoint::GetInstance()->EnableProcessing();
363
382
  std::vector<size_t> block_sizes = {
@@ -414,7 +433,7 @@ TEST_F(BlockTest, BlockReadAmpBitmap) {
414
433
 
415
434
  for (size_t i = 0; i < random_entries.size(); i++) {
416
435
  read_amp_slow_and_accurate.ResetCheckSequence();
417
- auto &current_entry = random_entries[rnd.Next() % random_entries.size()];
436
+ auto& current_entry = random_entries[rnd.Next() % random_entries.size()];
418
437
 
419
438
  read_amp_bitmap.Mark(static_cast<uint32_t>(current_entry.first),
420
439
  static_cast<uint32_t>(current_entry.second));
@@ -465,7 +484,7 @@ TEST_F(BlockTest, BlockWithReadAmpBitmap) {
465
484
 
466
485
  // read contents of block sequentially
467
486
  size_t read_bytes = 0;
468
- DataBlockIter *iter = reader.NewDataIterator(
487
+ DataBlockIter* iter = reader.NewDataIterator(
469
488
  options.comparator, kDisableGlobalSequenceNumber, nullptr, stats.get());
470
489
  for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
471
490
  iter->value();
@@ -496,7 +515,7 @@ TEST_F(BlockTest, BlockWithReadAmpBitmap) {
496
515
  Block reader(std::move(contents), kBytesPerBit, stats.get());
497
516
 
498
517
  size_t read_bytes = 0;
499
- DataBlockIter *iter = reader.NewDataIterator(
518
+ DataBlockIter* iter = reader.NewDataIterator(
500
519
  options.comparator, kDisableGlobalSequenceNumber, nullptr, stats.get());
501
520
  for (int i = 0; i < num_records; i++) {
502
521
  Slice k(keys[i]);
@@ -530,7 +549,7 @@ TEST_F(BlockTest, BlockWithReadAmpBitmap) {
530
549
  Block reader(std::move(contents), kBytesPerBit, stats.get());
531
550
 
532
551
  size_t read_bytes = 0;
533
- DataBlockIter *iter = reader.NewDataIterator(
552
+ DataBlockIter* iter = reader.NewDataIterator(
534
553
  options.comparator, kDisableGlobalSequenceNumber, nullptr, stats.get());
535
554
  std::unordered_set<int> read_keys;
536
555
  for (int i = 0; i < num_records; i++) {
@@ -576,41 +595,103 @@ TEST_F(BlockTest, ReadAmpBitmapPow2) {
576
595
  ASSERT_EQ(BlockReadAmpBitmap(100, 35, stats.get()).GetBytesPerBit(), 32u);
577
596
  }
578
597
 
598
+ void AddIndexBlockEntry(BlockBuilder& builder, const Slice& key,
599
+ const BlockHandle& bh, const BlockHandle* prev,
600
+ bool include_first_key,
601
+ const Slice& first_internal_key = Slice()) {
602
+ IndexValue entry(bh, first_internal_key);
603
+ std::string encoded_entry;
604
+ entry.EncodeTo(&encoded_entry, include_first_key, nullptr);
605
+ std::string delta_encoded_entry;
606
+ if (prev) {
607
+ entry.EncodeTo(&delta_encoded_entry, include_first_key, prev);
608
+ }
609
+ const Slice delta_slice(delta_encoded_entry);
610
+ builder.Add(key, encoded_entry, &delta_slice);
611
+ }
612
+
613
+ enum class KeyDistribution { kUniform, kNonUniform };
614
+
579
615
  class IndexBlockTest
580
616
  : public testing::Test,
581
617
  public testing::WithParamInterface<
582
- std::tuple<bool, bool, bool, test::UserDefinedTimestampTestMode>> {
618
+ std::tuple<bool, bool, bool, bool, test::UserDefinedTimestampTestMode,
619
+ BlockBasedTableOptions::BlockSearchType, int, int, int,
620
+ std::pair<int, KeyDistribution>>> {
583
621
  public:
584
622
  IndexBlockTest() = default;
585
623
 
586
624
  bool keyIncludesSeq() const { return std::get<0>(GetParam()); }
587
625
  bool useValueDeltaEncoding() const { return std::get<1>(GetParam()); }
588
626
  bool includeFirstKey() const { return std::get<2>(GetParam()); }
627
+ bool useSeparatedKVStorage() const { return std::get<3>(GetParam()); }
589
628
  bool isUDTEnabled() const {
590
- return test::IsUDTEnabled(std::get<3>(GetParam()));
629
+ return test::IsUDTEnabled(std::get<4>(GetParam()));
591
630
  }
592
631
  bool shouldPersistUDT() const {
593
- return test::ShouldPersistUDT(std::get<3>(GetParam()));
632
+ return test::ShouldPersistUDT(std::get<4>(GetParam()));
633
+ }
634
+ BlockBasedTableOptions::BlockSearchType indexSearchType() const {
635
+ return isUDTEnabled() ? BlockBasedTableOptions::kBinary
636
+ : std::get<5>(GetParam());
637
+ }
638
+ int numRecords() const {
639
+ return std::min(1 << keyLength(), std::get<6>(GetParam()));
640
+ }
641
+ int indexBlockRestartInterval() const { return std::get<7>(GetParam()); }
642
+ int keyLength() const { return std::get<8>(GetParam()); }
643
+ // prefix_length and key_distribution are bundled into a std::pair to stay
644
+ // within gtest 1.8.1's 10-parameter Combine limit.
645
+ int prefixLength() const { return std::get<9>(GetParam()).first; }
646
+ KeyDistribution keyDistribution() const {
647
+ return std::get<9>(GetParam()).second;
594
648
  }
595
649
  };
596
650
 
597
- // Similar to GenerateRandomKVs but for index block contents.
598
- void GenerateRandomIndexEntries(std::vector<std::string> *separators,
599
- std::vector<BlockHandle> *block_handles,
600
- std::vector<std::string> *first_keys,
601
- const int len, size_t ts_sz = 0,
602
- bool zero_seqno = false) {
651
+ // Similar to GenerateRandomKVs but for index block contents. Keys always
652
+ // contain a 0-sequence number, callers may extract the user key if needed.
653
+ void GenerateRandomIndexEntries(
654
+ std::vector<std::string>* separators,
655
+ std::vector<BlockHandle>* block_handles,
656
+ std::vector<std::string>* first_keys, const int len, size_t ts_sz = 0,
657
+ int key_length = 12, int prefix_length = 0,
658
+ KeyDistribution distribution = KeyDistribution::kUniform) {
603
659
  Random rnd(42);
660
+ std::string prefix(prefix_length, 'x');
604
661
 
605
662
  // For each of `len` blocks, we need to generate a first and last key.
606
- // Let's generate n*2 random keys, sort them, group into consecutive pairs.
663
+ // Generate n*2 random keys, sort them, group into consecutive pairs.
607
664
  std::set<std::string> keys;
665
+
666
+ // Two clusters with shared prefixes of effective_key_length - 2. This
667
+ // stresses interpolation search's uniform distribution assumption.
668
+ int cluster_prefix_len = std::max(0, key_length - 5);
669
+ std::string cluster1_prefix = prefix + rnd.RandomString(cluster_prefix_len);
670
+ std::string cluster2_prefix = prefix + rnd.RandomString(cluster_prefix_len);
671
+
608
672
  while ((int)keys.size() < len * 2) {
609
- // Keys need to be at least 8 bytes long to look like internal keys.
610
- std::string new_key = test::RandomKey(&rnd, 12);
611
- if (zero_seqno) {
612
- AppendInternalKeyFooter(&new_key, 0 /* seqno */, kTypeValue);
673
+ std::string new_key;
674
+ if (distribution == KeyDistribution::kNonUniform) {
675
+ int remaining = key_length - cluster_prefix_len;
676
+ const std::string& cp =
677
+ (keys.size() % 2 == 0) ? cluster1_prefix : cluster2_prefix;
678
+ new_key = cp + rnd.RandomString(std::max(1, remaining));
679
+ } else {
680
+ // Generate evenly-spaced keys to ensure numeric uniformity.
681
+ // Encode the key index as big-endian with jitter to avoid
682
+ // perfectly equal gaps while maintaining uniformity.
683
+ uint64_t base =
684
+ static_cast<uint64_t>(keys.size()) * 1000 + rnd.Uniform(100);
685
+ std::string key_bytes(key_length, '\0');
686
+ // Write big-endian uint64 into the last 8 bytes (or fewer if shorter)
687
+ for (int j = key_length - 1; j >= 0 && base > 0; j--) {
688
+ key_bytes[j] = static_cast<char>(base & 0xFF);
689
+ base >>= 8;
690
+ }
691
+ new_key = prefix + key_bytes;
613
692
  }
693
+
694
+ AppendInternalKeyFooter(&new_key, 0 /* seqno */, kTypeValue);
614
695
  if (ts_sz > 0) {
615
696
  std::string key;
616
697
  PadInternalKeyWithMinTimestamp(&key, new_key, ts_sz);
@@ -643,15 +724,18 @@ TEST_P(IndexBlockTest, IndexValueEncodingTest) {
643
724
  std::vector<BlockHandle> block_handles;
644
725
  std::vector<std::string> first_keys;
645
726
  const bool kUseDeltaEncoding = true;
646
- BlockBuilder builder(16, kUseDeltaEncoding, useValueDeltaEncoding(),
647
- BlockBasedTableOptions::kDataBlockBinarySearch,
648
- 0.75 /* data_block_hash_table_util_ratio */, ts_sz,
649
- shouldPersistUDT(), !keyIncludesSeq());
727
+ BlockBuilder builder(
728
+ indexBlockRestartInterval(), kUseDeltaEncoding, useValueDeltaEncoding(),
729
+ BlockBasedTableOptions::kDataBlockBinarySearch,
730
+ 0.75 /* data_block_hash_table_util_ratio */, ts_sz, shouldPersistUDT(),
731
+ !keyIncludesSeq(), useSeparatedKVStorage(), nullptr /* statistics */,
732
+ 0.2 /* uniform_cv_threshold */);
650
733
 
651
- int num_records = 100;
734
+ int num_records = numRecords();
652
735
 
653
736
  GenerateRandomIndexEntries(&separators, &block_handles, &first_keys,
654
- num_records, ts_sz, false /* zero_seqno */);
737
+ num_records, ts_sz, keyLength(), prefixLength(),
738
+ keyDistribution());
655
739
  BlockHandle last_encoded_handle;
656
740
  for (int i = 0; i < num_records; i++) {
657
741
  std::string first_key_to_persist_buf;
@@ -661,23 +745,13 @@ TEST_P(IndexBlockTest, IndexValueEncodingTest) {
661
745
  ts_sz);
662
746
  first_internal_key = first_key_to_persist_buf;
663
747
  }
664
- IndexValue entry(block_handles[i], first_internal_key);
665
- std::string encoded_entry;
666
- std::string delta_encoded_entry;
667
- entry.EncodeTo(&encoded_entry, includeFirstKey(), nullptr);
668
- if (useValueDeltaEncoding() && i > 0) {
669
- entry.EncodeTo(&delta_encoded_entry, includeFirstKey(),
670
- &last_encoded_handle);
671
- }
672
- last_encoded_handle = entry.handle;
673
- const Slice delta_encoded_entry_slice(delta_encoded_entry);
674
-
675
- if (keyIncludesSeq()) {
676
- builder.Add(separators[i], encoded_entry, &delta_encoded_entry_slice);
677
- } else {
678
- const Slice user_key = ExtractUserKey(separators[i]);
679
- builder.Add(user_key, encoded_entry, &delta_encoded_entry_slice);
680
- }
748
+ const BlockHandle* prev =
749
+ (useValueDeltaEncoding() && i > 0) ? &last_encoded_handle : nullptr;
750
+ Slice add_key =
751
+ keyIncludesSeq() ? Slice(separators[i]) : ExtractUserKey(separators[i]);
752
+ AddIndexBlockEntry(builder, add_key, block_handles[i], prev,
753
+ includeFirstKey(), first_internal_key);
754
+ last_encoded_handle = block_handles[i];
681
755
  }
682
756
 
683
757
  // read serialized contents of the block
@@ -686,17 +760,19 @@ TEST_P(IndexBlockTest, IndexValueEncodingTest) {
686
760
  // create block reader
687
761
  BlockContents contents;
688
762
  contents.data = rawblock;
689
- Block reader(std::move(contents));
763
+ Block reader(std::move(contents), 0 /* read_amp_bytes_per_bit */,
764
+ nullptr /* statistics */,
765
+ static_cast<uint32_t>(indexBlockRestartInterval()));
690
766
 
691
767
  const bool kTotalOrderSeek = true;
692
- IndexBlockIter *kNullIter = nullptr;
693
- Statistics *kNullStats = nullptr;
768
+ IndexBlockIter* kNullIter = nullptr;
769
+ Statistics* kNullStats = nullptr;
694
770
  // read contents of block sequentially
695
- InternalIteratorBase<IndexValue> *iter = reader.NewIndexIterator(
771
+ InternalIteratorBase<IndexValue>* iter = reader.NewIndexIterator(
696
772
  options.comparator, kDisableGlobalSequenceNumber, kNullIter, kNullStats,
697
773
  kTotalOrderSeek, includeFirstKey(), keyIncludesSeq(),
698
774
  !useValueDeltaEncoding(), false /* block_contents_pinned */,
699
- shouldPersistUDT());
775
+ shouldPersistUDT(), nullptr /* prefix_index */, indexSearchType());
700
776
  iter->SeekToFirst();
701
777
  for (int index = 0; index < num_records; ++index) {
702
778
  ASSERT_TRUE(iter->Valid());
@@ -719,12 +795,22 @@ TEST_P(IndexBlockTest, IndexValueEncodingTest) {
719
795
  }
720
796
  delete iter;
721
797
 
798
+ // ScanForUniformity requires at least 3 restart points to determine
799
+ // uniformity. With fewer restarts, is_uniform is always false.
800
+ // When UDT is enabled, min-timestamps alter the key byte distribution,
801
+ // so skip the uniformity check.
802
+ if (!isUDTEnabled()) {
803
+ bool expect_uniform = reader.NumRestarts() >= 3 &&
804
+ keyDistribution() == KeyDistribution::kUniform;
805
+ EXPECT_EQ(reader.IsUniform(), expect_uniform);
806
+ }
807
+
722
808
  // read block contents randomly
723
809
  iter = reader.NewIndexIterator(
724
810
  options.comparator, kDisableGlobalSequenceNumber, kNullIter, kNullStats,
725
811
  kTotalOrderSeek, includeFirstKey(), keyIncludesSeq(),
726
812
  !useValueDeltaEncoding(), false /* block_contents_pinned */,
727
- shouldPersistUDT());
813
+ shouldPersistUDT(), nullptr /* prefix_index */, indexSearchType());
728
814
  for (int i = 0; i < num_records * 2; i++) {
729
815
  // find a random key in the lookaside array
730
816
  int index = rnd.Uniform(num_records);
@@ -752,11 +838,208 @@ TEST_P(IndexBlockTest, IndexValueEncodingTest) {
752
838
  // key as key entry in index block).
753
839
  // Param 1: use value delta encoding
754
840
  // Param 2: include first key
755
- // Param 3: user-defined timestamp test mode
841
+ // Param 3: use separated KV storage
842
+ // Param 4: user-defined timestamp test mode
843
+ // Param 5: index search type (binary search or interpolation search)
844
+ // Param 6: number of records
845
+ // Param 7: index block restart interval
846
+ // Param 8: key length
847
+ // Param 9: (prefix_length, key_distribution) pair
756
848
  INSTANTIATE_TEST_CASE_P(
757
849
  P, IndexBlockTest,
758
- ::testing::Combine(::testing::Bool(), ::testing::Bool(), ::testing::Bool(),
759
- ::testing::ValuesIn(test::GetUDTTestModes())));
850
+ ::testing::Combine(
851
+ ::testing::Bool(), ::testing::Bool(), ::testing::Bool(),
852
+ ::testing::Bool(), ::testing::ValuesIn(test::GetUDTTestModes()),
853
+ ::testing::Values(
854
+ BlockBasedTableOptions::BlockSearchType::kBinary,
855
+ BlockBasedTableOptions::BlockSearchType::kInterpolation,
856
+ BlockBasedTableOptions::BlockSearchType::kAuto),
857
+ ::testing::Values(1, 100), // num_records
858
+ ::testing::Values(1, 16), // index_block_restart_interval
859
+ ::testing::Values(1, 8, 12), // key_length
860
+ ::testing::Values(std::make_pair(0, KeyDistribution::kUniform),
861
+ std::make_pair(0, KeyDistribution::kNonUniform),
862
+ std::make_pair(50, KeyDistribution::kUniform),
863
+ std::make_pair(50, KeyDistribution::kNonUniform))));
864
+
865
+ TEST(IndexBlockTest, InterpolationSearchPrefixBoundary) {
866
+ const bool kIncludeFirstKey = false;
867
+ const bool kUseValueDeltaEncoding = true;
868
+ const uint64_t kBlockSize = 50;
869
+
870
+ // 20 user keys sharing prefix "ABCDEFGHIJ" with evenly spaced suffixes.
871
+ const std::string kPrefix = "ABCDEFGHIJ";
872
+ const int kNumKeys = 20;
873
+ std::vector<std::string> keys;
874
+ keys.reserve(kNumKeys);
875
+ for (int i = 0; i < kNumKeys; i++) {
876
+ std::string suffix = std::to_string(i);
877
+ char formatted_suffix[4];
878
+ snprintf(formatted_suffix, sizeof(formatted_suffix), "%03d", i);
879
+ keys.push_back(kPrefix + formatted_suffix);
880
+ }
881
+
882
+ std::vector<BlockHandle> handles;
883
+ handles.reserve(kNumKeys);
884
+ for (int i = 0; i < kNumKeys; i++) {
885
+ handles.emplace_back(i * (kBlockSize + BlockBasedTable::kBlockTrailerSize),
886
+ kBlockSize);
887
+ }
888
+
889
+ BlockBuilder builder(
890
+ 1 /* restart_interval */, true /* use_delta_encoding */,
891
+ kUseValueDeltaEncoding, BlockBasedTableOptions::kDataBlockBinarySearch,
892
+ 0.75 /* data_block_hash_table_util_ratio */, 0 /* ts_sz */,
893
+ false /* persist_udt */, true /* is_user_key */);
894
+
895
+ for (int i = 0; i < kNumKeys; i++) {
896
+ BlockHandle* prev = i > 0 ? &handles[i - 1] : nullptr;
897
+ AddIndexBlockEntry(builder, keys[i], handles[i], prev, kIncludeFirstKey);
898
+ }
899
+
900
+ Slice rawblock = builder.Finish();
901
+ BlockContents contents;
902
+ contents.data = rawblock;
903
+ Block reader(std::move(contents));
904
+
905
+ // Seek targets must be internal keys since SeekImpl calls ExtractUserKey().
906
+ auto make_target = [](const std::string& user_key) {
907
+ std::string target = user_key;
908
+ AppendInternalKeyFooter(&target, kMaxSequenceNumber, kValueTypeForSeek);
909
+ return target;
910
+ };
911
+
912
+ std::unique_ptr<InternalIteratorBase<IndexValue>> iter(
913
+ reader.NewIndexIterator(
914
+ BytewiseComparator(), kDisableGlobalSequenceNumber,
915
+ nullptr /* iter */, nullptr /* stats */, true /* total_order_seek */,
916
+ kIncludeFirstKey, false /* key_includes_seq */,
917
+ !kUseValueDeltaEncoding /* value_is_full */,
918
+ false /* block_contents_pinned */,
919
+ true /* user_defined_timestamps_persisted */,
920
+ nullptr /* prefix_index */,
921
+ BlockBasedTableOptions::BlockSearchType::kInterpolation));
922
+
923
+ // Case 1: target prefix < shared prefix
924
+ iter->Seek(make_target("AAAAAA"));
925
+ ASSERT_TRUE(iter->Valid());
926
+ EXPECT_EQ(iter->key(), keys[0]);
927
+
928
+ iter->Seek(make_target(""));
929
+ ASSERT_TRUE(iter->Valid());
930
+ EXPECT_EQ(iter->key(), keys[0]);
931
+
932
+ // Case 2: target prefix > shared prefix
933
+ iter->Seek(make_target("ABCDEFGHZZ"));
934
+ ASSERT_FALSE(iter->Valid());
935
+
936
+ // Case 3: target is the prefix
937
+ iter->Seek(make_target("ABCDEFGHIJ"));
938
+ ASSERT_TRUE(iter->Valid());
939
+ EXPECT_EQ(iter->key(), keys[0]);
940
+
941
+ // Case 4: target a subset of the prefix
942
+ iter->Seek(make_target("ABCDEFG"));
943
+ ASSERT_TRUE(iter->Valid());
944
+ EXPECT_EQ(iter->key(), keys[0]);
945
+ }
946
+
947
+ // Like the above test, but extend the shared prefix into internal bytes
948
+ TEST(IndexBlockTest, InterpolationSearchPrefixBoundary2) {
949
+ const bool kIncludeFirstKey = false;
950
+ const bool kUseValueDeltaEncoding = true;
951
+ const uint64_t kBlockSize = 50;
952
+
953
+ // 20 internal keys with the same user key but decreasing sequence numbers
954
+ // (which is ascending InternalKeyComparator order).
955
+ const std::string kUserKey = "ABCDEFGHIJ";
956
+ const int kNumKeys = 20;
957
+ std::vector<std::string> keys;
958
+ keys.reserve(kNumKeys);
959
+ for (int i = 0; i < kNumKeys; i++) {
960
+ std::string ikey = kUserKey;
961
+ SequenceNumber seq = static_cast<SequenceNumber>(kNumKeys - i);
962
+ AppendInternalKeyFooter(&ikey, seq, kTypeValue);
963
+ keys.push_back(ikey);
964
+ }
965
+
966
+ std::vector<BlockHandle> handles;
967
+ handles.reserve(kNumKeys);
968
+ for (int i = 0; i < kNumKeys; i++) {
969
+ handles.emplace_back(i * (kBlockSize + BlockBasedTable::kBlockTrailerSize),
970
+ kBlockSize);
971
+ }
972
+
973
+ BlockBuilder builder(
974
+ 1 /* restart_interval */, true /* use_delta_encoding */,
975
+ kUseValueDeltaEncoding, BlockBasedTableOptions::kDataBlockBinarySearch,
976
+ 0.75 /* data_block_hash_table_util_ratio */, 0 /* ts_sz */,
977
+ false /* persist_udt */, false /* is_user_key */);
978
+
979
+ for (int i = 0; i < kNumKeys; i++) {
980
+ BlockHandle* prev = i > 0 ? &handles[i - 1] : nullptr;
981
+ AddIndexBlockEntry(builder, keys[i], handles[i], prev, kIncludeFirstKey);
982
+ }
983
+
984
+ Slice rawblock = builder.Finish();
985
+ BlockContents contents;
986
+ contents.data = rawblock;
987
+ Block reader(std::move(contents));
988
+
989
+ auto make_target = [&](const std::string& user_key,
990
+ SequenceNumber seq = kMaxSequenceNumber) {
991
+ std::string target = user_key;
992
+ AppendInternalKeyFooter(&target, seq, kTypeValue);
993
+ return target;
994
+ };
995
+
996
+ std::unique_ptr<InternalIteratorBase<IndexValue>> iter(
997
+ reader.NewIndexIterator(
998
+ BytewiseComparator(), kDisableGlobalSequenceNumber,
999
+ nullptr /* iter */, nullptr /* stats */, true /* total_order_seek */,
1000
+ kIncludeFirstKey, true /* key_includes_seq */,
1001
+ !kUseValueDeltaEncoding /* value_is_full */,
1002
+ false /* block_contents_pinned */,
1003
+ true /* user_defined_timestamps_persisted */,
1004
+ nullptr /* prefix_index */,
1005
+ BlockBasedTableOptions::BlockSearchType::kInterpolation));
1006
+
1007
+ // Seek to each existing sequence number
1008
+ for (int i = 0; i < kNumKeys; i++) {
1009
+ SequenceNumber seq = static_cast<SequenceNumber>(kNumKeys - i);
1010
+ iter->Seek(make_target(kUserKey, seq));
1011
+ ASSERT_TRUE(iter->Valid());
1012
+ EXPECT_EQ(iter->key(), keys[i]);
1013
+ }
1014
+
1015
+ // Case 1: target prefix < shared prefix
1016
+ iter->Seek(make_target("AAAAAA"));
1017
+ ASSERT_TRUE(iter->Valid());
1018
+ EXPECT_EQ(iter->key(), keys[0]);
1019
+
1020
+ iter->Seek(make_target(""));
1021
+ ASSERT_TRUE(iter->Valid());
1022
+ EXPECT_EQ(iter->key(), keys[0]);
1023
+
1024
+ // Case 2: target prefix > shared prefix
1025
+ iter->Seek(make_target("ABCDEFGHZZ"));
1026
+ ASSERT_FALSE(iter->Valid());
1027
+
1028
+ // Case 3: target has the same user key with kMaxSequenceNumber
1029
+ iter->Seek(make_target("ABCDEFGHIJ"));
1030
+ ASSERT_TRUE(iter->Valid());
1031
+ EXPECT_EQ(iter->key(), keys[0]);
1032
+
1033
+ // Case 4: target a subset of the prefix
1034
+ iter->Seek(make_target("ABCDEFG"));
1035
+ ASSERT_TRUE(iter->Valid());
1036
+ EXPECT_EQ(iter->key(), keys[0]);
1037
+
1038
+ // Case 5: target key is a prefix that also extends into the internal bytes
1039
+ // footer
1040
+ iter->Seek(make_target("ABCDEFGHIJ" + std::string(1, kTypeValue)));
1041
+ ASSERT_FALSE(iter->Valid());
1042
+ }
760
1043
 
761
1044
  class BlockPerKVChecksumTest : public DBTestBase {
762
1045
  public:
@@ -764,8 +1047,8 @@ class BlockPerKVChecksumTest : public DBTestBase {
764
1047
  : DBTestBase("block_per_kv_checksum", /*env_do_fsync=*/false) {}
765
1048
 
766
1049
  template <typename TBlockIter>
767
- void TestIterateForward(std::unique_ptr<TBlockIter> &biter,
768
- size_t &verification_count) {
1050
+ void TestIterateForward(std::unique_ptr<TBlockIter>& biter,
1051
+ size_t& verification_count) {
769
1052
  while (biter->Valid()) {
770
1053
  verification_count = 0;
771
1054
  biter->Next();
@@ -776,8 +1059,8 @@ class BlockPerKVChecksumTest : public DBTestBase {
776
1059
  }
777
1060
 
778
1061
  template <typename TBlockIter>
779
- void TestIterateBackward(std::unique_ptr<TBlockIter> &biter,
780
- size_t &verification_count) {
1062
+ void TestIterateBackward(std::unique_ptr<TBlockIter>& biter,
1063
+ size_t& verification_count) {
781
1064
  while (biter->Valid()) {
782
1065
  verification_count = 0;
783
1066
  biter->Prev();
@@ -788,8 +1071,8 @@ class BlockPerKVChecksumTest : public DBTestBase {
788
1071
  }
789
1072
 
790
1073
  template <typename TBlockIter>
791
- void TestSeekToFirst(std::unique_ptr<TBlockIter> &biter,
792
- size_t &verification_count) {
1074
+ void TestSeekToFirst(std::unique_ptr<TBlockIter>& biter,
1075
+ size_t& verification_count) {
793
1076
  verification_count = 0;
794
1077
  biter->SeekToFirst();
795
1078
  ASSERT_GE(verification_count, 1);
@@ -797,8 +1080,8 @@ class BlockPerKVChecksumTest : public DBTestBase {
797
1080
  }
798
1081
 
799
1082
  template <typename TBlockIter>
800
- void TestSeekToLast(std::unique_ptr<TBlockIter> &biter,
801
- size_t &verification_count) {
1083
+ void TestSeekToLast(std::unique_ptr<TBlockIter>& biter,
1084
+ size_t& verification_count) {
802
1085
  verification_count = 0;
803
1086
  biter->SeekToLast();
804
1087
  ASSERT_GE(verification_count, 1);
@@ -806,8 +1089,8 @@ class BlockPerKVChecksumTest : public DBTestBase {
806
1089
  }
807
1090
 
808
1091
  template <typename TBlockIter>
809
- void TestSeekForPrev(std::unique_ptr<TBlockIter> &biter,
810
- size_t &verification_count, std::string k) {
1092
+ void TestSeekForPrev(std::unique_ptr<TBlockIter>& biter,
1093
+ size_t& verification_count, const std::string& k) {
811
1094
  verification_count = 0;
812
1095
  biter->SeekForPrev(k);
813
1096
  ASSERT_GE(verification_count, 1);
@@ -815,16 +1098,16 @@ class BlockPerKVChecksumTest : public DBTestBase {
815
1098
  }
816
1099
 
817
1100
  template <typename TBlockIter>
818
- void TestSeek(std::unique_ptr<TBlockIter> &biter, size_t &verification_count,
819
- std::string k) {
1101
+ void TestSeek(std::unique_ptr<TBlockIter>& biter, size_t& verification_count,
1102
+ const std::string& k) {
820
1103
  verification_count = 0;
821
1104
  biter->Seek(k);
822
1105
  ASSERT_GE(verification_count, 1);
823
1106
  TestIterateForward(biter, verification_count);
824
1107
  }
825
1108
 
826
- bool VerifyChecksum(uint32_t checksum_len, const char *checksum_ptr,
827
- const Slice &key, const Slice &val) {
1109
+ bool VerifyChecksum(uint32_t checksum_len, const char* checksum_ptr,
1110
+ const Slice& key, const Slice& val) {
828
1111
  if (!checksum_len) {
829
1112
  return checksum_ptr == nullptr;
830
1113
  }
@@ -834,13 +1117,12 @@ class BlockPerKVChecksumTest : public DBTestBase {
834
1117
  };
835
1118
 
836
1119
  namespace {
837
- const BlockBasedTableOptions *kTableOptions() {
1120
+ const BlockBasedTableOptions* kTableOptions() {
838
1121
  static BlockBasedTableOptions opts{};
839
1122
  return &opts;
840
1123
  }
841
- Decompressor *kDecompressor() {
842
- static auto mgr = GetBuiltinCompressionManager(
843
- GetCompressFormatForVersion(kTableOptions()->format_version));
1124
+ Decompressor* kDecompressor() {
1125
+ static auto mgr = GetBuiltinV2CompressionManager();
844
1126
  static auto decomp = mgr->GetDecompressor();
845
1127
  return decomp.get();
846
1128
  }
@@ -1057,7 +1339,7 @@ class DataBlockKVChecksumTest
1057
1339
  bool GetUseDeltaEncoding() const { return std::get<3>(GetParam()); }
1058
1340
 
1059
1341
  std::unique_ptr<Block_kData> GenerateDataBlock(
1060
- std::vector<std::string> &keys, std::vector<std::string> &values,
1342
+ std::vector<std::string>& keys, std::vector<std::string>& values,
1061
1343
  int num_record) {
1062
1344
  BlockCreateContext create_context{
1063
1345
  kTableOptions(), nullptr /* statistics */, nullptr /* ioptions */,
@@ -1090,9 +1372,9 @@ INSTANTIATE_TEST_CASE_P(
1090
1372
  ::testing::Values(0, 1, 2, 4, 8) /* protection_bytes_per_key */,
1091
1373
  ::testing::Values(1, 2, 3, 8, 16) /* restart_interval */,
1092
1374
  ::testing::Values(false, true)) /* delta_encoding */,
1093
- [](const testing::TestParamInfo<std::tuple<
1094
- BlockBasedTableOptions::DataBlockIndexType, uint8_t, uint32_t, bool>>
1095
- &args) {
1375
+ [](const testing::TestParamInfo<
1376
+ std::tuple<BlockBasedTableOptions::DataBlockIndexType, uint8_t,
1377
+ uint32_t, bool>>& args) {
1096
1378
  std::ostringstream oss;
1097
1379
  oss << GetDataBlockIndexTypeStr(std::get<0>(args.param))
1098
1380
  << "ProtectionPerKey" << std::to_string(std::get<1>(args.param))
@@ -1115,7 +1397,7 @@ TEST_P(DataBlockKVChecksumTest, ChecksumConstructionAndVerification) {
1115
1397
  std::unique_ptr<Block_kData> data_block =
1116
1398
  GenerateDataBlock(keys, values, kNumRecords);
1117
1399
 
1118
- const char *checksum_ptr = data_block->TEST_GetKVChecksum();
1400
+ const char* checksum_ptr = data_block->TEST_GetKVChecksum();
1119
1401
  // Check checksum of correct length is generated
1120
1402
  for (int i = 0; i < kNumRecords; i++) {
1121
1403
  ASSERT_TRUE(VerifyChecksum(protection_bytes_per_key,
@@ -1133,8 +1415,8 @@ TEST_P(DataBlockKVChecksumTest, ChecksumConstructionAndVerification) {
1133
1415
  // that case (see Block::VerifyChecksum()).
1134
1416
  SyncPoint::GetInstance()->SetCallBack(
1135
1417
  "Block::VerifyChecksum::checksum_len",
1136
- [&verification_count, protection_bytes_per_key](void *checksum_len) {
1137
- ASSERT_EQ((*static_cast<uint8_t *>(checksum_len)),
1418
+ [&verification_count, protection_bytes_per_key](void* checksum_len) {
1419
+ ASSERT_EQ((*static_cast<uint8_t*>(checksum_len)),
1138
1420
  protection_bytes_per_key);
1139
1421
  ++verification_count;
1140
1422
  });
@@ -1178,9 +1460,9 @@ class IndexBlockKVChecksumTest
1178
1460
  bool IncludeFirstKey() const { return std::get<4>(GetParam()); }
1179
1461
 
1180
1462
  std::unique_ptr<Block_kIndex> GenerateIndexBlock(
1181
- std::vector<std::string> &separators,
1182
- std::vector<BlockHandle> &block_handles,
1183
- std::vector<std::string> &first_keys, int num_record) {
1463
+ std::vector<std::string>& separators,
1464
+ std::vector<BlockHandle>& block_handles,
1465
+ std::vector<std::string>& first_keys, int num_record) {
1184
1466
  Options options = Options();
1185
1467
  uint8_t protection_bytes_per_key = GetChecksumLen();
1186
1468
  BlockCreateContext create_context{
@@ -1236,7 +1518,7 @@ INSTANTIATE_TEST_CASE_P(
1236
1518
  ::testing::Values(true, false), ::testing::Values(true, false)),
1237
1519
  [](const testing::TestParamInfo<
1238
1520
  std::tuple<BlockBasedTableOptions::DataBlockIndexType, uint8_t,
1239
- uint32_t, bool, bool>> &args) {
1521
+ uint32_t, bool, bool>>& args) {
1240
1522
  std::ostringstream oss;
1241
1523
  oss << GetDataBlockIndexTypeStr(std::get<0>(args.param)) << "ProtBytes"
1242
1524
  << std::to_string(std::get<1>(args.param)) << "RestartInterval"
@@ -1260,13 +1542,12 @@ TEST_P(IndexBlockKVChecksumTest, ChecksumConstructionAndVerification) {
1260
1542
  std::vector<BlockHandle> block_handles;
1261
1543
  std::vector<std::string> first_keys;
1262
1544
  GenerateRandomIndexEntries(&separators, &block_handles, &first_keys,
1263
- kNumRecords, 0 /* ts_sz */,
1264
- seqno != kDisableGlobalSequenceNumber);
1545
+ kNumRecords, 0 /* ts_sz */);
1265
1546
  SyncPoint::GetInstance()->DisableProcessing();
1266
1547
  std::unique_ptr<Block_kIndex> index_block = GenerateIndexBlock(
1267
1548
  separators, block_handles, first_keys, kNumRecords);
1268
- IndexBlockIter *kNullIter = nullptr;
1269
- Statistics *kNullStats = nullptr;
1549
+ IndexBlockIter* kNullIter = nullptr;
1550
+ Statistics* kNullStats = nullptr;
1270
1551
  // read contents of block sequentially
1271
1552
  std::unique_ptr<IndexBlockIter> biter{index_block->NewIndexIterator(
1272
1553
  options.comparator, seqno, kNullIter, kNullStats,
@@ -1277,7 +1558,7 @@ TEST_P(IndexBlockKVChecksumTest, ChecksumConstructionAndVerification) {
1277
1558
  true /* user_defined_timestamps_persisted */,
1278
1559
  nullptr /* prefix_index */)};
1279
1560
  biter->SeekToFirst();
1280
- const char *checksum_ptr = index_block->TEST_GetKVChecksum();
1561
+ const char* checksum_ptr = index_block->TEST_GetKVChecksum();
1281
1562
  // Check checksum of correct length is generated
1282
1563
  for (int i = 0; i < kNumRecords; i++) {
1283
1564
  // Obtaining the actual content written as value to index block is not
@@ -1297,8 +1578,8 @@ TEST_P(IndexBlockKVChecksumTest, ChecksumConstructionAndVerification) {
1297
1578
  // assert checking on checksum_len here.
1298
1579
  SyncPoint::GetInstance()->SetCallBack(
1299
1580
  "Block::VerifyChecksum::checksum_len",
1300
- [&verification_count, protection_bytes_per_key](void *checksum_len) {
1301
- ASSERT_EQ((*static_cast<uint8_t *>(checksum_len)),
1581
+ [&verification_count, protection_bytes_per_key](void* checksum_len) {
1582
+ ASSERT_EQ((*static_cast<uint8_t*>(checksum_len)),
1302
1583
  protection_bytes_per_key);
1303
1584
  ++verification_count;
1304
1585
  });
@@ -1321,7 +1602,7 @@ class MetaIndexBlockKVChecksumTest
1321
1602
  uint32_t GetRestartInterval() const { return 1; }
1322
1603
 
1323
1604
  std::unique_ptr<Block_kMetaIndex> GenerateMetaIndexBlock(
1324
- std::vector<std::string> &keys, std::vector<std::string> &values,
1605
+ std::vector<std::string>& keys, std::vector<std::string>& values,
1325
1606
  int num_record) {
1326
1607
  Options options = Options();
1327
1608
  uint8_t protection_bytes_per_key = GetChecksumLen();
@@ -1347,7 +1628,7 @@ class MetaIndexBlockKVChecksumTest
1347
1628
 
1348
1629
  INSTANTIATE_TEST_CASE_P(P, MetaIndexBlockKVChecksumTest,
1349
1630
  ::testing::Values(0, 1, 2, 4, 8),
1350
- [](const testing::TestParamInfo<uint8_t> &args) {
1631
+ [](const testing::TestParamInfo<uint8_t>& args) {
1351
1632
  std::ostringstream oss;
1352
1633
  oss << "ProtBytes" << std::to_string(args.param);
1353
1634
  return oss.str();
@@ -1369,7 +1650,7 @@ TEST_P(MetaIndexBlockKVChecksumTest, ChecksumConstructionAndVerification) {
1369
1650
  SyncPoint::GetInstance()->DisableProcessing();
1370
1651
  std::unique_ptr<Block_kMetaIndex> meta_block =
1371
1652
  GenerateMetaIndexBlock(keys, values, kNumRecords);
1372
- const char *checksum_ptr = meta_block->TEST_GetKVChecksum();
1653
+ const char* checksum_ptr = meta_block->TEST_GetKVChecksum();
1373
1654
  // Check checksum of correct length is generated
1374
1655
  for (int i = 0; i < kNumRecords; i++) {
1375
1656
  ASSERT_TRUE(VerifyChecksum(protection_bytes_per_key,
@@ -1384,8 +1665,8 @@ TEST_P(MetaIndexBlockKVChecksumTest, ChecksumConstructionAndVerification) {
1384
1665
  // checking on checksum_len here.
1385
1666
  SyncPoint::GetInstance()->SetCallBack(
1386
1667
  "Block::VerifyChecksum::checksum_len",
1387
- [&verification_count, protection_bytes_per_key](void *checksum_len) {
1388
- ASSERT_EQ((*static_cast<uint8_t *>(checksum_len)),
1668
+ [&verification_count, protection_bytes_per_key](void* checksum_len) {
1669
+ ASSERT_EQ((*static_cast<uint8_t*>(checksum_len)),
1389
1670
  protection_bytes_per_key);
1390
1671
  ++verification_count;
1391
1672
  });
@@ -1405,7 +1686,7 @@ class DataBlockKVChecksumCorruptionTest : public DataBlockKVChecksumTest {
1405
1686
  DataBlockKVChecksumCorruptionTest() = default;
1406
1687
 
1407
1688
  std::unique_ptr<DataBlockIter> GenerateDataBlockIter(
1408
- std::vector<std::string> &keys, std::vector<std::string> &values,
1689
+ std::vector<std::string>& keys, std::vector<std::string>& values,
1409
1690
  int num_record) {
1410
1691
  // During Block construction, we may create block iter to initialize per kv
1411
1692
  // checksum. Disable syncpoint that may be created for block iter methods.
@@ -1431,15 +1712,15 @@ TEST_P(DataBlockKVChecksumCorruptionTest, CorruptEntry) {
1431
1712
  GenerateRandomKVs(&keys, &values, 0, kNumRecords + 1, 1 /* step */,
1432
1713
  24 /* padding_size */);
1433
1714
  SyncPoint::GetInstance()->SetCallBack(
1434
- "BlockIter::UpdateKey::value", [](void *arg) {
1435
- char *value = static_cast<char *>(arg);
1715
+ "BlockIter::UpdateKey::value", [](void* arg) {
1716
+ char* value = static_cast<char*>(arg);
1436
1717
  // values generated by GenerateRandomKVs are of length 100
1437
1718
  ++value[10];
1438
1719
  });
1439
1720
 
1440
1721
  // Purely for reducing the number of lines of code.
1441
1722
  typedef std::unique_ptr<DataBlockIter> IterPtr;
1442
- typedef void(IterAPI)(IterPtr & iter, std::string &);
1723
+ typedef void(IterAPI)(IterPtr & iter, std::string&);
1443
1724
 
1444
1725
  std::string seek_key = keys[kNumRecords / 2];
1445
1726
  auto test_seek = [&](IterAPI iter_api) {
@@ -1450,14 +1731,14 @@ TEST_P(DataBlockKVChecksumCorruptionTest, CorruptEntry) {
1450
1731
  ASSERT_TRUE(biter->status().IsCorruption());
1451
1732
  };
1452
1733
 
1453
- test_seek([](IterPtr &iter, std::string &) { iter->SeekToFirst(); });
1454
- test_seek([](IterPtr &iter, std::string &) { iter->SeekToLast(); });
1455
- test_seek([](IterPtr &iter, std::string &k) { iter->Seek(k); });
1456
- test_seek([](IterPtr &iter, std::string &k) { iter->SeekForPrev(k); });
1457
- test_seek([](IterPtr &iter, std::string &k) { iter->SeekForGet(k); });
1734
+ test_seek([](IterPtr& iter, std::string&) { iter->SeekToFirst(); });
1735
+ test_seek([](IterPtr& iter, std::string&) { iter->SeekToLast(); });
1736
+ test_seek([](IterPtr& iter, std::string& k) { iter->Seek(k); });
1737
+ test_seek([](IterPtr& iter, std::string& k) { iter->SeekForPrev(k); });
1738
+ test_seek([](IterPtr& iter, std::string& k) { iter->SeekForGet(k); });
1458
1739
 
1459
1740
  typedef void (DataBlockIter::*IterStepAPI)();
1460
- auto test_step = [&](IterStepAPI iter_api, std::string &k) {
1741
+ auto test_step = [&](IterStepAPI iter_api, std::string& k) {
1461
1742
  IterPtr biter = GenerateDataBlockIter(keys, values, kNumRecords);
1462
1743
  SyncPoint::GetInstance()->DisableProcessing();
1463
1744
  biter->Seek(k);
@@ -1486,9 +1767,9 @@ INSTANTIATE_TEST_CASE_P(
1486
1767
  ::testing::Values(4, 8) /* block_protection_bytes_per_key */,
1487
1768
  ::testing::Values(1, 3, 8, 16) /* restart_interval */,
1488
1769
  ::testing::Values(false, true)),
1489
- [](const testing::TestParamInfo<std::tuple<
1490
- BlockBasedTableOptions::DataBlockIndexType, uint8_t, uint32_t, bool>>
1491
- &args) {
1770
+ [](const testing::TestParamInfo<
1771
+ std::tuple<BlockBasedTableOptions::DataBlockIndexType, uint8_t,
1772
+ uint32_t, bool>>& args) {
1492
1773
  std::ostringstream oss;
1493
1774
  oss << GetDataBlockIndexTypeStr(std::get<0>(args.param)) << "ProtBytes"
1494
1775
  << std::to_string(std::get<1>(args.param)) << "RestartInterval"
@@ -1502,9 +1783,9 @@ class IndexBlockKVChecksumCorruptionTest : public IndexBlockKVChecksumTest {
1502
1783
  IndexBlockKVChecksumCorruptionTest() = default;
1503
1784
 
1504
1785
  std::unique_ptr<IndexBlockIter> GenerateIndexBlockIter(
1505
- std::vector<std::string> &separators,
1506
- std::vector<BlockHandle> &block_handles,
1507
- std::vector<std::string> &first_keys, int num_record,
1786
+ std::vector<std::string>& separators,
1787
+ std::vector<BlockHandle>& block_handles,
1788
+ std::vector<std::string>& first_keys, int num_record,
1508
1789
  SequenceNumber seqno) {
1509
1790
  SyncPoint::GetInstance()->DisableProcessing();
1510
1791
  block_ =
@@ -1537,7 +1818,7 @@ INSTANTIATE_TEST_CASE_P(
1537
1818
  ::testing::Values(true, false), ::testing::Values(true, false)),
1538
1819
  [](const testing::TestParamInfo<
1539
1820
  std::tuple<BlockBasedTableOptions::DataBlockIndexType, uint8_t,
1540
- uint32_t, bool, bool>> &args) {
1821
+ uint32_t, bool, bool>>& args) {
1541
1822
  std::ostringstream oss;
1542
1823
  oss << GetDataBlockIndexTypeStr(std::get<0>(args.param)) << "ProtBytes"
1543
1824
  << std::to_string(std::get<1>(args.param)) << "RestartInterval"
@@ -1559,18 +1840,17 @@ TEST_P(IndexBlockKVChecksumCorruptionTest, CorruptEntry) {
1559
1840
  std::vector<BlockHandle> block_handles;
1560
1841
  std::vector<std::string> first_keys;
1561
1842
  GenerateRandomIndexEntries(&separators, &block_handles, &first_keys,
1562
- kNumRecords, 0 /* ts_sz */,
1563
- seqno != kDisableGlobalSequenceNumber);
1843
+ kNumRecords, 0 /* ts_sz */);
1564
1844
  SyncPoint::GetInstance()->SetCallBack(
1565
- "BlockIter::UpdateKey::value", [](void *arg) {
1566
- char *value = static_cast<char *>(arg);
1845
+ "BlockIter::UpdateKey::value", [](void* arg) {
1846
+ char* value = static_cast<char*>(arg);
1567
1847
  // value can be delta-encoded with different lengths, so we corrupt
1568
1848
  // first bytes here to be safe
1569
1849
  ++value[0];
1570
1850
  });
1571
1851
 
1572
1852
  typedef std::unique_ptr<IndexBlockIter> IterPtr;
1573
- typedef void(IterAPI)(IterPtr & iter, std::string &);
1853
+ typedef void(IterAPI)(IterPtr & iter, std::string&);
1574
1854
  std::string seek_key = first_keys[kNumRecords / 2];
1575
1855
  auto test_seek = [&](IterAPI iter_api) {
1576
1856
  std::unique_ptr<IndexBlockIter> biter = GenerateIndexBlockIter(
@@ -1580,12 +1860,12 @@ TEST_P(IndexBlockKVChecksumCorruptionTest, CorruptEntry) {
1580
1860
  ASSERT_FALSE(biter->Valid());
1581
1861
  ASSERT_TRUE(biter->status().IsCorruption());
1582
1862
  };
1583
- test_seek([](IterPtr &iter, std::string &) { iter->SeekToFirst(); });
1584
- test_seek([](IterPtr &iter, std::string &) { iter->SeekToLast(); });
1585
- test_seek([](IterPtr &iter, std::string &k) { iter->Seek(k); });
1863
+ test_seek([](IterPtr& iter, std::string&) { iter->SeekToFirst(); });
1864
+ test_seek([](IterPtr& iter, std::string&) { iter->SeekToLast(); });
1865
+ test_seek([](IterPtr& iter, std::string& k) { iter->Seek(k); });
1586
1866
 
1587
1867
  typedef void (IndexBlockIter::*IterStepAPI)();
1588
- auto test_step = [&](IterStepAPI iter_api, std::string &k) {
1868
+ auto test_step = [&](IterStepAPI iter_api, std::string& k) {
1589
1869
  std::unique_ptr<IndexBlockIter> biter = GenerateIndexBlockIter(
1590
1870
  separators, block_handles, first_keys, kNumRecords, seqno);
1591
1871
  SyncPoint::GetInstance()->DisableProcessing();
@@ -1611,7 +1891,7 @@ class MetaIndexBlockKVChecksumCorruptionTest
1611
1891
  MetaIndexBlockKVChecksumCorruptionTest() = default;
1612
1892
 
1613
1893
  std::unique_ptr<MetaBlockIter> GenerateMetaIndexBlockIter(
1614
- std::vector<std::string> &keys, std::vector<std::string> &values,
1894
+ std::vector<std::string>& keys, std::vector<std::string>& values,
1615
1895
  int num_record) {
1616
1896
  SyncPoint::GetInstance()->DisableProcessing();
1617
1897
  block_ = GenerateMetaIndexBlock(keys, values, num_record);
@@ -1628,7 +1908,7 @@ class MetaIndexBlockKVChecksumCorruptionTest
1628
1908
  INSTANTIATE_TEST_CASE_P(
1629
1909
  P, MetaIndexBlockKVChecksumCorruptionTest,
1630
1910
  ::testing::Values(4, 8) /* block_protection_bytes_per_key */,
1631
- [](const testing::TestParamInfo<uint8_t> &args) {
1911
+ [](const testing::TestParamInfo<uint8_t>& args) {
1632
1912
  std::ostringstream oss;
1633
1913
  oss << "ProtBytes" << std::to_string(args.param);
1634
1914
  return oss.str();
@@ -1645,14 +1925,14 @@ TEST_P(MetaIndexBlockKVChecksumCorruptionTest, CorruptEntry) {
1645
1925
  GenerateRandomKVs(&keys, &values, 0, kNumRecords + 1, 1 /* step */,
1646
1926
  24 /* padding_size */);
1647
1927
  SyncPoint::GetInstance()->SetCallBack(
1648
- "BlockIter::UpdateKey::value", [](void *arg) {
1649
- char *value = static_cast<char *>(arg);
1928
+ "BlockIter::UpdateKey::value", [](void* arg) {
1929
+ char* value = static_cast<char*>(arg);
1650
1930
  // values generated by GenerateRandomKVs are of length 100
1651
1931
  ++value[10];
1652
1932
  });
1653
1933
 
1654
1934
  typedef std::unique_ptr<MetaBlockIter> IterPtr;
1655
- typedef void(IterAPI)(IterPtr & iter, std::string &);
1935
+ typedef void(IterAPI)(IterPtr & iter, std::string&);
1656
1936
  typedef void (MetaBlockIter::*IterStepAPI)();
1657
1937
  std::string seek_key = keys[kNumRecords / 2];
1658
1938
  auto test_seek = [&](IterAPI iter_api) {
@@ -1663,12 +1943,12 @@ TEST_P(MetaIndexBlockKVChecksumCorruptionTest, CorruptEntry) {
1663
1943
  ASSERT_TRUE(biter->status().IsCorruption());
1664
1944
  };
1665
1945
 
1666
- test_seek([](IterPtr &iter, std::string &) { iter->SeekToFirst(); });
1667
- test_seek([](IterPtr &iter, std::string &) { iter->SeekToLast(); });
1668
- test_seek([](IterPtr &iter, std::string &k) { iter->Seek(k); });
1669
- test_seek([](IterPtr &iter, std::string &k) { iter->SeekForPrev(k); });
1946
+ test_seek([](IterPtr& iter, std::string&) { iter->SeekToFirst(); });
1947
+ test_seek([](IterPtr& iter, std::string&) { iter->SeekToLast(); });
1948
+ test_seek([](IterPtr& iter, std::string& k) { iter->Seek(k); });
1949
+ test_seek([](IterPtr& iter, std::string& k) { iter->SeekForPrev(k); });
1670
1950
 
1671
- auto test_step = [&](IterStepAPI iter_api, const std::string &k) {
1951
+ auto test_step = [&](IterStepAPI iter_api, const std::string& k) {
1672
1952
  IterPtr biter = GenerateMetaIndexBlockIter(keys, values, kNumRecords);
1673
1953
  SyncPoint::GetInstance()->DisableProcessing();
1674
1954
  biter->Seek(k);
@@ -1686,9 +1966,108 @@ TEST_P(MetaIndexBlockKVChecksumCorruptionTest, CorruptEntry) {
1686
1966
  }
1687
1967
  }
1688
1968
  }
1969
+
1970
+ class MetaBlockEntryCorruptionTest : public testing::TestWithParam<bool> {
1971
+ public:
1972
+ bool useSeparatedKVStorage() const { return GetParam(); }
1973
+
1974
+ std::string BuildBlock() {
1975
+ BlockBuilder builder(1 /* restart_interval */,
1976
+ true /* use_delta_encoding */,
1977
+ false /* use_value_delta_encoding */,
1978
+ BlockBasedTableOptions::kDataBlockBinarySearch,
1979
+ 0 /* data_block_hash_table_util_ratio */,
1980
+ 0 /* ts_sz */, false /* persist_udt */,
1981
+ true /* is_user_key */, useSeparatedKVStorage());
1982
+ builder.Add("key001", "val01");
1983
+ builder.Add("key002", "val02");
1984
+ builder.Add("key003", "val03");
1985
+ builder.Add("key004", "val04");
1986
+ Slice raw = builder.Finish();
1987
+ return std::string(raw.data(), raw.size());
1988
+ }
1989
+
1990
+ // Get the restart offset for a given restart index from the raw block data.
1991
+ uint32_t GetRestartOffset(const std::string& block_data, int restart_idx) {
1992
+ size_t footer_size = useSeparatedKVStorage() ? 8 : 4;
1993
+ uint32_t packed = DecodeFixed32(block_data.data() + block_data.size() - 4);
1994
+ uint32_t num_restarts = packed & DataBlockFooter::kMaxNumRestarts;
1995
+ size_t restarts_start =
1996
+ block_data.size() - footer_size - num_restarts * sizeof(uint32_t);
1997
+ return DecodeFixed32(block_data.data() + restarts_start +
1998
+ restart_idx * sizeof(uint32_t));
1999
+ }
2000
+
2001
+ uint32_t GetKeyEnd(const std::string& block_data) {
2002
+ size_t footer_size = useSeparatedKVStorage() ? 8 : 4;
2003
+ uint32_t packed = DecodeFixed32(block_data.data() + block_data.size() - 4);
2004
+ uint32_t num_restarts = packed & DataBlockFooter::kMaxNumRestarts;
2005
+ uint32_t restarts_start = static_cast<uint32_t>(
2006
+ block_data.size() - footer_size - num_restarts * sizeof(uint32_t));
2007
+ if (useSeparatedKVStorage()) {
2008
+ // values_section_offset is stored as the 4 bytes before the packed word.
2009
+ return DecodeFixed32(block_data.data() + block_data.size() - 8);
2010
+ }
2011
+ return restarts_start;
2012
+ }
2013
+
2014
+ uint32_t GetValueEnd(const std::string& block_data) {
2015
+ size_t footer_size = useSeparatedKVStorage() ? 8 : 4;
2016
+ uint32_t packed = DecodeFixed32(block_data.data() + block_data.size() - 4);
2017
+ uint32_t num_restarts = packed & DataBlockFooter::kMaxNumRestarts;
2018
+ return static_cast<uint32_t>(block_data.size() - footer_size -
2019
+ num_restarts * sizeof(uint32_t));
2020
+ }
2021
+ };
2022
+
2023
+ INSTANTIATE_TEST_CASE_P(P, MetaBlockEntryCorruptionTest, ::testing::Bool(),
2024
+ [](const testing::TestParamInfo<bool>& args) {
2025
+ return args.param ? "SeparatedKV" : "InlineKV";
2026
+ });
2027
+
2028
+ TEST_P(MetaBlockEntryCorruptionTest, CorruptedKeyLengthPastKeyEnd) {
2029
+ std::string block_data = BuildBlock();
2030
+ uint32_t key_end = GetKeyEnd(block_data);
2031
+
2032
+ // Corrupt the key length of the first entry so that
2033
+ // the key data would extend past the keys-end boundary.
2034
+ uint32_t first_entry_offset = GetRestartOffset(block_data, 0);
2035
+ block_data[first_entry_offset + 1] = static_cast<char>(key_end);
2036
+
2037
+ BlockContents contents;
2038
+ contents.data = Slice(block_data);
2039
+ Block block(std::move(contents), 0, nullptr, 1 /* restart_interval */);
2040
+ std::unique_ptr<MetaBlockIter> iter(block.NewMetaIterator());
2041
+
2042
+ // SeekToFirst should hit the corrupted first entry immediately.
2043
+ iter->SeekToFirst();
2044
+ ASSERT_FALSE(iter->Valid());
2045
+ ASSERT_TRUE(iter->status().IsCorruption());
2046
+ }
2047
+
2048
+ TEST_P(MetaBlockEntryCorruptionTest, CorruptedValueLengthPastValueEnd) {
2049
+ std::string block_data = BuildBlock();
2050
+ uint32_t value_end = GetValueEnd(block_data);
2051
+
2052
+ // Corrupt the first entry so that its value would extend past the
2053
+ // values-end boundary (start of the restart array).
2054
+ uint32_t first_entry_offset = GetRestartOffset(block_data, 0);
2055
+ block_data[first_entry_offset + 2] = static_cast<char>(value_end);
2056
+
2057
+ BlockContents contents;
2058
+ contents.data = Slice(block_data);
2059
+ Block block(std::move(contents), 0, nullptr, 1 /* restart_interval */);
2060
+ std::unique_ptr<MetaBlockIter> iter(block.NewMetaIterator());
2061
+
2062
+ // SeekToFirst should hit the corrupted first entry immediately.
2063
+ iter->SeekToFirst();
2064
+ ASSERT_FALSE(iter->Valid());
2065
+ ASSERT_TRUE(iter->status().IsCorruption());
2066
+ }
2067
+
1689
2068
  } // namespace ROCKSDB_NAMESPACE
1690
2069
 
1691
- int main(int argc, char **argv) {
2070
+ int main(int argc, char** argv) {
1692
2071
  ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
1693
2072
  ::testing::InitGoogleTest(&argc, argv);
1694
2073
  return RUN_ALL_TESTS();