| // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
| // This source code is licensed under both the GPLv2 (found in the |
| // COPYING file in the root directory) and Apache 2.0 License |
| // (found in the LICENSE.Apache file in the root directory). |
| // |
| // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. See the AUTHORS file for names of contributors. |
| #pragma once |
| #include <errno.h> |
| #include <unistd.h> |
| #include <atomic> |
| #include <string> |
| #include "rocksdb/env.h" |
| |
| // For non linux platform, the following macros are used only as place |
| // holder. |
| #if !(defined OS_LINUX) && !(defined CYGWIN) && !(defined OS_AIX) |
| #define POSIX_FADV_NORMAL 0 /* [MC1] no further special treatment */ |
| #define POSIX_FADV_RANDOM 1 /* [MC1] expect random page refs */ |
| #define POSIX_FADV_SEQUENTIAL 2 /* [MC1] expect sequential page refs */ |
| #define POSIX_FADV_WILLNEED 3 /* [MC1] will need these pages */ |
| #define POSIX_FADV_DONTNEED 4 /* [MC1] dont need these pages */ |
| #endif |
| |
| namespace rocksdb { |
| static std::string IOErrorMsg(const std::string& context, |
| const std::string& file_name) { |
| if (file_name.empty()) { |
| return context; |
| } |
| return context + ": " + file_name; |
| } |
| |
| // file_name can be left empty if it is not unkown. |
| static Status IOError(const std::string& context, const std::string& file_name, |
| int err_number) { |
| switch (err_number) { |
| case ENOSPC: |
| return Status::NoSpace(IOErrorMsg(context, file_name), |
| strerror(err_number)); |
| case ESTALE: |
| return Status::IOError(Status::kStaleFile); |
| default: |
| return Status::IOError(IOErrorMsg(context, file_name), |
| strerror(err_number)); |
| } |
| } |
| |
| class PosixHelper { |
| public: |
| static size_t GetUniqueIdFromFile(int fd, char* id, size_t max_size); |
| }; |
| |
| class PosixSequentialFile : public SequentialFile { |
| private: |
| std::string filename_; |
| FILE* file_; |
| int fd_; |
| bool use_direct_io_; |
| size_t logical_sector_size_; |
| |
| public: |
| PosixSequentialFile(const std::string& fname, FILE* file, int fd, |
| const EnvOptions& options); |
| virtual ~PosixSequentialFile(); |
| |
| virtual Status Read(size_t n, Slice* result, char* scratch) override; |
| virtual Status PositionedRead(uint64_t offset, size_t n, Slice* result, |
| char* scratch) override; |
| virtual Status Skip(uint64_t n) override; |
| virtual Status InvalidateCache(size_t offset, size_t length) override; |
| virtual bool use_direct_io() const override { return use_direct_io_; } |
| virtual size_t GetRequiredBufferAlignment() const override { |
| return logical_sector_size_; |
| } |
| }; |
| |
| class PosixRandomAccessFile : public RandomAccessFile { |
| protected: |
| std::string filename_; |
| int fd_; |
| bool use_direct_io_; |
| size_t logical_sector_size_; |
| |
| public: |
| PosixRandomAccessFile(const std::string& fname, int fd, |
| const EnvOptions& options); |
| virtual ~PosixRandomAccessFile(); |
| |
| virtual Status Read(uint64_t offset, size_t n, Slice* result, |
| char* scratch) const override; |
| |
| virtual Status Prefetch(uint64_t offset, size_t n) override; |
| |
| #if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_AIX) |
| virtual size_t GetUniqueId(char* id, size_t max_size) const override; |
| #endif |
| virtual void Hint(AccessPattern pattern) override; |
| virtual Status InvalidateCache(size_t offset, size_t length) override; |
| virtual bool use_direct_io() const override { return use_direct_io_; } |
| virtual size_t GetRequiredBufferAlignment() const override { |
| return logical_sector_size_; |
| } |
| }; |
| |
| class PosixWritableFile : public WritableFile { |
| protected: |
| const std::string filename_; |
| const bool use_direct_io_; |
| int fd_; |
| uint64_t filesize_; |
| size_t logical_sector_size_; |
| #ifdef ROCKSDB_FALLOCATE_PRESENT |
| bool allow_fallocate_; |
| bool fallocate_with_keep_size_; |
| #endif |
| |
| public: |
| explicit PosixWritableFile(const std::string& fname, int fd, |
| const EnvOptions& options); |
| virtual ~PosixWritableFile(); |
| |
| // Need to implement this so the file is truncated correctly |
| // with direct I/O |
| virtual Status Truncate(uint64_t size) override; |
| virtual Status Close() override; |
| virtual Status Append(const Slice& data) override; |
| virtual Status PositionedAppend(const Slice& data, uint64_t offset) override; |
| virtual Status Flush() override; |
| virtual Status Sync() override; |
| virtual Status Fsync() override; |
| virtual bool IsSyncThreadSafe() const override; |
| virtual bool use_direct_io() const override { return use_direct_io_; } |
| virtual uint64_t GetFileSize() override; |
| virtual Status InvalidateCache(size_t offset, size_t length) override; |
| virtual size_t GetRequiredBufferAlignment() const override { |
| return logical_sector_size_; |
| } |
| #ifdef ROCKSDB_FALLOCATE_PRESENT |
| virtual Status Allocate(uint64_t offset, uint64_t len) override; |
| #endif |
| #ifdef ROCKSDB_RANGESYNC_PRESENT |
| virtual Status RangeSync(uint64_t offset, uint64_t nbytes) override; |
| #endif |
| #ifdef OS_LINUX |
| virtual size_t GetUniqueId(char* id, size_t max_size) const override; |
| #endif |
| }; |
| |
| // mmap() based random-access |
| class PosixMmapReadableFile : public RandomAccessFile { |
| private: |
| int fd_; |
| std::string filename_; |
| void* mmapped_region_; |
| size_t length_; |
| |
| public: |
| PosixMmapReadableFile(const int fd, const std::string& fname, void* base, |
| size_t length, const EnvOptions& options); |
| virtual ~PosixMmapReadableFile(); |
| virtual Status Read(uint64_t offset, size_t n, Slice* result, |
| char* scratch) const override; |
| virtual Status InvalidateCache(size_t offset, size_t length) override; |
| }; |
| |
| class PosixMmapFile : public WritableFile { |
| private: |
| std::string filename_; |
| int fd_; |
| size_t page_size_; |
| size_t map_size_; // How much extra memory to map at a time |
| char* base_; // The mapped region |
| char* limit_; // Limit of the mapped region |
| char* dst_; // Where to write next (in range [base_,limit_]) |
| char* last_sync_; // Where have we synced up to |
| uint64_t file_offset_; // Offset of base_ in file |
| #ifdef ROCKSDB_FALLOCATE_PRESENT |
| bool allow_fallocate_; // If false, fallocate calls are bypassed |
| bool fallocate_with_keep_size_; |
| #endif |
| |
| // Roundup x to a multiple of y |
| static size_t Roundup(size_t x, size_t y) { return ((x + y - 1) / y) * y; } |
| |
| size_t TruncateToPageBoundary(size_t s) { |
| s -= (s & (page_size_ - 1)); |
| assert((s % page_size_) == 0); |
| return s; |
| } |
| |
| Status MapNewRegion(); |
| Status UnmapCurrentRegion(); |
| Status Msync(); |
| |
| public: |
| PosixMmapFile(const std::string& fname, int fd, size_t page_size, |
| const EnvOptions& options); |
| ~PosixMmapFile(); |
| |
| // Means Close() will properly take care of truncate |
| // and it does not need any additional information |
| virtual Status Truncate(uint64_t size) override { return Status::OK(); } |
| virtual Status Close() override; |
| virtual Status Append(const Slice& data) override; |
| virtual Status Flush() override; |
| virtual Status Sync() override; |
| virtual Status Fsync() override; |
| virtual uint64_t GetFileSize() override; |
| virtual Status InvalidateCache(size_t offset, size_t length) override; |
| #ifdef ROCKSDB_FALLOCATE_PRESENT |
| virtual Status Allocate(uint64_t offset, uint64_t len) override; |
| #endif |
| }; |
| |
| class PosixRandomRWFile : public RandomRWFile { |
| public: |
| explicit PosixRandomRWFile(const std::string& fname, int fd, |
| const EnvOptions& options); |
| virtual ~PosixRandomRWFile(); |
| |
| virtual Status Write(uint64_t offset, const Slice& data) override; |
| |
| virtual Status Read(uint64_t offset, size_t n, Slice* result, |
| char* scratch) const override; |
| |
| virtual Status Flush() override; |
| virtual Status Sync() override; |
| virtual Status Fsync() override; |
| virtual Status Close() override; |
| |
| private: |
| const std::string filename_; |
| int fd_; |
| }; |
| |
| class PosixDirectory : public Directory { |
| public: |
| explicit PosixDirectory(int fd) : fd_(fd) {} |
| ~PosixDirectory(); |
| virtual Status Fsync() override; |
| |
| private: |
| int fd_; |
| }; |
| |
| } // namespace rocksdb |