1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
# 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结构体: ``` ```go 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结构体: ```go 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结构体: ```go type BlockData struct { Data [][]byte //Data,存储交易信息 } func (m *BlockData) GetData() [][]byte //获取Data,即m.Data //代码在protos/common/common.pb.go ``` BlockMetadata结构体: ```go type BlockMetadata struct { Metadata [][]byte //K/V均为[]byte格式 } func (m *BlockMetadata) GetMetadata() [][]byte //m.Metadata //代码在protos/common/common.pb.go ``` 补充BlockMetadataIndex: ```go 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结构体定义及工具函数: ```go 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,即检查点信息,结构体定义如下: ```go type checkpointInfo struct { latestFileChunkSuffixNum int //最新的区块文件后缀,如blockfile_000000 latestFileChunksize int //最新的区块文件大小 isChainEmpty bool //是否空链 lastBlockNumber uint64 //最新的区块编号 } //代码在common/ledger/blkstorage/fsblkstorage/blockfile_mgr.go ``` 涉及方法如下: ```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定义如下: ```go 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 ``` 涉及方法如下: ```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) 代码如下: ```go 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:块位置信息 ```go type blockPlacementInfo struct { fileNum int //块文件后缀 blockStartOffset int64 //n+length,n之前 blockBytesOffset int64 //n+length,length之前 } //代码在common/ledger/blkstorage/fsblkstorage/block_stream.go ``` ## 5、blockfileWriter结构体定义及方法 ```go 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接口定义 ```go 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结构体定义如下: ```go type blockIndex struct { indexItemsMap map[blkstorage.IndexableAttr]bool //index属性映射 db *leveldbhelper.DBHandle //index leveldb操作 } //代码在common/ledger/blkstorage/fsblkstorage/blockindex.go ``` 补充IndexableAttr: ```go const ( IndexableAttrBlockNum = IndexableAttr("BlockNum") IndexableAttrBlockHash = IndexableAttr("BlockHash") IndexableAttrTxID = IndexableAttr("TxID") IndexableAttrBlockNumTranNum = IndexableAttr("BlockNumTranNum") IndexableAttrBlockTxID = IndexableAttr("BlockTxID") IndexableAttrTxValidationCode = IndexableAttr("TxValidationCode") ) //代码在common/ledger/blkstorage/blockstorage.go |
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31557831/viewspace-2215947/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/31557831/viewspace-2215947/