@nxtedition/rocksdb 10.1.5 → 10.2.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.cc +19 -11
- package/deps/rocksdb/rocksdb/CMakeLists.txt +16 -5
- package/deps/rocksdb/rocksdb/Makefile +38 -15
- package/deps/rocksdb/rocksdb/TARGETS +10 -0
- package/deps/rocksdb/rocksdb/cache/cache_test.cc +58 -0
- package/deps/rocksdb/rocksdb/db/arena_wrapped_db_iter.cc +4 -4
- package/deps/rocksdb/rocksdb/db/arena_wrapped_db_iter.h +4 -2
- package/deps/rocksdb/rocksdb/db/builder.cc +2 -2
- package/deps/rocksdb/rocksdb/db/builder.h +1 -1
- package/deps/rocksdb/rocksdb/db/c.cc +205 -6
- package/deps/rocksdb/rocksdb/db/c_test.c +189 -1
- package/deps/rocksdb/rocksdb/db/column_family.cc +28 -0
- package/deps/rocksdb/rocksdb/db/column_family.h +17 -0
- package/deps/rocksdb/rocksdb/db/column_family_test.cc +234 -60
- package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +8 -1
- package/deps/rocksdb/rocksdb/db/compaction/compaction.h +11 -9
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +4 -4
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.h +2 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +22 -25
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +2 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +112 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +72 -21
- package/deps/rocksdb/rocksdb/db/compaction/compaction_service_job.cc +2 -0
- package/deps/rocksdb/rocksdb/db/compaction/tiered_compaction_test.cc +77 -0
- package/deps/rocksdb/rocksdb/db/convenience.cc +3 -0
- package/deps/rocksdb/rocksdb/db/db_block_cache_test.cc +269 -112
- package/deps/rocksdb/rocksdb/db/db_bloom_filter_test.cc +107 -43
- package/deps/rocksdb/rocksdb/db/db_filesnapshot.cc +93 -24
- package/deps/rocksdb/rocksdb/db/db_flush_test.cc +5 -5
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +157 -68
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +56 -15
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +78 -105
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_files.cc +39 -9
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_follower.cc +1 -0
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +21 -14
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_write.cc +107 -63
- package/deps/rocksdb/rocksdb/db/db_properties_test.cc +43 -2
- package/deps/rocksdb/rocksdb/db/db_range_del_test.cc +4 -0
- package/deps/rocksdb/rocksdb/db/db_rate_limiter_test.cc +6 -0
- package/deps/rocksdb/rocksdb/db/db_test.cc +10 -2
- package/deps/rocksdb/rocksdb/db/db_test2.cc +1 -1
- package/deps/rocksdb/rocksdb/db/db_test_util.cc +5 -0
- package/deps/rocksdb/rocksdb/db/db_test_util.h +7 -6
- package/deps/rocksdb/rocksdb/db/db_wal_test.cc +92 -2
- package/deps/rocksdb/rocksdb/db/error_handler.cc +34 -39
- package/deps/rocksdb/rocksdb/db/error_handler.h +3 -4
- package/deps/rocksdb/rocksdb/db/error_handler_fs_test.cc +8 -4
- package/deps/rocksdb/rocksdb/db/event_helpers.cc +6 -3
- package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +71 -15
- package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.h +11 -0
- package/deps/rocksdb/rocksdb/db/external_sst_file_test.cc +383 -4
- package/deps/rocksdb/rocksdb/db/fault_injection_test.cc +88 -72
- package/deps/rocksdb/rocksdb/db/flush_job.cc +30 -3
- package/deps/rocksdb/rocksdb/db/flush_job.h +14 -0
- package/deps/rocksdb/rocksdb/db/internal_stats.cc +60 -1
- package/deps/rocksdb/rocksdb/db/internal_stats.h +20 -1
- package/deps/rocksdb/rocksdb/db/log_writer.cc +24 -0
- package/deps/rocksdb/rocksdb/db/log_writer.h +5 -0
- package/deps/rocksdb/rocksdb/db/memtable.cc +6 -4
- package/deps/rocksdb/rocksdb/db/memtable.h +10 -10
- package/deps/rocksdb/rocksdb/db/memtable_list.cc +4 -4
- package/deps/rocksdb/rocksdb/db/multi_cf_iterator_impl.h +10 -3
- package/deps/rocksdb/rocksdb/db/range_tombstone_fragmenter.h +8 -10
- package/deps/rocksdb/rocksdb/db/repair.cc +4 -3
- package/deps/rocksdb/rocksdb/db/seqno_to_time_mapping.cc +30 -0
- package/deps/rocksdb/rocksdb/db/seqno_to_time_mapping.h +9 -0
- package/deps/rocksdb/rocksdb/db/table_cache.cc +17 -2
- package/deps/rocksdb/rocksdb/db/table_cache.h +9 -1
- package/deps/rocksdb/rocksdb/db/table_properties_collector.h +9 -2
- package/deps/rocksdb/rocksdb/db/table_properties_collector_test.cc +3 -1
- package/deps/rocksdb/rocksdb/db/transaction_log_impl.cc +3 -3
- package/deps/rocksdb/rocksdb/db/transaction_log_impl.h +7 -7
- package/deps/rocksdb/rocksdb/db/version_edit.cc +0 -1
- package/deps/rocksdb/rocksdb/db/version_edit_handler.h +7 -6
- package/deps/rocksdb/rocksdb/db/version_set.cc +54 -31
- package/deps/rocksdb/rocksdb/db/version_set.h +14 -7
- package/deps/rocksdb/rocksdb/db/wal_manager.cc +37 -29
- package/deps/rocksdb/rocksdb/db/wal_manager.h +6 -5
- package/deps/rocksdb/rocksdb/db/wide/wide_columns_helper.cc +6 -0
- package/deps/rocksdb/rocksdb/db/write_batch.cc +54 -23
- package/deps/rocksdb/rocksdb/db/write_callback_test.cc +46 -5
- package/deps/rocksdb/rocksdb/db/write_thread.cc +53 -5
- package/deps/rocksdb/rocksdb/db/write_thread.h +36 -4
- package/deps/rocksdb/rocksdb/db_stress_tool/CMakeLists.txt +1 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/batched_ops_stress.cc +5 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/cf_consistency_stress.cc +57 -17
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.cc +11 -3
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +8 -4
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_driver.cc +10 -25
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_env_wrapper.h +25 -88
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_filters.cc +93 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_filters.h +16 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +43 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_listener.h +109 -21
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_shared_state.h +8 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +666 -205
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.h +55 -10
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_tool.cc +18 -16
- package/deps/rocksdb/rocksdb/db_stress_tool/multi_ops_txns_stress.cc +19 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/multi_ops_txns_stress.h +5 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/no_batched_ops_stress.cc +782 -494
- package/deps/rocksdb/rocksdb/env/composite_env_wrapper.h +21 -0
- package/deps/rocksdb/rocksdb/env/env.cc +6 -0
- package/deps/rocksdb/rocksdb/env/io_posix.cc +0 -1
- package/deps/rocksdb/rocksdb/file/file_util.cc +8 -2
- package/deps/rocksdb/rocksdb/file/prefetch_test.cc +34 -19
- package/deps/rocksdb/rocksdb/file/writable_file_writer.cc +29 -32
- package/deps/rocksdb/rocksdb/file/writable_file_writer.h +41 -15
- package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +4 -2
- package/deps/rocksdb/rocksdb/include/rocksdb/c.h +63 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/db.h +16 -5
- package/deps/rocksdb/rocksdb/include/rocksdb/env.h +5 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/iterator.h +0 -16
- package/deps/rocksdb/rocksdb/include/rocksdb/iterator_base.h +16 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/listener.h +21 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/options.h +76 -3
- package/deps/rocksdb/rocksdb/include/rocksdb/table_properties.h +17 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/transaction_log.h +12 -6
- package/deps/rocksdb/rocksdb/include/rocksdb/universal_compaction.h +31 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/user_write_callback.h +29 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/checkpoint.h +4 -2
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/customizable_util.h +0 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/ldb_cmd.h +17 -8
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +2 -2
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/table_properties_collectors.h +46 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/transaction.h +7 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/version.h +2 -2
- package/deps/rocksdb/rocksdb/options/cf_options.cc +13 -2
- package/deps/rocksdb/rocksdb/options/cf_options.h +6 -2
- package/deps/rocksdb/rocksdb/options/db_options.cc +8 -0
- package/deps/rocksdb/rocksdb/options/db_options.h +9 -5
- package/deps/rocksdb/rocksdb/options/options.cc +3 -0
- package/deps/rocksdb/rocksdb/options/options_helper.cc +1 -0
- package/deps/rocksdb/rocksdb/options/options_settable_test.cc +3 -1
- package/deps/rocksdb/rocksdb/port/jemalloc_helper.h +2 -2
- package/deps/rocksdb/rocksdb/port/stack_trace.cc +1 -0
- package/deps/rocksdb/rocksdb/port/win/port_win.cc +3 -2
- package/deps/rocksdb/rocksdb/src.mk +4 -0
- package/deps/rocksdb/rocksdb/table/block_based/binary_search_index_reader.cc +1 -2
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +4 -2
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.cc +15 -0
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +102 -41
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +15 -7
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_impl.h +1 -3
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_sync_and_async.h +5 -6
- package/deps/rocksdb/rocksdb/table/block_based/block_cache.h +31 -0
- package/deps/rocksdb/rocksdb/table/block_based/block_prefetcher.cc +6 -0
- package/deps/rocksdb/rocksdb/table/block_based/cachable_entry.h +10 -5
- package/deps/rocksdb/rocksdb/table/block_based/filter_block.h +11 -15
- package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.cc +17 -11
- package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.h +5 -2
- package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.cc +28 -21
- package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.h +9 -11
- package/deps/rocksdb/rocksdb/table/block_based/full_filter_block_test.cc +16 -16
- package/deps/rocksdb/rocksdb/table/block_based/hash_index_reader.cc +1 -2
- package/deps/rocksdb/rocksdb/table/block_based/index_reader_common.cc +14 -9
- package/deps/rocksdb/rocksdb/table/block_based/index_reader_common.h +4 -1
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +82 -41
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.h +13 -14
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block_test.cc +18 -22
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_index_reader.cc +51 -13
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_index_reader.h +2 -0
- package/deps/rocksdb/rocksdb/table/block_based/uncompression_dict_reader.cc +3 -11
- package/deps/rocksdb/rocksdb/table/block_based/uncompression_dict_reader.h +2 -3
- package/deps/rocksdb/rocksdb/table/compaction_merging_iterator.cc +9 -10
- package/deps/rocksdb/rocksdb/table/compaction_merging_iterator.h +3 -2
- package/deps/rocksdb/rocksdb/table/format.cc +1 -2
- package/deps/rocksdb/rocksdb/table/merging_iterator.cc +18 -13
- package/deps/rocksdb/rocksdb/table/merging_iterator.h +5 -3
- package/deps/rocksdb/rocksdb/table/plain/plain_table_builder.cc +2 -2
- package/deps/rocksdb/rocksdb/table/sst_file_reader.cc +1 -1
- package/deps/rocksdb/rocksdb/table/sst_file_writer_collectors.h +3 -1
- package/deps/rocksdb/rocksdb/table/table_builder.h +8 -7
- package/deps/rocksdb/rocksdb/table/table_reader.h +9 -0
- package/deps/rocksdb/rocksdb/test_util/testutil.cc +1 -0
- package/deps/rocksdb/rocksdb/test_util/testutil.h +6 -0
- package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +19 -0
- package/deps/rocksdb/rocksdb/tools/ldb_cmd.cc +434 -110
- package/deps/rocksdb/rocksdb/tools/ldb_cmd_impl.h +3 -1
- package/deps/rocksdb/rocksdb/tools/ldb_tool.cc +3 -0
- package/deps/rocksdb/rocksdb/util/aligned_storage.h +24 -0
- package/deps/rocksdb/rocksdb/util/filter_bench.cc +1 -1
- package/deps/rocksdb/rocksdb/util/random.cc +2 -1
- package/deps/rocksdb/rocksdb/util/stderr_logger.h +1 -1
- package/deps/rocksdb/rocksdb/util/udt_util.cc +33 -0
- package/deps/rocksdb/rocksdb/util/udt_util.h +7 -0
- package/deps/rocksdb/rocksdb/util/udt_util_test.cc +33 -0
- package/deps/rocksdb/rocksdb/util/write_batch_util.h +5 -0
- package/deps/rocksdb/rocksdb/util/xxhash.h +10 -3
- package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +13 -13
- package/deps/rocksdb/rocksdb/utilities/checkpoint/checkpoint_test.cc +104 -48
- package/deps/rocksdb/rocksdb/utilities/debug.cc +16 -4
- package/deps/rocksdb/rocksdb/utilities/fault_injection_fs.cc +647 -235
- package/deps/rocksdb/rocksdb/utilities/fault_injection_fs.h +274 -157
- package/deps/rocksdb/rocksdb/utilities/table_properties_collectors/compact_for_tiering_collector.cc +144 -0
- package/deps/rocksdb/rocksdb/utilities/table_properties_collectors/compact_for_tiering_collector.h +45 -0
- package/deps/rocksdb/rocksdb/utilities/table_properties_collectors/compact_for_tiering_collector_test.cc +139 -0
- package/deps/rocksdb/rocksdb/utilities/table_properties_collectors/compact_on_deletion_collector.cc +12 -0
- package/deps/rocksdb/rocksdb/utilities/table_properties_collectors/compact_on_deletion_collector_test.cc +3 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/optimistic_transaction_test.cc +105 -6
- package/deps/rocksdb/rocksdb/utilities/transactions/pessimistic_transaction.cc +64 -8
- package/deps/rocksdb/rocksdb/utilities/transactions/pessimistic_transaction.h +5 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/transaction_base.cc +43 -5
- package/deps/rocksdb/rocksdb/utilities/transactions/transaction_base.h +5 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.cc +154 -6
- package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.h +1 -1
- package/deps/rocksdb/rocksdb/utilities/transactions/write_committed_transaction_ts_test.cc +158 -2
- package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_txn.cc +16 -11
- package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_txn_db.cc +4 -4
- package/deps/rocksdb/rocksdb/utilities/transactions/write_unprepared_txn.cc +9 -8
- package/deps/rocksdb/rocksdb/utilities/transactions/write_unprepared_txn_db.cc +2 -1
- package/deps/rocksdb/rocksdb/utilities/write_batch_with_index/write_batch_with_index.cc +43 -7
- package/deps/rocksdb/rocksdb/utilities/write_batch_with_index/write_batch_with_index_internal.cc +2 -0
- package/deps/rocksdb/rocksdb/utilities/write_batch_with_index/write_batch_with_index_internal.h +1 -1
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/@nxtedition+rocksdb.node +0 -0
- package/prebuilds/linux-x64/@nxtedition+rocksdb.node +0 -0
- package/.tap/test-results/node_modules/abstract-level/test/chained-batch-test.js.tap +0 -0
- package/.tap/test-results/node_modules/abstract-level/test/get-test.js.tap +0 -0
- package/.tap/test-results/test/abstract-level-test.js.tap +0 -1077
- package/.tap/test-results/test/batch-test.js.tap +0 -12
- package/.tap/test-results/test/chained-batch-gc-test.js.tap +0 -11
- package/.tap/test-results/test/cleanup-hanging-iterators-test.js.tap +0 -135
- package/.tap/test-results/test/clear-gc-test.js.tap +0 -13
- package/.tap/test-results/test/column-test.js.tap +0 -55
- package/.tap/test-results/test/common.js.tap +0 -0
- package/.tap/test-results/test/compression-test.js.tap +0 -30
- package/.tap/test-results/test/db-identity.js.tap +0 -12
- package/.tap/test-results/test/electron.js.tap +0 -0
- package/.tap/test-results/test/env-cleanup-hook-test.js.tap +0 -40
- package/.tap/test-results/test/env-cleanup-hook.js.tap +0 -0
- package/.tap/test-results/test/gc.js.tap +0 -0
- package/.tap/test-results/test/getproperty-test.js.tap +0 -29
- package/.tap/test-results/test/iterator-gc-test.js.tap +0 -15
- package/.tap/test-results/test/iterator-hwm-test.js.tap +0 -131
- package/.tap/test-results/test/iterator-recursion-test.js.tap +0 -12
- package/.tap/test-results/test/iterator-starvation-test.js.tap +0 -73
- package/.tap/test-results/test/iterator-test.js.tap +0 -6
- package/.tap/test-results/test/leak-tester-batch.js.tap +0 -0
- package/.tap/test-results/test/leak-tester-iterator.js.tap +0 -0
- package/.tap/test-results/test/leak-tester.js.tap +0 -0
- package/.tap/test-results/test/lock-test.js.tap +0 -18
- package/.tap/test-results/test/lock.js.tap +0 -0
- package/.tap/test-results/test/make.js.tap +0 -0
- package/.tap/test-results/test/max-rev-merge.js.tap +0 -0
- package/.tap/test-results/test/merge-operator-test.js.tap +0 -12
- package/.tap/test-results/test/mkdir-test.js.tap +0 -15
- package/.tap/test-results/test/segfault-test.js.tap +0 -76
- package/.tap/test-results/test/stack-blower.js.tap +0 -0
- package/deps/rocksdb/rocksdb/README.md +0 -29
- package/deps/rocksdb/rocksdb/microbench/README.md +0 -60
- package/deps/rocksdb/rocksdb/plugin/README.md +0 -43
- package/deps/rocksdb/rocksdb/port/README +0 -10
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_tree/lib/README +0 -13
|
@@ -7,7 +7,11 @@
|
|
|
7
7
|
// Use of this source code is governed by a BSD-style license that can be
|
|
8
8
|
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
|
9
9
|
|
|
10
|
+
#include "db/dbformat.h"
|
|
11
|
+
#include "db_stress_tool/db_stress_listener.h"
|
|
12
|
+
#include "db_stress_tool/db_stress_shared_state.h"
|
|
10
13
|
#include "db_stress_tool/expected_state.h"
|
|
14
|
+
#include "rocksdb/status.h"
|
|
11
15
|
#ifdef GFLAGS
|
|
12
16
|
#include "db/wide/wide_columns_helper.h"
|
|
13
17
|
#include "db_stress_tool/db_stress_common.h"
|
|
@@ -507,12 +511,6 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
507
511
|
std::string key_str = Key(rand_keys[0]);
|
|
508
512
|
Slice key = key_str;
|
|
509
513
|
std::string from_db;
|
|
510
|
-
int error_count = 0;
|
|
511
|
-
|
|
512
|
-
if (fault_fs_guard) {
|
|
513
|
-
fault_fs_guard->EnableErrorInjection();
|
|
514
|
-
SharedState::ignore_read_error = false;
|
|
515
|
-
}
|
|
516
514
|
|
|
517
515
|
ReadOptions read_opts_copy = read_opts;
|
|
518
516
|
std::string read_ts_str;
|
|
@@ -525,26 +523,43 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
525
523
|
bool read_older_ts = MaybeUseOlderTimestampForPointLookup(
|
|
526
524
|
thread, read_ts_str, read_ts_slice, read_opts_copy);
|
|
527
525
|
|
|
526
|
+
if (fault_fs_guard) {
|
|
527
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
528
|
+
FaultInjectionIOType::kRead);
|
|
529
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
530
|
+
FaultInjectionIOType::kMetadataRead);
|
|
531
|
+
SharedState::ignore_read_error = false;
|
|
532
|
+
}
|
|
533
|
+
|
|
528
534
|
const ExpectedValue pre_read_expected_value =
|
|
529
535
|
thread->shared->Get(rand_column_families[0], rand_keys[0]);
|
|
530
536
|
Status s = db_->Get(read_opts_copy, cfh, key, &from_db);
|
|
531
537
|
const ExpectedValue post_read_expected_value =
|
|
532
538
|
thread->shared->Get(rand_column_families[0], rand_keys[0]);
|
|
539
|
+
|
|
540
|
+
int injected_error_count = 0;
|
|
533
541
|
if (fault_fs_guard) {
|
|
534
|
-
|
|
542
|
+
injected_error_count = GetMinInjectedErrorCount(
|
|
543
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
544
|
+
FaultInjectionIOType::kRead),
|
|
545
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
546
|
+
FaultInjectionIOType::kMetadataRead));
|
|
547
|
+
if (!SharedState::ignore_read_error && injected_error_count > 0 &&
|
|
548
|
+
(s.ok() || s.IsNotFound())) {
|
|
549
|
+
// Grab mutex so multiple thread don't try to print the
|
|
550
|
+
// stack trace at the same time
|
|
551
|
+
MutexLock l(thread->shared->GetMutex());
|
|
552
|
+
fprintf(stderr, "Didn't get expected error from Get\n");
|
|
553
|
+
fprintf(stderr, "Callstack that injected the fault\n");
|
|
554
|
+
fault_fs_guard->PrintInjectedThreadLocalErrorBacktrace(
|
|
555
|
+
FaultInjectionIOType::kRead);
|
|
556
|
+
fault_fs_guard->PrintInjectedThreadLocalErrorBacktrace(
|
|
557
|
+
FaultInjectionIOType::kMetadataRead);
|
|
558
|
+
std::terminate();
|
|
559
|
+
}
|
|
535
560
|
}
|
|
561
|
+
|
|
536
562
|
if (s.ok()) {
|
|
537
|
-
if (fault_fs_guard) {
|
|
538
|
-
if (error_count && !SharedState::ignore_read_error) {
|
|
539
|
-
// Grab mutex so multiple thread don't try to print the
|
|
540
|
-
// stack trace at the same time
|
|
541
|
-
MutexLock l(thread->shared->GetMutex());
|
|
542
|
-
fprintf(stderr, "Didn't get expected error from Get\n");
|
|
543
|
-
fprintf(stderr, "Callstack that injected the fault\n");
|
|
544
|
-
fault_fs_guard->PrintFaultBacktrace();
|
|
545
|
-
std::terminate();
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
563
|
// found case
|
|
549
564
|
thread->stats.AddGets(1, 1);
|
|
550
565
|
// we only have the latest expected state
|
|
@@ -584,16 +599,10 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
584
599
|
key.ToString(true).c_str());
|
|
585
600
|
}
|
|
586
601
|
}
|
|
587
|
-
} else {
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
} else {
|
|
592
|
-
thread->stats.AddVerifiedErrors(1);
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
if (fault_fs_guard) {
|
|
596
|
-
fault_fs_guard->DisableErrorInjection();
|
|
602
|
+
} else if (injected_error_count == 0 || !IsErrorInjectedAndRetryable(s)) {
|
|
603
|
+
thread->shared->SetVerificationFailure();
|
|
604
|
+
fprintf(stderr, "error : Get() returns %s for key: %s.\n",
|
|
605
|
+
s.ToString().c_str(), key.ToString(true).c_str());
|
|
597
606
|
}
|
|
598
607
|
return s;
|
|
599
608
|
}
|
|
@@ -610,14 +619,13 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
610
619
|
std::vector<PinnableSlice> values(num_keys);
|
|
611
620
|
std::vector<Status> statuses(num_keys);
|
|
612
621
|
// When Flags_use_txn is enabled, we also do a read your write check.
|
|
613
|
-
std::
|
|
614
|
-
ryw_expected_values.reserve(num_keys);
|
|
622
|
+
std::unordered_map<std::string, ExpectedValue> ryw_expected_values;
|
|
615
623
|
|
|
616
624
|
SharedState* shared = thread->shared;
|
|
625
|
+
assert(shared);
|
|
617
626
|
|
|
618
627
|
int column_family = rand_column_families[0];
|
|
619
628
|
ColumnFamilyHandle* cfh = column_families_[column_family];
|
|
620
|
-
int error_count = 0;
|
|
621
629
|
|
|
622
630
|
bool do_consistency_check = FLAGS_check_multiget_consistency;
|
|
623
631
|
|
|
@@ -643,6 +651,13 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
643
651
|
// will be rolled back once MultiGet returns.
|
|
644
652
|
std::unique_ptr<Transaction> txn;
|
|
645
653
|
if (use_txn) {
|
|
654
|
+
// TODO(hx235): test fault injection with MultiGet() with transactions
|
|
655
|
+
if (fault_fs_guard) {
|
|
656
|
+
fault_fs_guard->DisableThreadLocalErrorInjection(
|
|
657
|
+
FaultInjectionIOType::kRead);
|
|
658
|
+
fault_fs_guard->DisableThreadLocalErrorInjection(
|
|
659
|
+
FaultInjectionIOType::kMetadataRead);
|
|
660
|
+
}
|
|
646
661
|
WriteOptions wo;
|
|
647
662
|
if (FLAGS_rate_limit_auto_wal_flush) {
|
|
648
663
|
wo.rate_limiter_priority = Env::IO_USER;
|
|
@@ -650,7 +665,7 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
650
665
|
Status s = NewTxn(wo, &txn);
|
|
651
666
|
if (!s.ok()) {
|
|
652
667
|
fprintf(stderr, "NewTxn error: %s\n", s.ToString().c_str());
|
|
653
|
-
|
|
668
|
+
shared->SafeTerminate();
|
|
654
669
|
}
|
|
655
670
|
}
|
|
656
671
|
for (size_t i = 0; i < num_keys; ++i) {
|
|
@@ -658,66 +673,54 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
658
673
|
key_str.emplace_back(Key(rand_key));
|
|
659
674
|
keys.emplace_back(key_str.back());
|
|
660
675
|
if (use_txn) {
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
// Just do read your write checks for keys that allow overwrites.
|
|
664
|
-
ryw_expected_values.emplace_back(std::nullopt);
|
|
665
|
-
continue;
|
|
666
|
-
}
|
|
667
|
-
// With a 1 in 10 probability, insert the just added key in the batch
|
|
668
|
-
// into the transaction. This will create an overlap with the MultiGet
|
|
669
|
-
// keys and exercise some corner cases in the code
|
|
670
|
-
if (thread->rand.OneIn(10)) {
|
|
671
|
-
int op = thread->rand.Uniform(2);
|
|
672
|
-
Status s;
|
|
673
|
-
assert(txn);
|
|
674
|
-
switch (op) {
|
|
675
|
-
case 0:
|
|
676
|
-
case 1: {
|
|
677
|
-
ExpectedValue put_value;
|
|
678
|
-
put_value.Put(false /* pending */);
|
|
679
|
-
ryw_expected_values.emplace_back(put_value);
|
|
680
|
-
char value[100];
|
|
681
|
-
size_t sz =
|
|
682
|
-
GenerateValue(put_value.GetValueBase(), value, sizeof(value));
|
|
683
|
-
Slice v(value, sz);
|
|
684
|
-
if (op == 0) {
|
|
685
|
-
s = txn->Put(cfh, keys.back(), v);
|
|
686
|
-
} else {
|
|
687
|
-
s = txn->Merge(cfh, keys.back(), v);
|
|
688
|
-
}
|
|
689
|
-
break;
|
|
690
|
-
}
|
|
691
|
-
case 2: {
|
|
692
|
-
ExpectedValue delete_value;
|
|
693
|
-
delete_value.Delete(false /* pending */);
|
|
694
|
-
ryw_expected_values.emplace_back(delete_value);
|
|
695
|
-
s = txn->Delete(cfh, keys.back());
|
|
696
|
-
break;
|
|
697
|
-
}
|
|
698
|
-
default:
|
|
699
|
-
assert(false);
|
|
700
|
-
}
|
|
701
|
-
if (!s.ok()) {
|
|
702
|
-
fprintf(stderr, "Transaction put error: %s\n",
|
|
703
|
-
s.ToString().c_str());
|
|
704
|
-
thread->shared->SafeTerminate();
|
|
705
|
-
}
|
|
706
|
-
} else {
|
|
707
|
-
ryw_expected_values.emplace_back(std::nullopt);
|
|
708
|
-
}
|
|
676
|
+
MaybeAddKeyToTxnForRYW(thread, column_family, rand_key, txn.get(),
|
|
677
|
+
ryw_expected_values);
|
|
709
678
|
}
|
|
710
679
|
}
|
|
711
680
|
|
|
681
|
+
int injected_error_count = 0;
|
|
682
|
+
|
|
712
683
|
if (!use_txn) {
|
|
713
684
|
if (fault_fs_guard) {
|
|
714
|
-
fault_fs_guard->
|
|
685
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
686
|
+
FaultInjectionIOType::kRead);
|
|
687
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
688
|
+
FaultInjectionIOType::kMetadataRead);
|
|
715
689
|
SharedState::ignore_read_error = false;
|
|
716
690
|
}
|
|
717
691
|
db_->MultiGet(readoptionscopy, cfh, num_keys, keys.data(), values.data(),
|
|
718
692
|
statuses.data());
|
|
719
693
|
if (fault_fs_guard) {
|
|
720
|
-
|
|
694
|
+
injected_error_count = GetMinInjectedErrorCount(
|
|
695
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
696
|
+
FaultInjectionIOType::kRead),
|
|
697
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
698
|
+
FaultInjectionIOType::kMetadataRead));
|
|
699
|
+
|
|
700
|
+
if (injected_error_count > 0) {
|
|
701
|
+
int stat_nok_nfound = 0;
|
|
702
|
+
for (const auto& s : statuses) {
|
|
703
|
+
if (!s.ok() && !s.IsNotFound()) {
|
|
704
|
+
stat_nok_nfound++;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
if (!SharedState::ignore_read_error &&
|
|
708
|
+
stat_nok_nfound < injected_error_count) {
|
|
709
|
+
// Grab mutex so multiple thread don't try to print the
|
|
710
|
+
// stack trace at the same time
|
|
711
|
+
MutexLock l(shared->GetMutex());
|
|
712
|
+
fprintf(stderr, "Didn't get expected error from MultiGet. \n");
|
|
713
|
+
fprintf(stderr,
|
|
714
|
+
"num_keys %zu Expected %d errors, seen at least %d\n",
|
|
715
|
+
num_keys, injected_error_count, stat_nok_nfound);
|
|
716
|
+
fprintf(stderr, "Callstack that injected the fault\n");
|
|
717
|
+
fault_fs_guard->PrintInjectedThreadLocalErrorBacktrace(
|
|
718
|
+
FaultInjectionIOType::kRead);
|
|
719
|
+
fault_fs_guard->PrintInjectedThreadLocalErrorBacktrace(
|
|
720
|
+
FaultInjectionIOType::kMetadataRead);
|
|
721
|
+
std::terminate();
|
|
722
|
+
}
|
|
723
|
+
}
|
|
721
724
|
}
|
|
722
725
|
} else {
|
|
723
726
|
assert(txn);
|
|
@@ -725,30 +728,6 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
725
728
|
statuses.data());
|
|
726
729
|
}
|
|
727
730
|
|
|
728
|
-
if (fault_fs_guard && error_count && !SharedState::ignore_read_error) {
|
|
729
|
-
int stat_nok = 0;
|
|
730
|
-
for (const auto& s : statuses) {
|
|
731
|
-
if (!s.ok() && !s.IsNotFound()) {
|
|
732
|
-
stat_nok++;
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
if (stat_nok < error_count) {
|
|
737
|
-
// Grab mutex so multiple thread don't try to print the
|
|
738
|
-
// stack trace at the same time
|
|
739
|
-
MutexLock l(thread->shared->GetMutex());
|
|
740
|
-
fprintf(stderr, "Didn't get expected error from MultiGet. \n");
|
|
741
|
-
fprintf(stderr, "num_keys %zu Expected %d errors, seen %d\n", num_keys,
|
|
742
|
-
error_count, stat_nok);
|
|
743
|
-
fprintf(stderr, "Callstack that injected the fault\n");
|
|
744
|
-
fault_fs_guard->PrintFaultBacktrace();
|
|
745
|
-
std::terminate();
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
if (fault_fs_guard) {
|
|
749
|
-
fault_fs_guard->DisableErrorInjection();
|
|
750
|
-
}
|
|
751
|
-
|
|
752
731
|
auto ryw_check =
|
|
753
732
|
[](const Slice& key, const PinnableSlice& value, const Status& s,
|
|
754
733
|
const std::optional<ExpectedValue>& ryw_expected_value) -> bool {
|
|
@@ -803,63 +782,69 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
803
782
|
[&](const Slice& key, const PinnableSlice& expected_value,
|
|
804
783
|
const Status& s,
|
|
805
784
|
const std::optional<ExpectedValue>& ryw_expected_value) -> bool {
|
|
785
|
+
// Temporarily disable error injection for verification
|
|
786
|
+
if (fault_fs_guard) {
|
|
787
|
+
fault_fs_guard->DisableThreadLocalErrorInjection(
|
|
788
|
+
FaultInjectionIOType::kRead);
|
|
789
|
+
fault_fs_guard->DisableThreadLocalErrorInjection(
|
|
790
|
+
FaultInjectionIOType::kMetadataRead);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
bool check_multiget_res = true;
|
|
806
794
|
bool is_consistent = true;
|
|
807
795
|
bool is_ryw_correct = true;
|
|
808
|
-
|
|
809
|
-
//
|
|
810
|
-
//
|
|
811
|
-
// from db `Get` and db `MultiGet` are consistent.
|
|
796
|
+
|
|
797
|
+
// If test does not use transaction, the consistency check for each key
|
|
798
|
+
// included check results from db `Get` and db `MultiGet` are consistent.
|
|
812
799
|
// If test use transaction, after consistency check, also do a read your
|
|
813
800
|
// own write check.
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
std::string value;
|
|
801
|
+
Status tmp_s;
|
|
802
|
+
std::string value;
|
|
817
803
|
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
}
|
|
804
|
+
if (use_txn) {
|
|
805
|
+
assert(txn);
|
|
806
|
+
ThreadStatusUtil::SetThreadOperation(
|
|
807
|
+
ThreadStatus::OperationType::OP_GET);
|
|
808
|
+
tmp_s = txn->Get(readoptionscopy, cfh, key, &value);
|
|
809
|
+
ThreadStatusUtil::SetThreadOperation(
|
|
810
|
+
ThreadStatus::OperationType::OP_MULTIGET);
|
|
811
|
+
} else {
|
|
812
|
+
ThreadStatusUtil::SetThreadOperation(
|
|
813
|
+
ThreadStatus::OperationType::OP_GET);
|
|
814
|
+
tmp_s = db_->Get(readoptionscopy, cfh, key, &value);
|
|
815
|
+
ThreadStatusUtil::SetThreadOperation(
|
|
816
|
+
ThreadStatus::OperationType::OP_MULTIGET);
|
|
817
|
+
}
|
|
818
|
+
if (!tmp_s.ok() && !tmp_s.IsNotFound()) {
|
|
819
|
+
fprintf(stderr, "Get error: %s\n", s.ToString().c_str());
|
|
820
|
+
is_consistent = false;
|
|
821
|
+
} else if (!s.ok() && tmp_s.ok()) {
|
|
822
|
+
fprintf(stderr,
|
|
823
|
+
"MultiGet(%d) returned different results with key %s. "
|
|
824
|
+
"Snapshot Seq No: %" PRIu64 "\n",
|
|
825
|
+
column_family, key.ToString(true).c_str(),
|
|
826
|
+
readoptionscopy.snapshot->GetSequenceNumber());
|
|
827
|
+
fprintf(stderr, "Get returned ok, MultiGet returned not found\n");
|
|
828
|
+
is_consistent = false;
|
|
829
|
+
} else if (s.ok() && tmp_s.IsNotFound()) {
|
|
830
|
+
fprintf(stderr,
|
|
831
|
+
"MultiGet(%d) returned different results with key %s. "
|
|
832
|
+
"Snapshot Seq No: %" PRIu64 "\n",
|
|
833
|
+
column_family, key.ToString(true).c_str(),
|
|
834
|
+
readoptionscopy.snapshot->GetSequenceNumber());
|
|
835
|
+
fprintf(stderr, "MultiGet returned ok, Get returned not found\n");
|
|
836
|
+
is_consistent = false;
|
|
837
|
+
} else if (s.ok() && value != expected_value.ToString()) {
|
|
838
|
+
fprintf(stderr,
|
|
839
|
+
"MultiGet(%d) returned different results with key %s. "
|
|
840
|
+
"Snapshot Seq No: %" PRIu64 "\n",
|
|
841
|
+
column_family, key.ToString(true).c_str(),
|
|
842
|
+
readoptionscopy.snapshot->GetSequenceNumber());
|
|
843
|
+
fprintf(stderr, "MultiGet returned value %s\n",
|
|
844
|
+
expected_value.ToString(true).c_str());
|
|
845
|
+
fprintf(stderr, "Get returned value %s\n",
|
|
846
|
+
Slice(value).ToString(true /* hex */).c_str());
|
|
847
|
+
is_consistent = false;
|
|
863
848
|
}
|
|
864
849
|
|
|
865
850
|
// If test uses transaction, continue to do a read your own write check.
|
|
@@ -870,15 +855,15 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
870
855
|
if (!is_consistent) {
|
|
871
856
|
fprintf(stderr, "TestMultiGet error: is_consistent is false\n");
|
|
872
857
|
thread->stats.AddErrors(1);
|
|
858
|
+
check_multiget_res = false;
|
|
873
859
|
// Fail fast to preserve the DB state
|
|
874
|
-
|
|
875
|
-
return false;
|
|
860
|
+
shared->SetVerificationFailure();
|
|
876
861
|
} else if (!is_ryw_correct) {
|
|
877
862
|
fprintf(stderr, "TestMultiGet error: is_ryw_correct is false\n");
|
|
878
863
|
thread->stats.AddErrors(1);
|
|
864
|
+
check_multiget_res = false;
|
|
879
865
|
// Fail fast to preserve the DB state
|
|
880
|
-
|
|
881
|
-
return false;
|
|
866
|
+
shared->SetVerificationFailure();
|
|
882
867
|
} else if (s.ok()) {
|
|
883
868
|
// found case
|
|
884
869
|
thread->stats.AddGets(1, 1);
|
|
@@ -888,33 +873,46 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
888
873
|
} else if (s.IsMergeInProgress() && use_txn) {
|
|
889
874
|
// With txn this is sometimes expected.
|
|
890
875
|
thread->stats.AddGets(1, 1);
|
|
891
|
-
} else {
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
thread->stats.AddErrors(1);
|
|
896
|
-
} else {
|
|
897
|
-
thread->stats.AddVerifiedErrors(1);
|
|
898
|
-
}
|
|
876
|
+
} else if (injected_error_count == 0 || !IsErrorInjectedAndRetryable(s)) {
|
|
877
|
+
fprintf(stderr, "MultiGet error: %s\n", s.ToString().c_str());
|
|
878
|
+
thread->stats.AddErrors(1);
|
|
879
|
+
shared->SetVerificationFailure();
|
|
899
880
|
}
|
|
900
|
-
return true;
|
|
901
|
-
};
|
|
902
881
|
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
assert(ryw_expected_values.size() == num_of_keys);
|
|
910
|
-
check_result = check_multiget(keys[i], values[i], statuses[i],
|
|
911
|
-
ryw_expected_values[i]);
|
|
912
|
-
} else {
|
|
913
|
-
check_result = check_multiget(keys[i], values[i], statuses[i],
|
|
914
|
-
std::nullopt /* ryw_expected_value */);
|
|
882
|
+
// Enable back error injection disbled for checking results
|
|
883
|
+
if (fault_fs_guard) {
|
|
884
|
+
fault_fs_guard->DisableThreadLocalErrorInjection(
|
|
885
|
+
FaultInjectionIOType::kRead);
|
|
886
|
+
fault_fs_guard->DisableThreadLocalErrorInjection(
|
|
887
|
+
FaultInjectionIOType::kMetadataRead);
|
|
915
888
|
}
|
|
916
|
-
|
|
917
|
-
|
|
889
|
+
return check_multiget_res;
|
|
890
|
+
};
|
|
891
|
+
|
|
892
|
+
// Consistency check
|
|
893
|
+
if (do_consistency_check && injected_error_count == 0) {
|
|
894
|
+
size_t num_of_keys = keys.size();
|
|
895
|
+
assert(values.size() == num_of_keys);
|
|
896
|
+
assert(statuses.size() == num_of_keys);
|
|
897
|
+
for (size_t i = 0; i < num_of_keys; ++i) {
|
|
898
|
+
bool check_result = true;
|
|
899
|
+
if (use_txn) {
|
|
900
|
+
std::optional<ExpectedValue> ryw_expected_value;
|
|
901
|
+
|
|
902
|
+
const auto it = ryw_expected_values.find(key_str[i]);
|
|
903
|
+
if (it != ryw_expected_values.end()) {
|
|
904
|
+
ryw_expected_value = it->second;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
check_result = check_multiget(keys[i], values[i], statuses[i],
|
|
908
|
+
ryw_expected_value);
|
|
909
|
+
} else {
|
|
910
|
+
check_result = check_multiget(keys[i], values[i], statuses[i],
|
|
911
|
+
std::nullopt /* ryw_expected_value */);
|
|
912
|
+
}
|
|
913
|
+
if (!check_result) {
|
|
914
|
+
break;
|
|
915
|
+
}
|
|
918
916
|
}
|
|
919
917
|
}
|
|
920
918
|
|
|
@@ -923,6 +921,13 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
923
921
|
}
|
|
924
922
|
if (use_txn) {
|
|
925
923
|
txn->Rollback().PermitUncheckedError();
|
|
924
|
+
// Enable back error injection disbled for transactions
|
|
925
|
+
if (fault_fs_guard) {
|
|
926
|
+
fault_fs_guard->EnableThreadLocalErrorInjection(
|
|
927
|
+
FaultInjectionIOType::kRead);
|
|
928
|
+
fault_fs_guard->EnableThreadLocalErrorInjection(
|
|
929
|
+
FaultInjectionIOType::kMetadataRead);
|
|
930
|
+
}
|
|
926
931
|
}
|
|
927
932
|
return statuses;
|
|
928
933
|
}
|
|
@@ -930,29 +935,25 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
930
935
|
void TestGetEntity(ThreadState* thread, const ReadOptions& read_opts,
|
|
931
936
|
const std::vector<int>& rand_column_families,
|
|
932
937
|
const std::vector<int64_t>& rand_keys) override {
|
|
933
|
-
if (fault_fs_guard) {
|
|
934
|
-
fault_fs_guard->EnableErrorInjection();
|
|
935
|
-
SharedState::ignore_read_error = false;
|
|
936
|
-
}
|
|
937
|
-
|
|
938
938
|
assert(thread);
|
|
939
939
|
|
|
940
940
|
SharedState* const shared = thread->shared;
|
|
941
941
|
assert(shared);
|
|
942
942
|
|
|
943
943
|
assert(!rand_column_families.empty());
|
|
944
|
-
assert(!rand_keys.empty());
|
|
945
944
|
|
|
946
|
-
|
|
947
|
-
shared->GetMutexForKey(rand_column_families[0], rand_keys[0])));
|
|
945
|
+
const int column_family = rand_column_families[0];
|
|
948
946
|
|
|
949
|
-
assert(
|
|
950
|
-
assert(
|
|
947
|
+
assert(column_family >= 0);
|
|
948
|
+
assert(column_family < static_cast<int>(column_families_.size()));
|
|
951
949
|
|
|
952
|
-
ColumnFamilyHandle* const cfh = column_families_[
|
|
950
|
+
ColumnFamilyHandle* const cfh = column_families_[column_family];
|
|
953
951
|
assert(cfh);
|
|
954
952
|
|
|
955
|
-
|
|
953
|
+
assert(!rand_keys.empty());
|
|
954
|
+
|
|
955
|
+
const int64_t key = rand_keys[0];
|
|
956
|
+
const std::string key_str = Key(key);
|
|
956
957
|
|
|
957
958
|
PinnableWideColumns columns_from_db;
|
|
958
959
|
PinnableAttributeGroups attribute_groups_from_db;
|
|
@@ -965,39 +966,57 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
965
966
|
read_ts_slice = read_ts_str;
|
|
966
967
|
read_opts_copy.timestamp = &read_ts_slice;
|
|
967
968
|
}
|
|
968
|
-
bool read_older_ts = MaybeUseOlderTimestampForPointLookup(
|
|
969
|
+
const bool read_older_ts = MaybeUseOlderTimestampForPointLookup(
|
|
969
970
|
thread, read_ts_str, read_ts_slice, read_opts_copy);
|
|
970
971
|
|
|
972
|
+
const ExpectedValue pre_read_expected_value =
|
|
973
|
+
thread->shared->Get(column_family, key);
|
|
974
|
+
|
|
975
|
+
if (fault_fs_guard) {
|
|
976
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
977
|
+
FaultInjectionIOType::kRead);
|
|
978
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
979
|
+
FaultInjectionIOType::kMetadataRead);
|
|
980
|
+
SharedState::ignore_read_error = false;
|
|
981
|
+
}
|
|
982
|
+
|
|
971
983
|
Status s;
|
|
972
984
|
if (FLAGS_use_attribute_group) {
|
|
973
985
|
attribute_groups_from_db.emplace_back(cfh);
|
|
974
|
-
s = db_->GetEntity(read_opts_copy,
|
|
986
|
+
s = db_->GetEntity(read_opts_copy, key_str, &attribute_groups_from_db);
|
|
975
987
|
if (s.ok()) {
|
|
976
988
|
s = attribute_groups_from_db.back().status();
|
|
977
989
|
}
|
|
978
990
|
} else {
|
|
979
|
-
s = db_->GetEntity(read_opts_copy, cfh,
|
|
991
|
+
s = db_->GetEntity(read_opts_copy, cfh, key_str, &columns_from_db);
|
|
980
992
|
}
|
|
981
993
|
|
|
982
|
-
|
|
994
|
+
const ExpectedValue post_read_expected_value =
|
|
995
|
+
thread->shared->Get(column_family, key);
|
|
983
996
|
|
|
997
|
+
int injected_error_count = 0;
|
|
984
998
|
if (fault_fs_guard) {
|
|
985
|
-
|
|
999
|
+
injected_error_count = GetMinInjectedErrorCount(
|
|
1000
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
1001
|
+
FaultInjectionIOType::kRead),
|
|
1002
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
1003
|
+
FaultInjectionIOType::kMetadataRead));
|
|
1004
|
+
if (!SharedState::ignore_read_error && injected_error_count > 0 &&
|
|
1005
|
+
(s.ok() || s.IsNotFound())) {
|
|
1006
|
+
// Grab mutex so multiple thread don't try to print the
|
|
1007
|
+
// stack trace at the same time
|
|
1008
|
+
MutexLock l(thread->shared->GetMutex());
|
|
1009
|
+
fprintf(stderr, "Didn't get expected error from GetEntity\n");
|
|
1010
|
+
fprintf(stderr, "Callstack that injected the fault\n");
|
|
1011
|
+
fault_fs_guard->PrintInjectedThreadLocalErrorBacktrace(
|
|
1012
|
+
FaultInjectionIOType::kRead);
|
|
1013
|
+
fault_fs_guard->PrintInjectedThreadLocalErrorBacktrace(
|
|
1014
|
+
FaultInjectionIOType::kMetadataRead);
|
|
1015
|
+
std::terminate();
|
|
1016
|
+
}
|
|
986
1017
|
}
|
|
987
1018
|
|
|
988
1019
|
if (s.ok()) {
|
|
989
|
-
if (fault_fs_guard) {
|
|
990
|
-
if (error_count && !SharedState::ignore_read_error) {
|
|
991
|
-
// Grab mutex so multiple threads don't try to print the
|
|
992
|
-
// stack trace at the same time
|
|
993
|
-
MutexLock l(shared->GetMutex());
|
|
994
|
-
fprintf(stderr, "Didn't get expected error from GetEntity\n");
|
|
995
|
-
fprintf(stderr, "Call stack that injected the fault\n");
|
|
996
|
-
fault_fs_guard->PrintFaultBacktrace();
|
|
997
|
-
std::terminate();
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
1020
|
thread->stats.AddGets(1, 1);
|
|
1002
1021
|
|
|
1003
1022
|
if (!FLAGS_skip_verifydb && !read_older_ts) {
|
|
@@ -1008,48 +1027,55 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1008
1027
|
FLAGS_use_attribute_group
|
|
1009
1028
|
? attribute_groups_from_db.back().columns()
|
|
1010
1029
|
: columns_from_db.columns();
|
|
1011
|
-
ExpectedValue expected =
|
|
1012
|
-
shared->Get(rand_column_families[0], rand_keys[0]);
|
|
1013
1030
|
if (!VerifyWideColumns(columns)) {
|
|
1014
1031
|
shared->SetVerificationFailure();
|
|
1015
1032
|
fprintf(stderr,
|
|
1016
1033
|
"error : inconsistent columns returned by GetEntity for key "
|
|
1017
1034
|
"%s: %s\n",
|
|
1018
|
-
StringToHex(
|
|
1019
|
-
|
|
1020
|
-
|
|
1035
|
+
StringToHex(key_str).c_str(),
|
|
1036
|
+
WideColumnsToHex(columns).c_str());
|
|
1037
|
+
} else if (ExpectedValueHelper::MustHaveNotExisted(
|
|
1038
|
+
pre_read_expected_value, post_read_expected_value)) {
|
|
1021
1039
|
shared->SetVerificationFailure();
|
|
1022
1040
|
fprintf(
|
|
1023
1041
|
stderr,
|
|
1024
1042
|
"error : inconsistent values for key %s: GetEntity returns %s, "
|
|
1025
1043
|
"expected state does not have the key.\n",
|
|
1026
|
-
StringToHex(
|
|
1044
|
+
StringToHex(key_str).c_str(), WideColumnsToHex(columns).c_str());
|
|
1045
|
+
} else {
|
|
1046
|
+
const uint32_t value_base_from_db =
|
|
1047
|
+
GetValueBase(WideColumnsHelper::GetDefaultColumn(columns));
|
|
1048
|
+
if (!ExpectedValueHelper::InExpectedValueBaseRange(
|
|
1049
|
+
value_base_from_db, pre_read_expected_value,
|
|
1050
|
+
post_read_expected_value)) {
|
|
1051
|
+
shared->SetVerificationFailure();
|
|
1052
|
+
fprintf(
|
|
1053
|
+
stderr,
|
|
1054
|
+
"error : inconsistent values for key %s: GetEntity returns %s "
|
|
1055
|
+
"with value base %d that falls out of expected state's value "
|
|
1056
|
+
"base range.\n",
|
|
1057
|
+
StringToHex(key_str).c_str(), WideColumnsToHex(columns).c_str(),
|
|
1058
|
+
value_base_from_db);
|
|
1059
|
+
}
|
|
1027
1060
|
}
|
|
1028
1061
|
}
|
|
1029
1062
|
} else if (s.IsNotFound()) {
|
|
1030
1063
|
thread->stats.AddGets(1, 0);
|
|
1031
1064
|
|
|
1032
1065
|
if (!FLAGS_skip_verifydb && !read_older_ts) {
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
if (ExpectedValueHelper::MustHaveExisted(expected, expected)) {
|
|
1066
|
+
if (ExpectedValueHelper::MustHaveExisted(pre_read_expected_value,
|
|
1067
|
+
post_read_expected_value)) {
|
|
1036
1068
|
shared->SetVerificationFailure();
|
|
1037
1069
|
fprintf(stderr,
|
|
1038
1070
|
"error : inconsistent values for key %s: expected state has "
|
|
1039
1071
|
"the key, GetEntity returns NotFound.\n",
|
|
1040
|
-
StringToHex(
|
|
1072
|
+
StringToHex(key_str).c_str());
|
|
1041
1073
|
}
|
|
1042
1074
|
}
|
|
1043
|
-
} else {
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
thread->stats.AddVerifiedErrors(1);
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
if (fault_fs_guard) {
|
|
1052
|
-
fault_fs_guard->DisableErrorInjection();
|
|
1075
|
+
} else if (injected_error_count == 0 || !IsErrorInjectedAndRetryable(s)) {
|
|
1076
|
+
fprintf(stderr, "error : GetEntity() returns %s for key: %s.\n",
|
|
1077
|
+
s.ToString().c_str(), StringToHex(key_str).c_str());
|
|
1078
|
+
thread->shared->SetVerificationFailure();
|
|
1053
1079
|
}
|
|
1054
1080
|
}
|
|
1055
1081
|
|
|
@@ -1064,272 +1090,347 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1064
1090
|
read_opts_copy.snapshot = snapshot_guard.snapshot();
|
|
1065
1091
|
|
|
1066
1092
|
assert(!rand_column_families.empty());
|
|
1067
|
-
assert(rand_column_families[0] >= 0);
|
|
1068
|
-
assert(rand_column_families[0] < static_cast<int>(column_families_.size()));
|
|
1069
1093
|
|
|
1070
|
-
|
|
1094
|
+
const int column_family = rand_column_families[0];
|
|
1095
|
+
|
|
1096
|
+
assert(column_family >= 0);
|
|
1097
|
+
assert(column_family < static_cast<int>(column_families_.size()));
|
|
1098
|
+
|
|
1099
|
+
ColumnFamilyHandle* const cfh = column_families_[column_family];
|
|
1071
1100
|
assert(cfh);
|
|
1072
1101
|
|
|
1073
1102
|
assert(!rand_keys.empty());
|
|
1074
1103
|
|
|
1075
1104
|
const size_t num_keys = rand_keys.size();
|
|
1076
1105
|
|
|
1077
|
-
std::
|
|
1078
|
-
std::vector<Slice> key_slices(num_keys);
|
|
1106
|
+
std::unique_ptr<Transaction> txn;
|
|
1079
1107
|
|
|
1080
|
-
if (
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1108
|
+
if (FLAGS_use_txn) {
|
|
1109
|
+
// TODO(hx235): test fault injection with MultiGetEntity() with
|
|
1110
|
+
// transactions
|
|
1111
|
+
if (fault_fs_guard) {
|
|
1112
|
+
fault_fs_guard->DisableThreadLocalErrorInjection(
|
|
1113
|
+
FaultInjectionIOType::kRead);
|
|
1114
|
+
fault_fs_guard->DisableThreadLocalErrorInjection(
|
|
1115
|
+
FaultInjectionIOType::kMetadataRead);
|
|
1116
|
+
}
|
|
1117
|
+
WriteOptions write_options;
|
|
1118
|
+
if (FLAGS_rate_limit_auto_wal_flush) {
|
|
1119
|
+
write_options.rate_limiter_priority = Env::IO_USER;
|
|
1120
|
+
}
|
|
1084
1121
|
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1122
|
+
const Status s = NewTxn(write_options, &txn);
|
|
1123
|
+
if (!s.ok()) {
|
|
1124
|
+
fprintf(stderr, "NewTxn error: %s\n", s.ToString().c_str());
|
|
1125
|
+
thread->shared->SafeTerminate();
|
|
1126
|
+
}
|
|
1088
1127
|
}
|
|
1089
1128
|
|
|
1090
|
-
|
|
1129
|
+
std::vector<std::string> keys(num_keys);
|
|
1130
|
+
std::vector<Slice> key_slices(num_keys);
|
|
1131
|
+
std::unordered_map<std::string, ExpectedValue> ryw_expected_values;
|
|
1091
1132
|
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
if (!is_consistent) {
|
|
1095
|
-
fprintf(stderr,
|
|
1096
|
-
"TestMultiGetEntity%s error: results are not consistent\n",
|
|
1097
|
-
FLAGS_use_attribute_group ? "(AttributeGroup)" : "");
|
|
1098
|
-
_thread->stats.AddErrors(1);
|
|
1099
|
-
// Fail fast to preserve the DB state
|
|
1100
|
-
_thread->shared->SetVerificationFailure();
|
|
1101
|
-
} else if (s.ok()) {
|
|
1102
|
-
_thread->stats.AddGets(1, 1);
|
|
1103
|
-
} else if (s.IsNotFound()) {
|
|
1104
|
-
_thread->stats.AddGets(1, 0);
|
|
1105
|
-
} else {
|
|
1106
|
-
if (err_count == 0) {
|
|
1107
|
-
fprintf(stderr, "MultiGetEntity%s error: %s\n",
|
|
1108
|
-
FLAGS_use_attribute_group ? "(AttributeGroup)" : "",
|
|
1109
|
-
s.ToString().c_str());
|
|
1110
|
-
_thread->stats.AddErrors(1);
|
|
1111
|
-
} else {
|
|
1112
|
-
_thread->stats.AddVerifiedErrors(1);
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
|
-
};
|
|
1133
|
+
for (size_t i = 0; i < num_keys; ++i) {
|
|
1134
|
+
const int64_t key = rand_keys[i];
|
|
1116
1135
|
|
|
1117
|
-
|
|
1118
|
-
|
|
1136
|
+
keys[i] = Key(key);
|
|
1137
|
+
key_slices[i] = keys[i];
|
|
1119
1138
|
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
PinnableAttributeGroups attribute_groups;
|
|
1124
|
-
attribute_groups.emplace_back(cfh);
|
|
1125
|
-
results.emplace_back(std::move(attribute_groups));
|
|
1139
|
+
if (FLAGS_use_txn) {
|
|
1140
|
+
MaybeAddKeyToTxnForRYW(thread, column_family, key, txn.get(),
|
|
1141
|
+
ryw_expected_values);
|
|
1126
1142
|
}
|
|
1127
|
-
|
|
1128
|
-
results.data());
|
|
1143
|
+
}
|
|
1129
1144
|
|
|
1130
|
-
|
|
1131
|
-
error_count = fault_fs_guard->GetAndResetErrorCount();
|
|
1145
|
+
int injected_error_count = 0;
|
|
1132
1146
|
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1147
|
+
auto verify_expected_errors = [&](auto get_status) {
|
|
1148
|
+
assert(fault_fs_guard);
|
|
1149
|
+
injected_error_count = GetMinInjectedErrorCount(
|
|
1150
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
1151
|
+
FaultInjectionIOType::kRead),
|
|
1152
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
1153
|
+
FaultInjectionIOType::kMetadataRead));
|
|
1154
|
+
if (injected_error_count) {
|
|
1155
|
+
int stat_nok_nfound = 0;
|
|
1156
|
+
for (size_t i = 0; i < num_keys; ++i) {
|
|
1157
|
+
const Status& s = get_status(i);
|
|
1158
|
+
if (!s.ok() && !s.IsNotFound()) {
|
|
1159
|
+
++stat_nok_nfound;
|
|
1140
1160
|
}
|
|
1161
|
+
}
|
|
1141
1162
|
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1163
|
+
if (!SharedState::ignore_read_error &&
|
|
1164
|
+
stat_nok_nfound < injected_error_count) {
|
|
1165
|
+
// Grab mutex so multiple threads don't try to print the
|
|
1166
|
+
// stack trace at the same time
|
|
1167
|
+
assert(thread->shared);
|
|
1168
|
+
MutexLock l(thread->shared->GetMutex());
|
|
1147
1169
|
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1170
|
+
fprintf(stderr, "Didn't get expected error from MultiGetEntity\n");
|
|
1171
|
+
fprintf(stderr, "num_keys %zu Expected %d errors, seen %d\n",
|
|
1172
|
+
num_keys, injected_error_count, stat_nok_nfound);
|
|
1173
|
+
fprintf(stderr, "Call stack that injected the fault\n");
|
|
1174
|
+
fault_fs_guard->PrintInjectedThreadLocalErrorBacktrace(
|
|
1175
|
+
FaultInjectionIOType::kRead);
|
|
1176
|
+
fault_fs_guard->PrintInjectedThreadLocalErrorBacktrace(
|
|
1177
|
+
FaultInjectionIOType::kMetadataRead);
|
|
1178
|
+
std::terminate();
|
|
1157
1179
|
}
|
|
1158
|
-
fault_fs_guard->DisableErrorInjection();
|
|
1159
1180
|
}
|
|
1181
|
+
};
|
|
1160
1182
|
|
|
1161
|
-
|
|
1183
|
+
auto check_results = [&](auto get_columns, auto get_status,
|
|
1184
|
+
auto do_extra_check, auto call_get_entity) {
|
|
1185
|
+
// Temporarily disable error injection for checking results
|
|
1186
|
+
if (fault_fs_guard) {
|
|
1187
|
+
fault_fs_guard->DisableThreadLocalErrorInjection(
|
|
1188
|
+
FaultInjectionIOType::kRead);
|
|
1189
|
+
fault_fs_guard->DisableThreadLocalErrorInjection(
|
|
1190
|
+
FaultInjectionIOType::kMetadataRead);
|
|
1191
|
+
}
|
|
1162
1192
|
const bool check_get_entity =
|
|
1163
|
-
!
|
|
1193
|
+
!injected_error_count && FLAGS_check_multiget_entity_consistency;
|
|
1164
1194
|
|
|
1165
1195
|
for (size_t i = 0; i < num_keys; ++i) {
|
|
1166
|
-
|
|
1167
|
-
const Status& s =
|
|
1196
|
+
const WideColumns& columns = get_columns(i);
|
|
1197
|
+
const Status& s = get_status(i);
|
|
1168
1198
|
|
|
1169
1199
|
bool is_consistent = true;
|
|
1170
1200
|
|
|
1171
|
-
if (s.ok() && !VerifyWideColumns(
|
|
1172
|
-
fprintf(
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
WideColumnsToHex(results[i][0].columns()).c_str());
|
|
1201
|
+
if (s.ok() && !VerifyWideColumns(columns)) {
|
|
1202
|
+
fprintf(
|
|
1203
|
+
stderr,
|
|
1204
|
+
"error : inconsistent columns returned by MultiGetEntity for key "
|
|
1205
|
+
"%s: %s\n",
|
|
1206
|
+
StringToHex(keys[i]).c_str(), WideColumnsToHex(columns).c_str());
|
|
1178
1207
|
is_consistent = false;
|
|
1179
|
-
} else if (
|
|
1180
|
-
|
|
1181
|
-
ThreadStatusUtil::SetThreadOperation(
|
|
1182
|
-
ThreadStatus::OperationType::OP_GETENTITY);
|
|
1183
|
-
const Status cmp_s =
|
|
1184
|
-
db_->GetEntity(read_opts_copy, cfh, key_slices[i], &cmp_result);
|
|
1185
|
-
|
|
1186
|
-
if (!cmp_s.ok() && !cmp_s.IsNotFound()) {
|
|
1187
|
-
fprintf(stderr, "GetEntity error: %s\n", cmp_s.ToString().c_str());
|
|
1208
|
+
} else if (s.ok() || s.IsNotFound()) {
|
|
1209
|
+
if (!do_extra_check(keys[i], columns, s)) {
|
|
1188
1210
|
is_consistent = false;
|
|
1189
|
-
} else if (
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
} else {
|
|
1199
|
-
assert(cmp_s.ok());
|
|
1200
|
-
|
|
1201
|
-
if (s.IsNotFound()) {
|
|
1202
|
-
fprintf(stderr,
|
|
1203
|
-
"Inconsistent results for key %s: MultiGetEntity "
|
|
1204
|
-
"(AttributeGroup) returned "
|
|
1205
|
-
"not found, GetEntity returned ok\n",
|
|
1206
|
-
StringToHex(keys[i]).c_str());
|
|
1211
|
+
} else if (check_get_entity) {
|
|
1212
|
+
PinnableWideColumns cmp_result;
|
|
1213
|
+
ThreadStatusUtil::SetThreadOperation(
|
|
1214
|
+
ThreadStatus::OperationType::OP_GETENTITY);
|
|
1215
|
+
const Status cmp_s = call_get_entity(key_slices[i], &cmp_result);
|
|
1216
|
+
|
|
1217
|
+
if (!cmp_s.ok() && !cmp_s.IsNotFound()) {
|
|
1218
|
+
fprintf(stderr, "GetEntity error: %s\n",
|
|
1219
|
+
cmp_s.ToString().c_str());
|
|
1207
1220
|
is_consistent = false;
|
|
1221
|
+
} else if (cmp_s.IsNotFound()) {
|
|
1222
|
+
if (s.ok()) {
|
|
1223
|
+
fprintf(
|
|
1224
|
+
stderr,
|
|
1225
|
+
"Inconsistent results for key %s: MultiGetEntity returned "
|
|
1226
|
+
"ok, GetEntity returned not found\n",
|
|
1227
|
+
StringToHex(keys[i]).c_str());
|
|
1228
|
+
is_consistent = false;
|
|
1229
|
+
}
|
|
1208
1230
|
} else {
|
|
1209
|
-
assert(
|
|
1210
|
-
|
|
1211
|
-
if (
|
|
1212
|
-
fprintf(
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
WideColumnsToHex(results[i][0].columns()).c_str(),
|
|
1218
|
-
WideColumnsToHex(cmp_result.columns()).c_str());
|
|
1231
|
+
assert(cmp_s.ok());
|
|
1232
|
+
|
|
1233
|
+
if (s.IsNotFound()) {
|
|
1234
|
+
fprintf(
|
|
1235
|
+
stderr,
|
|
1236
|
+
"Inconsistent results for key %s: MultiGetEntity returned "
|
|
1237
|
+
"not found, GetEntity returned ok\n",
|
|
1238
|
+
StringToHex(keys[i]).c_str());
|
|
1219
1239
|
is_consistent = false;
|
|
1240
|
+
} else {
|
|
1241
|
+
assert(s.ok());
|
|
1242
|
+
|
|
1243
|
+
const WideColumns& cmp_columns = cmp_result.columns();
|
|
1244
|
+
|
|
1245
|
+
if (columns != cmp_columns) {
|
|
1246
|
+
fprintf(stderr,
|
|
1247
|
+
"Inconsistent results for key %s: MultiGetEntity "
|
|
1248
|
+
"returned "
|
|
1249
|
+
"%s, GetEntity returned %s\n",
|
|
1250
|
+
StringToHex(keys[i]).c_str(),
|
|
1251
|
+
WideColumnsToHex(columns).c_str(),
|
|
1252
|
+
WideColumnsToHex(cmp_columns).c_str());
|
|
1253
|
+
is_consistent = false;
|
|
1254
|
+
}
|
|
1220
1255
|
}
|
|
1221
1256
|
}
|
|
1222
1257
|
}
|
|
1223
1258
|
}
|
|
1224
|
-
|
|
1259
|
+
|
|
1225
1260
|
if (!is_consistent) {
|
|
1261
|
+
fprintf(stderr,
|
|
1262
|
+
"TestMultiGetEntity error: results are not consistent\n");
|
|
1263
|
+
thread->stats.AddErrors(1);
|
|
1264
|
+
// Fail fast to preserve the DB state
|
|
1265
|
+
thread->shared->SetVerificationFailure();
|
|
1226
1266
|
break;
|
|
1267
|
+
} else if (s.ok()) {
|
|
1268
|
+
thread->stats.AddGets(1, 1);
|
|
1269
|
+
} else if (s.IsNotFound()) {
|
|
1270
|
+
thread->stats.AddGets(1, 0);
|
|
1271
|
+
} else if (injected_error_count == 0 ||
|
|
1272
|
+
!IsErrorInjectedAndRetryable(s)) {
|
|
1273
|
+
fprintf(stderr, "MultiGetEntity error: %s\n", s.ToString().c_str());
|
|
1274
|
+
thread->stats.AddErrors(1);
|
|
1275
|
+
thread->shared->SetVerificationFailure();
|
|
1227
1276
|
}
|
|
1228
1277
|
}
|
|
1229
|
-
|
|
1230
|
-
|
|
1278
|
+
// Enable back error injection disbled for checking results
|
|
1279
|
+
if (fault_fs_guard) {
|
|
1280
|
+
fault_fs_guard->EnableThreadLocalErrorInjection(
|
|
1281
|
+
FaultInjectionIOType::kRead);
|
|
1282
|
+
fault_fs_guard->EnableThreadLocalErrorInjection(
|
|
1283
|
+
FaultInjectionIOType::kMetadataRead);
|
|
1284
|
+
}
|
|
1285
|
+
};
|
|
1231
1286
|
|
|
1287
|
+
if (FLAGS_use_txn) {
|
|
1288
|
+
// Transactional/read-your-own-writes MultiGetEntity verification
|
|
1232
1289
|
std::vector<PinnableWideColumns> results(num_keys);
|
|
1233
1290
|
std::vector<Status> statuses(num_keys);
|
|
1234
1291
|
|
|
1235
|
-
|
|
1292
|
+
assert(txn);
|
|
1293
|
+
txn->MultiGetEntity(read_opts_copy, cfh, num_keys, key_slices.data(),
|
|
1236
1294
|
results.data(), statuses.data());
|
|
1237
1295
|
|
|
1238
|
-
|
|
1239
|
-
|
|
1296
|
+
auto ryw_check = [&](const std::string& key, const WideColumns& columns,
|
|
1297
|
+
const Status& s) -> bool {
|
|
1298
|
+
const auto it = ryw_expected_values.find(key);
|
|
1299
|
+
if (it == ryw_expected_values.end()) {
|
|
1300
|
+
return true;
|
|
1301
|
+
}
|
|
1240
1302
|
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1303
|
+
const auto& ryw_expected_value = it->second;
|
|
1304
|
+
|
|
1305
|
+
if (s.ok()) {
|
|
1306
|
+
if (ryw_expected_value.IsDeleted()) {
|
|
1307
|
+
fprintf(
|
|
1308
|
+
stderr,
|
|
1309
|
+
"MultiGetEntity failed the read-your-own-write check for key "
|
|
1310
|
+
"%s\n",
|
|
1311
|
+
Slice(key).ToString(true).c_str());
|
|
1312
|
+
fprintf(stderr,
|
|
1313
|
+
"MultiGetEntity returned ok, transaction has non-committed "
|
|
1314
|
+
"delete\n");
|
|
1315
|
+
return false;
|
|
1316
|
+
} else {
|
|
1317
|
+
const uint32_t value_base = ryw_expected_value.GetValueBase();
|
|
1318
|
+
char expected_value[100];
|
|
1319
|
+
const size_t sz = GenerateValue(value_base, expected_value,
|
|
1320
|
+
sizeof(expected_value));
|
|
1321
|
+
const Slice expected_slice(expected_value, sz);
|
|
1322
|
+
const WideColumns expected_columns =
|
|
1323
|
+
GenerateExpectedWideColumns(value_base, expected_slice);
|
|
1324
|
+
|
|
1325
|
+
if (columns != expected_columns) {
|
|
1326
|
+
fprintf(
|
|
1327
|
+
stderr,
|
|
1328
|
+
"MultiGetEntity failed the read-your-own-write check for key "
|
|
1329
|
+
"%s\n",
|
|
1330
|
+
Slice(key).ToString(true).c_str());
|
|
1331
|
+
fprintf(stderr, "MultiGetEntity returned %s\n",
|
|
1332
|
+
WideColumnsToHex(columns).c_str());
|
|
1333
|
+
fprintf(stderr, "Transaction has non-committed write %s\n",
|
|
1334
|
+
WideColumnsToHex(expected_columns).c_str());
|
|
1335
|
+
return false;
|
|
1246
1336
|
}
|
|
1247
|
-
}
|
|
1248
1337
|
|
|
1249
|
-
|
|
1250
|
-
// Grab mutex so multiple threads don't try to print the
|
|
1251
|
-
// stack trace at the same time
|
|
1252
|
-
assert(thread->shared);
|
|
1253
|
-
MutexLock l(thread->shared->GetMutex());
|
|
1254
|
-
|
|
1255
|
-
fprintf(stderr, "Didn't get expected error from MultiGetEntity\n");
|
|
1256
|
-
fprintf(stderr, "num_keys %zu Expected %d errors, seen %d\n",
|
|
1257
|
-
num_keys, error_count, stat_nok);
|
|
1258
|
-
fprintf(stderr, "Call stack that injected the fault\n");
|
|
1259
|
-
fault_fs_guard->PrintFaultBacktrace();
|
|
1260
|
-
std::terminate();
|
|
1338
|
+
return true;
|
|
1261
1339
|
}
|
|
1262
1340
|
}
|
|
1263
1341
|
|
|
1264
|
-
|
|
1342
|
+
assert(s.IsNotFound());
|
|
1343
|
+
if (!ryw_expected_value.IsDeleted()) {
|
|
1344
|
+
fprintf(stderr,
|
|
1345
|
+
"MultiGetEntity failed the read-your-own-write check for key "
|
|
1346
|
+
"%s\n",
|
|
1347
|
+
Slice(key).ToString(true).c_str());
|
|
1348
|
+
fprintf(stderr,
|
|
1349
|
+
"MultiGetEntity returned not found, transaction has "
|
|
1350
|
+
"non-committed write\n");
|
|
1351
|
+
return false;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
return true;
|
|
1355
|
+
};
|
|
1356
|
+
|
|
1357
|
+
check_results([&](size_t i) { return results[i].columns(); },
|
|
1358
|
+
[&](size_t i) { return statuses[i]; }, ryw_check,
|
|
1359
|
+
[&](const Slice& key, PinnableWideColumns* result) {
|
|
1360
|
+
return txn->GetEntity(read_opts_copy, cfh, key, result);
|
|
1361
|
+
});
|
|
1362
|
+
|
|
1363
|
+
txn->Rollback().PermitUncheckedError();
|
|
1364
|
+
// Enable back error injection disbled for transactions
|
|
1365
|
+
if (fault_fs_guard) {
|
|
1366
|
+
fault_fs_guard->EnableThreadLocalErrorInjection(
|
|
1367
|
+
FaultInjectionIOType::kRead);
|
|
1368
|
+
fault_fs_guard->EnableThreadLocalErrorInjection(
|
|
1369
|
+
FaultInjectionIOType::kMetadataRead);
|
|
1265
1370
|
}
|
|
1371
|
+
} else if (FLAGS_use_attribute_group) {
|
|
1372
|
+
// AttributeGroup MultiGetEntity verification
|
|
1266
1373
|
|
|
1267
|
-
|
|
1268
|
-
|
|
1374
|
+
if (fault_fs_guard) {
|
|
1375
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
1376
|
+
FaultInjectionIOType::kRead);
|
|
1377
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
1378
|
+
FaultInjectionIOType::kMetadataRead);
|
|
1379
|
+
SharedState::ignore_read_error = false;
|
|
1380
|
+
}
|
|
1269
1381
|
|
|
1382
|
+
std::vector<PinnableAttributeGroups> results;
|
|
1383
|
+
results.reserve(num_keys);
|
|
1270
1384
|
for (size_t i = 0; i < num_keys; ++i) {
|
|
1271
|
-
|
|
1385
|
+
PinnableAttributeGroups attribute_groups;
|
|
1386
|
+
attribute_groups.emplace_back(cfh);
|
|
1387
|
+
results.emplace_back(std::move(attribute_groups));
|
|
1388
|
+
}
|
|
1272
1389
|
|
|
1273
|
-
|
|
1390
|
+
db_->MultiGetEntity(read_opts_copy, num_keys, key_slices.data(),
|
|
1391
|
+
results.data());
|
|
1274
1392
|
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
"%s: %s\n",
|
|
1280
|
-
StringToHex(keys[i]).c_str(),
|
|
1281
|
-
WideColumnsToHex(results[i].columns()).c_str());
|
|
1282
|
-
is_consistent = false;
|
|
1283
|
-
} else if (check_get_entity && (s.ok() || s.IsNotFound())) {
|
|
1284
|
-
PinnableWideColumns cmp_result;
|
|
1285
|
-
ThreadStatusUtil::SetThreadOperation(
|
|
1286
|
-
ThreadStatus::OperationType::OP_GETENTITY);
|
|
1287
|
-
const Status cmp_s =
|
|
1288
|
-
db_->GetEntity(read_opts_copy, cfh, key_slices[i], &cmp_result);
|
|
1289
|
-
|
|
1290
|
-
if (!cmp_s.ok() && !cmp_s.IsNotFound()) {
|
|
1291
|
-
fprintf(stderr, "GetEntity error: %s\n", cmp_s.ToString().c_str());
|
|
1292
|
-
is_consistent = false;
|
|
1293
|
-
} else if (cmp_s.IsNotFound()) {
|
|
1294
|
-
if (s.ok()) {
|
|
1295
|
-
fprintf(
|
|
1296
|
-
stderr,
|
|
1297
|
-
"Inconsistent results for key %s: MultiGetEntity returned "
|
|
1298
|
-
"ok, GetEntity returned not found\n",
|
|
1299
|
-
StringToHex(keys[i]).c_str());
|
|
1300
|
-
is_consistent = false;
|
|
1301
|
-
}
|
|
1302
|
-
} else {
|
|
1303
|
-
assert(cmp_s.ok());
|
|
1393
|
+
if (fault_fs_guard) {
|
|
1394
|
+
verify_expected_errors(
|
|
1395
|
+
[&](size_t i) { return results[i][0].status(); });
|
|
1396
|
+
}
|
|
1304
1397
|
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1398
|
+
// Compare against non-attribute-group GetEntity result
|
|
1399
|
+
check_results([&](size_t i) { return results[i][0].columns(); },
|
|
1400
|
+
[&](size_t i) { return results[i][0].status(); },
|
|
1401
|
+
[](const Slice& /* key */, const WideColumns& /* columns */,
|
|
1402
|
+
const Status& /* s */) { return true; },
|
|
1403
|
+
[&](const Slice& key, PinnableWideColumns* result) {
|
|
1404
|
+
return db_->GetEntity(read_opts_copy, cfh, key, result);
|
|
1405
|
+
});
|
|
1406
|
+
} else {
|
|
1407
|
+
// Non-AttributeGroup MultiGetEntity verification
|
|
1314
1408
|
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
WideColumnsToHex(results[i].columns()).c_str(),
|
|
1322
|
-
WideColumnsToHex(cmp_result.columns()).c_str());
|
|
1323
|
-
is_consistent = false;
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
}
|
|
1328
|
-
handle_result(thread, s, is_consistent, error_count);
|
|
1329
|
-
if (!is_consistent) {
|
|
1330
|
-
break;
|
|
1331
|
-
}
|
|
1409
|
+
if (fault_fs_guard) {
|
|
1410
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
1411
|
+
FaultInjectionIOType::kRead);
|
|
1412
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
1413
|
+
FaultInjectionIOType::kMetadataRead);
|
|
1414
|
+
SharedState::ignore_read_error = false;
|
|
1332
1415
|
}
|
|
1416
|
+
|
|
1417
|
+
std::vector<PinnableWideColumns> results(num_keys);
|
|
1418
|
+
std::vector<Status> statuses(num_keys);
|
|
1419
|
+
|
|
1420
|
+
db_->MultiGetEntity(read_opts_copy, cfh, num_keys, key_slices.data(),
|
|
1421
|
+
results.data(), statuses.data());
|
|
1422
|
+
|
|
1423
|
+
if (fault_fs_guard) {
|
|
1424
|
+
verify_expected_errors([&](size_t i) { return statuses[i]; });
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
check_results([&](size_t i) { return results[i].columns(); },
|
|
1428
|
+
[&](size_t i) { return statuses[i]; },
|
|
1429
|
+
[](const Slice& /* key */, const WideColumns& /* columns */,
|
|
1430
|
+
const Status& /* s */) { return true; },
|
|
1431
|
+
[&](const Slice& key, PinnableWideColumns* result) {
|
|
1432
|
+
return db_->GetEntity(read_opts_copy, cfh, key, result);
|
|
1433
|
+
});
|
|
1333
1434
|
}
|
|
1334
1435
|
}
|
|
1335
1436
|
|
|
@@ -1355,6 +1456,10 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1355
1456
|
// For half of the time, set the upper bound to the next prefix
|
|
1356
1457
|
ub_slice = Slice(upper_bound);
|
|
1357
1458
|
ro_copy.iterate_upper_bound = &ub_slice;
|
|
1459
|
+
if (FLAGS_use_sqfc_for_range_queries) {
|
|
1460
|
+
ro_copy.table_filter =
|
|
1461
|
+
sqfc_factory_->GetTableFilterForRangeQuery(prefix, ub_slice);
|
|
1462
|
+
}
|
|
1358
1463
|
}
|
|
1359
1464
|
|
|
1360
1465
|
std::string read_ts_str;
|
|
@@ -1362,16 +1467,19 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1362
1467
|
MaybeUseOlderTimestampForRangeScan(thread, read_ts_str, read_ts_slice,
|
|
1363
1468
|
ro_copy);
|
|
1364
1469
|
|
|
1470
|
+
if (fault_fs_guard) {
|
|
1471
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
1472
|
+
FaultInjectionIOType::kRead);
|
|
1473
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
1474
|
+
FaultInjectionIOType::kMetadataRead);
|
|
1475
|
+
SharedState::ignore_read_error = false;
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1365
1478
|
std::unique_ptr<Iterator> iter(db_->NewIterator(ro_copy, cfh));
|
|
1366
1479
|
|
|
1367
1480
|
uint64_t count = 0;
|
|
1368
1481
|
Status s;
|
|
1369
1482
|
|
|
1370
|
-
if (fault_fs_guard) {
|
|
1371
|
-
fault_fs_guard->EnableErrorInjection();
|
|
1372
|
-
SharedState::ignore_read_error = false;
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
1483
|
for (iter->Seek(prefix); iter->Valid() && iter->key().starts_with(prefix);
|
|
1376
1484
|
iter->Next()) {
|
|
1377
1485
|
++count;
|
|
@@ -1402,23 +1510,36 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1402
1510
|
s = iter->status();
|
|
1403
1511
|
}
|
|
1404
1512
|
|
|
1405
|
-
|
|
1513
|
+
int injected_error_count = 0;
|
|
1406
1514
|
if (fault_fs_guard) {
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1515
|
+
injected_error_count = GetMinInjectedErrorCount(
|
|
1516
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
1517
|
+
FaultInjectionIOType::kRead),
|
|
1518
|
+
fault_fs_guard->GetAndResetInjectedThreadLocalErrorCount(
|
|
1519
|
+
FaultInjectionIOType::kMetadataRead));
|
|
1520
|
+
if (!SharedState::ignore_read_error && injected_error_count > 0 &&
|
|
1521
|
+
s.ok()) {
|
|
1522
|
+
// Grab mutex so multiple thread don't try to print the
|
|
1523
|
+
// stack trace at the same time
|
|
1524
|
+
MutexLock l(thread->shared->GetMutex());
|
|
1525
|
+
fprintf(stderr, "Didn't get expected error from PrefixScan\n");
|
|
1526
|
+
fprintf(stderr, "Callstack that injected the fault\n");
|
|
1527
|
+
fault_fs_guard->PrintInjectedThreadLocalErrorBacktrace(
|
|
1528
|
+
FaultInjectionIOType::kRead);
|
|
1529
|
+
fault_fs_guard->PrintInjectedThreadLocalErrorBacktrace(
|
|
1530
|
+
FaultInjectionIOType::kMetadataRead);
|
|
1531
|
+
std::terminate();
|
|
1532
|
+
}
|
|
1414
1533
|
}
|
|
1415
1534
|
|
|
1416
|
-
if (
|
|
1417
|
-
|
|
1535
|
+
if (s.ok()) {
|
|
1536
|
+
thread->stats.AddPrefixes(1, count);
|
|
1537
|
+
} else if (injected_error_count == 0 || !IsErrorInjectedAndRetryable(s)) {
|
|
1538
|
+
fprintf(stderr, "TestPrefixScan error: %s\n", s.ToString().c_str());
|
|
1539
|
+
thread->shared->SetVerificationFailure();
|
|
1418
1540
|
}
|
|
1419
|
-
thread->stats.AddPrefixes(1, count);
|
|
1420
1541
|
|
|
1421
|
-
return
|
|
1542
|
+
return s;
|
|
1422
1543
|
}
|
|
1423
1544
|
|
|
1424
1545
|
Status TestPut(ThreadState* thread, WriteOptions& write_opts,
|
|
@@ -1464,11 +1585,28 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1464
1585
|
assert(cfh);
|
|
1465
1586
|
|
|
1466
1587
|
if (FLAGS_verify_before_write) {
|
|
1588
|
+
// Temporarily disable error injection for preparation
|
|
1589
|
+
if (fault_fs_guard) {
|
|
1590
|
+
fault_fs_guard->DisableThreadLocalErrorInjection(
|
|
1591
|
+
FaultInjectionIOType::kRead);
|
|
1592
|
+
fault_fs_guard->DisableThreadLocalErrorInjection(
|
|
1593
|
+
FaultInjectionIOType::kMetadataRead);
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1467
1596
|
std::string from_db;
|
|
1468
1597
|
Status s = db_->Get(read_opts, cfh, k, &from_db);
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1598
|
+
bool res = VerifyOrSyncValue(
|
|
1599
|
+
rand_column_family, rand_key, read_opts, shared,
|
|
1600
|
+
/* msg_prefix */ "Pre-Put Get verification", from_db, s);
|
|
1601
|
+
|
|
1602
|
+
// Enable back error injection disabled for preparation
|
|
1603
|
+
if (fault_fs_guard) {
|
|
1604
|
+
fault_fs_guard->EnableThreadLocalErrorInjection(
|
|
1605
|
+
FaultInjectionIOType::kRead);
|
|
1606
|
+
fault_fs_guard->EnableThreadLocalErrorInjection(
|
|
1607
|
+
FaultInjectionIOType::kMetadataRead);
|
|
1608
|
+
}
|
|
1609
|
+
if (!res) {
|
|
1472
1610
|
return s;
|
|
1473
1611
|
}
|
|
1474
1612
|
}
|
|
@@ -1483,12 +1621,18 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1483
1621
|
|
|
1484
1622
|
if (FLAGS_use_put_entity_one_in > 0 &&
|
|
1485
1623
|
(value_base % FLAGS_use_put_entity_one_in) == 0) {
|
|
1486
|
-
if (
|
|
1487
|
-
|
|
1488
|
-
|
|
1624
|
+
if (!FLAGS_use_txn) {
|
|
1625
|
+
if (FLAGS_use_attribute_group) {
|
|
1626
|
+
s = db_->PutEntity(write_opts, k,
|
|
1627
|
+
GenerateAttributeGroups({cfh}, value_base, v));
|
|
1628
|
+
} else {
|
|
1629
|
+
s = db_->PutEntity(write_opts, cfh, k,
|
|
1630
|
+
GenerateWideColumns(value_base, v));
|
|
1631
|
+
}
|
|
1489
1632
|
} else {
|
|
1490
|
-
s =
|
|
1491
|
-
|
|
1633
|
+
s = ExecuteTransaction(write_opts, thread, [&](Transaction& txn) {
|
|
1634
|
+
return txn.PutEntity(cfh, k, GenerateWideColumns(value_base, v));
|
|
1635
|
+
});
|
|
1492
1636
|
}
|
|
1493
1637
|
} else if (FLAGS_use_timed_put_one_in > 0 &&
|
|
1494
1638
|
((value_base + kLargePrimeForCommonFactorSkew) %
|
|
@@ -1527,7 +1671,9 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1527
1671
|
|
|
1528
1672
|
if (!s.ok()) {
|
|
1529
1673
|
pending_expected_value.Rollback();
|
|
1530
|
-
if (
|
|
1674
|
+
if (IsErrorInjectedAndRetryable(s)) {
|
|
1675
|
+
return s;
|
|
1676
|
+
} else if (FLAGS_inject_error_severity == 2) {
|
|
1531
1677
|
if (!is_db_stopped_ && s.severity() >= Status::Severity::kFatalError) {
|
|
1532
1678
|
is_db_stopped_ = true;
|
|
1533
1679
|
} else if (!is_db_stopped_ ||
|
|
@@ -1585,7 +1731,9 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1585
1731
|
|
|
1586
1732
|
if (!s.ok()) {
|
|
1587
1733
|
pending_expected_value.Rollback();
|
|
1588
|
-
if (
|
|
1734
|
+
if (IsErrorInjectedAndRetryable(s)) {
|
|
1735
|
+
return s;
|
|
1736
|
+
} else if (FLAGS_inject_error_severity == 2) {
|
|
1589
1737
|
if (!is_db_stopped_ &&
|
|
1590
1738
|
s.severity() >= Status::Severity::kFatalError) {
|
|
1591
1739
|
is_db_stopped_ = true;
|
|
@@ -1618,7 +1766,9 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1618
1766
|
|
|
1619
1767
|
if (!s.ok()) {
|
|
1620
1768
|
pending_expected_value.Rollback();
|
|
1621
|
-
if (
|
|
1769
|
+
if (IsErrorInjectedAndRetryable(s)) {
|
|
1770
|
+
return s;
|
|
1771
|
+
} else if (FLAGS_inject_error_severity == 2) {
|
|
1622
1772
|
if (!is_db_stopped_ &&
|
|
1623
1773
|
s.severity() >= Status::Severity::kFatalError) {
|
|
1624
1774
|
is_db_stopped_ = true;
|
|
@@ -1686,7 +1836,9 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1686
1836
|
pending_expected_values) {
|
|
1687
1837
|
pending_expected_value.Rollback();
|
|
1688
1838
|
}
|
|
1689
|
-
if (
|
|
1839
|
+
if (IsErrorInjectedAndRetryable(s)) {
|
|
1840
|
+
return s;
|
|
1841
|
+
} else if (FLAGS_inject_error_severity == 2) {
|
|
1690
1842
|
if (!is_db_stopped_ && s.severity() >= Status::Severity::kFatalError) {
|
|
1691
1843
|
is_db_stopped_ = true;
|
|
1692
1844
|
} else if (!is_db_stopped_ ||
|
|
@@ -1715,11 +1867,26 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1715
1867
|
FLAGS_db + "/." + std::to_string(thread->tid) + ".sst";
|
|
1716
1868
|
Status s;
|
|
1717
1869
|
std::ostringstream ingest_options_oss;
|
|
1870
|
+
|
|
1871
|
+
// Temporarily disable error injection for preparation
|
|
1872
|
+
if (fault_fs_guard) {
|
|
1873
|
+
fault_fs_guard->DisableThreadLocalErrorInjection(
|
|
1874
|
+
FaultInjectionIOType::kMetadataRead);
|
|
1875
|
+
fault_fs_guard->DisableThreadLocalErrorInjection(
|
|
1876
|
+
FaultInjectionIOType::kMetadataWrite);
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1718
1879
|
if (db_stress_env->FileExists(sst_filename).ok()) {
|
|
1719
1880
|
// Maybe we terminated abnormally before, so cleanup to give this file
|
|
1720
1881
|
// ingestion a clean slate
|
|
1721
1882
|
s = db_stress_env->DeleteFile(sst_filename);
|
|
1722
1883
|
}
|
|
1884
|
+
if (fault_fs_guard) {
|
|
1885
|
+
fault_fs_guard->EnableThreadLocalErrorInjection(
|
|
1886
|
+
FaultInjectionIOType::kMetadataRead);
|
|
1887
|
+
fault_fs_guard->EnableThreadLocalErrorInjection(
|
|
1888
|
+
FaultInjectionIOType::kMetadataWrite);
|
|
1889
|
+
}
|
|
1723
1890
|
|
|
1724
1891
|
SstFileWriter sst_file_writer(EnvOptions(options_), options_);
|
|
1725
1892
|
if (s.ok()) {
|
|
@@ -1801,15 +1968,14 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1801
1968
|
pending_expected_values) {
|
|
1802
1969
|
pending_expected_value.Rollback();
|
|
1803
1970
|
}
|
|
1804
|
-
|
|
1971
|
+
|
|
1972
|
+
if (!IsErrorInjectedAndRetryable(s)) {
|
|
1805
1973
|
fprintf(stderr,
|
|
1806
1974
|
"file ingestion error: %s under specified "
|
|
1807
1975
|
"IngestExternalFileOptions: %s (Empty string or "
|
|
1808
1976
|
"missing field indicates default option or value is used)\n",
|
|
1809
1977
|
s.ToString().c_str(), ingest_options_oss.str().c_str());
|
|
1810
1978
|
thread->shared->SafeTerminate();
|
|
1811
|
-
} else {
|
|
1812
|
-
fprintf(stdout, "file ingestion error: %s\n", s.ToString().c_str());
|
|
1813
1979
|
}
|
|
1814
1980
|
} else {
|
|
1815
1981
|
for (PendingExpectedValue& pending_expected_value :
|
|
@@ -1876,6 +2042,13 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1876
2042
|
// GetIntVal().
|
|
1877
2043
|
ro.iterate_upper_bound = &max_key_slice;
|
|
1878
2044
|
}
|
|
2045
|
+
std::string ub_str, lb_str;
|
|
2046
|
+
if (FLAGS_use_sqfc_for_range_queries) {
|
|
2047
|
+
ub_str = Key(ub);
|
|
2048
|
+
lb_str = Key(lb);
|
|
2049
|
+
ro.table_filter =
|
|
2050
|
+
sqfc_factory_->GetTableFilterForRangeQuery(lb_str, ub_str);
|
|
2051
|
+
}
|
|
1879
2052
|
|
|
1880
2053
|
ColumnFamilyHandle* const cfh = column_families_[rand_column_family];
|
|
1881
2054
|
assert(cfh);
|
|
@@ -1888,7 +2061,19 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1888
2061
|
pre_read_expected_values.push_back(
|
|
1889
2062
|
shared->Get(rand_column_family, i + lb));
|
|
1890
2063
|
}
|
|
1891
|
-
std::unique_ptr<Iterator> iter
|
|
2064
|
+
std::unique_ptr<Iterator> iter;
|
|
2065
|
+
if (FLAGS_use_multi_cf_iterator) {
|
|
2066
|
+
std::vector<ColumnFamilyHandle*> cfhs;
|
|
2067
|
+
cfhs.reserve(rand_column_families.size());
|
|
2068
|
+
for (auto cf_index : rand_column_families) {
|
|
2069
|
+
cfhs.emplace_back(column_families_[cf_index]);
|
|
2070
|
+
}
|
|
2071
|
+
assert(!cfhs.empty());
|
|
2072
|
+
iter = db_->NewCoalescingIterator(ro, cfhs);
|
|
2073
|
+
} else {
|
|
2074
|
+
iter = std::unique_ptr<Iterator>(db_->NewIterator(ro, cfh));
|
|
2075
|
+
}
|
|
2076
|
+
|
|
1892
2077
|
for (int64_t i = 0; i < static_cast<int64_t>(expected_values_size); ++i) {
|
|
1893
2078
|
post_read_expected_values.push_back(
|
|
1894
2079
|
shared->Get(rand_column_family, i + lb));
|
|
@@ -1973,13 +2158,17 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
1973
2158
|
assert(last_key < ub);
|
|
1974
2159
|
if (!iter->Valid()) {
|
|
1975
2160
|
if (!iter->status().ok()) {
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
2161
|
+
if (IsErrorInjectedAndRetryable(iter->status())) {
|
|
2162
|
+
return iter->status();
|
|
2163
|
+
} else {
|
|
2164
|
+
thread->shared->SetVerificationFailure();
|
|
2165
|
+
fprintf(stderr, "TestIterate against expected state error: %s\n",
|
|
2166
|
+
iter->status().ToString().c_str());
|
|
2167
|
+
fprintf(stderr, "Column family: %s, op_logs: %s\n",
|
|
2168
|
+
cfh->GetName().c_str(), op_logs.c_str());
|
|
2169
|
+
thread->stats.AddErrors(1);
|
|
2170
|
+
return iter->status();
|
|
2171
|
+
}
|
|
1983
2172
|
}
|
|
1984
2173
|
if (!check_no_key_in_range(last_key + 1, ub)) {
|
|
1985
2174
|
return Status::OK();
|
|
@@ -2031,13 +2220,17 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
2031
2220
|
assert(lb < last_key);
|
|
2032
2221
|
if (!iter->Valid()) {
|
|
2033
2222
|
if (!iter->status().ok()) {
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2223
|
+
if (IsErrorInjectedAndRetryable(iter->status())) {
|
|
2224
|
+
return iter->status();
|
|
2225
|
+
} else {
|
|
2226
|
+
thread->shared->SetVerificationFailure();
|
|
2227
|
+
fprintf(stderr, "TestIterate against expected state error: %s\n",
|
|
2228
|
+
iter->status().ToString().c_str());
|
|
2229
|
+
fprintf(stderr, "Column family: %s, op_logs: %s\n",
|
|
2230
|
+
cfh->GetName().c_str(), op_logs.c_str());
|
|
2231
|
+
thread->stats.AddErrors(1);
|
|
2232
|
+
return iter->status();
|
|
2233
|
+
}
|
|
2041
2234
|
}
|
|
2042
2235
|
if (!check_no_key_in_range(lb, last_key)) {
|
|
2043
2236
|
return Status::OK();
|
|
@@ -2078,9 +2271,10 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
2078
2271
|
op_logs += "P";
|
|
2079
2272
|
}
|
|
2080
2273
|
|
|
2081
|
-
// Write-prepared and
|
|
2274
|
+
// Write-prepared/write-unprepared transactions and multi-CF iterator do not
|
|
2275
|
+
// support Refresh() yet.
|
|
2082
2276
|
if (!(FLAGS_use_txn && FLAGS_txn_write_policy != 0) &&
|
|
2083
|
-
thread->rand.OneIn(2)) {
|
|
2277
|
+
!FLAGS_use_multi_cf_iterator && thread->rand.OneIn(2)) {
|
|
2084
2278
|
pre_read_expected_values.clear();
|
|
2085
2279
|
post_read_expected_values.clear();
|
|
2086
2280
|
// Refresh after forward/backward scan to allow higher chance of SV
|
|
@@ -2090,6 +2284,9 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
2090
2284
|
shared->Get(rand_column_family, i + lb));
|
|
2091
2285
|
}
|
|
2092
2286
|
Status rs = iter->Refresh();
|
|
2287
|
+
if (!rs.ok() && IsErrorInjectedAndRetryable(rs)) {
|
|
2288
|
+
return rs;
|
|
2289
|
+
}
|
|
2093
2290
|
assert(rs.ok());
|
|
2094
2291
|
op_logs += "Refresh ";
|
|
2095
2292
|
for (int64_t i = 0; i < static_cast<int64_t>(expected_values_size); ++i) {
|
|
@@ -2251,13 +2448,17 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
2251
2448
|
}
|
|
2252
2449
|
|
|
2253
2450
|
if (!iter->status().ok()) {
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2451
|
+
if (IsErrorInjectedAndRetryable(iter->status())) {
|
|
2452
|
+
return iter->status();
|
|
2453
|
+
} else {
|
|
2454
|
+
thread->shared->SetVerificationFailure();
|
|
2455
|
+
fprintf(stderr, "TestIterate against expected state error: %s\n",
|
|
2456
|
+
iter->status().ToString().c_str());
|
|
2457
|
+
fprintf(stderr, "Column family: %s, op_logs: %s\n",
|
|
2458
|
+
cfh->GetName().c_str(), op_logs.c_str());
|
|
2459
|
+
thread->stats.AddErrors(1);
|
|
2460
|
+
return iter->status();
|
|
2461
|
+
}
|
|
2261
2462
|
}
|
|
2262
2463
|
|
|
2263
2464
|
thread->stats.AddIterations(1);
|
|
@@ -2372,6 +2573,93 @@ class NonBatchedOpsStressTest : public StressTest {
|
|
|
2372
2573
|
return !shared->AllowsOverwrite(key_num);
|
|
2373
2574
|
};
|
|
2374
2575
|
}
|
|
2576
|
+
|
|
2577
|
+
void MaybeAddKeyToTxnForRYW(
|
|
2578
|
+
ThreadState* thread, int column_family, int64_t key, Transaction* txn,
|
|
2579
|
+
std::unordered_map<std::string, ExpectedValue>& ryw_expected_values) {
|
|
2580
|
+
assert(thread);
|
|
2581
|
+
assert(txn);
|
|
2582
|
+
|
|
2583
|
+
SharedState* const shared = thread->shared;
|
|
2584
|
+
assert(shared);
|
|
2585
|
+
|
|
2586
|
+
if (!shared->AllowsOverwrite(key) && shared->Exists(column_family, key)) {
|
|
2587
|
+
// Just do read your write checks for keys that allow overwrites.
|
|
2588
|
+
return;
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
// With a 1 in 10 probability, insert the just added key in the batch
|
|
2592
|
+
// into the transaction. This will create an overlap with the MultiGet
|
|
2593
|
+
// keys and exercise some corner cases in the code
|
|
2594
|
+
if (thread->rand.OneIn(10)) {
|
|
2595
|
+
assert(column_family >= 0);
|
|
2596
|
+
assert(column_family < static_cast<int>(column_families_.size()));
|
|
2597
|
+
|
|
2598
|
+
ColumnFamilyHandle* const cfh = column_families_[column_family];
|
|
2599
|
+
assert(cfh);
|
|
2600
|
+
|
|
2601
|
+
const std::string k = Key(key);
|
|
2602
|
+
|
|
2603
|
+
enum class Op {
|
|
2604
|
+
PutOrPutEntity,
|
|
2605
|
+
Merge,
|
|
2606
|
+
Delete,
|
|
2607
|
+
// add new operations above this line
|
|
2608
|
+
NumberOfOps
|
|
2609
|
+
};
|
|
2610
|
+
|
|
2611
|
+
const Op op = static_cast<Op>(
|
|
2612
|
+
thread->rand.Uniform(static_cast<int>(Op::NumberOfOps)));
|
|
2613
|
+
|
|
2614
|
+
Status s;
|
|
2615
|
+
|
|
2616
|
+
switch (op) {
|
|
2617
|
+
case Op::PutOrPutEntity:
|
|
2618
|
+
case Op::Merge: {
|
|
2619
|
+
ExpectedValue put_value;
|
|
2620
|
+
put_value.SyncPut(static_cast<uint32_t>(thread->rand.Uniform(
|
|
2621
|
+
static_cast<int>(ExpectedValue::GetValueBaseMask()))));
|
|
2622
|
+
ryw_expected_values[k] = put_value;
|
|
2623
|
+
|
|
2624
|
+
const uint32_t value_base = put_value.GetValueBase();
|
|
2625
|
+
|
|
2626
|
+
char value[100];
|
|
2627
|
+
const size_t sz = GenerateValue(value_base, value, sizeof(value));
|
|
2628
|
+
const Slice v(value, sz);
|
|
2629
|
+
|
|
2630
|
+
if (op == Op::PutOrPutEntity) {
|
|
2631
|
+
if (FLAGS_use_put_entity_one_in > 0 &&
|
|
2632
|
+
(value_base % FLAGS_use_put_entity_one_in) == 0) {
|
|
2633
|
+
s = txn->PutEntity(cfh, k, GenerateWideColumns(value_base, v));
|
|
2634
|
+
} else {
|
|
2635
|
+
s = txn->Put(cfh, k, v);
|
|
2636
|
+
}
|
|
2637
|
+
} else {
|
|
2638
|
+
s = txn->Merge(cfh, k, v);
|
|
2639
|
+
}
|
|
2640
|
+
|
|
2641
|
+
break;
|
|
2642
|
+
}
|
|
2643
|
+
case Op::Delete: {
|
|
2644
|
+
ExpectedValue delete_value;
|
|
2645
|
+
delete_value.SyncDelete();
|
|
2646
|
+
ryw_expected_values[k] = delete_value;
|
|
2647
|
+
|
|
2648
|
+
s = txn->Delete(cfh, k);
|
|
2649
|
+
break;
|
|
2650
|
+
}
|
|
2651
|
+
default:
|
|
2652
|
+
assert(false);
|
|
2653
|
+
}
|
|
2654
|
+
|
|
2655
|
+
if (!s.ok()) {
|
|
2656
|
+
fprintf(stderr,
|
|
2657
|
+
"Transaction write error in read-your-own-write test: %s\n",
|
|
2658
|
+
s.ToString().c_str());
|
|
2659
|
+
shared->SafeTerminate();
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2375
2663
|
};
|
|
2376
2664
|
|
|
2377
2665
|
StressTest* CreateNonBatchedOpsStressTest() {
|