summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHui Xiao <huixiao@fb.com>2024-03-12 17:24:12 -0700
committerFacebook GitHub Bot <facebook-github-bot@users.noreply.github.com>2024-03-12 17:24:12 -0700
commit30243c6573e2a8f8612f88257a70f7a1ac51ce63 (patch)
tree7401ccb339a4f64ce8f40be7dda7fcb8a307dbf3
parent122510dc09e8286b006e65964faf3fa7c01de818 (diff)
Add missing db crash options (#12414)
Summary: **Context/Summary:** We are doing a sweep in all public options, including but not limited to the `Options`, `Read/WriteOptions`, `IngestExternalFileOptions`, cache options.., to find and add the uncovered ones into db crash. The options included in this PR require minimum changes to db crash other than adding the options themselves. A bonus change: to surface new issues by improved coverage in stderror, we decided to fail/terminate crash test for manual compactions (CompactFiles, CompactRange()) on meaningful errors. See https://github.com/facebook/rocksdb/pull/12414/files#diff-5c4ced6afb6a90e27fec18ab03b2cd89e8f99db87791b4ecc6fa2694284d50c0R2528-R2532, https://github.com/facebook/rocksdb/pull/12414/files#diff-5c4ced6afb6a90e27fec18ab03b2cd89e8f99db87791b4ecc6fa2694284d50c0R2330-R2336 for more. Pull Request resolved: https://github.com/facebook/rocksdb/pull/12414 Test Plan: - Run `python3 ./tools/db_crashtest.py --simple blackbox` for 10 minutes to ensure no trivial failure - Run `python3 tools/db_crashtest.py --simple blackbox --compact_files_one_in=1 --compact_range_one_in=1 --read_fault_one_in=1 --write_fault_one_in=1 --interval=50` for a while to ensure the bonus change does not result in trivial crash/termination of stress test Reviewed By: ajkr, jowlyzhang, cbi42 Differential Revision: D54691774 Pulled By: hx235 fbshipit-source-id: 50443dfb6aaabd8e24c79a2e42b68c6de877be88
-rw-r--r--db_stress_tool/db_stress_common.h39
-rw-r--r--db_stress_tool/db_stress_gflags.cc157
-rw-r--r--db_stress_tool/db_stress_test_base.cc245
-rw-r--r--db_stress_tool/no_batched_ops_stress.cc19
-rw-r--r--tools/db_crashtest.py41
5 files changed, 454 insertions, 47 deletions
diff --git a/db_stress_tool/db_stress_common.h b/db_stress_tool/db_stress_common.h
index 768e90b9f..977aecff6 100644
--- a/db_stress_tool/db_stress_common.h
+++ b/db_stress_tool/db_stress_common.h
@@ -352,6 +352,45 @@ DECLARE_uint64(initial_auto_readahead_size);
DECLARE_uint64(max_auto_readahead_size);
DECLARE_uint64(num_file_reads_for_auto_readahead);
DECLARE_bool(auto_readahead_size);
+DECLARE_bool(allow_fallocate);
+DECLARE_int32(table_cache_numshardbits);
+DECLARE_bool(enable_write_thread_adaptive_yield);
+DECLARE_uint64(log_readahead_size);
+DECLARE_uint64(bgerror_resume_retry_interval);
+DECLARE_uint64(delete_obsolete_files_period_micros);
+DECLARE_uint64(max_log_file_size);
+DECLARE_uint64(log_file_time_to_roll);
+DECLARE_bool(use_adaptive_mutex);
+DECLARE_bool(advise_random_on_open);
+DECLARE_uint64(WAL_ttl_seconds);
+DECLARE_uint64(WAL_size_limit_MB);
+DECLARE_bool(strict_bytes_per_sync);
+DECLARE_bool(avoid_flush_during_shutdown);
+DECLARE_bool(fill_cache);
+DECLARE_bool(optimize_multiget_for_io);
+DECLARE_bool(memtable_insert_hint_per_batch);
+DECLARE_bool(dump_malloc_stats);
+DECLARE_uint64(stats_history_buffer_size);
+DECLARE_bool(skip_stats_update_on_db_open);
+DECLARE_bool(optimize_filters_for_hits);
+DECLARE_uint64(sample_for_compression);
+DECLARE_bool(report_bg_io_stats);
+DECLARE_bool(cache_index_and_filter_blocks_with_high_priority);
+DECLARE_bool(use_delta_encoding);
+DECLARE_bool(verify_compression);
+DECLARE_uint32(read_amp_bytes_per_bit);
+DECLARE_bool(enable_index_compression);
+DECLARE_uint32(index_shortening);
+DECLARE_uint32(metadata_charge_policy);
+DECLARE_bool(use_adaptive_mutex_lru);
+DECLARE_uint32(compress_format_version);
+DECLARE_uint64(manifest_preallocation_size);
+DECLARE_bool(enable_checksum_handoff);
+DECLARE_uint64(max_total_wal_size);
+DECLARE_double(high_pri_pool_ratio);
+DECLARE_double(low_pri_pool_ratio);
+DECLARE_uint64(soft_pending_compaction_bytes_limit);
+DECLARE_uint64(hard_pending_compaction_bytes_limit);
constexpr long KB = 1024;
constexpr int kRandomValueMaxFactor = 3;
diff --git a/db_stress_tool/db_stress_gflags.cc b/db_stress_tool/db_stress_gflags.cc
index 3a0059425..3156cd2d2 100644
--- a/db_stress_tool/db_stress_gflags.cc
+++ b/db_stress_tool/db_stress_gflags.cc
@@ -7,6 +7,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
+#include "rocksdb/cache.h"
+#include "rocksdb/options.h"
+#include "rocksdb/utilities/backup_engine.h"
#ifdef GFLAGS
#include "db_stress_tool/db_stress_common.h"
@@ -402,7 +405,8 @@ DEFINE_double(experimental_mempurge_threshold, 0.0,
"Maximum estimated useful payload that triggers a "
"mempurge process to collect memtable garbage bytes.");
-DEFINE_bool(enable_write_thread_adaptive_yield, true,
+DEFINE_bool(enable_write_thread_adaptive_yield,
+ ROCKSDB_NAMESPACE::Options().enable_write_thread_adaptive_yield,
"Use a yielding spin loop for brief writer thread waits.");
// Options for StackableDB-based BlobDB
@@ -1144,4 +1148,155 @@ DEFINE_uint32(bottommost_file_compaction_delay, 0,
DEFINE_bool(auto_readahead_size, false,
"Does auto tuning of readahead_size when enabled during scans.");
+DEFINE_bool(allow_fallocate, ROCKSDB_NAMESPACE::Options().allow_fallocate,
+ "Options.allow_fallocate");
+
+DEFINE_int32(table_cache_numshardbits,
+ ROCKSDB_NAMESPACE::Options().table_cache_numshardbits,
+ "Options.table_cache_numshardbits");
+
+DEFINE_uint64(log_readahead_size,
+ ROCKSDB_NAMESPACE::Options().log_readahead_size,
+ "Options.log_readahead_size");
+
+DEFINE_uint64(bgerror_resume_retry_interval,
+ ROCKSDB_NAMESPACE::Options().bgerror_resume_retry_interval,
+ "Options.bgerror_resume_retry_interval");
+
+DEFINE_uint64(delete_obsolete_files_period_micros,
+ ROCKSDB_NAMESPACE::Options().delete_obsolete_files_period_micros,
+ "Options.delete_obsolete_files_period_micros");
+
+DEFINE_uint64(max_log_file_size, ROCKSDB_NAMESPACE::Options().max_log_file_size,
+ "Options.max_log_file_sizes");
+
+DEFINE_uint64(log_file_time_to_roll,
+ ROCKSDB_NAMESPACE::Options().log_file_time_to_roll,
+ "Options.log_file_time_to_roll");
+
+DEFINE_bool(use_adaptive_mutex, ROCKSDB_NAMESPACE::Options().use_adaptive_mutex,
+ "Options.use_adaptive_mutex");
+
+DEFINE_bool(advise_random_on_open,
+ ROCKSDB_NAMESPACE::Options().advise_random_on_open,
+ "Options.advise_random_on_open");
+
+DEFINE_uint64(WAL_ttl_seconds, ROCKSDB_NAMESPACE::Options().WAL_ttl_seconds,
+ "Options.WAL_ttl_seconds");
+
+DEFINE_uint64(WAL_size_limit_MB, ROCKSDB_NAMESPACE::Options().WAL_size_limit_MB,
+ "Options.WAL_size_limit_MB");
+
+DEFINE_bool(strict_bytes_per_sync,
+ ROCKSDB_NAMESPACE::Options().strict_bytes_per_sync,
+ "Options.strict_bytes_per_sync");
+
+DEFINE_bool(avoid_flush_during_shutdown,
+ ROCKSDB_NAMESPACE::Options().avoid_flush_during_shutdown,
+ "Options.avoid_flush_during_shutdown");
+
+DEFINE_bool(fill_cache, ROCKSDB_NAMESPACE::ReadOptions().fill_cache,
+ "ReadOptions.fill_cache");
+
+DEFINE_bool(optimize_multiget_for_io,
+ ROCKSDB_NAMESPACE::ReadOptions().optimize_multiget_for_io,
+ "ReadOptions.optimize_multiget_for_io");
+
+DEFINE_bool(memtable_insert_hint_per_batch,
+ ROCKSDB_NAMESPACE::WriteOptions().memtable_insert_hint_per_batch,
+ "WriteOptions.memtable_insert_hint_per_batch");
+
+DEFINE_bool(dump_malloc_stats, ROCKSDB_NAMESPACE::Options().dump_malloc_stats,
+ "Options.dump_malloc_stats");
+
+DEFINE_uint64(stats_history_buffer_size,
+ ROCKSDB_NAMESPACE::Options().stats_history_buffer_size,
+ "Options.stats_history_buffer_size");
+
+DEFINE_bool(skip_stats_update_on_db_open,
+ ROCKSDB_NAMESPACE::Options().skip_stats_update_on_db_open,
+ "Options.skip_stats_update_on_db_open");
+
+DEFINE_bool(optimize_filters_for_hits,
+ ROCKSDB_NAMESPACE::Options().optimize_filters_for_hits,
+ "Options.optimize_filters_for_hits");
+
+DEFINE_uint64(sample_for_compression,
+ ROCKSDB_NAMESPACE::Options().sample_for_compression,
+ "Options.sample_for_compression");
+
+DEFINE_bool(report_bg_io_stats, ROCKSDB_NAMESPACE::Options().report_bg_io_stats,
+ "Options.report_bg_io_stats");
+
+DEFINE_bool(
+ cache_index_and_filter_blocks_with_high_priority,
+ ROCKSDB_NAMESPACE::BlockBasedTableOptions()
+ .cache_index_and_filter_blocks_with_high_priority,
+ "BlockBasedTableOptions.cache_index_and_filter_blocks_with_high_priority");
+
+DEFINE_bool(use_delta_encoding,
+ ROCKSDB_NAMESPACE::BlockBasedTableOptions().use_delta_encoding,
+ "BlockBasedTableOptions.use_delta_encoding");
+
+DEFINE_bool(verify_compression,
+ ROCKSDB_NAMESPACE::BlockBasedTableOptions().verify_compression,
+ "BlockBasedTableOptions.verify_compression");
+
+DEFINE_uint32(
+ read_amp_bytes_per_bit,
+ ROCKSDB_NAMESPACE::BlockBasedTableOptions().read_amp_bytes_per_bit,
+ "Options.read_amp_bytes_per_bit");
+
+DEFINE_bool(
+ enable_index_compression,
+ ROCKSDB_NAMESPACE::BlockBasedTableOptions().enable_index_compression,
+ "BlockBasedTableOptions.enable_index_compression");
+
+DEFINE_uint32(index_shortening,
+ static_cast<uint32_t>(
+ ROCKSDB_NAMESPACE::BlockBasedTableOptions().index_shortening),
+ "BlockBasedTableOptions.index_shortening");
+
+DEFINE_uint32(metadata_charge_policy,
+ static_cast<uint32_t>(ROCKSDB_NAMESPACE::ShardedCacheOptions()
+ .metadata_charge_policy),
+ "ShardedCacheOptions.metadata_charge_policy");
+
+DEFINE_bool(use_adaptive_mutex_lru,
+ ROCKSDB_NAMESPACE::LRUCacheOptions().use_adaptive_mutex,
+ "LRUCacheOptions.use_adaptive_mutex");
+
+DEFINE_uint32(
+ compress_format_version,
+ static_cast<uint32_t>(ROCKSDB_NAMESPACE::CompressedSecondaryCacheOptions()
+ .compress_format_version),
+ "CompressedSecondaryCacheOptions.compress_format_version");
+
+DEFINE_uint64(manifest_preallocation_size,
+ ROCKSDB_NAMESPACE::Options().manifest_preallocation_size,
+ "Options.manifest_preallocation_size");
+
+DEFINE_uint64(max_total_wal_size,
+ ROCKSDB_NAMESPACE::Options().max_total_wal_size,
+ "Options.max_total_wal_size");
+
+DEFINE_bool(enable_checksum_handoff, false,
+ "If true, include all the supported files in "
+ "Options.checksum_handoff_file. Otherwise include no files.");
+
+DEFINE_double(high_pri_pool_ratio,
+ ROCKSDB_NAMESPACE::LRUCacheOptions().high_pri_pool_ratio,
+ "LRUCacheOptions.high_pri_pool_ratio");
+
+DEFINE_double(low_pri_pool_ratio,
+ ROCKSDB_NAMESPACE::LRUCacheOptions().low_pri_pool_ratio,
+ "LRUCacheOptions.low_pri_pool_ratio");
+
+DEFINE_uint64(soft_pending_compaction_bytes_limit,
+ ROCKSDB_NAMESPACE::Options().soft_pending_compaction_bytes_limit,
+ "Options.soft_pending_compaction_bytes_limit");
+
+DEFINE_uint64(hard_pending_compaction_bytes_limit,
+ ROCKSDB_NAMESPACE::Options().hard_pending_compaction_bytes_limit,
+ "Options.hard_pending_compaction_bytes_limit");
#endif // GFLAGS
diff --git a/db_stress_tool/db_stress_test_base.cc b/db_stress_tool/db_stress_test_base.cc
index feec339d9..7376defbb 100644
--- a/db_stress_tool/db_stress_test_base.cc
+++ b/db_stress_tool/db_stress_test_base.cc
@@ -141,6 +141,7 @@ std::shared_ptr<Cache> StressTest::NewCache(size_t capacity,
}
CompressedSecondaryCacheOptions opts;
opts.capacity = FLAGS_compressed_secondary_cache_size;
+ opts.compress_format_version = FLAGS_compress_format_version;
secondary_cache = NewCompressedSecondaryCache(opts);
if (secondary_cache == nullptr) {
fprintf(stderr, "Failed to allocate compressed secondary cache\n");
@@ -191,6 +192,11 @@ std::shared_ptr<Cache> StressTest::NewCache(size_t capacity,
LRUCacheOptions opts;
opts.capacity = capacity;
opts.num_shard_bits = num_shard_bits;
+ opts.metadata_charge_policy =
+ static_cast<CacheMetadataChargePolicy>(FLAGS_metadata_charge_policy);
+ opts.use_adaptive_mutex = FLAGS_use_adaptive_mutex_lru;
+ opts.high_pri_pool_ratio = FLAGS_high_pri_pool_ratio;
+ opts.low_pri_pool_ratio = FLAGS_low_pri_pool_ratio;
if (tiered) {
TieredCacheOptions tiered_opts;
tiered_opts.cache_opts = &opts;
@@ -830,10 +836,14 @@ void StressTest::OperateDb(ThreadState* thread) {
read_opts.adaptive_readahead = FLAGS_adaptive_readahead;
read_opts.readahead_size = FLAGS_readahead_size;
read_opts.auto_readahead_size = FLAGS_auto_readahead_size;
+ read_opts.fill_cache = FLAGS_fill_cache;
+ read_opts.optimize_multiget_for_io = FLAGS_optimize_multiget_for_io;
WriteOptions write_opts;
if (FLAGS_rate_limit_auto_wal_flush) {
write_opts.rate_limiter_priority = Env::IO_USER;
}
+ write_opts.memtable_insert_hint_per_batch =
+ FLAGS_memtable_insert_hint_per_batch;
auto shared = thread->shared;
char value[100];
std::string from_db;
@@ -1264,6 +1274,10 @@ Status StressTest::TestIterate(ThreadState* thread,
Slice read_ts_slice;
MaybeUseOlderTimestampForRangeScan(thread, read_ts_str, read_ts_slice, ro);
+ std::string op_logs;
+ ro.pin_data = thread->rand.OneIn(2);
+ ro.background_purge_on_iterator_cleanup = thread->rand.OneIn(2);
+
bool expect_total_order = false;
if (thread->rand.OneIn(16)) {
// When prefix extractor is used, it's useful to cover total order seek.
@@ -1315,7 +1329,6 @@ Status StressTest::TestIterate(ThreadState* thread,
}
}
- std::string op_logs;
constexpr size_t kOpLogsLimit = 10000;
for (const std::string& key_str : key_strs) {
@@ -1343,18 +1356,6 @@ Status StressTest::TestIterate(ThreadState* thread,
lower_bound = Slice(lower_bound_str);
}
- // Record some options to op_logs
- op_logs += "total_order_seek: ";
- op_logs += (ro.total_order_seek ? "1 " : "0 ");
- op_logs += "auto_prefix_mode: ";
- op_logs += (ro.auto_prefix_mode ? "1 " : "0 ");
- if (ro.iterate_upper_bound != nullptr) {
- op_logs += "ub: " + upper_bound.ToString(true) + " ";
- }
- if (ro.iterate_lower_bound != nullptr) {
- op_logs += "lb: " + lower_bound.ToString(true) + " ";
- }
-
// Set up an iterator, perform the same operations without bounds and with
// total order seek, and compare the results. This is to identify bugs
// related to bounds, prefix extractor, or reseeking. Sometimes we are
@@ -1531,7 +1532,20 @@ void StressTest::VerifyIterator(ThreadState* thread,
? nullptr
: options_.prefix_extractor.get();
const Comparator* cmp = options_.comparator;
-
+ std::ostringstream read_opt_oss;
+ read_opt_oss << "pin_data: " << ro.pin_data
+ << ", background_purge_on_iterator_cleanup: "
+ << ro.background_purge_on_iterator_cleanup
+ << ", total_order_seek: " << ro.total_order_seek
+ << ", auto_prefix_mode: " << ro.auto_prefix_mode
+ << ", iterate_upper_bound: "
+ << (ro.iterate_upper_bound
+ ? ro.iterate_upper_bound->ToString(true).c_str()
+ : "")
+ << ", iterate_lower_bound: "
+ << (ro.iterate_lower_bound
+ ? ro.iterate_lower_bound->ToString(true).c_str()
+ : "");
if (iter->Valid() && !cmp_iter->Valid()) {
if (pe != nullptr) {
if (!pe->InDomain(seek_key)) {
@@ -1550,8 +1564,10 @@ void StressTest::VerifyIterator(ThreadState* thread,
}
fprintf(stderr,
"Control iterator is invalid but iterator has key %s "
- "%s\n",
- iter->key().ToString(true).c_str(), op_logs.c_str());
+ "%s under specified iterator ReadOptions: %s (Empty string or "
+ "missing field indicates default option or value is used)\n",
+ iter->key().ToString(true).c_str(), op_logs.c_str(),
+ read_opt_oss.str().c_str());
*diverged = true;
} else if (cmp_iter->Valid()) {
@@ -1579,9 +1595,12 @@ void StressTest::VerifyIterator(ThreadState* thread,
}
fprintf(stderr,
"Iterator stays in prefix but control doesn't"
- " iterator key %s control iterator key %s %s\n",
+ " iterator key %s control iterator key %s %s under specified "
+ "iterator ReadOptions: %s (Empty string or "
+ "missing field indicates default option or value is used)\n",
iter->key().ToString(true).c_str(),
- cmp_iter->key().ToString(true).c_str(), op_logs.c_str());
+ cmp_iter->key().ToString(true).c_str(), op_logs.c_str(),
+ read_opt_oss.str().c_str());
}
}
// Check upper or lower bounds.
@@ -1598,8 +1617,11 @@ void StressTest::VerifyIterator(ThreadState* thread,
/*b_has_ts=*/false) > 0))) {
fprintf(stderr,
"Iterator diverged from control iterator which"
- " has value %s %s\n",
- total_order_key.ToString(true).c_str(), op_logs.c_str());
+ " has value %s %s under specified iterator ReadOptions: %s "
+ "(Empty string or "
+ "missing field indicates default option or value is used)\n",
+ total_order_key.ToString(true).c_str(), op_logs.c_str(),
+ read_opt_oss.str().c_str());
if (iter->Valid()) {
fprintf(stderr, "iterator has value %s\n",
iter->key().ToString(true).c_str());
@@ -1681,6 +1703,37 @@ Status StressTest::TestBackupRestore(
} else {
backup_opts.schema_version = 2;
}
+ if (thread->rand.OneIn(3)) {
+ backup_opts.max_background_operations = 16;
+ } else {
+ backup_opts.max_background_operations = 1;
+ }
+ if (thread->rand.OneIn(2)) {
+ backup_opts.backup_rate_limiter.reset(NewGenericRateLimiter(
+ FLAGS_backup_max_size * 1000000 /* rate_bytes_per_sec */,
+ 1 /* refill_period_us */));
+ }
+ if (thread->rand.OneIn(2)) {
+ backup_opts.restore_rate_limiter.reset(NewGenericRateLimiter(
+ FLAGS_backup_max_size * 1000000 /* rate_bytes_per_sec */,
+ 1 /* refill_period_us */));
+ }
+ std::ostringstream backup_opt_oss;
+ backup_opt_oss << "share_table_files: " << backup_opts.share_table_files
+ << ", share_files_with_checksum: "
+ << backup_opts.share_files_with_checksum
+ << ", share_files_with_checksum_naming: "
+ << backup_opts.share_files_with_checksum_naming
+ << ", schema_version: " << backup_opts.schema_version
+ << ", max_background_operations: "
+ << backup_opts.max_background_operations
+ << ", backup_rate_limiter: "
+ << backup_opts.backup_rate_limiter.get()
+ << ", restore_rate_limiter: "
+ << backup_opts.restore_rate_limiter.get();
+
+ std::ostringstream create_backup_opt_oss;
+ std::ostringstream restore_opts_oss;
BackupEngine* backup_engine = nullptr;
std::string from = "a backup/restore operation";
Status s = BackupEngine::Open(db_stress_env, backup_opts, &backup_engine);
@@ -1707,6 +1760,16 @@ Status StressTest::TestBackupRestore(
// lock and wait on a background operation (flush).
create_opts.flush_before_backup = true;
}
+ create_opts.decrease_background_thread_cpu_priority = thread->rand.OneIn(2);
+ create_opts.background_thread_cpu_priority = static_cast<CpuPriority>(
+ thread->rand.Next() % (static_cast<int>(CpuPriority::kHigh) + 1));
+ create_backup_opt_oss << "flush_before_backup: "
+ << create_opts.flush_before_backup
+ << ", decrease_background_thread_cpu_priority: "
+ << create_opts.decrease_background_thread_cpu_priority
+ << ", background_thread_cpu_priority: "
+ << static_cast<int>(
+ create_opts.background_thread_cpu_priority);
s = backup_engine->CreateNewBackup(create_opts, db_);
if (!s.ok()) {
from = "BackupEngine::CreateNewBackup";
@@ -1744,19 +1807,21 @@ Status StressTest::TestBackupRestore(
const bool allow_persistent = thread->tid == 0; // not too many
bool from_latest = false;
int count = static_cast<int>(backup_info.size());
+ RestoreOptions restore_options;
+ restore_options.keep_log_files = thread->rand.OneIn(2);
+ restore_opts_oss << "keep_log_files: " << restore_options.keep_log_files;
if (s.ok() && !inplace_not_restore) {
if (count > 1) {
s = backup_engine->RestoreDBFromBackup(
- RestoreOptions(), backup_info[thread->rand.Uniform(count)].backup_id,
+ restore_options, backup_info[thread->rand.Uniform(count)].backup_id,
restore_dir /* db_dir */, restore_dir /* wal_dir */);
if (!s.ok()) {
from = "BackupEngine::RestoreDBFromBackup";
}
} else {
from_latest = true;
- s = backup_engine->RestoreDBFromLatestBackup(RestoreOptions(),
- restore_dir /* db_dir */,
- restore_dir /* wal_dir */);
+ s = backup_engine->RestoreDBFromLatestBackup(
+ restore_options, restore_dir /* db_dir */, restore_dir /* wal_dir */);
if (!s.ok()) {
from = "BackupEngine::RestoreDBFromLatestBackup";
}
@@ -1779,9 +1844,9 @@ Status StressTest::TestBackupRestore(
std::vector<ColumnFamilyHandle*> restored_cf_handles;
// Not yet implemented: opening restored BlobDB or TransactionDB
- Options restore_options;
+ Options db_opt;
if (s.ok() && !FLAGS_use_txn && !FLAGS_use_blob_db) {
- s = PrepareOptionsForRestoredDB(&restore_options);
+ s = PrepareOptionsForRestoredDB(&db_opt);
if (!s.ok()) {
from = "PrepareRestoredDBOptions in backup/restore";
}
@@ -1794,19 +1859,19 @@ Status StressTest::TestBackupRestore(
// the same order as `column_family_names_`.
assert(FLAGS_clear_column_family_one_in == 0);
for (const auto& name : column_family_names_) {
- cf_descriptors.emplace_back(name, ColumnFamilyOptions(restore_options));
+ cf_descriptors.emplace_back(name, ColumnFamilyOptions(db_opt));
}
if (inplace_not_restore) {
BackupInfo& info = backup_info[thread->rand.Uniform(count)];
- restore_options.env = info.env_for_open.get();
- s = DB::OpenForReadOnly(DBOptions(restore_options), info.name_for_open,
+ db_opt.env = info.env_for_open.get();
+ s = DB::OpenForReadOnly(DBOptions(db_opt), info.name_for_open,
cf_descriptors, &restored_cf_handles,
&restored_db);
if (!s.ok()) {
from = "DB::OpenForReadOnly in backup/restore";
}
} else {
- s = DB::Open(DBOptions(restore_options), restore_dir, cf_descriptors,
+ s = DB::Open(DBOptions(db_opt), restore_dir, cf_descriptors,
&restored_cf_handles, &restored_db);
if (!s.ok()) {
from = "DB::Open in backup/restore";
@@ -1898,8 +1963,13 @@ Status StressTest::TestBackupRestore(
}
}
if (!s.ok() && (!s.IsIOError() || !std::strstr(s.getState(), "injected"))) {
- fprintf(stderr, "Failure in %s with: %s\n", from.c_str(),
- s.ToString().c_str());
+ fprintf(stderr,
+ "Failure in %s with: %s under specified BackupEngineOptions: %s, "
+ "CreateBackupOptions: %s, RestoreOptions: %s (Empty string or "
+ "missing field indicates default option or value is used)\n",
+ from.c_str(), s.ToString().c_str(), backup_opt_oss.str().c_str(),
+ create_backup_opt_oss.str().c_str(),
+ restore_opts_oss.str().c_str());
}
return s;
}
@@ -2248,12 +2318,27 @@ void StressTest::TestCompactFiles(ThreadState* thread,
size_t output_level =
std::min(random_level + 1, cf_meta_data.levels.size() - 1);
- auto s = db_->CompactFiles(CompactionOptions(), column_family,
- input_files, static_cast<int>(output_level));
- if (!s.ok()) {
- fprintf(stdout, "Unable to perform CompactFiles(): %s\n",
- s.ToString().c_str());
+ CompactionOptions compact_options;
+ if (thread->rand.OneIn(2)) {
+ compact_options.output_file_size_limit = FLAGS_target_file_size_base;
+ }
+ std::ostringstream compact_opt_oss;
+ compact_opt_oss << "output_file_size_limit: "
+ << compact_options.output_file_size_limit;
+ auto s = db_->CompactFiles(compact_options, column_family, input_files,
+ static_cast<int>(output_level));
+ if (!s.ok() && !s.IsManualCompactionPaused() && !s.IsAborted() &&
+ !std::strstr(s.getState(), "injected") &&
+ !(s.IsInvalidArgument() &&
+ std::strstr(s.getState(), "Specified compaction input file") &&
+ std::strstr(s.getState(), "does not exist in column family"))) {
+ fprintf(stderr,
+ "Unable to perform CompactFiles(): %s under specified "
+ "CompactionOptions: %s (Empty string or "
+ "missing field indicates default option or value is used)\n",
+ s.ToString().c_str(), compact_opt_oss.str().c_str());
thread->stats.AddNumCompactFilesFailed(1);
+ thread->shared->SafeTerminate();
} else {
thread->stats.AddNumCompactFilesSucceed(1);
}
@@ -2396,6 +2481,9 @@ void StressTest::TestCompactRange(ThreadState* thread, int64_t rand_key,
CompactRangeOptions cro;
cro.exclusive_manual_compaction = static_cast<bool>(thread->rand.Next() % 2);
cro.change_level = static_cast<bool>(thread->rand.Next() % 2);
+ if (thread->rand.OneIn(2)) {
+ cro.target_level = thread->rand.Next() % options_.num_levels;
+ }
std::vector<BottommostLevelCompaction> bottom_level_styles = {
BottommostLevelCompaction::kSkip,
BottommostLevelCompaction::kIfHaveCompactionFilter,
@@ -2425,12 +2513,36 @@ void StressTest::TestCompactRange(ThreadState* thread, int64_t rand_key,
pre_hash =
GetRangeHash(thread, pre_snapshot, column_family, start_key, end_key);
}
-
+ std::ostringstream compact_range_opt_oss;
+ compact_range_opt_oss << "exclusive_manual_compaction: "
+ << cro.exclusive_manual_compaction
+ << ", change_level: " << cro.change_level
+ << ", target_level: " << cro.target_level
+ << ", bottommost_level_compaction: "
+ << static_cast<int>(cro.bottommost_level_compaction)
+ << ", allow_write_stall: " << cro.allow_write_stall
+ << ", max_subcompactions: " << cro.max_subcompactions
+ << ", blob_garbage_collection_policy: "
+ << static_cast<int>(cro.blob_garbage_collection_policy)
+ << ", blob_garbage_collection_age_cutoff: "
+ << cro.blob_garbage_collection_age_cutoff;
Status status = db_->CompactRange(cro, column_family, &start_key, &end_key);
- if (!status.ok()) {
- fprintf(stdout, "Unable to perform CompactRange(): %s\n",
- status.ToString().c_str());
+ if (!status.ok() && !status.IsManualCompactionPaused() &&
+ !std::strstr(status.getState(), "injected") &&
+ !(status.IsNotSupported() &&
+ (std::strstr(status.getState(), "another thread is refitting") ||
+ std::strstr(
+ status.getState(),
+ "Levels between source and target are not empty for a move")))) {
+ fprintf(stdout,
+ "Unable to perform CompactRange(): %s under specified "
+ "CompactRangeOptions: %s (Empty string or "
+ "missing field indicates default option or value is used)\n",
+ status.ToString().c_str(), compact_range_opt_oss.str().c_str());
+ thread->stats.AddErrors(1);
+ // Fail fast to preserve the DB state.
+ thread->shared->SetVerificationFailure();
}
if (pre_snapshot != nullptr) {
@@ -2439,8 +2551,11 @@ void StressTest::TestCompactRange(ThreadState* thread, int64_t rand_key,
if (pre_hash != post_hash) {
fprintf(stderr,
"Data hash different before and after compact range "
- "start_key %s end_key %s\n",
- start_key.ToString(true).c_str(), end_key.ToString(true).c_str());
+ "start_key %s end_key %s under specified CompactRangeOptions: %s "
+ "(Empty string or "
+ "missing field indicates default option or value is used)\n",
+ start_key.ToString(true).c_str(), end_key.ToString(true).c_str(),
+ compact_range_opt_oss.str().c_str());
thread->stats.AddErrors(1);
// Fail fast to preserve the DB state.
thread->shared->SetVerificationFailure();
@@ -3286,6 +3401,15 @@ void InitializeOptionsFromFlags(
block_based_options.max_auto_readahead_size = FLAGS_max_auto_readahead_size;
block_based_options.num_file_reads_for_auto_readahead =
FLAGS_num_file_reads_for_auto_readahead;
+ block_based_options.cache_index_and_filter_blocks_with_high_priority =
+ FLAGS_cache_index_and_filter_blocks_with_high_priority;
+ block_based_options.use_delta_encoding = FLAGS_use_delta_encoding;
+ block_based_options.verify_compression = FLAGS_verify_compression;
+ block_based_options.read_amp_bytes_per_bit = FLAGS_read_amp_bytes_per_bit;
+ block_based_options.enable_index_compression = FLAGS_enable_index_compression;
+ block_based_options.index_shortening =
+ static_cast<BlockBasedTableOptions::IndexShorteningMode>(
+ FLAGS_index_shortening);
options.table_factory.reset(NewBlockBasedTableFactory(block_based_options));
options.db_write_buffer_size = FLAGS_db_write_buffer_size;
options.write_buffer_size = FLAGS_write_buffer_size;
@@ -3486,6 +3610,41 @@ void InitializeOptionsFromFlags(
options.bottommost_file_compaction_delay =
FLAGS_bottommost_file_compaction_delay;
+
+ options.allow_fallocate = FLAGS_allow_fallocate;
+ options.table_cache_numshardbits = FLAGS_table_cache_numshardbits;
+ options.log_readahead_size = FLAGS_log_readahead_size;
+ options.bgerror_resume_retry_interval = FLAGS_bgerror_resume_retry_interval;
+ options.delete_obsolete_files_period_micros =
+ FLAGS_delete_obsolete_files_period_micros;
+ options.max_log_file_size = FLAGS_max_log_file_size;
+ options.log_file_time_to_roll = FLAGS_log_file_time_to_roll;
+ options.use_adaptive_mutex = FLAGS_use_adaptive_mutex;
+ options.advise_random_on_open = FLAGS_advise_random_on_open;
+ // TODO (hx235): test the functionality of `WAL_ttl_seconds`,
+ // `WAL_size_limit_MB` i.e, `GetUpdatesSince()`
+ options.WAL_ttl_seconds = FLAGS_WAL_ttl_seconds;
+ options.WAL_size_limit_MB = FLAGS_WAL_size_limit_MB;
+ options.wal_bytes_per_sync = FLAGS_wal_bytes_per_sync;
+ options.strict_bytes_per_sync = FLAGS_strict_bytes_per_sync;
+ options.avoid_flush_during_shutdown = FLAGS_avoid_flush_during_shutdown;
+ options.dump_malloc_stats = FLAGS_dump_malloc_stats;
+ options.stats_history_buffer_size = FLAGS_stats_history_buffer_size;
+ options.skip_stats_update_on_db_open = FLAGS_skip_stats_update_on_db_open;
+ options.optimize_filters_for_hits = FLAGS_optimize_filters_for_hits;
+ options.sample_for_compression = FLAGS_sample_for_compression;
+ options.report_bg_io_stats = FLAGS_report_bg_io_stats;
+ options.manifest_preallocation_size = FLAGS_manifest_preallocation_size;
+ if (FLAGS_enable_checksum_handoff) {
+ options.checksum_handoff_file_types = {FileTypeSet::All()};
+ } else {
+ options.checksum_handoff_file_types = {};
+ }
+ options.max_total_wal_size = FLAGS_max_total_wal_size;
+ options.soft_pending_compaction_bytes_limit =
+ FLAGS_soft_pending_compaction_bytes_limit;
+ options.hard_pending_compaction_bytes_limit =
+ FLAGS_hard_pending_compaction_bytes_limit;
}
void InitializeOptionsGeneral(
diff --git a/db_stress_tool/no_batched_ops_stress.cc b/db_stress_tool/no_batched_ops_stress.cc
index 7b0c6d2eb..a94de3897 100644
--- a/db_stress_tool/no_batched_ops_stress.cc
+++ b/db_stress_tool/no_batched_ops_stress.cc
@@ -1526,6 +1526,7 @@ class NonBatchedOpsStressTest : public StressTest {
const std::string sst_filename =
FLAGS_db + "/." + std::to_string(thread->tid) + ".sst";
Status s;
+ std::ostringstream ingest_options_oss;
if (db_stress_env->FileExists(sst_filename).ok()) {
// Maybe we terminated abnormally before, so cleanup to give this file
// ingestion a clean slate
@@ -1594,8 +1595,18 @@ class NonBatchedOpsStressTest : public StressTest {
s = sst_file_writer.Finish();
}
if (s.ok()) {
+ IngestExternalFileOptions ingest_options;
+ ingest_options.move_files = thread->rand.OneInOpt(2);
+ ingest_options.verify_checksums_before_ingest = thread->rand.OneInOpt(2);
+ ingest_options.verify_checksums_readahead_size =
+ thread->rand.OneInOpt(2) ? 1024 * 1024 : 0;
+ ingest_options_oss << "move_files: " << ingest_options.move_files
+ << ", verify_checksums_before_ingest: "
+ << ingest_options.verify_checksums_before_ingest
+ << ", verify_checksums_readahead_size: "
+ << ingest_options.verify_checksums_readahead_size;
s = db_->IngestExternalFile(column_families_[column_family],
- {sst_filename}, IngestExternalFileOptions());
+ {sst_filename}, ingest_options);
}
if (!s.ok()) {
for (PendingExpectedValue& pending_expected_value :
@@ -1603,7 +1614,11 @@ class NonBatchedOpsStressTest : public StressTest {
pending_expected_value.Rollback();
}
if (!s.IsIOError() || !std::strstr(s.getState(), "injected")) {
- fprintf(stderr, "file ingestion error: %s\n", s.ToString().c_str());
+ fprintf(stderr,
+ "file ingestion error: %s under specified "
+ "IngestExternalFileOptions: %s (Empty string or "
+ "missing field indicates default option or value is used)\n",
+ s.ToString().c_str(), ingest_options_oss.str().c_str());
thread->shared->SafeTerminate();
} else {
fprintf(stdout, "file ingestion error: %s\n", s.ToString().c_str());
diff --git a/tools/db_crashtest.py b/tools/db_crashtest.py
index 7037156b5..ddd1b9eca 100644
--- a/tools/db_crashtest.py
+++ b/tools/db_crashtest.py
@@ -227,8 +227,47 @@ default_params = {
),
"auto_readahead_size" : lambda: random.choice([0, 1]),
"verify_iterator_with_expected_state_one_in": 5,
+ "allow_fallocate": lambda: random.choice([0, 1]),
+ "table_cache_numshardbits": lambda: random.choice([6] * 3 + [-1] * 2 + [0]),
+ "enable_write_thread_adaptive_yield": lambda: random.choice([0, 1]),
+ "log_readahead_size": lambda: random.choice([0, 16 * 1024 * 1024]),
+ "bgerror_resume_retry_interval": lambda: random.choice([10000, 1000000]),
+ "delete_obsolete_files_period_micros": lambda: random.choice([6 * 60 * 60 * 1000000, 30 * 1000000]),
+ "max_log_file_size": lambda: random.choice([0, 1024 * 1024]),
+ "log_file_time_to_roll": lambda: random.choice([0, 60]),
+ "use_adaptive_mutex": lambda: random.choice([0, 1]),
+ "advise_random_on_open": lambda: random.choice([0] + [1] * 3),
+ "WAL_ttl_seconds": lambda: random.choice([0, 60]),
+ "WAL_size_limit_MB": lambda: random.choice([0, 1]),
+ "wal_bytes_per_sync": lambda: random.choice([0, 1024 * 1024]),
+ "strict_bytes_per_sync": lambda: random.choice([0, 1]),
+ "avoid_flush_during_shutdown": lambda: random.choice([0, 1]),
+ "fill_cache": lambda: random.choice([0, 1]),
+ "optimize_multiget_for_io": lambda: random.choice([0, 1]),
+ "memtable_insert_hint_per_batch": lambda: random.choice([0, 1]),
+ "dump_malloc_stats": lambda: random.choice([0, 1]),
+ "stats_history_buffer_size": lambda: random.choice([0, 1024 * 1024]),
+ "skip_stats_update_on_db_open": lambda: random.choice([0, 1]),
+ "optimize_filters_for_hits": lambda: random.choice([0, 1]),
+ "sample_for_compression": lambda: random.choice([0, 5]),
+ "report_bg_io_stats": lambda: random.choice([0, 1]),
+ "cache_index_and_filter_blocks_with_high_priority": lambda: random.choice([0, 1]),
+ "use_delta_encoding": lambda: random.choice([0, 1]),
+ "verify_compression": lambda: random.choice([0, 1]),
+ "read_amp_bytes_per_bit": lambda: random.choice([0, 32]),
+ "enable_index_compression": lambda: random.choice([0, 1]),
+ "index_shortening": lambda: random.choice([0, 1, 2]),
+ "metadata_charge_policy": lambda: random.choice([0, 1]),
+ "use_adaptive_mutex_lru": lambda: random.choice([0, 1]),
+ "compress_format_version": lambda: random.choice([1, 2]),
+ "manifest_preallocation_size": lambda: random.choice([0, 5 * 1024]),
+ "enable_checksum_handoff": lambda: random.choice([0, 1]),
+ "max_total_wal_size": lambda: random.choice([0] * 4 + [64 * 1024 * 1024]),
+ "high_pri_pool_ratio": lambda: random.choice([0, 0.5]),
+ "low_pri_pool_ratio": lambda: random.choice([0, 0.5]),
+ "soft_pending_compaction_bytes_limit" : lambda: random.choice([1024 * 1024] + [64 * 1073741824] * 4),
+ "hard_pending_compaction_bytes_limit" : lambda: random.choice([2 * 1024 * 1024] + [256 * 1073741824] * 4),
}
-
_TEST_DIR_ENV_VAR = "TEST_TMPDIR"
# If TEST_TMPDIR_EXPECTED is not specified, default value will be TEST_TMPDIR
_TEST_EXPECTED_DIR_ENV_VAR = "TEST_TMPDIR_EXPECTED"