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 }