// Copyright (c) 2011-present, Facebook, Inc. All rights reserved. // This source code is licensed under both the GPLv2 (found in the // COPYING file in the root directory) and Apache 2.0 License // (found in the LICENSE.Apache file in the root directory). // // Copyright (c) 2011 The LevelDB Authors. All rights reserved. // 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. #ifdef GFLAGS #pragma once #include "db_stress_tool/db_stress_common.h" #include "db_stress_tool/db_stress_shared_state.h" namespace rocksdb { class Transaction; class TransactionDB; class StressTest { public: StressTest(); virtual ~StressTest(); std::shared_ptr NewCache(size_t capacity); bool BuildOptionsTable(); void InitDb(); void InitReadonlyDb(SharedState*); // Return false if verification fails. bool VerifySecondaries(); void OperateDb(ThreadState* thread); virtual void VerifyDb(ThreadState* thread) const = 0; void PrintStatistics(); protected: Status AssertSame(DB* db, ColumnFamilyHandle* cf, ThreadState::SnapshotState& snap_state); // Currently PreloadDb has to be single-threaded. void PreloadDbAndReopenAsReadOnly(int64_t number_of_keys, SharedState* shared); Status SetOptions(ThreadState* thread); #ifndef ROCKSDB_LITE Status NewTxn(WriteOptions& write_opts, Transaction** txn); Status CommitTxn(Transaction* txn); #endif virtual void MaybeClearOneColumnFamily(ThreadState* /* thread */) {} virtual bool ShouldAcquireMutexOnKey() const { return false; } virtual std::vector GenerateColumnFamilies( const int /* num_column_families */, int rand_column_family) const { return {rand_column_family}; } virtual std::vector GenerateKeys(int64_t rand_key) const { return {rand_key}; } virtual Status TestGet(ThreadState* thread, const ReadOptions& read_opts, const std::vector& rand_column_families, const std::vector& rand_keys) = 0; virtual std::vector TestMultiGet( ThreadState* thread, const ReadOptions& read_opts, const std::vector& rand_column_families, const std::vector& rand_keys) = 0; virtual Status TestPrefixScan(ThreadState* thread, const ReadOptions& read_opts, const std::vector& rand_column_families, const std::vector& rand_keys) = 0; virtual Status TestPut(ThreadState* thread, WriteOptions& write_opts, const ReadOptions& read_opts, const std::vector& cf_ids, const std::vector& keys, char (&value)[100], std::unique_ptr& lock) = 0; virtual Status TestDelete(ThreadState* thread, WriteOptions& write_opts, const std::vector& rand_column_families, const std::vector& rand_keys, std::unique_ptr& lock) = 0; virtual Status TestDeleteRange(ThreadState* thread, WriteOptions& write_opts, const std::vector& rand_column_families, const std::vector& rand_keys, std::unique_ptr& lock) = 0; virtual void TestIngestExternalFile( ThreadState* thread, const std::vector& rand_column_families, const std::vector& rand_keys, std::unique_ptr& lock) = 0; // Issue compact range, starting with start_key, whose integer value // is rand_key. virtual void TestCompactRange(ThreadState* thread, int64_t rand_key, const Slice& start_key, ColumnFamilyHandle* column_family); // Calculate a hash value for all keys in range [start_key, end_key] // at a certain snapshot. uint32_t GetRangeHash(ThreadState* thread, const Snapshot* snapshot, ColumnFamilyHandle* column_family, const Slice& start_key, const Slice& end_key); // Return a column family handle that mirrors what is pointed by // `column_family_id`, which will be used to validate data to be correct. // By default, the column family itself will be returned. virtual ColumnFamilyHandle* GetControlCfh(ThreadState* /* thread*/, int column_family_id) { return column_families_[column_family_id]; } #ifndef ROCKSDB_LITE // Generated a list of keys that close to boundaries of SST keys. // If there isn't any SST file in the DB, return empty list. std::vector GetWhiteBoxKeys(ThreadState* thread, DB* db, ColumnFamilyHandle* cfh, size_t num_keys); #else // !ROCKSDB_LITE std::vector GetWhiteBoxKeys(ThreadState*, DB*, ColumnFamilyHandle*, size_t) { // Not supported in LITE mode. return {}; } #endif // !ROCKSDB_LITE // Given a key K, this creates an iterator which scans to K and then // does a random sequence of Next/Prev operations. virtual Status TestIterate(ThreadState* thread, const ReadOptions& read_opts, const std::vector& rand_column_families, const std::vector& rand_keys); // Enum used by VerifyIterator() to identify the mode to validate. enum LastIterateOp { kLastOpSeek, kLastOpSeekForPrev, kLastOpNextOrPrev }; // Compare the two iterator, iter and cmp_iter are in the same position, // unless iter might be made invalidate or undefined because of // upper or lower bounds, or prefix extractor. // Will flag failure if the verification fails. // diverged = true if the two iterator is already diverged. // True if verification passed, false if not. void VerifyIterator(ThreadState* thread, ColumnFamilyHandle* cmp_cfh, const ReadOptions& ro, Iterator* iter, Iterator* cmp_iter, LastIterateOp op, const Slice& seek_key, bool* diverged); virtual Status TestBackupRestore(ThreadState* thread, const std::vector& rand_column_families, const std::vector& rand_keys); virtual Status TestCheckpoint(ThreadState* thread, const std::vector& rand_column_families, const std::vector& rand_keys); void VerificationAbort(SharedState* shared, std::string msg, Status s) const; void VerificationAbort(SharedState* shared, std::string msg, int cf, int64_t key) const; void PrintEnv() const; void Open(); void Reopen(); std::shared_ptr cache_; std::shared_ptr compressed_cache_; std::shared_ptr filter_policy_; DB* db_; #ifndef ROCKSDB_LITE TransactionDB* txn_db_; #endif Options options_; std::vector column_families_; std::vector column_family_names_; std::atomic new_column_family_name_; int num_times_reopened_; std::unordered_map> options_table_; std::vector options_index_; std::atomic db_preload_finished_; // Fields used for stress-testing secondary instance in the same process std::vector secondaries_; std::vector> secondary_cfh_lists_; }; } // namespace rocksdb #endif // GFLAGS