github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/core/bloombits/scheduler.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  //版权所有2017 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  package bloombits
    26  
    27  import (
    28  	"sync"
    29  )
    30  
    31  //请求表示一个Bloom检索任务,以确定优先级并从本地
    32  //数据库或从网络远程访问。
    33  type request struct {
    34  section uint64 //从中检索位向量的节索引
    35  bit     uint   //段内的位索引,用于检索
    36  }
    37  
    38  //响应表示通过调度程序请求的位向量的状态。
    39  type response struct {
    40  cached []byte        //用于消除多个请求的缓存位
    41  done   chan struct{} //允许等待完成的通道
    42  }
    43  
    44  //调度程序处理Bloom过滤器检索操作的调度
    45  //整段批次属于一个单独的开孔钻头。除了安排
    46  //检索操作,此结构还消除重复请求和缓存
    47  //即使在复杂的过滤中,也能最大限度地减少网络/数据库开销。
    48  //情节。
    49  type scheduler struct {
    50  bit       uint                 //此计划程序负责的Bloom筛选器中位的索引
    51  responses map[uint64]*response //当前挂起的检索请求或已缓存的响应
    52  lock      sync.Mutex           //防止响应并发访问的锁
    53  }
    54  
    55  //Newscheduler为特定的
    56  //位索引。
    57  func newScheduler(idx uint) *scheduler {
    58  	return &scheduler{
    59  		bit:       idx,
    60  		responses: make(map[uint64]*response),
    61  	}
    62  }
    63  
    64  //运行创建检索管道,从节和
    65  //通过完成通道以相同顺序返回结果。同时发生的
    66  //允许运行同一个调度程序,从而导致检索任务重复数据消除。
    67  func (s *scheduler) run(sections chan uint64, dist chan *request, done chan []byte, quit chan struct{}, wg *sync.WaitGroup) {
    68  //在与相同大小的请求和响应之间创建转发器通道
    69  //分配通道(因为这样会阻塞管道)。
    70  	pend := make(chan uint64, cap(dist))
    71  
    72  //启动管道调度程序在用户->分发服务器->用户之间转发
    73  	wg.Add(2)
    74  	go s.scheduleRequests(sections, dist, pend, quit, wg)
    75  	go s.scheduleDeliveries(pend, done, quit, wg)
    76  }
    77  
    78  //重置将清除以前运行的所有剩余部分。这是在
    79  //重新启动以确保以前没有请求但从未传递的状态将
    80  //导致锁定。
    81  func (s *scheduler) reset() {
    82  	s.lock.Lock()
    83  	defer s.lock.Unlock()
    84  
    85  	for section, res := range s.responses {
    86  		if res.cached == nil {
    87  			delete(s.responses, section)
    88  		}
    89  	}
    90  }
    91  
    92  //schedulerequests从输入通道读取段检索请求,
    93  //消除流中的重复数据并将唯一的检索任务推送到分发中
    94  //数据库或网络层的通道。
    95  func (s *scheduler) scheduleRequests(reqs chan uint64, dist chan *request, pend chan uint64, quit chan struct{}, wg *sync.WaitGroup) {
    96  //完成后清理Goroutine和管道
    97  	defer wg.Done()
    98  	defer close(pend)
    99  
   100  //继续阅读和安排分区请求
   101  	for {
   102  		select {
   103  		case <-quit:
   104  			return
   105  
   106  		case section, ok := <-reqs:
   107  //请求新分区检索
   108  			if !ok {
   109  				return
   110  			}
   111  //消除重复检索请求
   112  			unique := false
   113  
   114  			s.lock.Lock()
   115  			if s.responses[section] == nil {
   116  				s.responses[section] = &response{
   117  					done: make(chan struct{}),
   118  				}
   119  				unique = true
   120  			}
   121  			s.lock.Unlock()
   122  
   123  //安排检索部分的时间,并通知交付者期望此部分
   124  			if unique {
   125  				select {
   126  				case <-quit:
   127  					return
   128  				case dist <- &request{bit: s.bit, section: section}:
   129  				}
   130  			}
   131  			select {
   132  			case <-quit:
   133  				return
   134  			case pend <- section:
   135  			}
   136  		}
   137  	}
   138  }
   139  
   140  //ScheduledDeliveries读取区段接受通知并等待它们
   141  //要传递,将它们推入输出数据缓冲区。
   142  func (s *scheduler) scheduleDeliveries(pend chan uint64, done chan []byte, quit chan struct{}, wg *sync.WaitGroup) {
   143  //完成后清理Goroutine和管道
   144  	defer wg.Done()
   145  	defer close(done)
   146  
   147  //继续阅读通知并安排交货
   148  	for {
   149  		select {
   150  		case <-quit:
   151  			return
   152  
   153  		case idx, ok := <-pend:
   154  //新分区检索挂起
   155  			if !ok {
   156  				return
   157  			}
   158  //等到请求得到满足为止
   159  			s.lock.Lock()
   160  			res := s.responses[idx]
   161  			s.lock.Unlock()
   162  
   163  			select {
   164  			case <-quit:
   165  				return
   166  			case <-res.done:
   167  			}
   168  //交付结果
   169  			select {
   170  			case <-quit:
   171  				return
   172  			case done <- res.cached:
   173  			}
   174  		}
   175  	}
   176  }
   177  
   178  //请求分发服务器在对请求的答复到达时调用传递。
   179  func (s *scheduler) deliver(sections []uint64, data [][]byte) {
   180  	s.lock.Lock()
   181  	defer s.lock.Unlock()
   182  
   183  	for i, section := range sections {
   184  if res := s.responses[section]; res != nil && res.cached == nil { //避免非请求和双倍交货
   185  			res.cached = data[i]
   186  			close(res.done)
   187  		}
   188  	}
   189  }