1 // Copyright (c) 2011-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 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
6 // Use of this source code is governed by a BSD-style license that can be
7 // found in the LICENSE file. See the AUTHORS file for names of contributors.
8 //
9 // An Env is an interface used by the rocksdb implementation to access
10 // operating system functionality like the filesystem etc.  Callers
11 // may wish to provide a custom Env object when opening a database to
12 // get fine gain control; e.g., to rate limit file system operations.
13 //
14 // All Env implementations are safe for concurrent access from
15 // multiple threads without any external synchronization.
16 
17 #pragma once
18 
19 #include <stdint.h>
20 #include <cstdarg>
21 #include <functional>
22 #include <limits>
23 #include <memory>
24 #include <string>
25 #include <vector>
26 #include "rocksdb/status.h"
27 #include "rocksdb/thread_status.h"
28 
29 #ifdef _WIN32
30 // Windows API macro interference
31 #undef DeleteFile
32 #undef GetCurrentTime
33 #endif
34 
35 #if defined(__GNUC__) || defined(__clang__)
36 #define ROCKSDB_PRINTF_FORMAT_ATTR(format_param, dots_param) \
37     __attribute__((__format__(__printf__, format_param, dots_param)))
38 #else
39 #define ROCKSDB_PRINTF_FORMAT_ATTR(format_param, dots_param)
40 #endif
41 
42 namespace ROCKSDB_NAMESPACE {
43 
44 class DynamicLibrary;
45 class FileLock;
46 class Logger;
47 class RandomAccessFile;
48 class SequentialFile;
49 class Slice;
50 class WritableFile;
51 class RandomRWFile;
52 class MemoryMappedFileBuffer;
53 class Directory;
54 struct DBOptions;
55 struct ImmutableDBOptions;
56 struct MutableDBOptions;
57 class RateLimiter;
58 class ThreadStatusUpdater;
59 struct ThreadStatus;
60 class FileSystem;
61 
62 const size_t kDefaultPageSize = 4 * 1024;
63 
64 // Options while opening a file to read/write
65 struct EnvOptions {
66   // Construct with default Options
67   EnvOptions();
68 
69   // Construct from Options
70   explicit EnvOptions(const DBOptions& options);
71 
72   // If true, then use mmap to read data
73   bool use_mmap_reads = false;
74 
75   // If true, then use mmap to write data
76   bool use_mmap_writes = true;
77 
78   // If true, then use O_DIRECT for reading data
79   bool use_direct_reads = false;
80 
81   // If true, then use O_DIRECT for writing data
82   bool use_direct_writes = false;
83 
84   // If false, fallocate() calls are bypassed
85   bool allow_fallocate = true;
86 
87   // If true, set the FD_CLOEXEC on open fd.
88   bool set_fd_cloexec = true;
89 
90   // Allows OS to incrementally sync files to disk while they are being
91   // written, in the background. Issue one request for every bytes_per_sync
92   // written. 0 turns it off.
93   // Default: 0
94   uint64_t bytes_per_sync = 0;
95 
96   // When true, guarantees the file has at most `bytes_per_sync` bytes submitted
97   // for writeback at any given time.
98   //
99   //  - If `sync_file_range` is supported it achieves this by waiting for any
100   //    prior `sync_file_range`s to finish before proceeding. In this way,
101   //    processing (compression, etc.) can proceed uninhibited in the gap
102   //    between `sync_file_range`s, and we block only when I/O falls behind.
103   //  - Otherwise the `WritableFile::Sync` method is used. Note this mechanism
104   //    always blocks, thus preventing the interleaving of I/O and processing.
105   //
106   // Note: Enabling this option does not provide any additional persistence
107   // guarantees, as it may use `sync_file_range`, which does not write out
108   // metadata.
109   //
110   // Default: false
111   bool strict_bytes_per_sync = false;
112 
113   // If true, we will preallocate the file with FALLOC_FL_KEEP_SIZE flag, which
114   // means that file size won't change as part of preallocation.
115   // If false, preallocation will also change the file size. This option will
116   // improve the performance in workloads where you sync the data on every
117   // write. By default, we set it to true for MANIFEST writes and false for
118   // WAL writes
119   bool fallocate_with_keep_size = true;
120 
121   // See DBOptions doc
122   size_t compaction_readahead_size = 0;
123 
124   // See DBOptions doc
125   size_t random_access_max_buffer_size = 0;
126 
127   // See DBOptions doc
128   size_t writable_file_max_buffer_size = 1024 * 1024;
129 
130   // If not nullptr, write rate limiting is enabled for flush and compaction
131   RateLimiter* rate_limiter = nullptr;
132 };
133 
134 class Env {
135  public:
136   struct FileAttributes {
137     // File name
138     std::string name;
139 
140     // Size of file in bytes
141     uint64_t size_bytes;
142   };
143 
144   Env();
145   // Construct an Env with a separate FileSystem implementation
146   Env(std::shared_ptr<FileSystem> fs);
147   // No copying allowed
148   Env(const Env&) = delete;
149   void operator=(const Env&) = delete;
150 
151   virtual ~Env();
152 
Type()153   static const char* Type() { return "Environment"; }
154 
155   // Loads the environment specified by the input value into the result
156   static Status LoadEnv(const std::string& value, Env** result);
157 
158   // Loads the environment specified by the input value into the result
159   static Status LoadEnv(const std::string& value, Env** result,
160                         std::shared_ptr<Env>* guard);
161 
162   // Return a default environment suitable for the current operating
163   // system.  Sophisticated users may wish to provide their own Env
164   // implementation instead of relying on this default environment.
165   //
166   // The result of Default() belongs to rocksdb and must never be deleted.
167   static Env* Default();
168 
169   // See FileSystem::RegisterDbPaths.
RegisterDbPaths(const std::vector<std::string> &)170   virtual Status RegisterDbPaths(const std::vector<std::string>& /*paths*/) {
171     return Status::OK();
172   }
173   // See FileSystem::UnregisterDbPaths.
UnregisterDbPaths(const std::vector<std::string> &)174   virtual Status UnregisterDbPaths(const std::vector<std::string>& /*paths*/) {
175     return Status::OK();
176   }
177 
178   // Create a brand new sequentially-readable file with the specified name.
179   // On success, stores a pointer to the new file in *result and returns OK.
180   // On failure stores nullptr in *result and returns non-OK.  If the file does
181   // not exist, returns a non-OK status.
182   //
183   // The returned file will only be accessed by one thread at a time.
184   virtual Status NewSequentialFile(const std::string& fname,
185                                    std::unique_ptr<SequentialFile>* result,
186                                    const EnvOptions& options) = 0;
187 
188   // Create a brand new random access read-only file with the
189   // specified name.  On success, stores a pointer to the new file in
190   // *result and returns OK.  On failure stores nullptr in *result and
191   // returns non-OK.  If the file does not exist, returns a non-OK
192   // status.
193   //
194   // The returned file may be concurrently accessed by multiple threads.
195   virtual Status NewRandomAccessFile(const std::string& fname,
196                                      std::unique_ptr<RandomAccessFile>* result,
197                                      const EnvOptions& options) = 0;
198   // These values match Linux definition
199   // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/fcntl.h#n56
200   enum WriteLifeTimeHint {
201     WLTH_NOT_SET = 0,  // No hint information set
202     WLTH_NONE,         // No hints about write life time
203     WLTH_SHORT,        // Data written has a short life time
204     WLTH_MEDIUM,       // Data written has a medium life time
205     WLTH_LONG,         // Data written has a long life time
206     WLTH_EXTREME,      // Data written has an extremely long life time
207   };
208 
209   // Create an object that writes to a new file with the specified
210   // name.  Deletes any existing file with the same name and creates a
211   // new file.  On success, stores a pointer to the new file in
212   // *result and returns OK.  On failure stores nullptr in *result and
213   // returns non-OK.
214   //
215   // The returned file will only be accessed by one thread at a time.
216   virtual Status NewWritableFile(const std::string& fname,
217                                  std::unique_ptr<WritableFile>* result,
218                                  const EnvOptions& options) = 0;
219 
220   // Create an object that writes to a new file with the specified
221   // name.  Deletes any existing file with the same name and creates a
222   // new file.  On success, stores a pointer to the new file in
223   // *result and returns OK.  On failure stores nullptr in *result and
224   // returns non-OK.
225   //
226   // The returned file will only be accessed by one thread at a time.
ReopenWritableFile(const std::string &,std::unique_ptr<WritableFile> *,const EnvOptions &)227   virtual Status ReopenWritableFile(const std::string& /*fname*/,
228                                     std::unique_ptr<WritableFile>* /*result*/,
229                                     const EnvOptions& /*options*/) {
230     return Status::NotSupported();
231   }
232 
233   // Reuse an existing file by renaming it and opening it as writable.
234   virtual Status ReuseWritableFile(const std::string& fname,
235                                    const std::string& old_fname,
236                                    std::unique_ptr<WritableFile>* result,
237                                    const EnvOptions& options);
238 
239   // Open `fname` for random read and write, if file doesn't exist the file
240   // will be created.  On success, stores a pointer to the new file in
241   // *result and returns OK.  On failure returns non-OK.
242   //
243   // The returned file will only be accessed by one thread at a time.
NewRandomRWFile(const std::string &,std::unique_ptr<RandomRWFile> *,const EnvOptions &)244   virtual Status NewRandomRWFile(const std::string& /*fname*/,
245                                  std::unique_ptr<RandomRWFile>* /*result*/,
246                                  const EnvOptions& /*options*/) {
247     return Status::NotSupported("RandomRWFile is not implemented in this Env");
248   }
249 
250   // Opens `fname` as a memory-mapped file for read and write (in-place updates
251   // only, i.e., no appends). On success, stores a raw buffer covering the whole
252   // file in `*result`. The file must exist prior to this call.
NewMemoryMappedFileBuffer(const std::string &,std::unique_ptr<MemoryMappedFileBuffer> *)253   virtual Status NewMemoryMappedFileBuffer(
254       const std::string& /*fname*/,
255       std::unique_ptr<MemoryMappedFileBuffer>* /*result*/) {
256     return Status::NotSupported(
257         "MemoryMappedFileBuffer is not implemented in this Env");
258   }
259 
260   // Create an object that represents a directory. Will fail if directory
261   // doesn't exist. If the directory exists, it will open the directory
262   // and create a new Directory object.
263   //
264   // On success, stores a pointer to the new Directory in
265   // *result and returns OK. On failure stores nullptr in *result and
266   // returns non-OK.
267   virtual Status NewDirectory(const std::string& name,
268                               std::unique_ptr<Directory>* result) = 0;
269 
270   // Returns OK if the named file exists.
271   //         NotFound if the named file does not exist,
272   //                  the calling process does not have permission to determine
273   //                  whether this file exists, or if the path is invalid.
274   //         IOError if an IO Error was encountered
275   virtual Status FileExists(const std::string& fname) = 0;
276 
277   // Store in *result the names of the children of the specified directory.
278   // The names are relative to "dir".
279   // Original contents of *results are dropped.
280   // Returns OK if "dir" exists and "*result" contains its children.
281   //         NotFound if "dir" does not exist, the calling process does not have
282   //                  permission to access "dir", or if "dir" is invalid.
283   //         IOError if an IO Error was encountered
284   virtual Status GetChildren(const std::string& dir,
285                              std::vector<std::string>* result) = 0;
286 
287   // Store in *result the attributes of the children of the specified directory.
288   // In case the implementation lists the directory prior to iterating the files
289   // and files are concurrently deleted, the deleted files will be omitted from
290   // result.
291   // The name attributes are relative to "dir".
292   // Original contents of *results are dropped.
293   // Returns OK if "dir" exists and "*result" contains its children.
294   //         NotFound if "dir" does not exist, the calling process does not have
295   //                  permission to access "dir", or if "dir" is invalid.
296   //         IOError if an IO Error was encountered
297   virtual Status GetChildrenFileAttributes(const std::string& dir,
298                                            std::vector<FileAttributes>* result);
299 
300   // Delete the named file.
301   virtual Status DeleteFile(const std::string& fname) = 0;
302 
303   // Truncate the named file to the specified size.
Truncate(const std::string &,size_t)304   virtual Status Truncate(const std::string& /*fname*/, size_t /*size*/) {
305     return Status::NotSupported("Truncate is not supported for this Env");
306   }
307 
308   // Create the specified directory. Returns error if directory exists.
309   virtual Status CreateDir(const std::string& dirname) = 0;
310 
311   // Creates directory if missing. Return Ok if it exists, or successful in
312   // Creating.
313   virtual Status CreateDirIfMissing(const std::string& dirname) = 0;
314 
315   // Delete the specified directory.
316   virtual Status DeleteDir(const std::string& dirname) = 0;
317 
318   // Store the size of fname in *file_size.
319   virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) = 0;
320 
321   // Store the last modification time of fname in *file_mtime.
322   virtual Status GetFileModificationTime(const std::string& fname,
323                                          uint64_t* file_mtime) = 0;
324   // Rename file src to target.
325   virtual Status RenameFile(const std::string& src,
326                             const std::string& target) = 0;
327 
328   // Hard Link file src to target.
LinkFile(const std::string &,const std::string &)329   virtual Status LinkFile(const std::string& /*src*/,
330                           const std::string& /*target*/) {
331     return Status::NotSupported("LinkFile is not supported for this Env");
332   }
333 
NumFileLinks(const std::string &,uint64_t *)334   virtual Status NumFileLinks(const std::string& /*fname*/,
335                               uint64_t* /*count*/) {
336     return Status::NotSupported(
337         "Getting number of file links is not supported for this Env");
338   }
339 
AreFilesSame(const std::string &,const std::string &,bool *)340   virtual Status AreFilesSame(const std::string& /*first*/,
341                               const std::string& /*second*/, bool* /*res*/) {
342     return Status::NotSupported("AreFilesSame is not supported for this Env");
343   }
344 
345   // Lock the specified file.  Used to prevent concurrent access to
346   // the same db by multiple processes.  On failure, stores nullptr in
347   // *lock and returns non-OK.
348   //
349   // On success, stores a pointer to the object that represents the
350   // acquired lock in *lock and returns OK.  The caller should call
351   // UnlockFile(*lock) to release the lock.  If the process exits,
352   // the lock will be automatically released.
353   //
354   // If somebody else already holds the lock, finishes immediately
355   // with a failure.  I.e., this call does not wait for existing locks
356   // to go away.
357   //
358   // May create the named file if it does not already exist.
359   virtual Status LockFile(const std::string& fname, FileLock** lock) = 0;
360 
361   // Release the lock acquired by a previous successful call to LockFile.
362   // REQUIRES: lock was returned by a successful LockFile() call
363   // REQUIRES: lock has not already been unlocked.
364   virtual Status UnlockFile(FileLock* lock) = 0;
365 
366   // Opens `lib_name` as a dynamic library.
367   // If the 'search_path' is specified, breaks the path into its components
368   // based on the appropriate platform separator (";" or ";") and looks for the
369   // library in those directories.  If 'search path is not specified, uses the
370   // default library path search mechanism (such as LD_LIBRARY_PATH). On
371   // success, stores a dynamic library in `*result`.
LoadLibrary(const std::string &,const std::string &,std::shared_ptr<DynamicLibrary> *)372   virtual Status LoadLibrary(const std::string& /*lib_name*/,
373                              const std::string& /*search_path */,
374                              std::shared_ptr<DynamicLibrary>* /*result*/) {
375     return Status::NotSupported("LoadLibrary is not implemented in this Env");
376   }
377 
378   // Priority for scheduling job in thread pool
379   enum Priority { BOTTOM, LOW, HIGH, USER, TOTAL };
380 
381   static std::string PriorityToString(Priority priority);
382 
383   // Priority for requesting bytes in rate limiter scheduler
384   enum IOPriority { IO_LOW = 0, IO_HIGH = 1, IO_TOTAL = 2 };
385 
386   // Arrange to run "(*function)(arg)" once in a background thread, in
387   // the thread pool specified by pri. By default, jobs go to the 'LOW'
388   // priority thread pool.
389 
390   // "function" may run in an unspecified thread.  Multiple functions
391   // added to the same Env may run concurrently in different threads.
392   // I.e., the caller may not assume that background work items are
393   // serialized.
394   // When the UnSchedule function is called, the unschedFunction
395   // registered at the time of Schedule is invoked with arg as a parameter.
396   virtual void Schedule(void (*function)(void* arg), void* arg,
397                         Priority pri = LOW, void* tag = nullptr,
398                         void (*unschedFunction)(void* arg) = nullptr) = 0;
399 
400   // Arrange to remove jobs for given arg from the queue_ if they are not
401   // already scheduled. Caller is expected to have exclusive lock on arg.
UnSchedule(void *,Priority)402   virtual int UnSchedule(void* /*arg*/, Priority /*pri*/) { return 0; }
403 
404   // Start a new thread, invoking "function(arg)" within the new thread.
405   // When "function(arg)" returns, the thread will be destroyed.
406   virtual void StartThread(void (*function)(void* arg), void* arg) = 0;
407 
408   // Wait for all threads started by StartThread to terminate.
WaitForJoin()409   virtual void WaitForJoin() {}
410 
411   // Get thread pool queue length for specific thread pool.
412   virtual unsigned int GetThreadPoolQueueLen(Priority /*pri*/ = LOW) const {
413     return 0;
414   }
415 
416   // *path is set to a temporary directory that can be used for testing. It may
417   // or many not have just been created. The directory may or may not differ
418   // between runs of the same process, but subsequent calls will return the
419   // same directory.
420   virtual Status GetTestDirectory(std::string* path) = 0;
421 
422   // Create and returns a default logger (an instance of EnvLogger) for storing
423   // informational messages. Derived classes can overide to provide custom
424   // logger.
425   virtual Status NewLogger(const std::string& fname,
426                            std::shared_ptr<Logger>* result);
427 
428   // Returns the number of micro-seconds since some fixed point in time.
429   // It is often used as system time such as in GenericRateLimiter
430   // and other places so a port needs to return system time in order to work.
431   virtual uint64_t NowMicros() = 0;
432 
433   // Returns the number of nano-seconds since some fixed point in time. Only
434   // useful for computing deltas of time in one run.
435   // Default implementation simply relies on NowMicros.
436   // In platform-specific implementations, NowNanos() should return time points
437   // that are MONOTONIC.
NowNanos()438   virtual uint64_t NowNanos() { return NowMicros() * 1000; }
439 
440   // 0 indicates not supported.
NowCPUNanos()441   virtual uint64_t NowCPUNanos() { return 0; }
442 
443   // Sleep/delay the thread for the prescribed number of micro-seconds.
444   virtual void SleepForMicroseconds(int micros) = 0;
445 
446   // Get the current host name.
447   virtual Status GetHostName(char* name, uint64_t len) = 0;
448 
449   // Get the number of seconds since the Epoch, 1970-01-01 00:00:00 (UTC).
450   // Only overwrites *unix_time on success.
451   virtual Status GetCurrentTime(int64_t* unix_time) = 0;
452 
453   // Get full directory name for this db.
454   virtual Status GetAbsolutePath(const std::string& db_path,
455                                  std::string* output_path) = 0;
456 
457   // The number of background worker threads of a specific thread pool
458   // for this environment. 'LOW' is the default pool.
459   // default number: 1
460   virtual void SetBackgroundThreads(int number, Priority pri = LOW) = 0;
461   virtual int GetBackgroundThreads(Priority pri = LOW) = 0;
462 
SetAllowNonOwnerAccess(bool)463   virtual Status SetAllowNonOwnerAccess(bool /*allow_non_owner_access*/) {
464     return Status::NotSupported("Not supported.");
465   }
466 
467   // Enlarge number of background worker threads of a specific thread pool
468   // for this environment if it is smaller than specified. 'LOW' is the default
469   // pool.
470   virtual void IncBackgroundThreadsIfNeeded(int number, Priority pri) = 0;
471 
472   // Lower IO priority for threads from the specified pool.
473   virtual void LowerThreadPoolIOPriority(Priority /*pool*/ = LOW) {}
474 
475   // Lower CPU priority for threads from the specified pool.
476   virtual void LowerThreadPoolCPUPriority(Priority /*pool*/ = LOW) {}
477 
478   // Converts seconds-since-Jan-01-1970 to a printable string
479   virtual std::string TimeToString(uint64_t time) = 0;
480 
481   // Generates a unique id that can be used to identify a db
482   virtual std::string GenerateUniqueId();
483 
484   // OptimizeForLogWrite will create a new EnvOptions object that is a copy of
485   // the EnvOptions in the parameters, but is optimized for reading log files.
486   virtual EnvOptions OptimizeForLogRead(const EnvOptions& env_options) const;
487 
488   // OptimizeForManifestRead will create a new EnvOptions object that is a copy
489   // of the EnvOptions in the parameters, but is optimized for reading manifest
490   // files.
491   virtual EnvOptions OptimizeForManifestRead(
492       const EnvOptions& env_options) const;
493 
494   // OptimizeForLogWrite will create a new EnvOptions object that is a copy of
495   // the EnvOptions in the parameters, but is optimized for writing log files.
496   // Default implementation returns the copy of the same object.
497   virtual EnvOptions OptimizeForLogWrite(const EnvOptions& env_options,
498                                          const DBOptions& db_options) const;
499   // OptimizeForManifestWrite will create a new EnvOptions object that is a copy
500   // of the EnvOptions in the parameters, but is optimized for writing manifest
501   // files. Default implementation returns the copy of the same object.
502   virtual EnvOptions OptimizeForManifestWrite(
503       const EnvOptions& env_options) const;
504 
505   // OptimizeForCompactionTableWrite will create a new EnvOptions object that is
506   // a copy of the EnvOptions in the parameters, but is optimized for writing
507   // table files.
508   virtual EnvOptions OptimizeForCompactionTableWrite(
509       const EnvOptions& env_options,
510       const ImmutableDBOptions& immutable_ops) const;
511 
512   // OptimizeForCompactionTableWrite will create a new EnvOptions object that
513   // is a copy of the EnvOptions in the parameters, but is optimized for reading
514   // table files.
515   virtual EnvOptions OptimizeForCompactionTableRead(
516       const EnvOptions& env_options,
517       const ImmutableDBOptions& db_options) const;
518 
519   // Returns the status of all threads that belong to the current Env.
GetThreadList(std::vector<ThreadStatus> *)520   virtual Status GetThreadList(std::vector<ThreadStatus>* /*thread_list*/) {
521     return Status::NotSupported("Not supported.");
522   }
523 
524   // Returns the pointer to ThreadStatusUpdater.  This function will be
525   // used in RocksDB internally to update thread status and supports
526   // GetThreadList().
GetThreadStatusUpdater()527   virtual ThreadStatusUpdater* GetThreadStatusUpdater() const {
528     return thread_status_updater_;
529   }
530 
531   // Returns the ID of the current thread.
532   virtual uint64_t GetThreadID() const;
533 
534 // This seems to clash with a macro on Windows, so #undef it here
535 #undef GetFreeSpace
536 
537   // Get the amount of free disk space
GetFreeSpace(const std::string &,uint64_t *)538   virtual Status GetFreeSpace(const std::string& /*path*/,
539                               uint64_t* /*diskfree*/) {
540     return Status::NotSupported();
541   }
542 
SanitizeEnvOptions(EnvOptions *)543   virtual void SanitizeEnvOptions(EnvOptions* /*env_opts*/) const {}
544 
545   // Get the FileSystem implementation this Env was constructed with. It
546   // could be a fully implemented one, or a wrapper class around the Env
547   const std::shared_ptr<FileSystem>& GetFileSystem() const;
548 
549   // If you're adding methods here, remember to add them to EnvWrapper too.
550 
551  protected:
552   // The pointer to an internal structure that will update the
553   // status of each thread.
554   ThreadStatusUpdater* thread_status_updater_;
555 
556   // Pointer to the underlying FileSystem implementation
557   std::shared_ptr<FileSystem> file_system_;
558 };
559 
560 // The factory function to construct a ThreadStatusUpdater.  Any Env
561 // that supports GetThreadList() feature should call this function in its
562 // constructor to initialize thread_status_updater_.
563 ThreadStatusUpdater* CreateThreadStatusUpdater();
564 
565 // A file abstraction for reading sequentially through a file
566 class SequentialFile {
567  public:
SequentialFile()568   SequentialFile() {}
569   virtual ~SequentialFile();
570 
571   // Read up to "n" bytes from the file.  "scratch[0..n-1]" may be
572   // written by this routine.  Sets "*result" to the data that was
573   // read (including if fewer than "n" bytes were successfully read).
574   // May set "*result" to point at data in "scratch[0..n-1]", so
575   // "scratch[0..n-1]" must be live when "*result" is used.
576   // If an error was encountered, returns a non-OK status.
577   //
578   // REQUIRES: External synchronization
579   virtual Status Read(size_t n, Slice* result, char* scratch) = 0;
580 
581   // Skip "n" bytes from the file. This is guaranteed to be no
582   // slower that reading the same data, but may be faster.
583   //
584   // If end of file is reached, skipping will stop at the end of the
585   // file, and Skip will return OK.
586   //
587   // REQUIRES: External synchronization
588   virtual Status Skip(uint64_t n) = 0;
589 
590   // Indicates the upper layers if the current SequentialFile implementation
591   // uses direct IO.
use_direct_io()592   virtual bool use_direct_io() const { return false; }
593 
594   // Use the returned alignment value to allocate
595   // aligned buffer for Direct I/O
GetRequiredBufferAlignment()596   virtual size_t GetRequiredBufferAlignment() const { return kDefaultPageSize; }
597 
598   // Remove any kind of caching of data from the offset to offset+length
599   // of this file. If the length is 0, then it refers to the end of file.
600   // If the system is not caching the file contents, then this is a noop.
InvalidateCache(size_t,size_t)601   virtual Status InvalidateCache(size_t /*offset*/, size_t /*length*/) {
602     return Status::NotSupported("InvalidateCache not supported.");
603   }
604 
605   // Positioned Read for direct I/O
606   // If Direct I/O enabled, offset, n, and scratch should be properly aligned
PositionedRead(uint64_t,size_t,Slice *,char *)607   virtual Status PositionedRead(uint64_t /*offset*/, size_t /*n*/,
608                                 Slice* /*result*/, char* /*scratch*/) {
609     return Status::NotSupported();
610   }
611 
612   // If you're adding methods here, remember to add them to
613   // SequentialFileWrapper too.
614 };
615 
616 // A read IO request structure for use in MultiRead
617 struct ReadRequest {
618   // File offset in bytes
619   uint64_t offset;
620 
621   // Length to read in bytes
622   size_t len;
623 
624   // A buffer that MultiRead()  can optionally place data in. It can
625   // ignore this and allocate its own buffer
626   char* scratch;
627 
628   // Output parameter set by MultiRead() to point to the data buffer, and
629   // the number of valid bytes
630   Slice result;
631 
632   // Status of read
633   Status status;
634 };
635 
636 // A file abstraction for randomly reading the contents of a file.
637 class RandomAccessFile {
638  public:
RandomAccessFile()639   RandomAccessFile() {}
640   virtual ~RandomAccessFile();
641 
642   // Read up to "n" bytes from the file starting at "offset".
643   // "scratch[0..n-1]" may be written by this routine.  Sets "*result"
644   // to the data that was read (including if fewer than "n" bytes were
645   // successfully read).  May set "*result" to point at data in
646   // "scratch[0..n-1]", so "scratch[0..n-1]" must be live when
647   // "*result" is used.  If an error was encountered, returns a non-OK
648   // status.
649   //
650   // Safe for concurrent use by multiple threads.
651   // If Direct I/O enabled, offset, n, and scratch should be aligned properly.
652   virtual Status Read(uint64_t offset, size_t n, Slice* result,
653                       char* scratch) const = 0;
654 
655   // Readahead the file starting from offset by n bytes for caching.
Prefetch(uint64_t,size_t)656   virtual Status Prefetch(uint64_t /*offset*/, size_t /*n*/) {
657     return Status::OK();
658   }
659 
660   // Read a bunch of blocks as described by reqs. The blocks can
661   // optionally be read in parallel. This is a synchronous call, i.e it
662   // should return after all reads have completed. The reads will be
663   // non-overlapping. If the function return Status is not ok, status of
664   // individual requests will be ignored and return status will be assumed
665   // for all read requests. The function return status is only meant for any
666   // any errors that occur before even processing specific read requests
MultiRead(ReadRequest * reqs,size_t num_reqs)667   virtual Status MultiRead(ReadRequest* reqs, size_t num_reqs) {
668     assert(reqs != nullptr);
669     for (size_t i = 0; i < num_reqs; ++i) {
670       ReadRequest& req = reqs[i];
671       req.status = Read(req.offset, req.len, &req.result, req.scratch);
672     }
673     return Status::OK();
674   }
675 
676   // Tries to get an unique ID for this file that will be the same each time
677   // the file is opened (and will stay the same while the file is open).
678   // Furthermore, it tries to make this ID at most "max_size" bytes. If such an
679   // ID can be created this function returns the length of the ID and places it
680   // in "id"; otherwise, this function returns 0, in which case "id"
681   // may not have been modified.
682   //
683   // This function guarantees, for IDs from a given environment, two unique ids
684   // cannot be made equal to each other by adding arbitrary bytes to one of
685   // them. That is, no unique ID is the prefix of another.
686   //
687   // This function guarantees that the returned ID will not be interpretable as
688   // a single varint.
689   //
690   // Note: these IDs are only valid for the duration of the process.
GetUniqueId(char *,size_t)691   virtual size_t GetUniqueId(char* /*id*/, size_t /*max_size*/) const {
692     return 0;  // Default implementation to prevent issues with backwards
693                // compatibility.
694   }
695 
696   enum AccessPattern { NORMAL, RANDOM, SEQUENTIAL, WILLNEED, DONTNEED };
697 
Hint(AccessPattern)698   virtual void Hint(AccessPattern /*pattern*/) {}
699 
700   // Indicates the upper layers if the current RandomAccessFile implementation
701   // uses direct IO.
use_direct_io()702   virtual bool use_direct_io() const { return false; }
703 
704   // Use the returned alignment value to allocate
705   // aligned buffer for Direct I/O
GetRequiredBufferAlignment()706   virtual size_t GetRequiredBufferAlignment() const { return kDefaultPageSize; }
707 
708   // Remove any kind of caching of data from the offset to offset+length
709   // of this file. If the length is 0, then it refers to the end of file.
710   // If the system is not caching the file contents, then this is a noop.
InvalidateCache(size_t,size_t)711   virtual Status InvalidateCache(size_t /*offset*/, size_t /*length*/) {
712     return Status::NotSupported("InvalidateCache not supported.");
713   }
714 
715   // If you're adding methods here, remember to add them to
716   // RandomAccessFileWrapper too.
717 };
718 
719 // A file abstraction for sequential writing.  The implementation
720 // must provide buffering since callers may append small fragments
721 // at a time to the file.
722 class WritableFile {
723  public:
WritableFile()724   WritableFile()
725       : last_preallocated_block_(0),
726         preallocation_block_size_(0),
727         io_priority_(Env::IO_TOTAL),
728         write_hint_(Env::WLTH_NOT_SET),
729         strict_bytes_per_sync_(false) {}
730 
WritableFile(const EnvOptions & options)731   explicit WritableFile(const EnvOptions& options)
732       : last_preallocated_block_(0),
733         preallocation_block_size_(0),
734         io_priority_(Env::IO_TOTAL),
735         write_hint_(Env::WLTH_NOT_SET),
736         strict_bytes_per_sync_(options.strict_bytes_per_sync) {}
737   // No copying allowed
738   WritableFile(const WritableFile&) = delete;
739   void operator=(const WritableFile&) = delete;
740 
741   virtual ~WritableFile();
742 
743   // Append data to the end of the file
744   // Note: A WriteabelFile object must support either Append or
745   // PositionedAppend, so the users cannot mix the two.
746   virtual Status Append(const Slice& data) = 0;
747 
748   // PositionedAppend data to the specified offset. The new EOF after append
749   // must be larger than the previous EOF. This is to be used when writes are
750   // not backed by OS buffers and hence has to always start from the start of
751   // the sector. The implementation thus needs to also rewrite the last
752   // partial sector.
753   // Note: PositionAppend does not guarantee moving the file offset after the
754   // write. A WritableFile object must support either Append or
755   // PositionedAppend, so the users cannot mix the two.
756   //
757   // PositionedAppend() can only happen on the page/sector boundaries. For that
758   // reason, if the last write was an incomplete sector we still need to rewind
759   // back to the nearest sector/page and rewrite the portion of it with whatever
760   // we need to add. We need to keep where we stop writing.
761   //
762   // PositionedAppend() can only write whole sectors. For that reason we have to
763   // pad with zeros for the last write and trim the file when closing according
764   // to the position we keep in the previous step.
765   //
766   // PositionedAppend() requires aligned buffer to be passed in. The alignment
767   // required is queried via GetRequiredBufferAlignment()
PositionedAppend(const Slice &,uint64_t)768   virtual Status PositionedAppend(const Slice& /* data */,
769                                   uint64_t /* offset */) {
770     return Status::NotSupported();
771   }
772 
773   // Truncate is necessary to trim the file to the correct size
774   // before closing. It is not always possible to keep track of the file
775   // size due to whole pages writes. The behavior is undefined if called
776   // with other writes to follow.
Truncate(uint64_t)777   virtual Status Truncate(uint64_t /*size*/) { return Status::OK(); }
778   virtual Status Close() = 0;
779   virtual Status Flush() = 0;
780   virtual Status Sync() = 0;  // sync data
781 
782   /*
783    * Sync data and/or metadata as well.
784    * By default, sync only data.
785    * Override this method for environments where we need to sync
786    * metadata as well.
787    */
Fsync()788   virtual Status Fsync() { return Sync(); }
789 
790   // true if Sync() and Fsync() are safe to call concurrently with Append()
791   // and Flush().
IsSyncThreadSafe()792   virtual bool IsSyncThreadSafe() const { return false; }
793 
794   // Indicates the upper layers if the current WritableFile implementation
795   // uses direct IO.
use_direct_io()796   virtual bool use_direct_io() const { return false; }
797 
798   // Use the returned alignment value to allocate
799   // aligned buffer for Direct I/O
GetRequiredBufferAlignment()800   virtual size_t GetRequiredBufferAlignment() const { return kDefaultPageSize; }
801   /*
802    * Change the priority in rate limiter if rate limiting is enabled.
803    * If rate limiting is not enabled, this call has no effect.
804    */
SetIOPriority(Env::IOPriority pri)805   virtual void SetIOPriority(Env::IOPriority pri) { io_priority_ = pri; }
806 
GetIOPriority()807   virtual Env::IOPriority GetIOPriority() { return io_priority_; }
808 
SetWriteLifeTimeHint(Env::WriteLifeTimeHint hint)809   virtual void SetWriteLifeTimeHint(Env::WriteLifeTimeHint hint) {
810     write_hint_ = hint;
811   }
812 
GetWriteLifeTimeHint()813   virtual Env::WriteLifeTimeHint GetWriteLifeTimeHint() { return write_hint_; }
814   /*
815    * Get the size of valid data in the file.
816    */
GetFileSize()817   virtual uint64_t GetFileSize() { return 0; }
818 
819   /*
820    * Get and set the default pre-allocation block size for writes to
821    * this file.  If non-zero, then Allocate will be used to extend the
822    * underlying storage of a file (generally via fallocate) if the Env
823    * instance supports it.
824    */
SetPreallocationBlockSize(size_t size)825   virtual void SetPreallocationBlockSize(size_t size) {
826     preallocation_block_size_ = size;
827   }
828 
GetPreallocationStatus(size_t * block_size,size_t * last_allocated_block)829   virtual void GetPreallocationStatus(size_t* block_size,
830                                       size_t* last_allocated_block) {
831     *last_allocated_block = last_preallocated_block_;
832     *block_size = preallocation_block_size_;
833   }
834 
835   // For documentation, refer to RandomAccessFile::GetUniqueId()
GetUniqueId(char *,size_t)836   virtual size_t GetUniqueId(char* /*id*/, size_t /*max_size*/) const {
837     return 0;  // Default implementation to prevent issues with backwards
838   }
839 
840   // Remove any kind of caching of data from the offset to offset+length
841   // of this file. If the length is 0, then it refers to the end of file.
842   // If the system is not caching the file contents, then this is a noop.
843   // This call has no effect on dirty pages in the cache.
InvalidateCache(size_t,size_t)844   virtual Status InvalidateCache(size_t /*offset*/, size_t /*length*/) {
845     return Status::NotSupported("InvalidateCache not supported.");
846   }
847 
848   // Sync a file range with disk.
849   // offset is the starting byte of the file range to be synchronized.
850   // nbytes specifies the length of the range to be synchronized.
851   // This asks the OS to initiate flushing the cached data to disk,
852   // without waiting for completion.
853   // Default implementation does nothing.
RangeSync(uint64_t,uint64_t)854   virtual Status RangeSync(uint64_t /*offset*/, uint64_t /*nbytes*/) {
855     if (strict_bytes_per_sync_) {
856       return Sync();
857     }
858     return Status::OK();
859   }
860 
861   // PrepareWrite performs any necessary preparation for a write
862   // before the write actually occurs.  This allows for pre-allocation
863   // of space on devices where it can result in less file
864   // fragmentation and/or less waste from over-zealous filesystem
865   // pre-allocation.
PrepareWrite(size_t offset,size_t len)866   virtual void PrepareWrite(size_t offset, size_t len) {
867     if (preallocation_block_size_ == 0) {
868       return;
869     }
870     // If this write would cross one or more preallocation blocks,
871     // determine what the last preallocation block necessary to
872     // cover this write would be and Allocate to that point.
873     const auto block_size = preallocation_block_size_;
874     size_t new_last_preallocated_block =
875         (offset + len + block_size - 1) / block_size;
876     if (new_last_preallocated_block > last_preallocated_block_) {
877       size_t num_spanned_blocks =
878           new_last_preallocated_block - last_preallocated_block_;
879       Allocate(block_size * last_preallocated_block_,
880                block_size * num_spanned_blocks);
881       last_preallocated_block_ = new_last_preallocated_block;
882     }
883   }
884 
885   // Pre-allocates space for a file.
Allocate(uint64_t,uint64_t)886   virtual Status Allocate(uint64_t /*offset*/, uint64_t /*len*/) {
887     return Status::OK();
888   }
889 
890   // If you're adding methods here, remember to add them to
891   // WritableFileWrapper too.
892 
893  protected:
preallocation_block_size()894   size_t preallocation_block_size() { return preallocation_block_size_; }
895 
896  private:
897   size_t last_preallocated_block_;
898   size_t preallocation_block_size_;
899 
900  protected:
901   Env::IOPriority io_priority_;
902   Env::WriteLifeTimeHint write_hint_;
903   const bool strict_bytes_per_sync_;
904 };
905 
906 // A file abstraction for random reading and writing.
907 class RandomRWFile {
908  public:
RandomRWFile()909   RandomRWFile() {}
910   // No copying allowed
911   RandomRWFile(const RandomRWFile&) = delete;
912   RandomRWFile& operator=(const RandomRWFile&) = delete;
913 
~RandomRWFile()914   virtual ~RandomRWFile() {}
915 
916   // Indicates if the class makes use of direct I/O
917   // If false you must pass aligned buffer to Write()
use_direct_io()918   virtual bool use_direct_io() const { return false; }
919 
920   // Use the returned alignment value to allocate
921   // aligned buffer for Direct I/O
GetRequiredBufferAlignment()922   virtual size_t GetRequiredBufferAlignment() const { return kDefaultPageSize; }
923 
924   // Write bytes in `data` at  offset `offset`, Returns Status::OK() on success.
925   // Pass aligned buffer when use_direct_io() returns true.
926   virtual Status Write(uint64_t offset, const Slice& data) = 0;
927 
928   // Read up to `n` bytes starting from offset `offset` and store them in
929   // result, provided `scratch` size should be at least `n`.
930   // Returns Status::OK() on success.
931   virtual Status Read(uint64_t offset, size_t n, Slice* result,
932                       char* scratch) const = 0;
933 
934   virtual Status Flush() = 0;
935 
936   virtual Status Sync() = 0;
937 
Fsync()938   virtual Status Fsync() { return Sync(); }
939 
940   virtual Status Close() = 0;
941 
942   // If you're adding methods here, remember to add them to
943   // RandomRWFileWrapper too.
944 };
945 
946 // MemoryMappedFileBuffer object represents a memory-mapped file's raw buffer.
947 // Subclasses should release the mapping upon destruction.
948 class MemoryMappedFileBuffer {
949  public:
MemoryMappedFileBuffer(void * _base,size_t _length)950   MemoryMappedFileBuffer(void* _base, size_t _length)
951       : base_(_base), length_(_length) {}
952 
953   virtual ~MemoryMappedFileBuffer() = 0;
954 
955   // We do not want to unmap this twice. We can make this class
956   // movable if desired, however, since
957   MemoryMappedFileBuffer(const MemoryMappedFileBuffer&) = delete;
958   MemoryMappedFileBuffer& operator=(const MemoryMappedFileBuffer&) = delete;
959 
GetBase()960   void* GetBase() const { return base_; }
GetLen()961   size_t GetLen() const { return length_; }
962 
963  protected:
964   void* base_;
965   const size_t length_;
966 };
967 
968 // Directory object represents collection of files and implements
969 // filesystem operations that can be executed on directories.
970 class Directory {
971  public:
~Directory()972   virtual ~Directory() {}
973   // Fsync directory. Can be called concurrently from multiple threads.
974   virtual Status Fsync() = 0;
975 
GetUniqueId(char *,size_t)976   virtual size_t GetUniqueId(char* /*id*/, size_t /*max_size*/) const {
977     return 0;
978   }
979 
980   // If you're adding methods here, remember to add them to
981   // DirectoryWrapper too.
982 };
983 
984 enum InfoLogLevel : unsigned char {
985   DEBUG_LEVEL = 0,
986   INFO_LEVEL,
987   WARN_LEVEL,
988   ERROR_LEVEL,
989   FATAL_LEVEL,
990   HEADER_LEVEL,
991   NUM_INFO_LOG_LEVELS,
992 };
993 
994 // An interface for writing log messages.
995 class Logger {
996  public:
997   size_t kDoNotSupportGetLogFileSize = (std::numeric_limits<size_t>::max)();
998 
999   explicit Logger(const InfoLogLevel log_level = InfoLogLevel::INFO_LEVEL)
closed_(false)1000       : closed_(false), log_level_(log_level) {}
1001   // No copying allowed
1002   Logger(const Logger&) = delete;
1003   void operator=(const Logger&) = delete;
1004 
1005   virtual ~Logger();
1006 
1007   // Close the log file. Must be called before destructor. If the return
1008   // status is NotSupported(), it means the implementation does cleanup in
1009   // the destructor
1010   virtual Status Close();
1011 
1012   // Write a header to the log file with the specified format
1013   // It is recommended that you log all header information at the start of the
1014   // application. But it is not enforced.
LogHeader(const char * format,va_list ap)1015   virtual void LogHeader(const char* format, va_list ap) {
1016     // Default implementation does a simple INFO level log write.
1017     // Please override as per the logger class requirement.
1018     Logv(format, ap);
1019   }
1020 
1021   // Write an entry to the log file with the specified format.
1022   virtual void Logv(const char* format, va_list ap) = 0;
1023 
1024   // Write an entry to the log file with the specified log level
1025   // and format.  Any log with level under the internal log level
1026   // of *this (see @SetInfoLogLevel and @GetInfoLogLevel) will not be
1027   // printed.
1028   virtual void Logv(const InfoLogLevel log_level, const char* format,
1029                     va_list ap);
1030 
GetLogFileSize()1031   virtual size_t GetLogFileSize() const { return kDoNotSupportGetLogFileSize; }
1032   // Flush to the OS buffers
Flush()1033   virtual void Flush() {}
GetInfoLogLevel()1034   virtual InfoLogLevel GetInfoLogLevel() const { return log_level_; }
SetInfoLogLevel(const InfoLogLevel log_level)1035   virtual void SetInfoLogLevel(const InfoLogLevel log_level) {
1036     log_level_ = log_level;
1037   }
1038 
1039   // If you're adding methods here, remember to add them to LoggerWrapper too.
1040 
1041  protected:
1042   virtual Status CloseImpl();
1043   bool closed_;
1044 
1045  private:
1046   InfoLogLevel log_level_;
1047 };
1048 
1049 // Identifies a locked file.
1050 class FileLock {
1051  public:
FileLock()1052   FileLock() {}
1053   virtual ~FileLock();
1054 
1055  private:
1056   // No copying allowed
1057   FileLock(const FileLock&) = delete;
1058   void operator=(const FileLock&) = delete;
1059 };
1060 
1061 class DynamicLibrary {
1062  public:
~DynamicLibrary()1063   virtual ~DynamicLibrary() {}
1064 
1065   // Returns the name of the dynamic library.
1066   virtual const char* Name() const = 0;
1067 
1068   // Loads the symbol for sym_name from the library and updates the input
1069   // function. Returns the loaded symbol.
1070   template <typename T>
LoadFunction(const std::string & sym_name,std::function<T> * function)1071   Status LoadFunction(const std::string& sym_name, std::function<T>* function) {
1072     assert(nullptr != function);
1073     void* ptr = nullptr;
1074     Status s = LoadSymbol(sym_name, &ptr);
1075     *function = reinterpret_cast<T*>(ptr);
1076     return s;
1077   }
1078   // Loads and returns the symbol for sym_name from the library.
1079   virtual Status LoadSymbol(const std::string& sym_name, void** func) = 0;
1080 };
1081 
1082 extern void LogFlush(const std::shared_ptr<Logger>& info_log);
1083 
1084 extern void Log(const InfoLogLevel log_level,
1085                 const std::shared_ptr<Logger>& info_log, const char* format,
1086                 ...) ROCKSDB_PRINTF_FORMAT_ATTR(3, 4);
1087 
1088 // a set of log functions with different log levels.
1089 extern void Header(const std::shared_ptr<Logger>& info_log, const char* format,
1090                    ...) ROCKSDB_PRINTF_FORMAT_ATTR(2, 3);
1091 extern void Debug(const std::shared_ptr<Logger>& info_log, const char* format,
1092                   ...) ROCKSDB_PRINTF_FORMAT_ATTR(2, 3);
1093 extern void Info(const std::shared_ptr<Logger>& info_log, const char* format,
1094                  ...) ROCKSDB_PRINTF_FORMAT_ATTR(2, 3);
1095 extern void Warn(const std::shared_ptr<Logger>& info_log, const char* format,
1096                  ...) ROCKSDB_PRINTF_FORMAT_ATTR(2, 3);
1097 extern void Error(const std::shared_ptr<Logger>& info_log, const char* format,
1098                   ...) ROCKSDB_PRINTF_FORMAT_ATTR(2, 3);
1099 extern void Fatal(const std::shared_ptr<Logger>& info_log, const char* format,
1100                   ...) ROCKSDB_PRINTF_FORMAT_ATTR(2, 3);
1101 
1102 // Log the specified data to *info_log if info_log is non-nullptr.
1103 // The default info log level is InfoLogLevel::INFO_LEVEL.
1104 extern void Log(const std::shared_ptr<Logger>& info_log, const char* format,
1105                 ...) ROCKSDB_PRINTF_FORMAT_ATTR(2, 3);
1106 
1107 extern void LogFlush(Logger* info_log);
1108 
1109 extern void Log(const InfoLogLevel log_level, Logger* info_log,
1110                 const char* format, ...) ROCKSDB_PRINTF_FORMAT_ATTR(3, 4);
1111 
1112 // The default info log level is InfoLogLevel::INFO_LEVEL.
1113 extern void Log(Logger* info_log, const char* format, ...)
1114     ROCKSDB_PRINTF_FORMAT_ATTR(2, 3);
1115 
1116 // a set of log functions with different log levels.
1117 extern void Header(Logger* info_log, const char* format, ...)
1118     ROCKSDB_PRINTF_FORMAT_ATTR(2, 3);
1119 extern void Debug(Logger* info_log, const char* format, ...)
1120     ROCKSDB_PRINTF_FORMAT_ATTR(2, 3);
1121 extern void Info(Logger* info_log, const char* format, ...)
1122     ROCKSDB_PRINTF_FORMAT_ATTR(2, 3);
1123 extern void Warn(Logger* info_log, const char* format, ...)
1124     ROCKSDB_PRINTF_FORMAT_ATTR(2, 3);
1125 extern void Error(Logger* info_log, const char* format, ...)
1126     ROCKSDB_PRINTF_FORMAT_ATTR(2, 3);
1127 extern void Fatal(Logger* info_log, const char* format, ...)
1128     ROCKSDB_PRINTF_FORMAT_ATTR(2, 3);
1129 
1130 // A utility routine: write "data" to the named file.
1131 extern Status WriteStringToFile(Env* env, const Slice& data,
1132                                 const std::string& fname,
1133                                 bool should_sync = false);
1134 
1135 // A utility routine: read contents of named file into *data
1136 extern Status ReadFileToString(Env* env, const std::string& fname,
1137                                std::string* data);
1138 
1139 // Below are helpers for wrapping most of the classes in this file.
1140 // They forward all calls to another instance of the class.
1141 // Useful when wrapping the default implementations.
1142 // Typical usage is to inherit your wrapper from *Wrapper, e.g.:
1143 //
1144 // class MySequentialFileWrapper : public
1145 // ROCKSDB_NAMESPACE::SequentialFileWrapper {
1146 //  public:
1147 //   MySequentialFileWrapper(ROCKSDB_NAMESPACE::SequentialFile* target):
1148 //     ROCKSDB_NAMESPACE::SequentialFileWrapper(target) {}
1149 //   Status Read(size_t n, Slice* result, char* scratch) override {
1150 //     cout << "Doing a read of size " << n << "!" << endl;
1151 //     return ROCKSDB_NAMESPACE::SequentialFileWrapper::Read(n, result,
1152 //     scratch);
1153 //   }
1154 //   // All other methods are forwarded to target_ automatically.
1155 // };
1156 //
1157 // This is often more convenient than inheriting the class directly because
1158 // (a) Don't have to override and forward all methods - the Wrapper will
1159 //     forward everything you're not explicitly overriding.
1160 // (b) Don't need to update the wrapper when more methods are added to the
1161 //     rocksdb class. Unless you actually want to override the behavior.
1162 //     (And unless rocksdb people forgot to update the *Wrapper class.)
1163 
1164 // An implementation of Env that forwards all calls to another Env.
1165 // May be useful to clients who wish to override just part of the
1166 // functionality of another Env.
1167 class EnvWrapper : public Env {
1168  public:
1169   // Initialize an EnvWrapper that delegates all calls to *t
EnvWrapper(Env * t)1170   explicit EnvWrapper(Env* t) : target_(t) {}
1171   ~EnvWrapper() override;
1172 
1173   // Return the target to which this Env forwards all calls
target()1174   Env* target() const { return target_; }
1175 
1176   // The following text is boilerplate that forwards all methods to target()
RegisterDbPaths(const std::vector<std::string> & paths)1177   Status RegisterDbPaths(const std::vector<std::string>& paths) override {
1178     return target_->RegisterDbPaths(paths);
1179   }
1180 
UnregisterDbPaths(const std::vector<std::string> & paths)1181   Status UnregisterDbPaths(const std::vector<std::string>& paths) override {
1182     return target_->UnregisterDbPaths(paths);
1183   }
1184 
NewSequentialFile(const std::string & f,std::unique_ptr<SequentialFile> * r,const EnvOptions & options)1185   Status NewSequentialFile(const std::string& f,
1186                            std::unique_ptr<SequentialFile>* r,
1187                            const EnvOptions& options) override {
1188     return target_->NewSequentialFile(f, r, options);
1189   }
NewRandomAccessFile(const std::string & f,std::unique_ptr<RandomAccessFile> * r,const EnvOptions & options)1190   Status NewRandomAccessFile(const std::string& f,
1191                              std::unique_ptr<RandomAccessFile>* r,
1192                              const EnvOptions& options) override {
1193     return target_->NewRandomAccessFile(f, r, options);
1194   }
NewWritableFile(const std::string & f,std::unique_ptr<WritableFile> * r,const EnvOptions & options)1195   Status NewWritableFile(const std::string& f, std::unique_ptr<WritableFile>* r,
1196                          const EnvOptions& options) override {
1197     return target_->NewWritableFile(f, r, options);
1198   }
ReopenWritableFile(const std::string & fname,std::unique_ptr<WritableFile> * result,const EnvOptions & options)1199   Status ReopenWritableFile(const std::string& fname,
1200                             std::unique_ptr<WritableFile>* result,
1201                             const EnvOptions& options) override {
1202     return target_->ReopenWritableFile(fname, result, options);
1203   }
ReuseWritableFile(const std::string & fname,const std::string & old_fname,std::unique_ptr<WritableFile> * r,const EnvOptions & options)1204   Status ReuseWritableFile(const std::string& fname,
1205                            const std::string& old_fname,
1206                            std::unique_ptr<WritableFile>* r,
1207                            const EnvOptions& options) override {
1208     return target_->ReuseWritableFile(fname, old_fname, r, options);
1209   }
NewRandomRWFile(const std::string & fname,std::unique_ptr<RandomRWFile> * result,const EnvOptions & options)1210   Status NewRandomRWFile(const std::string& fname,
1211                          std::unique_ptr<RandomRWFile>* result,
1212                          const EnvOptions& options) override {
1213     return target_->NewRandomRWFile(fname, result, options);
1214   }
NewMemoryMappedFileBuffer(const std::string & fname,std::unique_ptr<MemoryMappedFileBuffer> * result)1215   Status NewMemoryMappedFileBuffer(
1216       const std::string& fname,
1217       std::unique_ptr<MemoryMappedFileBuffer>* result) override {
1218     return target_->NewMemoryMappedFileBuffer(fname, result);
1219   }
NewDirectory(const std::string & name,std::unique_ptr<Directory> * result)1220   Status NewDirectory(const std::string& name,
1221                       std::unique_ptr<Directory>* result) override {
1222     return target_->NewDirectory(name, result);
1223   }
FileExists(const std::string & f)1224   Status FileExists(const std::string& f) override {
1225     return target_->FileExists(f);
1226   }
GetChildren(const std::string & dir,std::vector<std::string> * r)1227   Status GetChildren(const std::string& dir,
1228                      std::vector<std::string>* r) override {
1229     return target_->GetChildren(dir, r);
1230   }
GetChildrenFileAttributes(const std::string & dir,std::vector<FileAttributes> * result)1231   Status GetChildrenFileAttributes(
1232       const std::string& dir, std::vector<FileAttributes>* result) override {
1233     return target_->GetChildrenFileAttributes(dir, result);
1234   }
DeleteFile(const std::string & f)1235   Status DeleteFile(const std::string& f) override {
1236     return target_->DeleteFile(f);
1237   }
Truncate(const std::string & fname,size_t size)1238   Status Truncate(const std::string& fname, size_t size) override {
1239     return target_->Truncate(fname, size);
1240   }
CreateDir(const std::string & d)1241   Status CreateDir(const std::string& d) override {
1242     return target_->CreateDir(d);
1243   }
CreateDirIfMissing(const std::string & d)1244   Status CreateDirIfMissing(const std::string& d) override {
1245     return target_->CreateDirIfMissing(d);
1246   }
DeleteDir(const std::string & d)1247   Status DeleteDir(const std::string& d) override {
1248     return target_->DeleteDir(d);
1249   }
GetFileSize(const std::string & f,uint64_t * s)1250   Status GetFileSize(const std::string& f, uint64_t* s) override {
1251     return target_->GetFileSize(f, s);
1252   }
1253 
GetFileModificationTime(const std::string & fname,uint64_t * file_mtime)1254   Status GetFileModificationTime(const std::string& fname,
1255                                  uint64_t* file_mtime) override {
1256     return target_->GetFileModificationTime(fname, file_mtime);
1257   }
1258 
RenameFile(const std::string & s,const std::string & t)1259   Status RenameFile(const std::string& s, const std::string& t) override {
1260     return target_->RenameFile(s, t);
1261   }
1262 
LinkFile(const std::string & s,const std::string & t)1263   Status LinkFile(const std::string& s, const std::string& t) override {
1264     return target_->LinkFile(s, t);
1265   }
1266 
NumFileLinks(const std::string & fname,uint64_t * count)1267   Status NumFileLinks(const std::string& fname, uint64_t* count) override {
1268     return target_->NumFileLinks(fname, count);
1269   }
1270 
AreFilesSame(const std::string & first,const std::string & second,bool * res)1271   Status AreFilesSame(const std::string& first, const std::string& second,
1272                       bool* res) override {
1273     return target_->AreFilesSame(first, second, res);
1274   }
1275 
LockFile(const std::string & f,FileLock ** l)1276   Status LockFile(const std::string& f, FileLock** l) override {
1277     return target_->LockFile(f, l);
1278   }
1279 
UnlockFile(FileLock * l)1280   Status UnlockFile(FileLock* l) override { return target_->UnlockFile(l); }
1281 
LoadLibrary(const std::string & lib_name,const std::string & search_path,std::shared_ptr<DynamicLibrary> * result)1282   Status LoadLibrary(const std::string& lib_name,
1283                      const std::string& search_path,
1284                      std::shared_ptr<DynamicLibrary>* result) override {
1285     return target_->LoadLibrary(lib_name, search_path, result);
1286   }
1287 
1288   void Schedule(void (*f)(void* arg), void* a, Priority pri,
1289                 void* tag = nullptr, void (*u)(void* arg) = nullptr) override {
1290     return target_->Schedule(f, a, pri, tag, u);
1291   }
1292 
UnSchedule(void * tag,Priority pri)1293   int UnSchedule(void* tag, Priority pri) override {
1294     return target_->UnSchedule(tag, pri);
1295   }
1296 
StartThread(void (* f)(void *),void * a)1297   void StartThread(void (*f)(void*), void* a) override {
1298     return target_->StartThread(f, a);
1299   }
WaitForJoin()1300   void WaitForJoin() override { return target_->WaitForJoin(); }
1301   unsigned int GetThreadPoolQueueLen(Priority pri = LOW) const override {
1302     return target_->GetThreadPoolQueueLen(pri);
1303   }
GetTestDirectory(std::string * path)1304   Status GetTestDirectory(std::string* path) override {
1305     return target_->GetTestDirectory(path);
1306   }
NewLogger(const std::string & fname,std::shared_ptr<Logger> * result)1307   Status NewLogger(const std::string& fname,
1308                    std::shared_ptr<Logger>* result) override {
1309     return target_->NewLogger(fname, result);
1310   }
NowMicros()1311   uint64_t NowMicros() override { return target_->NowMicros(); }
NowNanos()1312   uint64_t NowNanos() override { return target_->NowNanos(); }
NowCPUNanos()1313   uint64_t NowCPUNanos() override { return target_->NowCPUNanos(); }
1314 
SleepForMicroseconds(int micros)1315   void SleepForMicroseconds(int micros) override {
1316     target_->SleepForMicroseconds(micros);
1317   }
GetHostName(char * name,uint64_t len)1318   Status GetHostName(char* name, uint64_t len) override {
1319     return target_->GetHostName(name, len);
1320   }
GetCurrentTime(int64_t * unix_time)1321   Status GetCurrentTime(int64_t* unix_time) override {
1322     return target_->GetCurrentTime(unix_time);
1323   }
GetAbsolutePath(const std::string & db_path,std::string * output_path)1324   Status GetAbsolutePath(const std::string& db_path,
1325                          std::string* output_path) override {
1326     return target_->GetAbsolutePath(db_path, output_path);
1327   }
SetBackgroundThreads(int num,Priority pri)1328   void SetBackgroundThreads(int num, Priority pri) override {
1329     return target_->SetBackgroundThreads(num, pri);
1330   }
GetBackgroundThreads(Priority pri)1331   int GetBackgroundThreads(Priority pri) override {
1332     return target_->GetBackgroundThreads(pri);
1333   }
1334 
SetAllowNonOwnerAccess(bool allow_non_owner_access)1335   Status SetAllowNonOwnerAccess(bool allow_non_owner_access) override {
1336     return target_->SetAllowNonOwnerAccess(allow_non_owner_access);
1337   }
1338 
IncBackgroundThreadsIfNeeded(int num,Priority pri)1339   void IncBackgroundThreadsIfNeeded(int num, Priority pri) override {
1340     return target_->IncBackgroundThreadsIfNeeded(num, pri);
1341   }
1342 
1343   void LowerThreadPoolIOPriority(Priority pool = LOW) override {
1344     target_->LowerThreadPoolIOPriority(pool);
1345   }
1346 
1347   void LowerThreadPoolCPUPriority(Priority pool = LOW) override {
1348     target_->LowerThreadPoolCPUPriority(pool);
1349   }
1350 
TimeToString(uint64_t time)1351   std::string TimeToString(uint64_t time) override {
1352     return target_->TimeToString(time);
1353   }
1354 
GetThreadList(std::vector<ThreadStatus> * thread_list)1355   Status GetThreadList(std::vector<ThreadStatus>* thread_list) override {
1356     return target_->GetThreadList(thread_list);
1357   }
1358 
GetThreadStatusUpdater()1359   ThreadStatusUpdater* GetThreadStatusUpdater() const override {
1360     return target_->GetThreadStatusUpdater();
1361   }
1362 
GetThreadID()1363   uint64_t GetThreadID() const override { return target_->GetThreadID(); }
1364 
GenerateUniqueId()1365   std::string GenerateUniqueId() override {
1366     return target_->GenerateUniqueId();
1367   }
1368 
OptimizeForLogRead(const EnvOptions & env_options)1369   EnvOptions OptimizeForLogRead(const EnvOptions& env_options) const override {
1370     return target_->OptimizeForLogRead(env_options);
1371   }
OptimizeForManifestRead(const EnvOptions & env_options)1372   EnvOptions OptimizeForManifestRead(
1373       const EnvOptions& env_options) const override {
1374     return target_->OptimizeForManifestRead(env_options);
1375   }
OptimizeForLogWrite(const EnvOptions & env_options,const DBOptions & db_options)1376   EnvOptions OptimizeForLogWrite(const EnvOptions& env_options,
1377                                  const DBOptions& db_options) const override {
1378     return target_->OptimizeForLogWrite(env_options, db_options);
1379   }
OptimizeForManifestWrite(const EnvOptions & env_options)1380   EnvOptions OptimizeForManifestWrite(
1381       const EnvOptions& env_options) const override {
1382     return target_->OptimizeForManifestWrite(env_options);
1383   }
OptimizeForCompactionTableWrite(const EnvOptions & env_options,const ImmutableDBOptions & immutable_ops)1384   EnvOptions OptimizeForCompactionTableWrite(
1385       const EnvOptions& env_options,
1386       const ImmutableDBOptions& immutable_ops) const override {
1387     return target_->OptimizeForCompactionTableWrite(env_options, immutable_ops);
1388   }
OptimizeForCompactionTableRead(const EnvOptions & env_options,const ImmutableDBOptions & db_options)1389   EnvOptions OptimizeForCompactionTableRead(
1390       const EnvOptions& env_options,
1391       const ImmutableDBOptions& db_options) const override {
1392     return target_->OptimizeForCompactionTableRead(env_options, db_options);
1393   }
GetFreeSpace(const std::string & path,uint64_t * diskfree)1394   Status GetFreeSpace(const std::string& path, uint64_t* diskfree) override {
1395     return target_->GetFreeSpace(path, diskfree);
1396   }
SanitizeEnvOptions(EnvOptions * env_opts)1397   void SanitizeEnvOptions(EnvOptions* env_opts) const override {
1398     target_->SanitizeEnvOptions(env_opts);
1399   }
1400 
1401  private:
1402   Env* target_;
1403 };
1404 
1405 class SequentialFileWrapper : public SequentialFile {
1406  public:
SequentialFileWrapper(SequentialFile * target)1407   explicit SequentialFileWrapper(SequentialFile* target) : target_(target) {}
1408 
Read(size_t n,Slice * result,char * scratch)1409   Status Read(size_t n, Slice* result, char* scratch) override {
1410     return target_->Read(n, result, scratch);
1411   }
Skip(uint64_t n)1412   Status Skip(uint64_t n) override { return target_->Skip(n); }
use_direct_io()1413   bool use_direct_io() const override { return target_->use_direct_io(); }
GetRequiredBufferAlignment()1414   size_t GetRequiredBufferAlignment() const override {
1415     return target_->GetRequiredBufferAlignment();
1416   }
InvalidateCache(size_t offset,size_t length)1417   Status InvalidateCache(size_t offset, size_t length) override {
1418     return target_->InvalidateCache(offset, length);
1419   }
PositionedRead(uint64_t offset,size_t n,Slice * result,char * scratch)1420   Status PositionedRead(uint64_t offset, size_t n, Slice* result,
1421                         char* scratch) override {
1422     return target_->PositionedRead(offset, n, result, scratch);
1423   }
1424 
1425  private:
1426   SequentialFile* target_;
1427 };
1428 
1429 class RandomAccessFileWrapper : public RandomAccessFile {
1430  public:
RandomAccessFileWrapper(RandomAccessFile * target)1431   explicit RandomAccessFileWrapper(RandomAccessFile* target)
1432       : target_(target) {}
1433 
Read(uint64_t offset,size_t n,Slice * result,char * scratch)1434   Status Read(uint64_t offset, size_t n, Slice* result,
1435               char* scratch) const override {
1436     return target_->Read(offset, n, result, scratch);
1437   }
MultiRead(ReadRequest * reqs,size_t num_reqs)1438   Status MultiRead(ReadRequest* reqs, size_t num_reqs) override {
1439     return target_->MultiRead(reqs, num_reqs);
1440   }
Prefetch(uint64_t offset,size_t n)1441   Status Prefetch(uint64_t offset, size_t n) override {
1442     return target_->Prefetch(offset, n);
1443   }
GetUniqueId(char * id,size_t max_size)1444   size_t GetUniqueId(char* id, size_t max_size) const override {
1445     return target_->GetUniqueId(id, max_size);
1446   }
Hint(AccessPattern pattern)1447   void Hint(AccessPattern pattern) override { target_->Hint(pattern); }
use_direct_io()1448   bool use_direct_io() const override { return target_->use_direct_io(); }
GetRequiredBufferAlignment()1449   size_t GetRequiredBufferAlignment() const override {
1450     return target_->GetRequiredBufferAlignment();
1451   }
InvalidateCache(size_t offset,size_t length)1452   Status InvalidateCache(size_t offset, size_t length) override {
1453     return target_->InvalidateCache(offset, length);
1454   }
1455 
1456  private:
1457   RandomAccessFile* target_;
1458 };
1459 
1460 class WritableFileWrapper : public WritableFile {
1461  public:
WritableFileWrapper(WritableFile * t)1462   explicit WritableFileWrapper(WritableFile* t) : target_(t) {}
1463 
Append(const Slice & data)1464   Status Append(const Slice& data) override { return target_->Append(data); }
PositionedAppend(const Slice & data,uint64_t offset)1465   Status PositionedAppend(const Slice& data, uint64_t offset) override {
1466     return target_->PositionedAppend(data, offset);
1467   }
Truncate(uint64_t size)1468   Status Truncate(uint64_t size) override { return target_->Truncate(size); }
Close()1469   Status Close() override { return target_->Close(); }
Flush()1470   Status Flush() override { return target_->Flush(); }
Sync()1471   Status Sync() override { return target_->Sync(); }
Fsync()1472   Status Fsync() override { return target_->Fsync(); }
IsSyncThreadSafe()1473   bool IsSyncThreadSafe() const override { return target_->IsSyncThreadSafe(); }
1474 
use_direct_io()1475   bool use_direct_io() const override { return target_->use_direct_io(); }
1476 
GetRequiredBufferAlignment()1477   size_t GetRequiredBufferAlignment() const override {
1478     return target_->GetRequiredBufferAlignment();
1479   }
1480 
SetIOPriority(Env::IOPriority pri)1481   void SetIOPriority(Env::IOPriority pri) override {
1482     target_->SetIOPriority(pri);
1483   }
1484 
GetIOPriority()1485   Env::IOPriority GetIOPriority() override { return target_->GetIOPriority(); }
1486 
SetWriteLifeTimeHint(Env::WriteLifeTimeHint hint)1487   void SetWriteLifeTimeHint(Env::WriteLifeTimeHint hint) override {
1488     target_->SetWriteLifeTimeHint(hint);
1489   }
1490 
GetWriteLifeTimeHint()1491   Env::WriteLifeTimeHint GetWriteLifeTimeHint() override {
1492     return target_->GetWriteLifeTimeHint();
1493   }
1494 
GetFileSize()1495   uint64_t GetFileSize() override { return target_->GetFileSize(); }
1496 
SetPreallocationBlockSize(size_t size)1497   void SetPreallocationBlockSize(size_t size) override {
1498     target_->SetPreallocationBlockSize(size);
1499   }
1500 
GetPreallocationStatus(size_t * block_size,size_t * last_allocated_block)1501   void GetPreallocationStatus(size_t* block_size,
1502                               size_t* last_allocated_block) override {
1503     target_->GetPreallocationStatus(block_size, last_allocated_block);
1504   }
1505 
GetUniqueId(char * id,size_t max_size)1506   size_t GetUniqueId(char* id, size_t max_size) const override {
1507     return target_->GetUniqueId(id, max_size);
1508   }
1509 
InvalidateCache(size_t offset,size_t length)1510   Status InvalidateCache(size_t offset, size_t length) override {
1511     return target_->InvalidateCache(offset, length);
1512   }
1513 
RangeSync(uint64_t offset,uint64_t nbytes)1514   Status RangeSync(uint64_t offset, uint64_t nbytes) override {
1515     return target_->RangeSync(offset, nbytes);
1516   }
1517 
PrepareWrite(size_t offset,size_t len)1518   void PrepareWrite(size_t offset, size_t len) override {
1519     target_->PrepareWrite(offset, len);
1520   }
1521 
Allocate(uint64_t offset,uint64_t len)1522   Status Allocate(uint64_t offset, uint64_t len) override {
1523     return target_->Allocate(offset, len);
1524   }
1525 
1526  private:
1527   WritableFile* target_;
1528 };
1529 
1530 class RandomRWFileWrapper : public RandomRWFile {
1531  public:
RandomRWFileWrapper(RandomRWFile * target)1532   explicit RandomRWFileWrapper(RandomRWFile* target) : target_(target) {}
1533 
use_direct_io()1534   bool use_direct_io() const override { return target_->use_direct_io(); }
GetRequiredBufferAlignment()1535   size_t GetRequiredBufferAlignment() const override {
1536     return target_->GetRequiredBufferAlignment();
1537   }
Write(uint64_t offset,const Slice & data)1538   Status Write(uint64_t offset, const Slice& data) override {
1539     return target_->Write(offset, data);
1540   }
Read(uint64_t offset,size_t n,Slice * result,char * scratch)1541   Status Read(uint64_t offset, size_t n, Slice* result,
1542               char* scratch) const override {
1543     return target_->Read(offset, n, result, scratch);
1544   }
Flush()1545   Status Flush() override { return target_->Flush(); }
Sync()1546   Status Sync() override { return target_->Sync(); }
Fsync()1547   Status Fsync() override { return target_->Fsync(); }
Close()1548   Status Close() override { return target_->Close(); }
1549 
1550  private:
1551   RandomRWFile* target_;
1552 };
1553 
1554 class DirectoryWrapper : public Directory {
1555  public:
DirectoryWrapper(Directory * target)1556   explicit DirectoryWrapper(Directory* target) : target_(target) {}
1557 
Fsync()1558   Status Fsync() override { return target_->Fsync(); }
GetUniqueId(char * id,size_t max_size)1559   size_t GetUniqueId(char* id, size_t max_size) const override {
1560     return target_->GetUniqueId(id, max_size);
1561   }
1562 
1563  private:
1564   Directory* target_;
1565 };
1566 
1567 class LoggerWrapper : public Logger {
1568  public:
LoggerWrapper(Logger * target)1569   explicit LoggerWrapper(Logger* target) : target_(target) {}
1570 
Close()1571   Status Close() override { return target_->Close(); }
LogHeader(const char * format,va_list ap)1572   void LogHeader(const char* format, va_list ap) override {
1573     return target_->LogHeader(format, ap);
1574   }
Logv(const char * format,va_list ap)1575   void Logv(const char* format, va_list ap) override {
1576     return target_->Logv(format, ap);
1577   }
Logv(const InfoLogLevel log_level,const char * format,va_list ap)1578   void Logv(const InfoLogLevel log_level, const char* format,
1579             va_list ap) override {
1580     return target_->Logv(log_level, format, ap);
1581   }
GetLogFileSize()1582   size_t GetLogFileSize() const override { return target_->GetLogFileSize(); }
Flush()1583   void Flush() override { return target_->Flush(); }
GetInfoLogLevel()1584   InfoLogLevel GetInfoLogLevel() const override {
1585     return target_->GetInfoLogLevel();
1586   }
SetInfoLogLevel(const InfoLogLevel log_level)1587   void SetInfoLogLevel(const InfoLogLevel log_level) override {
1588     return target_->SetInfoLogLevel(log_level);
1589   }
1590 
1591  private:
1592   Logger* target_;
1593 };
1594 
1595 // Returns a new environment that stores its data in memory and delegates
1596 // all non-file-storage tasks to base_env. The caller must delete the result
1597 // when it is no longer needed.
1598 // *base_env must remain live while the result is in use.
1599 Env* NewMemEnv(Env* base_env);
1600 
1601 // Returns a new environment that is used for HDFS environment.
1602 // This is a factory method for HdfsEnv declared in hdfs/env_hdfs.h
1603 Status NewHdfsEnv(Env** hdfs_env, const std::string& fsname);
1604 
1605 // Returns a new environment that measures function call times for filesystem
1606 // operations, reporting results to variables in PerfContext.
1607 // This is a factory method for TimedEnv defined in utilities/env_timed.cc.
1608 Env* NewTimedEnv(Env* base_env);
1609 
1610 // Returns an instance of logger that can be used for storing informational
1611 // messages.
1612 // This is a factory method for EnvLogger declared in logging/env_logging.h
1613 Status NewEnvLogger(const std::string& fname, Env* env,
1614                     std::shared_ptr<Logger>* result);
1615 
1616 std::unique_ptr<Env> NewCompositeEnv(std::shared_ptr<FileSystem> fs);
1617 
1618 }  // namespace ROCKSDB_NAMESPACE
1619