github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/store/cache/cache.go (about)

     1  package cache
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/cachekv"
     7  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/types"
     8  
     9  	lru "github.com/hashicorp/golang-lru"
    10  )
    11  
    12  var (
    13  	_ types.CommitKVStore             = (*CommitKVStoreCache)(nil)
    14  	_ types.MultiStorePersistentCache = (*CommitKVStoreCacheManager)(nil)
    15  
    16  	// DefaultCommitKVStoreCacheSize defines the persistent ARC cache size for a
    17  	// CommitKVStoreCache.
    18  	DefaultCommitKVStoreCacheSize uint = 1000
    19  )
    20  
    21  type (
    22  	// CommitKVStoreCache implements an inter-block (persistent) cache that wraps a
    23  	// CommitKVStore. Reads first hit the internal ARC (Adaptive Replacement Cache).
    24  	// During a cache miss, the read is delegated to the underlying CommitKVStore
    25  	// and cached. Deletes and writes always happen to both the cache and the
    26  	// CommitKVStore in a write-through manner. Caching performed in the
    27  	// CommitKVStore and below is completely irrelevant to this layer.
    28  	CommitKVStoreCache struct {
    29  		types.CommitKVStore
    30  		cache *lru.ARCCache
    31  	}
    32  
    33  	// CommitKVStoreCacheManager maintains a mapping from a StoreKey to a
    34  	// CommitKVStoreCache. Each CommitKVStore, per StoreKey, is meant to be used
    35  	// in an inter-block (persistent) manner and typically provided by a
    36  	// CommitMultiStore.
    37  	CommitKVStoreCacheManager struct {
    38  		cacheSize uint
    39  		caches    map[string]types.CommitKVStore
    40  	}
    41  )
    42  
    43  func NewCommitKVStoreCache(store types.CommitKVStore, size uint) *CommitKVStoreCache {
    44  	cache, err := lru.NewARC(int(size))
    45  	if err != nil {
    46  		panic(fmt.Errorf("failed to create KVStore cache: %s", err))
    47  	}
    48  
    49  	return &CommitKVStoreCache{
    50  		CommitKVStore: store,
    51  		cache:         cache,
    52  	}
    53  }
    54  
    55  func NewCommitKVStoreCacheManager(size uint) *CommitKVStoreCacheManager {
    56  	return &CommitKVStoreCacheManager{
    57  		cacheSize: size,
    58  		caches:    make(map[string]types.CommitKVStore),
    59  	}
    60  }
    61  
    62  // GetStoreCache returns a Cache from the CommitStoreCacheManager for a given
    63  // StoreKey. If no Cache exists for the StoreKey, then one is created and set.
    64  // The returned Cache is meant to be used in a persistent manner.
    65  func (cmgr *CommitKVStoreCacheManager) GetStoreCache(key types.StoreKey, store types.CommitKVStore) types.CommitKVStore {
    66  	if cmgr.caches[key.Name()] == nil {
    67  		cmgr.caches[key.Name()] = NewCommitKVStoreCache(store, cmgr.cacheSize)
    68  	}
    69  
    70  	return cmgr.caches[key.Name()]
    71  }
    72  
    73  // Unwrap returns the underlying CommitKVStore for a given StoreKey.
    74  func (cmgr *CommitKVStoreCacheManager) Unwrap(key types.StoreKey) types.CommitKVStore {
    75  	if ckv, ok := cmgr.caches[key.Name()]; ok {
    76  		return ckv.(*CommitKVStoreCache).CommitKVStore
    77  	}
    78  
    79  	return nil
    80  }
    81  
    82  // Reset resets in the internal caches.
    83  func (cmgr *CommitKVStoreCacheManager) Reset() {
    84  	cmgr.caches = make(map[string]types.CommitKVStore)
    85  }
    86  
    87  // CacheWrap returns the inter-block cache as a cache-wrapped CommitKVStore.
    88  func (ckv *CommitKVStoreCache) CacheWrap() types.CacheWrap {
    89  	return cachekv.NewStore(ckv)
    90  }
    91  
    92  // Get retrieves a value by key. It will first look in the write-through cache.
    93  // If the value doesn't exist in the write-through cache, the query is delegated
    94  // to the underlying CommitKVStore.
    95  func (ckv *CommitKVStoreCache) Get(key []byte) []byte {
    96  	types.AssertValidKey(key)
    97  
    98  	keyStr := string(key)
    99  	valueI, ok := ckv.cache.Get(keyStr)
   100  	if ok {
   101  		// cache hit
   102  		return valueI.([]byte)
   103  	}
   104  
   105  	// cache miss; write to cache
   106  	value := ckv.CommitKVStore.Get(key)
   107  	ckv.cache.Add(keyStr, value)
   108  
   109  	return value
   110  }
   111  
   112  // Set inserts a key/value pair into both the write-through cache and the
   113  // underlying CommitKVStore.
   114  func (ckv *CommitKVStoreCache) Set(key, value []byte) {
   115  	types.AssertValidKey(key)
   116  	types.AssertValidValue(value)
   117  
   118  	ckv.cache.Add(string(key), value)
   119  	ckv.CommitKVStore.Set(key, value)
   120  }
   121  
   122  // Delete removes a key/value pair from both the write-through cache and the
   123  // underlying CommitKVStore.
   124  func (ckv *CommitKVStoreCache) Delete(key []byte) {
   125  	ckv.cache.Remove(string(key))
   126  	ckv.CommitKVStore.Delete(key)
   127  }