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) {}