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