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; }
沒有留言:
張貼留言