github.com/number571/tendermint@v0.34.11-gost/internal/mempool/cache.go (about)

     1  package mempool
     2  
     3  import (
     4  	"container/list"
     5  
     6  	tmsync "github.com/number571/tendermint/internal/libs/sync"
     7  	"github.com/number571/tendermint/types"
     8  )
     9  
    10  // TxCache defines an interface for raw transaction caching in a mempool.
    11  // Currently, a TxCache does not allow direct reading or getting of transaction
    12  // values. A TxCache is used primarily to push transactions and removing
    13  // transactions. Pushing via Push returns a boolean telling the caller if the
    14  // transaction already exists in the cache or not.
    15  type TxCache interface {
    16  	// Reset resets the cache to an empty state.
    17  	Reset()
    18  
    19  	// Push adds the given raw transaction to the cache and returns true if it was
    20  	// newly added. Otherwise, it returns false.
    21  	Push(tx types.Tx) bool
    22  
    23  	// Remove removes the given raw transaction from the cache.
    24  	Remove(tx types.Tx)
    25  }
    26  
    27  var _ TxCache = (*LRUTxCache)(nil)
    28  
    29  // LRUTxCache maintains a thread-safe LRU cache of raw transactions. The cache
    30  // only stores the hash of the raw transaction.
    31  type LRUTxCache struct {
    32  	mtx      tmsync.Mutex
    33  	size     int
    34  	cacheMap map[[TxKeySize]byte]*list.Element
    35  	list     *list.List
    36  }
    37  
    38  func NewLRUTxCache(cacheSize int) *LRUTxCache {
    39  	return &LRUTxCache{
    40  		size:     cacheSize,
    41  		cacheMap: make(map[[TxKeySize]byte]*list.Element, cacheSize),
    42  		list:     list.New(),
    43  	}
    44  }
    45  
    46  // GetList returns the underlying linked-list that backs the LRU cache. Note,
    47  // this should be used for testing purposes only!
    48  func (c *LRUTxCache) GetList() *list.List {
    49  	return c.list
    50  }
    51  
    52  func (c *LRUTxCache) Reset() {
    53  	c.mtx.Lock()
    54  	defer c.mtx.Unlock()
    55  
    56  	c.cacheMap = make(map[[TxKeySize]byte]*list.Element, c.size)
    57  	c.list.Init()
    58  }
    59  
    60  func (c *LRUTxCache) Push(tx types.Tx) bool {
    61  	c.mtx.Lock()
    62  	defer c.mtx.Unlock()
    63  
    64  	key := TxKey(tx)
    65  
    66  	moved, ok := c.cacheMap[key]
    67  	if ok {
    68  		c.list.MoveToBack(moved)
    69  		return false
    70  	}
    71  
    72  	if c.list.Len() >= c.size {
    73  		front := c.list.Front()
    74  		if front != nil {
    75  			frontKey := front.Value.([TxKeySize]byte)
    76  			delete(c.cacheMap, frontKey)
    77  			c.list.Remove(front)
    78  		}
    79  	}
    80  
    81  	e := c.list.PushBack(key)
    82  	c.cacheMap[key] = e
    83  
    84  	return true
    85  }
    86  
    87  func (c *LRUTxCache) Remove(tx types.Tx) {
    88  	c.mtx.Lock()
    89  	defer c.mtx.Unlock()
    90  
    91  	key := TxKey(tx)
    92  	e := c.cacheMap[key]
    93  	delete(c.cacheMap, key)
    94  
    95  	if e != nil {
    96  		c.list.Remove(e)
    97  	}
    98  }
    99  
   100  // NopTxCache defines a no-op raw transaction cache.
   101  type NopTxCache struct{}
   102  
   103  var _ TxCache = (*NopTxCache)(nil)
   104  
   105  func (NopTxCache) Reset()             {}
   106  func (NopTxCache) Push(types.Tx) bool { return true }
   107  func (NopTxCache) Remove(types.Tx)    {}