simulated_hybrid_file_system.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. #pragma once
  6. #include <utility>
  7. #include "rocksdb/file_system.h"
  8. namespace ROCKSDB_NAMESPACE {
  9. // A FileSystem simulates hybrid file system by ingesting latency and limit
  10. // IOPs.
  11. // This class is only used for development purpose and should not be used
  12. // in production.
  13. // Right now we ingest 15ms latency and allow 100 requests per second when
  14. // the file is for warm temperature.
  15. // When the object is destroyed, the list of warm files are written to a
  16. // file, which can be used to reopen a FileSystem and still recover the
  17. // list. This is to allow the information to preserve between db_bench
  18. // runs.
  19. class SimulatedHybridFileSystem : public FileSystemWrapper {
  20. public:
  21. // metadata_file_name stores metadata of the files, so that it can be
  22. // loaded after process restarts. If the file doesn't exist, create
  23. // one. The file is written when the class is destroyed.
  24. // throughput_multiplier: multiplier of throughput. For example, 1 is to
  25. // simulate single disk spindle. 4 is to simualte 4 disk spindles.
  26. // is_full_fs_warm: if true, all files are all included in slow I/O
  27. // simulation.
  28. SimulatedHybridFileSystem(const std::shared_ptr<FileSystem>& base,
  29. const std::string& metadata_file_name,
  30. int throughput_multiplier, bool is_full_fs_warm);
  31. ~SimulatedHybridFileSystem() override;
  32. public:
  33. IOStatus NewRandomAccessFile(const std::string& fname,
  34. const FileOptions& file_opts,
  35. std::unique_ptr<FSRandomAccessFile>* result,
  36. IODebugContext* dbg) override;
  37. IOStatus NewWritableFile(const std::string& fname,
  38. const FileOptions& file_opts,
  39. std::unique_ptr<FSWritableFile>* result,
  40. IODebugContext* dbg) override;
  41. IOStatus DeleteFile(const std::string& fname, const IOOptions& options,
  42. IODebugContext* dbg) override;
  43. const char* Name() const override { return name_.c_str(); }
  44. private:
  45. // Limit 100 requests per second. Rate limiter is designed to byte but
  46. // we use it as fixed bytes is one request.
  47. std::shared_ptr<RateLimiter> rate_limiter_;
  48. std::mutex mutex_;
  49. std::unordered_set<std::string> warm_file_set_;
  50. std::string metadata_file_name_;
  51. std::string name_;
  52. bool is_full_fs_warm_;
  53. };
  54. // Simulated random access file that can control IOPs and latency to simulate
  55. // specific storage media
  56. class SimulatedHybridRaf : public FSRandomAccessFileOwnerWrapper {
  57. public:
  58. SimulatedHybridRaf(std::unique_ptr<FSRandomAccessFile>&& t,
  59. std::shared_ptr<RateLimiter> rate_limiter,
  60. Temperature temperature)
  61. : FSRandomAccessFileOwnerWrapper(std::move(t)),
  62. rate_limiter_(rate_limiter),
  63. temperature_(temperature) {}
  64. ~SimulatedHybridRaf() override {}
  65. IOStatus Read(uint64_t offset, size_t n, const IOOptions& options,
  66. Slice* result, char* scratch,
  67. IODebugContext* dbg) const override;
  68. IOStatus MultiRead(FSReadRequest* reqs, size_t num_reqs,
  69. const IOOptions& options, IODebugContext* dbg) override;
  70. IOStatus Prefetch(uint64_t offset, size_t n, const IOOptions& options,
  71. IODebugContext* dbg) override;
  72. private:
  73. std::shared_ptr<RateLimiter> rate_limiter_;
  74. Temperature temperature_;
  75. void SimulateIOWait(int64_t num_requests) const;
  76. };
  77. class SimulatedWritableFile : public FSWritableFileWrapper {
  78. public:
  79. SimulatedWritableFile(std::unique_ptr<FSWritableFile>&& t,
  80. std::shared_ptr<RateLimiter> rate_limiter)
  81. : FSWritableFileWrapper(t.get()),
  82. file_guard_(std::move(t)),
  83. rate_limiter_(rate_limiter) {}
  84. IOStatus Append(const Slice& data, const IOOptions&,
  85. IODebugContext*) override;
  86. IOStatus Append(const Slice& data, const IOOptions& options,
  87. const DataVerificationInfo& verification_info,
  88. IODebugContext* dbg) override;
  89. IOStatus Sync(const IOOptions& options, IODebugContext* dbg) override;
  90. IOStatus PositionedAppend(const Slice& data, uint64_t offset,
  91. const IOOptions& options,
  92. IODebugContext* dbg) override;
  93. IOStatus PositionedAppend(const Slice& data, uint64_t offset,
  94. const IOOptions& options,
  95. const DataVerificationInfo& verification_info,
  96. IODebugContext* dbg) override;
  97. private:
  98. std::unique_ptr<FSWritableFile> file_guard_;
  99. std::shared_ptr<RateLimiter> rate_limiter_;
  100. size_t unsynced_bytes = 0;
  101. void SimulateIOWait(int64_t num_requests) const;
  102. };
  103. } // namespace ROCKSDB_NAMESPACE