rocksdb-native 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/binding.c +92 -10
  2. package/index.js +9 -0
  3. package/lib/batch.js +11 -1
  4. package/lib/iterator.js +3 -1
  5. package/lib/snapshot.js +21 -0
  6. package/package.json +1 -1
  7. package/prebuilds/darwin-arm64/rocksdb-native.bare +0 -0
  8. package/prebuilds/darwin-arm64/rocksdb-native.node +0 -0
  9. package/prebuilds/darwin-x64/rocksdb-native.bare +0 -0
  10. package/prebuilds/darwin-x64/rocksdb-native.node +0 -0
  11. package/prebuilds/linux-arm64/rocksdb-native.bare +0 -0
  12. package/prebuilds/linux-arm64/rocksdb-native.node +0 -0
  13. package/prebuilds/linux-x64/rocksdb-native.bare +0 -0
  14. package/prebuilds/linux-x64/rocksdb-native.node +0 -0
  15. package/prebuilds/win32-x64/rocksdb-native.bare +0 -0
  16. package/prebuilds/win32-x64/rocksdb-native.node +0 -0
  17. package/vendor/librocksdb/include/rocksdb.h +38 -4
  18. package/vendor/librocksdb/src/rocksdb.cc +114 -14
  19. package/vendor/librocksdb/vendor/rocksdb/CMakeLists.txt +21 -4
  20. package/vendor/librocksdb/vendor/rocksdb/cache/secondary_cache_adapter.cc +6 -3
  21. package/vendor/librocksdb/vendor/rocksdb/db/arena_wrapped_db_iter.cc +4 -4
  22. package/vendor/librocksdb/vendor/rocksdb/db/arena_wrapped_db_iter.h +4 -2
  23. package/vendor/librocksdb/vendor/rocksdb/db/attribute_group_iterator_impl.cc +20 -0
  24. package/vendor/librocksdb/vendor/rocksdb/db/attribute_group_iterator_impl.h +83 -0
  25. package/vendor/librocksdb/vendor/rocksdb/db/builder.cc +9 -5
  26. package/vendor/librocksdb/vendor/rocksdb/db/builder.h +1 -1
  27. package/vendor/librocksdb/vendor/rocksdb/db/c.cc +231 -6
  28. package/vendor/librocksdb/vendor/rocksdb/db/c_test.c +202 -2
  29. package/vendor/librocksdb/vendor/rocksdb/db/coalescing_iterator.cc +47 -0
  30. package/vendor/librocksdb/vendor/rocksdb/db/coalescing_iterator.h +79 -0
  31. package/vendor/librocksdb/vendor/rocksdb/db/column_family.cc +28 -0
  32. package/vendor/librocksdb/vendor/rocksdb/db/column_family.h +17 -0
  33. package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction.cc +8 -1
  34. package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction.h +11 -9
  35. package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_iterator.cc +50 -23
  36. package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_iterator.h +13 -0
  37. package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_job.cc +22 -25
  38. package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_job.h +2 -0
  39. package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_outputs.cc +8 -1
  40. package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_outputs.h +1 -0
  41. package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_picker.cc +40 -17
  42. package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_picker.h +20 -14
  43. package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_picker_level.cc +11 -6
  44. package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_picker_universal.cc +77 -24
  45. package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_service_job.cc +2 -0
  46. package/vendor/librocksdb/vendor/rocksdb/db/convenience.cc +3 -0
  47. package/vendor/librocksdb/vendor/rocksdb/db/db_filesnapshot.cc +125 -31
  48. package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl.cc +457 -231
  49. package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl.h +172 -73
  50. package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_compaction_flush.cc +152 -133
  51. package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_debug.cc +5 -0
  52. package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_files.cc +58 -52
  53. package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_follower.cc +348 -0
  54. package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_follower.h +54 -0
  55. package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_open.cc +136 -117
  56. package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_secondary.cc +4 -3
  57. package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_secondary.h +7 -6
  58. package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_write.cc +134 -80
  59. package/vendor/librocksdb/vendor/rocksdb/db/db_iter.cc +11 -0
  60. package/vendor/librocksdb/vendor/rocksdb/db/db_test2.cc +1 -1
  61. package/vendor/librocksdb/vendor/rocksdb/db/db_test_util.cc +11 -1
  62. package/vendor/librocksdb/vendor/rocksdb/db/db_test_util.h +11 -7
  63. package/vendor/librocksdb/vendor/rocksdb/db/dbformat.cc +19 -4
  64. package/vendor/librocksdb/vendor/rocksdb/db/dbformat.h +3 -2
  65. package/vendor/librocksdb/vendor/rocksdb/db/error_handler.cc +34 -39
  66. package/vendor/librocksdb/vendor/rocksdb/db/error_handler.h +3 -4
  67. package/vendor/librocksdb/vendor/rocksdb/db/event_helpers.cc +6 -3
  68. package/vendor/librocksdb/vendor/rocksdb/db/experimental.cc +3 -2
  69. package/vendor/librocksdb/vendor/rocksdb/db/external_sst_file_ingestion_job.cc +76 -18
  70. package/vendor/librocksdb/vendor/rocksdb/db/external_sst_file_ingestion_job.h +11 -0
  71. package/vendor/librocksdb/vendor/rocksdb/db/flush_job.cc +37 -5
  72. package/vendor/librocksdb/vendor/rocksdb/db/flush_job.h +14 -0
  73. package/vendor/librocksdb/vendor/rocksdb/db/import_column_family_job.cc +49 -45
  74. package/vendor/librocksdb/vendor/rocksdb/db/internal_stats.cc +60 -1
  75. package/vendor/librocksdb/vendor/rocksdb/db/internal_stats.h +20 -1
  76. package/vendor/librocksdb/vendor/rocksdb/db/log_reader.cc +15 -6
  77. package/vendor/librocksdb/vendor/rocksdb/db/log_writer.cc +59 -10
  78. package/vendor/librocksdb/vendor/rocksdb/db/log_writer.h +8 -0
  79. package/vendor/librocksdb/vendor/rocksdb/db/memtable.cc +24 -40
  80. package/vendor/librocksdb/vendor/rocksdb/db/memtable.h +10 -10
  81. package/vendor/librocksdb/vendor/rocksdb/db/memtable_list.cc +9 -8
  82. package/vendor/librocksdb/vendor/rocksdb/db/multi_cf_iterator_impl.h +296 -0
  83. package/vendor/librocksdb/vendor/rocksdb/db/range_tombstone_fragmenter.h +8 -10
  84. package/vendor/librocksdb/vendor/rocksdb/db/repair.cc +4 -3
  85. package/vendor/librocksdb/vendor/rocksdb/db/seqno_to_time_mapping.cc +30 -0
  86. package/vendor/librocksdb/vendor/rocksdb/db/seqno_to_time_mapping.h +9 -0
  87. package/vendor/librocksdb/vendor/rocksdb/db/table_cache.cc +17 -2
  88. package/vendor/librocksdb/vendor/rocksdb/db/table_cache.h +9 -1
  89. package/vendor/librocksdb/vendor/rocksdb/db/table_properties_collector.h +9 -2
  90. package/vendor/librocksdb/vendor/rocksdb/db/transaction_log_impl.cc +3 -3
  91. package/vendor/librocksdb/vendor/rocksdb/db/transaction_log_impl.h +7 -7
  92. package/vendor/librocksdb/vendor/rocksdb/db/version_edit.cc +0 -1
  93. package/vendor/librocksdb/vendor/rocksdb/db/version_edit_handler.cc +39 -5
  94. package/vendor/librocksdb/vendor/rocksdb/db/version_edit_handler.h +24 -15
  95. package/vendor/librocksdb/vendor/rocksdb/db/version_set.cc +117 -64
  96. package/vendor/librocksdb/vendor/rocksdb/db/version_set.h +27 -10
  97. package/vendor/librocksdb/vendor/rocksdb/db/wal_manager.cc +37 -29
  98. package/vendor/librocksdb/vendor/rocksdb/db/wal_manager.h +6 -5
  99. package/vendor/librocksdb/vendor/rocksdb/db/wide/wide_columns.cc +2 -3
  100. package/vendor/librocksdb/vendor/rocksdb/db/wide/wide_columns_helper.cc +6 -0
  101. package/vendor/librocksdb/vendor/rocksdb/db/write_batch.cc +89 -31
  102. package/vendor/librocksdb/vendor/rocksdb/db/write_thread.cc +53 -5
  103. package/vendor/librocksdb/vendor/rocksdb/db/write_thread.h +36 -4
  104. package/vendor/librocksdb/vendor/rocksdb/env/composite_env_wrapper.h +21 -0
  105. package/vendor/librocksdb/vendor/rocksdb/env/env.cc +15 -0
  106. package/vendor/librocksdb/vendor/rocksdb/env/fs_on_demand.cc +331 -0
  107. package/vendor/librocksdb/vendor/rocksdb/env/fs_on_demand.h +139 -0
  108. package/vendor/librocksdb/vendor/rocksdb/env/io_posix.cc +8 -6
  109. package/vendor/librocksdb/vendor/rocksdb/env/io_posix.h +1 -1
  110. package/vendor/librocksdb/vendor/rocksdb/file/delete_scheduler.cc +130 -27
  111. package/vendor/librocksdb/vendor/rocksdb/file/delete_scheduler.h +61 -8
  112. package/vendor/librocksdb/vendor/rocksdb/file/file_util.cc +25 -4
  113. package/vendor/librocksdb/vendor/rocksdb/file/file_util.h +15 -0
  114. package/vendor/librocksdb/vendor/rocksdb/file/sequence_file_reader.cc +1 -0
  115. package/vendor/librocksdb/vendor/rocksdb/file/sequence_file_reader.h +9 -4
  116. package/vendor/librocksdb/vendor/rocksdb/file/sst_file_manager_impl.cc +18 -0
  117. package/vendor/librocksdb/vendor/rocksdb/file/sst_file_manager_impl.h +31 -4
  118. package/vendor/librocksdb/vendor/rocksdb/file/writable_file_writer.cc +40 -38
  119. package/vendor/librocksdb/vendor/rocksdb/file/writable_file_writer.h +48 -15
  120. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/advanced_options.h +12 -3
  121. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/attribute_groups.h +114 -0
  122. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/c.h +90 -0
  123. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/cache.h +5 -0
  124. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/comparator.h +27 -0
  125. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/db.h +71 -12
  126. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/env.h +9 -0
  127. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/experimental.h +5 -0
  128. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/file_system.h +14 -0
  129. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/iterator.h +9 -71
  130. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/iterator_base.h +90 -0
  131. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/listener.h +21 -0
  132. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/options.h +125 -12
  133. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/perf_context.h +1 -1
  134. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/sst_file_reader.h +11 -1
  135. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/table.h +6 -6
  136. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/table_properties.h +19 -0
  137. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/transaction_log.h +12 -6
  138. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/types.h +12 -0
  139. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/universal_compaction.h +31 -0
  140. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/user_write_callback.h +29 -0
  141. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/cache_dump_load.h +4 -0
  142. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/checkpoint.h +4 -2
  143. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/customizable_util.h +0 -1
  144. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/env_mirror.h +1 -1
  145. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/ldb_cmd.h +24 -7
  146. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/option_change_migration.h +4 -4
  147. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/stackable_db.h +24 -5
  148. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/table_properties_collectors.h +46 -0
  149. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/transaction.h +42 -17
  150. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/transaction_db.h +5 -0
  151. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/types_util.h +36 -0
  152. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/write_batch_with_index.h +71 -3
  153. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/version.h +2 -2
  154. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/wide_columns.h +87 -72
  155. package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/write_batch_base.h +1 -1
  156. package/vendor/librocksdb/vendor/rocksdb/memory/memory_allocator.cc +1 -0
  157. package/vendor/librocksdb/vendor/rocksdb/options/cf_options.cc +13 -2
  158. package/vendor/librocksdb/vendor/rocksdb/options/cf_options.h +6 -2
  159. package/vendor/librocksdb/vendor/rocksdb/options/db_options.cc +27 -1
  160. package/vendor/librocksdb/vendor/rocksdb/options/db_options.h +10 -3
  161. package/vendor/librocksdb/vendor/rocksdb/options/options.cc +3 -0
  162. package/vendor/librocksdb/vendor/rocksdb/options/options_helper.cc +1 -0
  163. package/vendor/librocksdb/vendor/rocksdb/port/jemalloc_helper.h +2 -2
  164. package/vendor/librocksdb/vendor/rocksdb/port/stack_trace.cc +1 -0
  165. package/vendor/librocksdb/vendor/rocksdb/port/win/port_win.cc +3 -2
  166. package/vendor/librocksdb/vendor/rocksdb/table/block_based/binary_search_index_reader.cc +1 -2
  167. package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_builder.cc +47 -31
  168. package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_factory.cc +15 -0
  169. package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_iterator.cc +37 -18
  170. package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_iterator.h +10 -3
  171. package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_reader.cc +102 -41
  172. package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_reader.h +15 -7
  173. package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_reader_impl.h +1 -3
  174. package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_reader_sync_and_async.h +5 -6
  175. package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_cache.h +31 -0
  176. package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_prefetcher.cc +6 -0
  177. package/vendor/librocksdb/vendor/rocksdb/table/block_based/cachable_entry.h +10 -5
  178. package/vendor/librocksdb/vendor/rocksdb/table/block_based/filter_block.h +34 -28
  179. package/vendor/librocksdb/vendor/rocksdb/table/block_based/filter_block_reader_common.cc +17 -11
  180. package/vendor/librocksdb/vendor/rocksdb/table/block_based/filter_block_reader_common.h +5 -2
  181. package/vendor/librocksdb/vendor/rocksdb/table/block_based/filter_policy.cc +12 -3
  182. package/vendor/librocksdb/vendor/rocksdb/table/block_based/full_filter_block.cc +37 -30
  183. package/vendor/librocksdb/vendor/rocksdb/table/block_based/full_filter_block.h +11 -13
  184. package/vendor/librocksdb/vendor/rocksdb/table/block_based/hash_index_reader.cc +1 -2
  185. package/vendor/librocksdb/vendor/rocksdb/table/block_based/index_builder.cc +62 -53
  186. package/vendor/librocksdb/vendor/rocksdb/table/block_based/index_builder.h +60 -38
  187. package/vendor/librocksdb/vendor/rocksdb/table/block_based/index_reader_common.cc +14 -9
  188. package/vendor/librocksdb/vendor/rocksdb/table/block_based/index_reader_common.h +4 -1
  189. package/vendor/librocksdb/vendor/rocksdb/table/block_based/partitioned_filter_block.cc +135 -94
  190. package/vendor/librocksdb/vendor/rocksdb/table/block_based/partitioned_filter_block.h +52 -46
  191. package/vendor/librocksdb/vendor/rocksdb/table/block_based/partitioned_index_reader.cc +51 -13
  192. package/vendor/librocksdb/vendor/rocksdb/table/block_based/partitioned_index_reader.h +2 -0
  193. package/vendor/librocksdb/vendor/rocksdb/table/block_based/uncompression_dict_reader.cc +3 -11
  194. package/vendor/librocksdb/vendor/rocksdb/table/block_based/uncompression_dict_reader.h +2 -3
  195. package/vendor/librocksdb/vendor/rocksdb/table/block_fetcher.cc +8 -10
  196. package/vendor/librocksdb/vendor/rocksdb/table/block_fetcher.h +2 -1
  197. package/vendor/librocksdb/vendor/rocksdb/table/compaction_merging_iterator.cc +9 -10
  198. package/vendor/librocksdb/vendor/rocksdb/table/compaction_merging_iterator.h +3 -2
  199. package/vendor/librocksdb/vendor/rocksdb/table/format.cc +1 -2
  200. package/vendor/librocksdb/vendor/rocksdb/table/iterator.cc +4 -0
  201. package/vendor/librocksdb/vendor/rocksdb/table/merging_iterator.cc +18 -13
  202. package/vendor/librocksdb/vendor/rocksdb/table/merging_iterator.h +5 -3
  203. package/vendor/librocksdb/vendor/rocksdb/table/meta_blocks.cc +18 -4
  204. package/vendor/librocksdb/vendor/rocksdb/table/meta_blocks.h +4 -0
  205. package/vendor/librocksdb/vendor/rocksdb/table/plain/plain_table_builder.cc +2 -2
  206. package/vendor/librocksdb/vendor/rocksdb/table/sst_file_dumper.cc +6 -6
  207. package/vendor/librocksdb/vendor/rocksdb/table/sst_file_reader.cc +24 -2
  208. package/vendor/librocksdb/vendor/rocksdb/table/sst_file_writer_collectors.h +3 -1
  209. package/vendor/librocksdb/vendor/rocksdb/table/table_builder.h +8 -7
  210. package/vendor/librocksdb/vendor/rocksdb/table/table_iterator.h +69 -0
  211. package/vendor/librocksdb/vendor/rocksdb/table/table_reader.h +9 -0
  212. package/vendor/librocksdb/vendor/rocksdb/test_util/testutil.cc +25 -0
  213. package/vendor/librocksdb/vendor/rocksdb/test_util/testutil.h +12 -0
  214. package/vendor/librocksdb/vendor/rocksdb/tools/db_bench_tool.cc +32 -0
  215. package/vendor/librocksdb/vendor/rocksdb/tools/ldb_cmd.cc +618 -124
  216. package/vendor/librocksdb/vendor/rocksdb/tools/ldb_cmd_impl.h +19 -1
  217. package/vendor/librocksdb/vendor/rocksdb/tools/ldb_tool.cc +9 -0
  218. package/vendor/librocksdb/vendor/rocksdb/util/aligned_storage.h +24 -0
  219. package/vendor/librocksdb/vendor/rocksdb/util/autovector.h +4 -0
  220. package/vendor/librocksdb/vendor/rocksdb/util/comparator.cc +12 -0
  221. package/vendor/librocksdb/vendor/rocksdb/util/filter_bench.cc +1 -1
  222. package/vendor/librocksdb/vendor/rocksdb/util/random.cc +2 -1
  223. package/vendor/librocksdb/vendor/rocksdb/util/stderr_logger.cc +3 -4
  224. package/vendor/librocksdb/vendor/rocksdb/util/stderr_logger.h +1 -1
  225. package/vendor/librocksdb/vendor/rocksdb/util/udt_util.cc +33 -0
  226. package/vendor/librocksdb/vendor/rocksdb/util/udt_util.h +7 -0
  227. package/vendor/librocksdb/vendor/rocksdb/util/write_batch_util.h +5 -0
  228. package/vendor/librocksdb/vendor/rocksdb/util/xxhash.h +36 -29
  229. package/vendor/librocksdb/vendor/rocksdb/utilities/blob_db/blob_db_impl.h +3 -0
  230. package/vendor/librocksdb/vendor/rocksdb/utilities/blob_db/blob_db_impl_filesnapshot.cc +20 -0
  231. package/vendor/librocksdb/vendor/rocksdb/utilities/cache_dump_load_impl.cc +29 -9
  232. package/vendor/librocksdb/vendor/rocksdb/utilities/cache_dump_load_impl.h +14 -3
  233. package/vendor/librocksdb/vendor/rocksdb/utilities/debug.cc +16 -4
  234. package/vendor/librocksdb/vendor/rocksdb/utilities/fault_injection_fs.cc +677 -248
  235. package/vendor/librocksdb/vendor/rocksdb/utilities/fault_injection_fs.h +325 -158
  236. package/vendor/librocksdb/vendor/rocksdb/utilities/option_change_migration/option_change_migration.cc +1 -8
  237. package/vendor/librocksdb/vendor/rocksdb/utilities/table_properties_collectors/compact_for_tiering_collector.cc +144 -0
  238. package/vendor/librocksdb/vendor/rocksdb/utilities/table_properties_collectors/compact_for_tiering_collector.h +45 -0
  239. package/vendor/librocksdb/vendor/rocksdb/utilities/table_properties_collectors/compact_on_deletion_collector.cc +12 -0
  240. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/lock/range/range_tree/lib/portability/toku_time.h +1 -1
  241. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/lock/range/range_tree/lib/util/growable_array.h +3 -3
  242. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/pessimistic_transaction.cc +116 -20
  243. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/pessimistic_transaction.h +33 -1
  244. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/pessimistic_transaction_db.cc +78 -13
  245. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/pessimistic_transaction_db.h +33 -1
  246. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/transaction_base.cc +106 -7
  247. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/transaction_base.h +68 -10
  248. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/transaction_test.h +7 -3
  249. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/transaction_util.cc +8 -5
  250. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/transaction_util.h +7 -4
  251. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/write_prepared_txn.cc +18 -12
  252. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/write_prepared_txn_db.cc +4 -4
  253. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/write_prepared_txn_db.h +17 -0
  254. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/write_unprepared_txn.cc +11 -9
  255. package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/write_unprepared_txn_db.cc +2 -1
  256. package/vendor/librocksdb/vendor/rocksdb/utilities/types_util.cc +88 -0
  257. package/vendor/librocksdb/vendor/rocksdb/utilities/write_batch_with_index/write_batch_with_index.cc +313 -14
  258. package/vendor/librocksdb/vendor/rocksdb/utilities/write_batch_with_index/write_batch_with_index_internal.cc +7 -0
  259. package/vendor/librocksdb/vendor/rocksdb/utilities/write_batch_with_index/write_batch_with_index_internal.h +1 -1
  260. package/vendor/librocksdb/vendor/rocksdb/db/multi_cf_iterator.cc +0 -102
  261. package/vendor/librocksdb/vendor/rocksdb/db/multi_cf_iterator.h +0 -159
@@ -17,12 +17,16 @@
17
17
  #include "utilities/fault_injection_fs.h"
18
18
 
19
19
  #include <algorithm>
20
+ #include <cstdio>
20
21
  #include <functional>
21
22
  #include <utility>
22
23
 
23
24
  #include "env/composite_env_wrapper.h"
24
25
  #include "port/lang.h"
25
26
  #include "port/stack_trace.h"
27
+ #include "rocksdb/env.h"
28
+ #include "rocksdb/io_status.h"
29
+ #include "rocksdb/types.h"
26
30
  #include "test_util/sync_point.h"
27
31
  #include "util/coding.h"
28
32
  #include "util/crc32c.h"
@@ -92,20 +96,15 @@ IOStatus TestFSDirectory::Fsync(const IOOptions& options, IODebugContext* dbg) {
92
96
  if (!fs_->IsFilesystemActive()) {
93
97
  return fs_->GetError();
94
98
  }
95
- {
96
- IOStatus in_s = fs_->InjectMetadataWriteError();
97
- if (!in_s.ok()) {
98
- return in_s;
99
- }
99
+
100
+ IOStatus s = fs_->MaybeInjectThreadLocalError(
101
+ FaultInjectionIOType::kMetadataWrite, options);
102
+ if (!s.ok()) {
103
+ return s;
100
104
  }
105
+
101
106
  fs_->SyncDir(dirname_);
102
- IOStatus s = dir_->Fsync(options, dbg);
103
- {
104
- IOStatus in_s = fs_->InjectMetadataWriteError();
105
- if (!in_s.ok()) {
106
- return in_s;
107
- }
108
- }
107
+ s = dir_->Fsync(options, dbg);
109
108
  return s;
110
109
  }
111
110
 
@@ -113,7 +112,14 @@ IOStatus TestFSDirectory::Close(const IOOptions& options, IODebugContext* dbg) {
113
112
  if (!fs_->IsFilesystemActive()) {
114
113
  return fs_->GetError();
115
114
  }
116
- IOStatus s = dir_->Close(options, dbg);
115
+
116
+ IOStatus s = fs_->MaybeInjectThreadLocalError(
117
+ FaultInjectionIOType::kMetadataWrite, options);
118
+ if (!s.ok()) {
119
+ return s;
120
+ }
121
+
122
+ s = dir_->Close(options, dbg);
117
123
  return s;
118
124
  }
119
125
 
@@ -123,20 +129,14 @@ IOStatus TestFSDirectory::FsyncWithDirOptions(
123
129
  if (!fs_->IsFilesystemActive()) {
124
130
  return fs_->GetError();
125
131
  }
126
- {
127
- IOStatus in_s = fs_->InjectMetadataWriteError();
128
- if (!in_s.ok()) {
129
- return in_s;
130
- }
132
+ IOStatus s = fs_->MaybeInjectThreadLocalError(
133
+ FaultInjectionIOType::kMetadataWrite, options);
134
+ if (!s.ok()) {
135
+ return s;
131
136
  }
137
+
132
138
  fs_->SyncDir(dirname_);
133
- IOStatus s = dir_->FsyncWithDirOptions(options, dbg, dir_fsync_options);
134
- {
135
- IOStatus in_s = fs_->InjectMetadataWriteError();
136
- if (!in_s.ok()) {
137
- return in_s;
138
- }
139
- }
139
+ s = dir_->FsyncWithDirOptions(options, dbg, dir_fsync_options);
140
140
  return s;
141
141
  }
142
142
 
@@ -148,9 +148,11 @@ TestFSWritableFile::TestFSWritableFile(const std::string& fname,
148
148
  file_opts_(file_opts),
149
149
  target_(std::move(f)),
150
150
  writable_file_opened_(true),
151
- fs_(fs) {
151
+ fs_(fs),
152
+ unsync_data_loss_(fs_->InjectUnsyncedDataLoss()) {
152
153
  assert(target_ != nullptr);
153
- state_.pos_ = 0;
154
+ assert(state_.pos_at_last_append_ == 0);
155
+ assert(state_.pos_at_last_sync_ == 0);
154
156
  }
155
157
 
156
158
  TestFSWritableFile::~TestFSWritableFile() {
@@ -165,15 +167,28 @@ IOStatus TestFSWritableFile::Append(const Slice& data, const IOOptions& options,
165
167
  if (!fs_->IsFilesystemActive()) {
166
168
  return fs_->GetError();
167
169
  }
168
- if (target_->use_direct_io()) {
169
- target_->Append(data, options, dbg).PermitUncheckedError();
170
+
171
+ IOStatus s = fs_->MaybeInjectThreadLocalError(
172
+ FaultInjectionIOType::kWrite, options, state_.filename_,
173
+ FaultInjectionTestFS::ErrorOperation::kAppend);
174
+ if (!s.ok()) {
175
+ return s;
176
+ }
177
+
178
+ if (target_->use_direct_io() || !unsync_data_loss_) {
179
+ // TODO(hx235): buffer data for direct IO write to simulate data loss like
180
+ // non-direct IO write
181
+ s = target_->Append(data, options, dbg);
170
182
  } else {
171
183
  state_.buffer_.append(data.data(), data.size());
172
- state_.pos_ += data.size();
184
+ }
185
+
186
+ if (s.ok()) {
187
+ state_.pos_at_last_append_ += data.size();
173
188
  fs_->WritableFileAppended(state_);
174
189
  }
175
- IOStatus io_s = fs_->InjectWriteError(state_.filename_);
176
- return io_s;
190
+
191
+ return s;
177
192
  }
178
193
 
179
194
  // By setting the IngestDataCorruptionBeforeWrite(), the data corruption is
@@ -189,6 +204,13 @@ IOStatus TestFSWritableFile::Append(
189
204
  return IOStatus::Corruption("Data is corrupted!");
190
205
  }
191
206
 
207
+ IOStatus s = fs_->MaybeInjectThreadLocalError(
208
+ FaultInjectionIOType::kWrite, options, state_.filename_,
209
+ FaultInjectionTestFS::ErrorOperation::kAppend);
210
+ if (!s.ok()) {
211
+ return s;
212
+ }
213
+
192
214
  // Calculate the checksum
193
215
  std::string checksum;
194
216
  CalculateTypedChecksum(fs_->GetChecksumHandoffFuncType(), data.data(),
@@ -201,15 +223,66 @@ IOStatus TestFSWritableFile::Append(
201
223
  "current data checksum: " + Slice(checksum).ToString(true);
202
224
  return IOStatus::Corruption(msg);
203
225
  }
204
- if (target_->use_direct_io()) {
205
- target_->Append(data, options, dbg).PermitUncheckedError();
226
+
227
+ if (target_->use_direct_io() || !unsync_data_loss_) {
228
+ // TODO(hx235): buffer data for direct IO write to simulate data loss like
229
+ // non-direct IO write
230
+ s = target_->Append(data, options, dbg);
206
231
  } else {
207
232
  state_.buffer_.append(data.data(), data.size());
208
- state_.pos_ += data.size();
233
+ }
234
+ if (s.ok()) {
235
+ state_.pos_at_last_append_ += data.size();
209
236
  fs_->WritableFileAppended(state_);
210
237
  }
211
- IOStatus io_s = fs_->InjectWriteError(state_.filename_);
212
- return io_s;
238
+ return s;
239
+ }
240
+
241
+ IOStatus TestFSWritableFile::Truncate(uint64_t size, const IOOptions& options,
242
+ IODebugContext* dbg) {
243
+ MutexLock l(&mutex_);
244
+ if (!fs_->IsFilesystemActive()) {
245
+ return fs_->GetError();
246
+ }
247
+ IOStatus s = fs_->MaybeInjectThreadLocalError(FaultInjectionIOType::kWrite,
248
+ options, state_.filename_);
249
+ if (!s.ok()) {
250
+ return s;
251
+ }
252
+
253
+ s = target_->Truncate(size, options, dbg);
254
+ if (s.ok()) {
255
+ state_.pos_at_last_append_ = size;
256
+ }
257
+ return s;
258
+ }
259
+
260
+ IOStatus TestFSWritableFile::PositionedAppend(const Slice& data,
261
+ uint64_t offset,
262
+ const IOOptions& options,
263
+ IODebugContext* dbg) {
264
+ MutexLock l(&mutex_);
265
+ if (!fs_->IsFilesystemActive()) {
266
+ return fs_->GetError();
267
+ }
268
+ if (fs_->ShouldDataCorruptionBeforeWrite()) {
269
+ return IOStatus::Corruption("Data is corrupted!");
270
+ }
271
+ IOStatus s = fs_->MaybeInjectThreadLocalError(
272
+ FaultInjectionIOType::kWrite, options, state_.filename_,
273
+ FaultInjectionTestFS::ErrorOperation::kPositionedAppend);
274
+ if (!s.ok()) {
275
+ return s;
276
+ }
277
+
278
+ // TODO(hx235): buffer data for direct IO write to simulate data loss like
279
+ // non-direct IO write
280
+ s = target_->PositionedAppend(data, offset, options, dbg);
281
+ if (s.ok()) {
282
+ state_.pos_at_last_append_ = offset + data.size();
283
+ fs_->WritableFileAppended(state_);
284
+ }
285
+ return s;
213
286
  }
214
287
 
215
288
  IOStatus TestFSWritableFile::PositionedAppend(
@@ -222,6 +295,12 @@ IOStatus TestFSWritableFile::PositionedAppend(
222
295
  if (fs_->ShouldDataCorruptionBeforeWrite()) {
223
296
  return IOStatus::Corruption("Data is corrupted!");
224
297
  }
298
+ IOStatus s = fs_->MaybeInjectThreadLocalError(
299
+ FaultInjectionIOType::kWrite, options, state_.filename_,
300
+ FaultInjectionTestFS::ErrorOperation::kPositionedAppend);
301
+ if (!s.ok()) {
302
+ return s;
303
+ }
225
304
 
226
305
  // Calculate the checksum
227
306
  std::string checksum;
@@ -235,9 +314,14 @@ IOStatus TestFSWritableFile::PositionedAppend(
235
314
  "current data checksum: " + Slice(checksum).ToString(true);
236
315
  return IOStatus::Corruption(msg);
237
316
  }
238
- target_->PositionedAppend(data, offset, options, dbg);
239
- IOStatus io_s = fs_->InjectWriteError(state_.filename_);
240
- return io_s;
317
+ // TODO(hx235): buffer data for direct IO write to simulate data loss like
318
+ // non-direct IO write
319
+ s = target_->PositionedAppend(data, offset, options, dbg);
320
+ if (s.ok()) {
321
+ state_.pos_at_last_append_ = offset + data.size();
322
+ fs_->WritableFileAppended(state_);
323
+ }
324
+ return s;
241
325
  }
242
326
 
243
327
  IOStatus TestFSWritableFile::Close(const IOOptions& options,
@@ -247,29 +331,17 @@ IOStatus TestFSWritableFile::Close(const IOOptions& options,
247
331
  if (!fs_->IsFilesystemActive()) {
248
332
  return fs_->GetError();
249
333
  }
250
- {
251
- IOStatus in_s = fs_->InjectMetadataWriteError();
252
- if (!in_s.ok()) {
253
- return in_s;
254
- }
334
+ IOStatus io_s = fs_->MaybeInjectThreadLocalError(
335
+ FaultInjectionIOType::kMetadataWrite, options);
336
+ if (!io_s.ok()) {
337
+ return io_s;
255
338
  }
256
339
  writable_file_opened_ = false;
257
- IOStatus io_s;
258
- if (!target_->use_direct_io()) {
259
- io_s = target_->Append(state_.buffer_, options, dbg);
260
- }
261
- if (io_s.ok()) {
262
- state_.buffer_.resize(0);
263
- // Ignore sync errors
264
- target_->Sync(options, dbg).PermitUncheckedError();
265
- io_s = target_->Close(options, dbg);
266
- }
267
- if (io_s.ok()) {
268
- IOStatus in_s = fs_->InjectMetadataWriteError();
269
- if (!in_s.ok()) {
270
- return in_s;
271
- }
272
- }
340
+
341
+ // Drop buffered data that was never synced because close is not a syncing
342
+ // mechanism in POSIX file semantics.
343
+ state_.buffer_.resize(0);
344
+ io_s = target_->Close(options, dbg);
273
345
  return io_s;
274
346
  }
275
347
 
@@ -278,9 +350,6 @@ IOStatus TestFSWritableFile::Flush(const IOOptions&, IODebugContext*) {
278
350
  if (!fs_->IsFilesystemActive()) {
279
351
  return fs_->GetError();
280
352
  }
281
- if (fs_->IsFilesystemActive()) {
282
- state_.pos_at_last_flush_ = state_.pos_;
283
- }
284
353
  return IOStatus::OK();
285
354
  }
286
355
 
@@ -299,7 +368,7 @@ IOStatus TestFSWritableFile::Sync(const IOOptions& options,
299
368
  state_.buffer_.resize(0);
300
369
  // Ignore sync errors
301
370
  target_->Sync(options, dbg).PermitUncheckedError();
302
- state_.pos_at_last_sync_ = state_.pos_;
371
+ state_.pos_at_last_sync_ = state_.pos_at_last_append_;
303
372
  fs_->WritableFileSynced(state_);
304
373
  return io_s;
305
374
  }
@@ -313,15 +382,13 @@ IOStatus TestFSWritableFile::RangeSync(uint64_t offset, uint64_t nbytes,
313
382
  }
314
383
  // Assumes caller passes consecutive byte ranges.
315
384
  uint64_t sync_limit = offset + nbytes;
316
- uint64_t buf_begin =
317
- state_.pos_at_last_sync_ < 0 ? 0 : state_.pos_at_last_sync_;
318
385
 
319
386
  IOStatus io_s;
320
- if (sync_limit < buf_begin) {
387
+ if (sync_limit < state_.pos_at_last_sync_) {
321
388
  return io_s;
322
389
  }
323
390
  uint64_t num_to_sync = std::min(static_cast<uint64_t>(state_.buffer_.size()),
324
- sync_limit - buf_begin);
391
+ sync_limit - state_.pos_at_last_sync_);
325
392
  Slice buf_to_sync(state_.buffer_.data(), num_to_sync);
326
393
  io_s = target_->Append(buf_to_sync, options, dbg);
327
394
  state_.buffer_ = state_.buffer_.substr(num_to_sync);
@@ -360,6 +427,7 @@ IOStatus TestFSRandomRWFile::Read(uint64_t offset, size_t n,
360
427
  if (!fs_->IsFilesystemActive()) {
361
428
  return fs_->GetError();
362
429
  }
430
+ // TODO (low priority): fs_->ReadUnsyncedData()
363
431
  return target_->Read(offset, n, options, result, scratch, dbg);
364
432
  }
365
433
 
@@ -403,15 +471,17 @@ IOStatus TestFSRandomAccessFile::Read(uint64_t offset, size_t n,
403
471
  if (!fs_->IsFilesystemActive()) {
404
472
  return fs_->GetError();
405
473
  }
406
- IOStatus s = target_->Read(offset, n, options, result, scratch, dbg);
407
- if (s.ok()) {
408
- s = fs_->InjectThreadSpecificReadError(
409
- FaultInjectionTestFS::ErrorOperation::kRead, result, use_direct_io(),
410
- scratch, /*need_count_increase=*/true, /*fault_injected=*/nullptr);
411
- }
412
- if (s.ok() && fs_->ShouldInjectRandomReadError()) {
413
- return IOStatus::IOError("injected read error");
474
+ IOStatus s = fs_->MaybeInjectThreadLocalError(
475
+ FaultInjectionIOType::kRead, options, "",
476
+ FaultInjectionTestFS::ErrorOperation::kRead, result, use_direct_io(),
477
+ scratch, /*need_count_increase=*/true,
478
+ /*fault_injected=*/nullptr);
479
+ if (!s.ok()) {
480
+ return s;
414
481
  }
482
+
483
+ s = target_->Read(offset, n, options, result, scratch, dbg);
484
+ // TODO (low priority): fs_->ReadUnsyncedData()
415
485
  return s;
416
486
  }
417
487
 
@@ -419,28 +489,35 @@ IOStatus TestFSRandomAccessFile::ReadAsync(
419
489
  FSReadRequest& req, const IOOptions& opts,
420
490
  std::function<void(FSReadRequest&, void*)> cb, void* cb_arg,
421
491
  void** io_handle, IOHandleDeleter* del_fn, IODebugContext* /*dbg*/) {
422
- IOStatus ret;
423
- IOStatus s;
492
+ IOStatus res_status;
424
493
  FSReadRequest res;
494
+ IOStatus s;
425
495
  if (!fs_->IsFilesystemActive()) {
426
- ret = fs_->GetError();
427
- } else {
428
- ret = fs_->InjectThreadSpecificReadError(
496
+ res_status = fs_->GetError();
497
+ }
498
+ if (res_status.ok()) {
499
+ res_status = fs_->MaybeInjectThreadLocalError(
500
+ FaultInjectionIOType::kRead, opts, "",
429
501
  FaultInjectionTestFS::ErrorOperation::kRead, &res.result,
430
502
  use_direct_io(), req.scratch, /*need_count_increase=*/true,
431
503
  /*fault_injected=*/nullptr);
432
504
  }
433
- if (ret.ok()) {
434
- if (fs_->ShouldInjectRandomReadError()) {
435
- ret = IOStatus::IOError("injected read error");
436
- } else {
437
- s = target_->ReadAsync(req, opts, cb, cb_arg, io_handle, del_fn, nullptr);
438
- }
439
- }
440
- if (!ret.ok()) {
441
- res.status = ret;
505
+ if (res_status.ok()) {
506
+ s = target_->ReadAsync(req, opts, cb, cb_arg, io_handle, del_fn, nullptr);
507
+ // TODO (low priority): fs_->ReadUnsyncedData()
508
+ } else {
509
+ // If there’s no injected error, then cb will be called asynchronously when
510
+ // target_ actually finishes the read. But if there’s an injected error, it
511
+ // needs to immediately call cb(res, cb_arg) s since target_->ReadAsync()
512
+ // isn’t invoked at all.
513
+ res.status = res_status;
442
514
  cb(res, cb_arg);
443
515
  }
516
+ // We return ReadAsync()'s status intead of injected error status here since
517
+ // the return status is not supposed to be the status of the actual IO (i.e,
518
+ // the actual async read). The actual status of the IO will be passed to cb()
519
+ // callback upon the actual read finishes or like above when injected error
520
+ // happens.
444
521
  return s;
445
522
  }
446
523
 
@@ -451,6 +528,7 @@ IOStatus TestFSRandomAccessFile::MultiRead(FSReadRequest* reqs, size_t num_reqs,
451
528
  return fs_->GetError();
452
529
  }
453
530
  IOStatus s = target_->MultiRead(reqs, num_reqs, options, dbg);
531
+ // TODO (low priority): fs_->ReadUnsyncedData()
454
532
  bool injected_error = false;
455
533
  for (size_t i = 0; i < num_reqs; i++) {
456
534
  if (!reqs[i].status.ok()) {
@@ -458,7 +536,8 @@ IOStatus TestFSRandomAccessFile::MultiRead(FSReadRequest* reqs, size_t num_reqs,
458
536
  break;
459
537
  }
460
538
  bool this_injected_error;
461
- reqs[i].status = fs_->InjectThreadSpecificReadError(
539
+ reqs[i].status = fs_->MaybeInjectThreadLocalError(
540
+ FaultInjectionIOType::kRead, options, "",
462
541
  FaultInjectionTestFS::ErrorOperation::kRead, &(reqs[i].result),
463
542
  use_direct_io(), reqs[i].scratch,
464
543
  /*need_count_increase=*/true,
@@ -466,14 +545,12 @@ IOStatus TestFSRandomAccessFile::MultiRead(FSReadRequest* reqs, size_t num_reqs,
466
545
  injected_error |= this_injected_error;
467
546
  }
468
547
  if (s.ok()) {
469
- s = fs_->InjectThreadSpecificReadError(
548
+ s = fs_->MaybeInjectThreadLocalError(
549
+ FaultInjectionIOType::kRead, options, "",
470
550
  FaultInjectionTestFS::ErrorOperation::kMultiRead, nullptr,
471
551
  use_direct_io(), nullptr, /*need_count_increase=*/!injected_error,
472
552
  /*fault_injected=*/nullptr);
473
553
  }
474
- if (s.ok() && fs_->ShouldInjectRandomReadError()) {
475
- return IOStatus::IOError("injected read error");
476
- }
477
554
  return s;
478
555
  }
479
556
 
@@ -484,13 +561,196 @@ size_t TestFSRandomAccessFile::GetUniqueId(char* id, size_t max_size) const {
484
561
  return target_->GetUniqueId(id, max_size);
485
562
  }
486
563
  }
564
+
565
+ namespace {
566
+ // Modifies `result` to start at the beginning of `scratch` if not already,
567
+ // copying data there if needed.
568
+ void MoveToScratchIfNeeded(Slice* result, char* scratch) {
569
+ if (result->data() != scratch) {
570
+ // NOTE: might overlap, where result is later in scratch
571
+ std::copy(result->data(), result->data() + result->size(), scratch);
572
+ *result = Slice(scratch, result->size());
573
+ }
574
+ }
575
+ } // namespace
576
+
577
+ void FaultInjectionTestFS::ReadUnsynced(const std::string& fname,
578
+ uint64_t offset, size_t n,
579
+ Slice* result, char* scratch,
580
+ int64_t* pos_at_last_sync) {
581
+ *result = Slice(scratch, 0); // default empty result
582
+ assert(*pos_at_last_sync == -1); // default "unknown"
583
+
584
+ MutexLock l(&mutex_);
585
+ auto it = db_file_state_.find(fname);
586
+ if (it != db_file_state_.end()) {
587
+ auto& st = it->second;
588
+ *pos_at_last_sync = static_cast<int64_t>(st.pos_at_last_sync_);
589
+ // Find overlap between [offset, offset + n) and
590
+ // [*pos_at_last_sync, *pos_at_last_sync + st.buffer_.size())
591
+ int64_t begin = std::max(static_cast<int64_t>(offset), *pos_at_last_sync);
592
+ int64_t end =
593
+ std::min(static_cast<int64_t>(offset + n),
594
+ *pos_at_last_sync + static_cast<int64_t>(st.buffer_.size()));
595
+
596
+ // Copy and return overlap if there is any
597
+ if (begin < end) {
598
+ size_t offset_in_buffer = static_cast<size_t>(begin - *pos_at_last_sync);
599
+ size_t offset_in_scratch = static_cast<size_t>(begin - offset);
600
+ std::copy_n(st.buffer_.data() + offset_in_buffer, end - begin,
601
+ scratch + offset_in_scratch);
602
+ *result = Slice(scratch + offset_in_scratch, end - begin);
603
+ }
604
+ }
605
+ }
606
+
487
607
  IOStatus TestFSSequentialFile::Read(size_t n, const IOOptions& options,
488
608
  Slice* result, char* scratch,
489
609
  IODebugContext* dbg) {
490
- IOStatus s = target()->Read(n, options, result, scratch, dbg);
491
- if (s.ok() && fs_->ShouldInjectRandomReadError()) {
492
- return IOStatus::IOError("injected seq read error");
610
+ IOStatus s = fs_->MaybeInjectThreadLocalError(
611
+ FaultInjectionIOType::kRead, options, "",
612
+ FaultInjectionTestFS::ErrorOperation::kRead, result, use_direct_io(),
613
+ scratch, true /*need_count_increase=*/, nullptr /* fault_injected*/);
614
+ if (!s.ok()) {
615
+ return s;
616
+ }
617
+
618
+ // Some complex logic is needed to deal with concurrent write to the same
619
+ // file, while keeping good performance (e.g. not holding FS mutex during
620
+ // I/O op), especially in common cases.
621
+
622
+ if (read_pos_ == target_read_pos_) {
623
+ // Normal case: start by reading from underlying file
624
+ s = target()->Read(n, options, result, scratch, dbg);
625
+ if (!s.ok()) {
626
+ return s;
627
+ }
628
+ target_read_pos_ += result->size();
629
+ } else {
630
+ // We must have previously read buffered data (unsynced) not written to
631
+ // target. Deal with this case (and more) below.
632
+ *result = {};
633
+ }
634
+
635
+ if (fs_->ReadUnsyncedData() && result->size() < n) {
636
+ // We need to check if there's unsynced data to fill out the rest of the
637
+ // read.
638
+
639
+ // First, ensure target read data is in scratch for easy handling.
640
+ MoveToScratchIfNeeded(result, scratch);
641
+ assert(result->data() == scratch);
642
+
643
+ // If we just did a target Read, we only want unsynced data after it
644
+ // (target_read_pos_). Otherwise (e.g. if target is behind because of
645
+ // unsynced data) we want unsynced data starting at the current read pos
646
+ // (read_pos_, not yet updated).
647
+ const uint64_t unsynced_read_pos = std::max(target_read_pos_, read_pos_);
648
+ const size_t offset_from_read_pos =
649
+ static_cast<size_t>(unsynced_read_pos - read_pos_);
650
+ Slice unsynced_result;
651
+ int64_t pos_at_last_sync = -1;
652
+ fs_->ReadUnsynced(fname_, unsynced_read_pos, n - offset_from_read_pos,
653
+ &unsynced_result, scratch + offset_from_read_pos,
654
+ &pos_at_last_sync);
655
+ assert(unsynced_result.data() >= scratch + offset_from_read_pos);
656
+ assert(unsynced_result.data() < scratch + n);
657
+ // Now, there are several cases to consider (some grouped together):
658
+ if (pos_at_last_sync <= static_cast<int64_t>(unsynced_read_pos)) {
659
+ // 1. We didn't get any unsynced data because nothing has been written
660
+ // to the file beyond unsynced_read_pos (including untracked
661
+ // pos_at_last_sync == -1)
662
+ // 2. We got some unsynced data starting at unsynced_read_pos (possibly
663
+ // on top of some synced data from target). We don't need to try reading
664
+ // any more from target because we established a "point in time" for
665
+ // completing this Read in which we read as much tail data (unsynced) as
666
+ // we could.
667
+
668
+ // We got pos_at_last_sync info if we got any unsynced data.
669
+ assert(pos_at_last_sync >= 0 || unsynced_result.size() == 0);
670
+
671
+ // Combined data is already lined up in scratch.
672
+ assert(result->data() + result->size() == unsynced_result.data());
673
+ assert(result->size() + unsynced_result.size() <= n);
674
+ // Combine results
675
+ *result = Slice(result->data(), result->size() + unsynced_result.size());
676
+ } else {
677
+ // 3. Any unsynced data we got was after unsynced_read_pos because the
678
+ // file was synced some time since our last target Read (either from this
679
+ // Read or a prior Read). We need to read more data from target to ensure
680
+ // this Read is filled out, even though we might have already read some
681
+ // (but not all due to a race). This code handles:
682
+ //
683
+ // * Catching up target after prior read(s) of unsynced data
684
+ // * Racing Sync in another thread since we called target Read above
685
+ //
686
+ // And merging potentially three results together for this Read:
687
+ // * The original target Read above
688
+ // * The following (non-throw-away) target Read
689
+ // * The ReadUnsynced above, which is always last if it returned data,
690
+ // so that we have a "point in time" for completing this Read in which we
691
+ // read as much tail data (unsynced) as we could.
692
+ //
693
+ // Deeper note about the race: we cannot just treat the original target
694
+ // Read as a "point in time" view of available data in the file, because
695
+ // there might have been unsynced data at that time, which became synced
696
+ // data by the time we read unsynced data. That is the race we are
697
+ // resolving with this "double check"-style code.
698
+ const size_t supplemental_read_pos = unsynced_read_pos;
699
+
700
+ // First, if there's any data from target that we know we would need to
701
+ // throw away to catch up, try to do it.
702
+ if (target_read_pos_ < supplemental_read_pos) {
703
+ Slice throw_away_result;
704
+ size_t throw_away_n = supplemental_read_pos - target_read_pos_;
705
+ std::unique_ptr<char[]> throw_away_scratch{new char[throw_away_n]};
706
+ s = target()->Read(throw_away_n, options, &throw_away_result,
707
+ throw_away_scratch.get(), dbg);
708
+ if (!s.ok()) {
709
+ read_pos_ += result->size();
710
+ return s;
711
+ }
712
+ target_read_pos_ += throw_away_result.size();
713
+ if (target_read_pos_ < supplemental_read_pos) {
714
+ // Because of pos_at_last_sync > supplemental_read_pos, we should
715
+ // have been able to catch up
716
+ read_pos_ += result->size();
717
+ return IOStatus::IOError(
718
+ "Unexpected truncation or short read of file " + fname_);
719
+ }
720
+ }
721
+ // Now we can do a productive supplemental Read from target
722
+ assert(target_read_pos_ == supplemental_read_pos);
723
+ Slice supplemental_result;
724
+ size_t supplemental_n =
725
+ unsynced_result.size() == 0
726
+ ? n - offset_from_read_pos
727
+ : unsynced_result.data() - (scratch + offset_from_read_pos);
728
+ s = target()->Read(supplemental_n, options, &supplemental_result,
729
+ scratch + offset_from_read_pos, dbg);
730
+ if (!s.ok()) {
731
+ read_pos_ += result->size();
732
+ return s;
733
+ }
734
+ target_read_pos_ += supplemental_result.size();
735
+ MoveToScratchIfNeeded(&supplemental_result,
736
+ scratch + offset_from_read_pos);
737
+
738
+ // Combined data is already lined up in scratch.
739
+ assert(result->data() + result->size() == supplemental_result.data());
740
+ assert(unsynced_result.size() == 0 ||
741
+ supplemental_result.data() + supplemental_result.size() ==
742
+ unsynced_result.data());
743
+ assert(result->size() + supplemental_result.size() +
744
+ unsynced_result.size() <=
745
+ n);
746
+ // Combine results
747
+ *result =
748
+ Slice(result->data(), result->size() + supplemental_result.size() +
749
+ unsynced_result.size());
750
+ }
493
751
  }
752
+ read_pos_ += result->size();
753
+
494
754
  return s;
495
755
  }
496
756
 
@@ -498,11 +758,16 @@ IOStatus TestFSSequentialFile::PositionedRead(uint64_t offset, size_t n,
498
758
  const IOOptions& options,
499
759
  Slice* result, char* scratch,
500
760
  IODebugContext* dbg) {
501
- IOStatus s =
502
- target()->PositionedRead(offset, n, options, result, scratch, dbg);
503
- if (s.ok() && fs_->ShouldInjectRandomReadError()) {
504
- return IOStatus::IOError("injected seq positioned read error");
761
+ IOStatus s = fs_->MaybeInjectThreadLocalError(
762
+ FaultInjectionIOType::kRead, options, "",
763
+ FaultInjectionTestFS::ErrorOperation::kRead, result, use_direct_io(),
764
+ scratch, true /*need_count_increase=*/, nullptr /* fault_injected */);
765
+ if (!s.ok()) {
766
+ return s;
505
767
  }
768
+
769
+ s = target()->PositionedRead(offset, n, options, result, scratch, dbg);
770
+ // TODO (low priority): fs_->ReadUnsyncedData()
506
771
  return s;
507
772
  }
508
773
 
@@ -519,24 +784,77 @@ IOStatus FaultInjectionTestFS::NewDirectory(
519
784
  return IOStatus::OK();
520
785
  }
521
786
 
787
+ IOStatus FaultInjectionTestFS::FileExists(const std::string& fname,
788
+ const IOOptions& options,
789
+ IODebugContext* dbg) {
790
+ if (!IsFilesystemActive()) {
791
+ return GetError();
792
+ }
793
+
794
+ IOStatus io_s =
795
+ MaybeInjectThreadLocalError(FaultInjectionIOType::kMetadataRead, options);
796
+ if (!io_s.ok()) {
797
+ return io_s;
798
+ }
799
+
800
+ io_s = target()->FileExists(fname, options, dbg);
801
+ return io_s;
802
+ }
803
+
804
+ IOStatus FaultInjectionTestFS::GetChildren(const std::string& dir,
805
+ const IOOptions& options,
806
+ std::vector<std::string>* result,
807
+ IODebugContext* dbg) {
808
+ if (!IsFilesystemActive()) {
809
+ return GetError();
810
+ }
811
+
812
+ IOStatus io_s =
813
+ MaybeInjectThreadLocalError(FaultInjectionIOType::kMetadataRead, options);
814
+ if (!io_s.ok()) {
815
+ return io_s;
816
+ }
817
+
818
+ io_s = target()->GetChildren(dir, options, result, dbg);
819
+ return io_s;
820
+ }
821
+
822
+ IOStatus FaultInjectionTestFS::GetChildrenFileAttributes(
823
+ const std::string& dir, const IOOptions& options,
824
+ std::vector<FileAttributes>* result, IODebugContext* dbg) {
825
+ if (!IsFilesystemActive()) {
826
+ return GetError();
827
+ }
828
+
829
+ IOStatus io_s =
830
+ MaybeInjectThreadLocalError(FaultInjectionIOType::kMetadataRead, options);
831
+ if (!io_s.ok()) {
832
+ return io_s;
833
+ }
834
+
835
+ io_s = target()->GetChildrenFileAttributes(dir, options, result, dbg);
836
+ return io_s;
837
+ }
838
+
522
839
  IOStatus FaultInjectionTestFS::NewWritableFile(
523
840
  const std::string& fname, const FileOptions& file_opts,
524
841
  std::unique_ptr<FSWritableFile>* result, IODebugContext* dbg) {
525
842
  if (!IsFilesystemActive()) {
526
843
  return GetError();
527
844
  }
528
- {
529
- IOStatus in_s = InjectMetadataWriteError();
530
- if (!in_s.ok()) {
531
- return in_s;
532
- }
533
- }
534
845
 
535
- if (ShouldUseDiretWritable(fname)) {
846
+ if (IsFilesystemDirectWritable()) {
536
847
  return target()->NewWritableFile(fname, file_opts, result, dbg);
537
848
  }
538
849
 
539
- IOStatus io_s = target()->NewWritableFile(fname, file_opts, result, dbg);
850
+ IOStatus io_s = MaybeInjectThreadLocalError(
851
+ FaultInjectionIOType::kWrite, file_opts.io_options, fname,
852
+ FaultInjectionTestFS::ErrorOperation::kOpen);
853
+ if (!io_s.ok()) {
854
+ return io_s;
855
+ }
856
+
857
+ io_s = target()->NewWritableFile(fname, file_opts, result, dbg);
540
858
  if (io_s.ok()) {
541
859
  result->reset(
542
860
  new TestFSWritableFile(fname, file_opts, std::move(*result), this));
@@ -553,12 +871,6 @@ IOStatus FaultInjectionTestFS::NewWritableFile(
553
871
  // dropping unsynced files.
554
872
  list[dir_and_name.second] = kNewFileNoOverwrite;
555
873
  }
556
- {
557
- IOStatus in_s = InjectMetadataWriteError();
558
- if (!in_s.ok()) {
559
- return in_s;
560
- }
561
- }
562
874
  }
563
875
  return io_s;
564
876
  }
@@ -569,19 +881,18 @@ IOStatus FaultInjectionTestFS::ReopenWritableFile(
569
881
  if (!IsFilesystemActive()) {
570
882
  return GetError();
571
883
  }
572
- if (ShouldUseDiretWritable(fname)) {
884
+ if (IsFilesystemDirectWritable()) {
573
885
  return target()->ReopenWritableFile(fname, file_opts, result, dbg);
574
886
  }
575
- {
576
- IOStatus in_s = InjectMetadataWriteError();
577
- if (!in_s.ok()) {
578
- return in_s;
579
- }
887
+ IOStatus io_s = MaybeInjectThreadLocalError(FaultInjectionIOType::kWrite,
888
+ file_opts.io_options, fname);
889
+ if (!io_s.ok()) {
890
+ return io_s;
580
891
  }
581
892
 
582
893
  bool exists;
583
- IOStatus io_s,
584
- exists_s = target()->FileExists(fname, IOOptions(), nullptr /* dbg */);
894
+ IOStatus exists_s =
895
+ target()->FileExists(fname, IOOptions(), nullptr /* dbg */);
585
896
  if (exists_s.IsNotFound()) {
586
897
  exists = false;
587
898
  } else if (exists_s.ok()) {
@@ -591,10 +902,12 @@ IOStatus FaultInjectionTestFS::ReopenWritableFile(
591
902
  exists = false;
592
903
  }
593
904
 
594
- if (io_s.ok()) {
595
- io_s = target()->ReopenWritableFile(fname, file_opts, result, dbg);
905
+ if (!io_s.ok()) {
906
+ return io_s;
596
907
  }
597
908
 
909
+ io_s = target()->ReopenWritableFile(fname, file_opts, result, dbg);
910
+
598
911
  // Only track files we created. Files created outside of this
599
912
  // `FaultInjectionTestFS` are not eligible for tracking/data dropping
600
913
  // (for example, they may contain data a previous db_stress run expects to
@@ -623,32 +936,38 @@ IOStatus FaultInjectionTestFS::ReopenWritableFile(
623
936
  result->reset(
624
937
  new TestFSWritableFile(fname, file_opts, std::move(*result), this));
625
938
  }
626
- {
627
- IOStatus in_s = InjectMetadataWriteError();
628
- if (!in_s.ok()) {
629
- return in_s;
630
- }
631
- }
632
939
  }
633
940
  return io_s;
634
941
  }
635
942
 
943
+ IOStatus FaultInjectionTestFS::ReuseWritableFile(
944
+ const std::string& fname, const std::string& old_fname,
945
+ const FileOptions& file_opts, std::unique_ptr<FSWritableFile>* result,
946
+ IODebugContext* dbg) {
947
+ IOStatus s = RenameFile(old_fname, fname, file_opts.io_options, dbg);
948
+ if (!s.ok()) {
949
+ return s;
950
+ }
951
+ return NewWritableFile(fname, file_opts, result, dbg);
952
+ }
953
+
636
954
  IOStatus FaultInjectionTestFS::NewRandomRWFile(
637
955
  const std::string& fname, const FileOptions& file_opts,
638
956
  std::unique_ptr<FSRandomRWFile>* result, IODebugContext* dbg) {
639
957
  if (!IsFilesystemActive()) {
640
958
  return GetError();
641
959
  }
642
- if (ShouldUseDiretWritable(fname)) {
960
+ if (IsFilesystemDirectWritable()) {
643
961
  return target()->NewRandomRWFile(fname, file_opts, result, dbg);
644
962
  }
645
- {
646
- IOStatus in_s = InjectMetadataWriteError();
647
- if (!in_s.ok()) {
648
- return in_s;
649
- }
963
+ IOStatus io_s = MaybeInjectThreadLocalError(FaultInjectionIOType::kWrite,
964
+ file_opts.io_options, fname);
965
+ if (!io_s.ok()) {
966
+ return io_s;
650
967
  }
651
- IOStatus io_s = target()->NewRandomRWFile(fname, file_opts, result, dbg);
968
+
969
+ io_s = target()->NewRandomRWFile(fname, file_opts, result, dbg);
970
+
652
971
  if (io_s.ok()) {
653
972
  result->reset(new TestFSRandomRWFile(fname, std::move(*result), this));
654
973
  // WritableFileWriter* file is opened
@@ -663,12 +982,6 @@ IOStatus FaultInjectionTestFS::NewRandomRWFile(
663
982
  // implementation by ignoring it.
664
983
  list[dir_and_name.second] = kNewFileNoOverwrite;
665
984
  }
666
- {
667
- IOStatus in_s = InjectMetadataWriteError();
668
- if (!in_s.ok()) {
669
- return in_s;
670
- }
671
- }
672
985
  }
673
986
  return io_s;
674
987
  }
@@ -679,16 +992,17 @@ IOStatus FaultInjectionTestFS::NewRandomAccessFile(
679
992
  if (!IsFilesystemActive()) {
680
993
  return GetError();
681
994
  }
682
- if (ShouldInjectRandomReadError()) {
683
- return IOStatus::IOError("injected error when open random access file");
684
- }
685
- IOStatus io_s = InjectThreadSpecificReadError(ErrorOperation::kOpen, nullptr,
686
- false, nullptr,
687
- /*need_count_increase=*/true,
688
- /*fault_injected=*/nullptr);
689
- if (io_s.ok()) {
690
- io_s = target()->NewRandomAccessFile(fname, file_opts, result, dbg);
995
+ IOStatus io_s = MaybeInjectThreadLocalError(
996
+ FaultInjectionIOType::kRead, file_opts.io_options, fname,
997
+ ErrorOperation::kOpen, nullptr /* result */, false /* direct_io */,
998
+ nullptr /* scratch */, true /*need_count_increase*/,
999
+ nullptr /*fault_injected*/);
1000
+ if (!io_s.ok()) {
1001
+ return io_s;
691
1002
  }
1003
+
1004
+ io_s = target()->NewRandomAccessFile(fname, file_opts, result, dbg);
1005
+
692
1006
  if (io_s.ok()) {
693
1007
  result->reset(new TestFSRandomAccessFile(fname, std::move(*result), this));
694
1008
  }
@@ -701,13 +1015,19 @@ IOStatus FaultInjectionTestFS::NewSequentialFile(
701
1015
  if (!IsFilesystemActive()) {
702
1016
  return GetError();
703
1017
  }
704
-
705
- if (ShouldInjectRandomReadError()) {
706
- return IOStatus::IOError("injected read error when creating seq file");
1018
+ IOStatus io_s = MaybeInjectThreadLocalError(
1019
+ FaultInjectionIOType::kRead, file_opts.io_options, fname,
1020
+ ErrorOperation::kOpen, nullptr /* result */, false /* direct_io */,
1021
+ nullptr /* scratch */, true /*need_count_increase*/,
1022
+ nullptr /*fault_injected*/);
1023
+ if (!io_s.ok()) {
1024
+ return io_s;
707
1025
  }
708
- IOStatus io_s = target()->NewSequentialFile(fname, file_opts, result, dbg);
1026
+
1027
+ io_s = target()->NewSequentialFile(fname, file_opts, result, dbg);
1028
+
709
1029
  if (io_s.ok()) {
710
- result->reset(new TestFSSequentialFile(std::move(*result), this));
1030
+ result->reset(new TestFSSequentialFile(std::move(*result), this, fname));
711
1031
  }
712
1032
  return io_s;
713
1033
  }
@@ -718,25 +1038,66 @@ IOStatus FaultInjectionTestFS::DeleteFile(const std::string& f,
718
1038
  if (!IsFilesystemActive()) {
719
1039
  return GetError();
720
1040
  }
721
- {
722
- IOStatus in_s = InjectMetadataWriteError();
723
- if (!in_s.ok()) {
724
- return in_s;
725
- }
1041
+ IOStatus io_s = MaybeInjectThreadLocalError(
1042
+ FaultInjectionIOType::kMetadataWrite, options);
1043
+ if (!io_s.ok()) {
1044
+ return io_s;
726
1045
  }
727
- IOStatus io_s = FileSystemWrapper::DeleteFile(f, options, dbg);
1046
+
1047
+ io_s = FileSystemWrapper::DeleteFile(f, options, dbg);
1048
+
728
1049
  if (io_s.ok()) {
729
1050
  UntrackFile(f);
730
- {
731
- IOStatus in_s = InjectMetadataWriteError();
732
- if (!in_s.ok()) {
733
- return in_s;
734
- }
1051
+ }
1052
+ return io_s;
1053
+ }
1054
+
1055
+ IOStatus FaultInjectionTestFS::GetFileSize(const std::string& f,
1056
+ const IOOptions& options,
1057
+ uint64_t* file_size,
1058
+ IODebugContext* dbg) {
1059
+ if (!IsFilesystemActive()) {
1060
+ return GetError();
1061
+ }
1062
+ IOStatus io_s =
1063
+ MaybeInjectThreadLocalError(FaultInjectionIOType::kMetadataRead, options);
1064
+ if (!io_s.ok()) {
1065
+ return io_s;
1066
+ }
1067
+
1068
+ io_s = target()->GetFileSize(f, options, file_size, dbg);
1069
+ if (!io_s.ok()) {
1070
+ return io_s;
1071
+ }
1072
+
1073
+ if (ReadUnsyncedData()) {
1074
+ // Need to report flushed size, not synced size
1075
+ MutexLock l(&mutex_);
1076
+ auto it = db_file_state_.find(f);
1077
+ if (it != db_file_state_.end()) {
1078
+ *file_size = it->second.pos_at_last_append_;
735
1079
  }
736
1080
  }
737
1081
  return io_s;
738
1082
  }
739
1083
 
1084
+ IOStatus FaultInjectionTestFS::GetFileModificationTime(const std::string& fname,
1085
+ const IOOptions& options,
1086
+ uint64_t* file_mtime,
1087
+ IODebugContext* dbg) {
1088
+ if (!IsFilesystemActive()) {
1089
+ return GetError();
1090
+ }
1091
+ IOStatus io_s =
1092
+ MaybeInjectThreadLocalError(FaultInjectionIOType::kMetadataRead, options);
1093
+ if (!io_s.ok()) {
1094
+ return io_s;
1095
+ }
1096
+
1097
+ io_s = target()->GetFileModificationTime(fname, options, file_mtime, dbg);
1098
+ return io_s;
1099
+ }
1100
+
740
1101
  IOStatus FaultInjectionTestFS::RenameFile(const std::string& s,
741
1102
  const std::string& t,
742
1103
  const IOOptions& options,
@@ -744,11 +1105,10 @@ IOStatus FaultInjectionTestFS::RenameFile(const std::string& s,
744
1105
  if (!IsFilesystemActive()) {
745
1106
  return GetError();
746
1107
  }
747
- {
748
- IOStatus in_s = InjectMetadataWriteError();
749
- if (!in_s.ok()) {
750
- return in_s;
751
- }
1108
+ IOStatus io_s = MaybeInjectThreadLocalError(
1109
+ FaultInjectionIOType::kMetadataWrite, options);
1110
+ if (!io_s.ok()) {
1111
+ return io_s;
752
1112
  }
753
1113
 
754
1114
  // We preserve contents of overwritten files up to a size threshold.
@@ -763,7 +1123,7 @@ IOStatus FaultInjectionTestFS::RenameFile(const std::string& s,
763
1123
  ReadFileToString(target(), t, &previous_contents).PermitUncheckedError();
764
1124
  }
765
1125
  }
766
- IOStatus io_s = FileSystemWrapper::RenameFile(s, t, options, dbg);
1126
+ io_s = FileSystemWrapper::RenameFile(s, t, options, dbg);
767
1127
 
768
1128
  if (io_s.ok()) {
769
1129
  {
@@ -777,16 +1137,10 @@ IOStatus FaultInjectionTestFS::RenameFile(const std::string& s,
777
1137
  auto tdn = TestFSGetDirAndName(t);
778
1138
  if (dir_to_new_files_since_last_sync_[sdn.first].erase(sdn.second) != 0) {
779
1139
  auto& tlist = dir_to_new_files_since_last_sync_[tdn.first];
780
- assert(tlist.find(tdn.second) == tlist.end());
781
1140
  tlist[tdn.second] = previous_contents;
782
1141
  }
783
1142
  }
784
- IOStatus in_s = InjectMetadataWriteError();
785
- if (!in_s.ok()) {
786
- return in_s;
787
- }
788
1143
  }
789
-
790
1144
  return io_s;
791
1145
  }
792
1146
 
@@ -797,22 +1151,27 @@ IOStatus FaultInjectionTestFS::LinkFile(const std::string& s,
797
1151
  if (!IsFilesystemActive()) {
798
1152
  return GetError();
799
1153
  }
800
- {
801
- IOStatus in_s = InjectMetadataWriteError();
802
- if (!in_s.ok()) {
803
- return in_s;
804
- }
1154
+ IOStatus io_s = MaybeInjectThreadLocalError(
1155
+ FaultInjectionIOType::kMetadataWrite, options);
1156
+ if (!io_s.ok()) {
1157
+ return io_s;
805
1158
  }
806
1159
 
807
1160
  // Using the value in `dir_to_new_files_since_last_sync_` for the source file
808
1161
  // may be a more reasonable choice.
809
1162
  std::string previous_contents = kNewFileNoOverwrite;
810
1163
 
811
- IOStatus io_s = FileSystemWrapper::LinkFile(s, t, options, dbg);
1164
+ io_s = FileSystemWrapper::LinkFile(s, t, options, dbg);
812
1165
 
813
1166
  if (io_s.ok()) {
814
1167
  {
815
1168
  MutexLock l(&mutex_);
1169
+ if (!allow_link_open_file_ &&
1170
+ open_managed_files_.find(s) != open_managed_files_.end()) {
1171
+ fprintf(stderr, "Attempt to LinkFile while open for write: %s\n",
1172
+ s.c_str());
1173
+ abort();
1174
+ }
816
1175
  if (db_file_state_.find(s) != db_file_state_.end()) {
817
1176
  db_file_state_[t] = db_file_state_[s];
818
1177
  }
@@ -826,12 +1185,74 @@ IOStatus FaultInjectionTestFS::LinkFile(const std::string& s,
826
1185
  tlist[tdn.second] = previous_contents;
827
1186
  }
828
1187
  }
829
- IOStatus in_s = InjectMetadataWriteError();
830
- if (!in_s.ok()) {
831
- return in_s;
832
- }
833
1188
  }
1189
+ return io_s;
1190
+ }
834
1191
 
1192
+ IOStatus FaultInjectionTestFS::NumFileLinks(const std::string& fname,
1193
+ const IOOptions& options,
1194
+ uint64_t* count,
1195
+ IODebugContext* dbg) {
1196
+ if (!IsFilesystemActive()) {
1197
+ return GetError();
1198
+ }
1199
+ IOStatus io_s =
1200
+ MaybeInjectThreadLocalError(FaultInjectionIOType::kMetadataRead, options);
1201
+ if (!io_s.ok()) {
1202
+ return io_s;
1203
+ }
1204
+
1205
+ io_s = target()->NumFileLinks(fname, options, count, dbg);
1206
+ return io_s;
1207
+ }
1208
+
1209
+ IOStatus FaultInjectionTestFS::AreFilesSame(const std::string& first,
1210
+ const std::string& second,
1211
+ const IOOptions& options, bool* res,
1212
+ IODebugContext* dbg) {
1213
+ if (!IsFilesystemActive()) {
1214
+ return GetError();
1215
+ }
1216
+ IOStatus io_s =
1217
+ MaybeInjectThreadLocalError(FaultInjectionIOType::kMetadataRead, options);
1218
+ if (!io_s.ok()) {
1219
+ return io_s;
1220
+ }
1221
+
1222
+ io_s = target()->AreFilesSame(first, second, options, res, dbg);
1223
+ return io_s;
1224
+ }
1225
+
1226
+ IOStatus FaultInjectionTestFS::GetAbsolutePath(const std::string& db_path,
1227
+ const IOOptions& options,
1228
+ std::string* output_path,
1229
+ IODebugContext* dbg) {
1230
+ if (!IsFilesystemActive()) {
1231
+ return GetError();
1232
+ }
1233
+ IOStatus io_s =
1234
+ MaybeInjectThreadLocalError(FaultInjectionIOType::kMetadataRead, options);
1235
+ if (!io_s.ok()) {
1236
+ return io_s;
1237
+ }
1238
+
1239
+ io_s = target()->GetAbsolutePath(db_path, options, output_path, dbg);
1240
+ return io_s;
1241
+ }
1242
+
1243
+ IOStatus FaultInjectionTestFS::IsDirectory(const std::string& path,
1244
+ const IOOptions& options,
1245
+ bool* is_dir, IODebugContext* dgb) {
1246
+ if (!IsFilesystemActive()) {
1247
+ return GetError();
1248
+ }
1249
+ IOStatus io_s =
1250
+ MaybeInjectThreadLocalError(FaultInjectionIOType::kMetadataRead, options);
1251
+ if (!io_s.ok()) {
1252
+ return io_s;
1253
+ }
1254
+
1255
+ io_s = target()->IsDirectory(path, options, is_dir, dgb);
835
1256
  return io_s;
836
1257
  }
837
1258
 
@@ -948,14 +1369,17 @@ void FaultInjectionTestFS::UntrackFile(const std::string& f) {
948
1369
  open_managed_files_.erase(f);
949
1370
  }
950
1371
 
951
- IOStatus FaultInjectionTestFS::InjectThreadSpecificReadError(
952
- ErrorOperation op, Slice* result, bool direct_io, char* scratch,
953
- bool need_count_increase, bool* fault_injected) {
1372
+ IOStatus FaultInjectionTestFS::MaybeInjectThreadLocalReadError(
1373
+ const IOOptions& io_options, ErrorOperation op, Slice* result,
1374
+ bool direct_io, char* scratch, bool need_count_increase,
1375
+ bool* fault_injected) {
954
1376
  bool dummy_bool;
955
1377
  bool& ret_fault_injected = fault_injected ? *fault_injected : dummy_bool;
956
1378
  ret_fault_injected = false;
957
- ErrorContext* ctx = static_cast<ErrorContext*>(thread_local_error_->Get());
958
- if (ctx == nullptr || !ctx->enable_error_injection || !ctx->one_in) {
1379
+ ErrorContext* ctx =
1380
+ static_cast<ErrorContext*>(injected_thread_local_read_error_.Get());
1381
+ if (ctx == nullptr || !ctx->enable_error_injection || !ctx->one_in ||
1382
+ ShouldIOActivtiesExcludedFromFaultInjection(io_options.io_activity)) {
959
1383
  return IOStatus::OK();
960
1384
  }
961
1385
 
@@ -972,9 +1396,12 @@ IOStatus FaultInjectionTestFS::InjectThreadSpecificReadError(
972
1396
  }
973
1397
  ctx->callstack = port::SaveStack(&ctx->frames);
974
1398
 
1399
+ std::stringstream msg;
1400
+ msg << FaultInjectionTestFS::kInjected << " ";
975
1401
  if (op != ErrorOperation::kMultiReadSingleReq) {
976
1402
  // Likely non-per read status code for MultiRead
977
- ctx->message += "injected read error; ";
1403
+ msg << "read error";
1404
+ ctx->message = msg.str();
978
1405
  ret_fault_injected = true;
979
1406
  ret = IOStatus::IOError(ctx->message);
980
1407
  } else if (Random::GetTLSInstance()->OneIn(8)) {
@@ -982,7 +1409,8 @@ IOStatus FaultInjectionTestFS::InjectThreadSpecificReadError(
982
1409
  // For a small chance, set the failure to status but turn the
983
1410
  // result to be empty, which is supposed to be caught for a check.
984
1411
  *result = Slice();
985
- ctx->message += "injected empty result; ";
1412
+ msg << "empty result";
1413
+ ctx->message = msg.str();
986
1414
  ret_fault_injected = true;
987
1415
  } else if (!direct_io && Random::GetTLSInstance()->OneIn(7) &&
988
1416
  scratch != nullptr && result->data() == scratch) {
@@ -999,17 +1427,19 @@ IOStatus FaultInjectionTestFS::InjectThreadSpecificReadError(
999
1427
  // It would work for CRC. Not 100% sure for xxhash and will adjust
1000
1428
  // if it is not the case.
1001
1429
  const_cast<char*>(result->data())[result->size() - 1]++;
1002
- ctx->message += "injected corrupt last byte; ";
1430
+ msg << "corrupt last byte";
1431
+ ctx->message = msg.str();
1003
1432
  ret_fault_injected = true;
1004
1433
  } else {
1005
- ctx->message += "injected error result multiget single; ";
1434
+ msg << "error result multiget single";
1435
+ ctx->message = msg.str();
1006
1436
  ret_fault_injected = true;
1007
1437
  ret = IOStatus::IOError(ctx->message);
1008
1438
  }
1009
1439
  }
1010
- if (ctx->retryable) {
1011
- ret.SetRetryable(true);
1012
- }
1440
+
1441
+ ret.SetRetryable(ctx->retryable);
1442
+ ret.SetDataLoss(ctx->has_data_loss);
1013
1443
  return ret;
1014
1444
  }
1015
1445
 
@@ -1020,59 +1450,58 @@ bool FaultInjectionTestFS::TryParseFileName(const std::string& file_name,
1020
1450
  return ParseFileName(file, number, type);
1021
1451
  }
1022
1452
 
1023
- IOStatus FaultInjectionTestFS::InjectWriteError(const std::string& file_name) {
1024
- MutexLock l(&mutex_);
1025
- if (!enable_write_error_injection_ || !write_error_one_in_) {
1453
+ IOStatus FaultInjectionTestFS::MaybeInjectThreadLocalError(
1454
+ FaultInjectionIOType type, const IOOptions& io_options,
1455
+ const std::string& file_name, ErrorOperation op, Slice* result,
1456
+ bool direct_io, char* scratch, bool need_count_increase,
1457
+ bool* fault_injected) {
1458
+ if (type == FaultInjectionIOType::kRead) {
1459
+ return MaybeInjectThreadLocalReadError(io_options, op, result, direct_io,
1460
+ scratch, need_count_increase,
1461
+ fault_injected);
1462
+ }
1463
+
1464
+ ErrorContext* ctx = GetErrorContextFromFaultInjectionIOType(type);
1465
+ if (ctx == nullptr || !ctx->enable_error_injection || !ctx->one_in ||
1466
+ ShouldIOActivtiesExcludedFromFaultInjection(io_options.io_activity) ||
1467
+ (type == FaultInjectionIOType::kWrite &&
1468
+ ShouldExcludeFromWriteFaultInjection(file_name))) {
1026
1469
  return IOStatus::OK();
1027
1470
  }
1028
- bool allowed_type = false;
1029
-
1030
- if (inject_for_all_file_types_) {
1031
- allowed_type = true;
1032
- } else {
1033
- uint64_t number;
1034
- FileType cur_type = kTempFile;
1035
- if (TryParseFileName(file_name, &number, &cur_type)) {
1036
- for (const auto& type : write_error_allowed_types_) {
1037
- if (cur_type == type) {
1038
- allowed_type = true;
1039
- }
1040
- }
1041
- }
1042
- }
1043
1471
 
1044
- if (allowed_type) {
1045
- if (write_error_rand_.OneIn(write_error_one_in_)) {
1046
- return GetError();
1472
+ IOStatus ret;
1473
+ if (ctx->rand.OneIn(ctx->one_in)) {
1474
+ ctx->count++;
1475
+ if (ctx->callstack) {
1476
+ free(ctx->callstack);
1047
1477
  }
1048
- }
1049
- return IOStatus::OK();
1050
- }
1051
-
1052
- IOStatus FaultInjectionTestFS::InjectMetadataWriteError() {
1053
- {
1054
- MutexLock l(&mutex_);
1055
- if (!enable_metadata_write_error_injection_ ||
1056
- !metadata_write_error_one_in_ ||
1057
- !write_error_rand_.OneIn(metadata_write_error_one_in_)) {
1058
- return IOStatus::OK();
1478
+ ctx->callstack = port::SaveStack(&ctx->frames);
1479
+ ctx->message = GetErrorMessage(type, file_name, op);
1480
+ ret = IOStatus::IOError(ctx->message);
1481
+ ret.SetRetryable(ctx->retryable);
1482
+ ret.SetDataLoss(ctx->has_data_loss);
1483
+ if (type == FaultInjectionIOType::kWrite) {
1484
+ TEST_SYNC_POINT(
1485
+ "FaultInjectionTestFS::InjectMetadataWriteError:Injected");
1059
1486
  }
1060
1487
  }
1061
- TEST_SYNC_POINT("FaultInjectionTestFS::InjectMetadataWriteError:Injected");
1062
- return IOStatus::IOError("injected metadata write error");
1488
+ return ret;
1063
1489
  }
1064
1490
 
1065
- void FaultInjectionTestFS::PrintFaultBacktrace() {
1491
+ void FaultInjectionTestFS::PrintInjectedThreadLocalErrorBacktrace(
1492
+ FaultInjectionIOType type) {
1066
1493
  #if defined(OS_LINUX)
1067
- ErrorContext* ctx = static_cast<ErrorContext*>(thread_local_error_->Get());
1068
- if (ctx == nullptr) {
1069
- return;
1494
+ ErrorContext* ctx = GetErrorContextFromFaultInjectionIOType(type);
1495
+ if (ctx) {
1496
+ if (type == FaultInjectionIOType::kRead) {
1497
+ fprintf(stderr, "Injected read error type = %d\n", ctx->type);
1498
+ }
1499
+ fprintf(stderr, "Message: %s\n", ctx->message.c_str());
1500
+ port::PrintAndFreeStack(ctx->callstack, ctx->frames);
1501
+ ctx->callstack = nullptr;
1070
1502
  }
1071
- fprintf(stderr, "Injected error type = %d\n", ctx->type);
1072
- fprintf(stderr, "Message: %s\n", ctx->message.c_str());
1073
- port::PrintAndFreeStack(ctx->callstack, ctx->frames);
1074
- ctx->callstack = nullptr;
1503
+ #else
1504
+ (void)type;
1075
1505
  #endif
1076
1506
  }
1077
-
1078
1507
  } // namespace ROCKSDB_NAMESPACE