在LevelDB中为了便于抛出异常,定义了一个Status类,用作函数的返回参数。
在枚举类型中定义了状态码。
class Status {
public:
...
private:
enum Code {
kOk = 0, //操作成功
kNotFound = 1, //没有找到相关项
kCorruption = 2,//数据异常崩溃
kNotSupported = 3, //表示不支持
kInvalidArgument = 4,//表示非法参数
kIOError = 5//表示IO操作错误
};
// state_[0..3] 为message长度
// state_[4]为code
// state_[5...]为message
// OK状态的state_为null。
const char* state_;
};这里将state_分为三段,来表示一个完整的错误信息,包括错误码与错误message。
提供判断Status类型的方法,即根据code的值判断:
public:
bool ok() const { return state_ == nullptr; }
bool IsNotFound() const { return code() == kNotFound; }
bool IsCorruption() const { return code() == kCorruption; }
bool IsNotSupported() const { return code() == kNotSupported; }
bool IsInvalidArgument() const { return code() == kInvalidArgument; }
bool IsIOError() const { return code() == kIOError; }
private:
Code code() const {
return (state_ == nullptr) ? kOk : static_cast<Code>(state_[4]);
}还需要能够获取错误信息的方法,能够直接获得错误信息的字符串:
std::string ToString() const;
std::string Status::ToString() const {
// 返回 错误类型:错误信息 这样的字符串
if (state_ == nullptr) {
return "OK";
}
const char* type;
char tmp[30];
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:
std::snprintf(tmp, sizeof(tmp), "Unknown code(%d): ", static_cast<int>(code()));
type = tmp;
}
std::string result(type);
uint32_t size;
memcpy(&size, state_, sizeof(size));
result.append(state_ + 5, size);
return result;
}还提供了静态方法用于快速创建对应错误类型的Status:
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) {
return Status(kCorruption, msg, msg2);
}
static Status NotFound(const Slice& msg, const Slice& msg2) {
return Status(kNotFound, msg, msg2);
}
static Status NotSupport(const Slice& msg, const Slice& msg2) {
return Status(kNotSupported, msg, msg2);
}
static Status InvalidArgument(const Slice& msg, const Slice& msg2) {
return Status(kInvalidArgument, msg, msg2);
}
static Status IOError(const Slice& msg, const Slice& msg2) {
return Status(kIOError, 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];
std::memcpy(result, &size, sizeof(size));
result[4] = static_cast<char>(code);
std::memcpy(result + 5, msg.data(), len1);
if (len2) {
result[5 + len1] = ':';
result[6 + len1] = ' ';
}
std::memcpy(result + 7 + len1, msg2.data(), len2);
state_ = result;
}