[LevelDB]狀態(tài)類的設(shè)計.md
LevelDB的狀態(tài)類是leveldb::Status
幅垮,以下簡稱Status
祭陷。
狀態(tài)信息的存儲
Status
中使用char*
來存儲狀態(tài)信息球及。
// 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
const char* state_;
如注釋所說,其內(nèi)容分為三部分,前4個字節(jié)存儲從第6個字節(jié)開始的提示信息的長度,第5個字節(jié)存儲狀態(tài)碼雇逞,之后的字節(jié)存儲提示信息。
狀態(tài)碼使用枚舉類型表示茁裙。
enum Code {
kOk = 0,
kNotFound = 1,
kCorruption = 2,
kNotSupported = 3,
kInvalidArgument = 4,
kIOError = 5
};
狀態(tài)碼一共有6個狀態(tài)塘砸。但其實kOk
不用于記錄正常狀態(tài),而是用于與其他狀態(tài)比對呜达。當(dāng)返回狀態(tài)為正產(chǎn)時谣蠢,理論上不需要任何提示信息,state_
第一部分和第二部分存儲的信息就不必存儲信息查近,空留狀態(tài)碼意義不大眉踱,所以作者的做法是創(chuàng)建Ok類型的狀態(tài)類時,直接將state_
設(shè)置為空指針霜威。
創(chuàng)建狀態(tài)信息
狀態(tài)信息的聲明周期應(yīng)為短暫的谈喳、一次性的,只需要創(chuàng)建狀態(tài)信息戈泼,然后驗證狀態(tài)信息即可婿禽。LevelDB正是這樣做的赏僧,去除默認(rèn)構(gòu)造函數(shù)和拷貝構(gòu)造函數(shù)外,Status
類中設(shè)計了6個靜態(tài)成員函數(shù)扭倾,正好對應(yīng)狀態(tài)碼的6個狀態(tài)淀零。其中生成Ok狀態(tài)的函數(shù)直接調(diào)用默認(rèn)構(gòu)造函數(shù),生成一個空狀態(tài)對象膛壹。其余函數(shù)在調(diào)用時均需要傳入1或2條提示信息驾中,狀態(tài)碼在函數(shù)內(nèi)自動賦予。
以上靜態(tài)函數(shù)是供調(diào)用者使用模聋,實際上產(chǎn)生異常狀態(tài)對象時肩民,它們都調(diào)用同一個私有構(gòu)造函數(shù)。
Status(Code code, const Slice& msg, const Slice& msg2) {
assert(code != kOk);
const uint32_t len1 = msg.size();
const uint32_t len2 = 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;
}
在這個函數(shù)中可以看到狀態(tài)信息的存儲過程链方。
創(chuàng)建狀態(tài)碼示例:
Status LockFile(const std::string& fname, FileLock** lock) override {
*lock = new FileLock;
return Status::OK();
}
獲取狀態(tài)信息
同創(chuàng)建狀態(tài)信息一致持痰,LevelDB也提供了6個獲取狀態(tài)類型的接口。
// 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; }
除驗證狀態(tài)是否正常函數(shù)外祟蚀,其他函數(shù)內(nèi)部都是通過code()
函數(shù)獲取status_
的第5位狀態(tài)碼值之后工窍,與期望狀態(tài)碼值比較,返回布爾值暂题。注意移剪,當(dāng)狀態(tài)為正常時,code()
函數(shù)會范圍kOk
的狀態(tài)碼薪者,這就上文所說的kOk
狀態(tài)碼的作用纵苛。
獲取狀態(tài)信息示例:
Status s = impl->Recover(&edit, &save_manifest);
if (s.ok() && impl->mem_ == nullptr) {
// Create new log and a corresponding memtable.
uint64_t new_log_number = impl->versions_->NewFileNumber();
WritableFile* lfile;
s = options.env->NewWritableFile(LogFileName(dbname, new_log_number), &lfile);
if (s.ok()) {
edit.SetLogNumber(new_log_number);
impl->logfile_ = lfile;
impl->logfile_number_ = new_log_number;
impl->log_ = new log::Writer(lfile);
impl->mem_ = new MemTable(impl->internal_comparator_);
impl->mem_->Ref();
}
}