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.
- package/binding.c +92 -10
- package/index.js +9 -0
- package/lib/batch.js +11 -1
- package/lib/iterator.js +3 -1
- package/lib/snapshot.js +21 -0
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/rocksdb-native.bare +0 -0
- package/prebuilds/darwin-arm64/rocksdb-native.node +0 -0
- package/prebuilds/darwin-x64/rocksdb-native.bare +0 -0
- package/prebuilds/darwin-x64/rocksdb-native.node +0 -0
- package/prebuilds/linux-arm64/rocksdb-native.bare +0 -0
- package/prebuilds/linux-arm64/rocksdb-native.node +0 -0
- package/prebuilds/linux-x64/rocksdb-native.bare +0 -0
- package/prebuilds/linux-x64/rocksdb-native.node +0 -0
- package/prebuilds/win32-x64/rocksdb-native.bare +0 -0
- package/prebuilds/win32-x64/rocksdb-native.node +0 -0
- package/vendor/librocksdb/include/rocksdb.h +38 -4
- package/vendor/librocksdb/src/rocksdb.cc +114 -14
- package/vendor/librocksdb/vendor/rocksdb/CMakeLists.txt +21 -4
- package/vendor/librocksdb/vendor/rocksdb/cache/secondary_cache_adapter.cc +6 -3
- package/vendor/librocksdb/vendor/rocksdb/db/arena_wrapped_db_iter.cc +4 -4
- package/vendor/librocksdb/vendor/rocksdb/db/arena_wrapped_db_iter.h +4 -2
- package/vendor/librocksdb/vendor/rocksdb/db/attribute_group_iterator_impl.cc +20 -0
- package/vendor/librocksdb/vendor/rocksdb/db/attribute_group_iterator_impl.h +83 -0
- package/vendor/librocksdb/vendor/rocksdb/db/builder.cc +9 -5
- package/vendor/librocksdb/vendor/rocksdb/db/builder.h +1 -1
- package/vendor/librocksdb/vendor/rocksdb/db/c.cc +231 -6
- package/vendor/librocksdb/vendor/rocksdb/db/c_test.c +202 -2
- package/vendor/librocksdb/vendor/rocksdb/db/coalescing_iterator.cc +47 -0
- package/vendor/librocksdb/vendor/rocksdb/db/coalescing_iterator.h +79 -0
- package/vendor/librocksdb/vendor/rocksdb/db/column_family.cc +28 -0
- package/vendor/librocksdb/vendor/rocksdb/db/column_family.h +17 -0
- package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction.cc +8 -1
- package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction.h +11 -9
- package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_iterator.cc +50 -23
- package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_iterator.h +13 -0
- package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_job.cc +22 -25
- package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_job.h +2 -0
- package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_outputs.cc +8 -1
- package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_outputs.h +1 -0
- package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_picker.cc +40 -17
- package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_picker.h +20 -14
- package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_picker_level.cc +11 -6
- package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_picker_universal.cc +77 -24
- package/vendor/librocksdb/vendor/rocksdb/db/compaction/compaction_service_job.cc +2 -0
- package/vendor/librocksdb/vendor/rocksdb/db/convenience.cc +3 -0
- package/vendor/librocksdb/vendor/rocksdb/db/db_filesnapshot.cc +125 -31
- package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl.cc +457 -231
- package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl.h +172 -73
- package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_compaction_flush.cc +152 -133
- package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_debug.cc +5 -0
- package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_files.cc +58 -52
- package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_follower.cc +348 -0
- package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_follower.h +54 -0
- package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_open.cc +136 -117
- package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_secondary.cc +4 -3
- package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_secondary.h +7 -6
- package/vendor/librocksdb/vendor/rocksdb/db/db_impl/db_impl_write.cc +134 -80
- package/vendor/librocksdb/vendor/rocksdb/db/db_iter.cc +11 -0
- package/vendor/librocksdb/vendor/rocksdb/db/db_test2.cc +1 -1
- package/vendor/librocksdb/vendor/rocksdb/db/db_test_util.cc +11 -1
- package/vendor/librocksdb/vendor/rocksdb/db/db_test_util.h +11 -7
- package/vendor/librocksdb/vendor/rocksdb/db/dbformat.cc +19 -4
- package/vendor/librocksdb/vendor/rocksdb/db/dbformat.h +3 -2
- package/vendor/librocksdb/vendor/rocksdb/db/error_handler.cc +34 -39
- package/vendor/librocksdb/vendor/rocksdb/db/error_handler.h +3 -4
- package/vendor/librocksdb/vendor/rocksdb/db/event_helpers.cc +6 -3
- package/vendor/librocksdb/vendor/rocksdb/db/experimental.cc +3 -2
- package/vendor/librocksdb/vendor/rocksdb/db/external_sst_file_ingestion_job.cc +76 -18
- package/vendor/librocksdb/vendor/rocksdb/db/external_sst_file_ingestion_job.h +11 -0
- package/vendor/librocksdb/vendor/rocksdb/db/flush_job.cc +37 -5
- package/vendor/librocksdb/vendor/rocksdb/db/flush_job.h +14 -0
- package/vendor/librocksdb/vendor/rocksdb/db/import_column_family_job.cc +49 -45
- package/vendor/librocksdb/vendor/rocksdb/db/internal_stats.cc +60 -1
- package/vendor/librocksdb/vendor/rocksdb/db/internal_stats.h +20 -1
- package/vendor/librocksdb/vendor/rocksdb/db/log_reader.cc +15 -6
- package/vendor/librocksdb/vendor/rocksdb/db/log_writer.cc +59 -10
- package/vendor/librocksdb/vendor/rocksdb/db/log_writer.h +8 -0
- package/vendor/librocksdb/vendor/rocksdb/db/memtable.cc +24 -40
- package/vendor/librocksdb/vendor/rocksdb/db/memtable.h +10 -10
- package/vendor/librocksdb/vendor/rocksdb/db/memtable_list.cc +9 -8
- package/vendor/librocksdb/vendor/rocksdb/db/multi_cf_iterator_impl.h +296 -0
- package/vendor/librocksdb/vendor/rocksdb/db/range_tombstone_fragmenter.h +8 -10
- package/vendor/librocksdb/vendor/rocksdb/db/repair.cc +4 -3
- package/vendor/librocksdb/vendor/rocksdb/db/seqno_to_time_mapping.cc +30 -0
- package/vendor/librocksdb/vendor/rocksdb/db/seqno_to_time_mapping.h +9 -0
- package/vendor/librocksdb/vendor/rocksdb/db/table_cache.cc +17 -2
- package/vendor/librocksdb/vendor/rocksdb/db/table_cache.h +9 -1
- package/vendor/librocksdb/vendor/rocksdb/db/table_properties_collector.h +9 -2
- package/vendor/librocksdb/vendor/rocksdb/db/transaction_log_impl.cc +3 -3
- package/vendor/librocksdb/vendor/rocksdb/db/transaction_log_impl.h +7 -7
- package/vendor/librocksdb/vendor/rocksdb/db/version_edit.cc +0 -1
- package/vendor/librocksdb/vendor/rocksdb/db/version_edit_handler.cc +39 -5
- package/vendor/librocksdb/vendor/rocksdb/db/version_edit_handler.h +24 -15
- package/vendor/librocksdb/vendor/rocksdb/db/version_set.cc +117 -64
- package/vendor/librocksdb/vendor/rocksdb/db/version_set.h +27 -10
- package/vendor/librocksdb/vendor/rocksdb/db/wal_manager.cc +37 -29
- package/vendor/librocksdb/vendor/rocksdb/db/wal_manager.h +6 -5
- package/vendor/librocksdb/vendor/rocksdb/db/wide/wide_columns.cc +2 -3
- package/vendor/librocksdb/vendor/rocksdb/db/wide/wide_columns_helper.cc +6 -0
- package/vendor/librocksdb/vendor/rocksdb/db/write_batch.cc +89 -31
- package/vendor/librocksdb/vendor/rocksdb/db/write_thread.cc +53 -5
- package/vendor/librocksdb/vendor/rocksdb/db/write_thread.h +36 -4
- package/vendor/librocksdb/vendor/rocksdb/env/composite_env_wrapper.h +21 -0
- package/vendor/librocksdb/vendor/rocksdb/env/env.cc +15 -0
- package/vendor/librocksdb/vendor/rocksdb/env/fs_on_demand.cc +331 -0
- package/vendor/librocksdb/vendor/rocksdb/env/fs_on_demand.h +139 -0
- package/vendor/librocksdb/vendor/rocksdb/env/io_posix.cc +8 -6
- package/vendor/librocksdb/vendor/rocksdb/env/io_posix.h +1 -1
- package/vendor/librocksdb/vendor/rocksdb/file/delete_scheduler.cc +130 -27
- package/vendor/librocksdb/vendor/rocksdb/file/delete_scheduler.h +61 -8
- package/vendor/librocksdb/vendor/rocksdb/file/file_util.cc +25 -4
- package/vendor/librocksdb/vendor/rocksdb/file/file_util.h +15 -0
- package/vendor/librocksdb/vendor/rocksdb/file/sequence_file_reader.cc +1 -0
- package/vendor/librocksdb/vendor/rocksdb/file/sequence_file_reader.h +9 -4
- package/vendor/librocksdb/vendor/rocksdb/file/sst_file_manager_impl.cc +18 -0
- package/vendor/librocksdb/vendor/rocksdb/file/sst_file_manager_impl.h +31 -4
- package/vendor/librocksdb/vendor/rocksdb/file/writable_file_writer.cc +40 -38
- package/vendor/librocksdb/vendor/rocksdb/file/writable_file_writer.h +48 -15
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/advanced_options.h +12 -3
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/attribute_groups.h +114 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/c.h +90 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/cache.h +5 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/comparator.h +27 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/db.h +71 -12
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/env.h +9 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/experimental.h +5 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/file_system.h +14 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/iterator.h +9 -71
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/iterator_base.h +90 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/listener.h +21 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/options.h +125 -12
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/perf_context.h +1 -1
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/sst_file_reader.h +11 -1
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/table.h +6 -6
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/table_properties.h +19 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/transaction_log.h +12 -6
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/types.h +12 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/universal_compaction.h +31 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/user_write_callback.h +29 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/cache_dump_load.h +4 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/checkpoint.h +4 -2
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/customizable_util.h +0 -1
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/env_mirror.h +1 -1
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/ldb_cmd.h +24 -7
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/option_change_migration.h +4 -4
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/stackable_db.h +24 -5
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/table_properties_collectors.h +46 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/transaction.h +42 -17
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/transaction_db.h +5 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/types_util.h +36 -0
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/utilities/write_batch_with_index.h +71 -3
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/version.h +2 -2
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/wide_columns.h +87 -72
- package/vendor/librocksdb/vendor/rocksdb/include/rocksdb/write_batch_base.h +1 -1
- package/vendor/librocksdb/vendor/rocksdb/memory/memory_allocator.cc +1 -0
- package/vendor/librocksdb/vendor/rocksdb/options/cf_options.cc +13 -2
- package/vendor/librocksdb/vendor/rocksdb/options/cf_options.h +6 -2
- package/vendor/librocksdb/vendor/rocksdb/options/db_options.cc +27 -1
- package/vendor/librocksdb/vendor/rocksdb/options/db_options.h +10 -3
- package/vendor/librocksdb/vendor/rocksdb/options/options.cc +3 -0
- package/vendor/librocksdb/vendor/rocksdb/options/options_helper.cc +1 -0
- package/vendor/librocksdb/vendor/rocksdb/port/jemalloc_helper.h +2 -2
- package/vendor/librocksdb/vendor/rocksdb/port/stack_trace.cc +1 -0
- package/vendor/librocksdb/vendor/rocksdb/port/win/port_win.cc +3 -2
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/binary_search_index_reader.cc +1 -2
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_builder.cc +47 -31
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_factory.cc +15 -0
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_iterator.cc +37 -18
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_iterator.h +10 -3
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_reader.cc +102 -41
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_reader.h +15 -7
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_reader_impl.h +1 -3
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_based_table_reader_sync_and_async.h +5 -6
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_cache.h +31 -0
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/block_prefetcher.cc +6 -0
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/cachable_entry.h +10 -5
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/filter_block.h +34 -28
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/filter_block_reader_common.cc +17 -11
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/filter_block_reader_common.h +5 -2
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/filter_policy.cc +12 -3
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/full_filter_block.cc +37 -30
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/full_filter_block.h +11 -13
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/hash_index_reader.cc +1 -2
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/index_builder.cc +62 -53
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/index_builder.h +60 -38
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/index_reader_common.cc +14 -9
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/index_reader_common.h +4 -1
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/partitioned_filter_block.cc +135 -94
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/partitioned_filter_block.h +52 -46
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/partitioned_index_reader.cc +51 -13
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/partitioned_index_reader.h +2 -0
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/uncompression_dict_reader.cc +3 -11
- package/vendor/librocksdb/vendor/rocksdb/table/block_based/uncompression_dict_reader.h +2 -3
- package/vendor/librocksdb/vendor/rocksdb/table/block_fetcher.cc +8 -10
- package/vendor/librocksdb/vendor/rocksdb/table/block_fetcher.h +2 -1
- package/vendor/librocksdb/vendor/rocksdb/table/compaction_merging_iterator.cc +9 -10
- package/vendor/librocksdb/vendor/rocksdb/table/compaction_merging_iterator.h +3 -2
- package/vendor/librocksdb/vendor/rocksdb/table/format.cc +1 -2
- package/vendor/librocksdb/vendor/rocksdb/table/iterator.cc +4 -0
- package/vendor/librocksdb/vendor/rocksdb/table/merging_iterator.cc +18 -13
- package/vendor/librocksdb/vendor/rocksdb/table/merging_iterator.h +5 -3
- package/vendor/librocksdb/vendor/rocksdb/table/meta_blocks.cc +18 -4
- package/vendor/librocksdb/vendor/rocksdb/table/meta_blocks.h +4 -0
- package/vendor/librocksdb/vendor/rocksdb/table/plain/plain_table_builder.cc +2 -2
- package/vendor/librocksdb/vendor/rocksdb/table/sst_file_dumper.cc +6 -6
- package/vendor/librocksdb/vendor/rocksdb/table/sst_file_reader.cc +24 -2
- package/vendor/librocksdb/vendor/rocksdb/table/sst_file_writer_collectors.h +3 -1
- package/vendor/librocksdb/vendor/rocksdb/table/table_builder.h +8 -7
- package/vendor/librocksdb/vendor/rocksdb/table/table_iterator.h +69 -0
- package/vendor/librocksdb/vendor/rocksdb/table/table_reader.h +9 -0
- package/vendor/librocksdb/vendor/rocksdb/test_util/testutil.cc +25 -0
- package/vendor/librocksdb/vendor/rocksdb/test_util/testutil.h +12 -0
- package/vendor/librocksdb/vendor/rocksdb/tools/db_bench_tool.cc +32 -0
- package/vendor/librocksdb/vendor/rocksdb/tools/ldb_cmd.cc +618 -124
- package/vendor/librocksdb/vendor/rocksdb/tools/ldb_cmd_impl.h +19 -1
- package/vendor/librocksdb/vendor/rocksdb/tools/ldb_tool.cc +9 -0
- package/vendor/librocksdb/vendor/rocksdb/util/aligned_storage.h +24 -0
- package/vendor/librocksdb/vendor/rocksdb/util/autovector.h +4 -0
- package/vendor/librocksdb/vendor/rocksdb/util/comparator.cc +12 -0
- package/vendor/librocksdb/vendor/rocksdb/util/filter_bench.cc +1 -1
- package/vendor/librocksdb/vendor/rocksdb/util/random.cc +2 -1
- package/vendor/librocksdb/vendor/rocksdb/util/stderr_logger.cc +3 -4
- package/vendor/librocksdb/vendor/rocksdb/util/stderr_logger.h +1 -1
- package/vendor/librocksdb/vendor/rocksdb/util/udt_util.cc +33 -0
- package/vendor/librocksdb/vendor/rocksdb/util/udt_util.h +7 -0
- package/vendor/librocksdb/vendor/rocksdb/util/write_batch_util.h +5 -0
- package/vendor/librocksdb/vendor/rocksdb/util/xxhash.h +36 -29
- package/vendor/librocksdb/vendor/rocksdb/utilities/blob_db/blob_db_impl.h +3 -0
- package/vendor/librocksdb/vendor/rocksdb/utilities/blob_db/blob_db_impl_filesnapshot.cc +20 -0
- package/vendor/librocksdb/vendor/rocksdb/utilities/cache_dump_load_impl.cc +29 -9
- package/vendor/librocksdb/vendor/rocksdb/utilities/cache_dump_load_impl.h +14 -3
- package/vendor/librocksdb/vendor/rocksdb/utilities/debug.cc +16 -4
- package/vendor/librocksdb/vendor/rocksdb/utilities/fault_injection_fs.cc +677 -248
- package/vendor/librocksdb/vendor/rocksdb/utilities/fault_injection_fs.h +325 -158
- package/vendor/librocksdb/vendor/rocksdb/utilities/option_change_migration/option_change_migration.cc +1 -8
- package/vendor/librocksdb/vendor/rocksdb/utilities/table_properties_collectors/compact_for_tiering_collector.cc +144 -0
- package/vendor/librocksdb/vendor/rocksdb/utilities/table_properties_collectors/compact_for_tiering_collector.h +45 -0
- package/vendor/librocksdb/vendor/rocksdb/utilities/table_properties_collectors/compact_on_deletion_collector.cc +12 -0
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/lock/range/range_tree/lib/portability/toku_time.h +1 -1
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/lock/range/range_tree/lib/util/growable_array.h +3 -3
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/pessimistic_transaction.cc +116 -20
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/pessimistic_transaction.h +33 -1
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/pessimistic_transaction_db.cc +78 -13
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/pessimistic_transaction_db.h +33 -1
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/transaction_base.cc +106 -7
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/transaction_base.h +68 -10
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/transaction_test.h +7 -3
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/transaction_util.cc +8 -5
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/transaction_util.h +7 -4
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/write_prepared_txn.cc +18 -12
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/write_prepared_txn_db.cc +4 -4
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/write_prepared_txn_db.h +17 -0
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/write_unprepared_txn.cc +11 -9
- package/vendor/librocksdb/vendor/rocksdb/utilities/transactions/write_unprepared_txn_db.cc +2 -1
- package/vendor/librocksdb/vendor/rocksdb/utilities/types_util.cc +88 -0
- package/vendor/librocksdb/vendor/rocksdb/utilities/write_batch_with_index/write_batch_with_index.cc +313 -14
- package/vendor/librocksdb/vendor/rocksdb/utilities/write_batch_with_index/write_batch_with_index_internal.cc +7 -0
- package/vendor/librocksdb/vendor/rocksdb/utilities/write_batch_with_index/write_batch_with_index_internal.h +1 -1
- package/vendor/librocksdb/vendor/rocksdb/db/multi_cf_iterator.cc +0 -102
- 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
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
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_.
|
|
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
|
-
|
|
169
|
-
|
|
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
|
-
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (s.ok()) {
|
|
187
|
+
state_.pos_at_last_append_ += data.size();
|
|
173
188
|
fs_->WritableFileAppended(state_);
|
|
174
189
|
}
|
|
175
|
-
|
|
176
|
-
return
|
|
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
|
-
|
|
205
|
-
|
|
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
|
-
|
|
233
|
+
}
|
|
234
|
+
if (s.ok()) {
|
|
235
|
+
state_.pos_at_last_append_ += data.size();
|
|
209
236
|
fs_->WritableFileAppended(state_);
|
|
210
237
|
}
|
|
211
|
-
|
|
212
|
-
|
|
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
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
|
|
252
|
-
|
|
253
|
-
|
|
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
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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_.
|
|
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 <
|
|
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 -
|
|
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 =
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
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
|
|
423
|
-
IOStatus s;
|
|
492
|
+
IOStatus res_status;
|
|
424
493
|
FSReadRequest res;
|
|
494
|
+
IOStatus s;
|
|
425
495
|
if (!fs_->IsFilesystemActive()) {
|
|
426
|
-
|
|
427
|
-
}
|
|
428
|
-
|
|
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 (
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
res.status =
|
|
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_->
|
|
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_->
|
|
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 =
|
|
491
|
-
|
|
492
|
-
|
|
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
|
-
|
|
503
|
-
|
|
504
|
-
|
|
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 (
|
|
846
|
+
if (IsFilesystemDirectWritable()) {
|
|
536
847
|
return target()->NewWritableFile(fname, file_opts, result, dbg);
|
|
537
848
|
}
|
|
538
849
|
|
|
539
|
-
IOStatus io_s =
|
|
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 (
|
|
884
|
+
if (IsFilesystemDirectWritable()) {
|
|
573
885
|
return target()->ReopenWritableFile(fname, file_opts, result, dbg);
|
|
574
886
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
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
|
|
584
|
-
|
|
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
|
|
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 (
|
|
960
|
+
if (IsFilesystemDirectWritable()) {
|
|
643
961
|
return target()->NewRandomRWFile(fname, file_opts, result, dbg);
|
|
644
962
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
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
|
-
|
|
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
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
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
|
-
|
|
706
|
-
|
|
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
|
-
|
|
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
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
}
|
|
1041
|
+
IOStatus io_s = MaybeInjectThreadLocalError(
|
|
1042
|
+
FaultInjectionIOType::kMetadataWrite, options);
|
|
1043
|
+
if (!io_s.ok()) {
|
|
1044
|
+
return io_s;
|
|
726
1045
|
}
|
|
727
|
-
|
|
1046
|
+
|
|
1047
|
+
io_s = FileSystemWrapper::DeleteFile(f, options, dbg);
|
|
1048
|
+
|
|
728
1049
|
if (io_s.ok()) {
|
|
729
1050
|
UntrackFile(f);
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
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
|
-
|
|
749
|
-
|
|
750
|
-
|
|
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
|
-
|
|
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
|
-
|
|
802
|
-
|
|
803
|
-
|
|
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
|
-
|
|
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::
|
|
952
|
-
ErrorOperation op, Slice* result,
|
|
953
|
-
bool
|
|
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 =
|
|
958
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1430
|
+
msg << "corrupt last byte";
|
|
1431
|
+
ctx->message = msg.str();
|
|
1003
1432
|
ret_fault_injected = true;
|
|
1004
1433
|
} else {
|
|
1005
|
-
|
|
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
|
-
|
|
1011
|
-
|
|
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::
|
|
1024
|
-
|
|
1025
|
-
|
|
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
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
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
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
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
|
-
|
|
1062
|
-
return IOStatus::IOError("injected metadata write error");
|
|
1488
|
+
return ret;
|
|
1063
1489
|
}
|
|
1064
1490
|
|
|
1065
|
-
void FaultInjectionTestFS::
|
|
1491
|
+
void FaultInjectionTestFS::PrintInjectedThreadLocalErrorBacktrace(
|
|
1492
|
+
FaultInjectionIOType type) {
|
|
1066
1493
|
#if defined(OS_LINUX)
|
|
1067
|
-
ErrorContext* ctx =
|
|
1068
|
-
if (ctx
|
|
1069
|
-
|
|
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
|
-
|
|
1072
|
-
|
|
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
|