LevelDB的返回状态status
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的主要内容,如果未能解决你的问题,请参考以下文章