@nxtedition/rocksdb 15.4.1 → 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 (399) hide show
  1. package/binding.cc +24 -15
  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/iterator.js +2 -2
  395. package/package.json +1 -1
  396. package/prebuilds/darwin-arm64/@nxtedition+rocksdb.node +0 -0
  397. package/prebuilds/linux-x64/@nxtedition+rocksdb.node +0 -0
  398. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/lua/rocks_lua_custom_library.h +0 -43
  399. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/lua/rocks_lua_util.h +0 -55
@@ -0,0 +1,993 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // This source code is licensed under both the GPLv2 (found in the
3
+ // COPYING file in the root directory) and Apache 2.0 License
4
+ // (found in the LICENSE.Apache file in the root directory).
5
+
6
+ #include <atomic>
7
+ #include <set>
8
+ #include <thread>
9
+ #include <unordered_map>
10
+
11
+ #include "db/compaction/compaction_job.h"
12
+ #include "db/db_impl/db_impl_secondary.h"
13
+ #include "db/db_test_util.h"
14
+ #include "options/options_helper.h"
15
+ #include "port/stack_trace.h"
16
+ #include "rocksdb/db.h"
17
+ #include "rocksdb/sst_file_writer.h"
18
+ #include "test_util/sync_point.h"
19
+ #include "test_util/testharness.h"
20
+
21
+ namespace ROCKSDB_NAMESPACE {
22
+
23
+ // Helper class to manage abort synchronization in tests.
24
+ //
25
+ // Compaction abort could happen at various stage of compaction.
26
+ // To test this, we need to trigger abort at different stage. This requires
27
+ // precise control on the timing of abort API invocation. To achieve this in a
28
+ // consistent way across various tests, we invoke AbortAllCompactions() within
29
+ // the sync point callback, that is added at various stages of compaction.
30
+ // However as the abort API is a blocking call, calling it within the sync point
31
+ // callback on the compaction thread would cause deadlock. This test helper
32
+ // class is designed to solve this challenge.
33
+ //
34
+ // 1. Abort must happen from a different thread:
35
+ // AbortAllCompactions() is typically called from the compaction thread
36
+ // via a sync point callback, so that we could precisely control the time of
37
+ // API invocation to simulate abort at different stage of compaction.
38
+ // However, we can't block the compaction thread waiting for the abort to
39
+ // complete - the compaction needs to continue executing to actually check
40
+ // the abort flag and exit. So we spawn a separate thread to call
41
+ // AbortAllCompactions().
42
+ //
43
+ // 2. We need to know when abort completes:
44
+ // After compaction returns (with aborted status), we often need to:
45
+ // - Verify state (e.g., no output files created)
46
+ // - Call ResumeAllCompactions()
47
+ // - Run compaction again to verify it succeeds
48
+ // We must wait for the abort thread to finish before proceeding, otherwise
49
+ // we might call Resume before Abort completes, causing race conditions.
50
+ //
51
+ // 3. Sync point callbacks may fire multiple times:
52
+ // With multiple subcompactions, a callback like
53
+ // "CompactionJob::ProcessKeyValueCompaction:Start" fires once per
54
+ // subcompaction. We only want to trigger abort once, so we use
55
+ // abort_triggered_ as a guard.
56
+ //
57
+ // 4. Tests may need multiple abort cycles:
58
+ // Some tests (e.g., MultipleAbortResumeSequence) do abort->resume->abort
59
+ // multiple times. The class supports this by auto-resetting when a
60
+ // previous abort has completed.
61
+ class AbortSynchronizer {
62
+ public:
63
+ AbortSynchronizer() : abort_cv_(&abort_mutex_) {}
64
+
65
+ ~AbortSynchronizer() {
66
+ // Join the thread if it was started - ensures clean shutdown
67
+ if (abort_thread_.joinable()) {
68
+ abort_thread_.join();
69
+ }
70
+ }
71
+
72
+ // Non-copyable, non-movable due to thread member
73
+ AbortSynchronizer(const AbortSynchronizer&) = delete;
74
+ AbortSynchronizer& operator=(const AbortSynchronizer&) = delete;
75
+
76
+ // Trigger abort from a separate thread.
77
+ // - Safe to call multiple times; only first call in each cycle spawns thread
78
+ // - If a previous abort has completed, automatically resets state first
79
+ // - The spawned thread calls AbortAllCompactions() and signals completion
80
+ void TriggerAbort(DBImpl* db) {
81
+ // If previous abort completed, reset state to allow new abort
82
+ if (abort_triggered_.load() && abort_completed_.load()) {
83
+ Reset();
84
+ }
85
+
86
+ if (!abort_triggered_.exchange(true)) {
87
+ abort_thread_ = std::thread([this, db]() {
88
+ db->AbortAllCompactions();
89
+ SignalAbortCompleted();
90
+ });
91
+ }
92
+ }
93
+
94
+ // Wait for the abort thread to complete.
95
+ // Call this AFTER compaction returns to ensure the abort thread has finished
96
+ // before proceeding with Resume or other operations.
97
+ void WaitForAbortCompletion() {
98
+ MutexLock l(&abort_mutex_);
99
+ while (!abort_completed_.load()) {
100
+ abort_cv_.Wait();
101
+ }
102
+ }
103
+
104
+ // Reset state for reuse. Joins any previous thread first.
105
+ // Called automatically by TriggerAbort() if previous abort completed,
106
+ // but can also be called explicitly for clarity.
107
+ void Reset() {
108
+ if (abort_thread_.joinable()) {
109
+ abort_thread_.join();
110
+ }
111
+ abort_triggered_.store(false);
112
+ abort_completed_.store(false);
113
+ }
114
+
115
+ bool IsAbortTriggered() const { return abort_triggered_.load(); }
116
+
117
+ private:
118
+ void SignalAbortCompleted() {
119
+ MutexLock l(&abort_mutex_);
120
+ abort_completed_.store(true);
121
+ abort_cv_.SignalAll();
122
+ }
123
+
124
+ std::atomic<bool> abort_triggered_{false}; // Guards against multiple spawns
125
+ std::atomic<bool> abort_completed_{false}; // Signals thread completion
126
+ port::Mutex abort_mutex_;
127
+ port::CondVar abort_cv_;
128
+ std::thread abort_thread_; // The thread that calls AbortAllCompactions()
129
+ };
130
+
131
+ // Helper to clean up SyncPoint state after tests
132
+ inline void CleanupSyncPoints() {
133
+ ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->DisableProcessing();
134
+ ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
135
+ }
136
+
137
+ // Helper class that combines AbortSynchronizer with sync point setup for
138
+ // deterministic abort triggering. This adds sync point coordination on top
139
+ // of AbortSynchronizer:
140
+ //
141
+ // This is useful when you need deterministic timing - the callback won't
142
+ // return until AbortAllCompactions() has actually set the abort flag,
143
+ // guaranteeing the compaction will see it on the next check.
144
+ class SyncPointAbortHelper {
145
+ public:
146
+ explicit SyncPointAbortHelper(const std::string& trigger_point)
147
+ : trigger_point_(trigger_point) {}
148
+
149
+ // Set up sync points and callbacks. Call this before starting compaction.
150
+ void Setup(DBImpl* db_impl) {
151
+ db_impl_ = db_impl;
152
+
153
+ ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->LoadDependency({
154
+ {"DBImpl::AbortAllCompactions:FlagSet", kWaitPointName},
155
+ });
156
+
157
+ ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
158
+ trigger_point_, [this](void* /*arg*/) {
159
+ // Use AbortSynchronizer to handle the abort in a separate thread
160
+ abort_sync_.TriggerAbort(db_impl_);
161
+
162
+ // Wait for abort flag to be set via sync point dependency
163
+ // This ensures deterministic timing - compaction will see the flag
164
+ TEST_SYNC_POINT_CALLBACK(kWaitPointName, nullptr);
165
+ });
166
+ ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
167
+ }
168
+
169
+ // Wait for the abort to complete. Call this after compaction returns.
170
+ void WaitForAbortCompletion() { abort_sync_.WaitForAbortCompletion(); }
171
+
172
+ // Clean up sync points and wait for abort completion in one call
173
+ void CleanupAndWait() {
174
+ CleanupSyncPoints();
175
+ WaitForAbortCompletion();
176
+ }
177
+
178
+ private:
179
+ static constexpr const char* kWaitPointName =
180
+ "SyncPointAbortHelper::WaitForAbort";
181
+ std::string trigger_point_;
182
+ DBImpl* db_impl_{nullptr};
183
+ AbortSynchronizer abort_sync_;
184
+ };
185
+
186
+ class DBCompactionAbortTest : public DBTestBase {
187
+ public:
188
+ DBCompactionAbortTest()
189
+ : DBTestBase("db_compaction_abort_test", /*env_do_fsync=*/false) {}
190
+
191
+ protected:
192
+ // Map to track the latest value of each key for verification
193
+ std::unordered_map<std::string, std::string> expected_values_;
194
+
195
+ // Statistics object for verifying compaction metrics
196
+ std::shared_ptr<Statistics> stats_;
197
+
198
+ // Get current options with statistics enabled
199
+ Options GetOptionsWithStats() {
200
+ Options options = CurrentOptions();
201
+ stats_ = CreateDBStatistics();
202
+ options.statistics = stats_;
203
+ return options;
204
+ }
205
+
206
+ // Populate database with test data.
207
+ // If overlapping=true, uses the same key range (0 to keys_per_file-1) in each
208
+ // file to ensure compaction has work to do.
209
+ // If overlapping=false, uses non-overlapping keys across files.
210
+ void PopulateData(int num_files, int keys_per_file, int value_size,
211
+ bool overlapping = true, int seed = 301) {
212
+ Random rnd(seed);
213
+ for (int i = 0; i < num_files; ++i) {
214
+ for (int j = 0; j < keys_per_file; ++j) {
215
+ int key_index = overlapping ? j : (j + i * keys_per_file);
216
+ std::string key = Key(key_index);
217
+ std::string value = rnd.RandomString(value_size);
218
+ ASSERT_OK(Put(key, value));
219
+ expected_values_[key] = value;
220
+ }
221
+ ASSERT_OK(Flush());
222
+ }
223
+ }
224
+
225
+ // Verify data integrity by reading all keys and comparing with expected
226
+ // values
227
+ void VerifyDataIntegrity(int num_keys, int start_key = 0) {
228
+ std::string val;
229
+ for (int j = start_key; j < start_key + num_keys; ++j) {
230
+ std::string key = Key(j);
231
+ ASSERT_OK(dbfull()->Get(ReadOptions(), key, &val));
232
+ auto it = expected_values_.find(key);
233
+ if (it != expected_values_.end()) {
234
+ ASSERT_EQ(it->second, val) << "Value mismatch for key: " << key;
235
+ }
236
+ }
237
+ }
238
+
239
+ // Clear expected values (useful when reopening DB or between tests)
240
+ void ClearExpectedValues() { expected_values_.clear(); }
241
+
242
+ // Run the common abort test pattern with SyncPointAbortHelper:
243
+ // 1. Set up sync point abort helper
244
+ // 2. Run compaction and verify it's aborted
245
+ // 3. Verify COMPACTION_ABORTED stat increased (if stats enabled)
246
+ // 4. Clean up, resume, and verify compaction succeeds
247
+ // 5. Verify COMPACT_WRITE_BYTES increased (if stats enabled)
248
+ void RunSyncPointAbortTest(const std::string& trigger_point,
249
+ CompactRangeOptions cro = CompactRangeOptions()) {
250
+ // Capture stats and file counts before abort
251
+ uint64_t aborted_before = 0;
252
+ uint64_t write_bytes_before = 0;
253
+ if (stats_) {
254
+ aborted_before = stats_->getTickerCount(COMPACTION_ABORTED);
255
+ write_bytes_before = stats_->getTickerCount(COMPACT_WRITE_BYTES);
256
+ }
257
+
258
+ SyncPointAbortHelper helper(trigger_point);
259
+ helper.Setup(dbfull());
260
+
261
+ Status s = dbfull()->CompactRange(cro, nullptr, nullptr);
262
+ ASSERT_TRUE(s.IsIncomplete());
263
+ ASSERT_TRUE(s.IsCompactionAborted());
264
+
265
+ // Verify abort was counted
266
+ if (stats_) {
267
+ uint64_t aborted_after = stats_->getTickerCount(COMPACTION_ABORTED);
268
+ ASSERT_GT(aborted_after, aborted_before)
269
+ << "COMPACTION_ABORTED stat should increase after abort";
270
+ }
271
+
272
+ helper.CleanupAndWait();
273
+ dbfull()->ResumeAllCompactions();
274
+
275
+ ASSERT_OK(dbfull()->CompactRange(cro, nullptr, nullptr));
276
+
277
+ // Verify compaction completed and wrote bytes
278
+ if (stats_) {
279
+ uint64_t write_bytes_after = stats_->getTickerCount(COMPACT_WRITE_BYTES);
280
+ ASSERT_GT(write_bytes_after, write_bytes_before)
281
+ << "COMPACT_WRITE_BYTES should increase after successful compaction";
282
+ }
283
+ }
284
+ };
285
+
286
+ // Parameterized test for abort with different number of max subcompactions.
287
+ // This consolidates tests that were essentially duplicates with different
288
+ // max_subcompactions values
289
+ class DBCompactionAbortSubcompactionTest
290
+ : public DBCompactionAbortTest,
291
+ public ::testing::WithParamInterface<int> {};
292
+
293
+ TEST_P(DBCompactionAbortSubcompactionTest, AbortWithVaryingSubcompactions) {
294
+ int max_subcompactions = GetParam();
295
+
296
+ Options options = GetOptionsWithStats();
297
+ options.level0_file_num_compaction_trigger = 4;
298
+ options.max_subcompactions = max_subcompactions;
299
+ options.disable_auto_compactions = true;
300
+ Reopen(options);
301
+
302
+ PopulateData(/*num_files=*/4, /*keys_per_file=*/100, /*value_size=*/100);
303
+
304
+ RunSyncPointAbortTest("CompactionJob::RunSubcompactions:BeforeStart");
305
+
306
+ VerifyDataIntegrity(/*num_keys=*/100);
307
+ }
308
+
309
+ INSTANTIATE_TEST_CASE_P(SubcompactionVariants,
310
+ DBCompactionAbortSubcompactionTest,
311
+ ::testing::Values(1, 2, 4),
312
+ [](const ::testing::TestParamInfo<int>& param_info) {
313
+ return "MaxSubcompactionCount_" +
314
+ std::to_string(param_info.param);
315
+ });
316
+
317
+ // Parameterized test for abort with different compaction styles
318
+ // This consolidates tests for Level, Universal, and FIFO compaction styles
319
+ class DBCompactionAbortStyleTest
320
+ : public DBCompactionAbortTest,
321
+ public ::testing::WithParamInterface<CompactionStyle> {
322
+ protected:
323
+ // Configure options based on compaction style
324
+ void ConfigureOptionsForStyle(Options& options, CompactionStyle style) {
325
+ options.compaction_style = style;
326
+ options.level0_file_num_compaction_trigger = 4;
327
+ options.disable_auto_compactions = true;
328
+
329
+ switch (style) {
330
+ case kCompactionStyleLevel:
331
+ // Level compaction uses default settings
332
+ break;
333
+ case kCompactionStyleUniversal:
334
+ options.compaction_options_universal.size_ratio = 10;
335
+ break;
336
+ case kCompactionStyleFIFO:
337
+ // Set a large max_table_files_size to avoid deletion compaction
338
+ options.compaction_options_fifo.max_table_files_size =
339
+ 100 * 1024 * 1024;
340
+ // Enable intra-L0 compaction which goes through normal compaction path
341
+ options.compaction_options_fifo.allow_compaction = true;
342
+ options.max_open_files = -1; // Required for FIFO compaction
343
+ break;
344
+ default:
345
+ break;
346
+ }
347
+ }
348
+ };
349
+
350
+ TEST_P(DBCompactionAbortStyleTest, AbortCompaction) {
351
+ CompactionStyle style = GetParam();
352
+
353
+ Options options = GetOptionsWithStats();
354
+ options.max_subcompactions = 1;
355
+ ConfigureOptionsForStyle(options, style);
356
+ Reopen(options);
357
+
358
+ PopulateData(/*num_files=*/4, /*keys_per_file=*/100, /*value_size=*/100);
359
+
360
+ RunSyncPointAbortTest("CompactionJob::RunSubcompactions:BeforeStart");
361
+
362
+ VerifyDataIntegrity(/*num_keys=*/100);
363
+ }
364
+
365
+ INSTANTIATE_TEST_CASE_P(
366
+ CompactionStyleVariants, DBCompactionAbortStyleTest,
367
+ ::testing::Values(kCompactionStyleLevel, kCompactionStyleUniversal,
368
+ kCompactionStyleFIFO),
369
+ [](const ::testing::TestParamInfo<CompactionStyle>& param_info) {
370
+ return OptionsHelper::compaction_style_to_string.at(param_info.param);
371
+ });
372
+
373
+ TEST_F(DBCompactionAbortTest, AbortManualCompaction) {
374
+ Options options = GetOptionsWithStats();
375
+ options.level0_file_num_compaction_trigger = 10;
376
+ options.disable_auto_compactions = true;
377
+ Reopen(options);
378
+
379
+ PopulateData(/*num_files=*/5, /*keys_per_file=*/100, /*value_size=*/1000);
380
+
381
+ CompactRangeOptions cro;
382
+ cro.exclusive_manual_compaction = true;
383
+ RunSyncPointAbortTest("CompactionJob::ProcessKeyValueCompaction:Start", cro);
384
+
385
+ VerifyDataIntegrity(/*num_keys=*/100);
386
+ }
387
+
388
+ TEST_F(DBCompactionAbortTest, AbortAutomaticCompaction) {
389
+ Options options = CurrentOptions();
390
+ options.level0_file_num_compaction_trigger = 4;
391
+ options.max_subcompactions = 2;
392
+ options.disable_auto_compactions = false;
393
+ Reopen(options);
394
+
395
+ Random rnd(301);
396
+ AbortSynchronizer abort_sync;
397
+
398
+ ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
399
+ "CompactionJob::ProcessKeyValueCompaction:Start",
400
+ [&](void* /*arg*/) { abort_sync.TriggerAbort(dbfull()); });
401
+ ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
402
+
403
+ for (int i = 0; i < 4; ++i) {
404
+ for (int j = 0; j < 100; ++j) {
405
+ ASSERT_OK(Put(Key(j), rnd.RandomString(1000)));
406
+ }
407
+ ASSERT_OK(Flush());
408
+ }
409
+
410
+ ASSERT_OK(dbfull()->TEST_WaitForCompact());
411
+
412
+ CleanupSyncPoints();
413
+
414
+ abort_sync.WaitForAbortCompletion();
415
+ dbfull()->ResumeAllCompactions();
416
+
417
+ for (int j = 0; j < 100; ++j) {
418
+ ASSERT_OK(Put(Key(j), rnd.RandomString(1000)));
419
+ }
420
+ ASSERT_OK(Flush());
421
+
422
+ ASSERT_OK(dbfull()->TEST_WaitForCompact());
423
+
424
+ std::string val;
425
+ for (int j = 0; j < 100; ++j) {
426
+ ASSERT_OK(dbfull()->Get(ReadOptions(), Key(j), &val));
427
+ }
428
+ }
429
+
430
+ TEST_F(DBCompactionAbortTest, AbortAndVerifyNoOutputFiles) {
431
+ Options options = CurrentOptions();
432
+ options.level0_file_num_compaction_trigger = 4;
433
+ options.max_subcompactions = 2;
434
+ options.disable_auto_compactions = true;
435
+ Reopen(options);
436
+
437
+ PopulateData(/*num_files=*/4, /*keys_per_file=*/100, /*value_size=*/1000);
438
+
439
+ int num_l0_files_before = NumTableFilesAtLevel(0);
440
+ int num_l1_files_before = NumTableFilesAtLevel(1);
441
+
442
+ SyncPointAbortHelper helper("CompactionJob::ProcessKeyValueCompaction:Start");
443
+ helper.Setup(dbfull());
444
+
445
+ CompactRangeOptions cro;
446
+ Status s = dbfull()->CompactRange(cro, nullptr, nullptr);
447
+ ASSERT_TRUE(s.IsIncomplete());
448
+ ASSERT_TRUE(s.IsCompactionAborted());
449
+
450
+ CleanupSyncPoints();
451
+
452
+ int num_l0_files_after = NumTableFilesAtLevel(0);
453
+ int num_l1_files_after = NumTableFilesAtLevel(1);
454
+
455
+ ASSERT_EQ(num_l0_files_before, num_l0_files_after);
456
+ ASSERT_EQ(num_l1_files_before, num_l1_files_after);
457
+
458
+ helper.WaitForAbortCompletion();
459
+ dbfull()->ResumeAllCompactions();
460
+
461
+ ASSERT_OK(dbfull()->CompactRange(cro, nullptr, nullptr));
462
+
463
+ int num_l0_files_final = NumTableFilesAtLevel(0);
464
+ int num_l1_files_final = NumTableFilesAtLevel(1);
465
+
466
+ ASSERT_EQ(0, num_l0_files_final);
467
+ ASSERT_GT(num_l1_files_final, 0);
468
+
469
+ VerifyDataIntegrity(/*num_keys=*/100);
470
+ }
471
+
472
+ TEST_F(DBCompactionAbortTest, MultipleAbortResumeSequence) {
473
+ Options options = CurrentOptions();
474
+ options.level0_file_num_compaction_trigger = 4;
475
+ options.max_subcompactions = 2;
476
+ options.disable_auto_compactions = true;
477
+ Reopen(options);
478
+
479
+ PopulateData(/*num_files=*/4, /*keys_per_file=*/100, /*value_size=*/1000);
480
+
481
+ for (int round = 0; round < 3; ++round) {
482
+ // Use SyncPointAbortHelper for deterministic abort timing - it waits
483
+ // for the abort flag to be set via sync point dependency
484
+ SyncPointAbortHelper helper(
485
+ "CompactionJob::ProcessKeyValueCompaction:Start");
486
+ helper.Setup(dbfull());
487
+
488
+ CompactRangeOptions cro;
489
+ Status s = dbfull()->CompactRange(cro, nullptr, nullptr);
490
+ ASSERT_TRUE(s.IsIncomplete());
491
+ ASSERT_TRUE(s.IsCompactionAborted());
492
+
493
+ helper.CleanupAndWait();
494
+ dbfull()->ResumeAllCompactions();
495
+ }
496
+
497
+ ASSERT_OK(dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr));
498
+
499
+ VerifyDataIntegrity(/*num_keys=*/100);
500
+ }
501
+
502
+ TEST_F(DBCompactionAbortTest, AbortWithOutputFilesCleanup) {
503
+ Options options = CurrentOptions();
504
+ options.num_levels = 2; // Ensure compaction output goes to L1
505
+ options.level0_file_num_compaction_trigger = 4;
506
+ options.max_subcompactions = 2;
507
+ options.disable_auto_compactions = true;
508
+ options.target_file_size_base = 50 * 1024;
509
+ Reopen(options);
510
+
511
+ PopulateData(/*num_files=*/4, /*keys_per_file=*/100, /*value_size=*/100);
512
+
513
+ SyncPointAbortHelper helper("CompactionJob::RunSubcompactions:BeforeStart");
514
+ helper.Setup(dbfull());
515
+
516
+ CompactRangeOptions cro;
517
+ Status s = dbfull()->CompactRange(cro, nullptr, nullptr);
518
+ ASSERT_TRUE(s.IsIncomplete());
519
+ ASSERT_TRUE(s.IsCompactionAborted());
520
+
521
+ CleanupSyncPoints();
522
+
523
+ int num_l1_files_after_abort = NumTableFilesAtLevel(1);
524
+ ASSERT_EQ(0, num_l1_files_after_abort);
525
+
526
+ helper.WaitForAbortCompletion();
527
+ dbfull()->ResumeAllCompactions();
528
+
529
+ ASSERT_OK(dbfull()->CompactRange(cro, nullptr, nullptr));
530
+
531
+ // Verify L0 files are compacted and L1 has output files
532
+ int num_l0_files_final = NumTableFilesAtLevel(0);
533
+ int num_l1_files_final = NumTableFilesAtLevel(1);
534
+ ASSERT_EQ(0, num_l0_files_final)
535
+ << "L0 should be empty after successful compaction";
536
+ ASSERT_GT(num_l1_files_final, 0)
537
+ << "L1 should have files after successful compaction";
538
+
539
+ VerifyDataIntegrity(/*num_keys=*/100);
540
+ }
541
+
542
+ TEST_F(DBCompactionAbortTest, NestedAbortResumeCalls) {
543
+ // Test that nested AbortAllCompactions() calls work correctly with the
544
+ // counter
545
+ Options options = CurrentOptions();
546
+ options.level0_file_num_compaction_trigger = 4;
547
+ options.max_subcompactions = 2;
548
+ options.disable_auto_compactions = true;
549
+ Reopen(options);
550
+
551
+ PopulateData(/*num_files=*/4, /*keys_per_file=*/100, /*value_size=*/1000);
552
+
553
+ // First abort call
554
+ dbfull()->AbortAllCompactions();
555
+
556
+ // Nested abort call (counter should be 2)
557
+ dbfull()->AbortAllCompactions();
558
+
559
+ // Compaction should still be blocked after one resume
560
+ dbfull()->ResumeAllCompactions();
561
+
562
+ // Compaction should still return aborted because counter is still 1
563
+ CompactRangeOptions cro;
564
+ Status s = dbfull()->CompactRange(cro, nullptr, nullptr);
565
+ ASSERT_TRUE(s.IsIncomplete());
566
+ ASSERT_TRUE(s.IsCompactionAborted());
567
+
568
+ // Second resume - counter should be 0 now
569
+ dbfull()->ResumeAllCompactions();
570
+
571
+ // Compaction should succeed now
572
+ ASSERT_OK(dbfull()->CompactRange(cro, nullptr, nullptr));
573
+
574
+ VerifyDataIntegrity(/*num_keys=*/100);
575
+ }
576
+
577
+ TEST_F(DBCompactionAbortTest, AbortCompactFilesAPI) {
578
+ // Test that AbortAllCompactions works with CompactFiles API
579
+ Options options = CurrentOptions();
580
+ options.level0_file_num_compaction_trigger = 100; // Disable auto compaction
581
+ options.disable_auto_compactions = true;
582
+ Reopen(options);
583
+
584
+ PopulateData(/*num_files=*/4, /*keys_per_file=*/100, /*value_size=*/1000);
585
+
586
+ // Get the L0 file names
587
+ std::vector<std::string> files_to_compact;
588
+ ColumnFamilyMetaData cf_meta;
589
+ dbfull()->GetColumnFamilyMetaData(dbfull()->DefaultColumnFamily(), &cf_meta);
590
+ for (const auto& file : cf_meta.levels[0].files) {
591
+ files_to_compact.push_back(file.name);
592
+ }
593
+ ASSERT_GE(files_to_compact.size(), 2);
594
+
595
+ SyncPointAbortHelper helper("CompactionJob::ProcessKeyValueCompaction:Start");
596
+ helper.Setup(dbfull());
597
+
598
+ CompactionOptions compact_options;
599
+ Status s = dbfull()->CompactFiles(compact_options, files_to_compact, 1);
600
+ ASSERT_TRUE(s.IsIncomplete());
601
+ ASSERT_TRUE(s.IsCompactionAborted());
602
+
603
+ helper.CleanupAndWait();
604
+ dbfull()->ResumeAllCompactions();
605
+
606
+ // CompactFiles should work after resume
607
+ ASSERT_OK(dbfull()->CompactFiles(compact_options, files_to_compact, 1));
608
+
609
+ VerifyDataIntegrity(/*num_keys=*/100);
610
+ }
611
+
612
+ TEST_F(DBCompactionAbortTest, AbortDoesNotAffectFlush) {
613
+ // Test that AbortAllCompactions does not affect flush operations
614
+ Options options = CurrentOptions();
615
+ options.level0_file_num_compaction_trigger = 100;
616
+ options.disable_auto_compactions = true;
617
+ Reopen(options);
618
+
619
+ Random rnd(301);
620
+ for (int j = 0; j < 100; ++j) {
621
+ ASSERT_OK(Put(Key(j), rnd.RandomString(1000)));
622
+ }
623
+
624
+ // Abort compactions
625
+ dbfull()->AbortAllCompactions();
626
+
627
+ // Flush should still work
628
+ ASSERT_OK(Flush());
629
+
630
+ // Write more data
631
+ for (int j = 100; j < 200; ++j) {
632
+ ASSERT_OK(Put(Key(j), rnd.RandomString(1000)));
633
+ }
634
+
635
+ // Flush should still work
636
+ ASSERT_OK(Flush());
637
+
638
+ // Resume compactions
639
+ dbfull()->ResumeAllCompactions();
640
+
641
+ VerifyDataIntegrity(/*num_keys=*/200);
642
+ }
643
+
644
+ TEST_F(DBCompactionAbortTest, AbortBeforeCompactionStarts) {
645
+ // Test aborting before any compaction has started
646
+ Options options = CurrentOptions();
647
+ options.level0_file_num_compaction_trigger = 4;
648
+ options.disable_auto_compactions = true;
649
+ Reopen(options);
650
+
651
+ PopulateData(/*num_files=*/4, /*keys_per_file=*/100, /*value_size=*/1000);
652
+
653
+ // Abort before starting compaction
654
+ dbfull()->AbortAllCompactions();
655
+
656
+ // Compaction should immediately return aborted
657
+ CompactRangeOptions cro;
658
+ Status s = dbfull()->CompactRange(cro, nullptr, nullptr);
659
+ ASSERT_TRUE(s.IsIncomplete());
660
+ ASSERT_TRUE(s.IsCompactionAborted());
661
+
662
+ // Resume
663
+ dbfull()->ResumeAllCompactions();
664
+
665
+ // Now compaction should work
666
+ ASSERT_OK(dbfull()->CompactRange(cro, nullptr, nullptr));
667
+
668
+ // Verify L0 files are compacted
669
+ ASSERT_EQ(0, NumTableFilesAtLevel(0));
670
+ }
671
+
672
+ // Test that in-progress blob and SST files are properly cleaned up when
673
+ // compaction is aborted. This specifically tests the case where abort happens
674
+ // while files are being written (opened but not yet completed/closed).
675
+ // This catches the bug where files exist on disk but are removed from the
676
+ // outputs_ vector (e.g., by RemoveLastEmptyOutput when file_size is 0 because
677
+ // the builder was abandoned), leaving orphan files.
678
+ TEST_F(DBCompactionAbortTest, AbortWithInProgressFileCleanup) {
679
+ Options options = CurrentOptions();
680
+ options.level0_file_num_compaction_trigger = 4;
681
+ options.max_subcompactions =
682
+ 1; // Single subcompaction for deterministic behavior
683
+ options.disable_auto_compactions = true;
684
+ options.target_file_size_base = 32 * 1024; // 32KB
685
+
686
+ // Enable BlobDB with garbage collection to force blob rewriting during
687
+ // compaction
688
+ options.enable_blob_files = true;
689
+ options.min_blob_size = 0; // All values go to blob files
690
+ options.blob_file_size =
691
+ 1024 * 1024; // 1MB - large enough to not close during test
692
+ // Enable blob garbage collection - this forces blob data to be rewritten
693
+ // during compaction, creating new blob files
694
+ options.enable_blob_garbage_collection = true;
695
+ options.blob_garbage_collection_age_cutoff = 1.0; // Include all blob files
696
+ options.blob_garbage_collection_force_threshold = 0.0; // Always force GC
697
+
698
+ Reopen(options);
699
+
700
+ // Write enough data to trigger the periodic abort check (every 1000 records).
701
+ // 4 files * 2000 keys = 2000 unique overlapping keys processed during
702
+ // compaction. The sync point triggers at 999, 1999, etc.
703
+ PopulateData(/*num_files=*/4, /*keys_per_file=*/2000, /*value_size=*/500);
704
+
705
+ // Helper function to get blob files on disk with their names
706
+ auto GetBlobFilesOnDisk = [this]() -> std::vector<std::string> {
707
+ std::vector<std::string> blob_files;
708
+ std::vector<std::string> files;
709
+ EXPECT_OK(env_->GetChildren(dbname_, &files));
710
+ for (const auto& f : files) {
711
+ if (f.find(".blob") != std::string::npos) {
712
+ blob_files.push_back(f);
713
+ }
714
+ }
715
+ std::sort(blob_files.begin(), blob_files.end());
716
+ return blob_files;
717
+ };
718
+
719
+ // Helper function to get blob file count in metadata
720
+ auto GetBlobFilesInMetadata = [this]() -> std::vector<uint64_t> {
721
+ std::vector<uint64_t> blob_file_numbers;
722
+ ColumnFamilyMetaData cf_meta;
723
+ dbfull()->GetColumnFamilyMetaData(db_->DefaultColumnFamily(), &cf_meta);
724
+ for (const auto& blob_meta : cf_meta.blob_files) {
725
+ blob_file_numbers.push_back(blob_meta.blob_file_number);
726
+ }
727
+ std::sort(blob_file_numbers.begin(), blob_file_numbers.end());
728
+ return blob_file_numbers;
729
+ };
730
+
731
+ // Helper function to get SST files on disk
732
+ auto GetSstFilesOnDisk = [this]() -> std::vector<std::string> {
733
+ std::vector<std::string> sst_files;
734
+ std::vector<std::string> files;
735
+ EXPECT_OK(env_->GetChildren(dbname_, &files));
736
+ for (const auto& f : files) {
737
+ if (f.find(".sst") != std::string::npos) {
738
+ sst_files.push_back(f);
739
+ }
740
+ }
741
+ std::sort(sst_files.begin(), sst_files.end());
742
+ return sst_files;
743
+ };
744
+
745
+ // Helper function to get SST file numbers in metadata
746
+ auto GetSstFilesInMetadata = [this]() -> std::vector<uint64_t> {
747
+ std::vector<uint64_t> sst_file_numbers;
748
+ ColumnFamilyMetaData cf_meta;
749
+ dbfull()->GetColumnFamilyMetaData(db_->DefaultColumnFamily(), &cf_meta);
750
+ for (const auto& level : cf_meta.levels) {
751
+ for (const auto& file : level.files) {
752
+ // Extract file number from the file name (e.g., "000010.sst" -> 10)
753
+ uint64_t file_num = 0;
754
+ std::string fname = file.name;
755
+ // Remove leading path separators if present
756
+ size_t pos = fname.rfind('/');
757
+ if (pos != std::string::npos) {
758
+ fname = fname.substr(pos + 1);
759
+ }
760
+ if (sscanf(fname.c_str(), "%" PRIu64, &file_num) == 1) {
761
+ sst_file_numbers.push_back(file_num);
762
+ }
763
+ }
764
+ }
765
+ std::sort(sst_file_numbers.begin(), sst_file_numbers.end());
766
+ return sst_file_numbers;
767
+ };
768
+
769
+ std::vector<std::string> initial_blob_files = GetBlobFilesOnDisk();
770
+ std::vector<uint64_t> initial_meta_blobs = GetBlobFilesInMetadata();
771
+ std::vector<std::string> initial_sst_files = GetSstFilesOnDisk();
772
+ std::vector<uint64_t> initial_meta_ssts = GetSstFilesInMetadata();
773
+
774
+ ASSERT_GT(initial_blob_files.size(), 0u) << "Expected initial blob files";
775
+ ASSERT_EQ(initial_blob_files.size(), initial_meta_blobs.size())
776
+ << "Initial blob files should match between disk and metadata";
777
+ ASSERT_GT(initial_sst_files.size(), 0u) << "Expected initial SST files";
778
+ ASSERT_EQ(initial_sst_files.size(), initial_meta_ssts.size())
779
+ << "Initial SST files should match between disk and metadata";
780
+
781
+ // Tracking variables for blob file lifecycle
782
+ std::atomic<int> blob_writes{0};
783
+ std::atomic<bool> abort_triggered{false};
784
+ AbortSynchronizer abort_sync;
785
+
786
+ // Set up dependency: the wait point will block until FlagSet is hit
787
+ ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->LoadDependency({
788
+ {"DBImpl::AbortAllCompactions:FlagSet",
789
+ "DBCompactionAbortTest::InProgressBlob:WaitForAbort"},
790
+ });
791
+
792
+ // Trigger abort after some blob writes during compaction output.
793
+ // This ensures we have an in-progress blob file when abort happens.
794
+ ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->SetCallBack(
795
+ "BlobFileBuilder::WriteBlobToFile:AddRecord", [&](void* /*arg*/) {
796
+ int count = blob_writes.fetch_add(1) + 1;
797
+
798
+ // Trigger abort after 100 blob writes - this ensures:
799
+ // 1. A blob file has been opened (for writing)
800
+ // 2. Some data has been written to it
801
+ // 3. But it's not yet completed (blob_file_size is 1MB)
802
+ if (count == 100 && !abort_triggered.exchange(true)) {
803
+ abort_sync.TriggerAbort(dbfull());
804
+ // Wait for abort flag to be set - this sync point blocks until
805
+ // FlagSet is processed
806
+ TEST_SYNC_POINT_CALLBACK(
807
+ "DBCompactionAbortTest::InProgressBlob:WaitForAbort", nullptr);
808
+ }
809
+ });
810
+
811
+ ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->EnableProcessing();
812
+
813
+ // Run compaction - it should be aborted while blob file is in-progress
814
+ CompactRangeOptions cro;
815
+ Status s = dbfull()->CompactRange(cro, nullptr, nullptr);
816
+
817
+ ASSERT_TRUE(s.IsIncomplete())
818
+ << "Expected compaction to be aborted, got: " << s.ToString();
819
+
820
+ CleanupSyncPoints();
821
+ abort_sync.WaitForAbortCompletion();
822
+
823
+ // Check state after abort
824
+ std::vector<std::string> post_abort_disk_blobs = GetBlobFilesOnDisk();
825
+ std::vector<uint64_t> post_abort_meta_blobs = GetBlobFilesInMetadata();
826
+ std::vector<std::string> post_abort_disk_ssts = GetSstFilesOnDisk();
827
+ std::vector<uint64_t> post_abort_meta_ssts = GetSstFilesInMetadata();
828
+
829
+ // This is the key assertion for blob files: files on disk should match
830
+ // metadata. If the in-progress blob file was NOT cleaned up, there will be an
831
+ // extra file on disk that's not in metadata (orphan).
832
+ ASSERT_EQ(post_abort_disk_blobs.size(), post_abort_meta_blobs.size())
833
+ << "Orphan blob file detected! In-progress blob file was not cleaned up "
834
+ "after abort. Files on disk: "
835
+ << post_abort_disk_blobs.size()
836
+ << ", Files in metadata: " << post_abort_meta_blobs.size()
837
+ << ". The difference indicates orphaned in-progress blob file(s).";
838
+
839
+ // This is the key assertion for SST files: files on disk should match
840
+ // metadata. If the in-progress SST file was NOT cleaned up, there will be an
841
+ // extra file on disk that's not in metadata (orphan).
842
+ ASSERT_EQ(post_abort_disk_ssts.size(), post_abort_meta_ssts.size())
843
+ << "Orphan SST file detected! In-progress SST file was not cleaned up "
844
+ "after abort. Files on disk: "
845
+ << post_abort_disk_ssts.size()
846
+ << ", Files in metadata: " << post_abort_meta_ssts.size()
847
+ << ". The difference indicates orphaned in-progress SST file(s).";
848
+
849
+ // Resume and complete compaction to verify DB is still functional
850
+ dbfull()->ResumeAllCompactions();
851
+
852
+ ASSERT_OK(dbfull()->CompactRange(cro, nullptr, nullptr));
853
+
854
+ // Verify data integrity - we wrote 4 files * 2000 keys with overlapping keys
855
+ VerifyDataIntegrity(/*num_keys=*/2000);
856
+ }
857
+
858
+ TEST_F(DBCompactionAbortTest, AbortBottommostLevelCompaction) {
859
+ Options options = CurrentOptions();
860
+ options.num_levels = 4;
861
+ options.level0_file_num_compaction_trigger = 2;
862
+ options.max_bytes_for_level_base = 1024 * 10; // 10KB
863
+ options.max_bytes_for_level_multiplier = 2;
864
+ options.disable_auto_compactions = true;
865
+ Reopen(options);
866
+
867
+ // Write data to fill multiple levels (non-overlapping keys)
868
+ PopulateData(/*num_files=*/6, /*keys_per_file=*/100,
869
+ /*value_size=*/500, /*overlapping=*/false);
870
+
871
+ // First compact to push data to lower levels
872
+ ASSERT_OK(dbfull()->CompactRange(CompactRangeOptions(), nullptr, nullptr));
873
+
874
+ // Write more data to L0 (overlapping keys)
875
+ PopulateData(/*num_files=*/4, /*keys_per_file=*/100, /*value_size=*/500);
876
+
877
+ SyncPointAbortHelper helper("CompactionJob::ProcessKeyValueCompaction:Start");
878
+ helper.Setup(dbfull());
879
+
880
+ // Trigger bottommost level compaction
881
+ CompactRangeOptions cro;
882
+ cro.bottommost_level_compaction = BottommostLevelCompaction::kForce;
883
+ Status s = dbfull()->CompactRange(cro, nullptr, nullptr);
884
+ ASSERT_TRUE(s.IsIncomplete());
885
+ ASSERT_TRUE(s.IsCompactionAborted());
886
+
887
+ helper.CleanupAndWait();
888
+ dbfull()->ResumeAllCompactions();
889
+
890
+ ASSERT_OK(dbfull()->CompactRange(cro, nullptr, nullptr));
891
+
892
+ VerifyDataIntegrity(/*num_keys=*/600);
893
+ }
894
+
895
+ // Test that while compactions are aborted, atomic range replace
896
+ // (IngestExternalFiles with atomic_replace_range) works correctly.
897
+ // This verifies that the abort state doesn't block other write operations
898
+ // like atomic range replace.
899
+ TEST_F(DBCompactionAbortTest, AbortThenAtomicRangeReplace) {
900
+ Options options = CurrentOptions();
901
+ options.level0_file_num_compaction_trigger = 4;
902
+ options.max_subcompactions = 2;
903
+ options.disable_auto_compactions = true;
904
+ Reopen(options);
905
+
906
+ // Create a directory for SST files
907
+ std::string sst_files_dir = dbname_ + "_sst_files/";
908
+ ASSERT_OK(env_->CreateDirIfMissing(sst_files_dir));
909
+
910
+ // Populate initial data with overlapping keys
911
+ PopulateData(/*num_files=*/4, /*keys_per_file=*/100, /*value_size=*/500);
912
+
913
+ // Verify initial data
914
+ VerifyDataIntegrity(/*num_keys=*/100);
915
+
916
+ // Trigger compaction and abort it
917
+ SyncPointAbortHelper helper("CompactionJob::ProcessKeyValueCompaction:Start");
918
+ helper.Setup(dbfull());
919
+
920
+ CompactRangeOptions cro;
921
+ Status s = dbfull()->CompactRange(cro, nullptr, nullptr);
922
+ ASSERT_TRUE(s.IsIncomplete());
923
+ ASSERT_TRUE(s.IsCompactionAborted());
924
+
925
+ helper.CleanupAndWait();
926
+
927
+ // While compaction is still aborted, perform atomic range replace using
928
+ // IngestExternalFiles with atomic_replace_range. This verifies that the
929
+ // abort state doesn't block other write operations.
930
+ // Using RangeOpt() (empty range) means replace everything in the CF.
931
+
932
+ // Create an SST file with new data for keys 0-49 (replacing keys 0-99)
933
+ std::string sst_file_path = sst_files_dir + "atomic_replace_1.sst";
934
+ SstFileWriter sst_file_writer(EnvOptions(), options);
935
+ ASSERT_OK(sst_file_writer.Open(sst_file_path));
936
+
937
+ // Write new values for keys 0-49
938
+ Random rnd(42);
939
+ std::unordered_map<std::string, std::string> new_values;
940
+ for (int j = 0; j < 50; ++j) {
941
+ std::string key = Key(j);
942
+ std::string value = "replaced_" + rnd.RandomString(100);
943
+ ASSERT_OK(sst_file_writer.Put(key, value));
944
+ new_values[key] = value;
945
+ }
946
+ ASSERT_OK(sst_file_writer.Finish());
947
+
948
+ // Perform atomic range replace for the entire column family.
949
+ // Using RangeOpt() (default constructor) means replace everything in the CF.
950
+ IngestExternalFileArg arg;
951
+ arg.column_family = db_->DefaultColumnFamily();
952
+ arg.external_files = {sst_file_path};
953
+ arg.atomic_replace_range = RangeOpt();
954
+ // snapshot_consistency must be false when using atomic_replace_range
955
+ arg.options.snapshot_consistency = false;
956
+
957
+ // Atomic range replace should work even while compactions are aborted
958
+ ASSERT_OK(db_->IngestExternalFiles({arg}));
959
+
960
+ // Now resume compactions after the atomic range replace
961
+ dbfull()->ResumeAllCompactions();
962
+
963
+ // Verify that the atomic range replace worked correctly:
964
+ // 1. Keys 0-49 should have new replaced values
965
+ std::string val;
966
+ for (int j = 0; j < 50; ++j) {
967
+ std::string key = Key(j);
968
+ ASSERT_OK(db_->Get(ReadOptions(), key, &val));
969
+ auto it = new_values.find(key);
970
+ ASSERT_NE(it, new_values.end());
971
+ ASSERT_EQ(it->second, val) << "Value mismatch for replaced key: " << key;
972
+ }
973
+
974
+ // 2. Keys 50-99 should not exist (they were replaced/deleted by atomic
975
+ // replace)
976
+ for (int j = 50; j < 100; ++j) {
977
+ std::string key = Key(j);
978
+ Status get_status = db_->Get(ReadOptions(), key, &val);
979
+ ASSERT_TRUE(get_status.IsNotFound())
980
+ << "Key " << key << " should not exist after full CF replace";
981
+ }
982
+
983
+ // Clean up SST files directory
984
+ ASSERT_OK(DestroyDir(env_, sst_files_dir));
985
+ }
986
+
987
+ } // namespace ROCKSDB_NAMESPACE
988
+
989
+ int main(int argc, char** argv) {
990
+ ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
991
+ ::testing::InitGoogleTest(&argc, argv);
992
+ return RUN_ALL_TESTS();
993
+ }