@nxtedition/rocksdb 8.2.0 → 8.2.2

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 (321) hide show
  1. package/binding.cc +3 -3
  2. package/deps/rocksdb/rocksdb/CMakeLists.txt +16 -52
  3. package/deps/rocksdb/rocksdb/Makefile +10 -5
  4. package/deps/rocksdb/rocksdb/TARGETS +8 -345
  5. package/deps/rocksdb/rocksdb/cache/cache_test.cc +92 -0
  6. package/deps/rocksdb/rocksdb/cache/clock_cache.cc +32 -32
  7. package/deps/rocksdb/rocksdb/cache/clock_cache.h +12 -9
  8. package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.cc +6 -43
  9. package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.h +3 -13
  10. package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache_test.cc +8 -5
  11. package/deps/rocksdb/rocksdb/cache/lru_cache.cc +21 -47
  12. package/deps/rocksdb/rocksdb/cache/lru_cache.h +3 -8
  13. package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +2 -1
  14. package/deps/rocksdb/rocksdb/cache/secondary_cache_adapter.cc +1 -2
  15. package/deps/rocksdb/rocksdb/cache/sharded_cache.cc +44 -7
  16. package/deps/rocksdb/rocksdb/cache/sharded_cache.h +13 -14
  17. package/deps/rocksdb/rocksdb/db/blob/blob_contents.h +1 -1
  18. package/deps/rocksdb/rocksdb/db/blob/blob_file_builder.cc +1 -0
  19. package/deps/rocksdb/rocksdb/db/blob/blob_file_cache.cc +2 -2
  20. package/deps/rocksdb/rocksdb/db/blob/blob_file_cache.h +2 -1
  21. package/deps/rocksdb/rocksdb/db/blob/blob_file_cache_test.cc +17 -8
  22. package/deps/rocksdb/rocksdb/db/blob/blob_file_reader.cc +40 -21
  23. package/deps/rocksdb/rocksdb/db/blob/blob_file_reader.h +5 -1
  24. package/deps/rocksdb/rocksdb/db/blob/blob_file_reader_test.cc +41 -42
  25. package/deps/rocksdb/rocksdb/db/blob/blob_log_sequential_reader.cc +1 -1
  26. package/deps/rocksdb/rocksdb/db/blob/blob_log_writer.cc +1 -1
  27. package/deps/rocksdb/rocksdb/db/blob/blob_source.cc +5 -4
  28. package/deps/rocksdb/rocksdb/db/blob/blob_source.h +2 -2
  29. package/deps/rocksdb/rocksdb/db/blob/blob_source_test.cc +5 -3
  30. package/deps/rocksdb/rocksdb/db/builder.cc +7 -6
  31. package/deps/rocksdb/rocksdb/db/builder.h +2 -2
  32. package/deps/rocksdb/rocksdb/db/c.cc +76 -5
  33. package/deps/rocksdb/rocksdb/db/c_test.c +141 -0
  34. package/deps/rocksdb/rocksdb/db/column_family.cc +32 -0
  35. package/deps/rocksdb/rocksdb/db/compact_files_test.cc +3 -2
  36. package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +5 -0
  37. package/deps/rocksdb/rocksdb/db/compaction/compaction.h +8 -5
  38. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +12 -10
  39. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +21 -17
  40. package/deps/rocksdb/rocksdb/db/compaction/compaction_job_stats_test.cc +2 -2
  41. package/deps/rocksdb/rocksdb/db/compaction/compaction_job_test.cc +8 -7
  42. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +3 -1
  43. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.cc +1 -1
  44. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.cc +77 -50
  45. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.h +4 -5
  46. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_level.cc +55 -8
  47. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +142 -56
  48. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +1 -1
  49. package/deps/rocksdb/rocksdb/db/compaction/compaction_service_test.cc +1 -2
  50. package/deps/rocksdb/rocksdb/db/compaction/tiered_compaction_test.cc +21 -20
  51. package/deps/rocksdb/rocksdb/db/convenience.cc +8 -6
  52. package/deps/rocksdb/rocksdb/db/corruption_test.cc +5 -4
  53. package/deps/rocksdb/rocksdb/db/db_block_cache_test.cc +6 -3
  54. package/deps/rocksdb/rocksdb/db/db_bloom_filter_test.cc +260 -220
  55. package/deps/rocksdb/rocksdb/db/db_clip_test.cc +142 -0
  56. package/deps/rocksdb/rocksdb/db/db_compaction_filter_test.cc +1 -1
  57. package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +333 -27
  58. package/deps/rocksdb/rocksdb/db/db_impl/compacted_db_impl.cc +5 -0
  59. package/deps/rocksdb/rocksdb/db/db_impl/compacted_db_impl.h +7 -0
  60. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +189 -27
  61. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +23 -10
  62. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +134 -90
  63. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_debug.cc +2 -2
  64. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_experimental.cc +5 -3
  65. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_files.cc +5 -1
  66. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +124 -16
  67. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_readonly.cc +10 -0
  68. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_readonly.h +7 -0
  69. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.cc +15 -0
  70. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_write.cc +11 -5
  71. package/deps/rocksdb/rocksdb/db/db_iter.cc +7 -8
  72. package/deps/rocksdb/rocksdb/db/db_iterator_test.cc +54 -3
  73. package/deps/rocksdb/rocksdb/db/db_merge_operator_test.cc +42 -0
  74. package/deps/rocksdb/rocksdb/db/db_options_test.cc +116 -1
  75. package/deps/rocksdb/rocksdb/db/db_properties_test.cc +3 -2
  76. package/deps/rocksdb/rocksdb/db/db_rate_limiter_test.cc +3 -2
  77. package/deps/rocksdb/rocksdb/db/db_sst_test.cc +9 -8
  78. package/deps/rocksdb/rocksdb/db/db_statistics_test.cc +142 -63
  79. package/deps/rocksdb/rocksdb/db/db_test.cc +28 -7
  80. package/deps/rocksdb/rocksdb/db/db_test2.cc +71 -131
  81. package/deps/rocksdb/rocksdb/db/db_test_util.cc +18 -0
  82. package/deps/rocksdb/rocksdb/db/db_test_util.h +6 -0
  83. package/deps/rocksdb/rocksdb/db/db_universal_compaction_test.cc +10 -10
  84. package/deps/rocksdb/rocksdb/db/db_wal_test.cc +25 -0
  85. package/deps/rocksdb/rocksdb/db/db_with_timestamp_basic_test.cc +88 -0
  86. package/deps/rocksdb/rocksdb/db/db_write_buffer_manager_test.cc +67 -0
  87. package/deps/rocksdb/rocksdb/db/db_write_test.cc +5 -0
  88. package/deps/rocksdb/rocksdb/db/error_handler_fs_test.cc +4 -4
  89. package/deps/rocksdb/rocksdb/db/experimental.cc +4 -2
  90. package/deps/rocksdb/rocksdb/db/external_sst_file_basic_test.cc +86 -1
  91. package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +15 -2
  92. package/deps/rocksdb/rocksdb/db/external_sst_file_test.cc +1 -2
  93. package/deps/rocksdb/rocksdb/db/flush_job.cc +21 -14
  94. package/deps/rocksdb/rocksdb/db/forward_iterator.cc +14 -7
  95. package/deps/rocksdb/rocksdb/db/import_column_family_job.cc +31 -8
  96. package/deps/rocksdb/rocksdb/db/import_column_family_test.cc +21 -19
  97. package/deps/rocksdb/rocksdb/db/internal_stats.cc +42 -12
  98. package/deps/rocksdb/rocksdb/db/internal_stats.h +1 -0
  99. package/deps/rocksdb/rocksdb/db/kv_checksum.h +92 -6
  100. package/deps/rocksdb/rocksdb/db/listener_test.cc +2 -2
  101. package/deps/rocksdb/rocksdb/db/log_format.h +8 -4
  102. package/deps/rocksdb/rocksdb/db/log_reader.cc +129 -51
  103. package/deps/rocksdb/rocksdb/db/log_reader.h +16 -0
  104. package/deps/rocksdb/rocksdb/db/log_test.cc +125 -4
  105. package/deps/rocksdb/rocksdb/db/log_writer.cc +32 -2
  106. package/deps/rocksdb/rocksdb/db/log_writer.h +16 -0
  107. package/deps/rocksdb/rocksdb/db/memtable.cc +17 -46
  108. package/deps/rocksdb/rocksdb/db/memtable.h +1 -1
  109. package/deps/rocksdb/rocksdb/db/memtable_list.cc +8 -4
  110. package/deps/rocksdb/rocksdb/db/merge_helper.cc +1 -1
  111. package/deps/rocksdb/rocksdb/db/perf_context_test.cc +2 -1
  112. package/deps/rocksdb/rocksdb/db/plain_table_db_test.cc +5 -4
  113. package/deps/rocksdb/rocksdb/db/repair.cc +38 -11
  114. package/deps/rocksdb/rocksdb/db/seqno_time_test.cc +3 -3
  115. package/deps/rocksdb/rocksdb/db/table_cache.cc +68 -51
  116. package/deps/rocksdb/rocksdb/db/table_cache.h +20 -10
  117. package/deps/rocksdb/rocksdb/db/table_cache_sync_and_async.h +2 -1
  118. package/deps/rocksdb/rocksdb/db/table_properties_collector_test.cc +6 -3
  119. package/deps/rocksdb/rocksdb/db/version_builder.cc +9 -5
  120. package/deps/rocksdb/rocksdb/db/version_builder.h +2 -1
  121. package/deps/rocksdb/rocksdb/db/version_builder_test.cc +140 -120
  122. package/deps/rocksdb/rocksdb/db/version_edit.cc +14 -0
  123. package/deps/rocksdb/rocksdb/db/version_edit.h +12 -4
  124. package/deps/rocksdb/rocksdb/db/version_edit_handler.cc +21 -13
  125. package/deps/rocksdb/rocksdb/db/version_edit_handler.h +26 -16
  126. package/deps/rocksdb/rocksdb/db/version_edit_test.cc +9 -9
  127. package/deps/rocksdb/rocksdb/db/version_set.cc +292 -96
  128. package/deps/rocksdb/rocksdb/db/version_set.h +53 -28
  129. package/deps/rocksdb/rocksdb/db/version_set_sync_and_async.h +1 -0
  130. package/deps/rocksdb/rocksdb/db/version_set_test.cc +62 -22
  131. package/deps/rocksdb/rocksdb/db/version_util.h +5 -4
  132. package/deps/rocksdb/rocksdb/db/write_batch.cc +3 -1
  133. package/deps/rocksdb/rocksdb/db_stress_tool/CMakeLists.txt +1 -0
  134. package/deps/rocksdb/rocksdb/db_stress_tool/batched_ops_stress.cc +119 -27
  135. package/deps/rocksdb/rocksdb/db_stress_tool/cf_consistency_stress.cc +123 -0
  136. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +4 -0
  137. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_driver.cc +7 -2
  138. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_env_wrapper.h +34 -0
  139. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +13 -0
  140. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_shared_state.h +43 -33
  141. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +29 -17
  142. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.h +5 -0
  143. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_tool.cc +6 -1
  144. package/deps/rocksdb/rocksdb/db_stress_tool/expected_state.cc +85 -50
  145. package/deps/rocksdb/rocksdb/db_stress_tool/expected_state.h +96 -54
  146. package/deps/rocksdb/rocksdb/db_stress_tool/expected_value.cc +122 -0
  147. package/deps/rocksdb/rocksdb/db_stress_tool/expected_value.h +206 -0
  148. package/deps/rocksdb/rocksdb/db_stress_tool/multi_ops_txns_stress.cc +9 -1
  149. package/deps/rocksdb/rocksdb/db_stress_tool/multi_ops_txns_stress.h +9 -3
  150. package/deps/rocksdb/rocksdb/db_stress_tool/no_batched_ops_stress.cc +322 -92
  151. package/deps/rocksdb/rocksdb/env/env_posix.cc +12 -8
  152. package/deps/rocksdb/rocksdb/env/env_test.cc +31 -0
  153. package/deps/rocksdb/rocksdb/env/mock_env.cc +1 -1
  154. package/deps/rocksdb/rocksdb/env/unique_id_gen.h +14 -0
  155. package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.cc +1 -1
  156. package/deps/rocksdb/rocksdb/file/file_prefetch_buffer.h +5 -1
  157. package/deps/rocksdb/rocksdb/file/file_util.cc +3 -3
  158. package/deps/rocksdb/rocksdb/file/file_util.h +2 -0
  159. package/deps/rocksdb/rocksdb/file/prefetch_test.cc +89 -0
  160. package/deps/rocksdb/rocksdb/file/random_access_file_reader.cc +22 -7
  161. package/deps/rocksdb/rocksdb/file/random_access_file_reader.h +3 -2
  162. package/deps/rocksdb/rocksdb/file/readahead_raf.cc +1 -1
  163. package/deps/rocksdb/rocksdb/file/sequence_file_reader.cc +1 -1
  164. package/deps/rocksdb/rocksdb/file/writable_file_writer.cc +1 -1
  165. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_cache.h +3 -0
  166. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +154 -74
  167. package/deps/rocksdb/rocksdb/include/rocksdb/c.h +27 -7
  168. package/deps/rocksdb/rocksdb/include/rocksdb/cache.h +107 -28
  169. package/deps/rocksdb/rocksdb/include/rocksdb/db.h +19 -0
  170. package/deps/rocksdb/rocksdb/include/rocksdb/env.h +8 -0
  171. package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +2 -0
  172. package/deps/rocksdb/rocksdb/include/rocksdb/memory_allocator.h +7 -1
  173. package/deps/rocksdb/rocksdb/include/rocksdb/options.h +137 -152
  174. package/deps/rocksdb/rocksdb/include/rocksdb/perf_context.h +61 -26
  175. package/deps/rocksdb/rocksdb/include/rocksdb/secondary_cache.h +30 -26
  176. package/deps/rocksdb/rocksdb/include/rocksdb/sst_file_writer.h +33 -16
  177. package/deps/rocksdb/rocksdb/include/rocksdb/statistics.h +87 -8
  178. package/deps/rocksdb/rocksdb/include/rocksdb/table.h +1 -1
  179. package/deps/rocksdb/rocksdb/include/rocksdb/table_properties.h +5 -0
  180. package/deps/rocksdb/rocksdb/include/rocksdb/thread_status.h +1 -0
  181. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/options_util.h +1 -0
  182. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +7 -0
  183. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/transaction.h +0 -1
  184. package/deps/rocksdb/rocksdb/include/rocksdb/version.h +2 -2
  185. package/deps/rocksdb/rocksdb/include/rocksdb/write_buffer_manager.h +9 -2
  186. package/deps/rocksdb/rocksdb/logging/env_logger.h +2 -0
  187. package/deps/rocksdb/rocksdb/memory/jemalloc_nodump_allocator.cc +78 -42
  188. package/deps/rocksdb/rocksdb/memory/jemalloc_nodump_allocator.h +14 -9
  189. package/deps/rocksdb/rocksdb/memtable/inlineskiplist_test.cc +1 -0
  190. package/deps/rocksdb/rocksdb/memtable/skiplist_test.cc +1 -0
  191. package/deps/rocksdb/rocksdb/memtable/write_buffer_manager.cc +4 -9
  192. package/deps/rocksdb/rocksdb/microbench/db_basic_bench.cc +19 -11
  193. package/deps/rocksdb/rocksdb/monitoring/instrumented_mutex.h +1 -1
  194. package/deps/rocksdb/rocksdb/monitoring/perf_context.cc +211 -555
  195. package/deps/rocksdb/rocksdb/monitoring/perf_step_timer.h +1 -1
  196. package/deps/rocksdb/rocksdb/monitoring/statistics.cc +36 -2
  197. package/deps/rocksdb/rocksdb/monitoring/thread_status_updater.cc +17 -7
  198. package/deps/rocksdb/rocksdb/monitoring/thread_status_updater.h +10 -7
  199. package/deps/rocksdb/rocksdb/monitoring/thread_status_util.cc +19 -18
  200. package/deps/rocksdb/rocksdb/monitoring/thread_status_util.h +10 -2
  201. package/deps/rocksdb/rocksdb/monitoring/thread_status_util_debug.cc +14 -0
  202. package/deps/rocksdb/rocksdb/options/cf_options.cc +35 -2
  203. package/deps/rocksdb/rocksdb/options/cf_options.h +5 -0
  204. package/deps/rocksdb/rocksdb/options/customizable_test.cc +1 -1
  205. package/deps/rocksdb/rocksdb/options/options.cc +12 -53
  206. package/deps/rocksdb/rocksdb/options/options_helper.cc +4 -0
  207. package/deps/rocksdb/rocksdb/options/options_parser.cc +11 -0
  208. package/deps/rocksdb/rocksdb/options/options_settable_test.cc +32 -4
  209. package/deps/rocksdb/rocksdb/options/options_test.cc +89 -5
  210. package/deps/rocksdb/rocksdb/port/lang.h +27 -0
  211. package/deps/rocksdb/rocksdb/port/stack_trace.cc +67 -24
  212. package/deps/rocksdb/rocksdb/src.mk +2 -0
  213. package/deps/rocksdb/rocksdb/table/block_based/binary_search_index_reader.cc +2 -3
  214. package/deps/rocksdb/rocksdb/table/block_based/block.cc +195 -35
  215. package/deps/rocksdb/rocksdb/table/block_based/block.h +197 -24
  216. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +71 -51
  217. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.h +7 -1
  218. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.cc +4 -6
  219. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.h +3 -0
  220. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.cc +43 -2
  221. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.h +36 -6
  222. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +266 -166
  223. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +44 -14
  224. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_impl.h +1 -1
  225. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_sync_and_async.h +63 -56
  226. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_test.cc +8 -2
  227. package/deps/rocksdb/rocksdb/table/block_based/block_builder.h +4 -2
  228. package/deps/rocksdb/rocksdb/table/block_based/block_cache.cc +10 -0
  229. package/deps/rocksdb/rocksdb/table/block_based/block_cache.h +14 -2
  230. package/deps/rocksdb/rocksdb/table/block_based/block_test.cc +918 -2
  231. package/deps/rocksdb/rocksdb/table/block_based/data_block_hash_index_test.cc +3 -2
  232. package/deps/rocksdb/rocksdb/table/block_based/filter_block.h +10 -9
  233. package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.cc +6 -8
  234. package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.h +2 -2
  235. package/deps/rocksdb/rocksdb/table/block_based/flush_block_policy.cc +1 -1
  236. package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.cc +18 -23
  237. package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.h +8 -8
  238. package/deps/rocksdb/rocksdb/table/block_based/full_filter_block_test.cc +16 -32
  239. package/deps/rocksdb/rocksdb/table/block_based/hash_index_reader.cc +7 -8
  240. package/deps/rocksdb/rocksdb/table/block_based/index_reader_common.cc +4 -5
  241. package/deps/rocksdb/rocksdb/table/block_based/index_reader_common.h +3 -3
  242. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +46 -53
  243. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.h +12 -12
  244. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block_test.cc +7 -9
  245. package/deps/rocksdb/rocksdb/table/block_based/partitioned_index_reader.cc +26 -23
  246. package/deps/rocksdb/rocksdb/table/block_based/partitioned_index_reader.h +2 -1
  247. package/deps/rocksdb/rocksdb/table/block_based/reader_common.h +3 -0
  248. package/deps/rocksdb/rocksdb/table/block_based/uncompression_dict_reader.cc +4 -2
  249. package/deps/rocksdb/rocksdb/table/block_based/uncompression_dict_reader.h +3 -2
  250. package/deps/rocksdb/rocksdb/table/block_fetcher.cc +7 -1
  251. package/deps/rocksdb/rocksdb/table/block_fetcher.h +1 -1
  252. package/deps/rocksdb/rocksdb/table/block_fetcher_test.cc +2 -1
  253. package/deps/rocksdb/rocksdb/table/cuckoo/cuckoo_table_builder_test.cc +3 -2
  254. package/deps/rocksdb/rocksdb/table/cuckoo/cuckoo_table_reader.cc +5 -2
  255. package/deps/rocksdb/rocksdb/table/cuckoo/cuckoo_table_reader.h +4 -2
  256. package/deps/rocksdb/rocksdb/table/format.cc +4 -4
  257. package/deps/rocksdb/rocksdb/table/format.h +1 -1
  258. package/deps/rocksdb/rocksdb/table/get_context.cc +1 -1
  259. package/deps/rocksdb/rocksdb/table/meta_blocks.cc +33 -22
  260. package/deps/rocksdb/rocksdb/table/meta_blocks.h +4 -0
  261. package/deps/rocksdb/rocksdb/table/mock_table.cc +4 -2
  262. package/deps/rocksdb/rocksdb/table/persistent_cache_helper.h +1 -1
  263. package/deps/rocksdb/rocksdb/table/persistent_cache_options.h +1 -1
  264. package/deps/rocksdb/rocksdb/table/plain/plain_table_reader.cc +18 -10
  265. package/deps/rocksdb/rocksdb/table/plain/plain_table_reader.h +4 -3
  266. package/deps/rocksdb/rocksdb/table/sst_file_dumper.cc +10 -7
  267. package/deps/rocksdb/rocksdb/table/sst_file_reader.cc +4 -2
  268. package/deps/rocksdb/rocksdb/table/sst_file_writer.cc +11 -0
  269. package/deps/rocksdb/rocksdb/table/table_builder.h +14 -5
  270. package/deps/rocksdb/rocksdb/table/table_properties.cc +2 -0
  271. package/deps/rocksdb/rocksdb/table/table_reader.h +6 -3
  272. package/deps/rocksdb/rocksdb/table/table_reader_bench.cc +1 -1
  273. package/deps/rocksdb/rocksdb/table/table_test.cc +291 -34
  274. package/deps/rocksdb/rocksdb/test_util/secondary_cache_test_util.h +3 -1
  275. package/deps/rocksdb/rocksdb/test_util/testharness.h +5 -0
  276. package/deps/rocksdb/rocksdb/test_util/testutil.cc +2 -2
  277. package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +33 -17
  278. package/deps/rocksdb/rocksdb/tools/ldb_cmd.cc +3 -1
  279. package/deps/rocksdb/rocksdb/util/bloom_impl.h +2 -2
  280. package/deps/rocksdb/rocksdb/util/compression.h +1 -1
  281. package/deps/rocksdb/rocksdb/util/crc32c.cc +24 -83
  282. package/deps/rocksdb/rocksdb/util/crc32c_arm64.cc +7 -9
  283. package/deps/rocksdb/rocksdb/util/file_checksum_helper.cc +4 -1
  284. package/deps/rocksdb/rocksdb/util/filter_bench.cc +1 -1
  285. package/deps/rocksdb/rocksdb/util/gflags_compat.h +9 -10
  286. package/deps/rocksdb/rocksdb/util/math.h +12 -7
  287. package/deps/rocksdb/rocksdb/util/rate_limiter.cc +16 -18
  288. package/deps/rocksdb/rocksdb/util/rate_limiter_test.cc +46 -2
  289. package/deps/rocksdb/rocksdb/util/ribbon_test.cc +6 -6
  290. package/deps/rocksdb/rocksdb/util/slice_transform_test.cc +12 -7
  291. package/deps/rocksdb/rocksdb/util/stop_watch.h +31 -13
  292. package/deps/rocksdb/rocksdb/util/thread_list_test.cc +2 -0
  293. package/deps/rocksdb/rocksdb/util/thread_operation.h +2 -1
  294. package/deps/rocksdb/rocksdb/util/udt_util.h +77 -0
  295. package/deps/rocksdb/rocksdb/utilities/agg_merge/agg_merge.cc +2 -2
  296. package/deps/rocksdb/rocksdb/utilities/agg_merge/agg_merge_test.cc +1 -1
  297. package/deps/rocksdb/rocksdb/utilities/agg_merge/test_agg_merge.cc +1 -1
  298. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine.cc +1 -1
  299. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +1 -1
  300. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_compaction_filter.h +1 -1
  301. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_impl.cc +11 -1
  302. package/deps/rocksdb/rocksdb/utilities/blob_db/blob_db_test.cc +34 -1
  303. package/deps/rocksdb/rocksdb/utilities/options/options_util_test.cc +15 -0
  304. package/deps/rocksdb/rocksdb/utilities/simulator_cache/sim_cache.cc +1 -1
  305. package/deps/rocksdb/rocksdb/utilities/transactions/pessimistic_transaction.cc +5 -1
  306. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_base.cc +29 -1
  307. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.cc +0 -1
  308. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_transaction_test.cc +0 -1
  309. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_txn.cc +6 -1
  310. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_txn_db.cc +10 -0
  311. package/deps/rocksdb/rocksdb/utilities/transactions/write_unprepared_txn.cc +6 -1
  312. package/deps/rocksdb/rocksdb/utilities/transactions/write_unprepared_txn_db.cc +5 -0
  313. package/deps/rocksdb/rocksdb/utilities/ttl/db_ttl_impl.cc +5 -0
  314. package/package.json +1 -1
  315. package/prebuilds/darwin-arm64/node.napi.node +0 -0
  316. package/prebuilds/linux-x64/node.napi.node +0 -0
  317. /package/deps/rocksdb/rocksdb/memory/{memory_allocator.h → memory_allocator_impl.h} +0 -0
  318. /package/deps/rocksdb/rocksdb/monitoring/{statistics.h → statistics_impl.h} +0 -0
  319. /package/deps/rocksdb/rocksdb/table/block_based/{flush_block_policy.h → flush_block_policy_impl.h} +0 -0
  320. /package/deps/rocksdb/rocksdb/util/{rate_limiter.h → rate_limiter_impl.h} +0 -0
  321. /package/deps/rocksdb/rocksdb/utilities/agg_merge/{agg_merge.h → agg_merge_impl.h} +0 -0
@@ -15,6 +15,7 @@
15
15
  #include <utility>
16
16
  #include <vector>
17
17
 
18
+ #include "db/db_test_util.h"
18
19
  #include "db/dbformat.h"
19
20
  #include "db/memtable.h"
20
21
  #include "db/write_batch_internal.h"
@@ -506,7 +507,7 @@ class IndexBlockTest
506
507
  void GenerateRandomIndexEntries(std::vector<std::string> *separators,
507
508
  std::vector<BlockHandle> *block_handles,
508
509
  std::vector<std::string> *first_keys,
509
- const int len) {
510
+ const int len, bool zero_seqno = false) {
510
511
  Random rnd(42);
511
512
 
512
513
  // For each of `len` blocks, we need to generate a first and last key.
@@ -514,7 +515,11 @@ void GenerateRandomIndexEntries(std::vector<std::string> *separators,
514
515
  std::set<std::string> keys;
515
516
  while ((int)keys.size() < len * 2) {
516
517
  // Keys need to be at least 8 bytes long to look like internal keys.
517
- keys.insert(test::RandomKey(&rnd, 12));
518
+ std::string new_key = test::RandomKey(&rnd, 12);
519
+ if (zero_seqno) {
520
+ AppendInternalKeyFooter(&new_key, 0 /* seqno */, kTypeValue);
521
+ }
522
+ keys.insert(std::move(new_key));
518
523
  }
519
524
 
520
525
  uint64_t offset = 0;
@@ -618,6 +623,917 @@ INSTANTIATE_TEST_CASE_P(P, IndexBlockTest,
618
623
  std::make_tuple(true, false),
619
624
  std::make_tuple(true, true)));
620
625
 
626
+ class BlockPerKVChecksumTest : public DBTestBase {
627
+ public:
628
+ BlockPerKVChecksumTest()
629
+ : DBTestBase("block_per_kv_checksum", /*env_do_fsync=*/false) {}
630
+
631
+ template <typename TBlockIter>
632
+ void TestIterateForward(std::unique_ptr<TBlockIter> &biter,
633
+ size_t &verification_count) {
634
+ while (biter->Valid()) {
635
+ verification_count = 0;
636
+ biter->Next();
637
+ if (biter->Valid()) {
638
+ ASSERT_GE(verification_count, 1);
639
+ }
640
+ }
641
+ }
642
+
643
+ template <typename TBlockIter>
644
+ void TestIterateBackward(std::unique_ptr<TBlockIter> &biter,
645
+ size_t &verification_count) {
646
+ while (biter->Valid()) {
647
+ verification_count = 0;
648
+ biter->Prev();
649
+ if (biter->Valid()) {
650
+ ASSERT_GE(verification_count, 1);
651
+ }
652
+ }
653
+ }
654
+
655
+ template <typename TBlockIter>
656
+ void TestSeekToFirst(std::unique_ptr<TBlockIter> &biter,
657
+ size_t &verification_count) {
658
+ verification_count = 0;
659
+ biter->SeekToFirst();
660
+ ASSERT_GE(verification_count, 1);
661
+ TestIterateForward(biter, verification_count);
662
+ }
663
+
664
+ template <typename TBlockIter>
665
+ void TestSeekToLast(std::unique_ptr<TBlockIter> &biter,
666
+ size_t &verification_count) {
667
+ verification_count = 0;
668
+ biter->SeekToLast();
669
+ ASSERT_GE(verification_count, 1);
670
+ TestIterateBackward(biter, verification_count);
671
+ }
672
+
673
+ template <typename TBlockIter>
674
+ void TestSeekForPrev(std::unique_ptr<TBlockIter> &biter,
675
+ size_t &verification_count, std::string k) {
676
+ verification_count = 0;
677
+ biter->SeekForPrev(k);
678
+ ASSERT_GE(verification_count, 1);
679
+ TestIterateBackward(biter, verification_count);
680
+ }
681
+
682
+ template <typename TBlockIter>
683
+ void TestSeek(std::unique_ptr<TBlockIter> &biter, size_t &verification_count,
684
+ std::string k) {
685
+ verification_count = 0;
686
+ biter->Seek(k);
687
+ ASSERT_GE(verification_count, 1);
688
+ TestIterateForward(biter, verification_count);
689
+ }
690
+
691
+ bool VerifyChecksum(uint32_t checksum_len, const char *checksum_ptr,
692
+ const Slice &key, const Slice &val) {
693
+ if (!checksum_len) {
694
+ return checksum_ptr == nullptr;
695
+ }
696
+ return ProtectionInfo64().ProtectKV(key, val).Verify(
697
+ static_cast<uint8_t>(checksum_len), checksum_ptr);
698
+ }
699
+ };
700
+
701
+ TEST_F(BlockPerKVChecksumTest, EmptyBlock) {
702
+ // Tests that empty block code path is not broken by per kv checksum.
703
+ BlockBuilder builder(
704
+ 16 /* block_restart_interval */, true /* use_delta_encoding */,
705
+ false /* use_value_delta_encoding */,
706
+ BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch);
707
+ Slice raw_block = builder.Finish();
708
+ BlockContents contents;
709
+ contents.data = raw_block;
710
+
711
+ std::unique_ptr<Block_kData> data_block;
712
+ Options options = Options();
713
+ BlockBasedTableOptions tbo;
714
+ uint8_t protection_bytes_per_key = 8;
715
+ BlockCreateContext create_context{
716
+ &tbo, nullptr /* statistics */, false /* using_zstd */,
717
+ protection_bytes_per_key, options.comparator};
718
+ create_context.Create(&data_block, std::move(contents));
719
+ std::unique_ptr<DataBlockIter> biter{data_block->NewDataIterator(
720
+ options.comparator, kDisableGlobalSequenceNumber)};
721
+ biter->SeekToFirst();
722
+ ASSERT_FALSE(biter->Valid());
723
+ ASSERT_OK(biter->status());
724
+ Random rnd(33);
725
+ biter->SeekForGet(GenerateInternalKey(1, 1, 10, &rnd));
726
+ ASSERT_FALSE(biter->Valid());
727
+ ASSERT_OK(biter->status());
728
+ biter->SeekToLast();
729
+ ASSERT_FALSE(biter->Valid());
730
+ ASSERT_OK(biter->status());
731
+ biter->Seek(GenerateInternalKey(1, 1, 10, &rnd));
732
+ ASSERT_FALSE(biter->Valid());
733
+ ASSERT_OK(biter->status());
734
+ biter->SeekForPrev(GenerateInternalKey(1, 1, 10, &rnd));
735
+ ASSERT_FALSE(biter->Valid());
736
+ ASSERT_OK(biter->status());
737
+ }
738
+
739
+ TEST_F(BlockPerKVChecksumTest, UnsupportedOptionValue) {
740
+ Options options = Options();
741
+ options.block_protection_bytes_per_key = 128;
742
+ Destroy(options);
743
+ ASSERT_TRUE(TryReopen(options).IsNotSupported());
744
+ }
745
+
746
+ TEST_F(BlockPerKVChecksumTest, InitializeProtectionInfo) {
747
+ // Make sure that the checksum construction code path does not break
748
+ // when the block is itself already corrupted.
749
+ Options options = Options();
750
+ BlockBasedTableOptions tbo;
751
+ uint8_t protection_bytes_per_key = 8;
752
+ BlockCreateContext create_context{
753
+ &tbo, nullptr /* statistics */, false /* using_zstd */,
754
+ protection_bytes_per_key, options.comparator};
755
+
756
+ {
757
+ std::string invalid_content = "1";
758
+ Slice raw_block = invalid_content;
759
+ BlockContents contents;
760
+ contents.data = raw_block;
761
+ std::unique_ptr<Block_kData> data_block;
762
+ create_context.Create(&data_block, std::move(contents));
763
+ std::unique_ptr<DataBlockIter> iter{data_block->NewDataIterator(
764
+ options.comparator, kDisableGlobalSequenceNumber)};
765
+ ASSERT_TRUE(iter->status().IsCorruption());
766
+ }
767
+ {
768
+ std::string invalid_content = "1";
769
+ Slice raw_block = invalid_content;
770
+ BlockContents contents;
771
+ contents.data = raw_block;
772
+ std::unique_ptr<Block_kIndex> index_block;
773
+ create_context.Create(&index_block, std::move(contents));
774
+ std::unique_ptr<IndexBlockIter> iter{index_block->NewIndexIterator(
775
+ options.comparator, kDisableGlobalSequenceNumber, nullptr, nullptr,
776
+ true, false, true, true)};
777
+ ASSERT_TRUE(iter->status().IsCorruption());
778
+ }
779
+ {
780
+ std::string invalid_content = "1";
781
+ Slice raw_block = invalid_content;
782
+ BlockContents contents;
783
+ contents.data = raw_block;
784
+ std::unique_ptr<Block_kMetaIndex> meta_block;
785
+ create_context.Create(&meta_block, std::move(contents));
786
+ std::unique_ptr<MetaBlockIter> iter{meta_block->NewMetaIterator(true)};
787
+ ASSERT_TRUE(iter->status().IsCorruption());
788
+ }
789
+ }
790
+
791
+ TEST_F(BlockPerKVChecksumTest, ApproximateMemory) {
792
+ // Tests that ApproximateMemoryUsage() includes memory used by block kv
793
+ // checksum.
794
+ const int kNumRecords = 20;
795
+ std::vector<std::string> keys;
796
+ std::vector<std::string> values;
797
+ GenerateRandomKVs(&keys, &values, 0, kNumRecords, 1 /* step */,
798
+ 24 /* padding_size */);
799
+ std::unique_ptr<BlockBuilder> builder;
800
+ auto generate_block_content = [&]() {
801
+ builder = std::make_unique<BlockBuilder>(16 /* restart_interval */);
802
+ for (int i = 0; i < kNumRecords; ++i) {
803
+ builder->Add(keys[i], values[i]);
804
+ }
805
+ Slice raw_block = builder->Finish();
806
+ BlockContents contents;
807
+ contents.data = raw_block;
808
+ return contents;
809
+ };
810
+
811
+ Options options = Options();
812
+ BlockBasedTableOptions tbo;
813
+ uint8_t protection_bytes_per_key = 8;
814
+ BlockCreateContext with_checksum_create_context{
815
+ &tbo,
816
+ nullptr /* statistics */,
817
+ false /* using_zstd */,
818
+ protection_bytes_per_key,
819
+ options.comparator,
820
+ true /* index_value_is_full */};
821
+ BlockCreateContext create_context{
822
+ &tbo, nullptr /* statistics */, false /* using_zstd */,
823
+ 0, options.comparator, true /* index_value_is_full */};
824
+
825
+ {
826
+ std::unique_ptr<Block_kData> data_block;
827
+ create_context.Create(&data_block, generate_block_content());
828
+ size_t block_memory = data_block->ApproximateMemoryUsage();
829
+ std::unique_ptr<Block_kData> with_checksum_data_block;
830
+ with_checksum_create_context.Create(&with_checksum_data_block,
831
+ generate_block_content());
832
+ ASSERT_GT(with_checksum_data_block->ApproximateMemoryUsage() - block_memory,
833
+ 100);
834
+ }
835
+
836
+ {
837
+ std::unique_ptr<Block_kData> meta_block;
838
+ create_context.Create(&meta_block, generate_block_content());
839
+ size_t block_memory = meta_block->ApproximateMemoryUsage();
840
+ std::unique_ptr<Block_kData> with_checksum_meta_block;
841
+ with_checksum_create_context.Create(&with_checksum_meta_block,
842
+ generate_block_content());
843
+ // Rough comparison to avoid flaky test due to memory allocation alignment.
844
+ ASSERT_GT(with_checksum_meta_block->ApproximateMemoryUsage() - block_memory,
845
+ 100);
846
+ }
847
+
848
+ {
849
+ // Index block has different contents.
850
+ std::vector<std::string> separators;
851
+ std::vector<BlockHandle> block_handles;
852
+ std::vector<std::string> first_keys;
853
+ GenerateRandomIndexEntries(&separators, &block_handles, &first_keys,
854
+ kNumRecords);
855
+ auto generate_index_content = [&]() {
856
+ builder = std::make_unique<BlockBuilder>(16 /* restart_interval */);
857
+ BlockHandle last_encoded_handle;
858
+ for (int i = 0; i < kNumRecords; ++i) {
859
+ IndexValue entry(block_handles[i], first_keys[i]);
860
+ std::string encoded_entry;
861
+ std::string delta_encoded_entry;
862
+ entry.EncodeTo(&encoded_entry, false, nullptr);
863
+ last_encoded_handle = entry.handle;
864
+ const Slice delta_encoded_entry_slice(delta_encoded_entry);
865
+ builder->Add(separators[i], encoded_entry, &delta_encoded_entry_slice);
866
+ }
867
+ Slice raw_block = builder->Finish();
868
+ BlockContents contents;
869
+ contents.data = raw_block;
870
+ return contents;
871
+ };
872
+
873
+ std::unique_ptr<Block_kIndex> index_block;
874
+ create_context.Create(&index_block, generate_index_content());
875
+ size_t block_memory = index_block->ApproximateMemoryUsage();
876
+ std::unique_ptr<Block_kIndex> with_checksum_index_block;
877
+ with_checksum_create_context.Create(&with_checksum_index_block,
878
+ generate_index_content());
879
+ ASSERT_GT(
880
+ with_checksum_index_block->ApproximateMemoryUsage() - block_memory,
881
+ 100);
882
+ }
883
+ }
884
+
885
+ std::string GetDataBlockIndexTypeStr(
886
+ BlockBasedTableOptions::DataBlockIndexType t) {
887
+ return t == BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch
888
+ ? "BinarySearch"
889
+ : "BinaryAndHash";
890
+ }
891
+
892
+ class DataBlockKVChecksumTest
893
+ : public BlockPerKVChecksumTest,
894
+ public testing::WithParamInterface<std::tuple<
895
+ BlockBasedTableOptions::DataBlockIndexType,
896
+ uint8_t /* block_protection_bytes_per_key */,
897
+ uint32_t /* restart_interval*/, bool /* use_delta_encoding */>> {
898
+ public:
899
+ DataBlockKVChecksumTest() = default;
900
+
901
+ BlockBasedTableOptions::DataBlockIndexType GetDataBlockIndexType() const {
902
+ return std::get<0>(GetParam());
903
+ }
904
+ uint8_t GetChecksumLen() const { return std::get<1>(GetParam()); }
905
+ uint32_t GetRestartInterval() const { return std::get<2>(GetParam()); }
906
+ bool GetUseDeltaEncoding() const { return std::get<3>(GetParam()); }
907
+
908
+ std::unique_ptr<Block_kData> GenerateDataBlock(
909
+ std::vector<std::string> &keys, std::vector<std::string> &values,
910
+ int num_record) {
911
+ BlockBasedTableOptions tbo;
912
+ BlockCreateContext create_context{&tbo, nullptr /* statistics */,
913
+ false /* using_zstd */, GetChecksumLen(),
914
+ Options().comparator};
915
+ builder_ = std::make_unique<BlockBuilder>(
916
+ static_cast<int>(GetRestartInterval()),
917
+ GetUseDeltaEncoding() /* use_delta_encoding */,
918
+ false /* use_value_delta_encoding */, GetDataBlockIndexType());
919
+ for (int i = 0; i < num_record; i++) {
920
+ builder_->Add(keys[i], values[i]);
921
+ }
922
+ Slice raw_block = builder_->Finish();
923
+ BlockContents contents;
924
+ contents.data = raw_block;
925
+ std::unique_ptr<Block_kData> data_block;
926
+ create_context.Create(&data_block, std::move(contents));
927
+ return data_block;
928
+ }
929
+
930
+ std::unique_ptr<BlockBuilder> builder_;
931
+ };
932
+
933
+ INSTANTIATE_TEST_CASE_P(
934
+ P, DataBlockKVChecksumTest,
935
+ ::testing::Combine(
936
+ ::testing::Values(
937
+ BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch,
938
+ BlockBasedTableOptions::DataBlockIndexType::
939
+ kDataBlockBinaryAndHash),
940
+ ::testing::Values(0, 1, 2, 4, 8) /* protection_bytes_per_key */,
941
+ ::testing::Values(1, 2, 3, 8, 16) /* restart_interval */,
942
+ ::testing::Values(false, true)) /* delta_encoding */,
943
+ [](const testing::TestParamInfo<std::tuple<
944
+ BlockBasedTableOptions::DataBlockIndexType, uint8_t, uint32_t, bool>>
945
+ &args) {
946
+ std::ostringstream oss;
947
+ oss << GetDataBlockIndexTypeStr(std::get<0>(args.param))
948
+ << "ProtectionPerKey" << std::to_string(std::get<1>(args.param))
949
+ << "RestartInterval" << std::to_string(std::get<2>(args.param))
950
+ << "DeltaEncode" << std::to_string(std::get<3>(args.param));
951
+ return oss.str();
952
+ });
953
+
954
+ TEST_P(DataBlockKVChecksumTest, ChecksumConstructionAndVerification) {
955
+ uint8_t protection_bytes_per_key = GetChecksumLen();
956
+ std::vector<int> num_restart_intervals = {1, 16};
957
+ for (const auto num_restart_interval : num_restart_intervals) {
958
+ const int kNumRecords =
959
+ num_restart_interval * static_cast<int>(GetRestartInterval());
960
+ std::vector<std::string> keys;
961
+ std::vector<std::string> values;
962
+ GenerateRandomKVs(&keys, &values, 0, kNumRecords + 1, 1 /* step */,
963
+ 24 /* padding_size */);
964
+ SyncPoint::GetInstance()->DisableProcessing();
965
+ std::unique_ptr<Block_kData> data_block =
966
+ GenerateDataBlock(keys, values, kNumRecords);
967
+
968
+ const char *checksum_ptr = data_block->TEST_GetKVChecksum();
969
+ // Check checksum of correct length is generated
970
+ for (int i = 0; i < kNumRecords; i++) {
971
+ ASSERT_TRUE(VerifyChecksum(protection_bytes_per_key,
972
+ checksum_ptr + i * protection_bytes_per_key,
973
+ keys[i], values[i]));
974
+ }
975
+ std::vector<SequenceNumber> seqnos{kDisableGlobalSequenceNumber, 0};
976
+
977
+ // Could just use a boolean flag. Use a counter here just to keep open the
978
+ // possibility of checking the exact number of verifications in the future.
979
+ size_t verification_count = 0;
980
+ // The SyncPoint is placed before checking checksum_len == 0 in
981
+ // Block::VerifyChecksum(). So verification count is incremented even with
982
+ // protection_bytes_per_key = 0. No actual checksum computation is done in
983
+ // that case (see Block::VerifyChecksum()).
984
+ SyncPoint::GetInstance()->SetCallBack(
985
+ "Block::VerifyChecksum::checksum_len",
986
+ [&verification_count, protection_bytes_per_key](void *checksum_len) {
987
+ ASSERT_EQ((*static_cast<uint8_t *>(checksum_len)),
988
+ protection_bytes_per_key);
989
+ ++verification_count;
990
+ });
991
+ SyncPoint::GetInstance()->EnableProcessing();
992
+
993
+ for (const auto seqno : seqnos) {
994
+ std::unique_ptr<DataBlockIter> biter{
995
+ data_block->NewDataIterator(Options().comparator, seqno)};
996
+
997
+ // SeekForGet() some key that does not exist
998
+ biter->SeekForGet(keys[kNumRecords]);
999
+ TestIterateForward(biter, verification_count);
1000
+
1001
+ verification_count = 0;
1002
+ biter->SeekForGet(keys[kNumRecords / 2]);
1003
+ ASSERT_GE(verification_count, 1);
1004
+ TestIterateForward(biter, verification_count);
1005
+
1006
+ TestSeekToFirst(biter, verification_count);
1007
+ TestSeekToLast(biter, verification_count);
1008
+ TestSeekForPrev(biter, verification_count, keys[kNumRecords / 2]);
1009
+ TestSeek(biter, verification_count, keys[kNumRecords / 2]);
1010
+ }
1011
+ }
1012
+ }
1013
+
1014
+ class IndexBlockKVChecksumTest
1015
+ : public BlockPerKVChecksumTest,
1016
+ public testing::WithParamInterface<
1017
+ std::tuple<BlockBasedTableOptions::DataBlockIndexType, uint8_t,
1018
+ uint32_t, bool, bool>> {
1019
+ public:
1020
+ IndexBlockKVChecksumTest() = default;
1021
+
1022
+ BlockBasedTableOptions::DataBlockIndexType GetDataBlockIndexType() const {
1023
+ return std::get<0>(GetParam());
1024
+ }
1025
+ uint8_t GetChecksumLen() const { return std::get<1>(GetParam()); }
1026
+ uint32_t GetRestartInterval() const { return std::get<2>(GetParam()); }
1027
+ bool UseValueDeltaEncoding() const { return std::get<3>(GetParam()); }
1028
+ bool IncludeFirstKey() const { return std::get<4>(GetParam()); }
1029
+
1030
+ std::unique_ptr<Block_kIndex> GenerateIndexBlock(
1031
+ std::vector<std::string> &separators,
1032
+ std::vector<BlockHandle> &block_handles,
1033
+ std::vector<std::string> &first_keys, int num_record) {
1034
+ Options options = Options();
1035
+ BlockBasedTableOptions tbo;
1036
+ uint8_t protection_bytes_per_key = GetChecksumLen();
1037
+ BlockCreateContext create_context{
1038
+ &tbo,
1039
+ nullptr /* statistics */,
1040
+ false /* _using_zstd */,
1041
+ protection_bytes_per_key,
1042
+ options.comparator,
1043
+ !UseValueDeltaEncoding() /* value_is_full */,
1044
+ IncludeFirstKey()};
1045
+ builder_ = std::make_unique<BlockBuilder>(
1046
+ static_cast<int>(GetRestartInterval()), true /* use_delta_encoding */,
1047
+ UseValueDeltaEncoding() /* use_value_delta_encoding */,
1048
+ GetDataBlockIndexType());
1049
+ BlockHandle last_encoded_handle;
1050
+ for (int i = 0; i < num_record; i++) {
1051
+ IndexValue entry(block_handles[i], first_keys[i]);
1052
+ std::string encoded_entry;
1053
+ std::string delta_encoded_entry;
1054
+ entry.EncodeTo(&encoded_entry, IncludeFirstKey(), nullptr);
1055
+ if (UseValueDeltaEncoding() && i > 0) {
1056
+ entry.EncodeTo(&delta_encoded_entry, IncludeFirstKey(),
1057
+ &last_encoded_handle);
1058
+ }
1059
+
1060
+ last_encoded_handle = entry.handle;
1061
+ const Slice delta_encoded_entry_slice(delta_encoded_entry);
1062
+ builder_->Add(separators[i], encoded_entry, &delta_encoded_entry_slice);
1063
+ }
1064
+ // read serialized contents of the block
1065
+ Slice raw_block = builder_->Finish();
1066
+ // create block reader
1067
+ BlockContents contents;
1068
+ contents.data = raw_block;
1069
+ std::unique_ptr<Block_kIndex> index_block;
1070
+
1071
+ create_context.Create(&index_block, std::move(contents));
1072
+ return index_block;
1073
+ }
1074
+
1075
+ std::unique_ptr<BlockBuilder> builder_;
1076
+ };
1077
+
1078
+ INSTANTIATE_TEST_CASE_P(
1079
+ P, IndexBlockKVChecksumTest,
1080
+ ::testing::Combine(
1081
+ ::testing::Values(
1082
+ BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch,
1083
+ BlockBasedTableOptions::DataBlockIndexType::
1084
+ kDataBlockBinaryAndHash),
1085
+ ::testing::Values(0, 1, 2, 4, 8), ::testing::Values(1, 3, 8, 16),
1086
+ ::testing::Values(true, false), ::testing::Values(true, false)),
1087
+ [](const testing::TestParamInfo<
1088
+ std::tuple<BlockBasedTableOptions::DataBlockIndexType, uint8_t,
1089
+ uint32_t, bool, bool>> &args) {
1090
+ std::ostringstream oss;
1091
+ oss << GetDataBlockIndexTypeStr(std::get<0>(args.param)) << "ProtBytes"
1092
+ << std::to_string(std::get<1>(args.param)) << "RestartInterval"
1093
+ << std::to_string(std::get<2>(args.param)) << "ValueDeltaEncode"
1094
+ << std::to_string(std::get<3>(args.param)) << "IncludeFirstKey"
1095
+ << std::to_string(std::get<4>(args.param));
1096
+ return oss.str();
1097
+ });
1098
+
1099
+ TEST_P(IndexBlockKVChecksumTest, ChecksumConstructionAndVerification) {
1100
+ Options options = Options();
1101
+ uint8_t protection_bytes_per_key = GetChecksumLen();
1102
+ std::vector<int> num_restart_intervals = {1, 16};
1103
+ std::vector<SequenceNumber> seqnos{kDisableGlobalSequenceNumber, 10001};
1104
+
1105
+ for (const auto num_restart_interval : num_restart_intervals) {
1106
+ const int kNumRecords =
1107
+ num_restart_interval * static_cast<int>(GetRestartInterval());
1108
+ for (const auto seqno : seqnos) {
1109
+ std::vector<std::string> separators;
1110
+ std::vector<BlockHandle> block_handles;
1111
+ std::vector<std::string> first_keys;
1112
+ GenerateRandomIndexEntries(&separators, &block_handles, &first_keys,
1113
+ kNumRecords,
1114
+ seqno != kDisableGlobalSequenceNumber);
1115
+ SyncPoint::GetInstance()->DisableProcessing();
1116
+ std::unique_ptr<Block_kIndex> index_block = GenerateIndexBlock(
1117
+ separators, block_handles, first_keys, kNumRecords);
1118
+ IndexBlockIter *kNullIter = nullptr;
1119
+ Statistics *kNullStats = nullptr;
1120
+ // read contents of block sequentially
1121
+ std::unique_ptr<IndexBlockIter> biter{index_block->NewIndexIterator(
1122
+ options.comparator, seqno, kNullIter, kNullStats,
1123
+ true /* total_order_seek */, IncludeFirstKey() /* have_first_key */,
1124
+ true /* key_includes_seq */,
1125
+ !UseValueDeltaEncoding() /* value_is_full */,
1126
+ true /* block_contents_pinned */, nullptr /* prefix_index */)};
1127
+ biter->SeekToFirst();
1128
+ const char *checksum_ptr = index_block->TEST_GetKVChecksum();
1129
+ // Check checksum of correct length is generated
1130
+ for (int i = 0; i < kNumRecords; i++) {
1131
+ // Obtaining the actual content written as value to index block is not
1132
+ // trivial: delta-encoded value is only persisted when not at block
1133
+ // restart point and that keys share some byte (see more in
1134
+ // BlockBuilder::AddWithLastKeyImpl()). So here we just do verification
1135
+ // using value from iterator unlike tests for DataBlockIter or
1136
+ // MetaBlockIter.
1137
+ ASSERT_TRUE(VerifyChecksum(protection_bytes_per_key, checksum_ptr,
1138
+ biter->key(), biter->raw_value()));
1139
+ }
1140
+
1141
+ size_t verification_count = 0;
1142
+ // The SyncPoint is placed before checking checksum_len == 0 in
1143
+ // Block::VerifyChecksum(). To make the testing code below simpler and not
1144
+ // having to differentiate 0 vs non-0 checksum_len, we do an explicit
1145
+ // assert checking on checksum_len here.
1146
+ SyncPoint::GetInstance()->SetCallBack(
1147
+ "Block::VerifyChecksum::checksum_len",
1148
+ [&verification_count, protection_bytes_per_key](void *checksum_len) {
1149
+ ASSERT_EQ((*static_cast<uint8_t *>(checksum_len)),
1150
+ protection_bytes_per_key);
1151
+ ++verification_count;
1152
+ });
1153
+ SyncPoint::GetInstance()->EnableProcessing();
1154
+
1155
+ TestSeekToFirst(biter, verification_count);
1156
+ TestSeekToLast(biter, verification_count);
1157
+ TestSeek(biter, verification_count, first_keys[kNumRecords / 2]);
1158
+ }
1159
+ }
1160
+ }
1161
+
1162
+ class MetaIndexBlockKVChecksumTest
1163
+ : public BlockPerKVChecksumTest,
1164
+ public testing::WithParamInterface<
1165
+ uint8_t /* block_protection_bytes_per_key */> {
1166
+ public:
1167
+ MetaIndexBlockKVChecksumTest() = default;
1168
+ uint8_t GetChecksumLen() const { return GetParam(); }
1169
+ uint32_t GetRestartInterval() const { return 1; }
1170
+
1171
+ std::unique_ptr<Block_kMetaIndex> GenerateMetaIndexBlock(
1172
+ std::vector<std::string> &keys, std::vector<std::string> &values,
1173
+ int num_record) {
1174
+ Options options = Options();
1175
+ BlockBasedTableOptions tbo;
1176
+ uint8_t protection_bytes_per_key = GetChecksumLen();
1177
+ BlockCreateContext create_context{
1178
+ &tbo, nullptr /* statistics */, false /* using_zstd */,
1179
+ protection_bytes_per_key, options.comparator};
1180
+ builder_ =
1181
+ std::make_unique<BlockBuilder>(static_cast<int>(GetRestartInterval()));
1182
+ // add a bunch of records to a block
1183
+ for (int i = 0; i < num_record; i++) {
1184
+ builder_->Add(keys[i], values[i]);
1185
+ }
1186
+ Slice raw_block = builder_->Finish();
1187
+ BlockContents contents;
1188
+ contents.data = raw_block;
1189
+ std::unique_ptr<Block_kMetaIndex> meta_block;
1190
+ create_context.Create(&meta_block, std::move(contents));
1191
+ return meta_block;
1192
+ }
1193
+
1194
+ std::unique_ptr<BlockBuilder> builder_;
1195
+ };
1196
+
1197
+ INSTANTIATE_TEST_CASE_P(P, MetaIndexBlockKVChecksumTest,
1198
+ ::testing::Values(0, 1, 2, 4, 8),
1199
+ [](const testing::TestParamInfo<uint8_t> &args) {
1200
+ std::ostringstream oss;
1201
+ oss << "ProtBytes" << std::to_string(args.param);
1202
+ return oss.str();
1203
+ });
1204
+
1205
+ TEST_P(MetaIndexBlockKVChecksumTest, ChecksumConstructionAndVerification) {
1206
+ Options options = Options();
1207
+ BlockBasedTableOptions tbo;
1208
+ uint8_t protection_bytes_per_key = GetChecksumLen();
1209
+ BlockCreateContext create_context{
1210
+ &tbo, nullptr /* statistics */, false /* using_zstd */,
1211
+ protection_bytes_per_key, options.comparator};
1212
+ std::vector<int> num_restart_intervals = {1, 16};
1213
+ for (const auto num_restart_interval : num_restart_intervals) {
1214
+ const int kNumRecords = num_restart_interval * GetRestartInterval();
1215
+ std::vector<std::string> keys;
1216
+ std::vector<std::string> values;
1217
+ GenerateRandomKVs(&keys, &values, 0, kNumRecords + 1, 1 /* step */,
1218
+ 24 /* padding_size */);
1219
+ SyncPoint::GetInstance()->DisableProcessing();
1220
+ std::unique_ptr<Block_kMetaIndex> meta_block =
1221
+ GenerateMetaIndexBlock(keys, values, kNumRecords);
1222
+ const char *checksum_ptr = meta_block->TEST_GetKVChecksum();
1223
+ // Check checksum of correct length is generated
1224
+ for (int i = 0; i < kNumRecords; i++) {
1225
+ ASSERT_TRUE(VerifyChecksum(protection_bytes_per_key,
1226
+ checksum_ptr + i * protection_bytes_per_key,
1227
+ keys[i], values[i]));
1228
+ }
1229
+
1230
+ size_t verification_count = 0;
1231
+ // The SyncPoint is placed before checking checksum_len == 0 in
1232
+ // Block::VerifyChecksum(). To make the testing code below simpler and not
1233
+ // having to differentiate 0 vs non-0 checksum_len, we do an explicit assert
1234
+ // checking on checksum_len here.
1235
+ SyncPoint::GetInstance()->SetCallBack(
1236
+ "Block::VerifyChecksum::checksum_len",
1237
+ [&verification_count, protection_bytes_per_key](void *checksum_len) {
1238
+ ASSERT_EQ((*static_cast<uint8_t *>(checksum_len)),
1239
+ protection_bytes_per_key);
1240
+ ++verification_count;
1241
+ });
1242
+ SyncPoint::GetInstance()->EnableProcessing();
1243
+ // Check that block iterator does checksum verification
1244
+ std::unique_ptr<MetaBlockIter> biter{
1245
+ meta_block->NewMetaIterator(true /* block_contents_pinned */)};
1246
+ TestSeekToFirst(biter, verification_count);
1247
+ TestSeekToLast(biter, verification_count);
1248
+ TestSeek(biter, verification_count, keys[kNumRecords / 2]);
1249
+ TestSeekForPrev(biter, verification_count, keys[kNumRecords / 2]);
1250
+ }
1251
+ }
1252
+
1253
+ class DataBlockKVChecksumCorruptionTest : public DataBlockKVChecksumTest {
1254
+ public:
1255
+ DataBlockKVChecksumCorruptionTest() = default;
1256
+
1257
+ std::unique_ptr<DataBlockIter> GenerateDataBlockIter(
1258
+ std::vector<std::string> &keys, std::vector<std::string> &values,
1259
+ int num_record) {
1260
+ // During Block construction, we may create block iter to initialize per kv
1261
+ // checksum. Disable syncpoint that may be created for block iter methods.
1262
+ SyncPoint::GetInstance()->DisableProcessing();
1263
+ block_ = GenerateDataBlock(keys, values, num_record);
1264
+ std::unique_ptr<DataBlockIter> biter{block_->NewDataIterator(
1265
+ Options().comparator, kDisableGlobalSequenceNumber)};
1266
+ SyncPoint::GetInstance()->EnableProcessing();
1267
+ return biter;
1268
+ }
1269
+
1270
+ protected:
1271
+ std::unique_ptr<Block_kData> block_;
1272
+ };
1273
+
1274
+ TEST_P(DataBlockKVChecksumCorruptionTest, CorruptEntry) {
1275
+ std::vector<int> num_restart_intervals = {1, 3};
1276
+ for (const auto num_restart_interval : num_restart_intervals) {
1277
+ const int kNumRecords =
1278
+ num_restart_interval * static_cast<int>(GetRestartInterval());
1279
+ std::vector<std::string> keys;
1280
+ std::vector<std::string> values;
1281
+ GenerateRandomKVs(&keys, &values, 0, kNumRecords + 1, 1 /* step */,
1282
+ 24 /* padding_size */);
1283
+ SyncPoint::GetInstance()->SetCallBack(
1284
+ "BlockIter::UpdateKey::value", [](void *arg) {
1285
+ char *value = static_cast<char *>(arg);
1286
+ // values generated by GenerateRandomKVs are of length 100
1287
+ ++value[10];
1288
+ });
1289
+
1290
+ // Purely for reducing the number of lines of code.
1291
+ typedef std::unique_ptr<DataBlockIter> IterPtr;
1292
+ typedef void(IterAPI)(IterPtr & iter, std::string &);
1293
+
1294
+ std::string seek_key = keys[kNumRecords / 2];
1295
+ auto test_seek = [&](IterAPI iter_api) {
1296
+ IterPtr biter = GenerateDataBlockIter(keys, values, kNumRecords);
1297
+ ASSERT_OK(biter->status());
1298
+ iter_api(biter, seek_key);
1299
+ ASSERT_FALSE(biter->Valid());
1300
+ ASSERT_TRUE(biter->status().IsCorruption());
1301
+ };
1302
+
1303
+ test_seek([](IterPtr &iter, std::string &) { iter->SeekToFirst(); });
1304
+ test_seek([](IterPtr &iter, std::string &) { iter->SeekToLast(); });
1305
+ test_seek([](IterPtr &iter, std::string &k) { iter->Seek(k); });
1306
+ test_seek([](IterPtr &iter, std::string &k) { iter->SeekForPrev(k); });
1307
+ test_seek([](IterPtr &iter, std::string &k) { iter->SeekForGet(k); });
1308
+
1309
+ typedef void (DataBlockIter::*IterStepAPI)();
1310
+ auto test_step = [&](IterStepAPI iter_api, std::string &k) {
1311
+ IterPtr biter = GenerateDataBlockIter(keys, values, kNumRecords);
1312
+ SyncPoint::GetInstance()->DisableProcessing();
1313
+ biter->Seek(k);
1314
+ ASSERT_TRUE(biter->Valid());
1315
+ ASSERT_OK(biter->status());
1316
+ SyncPoint::GetInstance()->EnableProcessing();
1317
+ std::invoke(iter_api, biter);
1318
+ ASSERT_FALSE(biter->Valid());
1319
+ ASSERT_TRUE(biter->status().IsCorruption());
1320
+ };
1321
+
1322
+ if (kNumRecords > 1) {
1323
+ test_step(&DataBlockIter::Prev, seek_key);
1324
+ test_step(&DataBlockIter::Next, seek_key);
1325
+ }
1326
+ }
1327
+ }
1328
+
1329
+ INSTANTIATE_TEST_CASE_P(
1330
+ P, DataBlockKVChecksumCorruptionTest,
1331
+ ::testing::Combine(
1332
+ ::testing::Values(
1333
+ BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch,
1334
+ BlockBasedTableOptions::DataBlockIndexType::
1335
+ kDataBlockBinaryAndHash),
1336
+ ::testing::Values(4, 8) /* block_protection_bytes_per_key */,
1337
+ ::testing::Values(1, 3, 8, 16) /* restart_interval */,
1338
+ ::testing::Values(false, true)),
1339
+ [](const testing::TestParamInfo<std::tuple<
1340
+ BlockBasedTableOptions::DataBlockIndexType, uint8_t, uint32_t, bool>>
1341
+ &args) {
1342
+ std::ostringstream oss;
1343
+ oss << GetDataBlockIndexTypeStr(std::get<0>(args.param)) << "ProtBytes"
1344
+ << std::to_string(std::get<1>(args.param)) << "RestartInterval"
1345
+ << std::to_string(std::get<2>(args.param)) << "DeltaEncode"
1346
+ << std::to_string(std::get<3>(args.param));
1347
+ return oss.str();
1348
+ });
1349
+
1350
+ class IndexBlockKVChecksumCorruptionTest : public IndexBlockKVChecksumTest {
1351
+ public:
1352
+ IndexBlockKVChecksumCorruptionTest() = default;
1353
+
1354
+ std::unique_ptr<IndexBlockIter> GenerateIndexBlockIter(
1355
+ std::vector<std::string> &separators,
1356
+ std::vector<BlockHandle> &block_handles,
1357
+ std::vector<std::string> &first_keys, int num_record,
1358
+ SequenceNumber seqno) {
1359
+ SyncPoint::GetInstance()->DisableProcessing();
1360
+ block_ =
1361
+ GenerateIndexBlock(separators, block_handles, first_keys, num_record);
1362
+ std::unique_ptr<IndexBlockIter> biter{block_->NewIndexIterator(
1363
+ Options().comparator, seqno, nullptr, nullptr,
1364
+ true /* total_order_seek */, IncludeFirstKey() /* have_first_key */,
1365
+ true /* key_includes_seq */,
1366
+ !UseValueDeltaEncoding() /* value_is_full */,
1367
+ true /* block_contents_pinned */, nullptr /* prefix_index */)};
1368
+ SyncPoint::GetInstance()->EnableProcessing();
1369
+ return biter;
1370
+ }
1371
+
1372
+ protected:
1373
+ std::unique_ptr<Block_kIndex> block_;
1374
+ };
1375
+
1376
+ INSTANTIATE_TEST_CASE_P(
1377
+ P, IndexBlockKVChecksumCorruptionTest,
1378
+ ::testing::Combine(
1379
+ ::testing::Values(
1380
+ BlockBasedTableOptions::DataBlockIndexType::kDataBlockBinarySearch,
1381
+ BlockBasedTableOptions::DataBlockIndexType::
1382
+ kDataBlockBinaryAndHash),
1383
+ ::testing::Values(4, 8) /* block_protection_bytes_per_key */,
1384
+ ::testing::Values(1, 3, 8, 16) /* restart_interval */,
1385
+ ::testing::Values(true, false), ::testing::Values(true, false)),
1386
+ [](const testing::TestParamInfo<
1387
+ std::tuple<BlockBasedTableOptions::DataBlockIndexType, uint8_t,
1388
+ uint32_t, bool, bool>> &args) {
1389
+ std::ostringstream oss;
1390
+ oss << GetDataBlockIndexTypeStr(std::get<0>(args.param)) << "ProtBytes"
1391
+ << std::to_string(std::get<1>(args.param)) << "RestartInterval"
1392
+ << std::to_string(std::get<2>(args.param)) << "ValueDeltaEncode"
1393
+ << std::to_string(std::get<3>(args.param)) << "IncludeFirstKey"
1394
+ << std::to_string(std::get<4>(args.param));
1395
+ return oss.str();
1396
+ });
1397
+
1398
+ TEST_P(IndexBlockKVChecksumCorruptionTest, CorruptEntry) {
1399
+ std::vector<int> num_restart_intervals = {1, 3};
1400
+ std::vector<SequenceNumber> seqnos{kDisableGlobalSequenceNumber, 10001};
1401
+
1402
+ for (const auto num_restart_interval : num_restart_intervals) {
1403
+ const int kNumRecords =
1404
+ num_restart_interval * static_cast<int>(GetRestartInterval());
1405
+ for (const auto seqno : seqnos) {
1406
+ std::vector<std::string> separators;
1407
+ std::vector<BlockHandle> block_handles;
1408
+ std::vector<std::string> first_keys;
1409
+ GenerateRandomIndexEntries(&separators, &block_handles, &first_keys,
1410
+ kNumRecords,
1411
+ seqno != kDisableGlobalSequenceNumber);
1412
+ SyncPoint::GetInstance()->SetCallBack(
1413
+ "BlockIter::UpdateKey::value", [](void *arg) {
1414
+ char *value = static_cast<char *>(arg);
1415
+ // value can be delta-encoded with different lengths, so we corrupt
1416
+ // first bytes here to be safe
1417
+ ++value[0];
1418
+ });
1419
+
1420
+ typedef std::unique_ptr<IndexBlockIter> IterPtr;
1421
+ typedef void(IterAPI)(IterPtr & iter, std::string &);
1422
+ std::string seek_key = first_keys[kNumRecords / 2];
1423
+ auto test_seek = [&](IterAPI iter_api) {
1424
+ std::unique_ptr<IndexBlockIter> biter = GenerateIndexBlockIter(
1425
+ separators, block_handles, first_keys, kNumRecords, seqno);
1426
+ ASSERT_OK(biter->status());
1427
+ iter_api(biter, seek_key);
1428
+ ASSERT_FALSE(biter->Valid());
1429
+ ASSERT_TRUE(biter->status().IsCorruption());
1430
+ };
1431
+ test_seek([](IterPtr &iter, std::string &) { iter->SeekToFirst(); });
1432
+ test_seek([](IterPtr &iter, std::string &) { iter->SeekToLast(); });
1433
+ test_seek([](IterPtr &iter, std::string &k) { iter->Seek(k); });
1434
+
1435
+ typedef void (IndexBlockIter::*IterStepAPI)();
1436
+ auto test_step = [&](IterStepAPI iter_api, std::string &k) {
1437
+ std::unique_ptr<IndexBlockIter> biter = GenerateIndexBlockIter(
1438
+ separators, block_handles, first_keys, kNumRecords, seqno);
1439
+ SyncPoint::GetInstance()->DisableProcessing();
1440
+ biter->Seek(k);
1441
+ ASSERT_TRUE(biter->Valid());
1442
+ ASSERT_OK(biter->status());
1443
+ SyncPoint::GetInstance()->EnableProcessing();
1444
+ std::invoke(iter_api, biter);
1445
+ ASSERT_FALSE(biter->Valid());
1446
+ ASSERT_TRUE(biter->status().IsCorruption());
1447
+ };
1448
+ if (kNumRecords > 1) {
1449
+ test_step(&IndexBlockIter::Prev, seek_key);
1450
+ test_step(&IndexBlockIter::Next, seek_key);
1451
+ }
1452
+ }
1453
+ }
1454
+ }
1455
+
1456
+ class MetaIndexBlockKVChecksumCorruptionTest
1457
+ : public MetaIndexBlockKVChecksumTest {
1458
+ public:
1459
+ MetaIndexBlockKVChecksumCorruptionTest() = default;
1460
+
1461
+ std::unique_ptr<MetaBlockIter> GenerateMetaIndexBlockIter(
1462
+ std::vector<std::string> &keys, std::vector<std::string> &values,
1463
+ int num_record) {
1464
+ SyncPoint::GetInstance()->DisableProcessing();
1465
+ block_ = GenerateMetaIndexBlock(keys, values, num_record);
1466
+ std::unique_ptr<MetaBlockIter> biter{
1467
+ block_->NewMetaIterator(true /* block_contents_pinned */)};
1468
+ SyncPoint::GetInstance()->EnableProcessing();
1469
+ return biter;
1470
+ }
1471
+
1472
+ protected:
1473
+ std::unique_ptr<Block_kMetaIndex> block_;
1474
+ };
1475
+
1476
+ INSTANTIATE_TEST_CASE_P(
1477
+ P, MetaIndexBlockKVChecksumCorruptionTest,
1478
+ ::testing::Values(4, 8) /* block_protection_bytes_per_key */,
1479
+ [](const testing::TestParamInfo<uint8_t> &args) {
1480
+ std::ostringstream oss;
1481
+ oss << "ProtBytes" << std::to_string(args.param);
1482
+ return oss.str();
1483
+ });
1484
+
1485
+ TEST_P(MetaIndexBlockKVChecksumCorruptionTest, CorruptEntry) {
1486
+ Options options = Options();
1487
+ std::vector<int> num_restart_intervals = {1, 3};
1488
+ for (const auto num_restart_interval : num_restart_intervals) {
1489
+ const int kNumRecords =
1490
+ num_restart_interval * static_cast<int>(GetRestartInterval());
1491
+ std::vector<std::string> keys;
1492
+ std::vector<std::string> values;
1493
+ GenerateRandomKVs(&keys, &values, 0, kNumRecords + 1, 1 /* step */,
1494
+ 24 /* padding_size */);
1495
+ SyncPoint::GetInstance()->SetCallBack(
1496
+ "BlockIter::UpdateKey::value", [](void *arg) {
1497
+ char *value = static_cast<char *>(arg);
1498
+ // values generated by GenerateRandomKVs are of length 100
1499
+ ++value[10];
1500
+ });
1501
+
1502
+ typedef std::unique_ptr<MetaBlockIter> IterPtr;
1503
+ typedef void(IterAPI)(IterPtr & iter, std::string &);
1504
+ typedef void (MetaBlockIter::*IterStepAPI)();
1505
+ std::string seek_key = keys[kNumRecords / 2];
1506
+ auto test_seek = [&](IterAPI iter_api) {
1507
+ IterPtr biter = GenerateMetaIndexBlockIter(keys, values, kNumRecords);
1508
+ ASSERT_OK(biter->status());
1509
+ iter_api(biter, seek_key);
1510
+ ASSERT_FALSE(biter->Valid());
1511
+ ASSERT_TRUE(biter->status().IsCorruption());
1512
+ };
1513
+
1514
+ test_seek([](IterPtr &iter, std::string &) { iter->SeekToFirst(); });
1515
+ test_seek([](IterPtr &iter, std::string &) { iter->SeekToLast(); });
1516
+ test_seek([](IterPtr &iter, std::string &k) { iter->Seek(k); });
1517
+ test_seek([](IterPtr &iter, std::string &k) { iter->SeekForPrev(k); });
1518
+
1519
+ auto test_step = [&](IterStepAPI iter_api, const std::string &k) {
1520
+ IterPtr biter = GenerateMetaIndexBlockIter(keys, values, kNumRecords);
1521
+ SyncPoint::GetInstance()->DisableProcessing();
1522
+ biter->Seek(k);
1523
+ ASSERT_TRUE(biter->Valid());
1524
+ ASSERT_OK(biter->status());
1525
+ SyncPoint::GetInstance()->EnableProcessing();
1526
+ std::invoke(iter_api, biter);
1527
+ ASSERT_FALSE(biter->Valid());
1528
+ ASSERT_TRUE(biter->status().IsCorruption());
1529
+ };
1530
+
1531
+ if (kNumRecords > 1) {
1532
+ test_step(&MetaBlockIter::Prev, seek_key);
1533
+ test_step(&MetaBlockIter::Next, seek_key);
1534
+ }
1535
+ }
1536
+ }
621
1537
  } // namespace ROCKSDB_NAMESPACE
622
1538
 
623
1539
  int main(int argc, char **argv) {