github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/eth/downloader/queue.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:38</date> 10 //</624342634235695104> 11 12 13 //包含用于收集下载任务和计划的块下载计划程序 14 //他们井然有序,步履维艰。 15 16 package downloader 17 18 import ( 19 "errors" 20 "fmt" 21 "sync" 22 "time" 23 24 "github.com/ethereum/go-ethereum/common" 25 "github.com/ethereum/go-ethereum/core/types" 26 "github.com/ethereum/go-ethereum/log" 27 "github.com/ethereum/go-ethereum/metrics" 28 "gopkg.in/karalabe/cookiejar.v2/collections/prque" 29 ) 30 31 var ( 32 blockCacheItems = 8192 //限制下载前要缓存的最大块数 33 blockCacheMemory = 64 * 1024 * 1024 //用于块缓存的最大内存量 34 blockCacheSizeWeight = 0.1 //乘数,根据过去的块大小近似平均块大小 35 ) 36 37 var ( 38 errNoFetchesPending = errors.New("no fetches pending") 39 errStaleDelivery = errors.New("stale delivery") 40 ) 41 42 //FetchRequest是当前正在运行的数据检索操作。 43 type fetchRequest struct { 44 Peer *peerConnection //请求发送到的对等机 45 From uint64 //[ETH/62]请求的链元素索引(仅用于骨架填充) 46 Headers []*types.Header //[ETH/62]请求的标题,按请求顺序排序 47 Time time.Time //提出请求的时间 48 } 49 50 //fetchresult是一个结构,从数据获取程序收集部分结果,直到 51 //所有未完成的部分都已完成,结果作为一个整体可以处理。 52 type fetchResult struct { 53 Pending int //仍挂起的数据提取数 54 Hash common.Hash //阻止重新计算的头的哈希 55 56 Header *types.Header 57 Uncles []*types.Header 58 Transactions types.Transactions 59 Receipts types.Receipts 60 } 61 62 //队列表示需要获取或正在获取的哈希 63 type queue struct { 64 mode SyncMode //同步模式,用于确定要计划取件的块零件 65 66 //头是“特殊的”,它们批量下载,由一个框架链支持。 67 headerHead common.Hash //[eth/62]验证顺序的最后一个排队头的哈希 68 headerTaskPool map[uint64]*types.Header //[ETH/62]挂起的头检索任务,将开始索引映射到骨架头 69 headerTaskQueue *prque.Prque //[eth/62]获取填充头的骨架索引的优先级队列 70 headerPeerMiss map[string]map[uint64]struct{} //[eth/62]已知不可用的每对等头批的集合 71 headerPendPool map[string]*fetchRequest //[ETH/62]当前挂起的头检索操作 72 headerResults []*types.Header //[ETH/62]结果缓存累积已完成的头段 73 headerProced int //[ETH/62 ]已从结果中处理的页眉数 74 headerOffset uint64 //[eth/62]结果缓存中第一个头的编号 75 headerContCh chan bool //[ETH/62]当头下载完成时通知的通道 76 77 //下面的所有数据检索都基于已组装的头链 78 blockTaskPool map[common.Hash]*types.Header //[ETH/62]挂起的块(体)检索任务,将哈希映射到头 79 blockTaskQueue *prque.Prque //[eth/62]头的优先级队列,用于获取块(体) 80 blockPendPool map[string]*fetchRequest //[ETH/62]当前正在等待的块(体)检索操作 81 blockDonePool map[common.Hash]struct{} //[ETH/62]完成的块(体)提取集 82 83 receiptTaskPool map[common.Hash]*types.Header //[ETH/63]挂起的收据检索任务,将哈希映射到标题 84 receiptTaskQueue *prque.Prque //[ETH/63]标题的优先级队列,用于获取收据 85 receiptPendPool map[string]*fetchRequest //[ETH/63]当前正在等待收据检索操作 86 receiptDonePool map[common.Hash]struct{} //[ETH/63]一套完整的收据提取 87 88 resultCache []*fetchResult //已下载但尚未传递提取结果 89 resultOffset uint64 //块链中第一个缓存获取结果的偏移量 90 resultSize common.StorageSize //块的近似大小(指数移动平均值) 91 92 lock *sync.Mutex 93 active *sync.Cond 94 closed bool 95 } 96 97 //new queue为计划块检索创建新的下载队列。 98 func newQueue() *queue { 99 lock := new(sync.Mutex) 100 return &queue{ 101 headerPendPool: make(map[string]*fetchRequest), 102 headerContCh: make(chan bool), 103 blockTaskPool: make(map[common.Hash]*types.Header), 104 blockTaskQueue: prque.New(), 105 blockPendPool: make(map[string]*fetchRequest), 106 blockDonePool: make(map[common.Hash]struct{}), 107 receiptTaskPool: make(map[common.Hash]*types.Header), 108 receiptTaskQueue: prque.New(), 109 receiptPendPool: make(map[string]*fetchRequest), 110 receiptDonePool: make(map[common.Hash]struct{}), 111 resultCache: make([]*fetchResult, blockCacheItems), 112 active: sync.NewCond(lock), 113 lock: lock, 114 } 115 } 116 117 //重置将清除队列内容。 118 func (q *queue) Reset() { 119 q.lock.Lock() 120 defer q.lock.Unlock() 121 122 q.closed = false 123 q.mode = FullSync 124 125 q.headerHead = common.Hash{} 126 q.headerPendPool = make(map[string]*fetchRequest) 127 128 q.blockTaskPool = make(map[common.Hash]*types.Header) 129 q.blockTaskQueue.Reset() 130 q.blockPendPool = make(map[string]*fetchRequest) 131 q.blockDonePool = make(map[common.Hash]struct{}) 132 133 q.receiptTaskPool = make(map[common.Hash]*types.Header) 134 q.receiptTaskQueue.Reset() 135 q.receiptPendPool = make(map[string]*fetchRequest) 136 q.receiptDonePool = make(map[common.Hash]struct{}) 137 138 q.resultCache = make([]*fetchResult, blockCacheItems) 139 q.resultOffset = 0 140 } 141 142 //关闭标记同步结束,取消阻止等待结果。 143 //即使队列已经关闭,也可以调用它。 144 func (q *queue) Close() { 145 q.lock.Lock() 146 q.closed = true 147 q.lock.Unlock() 148 q.active.Broadcast() 149 } 150 151 //PendingHeaders检索等待检索的头请求数。 152 func (q *queue) PendingHeaders() int { 153 q.lock.Lock() 154 defer q.lock.Unlock() 155 156 return q.headerTaskQueue.Size() 157 } 158 159 //PungBug检索待检索的块(体)请求的数量。 160 func (q *queue) PendingBlocks() int { 161 q.lock.Lock() 162 defer q.lock.Unlock() 163 164 return q.blockTaskQueue.Size() 165 } 166 167 //PendingReceipts检索待检索的块接收数。 168 func (q *queue) PendingReceipts() int { 169 q.lock.Lock() 170 defer q.lock.Unlock() 171 172 return q.receiptTaskQueue.Size() 173 } 174 175 //InlightHeaders检索当前是否有头提取请求 176 //在飞行中。 177 func (q *queue) InFlightHeaders() bool { 178 q.lock.Lock() 179 defer q.lock.Unlock() 180 181 return len(q.headerPendPool) > 0 182 } 183 184 //InlightBlocks检索当前是否存在块提取请求 185 //飞行。 186 func (q *queue) InFlightBlocks() bool { 187 q.lock.Lock() 188 defer q.lock.Unlock() 189 190 return len(q.blockPendPool) > 0 191 } 192 193 //航班收据检索当前是否有收据取索请求 194 //在飞行中。 195 func (q *queue) InFlightReceipts() bool { 196 q.lock.Lock() 197 defer q.lock.Unlock() 198 199 return len(q.receiptPendPool) > 0 200 } 201 202 //如果队列完全空闲或其中仍有一些数据,则IDLE返回。 203 func (q *queue) Idle() bool { 204 q.lock.Lock() 205 defer q.lock.Unlock() 206 207 queued := q.blockTaskQueue.Size() + q.receiptTaskQueue.Size() 208 pending := len(q.blockPendPool) + len(q.receiptPendPool) 209 cached := len(q.blockDonePool) + len(q.receiptDonePool) 210 211 return (queued + pending + cached) == 0 212 } 213 214 //shouldthrottleBlocks检查是否应限制下载(活动块(正文) 215 //获取超过块缓存)。 216 func (q *queue) ShouldThrottleBlocks() bool { 217 q.lock.Lock() 218 defer q.lock.Unlock() 219 220 return q.resultSlots(q.blockPendPool, q.blockDonePool) <= 0 221 } 222 223 //tottleReceipts是否应检查是否应限制下载(活动收据 224 //获取超过块缓存)。 225 func (q *queue) ShouldThrottleReceipts() bool { 226 q.lock.Lock() 227 defer q.lock.Unlock() 228 229 return q.resultSlots(q.receiptPendPool, q.receiptDonePool) <= 0 230 } 231 232 //resultslots计算可用于请求的结果槽数 233 //同时遵守项目和结果的内存限制 234 //隐藏物。 235 func (q *queue) resultSlots(pendPool map[string]*fetchRequest, donePool map[common.Hash]struct{}) int { 236 //计算内存限制限制的最大长度 237 limit := len(q.resultCache) 238 if common.StorageSize(len(q.resultCache))*q.resultSize > common.StorageSize(blockCacheMemory) { 239 limit = int((common.StorageSize(blockCacheMemory) + q.resultSize - 1) / q.resultSize) 240 } 241 //计算已完成的插槽数 242 finished := 0 243 for _, result := range q.resultCache[:limit] { 244 if result == nil { 245 break 246 } 247 if _, ok := donePool[result.Hash]; ok { 248 finished++ 249 } 250 } 251 //计算当前下载的插槽数 252 pending := 0 253 for _, request := range pendPool { 254 for _, header := range request.Headers { 255 if header.Number.Uint64() < q.resultOffset+uint64(limit) { 256 pending++ 257 } 258 } 259 } 260 //返回空闲插槽进行分发 261 return limit - finished - pending 262 } 263 264 //TraceSkelon将一批报头检索任务添加到队列中以填充 265 //找到一个已经检索到的头部骨架。 266 func (q *queue) ScheduleSkeleton(from uint64, skeleton []*types.Header) { 267 q.lock.Lock() 268 defer q.lock.Unlock() 269 270 //无法进行骨架检索,如果进行,则很难失败(巨大的实现错误) 271 if q.headerResults != nil { 272 panic("skeleton assembly already in progress") 273 } 274 //为骨架程序集安排所有头检索任务 275 q.headerTaskPool = make(map[uint64]*types.Header) 276 q.headerTaskQueue = prque.New() 277 q.headerPeerMiss = make(map[string]map[uint64]struct{}) //重置可用性以更正无效的链 278 q.headerResults = make([]*types.Header, len(skeleton)*MaxHeaderFetch) 279 q.headerProced = 0 280 q.headerOffset = from 281 q.headerContCh = make(chan bool, 1) 282 283 for i, header := range skeleton { 284 index := from + uint64(i*MaxHeaderFetch) 285 286 q.headerTaskPool[index] = header 287 q.headerTaskQueue.Push(index, -float32(index)) 288 } 289 } 290 291 //RetrieveHeaders根据调度的 292 //骨骼。 293 func (q *queue) RetrieveHeaders() ([]*types.Header, int) { 294 q.lock.Lock() 295 defer q.lock.Unlock() 296 297 headers, proced := q.headerResults, q.headerProced 298 q.headerResults, q.headerProced = nil, 0 299 300 return headers, proced 301 } 302 303 //schedule为下载队列添加一组头以便进行调度,返回 304 //遇到新邮件头。 305 func (q *queue) Schedule(headers []*types.Header, from uint64) []*types.Header { 306 q.lock.Lock() 307 defer q.lock.Unlock() 308 309 //插入按包含的块编号排序的所有标题 310 inserts := make([]*types.Header, 0, len(headers)) 311 for _, header := range headers { 312 //确保连锁订单始终得到遵守和保存 313 hash := header.Hash() 314 if header.Number == nil || header.Number.Uint64() != from { 315 log.Warn("Header broke chain ordering", "number", header.Number, "hash", hash, "expected", from) 316 break 317 } 318 if q.headerHead != (common.Hash{}) && q.headerHead != header.ParentHash { 319 log.Warn("Header broke chain ancestry", "number", header.Number, "hash", hash) 320 break 321 } 322 //确保没有执行重复的请求 323 if _, ok := q.blockTaskPool[hash]; ok { 324 log.Warn("Header already scheduled for block fetch", "number", header.Number, "hash", hash) 325 continue 326 } 327 if _, ok := q.receiptTaskPool[hash]; ok { 328 log.Warn("Header already scheduled for receipt fetch", "number", header.Number, "hash", hash) 329 continue 330 } 331 //将标题排队以进行内容检索 332 q.blockTaskPool[hash] = header 333 q.blockTaskQueue.Push(header, -float32(header.Number.Uint64())) 334 335 if q.mode == FastSync { 336 q.receiptTaskPool[hash] = header 337 q.receiptTaskQueue.Push(header, -float32(header.Number.Uint64())) 338 } 339 inserts = append(inserts, header) 340 q.headerHead = hash 341 from++ 342 } 343 return inserts 344 } 345 346 //结果从中检索并永久删除一批提取结果 347 //高速缓存。如果队列已关闭,则结果切片将为空。 348 func (q *queue) Results(block bool) []*fetchResult { 349 q.lock.Lock() 350 defer q.lock.Unlock() 351 352 //统计可供处理的项目数 353 nproc := q.countProcessableItems() 354 for nproc == 0 && !q.closed { 355 if !block { 356 return nil 357 } 358 q.active.Wait() 359 nproc = q.countProcessableItems() 360 } 361 //因为我们有一个批量限制,所以不要在“悬空”的记忆中多拉一些。 362 if nproc > maxResultsProcess { 363 nproc = maxResultsProcess 364 } 365 results := make([]*fetchResult, nproc) 366 copy(results, q.resultCache[:nproc]) 367 if len(results) > 0 { 368 //将结果标记为已完成,然后将其从缓存中删除。 369 for _, result := range results { 370 hash := result.Header.Hash() 371 delete(q.blockDonePool, hash) 372 delete(q.receiptDonePool, hash) 373 } 374 //从缓存中删除结果并清除尾部。 375 copy(q.resultCache, q.resultCache[nproc:]) 376 for i := len(q.resultCache) - nproc; i < len(q.resultCache); i++ { 377 q.resultCache[i] = nil 378 } 379 //前进第一个缓存项的预期块号。 380 q.resultOffset += uint64(nproc) 381 382 //重新计算结果项权重以防止内存耗尽 383 for _, result := range results { 384 size := result.Header.Size() 385 for _, uncle := range result.Uncles { 386 size += uncle.Size() 387 } 388 for _, receipt := range result.Receipts { 389 size += receipt.Size() 390 } 391 for _, tx := range result.Transactions { 392 size += tx.Size() 393 } 394 q.resultSize = common.StorageSize(blockCacheSizeWeight)*size + (1-common.StorageSize(blockCacheSizeWeight))*q.resultSize 395 } 396 } 397 return results 398 } 399 400 //CountProcessableItems统计可处理的项。 401 func (q *queue) countProcessableItems() int { 402 for i, result := range q.resultCache { 403 if result == nil || result.Pending > 0 { 404 return i 405 } 406 } 407 return len(q.resultCache) 408 } 409 410 //ReserveHeaders为给定的对等端保留一组头,跳过任何 411 //以前失败的批。 412 func (q *queue) ReserveHeaders(p *peerConnection, count int) *fetchRequest { 413 q.lock.Lock() 414 defer q.lock.Unlock() 415 416 //如果对方已经下载了内容,则短路(请检查是否正常) 417 //未损坏状态) 418 if _, ok := q.headerPendPool[p.id]; ok { 419 return nil 420 } 421 //检索一批哈希,跳过以前失败的哈希 422 send, skip := uint64(0), []uint64{} 423 for send == 0 && !q.headerTaskQueue.Empty() { 424 from, _ := q.headerTaskQueue.Pop() 425 if q.headerPeerMiss[p.id] != nil { 426 if _, ok := q.headerPeerMiss[p.id][from.(uint64)]; ok { 427 skip = append(skip, from.(uint64)) 428 continue 429 } 430 } 431 send = from.(uint64) 432 } 433 //将所有跳过的批合并回 434 for _, from := range skip { 435 q.headerTaskQueue.Push(from, -float32(from)) 436 } 437 //汇编并返回块下载请求 438 if send == 0 { 439 return nil 440 } 441 request := &fetchRequest{ 442 Peer: p, 443 From: send, 444 Time: time.Now(), 445 } 446 q.headerPendPool[p.id] = request 447 return request 448 } 449 450 //ReserveBodies为给定的对等端保留一组正文提取,跳过任何 451 //以前下载失败。除了下一批需要的回迁之外,它还 452 //返回一个标志,指示是否已将空块排队以进行处理。 453 func (q *queue) ReserveBodies(p *peerConnection, count int) (*fetchRequest, bool, error) { 454 isNoop := func(header *types.Header) bool { 455 return header.TxHash == types.EmptyRootHash && header.UncleHash == types.EmptyUncleHash 456 } 457 q.lock.Lock() 458 defer q.lock.Unlock() 459 460 return q.reserveHeaders(p, count, q.blockTaskPool, q.blockTaskQueue, q.blockPendPool, q.blockDonePool, isNoop) 461 } 462 463 //ReserveReceipts为给定的对等方保留一组收据提取,跳过 464 //任何以前失败的下载。除了下一批需要的回迁之外,它 465 //还返回一个标志,指示是否已将空收据排队,需要导入。 466 func (q *queue) ReserveReceipts(p *peerConnection, count int) (*fetchRequest, bool, error) { 467 isNoop := func(header *types.Header) bool { 468 return header.ReceiptHash == types.EmptyRootHash 469 } 470 q.lock.Lock() 471 defer q.lock.Unlock() 472 473 return q.reserveHeaders(p, count, q.receiptTaskPool, q.receiptTaskQueue, q.receiptPendPool, q.receiptDonePool, isNoop) 474 } 475 476 //ReserveHeaders为给定的对等端保留一组数据下载操作, 477 //跳过任何以前失败的。此方法是使用的通用版本 478 //通过单独的特殊预订功能。 479 // 480 //注意,此方法预期队列锁已被保存用于写入。这个 481 //此处未获取锁的原因是参数已经需要 482 //要访问队列,因此它们无论如何都需要一个锁。 483 func (q *queue) reserveHeaders(p *peerConnection, count int, taskPool map[common.Hash]*types.Header, taskQueue *prque.Prque, 484 pendPool map[string]*fetchRequest, donePool map[common.Hash]struct{}, isNoop func(*types.Header) bool) (*fetchRequest, bool, error) { 485 //如果池已耗尽或对等机已耗尽,则短路 486 //正在下载某些内容(健全性检查不到损坏状态) 487 if taskQueue.Empty() { 488 return nil, false, nil 489 } 490 if _, ok := pendPool[p.id]; ok { 491 return nil, false, nil 492 } 493 //计算我们可能获取的项目的上限(即限制) 494 space := q.resultSlots(pendPool, donePool) 495 496 //检索一批任务,跳过以前失败的任务 497 send := make([]*types.Header, 0, count) 498 skip := make([]*types.Header, 0) 499 500 progress := false 501 for proc := 0; proc < space && len(send) < count && !taskQueue.Empty(); proc++ { 502 header := taskQueue.PopItem().(*types.Header) 503 hash := header.Hash() 504 505 //如果我们是第一个请求此任务的人,请初始化结果容器 506 index := int(header.Number.Int64() - int64(q.resultOffset)) 507 if index >= len(q.resultCache) || index < 0 { 508 common.Report("index allocation went beyond available resultCache space") 509 return nil, false, errInvalidChain 510 } 511 if q.resultCache[index] == nil { 512 components := 1 513 if q.mode == FastSync { 514 components = 2 515 } 516 q.resultCache[index] = &fetchResult{ 517 Pending: components, 518 Hash: hash, 519 Header: header, 520 } 521 } 522 //如果此提取任务是NOOP,则跳过此提取操作 523 if isNoop(header) { 524 donePool[hash] = struct{}{} 525 delete(taskPool, hash) 526 527 space, proc = space-1, proc-1 528 q.resultCache[index].Pending-- 529 progress = true 530 continue 531 } 532 //否则,除非知道对等端没有数据,否则将添加到检索列表中。 533 if p.Lacks(hash) { 534 skip = append(skip, header) 535 } else { 536 send = append(send, header) 537 } 538 } 539 //将所有跳过的邮件头合并回 540 for _, header := range skip { 541 taskQueue.Push(header, -float32(header.Number.Uint64())) 542 } 543 if progress { 544 //wake waitresults,resultcache已修改 545 q.active.Signal() 546 } 547 //汇编并返回块下载请求 548 if len(send) == 0 { 549 return nil, progress, nil 550 } 551 request := &fetchRequest{ 552 Peer: p, 553 Headers: send, 554 Time: time.Now(), 555 } 556 pendPool[p.id] = request 557 558 return request, progress, nil 559 } 560 561 //CancelHeaders中止提取请求,将所有挂起的骨架索引返回到队列。 562 func (q *queue) CancelHeaders(request *fetchRequest) { 563 q.cancel(request, q.headerTaskQueue, q.headerPendPool) 564 } 565 566 //取消主体中止主体提取请求,将所有挂起的头返回到 567 //任务队列。 568 func (q *queue) CancelBodies(request *fetchRequest) { 569 q.cancel(request, q.blockTaskQueue, q.blockPendPool) 570 } 571 572 //CancelReceipts中止主体提取请求,将所有挂起的头返回到 573 //任务队列。 574 func (q *queue) CancelReceipts(request *fetchRequest) { 575 q.cancel(request, q.receiptTaskQueue, q.receiptPendPool) 576 } 577 578 //取消中止提取请求,将所有挂起的哈希返回到任务队列。 579 func (q *queue) cancel(request *fetchRequest, taskQueue *prque.Prque, pendPool map[string]*fetchRequest) { 580 q.lock.Lock() 581 defer q.lock.Unlock() 582 583 if request.From > 0 { 584 taskQueue.Push(request.From, -float32(request.From)) 585 } 586 for _, header := range request.Headers { 587 taskQueue.Push(header, -float32(header.Number.Uint64())) 588 } 589 delete(pendPool, request.Peer.id) 590 } 591 592 //REVOKE取消属于给定对等机的所有挂起请求。这种方法是 593 //用于在对等机丢弃期间调用以快速重新分配拥有的数据提取 594 //到其余节点。 595 func (q *queue) Revoke(peerID string) { 596 q.lock.Lock() 597 defer q.lock.Unlock() 598 599 if request, ok := q.blockPendPool[peerID]; ok { 600 for _, header := range request.Headers { 601 q.blockTaskQueue.Push(header, -float32(header.Number.Uint64())) 602 } 603 delete(q.blockPendPool, peerID) 604 } 605 if request, ok := q.receiptPendPool[peerID]; ok { 606 for _, header := range request.Headers { 607 q.receiptTaskQueue.Push(header, -float32(header.Number.Uint64())) 608 } 609 delete(q.receiptPendPool, peerID) 610 } 611 } 612 613 //ExpireHeaders检查是否有超过超时允许的飞行请求, 614 //取消他们并将负责的同僚送回受罚。 615 func (q *queue) ExpireHeaders(timeout time.Duration) map[string]int { 616 q.lock.Lock() 617 defer q.lock.Unlock() 618 619 return q.expire(timeout, q.headerPendPool, q.headerTaskQueue, headerTimeoutMeter) 620 } 621 622 //ExpireBodies检查超过超时的飞行中块体请求 623 //津贴,取消他们,并将负责的同龄人送回受罚。 624 func (q *queue) ExpireBodies(timeout time.Duration) map[string]int { 625 q.lock.Lock() 626 defer q.lock.Unlock() 627 628 return q.expire(timeout, q.blockPendPool, q.blockTaskQueue, bodyTimeoutMeter) 629 } 630 631 //ExpireReceipts检查超过超时的飞行中接收请求 632 //津贴,取消他们,并将负责的同龄人送回受罚。 633 func (q *queue) ExpireReceipts(timeout time.Duration) map[string]int { 634 q.lock.Lock() 635 defer q.lock.Unlock() 636 637 return q.expire(timeout, q.receiptPendPool, q.receiptTaskQueue, receiptTimeoutMeter) 638 } 639 640 //Expire是将过期任务从挂起池移回的常规检查。 641 //在任务池中,返回捕获到过期任务的所有实体。 642 // 643 //注意,此方法期望队列锁已经被持有。这个 644 //此处未获取锁的原因是参数已经需要 645 //要访问队列,因此它们无论如何都需要一个锁。 646 func (q *queue) expire(timeout time.Duration, pendPool map[string]*fetchRequest, taskQueue *prque.Prque, timeoutMeter metrics.Meter) map[string]int { 647 //迭代过期的请求并将每个请求返回到队列 648 expiries := make(map[string]int) 649 for id, request := range pendPool { 650 if time.Since(request.Time) > timeout { 651 //用超时更新度量 652 timeoutMeter.Mark(1) 653 654 //将任何未满足的请求返回池 655 if request.From > 0 { 656 taskQueue.Push(request.From, -float32(request.From)) 657 } 658 for _, header := range request.Headers { 659 taskQueue.Push(header, -float32(header.Number.Uint64())) 660 } 661 //将对等端添加到到期报告中,同时添加失败请求的数量。 662 expiries[id] = len(request.Headers) 663 } 664 } 665 //从挂起的池中删除过期的请求 666 for id := range expiries { 667 delete(pendPool, id) 668 } 669 return expiries 670 } 671 672 //DeliverHeaders将头检索响应注入头结果中 673 //隐藏物。此方法要么接受它接收到的所有头,要么不接受任何头。 674 //如果它们不能正确映射到骨架。 675 // 676 //如果头被接受,该方法将尝试传递集合 677 //准备好的头到处理器以保持管道满。然而它会 678 //不阻止阻止其他待定的交付。 679 func (q *queue) DeliverHeaders(id string, headers []*types.Header, headerProcCh chan []*types.Header) (int, error) { 680 q.lock.Lock() 681 defer q.lock.Unlock() 682 683 //如果从未请求数据,则短路 684 request := q.headerPendPool[id] 685 if request == nil { 686 return 0, errNoFetchesPending 687 } 688 headerReqTimer.UpdateSince(request.Time) 689 delete(q.headerPendPool, id) 690 691 //确保头可以映射到骨架链上 692 target := q.headerTaskPool[request.From].Hash() 693 694 accepted := len(headers) == MaxHeaderFetch 695 if accepted { 696 if headers[0].Number.Uint64() != request.From { 697 log.Trace("First header broke chain ordering", "peer", id, "number", headers[0].Number, "hash", headers[0].Hash(), request.From) 698 accepted = false 699 } else if headers[len(headers)-1].Hash() != target { 700 log.Trace("Last header broke skeleton structure ", "peer", id, "number", headers[len(headers)-1].Number, "hash", headers[len(headers)-1].Hash(), "expected", target) 701 accepted = false 702 } 703 } 704 if accepted { 705 for i, header := range headers[1:] { 706 hash := header.Hash() 707 if want := request.From + 1 + uint64(i); header.Number.Uint64() != want { 708 log.Warn("Header broke chain ordering", "peer", id, "number", header.Number, "hash", hash, "expected", want) 709 accepted = false 710 break 711 } 712 if headers[i].Hash() != header.ParentHash { 713 log.Warn("Header broke chain ancestry", "peer", id, "number", header.Number, "hash", hash) 714 accepted = false 715 break 716 } 717 } 718 } 719 //如果批头未被接受,则标记为不可用 720 if !accepted { 721 log.Trace("Skeleton filling not accepted", "peer", id, "from", request.From) 722 723 miss := q.headerPeerMiss[id] 724 if miss == nil { 725 q.headerPeerMiss[id] = make(map[uint64]struct{}) 726 miss = q.headerPeerMiss[id] 727 } 728 miss[request.From] = struct{}{} 729 730 q.headerTaskQueue.Push(request.From, -float32(request.From)) 731 return 0, errors.New("delivery not accepted") 732 } 733 //清除成功的获取并尝试传递任何子结果 734 copy(q.headerResults[request.From-q.headerOffset:], headers) 735 delete(q.headerTaskPool, request.From) 736 737 ready := 0 738 for q.headerProced+ready < len(q.headerResults) && q.headerResults[q.headerProced+ready] != nil { 739 ready += MaxHeaderFetch 740 } 741 if ready > 0 { 742 //收割台准备好交付,收集它们并向前推(非阻塞) 743 process := make([]*types.Header, ready) 744 copy(process, q.headerResults[q.headerProced:q.headerProced+ready]) 745 746 select { 747 case headerProcCh <- process: 748 log.Trace("Pre-scheduled new headers", "peer", id, "count", len(process), "from", process[0].Number) 749 q.headerProced += len(process) 750 default: 751 } 752 } 753 //检查终止和返回 754 if len(q.headerTaskPool) == 0 { 755 q.headerContCh <- false 756 } 757 return len(headers), nil 758 } 759 760 //DeliverBodies将块体检索响应注入结果队列。 761 //该方法返回从传递中接受的块体数,以及 762 //同时唤醒等待数据传递的任何线程。 763 func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, uncleLists [][]*types.Header) (int, error) { 764 q.lock.Lock() 765 defer q.lock.Unlock() 766 767 reconstruct := func(header *types.Header, index int, result *fetchResult) error { 768 if types.DeriveSha(types.Transactions(txLists[index])) != header.TxHash || types.CalcUncleHash(uncleLists[index]) != header.UncleHash { 769 return errInvalidBody 770 } 771 result.Transactions = txLists[index] 772 result.Uncles = uncleLists[index] 773 return nil 774 } 775 return q.deliver(id, q.blockTaskPool, q.blockTaskQueue, q.blockPendPool, q.blockDonePool, bodyReqTimer, len(txLists), reconstruct) 776 } 777 778 //DeliverReceipts将收据检索响应插入结果队列。 779 //该方法返回从传递中接受的事务处理接收数。 780 //并唤醒等待数据传递的任何线程。 781 func (q *queue) DeliverReceipts(id string, receiptList [][]*types.Receipt) (int, error) { 782 q.lock.Lock() 783 defer q.lock.Unlock() 784 785 reconstruct := func(header *types.Header, index int, result *fetchResult) error { 786 if types.DeriveSha(types.Receipts(receiptList[index])) != header.ReceiptHash { 787 return errInvalidReceipt 788 } 789 result.Receipts = receiptList[index] 790 return nil 791 } 792 return q.deliver(id, q.receiptTaskPool, q.receiptTaskQueue, q.receiptPendPool, q.receiptDonePool, receiptReqTimer, len(receiptList), reconstruct) 793 } 794 795 //传递将数据检索响应注入结果队列。 796 // 797 //注意,此方法预期队列锁已被保存用于写入。这个 798 //此处未获取锁的原因是参数已经需要 799 //要访问队列,因此它们无论如何都需要一个锁。 800 func (q *queue) deliver(id string, taskPool map[common.Hash]*types.Header, taskQueue *prque.Prque, 801 pendPool map[string]*fetchRequest, donePool map[common.Hash]struct{}, reqTimer metrics.Timer, 802 results int, reconstruct func(header *types.Header, index int, result *fetchResult) error) (int, error) { 803 804 //如果从未请求数据,则短路 805 request := pendPool[id] 806 if request == nil { 807 return 0, errNoFetchesPending 808 } 809 reqTimer.UpdateSince(request.Time) 810 delete(pendPool, id) 811 812 //如果未检索到数据项,则将其标记为对源对等机不可用 813 if results == 0 { 814 for _, header := range request.Headers { 815 request.Peer.MarkLacking(header.Hash()) 816 } 817 } 818 //将每个结果与其标题和检索到的数据部分组合在一起 819 var ( 820 accepted int 821 failure error 822 useful bool 823 ) 824 for i, header := range request.Headers { 825 //如果找不到更多提取结果,则短路程序集 826 if i >= results { 827 break 828 } 829 //如果内容匹配,则重建下一个结果 830 index := int(header.Number.Int64() - int64(q.resultOffset)) 831 if index >= len(q.resultCache) || index < 0 || q.resultCache[index] == nil { 832 failure = errInvalidChain 833 break 834 } 835 if err := reconstruct(header, i, q.resultCache[index]); err != nil { 836 failure = err 837 break 838 } 839 hash := header.Hash() 840 841 donePool[hash] = struct{}{} 842 q.resultCache[index].Pending-- 843 useful = true 844 accepted++ 845 846 //清除成功的获取 847 request.Headers[i] = nil 848 delete(taskPool, hash) 849 } 850 //将所有失败或丢失的提取返回到队列 851 for _, header := range request.Headers { 852 if header != nil { 853 taskQueue.Push(header, -float32(header.Number.Uint64())) 854 } 855 } 856 //唤醒等待结果 857 if accepted > 0 { 858 q.active.Signal() 859 } 860 //如果没有一个数据是好的,那就是过时的交付 861 switch { 862 case failure == nil || failure == errInvalidChain: 863 return accepted, failure 864 case useful: 865 return accepted, fmt.Errorf("partial failure: %v", failure) 866 default: 867 return accepted, errStaleDelivery 868 } 869 } 870 871 //准备将结果缓存配置为允许接受和缓存入站 872 //获取结果。 873 func (q *queue) Prepare(offset uint64, mode SyncMode) { 874 q.lock.Lock() 875 defer q.lock.Unlock() 876 877 //为同步结果准备队列 878 if q.resultOffset < offset { 879 q.resultOffset = offset 880 } 881 q.mode = mode 882 } 883