内容简介: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
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Scrum敏捷软件开发
Mike Cohn / 廖靖斌、吕梁岳、陈争云、阳陆育 / 清华大学出版社 / 2010-11 / 69.00元
《Scrum敏捷软件开发》是敏捷联盟及Scrum联盟创始人之一、敏捷估算及计划的鼻祖Mike Cohn三大经典著作中影响最为深厚的扛鼎之作,也是全球敏捷社区中获得广泛肯定的企业敏捷转型权威参考。作者花四年时间,把自己近十五年的敏捷实践经验,特别是近四年中针对各种敏捷转型企业的咨询和指导工作,并结合旁征博引的方式,从更高的思想层次对敏捷与Scrum多年来的经验和教训进行深入而前面的梳理和总结,最终集......一起来看看 《Scrum敏捷软件开发》 这本书的介绍吧!