github.com/annchain/OG@v0.0.9/og/syncer/bloom_filter.go (about) 1 // Copyright © 2019 Annchain Authors <EMAIL ADDRESS> 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 package syncer 15 16 import ( 17 "fmt" 18 "github.com/annchain/OG/arefactor/og/types" 19 "github.com/annchain/OG/og/types/archive" 20 "sync" 21 "time" 22 ) 23 24 //adding bloom filter status , avoid send too frequently, after sending a request , wait until got response or time out 25 // 26 type BloomFilterFireStatus struct { 27 mu sync.RWMutex 28 startTime time.Time 29 requestId uint32 30 gotResponse bool 31 minFrequency time.Duration 32 responseTimeOut time.Duration 33 } 34 35 func NewBloomFilterFireStatus(minFrequencyTime int, responseTimeOut int) *BloomFilterFireStatus { 36 if minFrequencyTime >= responseTimeOut { 37 panic(fmt.Sprintf("param err %v, %v", minFrequencyTime, responseTimeOut)) 38 } 39 return &BloomFilterFireStatus{ 40 requestId: 0, 41 gotResponse: true, 42 minFrequency: time.Duration(minFrequencyTime) * time.Millisecond, 43 responseTimeOut: time.Millisecond * time.Duration(responseTimeOut), 44 } 45 } 46 47 func (b *BloomFilterFireStatus) set(requestId uint32) { 48 b.requestId = requestId 49 b.gotResponse = false 50 b.startTime = time.Now() 51 } 52 53 func (b *BloomFilterFireStatus) Set(requestId uint32) { 54 b.mu.Lock() 55 defer b.mu.Unlock() 56 b.set(requestId) 57 } 58 59 func (b *BloomFilterFireStatus) UpdateResponse(requestId uint32) { 60 b.mu.RLock() 61 defer b.mu.RUnlock() 62 b.updateResponse(requestId) 63 } 64 65 func (b *BloomFilterFireStatus) updateResponse(requestId uint32) { 66 if b.requestId != requestId { 67 return 68 } 69 b.gotResponse = true 70 log.WithField("requestId ", requestId).WithField("after ", time.Now().Sub(b.startTime)).Debug( 71 "bloom filter got response after") 72 return 73 } 74 75 func (b *BloomFilterFireStatus) Check() bool { 76 b.mu.RLock() 77 defer b.mu.RUnlock() 78 return b.check() 79 } 80 81 func (b *BloomFilterFireStatus) check() bool { 82 stamp := time.Now().Sub(b.startTime) 83 if stamp > b.responseTimeOut { 84 return true 85 } 86 if b.gotResponse == true && stamp > b.minFrequency { 87 return true 88 } 89 return false 90 } 91 92 //sendBloomFilter , avoid sending bloom filter frequently ,wait until got response of bloom filter or timeout 93 94 func (m *IncrementalSyncer) sendBloomFilter(childhash types.Hash) { 95 if !m.bloomFilterStatus.Check() { 96 log.Debug("bloom filter request is pending") 97 return 98 } 99 req := archive.MessageSyncRequest{ 100 Filter: archive.NewBloomFilter(15000), 101 RequestId: message_archive.MsgCounter.Get(), 102 } 103 m.bloomFilterStatus.Set(req.RequestId) 104 height := m.getHeight() 105 req.Height = &height 106 hashs := m.getTxsHashes() 107 for _, hash := range hashs { 108 req.Filter.AddItem(hash.Bytes[:]) 109 } 110 err := req.Filter.Encode() 111 if err != nil { 112 log.WithError(err).Warn("encode filter err") 113 return 114 } 115 log.WithField("height ", height).WithField("type", archive.MessageTypeFetchByHashRequest).WithField( 116 "req ", req.String()).WithField("filter length", len(req.Filter.Data)).Debug( 117 "sending bloom filter MessageTypeFetchByHashRequest") 118 119 //m.messageSender.UnicastMessageRandomly(p2p_message.MessageTypeFetchByHashRequest, bytes) 120 //if the random peer dose't have this txs ,we will get nil response ,so broadcast it 121 hash := childhash 122 m.messageSender.MulticastToSource(archive.MessageTypeFetchByHashRequest, &req, &hash) 123 return 124 }