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