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