]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/include/rocksdb/file_system.h
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / rocksdb / include / rocksdb / file_system.h
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).
5 //
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.
10 //
11 // All FileSystem implementations are safe for concurrent access from
12 // multiple threads without any external synchronization.
13 //
14 // WARNING: Since this is a new interface, it is expected that there will be
15 // some changes as storage systems are ported over.
16
17 #pragma once
18
19 #include <stdint.h>
20 #include <chrono>
21 #include <cstdarg>
22 #include <functional>
23 #include <limits>
24 #include <memory>
25 #include <sstream>
26 #include <string>
27 #include <vector>
28 #include "rocksdb/env.h"
29 #include "rocksdb/io_status.h"
30 #include "rocksdb/options.h"
31 #include "rocksdb/thread_status.h"
32
33 namespace ROCKSDB_NAMESPACE {
34
35 class FileLock;
36 class FSDirectory;
37 class FSRandomAccessFile;
38 class FSRandomRWFile;
39 class FSSequentialFile;
40 class FSWritableFile;
41 class Logger;
42 class Slice;
43 struct ImmutableDBOptions;
44 struct MutableDBOptions;
45 class RateLimiter;
46
47 using AccessPattern = RandomAccessFile::AccessPattern;
48 using FileAttributes = Env::FileAttributes;
49
50 // Priority of an IO request. This is a hint and does not guarantee any
51 // particular QoS.
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 {
55 kIOLow,
56 kIOHigh,
57 kIOTotal,
58 };
59
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
62 // different ways
63 enum class IOType : uint8_t {
64 kData,
65 kFilter,
66 kIndex,
67 kMetadata,
68 kWAL,
69 kManifest,
70 kLog,
71 kUnknown,
72 kInvalid,
73 };
74
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.
79 struct IOOptions {
80 // Timeout for the operation in milliseconds
81 std::chrono::milliseconds timeout;
82
83 // Priority - high or low
84 IOPriority prio;
85
86 // Type of data being read/written
87 IOType type;
88 };
89
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
96 IOOptions io_options;
97
98 FileOptions() : EnvOptions() {}
99
100 FileOptions(const DBOptions& opts)
101 : EnvOptions(opts) {}
102
103 FileOptions(const EnvOptions& opts)
104 : EnvOptions(opts) {}
105 };
106
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;
112
113 // A map of counter names to values - set by the FileSystem implementation
114 std::map<std::string, uint64_t> counters;
115
116 // To be set by the FileSystem implementation
117 std::string msg;
118
119 IODebugContext() {}
120
121 void AddCounter(std::string& name, uint64_t value) {
122 counters.emplace(name, value);
123 }
124
125 std::string ToString() {
126 std::ostringstream ss;
127 ss << file_path << ", ";
128 for (auto counter : counters) {
129 ss << counter.first << " = " << counter.second << ",";
130 }
131 ss << msg;
132 return ss.str();
133 }
134 };
135
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
149 // retryable.
150 class FileSystem {
151 public:
152 FileSystem();
153
154 // No copying allowed
155 FileSystem(const FileSystem&) = delete;
156
157 virtual ~FileSystem();
158
159 virtual const char* Name() const = 0;
160
161 static const char* Type() { return "FileSystem"; }
162
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);
166
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
170 //
171 // The result of Default() belongs to rocksdb and must never be deleted.
172 static std::shared_ptr<FileSystem> Default();
173
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.
178 //
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;
184
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
189 // status.
190 //
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
205 };
206
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
211 // returns non-OK.
212 //
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;
218
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
223 // returns non-OK.
224 //
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();
230 }
231
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;
238
239 // Open `fname` for random read and write, if file doesn't exist the file
240 // will be created. On success, stores a pointer to the new file in
241 // *result and returns OK. On failure returns non-OK.
242 //
243 // The returned file will only be accessed by one thread at a time.
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");
250 }
251
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");
260 }
261
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.
265 //
266 // On success, stores a pointer to the new Directory in
267 // *result and returns OK. On failure stores nullptr in *result and
268 // returns non-OK.
269 virtual IOStatus NewDirectory(const std::string& name,
270 const IOOptions& io_opts,
271 std::unique_ptr<FSDirectory>* result,
272 IODebugContext* dbg) = 0;
273
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;
282
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;
293
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
297 // result.
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);
310 if (!s.ok()) {
311 return s;
312 }
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,
318 dbg))
319 .ok()) {
320 if (FileExists(path, options, dbg).IsNotFound()) {
321 // The file may have been deleted since we listed the directory
322 continue;
323 }
324 return s;
325 }
326 (*result)[result_size].name = std::move(child_fnames[i]);
327 result_size++;
328 }
329 result->resize(result_size);
330 return IOStatus::OK();
331 }
332
333 // Delete the named file.
334 virtual IOStatus DeleteFile(const std::string& fname,
335 const IOOptions& options,
336 IODebugContext* dbg) = 0;
337
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");
343 }
344
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;
348
349 // Creates directory if missing. Return Ok if it exists, or successful in
350 // Creating.
351 virtual IOStatus CreateDirIfMissing(const std::string& dirname,
352 const IOOptions& options,
353 IODebugContext* dbg) = 0;
354
355 // Delete the specified directory.
356 virtual IOStatus DeleteDir(const std::string& dirname,
357 const IOOptions& options, IODebugContext* dbg) = 0;
358
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;
363
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;
373
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");
380 }
381
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");
387 }
388
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");
394 }
395
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.
399 //
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.
404 //
405 // If somebody else already holds the lock, finishes immediately
406 // with a failure. I.e., this call does not wait for existing locks
407 // to go away.
408 //
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;
412
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;
418
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
422 // same directory.
423 virtual IOStatus GetTestDirectory(const IOOptions& options, std::string* path,
424 IODebugContext* dbg) = 0;
425
426 // Create and returns a default logger (an instance of EnvLogger) for storing
427 // informational messages. Derived classes can overide to provide custom
428 // logger.
429 virtual IOStatus NewLogger(const std::string& fname, const IOOptions& io_opts,
430 std::shared_ptr<Logger>* result,
431 IODebugContext* dbg) = 0;
432
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;
438
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;
442
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
445 // files.
446 virtual FileOptions OptimizeForManifestRead(
447 const FileOptions& file_options) const;
448
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;
454
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
458 // object.
459 virtual FileOptions OptimizeForManifestWrite(
460 const FileOptions& file_options) const;
461
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;
468
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;
475
476 // This seems to clash with a macro on Windows, so #undef it here
477 #ifdef GetFreeSpace
478 #undef GetFreeSpace
479 #endif
480
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();
487 }
488
489 // If you're adding methods here, remember to add them to EnvWrapper too.
490
491 private:
492 void operator=(const FileSystem&);
493 };
494
495 // A file abstraction for reading sequentially through a file
496 class FSSequentialFile {
497 public:
498 FSSequentialFile() {}
499
500 virtual ~FSSequentialFile() {}
501
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.
508 //
509 // REQUIRES: External synchronization
510 virtual IOStatus Read(size_t n, const IOOptions& options, Slice* result,
511 char* scratch, IODebugContext* dbg) = 0;
512
513 // Skip "n" bytes from the file. This is guaranteed to be no
514 // slower that reading the same data, but may be faster.
515 //
516 // If end of file is reached, skipping will stop at the end of the
517 // file, and Skip will return OK.
518 //
519 // REQUIRES: External synchronization
520 virtual IOStatus Skip(uint64_t n) = 0;
521
522 // Indicates the upper layers if the current SequentialFile implementation
523 // uses direct IO.
524 virtual bool use_direct_io() const { return false; }
525
526 // Use the returned alignment value to allocate
527 // aligned buffer for Direct I/O
528 virtual size_t GetRequiredBufferAlignment() const { return kDefaultPageSize; }
529
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.");
535 }
536
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();
544 }
545
546 // If you're adding methods here, remember to add them to
547 // SequentialFileWrapper too.
548 };
549
550 // A read IO request structure for use in MultiRead
551 struct FSReadRequest {
552 // File offset in bytes
553 uint64_t offset;
554
555 // Length to read in bytes
556 size_t len;
557
558 // A buffer that MultiRead() can optionally place data in. It can
559 // ignore this and allocate its own buffer
560 char* scratch;
561
562 // Output parameter set by MultiRead() to point to the data buffer, and
563 // the number of valid bytes
564 Slice result;
565
566 // Status of read
567 IOStatus status;
568 };
569
570 // A file abstraction for randomly reading the contents of a file.
571 class FSRandomAccessFile {
572 public:
573 FSRandomAccessFile() {}
574
575 virtual ~FSRandomAccessFile() {}
576
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
583 // status.
584 //
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;
590
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();
596 }
597
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];
610 req.status =
611 Read(req.offset, req.len, options, &req.result, req.scratch, dbg);
612 }
613 return IOStatus::OK();
614 }
615
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.
622 //
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.
626 //
627 // This function guarantees that the returned ID will not be interpretable as
628 // a single varint.
629 //
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
633 // compatibility.
634 };
635
636 enum AccessPattern { kNormal, kRandom, kSequential, kWillNeed, kWontNeed };
637
638 virtual void Hint(AccessPattern /*pattern*/) {}
639
640 // Indicates the upper layers if the current RandomAccessFile implementation
641 // uses direct IO.
642 virtual bool use_direct_io() const { return false; }
643
644 // Use the returned alignment value to allocate
645 // aligned buffer for Direct I/O
646 virtual size_t GetRequiredBufferAlignment() const { return kDefaultPageSize; }
647
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.");
653 }
654
655 // If you're adding methods here, remember to add them to
656 // RandomAccessFileWrapper too.
657 };
658
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 {
663 public:
664 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) {}
670
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) {}
677
678 virtual ~FSWritableFile() {}
679
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;
685
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
690 // partial sector.
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.
694 //
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.
699 //
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.
703 //
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();
711 }
712
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();
720 }
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
725
726 /*
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
730 * metadata as well.
731 */
732 virtual IOStatus Fsync(const IOOptions& options, IODebugContext* dbg) {
733 return Sync(options, dbg);
734 }
735
736 // true if Sync() and Fsync() are safe to call concurrently with Append()
737 // and Flush().
738 virtual bool IsSyncThreadSafe() const { return false; }
739
740 // Indicates the upper layers if the current WritableFile implementation
741 // uses direct IO.
742 virtual bool use_direct_io() const { return false; }
743
744 // Use the returned alignment value to allocate
745 // aligned buffer for Direct I/O
746 virtual size_t GetRequiredBufferAlignment() const { return kDefaultPageSize; }
747
748 virtual void SetWriteLifeTimeHint(Env::WriteLifeTimeHint hint) {
749 write_hint_ = hint;
750 }
751
752 virtual void SetIOPriority(Env::IOPriority pri) { io_priority_ = pri; }
753
754 virtual Env::IOPriority GetIOPriority() { return io_priority_; }
755
756 virtual Env::WriteLifeTimeHint GetWriteLifeTimeHint() { return write_hint_; }
757 /*
758 * Get the size of valid data in the file.
759 */
760 virtual uint64_t GetFileSize(const IOOptions& /*options*/,
761 IODebugContext* /*dbg*/) {
762 return 0;
763 }
764
765 /*
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.
770 */
771 virtual void SetPreallocationBlockSize(size_t size) {
772 preallocation_block_size_ = size;
773 }
774
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_;
779 }
780
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
784 }
785
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.");
792 }
793
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);
804 }
805 return IOStatus::OK();
806 }
807
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
812 // pre-allocation.
813 virtual void PrepareWrite(size_t offset, size_t len, const IOOptions& options,
814 IODebugContext* dbg) {
815 if (preallocation_block_size_ == 0) {
816 return;
817 }
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;
830 }
831 }
832
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();
838 }
839
840 // If you're adding methods here, remember to add them to
841 // WritableFileWrapper too.
842
843 protected:
844 size_t preallocation_block_size() { return preallocation_block_size_; }
845
846 private:
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&);
852
853 protected:
854 Env::IOPriority io_priority_;
855 Env::WriteLifeTimeHint write_hint_;
856 const bool strict_bytes_per_sync_;
857 };
858
859 // A file abstraction for random reading and writing.
860 class FSRandomRWFile {
861 public:
862 FSRandomRWFile() {}
863
864 virtual ~FSRandomRWFile() {}
865
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; }
869
870 // Use the returned alignment value to allocate
871 // aligned buffer for Direct I/O
872 virtual size_t GetRequiredBufferAlignment() const { return kDefaultPageSize; }
873
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;
878
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;
885
886 virtual IOStatus Flush(const IOOptions& options, IODebugContext* dbg) = 0;
887
888 virtual IOStatus Sync(const IOOptions& options, IODebugContext* dbg) = 0;
889
890 virtual IOStatus Fsync(const IOOptions& options, IODebugContext* dbg) {
891 return Sync(options, dbg);
892 }
893
894 virtual IOStatus Close(const IOOptions& options, IODebugContext* dbg) = 0;
895
896 // If you're adding methods here, remember to add them to
897 // RandomRWFileWrapper too.
898
899 // No copying allowed
900 FSRandomRWFile(const RandomRWFile&) = delete;
901 FSRandomRWFile& operator=(const RandomRWFile&) = delete;
902 };
903
904 // MemoryMappedFileBuffer object represents a memory-mapped file's raw buffer.
905 // Subclasses should release the mapping upon destruction.
906 class FSMemoryMappedFileBuffer {
907 public:
908 FSMemoryMappedFileBuffer(void* _base, size_t _length)
909 : base_(_base), length_(_length) {}
910
911 virtual ~FSMemoryMappedFileBuffer() = 0;
912
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;
917
918 void* GetBase() const { return base_; }
919 size_t GetLen() const { return length_; }
920
921 protected:
922 void* base_;
923 const size_t length_;
924 };
925
926 // Directory object represents collection of files and implements
927 // filesystem operations that can be executed on directories.
928 class FSDirectory {
929 public:
930 virtual ~FSDirectory() {}
931 // Fsync directory. Can be called concurrently from multiple threads.
932 virtual IOStatus Fsync(const IOOptions& options, IODebugContext* dbg) = 0;
933
934 virtual size_t GetUniqueId(char* /*id*/, size_t /*max_size*/) const {
935 return 0;
936 }
937
938 // If you're adding methods here, remember to add them to
939 // DirectoryWrapper too.
940 };
941
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.:
946 //
947 // class MySequentialFileWrapper : public
948 // ROCKSDB_NAMESPACE::FSSequentialFileWrapper {
949 // public:
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,
956 // result,
957 // scratch, dbg);
958 // }
959 // // All other methods are forwarded to target_ automatically.
960 // };
961 //
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.)
968
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 {
973 public:
974 // Initialize an EnvWrapper that delegates all calls to *t
975 explicit FileSystemWrapper(FileSystem* t) : target_(t) {}
976 ~FileSystemWrapper() override {}
977
978 // Return the target to which this Env forwards all calls
979 FileSystem* target() const { return target_; }
980
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);
987 }
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);
993 }
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);
998 }
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);
1004 }
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,
1011 dbg);
1012 }
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);
1018 }
1019 IOStatus NewMemoryMappedFileBuffer(
1020 const std::string& fname,
1021 std::unique_ptr<MemoryMappedFileBuffer>* result) override {
1022 return target_->NewMemoryMappedFileBuffer(fname, result);
1023 }
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);
1028 }
1029 IOStatus FileExists(const std::string& f, const IOOptions& io_opts,
1030 IODebugContext* dbg) override {
1031 return target_->FileExists(f, io_opts, dbg);
1032 }
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);
1037 }
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);
1043 }
1044 IOStatus DeleteFile(const std::string& f, const IOOptions& options,
1045 IODebugContext* dbg) override {
1046 return target_->DeleteFile(f, options, dbg);
1047 }
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);
1051 }
1052 IOStatus CreateDir(const std::string& d, const IOOptions& options,
1053 IODebugContext* dbg) override {
1054 return target_->CreateDir(d, options, dbg);
1055 }
1056 IOStatus CreateDirIfMissing(const std::string& d, const IOOptions& options,
1057 IODebugContext* dbg) override {
1058 return target_->CreateDirIfMissing(d, options, dbg);
1059 }
1060 IOStatus DeleteDir(const std::string& d, const IOOptions& options,
1061 IODebugContext* dbg) override {
1062 return target_->DeleteDir(d, options, dbg);
1063 }
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);
1067 }
1068
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);
1074 }
1075
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);
1080 }
1081
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);
1085 }
1086
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);
1090 }
1091
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);
1095 }
1096
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);
1101 }
1102
1103 IOStatus LockFile(const std::string& f, const IOOptions& options,
1104 FileLock** l, IODebugContext* dbg) override {
1105 return target_->LockFile(f, options, l, dbg);
1106 }
1107
1108 IOStatus UnlockFile(FileLock* l, const IOOptions& options,
1109 IODebugContext* dbg) override {
1110 return target_->UnlockFile(l, options, dbg);
1111 }
1112
1113 IOStatus GetTestDirectory(const IOOptions& options, std::string* path,
1114 IODebugContext* dbg) override {
1115 return target_->GetTestDirectory(options, path, dbg);
1116 }
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);
1121 }
1122
1123 FileOptions OptimizeForLogRead(
1124 const FileOptions& file_options) const override {
1125 return target_->OptimizeForLogRead(file_options);
1126 }
1127 FileOptions OptimizeForManifestRead(
1128 const FileOptions& file_options) const override {
1129 return target_->OptimizeForManifestRead(file_options);
1130 }
1131 FileOptions OptimizeForLogWrite(const FileOptions& file_options,
1132 const DBOptions& db_options) const override {
1133 return target_->OptimizeForLogWrite(file_options, db_options);
1134 }
1135 FileOptions OptimizeForManifestWrite(
1136 const FileOptions& file_options) const override {
1137 return target_->OptimizeForManifestWrite(file_options);
1138 }
1139 FileOptions OptimizeForCompactionTableWrite(
1140 const FileOptions& file_options,
1141 const ImmutableDBOptions& immutable_ops) const override {
1142 return target_->OptimizeForCompactionTableWrite(file_options,
1143 immutable_ops);
1144 }
1145 FileOptions OptimizeForCompactionTableRead(
1146 const FileOptions& file_options,
1147 const ImmutableDBOptions& db_options) const override {
1148 return target_->OptimizeForCompactionTableRead(file_options, db_options);
1149 }
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);
1153 }
1154
1155 private:
1156 FileSystem* target_;
1157 };
1158
1159 class FSSequentialFileWrapper : public FSSequentialFile {
1160 public:
1161 explicit FSSequentialFileWrapper(FSSequentialFile* target)
1162 : target_(target) {}
1163
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);
1167 }
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();
1172 }
1173 IOStatus InvalidateCache(size_t offset, size_t length) override {
1174 return target_->InvalidateCache(offset, length);
1175 }
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);
1180 }
1181
1182 private:
1183 FSSequentialFile* target_;
1184 };
1185
1186 class FSRandomAccessFileWrapper : public FSRandomAccessFile {
1187 public:
1188 explicit FSRandomAccessFileWrapper(FSRandomAccessFile* target)
1189 : target_(target) {}
1190
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);
1195 }
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);
1199 }
1200 IOStatus Prefetch(uint64_t offset, size_t n, const IOOptions& options,
1201 IODebugContext* dbg) override {
1202 return target_->Prefetch(offset, n, options, dbg);
1203 }
1204 size_t GetUniqueId(char* id, size_t max_size) const override {
1205 return target_->GetUniqueId(id, max_size);
1206 };
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();
1211 }
1212 IOStatus InvalidateCache(size_t offset, size_t length) override {
1213 return target_->InvalidateCache(offset, length);
1214 }
1215
1216 private:
1217 FSRandomAccessFile* target_;
1218 };
1219
1220 class FSWritableFileWrapper : public FSWritableFile {
1221 public:
1222 explicit FSWritableFileWrapper(FSWritableFile* t) : target_(t) {}
1223
1224 IOStatus Append(const Slice& data, const IOOptions& options,
1225 IODebugContext* dbg) override {
1226 return target_->Append(data, options, dbg);
1227 }
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);
1232 }
1233 IOStatus Truncate(uint64_t size, const IOOptions& options,
1234 IODebugContext* dbg) override {
1235 return target_->Truncate(size, options, dbg);
1236 }
1237 IOStatus Close(const IOOptions& options, IODebugContext* dbg) override {
1238 return target_->Close(options, dbg);
1239 }
1240 IOStatus Flush(const IOOptions& options, IODebugContext* dbg) override {
1241 return target_->Flush(options, dbg);
1242 }
1243 IOStatus Sync(const IOOptions& options, IODebugContext* dbg) override {
1244 return target_->Sync(options, dbg);
1245 }
1246 IOStatus Fsync(const IOOptions& options, IODebugContext* dbg) override {
1247 return target_->Fsync(options, dbg);
1248 }
1249 bool IsSyncThreadSafe() const override { return target_->IsSyncThreadSafe(); }
1250
1251 bool use_direct_io() const override { return target_->use_direct_io(); }
1252
1253 size_t GetRequiredBufferAlignment() const override {
1254 return target_->GetRequiredBufferAlignment();
1255 }
1256
1257 void SetWriteLifeTimeHint(Env::WriteLifeTimeHint hint) override {
1258 target_->SetWriteLifeTimeHint(hint);
1259 }
1260
1261 Env::WriteLifeTimeHint GetWriteLifeTimeHint() override {
1262 return target_->GetWriteLifeTimeHint();
1263 }
1264
1265 uint64_t GetFileSize(const IOOptions& options, IODebugContext* dbg) override {
1266 return target_->GetFileSize(options, dbg);
1267 }
1268
1269 void SetPreallocationBlockSize(size_t size) override {
1270 target_->SetPreallocationBlockSize(size);
1271 }
1272
1273 void GetPreallocationStatus(size_t* block_size,
1274 size_t* last_allocated_block) override {
1275 target_->GetPreallocationStatus(block_size, last_allocated_block);
1276 }
1277
1278 size_t GetUniqueId(char* id, size_t max_size) const override {
1279 return target_->GetUniqueId(id, max_size);
1280 }
1281
1282 IOStatus InvalidateCache(size_t offset, size_t length) override {
1283 return target_->InvalidateCache(offset, length);
1284 }
1285
1286 IOStatus RangeSync(uint64_t offset, uint64_t nbytes, const IOOptions& options,
1287 IODebugContext* dbg) override {
1288 return target_->RangeSync(offset, nbytes, options, dbg);
1289 }
1290
1291 void PrepareWrite(size_t offset, size_t len, const IOOptions& options,
1292 IODebugContext* dbg) override {
1293 target_->PrepareWrite(offset, len, options, dbg);
1294 }
1295
1296 IOStatus Allocate(uint64_t offset, uint64_t len, const IOOptions& options,
1297 IODebugContext* dbg) override {
1298 return target_->Allocate(offset, len, options, dbg);
1299 }
1300
1301 private:
1302 FSWritableFile* target_;
1303 };
1304
1305 class FSRandomRWFileWrapper : public FSRandomRWFile {
1306 public:
1307 explicit FSRandomRWFileWrapper(FSRandomRWFile* target) : target_(target) {}
1308
1309 bool use_direct_io() const override { return target_->use_direct_io(); }
1310 size_t GetRequiredBufferAlignment() const override {
1311 return target_->GetRequiredBufferAlignment();
1312 }
1313 IOStatus Write(uint64_t offset, const Slice& data, const IOOptions& options,
1314 IODebugContext* dbg) override {
1315 return target_->Write(offset, data, options, dbg);
1316 }
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);
1321 }
1322 IOStatus Flush(const IOOptions& options, IODebugContext* dbg) override {
1323 return target_->Flush(options, dbg);
1324 }
1325 IOStatus Sync(const IOOptions& options, IODebugContext* dbg) override {
1326 return target_->Sync(options, dbg);
1327 }
1328 IOStatus Fsync(const IOOptions& options, IODebugContext* dbg) override {
1329 return target_->Fsync(options, dbg);
1330 }
1331 IOStatus Close(const IOOptions& options, IODebugContext* dbg) override {
1332 return target_->Close(options, dbg);
1333 }
1334
1335 private:
1336 FSRandomRWFile* target_;
1337 };
1338
1339 class FSDirectoryWrapper : public FSDirectory {
1340 public:
1341 explicit FSDirectoryWrapper(FSDirectory* target) : target_(target) {}
1342
1343 IOStatus Fsync(const IOOptions& options, IODebugContext* dbg) override {
1344 return target_->Fsync(options, dbg);
1345 }
1346 size_t GetUniqueId(char* id, size_t max_size) const override {
1347 return target_->GetUniqueId(id, max_size);
1348 }
1349
1350 private:
1351 FSDirectory* target_;
1352 };
1353
1354 // A utility routine: read contents of named file into *data
1355 extern Status ReadFileToString(FileSystem* fs, const std::string& fname,
1356 std::string* data);
1357
1358 } // namespace ROCKSDB_NAMESPACE