1 // Copyright (c) 2019-present, Facebook, Inc.  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 #include "rocksdb/env.h"
9 #include "rocksdb/file_system.h"
10 #include "rocksdb/system_clock.h"
11 
12 #ifdef _WIN32
13 // Windows API macro interference
14 #undef DeleteFile
15 #undef GetCurrentTime
16 #undef LoadLibrary
17 #endif
18 
19 namespace ROCKSDB_NAMESPACE {
20 
21 class CompositeEnv : public Env {
22  public:
23   // Initialize a CompositeEnvWrapper that delegates all thread/time related
24   // calls to env, and all file operations to fs
CompositeEnv(const std::shared_ptr<FileSystem> & fs,const std::shared_ptr<SystemClock> & clock)25   explicit CompositeEnv(const std::shared_ptr<FileSystem>& fs,
26                         const std::shared_ptr<SystemClock>& clock)
27       : Env(fs, clock) {}
28 
RegisterDbPaths(const std::vector<std::string> & paths)29   Status RegisterDbPaths(const std::vector<std::string>& paths) override {
30     return file_system_->RegisterDbPaths(paths);
31   }
UnregisterDbPaths(const std::vector<std::string> & paths)32   Status UnregisterDbPaths(const std::vector<std::string>& paths) override {
33     return file_system_->UnregisterDbPaths(paths);
34   }
35 
36   // The following text is boilerplate that forwards all methods to target()
37   Status NewSequentialFile(const std::string& f,
38                            std::unique_ptr<SequentialFile>* r,
39                            const EnvOptions& options) override;
40 
41   Status NewRandomAccessFile(const std::string& f,
42                              std::unique_ptr<RandomAccessFile>* r,
43                              const EnvOptions& options) override;
44 
45   Status NewWritableFile(const std::string& f, std::unique_ptr<WritableFile>* r,
46                          const EnvOptions& options) override;
47 
48   Status ReopenWritableFile(const std::string& fname,
49                             std::unique_ptr<WritableFile>* result,
50                             const EnvOptions& options) override;
51 
52   Status ReuseWritableFile(const std::string& fname,
53                            const std::string& old_fname,
54                            std::unique_ptr<WritableFile>* r,
55                            const EnvOptions& options) override;
56 
57   Status NewRandomRWFile(const std::string& fname,
58                          std::unique_ptr<RandomRWFile>* result,
59                          const EnvOptions& options) override;
60 
NewMemoryMappedFileBuffer(const std::string & fname,std::unique_ptr<MemoryMappedFileBuffer> * result)61   Status NewMemoryMappedFileBuffer(
62       const std::string& fname,
63       std::unique_ptr<MemoryMappedFileBuffer>* result) override {
64     return file_system_->NewMemoryMappedFileBuffer(fname, result);
65   }
66 
67   Status NewDirectory(const std::string& name,
68                       std::unique_ptr<Directory>* result) override;
69 
FileExists(const std::string & f)70   Status FileExists(const std::string& f) override {
71     IOOptions io_opts;
72     IODebugContext dbg;
73     return file_system_->FileExists(f, io_opts, &dbg);
74   }
GetChildren(const std::string & dir,std::vector<std::string> * r)75   Status GetChildren(const std::string& dir,
76                      std::vector<std::string>* r) override {
77     IOOptions io_opts;
78     IODebugContext dbg;
79     return file_system_->GetChildren(dir, io_opts, r, &dbg);
80   }
GetChildrenFileAttributes(const std::string & dir,std::vector<FileAttributes> * result)81   Status GetChildrenFileAttributes(
82       const std::string& dir, std::vector<FileAttributes>* result) override {
83     IOOptions io_opts;
84     IODebugContext dbg;
85     return file_system_->GetChildrenFileAttributes(dir, io_opts, result, &dbg);
86   }
DeleteFile(const std::string & f)87   Status DeleteFile(const std::string& f) override {
88     IOOptions io_opts;
89     IODebugContext dbg;
90     return file_system_->DeleteFile(f, io_opts, &dbg);
91   }
Truncate(const std::string & fname,size_t size)92   Status Truncate(const std::string& fname, size_t size) override {
93     IOOptions io_opts;
94     IODebugContext dbg;
95     return file_system_->Truncate(fname, size, io_opts, &dbg);
96   }
CreateDir(const std::string & d)97   Status CreateDir(const std::string& d) override {
98     IOOptions io_opts;
99     IODebugContext dbg;
100     return file_system_->CreateDir(d, io_opts, &dbg);
101   }
CreateDirIfMissing(const std::string & d)102   Status CreateDirIfMissing(const std::string& d) override {
103     IOOptions io_opts;
104     IODebugContext dbg;
105     return file_system_->CreateDirIfMissing(d, io_opts, &dbg);
106   }
DeleteDir(const std::string & d)107   Status DeleteDir(const std::string& d) override {
108     IOOptions io_opts;
109     IODebugContext dbg;
110     return file_system_->DeleteDir(d, io_opts, &dbg);
111   }
GetFileSize(const std::string & f,uint64_t * s)112   Status GetFileSize(const std::string& f, uint64_t* s) override {
113     IOOptions io_opts;
114     IODebugContext dbg;
115     return file_system_->GetFileSize(f, io_opts, s, &dbg);
116   }
117 
GetFileModificationTime(const std::string & fname,uint64_t * file_mtime)118   Status GetFileModificationTime(const std::string& fname,
119                                  uint64_t* file_mtime) override {
120     IOOptions io_opts;
121     IODebugContext dbg;
122     return file_system_->GetFileModificationTime(fname, io_opts, file_mtime,
123                                                  &dbg);
124   }
125 
RenameFile(const std::string & s,const std::string & t)126   Status RenameFile(const std::string& s, const std::string& t) override {
127     IOOptions io_opts;
128     IODebugContext dbg;
129     return file_system_->RenameFile(s, t, io_opts, &dbg);
130   }
131 
LinkFile(const std::string & s,const std::string & t)132   Status LinkFile(const std::string& s, const std::string& t) override {
133     IOOptions io_opts;
134     IODebugContext dbg;
135     return file_system_->LinkFile(s, t, io_opts, &dbg);
136   }
137 
NumFileLinks(const std::string & fname,uint64_t * count)138   Status NumFileLinks(const std::string& fname, uint64_t* count) override {
139     IOOptions io_opts;
140     IODebugContext dbg;
141     return file_system_->NumFileLinks(fname, io_opts, count, &dbg);
142   }
143 
AreFilesSame(const std::string & first,const std::string & second,bool * res)144   Status AreFilesSame(const std::string& first, const std::string& second,
145                       bool* res) override {
146     IOOptions io_opts;
147     IODebugContext dbg;
148     return file_system_->AreFilesSame(first, second, io_opts, res, &dbg);
149   }
150 
LockFile(const std::string & f,FileLock ** l)151   Status LockFile(const std::string& f, FileLock** l) override {
152     IOOptions io_opts;
153     IODebugContext dbg;
154     return file_system_->LockFile(f, io_opts, l, &dbg);
155   }
156 
UnlockFile(FileLock * l)157   Status UnlockFile(FileLock* l) override {
158     IOOptions io_opts;
159     IODebugContext dbg;
160     return file_system_->UnlockFile(l, io_opts, &dbg);
161   }
162 
GetAbsolutePath(const std::string & db_path,std::string * output_path)163   Status GetAbsolutePath(const std::string& db_path,
164                          std::string* output_path) override {
165     IOOptions io_opts;
166     IODebugContext dbg;
167     return file_system_->GetAbsolutePath(db_path, io_opts, output_path, &dbg);
168   }
169 
NewLogger(const std::string & fname,std::shared_ptr<Logger> * result)170   Status NewLogger(const std::string& fname,
171                    std::shared_ptr<Logger>* result) override {
172     IOOptions io_opts;
173     IODebugContext dbg;
174     return file_system_->NewLogger(fname, io_opts, result, &dbg);
175   }
176 
IsDirectory(const std::string & path,bool * is_dir)177   Status IsDirectory(const std::string& path, bool* is_dir) override {
178     IOOptions io_opts;
179     IODebugContext dbg;
180     return file_system_->IsDirectory(path, io_opts, is_dir, &dbg);
181   }
182 
GetTestDirectory(std::string * path)183   Status GetTestDirectory(std::string* path) override {
184     IOOptions io_opts;
185     IODebugContext dbg;
186     return file_system_->GetTestDirectory(io_opts, path, &dbg);
187   }
188 
OptimizeForLogRead(const EnvOptions & env_options)189   EnvOptions OptimizeForLogRead(const EnvOptions& env_options) const override {
190     return file_system_->OptimizeForLogRead(FileOptions(env_options));
191   }
192 
OptimizeForManifestRead(const EnvOptions & env_options)193   EnvOptions OptimizeForManifestRead(
194       const EnvOptions& env_options) const override {
195     return file_system_->OptimizeForManifestRead(FileOptions(env_options));
196   }
197 
OptimizeForLogWrite(const EnvOptions & env_options,const DBOptions & db_options)198   EnvOptions OptimizeForLogWrite(const EnvOptions& env_options,
199                                  const DBOptions& db_options) const override {
200     return file_system_->OptimizeForLogWrite(FileOptions(env_options),
201                                              db_options);
202   }
203 
OptimizeForManifestWrite(const EnvOptions & env_options)204   EnvOptions OptimizeForManifestWrite(
205       const EnvOptions& env_options) const override {
206     return file_system_->OptimizeForManifestWrite(FileOptions(env_options));
207   }
208 
OptimizeForCompactionTableWrite(const EnvOptions & env_options,const ImmutableDBOptions & immutable_ops)209   EnvOptions OptimizeForCompactionTableWrite(
210       const EnvOptions& env_options,
211       const ImmutableDBOptions& immutable_ops) const override {
212     return file_system_->OptimizeForCompactionTableWrite(
213         FileOptions(env_options), immutable_ops);
214   }
OptimizeForCompactionTableRead(const EnvOptions & env_options,const ImmutableDBOptions & db_options)215   EnvOptions OptimizeForCompactionTableRead(
216       const EnvOptions& env_options,
217       const ImmutableDBOptions& db_options) const override {
218     return file_system_->OptimizeForCompactionTableRead(
219         FileOptions(env_options), db_options);
220   }
OptimizeForBlobFileRead(const EnvOptions & env_options,const ImmutableDBOptions & db_options)221   EnvOptions OptimizeForBlobFileRead(
222       const EnvOptions& env_options,
223       const ImmutableDBOptions& db_options) const override {
224     return file_system_->OptimizeForBlobFileRead(FileOptions(env_options),
225                                                  db_options);
226   }
227   // This seems to clash with a macro on Windows, so #undef it here
228 #ifdef GetFreeSpace
229 #undef GetFreeSpace
230 #endif
GetFreeSpace(const std::string & path,uint64_t * diskfree)231   Status GetFreeSpace(const std::string& path, uint64_t* diskfree) override {
232     IOOptions io_opts;
233     IODebugContext dbg;
234     return file_system_->GetFreeSpace(path, io_opts, diskfree, &dbg);
235   }
NowMicros()236   uint64_t NowMicros() override { return system_clock_->NowMicros(); }
NowNanos()237   uint64_t NowNanos() override { return system_clock_->NowNanos(); }
238 
NowCPUNanos()239   uint64_t NowCPUNanos() override { return system_clock_->CPUNanos(); }
240 
SleepForMicroseconds(int micros)241   void SleepForMicroseconds(int micros) override {
242     system_clock_->SleepForMicroseconds(micros);
243   }
244 
GetCurrentTime(int64_t * unix_time)245   Status GetCurrentTime(int64_t* unix_time) override {
246     return system_clock_->GetCurrentTime(unix_time);
247   }
TimeToString(uint64_t time)248   std::string TimeToString(uint64_t time) override {
249     return system_clock_->TimeToString(time);
250   }
251 };
252 
253 class CompositeEnvWrapper : public CompositeEnv {
254  public:
255   // Initialize a CompositeEnvWrapper that delegates all thread/time related
256   // calls to env, and all file operations to fs
CompositeEnvWrapper(Env * env,const std::shared_ptr<FileSystem> & fs)257   explicit CompositeEnvWrapper(Env* env, const std::shared_ptr<FileSystem>& fs)
258       : CompositeEnvWrapper(env, fs, env->GetSystemClock()) {}
259 
CompositeEnvWrapper(Env * env,const std::shared_ptr<SystemClock> & sc)260   explicit CompositeEnvWrapper(Env* env, const std::shared_ptr<SystemClock>& sc)
261       : CompositeEnvWrapper(env, env->GetFileSystem(), sc) {}
262 
CompositeEnvWrapper(Env * env,const std::shared_ptr<FileSystem> & fs,const std::shared_ptr<SystemClock> & sc)263   explicit CompositeEnvWrapper(Env* env, const std::shared_ptr<FileSystem>& fs,
264                                const std::shared_ptr<SystemClock>& sc)
265       : CompositeEnv(fs, sc), env_target_(env) {}
266 
267   // Return the target to which this Env forwards all calls
env_target()268   Env* env_target() const { return env_target_; }
269 
270 #if !defined(OS_WIN) && !defined(ROCKSDB_NO_DYNAMIC_EXTENSION)
LoadLibrary(const std::string & lib_name,const std::string & search_path,std::shared_ptr<DynamicLibrary> * result)271   Status LoadLibrary(const std::string& lib_name,
272                      const std::string& search_path,
273                      std::shared_ptr<DynamicLibrary>* result) override {
274     return env_target_->LoadLibrary(lib_name, search_path, result);
275   }
276 #endif
277 
278   void Schedule(void (*f)(void* arg), void* a, Priority pri,
279                 void* tag = nullptr, void (*u)(void* arg) = nullptr) override {
280     return env_target_->Schedule(f, a, pri, tag, u);
281   }
282 
UnSchedule(void * tag,Priority pri)283   int UnSchedule(void* tag, Priority pri) override {
284     return env_target_->UnSchedule(tag, pri);
285   }
286 
StartThread(void (* f)(void *),void * a)287   void StartThread(void (*f)(void*), void* a) override {
288     return env_target_->StartThread(f, a);
289   }
WaitForJoin()290   void WaitForJoin() override { return env_target_->WaitForJoin(); }
291   unsigned int GetThreadPoolQueueLen(Priority pri = LOW) const override {
292     return env_target_->GetThreadPoolQueueLen(pri);
293   }
294 
GetHostName(char * name,uint64_t len)295   Status GetHostName(char* name, uint64_t len) override {
296     return env_target_->GetHostName(name, len);
297   }
SetBackgroundThreads(int num,Priority pri)298   void SetBackgroundThreads(int num, Priority pri) override {
299     return env_target_->SetBackgroundThreads(num, pri);
300   }
GetBackgroundThreads(Priority pri)301   int GetBackgroundThreads(Priority pri) override {
302     return env_target_->GetBackgroundThreads(pri);
303   }
304 
SetAllowNonOwnerAccess(bool allow_non_owner_access)305   Status SetAllowNonOwnerAccess(bool allow_non_owner_access) override {
306     return env_target_->SetAllowNonOwnerAccess(allow_non_owner_access);
307   }
308 
IncBackgroundThreadsIfNeeded(int num,Priority pri)309   void IncBackgroundThreadsIfNeeded(int num, Priority pri) override {
310     return env_target_->IncBackgroundThreadsIfNeeded(num, pri);
311   }
312 
LowerThreadPoolIOPriority(Priority pool)313   void LowerThreadPoolIOPriority(Priority pool) override {
314     env_target_->LowerThreadPoolIOPriority(pool);
315   }
316 
LowerThreadPoolCPUPriority(Priority pool)317   void LowerThreadPoolCPUPriority(Priority pool) override {
318     env_target_->LowerThreadPoolCPUPriority(pool);
319   }
320 
LowerThreadPoolCPUPriority(Priority pool,CpuPriority pri)321   Status LowerThreadPoolCPUPriority(Priority pool, CpuPriority pri) override {
322     return env_target_->LowerThreadPoolCPUPriority(pool, pri);
323   }
324 
GetThreadList(std::vector<ThreadStatus> * thread_list)325   Status GetThreadList(std::vector<ThreadStatus>* thread_list) override {
326     return env_target_->GetThreadList(thread_list);
327   }
328 
GetThreadStatusUpdater()329   ThreadStatusUpdater* GetThreadStatusUpdater() const override {
330     return env_target_->GetThreadStatusUpdater();
331   }
332 
GetThreadID()333   uint64_t GetThreadID() const override { return env_target_->GetThreadID(); }
334 
GenerateUniqueId()335   std::string GenerateUniqueId() override {
336     return env_target_->GenerateUniqueId();
337   }
338 
339  private:
340   Env* env_target_;
341 };
342 }  // namespace ROCKSDB_NAMESPACE
343