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  }