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 
6 #pragma once
7 
8 #ifndef ROCKSDB_LITE
9 
10 #include <utility>
11 
12 #include "rocksdb/file_system.h"
13 
14 namespace ROCKSDB_NAMESPACE {
15 
16 // A FileSystem simulates hybrid file system by ingesting latency and limit
17 // IOPs.
18 // This class is only used for development purpose and should not be used
19 // in production.
20 // Right now we ingest 15ms latency and allow 100 requests per second when
21 // the file is for warm temperature.
22 // When the object is destroyed, the list of warm files are written to a
23 // file, which can be used to reopen a FileSystem and still recover the
24 // list. This is to allow the information to preserve between db_bench
25 // runs.
26 class SimulatedHybridFileSystem : public FileSystemWrapper {
27  public:
28   // metadata_file_name stores metadata of the files, so that it can be
29   // loaded after process restarts. If the file doesn't exist, create
30   // one. The file is written when the class is destroyed.
31   explicit SimulatedHybridFileSystem(const std::shared_ptr<FileSystem>& base,
32                                      const std::string& metadata_file_name);
33 
34   ~SimulatedHybridFileSystem() override;
35 
36  public:
37   IOStatus NewRandomAccessFile(const std::string& fname,
38                                const FileOptions& file_opts,
39                                std::unique_ptr<FSRandomAccessFile>* result,
40                                IODebugContext* dbg) override;
41   IOStatus NewWritableFile(const std::string& fname,
42                            const FileOptions& file_opts,
43                            std::unique_ptr<FSWritableFile>* result,
44                            IODebugContext* dbg) override;
45   IOStatus DeleteFile(const std::string& fname, const IOOptions& options,
46                       IODebugContext* dbg) override;
47 
Name()48   const char* Name() const override { return name_.c_str(); }
49 
50  private:
51   // Limit 100 requests per second. Rate limiter is designed to byte but
52   // we use it as fixed bytes is one request.
53   std::shared_ptr<RateLimiter> rate_limiter_;
54   std::mutex mutex_;
55   std::unordered_set<std::string> warm_file_set_;
56   std::string metadata_file_name_;
57   std::string name_;
58 };
59 
60 // Simulated random access file that can control IOPs and latency to simulate
61 // specific storage media
62 class SimulatedHybridRaf : public FSRandomAccessFileOwnerWrapper {
63  public:
SimulatedHybridRaf(std::unique_ptr<FSRandomAccessFile> && t,std::shared_ptr<RateLimiter> rate_limiter,Temperature temperature)64   SimulatedHybridRaf(std::unique_ptr<FSRandomAccessFile>&& t,
65                      std::shared_ptr<RateLimiter> rate_limiter,
66                      Temperature temperature)
67       : FSRandomAccessFileOwnerWrapper(std::move(t)),
68         rate_limiter_(rate_limiter),
69         temperature_(temperature) {}
70 
~SimulatedHybridRaf()71   ~SimulatedHybridRaf() override {}
72 
73   IOStatus Read(uint64_t offset, size_t n, const IOOptions& options,
74                 Slice* result, char* scratch,
75                 IODebugContext* dbg) const override;
76 
77   IOStatus MultiRead(FSReadRequest* reqs, size_t num_reqs,
78                      const IOOptions& options, IODebugContext* dbg) override;
79 
80   IOStatus Prefetch(uint64_t offset, size_t n, const IOOptions& options,
81                     IODebugContext* dbg) override;
82 
83  private:
84   std::shared_ptr<RateLimiter> rate_limiter_;
85   Temperature temperature_;
86 
87   void RequestRateLimit(int64_t num_requests) const;
88 };
89 }  // namespace ROCKSDB_NAMESPACE
90 
91 #endif  // ROCKSDB_LITE
92