github.com/lzy4123/fabric@v2.1.1+incompatible/common/ledger/blockledger/fileledger/impl.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package fileledger 8 9 import ( 10 cb "github.com/hyperledger/fabric-protos-go/common" 11 ab "github.com/hyperledger/fabric-protos-go/orderer" 12 "github.com/hyperledger/fabric/common/flogging" 13 "github.com/hyperledger/fabric/common/ledger" 14 "github.com/hyperledger/fabric/common/ledger/blockledger" 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 } 32 33 // NewFileLedger creates a new FileLedger for interaction with the ledger 34 func NewFileLedger(blockStore FileLedgerBlockStore) *FileLedger { 35 return &FileLedger{blockStore: blockStore, signal: make(chan struct{})} 36 } 37 38 type fileLedgerIterator struct { 39 ledger *FileLedger 40 blockNumber uint64 41 commonIterator ledger.ResultsIterator 42 } 43 44 // Next blocks until there is a new block available, or until Close is called. 45 // It returns an error if the next block is no longer retrievable. 46 func (i *fileLedgerIterator) Next() (*cb.Block, cb.Status) { 47 result, err := i.commonIterator.Next() 48 if err != nil { 49 logger.Error(err) 50 return nil, cb.Status_SERVICE_UNAVAILABLE 51 } 52 // Cover the case where another thread calls Close on the iterator. 53 if result == nil { 54 return nil, cb.Status_SERVICE_UNAVAILABLE 55 } 56 return result.(*cb.Block), cb.Status_SUCCESS 57 } 58 59 // Close releases resources acquired by the Iterator 60 func (i *fileLedgerIterator) Close() { 61 i.commonIterator.Close() 62 } 63 64 // Iterator returns an Iterator, as specified by an ab.SeekInfo message, and its 65 // starting block number 66 func (fl *FileLedger) Iterator(startPosition *ab.SeekPosition) (blockledger.Iterator, uint64) { 67 var startingBlockNumber uint64 68 switch start := startPosition.Type.(type) { 69 case *ab.SeekPosition_Oldest: 70 startingBlockNumber = 0 71 case *ab.SeekPosition_Newest: 72 info, err := fl.blockStore.GetBlockchainInfo() 73 if err != nil { 74 logger.Panic(err) 75 } 76 newestBlockNumber := info.Height - 1 77 startingBlockNumber = newestBlockNumber 78 case *ab.SeekPosition_Specified: 79 startingBlockNumber = start.Specified.Number 80 height := fl.Height() 81 if startingBlockNumber > height { 82 return &blockledger.NotFoundErrorIterator{}, 0 83 } 84 default: 85 return &blockledger.NotFoundErrorIterator{}, 0 86 } 87 88 iterator, err := fl.blockStore.RetrieveBlocks(startingBlockNumber) 89 if err != nil { 90 return &blockledger.NotFoundErrorIterator{}, 0 91 } 92 93 return &fileLedgerIterator{ledger: fl, blockNumber: startingBlockNumber, commonIterator: iterator}, startingBlockNumber 94 } 95 96 // Height returns the number of blocks on the ledger 97 func (fl *FileLedger) Height() uint64 { 98 info, err := fl.blockStore.GetBlockchainInfo() 99 if err != nil { 100 logger.Panic(err) 101 } 102 return info.Height 103 } 104 105 // Append a new block to the ledger 106 func (fl *FileLedger) Append(block *cb.Block) error { 107 err := fl.blockStore.AddBlock(block) 108 if err == nil { 109 close(fl.signal) 110 fl.signal = make(chan struct{}) 111 } 112 return err 113 }