github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/common/ledger/blkstorage/fsblkstorage/blocks_itr.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package fsblkstorage
    18  
    19  import (
    20  	"fmt"
    21  	"sync"
    22  
    23  	"github.com/hyperledger/fabric/common/ledger"
    24  
    25  	"github.com/hyperledger/fabric/protos/common"
    26  )
    27  
    28  // blockHolder holds block bytes
    29  type blockHolder struct {
    30  	blockBytes []byte
    31  }
    32  
    33  // GetBlock serializes Block from block bytes
    34  func (bh *blockHolder) GetBlock() *common.Block {
    35  	block, err := deserializeBlock(bh.blockBytes)
    36  	if err != nil {
    37  		panic(fmt.Errorf("Problem in deserialzing block: %s", err))
    38  	}
    39  	return block
    40  }
    41  
    42  // GetBlockBytes returns block bytes
    43  func (bh *blockHolder) GetBlockBytes() []byte {
    44  	return bh.blockBytes
    45  }
    46  
    47  // blocksItr - an iterator for iterating over a sequence of blocks
    48  type blocksItr struct {
    49  	mgr                  *blockfileMgr
    50  	maxBlockNumAvailable uint64
    51  	blockNumToRetrieve   uint64
    52  	stream               *blockStream
    53  	closeMarker          bool
    54  	closeMarkerLock      *sync.Mutex
    55  }
    56  
    57  func newBlockItr(mgr *blockfileMgr, startBlockNum uint64) *blocksItr {
    58  	return &blocksItr{mgr, mgr.cpInfo.lastBlockNumber, startBlockNum, nil, false, &sync.Mutex{}}
    59  }
    60  
    61  func (itr *blocksItr) waitForBlock(blockNum uint64) uint64 {
    62  	itr.mgr.cpInfoCond.L.Lock()
    63  	defer itr.mgr.cpInfoCond.L.Unlock()
    64  	for itr.mgr.cpInfo.lastBlockNumber < blockNum && !itr.shouldClose() {
    65  		logger.Debugf("Going to wait for newer blocks. maxAvailaBlockNumber=[%d], waitForBlockNum=[%d]",
    66  			itr.mgr.cpInfo.lastBlockNumber, blockNum)
    67  		itr.mgr.cpInfoCond.Wait()
    68  		logger.Debugf("Came out of wait. maxAvailaBlockNumber=[%d]", itr.mgr.cpInfo.lastBlockNumber)
    69  	}
    70  	return itr.mgr.cpInfo.lastBlockNumber
    71  }
    72  
    73  func (itr *blocksItr) initStream() error {
    74  	var lp *fileLocPointer
    75  	var err error
    76  	if lp, err = itr.mgr.index.getBlockLocByBlockNum(itr.blockNumToRetrieve); err != nil {
    77  		return err
    78  	}
    79  	if itr.stream, err = newBlockStream(itr.mgr.rootDir, lp.fileSuffixNum, int64(lp.offset), -1); err != nil {
    80  		return err
    81  	}
    82  	return nil
    83  }
    84  
    85  func (itr *blocksItr) shouldClose() bool {
    86  	itr.closeMarkerLock.Lock()
    87  	defer itr.closeMarkerLock.Unlock()
    88  	return itr.closeMarker
    89  }
    90  
    91  // Next moves the cursor to next block and returns true iff the iterator is not exhausted
    92  func (itr *blocksItr) Next() (ledger.QueryResult, error) {
    93  	if itr.maxBlockNumAvailable < itr.blockNumToRetrieve {
    94  		itr.maxBlockNumAvailable = itr.waitForBlock(itr.blockNumToRetrieve)
    95  	}
    96  	itr.closeMarkerLock.Lock()
    97  	defer itr.closeMarkerLock.Unlock()
    98  	if itr.closeMarker {
    99  		return nil, nil
   100  	}
   101  	if itr.stream == nil {
   102  		if err := itr.initStream(); err != nil {
   103  			return nil, err
   104  		}
   105  	}
   106  	nextBlockBytes, err := itr.stream.nextBlockBytes()
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  	itr.blockNumToRetrieve++
   111  	return &blockHolder{nextBlockBytes}, nil
   112  }
   113  
   114  // Close releases any resources held by the iterator
   115  func (itr *blocksItr) Close() {
   116  	itr.closeMarkerLock.Lock()
   117  	defer itr.closeMarkerLock.Unlock()
   118  	itr.closeMarker = true
   119  	itr.mgr.cpInfoCond.L.Lock()
   120  	defer itr.mgr.cpInfoCond.L.Unlock()
   121  	itr.mgr.cpInfoCond.Broadcast()
   122  	itr.stream.close()
   123  }