從leveldb中學(xué)編碼技巧(6)

leveldb的運(yùn)行涉及到很多文件,包括manifest文件,WAL log文件,sst文件,日志文件等,為了方便進(jìn)行文件io,leveldb抽象了幾個(gè)接口

// A file abstraction for reading sequentially through a file
class SequentialFile {
 public:
  SequentialFile() { }
  virtual ~SequentialFile();

  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.
  virtual Status Skip(uint64_t n) = 0;

 private:
  // No copying allowed
  SequentialFile(const SequentialFile&);
  void operator=(const SequentialFile&);
};

// A file abstraction for randomly reading the contents of a file.
class RandomAccessFile {
 public:
  RandomAccessFile() { }
  virtual ~RandomAccessFile();

  // Safe for concurrent use by multiple threads.
  virtual Status Read(uint64_t offset, size_t n, Slice* result,
                      char* scratch) const = 0;

 private:
  // No copying allowed
  RandomAccessFile(const RandomAccessFile&);
  void operator=(const RandomAccessFile&);
};

// A file abstraction for sequential writing.  The implementation
// must provide buffering since callers may append small fragments
// at a time to the file.
class WritableFile {
 public:
  WritableFile() { }
  virtual ~WritableFile();

  virtual Status Append(const Slice& data) = 0;
  virtual Status Close() = 0;
  virtual Status Flush() = 0;
  virtual Status Sync() = 0;

 private:
  // No copying allowed
  WritableFile(const WritableFile&);
  void operator=(const WritableFile&);
};

在具體實(shí)現(xiàn)這些接口的時(shí)候,除了RandomAccessFile類型外,leveldb都是使用標(biāo)準(zhǔn)IO庫來實(shí)現(xiàn),也就是<stdio>提供的一套函數(shù),標(biāo)準(zhǔn)IO庫有自己的緩存,leveldb沒有對磁盤文件做額外的緩存。
對RandomAccessFile 這個(gè)類型,leveldb使用了mmap來進(jìn)行內(nèi)存映射,以此提高文件IOD的性能。同時(shí)控制了能夠同時(shí)進(jìn)行內(nèi)存映射的文件數(shù)目。(為了防止內(nèi)存消耗過度?)

對于日志打印,leveldb的實(shí)現(xiàn)比較簡單。首先定義了一個(gè)接口:

// An interface for writing log messages.
class Logger {
 public:
  Logger() { }
  virtual ~Logger();

  // Write an entry to the log file with the specified format.
  virtual void Logv(const char* format, va_list ap) = 0;

 private:
  // No copying allowed
  Logger(const Logger&);
  void operator=(const Logger&);
};

然后根據(jù)具體環(huán)境來實(shí)現(xiàn)這個(gè)接口,在POSIX下,實(shí)現(xiàn)的class是:

class PosixLogger : public Logger {
 private:
  FILE* file_;
  uint64_t (*gettid_)();  // Return the thread id for the current thread
 public:
  PosixLogger(FILE* f, uint64_t (*gettid)()) : file_(f), gettid_(gettid) { }
  virtual ~PosixLogger() {
    fclose(file_);
  }
  virtual void Logv(const char* format, va_list ap);
}

打印日志的過程使用了變長參數(shù),這是日志的基本需求。值得注意的是,對于寫日志整個(gè)過程沒有使用額外的并發(fā)控制,主要是因?yàn)闃?biāo)準(zhǔn)IO庫<stdio>提供的讀寫函數(shù)都是線程安全的,多個(gè)線程可以對同一個(gè)FILE同時(shí)調(diào)用fwrite()。 每次寫完一條日志后,立即調(diào)用fflush()將緩存刷到操作系統(tǒng),但是并沒有調(diào)用fsync來落盤。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • ORA-00001: 違反唯一約束條件 (.) 錯(cuò)誤說明:當(dāng)在唯一索引所對應(yīng)的列上鍵入重復(fù)值時(shí),會(huì)觸發(fā)此異常。 O...
    我想起個(gè)好名字閱讀 5,980評論 0 9
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,668評論 1 32
  • 今天看到一位朋友寫的mysql筆記總結(jié),覺得寫的很詳細(xì)很用心,這里轉(zhuǎn)載一下,供大家參考下,也希望大家能關(guān)注他原文地...
    信仰與初衷閱讀 4,835評論 0 30
  • 在父母訓(xùn)練課程,來到三階段的時(shí)候,第一期的父母們開始每天的覺察,覺察什么呢?怎么覺察呢?覺察之后要做什么呢? 這本...
    黃麗浙江閱讀 867評論 1 7
  • 沒什么不好的 我這漂泊的浪兒 出身又不好 注定和你不是一個(gè)世界的人 你離開了很久 你離開有多久 我對你的思念便有多...
    會(huì)疼這思念閱讀 191評論 2 1

友情鏈接更多精彩內(nèi)容