zoukankan      html  css  js  c++  java
  • 【LevelDB源码阅读】Status

    是什么

    status用来判断函数返回的状态信息,封装了错误码和错误信息。

    为什么要用

    • 为了便于管理和定位错误类型,一般大型系统都自定义自己的函数返回状态信息

    学到什么

    • void *memcpy(void *str1, const void *str2, size_t n):从存储区 str2 复制 n 个字节到存储区 str1
    • 使用枚举类型定义多种状态
    • 字符串可以分为多个部分,不同部分描述不同内容
    • 通过static成员函数构造对象
    • noexcept使用
    • 格式化字符串snprint
    • 字符串追加s.append(args)

    源码分析

    将不同返回值码定义为一个枚举类型。

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

    枚举类型本质是一种int类型,4个字节,上述枚举类型定义不占用内存空间,只有当定义枚举类型变量时才占用空间,如: Code code,code只能使用声明中列出的字符串来初始化。

    Status本质就一个成员变量const char *state_,为了节省内存,state_分为三部分使用:

    • state_[0..3] == length of message
    • state_[4] == code
    • state_[5..] == message

    拷贝控制
    关键字noexcept声明符表明该函数不会抛出异常。
    主要优点:

    • 知道函数不会抛出异常有助于简化调用该函数代码
    • 编译器可以执行某些特殊优化操作
      // Create a success status.
      Status() noexcept : state_(nullptr) {}
      ~Status() { delete[] state_; }
    
      Status(const Status &rhs);
      Status& operator=(const Status &rhs);
    
      Status(Status &&rhs) noexcept : state_(rhs.state_) { rhs.state_ = nullptr; }
      Status& operator=(Status &&rhs) noexcept;
    

    具体实现

    inline Status::Status(const Status &rhs) {
      state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_);
    }
    inline Status& Status::operator=(const Status &rhs) {
      if (state_ != rhs.state_) {
        delete[] state_;
        state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_);
      }
      return *this;
    }
    inline Status& Status::operator=(Status &&rhs) noexcept {
      std::swap(state_, rhs.state_);
      return *this;
    }
    

    其中拷贝构造和拷贝赋值本质都是调用CopyState来完成,重新开辟一块内存存储s.state_并将指针赋给调用函数的s.state_,CopyState实现如下:

    const char* Status::CopyState(const char *state) {
      uint32_t size;
      memcpy(&size, state, sizeof(size));  // 复制长度到size
      char *result = new char[size + 5];  // 结果总长度包括前面5个字节
      memcpy(result, state, size + 5);  // 复制完整state内容,长度为size + 5
      return result;
    }
    

    主要对外接口
    直接返回特定类型对象

      // Return a success status.
      static Status OK() { return Status(); }
    
      // Return error status of an appropriate type.
      static Status NotFound(const Slice &msg, const Slice &msg2 = Slice()) {
        return Status(kNotFound, msg, msg2);
      }
      static Status Corruption(const Slice &msg, const Slice &msg2 = Slice()) {
        return Status(kCorruption, msg, msg2);
      }
      static Status NotSupported(const Slice &msg, const Slice &msg2 = Slice()) {
        return Status(kNotSupported, msg, msg2);
      }
      static Status InvalidArgument(const Slice &msg, const Slice &msg2 = Slice()) {
        return Status(kInvalidArgument, msg, msg2);
      }
      static Status IOError(const Slice &msg, const Slice &msg2 = Slice()) {
        return Status(kIOError, msg, msg2);
      }
    

    调用例子

    Status s;
    s = Status::Corruption("corrupted key for ", user_key);  // 会用到赋值操作符
    

    这几个函数又直接调用以下函数

    Status(Code code, const Slice &msg, const Slice &msg2);
    

    具体实现如下:

    Status::Status(Code code, const Slice &msg, const Slice &msg2) {
      assert(code != kOk);
      const uint32_t len1 = static_cast<uint32_t>(msg.size());
      const uint32_t len2 = static_cast<uint32_t>(msg2.size());
      const uint32_t size = len1 + (len2 ? (2 + len2) : 0);  // 2表示':'和' '
      char *result = new char[size + 5];  // state_总长度包括前面5个字节
      memcpy(result, &size, sizeof(size));  // 信息长度存入前4个字节
      result[4] = static_cast<char>(code);  // 状态存入第5个字节
      memcpy(result + 5, msg.data(), len1);  // 从第6个字节开始存储信息内容
      if (len2) {  // 如果msg2不为空,则信息内容加上': ' + msg2
        result[5 + len1] = ':';
        result[6 + len1] = ' ';
        memcpy(result + 7 + len1, msg2.data(), len2);
      }
      state_ = result;
    }
    

    判断状态成员方法

      // 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()方法返回状态,Code()实现如下:

      Code code() const {
        return (state_ == nullptr) ? kOk : static_cast<Code>(state_[4]);
      }
    

    输出状态

    std::string Status::ToString() const {
      if (state_ == nullptr) {
        return "OK";
      } else {
        char tmp[30];
        const char *type;
        switch (code()) {
          case kOk:
            type = "OK";
            break;
          case kNotFound:
            type = "NotFound: ";
            break;
          case kCorruption:
            type = "Corruption: ";
            break;
          case kNotSupported:
            type = "Not implemented: ";
            break;
          case kInvalidArgument:
            type = "Invalid argument: ";
            break;
          case kIOError:
            type = "IO error: ";
            break;
          default:
            snprintf(tmp, sizeof(tmp),
                     "Unknown code(%d): ", static_cast<int>(code()));
            type = tmp;
            break;
        }
        std::string result(type);
        uint32_t length;
        memcpy(&length, state_, sizeof(length));  // 取出state_信息长度存入length
        result.append(state_ + 5, length);  // 添加具体信息
        return result;  // 返回type + 具体信息
      }
    }
    

    其中snprintf将格式化的n个字节数据写入字符串,函数原型如下:

     int snprintf(char *str, int n, char * format [, argument, ...]);
    
  • 相关阅读:
    2017区块链七大趋势,概念热炒之后行业如何发展?
    区块链三大方向:比特币,其他公有链和区块链联盟,以及私有链。
    这条消息被许多人忽视,但对房价可能“一剑封喉”!
    世界主要城市名称中英文对照
    2016全球城市竞争力排行榜
    全球城市群Megalopolis
    gawc全球城市
    2016全球资产配置白皮书(附下载)
    160. Intersection of Two Linked Lists
    save change is not permitted
  • 原文地址:https://www.cnblogs.com/galaxy-hao/p/13063597.html
Copyright © 2011-2022 走看看