github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/eth/bloombits.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 19:16:37</date> 10 //</624450087761743872> 11 12 13 package eth 14 15 import ( 16 "context" 17 "time" 18 19 "github.com/ethereum/go-ethereum/common" 20 "github.com/ethereum/go-ethereum/common/bitutil" 21 "github.com/ethereum/go-ethereum/core" 22 "github.com/ethereum/go-ethereum/core/bloombits" 23 "github.com/ethereum/go-ethereum/core/rawdb" 24 "github.com/ethereum/go-ethereum/core/types" 25 "github.com/ethereum/go-ethereum/ethdb" 26 ) 27 28 const ( 29 //BloomServiceThreads是以太坊全局使用的Goroutine数。 30 //实例到服务BloomBits查找所有正在运行的筛选器。 31 bloomServiceThreads = 16 32 33 //BloomFilterThreads是每个筛选器本地使用的goroutine数,用于 34 //将请求多路传输到全局服务goroutine。 35 bloomFilterThreads = 3 36 37 //BloomRetrievalBatch是要服务的最大Bloom位检索数。 38 //一批。 39 bloomRetrievalBatch = 16 40 41 //BloomRetrievalWait是等待足够的Bloom位请求的最长时间。 42 //累积请求整个批(避免滞后)。 43 bloomRetrievalWait = time.Duration(0) 44 ) 45 46 //StartBloomHandlers启动一批Goroutine以接受BloomBit数据库 47 //retrievals from possibly a range of filters and serving the data to satisfy. 48 func (eth *Ethereum) startBloomHandlers(sectionSize uint64) { 49 for i := 0; i < bloomServiceThreads; i++ { 50 go func() { 51 for { 52 select { 53 case <-eth.shutdownChan: 54 return 55 56 case request := <-eth.bloomRequests: 57 task := <-request 58 task.Bitsets = make([][]byte, len(task.Sections)) 59 for i, section := range task.Sections { 60 head := rawdb.ReadCanonicalHash(eth.chainDb, (section+1)*sectionSize-1) 61 if compVector, err := rawdb.ReadBloomBits(eth.chainDb, task.Bit, section, head); err == nil { 62 if blob, err := bitutil.DecompressBytes(compVector, int(sectionSize/8)); err == nil { 63 task.Bitsets[i] = blob 64 } else { 65 task.Error = err 66 } 67 } else { 68 task.Error = err 69 } 70 } 71 request <- task 72 } 73 } 74 }() 75 } 76 } 77 78 const ( 79 //BloomThrottling是处理两个连续索引之间的等待时间。 80 //部分。它在链升级期间很有用,可以防止磁盘过载。 81 bloomThrottling = 100 * time.Millisecond 82 ) 83 84 //BloomIndexer实现core.chainIndexer,建立旋转的BloomBits索引 85 //对于以太坊头段Bloom过滤器,允许快速过滤。 86 type BloomIndexer struct { 87 size uint64 //要为其生成bloombits的节大小 88 db ethdb.Database //要将索引数据和元数据写入的数据库实例 89 gen *bloombits.Generator //发电机旋转盛开钻头,装入盛开指数 90 section uint64 //节是当前正在处理的节号 91 head common.Hash //head是最后处理的头的哈希值 92 } 93 94 //newbloomindexer返回一个链索引器,它为 95 //用于快速日志筛选的规范链。 96 func NewBloomIndexer(db ethdb.Database, size, confirms uint64) *core.ChainIndexer { 97 backend := &BloomIndexer{ 98 db: db, 99 size: size, 100 } 101 table := ethdb.NewTable(db, string(rawdb.BloomBitsIndexPrefix)) 102 103 return core.NewChainIndexer(db, table, backend, size, confirms, bloomThrottling, "bloombits") 104 } 105 106 //reset实现core.chainindexerbackend,启动新的bloombits索引 107 //部分。 108 func (b *BloomIndexer) Reset(ctx context.Context, section uint64, lastSectionHead common.Hash) error { 109 gen, err := bloombits.NewGenerator(uint(b.size)) 110 b.gen, b.section, b.head = gen, section, common.Hash{} 111 return err 112 } 113 114 //进程实现了core.chainindexerbackend,将新头的bloom添加到 115 //索引。 116 func (b *BloomIndexer) Process(ctx context.Context, header *types.Header) error { 117 b.gen.AddBloom(uint(header.Number.Uint64()-b.section*b.size), header.Bloom) 118 b.head = header.Hash() 119 return nil 120 } 121 122 //commit实现core.chainindexerbackend,完成bloom部分和 123 //把它写进数据库。 124 func (b *BloomIndexer) Commit() error { 125 batch := b.db.NewBatch() 126 for i := 0; i < types.BloomBitLength; i++ { 127 bits, err := b.gen.Bitset(uint(i)) 128 if err != nil { 129 return err 130 } 131 rawdb.WriteBloomBits(batch, uint(i), b.section, b.head, bitutil.CompressBytes(bits)) 132 } 133 return batch.Write() 134 } 135