github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/core/bloombits/matcher.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  	"bytes"
    29  	"context"
    30  	"errors"
    31  	"math"
    32  	"sort"
    33  	"sync"
    34  	"sync/atomic"
    35  	"time"
    36  
    37  	"github.com/ethereum/go-ethereum/common/bitutil"
    38  	"github.com/ethereum/go-ethereum/crypto"
    39  )
    40  
    41  //bloom indexes表示bloom过滤器中属于
    42  //一些关键。
    43  type bloomIndexes [3]uint
    44  
    45  //calcBloomIndexes返回属于给定键的BloomFilter位索引。
    46  func calcBloomIndexes(b []byte) bloomIndexes {
    47  	b = crypto.Keccak256(b)
    48  
    49  	var idxs bloomIndexes
    50  	for i := 0; i < len(idxs); i++ {
    51  		idxs[i] = (uint(b[2*i])<<8)&2047 + uint(b[2*i+1])
    52  	}
    53  	return idxs
    54  }
    55  
    56  //带有非零矢量的粒子图表示一个部分,其中一些子-
    57  //匹配者已经找到了可能的匹配项。后续的子匹配者将
    58  //二进制及其与该向量的匹配。如果矢量为零,则表示
    59  //由第一个子匹配器处理的部分。
    60  type partialMatches struct {
    61  	section uint64
    62  	bitset  []byte
    63  }
    64  
    65  //检索表示对给定任务的检索任务分配的请求
    66  //具有给定数量的提取元素的位,或对这种请求的响应。
    67  //它还可以将实际结果集用作传递数据结构。
    68  //
    69  //“竞赛”和“错误”字段由轻型客户端用于终止匹配
    70  //如果在管道的某个路径上遇到错误,则为早期。
    71  type Retrieval struct {
    72  	Bit      uint
    73  	Sections []uint64
    74  	Bitsets  [][]byte
    75  
    76  	Context context.Context
    77  	Error   error
    78  }
    79  
    80  //Matcher是一个由调度程序和逻辑匹配程序组成的流水线系统,执行
    81  //位流上的二进制和/或操作,创建一个潜在的流
    82  //要检查数据内容的块。
    83  type Matcher struct {
    84  sectionSize uint64 //要筛选的数据批的大小
    85  
    86  filters    [][]bloomIndexes    //系统匹配的筛选器
    87  schedulers map[uint]*scheduler //用于装载钻头的检索调度程序
    88  
    89  retrievers chan chan uint       //检索器处理等待位分配
    90  counters   chan chan uint       //检索器进程正在等待任务计数报告
    91  retrievals chan chan *Retrieval //检索器进程正在等待任务分配
    92  deliveries chan *Retrieval      //检索器进程正在等待任务响应传递
    93  
    94  running uint32 //原子标记会话是否处于活动状态
    95  }
    96  
    97  //NewMatcher创建了一个新的管道,用于检索Bloom位流并执行
    98  //地址和主题过滤。将筛选器组件设置为“nil”是
    99  //允许并将导致跳过该筛选规则(或0x11…1)。
   100  func NewMatcher(sectionSize uint64, filters [][][]byte) *Matcher {
   101  //创建Matcher实例
   102  	m := &Matcher{
   103  		sectionSize: sectionSize,
   104  		schedulers:  make(map[uint]*scheduler),
   105  		retrievers:  make(chan chan uint),
   106  		counters:    make(chan chan uint),
   107  		retrievals:  make(chan chan *Retrieval),
   108  		deliveries:  make(chan *Retrieval),
   109  	}
   110  //计算我们感兴趣的组的bloom位索引
   111  	m.filters = nil
   112  
   113  	for _, filter := range filters {
   114  //采集滤波规则的位指标,专用套管零滤波器
   115  		if len(filter) == 0 {
   116  			continue
   117  		}
   118  		bloomBits := make([]bloomIndexes, len(filter))
   119  		for i, clause := range filter {
   120  			if clause == nil {
   121  				bloomBits = nil
   122  				break
   123  			}
   124  			bloomBits[i] = calcBloomIndexes(clause)
   125  		}
   126  //如果不包含nil规则,则累积筛选规则
   127  		if bloomBits != nil {
   128  			m.filters = append(m.filters, bloomBits)
   129  		}
   130  	}
   131  //对于每个位,创建一个调度程序来加载/下载位向量
   132  	for _, bloomIndexLists := range m.filters {
   133  		for _, bloomIndexList := range bloomIndexLists {
   134  			for _, bloomIndex := range bloomIndexList {
   135  				m.addScheduler(bloomIndex)
   136  			}
   137  		}
   138  	}
   139  	return m
   140  }
   141  
   142  //addscheduler为给定的位索引添加位流检索计划程序,如果
   143  //它以前不存在。如果已选择位进行过滤,则
   144  //可以使用现有的计划程序。
   145  func (m *Matcher) addScheduler(idx uint) {
   146  	if _, ok := m.schedulers[idx]; ok {
   147  		return
   148  	}
   149  	m.schedulers[idx] = newScheduler(idx)
   150  }
   151  
   152  //Start启动匹配过程并返回一个bloom匹配流
   153  //给定的块范围。如果范围内没有更多匹配项,则返回结果
   154  //通道关闭。
   155  func (m *Matcher) Start(ctx context.Context, begin, end uint64, results chan uint64) (*MatcherSession, error) {
   156  //确保我们没有创建并发会话
   157  	if atomic.SwapUint32(&m.running, 1) == 1 {
   158  		return nil, errors.New("matcher already running")
   159  	}
   160  	defer atomic.StoreUint32(&m.running, 0)
   161  
   162  //启动新的匹配轮
   163  	session := &MatcherSession{
   164  		matcher: m,
   165  		quit:    make(chan struct{}),
   166  		kill:    make(chan struct{}),
   167  		ctx:     ctx,
   168  	}
   169  	for _, scheduler := range m.schedulers {
   170  		scheduler.reset()
   171  	}
   172  	sink := m.run(begin, end, cap(results), session)
   173  
   174  //从结果接收器读取输出并传递给用户
   175  	session.pend.Add(1)
   176  	go func() {
   177  		defer session.pend.Done()
   178  		defer close(results)
   179  
   180  		for {
   181  			select {
   182  			case <-session.quit:
   183  				return
   184  
   185  			case res, ok := <-sink:
   186  //找到新的匹配结果
   187  				if !ok {
   188  					return
   189  				}
   190  //计算该节的第一个和最后一个块
   191  				sectionStart := res.section * m.sectionSize
   192  
   193  				first := sectionStart
   194  				if begin > first {
   195  					first = begin
   196  				}
   197  				last := sectionStart + m.sectionSize - 1
   198  				if end < last {
   199  					last = end
   200  				}
   201  //遍历该节中的所有块并返回匹配的块
   202  				for i := first; i <= last; i++ {
   203  //如果在内部没有找到匹配项,则跳过整个字节(我们正在处理整个字节!)
   204  					next := res.bitset[(i-sectionStart)/8]
   205  					if next == 0 {
   206  						if i%8 == 0 {
   207  							i += 7
   208  						}
   209  						continue
   210  					}
   211  //设置一些位,做实际的子匹配
   212  					if bit := 7 - i%8; next&(1<<bit) != 0 {
   213  						select {
   214  						case <-session.quit:
   215  							return
   216  						case results <- i:
   217  						}
   218  					}
   219  				}
   220  			}
   221  		}
   222  	}()
   223  	return session, nil
   224  }
   225  
   226  //运行创建子匹配器的菊花链,一个用于地址集,另一个用于
   227  //对于每个主题集,每个子匹配器仅在上一个主题集
   228  //所有人都在该路段的一个街区找到了一个潜在的匹配点,
   229  //然后二进制和ing自己匹配并将结果转发到下一个结果。
   230  //
   231  //该方法开始向上的第一个子匹配器提供节索引。
   232  //并返回接收结果的接收通道。
   233  func (m *Matcher) run(begin, end uint64, buffer int, session *MatcherSession) chan *partialMatches {
   234  //创建源通道并将节索引馈送到
   235  	source := make(chan *partialMatches, buffer)
   236  
   237  	session.pend.Add(1)
   238  	go func() {
   239  		defer session.pend.Done()
   240  		defer close(source)
   241  
   242  		for i := begin / m.sectionSize; i <= end/m.sectionSize; i++ {
   243  			select {
   244  			case <-session.quit:
   245  				return
   246  			case source <- &partialMatches{i, bytes.Repeat([]byte{0xff}, int(m.sectionSize/8))}:
   247  			}
   248  		}
   249  	}()
   250  //组装菊花链过滤管道
   251  	next := source
   252  	dist := make(chan *request, buffer)
   253  
   254  	for _, bloom := range m.filters {
   255  		next = m.subMatch(next, dist, bloom, session)
   256  	}
   257  //启动请求分发
   258  	session.pend.Add(1)
   259  	go m.distributor(dist, session)
   260  
   261  	return next
   262  }
   263  
   264  //Submatch创建一个子匹配器,该匹配器过滤一组地址或主题(二进制或-s),然后
   265  //二进制和-s将结果发送到菊花链输入(源),并将其转发到菊花链输出。
   266  //每个地址/主题的匹配是通过获取属于
   267  //这个地址/主题,二进制和将这些向量组合在一起。
   268  func (m *Matcher) subMatch(source chan *partialMatches, dist chan *request, bloom []bloomIndexes, session *MatcherSession) chan *partialMatches {
   269  //为Bloom过滤器所需的每个位启动并发调度程序
   270  	sectionSources := make([][3]chan uint64, len(bloom))
   271  	sectionSinks := make([][3]chan []byte, len(bloom))
   272  	for i, bits := range bloom {
   273  		for j, bit := range bits {
   274  			sectionSources[i][j] = make(chan uint64, cap(source))
   275  			sectionSinks[i][j] = make(chan []byte, cap(source))
   276  
   277  			m.schedulers[bit].run(sectionSources[i][j], dist, sectionSinks[i][j], session.quit, &session.pend)
   278  		}
   279  	}
   280  
   281  process := make(chan *partialMatches, cap(source)) //在初始化提取之后,源中的条目将在此处转发。
   282  	results := make(chan *partialMatches, cap(source))
   283  
   284  	session.pend.Add(2)
   285  	go func() {
   286  //关闭Goroutine并终止所有源通道
   287  		defer session.pend.Done()
   288  		defer close(process)
   289  
   290  		defer func() {
   291  			for _, bloomSources := range sectionSources {
   292  				for _, bitSource := range bloomSources {
   293  					close(bitSource)
   294  				}
   295  			}
   296  		}()
   297  //从源信道中读取段,并多路复用到所有位调度程序中。
   298  		for {
   299  			select {
   300  			case <-session.quit:
   301  				return
   302  
   303  			case subres, ok := <-source:
   304  //从上一链接新建子结果
   305  				if !ok {
   306  					return
   307  				}
   308  //将区段索引多路复用到所有位调度程序
   309  				for _, bloomSources := range sectionSources {
   310  					for _, bitSource := range bloomSources {
   311  						select {
   312  						case <-session.quit:
   313  							return
   314  						case bitSource <- subres.section:
   315  						}
   316  					}
   317  				}
   318  //通知处理器此部分将可用
   319  				select {
   320  				case <-session.quit:
   321  					return
   322  				case process <- subres:
   323  				}
   324  			}
   325  		}
   326  	}()
   327  
   328  	go func() {
   329  //拆除Goroutine并终止最终水槽通道
   330  		defer session.pend.Done()
   331  		defer close(results)
   332  
   333  //读取源通知并收集传递的结果
   334  		for {
   335  			select {
   336  			case <-session.quit:
   337  				return
   338  
   339  			case subres, ok := <-process:
   340  //已通知正在检索的节
   341  				if !ok {
   342  					return
   343  				}
   344  //收集所有子结果并将它们合并在一起
   345  				var orVector []byte
   346  				for _, bloomSinks := range sectionSinks {
   347  					var andVector []byte
   348  					for _, bitSink := range bloomSinks {
   349  						var data []byte
   350  						select {
   351  						case <-session.quit:
   352  							return
   353  						case data = <-bitSink:
   354  						}
   355  						if andVector == nil {
   356  							andVector = make([]byte, int(m.sectionSize/8))
   357  							copy(andVector, data)
   358  						} else {
   359  							bitutil.ANDBytes(andVector, andVector, data)
   360  						}
   361  					}
   362  					if orVector == nil {
   363  						orVector = andVector
   364  					} else {
   365  						bitutil.ORBytes(orVector, orVector, andVector)
   366  					}
   367  				}
   368  
   369  				if orVector == nil {
   370  					orVector = make([]byte, int(m.sectionSize/8))
   371  				}
   372  				if subres.bitset != nil {
   373  					bitutil.ANDBytes(orVector, orVector, subres.bitset)
   374  				}
   375  				if bitutil.TestBytes(orVector) {
   376  					select {
   377  					case <-session.quit:
   378  						return
   379  					case results <- &partialMatches{subres.section, orVector}:
   380  					}
   381  				}
   382  			}
   383  		}
   384  	}()
   385  	return results
   386  }
   387  
   388  //分发服务器接收来自调度程序的请求并将它们排队到一个集合中
   389  //待处理的请求,这些请求被分配给想要完成它们的检索器。
   390  func (m *Matcher) distributor(dist chan *request, session *MatcherSession) {
   391  	defer session.pend.Done()
   392  
   393  	var (
   394  requests   = make(map[uint][]uint64) //按节号排序的节请求的逐位列表
   395  unallocs   = make(map[uint]struct{}) //具有挂起请求但未分配给任何检索器的位
   396  retrievers chan chan uint            //等待检索器(如果unallocs为空,则切换为nil)
   397  	)
   398  	var (
   399  allocs   int            //处理正常关闭请求的活动分配数
   400  shutdown = session.quit //关闭请求通道,将优雅地等待挂起的请求
   401  	)
   402  
   403  //assign是一个帮助方法,用于尝试将挂起的位
   404  //监听服务,或者在有人到达后安排它。
   405  	assign := func(bit uint) {
   406  		select {
   407  		case fetcher := <-m.retrievers:
   408  			allocs++
   409  			fetcher <- bit
   410  		default:
   411  //没有激活的检索器,开始监听新的检索器
   412  			retrievers = m.retrievers
   413  			unallocs[bit] = struct{}{}
   414  		}
   415  	}
   416  
   417  	for {
   418  		select {
   419  		case <-shutdown:
   420  //请求正常关闭,等待所有挂起的请求得到满足。
   421  			if allocs == 0 {
   422  				return
   423  			}
   424  			shutdown = nil
   425  
   426  		case <-session.kill:
   427  //未及时处理的未决请求,硬终止
   428  			return
   429  
   430  		case req := <-dist:
   431  //到达新的检索请求,将其分发到某个提取进程
   432  			queue := requests[req.bit]
   433  			index := sort.Search(len(queue), func(i int) bool { return queue[i] >= req.section })
   434  			requests[req.bit] = append(queue[:index], append([]uint64{req.section}, queue[index:]...)...)
   435  
   436  //如果是一个新的位,我们有等待取数器,分配给他们
   437  			if len(queue) == 0 {
   438  				assign(req.bit)
   439  			}
   440  
   441  		case fetcher := <-retrievers:
   442  //新的检索器到达,找到要分配的最下面的ed位。
   443  			bit, best := uint(0), uint64(math.MaxUint64)
   444  			for idx := range unallocs {
   445  				if requests[idx][0] < best {
   446  					bit, best = idx, requests[idx][0]
   447  				}
   448  			}
   449  //停止跟踪此位(如果没有更多工作可用,则停止分配通知)
   450  			delete(unallocs, bit)
   451  			if len(unallocs) == 0 {
   452  				retrievers = nil
   453  			}
   454  			allocs++
   455  			fetcher <- bit
   456  
   457  		case fetcher := <-m.counters:
   458  //新任务计数请求已到达,返回项目数
   459  			fetcher <- uint(len(requests[<-fetcher]))
   460  
   461  		case fetcher := <-m.retrievals:
   462  //等待任务检索、分配的新提取程序
   463  			task := <-fetcher
   464  			if want := len(task.Sections); want >= len(requests[task.Bit]) {
   465  				task.Sections = requests[task.Bit]
   466  				delete(requests, task.Bit)
   467  			} else {
   468  				task.Sections = append(task.Sections[:0], requests[task.Bit][:want]...)
   469  				requests[task.Bit] = append(requests[task.Bit][:0], requests[task.Bit][want:]...)
   470  			}
   471  			fetcher <- task
   472  
   473  //如果有未分配的内容,请尝试分配给其他人
   474  			if len(requests[task.Bit]) > 0 {
   475  				assign(task.Bit)
   476  			}
   477  
   478  		case result := <-m.deliveries:
   479  //从获取器中新建检索任务响应,拆分缺少的部分和
   480  //交付完整的
   481  			var (
   482  				sections = make([]uint64, 0, len(result.Sections))
   483  				bitsets  = make([][]byte, 0, len(result.Bitsets))
   484  				missing  = make([]uint64, 0, len(result.Sections))
   485  			)
   486  			for i, bitset := range result.Bitsets {
   487  				if len(bitset) == 0 {
   488  					missing = append(missing, result.Sections[i])
   489  					continue
   490  				}
   491  				sections = append(sections, result.Sections[i])
   492  				bitsets = append(bitsets, bitset)
   493  			}
   494  			m.schedulers[result.Bit].deliver(sections, bitsets)
   495  			allocs--
   496  
   497  //重新安排缺少的部分,如果新的部分可用,则分配位
   498  			if len(missing) > 0 {
   499  				queue := requests[result.Bit]
   500  				for _, section := range missing {
   501  					index := sort.Search(len(queue), func(i int) bool { return queue[i] >= section })
   502  					queue = append(queue[:index], append([]uint64{section}, queue[index:]...)...)
   503  				}
   504  				requests[result.Bit] = queue
   505  
   506  				if len(queue) == len(missing) {
   507  					assign(result.Bit)
   508  				}
   509  			}
   510  //如果我们正在关闭,请终止
   511  			if allocs == 0 && shutdown == nil {
   512  				return
   513  			}
   514  		}
   515  	}
   516  }
   517  
   518  //MatcherSession由已启动的Matcher返回,用作终止符
   519  //对于正在运行的匹配操作。
   520  type MatcherSession struct {
   521  	matcher *Matcher
   522  
   523  closer sync.Once     //同步对象以确保只关闭一次
   524  quit   chan struct{} //退出通道以请求管道终止
   525  kill   chan struct{} //表示非正常强制停机的通道
   526  
   527  ctx context.Context //轻型客户端用于中止筛选的上下文
   528  err atomic.Value    //跟踪链深处检索失败的全局错误
   529  
   530  	pend sync.WaitGroup
   531  }
   532  
   533  //关闭停止匹配进程并等待所有子进程终止
   534  //返回前。超时可用于正常关机,允许
   535  //当前正在运行要在此时间之前完成的检索。
   536  func (s *MatcherSession) Close() {
   537  	s.closer.Do(func() {
   538  //信号终止并等待所有Goroutine关闭
   539  		close(s.quit)
   540  		time.AfterFunc(time.Second, func() { close(s.kill) })
   541  		s.pend.Wait()
   542  	})
   543  }
   544  
   545  //错误返回匹配会话期间遇到的任何失败。
   546  func (s *MatcherSession) Error() error {
   547  	if err := s.err.Load(); err != nil {
   548  		return err.(error)
   549  	}
   550  	return nil
   551  }
   552  
   553  //allocateretrieval将一个bloom位索引分配给一个客户端进程,该进程可以
   554  //立即请求并获取分配给该位的节内容或等待
   555  //有一段时间需要更多的部分。
   556  func (s *MatcherSession) AllocateRetrieval() (uint, bool) {
   557  	fetcher := make(chan uint)
   558  
   559  	select {
   560  	case <-s.quit:
   561  		return 0, false
   562  	case s.matcher.retrievers <- fetcher:
   563  		bit, ok := <-fetcher
   564  		return bit, ok
   565  	}
   566  }
   567  
   568  //PendingSections返回属于
   569  //给定的牙轮钻头指数。
   570  func (s *MatcherSession) PendingSections(bit uint) int {
   571  	fetcher := make(chan uint)
   572  
   573  	select {
   574  	case <-s.quit:
   575  		return 0
   576  	case s.matcher.counters <- fetcher:
   577  		fetcher <- bit
   578  		return int(<-fetcher)
   579  	}
   580  }
   581  
   582  //分配操作分配已分配的位任务队列的全部或部分
   583  //到请求过程。
   584  func (s *MatcherSession) AllocateSections(bit uint, count int) []uint64 {
   585  	fetcher := make(chan *Retrieval)
   586  
   587  	select {
   588  	case <-s.quit:
   589  		return nil
   590  	case s.matcher.retrievals <- fetcher:
   591  		task := &Retrieval{
   592  			Bit:      bit,
   593  			Sections: make([]uint64, count),
   594  		}
   595  		fetcher <- task
   596  		return (<-fetcher).Sections
   597  	}
   598  }
   599  
   600  //deliversections为特定的bloom提供一批区段位向量
   601  //要注入处理管道的位索引。
   602  func (s *MatcherSession) DeliverSections(bit uint, sections []uint64, bitsets [][]byte) {
   603  	select {
   604  	case <-s.kill:
   605  		return
   606  	case s.matcher.deliveries <- &Retrieval{Bit: bit, Sections: sections, Bitsets: bitsets}:
   607  	}
   608  }
   609  
   610  //多路复用轮询匹配器会话以执行检索任务,并将其多路复用到
   611  //请求的检索队列将与其他会话一起提供服务。
   612  //
   613  //此方法将在会话的生存期内阻塞。即使在终止之后
   614  //在会议期间,任何在飞行中的请求都需要得到响应!空响应
   615  //不过在那种情况下还是可以的。
   616  func (s *MatcherSession) Multiplex(batch int, wait time.Duration, mux chan chan *Retrieval) {
   617  	for {
   618  //分配新的Bloom位索引以检索数据,完成后停止
   619  		bit, ok := s.AllocateRetrieval()
   620  		if !ok {
   621  			return
   622  		}
   623  //位分配,如果低于批处理限制,则限制一点
   624  		if s.PendingSections(bit) < batch {
   625  			select {
   626  			case <-s.quit:
   627  //会话终止,我们无法有意义地服务,中止
   628  				s.AllocateSections(bit, 0)
   629  				s.DeliverSections(bit, []uint64{}, [][]byte{})
   630  				return
   631  
   632  			case <-time.After(wait):
   633  //节流,获取任何可用的
   634  			}
   635  		}
   636  //尽可能多地分配和请求服务
   637  		sections := s.AllocateSections(bit, batch)
   638  		request := make(chan *Retrieval)
   639  
   640  		select {
   641  		case <-s.quit:
   642  //会话终止,我们无法有意义地服务,中止
   643  			s.DeliverSections(bit, sections, make([][]byte, len(sections)))
   644  			return
   645  
   646  		case mux <- request:
   647  //接受检索,必须在中止之前到达
   648  			request <- &Retrieval{Bit: bit, Sections: sections, Context: s.ctx}
   649  
   650  			result := <-request
   651  			if result.Error != nil {
   652  				s.err.Store(result.Error)
   653  				s.Close()
   654  			}
   655  			s.DeliverSections(result.Bit, result.Sections, result.Bitsets)
   656  		}
   657  	}
   658  }