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