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