1 // Copyright (c) 2019-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
6 // A FileSystem is an interface used by the rocksdb implementation to access
7 // storage functionality like the filesystem etc. Callers
8 // may wish to provide a custom FileSystem object when opening a database to
9 // get fine gain control; e.g., to rate limit file system operations.
11 // All FileSystem implementations are safe for concurrent access from
12 // multiple threads without any external synchronization.
14 // WARNING: Since this is a new interface, it is expected that there will be
15 // some changes as storage systems are ported over.
28 #include "rocksdb/env.h"
29 #include "rocksdb/io_status.h"
30 #include "rocksdb/options.h"
31 #include "rocksdb/thread_status.h"
33 namespace ROCKSDB_NAMESPACE
{
37 class FSRandomAccessFile
;
39 class FSSequentialFile
;
43 struct ImmutableDBOptions
;
44 struct MutableDBOptions
;
47 using AccessPattern
= RandomAccessFile::AccessPattern
;
48 using FileAttributes
= Env::FileAttributes
;
50 // Priority of an IO request. This is a hint and does not guarantee any
52 // IO_LOW - Typically background reads/writes such as compaction/flush
53 // IO_HIGH - Typically user reads/synchronous WAL writes
54 enum class IOPriority
: uint8_t {
60 // Type of the data begin read/written. It can be passed down as a flag
61 // for the FileSystem implementation to optionally handle different types in
63 enum class IOType
: uint8_t {
75 // Per-request options that can be passed down to the FileSystem
76 // implementation. These are hints and are not necessarily guaranteed to be
77 // honored. More hints can be added here in the future to indicate things like
78 // storage media (HDD/SSD) to be used, replication level etc.
80 // Timeout for the operation in milliseconds
81 std::chrono::milliseconds timeout
;
83 // Priority - high or low
86 // Type of data being read/written
90 // File scope options that control how a file is opened/created and accessed
91 // while its open. We may add more options here in the future such as
92 // redundancy level, media to use etc.
93 struct FileOptions
: EnvOptions
{
94 // Embedded IOOptions to control the parameters for any IOs that need
95 // to be issued for the file open/creation
98 FileOptions() : EnvOptions() {}
100 FileOptions(const DBOptions
& opts
)
101 : EnvOptions(opts
) {}
103 FileOptions(const EnvOptions
& opts
)
104 : EnvOptions(opts
) {}
107 // A structure to pass back some debugging information from the FileSystem
108 // implementation to RocksDB in case of an IO error
109 struct IODebugContext
{
110 // file_path to be filled in by RocksDB in case of an error
111 std::string file_path
;
113 // A map of counter names to values - set by the FileSystem implementation
114 std::map
<std::string
, uint64_t> counters
;
116 // To be set by the FileSystem implementation
121 void AddCounter(std::string
& name
, uint64_t value
) {
122 counters
.emplace(name
, value
);
125 std::string
ToString() {
126 std::ostringstream ss
;
127 ss
<< file_path
<< ", ";
128 for (auto counter
: counters
) {
129 ss
<< counter
.first
<< " = " << counter
.second
<< ",";
136 // The FileSystem, FSSequentialFile, FSRandomAccessFile, FSWritableFile,
137 // FSRandomRWFileclass, and FSDIrectory classes define the interface between
138 // RocksDB and storage systems, such as Posix filesystems,
139 // remote filesystems etc.
140 // The interface allows for fine grained control of individual IO operations,
141 // such as setting a timeout, prioritization, hints on data placement,
142 // different handling based on type of IO etc.
143 // This is accomplished by passing an instance of IOOptions to every
144 // API call that can potentially perform IO. Additionally, each such API is
145 // passed a pointer to a IODebugContext structure that can be used by the
146 // storage system to include troubleshooting information. The return values
147 // of the APIs is of type IOStatus, which can indicate an error code/sub-code,
148 // as well as metadata about the error such as its scope and whether its
154 // No copying allowed
155 FileSystem(const FileSystem
&) = delete;
157 virtual ~FileSystem();
159 virtual const char* Name() const = 0;
161 static const char* Type() { return "FileSystem"; }
163 // Loads the FileSystem specified by the input value into the result
164 static Status
Load(const std::string
& value
,
165 std::shared_ptr
<FileSystem
>* result
);
167 // Return a default fie_system suitable for the current operating
168 // system. Sophisticated users may wish to provide their own Env
169 // implementation instead of relying on this default file_system
171 // The result of Default() belongs to rocksdb and must never be deleted.
172 static std::shared_ptr
<FileSystem
> Default();
174 // Create a brand new sequentially-readable file with the specified name.
175 // On success, stores a pointer to the new file in *result and returns OK.
176 // On failure stores nullptr in *result and returns non-OK. If the file does
177 // not exist, returns a non-OK status.
179 // The returned file will only be accessed by one thread at a time.
180 virtual IOStatus
NewSequentialFile(const std::string
& fname
,
181 const FileOptions
& file_opts
,
182 std::unique_ptr
<FSSequentialFile
>* result
,
183 IODebugContext
* dbg
) = 0;
185 // Create a brand new random access read-only file with the
186 // specified name. On success, stores a pointer to the new file in
187 // *result and returns OK. On failure stores nullptr in *result and
188 // returns non-OK. If the file does not exist, returns a non-OK
191 // The returned file may be concurrently accessed by multiple threads.
192 virtual IOStatus
NewRandomAccessFile(
193 const std::string
& fname
, const FileOptions
& file_opts
,
194 std::unique_ptr
<FSRandomAccessFile
>* result
,
195 IODebugContext
* dbg
) = 0;
196 // These values match Linux definition
197 // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/fcntl.h#n56
198 enum WriteLifeTimeHint
{
199 kWLTHNotSet
= 0, // No hint information set
200 kWLTHNone
, // No hints about write life time
201 kWLTHShort
, // Data written has a short life time
202 kWLTHMedium
, // Data written has a medium life time
203 kWLTHLong
, // Data written has a long life time
204 kWLTHExtreme
, // Data written has an extremely long life time
207 // Create an object that writes to a new file with the specified
208 // name. Deletes any existing file with the same name and creates a
209 // new file. On success, stores a pointer to the new file in
210 // *result and returns OK. On failure stores nullptr in *result and
213 // The returned file will only be accessed by one thread at a time.
214 virtual IOStatus
NewWritableFile(const std::string
& fname
,
215 const FileOptions
& file_opts
,
216 std::unique_ptr
<FSWritableFile
>* result
,
217 IODebugContext
* dbg
) = 0;
219 // Create an object that writes to a new file with the specified
220 // name. Deletes any existing file with the same name and creates a
221 // new file. On success, stores a pointer to the new file in
222 // *result and returns OK. On failure stores nullptr in *result and
225 // The returned file will only be accessed by one thread at a time.
226 virtual IOStatus
ReopenWritableFile(
227 const std::string
& /*fname*/, const FileOptions
& /*options*/,
228 std::unique_ptr
<FSWritableFile
>* /*result*/, IODebugContext
* /*dbg*/) {
229 return IOStatus::NotSupported();
232 // Reuse an existing file by renaming it and opening it as writable.
233 virtual IOStatus
ReuseWritableFile(const std::string
& fname
,
234 const std::string
& old_fname
,
235 const FileOptions
& file_opts
,
236 std::unique_ptr
<FSWritableFile
>* result
,
237 IODebugContext
* dbg
) = 0;
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.
243 // The returned file will only be accessed by one thread at a time.
244 virtual IOStatus
NewRandomRWFile(const std::string
& /*fname*/,
245 const FileOptions
& /*options*/,
246 std::unique_ptr
<FSRandomRWFile
>* /*result*/,
247 IODebugContext
* /*dbg*/) {
248 return IOStatus::NotSupported(
249 "RandomRWFile is not implemented in this FileSystem");
252 // Opens `fname` as a memory-mapped file for read and write (in-place updates
253 // only, i.e., no appends). On success, stores a raw buffer covering the whole
254 // file in `*result`. The file must exist prior to this call.
255 virtual IOStatus
NewMemoryMappedFileBuffer(
256 const std::string
& /*fname*/,
257 std::unique_ptr
<MemoryMappedFileBuffer
>* /*result*/) {
258 return IOStatus::NotSupported(
259 "MemoryMappedFileBuffer is not implemented in this FileSystem");
262 // Create an object that represents a directory. Will fail if directory
263 // doesn't exist. If the directory exists, it will open the directory
264 // and create a new Directory object.
266 // On success, stores a pointer to the new Directory in
267 // *result and returns OK. On failure stores nullptr in *result and
269 virtual IOStatus
NewDirectory(const std::string
& name
,
270 const IOOptions
& io_opts
,
271 std::unique_ptr
<FSDirectory
>* result
,
272 IODebugContext
* dbg
) = 0;
274 // Returns OK if the named file exists.
275 // NotFound if the named file does not exist,
276 // the calling process does not have permission to determine
277 // whether this file exists, or if the path is invalid.
278 // IOError if an IO Error was encountered
279 virtual IOStatus
FileExists(const std::string
& fname
,
280 const IOOptions
& options
,
281 IODebugContext
* dbg
) = 0;
283 // Store in *result the names of the children of the specified directory.
284 // The names are relative to "dir".
285 // Original contents of *results are dropped.
286 // Returns OK if "dir" exists and "*result" contains its children.
287 // NotFound if "dir" does not exist, the calling process does not have
288 // permission to access "dir", or if "dir" is invalid.
289 // IOError if an IO Error was encountered
290 virtual IOStatus
GetChildren(const std::string
& dir
, const IOOptions
& options
,
291 std::vector
<std::string
>* result
,
292 IODebugContext
* dbg
) = 0;
294 // Store in *result the attributes of the children of the specified directory.
295 // In case the implementation lists the directory prior to iterating the files
296 // and files are concurrently deleted, the deleted files will be omitted from
298 // The name attributes are relative to "dir".
299 // Original contents of *results are dropped.
300 // Returns OK if "dir" exists and "*result" contains its children.
301 // NotFound if "dir" does not exist, the calling process does not have
302 // permission to access "dir", or if "dir" is invalid.
303 // IOError if an IO Error was encountered
304 virtual IOStatus
GetChildrenFileAttributes(
305 const std::string
& dir
, const IOOptions
& options
,
306 std::vector
<FileAttributes
>* result
, IODebugContext
* dbg
) {
307 assert(result
!= nullptr);
308 std::vector
<std::string
> child_fnames
;
309 IOStatus s
= GetChildren(dir
, options
, &child_fnames
, dbg
);
313 result
->resize(child_fnames
.size());
314 size_t result_size
= 0;
315 for (size_t i
= 0; i
< child_fnames
.size(); ++i
) {
316 const std::string path
= dir
+ "/" + child_fnames
[i
];
317 if (!(s
= GetFileSize(path
, options
, &(*result
)[result_size
].size_bytes
,
320 if (FileExists(path
, options
, dbg
).IsNotFound()) {
321 // The file may have been deleted since we listed the directory
326 (*result
)[result_size
].name
= std::move(child_fnames
[i
]);
329 result
->resize(result_size
);
330 return IOStatus::OK();
333 // Delete the named file.
334 virtual IOStatus
DeleteFile(const std::string
& fname
,
335 const IOOptions
& options
,
336 IODebugContext
* dbg
) = 0;
338 // Truncate the named file to the specified size.
339 virtual IOStatus
Truncate(const std::string
& /*fname*/, size_t /*size*/,
340 const IOOptions
& /*options*/,
341 IODebugContext
* /*dbg*/) {
342 return IOStatus::NotSupported("Truncate is not supported for this FileSystem");
345 // Create the specified directory. Returns error if directory exists.
346 virtual IOStatus
CreateDir(const std::string
& dirname
,
347 const IOOptions
& options
, IODebugContext
* dbg
) = 0;
349 // Creates directory if missing. Return Ok if it exists, or successful in
351 virtual IOStatus
CreateDirIfMissing(const std::string
& dirname
,
352 const IOOptions
& options
,
353 IODebugContext
* dbg
) = 0;
355 // Delete the specified directory.
356 virtual IOStatus
DeleteDir(const std::string
& dirname
,
357 const IOOptions
& options
, IODebugContext
* dbg
) = 0;
359 // Store the size of fname in *file_size.
360 virtual IOStatus
GetFileSize(const std::string
& fname
,
361 const IOOptions
& options
, uint64_t* file_size
,
362 IODebugContext
* dbg
) = 0;
364 // Store the last modification time of fname in *file_mtime.
365 virtual IOStatus
GetFileModificationTime(const std::string
& fname
,
366 const IOOptions
& options
,
367 uint64_t* file_mtime
,
368 IODebugContext
* dbg
) = 0;
369 // Rename file src to target.
370 virtual IOStatus
RenameFile(const std::string
& src
, const std::string
& target
,
371 const IOOptions
& options
,
372 IODebugContext
* dbg
) = 0;
374 // Hard Link file src to target.
375 virtual IOStatus
LinkFile(const std::string
& /*src*/,
376 const std::string
& /*target*/,
377 const IOOptions
& /*options*/,
378 IODebugContext
* /*dbg*/) {
379 return IOStatus::NotSupported("LinkFile is not supported for this FileSystem");
382 virtual IOStatus
NumFileLinks(const std::string
& /*fname*/,
383 const IOOptions
& /*options*/,
384 uint64_t* /*count*/, IODebugContext
* /*dbg*/) {
385 return IOStatus::NotSupported(
386 "Getting number of file links is not supported for this FileSystem");
389 virtual IOStatus
AreFilesSame(const std::string
& /*first*/,
390 const std::string
& /*second*/,
391 const IOOptions
& /*options*/, bool* /*res*/,
392 IODebugContext
* /*dbg*/) {
393 return IOStatus::NotSupported("AreFilesSame is not supported for this FileSystem");
396 // Lock the specified file. Used to prevent concurrent access to
397 // the same db by multiple processes. On failure, stores nullptr in
398 // *lock and returns non-OK.
400 // On success, stores a pointer to the object that represents the
401 // acquired lock in *lock and returns OK. The caller should call
402 // UnlockFile(*lock) to release the lock. If the process exits,
403 // the lock will be automatically released.
405 // If somebody else already holds the lock, finishes immediately
406 // with a failure. I.e., this call does not wait for existing locks
409 // May create the named file if it does not already exist.
410 virtual IOStatus
LockFile(const std::string
& fname
, const IOOptions
& options
,
411 FileLock
** lock
, IODebugContext
* dbg
) = 0;
413 // Release the lock acquired by a previous successful call to LockFile.
414 // REQUIRES: lock was returned by a successful LockFile() call
415 // REQUIRES: lock has not already been unlocked.
416 virtual IOStatus
UnlockFile(FileLock
* lock
, const IOOptions
& options
,
417 IODebugContext
* dbg
) = 0;
419 // *path is set to a temporary directory that can be used for testing. It may
420 // or many not have just been created. The directory may or may not differ
421 // between runs of the same process, but subsequent calls will return the
423 virtual IOStatus
GetTestDirectory(const IOOptions
& options
, std::string
* path
,
424 IODebugContext
* dbg
) = 0;
426 // Create and returns a default logger (an instance of EnvLogger) for storing
427 // informational messages. Derived classes can overide to provide custom
429 virtual IOStatus
NewLogger(const std::string
& fname
, const IOOptions
& io_opts
,
430 std::shared_ptr
<Logger
>* result
,
431 IODebugContext
* dbg
) = 0;
433 // Get full directory name for this db.
434 virtual IOStatus
GetAbsolutePath(const std::string
& db_path
,
435 const IOOptions
& options
,
436 std::string
* output_path
,
437 IODebugContext
* dbg
) = 0;
439 // OptimizeForLogRead will create a new FileOptions object that is a copy of
440 // the FileOptions in the parameters, but is optimized for reading log files.
441 virtual FileOptions
OptimizeForLogRead(const FileOptions
& file_options
) const;
443 // OptimizeForManifestRead will create a new FileOptions object that is a copy
444 // of the FileOptions in the parameters, but is optimized for reading manifest
446 virtual FileOptions
OptimizeForManifestRead(
447 const FileOptions
& file_options
) const;
449 // OptimizeForLogWrite will create a new FileOptions object that is a copy of
450 // the FileOptions in the parameters, but is optimized for writing log files.
451 // Default implementation returns the copy of the same object.
452 virtual FileOptions
OptimizeForLogWrite(const FileOptions
& file_options
,
453 const DBOptions
& db_options
) const;
455 // OptimizeForManifestWrite will create a new FileOptions object that is a
456 // copy of the FileOptions in the parameters, but is optimized for writing
457 // manifest files. Default implementation returns the copy of the same
459 virtual FileOptions
OptimizeForManifestWrite(
460 const FileOptions
& file_options
) const;
462 // OptimizeForCompactionTableWrite will create a new FileOptions object that
463 // is a copy of the FileOptions in the parameters, but is optimized for
464 // writing table files.
465 virtual FileOptions
OptimizeForCompactionTableWrite(
466 const FileOptions
& file_options
,
467 const ImmutableDBOptions
& immutable_ops
) const;
469 // OptimizeForCompactionTableRead will create a new FileOptions object that
470 // is a copy of the FileOptions in the parameters, but is optimized for
471 // reading table files.
472 virtual FileOptions
OptimizeForCompactionTableRead(
473 const FileOptions
& file_options
,
474 const ImmutableDBOptions
& db_options
) const;
476 // This seems to clash with a macro on Windows, so #undef it here
481 // Get the amount of free disk space
482 virtual IOStatus
GetFreeSpace(const std::string
& /*path*/,
483 const IOOptions
& /*options*/,
484 uint64_t* /*diskfree*/,
485 IODebugContext
* /*dbg*/) {
486 return IOStatus::NotSupported();
489 // If you're adding methods here, remember to add them to EnvWrapper too.
492 void operator=(const FileSystem
&);
495 // A file abstraction for reading sequentially through a file
496 class FSSequentialFile
{
498 FSSequentialFile() {}
500 virtual ~FSSequentialFile() {}
502 // Read up to "n" bytes from the file. "scratch[0..n-1]" may be
503 // written by this routine. Sets "*result" to the data that was
504 // read (including if fewer than "n" bytes were successfully read).
505 // May set "*result" to point at data in "scratch[0..n-1]", so
506 // "scratch[0..n-1]" must be live when "*result" is used.
507 // If an error was encountered, returns a non-OK status.
509 // REQUIRES: External synchronization
510 virtual IOStatus
Read(size_t n
, const IOOptions
& options
, Slice
* result
,
511 char* scratch
, IODebugContext
* dbg
) = 0;
513 // Skip "n" bytes from the file. This is guaranteed to be no
514 // slower that reading the same data, but may be faster.
516 // If end of file is reached, skipping will stop at the end of the
517 // file, and Skip will return OK.
519 // REQUIRES: External synchronization
520 virtual IOStatus
Skip(uint64_t n
) = 0;
522 // Indicates the upper layers if the current SequentialFile implementation
524 virtual bool use_direct_io() const { return false; }
526 // Use the returned alignment value to allocate
527 // aligned buffer for Direct I/O
528 virtual size_t GetRequiredBufferAlignment() const { return kDefaultPageSize
; }
530 // Remove any kind of caching of data from the offset to offset+length
531 // of this file. If the length is 0, then it refers to the end of file.
532 // If the system is not caching the file contents, then this is a noop.
533 virtual IOStatus
InvalidateCache(size_t /*offset*/, size_t /*length*/) {
534 return IOStatus::NotSupported("InvalidateCache not supported.");
537 // Positioned Read for direct I/O
538 // If Direct I/O enabled, offset, n, and scratch should be properly aligned
539 virtual IOStatus
PositionedRead(uint64_t /*offset*/, size_t /*n*/,
540 const IOOptions
& /*options*/,
541 Slice
* /*result*/, char* /*scratch*/,
542 IODebugContext
* /*dbg*/) {
543 return IOStatus::NotSupported();
546 // If you're adding methods here, remember to add them to
547 // SequentialFileWrapper too.
550 // A read IO request structure for use in MultiRead
551 struct FSReadRequest
{
552 // File offset in bytes
555 // Length to read in bytes
558 // A buffer that MultiRead() can optionally place data in. It can
559 // ignore this and allocate its own buffer
562 // Output parameter set by MultiRead() to point to the data buffer, and
563 // the number of valid bytes
570 // A file abstraction for randomly reading the contents of a file.
571 class FSRandomAccessFile
{
573 FSRandomAccessFile() {}
575 virtual ~FSRandomAccessFile() {}
577 // Read up to "n" bytes from the file starting at "offset".
578 // "scratch[0..n-1]" may be written by this routine. Sets "*result"
579 // to the data that was read (including if fewer than "n" bytes were
580 // successfully read). May set "*result" to point at data in
581 // "scratch[0..n-1]", so "scratch[0..n-1]" must be live when
582 // "*result" is used. If an error was encountered, returns a non-OK
585 // Safe for concurrent use by multiple threads.
586 // If Direct I/O enabled, offset, n, and scratch should be aligned properly.
587 virtual IOStatus
Read(uint64_t offset
, size_t n
, const IOOptions
& options
,
588 Slice
* result
, char* scratch
,
589 IODebugContext
* dbg
) const = 0;
591 // Readahead the file starting from offset by n bytes for caching.
592 virtual IOStatus
Prefetch(uint64_t /*offset*/, size_t /*n*/,
593 const IOOptions
& /*options*/,
594 IODebugContext
* /*dbg*/) {
595 return IOStatus::OK();
598 // Read a bunch of blocks as described by reqs. The blocks can
599 // optionally be read in parallel. This is a synchronous call, i.e it
600 // should return after all reads have completed. The reads will be
601 // non-overlapping. If the function return Status is not ok, status of
602 // individual requests will be ignored and return status will be assumed
603 // for all read requests. The function return status is only meant for any
604 // any errors that occur before even processing specific read requests
605 virtual IOStatus
MultiRead(FSReadRequest
* reqs
, size_t num_reqs
,
606 const IOOptions
& options
, IODebugContext
* dbg
) {
607 assert(reqs
!= nullptr);
608 for (size_t i
= 0; i
< num_reqs
; ++i
) {
609 FSReadRequest
& req
= reqs
[i
];
611 Read(req
.offset
, req
.len
, options
, &req
.result
, req
.scratch
, dbg
);
613 return IOStatus::OK();
616 // Tries to get an unique ID for this file that will be the same each time
617 // the file is opened (and will stay the same while the file is open).
618 // Furthermore, it tries to make this ID at most "max_size" bytes. If such an
619 // ID can be created this function returns the length of the ID and places it
620 // in "id"; otherwise, this function returns 0, in which case "id"
621 // may not have been modified.
623 // This function guarantees, for IDs from a given environment, two unique ids
624 // cannot be made equal to each other by adding arbitrary bytes to one of
625 // them. That is, no unique ID is the prefix of another.
627 // This function guarantees that the returned ID will not be interpretable as
630 // Note: these IDs are only valid for the duration of the process.
631 virtual size_t GetUniqueId(char* /*id*/, size_t /*max_size*/) const {
632 return 0; // Default implementation to prevent issues with backwards
636 enum AccessPattern
{ kNormal
, kRandom
, kSequential
, kWillNeed
, kWontNeed
};
638 virtual void Hint(AccessPattern
/*pattern*/) {}
640 // Indicates the upper layers if the current RandomAccessFile implementation
642 virtual bool use_direct_io() const { return false; }
644 // Use the returned alignment value to allocate
645 // aligned buffer for Direct I/O
646 virtual size_t GetRequiredBufferAlignment() const { return kDefaultPageSize
; }
648 // Remove any kind of caching of data from the offset to offset+length
649 // of this file. If the length is 0, then it refers to the end of file.
650 // If the system is not caching the file contents, then this is a noop.
651 virtual IOStatus
InvalidateCache(size_t /*offset*/, size_t /*length*/) {
652 return IOStatus::NotSupported("InvalidateCache not supported.");
655 // If you're adding methods here, remember to add them to
656 // RandomAccessFileWrapper too.
659 // A file abstraction for sequential writing. The implementation
660 // must provide buffering since callers may append small fragments
661 // at a time to the file.
662 class FSWritableFile
{
665 : last_preallocated_block_(0),
666 preallocation_block_size_(0),
667 io_priority_(Env::IO_TOTAL
),
668 write_hint_(Env::WLTH_NOT_SET
),
669 strict_bytes_per_sync_(false) {}
671 explicit FSWritableFile(const FileOptions
& options
)
672 : last_preallocated_block_(0),
673 preallocation_block_size_(0),
674 io_priority_(Env::IO_TOTAL
),
675 write_hint_(Env::WLTH_NOT_SET
),
676 strict_bytes_per_sync_(options
.strict_bytes_per_sync
) {}
678 virtual ~FSWritableFile() {}
680 // Append data to the end of the file
681 // Note: A WriteabelFile object must support either Append or
682 // PositionedAppend, so the users cannot mix the two.
683 virtual IOStatus
Append(const Slice
& data
, const IOOptions
& options
,
684 IODebugContext
* dbg
) = 0;
686 // PositionedAppend data to the specified offset. The new EOF after append
687 // must be larger than the previous EOF. This is to be used when writes are
688 // not backed by OS buffers and hence has to always start from the start of
689 // the sector. The implementation thus needs to also rewrite the last
691 // Note: PositionAppend does not guarantee moving the file offset after the
692 // write. A WritableFile object must support either Append or
693 // PositionedAppend, so the users cannot mix the two.
695 // PositionedAppend() can only happen on the page/sector boundaries. For that
696 // reason, if the last write was an incomplete sector we still need to rewind
697 // back to the nearest sector/page and rewrite the portion of it with whatever
698 // we need to add. We need to keep where we stop writing.
700 // PositionedAppend() can only write whole sectors. For that reason we have to
701 // pad with zeros for the last write and trim the file when closing according
702 // to the position we keep in the previous step.
704 // PositionedAppend() requires aligned buffer to be passed in. The alignment
705 // required is queried via GetRequiredBufferAlignment()
706 virtual IOStatus
PositionedAppend(const Slice
& /* data */,
707 uint64_t /* offset */,
708 const IOOptions
& /*options*/,
709 IODebugContext
* /*dbg*/) {
710 return IOStatus::NotSupported();
713 // Truncate is necessary to trim the file to the correct size
714 // before closing. It is not always possible to keep track of the file
715 // size due to whole pages writes. The behavior is undefined if called
716 // with other writes to follow.
717 virtual IOStatus
Truncate(uint64_t /*size*/, const IOOptions
& /*options*/,
718 IODebugContext
* /*dbg*/) {
719 return IOStatus::OK();
721 virtual IOStatus
Close(const IOOptions
& options
, IODebugContext
* dbg
) = 0;
722 virtual IOStatus
Flush(const IOOptions
& options
, IODebugContext
* dbg
) = 0;
723 virtual IOStatus
Sync(const IOOptions
& options
,
724 IODebugContext
* dbg
) = 0; // sync data
727 * Sync data and/or metadata as well.
728 * By default, sync only data.
729 * Override this method for environments where we need to sync
732 virtual IOStatus
Fsync(const IOOptions
& options
, IODebugContext
* dbg
) {
733 return Sync(options
, dbg
);
736 // true if Sync() and Fsync() are safe to call concurrently with Append()
738 virtual bool IsSyncThreadSafe() const { return false; }
740 // Indicates the upper layers if the current WritableFile implementation
742 virtual bool use_direct_io() const { return false; }
744 // Use the returned alignment value to allocate
745 // aligned buffer for Direct I/O
746 virtual size_t GetRequiredBufferAlignment() const { return kDefaultPageSize
; }
748 virtual void SetWriteLifeTimeHint(Env::WriteLifeTimeHint hint
) {
752 virtual void SetIOPriority(Env::IOPriority pri
) { io_priority_
= pri
; }
754 virtual Env::IOPriority
GetIOPriority() { return io_priority_
; }
756 virtual Env::WriteLifeTimeHint
GetWriteLifeTimeHint() { return write_hint_
; }
758 * Get the size of valid data in the file.
760 virtual uint64_t GetFileSize(const IOOptions
& /*options*/,
761 IODebugContext
* /*dbg*/) {
766 * Get and set the default pre-allocation block size for writes to
767 * this file. If non-zero, then Allocate will be used to extend the
768 * underlying storage of a file (generally via fallocate) if the Env
769 * instance supports it.
771 virtual void SetPreallocationBlockSize(size_t size
) {
772 preallocation_block_size_
= size
;
775 virtual void GetPreallocationStatus(size_t* block_size
,
776 size_t* last_allocated_block
) {
777 *last_allocated_block
= last_preallocated_block_
;
778 *block_size
= preallocation_block_size_
;
781 // For documentation, refer to RandomAccessFile::GetUniqueId()
782 virtual size_t GetUniqueId(char* /*id*/, size_t /*max_size*/) const {
783 return 0; // Default implementation to prevent issues with backwards
786 // Remove any kind of caching of data from the offset to offset+length
787 // of this file. If the length is 0, then it refers to the end of file.
788 // If the system is not caching the file contents, then this is a noop.
789 // This call has no effect on dirty pages in the cache.
790 virtual IOStatus
InvalidateCache(size_t /*offset*/, size_t /*length*/) {
791 return IOStatus::NotSupported("InvalidateCache not supported.");
794 // Sync a file range with disk.
795 // offset is the starting byte of the file range to be synchronized.
796 // nbytes specifies the length of the range to be synchronized.
797 // This asks the OS to initiate flushing the cached data to disk,
798 // without waiting for completion.
799 // Default implementation does nothing.
800 virtual IOStatus
RangeSync(uint64_t /*offset*/, uint64_t /*nbytes*/,
801 const IOOptions
& options
, IODebugContext
* dbg
) {
802 if (strict_bytes_per_sync_
) {
803 return Sync(options
, dbg
);
805 return IOStatus::OK();
808 // PrepareWrite performs any necessary preparation for a write
809 // before the write actually occurs. This allows for pre-allocation
810 // of space on devices where it can result in less file
811 // fragmentation and/or less waste from over-zealous filesystem
813 virtual void PrepareWrite(size_t offset
, size_t len
, const IOOptions
& options
,
814 IODebugContext
* dbg
) {
815 if (preallocation_block_size_
== 0) {
818 // If this write would cross one or more preallocation blocks,
819 // determine what the last preallocation block necessary to
820 // cover this write would be and Allocate to that point.
821 const auto block_size
= preallocation_block_size_
;
822 size_t new_last_preallocated_block
=
823 (offset
+ len
+ block_size
- 1) / block_size
;
824 if (new_last_preallocated_block
> last_preallocated_block_
) {
825 size_t num_spanned_blocks
=
826 new_last_preallocated_block
- last_preallocated_block_
;
827 Allocate(block_size
* last_preallocated_block_
,
828 block_size
* num_spanned_blocks
, options
, dbg
);
829 last_preallocated_block_
= new_last_preallocated_block
;
833 // Pre-allocates space for a file.
834 virtual IOStatus
Allocate(uint64_t /*offset*/, uint64_t /*len*/,
835 const IOOptions
& /*options*/,
836 IODebugContext
* /*dbg*/) {
837 return IOStatus::OK();
840 // If you're adding methods here, remember to add them to
841 // WritableFileWrapper too.
844 size_t preallocation_block_size() { return preallocation_block_size_
; }
847 size_t last_preallocated_block_
;
848 size_t preallocation_block_size_
;
849 // No copying allowed
850 FSWritableFile(const FSWritableFile
&);
851 void operator=(const FSWritableFile
&);
854 Env::IOPriority io_priority_
;
855 Env::WriteLifeTimeHint write_hint_
;
856 const bool strict_bytes_per_sync_
;
859 // A file abstraction for random reading and writing.
860 class FSRandomRWFile
{
864 virtual ~FSRandomRWFile() {}
866 // Indicates if the class makes use of direct I/O
867 // If false you must pass aligned buffer to Write()
868 virtual bool use_direct_io() const { return false; }
870 // Use the returned alignment value to allocate
871 // aligned buffer for Direct I/O
872 virtual size_t GetRequiredBufferAlignment() const { return kDefaultPageSize
; }
874 // Write bytes in `data` at offset `offset`, Returns Status::OK() on success.
875 // Pass aligned buffer when use_direct_io() returns true.
876 virtual IOStatus
Write(uint64_t offset
, const Slice
& data
,
877 const IOOptions
& options
, IODebugContext
* dbg
) = 0;
879 // Read up to `n` bytes starting from offset `offset` and store them in
880 // result, provided `scratch` size should be at least `n`.
881 // Returns Status::OK() on success.
882 virtual IOStatus
Read(uint64_t offset
, size_t n
, const IOOptions
& options
,
883 Slice
* result
, char* scratch
,
884 IODebugContext
* dbg
) const = 0;
886 virtual IOStatus
Flush(const IOOptions
& options
, IODebugContext
* dbg
) = 0;
888 virtual IOStatus
Sync(const IOOptions
& options
, IODebugContext
* dbg
) = 0;
890 virtual IOStatus
Fsync(const IOOptions
& options
, IODebugContext
* dbg
) {
891 return Sync(options
, dbg
);
894 virtual IOStatus
Close(const IOOptions
& options
, IODebugContext
* dbg
) = 0;
896 // If you're adding methods here, remember to add them to
897 // RandomRWFileWrapper too.
899 // No copying allowed
900 FSRandomRWFile(const RandomRWFile
&) = delete;
901 FSRandomRWFile
& operator=(const RandomRWFile
&) = delete;
904 // MemoryMappedFileBuffer object represents a memory-mapped file's raw buffer.
905 // Subclasses should release the mapping upon destruction.
906 class FSMemoryMappedFileBuffer
{
908 FSMemoryMappedFileBuffer(void* _base
, size_t _length
)
909 : base_(_base
), length_(_length
) {}
911 virtual ~FSMemoryMappedFileBuffer() = 0;
913 // We do not want to unmap this twice. We can make this class
914 // movable if desired, however, since
915 FSMemoryMappedFileBuffer(const FSMemoryMappedFileBuffer
&) = delete;
916 FSMemoryMappedFileBuffer
& operator=(const FSMemoryMappedFileBuffer
&) = delete;
918 void* GetBase() const { return base_
; }
919 size_t GetLen() const { return length_
; }
923 const size_t length_
;
926 // Directory object represents collection of files and implements
927 // filesystem operations that can be executed on directories.
930 virtual ~FSDirectory() {}
931 // Fsync directory. Can be called concurrently from multiple threads.
932 virtual IOStatus
Fsync(const IOOptions
& options
, IODebugContext
* dbg
) = 0;
934 virtual size_t GetUniqueId(char* /*id*/, size_t /*max_size*/) const {
938 // If you're adding methods here, remember to add them to
939 // DirectoryWrapper too.
942 // Below are helpers for wrapping most of the classes in this file.
943 // They forward all calls to another instance of the class.
944 // Useful when wrapping the default implementations.
945 // Typical usage is to inherit your wrapper from *Wrapper, e.g.:
947 // class MySequentialFileWrapper : public
948 // ROCKSDB_NAMESPACE::FSSequentialFileWrapper {
950 // MySequentialFileWrapper(ROCKSDB_NAMESPACE::FSSequentialFile* target):
951 // ROCKSDB_NAMESPACE::FSSequentialFileWrapper(target) {}
952 // Status Read(size_t n, FileSystem::IOOptions& options, Slice* result,
953 // char* scratch, FileSystem::IODebugContext* dbg) override {
954 // cout << "Doing a read of size " << n << "!" << endl;
955 // return ROCKSDB_NAMESPACE::FSSequentialFileWrapper::Read(n, options,
959 // // All other methods are forwarded to target_ automatically.
962 // This is often more convenient than inheriting the class directly because
963 // (a) Don't have to override and forward all methods - the Wrapper will
964 // forward everything you're not explicitly overriding.
965 // (b) Don't need to update the wrapper when more methods are added to the
966 // rocksdb class. Unless you actually want to override the behavior.
967 // (And unless rocksdb people forgot to update the *Wrapper class.)
969 // An implementation of Env that forwards all calls to another Env.
970 // May be useful to clients who wish to override just part of the
971 // functionality of another Env.
972 class FileSystemWrapper
: public FileSystem
{
974 // Initialize an EnvWrapper that delegates all calls to *t
975 explicit FileSystemWrapper(FileSystem
* t
) : target_(t
) {}
976 ~FileSystemWrapper() override
{}
978 // Return the target to which this Env forwards all calls
979 FileSystem
* target() const { return target_
; }
981 // The following text is boilerplate that forwards all methods to target()
982 IOStatus
NewSequentialFile(const std::string
& f
,
983 const FileOptions
& file_opts
,
984 std::unique_ptr
<FSSequentialFile
>* r
,
985 IODebugContext
* dbg
) override
{
986 return target_
->NewSequentialFile(f
, file_opts
, r
, dbg
);
988 IOStatus
NewRandomAccessFile(const std::string
& f
,
989 const FileOptions
& file_opts
,
990 std::unique_ptr
<FSRandomAccessFile
>* r
,
991 IODebugContext
* dbg
) override
{
992 return target_
->NewRandomAccessFile(f
, file_opts
, r
, dbg
);
994 IOStatus
NewWritableFile(const std::string
& f
, const FileOptions
& file_opts
,
995 std::unique_ptr
<FSWritableFile
>* r
,
996 IODebugContext
* dbg
) override
{
997 return target_
->NewWritableFile(f
, file_opts
, r
, dbg
);
999 IOStatus
ReopenWritableFile(const std::string
& fname
,
1000 const FileOptions
& file_opts
,
1001 std::unique_ptr
<FSWritableFile
>* result
,
1002 IODebugContext
* dbg
) override
{
1003 return target_
->ReopenWritableFile(fname
, file_opts
, result
, dbg
);
1005 IOStatus
ReuseWritableFile(const std::string
& fname
,
1006 const std::string
& old_fname
,
1007 const FileOptions
& file_opts
,
1008 std::unique_ptr
<FSWritableFile
>* r
,
1009 IODebugContext
* dbg
) override
{
1010 return target_
->ReuseWritableFile(fname
, old_fname
, file_opts
, r
,
1013 IOStatus
NewRandomRWFile(const std::string
& fname
,
1014 const FileOptions
& file_opts
,
1015 std::unique_ptr
<FSRandomRWFile
>* result
,
1016 IODebugContext
* dbg
) override
{
1017 return target_
->NewRandomRWFile(fname
, file_opts
, result
, dbg
);
1019 IOStatus
NewMemoryMappedFileBuffer(
1020 const std::string
& fname
,
1021 std::unique_ptr
<MemoryMappedFileBuffer
>* result
) override
{
1022 return target_
->NewMemoryMappedFileBuffer(fname
, result
);
1024 IOStatus
NewDirectory(const std::string
& name
, const IOOptions
& io_opts
,
1025 std::unique_ptr
<FSDirectory
>* result
,
1026 IODebugContext
* dbg
) override
{
1027 return target_
->NewDirectory(name
, io_opts
, result
, dbg
);
1029 IOStatus
FileExists(const std::string
& f
, const IOOptions
& io_opts
,
1030 IODebugContext
* dbg
) override
{
1031 return target_
->FileExists(f
, io_opts
, dbg
);
1033 IOStatus
GetChildren(const std::string
& dir
, const IOOptions
& io_opts
,
1034 std::vector
<std::string
>* r
,
1035 IODebugContext
* dbg
) override
{
1036 return target_
->GetChildren(dir
, io_opts
, r
, dbg
);
1038 IOStatus
GetChildrenFileAttributes(const std::string
& dir
,
1039 const IOOptions
& options
,
1040 std::vector
<FileAttributes
>* result
,
1041 IODebugContext
* dbg
) override
{
1042 return target_
->GetChildrenFileAttributes(dir
, options
, result
, dbg
);
1044 IOStatus
DeleteFile(const std::string
& f
, const IOOptions
& options
,
1045 IODebugContext
* dbg
) override
{
1046 return target_
->DeleteFile(f
, options
, dbg
);
1048 IOStatus
Truncate(const std::string
& fname
, size_t size
,
1049 const IOOptions
& options
, IODebugContext
* dbg
) override
{
1050 return target_
->Truncate(fname
, size
, options
, dbg
);
1052 IOStatus
CreateDir(const std::string
& d
, const IOOptions
& options
,
1053 IODebugContext
* dbg
) override
{
1054 return target_
->CreateDir(d
, options
, dbg
);
1056 IOStatus
CreateDirIfMissing(const std::string
& d
, const IOOptions
& options
,
1057 IODebugContext
* dbg
) override
{
1058 return target_
->CreateDirIfMissing(d
, options
, dbg
);
1060 IOStatus
DeleteDir(const std::string
& d
, const IOOptions
& options
,
1061 IODebugContext
* dbg
) override
{
1062 return target_
->DeleteDir(d
, options
, dbg
);
1064 IOStatus
GetFileSize(const std::string
& f
, const IOOptions
& options
,
1065 uint64_t* s
, IODebugContext
* dbg
) override
{
1066 return target_
->GetFileSize(f
, options
, s
, dbg
);
1069 IOStatus
GetFileModificationTime(const std::string
& fname
,
1070 const IOOptions
& options
,
1071 uint64_t* file_mtime
,
1072 IODebugContext
* dbg
) override
{
1073 return target_
->GetFileModificationTime(fname
, options
, file_mtime
, dbg
);
1076 IOStatus
GetAbsolutePath(const std::string
& db_path
, const IOOptions
& options
,
1077 std::string
* output_path
,
1078 IODebugContext
* dbg
) override
{
1079 return target_
->GetAbsolutePath(db_path
, options
, output_path
, dbg
);
1082 IOStatus
RenameFile(const std::string
& s
, const std::string
& t
,
1083 const IOOptions
& options
, IODebugContext
* dbg
) override
{
1084 return target_
->RenameFile(s
, t
, options
, dbg
);
1087 IOStatus
LinkFile(const std::string
& s
, const std::string
& t
,
1088 const IOOptions
& options
, IODebugContext
* dbg
) override
{
1089 return target_
->LinkFile(s
, t
, options
, dbg
);
1092 IOStatus
NumFileLinks(const std::string
& fname
, const IOOptions
& options
,
1093 uint64_t* count
, IODebugContext
* dbg
) override
{
1094 return target_
->NumFileLinks(fname
, options
, count
, dbg
);
1097 IOStatus
AreFilesSame(const std::string
& first
, const std::string
& second
,
1098 const IOOptions
& options
, bool* res
,
1099 IODebugContext
* dbg
) override
{
1100 return target_
->AreFilesSame(first
, second
, options
, res
, dbg
);
1103 IOStatus
LockFile(const std::string
& f
, const IOOptions
& options
,
1104 FileLock
** l
, IODebugContext
* dbg
) override
{
1105 return target_
->LockFile(f
, options
, l
, dbg
);
1108 IOStatus
UnlockFile(FileLock
* l
, const IOOptions
& options
,
1109 IODebugContext
* dbg
) override
{
1110 return target_
->UnlockFile(l
, options
, dbg
);
1113 IOStatus
GetTestDirectory(const IOOptions
& options
, std::string
* path
,
1114 IODebugContext
* dbg
) override
{
1115 return target_
->GetTestDirectory(options
, path
, dbg
);
1117 IOStatus
NewLogger(const std::string
& fname
, const IOOptions
& options
,
1118 std::shared_ptr
<Logger
>* result
,
1119 IODebugContext
* dbg
) override
{
1120 return target_
->NewLogger(fname
, options
, result
, dbg
);
1123 FileOptions
OptimizeForLogRead(
1124 const FileOptions
& file_options
) const override
{
1125 return target_
->OptimizeForLogRead(file_options
);
1127 FileOptions
OptimizeForManifestRead(
1128 const FileOptions
& file_options
) const override
{
1129 return target_
->OptimizeForManifestRead(file_options
);
1131 FileOptions
OptimizeForLogWrite(const FileOptions
& file_options
,
1132 const DBOptions
& db_options
) const override
{
1133 return target_
->OptimizeForLogWrite(file_options
, db_options
);
1135 FileOptions
OptimizeForManifestWrite(
1136 const FileOptions
& file_options
) const override
{
1137 return target_
->OptimizeForManifestWrite(file_options
);
1139 FileOptions
OptimizeForCompactionTableWrite(
1140 const FileOptions
& file_options
,
1141 const ImmutableDBOptions
& immutable_ops
) const override
{
1142 return target_
->OptimizeForCompactionTableWrite(file_options
,
1145 FileOptions
OptimizeForCompactionTableRead(
1146 const FileOptions
& file_options
,
1147 const ImmutableDBOptions
& db_options
) const override
{
1148 return target_
->OptimizeForCompactionTableRead(file_options
, db_options
);
1150 IOStatus
GetFreeSpace(const std::string
& path
, const IOOptions
& options
,
1151 uint64_t* diskfree
, IODebugContext
* dbg
) override
{
1152 return target_
->GetFreeSpace(path
, options
, diskfree
, dbg
);
1156 FileSystem
* target_
;
1159 class FSSequentialFileWrapper
: public FSSequentialFile
{
1161 explicit FSSequentialFileWrapper(FSSequentialFile
* target
)
1162 : target_(target
) {}
1164 IOStatus
Read(size_t n
, const IOOptions
& options
, Slice
* result
,
1165 char* scratch
, IODebugContext
* dbg
) override
{
1166 return target_
->Read(n
, options
, result
, scratch
, dbg
);
1168 IOStatus
Skip(uint64_t n
) override
{ return target_
->Skip(n
); }
1169 bool use_direct_io() const override
{ return target_
->use_direct_io(); }
1170 size_t GetRequiredBufferAlignment() const override
{
1171 return target_
->GetRequiredBufferAlignment();
1173 IOStatus
InvalidateCache(size_t offset
, size_t length
) override
{
1174 return target_
->InvalidateCache(offset
, length
);
1176 IOStatus
PositionedRead(uint64_t offset
, size_t n
, const IOOptions
& options
,
1177 Slice
* result
, char* scratch
,
1178 IODebugContext
* dbg
) override
{
1179 return target_
->PositionedRead(offset
, n
, options
, result
, scratch
, dbg
);
1183 FSSequentialFile
* target_
;
1186 class FSRandomAccessFileWrapper
: public FSRandomAccessFile
{
1188 explicit FSRandomAccessFileWrapper(FSRandomAccessFile
* target
)
1189 : target_(target
) {}
1191 IOStatus
Read(uint64_t offset
, size_t n
, const IOOptions
& options
,
1192 Slice
* result
, char* scratch
,
1193 IODebugContext
* dbg
) const override
{
1194 return target_
->Read(offset
, n
, options
, result
, scratch
, dbg
);
1196 IOStatus
MultiRead(FSReadRequest
* reqs
, size_t num_reqs
,
1197 const IOOptions
& options
, IODebugContext
* dbg
) override
{
1198 return target_
->MultiRead(reqs
, num_reqs
, options
, dbg
);
1200 IOStatus
Prefetch(uint64_t offset
, size_t n
, const IOOptions
& options
,
1201 IODebugContext
* dbg
) override
{
1202 return target_
->Prefetch(offset
, n
, options
, dbg
);
1204 size_t GetUniqueId(char* id
, size_t max_size
) const override
{
1205 return target_
->GetUniqueId(id
, max_size
);
1207 void Hint(AccessPattern pattern
) override
{ target_
->Hint(pattern
); }
1208 bool use_direct_io() const override
{ return target_
->use_direct_io(); }
1209 size_t GetRequiredBufferAlignment() const override
{
1210 return target_
->GetRequiredBufferAlignment();
1212 IOStatus
InvalidateCache(size_t offset
, size_t length
) override
{
1213 return target_
->InvalidateCache(offset
, length
);
1217 FSRandomAccessFile
* target_
;
1220 class FSWritableFileWrapper
: public FSWritableFile
{
1222 explicit FSWritableFileWrapper(FSWritableFile
* t
) : target_(t
) {}
1224 IOStatus
Append(const Slice
& data
, const IOOptions
& options
,
1225 IODebugContext
* dbg
) override
{
1226 return target_
->Append(data
, options
, dbg
);
1228 IOStatus
PositionedAppend(const Slice
& data
, uint64_t offset
,
1229 const IOOptions
& options
,
1230 IODebugContext
* dbg
) override
{
1231 return target_
->PositionedAppend(data
, offset
, options
, dbg
);
1233 IOStatus
Truncate(uint64_t size
, const IOOptions
& options
,
1234 IODebugContext
* dbg
) override
{
1235 return target_
->Truncate(size
, options
, dbg
);
1237 IOStatus
Close(const IOOptions
& options
, IODebugContext
* dbg
) override
{
1238 return target_
->Close(options
, dbg
);
1240 IOStatus
Flush(const IOOptions
& options
, IODebugContext
* dbg
) override
{
1241 return target_
->Flush(options
, dbg
);
1243 IOStatus
Sync(const IOOptions
& options
, IODebugContext
* dbg
) override
{
1244 return target_
->Sync(options
, dbg
);
1246 IOStatus
Fsync(const IOOptions
& options
, IODebugContext
* dbg
) override
{
1247 return target_
->Fsync(options
, dbg
);
1249 bool IsSyncThreadSafe() const override
{ return target_
->IsSyncThreadSafe(); }
1251 bool use_direct_io() const override
{ return target_
->use_direct_io(); }
1253 size_t GetRequiredBufferAlignment() const override
{
1254 return target_
->GetRequiredBufferAlignment();
1257 void SetWriteLifeTimeHint(Env::WriteLifeTimeHint hint
) override
{
1258 target_
->SetWriteLifeTimeHint(hint
);
1261 Env::WriteLifeTimeHint
GetWriteLifeTimeHint() override
{
1262 return target_
->GetWriteLifeTimeHint();
1265 uint64_t GetFileSize(const IOOptions
& options
, IODebugContext
* dbg
) override
{
1266 return target_
->GetFileSize(options
, dbg
);
1269 void SetPreallocationBlockSize(size_t size
) override
{
1270 target_
->SetPreallocationBlockSize(size
);
1273 void GetPreallocationStatus(size_t* block_size
,
1274 size_t* last_allocated_block
) override
{
1275 target_
->GetPreallocationStatus(block_size
, last_allocated_block
);
1278 size_t GetUniqueId(char* id
, size_t max_size
) const override
{
1279 return target_
->GetUniqueId(id
, max_size
);
1282 IOStatus
InvalidateCache(size_t offset
, size_t length
) override
{
1283 return target_
->InvalidateCache(offset
, length
);
1286 IOStatus
RangeSync(uint64_t offset
, uint64_t nbytes
, const IOOptions
& options
,
1287 IODebugContext
* dbg
) override
{
1288 return target_
->RangeSync(offset
, nbytes
, options
, dbg
);
1291 void PrepareWrite(size_t offset
, size_t len
, const IOOptions
& options
,
1292 IODebugContext
* dbg
) override
{
1293 target_
->PrepareWrite(offset
, len
, options
, dbg
);
1296 IOStatus
Allocate(uint64_t offset
, uint64_t len
, const IOOptions
& options
,
1297 IODebugContext
* dbg
) override
{
1298 return target_
->Allocate(offset
, len
, options
, dbg
);
1302 FSWritableFile
* target_
;
1305 class FSRandomRWFileWrapper
: public FSRandomRWFile
{
1307 explicit FSRandomRWFileWrapper(FSRandomRWFile
* target
) : target_(target
) {}
1309 bool use_direct_io() const override
{ return target_
->use_direct_io(); }
1310 size_t GetRequiredBufferAlignment() const override
{
1311 return target_
->GetRequiredBufferAlignment();
1313 IOStatus
Write(uint64_t offset
, const Slice
& data
, const IOOptions
& options
,
1314 IODebugContext
* dbg
) override
{
1315 return target_
->Write(offset
, data
, options
, dbg
);
1317 IOStatus
Read(uint64_t offset
, size_t n
, const IOOptions
& options
,
1318 Slice
* result
, char* scratch
,
1319 IODebugContext
* dbg
) const override
{
1320 return target_
->Read(offset
, n
, options
, result
, scratch
, dbg
);
1322 IOStatus
Flush(const IOOptions
& options
, IODebugContext
* dbg
) override
{
1323 return target_
->Flush(options
, dbg
);
1325 IOStatus
Sync(const IOOptions
& options
, IODebugContext
* dbg
) override
{
1326 return target_
->Sync(options
, dbg
);
1328 IOStatus
Fsync(const IOOptions
& options
, IODebugContext
* dbg
) override
{
1329 return target_
->Fsync(options
, dbg
);
1331 IOStatus
Close(const IOOptions
& options
, IODebugContext
* dbg
) override
{
1332 return target_
->Close(options
, dbg
);
1336 FSRandomRWFile
* target_
;
1339 class FSDirectoryWrapper
: public FSDirectory
{
1341 explicit FSDirectoryWrapper(FSDirectory
* target
) : target_(target
) {}
1343 IOStatus
Fsync(const IOOptions
& options
, IODebugContext
* dbg
) override
{
1344 return target_
->Fsync(options
, dbg
);
1346 size_t GetUniqueId(char* id
, size_t max_size
) const override
{
1347 return target_
->GetUniqueId(id
, max_size
);
1351 FSDirectory
* target_
;
1354 // A utility routine: read contents of named file into *data
1355 extern Status
ReadFileToString(FileSystem
* fs
, const std::string
& fname
,
1358 } // namespace ROCKSDB_NAMESPACE