/
blocks_itr.go
115 lines (100 loc) · 3.16 KB
/
blocks_itr.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//此源码被清华学神尹成大魔王专业翻译分析并修改
//尹成QQ77025077
//尹成微信18510341407
//尹成所在QQ群721929980
//尹成邮箱 yinc13@mails.tsinghua.edu.cn
//尹成毕业于清华大学,微软区块链领域全球最有价值专家
//https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
/*
版权所有IBM Corp.2016保留所有权利。
根据Apache许可证2.0版(以下简称“许可证”)获得许可;
除非符合许可证,否则您不能使用此文件。
您可以在以下网址获得许可证副本:
http://www.apache.org/licenses/license-2.0
除非适用法律要求或书面同意,软件
根据许可证分发是按“原样”分发的,
无任何明示或暗示的保证或条件。
有关管理权限和
许可证限制。
*/
package fsblkstorage
import (
"sync"
"github.com/hyperledger/fabric/common/ledger"
)
//
type blocksItr struct {
mgr *blockfileMgr
maxBlockNumAvailable uint64
blockNumToRetrieve uint64
stream *blockStream
closeMarker bool
closeMarkerLock *sync.Mutex
}
func newBlockItr(mgr *blockfileMgr, startBlockNum uint64) *blocksItr {
mgr.cpInfoCond.L.Lock()
defer mgr.cpInfoCond.L.Unlock()
return &blocksItr{mgr, mgr.cpInfo.lastBlockNumber, startBlockNum, nil, false, &sync.Mutex{}}
}
func (itr *blocksItr) waitForBlock(blockNum uint64) uint64 {
itr.mgr.cpInfoCond.L.Lock()
defer itr.mgr.cpInfoCond.L.Unlock()
for itr.mgr.cpInfo.lastBlockNumber < blockNum && !itr.shouldClose() {
logger.Debugf("Going to wait for newer blocks. maxAvailaBlockNumber=[%d], waitForBlockNum=[%d]",
itr.mgr.cpInfo.lastBlockNumber, blockNum)
itr.mgr.cpInfoCond.Wait()
logger.Debugf("Came out of wait. maxAvailaBlockNumber=[%d]", itr.mgr.cpInfo.lastBlockNumber)
}
return itr.mgr.cpInfo.lastBlockNumber
}
func (itr *blocksItr) initStream() error {
var lp *fileLocPointer
var err error
if lp, err = itr.mgr.index.getBlockLocByBlockNum(itr.blockNumToRetrieve); err != nil {
return err
}
if itr.stream, err = newBlockStream(itr.mgr.rootDir, lp.fileSuffixNum, int64(lp.offset), -1); err != nil {
return err
}
return nil
}
func (itr *blocksItr) shouldClose() bool {
itr.closeMarkerLock.Lock()
defer itr.closeMarkerLock.Unlock()
return itr.closeMarker
}
//
func (itr *blocksItr) Next() (ledger.QueryResult, error) {
if itr.maxBlockNumAvailable < itr.blockNumToRetrieve {
itr.maxBlockNumAvailable = itr.waitForBlock(itr.blockNumToRetrieve)
}
itr.closeMarkerLock.Lock()
defer itr.closeMarkerLock.Unlock()
if itr.closeMarker {
return nil, nil
}
if itr.stream == nil {
logger.Debugf("Initializing block stream for iterator. itr.maxBlockNumAvailable=%d", itr.maxBlockNumAvailable)
if err := itr.initStream(); err != nil {
return nil, err
}
}
nextBlockBytes, err := itr.stream.nextBlockBytes()
if err != nil {
return nil, err
}
itr.blockNumToRetrieve++
return deserializeBlock(nextBlockBytes)
}
//
func (itr *blocksItr) Close() {
itr.mgr.cpInfoCond.L.Lock()
defer itr.mgr.cpInfoCond.L.Unlock()
itr.closeMarkerLock.Lock()
defer itr.closeMarkerLock.Unlock()
itr.closeMarker = true
itr.mgr.cpInfoCond.Broadcast()
if itr.stream != nil {
itr.stream.close()
}
}