Fabric 1.0原始碼分析(21)Ledger #historydb(歷史資料庫)
# Fabric 1.0原始碼筆記 之 Ledger #historydb(歷史資料庫)
## 1、historydb概述
historydb,用於儲存所有塊讀寫集中寫集的內容。
程式碼分佈在core/ledger/kvledger/history/historydb目錄下,目錄結構如下:
* historydb.go,定義核心介面HistoryDBProvider和HistoryDB。
* histmgr_helper.go,historydb工具函式。
* historyleveldb目錄,historydb基於leveldb的實現。
* historyleveldb.go,HistoryDBProvider和HistoryDB介面實現,即historyleveldb.HistoryDBProvider和historyleveldb.historyDB結構體及方法。
* historyleveldb_query_executer.go,定義LevelHistoryDBQueryExecutor和historyScanner結構體及方法。
## 2、核心介面定義
HistoryDBProvider介面定義:
```go
type HistoryDBProvider interface {
GetDBHandle(id string) (HistoryDB, error) //獲取HistoryDB
Close() //關閉所有HistoryDB
}
//程式碼在core/ledger/kvledger/history/historydb/historydb.go
```
HistoryDB介面定義:
```go
type HistoryDB interface {
//構造 LevelHistoryDBQueryExecutor
NewHistoryQueryExecutor(blockStore blkstorage.BlockStore) (ledger.HistoryQueryExecutor, error)
//提交Block入historyDB
Commit(block *common.Block) error
//獲取savePointKey,即version.Height
GetLastSavepoint() (*version.Height, error)
//是否應該恢復,比較lastAvailableBlock和Savepoint
ShouldRecover(lastAvailableBlock uint64) (bool, uint64, error)
//提交丟失的塊
CommitLostBlock(block *common.Block) error
}
//程式碼在core/ledger/kvledger/history/historydb/historydb.go
```
補充ledger.HistoryQueryExecutor介面定義:執行歷史記錄查詢。
```go
type HistoryQueryExecutor interface {
GetHistoryForKey(namespace string, key string) (commonledger.ResultsIterator, error) //按key查歷史記錄
}
//程式碼在core/ledger/ledger_interface.go
```
## 3、historydb工具函式
```go
//構造複合HistoryKey,ns 0x00 key 0x00 blocknum trannum
func ConstructCompositeHistoryKey(ns string, key string, blocknum uint64, trannum uint64) []byte
//構造部分複合HistoryKey,ns 0x00 key 0x00 0xff
func ConstructPartialCompositeHistoryKey(ns string, key string, endkey bool) []byte
//按分隔符separator,分割bytesToSplit
func SplitCompositeHistoryKey(bytesToSplit []byte, separator []byte) ([]byte, []byte)
//程式碼在core/ledger/kvledger/history/historydb/histmgr_helper.go
```
## 4、HistoryDB介面實現
HistoryDB介面實現,即historyleveldb.historyDB結構體及方法。historyDB結構體定義如下:
```go
type historyDB struct {
db *leveldbhelper.DBHandle //leveldb
dbName string //dbName
}
//程式碼在core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go
```
涉及方法如下:
```go
//構造historyDB
func newHistoryDB(db *leveldbhelper.DBHandle, dbName string) *historyDB
//do nothing
func (historyDB *historyDB) Open() error
//do nothing
func (historyDB *historyDB) Close()
//提交Block入historyDB,將讀寫集中寫集入庫,並更新savePointKey
func (historyDB *historyDB) Commit(block *common.Block) error
//構造 LevelHistoryDBQueryExecutor
func (historyDB *historyDB) NewHistoryQueryExecutor(blockStore blkstorage.BlockStore) (ledger.HistoryQueryExecutor, error)
獲取savePointKey,即version.Height
func (historyDB *historyDB) GetLastSavepoint() (*version.Height, error)
//是否應該恢復,比較lastAvailableBlock和Savepoint
func (historyDB *historyDB) ShouldRecover(lastAvailableBlock uint64) (bool, uint64, error)
//提交丟失的塊,即呼叫historyDB.Commit(block)
func (historyDB *historyDB) CommitLostBlock(block *common.Block) error
//程式碼在core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go
```
func (historyDB *historyDB) Commit(block *common.Block) error程式碼如下:
```go
blockNo := block.Header.Number //區塊編號
var tranNo uint64 //交易編號,初始化值為0
dbBatch := leveldbhelper.NewUpdateBatch() //leveldb批量更新
//交易驗證程式碼,type TxValidationFlags []uint8
//交易篩選器
txsFilter := util.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
if len(txsFilter) == 0 {
txsFilter = util.NewTxValidationFlags(len(block.Data.Data))
block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsFilter
}
for _, envBytes := range block.Data.Data {
if txsFilter.IsInvalid(int(tranNo)) { //檢查指定的交易是否有效
tranNo++
continue
}
//[]byte反序列化為Envelope
env, err := putils.GetEnvelopeFromBlock(envBytes)
payload, err := putils.GetPayload(env) //e.Payload反序列化為Payload
//[]byte反序列化為ChannelHeader
chdr, err := putils.UnmarshalChannelHeader(payload.Header.ChannelHeader)
if common.HeaderType(chdr.Type) == common.HeaderType_ENDORSER_TRANSACTION { //背書交易,type HeaderType int32
respPayload, err := putils.GetActionFromEnvelope(envBytes) //獲取ChaincodeAction
txRWSet := &rwsetutil.TxRwSet{}
err = txRWSet.FromProtoBytes(respPayload.Results) //[]byte反序列化後構造NsRwSet,加入txRWSet.NsRwSets
for _, nsRWSet := range txRWSet.NsRwSets {
ns := nsRWSet.NameSpace
for _, kvWrite := range nsRWSet.KvRwSet.Writes {
writeKey := kvWrite.Key
//txRWSet中寫集入庫
compositeHistoryKey := historydb.ConstructCompositeHistoryKey(ns, writeKey, blockNo, tranNo)
dbBatch.Put(compositeHistoryKey, emptyValue)
}
}
} else {
logger.Debugf("Skipping transaction [%d] since it is not an endorsement transaction\n", tranNo)
}
tranNo++
}
height := version.NewHeight(blockNo, tranNo)
dbBatch.Put(savePointKey, height.ToBytes())
err := historyDB.db.WriteBatch(dbBatch, true)
//程式碼在core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go
```
Tx(Transaction 交易)相關更詳細內容,參考:[Fabric 1.0原始碼筆記 之 Tx(Transaction 交易)](../tx/README.md)
## 5、HistoryDBProvider介面實現
HistoryDBProvider介面實現,即historyleveldb.HistoryDBProvider結構體和方法。
```go
type HistoryDBProvider struct {
dbProvider *leveldbhelper.Provider
}
//構造HistoryDBProvider
func NewHistoryDBProvider() *HistoryDBProvider
//獲取HistoryDB
func (provider *HistoryDBProvider) GetDBHandle(dbName string) (historydb.HistoryDB, error)
//關閉所有HistoryDB控制程式碼,調取provider.dbProvider.Close()
func (provider *HistoryDBProvider) Close()
//程式碼在core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go
```
## 6、LevelHistoryDBQueryExecutor和historyScanner結構體及方法
LevelHistoryDBQueryExecutor結構體及方法:實現ledger.HistoryQueryExecutor介面。
```go
type LevelHistoryDBQueryExecutor struct {
historyDB *historyDB
blockStore blkstorage.BlockStore //用於傳遞給historyScanner
}
//按key查historyDB,呼叫q.historyDB.db.GetIterator(compositeStartKey, compositeEndKey)
func (q *LevelHistoryDBQueryExecutor) GetHistoryForKey(namespace string, key string) (commonledger.ResultsIterator, error)
//程式碼在core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb_query_executer.go
```
historyScanner結構體及方法:實現ledger.ResultsIterator介面。
```go
type historyScanner struct {
compositePartialKey []byte //ns 0x00 key 0x00
namespace string
key string
dbItr iterator.Iterator //leveldb迭代器
blockStore blkstorage.BlockStore
}
//構造historyScanner
func newHistoryScanner(compositePartialKey []byte, namespace string, key string, dbItr iterator.Iterator, blockStore blkstorage.BlockStore) *historyScanner
//按迭代器中key取blockNum和tranNum,再按blockNum和tranNum從blockStore中取Envelope,然後從Envelope的txRWSet.NsRwSets中按key查詢並構造queryresult.KeyModification
func (scanner *historyScanner) Next() (commonledger.QueryResult, error)
func (scanner *historyScanner) Close() //scanner.dbItr.Release()
從Envelope的txRWSet.NsRwSets中按key查詢並構造queryresult.KeyModification
func getKeyModificationFromTran(tranEnvelope *common.Envelope, namespace string, key string) (commonledger.QueryResult, error)
//程式碼在core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb_query_executer.go
```
補充queryresult.KeyModification:
```go
type KeyModification struct {
TxId string //交易ID,ChannelHeader.TxId
Value []byte //讀寫集中Value,KVWrite.Value
Timestamp *google_protobuf.Timestamp //ChannelHeader.Timestamp
IsDelete bool //KVWrite.IsDelete
}
//程式碼在protos/ledger/queryresult/kv_query_result.pb.go
```
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
相關文章
- Fabric 1.0原始碼分析(20) Ledger #idStore(ledgerID資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(19) Ledger #statedb(狀態資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(26)Orderer #ledger(Orderer Ledger)原始碼
- Fabric 1.0原始碼分析(18) Ledger(賬本)原始碼
- Fabric 1.0原始碼分析(23)LevelDB(KV資料庫)原始碼資料庫
- Fabric 1.0原始碼分析(22)Ledger #blkstorage(block檔案儲存)原始碼BloC
- Fabric 1.0原始碼分析(25) Orderer原始碼
- Fabric 1.0原始碼分析(31) Peer原始碼
- Fabric 1.0原始碼分析(3)Chaincode(鏈碼)原始碼AI
- Fabric 1.0原始碼分析(40) Proposal(提案)原始碼
- Fabric 1.0原始碼分析(14) flogging(Fabric日誌系統)原始碼
- Fabric 1.0原始碼分析(43) Tx(Transaction 交易)原始碼
- Fabric 1.0原始碼分析(47)Fabric 1.0.4 go程式碼量統計原始碼Go
- Fabric 1.0原始碼分析(42)scc(系統鏈碼)原始碼
- Fabric 1.0原始碼分析(13)events(事件服務)原始碼事件
- Fabric 1.0原始碼分析(39) policy(背書策略)原始碼
- Fabric 1.0原始碼分析(45)gRPC(Fabric中註冊的gRPC Service)原始碼RPC
- Fabric 1.0原始碼分析(10)consenter(共識外掛)原始碼
- Fabric 1.0原始碼分析(15)gossip(流言演算法)原始碼Go演算法
- Fabric 1.0原始碼分析(44)Tx #RWSet(讀寫集)原始碼
- Fabric 1.0原始碼分析(5)Chaincode(鏈碼)體系總結原始碼AI
- Fabric 1.0原始碼分析(6)configtx(配置交易) #ChannelConfig(通道配置)原始碼
- Fabric 1.0原始碼分析(29) Orderer #multichain(多鏈支援包)原始碼AI
- Fabric 1.0原始碼分析(30) Orderer #BroadcastServer(Broadcast服務端)原始碼ASTServer服務端
- Fabric 1.0原始碼分析(35)Peer #EndorserServer(Endorser服務端)原始碼Server服務端
- Fabric 1.0原始碼分析(36) Peer #EndorserClient(Endorser客戶端)原始碼client客戶端
- Fabric 1.0原始碼分析(37) Peer #DeliverClient(Deliver客戶端)原始碼client客戶端
- Fabric 1.0原始碼分析(38) Peer #BroadcastClient(Broadcast客戶端)原始碼ASTclient客戶端
- Fabric 1.0原始碼分析(41)putils(protos/utils工具包)原始碼
- Fabric 1.0原始碼分析(2) blockfile(區塊檔案儲存)原始碼BloC
- Fabric 1.0原始碼分析(7)configtx(配置交易) #configtxgen(生成通道配置)原始碼
- Fabric 1.0原始碼分析(9)configtx(配置交易)體系介紹原始碼
- Fabric 1.0原始碼分析(27) Orderer #configupdate(處理通道配置更新)原始碼
- Fabric 1.0原始碼分析(32) Peer #peer node start命令實現原始碼
- Fabric 1.0原始碼分析(42)scc(系統鏈碼) #cscc(通道相關)原始碼
- Fabric 1.0原始碼分析(4)Chaincode(鏈碼)#platforms(鏈碼語言平臺)原始碼AIPlatform
- Fabric 1.0原始碼分析(28) Orderer #localconfig(Orderer配置檔案定義)原始碼
- Fabric 1.0原始碼分析(11)consenter(共識外掛) #filter(過濾器)原始碼Filter過濾器