github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/ledger/blockledger/fileledger/impl.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package fileledger 8 9 import ( 10 "github.com/hechain20/hechain/common/flogging" 11 "github.com/hechain20/hechain/common/ledger" 12 "github.com/hechain20/hechain/common/ledger/blockledger" 13 cb "github.com/hyperledger/fabric-protos-go/common" 14 ab "github.com/hyperledger/fabric-protos-go/orderer" 15 ) 16 17 var logger = flogging.MustGetLogger("common.ledger.blockledger.file") 18 19 // FileLedger is a struct used to interact with a node's ledger 20 type FileLedger struct { 21 blockStore FileLedgerBlockStore 22 signal chan struct{} 23 } 24 25 // FileLedgerBlockStore defines the interface to interact with deliver when using a 26 // file ledger 27 type FileLedgerBlockStore interface { 28 AddBlock(block *cb.Block) error 29 GetBlockchainInfo() (*cb.BlockchainInfo, error) 30 RetrieveBlocks(startBlockNumber uint64) (ledger.ResultsIterator, error) 31 Shutdown() 32 RetrieveBlockByNumber(blockNum uint64) (*cb.Block, error) 33 } 34 35 // NewFileLedger creates a new FileLedger for interaction with the ledger 36 func NewFileLedger(blockStore FileLedgerBlockStore) *FileLedger { 37 return &FileLedger{blockStore: blockStore, signal: make(chan struct{})} 38 } 39 40 type fileLedgerIterator struct { 41 ledger *FileLedger 42 blockNumber uint64 43 commonIterator ledger.ResultsIterator 44 } 45 46 // Next blocks until there is a new block available, or until Close is called. 47 // It returns an error if the next block is no longer retrievable. 48 func (i *fileLedgerIterator) Next() (*cb.Block, cb.Status) { 49 result, err := i.commonIterator.Next() 50 if err != nil { 51 logger.Error(err) 52 return nil, cb.Status_SERVICE_UNAVAILABLE 53 } 54 // Cover the case where another thread calls Close on the iterator. 55 if result == nil { 56 return nil, cb.Status_SERVICE_UNAVAILABLE 57 } 58 return result.(*cb.Block), cb.Status_SUCCESS 59 } 60 61 // Close releases resources acquired by the Iterator 62 func (i *fileLedgerIterator) Close() { 63 i.commonIterator.Close() 64 } 65 66 // Iterator returns an Iterator, as specified by an ab.SeekInfo message, and its 67 // starting block number 68 func (fl *FileLedger) Iterator(startPosition *ab.SeekPosition) (blockledger.Iterator, uint64) { 69 var startingBlockNumber uint64 70 switch start := startPosition.Type.(type) { 71 case *ab.SeekPosition_Oldest: 72 startingBlockNumber = 0 73 case *ab.SeekPosition_Newest: 74 info, err := fl.blockStore.GetBlockchainInfo() 75 if err != nil { 76 logger.Panic(err) 77 } 78 newestBlockNumber := info.Height - 1 79 if info.BootstrappingSnapshotInfo != nil && newestBlockNumber == info.BootstrappingSnapshotInfo.LastBlockInSnapshot { 80 newestBlockNumber = info.Height 81 } 82 startingBlockNumber = newestBlockNumber 83 case *ab.SeekPosition_Specified: 84 startingBlockNumber = start.Specified.Number 85 height := fl.Height() 86 if startingBlockNumber > height { 87 return &blockledger.NotFoundErrorIterator{}, 0 88 } 89 case *ab.SeekPosition_NextCommit: 90 startingBlockNumber = fl.Height() 91 default: 92 return &blockledger.NotFoundErrorIterator{}, 0 93 } 94 95 iterator, err := fl.blockStore.RetrieveBlocks(startingBlockNumber) 96 if err != nil { 97 logger.Warnw("Failed to initialize block iterator", "blockNum", startingBlockNumber, "error", err) 98 return &blockledger.NotFoundErrorIterator{}, 0 99 } 100 101 return &fileLedgerIterator{ledger: fl, blockNumber: startingBlockNumber, commonIterator: iterator}, startingBlockNumber 102 } 103 104 // Height returns the number of blocks on the ledger 105 func (fl *FileLedger) Height() uint64 { 106 info, err := fl.blockStore.GetBlockchainInfo() 107 if err != nil { 108 logger.Panic(err) 109 } 110 return info.Height 111 } 112 113 // Append a new block to the ledger 114 func (fl *FileLedger) Append(block *cb.Block) error { 115 err := fl.blockStore.AddBlock(block) 116 if err == nil { 117 close(fl.signal) 118 fl.signal = make(chan struct{}) 119 } 120 return err 121 } 122 123 func (fl *FileLedger) RetrieveBlockByNumber(blockNumber uint64) (*cb.Block, error) { 124 return fl.blockStore.RetrieveBlockByNumber(blockNumber) 125 }