在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;
}