[TOC]
在账单获取章节,我们发现在执行到线程poolRoutine时,账单已经被打包进了BlockPool->bpRequester->BlockCache->Block->Data中了,因此我们需要理清这个数据是什么时候填充的。
类描述
type BlockPool struct {
BaseService
startTime time.Time
mtx sync.Mutex
// block requests
requesters map[agtypes.INT]*bpRequester
height agtypes.INT // the lowest key in requesters.
numPending int32 // number of requests pending assignment or block response
// peers
peers map[string]*bpPeer
requestsCh chan<- BlockRequest
timeoutsCh chan<- string
logger *zap.Logger
}
BaseService是用来启动服务的,和前面我们描述的几个服务类相似,就不赘述了。 requesters就是我们在11章节中描述的类。 height这个参数含义不明 numPending这个参数后面会有值的判断,似乎是连接最大数 peers节点的一些信息 requestsCh,通信channel,在sendRequest中被调用,未检测到使用。 timeoutsCh,通信channel,在sendTimeout中被调用,未检测到使用。
启动流程
启动:
func (pool *BlockPool) OnStart() error {
pool.BaseService.OnStart()
go pool.makeRequestersRoutine()
pool.startTime = time.Now()
return nil
}
pool.makeRequestersRoutine()启动自身线程。 自身线程我们关注下面这个函数:
// request for more blocks.
pool.makeNextRequester()
此函数除了request.Start()启动bpRequesters的线程外,还创建了新的request,这个就是我们要找的:
nextHeight := pool.height + agtypes.INT(len(pool.requesters))
request := newBPRequester(pool, nextHeight)
pool.requesters[nextHeight] = request
pool.numPending++
pool.height这个值是启动时设置的,默认是1,那么执行这部分代码就会增加一个requesters到map中,通过打印发现一共添加了300个requesters,然后就不再执行了。
len(pool.requesters): 299
pool.height: 1
nextHeight: 300
numPending: 300
为什么是300个呢,这就会回到上面的pool.makeRequestersRoutine()线程循环体内了:
// Run spawns requesters as needed.
func (pool *BlockPool) makeRequestersRoutine() {
for {
if !pool.IsRunning() {
break
}
_, numPending, lenRequesters := pool.GetStatus()
if numPending >= maxPendingRequests {
// sleep for a bit.
time.Sleep(requestIntervalMS * time.Millisecond)
// check for timed out peers
pool.removeTimedoutPeers()
} else if lenRequesters >= maxTotalRequesters {
// sleep for a bit.
time.Sleep(requestIntervalMS * time.Millisecond)
// check for timed out peers
pool.removeTimedoutPeers()
} else {
// request for more blocks.
pool.makeNextRequester()
}
}
}
maxPendingRequests的取值是300,因此如果numPending到300后,就不再添加新的requesters了。开始检测超时节点并清除。
block填充
上面我们只是分析了requesters的创建,那么在创建时的block是怎么填充的呢,在出块时还是通过block来获取数据的。 填充部分参见共识模块章节。