github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/ledger/blkstorage/blocks_itr.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package blkstorage
     8  
     9  import (
    10  	"sync"
    11  
    12  	"github.com/hechain20/hechain/common/ledger"
    13  )
    14  
    15  // blocksItr - an iterator for iterating over a sequence of blocks
    16  type blocksItr struct {
    17  	mgr                  *blockfileMgr
    18  	maxBlockNumAvailable uint64
    19  	blockNumToRetrieve   uint64
    20  	stream               *blockStream
    21  	closeMarker          bool
    22  	closeMarkerLock      *sync.Mutex
    23  }
    24  
    25  func newBlockItr(mgr *blockfileMgr, startBlockNum uint64) *blocksItr {
    26  	mgr.blkfilesInfoCond.L.Lock()
    27  	defer mgr.blkfilesInfoCond.L.Unlock()
    28  	return &blocksItr{mgr, mgr.blockfilesInfo.lastPersistedBlock, startBlockNum, nil, false, &sync.Mutex{}}
    29  }
    30  
    31  func (itr *blocksItr) waitForBlock(blockNum uint64) uint64 {
    32  	itr.mgr.blkfilesInfoCond.L.Lock()
    33  	defer itr.mgr.blkfilesInfoCond.L.Unlock()
    34  	for itr.mgr.blockfilesInfo.lastPersistedBlock < blockNum && !itr.shouldClose() {
    35  		logger.Debugf("Going to wait for newer blocks. maxAvailaBlockNumber=[%d], waitForBlockNum=[%d]",
    36  			itr.mgr.blockfilesInfo.lastPersistedBlock, blockNum)
    37  		itr.mgr.blkfilesInfoCond.Wait()
    38  		logger.Debugf("Came out of wait. maxAvailaBlockNumber=[%d]", itr.mgr.blockfilesInfo.lastPersistedBlock)
    39  	}
    40  	return itr.mgr.blockfilesInfo.lastPersistedBlock
    41  }
    42  
    43  func (itr *blocksItr) initStream() error {
    44  	var lp *fileLocPointer
    45  	var err error
    46  	if lp, err = itr.mgr.index.getBlockLocByBlockNum(itr.blockNumToRetrieve); err != nil {
    47  		return err
    48  	}
    49  	if itr.stream, err = newBlockStream(itr.mgr.rootDir, lp.fileSuffixNum, int64(lp.offset), -1); err != nil {
    50  		return err
    51  	}
    52  	return nil
    53  }
    54  
    55  func (itr *blocksItr) shouldClose() bool {
    56  	itr.closeMarkerLock.Lock()
    57  	defer itr.closeMarkerLock.Unlock()
    58  	return itr.closeMarker
    59  }
    60  
    61  // Next moves the cursor to next block and returns true iff the iterator is not exhausted
    62  func (itr *blocksItr) Next() (ledger.QueryResult, error) {
    63  	if itr.maxBlockNumAvailable < itr.blockNumToRetrieve {
    64  		itr.maxBlockNumAvailable = itr.waitForBlock(itr.blockNumToRetrieve)
    65  	}
    66  	itr.closeMarkerLock.Lock()
    67  	defer itr.closeMarkerLock.Unlock()
    68  	if itr.closeMarker {
    69  		return nil, nil
    70  	}
    71  	if itr.stream == nil {
    72  		logger.Debugf("Initializing block stream for iterator. itr.maxBlockNumAvailable=%d", itr.maxBlockNumAvailable)
    73  		if err := itr.initStream(); err != nil {
    74  			return nil, err
    75  		}
    76  	}
    77  	nextBlockBytes, err := itr.stream.nextBlockBytes()
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  	itr.blockNumToRetrieve++
    82  	return deserializeBlock(nextBlockBytes)
    83  }
    84  
    85  // Close releases any resources held by the iterator
    86  func (itr *blocksItr) Close() {
    87  	itr.mgr.blkfilesInfoCond.L.Lock()
    88  	defer itr.mgr.blkfilesInfoCond.L.Unlock()
    89  	itr.closeMarkerLock.Lock()
    90  	defer itr.closeMarkerLock.Unlock()
    91  	itr.closeMarker = true
    92  	itr.mgr.blkfilesInfoCond.Broadcast()
    93  	if itr.stream != nil {
    94  		itr.stream.close()
    95  	}
    96  }