LevelDB的返回状态status

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LevelDB的返回状态status相关的知识,希望对你有一定的参考价值。

LevelDB的返回状态status

include/leveldb/status.h

#include "leveldb/export.h"
#include "leveldb/slice.h"

namespace leveldb {

//对于OK消息,值就是nullptr
//对于不OK的消息,如果没有msg2那么值为:
	//size | code | msg
//对于不OK的消息,如果有msg2那么值为:
	//size | code | msg: msg2
    
class LEVELDB_EXPORT Status {
 public:
  // Create a success status.
    //初始化state_为nullptr,表示OK消息
  Status() noexcept : state_(nullptr) {}
    //析构,释放堆内存
  ~Status() { delete[] state_; }
//拷贝构造函数和拷贝赋值运算符声明为const的引用
  Status(const Status& rhs);
  Status& operator=(const Status& rhs);
//移动构造函数和移动赋值运算符声明为noexcept
  Status(Status&& rhs) noexcept : state_(rhs.state_) { rhs.state_ = nullptr; }
  Status& operator=(Status&& rhs) noexcept;

  // Return a success status.
    //调用默认构造函数啦,此时state_为nullptr,表示OK消息
  static Status OK() { return Status(); }

  // Return error status of an appropriate type.
    //下面这几个都调用了私有的构造函数,根据具体消息构造status,这个私有构造函数的实现在status.cc中
  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);
  }
//下面几个方法是判断消息是否是属于所给类型,是根据code()方法返回枚举变量中的值来实现的
  // 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; }

  // Return a string representation of this status suitable for printing.
  // Returns the string "OK" for success.
    //将status转换成字符串
  std::string ToString() const;

 private:
    //枚举变量成员
  enum Code {
    kOk = 0,
    kNotFound = 1,
    kCorruption = 2,
    kNotSupported = 3,
    kInvalidArgument = 4,
    kIOError = 5
  };
	//返回枚举变量成员的值
  Code code() const {
    return (state_ == nullptr) ? kOk : static_cast<Code>(state_[4]);
  }
//构造函数,在status.cc中实现
  Status(Code code, const Slice& msg, const Slice& msg2);
    //在status.cc中实现,用于复制一个state_,不仅仅是复制一个指针,而是复制指针里面的值,是深拷贝
  static const char* CopyState(const char* s);

  // 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
    //0-3字节是消息的长度,就是上面私有构造函数的msg1+msg2+2
    //4字节是消息的类型,也就是上面枚举类型的值
    //5字节后面的数据就是具体的消息了
    //指针state_指向了消息
  const char* state_;
};
//拷贝构造函数
inline Status::Status(const Status& rhs) {
    //注意这里是深拷贝,因为调用的是CopyState()
  state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_);
}
inline Status& Status::operator=(const Status& rhs) {
  // The following condition catches both aliasing (when this == &rhs),
  // and the common case where both rhs and *this are ok.
    //首先判断是不是自己给自己赋值
  if (state_ != rhs.state_) {
      //不是给自己赋值,就先释放自己的内存,然后深拷贝
    delete[] state_;
    state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_);
  }
  return *this;
}
    //移动赋值运算符
inline Status& Status::operator=(Status&& rhs) noexcept {
    //直接交换两个指针的值就OK了,之所以能行,是因为之前state_的值是nullptr
  std::swap(state_, rhs.state_);
  return *this;
}

}  // namespace leveldb

util/status.cc

#include "leveldb/status.h"

#include <cstdio>

#include "port/port.h"

//对于OK消息,值就是nullptr
//对于不OK的消息,如果没有msg2那么值为:
	//size | code | msg
//对于不OK的消息,如果有msg2那么值为:
	//size | code | msg: msg2

namespace leveldb {

const char* Status::CopyState(const char* state) {
    //记住这个类型uint32_t,它占4个字节
  uint32_t size;
    //将参数state的前4个字节拷贝给size,其实就是赋值啦
  std::memcpy(&size, state, sizeof(size));
    //然后申请内存,这个size的大小是上面msg: msg2的长度,5是size和code的长度
  char* result = new char[size + 5];
    //将state指向的字符串拷贝给刚创建的数组,然后返回刚创建的数组
  std::memcpy(result, state, size + 5);
  return result;
}
//这就是那个私有的构造函数啦
Status::Status(Code code, const Slice& msg, const Slice& msg2) {
    //当然状态不能是OK,因为这不是OK的构造函数
  assert(code != kOk);
  const uint32_t len1 = static_cast<uint32_t>(msg.size());
  const uint32_t len2 = static_cast<uint32_t>(msg2.size());
    //如果有msg2,那么总长度就是msg+\': \'+msg2,其中的2就是这个冒号和空格的长度
    //如果没有msg2,那么总长度自然就是msg的长度了
  const uint32_t size = len1 + (len2 ? (2 + len2) : 0);
    //这个5就是size和code的长度啦,size+5就是size+code+msg的总长度了
  char* result = new char[size + 5];
    //将消息的长度拷贝到前4个字节,是msg+msg2+": "的长度
  std::memcpy(result, &size, sizeof(size));
    //数组下标4的地方就放code了,注意枚举类型转换成char
  result[4] = static_cast<char>(code);
    //接下来拷贝msg的值
  std::memcpy(result + 5, msg.data(), len1);
  if (len2) {
      //如果有msg2,那么就跟着在后面拷贝": "和msg2
    result[5 + len1] = \':\';
    result[6 + len1] = \' \';
    std::memcpy(result + 7 + len1, msg2.data(), len2);
  }
    //返回,然后结束
  state_ = result;
}

    //这个就是转换成string了
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(char *buffer,size_t buf_size,char *format....)
            //能够向buffer中最多拷贝buf_size-1个字节,因为最后一个字节要放置\'\\0\'
        std::snprintf(tmp, sizeof(tmp),
                      "Unknown code(%d): ", static_cast<int>(code()));
        type = tmp;
        break;
    }
      //使用char *构造string
    std::string result(type);
    uint32_t length;
      //获取消息长度,为msg+": "+msg2的长度
    std::memcpy(&length, state_, sizeof(length));
      //然后将消息添加到string的后面
      // string.append(char *ptr,int n)
      //将ptr开始的n个字符添加到string后面
    result.append(state_ + 5, length);
    return result;
  }
}

}  // namespace leveldb

以上是关于LevelDB的返回状态status的主要内容,如果未能解决你的问题,请参考以下文章

XMLHttpRequest.status 返回服务器状态码

[leveldb] Recover

HTTP状态码 (HTTP Status Code)

HTTP状态码(HTTP Status Code)

HTTP协议状态码详解(HTTP Status Code)

HTTP协议状态码详解(HTTP Status Code)