github.com/true-sqn/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  }