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  }