github.com/aakash4dev/cometbft@v0.38.2/mempool/cache.go (about)

     1  package mempool
     2  
     3  import (
     4  	"container/list"
     5  
     6  	cmtsync "github.com/aakash4dev/cometbft/libs/sync"
     7  	"github.com/aakash4dev/cometbft/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  	// Has reports whether tx is present in the cache. Checking for presence is
    27  	// not treated as an access of the value.
    28  	Has(tx types.Tx) bool
    29  }
    30  
    31  var _ TxCache = (*LRUTxCache)(nil)
    32  
    33  // LRUTxCache maintains a thread-safe LRU cache of raw transactions. The cache
    34  // only stores the hash of the raw transaction.
    35  type LRUTxCache struct {
    36  	mtx      cmtsync.Mutex
    37  	size     int
    38  	cacheMap map[types.TxKey]*list.Element
    39  	list     *list.List
    40  }
    41  
    42  func NewLRUTxCache(cacheSize int) *LRUTxCache {
    43  	return &LRUTxCache{
    44  		size:     cacheSize,
    45  		cacheMap: make(map[types.TxKey]*list.Element, cacheSize),
    46  		list:     list.New(),
    47  	}
    48  }
    49  
    50  // GetList returns the underlying linked-list that backs the LRU cache. Note,
    51  // this should be used for testing purposes only!
    52  func (c *LRUTxCache) GetList() *list.List {
    53  	return c.list
    54  }
    55  
    56  func (c *LRUTxCache) Reset() {
    57  	c.mtx.Lock()
    58  	defer c.mtx.Unlock()
    59  
    60  	c.cacheMap = make(map[types.TxKey]*list.Element, c.size)
    61  	c.list.Init()
    62  }
    63  
    64  func (c *LRUTxCache) Push(tx types.Tx) bool {
    65  	c.mtx.Lock()
    66  	defer c.mtx.Unlock()
    67  
    68  	key := tx.Key()
    69  
    70  	moved, ok := c.cacheMap[key]
    71  	if ok {
    72  		c.list.MoveToBack(moved)
    73  		return false
    74  	}
    75  
    76  	if c.list.Len() >= c.size {
    77  		front := c.list.Front()
    78  		if front != nil {
    79  			frontKey := front.Value.(types.TxKey)
    80  			delete(c.cacheMap, frontKey)
    81  			c.list.Remove(front)
    82  		}
    83  	}
    84  
    85  	e := c.list.PushBack(key)
    86  	c.cacheMap[key] = e
    87  
    88  	return true
    89  }
    90  
    91  func (c *LRUTxCache) Remove(tx types.Tx) {
    92  	c.mtx.Lock()
    93  	defer c.mtx.Unlock()
    94  
    95  	key := tx.Key()
    96  	e := c.cacheMap[key]
    97  	delete(c.cacheMap, key)
    98  
    99  	if e != nil {
   100  		c.list.Remove(e)
   101  	}
   102  }
   103  
   104  func (c *LRUTxCache) Has(tx types.Tx) bool {
   105  	c.mtx.Lock()
   106  	defer c.mtx.Unlock()
   107  
   108  	_, ok := c.cacheMap[tx.Key()]
   109  	return ok
   110  }
   111  
   112  // NopTxCache defines a no-op raw transaction cache.
   113  type NopTxCache struct{}
   114  
   115  var _ TxCache = (*NopTxCache)(nil)
   116  
   117  func (NopTxCache) Reset()             {}
   118  func (NopTxCache) Push(types.Tx) bool { return true }
   119  func (NopTxCache) Remove(types.Tx)    {}
   120  func (NopTxCache) Has(types.Tx) bool  { return false }