標籤:items tin sig buffer and filename 大小 addm res
Fabric 1.0原始碼筆記 之 blockfile(區塊檔案儲存體)1、blockfile概述
blockfile,即Fabric區塊鏈區塊檔案儲存體,預設目錄/var/hyperledger/production/ledgersData/chains,含index和chains兩個子目錄。
其中index為索引目錄,採用leveldb實現。而chains為各ledger的區塊鏈檔案,子目錄以ledgerid為名,使用檔案系統實現。
區塊檔案以blockfile_為首碼,最大大小預設64M。
blockfile,相關代碼集中在common/ledger/blkstorage/fsblkstorage目錄,目錄結構如下:
- blockfile_mgr.go,blockfileMgr和checkpointInfo結構體及方法。
- block_stream.go,blockfileStream、blockStream、blockPlacementInfo結構體及方法。
- blockfile_rw.go,blockfileWriter和blockfileReader結構體及方法(blockfileReader未使用)。
- blockindex.go,index介面定義,index介面實現即blockIndex結構體及方法定義,以及blockIdxInfo、locPointer、fileLocPointer結構體及方法。
- blockfile_helper.go,定義了4個工具函數,constructCheckpointInfoFromBlockFiles、retrieveLastFileSuffix、isBlockFileName、getFileInfoOrPanic。
作用分別為:掃描最新的blockfile並重新構造檢查點資訊、擷取最新的檔案尾碼、根據檔案首碼判斷是否為區塊檔案、擷取檔案狀態資訊。
- block_serialization.go,block序列化相關工具函數。
- blocks_itr.go,blocksItr結構體及方法。
2、Block結構體定、以及Block序列化2.1、Block相關結構體
Block結構體:
type Block struct {????Header *BlockHeader //BlockHeader????Data *BlockData //BlockData????Metadata *BlockMetadata}func (m *Block) GetHeader() *BlockHeader //擷取BlockHeader,即m.Headerfunc (m *Block) GetData() *BlockData //擷取BlockData,即m.Datafunc (m *Block) GetMetadata() *BlockMetadata //m.Metadata//代碼在protos/common/common.pb.go
BlockHeader結構體:
type BlockHeader struct {????Number uint64 //區塊編號????PreviousHash []byte //前一個區塊雜湊????DataHash []byte //當前區塊雜湊}func (m *BlockHeader) GetNumber() uint64 //擷取區塊編號,即m.Numberfunc (m *BlockHeader) GetPreviousHash() []byte //擷取前一個區塊雜湊,即m.PreviousHashfunc (m *BlockHeader) GetDataHash() []byte //擷取當前區塊雜湊,即m.DataHash//代碼在protos/common/common.pb.go
BlockData結構體:
type BlockData struct {????Data [][]byte //Data,儲存體交易資訊}func (m *BlockData) GetData() [][]byte //擷取Data,即m.Data//代碼在protos/common/common.pb.go
BlockMetadata結構體:
type BlockMetadata struct {????Metadata [][]byte //K/V均為[]byte格式}func (m *BlockMetadata) GetMetadata() [][]byte //m.Metadata//代碼在protos/common/common.pb.go
補充BlockMetadataIndex:
type BlockMetadataIndex int32const (????BlockMetadataIndex_SIGNATURES BlockMetadataIndex = 0????BlockMetadataIndex_LAST_CONFIG BlockMetadataIndex = 1????BlockMetadataIndex_TRANSACTIONS_FILTER BlockMetadataIndex = 2????BlockMetadataIndex_ORDERER BlockMetadataIndex = 3)
2.2、Block序列化
serializedBlockInfo結構體定義及工具函數:
type serializedBlockInfo struct {????blockHeader *common.BlockHeader //BlockHeader????txOffsets []*txindexInfo //交易索引資訊????metadata *common.BlockMetadata}type txindexInfo struct {????txID string //交易ID????loc *locPointer //檔案指標}//序列化區塊,返回序列化後位元組,以及serializedBlockInfo(含BlockHeader和交易索引資訊)func serializeBlock(block *common.Block) ([]byte, *serializedBlockInfo, error)//還原序列化區塊,構建Block結構體func deserializeBlock(serializedBlockBytes []byte) (*common.Block, error)//還原序列化區塊,並構造serializedBlockInfofunc extractSerializedBlockInfo(serializedBlockBytes []byte) (*serializedBlockInfo, error)//序列化中添加BlockHeader,即Number、DataHash和PreviousHashfunc addHeaderBytes(blockHeader *common.BlockHeader, buf *proto.Buffer) error//序列化中添加BlockData,並從BlockData中解析txid,返回交易索引資訊數組func addDataBytes(blockData *common.BlockData, buf *proto.Buffer) ([]*txindexInfo, error)//序列化中添加Metadatafunc addMetadataBytes(blockMetadata *common.BlockMetadata, buf *proto.Buffer) error//還原序列化出BlockHeaderfunc extractHeader(buf *ledgerutil.Buffer) (*common.BlockHeader, error)//還原序列化出BlockData,並返回交易索引資訊數組func extractData(buf *ledgerutil.Buffer) (*common.BlockData, []*txindexInfo, error)//還原序列化出Metadatafunc extractMetadata(buf *ledgerutil.Buffer) (*common.BlockMetadata, error)//從BlockData中解析出交易IDfunc extractTxID(txEnvelopBytes []byte) (string, error)//代碼在common/ledger/blkstorage/fsblkstorage/block_serialization.go
3、checkpointInfo結構體定義及方法
checkpointInfo,即檢查點資訊,結構體定義如下:
type checkpointInfo struct {????latestFileChunkSuffixNum int //最新的區塊檔案尾碼,如blockfile_000000????latestFileChunksize int //最新的區塊檔案大小????isChainEmpty bool //是否空鏈????lastBlockNumber uint64 //最新的區塊編號}//代碼在common/ledger/blkstorage/fsblkstorage/blockfile_mgr.go
涉及方法如下:
func (i *checkpointInfo) marshal() ([]byte, error) //checkpointInfo序列化func (i *checkpointInfo) unmarshal(b []byte) error //checkpointInfo還原序列化func (i *checkpointInfo) String() string //轉換為string//代碼在common/ledger/blkstorage/fsblkstorage/blockfile_mgr.go
4、blockfileStream相關結構體及方法4.1、blockfileStream
blockfileStream定義如下:
type blockfileStream struct {????fileNum int //blockfile檔案尾碼????file *os.File //os.File????reader *bufio.Reader //bufio.Reader????currentOffset int64 //當前位移量}//代碼在common/ledger/blkstorage/fsblkstorage/block_stream.go
涉及方法如下:
//構造blockfileStreamfunc newBlockfileStream(rootDir string, fileNum int, startOffset int64) (*blockfileStream, error) func (s *blockfileStream) nextBlockBytes() ([]byte, error) //下一個塊,調取s.nextBlockBytesAndPlacementInfo()//下一個塊和位置資訊func (s *blockfileStream) nextBlockBytesAndPlacementInfo() ([]byte, *blockPlacementInfo, error) func (s *blockfileStream) close() error //關閉blockfileStream//代碼在common/ledger/blkstorage/fsblkstorage/block_stream.go
func (s blockfileStream) nextBlockBytesAndPlacementInfo() ([]byte, blockPlacementInfo, error) 代碼如下:
var lenBytes []bytevar err errorvar fileInfo os.FileInfomoreContentAvailable := truefileInfo, err = s.file.Stat() //擷取檔案狀態remainingBytes := fileInfo.Size() - s.currentOffset //檔案讀取剩餘位元組peekBytes := 8if remainingBytes < int64(peekBytes) { //剩餘位元組小於8,按實際剩餘位元組,否則按8????peekBytes = int(remainingBytes)????moreContentAvailable = false}//儲存形式:前n位儲存block長度length,之後length位為實際blocklenBytes, err = s.reader.Peek(peekBytes) //Peek 返回緩衝的一個切片,該切片引用緩衝中前 peekBytes 個位元組的資料length, n := proto.DecodeVarint(lenBytes) //從切片中讀取 varint 編碼的整數,它返回整數和被消耗的位元組數。????err = s.reader.Discard(n) //丟棄儲存block長度length的前n位????blockBytes := make([]byte, length)????_, err = io.ReadAtLeast(s.reader, blockBytes, int(length))????blockPlacementInfo := &blockPlacementInfo{????????fileNum: s.fileNum,????????blockStartOffset: s.currentOffset,????????blockBytesOffset: s.currentOffset + int64(n)}????s.currentOffset += int64(n) + int64(length)????return blockBytes, blockPlacementInfo, nil//代碼在common/ledger/blkstorage/fsblkstorage/block_stream.go
補充blockPlacementInfo:塊位置資訊
type blockPlacementInfo struct {????fileNum int //塊檔案尾碼????blockStartOffset int64 //n+length,n之前????blockBytesOffset int64 //n+length,length之前}//代碼在common/ledger/blkstorage/fsblkstorage/block_stream.go
5、blockfileWriter結構體定義及方法
type blockfileWriter struct {????filePath string //路徑????file *os.File //os.File}func newBlockfileWriter(filePath string) (*blockfileWriter, error) //構造blockfileWriter,並調用writer.open()func (w *blockfileWriter) truncateFile(targetSize int) error //截取檔案func (w *blockfileWriter) append(b []byte, sync bool) error //追加檔案func (w *blockfileWriter) open() error //開啟檔案func (w *blockfileWriter) close() error //關閉檔案//代碼在common/ledger/blkstorage/fsblkstorage/blockfile_rw.go
6、blockIndex相關結構體及方法6.1、index介面定義
type index interface {????getLastBlockIndexed() (uint64, error) //擷取最後一個塊索引(或編號)????indexBlock(blockIdxInfo *blockIdxInfo) error //索引區塊????getBlockLocByHash(blockHash []byte) (*fileLocPointer, error) //根據區塊雜湊,擷取檔案區塊指標????getBlockLocByBlockNum(blockNum uint64) (*fileLocPointer, error) //根據區塊編號,擷取檔案區塊指標????getTxLoc(txID string) (*fileLocPointer, error) //根據交易ID,擷取檔案交易指標????getTXLocByBlockNumTranNum(blockNum uint64, tranNum uint64) (*fileLocPointer, error) //根據區塊編號和交易編號,擷取檔案交易指標????getBlockLocByTxID(txID string) (*fileLocPointer, error)//根據交易ID,擷取檔案區塊指標????getTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error)//根據交易ID,擷取交易驗證代碼}//代碼在common/ledger/blkstorage/fsblkstorage/blockindex.go
6.2、blockIndex結構體
blockIndex結構體定義如下:
type blockIndex struct {????indexItemsMap map[blkstorage.IndexableAttr]bool //index屬性對應????db *leveldbhelper.DBHandle //index leveldb操作}//代碼在common/ledger/blkstorage/fsblkstorage/blockindex.go
補充IndexableAttr:
const (????IndexableAttrBlockNum = IndexableAttr("BlockNum")????IndexableAttrBlockHash = IndexableAttr("BlockHash")????IndexableAttrTxID = IndexableAttr("TxID")????IndexableAttrBlockNumTranNum = IndexableAttr("BlockNumTranNum")????IndexableAttrBlockTxID = IndexableAttr("BlockTxID")????IndexableAttrTxValidationCode = IndexableAttr("TxValidationCode"))//代碼在common/ledger/blkstorage/blockstorage.go
區塊鏈教程Fabric1.0原始碼分析blockfile區塊檔案儲存體一