github.com/turingchain2020/turingchain@v1.1.21/p2p/utils/filterrepeatdata.go (about)

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package utils
     6  
     7  import (
     8  	"sync"
     9  	"sync/atomic"
    10  	"time"
    11  
    12  	log "github.com/turingchain2020/turingchain/common/log/log15"
    13  
    14  	"github.com/turingchain2020/turingchain/types"
    15  	lru "github.com/hashicorp/golang-lru"
    16  )
    17  
    18  // NewFilter produce a filter object
    19  func NewFilter(num int) *Filterdata {
    20  	filter := new(Filterdata)
    21  	var err error
    22  	filter.regRData, err = lru.New(num)
    23  	if err != nil {
    24  		panic(err)
    25  	}
    26  	return filter
    27  }
    28  
    29  // Filterdata filter data attribute
    30  type Filterdata struct {
    31  	isclose    int32
    32  	regRData   *lru.Cache
    33  	atomicLock sync.Mutex
    34  }
    35  
    36  // GetAtomicLock get lock
    37  func (f *Filterdata) GetAtomicLock() {
    38  	f.atomicLock.Lock()
    39  }
    40  
    41  // ReleaseAtomicLock release lock
    42  func (f *Filterdata) ReleaseAtomicLock() {
    43  	f.atomicLock.Unlock()
    44  }
    45  
    46  // Contains  query receive data by key
    47  func (f *Filterdata) Contains(key string) bool {
    48  	ok := f.regRData.Contains(key)
    49  	return ok
    50  
    51  }
    52  
    53  // Remove remove receive data by key
    54  func (f *Filterdata) Remove(key string) {
    55  	f.regRData.Remove(key)
    56  }
    57  
    58  // Close the filter object
    59  func (f *Filterdata) Close() {
    60  	atomic.StoreInt32(&f.isclose, 1)
    61  }
    62  
    63  func (f *Filterdata) isClose() bool {
    64  	return atomic.LoadInt32(&f.isclose) == 1
    65  }
    66  
    67  // ManageRecvFilter manager receive filter
    68  func (f *Filterdata) ManageRecvFilter(tickTime time.Duration) {
    69  	ticker := time.NewTicker(tickTime)
    70  	var timeout int64 = 60
    71  	defer ticker.Stop()
    72  	for {
    73  		<-ticker.C
    74  		now := types.Now().Unix()
    75  		for _, key := range f.regRData.Keys() {
    76  			regtime, exist := f.regRData.Get(key)
    77  			if !exist {
    78  				log.Warn("Not found in regRData", "Key", key)
    79  				continue
    80  			}
    81  			if now-regtime.(int64) < timeout {
    82  				break
    83  			}
    84  			f.regRData.Remove(key)
    85  		}
    86  
    87  		if f.isClose() {
    88  			return
    89  		}
    90  	}
    91  }
    92  
    93  // Add add val
    94  func (f *Filterdata) Add(key string, val interface{}) bool {
    95  
    96  	return f.regRData.Add(key, val)
    97  }
    98  
    99  // Get get val
   100  func (f *Filterdata) Get(key string) (interface{}, bool) {
   101  	val, ok := f.regRData.Get(key)
   102  	return val, ok
   103  }
   104  
   105  //AddWithCheckAtomic add key if key not exist with atomic lock, return true if exist
   106  func (f *Filterdata) AddWithCheckAtomic(key string, val interface{}) (exist bool) {
   107  
   108  	f.GetAtomicLock()
   109  	defer f.ReleaseAtomicLock()
   110  	if f.Contains(key) {
   111  		return true
   112  	}
   113  	f.Add(key, val)
   114  	return false
   115  }