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