leveldb源码学习之基本数据结构Status

Leveldb 中的返回,将错误码和错误信息封装成Status类,统一进行处理。并定义了几种具体的返回状态。

为了节省空间Status并没有用std::string来存储错误信息,而是将返回码(code), 错误信息message及长度打包存储于一个字符串数组中。

成功状态OK 是NULL state_,否则state_ 是一个包含如下信息的数组:  

state_[0..3] == 消息message长度 

state_[4]    == 消息code

state_[5..]  ==消息message 
 

include/leveldb/status.h

// Status 封装了一次操作的结果。可以表示成功、或失败与相关信息.
//
// 多线程可以在不借助同步机制下调用const函数访问,若调用const函数,则必须有同步机制.

#ifndef STORAGE_LEVELDB_INCLUDE_STATUS_H_
#define STORAGE_LEVELDB_INCLUDE_STATUS_H_

#include <algorithm>
#include <string>

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

namespace leveldb {

class LEVELDB_EXPORT Status {
 public:
  // 创建一个成功的状态,空表示成功。.
  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;

  // 返回成功状态.
  static Status OK() { return Status(); }

  // 返回某种类型的错误状态.
  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);
  }

  // 若表示成功返回true.
  bool ok() const { return (state_ == nullptr); }

  // 若表示NotFound返回true.
  bool IsNotFound() const { return code() == kNotFound; }

  // 若表示Corruption 返回true.
  bool IsCorruption() const { return code() == kCorruption; }

  //若表示IOError返回true.
  bool IsIOError() const { return code() == kIOError; }

  // 若表示NotSupportedError返回true
  bool IsNotSupportedError() const { return code() == kNotSupported; }

  // 若表示InvalidArgument返回true .
  bool IsInvalidArgument() const { return code() == kInvalidArgument; }

  // 返回表示当前状态的可输入信息,成功返回 "OK" .
  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(Code code, const Slice& msg, const Slice& msg2);
  static const char* CopyState(const char* s);

  // OK 状态的state_为null.  否则 state_ 是以下形式的数组:
  //    state_[0..3] == 错误信息长度
  //    state_[4]    == 错误码
  //    state_[5..]  == 错误信息
  const char* state_;
};

inline Status::Status(const Status& rhs) {
  state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_);
}
inline Status& Status::operator=(const Status& rhs) {
  // 以下条件可判断是否自赋值 (when this == &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;
}

}  // namespace leveldb

#endif  // STORAGE_LEVELDB_INCLUDE_STATUS_H_

util/status.cc
 

#include "leveldb/status.h"
#include <stdio.h>
#include "port/port.h"
namespace leveldb {

const char* Status::CopyState(const char* state) {
  uint32_t size; 
  memcpy(&size, state, sizeof(size));// 获取status 中错误信息长度
  char* result = new char[size + 5]; // 总的长度为信息+错误码+长度
  memcpy(result, state, size + 5);
  return result;
}

// 构造Status ,msg2可以为空,否则是msg: 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);
  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;
}

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));
    result.append(state_ + 5, length);
    return result;
  }
}

}  // namespace leveldb

 

 

 

Leveldb源码分析

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值