@nxtedition/rocksdb 15.4.0 → 15.5.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 (402) hide show
  1. package/binding.cc +24 -19
  2. package/cache.js +1 -1
  3. package/chained-batch.js +12 -3
  4. package/deps/rocksdb/rocksdb/.clang-tidy +86 -0
  5. package/deps/rocksdb/rocksdb/BUCK +42 -0
  6. package/deps/rocksdb/rocksdb/CMakeLists.txt +11 -0
  7. package/deps/rocksdb/rocksdb/Makefile +59 -32
  8. package/deps/rocksdb/rocksdb/cache/cache.cc +0 -5
  9. package/deps/rocksdb/rocksdb/cache/cache_entry_stats.h +9 -9
  10. package/deps/rocksdb/rocksdb/cache/cache_key.cc +3 -3
  11. package/deps/rocksdb/rocksdb/cache/cache_key.h +5 -5
  12. package/deps/rocksdb/rocksdb/cache/cache_reservation_manager.h +16 -16
  13. package/deps/rocksdb/rocksdb/cache/cache_test.cc +1 -1
  14. package/deps/rocksdb/rocksdb/cache/clock_cache.cc +258 -294
  15. package/deps/rocksdb/rocksdb/cache/clock_cache.h +98 -49
  16. package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.cc +1 -5
  17. package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache_test.cc +2 -3
  18. package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +18 -18
  19. package/deps/rocksdb/rocksdb/crash_test.mk +5 -1
  20. package/deps/rocksdb/rocksdb/db/blob/blob_file_builder.cc +23 -22
  21. package/deps/rocksdb/rocksdb/db/blob/blob_file_builder.h +6 -1
  22. package/deps/rocksdb/rocksdb/db/blob/blob_file_builder_test.cc +14 -16
  23. package/deps/rocksdb/rocksdb/db/blob/blob_file_reader.cc +38 -26
  24. package/deps/rocksdb/rocksdb/db/blob/blob_file_reader.h +5 -1
  25. package/deps/rocksdb/rocksdb/db/blob/blob_file_reader_test.cc +101 -18
  26. package/deps/rocksdb/rocksdb/db/blob/blob_index.h +12 -0
  27. package/deps/rocksdb/rocksdb/db/blob/blob_source_test.cc +6 -9
  28. package/deps/rocksdb/rocksdb/db/builder.cc +23 -0
  29. package/deps/rocksdb/rocksdb/db/builder.h +7 -0
  30. package/deps/rocksdb/rocksdb/db/c.cc +373 -57
  31. package/deps/rocksdb/rocksdb/db/c_test.c +101 -1
  32. package/deps/rocksdb/rocksdb/db/column_family.cc +31 -3
  33. package/deps/rocksdb/rocksdb/db/column_family_test.cc +10 -13
  34. package/deps/rocksdb/rocksdb/db/compact_files_test.cc +35 -48
  35. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +13 -5
  36. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +201 -39
  37. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +15 -10
  38. package/deps/rocksdb/rocksdb/db/compaction/compaction_job_stats_test.cc +7 -7
  39. package/deps/rocksdb/rocksdb/db/compaction/compaction_job_test.cc +2 -455
  40. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +4 -2
  41. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.h +19 -0
  42. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.cc +72 -9
  43. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.h +12 -10
  44. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.cc +405 -83
  45. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.h +25 -1
  46. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_level.cc +23 -10
  47. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_level.h +1 -0
  48. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +1410 -106
  49. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +12 -5
  50. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.h +2 -1
  51. package/deps/rocksdb/rocksdb/db/compaction/compaction_service_job.cc +19 -10
  52. package/deps/rocksdb/rocksdb/db/compaction/compaction_service_test.cc +505 -45
  53. package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.cc +2 -2
  54. package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.h +9 -1
  55. package/deps/rocksdb/rocksdb/db/compaction/tiered_compaction_test.cc +4 -4
  56. package/deps/rocksdb/rocksdb/db/comparator_db_test.cc +7 -9
  57. package/deps/rocksdb/rocksdb/db/convenience.cc +4 -4
  58. package/deps/rocksdb/rocksdb/db/convenience_impl.h +2 -1
  59. package/deps/rocksdb/rocksdb/db/corruption_test.cc +60 -88
  60. package/deps/rocksdb/rocksdb/db/cuckoo_table_db_test.cc +10 -12
  61. package/deps/rocksdb/rocksdb/db/db_basic_test.cc +471 -40
  62. package/deps/rocksdb/rocksdb/db/db_block_cache_test.cc +116 -2
  63. package/deps/rocksdb/rocksdb/db/db_bloom_filter_test.cc +5 -15
  64. package/deps/rocksdb/rocksdb/db/db_compaction_abort_test.cc +993 -0
  65. package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +329 -29
  66. package/deps/rocksdb/rocksdb/db/db_flush_test.cc +155 -13
  67. package/deps/rocksdb/rocksdb/db/db_impl/compacted_db_impl.cc +54 -31
  68. package/deps/rocksdb/rocksdb/db/db_impl/compacted_db_impl.h +1 -0
  69. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +232 -70
  70. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +57 -9
  71. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +224 -31
  72. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_debug.cc +5 -0
  73. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_experimental.cc +4 -2
  74. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_files.cc +1 -1
  75. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_follower.cc +1 -0
  76. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +164 -8
  77. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_readonly.cc +6 -0
  78. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_readonly.h +5 -0
  79. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.cc +47 -35
  80. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.h +22 -9
  81. package/deps/rocksdb/rocksdb/db/db_iter.cc +9 -0
  82. package/deps/rocksdb/rocksdb/db/db_iterator_test.cc +371 -6
  83. package/deps/rocksdb/rocksdb/db/db_log_iter_test.cc +7 -5
  84. package/deps/rocksdb/rocksdb/db/db_logical_block_size_cache_test.cc +22 -23
  85. package/deps/rocksdb/rocksdb/db/db_memtable_test.cc +0 -2
  86. package/deps/rocksdb/rocksdb/db/db_merge_operator_test.cc +4 -4
  87. package/deps/rocksdb/rocksdb/db/db_options_test.cc +40 -0
  88. package/deps/rocksdb/rocksdb/db/db_properties_test.cc +32 -13
  89. package/deps/rocksdb/rocksdb/db/db_range_del_test.cc +1 -1
  90. package/deps/rocksdb/rocksdb/db/db_readonly_with_timestamp_test.cc +4 -4
  91. package/deps/rocksdb/rocksdb/db/db_secondary_test.cc +68 -15
  92. package/deps/rocksdb/rocksdb/db/db_sst_test.cc +1 -1
  93. package/deps/rocksdb/rocksdb/db/db_statistics_test.cc +2 -3
  94. package/deps/rocksdb/rocksdb/db/db_table_properties_test.cc +6 -21
  95. package/deps/rocksdb/rocksdb/db/db_test.cc +644 -128
  96. package/deps/rocksdb/rocksdb/db/db_test2.cc +198 -81
  97. package/deps/rocksdb/rocksdb/db/db_test_util.cc +35 -10
  98. package/deps/rocksdb/rocksdb/db/db_test_util.h +8 -2
  99. package/deps/rocksdb/rocksdb/db/db_wal_test.cc +36 -32
  100. package/deps/rocksdb/rocksdb/db/db_with_timestamp_basic_test.cc +11 -7
  101. package/deps/rocksdb/rocksdb/db/db_with_timestamp_compaction_test.cc +499 -0
  102. package/deps/rocksdb/rocksdb/db/db_write_buffer_manager_test.cc +284 -20
  103. package/deps/rocksdb/rocksdb/db/db_write_test.cc +3 -3
  104. package/deps/rocksdb/rocksdb/db/dbformat.h +0 -5
  105. package/deps/rocksdb/rocksdb/db/error_handler.cc +24 -0
  106. package/deps/rocksdb/rocksdb/db/error_handler_fs_test.cc +12 -14
  107. package/deps/rocksdb/rocksdb/db/experimental.cc +13 -10
  108. package/deps/rocksdb/rocksdb/db/external_sst_file_basic_test.cc +1 -1
  109. package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +22 -3
  110. package/deps/rocksdb/rocksdb/db/external_sst_file_test.cc +21 -15
  111. package/deps/rocksdb/rocksdb/db/fault_injection_test.cc +4 -6
  112. package/deps/rocksdb/rocksdb/db/flush_job.cc +11 -3
  113. package/deps/rocksdb/rocksdb/db/forward_iterator_bench.cc +5 -6
  114. package/deps/rocksdb/rocksdb/db/import_column_family_job.cc +4 -2
  115. package/deps/rocksdb/rocksdb/db/import_column_family_test.cc +17 -17
  116. package/deps/rocksdb/rocksdb/db/internal_stats.cc +13 -0
  117. package/deps/rocksdb/rocksdb/db/internal_stats.h +2 -0
  118. package/deps/rocksdb/rocksdb/db/listener_test.cc +154 -27
  119. package/deps/rocksdb/rocksdb/db/manual_compaction_test.cc +6 -6
  120. package/deps/rocksdb/rocksdb/db/memtable.cc +197 -51
  121. package/deps/rocksdb/rocksdb/db/memtable.h +6 -0
  122. package/deps/rocksdb/rocksdb/db/memtable_list_test.cc +3 -4
  123. package/deps/rocksdb/rocksdb/db/merge_test.cc +37 -35
  124. package/deps/rocksdb/rocksdb/db/obsolete_files_test.cc +2 -1
  125. package/deps/rocksdb/rocksdb/db/options_file_test.cc +4 -4
  126. package/deps/rocksdb/rocksdb/db/perf_context_test.cc +9 -11
  127. package/deps/rocksdb/rocksdb/db/periodic_task_scheduler.cc +10 -1
  128. package/deps/rocksdb/rocksdb/db/periodic_task_scheduler_test.cc +292 -15
  129. package/deps/rocksdb/rocksdb/db/plain_table_db_test.cc +10 -17
  130. package/deps/rocksdb/rocksdb/db/prefix_test.cc +6 -8
  131. package/deps/rocksdb/rocksdb/db/repair.cc +10 -10
  132. package/deps/rocksdb/rocksdb/db/seqno_time_test.cc +5 -5
  133. package/deps/rocksdb/rocksdb/db/table_cache.cc +142 -135
  134. package/deps/rocksdb/rocksdb/db/table_cache.h +30 -6
  135. package/deps/rocksdb/rocksdb/db/table_cache_sync_and_async.h +7 -7
  136. package/deps/rocksdb/rocksdb/db/version_builder.cc +11 -50
  137. package/deps/rocksdb/rocksdb/db/version_builder.h +2 -1
  138. package/deps/rocksdb/rocksdb/db/version_builder_test.cc +2 -1
  139. package/deps/rocksdb/rocksdb/db/version_edit.cc +51 -2
  140. package/deps/rocksdb/rocksdb/db/version_edit.h +91 -29
  141. package/deps/rocksdb/rocksdb/db/version_edit_handler.h +7 -7
  142. package/deps/rocksdb/rocksdb/db/version_set.cc +211 -50
  143. package/deps/rocksdb/rocksdb/db/version_set.h +40 -3
  144. package/deps/rocksdb/rocksdb/db/version_set_sync_and_async.h +5 -0
  145. package/deps/rocksdb/rocksdb/db/version_set_test.cc +294 -21
  146. package/deps/rocksdb/rocksdb/db/version_util.cc +96 -0
  147. package/deps/rocksdb/rocksdb/db/version_util.h +24 -0
  148. package/deps/rocksdb/rocksdb/db/wide/db_wide_basic_test.cc +5 -5
  149. package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization.cc +647 -31
  150. package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization.h +219 -1
  151. package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization_test.cc +549 -12
  152. package/deps/rocksdb/rocksdb/db/write_callback_test.cc +3 -3
  153. package/deps/rocksdb/rocksdb/db_stress_tool/cf_consistency_stress.cc +1 -1
  154. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.cc +19 -0
  155. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +21 -4
  156. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_env_wrapper.h +32 -0
  157. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +74 -22
  158. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_listener.h +9 -0
  159. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +143 -61
  160. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.h +15 -2
  161. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_tool.cc +76 -2
  162. package/deps/rocksdb/rocksdb/db_stress_tool/no_batched_ops_stress.cc +92 -72
  163. package/deps/rocksdb/rocksdb/env/env.cc +1 -0
  164. package/deps/rocksdb/rocksdb/env/env_test.cc +365 -2
  165. package/deps/rocksdb/rocksdb/env/fs_posix.cc +31 -30
  166. package/deps/rocksdb/rocksdb/env/io_posix.cc +8 -11
  167. package/deps/rocksdb/rocksdb/env/io_posix.h +30 -1
  168. package/deps/rocksdb/rocksdb/env/io_posix_test.cc +43 -0
  169. package/deps/rocksdb/rocksdb/file/delete_scheduler.cc +1 -1
  170. package/deps/rocksdb/rocksdb/file/delete_scheduler_test.cc +108 -0
  171. package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.cc +32 -4
  172. package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.h +4 -4
  173. package/deps/rocksdb/rocksdb/file/file_util.cc +8 -2
  174. package/deps/rocksdb/rocksdb/file/file_util.h +2 -1
  175. package/deps/rocksdb/rocksdb/file/prefetch_test.cc +331 -12
  176. package/deps/rocksdb/rocksdb/file/random_access_file_reader.cc +52 -35
  177. package/deps/rocksdb/rocksdb/folly.mk +22 -5
  178. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_cache.h +1 -1
  179. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_compression.h +100 -54
  180. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +67 -2
  181. package/deps/rocksdb/rocksdb/include/rocksdb/c.h +149 -13
  182. package/deps/rocksdb/rocksdb/include/rocksdb/cache.h +1 -12
  183. package/deps/rocksdb/rocksdb/include/rocksdb/db.h +78 -97
  184. package/deps/rocksdb/rocksdb/include/rocksdb/experimental.h +3 -3
  185. package/deps/rocksdb/rocksdb/include/rocksdb/external_table.h +2 -2
  186. package/deps/rocksdb/rocksdb/include/rocksdb/file_checksum.h +5 -0
  187. package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +17 -2
  188. package/deps/rocksdb/rocksdb/include/rocksdb/functor_wrapper.h +1 -1
  189. package/deps/rocksdb/rocksdb/include/rocksdb/io_dispatcher.h +358 -0
  190. package/deps/rocksdb/rocksdb/include/rocksdb/iostats_context.h +13 -0
  191. package/deps/rocksdb/rocksdb/include/rocksdb/listener.h +43 -0
  192. package/deps/rocksdb/rocksdb/include/rocksdb/memtablerep.h +20 -0
  193. package/deps/rocksdb/rocksdb/include/rocksdb/options.h +63 -21
  194. package/deps/rocksdb/rocksdb/include/rocksdb/perf_context.h +10 -1
  195. package/deps/rocksdb/rocksdb/include/rocksdb/rate_limiter.h +1 -1
  196. package/deps/rocksdb/rocksdb/include/rocksdb/slice_transform.h +2 -7
  197. package/deps/rocksdb/rocksdb/include/rocksdb/sst_file_reader.h +13 -0
  198. package/deps/rocksdb/rocksdb/include/rocksdb/sst_file_writer.h +3 -14
  199. package/deps/rocksdb/rocksdb/include/rocksdb/statistics.h +49 -9
  200. package/deps/rocksdb/rocksdb/include/rocksdb/status.h +8 -0
  201. package/deps/rocksdb/rocksdb/include/rocksdb/table.h +77 -6
  202. package/deps/rocksdb/rocksdb/include/rocksdb/table_properties.h +15 -0
  203. package/deps/rocksdb/rocksdb/include/rocksdb/tool_hooks.h +16 -10
  204. package/deps/rocksdb/rocksdb/include/rocksdb/unique_id.h +5 -5
  205. package/deps/rocksdb/rocksdb/include/rocksdb/universal_compaction.h +2 -4
  206. package/deps/rocksdb/rocksdb/include/rocksdb/user_defined_index.h +106 -46
  207. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/db_ttl.h +1 -1
  208. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/ldb_cmd.h +14 -1
  209. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/memory_util.h +5 -1
  210. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/optimistic_transaction_db.h +2 -1
  211. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +7 -9
  212. package/deps/rocksdb/rocksdb/include/rocksdb/version.h +2 -2
  213. package/deps/rocksdb/rocksdb/logging/auto_roll_logger_test.cc +1 -2
  214. package/deps/rocksdb/rocksdb/memory/memory_allocator_test.cc +2 -2
  215. package/deps/rocksdb/rocksdb/memtable/inlineskiplist.h +226 -8
  216. package/deps/rocksdb/rocksdb/memtable/inlineskiplist_test.cc +490 -0
  217. package/deps/rocksdb/rocksdb/memtable/skiplist.h +3 -3
  218. package/deps/rocksdb/rocksdb/memtable/skiplistrep.cc +11 -0
  219. package/deps/rocksdb/rocksdb/microbench/db_basic_bench.cc +4 -12
  220. package/deps/rocksdb/rocksdb/microbench/ribbon_bench.cc +5 -5
  221. package/deps/rocksdb/rocksdb/monitoring/file_read_sample.h +21 -4
  222. package/deps/rocksdb/rocksdb/monitoring/perf_context.cc +9 -3
  223. package/deps/rocksdb/rocksdb/monitoring/statistics.cc +21 -2
  224. package/deps/rocksdb/rocksdb/monitoring/stats_history_test.cc +2 -2
  225. package/deps/rocksdb/rocksdb/options/cf_options.cc +21 -1
  226. package/deps/rocksdb/rocksdb/options/cf_options.h +2 -0
  227. package/deps/rocksdb/rocksdb/options/customizable_test.cc +0 -2
  228. package/deps/rocksdb/rocksdb/options/db_options.cc +26 -5
  229. package/deps/rocksdb/rocksdb/options/db_options.h +3 -1
  230. package/deps/rocksdb/rocksdb/options/options.cc +5 -1
  231. package/deps/rocksdb/rocksdb/options/options_helper.cc +7 -2
  232. package/deps/rocksdb/rocksdb/options/options_settable_test.cc +109 -103
  233. package/deps/rocksdb/rocksdb/options/options_test.cc +14 -0
  234. package/deps/rocksdb/rocksdb/port/jemalloc_helper.h +15 -17
  235. package/deps/rocksdb/rocksdb/port/lang.h +4 -0
  236. package/deps/rocksdb/rocksdb/port/port_example.h +0 -23
  237. package/deps/rocksdb/rocksdb/port/stack_trace.cc +36 -0
  238. package/deps/rocksdb/rocksdb/port/stack_trace.h +9 -0
  239. package/deps/rocksdb/rocksdb/src.mk +12 -0
  240. package/deps/rocksdb/rocksdb/table/adaptive/adaptive_table_factory.cc +1 -2
  241. package/deps/rocksdb/rocksdb/table/block_based/binary_search_index_reader.cc +2 -1
  242. package/deps/rocksdb/rocksdb/table/block_based/block.cc +571 -292
  243. package/deps/rocksdb/rocksdb/table/block_based/block.h +143 -53
  244. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +154 -90
  245. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.h +5 -1
  246. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.cc +51 -14
  247. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.h +0 -2
  248. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.cc +147 -734
  249. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.h +30 -233
  250. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +178 -108
  251. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +13 -0
  252. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_impl.h +17 -4
  253. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_sync_and_async.h +5 -2
  254. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_test.cc +70 -0
  255. package/deps/rocksdb/rocksdb/table/block_based/block_builder.cc +168 -24
  256. package/deps/rocksdb/rocksdb/table/block_based/block_builder.h +25 -9
  257. package/deps/rocksdb/rocksdb/table/block_based/block_cache.cc +7 -4
  258. package/deps/rocksdb/rocksdb/table/block_based/block_cache.h +9 -2
  259. package/deps/rocksdb/rocksdb/table/block_based/block_test.cc +548 -169
  260. package/deps/rocksdb/rocksdb/table/block_based/block_type.h +30 -0
  261. package/deps/rocksdb/rocksdb/table/block_based/block_util.h +156 -0
  262. package/deps/rocksdb/rocksdb/table/block_based/data_block_footer.cc +73 -30
  263. package/deps/rocksdb/rocksdb/table/block_based/data_block_footer.h +74 -7
  264. package/deps/rocksdb/rocksdb/table/block_based/data_block_hash_index.h +1 -1
  265. package/deps/rocksdb/rocksdb/table/block_based/index_builder.cc +20 -14
  266. package/deps/rocksdb/rocksdb/table/block_based/index_builder.h +22 -12
  267. package/deps/rocksdb/rocksdb/table/block_based/mock_block_based_table.h +1 -1
  268. package/deps/rocksdb/rocksdb/table/block_based/multi_scan_index_iterator.cc +332 -0
  269. package/deps/rocksdb/rocksdb/table/block_based/multi_scan_index_iterator.h +133 -0
  270. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +4 -2
  271. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block_test.cc +1 -1
  272. package/deps/rocksdb/rocksdb/table/block_based/reader_common.cc +3 -2
  273. package/deps/rocksdb/rocksdb/table/block_based/reader_common.h +4 -1
  274. package/deps/rocksdb/rocksdb/table/block_based/uncompression_dict_reader.h +0 -1
  275. package/deps/rocksdb/rocksdb/table/block_based/user_defined_index_wrapper.h +126 -46
  276. package/deps/rocksdb/rocksdb/table/block_fetcher.cc +31 -3
  277. package/deps/rocksdb/rocksdb/table/block_fetcher_test.cc +1 -2
  278. package/deps/rocksdb/rocksdb/table/cleanable_test.cc +3 -1
  279. package/deps/rocksdb/rocksdb/table/external_table.cc +25 -4
  280. package/deps/rocksdb/rocksdb/table/format.cc +27 -15
  281. package/deps/rocksdb/rocksdb/table/format.h +41 -15
  282. package/deps/rocksdb/rocksdb/table/merging_iterator.cc +1 -0
  283. package/deps/rocksdb/rocksdb/table/meta_blocks.cc +22 -12
  284. package/deps/rocksdb/rocksdb/table/meta_blocks.h +0 -1
  285. package/deps/rocksdb/rocksdb/table/sst_file_dumper.cc +7 -21
  286. package/deps/rocksdb/rocksdb/table/sst_file_dumper.h +0 -1
  287. package/deps/rocksdb/rocksdb/table/sst_file_reader.cc +88 -13
  288. package/deps/rocksdb/rocksdb/table/sst_file_reader_test.cc +53 -42
  289. package/deps/rocksdb/rocksdb/table/sst_file_writer.cc +3 -12
  290. package/deps/rocksdb/rocksdb/table/table_builder.h +0 -4
  291. package/deps/rocksdb/rocksdb/table/table_properties.cc +18 -0
  292. package/deps/rocksdb/rocksdb/table/table_reader_bench.cc +2 -3
  293. package/deps/rocksdb/rocksdb/table/table_test.cc +848 -172
  294. package/deps/rocksdb/rocksdb/table/unique_id.cc +24 -20
  295. package/deps/rocksdb/rocksdb/table/unique_id_impl.h +8 -8
  296. package/deps/rocksdb/rocksdb/test_util/sync_point.h +5 -4
  297. package/deps/rocksdb/rocksdb/test_util/testutil.cc +2 -1
  298. package/deps/rocksdb/rocksdb/test_util/testutil.h +2 -2
  299. package/deps/rocksdb/rocksdb/tools/block_cache_analyzer/block_cache_trace_analyzer_test.cc +2 -1
  300. package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +238 -120
  301. package/deps/rocksdb/rocksdb/tools/db_repl_stress.cc +2 -2
  302. package/deps/rocksdb/rocksdb/tools/db_sanity_test.cc +2 -4
  303. package/deps/rocksdb/rocksdb/tools/dump/db_dump_tool.cc +4 -8
  304. package/deps/rocksdb/rocksdb/tools/dump/rocksdb_undump.cc +1 -1
  305. package/deps/rocksdb/rocksdb/tools/io_tracer_parser_test.cc +2 -3
  306. package/deps/rocksdb/rocksdb/tools/ldb_cmd.cc +82 -20
  307. package/deps/rocksdb/rocksdb/tools/ldb_cmd_test.cc +41 -47
  308. package/deps/rocksdb/rocksdb/tools/ldb_tool.cc +9 -0
  309. package/deps/rocksdb/rocksdb/tools/reduce_levels_test.cc +5 -6
  310. package/deps/rocksdb/rocksdb/tools/sst_dump_tool.cc +1 -1
  311. package/deps/rocksdb/rocksdb/tools/tool_hooks.cc +6 -5
  312. package/deps/rocksdb/rocksdb/tools/trace_analyzer_test.cc +4 -4
  313. package/deps/rocksdb/rocksdb/tools/write_stress.cc +1 -3
  314. package/deps/rocksdb/rocksdb/util/atomic.h +30 -23
  315. package/deps/rocksdb/rocksdb/util/auto_tune_compressor.cc +6 -7
  316. package/deps/rocksdb/rocksdb/util/auto_tune_compressor.h +3 -3
  317. package/deps/rocksdb/rocksdb/util/bit_fields.h +68 -46
  318. package/deps/rocksdb/rocksdb/util/bloom_impl.h +16 -16
  319. package/deps/rocksdb/rocksdb/util/coding.h +14 -27
  320. package/deps/rocksdb/rocksdb/util/compression.cc +365 -207
  321. package/deps/rocksdb/rocksdb/util/compression.h +16 -1298
  322. package/deps/rocksdb/rocksdb/util/compression_test.cc +347 -61
  323. package/deps/rocksdb/rocksdb/util/crc32c_arm64.cc +8 -9
  324. package/deps/rocksdb/rocksdb/util/crc32c_arm64.h +1 -1
  325. package/deps/rocksdb/rocksdb/util/crc32c_ppc.h +1 -1
  326. package/deps/rocksdb/rocksdb/util/dynamic_bloom_test.cc +3 -3
  327. package/deps/rocksdb/rocksdb/util/filter_bench.cc +18 -18
  328. package/deps/rocksdb/rocksdb/util/gflags_compat.h +3 -3
  329. package/deps/rocksdb/rocksdb/util/hash_test.cc +19 -7
  330. package/deps/rocksdb/rocksdb/util/io_dispatcher_imp.cc +1099 -0
  331. package/deps/rocksdb/rocksdb/util/io_dispatcher_imp.h +36 -0
  332. package/deps/rocksdb/rocksdb/util/io_dispatcher_test.cc +1919 -0
  333. package/deps/rocksdb/rocksdb/util/math.h +3 -1
  334. package/deps/rocksdb/rocksdb/util/mutexlock.h +19 -19
  335. package/deps/rocksdb/rocksdb/util/ribbon_alg.h +25 -25
  336. package/deps/rocksdb/rocksdb/util/simple_mixed_compressor.cc +5 -7
  337. package/deps/rocksdb/rocksdb/util/simple_mixed_compressor.h +4 -5
  338. package/deps/rocksdb/rocksdb/util/slice.cc +0 -10
  339. package/deps/rocksdb/rocksdb/util/slice_test.cc +35 -1
  340. package/deps/rocksdb/rocksdb/util/slice_transform_test.cc +5 -7
  341. package/deps/rocksdb/rocksdb/util/status.cc +3 -1
  342. package/deps/rocksdb/rocksdb/util/stop_watch.h +2 -0
  343. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine.cc +4 -1
  344. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +123 -78
  345. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_compaction_filter.cc +12 -93
  346. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_compaction_filter.h +1 -4
  347. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db.cc +0 -21
  348. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db.h +6 -48
  349. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_impl.cc +94 -307
  350. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_impl.h +12 -58
  351. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_impl_filesnapshot.cc +2 -8
  352. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_listener.h +2 -3
  353. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_test.cc +205 -811
  354. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_dump_tool.cc +18 -9
  355. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_file.cc +2 -7
  356. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_file.h +1 -9
  357. package/deps/rocksdb/rocksdb/utilities/cassandra/cassandra_functional_test.cc +17 -11
  358. package/deps/rocksdb/rocksdb/utilities/cassandra/test_utils.cc +1 -1
  359. package/deps/rocksdb/rocksdb/utilities/cassandra/test_utils.h +1 -1
  360. package/deps/rocksdb/rocksdb/utilities/checkpoint/checkpoint_impl.cc +1 -1
  361. package/deps/rocksdb/rocksdb/utilities/checkpoint/checkpoint_test.cc +68 -61
  362. package/deps/rocksdb/rocksdb/utilities/debug.cc +2 -1
  363. package/deps/rocksdb/rocksdb/utilities/fault_injection_fs.cc +105 -59
  364. package/deps/rocksdb/rocksdb/utilities/fault_injection_fs.h +274 -7
  365. package/deps/rocksdb/rocksdb/utilities/fault_injection_fs_test.cc +94 -0
  366. package/deps/rocksdb/rocksdb/utilities/memory/memory_test.cc +13 -17
  367. package/deps/rocksdb/rocksdb/utilities/memory/memory_util.cc +16 -3
  368. package/deps/rocksdb/rocksdb/utilities/merge_operators/string_append/stringappend_test.cc +25 -25
  369. package/deps/rocksdb/rocksdb/utilities/object_registry.cc +40 -40
  370. package/deps/rocksdb/rocksdb/utilities/option_change_migration/option_change_migration.cc +2 -5
  371. package/deps/rocksdb/rocksdb/utilities/options/options_util_test.cc +17 -19
  372. package/deps/rocksdb/rocksdb/utilities/persistent_cache/block_cache_tier_file.cc +2 -2
  373. package/deps/rocksdb/rocksdb/utilities/persistent_cache/block_cache_tier_file.h +2 -2
  374. package/deps/rocksdb/rocksdb/utilities/persistent_cache/volatile_tier_impl.cc +1 -1
  375. package/deps/rocksdb/rocksdb/utilities/transactions/optimistic_transaction_db_impl.cc +2 -2
  376. package/deps/rocksdb/rocksdb/utilities/transactions/optimistic_transaction_db_impl.h +4 -13
  377. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.cc +3 -3
  378. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.h +6 -0
  379. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_transaction_seqno_test.cc +431 -0
  380. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_transaction_test.cc +1 -2
  381. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_txn.h +91 -0
  382. package/deps/rocksdb/rocksdb/utilities/trie_index/bitvector.cc +562 -0
  383. package/deps/rocksdb/rocksdb/utilities/trie_index/bitvector.h +615 -0
  384. package/deps/rocksdb/rocksdb/utilities/trie_index/louds_trie.cc +2575 -0
  385. package/deps/rocksdb/rocksdb/utilities/trie_index/louds_trie.h +685 -0
  386. package/deps/rocksdb/rocksdb/utilities/trie_index/trie_index_db_test.cc +2843 -0
  387. package/deps/rocksdb/rocksdb/utilities/trie_index/trie_index_factory.cc +567 -0
  388. package/deps/rocksdb/rocksdb/utilities/trie_index/trie_index_factory.h +275 -0
  389. package/deps/rocksdb/rocksdb/utilities/trie_index/trie_index_test.cc +5183 -0
  390. package/deps/rocksdb/rocksdb/utilities/ttl/db_ttl_impl.cc +4 -3
  391. package/deps/rocksdb/rocksdb/utilities/ttl/db_ttl_impl.h +1 -1
  392. package/deps/rocksdb/rocksdb/utilities/ttl/ttl_test.cc +2 -2
  393. package/deps/rocksdb/rocksdb/utilities/write_batch_with_index/write_batch_with_index_internal.h +3 -3
  394. package/deps/rocksdb/rocksdb/utilities/write_batch_with_index/write_batch_with_index_test.cc +93 -88
  395. package/deps/rocksdb/rocksdb.gyp +7 -0
  396. package/index.js +11 -2
  397. package/iterator.js +15 -7
  398. package/package.json +1 -1
  399. package/prebuilds/darwin-arm64/@nxtedition+rocksdb.node +0 -0
  400. package/prebuilds/linux-x64/@nxtedition+rocksdb.node +0 -0
  401. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/lua/rocks_lua_custom_library.h +0 -43
  402. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/lua/rocks_lua_util.h +0 -55
@@ -309,6 +309,308 @@ TEST_F(InlineSkipTest, InsertWithHint_CompatibleWithInsertWithoutHint) {
309
309
  Validate(&list);
310
310
  }
311
311
 
312
+ TEST_F(InlineSkipTest, MultiGetBasic) {
313
+ const int N = 1000;
314
+ Arena arena;
315
+ TestComparator cmp;
316
+ InlineSkipList<TestComparator> list(cmp, &arena);
317
+
318
+ // Insert keys 0, 2, 4, ..., 2*(N-1)
319
+ for (int i = 0; i < N; i++) {
320
+ Key key = i * 2;
321
+ char* buf = list.AllocateKey(sizeof(Key));
322
+ memcpy(buf, &key, sizeof(Key));
323
+ list.Insert(buf);
324
+ }
325
+
326
+ // Callback that records the first key found for each query
327
+ struct CallbackArg {
328
+ bool found;
329
+ Key found_key;
330
+ };
331
+ auto callback = [](void* arg, const char* entry) -> bool {
332
+ auto* cb = static_cast<CallbackArg*>(arg);
333
+ if (!cb->found) {
334
+ cb->found = true;
335
+ cb->found_key = Decode(entry);
336
+ }
337
+ return false; // stop after first match
338
+ };
339
+
340
+ // MultiGet for a batch of sorted keys
341
+ const size_t num_queries = 10;
342
+ Key query_keys[num_queries];
343
+ const char* key_ptrs[num_queries];
344
+ void* cb_args[num_queries];
345
+ CallbackArg cb_data[num_queries];
346
+
347
+ for (size_t i = 0; i < num_queries; i++) {
348
+ // Query keys: 1, 101, 201, ..., 901 (odd, so exact matches won't exist)
349
+ query_keys[i] = 1 + i * 100;
350
+ key_ptrs[i] = Encode(&query_keys[i]);
351
+ cb_data[i].found = false;
352
+ cb_data[i].found_key = 0;
353
+ cb_args[i] = &cb_data[i];
354
+ }
355
+
356
+ ASSERT_OK(list.MultiGet(num_queries, key_ptrs, cb_args, callback));
357
+
358
+ // Verify: each query should find the next even number >= query key
359
+ for (size_t i = 0; i < num_queries; i++) {
360
+ Key expected = (query_keys[i] + 1) & ~1ULL; // round up to next even
361
+ if (expected < static_cast<Key>(N * 2)) {
362
+ ASSERT_TRUE(cb_data[i].found)
363
+ << "Query key " << query_keys[i] << " should have found a match";
364
+ ASSERT_EQ(cb_data[i].found_key, expected)
365
+ << "Query key " << query_keys[i];
366
+ }
367
+ }
368
+ }
369
+
370
+ TEST_F(InlineSkipTest, MultiGetExactMatches) {
371
+ const int N = 500;
372
+ Arena arena;
373
+ TestComparator cmp;
374
+ InlineSkipList<TestComparator> list(cmp, &arena);
375
+
376
+ for (int i = 0; i < N; i++) {
377
+ Key key = i * 10;
378
+ char* buf = list.AllocateKey(sizeof(Key));
379
+ memcpy(buf, &key, sizeof(Key));
380
+ list.Insert(buf);
381
+ }
382
+
383
+ // Query for exact matches: 0, 100, 200, ..., 900
384
+ const size_t num_queries = 10;
385
+ Key query_keys[num_queries];
386
+ const char* key_ptrs[num_queries];
387
+
388
+ struct CallbackArg {
389
+ bool found;
390
+ Key found_key;
391
+ };
392
+ void* cb_args[num_queries];
393
+ CallbackArg cb_data[num_queries];
394
+
395
+ auto callback = [](void* arg, const char* entry) -> bool {
396
+ auto* cb = static_cast<CallbackArg*>(arg);
397
+ if (!cb->found) {
398
+ cb->found = true;
399
+ cb->found_key = Decode(entry);
400
+ }
401
+ return false;
402
+ };
403
+
404
+ for (size_t i = 0; i < num_queries; i++) {
405
+ query_keys[i] = i * 100;
406
+ key_ptrs[i] = Encode(&query_keys[i]);
407
+ cb_data[i].found = false;
408
+ cb_data[i].found_key = 0;
409
+ cb_args[i] = &cb_data[i];
410
+ }
411
+
412
+ ASSERT_OK(list.MultiGet(num_queries, key_ptrs, cb_args, callback));
413
+
414
+ for (size_t i = 0; i < num_queries; i++) {
415
+ ASSERT_TRUE(cb_data[i].found) << "Key " << query_keys[i];
416
+ ASSERT_EQ(cb_data[i].found_key, query_keys[i]) << "Key " << query_keys[i];
417
+ }
418
+ }
419
+
420
+ TEST_F(InlineSkipTest, MultiGetEmpty) {
421
+ Arena arena;
422
+ TestComparator cmp;
423
+ InlineSkipList<TestComparator> list(cmp, &arena);
424
+
425
+ auto callback = [](void* /*arg*/, const char* /*entry*/) -> bool {
426
+ return false;
427
+ };
428
+
429
+ // MultiGet on empty list should not crash
430
+ Key query_key = 42;
431
+ const char* key_ptr = Encode(&query_key);
432
+ void* cb_arg = nullptr;
433
+ ASSERT_OK(list.MultiGet(1, &key_ptr, &cb_arg, callback));
434
+
435
+ // Zero keys
436
+ ASSERT_OK(list.MultiGet(0, nullptr, nullptr, callback));
437
+ }
438
+
439
+ TEST_F(InlineSkipTest, MultiGetSingleKey) {
440
+ Arena arena;
441
+ TestComparator cmp;
442
+ InlineSkipList<TestComparator> list(cmp, &arena);
443
+
444
+ Key key = 100;
445
+ char* buf = list.AllocateKey(sizeof(Key));
446
+ memcpy(buf, &key, sizeof(Key));
447
+ list.Insert(buf);
448
+
449
+ struct CallbackArg {
450
+ bool found;
451
+ Key found_key;
452
+ };
453
+ auto callback = [](void* arg, const char* entry) -> bool {
454
+ auto* cb = static_cast<CallbackArg*>(arg);
455
+ cb->found = true;
456
+ cb->found_key = Decode(entry);
457
+ return false;
458
+ };
459
+
460
+ // Query for the exact key
461
+ Key query = 100;
462
+ const char* key_ptr = Encode(&query);
463
+ CallbackArg cb_data{false, 0};
464
+ void* cb_arg = &cb_data;
465
+ ASSERT_OK(list.MultiGet(1, &key_ptr, &cb_arg, callback));
466
+
467
+ ASSERT_TRUE(cb_data.found);
468
+ ASSERT_EQ(cb_data.found_key, 100);
469
+ }
470
+
471
+ TEST_F(InlineSkipTest, MultiGetRandomized) {
472
+ uint32_t seed =
473
+ static_cast<uint32_t>(Env::Default()->NowMicros() & 0xFFFFFFFF);
474
+ SCOPED_TRACE("seed=" + std::to_string(seed));
475
+ Random rnd(seed);
476
+
477
+ const int N = 5000;
478
+ const int R = 10000;
479
+ Arena arena;
480
+ TestComparator cmp;
481
+ InlineSkipList<TestComparator> list(cmp, &arena);
482
+ std::set<Key> inserted;
483
+
484
+ for (int i = 0; i < N; i++) {
485
+ Key key = rnd.Next() % R;
486
+ if (inserted.insert(key).second) {
487
+ char* buf = list.AllocateKey(sizeof(Key));
488
+ memcpy(buf, &key, sizeof(Key));
489
+ list.Insert(buf);
490
+ }
491
+ }
492
+
493
+ // Generate sorted query keys
494
+ const size_t num_queries = 100;
495
+ std::vector<Key> query_keys;
496
+ query_keys.reserve(num_queries);
497
+ for (size_t i = 0; i < num_queries; i++) {
498
+ query_keys.push_back(rnd.Next() % R);
499
+ }
500
+ std::sort(query_keys.begin(), query_keys.end());
501
+
502
+ struct CallbackArg {
503
+ bool found;
504
+ Key found_key;
505
+ };
506
+ auto callback = [](void* arg, const char* entry) -> bool {
507
+ auto* cb = static_cast<CallbackArg*>(arg);
508
+ if (!cb->found) {
509
+ cb->found = true;
510
+ cb->found_key = Decode(entry);
511
+ }
512
+ return false;
513
+ };
514
+
515
+ std::vector<const char*> key_ptrs(num_queries);
516
+ std::vector<CallbackArg> cb_data(num_queries);
517
+ std::vector<void*> cb_args(num_queries);
518
+
519
+ for (size_t i = 0; i < num_queries; i++) {
520
+ key_ptrs[i] = Encode(&query_keys[i]);
521
+ cb_data[i].found = false;
522
+ cb_data[i].found_key = 0;
523
+ cb_args[i] = &cb_data[i];
524
+ }
525
+
526
+ ASSERT_OK(
527
+ list.MultiGet(num_queries, key_ptrs.data(), cb_args.data(), callback));
528
+
529
+ // Validate against std::set::lower_bound
530
+ for (size_t i = 0; i < num_queries; i++) {
531
+ auto model_iter = inserted.lower_bound(query_keys[i]);
532
+ if (model_iter == inserted.end()) {
533
+ ASSERT_FALSE(cb_data[i].found) << "Query " << query_keys[i];
534
+ } else {
535
+ ASSERT_TRUE(cb_data[i].found) << "Query " << query_keys[i];
536
+ ASSERT_EQ(cb_data[i].found_key, *model_iter) << "Query " << query_keys[i];
537
+ }
538
+ }
539
+ }
540
+
541
+ // Reproduces a bug where duplicate keys in a MultiGet batch cause an assertion
542
+ // failure when the callback walks forward (e.g., merge operands). After the
543
+ // callback loop for key[i] advances finger.prev_[0] to an entry with the same
544
+ // user key but a lower sequence number, the duplicate key[i+1] (which has
545
+ // kMaxSequenceNumber and thus sorts BEFORE the advanced finger position in
546
+ // internal key order) triggers the assertion:
547
+ // assert(before == head_ || KeyIsAfterNode(key, before))
548
+ TEST_F(InlineSkipTest, MultiGetDuplicateKeysWithCallbackWalk) {
549
+ Arena arena;
550
+ TestComparator cmp;
551
+ InlineSkipList<TestComparator> list(cmp, &arena);
552
+
553
+ // Insert keys: 10, 20, 30, 40, 50, 60
554
+ for (int i = 1; i <= 6; i++) {
555
+ Key key = i * 10;
556
+ char* buf = list.AllocateKey(sizeof(Key));
557
+ memcpy(buf, &key, sizeof(Key));
558
+ list.Insert(buf);
559
+ }
560
+
561
+ // Callback that walks forward through multiple entries before stopping.
562
+ // This simulates the Merge operand accumulation in SaveValue — the callback
563
+ // returns true for entries until it reaches one >= stop_at, simulating
564
+ // walking through merge chain entries.
565
+ struct WalkingCallbackArg {
566
+ Key stop_at; // stop when we reach this key
567
+ Key first_key; // first key seen
568
+ int num_visited; // number of entries visited
569
+ };
570
+ auto walking_callback = [](void* arg, const char* entry) -> bool {
571
+ auto* cb = static_cast<WalkingCallbackArg*>(arg);
572
+ Key k = Decode(entry);
573
+ if (cb->num_visited == 0) {
574
+ cb->first_key = k;
575
+ }
576
+ cb->num_visited++;
577
+ // Walk forward until we reach stop_at (simulates merge accumulation)
578
+ return k < cb->stop_at;
579
+ };
580
+
581
+ // Query with duplicate keys: [20, 20, 50]
582
+ // The first query for 20 walks forward to 40 (stop_at=40), advancing
583
+ // finger.prev_[0] to 30. Then the second query for 20 must still work
584
+ // correctly despite finger.prev_[0] being past key 20.
585
+ const size_t num_queries = 3;
586
+ Key query_keys[num_queries] = {20, 20, 50};
587
+ const char* key_ptrs[num_queries];
588
+ void* cb_args[num_queries];
589
+ WalkingCallbackArg cb_data[num_queries];
590
+
591
+ for (size_t i = 0; i < num_queries; i++) {
592
+ key_ptrs[i] = Encode(&query_keys[i]);
593
+ cb_data[i].stop_at = (i == 0) ? 40 : 0; // first query walks to 40
594
+ cb_data[i].first_key = 0;
595
+ cb_data[i].num_visited = 0;
596
+ cb_args[i] = &cb_data[i];
597
+ }
598
+
599
+ // This should not crash with the assertion failure
600
+ ASSERT_OK(list.MultiGet(num_queries, key_ptrs, cb_args, walking_callback));
601
+
602
+ // First query for 20: should find 20 and walk forward through 30 (stop at
603
+ // 40)
604
+ ASSERT_EQ(cb_data[0].first_key, 20);
605
+ ASSERT_GE(cb_data[0].num_visited, 2);
606
+
607
+ // Second query for 20: should also find 20 (duplicate key)
608
+ ASSERT_EQ(cb_data[1].first_key, 20);
609
+
610
+ // Third query for 50: should find 50
611
+ ASSERT_EQ(cb_data[2].first_key, 50);
612
+ }
613
+
312
614
  #if !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
313
615
  // We want to make sure that with a single writer and multiple
314
616
  // concurrent readers (with no synchronization other than when a
@@ -655,6 +957,194 @@ TEST_F(InlineSkipTest, ConcurrentInsertWithHint3) {
655
957
  RunConcurrentInsert(3, true);
656
958
  }
657
959
 
960
+ // Test read-after-write consistency with concurrent MultiGet and inserts.
961
+ // Exercises skip list height growth handling in FindGreaterOrEqualWithFinger.
962
+ //
963
+ // Design:
964
+ // - Generate a sequence of unique keys and split into per-thread chunks.
965
+ // - Each thread inserts its keys one at a time, and after each insert,
966
+ // does a MultiGet batch that includes the just-inserted key plus random
967
+ // keys from a shared "recently inserted" set populated by all threads.
968
+ // - Validates that the just-inserted key is always visible (read-after-write)
969
+ // and that any key from the shared set that was published before the
970
+ // MultiGet began is also visible.
971
+ struct ConcurrentMultiGetState {
972
+ InlineSkipList<TestComparator>* list;
973
+ // Per-thread chunk of unique keys to insert
974
+ const Key* keys;
975
+ size_t num_keys;
976
+ int seed;
977
+ std::atomic<int>* error_count;
978
+ std::atomic<int>* batches_done;
979
+ // Shared ring buffer of recently inserted keys from all threads.
980
+ // Writers publish keys here after insertion; readers sample from it.
981
+ static const int kRingSize = 1024;
982
+ std::atomic<Key>* shared_ring;
983
+ // Monotonically increasing write cursor into the ring buffer.
984
+ std::atomic<uint64_t>* ring_cursor;
985
+ };
986
+
987
+ static void ConcurrentMultiGetWorker(void* arg) {
988
+ auto* state = static_cast<ConcurrentMultiGetState*>(arg);
989
+ Random rnd(state->seed);
990
+ const int kExtraQueryKeys = 15; // additional random keys per batch
991
+
992
+ auto callback = [](void* cb_arg, const char* entry) -> bool {
993
+ auto* result = static_cast<Key*>(cb_arg);
994
+ *result = Decode(entry);
995
+ return false; // point lookup: stop after first entry
996
+ };
997
+
998
+ for (size_t i = 0; i < state->num_keys; i++) {
999
+ Key my_key = state->keys[i];
1000
+
1001
+ // Insert this thread's next unique key
1002
+ char* buf = state->list->AllocateKey(sizeof(Key));
1003
+ memcpy(buf, &my_key, sizeof(Key));
1004
+ state->list->InsertConcurrently(buf);
1005
+
1006
+ // Publish to shared ring buffer so other threads can query it
1007
+ uint64_t slot = state->ring_cursor->fetch_add(1, std::memory_order_relaxed);
1008
+ state->shared_ring[slot % ConcurrentMultiGetState::kRingSize].store(
1009
+ my_key, std::memory_order_release);
1010
+
1011
+ // Build a MultiGet batch: the just-inserted key + random shared keys
1012
+ std::vector<Key> query_keys;
1013
+ query_keys.reserve(1 + kExtraQueryKeys);
1014
+ query_keys.push_back(my_key);
1015
+
1016
+ // Sample recently inserted keys from other threads
1017
+ uint64_t cursor = state->ring_cursor->load(std::memory_order_acquire);
1018
+ for (int j = 0; j < kExtraQueryKeys; j++) {
1019
+ // Sample from the most recent entries in the ring
1020
+ uint64_t idx =
1021
+ (cursor > 0)
1022
+ ? (rnd.Next() %
1023
+ std::min(cursor, static_cast<uint64_t>(
1024
+ ConcurrentMultiGetState::kRingSize)))
1025
+ : 0;
1026
+ Key shared_key = state
1027
+ ->shared_ring[(cursor - 1 - idx) %
1028
+ ConcurrentMultiGetState::kRingSize]
1029
+ .load(std::memory_order_acquire);
1030
+ if (shared_key != 0) {
1031
+ query_keys.push_back(shared_key);
1032
+ }
1033
+ }
1034
+
1035
+ // Sort and deduplicate for MultiGet
1036
+ std::sort(query_keys.begin(), query_keys.end());
1037
+ query_keys.erase(std::unique(query_keys.begin(), query_keys.end()),
1038
+ query_keys.end());
1039
+
1040
+ size_t batch_size = query_keys.size();
1041
+ std::vector<const char*> key_ptrs(batch_size);
1042
+ std::vector<Key> results(batch_size, 0);
1043
+ std::vector<void*> cb_args(batch_size);
1044
+ for (size_t j = 0; j < batch_size; j++) {
1045
+ key_ptrs[j] = Encode(&query_keys[j]);
1046
+ cb_args[j] = &results[j];
1047
+ }
1048
+
1049
+ Status s = state->list->MultiGet(batch_size, key_ptrs.data(),
1050
+ cb_args.data(), callback);
1051
+ if (!s.ok()) {
1052
+ state->error_count->fetch_add(1, std::memory_order_relaxed);
1053
+ return;
1054
+ }
1055
+
1056
+ // Validate read-after-write: the key we just inserted MUST be visible.
1057
+ // Find my_key's position in the sorted query_keys.
1058
+ for (size_t j = 0; j < batch_size; j++) {
1059
+ if (query_keys[j] == my_key) {
1060
+ if (results[j] != my_key) {
1061
+ state->error_count->fetch_add(1, std::memory_order_relaxed);
1062
+ return;
1063
+ }
1064
+ break;
1065
+ }
1066
+ }
1067
+
1068
+ // Validate all results: each found result must equal its query key
1069
+ // (since all queried keys were inserted, an exact match is expected).
1070
+ // However, due to concurrent inserts, a key sampled from the ring
1071
+ // might not yet be visible — so we only check that if a result is
1072
+ // found, it equals the query key (i.e., no wrong key returned).
1073
+ for (size_t j = 0; j < batch_size; j++) {
1074
+ if (results[j] != 0 && results[j] != query_keys[j]) {
1075
+ // Got a result that doesn't match the query — either a bug or
1076
+ // the exact key wasn't inserted and we got the next one. Since
1077
+ // all our query keys are inserted, this means the result should
1078
+ // be >= query. For the just-inserted key we already checked
1079
+ // exact match above.
1080
+ if (results[j] < query_keys[j]) {
1081
+ state->error_count->fetch_add(1, std::memory_order_relaxed);
1082
+ return;
1083
+ }
1084
+ }
1085
+ }
1086
+
1087
+ state->batches_done->fetch_add(1, std::memory_order_relaxed);
1088
+ }
1089
+ }
1090
+
1091
+ TEST_F(InlineSkipTest, ConcurrentMultiGet) {
1092
+ uint32_t seed =
1093
+ static_cast<uint32_t>(Env::Default()->NowMicros() & 0xFFFFFFFF);
1094
+ SCOPED_TRACE("seed=" + std::to_string(seed));
1095
+
1096
+ ConcurrentArena arena;
1097
+ TestComparator cmp;
1098
+ InlineSkipList<TestComparator> list(cmp, &arena);
1099
+
1100
+ // Generate a sequence of unique keys and shuffle them
1101
+ const int kTotalKeys = 20000;
1102
+ const int kNumThreads = 4;
1103
+ std::vector<Key> all_keys(kTotalKeys);
1104
+ for (int i = 0; i < kTotalKeys; i++) {
1105
+ all_keys[i] = static_cast<Key>(i + 1); // keys 1..kTotalKeys
1106
+ }
1107
+ Random rnd(seed);
1108
+ for (int i = kTotalKeys - 1; i > 0; i--) {
1109
+ int j = rnd.Next() % (i + 1);
1110
+ std::swap(all_keys[i], all_keys[j]);
1111
+ }
1112
+
1113
+ // Shared ring buffer for cross-thread visibility checks
1114
+ std::atomic<Key> shared_ring[ConcurrentMultiGetState::kRingSize];
1115
+ for (auto& k : shared_ring) {
1116
+ k.store(0, std::memory_order_relaxed);
1117
+ }
1118
+ std::atomic<uint64_t> ring_cursor{0};
1119
+
1120
+ std::atomic<int> error_count{0};
1121
+ std::atomic<int> batches_done{0};
1122
+
1123
+ // Split keys into per-thread chunks and start worker threads.
1124
+ // Use StartThread (not Schedule) so WaitForJoin waits for completion.
1125
+ const int kKeysPerThread = kTotalKeys / kNumThreads;
1126
+ std::vector<ConcurrentMultiGetState> states(kNumThreads);
1127
+ for (int t = 0; t < kNumThreads; t++) {
1128
+ states[t].list = &list;
1129
+ states[t].keys = &all_keys[t * kKeysPerThread];
1130
+ states[t].num_keys = kKeysPerThread;
1131
+ states[t].seed = seed + t + 1;
1132
+ states[t].error_count = &error_count;
1133
+ states[t].batches_done = &batches_done;
1134
+ states[t].shared_ring = shared_ring;
1135
+ states[t].ring_cursor = &ring_cursor;
1136
+ Env::Default()->StartThread(ConcurrentMultiGetWorker, &states[t]);
1137
+ }
1138
+
1139
+ // Wait for all threads to finish
1140
+ Env::Default()->WaitForJoin();
1141
+
1142
+ ASSERT_EQ(error_count.load(), 0)
1143
+ << "Concurrent MultiGet read-after-write consistency check failed";
1144
+ ASSERT_EQ(batches_done.load(), kTotalKeys)
1145
+ << "Not all insert+query iterations completed";
1146
+ }
1147
+
658
1148
  #endif // !defined(ROCKSDB_VALGRIND_RUN) || defined(ROCKSDB_FULL_VALGRIND_RUN)
659
1149
  } // namespace ROCKSDB_NAMESPACE
660
1150
 
@@ -197,14 +197,14 @@ struct SkipList<Key, Comparator>::Node {
197
197
 
198
198
  private:
199
199
  // Array of length equal to the node height. next_[0] is lowest level link.
200
- AcqRelAtomic<Node*> next_[1];
200
+ Atomic<Node*> next_[1];
201
201
  };
202
202
 
203
203
  template <typename Key, class Comparator>
204
204
  typename SkipList<Key, Comparator>::Node* SkipList<Key, Comparator>::NewNode(
205
205
  const Key& key, int height) {
206
- char* mem = allocator_->AllocateAligned(
207
- sizeof(Node) + sizeof(AcqRelAtomic<Node*>) * (height - 1));
206
+ char* mem = allocator_->AllocateAligned(sizeof(Node) +
207
+ sizeof(Atomic<Node*>) * (height - 1));
208
208
  return new (mem) Node(key);
209
209
  }
210
210
 
@@ -109,6 +109,17 @@ class SkipListRep : public MemTableRep {
109
109
  return status;
110
110
  }
111
111
 
112
+ Status MultiGet(size_t num_keys, const char* const* keys,
113
+ void** callback_args,
114
+ bool (*callback_func)(void* arg, const char* entry),
115
+ bool allow_data_in_errors, bool detect_key_out_of_order,
116
+ const std::function<Status(const char*, bool)>&
117
+ key_validation_callback) override {
118
+ return skip_list_.MultiGet(num_keys, keys, callback_args, callback_func,
119
+ allow_data_in_errors, detect_key_out_of_order,
120
+ key_validation_callback);
121
+ }
122
+
112
123
  uint64_t ApproximateNumEntries(const Slice& start_ikey,
113
124
  const Slice& end_ikey) override {
114
125
  return skip_list_.ApproximateNumEntries(start_ikey, end_ikey);
@@ -138,13 +138,11 @@ static void SetupDB(benchmark::State& state, Options& options,
138
138
  db_path + kFilePathSeparator + test_name + std::to_string(getpid());
139
139
  DestroyDB(db_name, options);
140
140
 
141
- DB* db_ptr = nullptr;
142
- s = DB::Open(options, db_name, &db_ptr);
141
+ s = DB::Open(options, db_name, db);
143
142
  if (!s.ok()) {
144
143
  state.SkipWithError(s.ToString().c_str());
145
144
  return;
146
145
  }
147
- db->reset(db_ptr);
148
146
  }
149
147
 
150
148
  static void TeardownDB(benchmark::State& state, const std::unique_ptr<DB>& db,
@@ -181,12 +179,10 @@ static void DBOpen(benchmark::State& state) {
181
179
 
182
180
  for (auto _ : state) {
183
181
  {
184
- DB* db_ptr = nullptr;
185
- Status s = DB::Open(options, db_name, &db_ptr);
182
+ Status s = DB::Open(options, db_name, &db);
186
183
  if (!s.ok()) {
187
184
  state.SkipWithError(s.ToString().c_str());
188
185
  }
189
- db.reset(db_ptr);
190
186
  }
191
187
  state.PauseTiming();
192
188
  auto wo = WriteOptions();
@@ -231,12 +227,10 @@ static void DBClose(benchmark::State& state) {
231
227
  for (auto _ : state) {
232
228
  state.PauseTiming();
233
229
  {
234
- DB* db_ptr = nullptr;
235
- Status s = DB::Open(options, db_name, &db_ptr);
230
+ Status s = DB::Open(options, db_name, &db);
236
231
  if (!s.ok()) {
237
232
  state.SkipWithError(s.ToString().c_str());
238
233
  }
239
- db.reset(db_ptr);
240
234
  }
241
235
  auto wo = WriteOptions();
242
236
  Status s;
@@ -727,13 +721,11 @@ static void SimpleGetWithPerfContext(benchmark::State& state) {
727
721
  DestroyDB(db_name, options);
728
722
 
729
723
  {
730
- DB* db_ptr = nullptr;
731
- s = DB::Open(options, db_name, &db_ptr);
724
+ s = DB::Open(options, db_name, &db);
732
725
  if (!s.ok()) {
733
726
  state.SkipWithError(s.ToString().c_str());
734
727
  return;
735
728
  }
736
- db.reset(db_ptr);
737
729
  }
738
730
  // load db
739
731
  auto wo = WriteOptions();
@@ -32,7 +32,7 @@ struct KeyMaker {
32
32
  // To get range [avg_size - 2, avg_size + 2]
33
33
  // use range [smallest_size, smallest_size + 4]
34
34
  len += FastRange32((val_num >> 5) * 1234567891, 5);
35
- char *data = buf_.get() + start;
35
+ char* data = buf_.get() + start;
36
36
  // Populate key data such that all data makes it into a key of at
37
37
  // least 8 bytes. We also don't want all the within-filter key
38
38
  // variance confined to a contiguous 32 bits, because then a 32 bit
@@ -51,7 +51,7 @@ struct KeyMaker {
51
51
  // 1. filter config bits_per_key
52
52
  // 2. average data key length
53
53
  // 3. data entry number
54
- static void CustomArguments(benchmark::internal::Benchmark *b) {
54
+ static void CustomArguments(benchmark::internal::Benchmark* b) {
55
55
  const auto kImplCount =
56
56
  static_cast<int>(BloomLikeFilterPolicy::GetAllFixedImpls().size());
57
57
  for (int filter_impl = 0; filter_impl < kImplCount; ++filter_impl) {
@@ -66,7 +66,7 @@ static void CustomArguments(benchmark::internal::Benchmark *b) {
66
66
  b->ArgNames({"filter_impl", "bits_per_key", "key_len_avg", "entry_num"});
67
67
  }
68
68
 
69
- static void FilterBuild(benchmark::State &state) {
69
+ static void FilterBuild(benchmark::State& state) {
70
70
  // setup data
71
71
  auto filter = BloomLikeFilterPolicy::Create(
72
72
  BloomLikeFilterPolicy::GetAllFixedImpls().at(state.range(0)),
@@ -89,7 +89,7 @@ static void FilterBuild(benchmark::State &state) {
89
89
  }
90
90
  BENCHMARK(FilterBuild)->Apply(CustomArguments);
91
91
 
92
- static void FilterQueryPositive(benchmark::State &state) {
92
+ static void FilterQueryPositive(benchmark::State& state) {
93
93
  // setup data
94
94
  auto filter = BloomLikeFilterPolicy::Create(
95
95
  BloomLikeFilterPolicy::GetAllFixedImpls().at(state.range(0)),
@@ -117,7 +117,7 @@ static void FilterQueryPositive(benchmark::State &state) {
117
117
  }
118
118
  BENCHMARK(FilterQueryPositive)->Apply(CustomArguments);
119
119
 
120
- static void FilterQueryNegative(benchmark::State &state) {
120
+ static void FilterQueryNegative(benchmark::State& state) {
121
121
  // setup data
122
122
  auto filter = BloomLikeFilterPolicy::Create(
123
123
  BloomLikeFilterPolicy::GetAllFixedImpls().at(state.range(0)),
@@ -5,19 +5,36 @@
5
5
  //
6
6
  #pragma once
7
7
  #include "db/version_edit.h"
8
+ #include "test_util/sync_point.h"
8
9
  #include "util/random.h"
9
10
 
10
11
  namespace ROCKSDB_NAMESPACE {
11
12
  static const uint32_t kFileReadSampleRate = 1024;
12
- bool should_sample_file_read();
13
- void sample_file_read_inc(FileMetaData*);
13
+ static const uint32_t kFileReadNextSampleRate =
14
+ kFileReadSampleRate * 64; // Must be kept a power of 2
14
15
 
15
16
  inline bool should_sample_file_read() {
16
- return (Random::GetTLSInstance()->Next() % kFileReadSampleRate == 307);
17
+ bool result = (Random::GetTLSInstance()->Next() % kFileReadSampleRate == 307);
18
+ TEST_SYNC_POINT_CALLBACK("should_sample_file_read:override", &result);
19
+ return result;
17
20
  }
18
21
 
19
- inline void sample_file_read_inc(FileMetaData* meta) {
22
+ inline bool should_sample_file_read_next() {
23
+ // Decrease probability of sampling next() to discount it as it is cheaper
24
+ // than seek()
25
+ thread_local uint32_t counter = 0;
26
+ bool result = (++counter & (kFileReadNextSampleRate - 1)) == 0;
27
+ TEST_SYNC_POINT_CALLBACK("should_sample_file_read:override", &result);
28
+ return result;
29
+ }
30
+
31
+ inline void sample_file_read_inc(const FileMetaData* meta) {
20
32
  meta->stats.num_reads_sampled.fetch_add(kFileReadSampleRate,
21
33
  std::memory_order_relaxed);
22
34
  }
35
+
36
+ inline void sample_collapsible_entry_file_read_inc(const FileMetaData* meta) {
37
+ meta->stats.num_collapsible_entry_reads_sampled.fetch_add(
38
+ kFileReadSampleRate, std::memory_order_relaxed);
39
+ }
23
40
  } // namespace ROCKSDB_NAMESPACE