美文网首页
[LevelDB]状态类的设计

[LevelDB]状态类的设计

作者: 李若贤 | 来源:发表于2019-05-15 15:15 被阅读0次

    [LevelDB]状态类的设计.md

    LevelDB的状态类是leveldb::Status,以下简称Status

    状态信息的存储

    Status中使用char*来存储状态信息。

    // OK status has a null state_.  Otherwise, state_ is a new[] array
    // of the following form:
    //    state_[0..3] == length of message
    //    state_[4]    == code
    //    state_[5..]  == message
    const char* state_;
    

    如注释所说,其内容分为三部分,前4个字节存储从第6个字节开始的提示信息的长度,第5个字节存储状态码,之后的字节存储提示信息。

    状态码使用枚举类型表示。

    enum Code {
      kOk = 0,
      kNotFound = 1,
      kCorruption = 2,
      kNotSupported = 3,
      kInvalidArgument = 4,
      kIOError = 5
    };
    

    状态码一共有6个状态。但其实kOk不用于记录正常状态,而是用于与其他状态比对。当返回状态为正产时,理论上不需要任何提示信息,state_第一部分和第二部分存储的信息就不必存储信息,空留状态码意义不大,所以作者的做法是创建Ok类型的状态类时,直接将state_设置为空指针。

    创建状态信息

    状态信息的声明周期应为短暂的、一次性的,只需要创建状态信息,然后验证状态信息即可。LevelDB正是这样做的,去除默认构造函数和拷贝构造函数外,Status类中设计了6个静态成员函数,正好对应状态码的6个状态。其中生成Ok状态的函数直接调用默认构造函数,生成一个空状态对象。其余函数在调用时均需要传入1或2条提示信息,状态码在函数内自动赋予。

    以上静态函数是供调用者使用,实际上产生异常状态对象时,它们都调用同一个私有构造函数。

    Status(Code code, const Slice& msg, const Slice& msg2) {
      assert(code != kOk);
      const uint32_t len1 = msg.size();
      const uint32_t len2 = msg2.size();
      const uint32_t size = len1 + (len2 ? (2 + len2) : 0);
      char* result = new char[size + 5];
      memcpy(result, &size, sizeof(size));
      result[4] = static_cast<char>(code);
      memcpy(result + 5, msg.data(), len1);
      if (len2) {
        result[5 + len1] = ':';
        result[6 + len1] = ' ';
        memcpy(result + 7 + len1, msg2.data(), len2);
      }
      state_ = result;
    }
    

    在这个函数中可以看到状态信息的存储过程。

    创建状态码示例:

    Status LockFile(const std::string& fname, FileLock** lock) override {
      *lock = new FileLock;
      return Status::OK();
    }
    

    获取状态信息

    同创建状态信息一致,LevelDB也提供了6个获取状态类型的接口。

    // Returns true iff the status indicates success.
    bool ok() const { return (state_ == nullptr); }
    
    // Returns true iff the status indicates a NotFound error.
    bool IsNotFound() const { return code() == kNotFound; }
    
    // Returns true iff the status indicates a Corruption error.
    bool IsCorruption() const { return code() == kCorruption; }
    
    // Returns true iff the status indicates an IOError.
    bool IsIOError() const { return code() == kIOError; }
    
    // Returns true iff the status indicates a NotSupportedError.
    bool IsNotSupportedError() const { return code() == kNotSupported; }
    
    // Returns true iff the status indicates an InvalidArgument.
    bool IsInvalidArgument() const { return code() == kInvalidArgument; }
    

    除验证状态是否正常函数外,其他函数内部都是通过code()函数获取status_的第5位状态码值之后,与期望状态码值比较,返回布尔值。注意,当状态为正常时,code()函数会范围kOk的状态码,这就上文所说的kOk状态码的作用。

    获取状态信息示例:

    Status s = impl->Recover(&edit, &save_manifest);
    if (s.ok() && impl->mem_ == nullptr) {
      // Create new log and a corresponding memtable.
      uint64_t new_log_number = impl->versions_->NewFileNumber();
      WritableFile* lfile;
      s = options.env->NewWritableFile(LogFileName(dbname, new_log_number), &lfile);
      if (s.ok()) {
        edit.SetLogNumber(new_log_number);
        impl->logfile_ = lfile;
        impl->logfile_number_ = new_log_number;
        impl->log_ = new log::Writer(lfile);
        impl->mem_ = new MemTable(impl->internal_comparator_);
        impl->mem_->Ref();
      }
    }
    

    相关文章

      网友评论

          本文标题:[LevelDB]状态类的设计

          本文链接:https://www.haomeiwen.com/subject/svipaqtx.html