内容简介:blockfile,即Fabric区块链区块文件存储,默认目录/var/hyperledger/production/ledgersData/chains,含index和chains两个子目录。其中index为索引目录,采用leveldb实现。而chains为各ledger的区块链文件,子目录以ledgerid为名,使用文件系统实现。区块文件以blockfile_为前缀,最大大小默认64M。
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.Header func (m *Block) GetData() *BlockData //获取BlockData,即m.Data func (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.Number func (m *BlockHeader) GetPreviousHash() []byte //获取前一个区块哈希,即m.PreviousHash func (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 int32 const ( 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) //反序列化区块,并构造serializedBlockInfo func extractSerializedBlockInfo(serializedBlockBytes []byte) (*serializedBlockInfo, error) //序列化中添加BlockHeader,即Number、DataHash和PreviousHash func addHeaderBytes(blockHeader *common.BlockHeader, buf *proto.Buffer) error //序列化中添加BlockData,并从BlockData中解析txid,返回交易索引信息数组 func addDataBytes(blockData *common.BlockData, buf *proto.Buffer) ([]*txindexInfo, error) //序列化中添加Metadata func addMetadataBytes(blockMetadata *common.BlockMetadata, buf *proto.Buffer) error //反序列化出BlockHeader func extractHeader(buf *ledgerutil.Buffer) (*common.BlockHeader, error) //反序列化出BlockData,并返回交易索引信息数组 func extractData(buf *ledgerutil.Buffer) (*common.BlockData, []*txindexInfo, error) //反序列化出Metadata func extractMetadata(buf *ledgerutil.Buffer) (*common.BlockMetadata, error) //从BlockData中解析出交易ID func 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
涉及方法如下:
//构造blockfileStream func 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 []byte var err error var fileInfo os.FileInfo moreContentAvailable := true fileInfo, err = s.file.Stat() //获取文件状态 remainingBytes := fileInfo.Size() - s.currentOffset //文件读取剩余字节 peekBytes := 8 if remainingBytes < int64(peekBytes) { //剩余字节小于8,按实际剩余字节,否则按8 peekBytes = int(remainingBytes) moreContentAvailable = false } //存储形式:前n位存储block长度length,之后length位为实际block lenBytes, 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区块文件存储一》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 区块链教程Fabric1.0源代码分析blockfile区块文件存储2
- Fabric 1.0源代码分析(2) blockfile(区块文件存储)
- 区块链教程Fabric1.0源代码分析configtx#genesis
- 区块链教程Fabric1.0源代码分析Ledger(账本)二
- 区块链教程Fabric1.0源代码分析Ledger(账本)一
- 区块链教程Fabric1.0源代码分析Orderer localconfig
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Head First Design Patterns
Elisabeth Freeman、Eric Freeman、Bert Bates、Kathy Sierra、Elisabeth Robson / O'Reilly Media / 2004-11-1 / USD 49.99
You're not alone. At any given moment, somewhere in the world someone struggles with the same software design problems you have. You know you don't want to reinvent the wheel (or worse, a flat tire),......一起来看看 《Head First Design Patterns》 这本书的介绍吧!