Coverage Report

Created: 2025-10-26 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rocksdb/env/composite_env_wrapper.h
Line
Count
Source
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
// This class supports abstracting different types of an `Env`'s functionality
22
// into separate interfaces. It is constructed with a `FileSystem` and a
23
// `SystemClock` and delegates:
24
// * File system operations to member `file_system_`.
25
// * Time related misc operations to member `clock_`.
26
// A subclass needs to inherit `CompositeEnv` and provide implementations for
27
// the thread management related APIs.
28
class CompositeEnv : public Env {
29
 public:
30
  // Initialize a CompositeEnvWrapper that delegates all thread/time related
31
  // calls to env, and all file operations to fs
32
  explicit CompositeEnv(const std::shared_ptr<FileSystem>& fs,
33
                        const std::shared_ptr<SystemClock>& clock)
34
2
      : Env(fs, clock) {}
35
36
95.3k
  Status RegisterDbPaths(const std::vector<std::string>& paths) override {
37
95.3k
    return file_system_->RegisterDbPaths(paths);
38
95.3k
  }
39
95.3k
  Status UnregisterDbPaths(const std::vector<std::string>& paths) override {
40
95.3k
    return file_system_->UnregisterDbPaths(paths);
41
95.3k
  }
42
43
  // The following text is boilerplate that forwards all methods to target()
44
  Status NewSequentialFile(const std::string& f,
45
                           std::unique_ptr<SequentialFile>* r,
46
                           const EnvOptions& options) override;
47
48
  Status NewRandomAccessFile(const std::string& f,
49
                             std::unique_ptr<RandomAccessFile>* r,
50
                             const EnvOptions& options) override;
51
52
  Status NewWritableFile(const std::string& f, std::unique_ptr<WritableFile>* r,
53
                         const EnvOptions& options) override;
54
55
  Status ReopenWritableFile(const std::string& fname,
56
                            std::unique_ptr<WritableFile>* result,
57
                            const EnvOptions& options) override;
58
59
  Status ReuseWritableFile(const std::string& fname,
60
                           const std::string& old_fname,
61
                           std::unique_ptr<WritableFile>* r,
62
                           const EnvOptions& options) override;
63
64
  Status NewRandomRWFile(const std::string& fname,
65
                         std::unique_ptr<RandomRWFile>* result,
66
                         const EnvOptions& options) override;
67
68
  Status NewMemoryMappedFileBuffer(
69
      const std::string& fname,
70
0
      std::unique_ptr<MemoryMappedFileBuffer>* result) override {
71
0
    return file_system_->NewMemoryMappedFileBuffer(fname, result);
72
0
  }
73
74
  Status NewDirectory(const std::string& name,
75
                      std::unique_ptr<Directory>* result) override;
76
77
106k
  Status FileExists(const std::string& f) override {
78
106k
    IOOptions io_opts;
79
106k
    IODebugContext dbg;
80
106k
    return file_system_->FileExists(f, io_opts, &dbg);
81
106k
  }
82
  Status GetChildren(const std::string& dir,
83
96.8k
                     std::vector<std::string>* r) override {
84
96.8k
    IOOptions io_opts;
85
96.8k
    IODebugContext dbg;
86
96.8k
    return file_system_->GetChildren(dir, io_opts, r, &dbg);
87
96.8k
  }
88
  Status GetChildrenFileAttributes(
89
0
      const std::string& dir, std::vector<FileAttributes>* result) override {
90
0
    IOOptions io_opts;
91
0
    IODebugContext dbg;
92
0
    return file_system_->GetChildrenFileAttributes(dir, io_opts, result, &dbg);
93
0
  }
94
225k
  Status DeleteFile(const std::string& f) override {
95
225k
    IOOptions io_opts;
96
225k
    IODebugContext dbg;
97
225k
    return file_system_->DeleteFile(f, io_opts, &dbg);
98
225k
  }
99
0
  Status Truncate(const std::string& fname, size_t size) override {
100
0
    IOOptions io_opts;
101
0
    IODebugContext dbg;
102
0
    return file_system_->Truncate(fname, size, io_opts, &dbg);
103
0
  }
104
0
  Status CreateDir(const std::string& d) override {
105
0
    IOOptions io_opts;
106
0
    IODebugContext dbg;
107
0
    return file_system_->CreateDir(d, io_opts, &dbg);
108
0
  }
109
154k
  Status CreateDirIfMissing(const std::string& d) override {
110
154k
    IOOptions io_opts;
111
154k
    IODebugContext dbg;
112
154k
    return file_system_->CreateDirIfMissing(d, io_opts, &dbg);
113
154k
  }
114
9.23k
  Status DeleteDir(const std::string& d) override {
115
9.23k
    IOOptions io_opts;
116
9.23k
    IODebugContext dbg;
117
9.23k
    return file_system_->DeleteDir(d, io_opts, &dbg);
118
9.23k
  }
119
239k
  Status GetFileSize(const std::string& f, uint64_t* s) override {
120
239k
    IOOptions io_opts;
121
239k
    IODebugContext dbg;
122
239k
    return file_system_->GetFileSize(f, io_opts, s, &dbg);
123
239k
  }
124
125
  Status GetFileModificationTime(const std::string& fname,
126
0
                                 uint64_t* file_mtime) override {
127
0
    IOOptions io_opts;
128
0
    IODebugContext dbg;
129
0
    return file_system_->GetFileModificationTime(fname, io_opts, file_mtime,
130
0
                                                 &dbg);
131
0
  }
132
133
140k
  Status RenameFile(const std::string& s, const std::string& t) override {
134
140k
    IOOptions io_opts;
135
140k
    IODebugContext dbg;
136
140k
    return file_system_->RenameFile(s, t, io_opts, &dbg);
137
140k
  }
138
139
0
  Status LinkFile(const std::string& s, const std::string& t) override {
140
0
    IOOptions io_opts;
141
0
    IODebugContext dbg;
142
0
    return file_system_->LinkFile(s, t, io_opts, &dbg);
143
0
  }
144
145
0
  Status NumFileLinks(const std::string& fname, uint64_t* count) override {
146
0
    IOOptions io_opts;
147
0
    IODebugContext dbg;
148
0
    return file_system_->NumFileLinks(fname, io_opts, count, &dbg);
149
0
  }
150
151
  Status AreFilesSame(const std::string& first, const std::string& second,
152
0
                      bool* res) override {
153
0
    IOOptions io_opts;
154
0
    IODebugContext dbg;
155
0
    return file_system_->AreFilesSame(first, second, io_opts, res, &dbg);
156
0
  }
157
158
57.6k
  Status LockFile(const std::string& f, FileLock** l) override {
159
57.6k
    IOOptions io_opts;
160
57.6k
    IODebugContext dbg;
161
57.6k
    return file_system_->LockFile(f, io_opts, l, &dbg);
162
57.6k
  }
163
164
57.6k
  Status UnlockFile(FileLock* l) override {
165
57.6k
    IOOptions io_opts;
166
57.6k
    IODebugContext dbg;
167
57.6k
    return file_system_->UnlockFile(l, io_opts, &dbg);
168
57.6k
  }
169
170
  Status GetAbsolutePath(const std::string& db_path,
171
57.6k
                         std::string* output_path) override {
172
57.6k
    IOOptions io_opts;
173
57.6k
    IODebugContext dbg;
174
57.6k
    return file_system_->GetAbsolutePath(db_path, io_opts, output_path, &dbg);
175
57.6k
  }
176
177
  Status NewLogger(const std::string& fname,
178
57.6k
                   std::shared_ptr<Logger>* result) override {
179
57.6k
    IOOptions io_opts;
180
57.6k
    IODebugContext dbg;
181
57.6k
    return file_system_->NewLogger(fname, io_opts, result, &dbg);
182
57.6k
  }
183
184
0
  Status IsDirectory(const std::string& path, bool* is_dir) override {
185
0
    IOOptions io_opts;
186
0
    IODebugContext dbg;
187
0
    return file_system_->IsDirectory(path, io_opts, is_dir, &dbg);
188
0
  }
189
190
0
  Status GetTestDirectory(std::string* path) override {
191
0
    IOOptions io_opts;
192
0
    IODebugContext dbg;
193
0
    return file_system_->GetTestDirectory(io_opts, path, &dbg);
194
0
  }
195
196
0
  EnvOptions OptimizeForLogRead(const EnvOptions& env_options) const override {
197
0
    return file_system_->OptimizeForLogRead(FileOptions(env_options));
198
0
  }
199
200
  EnvOptions OptimizeForManifestRead(
201
0
      const EnvOptions& env_options) const override {
202
0
    return file_system_->OptimizeForManifestRead(FileOptions(env_options));
203
0
  }
204
205
  EnvOptions OptimizeForLogWrite(const EnvOptions& env_options,
206
0
                                 const DBOptions& db_options) const override {
207
0
    return file_system_->OptimizeForLogWrite(FileOptions(env_options),
208
0
                                             db_options);
209
0
  }
210
211
  EnvOptions OptimizeForManifestWrite(
212
0
      const EnvOptions& env_options) const override {
213
0
    return file_system_->OptimizeForManifestWrite(FileOptions(env_options));
214
0
  }
215
216
  EnvOptions OptimizeForCompactionTableWrite(
217
      const EnvOptions& env_options,
218
0
      const ImmutableDBOptions& immutable_ops) const override {
219
0
    return file_system_->OptimizeForCompactionTableWrite(
220
0
        FileOptions(env_options), immutable_ops);
221
0
  }
222
  EnvOptions OptimizeForCompactionTableRead(
223
      const EnvOptions& env_options,
224
0
      const ImmutableDBOptions& db_options) const override {
225
0
    return file_system_->OptimizeForCompactionTableRead(
226
0
        FileOptions(env_options), db_options);
227
0
  }
228
  EnvOptions OptimizeForBlobFileRead(
229
      const EnvOptions& env_options,
230
0
      const ImmutableDBOptions& db_options) const override {
231
0
    return file_system_->OptimizeForBlobFileRead(FileOptions(env_options),
232
0
                                                 db_options);
233
0
  }
234
  // This seems to clash with a macro on Windows, so #undef it here
235
#ifdef GetFreeSpace
236
#undef GetFreeSpace
237
#endif
238
0
  Status GetFreeSpace(const std::string& path, uint64_t* diskfree) override {
239
0
    IOOptions io_opts;
240
0
    IODebugContext dbg;
241
0
    return file_system_->GetFreeSpace(path, io_opts, diskfree, &dbg);
242
0
  }
243
0
  uint64_t NowMicros() override { return system_clock_->NowMicros(); }
244
4
  uint64_t NowNanos() override { return system_clock_->NowNanos(); }
245
246
0
  uint64_t NowCPUNanos() override { return system_clock_->CPUNanos(); }
247
248
0
  void SleepForMicroseconds(int micros) override {
249
0
    system_clock_->SleepForMicroseconds(micros);
250
0
  }
251
252
4
  Status GetCurrentTime(int64_t* unix_time) override {
253
4
    return system_clock_->GetCurrentTime(unix_time);
254
4
  }
255
0
  std::string TimeToString(uint64_t time) override {
256
0
    return system_clock_->TimeToString(time);
257
0
  }
258
};
259
260
// A `CompositeEnvWrapper` is constructed with a target `Env` object, an
261
// optional `FileSystem` object and an optional `SystemClock` object.
262
// `Env::GetFileSystem()` is a fallback file system if no such object is
263
// explicitly provided. Similarly, `Env::GetSystemClock()` is a fallback system
264
// clock.
265
// Besides delegating corresponding functionality to `file_system_` and `clock_`
266
// which is inherited from `CompositeEnv`, it also implements the thread
267
// management APIs by delegating them to the target `Env` object.
268
//
269
// Effectively, this class helps to support using customized file system
270
// implementations such as a remote file system instead of the default file
271
// system provided by the operating system.
272
//
273
// Also see public API `NewCompositeEnv` in rocksdb/include/env.h
274
class CompositeEnvWrapper : public CompositeEnv {
275
 public:
276
  // Initialize a CompositeEnvWrapper that delegates all thread/time related
277
  // calls to env, and all file operations to fs
278
  explicit CompositeEnvWrapper(Env* env)
279
0
      : CompositeEnvWrapper(env, env->GetFileSystem(), env->GetSystemClock()) {}
280
  explicit CompositeEnvWrapper(Env* env, const std::shared_ptr<FileSystem>& fs)
281
0
      : CompositeEnvWrapper(env, fs, env->GetSystemClock()) {}
282
283
  explicit CompositeEnvWrapper(Env* env, const std::shared_ptr<SystemClock>& sc)
284
0
      : CompositeEnvWrapper(env, env->GetFileSystem(), sc) {}
285
286
  explicit CompositeEnvWrapper(Env* env, const std::shared_ptr<FileSystem>& fs,
287
                               const std::shared_ptr<SystemClock>& sc);
288
289
  explicit CompositeEnvWrapper(const std::shared_ptr<Env>& env,
290
                               const std::shared_ptr<FileSystem>& fs)
291
0
      : CompositeEnvWrapper(env, fs, env->GetSystemClock()) {}
292
293
  explicit CompositeEnvWrapper(const std::shared_ptr<Env>& env,
294
                               const std::shared_ptr<SystemClock>& sc)
295
0
      : CompositeEnvWrapper(env, env->GetFileSystem(), sc) {}
296
297
  explicit CompositeEnvWrapper(const std::shared_ptr<Env>& env,
298
                               const std::shared_ptr<FileSystem>& fs,
299
                               const std::shared_ptr<SystemClock>& sc);
300
301
0
  static const char* kClassName() { return "CompositeEnv"; }
302
0
  const char* Name() const override { return kClassName(); }
303
0
  bool IsInstanceOf(const std::string& name) const override {
304
0
    if (name == kClassName()) {
305
0
      return true;
306
0
    } else {
307
0
      return CompositeEnv::IsInstanceOf(name);
308
0
    }
309
0
  }
310
0
  const Customizable* Inner() const override { return target_.env; }
311
312
  Status PrepareOptions(const ConfigOptions& options) override;
313
  std::string SerializeOptions(const ConfigOptions& config_options,
314
                               const std::string& header) const override;
315
316
  // Return the target to which this Env forwards all calls
317
0
  Env* env_target() const { return target_.env; }
318
319
#if !defined(OS_WIN) && !defined(ROCKSDB_NO_DYNAMIC_EXTENSION)
320
  Status LoadLibrary(const std::string& lib_name,
321
                     const std::string& search_path,
322
0
                     std::shared_ptr<DynamicLibrary>* result) override {
323
0
    return target_.env->LoadLibrary(lib_name, search_path, result);
324
0
  }
325
#endif
326
327
  void Schedule(void (*f)(void* arg), void* a, Priority pri,
328
0
                void* tag = nullptr, void (*u)(void* arg) = nullptr) override {
329
0
    return target_.env->Schedule(f, a, pri, tag, u);
330
0
  }
331
332
0
  int UnSchedule(void* tag, Priority pri) override {
333
0
    return target_.env->UnSchedule(tag, pri);
334
0
  }
335
336
0
  void StartThread(void (*f)(void*), void* a) override {
337
0
    return target_.env->StartThread(f, a);
338
0
  }
339
0
  void WaitForJoin() override { return target_.env->WaitForJoin(); }
340
0
  unsigned int GetThreadPoolQueueLen(Priority pri = LOW) const override {
341
0
    return target_.env->GetThreadPoolQueueLen(pri);
342
0
  }
343
344
0
  int ReserveThreads(int threads_to_be_reserved, Priority pri) override {
345
0
    return target_.env->ReserveThreads(threads_to_be_reserved, pri);
346
0
  }
347
348
0
  int ReleaseThreads(int threads_to_be_released, Priority pri) override {
349
0
    return target_.env->ReleaseThreads(threads_to_be_released, pri);
350
0
  }
351
352
0
  Status GetHostName(char* name, uint64_t len) override {
353
0
    return target_.env->GetHostName(name, len);
354
0
  }
355
0
  void SetBackgroundThreads(int num, Priority pri) override {
356
0
    return target_.env->SetBackgroundThreads(num, pri);
357
0
  }
358
0
  int GetBackgroundThreads(Priority pri) override {
359
0
    return target_.env->GetBackgroundThreads(pri);
360
0
  }
361
362
0
  Status SetAllowNonOwnerAccess(bool allow_non_owner_access) override {
363
0
    return target_.env->SetAllowNonOwnerAccess(allow_non_owner_access);
364
0
  }
365
366
0
  void IncBackgroundThreadsIfNeeded(int num, Priority pri) override {
367
0
    return target_.env->IncBackgroundThreadsIfNeeded(num, pri);
368
0
  }
369
370
0
  void LowerThreadPoolIOPriority(Priority pool) override {
371
0
    target_.env->LowerThreadPoolIOPriority(pool);
372
0
  }
373
374
0
  void LowerThreadPoolCPUPriority(Priority pool) override {
375
0
    target_.env->LowerThreadPoolCPUPriority(pool);
376
0
  }
377
378
0
  Status LowerThreadPoolCPUPriority(Priority pool, CpuPriority pri) override {
379
0
    return target_.env->LowerThreadPoolCPUPriority(pool, pri);
380
0
  }
381
382
0
  Status GetThreadList(std::vector<ThreadStatus>* thread_list) override {
383
0
    return target_.env->GetThreadList(thread_list);
384
0
  }
385
386
0
  ThreadStatusUpdater* GetThreadStatusUpdater() const override {
387
0
    return target_.env->GetThreadStatusUpdater();
388
0
  }
389
390
0
  uint64_t GetThreadID() const override { return target_.env->GetThreadID(); }
391
392
0
  std::string GenerateUniqueId() override {
393
0
    return target_.env->GenerateUniqueId();
394
0
  }
395
396
 private:
397
  EnvWrapper::Target target_;
398
};
399
}  // namespace ROCKSDB_NAMESPACE