Leveldb也有提供快照,提供一致性且唯讀。
Snapshot使用方式
在dbImpl類裡,調用GetSnapshot(),回傳SnapshotList類的new方法(下方會介紹),用上一個序列號生成一個快照,並插入快照鍊表中
const Snapshot* DBImpl::GetSnapshot() {
MutexLock l(&mutex_);
return snapshots_.New(versions_->LastSequence());
}
調用ReleaseSnapshot(const Snapshot* s),回傳Snapshotlist類Delete方法刪除當前快照
void DBImpl::ReleaseSnapshot(const Snapshot* s) {
MutexLock l(&mutex_);
snapshots_.Delete(reinterpret_cast(s));
}
Snapshot底層實作
Snapshots是抽象類別,在db.h中,而快照的實現為SnapshotImpl定義於snapshot.h中,而Snapshotlist是一個環狀鏈結串鍊的資料結構class SnapshotImpl : public Snapshot {
public:
SequenceNumber number_; // const after creation
//保存當前快照的序列號
private:
friend class SnapshotList;
// SnapshotImpl is kept in a doubly-linked circular list
SnapshotImpl* prev_;
SnapshotImpl* next_;
SnapshotList* list_; // just for sanity checks
};
class SnapshotList {
public:
SnapshotList() {
list_.prev_ = &list_;
list_.next_ = &list_;
}
//這邊所提到的實現也就是剛剛上方Get與Release所使用的New與Delete方法
bool empty() const { return list_.next_ == &list_; }//判斷是否是空
SnapshotImpl* oldest() const { assert(!empty()); return list_.next_; }//取出最舊的快照
SnapshotImpl* newest() const { assert(!empty()); return list_.prev_; }//取出最新的快照
//插入環狀鏈結
const SnapshotImpl* New(SequenceNumber seq) {
SnapshotImpl* s = new SnapshotImpl;
s->number_ = seq;//儲存序列號
s->list_ = this;//初始化
s->next_ = &list_;//s的next指向串列
s->prev_ = list_.prev_;//的prev指向原本串列的prev(也就是最後一個,因為頭的prev繞指向尾巴)
s->prev_->next_ = s;//s的prev(也就是最後一個)的next指向s
s->next_->prev_ = s;//s的next(原本串列的第一個)的prev指向s
return s;
}
//刪除道理相反,這邊就不再次解釋
void Delete(const SnapshotImpl* s) {
assert(s->list_ == this);
s->prev_->next_ = s->next_;
s->next_->prev_ = s->prev_;
delete s;
}
private:
// Dummy head of doubly-linked list of snapshots
SnapshotImpl list_;
};
這裡一個小程式示範snapshot的用法
輸出為Kobe的舊背號8# include <iostream> # include <cassert> # include <leveldb/db.h> int main ( void ) { leveldb::DB *db; leveldb::Options options; options.create_if_missing= true ; leveldb::Status status=leveldb::DB::Open(options, "player" ,&db); assert(status.ok()); std :: string key1= "kobe" ; std :: string value1= "8" ; status=db->Put(leveldb::WriteOptions(),key1,value1); assert(status.ok()); leveldb::ReadOptions readoptions; readoptions.snapshot=db->GetSnapshot();//儲存snapshot std :: string value2= "24" ; status=db->Put(leveldb::WriteOptions(),key1,value2); assert(status.ok()); std :: string value; status=db->Get(readoptions,key1,&value);//記得要放入你創建的readoptions assert(status.ok()); std :: cout <<value<< std :: endl ; db->ReleaseSnapshot(readoptions.snapshot); delete db; return 0; }
沒有留言:
張貼留言