diff options
Diffstat (limited to 'src/rocksdb/tools/simulated_hybrid_file_system.h')
-rw-r--r-- | src/rocksdb/tools/simulated_hybrid_file_system.h | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/src/rocksdb/tools/simulated_hybrid_file_system.h b/src/rocksdb/tools/simulated_hybrid_file_system.h new file mode 100644 index 000000000..251d89df7 --- /dev/null +++ b/src/rocksdb/tools/simulated_hybrid_file_system.h @@ -0,0 +1,126 @@ +// Copyright (c) Facebook, Inc. and its affiliates. 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). + +#pragma once + +#ifndef ROCKSDB_LITE + +#include <utility> + +#include "rocksdb/file_system.h" + +namespace ROCKSDB_NAMESPACE { + +// A FileSystem simulates hybrid file system by ingesting latency and limit +// IOPs. +// This class is only used for development purpose and should not be used +// in production. +// Right now we ingest 15ms latency and allow 100 requests per second when +// the file is for warm temperature. +// When the object is destroyed, the list of warm files are written to a +// file, which can be used to reopen a FileSystem and still recover the +// list. This is to allow the information to preserve between db_bench +// runs. +class SimulatedHybridFileSystem : public FileSystemWrapper { + public: + // metadata_file_name stores metadata of the files, so that it can be + // loaded after process restarts. If the file doesn't exist, create + // one. The file is written when the class is destroyed. + // throughput_multiplier: multiplier of throughput. For example, 1 is to + // simulate single disk spindle. 4 is to simualte 4 disk spindles. + // is_full_fs_warm: if true, all files are all included in slow I/O + // simulation. + SimulatedHybridFileSystem(const std::shared_ptr<FileSystem>& base, + const std::string& metadata_file_name, + int throughput_multiplier, bool is_full_fs_warm); + + ~SimulatedHybridFileSystem() override; + + public: + IOStatus NewRandomAccessFile(const std::string& fname, + const FileOptions& file_opts, + std::unique_ptr<FSRandomAccessFile>* result, + IODebugContext* dbg) override; + IOStatus NewWritableFile(const std::string& fname, + const FileOptions& file_opts, + std::unique_ptr<FSWritableFile>* result, + IODebugContext* dbg) override; + IOStatus DeleteFile(const std::string& fname, const IOOptions& options, + IODebugContext* dbg) override; + + const char* Name() const override { return name_.c_str(); } + + private: + // Limit 100 requests per second. Rate limiter is designed to byte but + // we use it as fixed bytes is one request. + std::shared_ptr<RateLimiter> rate_limiter_; + std::mutex mutex_; + std::unordered_set<std::string> warm_file_set_; + std::string metadata_file_name_; + std::string name_; + bool is_full_fs_warm_; +}; + +// Simulated random access file that can control IOPs and latency to simulate +// specific storage media +class SimulatedHybridRaf : public FSRandomAccessFileOwnerWrapper { + public: + SimulatedHybridRaf(std::unique_ptr<FSRandomAccessFile>&& t, + std::shared_ptr<RateLimiter> rate_limiter, + Temperature temperature) + : FSRandomAccessFileOwnerWrapper(std::move(t)), + rate_limiter_(rate_limiter), + temperature_(temperature) {} + + ~SimulatedHybridRaf() override {} + + IOStatus Read(uint64_t offset, size_t n, const IOOptions& options, + Slice* result, char* scratch, + IODebugContext* dbg) const override; + + IOStatus MultiRead(FSReadRequest* reqs, size_t num_reqs, + const IOOptions& options, IODebugContext* dbg) override; + + IOStatus Prefetch(uint64_t offset, size_t n, const IOOptions& options, + IODebugContext* dbg) override; + + private: + std::shared_ptr<RateLimiter> rate_limiter_; + Temperature temperature_; + + void SimulateIOWait(int64_t num_requests) const; +}; + +class SimulatedWritableFile : public FSWritableFileWrapper { + public: + SimulatedWritableFile(std::unique_ptr<FSWritableFile>&& t, + std::shared_ptr<RateLimiter> rate_limiter) + : FSWritableFileWrapper(t.get()), + file_guard_(std::move(t)), + rate_limiter_(rate_limiter) {} + IOStatus Append(const Slice& data, const IOOptions&, + IODebugContext*) override; + IOStatus Append(const Slice& data, const IOOptions& options, + const DataVerificationInfo& verification_info, + IODebugContext* dbg) override; + IOStatus Sync(const IOOptions& options, IODebugContext* dbg) override; + IOStatus PositionedAppend(const Slice& data, uint64_t offset, + const IOOptions& options, + IODebugContext* dbg) override; + IOStatus PositionedAppend(const Slice& data, uint64_t offset, + const IOOptions& options, + const DataVerificationInfo& verification_info, + IODebugContext* dbg) override; + + private: + std::unique_ptr<FSWritableFile> file_guard_; + std::shared_ptr<RateLimiter> rate_limiter_; + size_t unsynced_bytes = 0; + + void SimulateIOWait(int64_t num_requests) const; +}; +} // namespace ROCKSDB_NAMESPACE + +#endif // ROCKSDB_LITE |