Overview
對MergingIterator的遍歷會有序的遍歷其child iterator中的每個元素。
因為iter_遍歷的是數(shù)據(jù)庫的每一條記錄。它是以InternalKey(userkey, seq, type)為遍歷粒度的,只要InternalKey中任意一個組成元素不同,MergingIterator就認為他們是不同的kv對。
而DBIter是以userkey為遍歷粒度的,只要記錄的userkey相同,那么DBIter就認為他們是一條記錄(不同版本),sqe越大代表該記錄越新。每次迭代將跳到下一個不同userkey的記錄。
假設當前DBIter的sequence_為2,那么DBIter只會處理seq小于2的記錄,這也是訪問快照數(shù)據(jù)的原理。
圖中每個框框表示對應記錄的InternalKey(userkey, seq, type),key1 < key2 < key3 < key4,seq越大代表記錄越新,所以相同userkey的seq越大的順序越靠前(?。?。
Design 以下**
saved key
DBIter next的實現(xiàn)
假設iter_現(xiàn)在在key2:2:1的位置,DBIter也在這個位置,此時iter_的next會是key2:1:1。而DBIter的next將會是key4:2:1(因為key3:3:1seq不符,key3:2:0是一條刪除記錄,因此跳過key3:2:0和key3:1:1,key4:2:1seq不符)。
假設當前iter在key4:2:1上,direction為kForward。此時調用Prev(),此圖顯示了Prev操作執(zhí)行的5個步驟。
S1 首先因為direction為kForward,先調整iter到key3:1:1上。此圖也說明了調整的理由,key4:2:1前面還有key4:3:1。然后進入FindPrevUserEntry函數(shù),執(zhí)行S2到S4。
S2 跳到key3:2:0上時,這是一個刪除標記,清空saved key(其中保存的是key3:1:1)。
S3 循環(huán)繼續(xù),跳到key2:1:1上,此時key2:1:1 > saved key,設置saved key為key2:1:1,并繼續(xù)循環(huán)。
S4 循環(huán)繼續(xù),跳到key2:2:1上,此時key2:2:1 > saved key,設置saved key為key2:2:1,并繼續(xù)循環(huán)。
S5 跳到Key1:1:1上,因為key1:1:1 < saved key,跳出循環(huán)。
最終狀態(tài)iter_位置在key1:1:1上,而saved key保存的則是key2:2:1上,這也就是Prev應該定位到的值。也就是說在Prev操作下,iter_的位置并不是真正的key位置。這就是Get函數(shù)中,在direction為kReverse時,返回saved key/value的原因。
同理,在Next時,如果direction是kReverse,根據(jù)上面的Prev可以發(fā)現(xiàn),此時iter剛好是saved key的前一個entry。執(zhí)行iter->Next()就跳到了saved key的dentry范圍的sequence最大的那個entry。在前面的例子中,在Prev后執(zhí)行Next,那么iter首先跳轉到key2:3:1上,然后再調用FindNextUserEntry循環(huán),使iter定位在key2:2:1上。
prev的小結
prev就是要向前找到第一個符合條件的kv記錄,該記錄的userkey必須小于當前iter的userkey,并且該記錄是最新的而且不能是刪除類型的記錄。如何判斷出該記錄是不是最新的呢,先將該記錄保存在save(saved key/value)里,iter_繼續(xù)向前遍歷,如果遇到userkey和剛才save的記錄userkey不相等的,則說明剛才save的就是最新的記錄,此時iter_的位置并不是真正的key位置,saved key才是真正key的位置,因此需要用Direction來區(qū)分。
1) kForward,正向遍歷(向后移動),代碼保證此時DBIter的內部迭代器剛好定位在this->key(),this->value()這條記錄上;此時iter_一定是在一條最新的記錄上(seq最大的記錄上(當然seq得小于sequence_))
2) kReverse,反向遍歷(向前移動),代碼保證此時DBIter的內部迭代器剛好定位在所有key=this->key()的entry之前。此時iter_一定是在一條最老的記錄上。
其成員變量savedkey和saved value保存的是KReverse方向移動完成后的k/v對,每次seek系調用之后,其值都會跟隨iter_而改變。
Detail?Source?Code?Analysis?
please?look?at?my github: cld378632668
https://github.com/cld378632668/leveldb_chinese_comments
void DBIter::FindNextUserEntry(
void DBIter::FindPrevUserEntry()
Ref and Consult
http://blog.csdn.net/weixin_36145588/article/details/78690482