上一篇我們隊leveldb功能和靜態結構有個基礎的認識,那麼現在我們主要對leveldb源碼下各個文件的作用和結構做一個梳理。搞清楚各個類的功能和層級關係。
首先時include下的頭文件:
include
└── leveldb
├── c.h => c binding
├── cache.h => cache接口
├── comparator.h => 比較器接口
├── db.h => DB接口
├── env.h => 爲跨平臺準備的env接口
├── filter_policy.h => fliter策略,用於緩存,請看到文檔及相應實現
├── iterator.h => 迭代器,用於遍歷數據庫中存儲的數據
├── options.h => 包含控制數據庫的Options,控制讀的WriteOptions,ReadOptions
├── slice.h => Slice的接口
├── status.h => leveldb中大多接口返回的Status接口
├── table.h => immutable接口
├── table_builder.h => 用於創建table的構建器接口
└── write_batch.h => 使多個寫操作成爲原子寫的接口
c.h作用是爲了leveldb的C綁定。可用作穩定的ABI,可由將leveldb保留在共享庫中的程序使用,也可以用於JNI api。
(我們這裏主要關注c++11版本的leveldb,所以做個瞭解就好,用c將大部分c++的接口進行了封裝,讓c語言也可以使用leveldb。)
cache.h
顧名思義就是緩存啦,這裏採用的時LRU策略,同時對於不同條目會有動態的空間花費。觀察相應成員,成員函數:插入,查找,釋放,刪除,注意到這裏定義了一個空的結構體handler,handler的作用時在cache中實現kv之間的映射,至於爲什麼時空的,查閱博客知道所以Handle僅僅是一個虛的結構體.在具體實現時,可以參考leveldb.先自己定義一個結構體,在實現Cache相應的函數時,在返回或使用時調用reinterpret_cast<Cache::Handle*>。個人理解是先聲明一個空的結構體佔位一下,日後可以具體實現。
私有成員以及函數沒理解。在LRUCache中果然也沒有對應實現。所以暫時不說。
slice.h
slice是google定義的一個簡單的結構體,其中只有兩個成員,一個指向外存的指針,一個是大小。
slice的使用必須保證對應的外存沒有被釋放,同時多線程可以調用一個slice的常量方法無需同步,非常量則需要同步。
slice其實是google對字符串操作的精簡版,相較c++ 自帶的string,slice更加精簡,本身無法動態開闢空間,從拷貝函數可以看出,拷貝的僅僅是一個指針。因此,開銷會小很多。同時,C++ string和以null結尾的C風格字符串可以很方便的轉換成Slice
status.h
status.h中包含了Status
的聲明.Status
是leveldb大多數函數調用的返回值.其作用類似於errno,只不過封裝的更爲完善,也更爲c++.
Status的數據存儲在state_
中.state_
是一個長度至少爲6的字符串.前四位爲message的length,第5位爲status的狀態,再之後的爲message.
table.h
table是一個字符串排序後的表,它是不可改動的。成員函數包括了從文件中讀取table等一些操作
table_builder.h
table_builder主要是提供構建table的相關接口函數。
option.h
option主要定義了數據庫中各個部分的參數,數據壓縮類型,比較函數,block的size,讀的參數,寫的參數,等。
writebatch.h
定義了插入,刪除數據的一些原子操作,以及利用handler對數據的批量操作。這裏提到了append要比用iterate然後每個都put要快,這裏我還沒看具體實現,還不知道爲啥,先mark。
env.h
env.h 將系統調用
,文件操作
,文件鎖
,線程庫
等系統調用進行了封裝,成爲了Env
.另外將文件抽象成了RandomAccessFile
,SequentialFile
,WritableFile
.這麼抽象的好處顯而易見: 跨平臺更爲簡單.客戶端調用接口抽象出來的一致方法.使得不同平臺下的代碼更爲一致.而實現跨平臺也很簡單.無論是windows,還是*nix,甚至是android及ios,各個平臺只需要實現相應的方法就能完成port的工作.這種方式在開發跨平臺代碼時很值得借鑑.
filter_policy.h
filter_policy.h 作用是利用過濾器來查找key值的有無,https://www.jianshu.com/p/2104d11ee0a2這篇文章講的很好。關於布隆過濾器的。
db.h
db.h是使用leveldb時最經常include的頭文件.在這個頭文件中提供了DB的接口的定義,也是我們需要的部分.在db.h中,定義了Snapshot
,Range
,DB
三個接口.Range爲一個Slice對,定義了[start,end).符合C++的習慣.Snapshot
爲DB的某個特定狀態.由於其只讀,因此多線程訪問並不需要鎖.還有一些相應的函數,文檔寫的很清楚。就不過多贅述了。
這次主要解讀了include文件夾下頭文件的意義。下一章我們將從靜態結構入手,逐步仔細分析各組件的具體實現。