@nxtedition/rocksdb 13.5.13 → 15.0.1

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 (232) hide show
  1. package/binding.cc +55 -180
  2. package/binding.gyp +2 -2
  3. package/chained-batch.js +9 -16
  4. package/deps/rocksdb/rocksdb/BUCK +18 -1
  5. package/deps/rocksdb/rocksdb/CMakeLists.txt +10 -3
  6. package/deps/rocksdb/rocksdb/Makefile +20 -9
  7. package/deps/rocksdb/rocksdb/cache/cache_bench_tool.cc +90 -13
  8. package/deps/rocksdb/rocksdb/cache/clock_cache.cc +88 -75
  9. package/deps/rocksdb/rocksdb/cache/clock_cache.h +44 -36
  10. package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.cc +184 -148
  11. package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.h +5 -11
  12. package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache_test.cc +116 -47
  13. package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +1 -1
  14. package/deps/rocksdb/rocksdb/cache/secondary_cache_adapter.cc +3 -6
  15. package/deps/rocksdb/rocksdb/db/arena_wrapped_db_iter.h +1 -1
  16. package/deps/rocksdb/rocksdb/db/builder.cc +4 -2
  17. package/deps/rocksdb/rocksdb/db/c.cc +207 -0
  18. package/deps/rocksdb/rocksdb/db/c_test.c +72 -0
  19. package/deps/rocksdb/rocksdb/db/column_family.cc +3 -2
  20. package/deps/rocksdb/rocksdb/db/column_family.h +5 -0
  21. package/deps/rocksdb/rocksdb/db/compact_files_test.cc +4 -0
  22. package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +2 -0
  23. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +51 -38
  24. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.h +29 -12
  25. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator_test.cc +5 -10
  26. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +566 -366
  27. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +131 -4
  28. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +1 -0
  29. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.h +7 -0
  30. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.cc +4 -4
  31. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.h +13 -14
  32. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.cc +12 -7
  33. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.h +8 -10
  34. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +97 -76
  35. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +11 -14
  36. package/deps/rocksdb/rocksdb/db/compaction/compaction_service_job.cc +1 -1
  37. package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.h +8 -0
  38. package/deps/rocksdb/rocksdb/db/compaction/tiered_compaction_test.cc +16 -3
  39. package/deps/rocksdb/rocksdb/db/db_basic_test.cc +1 -0
  40. package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +448 -1
  41. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +22 -20
  42. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +4 -1
  43. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +5 -5
  44. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +7 -3
  45. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.cc +1 -1
  46. package/deps/rocksdb/rocksdb/db/db_iter.cc +104 -0
  47. package/deps/rocksdb/rocksdb/db/db_iter.h +4 -11
  48. package/deps/rocksdb/rocksdb/db/db_iterator_test.cc +331 -58
  49. package/deps/rocksdb/rocksdb/db/db_memtable_test.cc +129 -0
  50. package/deps/rocksdb/rocksdb/db/db_sst_test.cc +64 -0
  51. package/deps/rocksdb/rocksdb/db/db_table_properties_test.cc +40 -0
  52. package/deps/rocksdb/rocksdb/db/db_test2.cc +25 -15
  53. package/deps/rocksdb/rocksdb/db/db_test_util.cc +42 -24
  54. package/deps/rocksdb/rocksdb/db/db_test_util.h +29 -14
  55. package/deps/rocksdb/rocksdb/db/db_universal_compaction_test.cc +69 -36
  56. package/deps/rocksdb/rocksdb/db/db_with_timestamp_basic_test.cc +0 -1
  57. package/deps/rocksdb/rocksdb/db/event_helpers.cc +1 -0
  58. package/deps/rocksdb/rocksdb/db/experimental.cc +5 -4
  59. package/deps/rocksdb/rocksdb/db/external_sst_file_basic_test.cc +8 -1
  60. package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +275 -79
  61. package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.h +23 -5
  62. package/deps/rocksdb/rocksdb/db/external_sst_file_test.cc +591 -175
  63. package/deps/rocksdb/rocksdb/db/flush_job.cc +3 -4
  64. package/deps/rocksdb/rocksdb/db/log_reader.cc +5 -2
  65. package/deps/rocksdb/rocksdb/db/memtable.cc +84 -35
  66. package/deps/rocksdb/rocksdb/db/memtable.h +39 -34
  67. package/deps/rocksdb/rocksdb/db/merge_helper.cc +1 -0
  68. package/deps/rocksdb/rocksdb/db/merge_operator.cc +1 -1
  69. package/deps/rocksdb/rocksdb/db/multi_scan.cc +11 -5
  70. package/deps/rocksdb/rocksdb/db/version_edit.cc +1 -1
  71. package/deps/rocksdb/rocksdb/db/version_edit.h +1 -1
  72. package/deps/rocksdb/rocksdb/db/version_edit_handler.cc +34 -14
  73. package/deps/rocksdb/rocksdb/db/version_edit_handler.h +28 -5
  74. package/deps/rocksdb/rocksdb/db/version_set.cc +159 -14
  75. package/deps/rocksdb/rocksdb/db/version_set.h +2 -0
  76. package/deps/rocksdb/rocksdb/db_stress_tool/CMakeLists.txt +1 -1
  77. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.cc +60 -0
  78. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +16 -1
  79. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_compaction_service.h +75 -10
  80. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_compression_manager.cc +28 -0
  81. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_compression_manager.h +2 -0
  82. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_driver.cc +31 -1
  83. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +50 -2
  84. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_shared_state.h +57 -0
  85. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_stat.h +0 -4
  86. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +266 -35
  87. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.h +5 -0
  88. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_tool.cc +0 -6
  89. package/deps/rocksdb/rocksdb/db_stress_tool/no_batched_ops_stress.cc +18 -2
  90. package/deps/rocksdb/rocksdb/env/env.cc +12 -0
  91. package/deps/rocksdb/rocksdb/env/env_test.cc +18 -0
  92. package/deps/rocksdb/rocksdb/env/file_system_tracer.cc +2 -0
  93. package/deps/rocksdb/rocksdb/env/fs_posix.cc +9 -5
  94. package/deps/rocksdb/rocksdb/env/io_posix.cc +4 -2
  95. package/deps/rocksdb/rocksdb/file/random_access_file_reader.cc +19 -0
  96. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_compression.h +33 -31
  97. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +42 -9
  98. package/deps/rocksdb/rocksdb/include/rocksdb/c.h +93 -0
  99. package/deps/rocksdb/rocksdb/include/rocksdb/cache.h +43 -49
  100. package/deps/rocksdb/rocksdb/include/rocksdb/compaction_job_stats.h +4 -3
  101. package/deps/rocksdb/rocksdb/include/rocksdb/compression_type.h +8 -6
  102. package/deps/rocksdb/rocksdb/include/rocksdb/data_structure.h +487 -0
  103. package/deps/rocksdb/rocksdb/include/rocksdb/db.h +11 -12
  104. package/deps/rocksdb/rocksdb/include/rocksdb/env.h +135 -1
  105. package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +5 -0
  106. package/deps/rocksdb/rocksdb/include/rocksdb/iostats_context.h +12 -0
  107. package/deps/rocksdb/rocksdb/include/rocksdb/iterator.h +1 -1
  108. package/deps/rocksdb/rocksdb/include/rocksdb/ldb_tool.h +8 -0
  109. package/deps/rocksdb/rocksdb/include/rocksdb/memtablerep.h +12 -8
  110. package/deps/rocksdb/rocksdb/include/rocksdb/metadata.h +3 -0
  111. package/deps/rocksdb/rocksdb/include/rocksdb/multi_scan.h +19 -9
  112. package/deps/rocksdb/rocksdb/include/rocksdb/options.h +219 -24
  113. package/deps/rocksdb/rocksdb/include/rocksdb/point_lock_bench_tool.h +14 -0
  114. package/deps/rocksdb/rocksdb/include/rocksdb/secondary_cache.h +2 -2
  115. package/deps/rocksdb/rocksdb/include/rocksdb/slice.h +1 -1
  116. package/deps/rocksdb/rocksdb/include/rocksdb/statistics.h +7 -0
  117. package/deps/rocksdb/rocksdb/include/rocksdb/status.h +16 -0
  118. package/deps/rocksdb/rocksdb/include/rocksdb/table.h +16 -4
  119. package/deps/rocksdb/rocksdb/include/rocksdb/table_properties.h +13 -0
  120. package/deps/rocksdb/rocksdb/include/rocksdb/types.h +4 -0
  121. package/deps/rocksdb/rocksdb/include/rocksdb/universal_compaction.h +0 -2
  122. package/deps/rocksdb/rocksdb/include/rocksdb/user_defined_index.h +45 -0
  123. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/cache_dump_load.h +1 -1
  124. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +1 -1
  125. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/transaction.h +6 -1
  126. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/transaction_db.h +21 -0
  127. package/deps/rocksdb/rocksdb/include/rocksdb/version.h +2 -2
  128. package/deps/rocksdb/rocksdb/memory/memory_allocator_impl.h +3 -3
  129. package/deps/rocksdb/rocksdb/memtable/inlineskiplist.h +77 -51
  130. package/deps/rocksdb/rocksdb/memtable/skiplist.h +10 -13
  131. package/deps/rocksdb/rocksdb/memtable/skiplistrep.cc +16 -7
  132. package/deps/rocksdb/rocksdb/memtable/vectorrep.cc +9 -4
  133. package/deps/rocksdb/rocksdb/monitoring/iostats_context.cc +2 -0
  134. package/deps/rocksdb/rocksdb/monitoring/statistics.cc +6 -0
  135. package/deps/rocksdb/rocksdb/options/cf_options.cc +13 -1
  136. package/deps/rocksdb/rocksdb/options/cf_options.h +6 -2
  137. package/deps/rocksdb/rocksdb/options/options.cc +2 -0
  138. package/deps/rocksdb/rocksdb/options/options_helper.cc +9 -8
  139. package/deps/rocksdb/rocksdb/options/options_settable_test.cc +9 -5
  140. package/deps/rocksdb/rocksdb/port/mmap.cc +1 -1
  141. package/deps/rocksdb/rocksdb/port/win/xpress_win.cc +51 -0
  142. package/deps/rocksdb/rocksdb/port/win/xpress_win.h +4 -0
  143. package/deps/rocksdb/rocksdb/src.mk +8 -2
  144. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +1125 -765
  145. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.h +35 -24
  146. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.cc +29 -4
  147. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.cc +732 -256
  148. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.h +225 -16
  149. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +102 -26
  150. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +1 -1
  151. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_sync_and_async.h +2 -75
  152. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_test.cc +433 -141
  153. package/deps/rocksdb/rocksdb/table/block_based/block_builder.h +2 -0
  154. package/deps/rocksdb/rocksdb/table/block_based/flush_block_policy.cc +17 -10
  155. package/deps/rocksdb/rocksdb/table/block_based/flush_block_policy_impl.h +20 -0
  156. package/deps/rocksdb/rocksdb/table/block_based/index_builder.cc +112 -85
  157. package/deps/rocksdb/rocksdb/table/block_based/index_builder.h +191 -36
  158. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +2 -2
  159. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block_test.cc +1 -1
  160. package/deps/rocksdb/rocksdb/table/block_based/user_defined_index_wrapper.h +108 -31
  161. package/deps/rocksdb/rocksdb/table/external_table.cc +7 -3
  162. package/deps/rocksdb/rocksdb/table/format.cc +6 -12
  163. package/deps/rocksdb/rocksdb/table/format.h +10 -0
  164. package/deps/rocksdb/rocksdb/table/internal_iterator.h +1 -1
  165. package/deps/rocksdb/rocksdb/table/iterator_wrapper.h +1 -1
  166. package/deps/rocksdb/rocksdb/table/merging_iterator.cc +1 -1
  167. package/deps/rocksdb/rocksdb/table/meta_blocks.cc +5 -0
  168. package/deps/rocksdb/rocksdb/table/multiget_context.h +3 -1
  169. package/deps/rocksdb/rocksdb/table/sst_file_dumper.cc +118 -46
  170. package/deps/rocksdb/rocksdb/table/sst_file_dumper.h +9 -8
  171. package/deps/rocksdb/rocksdb/table/table_builder.h +5 -0
  172. package/deps/rocksdb/rocksdb/table/table_properties.cc +16 -0
  173. package/deps/rocksdb/rocksdb/table/table_test.cc +1540 -155
  174. package/deps/rocksdb/rocksdb/test_util/testutil.h +21 -5
  175. package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +26 -5
  176. package/deps/rocksdb/rocksdb/tools/ldb.cc +1 -2
  177. package/deps/rocksdb/rocksdb/tools/ldb_cmd.cc +2 -0
  178. package/deps/rocksdb/rocksdb/tools/ldb_tool.cc +9 -3
  179. package/deps/rocksdb/rocksdb/tools/sst_dump_test.cc +133 -165
  180. package/deps/rocksdb/rocksdb/tools/sst_dump_tool.cc +173 -64
  181. package/deps/rocksdb/rocksdb/util/aligned_buffer.h +69 -0
  182. package/deps/rocksdb/rocksdb/util/atomic.h +6 -0
  183. package/deps/rocksdb/rocksdb/util/auto_tune_compressor.cc +29 -20
  184. package/deps/rocksdb/rocksdb/util/auto_tune_compressor.h +10 -6
  185. package/deps/rocksdb/rocksdb/util/bit_fields.h +338 -0
  186. package/deps/rocksdb/rocksdb/util/coding.h +3 -3
  187. package/deps/rocksdb/rocksdb/util/compaction_job_stats_impl.cc +2 -2
  188. package/deps/rocksdb/rocksdb/util/compression.cc +777 -82
  189. package/deps/rocksdb/rocksdb/util/compression.h +5 -0
  190. package/deps/rocksdb/rocksdb/util/compression_test.cc +5 -3
  191. package/deps/rocksdb/rocksdb/util/dynamic_bloom.cc +2 -2
  192. package/deps/rocksdb/rocksdb/util/dynamic_bloom.h +15 -14
  193. package/deps/rocksdb/rocksdb/util/interval_test.cc +102 -0
  194. package/deps/rocksdb/rocksdb/util/semaphore.h +164 -0
  195. package/deps/rocksdb/rocksdb/util/simple_mixed_compressor.cc +10 -6
  196. package/deps/rocksdb/rocksdb/util/simple_mixed_compressor.h +4 -2
  197. package/deps/rocksdb/rocksdb/util/slice_test.cc +136 -0
  198. package/deps/rocksdb/rocksdb/util/status.cc +1 -0
  199. package/deps/rocksdb/rocksdb/util/string_util.cc +2 -16
  200. package/deps/rocksdb/rocksdb/utilities/cache_dump_load_impl.cc +1 -1
  201. package/deps/rocksdb/rocksdb/utilities/cache_dump_load_impl.h +1 -1
  202. package/deps/rocksdb/rocksdb/utilities/fault_injection_fs.cc +7 -4
  203. package/deps/rocksdb/rocksdb/utilities/fault_injection_fs.h +35 -14
  204. package/deps/rocksdb/rocksdb/utilities/persistent_cache/hash_table_test.cc +2 -0
  205. package/deps/rocksdb/rocksdb/utilities/transactions/lock/lock_manager.cc +5 -2
  206. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/any_lock_manager_test.h +244 -0
  207. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_bench.cc +18 -0
  208. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_bench_tool.cc +159 -0
  209. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager.cc +1244 -161
  210. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager.h +66 -12
  211. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager_stress_test.cc +103 -0
  212. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager_test.cc +1275 -8
  213. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager_test.h +40 -262
  214. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager_test_common.h +78 -0
  215. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_validation_test_runner.h +469 -0
  216. package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_locking_test.cc +2 -6
  217. package/deps/rocksdb/rocksdb/utilities/transactions/pessimistic_transaction.cc +4 -0
  218. package/deps/rocksdb/rocksdb/utilities/transactions/pessimistic_transaction.h +9 -1
  219. package/deps/rocksdb/rocksdb/utilities/transactions/timestamped_snapshot_test.cc +18 -9
  220. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_base.h +2 -0
  221. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_db_mutex_impl.cc +2 -1
  222. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.cc +72 -44
  223. package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.h +92 -15
  224. package/deps/rocksdb/rocksdb/utilities/transactions/write_committed_transaction_ts_test.cc +6 -20
  225. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_transaction_test.cc +143 -112
  226. package/deps/rocksdb/rocksdb/utilities/transactions/write_unprepared_transaction_test.cc +23 -16
  227. package/index.js +18 -42
  228. package/package.json +1 -1
  229. package/prebuilds/darwin-arm64/@nxtedition+rocksdb.node +0 -0
  230. package/prebuilds/linux-x64/@nxtedition+rocksdb.node +0 -0
  231. package/util.h +38 -12
  232. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_stat.cc +0 -17
@@ -18,6 +18,7 @@
18
18
  #include "rocksdb/comparator.h"
19
19
  #include "table/block_based/block_based_table_factory.h"
20
20
  #include "table/block_based/block_builder.h"
21
+ #include "table/block_based/flush_block_policy_impl.h"
21
22
  #include "table/format.h"
22
23
 
23
24
  namespace ROCKSDB_NAMESPACE {
@@ -76,6 +77,49 @@ class IndexBuilder {
76
77
  const BlockHandle& block_handle,
77
78
  std::string* separator_scratch) = 0;
78
79
 
80
+ // An abstract (extensible) holder for passing data from PrepareIndexEntry to
81
+ // FinishIndexEntry (see below).
82
+ struct PreparedIndexEntry {
83
+ virtual ~PreparedIndexEntry() = default;
84
+ };
85
+
86
+ // Parallel compression/construction alternative to AddIndexEntry, 1/3
87
+ //
88
+ // This function creates a holder for data that needs to be passed from
89
+ // PrepareIndexEntry to FinishIndexEntry, depending on the implementation
90
+ // of those. Few of these are created and reused, so construction/destruction
91
+ // performance is not critical.
92
+ virtual std::unique_ptr<PreparedIndexEntry> CreatePreparedIndexEntry() = 0;
93
+
94
+ // Parallel compression/construction alternative to AddIndexEntry, 2/3
95
+ //
96
+ // One thread calls this function for successive index entries to compute and
97
+ // record in `out` what is needed to build the index entry EXCEPT for the
98
+ // BlockHandle, which will only be known later. That thread is generally the
99
+ // same thread as calls every other function such as OnKeyAdded EXCEPT
100
+ // FinishIndexEntry (see below). This function should be considered "mostly
101
+ // stateless" but might modify state distinct from what is modified by
102
+ // FinishIndexEntry. Ideally synchronization within the IndexBuilder can be
103
+ // avoided.
104
+ //
105
+ // The passed-in PreparedIndexEntry object is likely reused so might be
106
+ // passed-in in any state.
107
+ virtual void PrepareIndexEntry(const Slice& last_key_in_current_block,
108
+ const Slice* first_key_in_next_block,
109
+ PreparedIndexEntry* out) = 0;
110
+
111
+ // Parallel compression/construction alternative to AddIndexEntry, 3/3
112
+ //
113
+ // This function is called by a different thread than PrepareIndexEntry, but
114
+ // is called on entries in the same order as PrepareIndexEntry, passed in the
115
+ // PreparedIndexEntry objects populated by PrepareIndexEntry. This function
116
+ // finishes the same effect of AddIndexEntry but split across a few functions.
117
+ //
118
+ // External synchronization ensures Finish is only called after all the
119
+ // FinishIndexEntry calls have completed.
120
+ virtual void FinishIndexEntry(const BlockHandle& block_handle,
121
+ PreparedIndexEntry* entry) = 0;
122
+
79
123
  // This method will be called whenever a key is added. The subclasses may
80
124
  // override OnKeyAdded() if they need to collect additional information.
81
125
  virtual void OnKeyAdded(const Slice& /*key*/,
@@ -109,7 +153,7 @@ class IndexBuilder {
109
153
  // Get the size for index block. Must be called after ::Finish.
110
154
  virtual size_t IndexSize() const = 0;
111
155
 
112
- virtual bool seperator_is_key_plus_seq() { return true; }
156
+ virtual bool separator_is_key_plus_seq() { return true; }
113
157
 
114
158
  protected:
115
159
  // Given the last key in current block and the first key in the next block,
@@ -117,7 +161,7 @@ class IndexBuilder {
117
161
  // can be used as separator.
118
162
  inline bool ShouldUseKeyPlusSeqAsSeparator(
119
163
  const Slice& last_key_in_current_block,
120
- const Slice& first_key_in_next_block) {
164
+ const Slice& first_key_in_next_block) const {
121
165
  Slice l_user_key = ExtractUserKey(last_key_in_current_block);
122
166
  Slice r_user_key = ExtractUserKey(first_key_in_next_block);
123
167
  // If user defined timestamps are not persisted. All the user keys will
@@ -178,7 +222,7 @@ class ShortenedIndexBuilder : public IndexBuilder {
178
222
  include_first_key_(include_first_key),
179
223
  shortening_mode_(shortening_mode) {
180
224
  // Making the default true will disable the feature for old versions
181
- seperator_is_key_plus_seq_ = (format_version <= 2);
225
+ must_use_separator_with_seq_ = (format_version <= 2);
182
226
  }
183
227
 
184
228
  void OnKeyAdded(const Slice& key,
@@ -188,49 +232,61 @@ class ShortenedIndexBuilder : public IndexBuilder {
188
232
  }
189
233
  }
190
234
 
191
- Slice AddIndexEntry(const Slice& last_key_in_current_block,
192
- const Slice* first_key_in_next_block,
193
- const BlockHandle& block_handle,
194
- std::string* separator_scratch) override {
195
- Slice separator;
235
+ Slice GetSeparatorWithSeq(const Slice& last_key_in_current_block,
236
+ const Slice* first_key_in_next_block,
237
+ std::string* separator_scratch) {
238
+ Slice separator_with_seq;
196
239
  if (first_key_in_next_block != nullptr) {
197
240
  if (shortening_mode_ !=
198
241
  BlockBasedTableOptions::IndexShorteningMode::kNoShortening) {
199
- separator = FindShortestInternalKeySeparator(
242
+ separator_with_seq = FindShortestInternalKeySeparator(
200
243
  *comparator_->user_comparator(), last_key_in_current_block,
201
244
  *first_key_in_next_block, separator_scratch);
202
245
  } else {
203
- separator = last_key_in_current_block;
246
+ separator_with_seq = last_key_in_current_block;
204
247
  }
205
- if (!seperator_is_key_plus_seq_ &&
248
+ if (!must_use_separator_with_seq_ &&
206
249
  ShouldUseKeyPlusSeqAsSeparator(last_key_in_current_block,
207
250
  *first_key_in_next_block)) {
208
- seperator_is_key_plus_seq_ = true;
251
+ must_use_separator_with_seq_ = true;
209
252
  }
210
253
  } else {
211
254
  if (shortening_mode_ == BlockBasedTableOptions::IndexShorteningMode::
212
255
  kShortenSeparatorsAndSuccessor) {
213
- separator = FindShortInternalKeySuccessor(
256
+ separator_with_seq = FindShortInternalKeySuccessor(
214
257
  *comparator_->user_comparator(), last_key_in_current_block,
215
258
  separator_scratch);
216
259
  } else {
217
- separator = last_key_in_current_block;
260
+ separator_with_seq = last_key_in_current_block;
218
261
  }
219
262
  }
263
+ return separator_with_seq;
264
+ }
220
265
 
221
- assert(!include_first_key_ || !current_block_first_internal_key_.empty());
266
+ Slice GetFirstInternalKey(std::string* first_internal_key_buf) const {
267
+ if (!include_first_key_) {
268
+ return Slice();
269
+ }
270
+ assert(!current_block_first_internal_key_.empty());
222
271
  // When UDT should not be persisted, the index block builders take care of
223
272
  // stripping UDT from the key, for the first internal key contained in the
224
273
  // IndexValue, we need to explicitly do the stripping here before passing
225
274
  // it to the block builders.
226
- std::string first_internal_key_buf;
227
275
  Slice first_internal_key = current_block_first_internal_key_;
228
276
  if (!current_block_first_internal_key_.empty() && ts_sz_ > 0 &&
229
277
  !persist_user_defined_timestamps_) {
230
- StripTimestampFromInternalKey(&first_internal_key_buf,
278
+ first_internal_key_buf->clear();
279
+ StripTimestampFromInternalKey(first_internal_key_buf,
231
280
  current_block_first_internal_key_, ts_sz_);
232
- first_internal_key = first_internal_key_buf;
281
+ first_internal_key = *first_internal_key_buf;
233
282
  }
283
+ return first_internal_key;
284
+ }
285
+
286
+ void AddIndexEntryImpl(const Slice& separator_with_seq,
287
+ const Slice& first_internal_key,
288
+ const BlockHandle& block_handle,
289
+ bool must_use_separator_with_seq) {
234
290
  IndexValue entry(block_handle, first_internal_key);
235
291
  std::string encoded_entry;
236
292
  std::string delta_encoded_entry;
@@ -254,21 +310,91 @@ class ShortenedIndexBuilder : public IndexBuilder {
254
310
  // away the UDT from key in index block as data block does the same thing.
255
311
  // What are the implications if a "FindShortInternalKeySuccessor"
256
312
  // optimization is provided.
257
- index_block_builder_.Add(separator, encoded_entry,
313
+ index_block_builder_.Add(separator_with_seq, encoded_entry,
258
314
  &delta_encoded_entry_slice);
259
- if (!seperator_is_key_plus_seq_) {
260
- index_block_builder_without_seq_.Add(
261
- ExtractUserKey(separator), encoded_entry, &delta_encoded_entry_slice);
315
+ if (!must_use_separator_with_seq) {
316
+ index_block_builder_without_seq_.Add(ExtractUserKey(separator_with_seq),
317
+ encoded_entry,
318
+ &delta_encoded_entry_slice);
262
319
  }
320
+ }
321
+
322
+ Slice AddIndexEntry(const Slice& last_key_in_current_block,
323
+ const Slice* first_key_in_next_block,
324
+ const BlockHandle& block_handle,
325
+ std::string* separator_scratch) override {
326
+ Slice separator_with_seq = GetSeparatorWithSeq(
327
+ last_key_in_current_block, first_key_in_next_block, separator_scratch);
263
328
 
329
+ std::string first_internal_key_buf;
330
+ Slice first_internal_key = GetFirstInternalKey(&first_internal_key_buf);
331
+
332
+ AddIndexEntryImpl(separator_with_seq, first_internal_key, block_handle,
333
+ must_use_separator_with_seq_);
334
+ current_block_first_internal_key_.clear();
335
+ return separator_with_seq;
336
+ }
337
+
338
+ struct ShortenedPreparedIndexEntry : public PreparedIndexEntry {
339
+ std::string separator_with_seq;
340
+ std::string first_internal_key;
341
+ bool must_use_separator_with_seq = false;
342
+ void SaveFrom(const Slice& from_separator,
343
+ const Slice& from_first_internal_key,
344
+ bool from_must_use_separator_with_seq) {
345
+ assert(from_separator.size() >= kNumInternalBytes);
346
+ if (from_separator.data() == separator_with_seq.data()) {
347
+ // No need to copy
348
+ assert(from_separator.size() == separator_with_seq.size());
349
+ } else {
350
+ // Copy the separator
351
+ separator_with_seq.assign(from_separator.data(), from_separator.size());
352
+ }
353
+ // first_internal_key is optional, so it may be empty.
354
+ assert(from_first_internal_key.empty() ||
355
+ from_first_internal_key.size() >= kNumInternalBytes);
356
+ if (from_first_internal_key.data() == first_internal_key.data()) {
357
+ // No need to copy
358
+ assert(from_first_internal_key.size() == first_internal_key.size());
359
+ } else {
360
+ // Copy the first internal key
361
+ first_internal_key.assign(from_first_internal_key.data(),
362
+ from_first_internal_key.size());
363
+ }
364
+ must_use_separator_with_seq = from_must_use_separator_with_seq;
365
+ }
366
+ };
367
+
368
+ std::unique_ptr<PreparedIndexEntry> CreatePreparedIndexEntry() override {
369
+ return std::make_unique<ShortenedPreparedIndexEntry>();
370
+ }
371
+
372
+ void PrepareIndexEntry(const Slice& last_key_in_current_block,
373
+ const Slice* first_key_in_next_block,
374
+ PreparedIndexEntry* out) override {
375
+ ShortenedPreparedIndexEntry* entry =
376
+ static_cast<ShortenedPreparedIndexEntry*>(out);
377
+ Slice separator =
378
+ GetSeparatorWithSeq(last_key_in_current_block, first_key_in_next_block,
379
+ &entry->separator_with_seq);
380
+ Slice first_internal_key = GetFirstInternalKey(&entry->first_internal_key);
381
+ entry->SaveFrom(separator, first_internal_key,
382
+ must_use_separator_with_seq_);
264
383
  current_block_first_internal_key_.clear();
265
- return separator;
384
+ }
385
+
386
+ void FinishIndexEntry(const BlockHandle& block_handle,
387
+ PreparedIndexEntry* base_entry) override {
388
+ ShortenedPreparedIndexEntry* entry =
389
+ static_cast<ShortenedPreparedIndexEntry*>(base_entry);
390
+ AddIndexEntryImpl(entry->separator_with_seq, entry->first_internal_key,
391
+ block_handle, entry->must_use_separator_with_seq);
266
392
  }
267
393
 
268
394
  using IndexBuilder::Finish;
269
395
  Status Finish(IndexBlocks* index_blocks,
270
396
  const BlockHandle& /*last_partition_block_handle*/) override {
271
- if (seperator_is_key_plus_seq_) {
397
+ if (must_use_separator_with_seq_) {
272
398
  index_blocks->index_block_contents = index_block_builder_.Finish();
273
399
  } else {
274
400
  index_blocks->index_block_contents =
@@ -280,8 +406,8 @@ class ShortenedIndexBuilder : public IndexBuilder {
280
406
 
281
407
  size_t IndexSize() const override { return index_size_; }
282
408
 
283
- bool seperator_is_key_plus_seq() override {
284
- return seperator_is_key_plus_seq_;
409
+ bool separator_is_key_plus_seq() override {
410
+ return must_use_separator_with_seq_;
285
411
  }
286
412
 
287
413
  // Changes *key to a short string >= *key.
@@ -299,9 +425,13 @@ class ShortenedIndexBuilder : public IndexBuilder {
299
425
 
300
426
  private:
301
427
  BlockBuilder index_block_builder_;
428
+ // TODO: consider optimizing to only one builder. When discovering that
429
+ // sequence numbers are needed, read existing entries without seq and rewrite
430
+ // them with seq (which should be trivial to populate since seq wasn't needed
431
+ // before).
302
432
  BlockBuilder index_block_builder_without_seq_;
303
433
  const bool use_value_delta_encoding_;
304
- bool seperator_is_key_plus_seq_;
434
+ bool must_use_separator_with_seq_;
305
435
  const bool include_first_key_;
306
436
  BlockBasedTableOptions::IndexShorteningMode shortening_mode_;
307
437
  BlockHandle last_encoded_handle_ = BlockHandle::NullBlockHandle();
@@ -360,6 +490,23 @@ class HashIndexBuilder : public IndexBuilder {
360
490
  separator_scratch);
361
491
  }
362
492
 
493
+ std::unique_ptr<PreparedIndexEntry> CreatePreparedIndexEntry() override {
494
+ return primary_index_builder_.CreatePreparedIndexEntry();
495
+ }
496
+
497
+ void PrepareIndexEntry(const Slice& last_key_in_current_block,
498
+ const Slice* first_key_in_next_block,
499
+ PreparedIndexEntry* out) override {
500
+ ++current_restart_index_;
501
+ primary_index_builder_.PrepareIndexEntry(last_key_in_current_block,
502
+ first_key_in_next_block, out);
503
+ }
504
+
505
+ void FinishIndexEntry(const BlockHandle& block_handle,
506
+ PreparedIndexEntry* entry) override {
507
+ primary_index_builder_.FinishIndexEntry(block_handle, entry);
508
+ }
509
+
363
510
  void OnKeyAdded(const Slice& key,
364
511
  const std::optional<Slice>& /*value*/) override {
365
512
  auto key_prefix = hash_key_extractor_->Transform(key);
@@ -407,8 +554,8 @@ class HashIndexBuilder : public IndexBuilder {
407
554
  prefix_meta_block_.size();
408
555
  }
409
556
 
410
- bool seperator_is_key_plus_seq() override {
411
- return primary_index_builder_.seperator_is_key_plus_seq();
557
+ bool separator_is_key_plus_seq() override {
558
+ return primary_index_builder_.separator_is_key_plus_seq();
412
559
  }
413
560
 
414
561
  private:
@@ -466,6 +613,14 @@ class PartitionedIndexBuilder : public IndexBuilder {
466
613
  const BlockHandle& block_handle,
467
614
  std::string* separator_scratch) override;
468
615
 
616
+ std::unique_ptr<PreparedIndexEntry> CreatePreparedIndexEntry() override;
617
+ void PrepareIndexEntry(const Slice& last_key_in_current_block,
618
+ const Slice* first_key_in_next_block,
619
+ PreparedIndexEntry* out) override;
620
+ void FinishIndexEntry(const BlockHandle& block_handle,
621
+ PreparedIndexEntry* entry) override;
622
+ void MaybeFlush(const Slice& index_key, const BlockHandle& index_value);
623
+
469
624
  Status Finish(IndexBlocks* index_blocks,
470
625
  const BlockHandle& last_partition_block_handle) override;
471
626
 
@@ -491,8 +646,8 @@ class PartitionedIndexBuilder : public IndexBuilder {
491
646
  // cutting the next partition
492
647
  void RequestPartitionCut();
493
648
 
494
- bool seperator_is_key_plus_seq() override {
495
- return seperator_is_key_plus_seq_;
649
+ bool separator_is_key_plus_seq() override {
650
+ return must_use_separator_with_seq_;
496
651
  }
497
652
 
498
653
  bool get_use_value_delta_encoding() const {
@@ -518,14 +673,14 @@ class PartitionedIndexBuilder : public IndexBuilder {
518
673
  std::list<Entry> entries_;
519
674
  BlockBuilder index_block_builder_; // top-level index builder
520
675
  BlockBuilder index_block_builder_without_seq_; // same for user keys
521
- // the active partition index builder
522
- std::unique_ptr<ShortenedIndexBuilder> sub_index_builder_;
676
+ // the active partition index builder (owned by an Entry in entries_)
677
+ ShortenedIndexBuilder* sub_index_builder_;
523
678
  // the last key in the active partition index builder
524
- std::unique_ptr<FlushBlockPolicy> flush_policy_;
679
+ std::unique_ptr<RetargetableFlushBlockPolicy> flush_policy_;
525
680
  // true if Finish is called once but not complete yet.
526
- bool finishing_indexes = false;
681
+ bool finishing_indexes_ = false;
527
682
  const BlockBasedTableOptions& table_opt_;
528
- bool seperator_is_key_plus_seq_;
683
+ bool must_use_separator_with_seq_;
529
684
  bool use_value_delta_encoding_;
530
685
  // true if an external entity (such as filter partition builder) request
531
686
  // cutting the next partition
@@ -240,7 +240,7 @@ Status PartitionedFilterBlockBuilder::Finish(
240
240
 
241
241
  index_on_filter_block_builder_.Add(e.ikey, handle_encoding,
242
242
  &handle_delta_encoding_slice);
243
- if (!p_index_builder_->seperator_is_key_plus_seq()) {
243
+ if (!p_index_builder_->separator_is_key_plus_seq()) {
244
244
  index_on_filter_block_builder_without_seq_.Add(
245
245
  ExtractUserKey(e.ikey), handle_encoding,
246
246
  &handle_delta_encoding_slice);
@@ -267,7 +267,7 @@ Status PartitionedFilterBlockBuilder::Finish(
267
267
  if (UNLIKELY(filters_.empty())) {
268
268
  if (!index_on_filter_block_builder_.empty()) {
269
269
  // Simplest to just add them all at the end
270
- if (p_index_builder_->seperator_is_key_plus_seq()) {
270
+ if (p_index_builder_->separator_is_key_plus_seq()) {
271
271
  *filter = index_on_filter_block_builder_.Finish();
272
272
  } else {
273
273
  *filter = index_on_filter_block_builder_without_seq_.Finish();
@@ -27,7 +27,7 @@ class MockedBlockBasedTable : public BlockBasedTable {
27
27
  MockedBlockBasedTable(Rep* rep, PartitionedIndexBuilder* pib)
28
28
  : BlockBasedTable(rep, /*block_cache_tracer=*/nullptr) {
29
29
  // Initialize what Open normally does as much as necessary for the test
30
- rep->index_key_includes_seq = pib->seperator_is_key_plus_seq();
30
+ rep->index_key_includes_seq = pib->separator_is_key_plus_seq();
31
31
  rep->index_value_is_full = !pib->get_use_value_delta_encoding();
32
32
  }
33
33
  };
@@ -46,23 +46,57 @@ class UserDefinedIndexBuilderWrapper : public IndexBuilder {
46
46
  handle.offset = block_handle.offset();
47
47
  handle.size = block_handle.size();
48
48
  // Forward the call to both index builders
49
- user_defined_index_builder_->AddIndexEntry(last_key_in_current_block,
50
- first_key_in_next_block, handle,
51
- separator_scratch);
49
+ ParsedInternalKey pkey_last;
50
+ ParsedInternalKey pkey_first;
51
+ // There's no way to return an error here, so we remember the statsu and
52
+ // return it in Finish()
53
+ if (status_.ok()) {
54
+ status_ = ParseInternalKey(last_key_in_current_block, &pkey_last,
55
+ /*lof_err_key*/ false);
56
+ }
57
+ if (status_.ok() && first_key_in_next_block) {
58
+ status_ = ParseInternalKey(*first_key_in_next_block, &pkey_first,
59
+ /*lof_err_key*/ false);
60
+ }
61
+ if (status_.ok()) {
62
+ user_defined_index_builder_->AddIndexEntry(
63
+ pkey_last.user_key,
64
+ first_key_in_next_block ? &pkey_first.user_key : nullptr, handle,
65
+ separator_scratch);
66
+ }
52
67
  return internal_index_builder_->AddIndexEntry(
53
68
  last_key_in_current_block, first_key_in_next_block, block_handle,
54
69
  separator_scratch);
55
70
  }
56
71
 
72
+ // Not supported with parallel compression
73
+ std::unique_ptr<PreparedIndexEntry> CreatePreparedIndexEntry() override {
74
+ return nullptr;
75
+ }
76
+ void PrepareIndexEntry(const Slice& last_key_in_current_block,
77
+ const Slice* first_key_in_next_block,
78
+ PreparedIndexEntry* out) override {
79
+ (void)last_key_in_current_block;
80
+ (void)first_key_in_next_block;
81
+ (void)out;
82
+ assert(false);
83
+ }
84
+ void FinishIndexEntry(const BlockHandle& block_handle,
85
+ PreparedIndexEntry* entry) override {
86
+ (void)block_handle;
87
+ (void)entry;
88
+ assert(false);
89
+ }
90
+
57
91
  void OnKeyAdded(const Slice& key,
58
92
  const std::optional<Slice>& value) override {
93
+ ParsedInternalKey pkey;
59
94
  if (status_.ok()) {
60
95
  if (!value.has_value()) {
61
96
  status_ = Status::InvalidArgument(
62
97
  "user_defined_index_factory not supported with parallel "
63
98
  "compression");
64
99
  } else {
65
- ParsedInternalKey pkey;
66
100
  status_ = ParseInternalKey(key, &pkey, /*lof_err_key*/ false);
67
101
  if (status_.ok() && pkey.type != ValueType::kTypeValue) {
68
102
  status_ = Status::InvalidArgument(
@@ -76,16 +110,38 @@ class UserDefinedIndexBuilderWrapper : public IndexBuilder {
76
110
 
77
111
  // Forward the call to both index builders
78
112
  internal_index_builder_->OnKeyAdded(key, value);
113
+
114
+ // Pass the user key to the UDI. We don't expect multiple entries with
115
+ // different sequence numbers for the same key in the file. RocksDB may
116
+ // enforce it in the future by allowing UDIs only for read only
117
+ // bulkloaded use cases, and only allow ingestion of files with
118
+ // sequence number 0.
79
119
  user_defined_index_builder_->OnKeyAdded(
80
- key, UserDefinedIndexBuilder::ValueType::kValue, value.value());
120
+ pkey.user_key, UserDefinedIndexBuilder::ValueType::kValue,
121
+ value.value());
81
122
  }
82
123
 
83
124
  Status Finish(IndexBlocks* index_blocks,
84
125
  const BlockHandle& last_partition_block_handle) override {
85
- if (!status_.ok()) {
126
+ if (!status_.ok() && !status_.IsIncomplete()) {
86
127
  return status_;
87
128
  }
88
129
 
130
+ if (!udi_finished_) {
131
+ // Finish the user defined index builder
132
+ Slice user_index_contents;
133
+ status_ = user_defined_index_builder_->Finish(&user_index_contents);
134
+ if (!status_.ok()) {
135
+ return status_;
136
+ }
137
+
138
+ // Add the user defined index to the meta blocks
139
+ std::string block_name = kUserDefinedIndexPrefix + name_;
140
+ index_blocks->meta_blocks.insert(
141
+ {block_name, {BlockType::kUserDefinedIndex, user_index_contents}});
142
+ udi_finished_ = true;
143
+ }
144
+
89
145
  // Finish the internal index builder
90
146
  status_ = internal_index_builder_->Finish(index_blocks,
91
147
  last_partition_block_handle);
@@ -93,26 +149,14 @@ class UserDefinedIndexBuilderWrapper : public IndexBuilder {
93
149
  return status_;
94
150
  }
95
151
 
96
- // Finish the user defined index builder
97
- Slice user_index_contents;
98
- status_ = user_defined_index_builder_->Finish(&user_index_contents);
99
- if (!status_.ok()) {
100
- return status_;
101
- }
102
-
103
- // Add the user defined index to the meta blocks
104
- std::string block_name = kUserDefinedIndexPrefix + name_;
105
- index_blocks->meta_blocks.insert(
106
- {block_name, {BlockType::kUserDefinedIndex, user_index_contents}});
107
-
108
152
  index_size_ = internal_index_builder_->IndexSize();
109
153
  return status_;
110
154
  }
111
155
 
112
156
  size_t IndexSize() const override { return index_size_; }
113
157
 
114
- bool seperator_is_key_plus_seq() override {
115
- return internal_index_builder_->seperator_is_key_plus_seq();
158
+ bool separator_is_key_plus_seq() override {
159
+ return internal_index_builder_->separator_is_key_plus_seq();
116
160
  }
117
161
 
118
162
  private:
@@ -120,6 +164,7 @@ class UserDefinedIndexBuilderWrapper : public IndexBuilder {
120
164
  std::unique_ptr<IndexBuilder> internal_index_builder_;
121
165
  std::unique_ptr<UserDefinedIndexBuilder> user_defined_index_builder_;
122
166
  Status status_;
167
+ bool udi_finished_ = false;
123
168
  };
124
169
 
125
170
  class UserDefinedIndexIteratorWrapper
@@ -144,23 +189,41 @@ class UserDefinedIndexIteratorWrapper
144
189
  status_ = ParseInternalKey(target, &pkey, /*log_err_key=*/false);
145
190
  if (status_.ok()) {
146
191
  status_ = udi_iter_->SeekAndGetResult(pkey.user_key, &result_);
147
- valid_ = status_.ok() &&
148
- result_.bound_check_result == IterBoundCheck::kInbound;
192
+ }
193
+ if (status_.ok()) {
194
+ valid_ = result_.bound_check_result == IterBoundCheck::kInbound;
195
+ if (valid_) {
196
+ ikey_.Set(result_.key, 0, ValueType::kTypeValue);
197
+ }
198
+ } else {
199
+ valid_ = false;
149
200
  }
150
201
  }
151
202
 
152
203
  void Next() override {
153
204
  status_ = udi_iter_->NextAndGetResult(&result_);
154
- valid_ =
155
- status_.ok() && result_.bound_check_result == IterBoundCheck::kInbound;
205
+ if (status_.ok()) {
206
+ valid_ = result_.bound_check_result == IterBoundCheck::kInbound;
207
+ if (valid_) {
208
+ ikey_.Set(result_.key, 0, ValueType::kTypeValue);
209
+ }
210
+ } else {
211
+ valid_ = false;
212
+ }
156
213
  }
157
214
 
158
215
  bool NextAndGetResult(IterateResult* result) override {
159
216
  status_ = udi_iter_->NextAndGetResult(&result_);
160
- valid_ =
161
- status_.ok() && result_.bound_check_result == IterBoundCheck::kInbound;
162
217
  if (status_.ok()) {
163
- *result = result_;
218
+ valid_ = result_.bound_check_result == IterBoundCheck::kInbound;
219
+ if (valid_) {
220
+ ikey_.Set(result_.key, 0, ValueType::kTypeValue);
221
+ }
222
+ if (status_.ok()) {
223
+ *result = result_;
224
+ }
225
+ } else {
226
+ valid_ = false;
164
227
  }
165
228
  return valid_;
166
229
  }
@@ -171,7 +234,7 @@ class UserDefinedIndexIteratorWrapper
171
234
 
172
235
  void Prev() override { status_ = Status::NotSupported("Prev not supported"); }
173
236
 
174
- Slice key() const override { return result_.key; }
237
+ Slice key() const override { return Slice(*ikey_.const_rep()); }
175
238
 
176
239
  IndexValue value() const override {
177
240
  auto handle = udi_iter_->value();
@@ -181,13 +244,21 @@ class UserDefinedIndexIteratorWrapper
181
244
 
182
245
  Status status() const override { return status_; }
183
246
 
184
- void Prepare(const std::vector<ScanOptions>* scan_opts) override {
185
- udi_iter_->Prepare(scan_opts->data(), scan_opts->size());
247
+ void Prepare(const MultiScanArgs* scan_opts) override {
248
+ if (scan_opts) {
249
+ udi_iter_->Prepare(scan_opts->GetScanRanges().data(),
250
+ scan_opts->GetScanRanges().size());
251
+ }
252
+ }
253
+
254
+ IterBoundCheck UpperBoundCheckResult() override {
255
+ return result_.bound_check_result;
186
256
  }
187
257
 
188
258
  private:
189
259
  std::unique_ptr<UserDefinedIndexIterator> udi_iter_;
190
260
  IterateResult result_;
261
+ InternalKey ikey_;
191
262
  Status status_;
192
263
  bool valid_;
193
264
  };
@@ -218,7 +289,13 @@ class UserDefinedIndexReaderWrapper : public BlockBasedTable::IndexReader {
218
289
  }
219
290
  std::unique_ptr<UserDefinedIndexIterator> udi_iter =
220
291
  udi_reader_->NewIterator(read_options);
221
- return new UserDefinedIndexIteratorWrapper(std::move(udi_iter));
292
+ if (udi_iter) {
293
+ InternalIteratorBase<IndexValue>* wrap_iter =
294
+ new UserDefinedIndexIteratorWrapper(std::move(udi_iter));
295
+ return wrap_iter;
296
+ }
297
+ return NewErrorInternalIterator<IndexValue>(
298
+ Status::NotFound("COuld not create UDI iterator"));
222
299
  }
223
300
 
224
301
  virtual Status CacheDependencies(
@@ -131,9 +131,11 @@ class ExternalTableIteratorAdapter : public InternalIterator {
131
131
 
132
132
  Status status() const override { return status_; }
133
133
 
134
- void Prepare(const std::vector<ScanOptions>* scan_opts) override {
135
- if (iterator_) {
136
- iterator_->Prepare(scan_opts->data(), scan_opts->size());
134
+ void Prepare(const MultiScanArgs* scan_opts) override {
135
+ if (iterator_ && scan_opts) {
136
+ iterator_->Prepare(scan_opts->GetScanRanges().data(), scan_opts->size());
137
+ } else if (iterator_) {
138
+ iterator_->Prepare(nullptr, 0);
137
139
  }
138
140
  }
139
141
 
@@ -224,6 +226,7 @@ class ExternalTableReaderAdapter : public TableReader {
224
226
  // external table reader
225
227
  props = std::make_shared<TableProperties>(*reader_->GetTableProperties());
226
228
  props->key_largest_seqno = 0;
229
+ props->key_smallest_seqno = 0;
227
230
  }
228
231
  return props;
229
232
  }
@@ -260,6 +263,7 @@ class ExternalTableBuilderAdapter : public TableBuilder {
260
263
  properties_.filter_size = 0;
261
264
  properties_.format_version = 0;
262
265
  properties_.key_largest_seqno = 0;
266
+ properties_.key_smallest_seqno = 0;
263
267
  properties_.column_family_id = topts.column_family_id;
264
268
  properties_.column_family_name = topts.column_family_name;
265
269
  properties_.db_id = topts.db_id;