leveldb env

read or write files

SequentialFile(线程不安全,顺序读)

// A file abstraction for reading sequentially through a file
class LEVELDB_EXPORT SequentialFile {
   
 public:
  SequentialFile() = default;

  SequentialFile(const SequentialFile&) = delete;
  SequentialFile& operator=(const SequentialFile&) = delete;

  virtual ~SequentialFile();

  // Read up to "n" bytes from the file.  "scratch[0..n-1]" may be
  // written by this routine.  Sets "*result" to the data that was
  // read (including if fewer than "n" bytes were successfully read).
  // May set "*result" to point at data in "scratch[0..n-1]", so
  // "scratch[0..n-1]" must be live when "*result" is used.
  // If an error was encountered, returns a non-OK status.
  //
  // REQUIRES: External synchronization
  virtual Status Read(size_t n, Slice* result, char* scratch) = 0;

  // Skip "n" bytes from the file. This is guaranteed to be no
  // slower that reading the same data, but may be faster.
  //
  // If end of file is reached, skipping will stop at the end of the
  // file, and Skip will return OK.
  //
  // REQUIRES: External synchronization
  virtual Status Skip(uint64_t n) = 0;
};

NewSequentialFile

// Create an object that sequentially reads the file with the specified name.
// On success, stores a pointer to the new file in *result and returns OK.
// On failure stores nullptr in *result and returns non-OK.  If the file does
// not exist, returns a non-OK status.  Implementations should return a
// NotFound status when the file does not exist.
//
// The returned file will only be accessed by one thread at a time.
Status PosixEnv::NewSequentialFile(const std::string& filename,
                         SequentialFile** result) override {
   
  int fd = ::open(filename.c_str(), O_RDONLY | kOpenBaseFlags);
  if (fd < 0) {
   
    *result = nullptr;
    return PosixError(filename, errno);
  }

  *result = new PosixSequentialFile(filename, fd);
  return Status::OK();
}

PosixSequentialFile

// Implements sequential read access in a file using read().
//
// Instances of this class are thread-friendly but not thread-safe, as required
// by the SequentialFile API.
class PosixSequentialFile final : public SequentialFile {
   
 public:
  PosixSequentialFile(std::string filename, int fd)
      : fd_(fd), filename_(filename) {
   }
  ~PosixSequentialFile() override {
    close(fd_); }

  Status Read(size_t n, Slice* result, char* scratch) override {
   
    Status status;
    while (true) {
   
      ::ssize_t read_size = ::read(fd_, scratch, n);
      if (read_size < 0) {
     // Read error.
        if (errno == EINTR) {
   
          continue;  // Retry
        }
        status = PosixError(filename_, errno);
        break;
      }
      *result = Slice(scratch, read_size);
      break;
    }
    return status;
  }

  Status Skip(uint64_t n) override {
   
    if (::lseek(fd_, n, SEEK_CUR) == static_cast<off_t>(-1)) {
   
      return PosixError(filename_, errno);
    }
    return Status::OK();
  }

 private:
  const int fd_;
  const std::string filename_;
};

RandomAccessFile(线程安全,随机读)

// A file abstraction for randomly reading the contents of a file.
class LEVELDB_EXPORT RandomAccessFile {
   
 public:
  RandomAccessFile() = default;

  RandomAccessFile(const RandomAccessFile&) = delete;
  RandomAccessFile& operator=(const RandomAccessFile&) = delete;

  virtual ~RandomAccessFile();

  // Read up to "n" bytes from the file starting at "offset".
  // "scratch[0..n-1]" may be written by this routine.  Sets "*result"
  // to the data that was read (including if fewer than "n" bytes were
  // successfully read).  May set "*result" to point at data in
  // "scratch[0..n-1]", so "scratch[0..n-1]" must be live when
  // "*result" is used.  If an error was encountered, returns a non-OK
  // status.
  //
  // Safe for concurrent use by multiple threads.
  virtual Status Read(uint64_t offset, size_t n, Slice* result,
                      char* scratch) const = 0;
};

NewRandomAccessFile

// Create an object supporting random-access reads from the file with the
// specified name.  On success, stores a pointer to the new file in
// *result and returns OK.  On failure stores nullptr in *result and
// returns non-OK.  If the file does not exist, returns a non-OK
// status.  Implementations should return a NotFound status when the file does
// not exist.
//
// The returned file may be concurrently accessed by multiple threads.
Status PosixEnv::NewRandomAccessFile(const std::string& filename,
                             RandomAccessFile** result) override {
   
  *result = nullptr;
  int fd = ::open(filename.c_str(), O_RDONLY | kOpenBaseFlags);
  if (fd < 0) {
   
    return PosixError(filename, errno);
  }

  if (!mmap_limiter_.Acquire()) {
   
 // 打开的 mmap 文件数量超过阈值
    *result = new PosixRandomAccessFile(filename, fd, &fd_limiter_);
    return Status::OK();
  }

  uint64_t file_size;
  Status status = GetFileSize(filename, &file_size);
  if (status.ok()) {
   
    void* mmap_base =
        ::mmap(/*addr=*/nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0);
    if (mmap_base != MAP_FAILED) {
   
      *result = new PosixMmapReadableFile(filename,
                                          reinterpret_cast<char*>(mmap_base),
                                          file_size, &mmap_limiter_);
    } else {
   
      status = PosixError(filename, errno);
    }
  }
  ::close(fd);
  if (!status.ok()) {
   
    mmap_limiter_.Release();
  }
  return status;
}

NewRandomAccessFile会优先选择PosixMmapReadableFile,但是如果!mmap_limiter_.Acquire()的话(打开的mmap文件数量超过阈值),会选择PosixRandomAccessFile

PosixRandomAccessFile

// Implements random read access in a file using pread().
// pread相当于先调用lseek接着调用read。但又不完全是这样:
//(1)pread是原子操作,定位和读操作在一个原子操作中完成,期间不可中断。但分开的lseek和read中间可能被其他程序中断。
//(2)pread不更改当前文件的指针,也就是说不改变当前文件偏移量。
//(3)pread中的offset是一个绝对量,相对于文件开始处的绝对量,与当前文件指针位置无关。
//
// Instances of this class are thread-safe, as required by the RandomAccessFile
// API. Instances are immutable and Read() only calls thread-safe library
// functions.
class PosixRandomAccessFile final : public RandomAccessFile {
   
 public:
  // The new instance takes ownership of |fd|. |fd_limiter| must outlive this
  // instance, and will be used to determine if .
  PosixRandomAccessFile(std::string filename, int fd, Limiter* fd_limiter)
      : has_permanent_fd_(fd_limiter->Acquire()),
        fd_(has_permanent_fd_ ? fd : -1),
        fd_limiter_(fd_limiter),
        filename_(std::move
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值