github.com/saintwish/kv@v1.0.4/kv1/kv1.go (about)

     1  package kv1
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  	
     7  	"github.com/dolthub/maphash"
     8  )
     9  
    10  type Cache[K comparable, V any] struct {
    11  	shards []shard[K, V]
    12  	shardCount uint64
    13  	hash maphash.Hasher[K]
    14  
    15  	OnEvicted func(K, V) //function that's called when cached item is deleted by the system
    16  }
    17  
    18  func New[K comparable, V any](ex time.Duration, sz uint64, sc uint64) *Cache[K, V] {
    19  	if sc > sz {
    20  		panic("kv1: shard count must be smaller than cache size!")
    21  	}
    22  
    23  	cache := Cache[K, V] {}
    24  	cache.shards = make([]shard[K, V], sc)
    25  	cache.hash = maphash.NewHasher[K]()
    26  	cache.shardCount = sc
    27  
    28  	for i := 0; i < int(sc); i++ {
    29  		cache.shards[i] = newShard[K, V](ex, sz, sc)
    30  	}
    31  
    32  	return &cache
    33  }
    34  
    35  func (c *Cache[K, V]) getShardIndex(key K) uint64 {
    36  	sum := c.hash.Hash(key)
    37  
    38  	return sum % c.shardCount
    39  }
    40  
    41  func (c *Cache[K, V]) getShard(key K) shard[K,V] {
    42  	sum := c.hash.Hash(key)
    43  	return c.shards[sum%c.shardCount]
    44  }
    45  
    46  func (c *Cache[K, V]) SetOnEvicted(f func(K, V)) {
    47  	c.OnEvicted = f
    48  }
    49  
    50  func (c *Cache[K, V]) Get(key K) V {
    51  	shard := c.getShard(key)
    52  	return shard.get(key)
    53  }
    54  
    55  func (c *Cache[K, V]) GetRenew(key K) V {
    56  	shard := c.getShard(key)
    57  	return shard.getRenew(key)
    58  }
    59  
    60  func (c *Cache[K, V]) GetHas(key K) (V, bool) {
    61  	shard := c.getShard(key)
    62  	return shard.getHas(key)
    63  }
    64  
    65  func (c *Cache[K, V]) GetHasRenew(key K) (V, bool) {
    66  	shard := c.getShard(key)
    67  	return shard.getHasRenew(key)
    68  }
    69  
    70  func (c *Cache[K, V]) Has(key K) bool {
    71  	shard := c.getShard(key)
    72  	return shard.has(key)
    73  }
    74  
    75  // Sets the key with value, will overwrite if key exists
    76  func (c *Cache[K, V]) Set(key K, val V) {
    77  	shard := c.getShard(key)
    78  	shard.set(key, val)
    79  }
    80  
    81  // Adds key with value to map, will error if key already exists.
    82  func (c *Cache[K, V]) Add(key K, val V) error {
    83  	shard := c.getShard(key)
    84  	if shard.has(key) {
    85  		return fmt.Errorf("kv1: Data already exists with given key %T", key)
    86  	}
    87  
    88  	shard.set(key, val)
    89  	return nil
    90  }
    91  
    92  // Updates given key, errors if key doesn't already exists.
    93  func (c *Cache[K, V]) Update(key K, val V) error {
    94  	shard := c.getShard(key)
    95  	if !shard.has(key) {
    96  		return fmt.Errorf("kv1: Data doesn't exists with given key %T", key)
    97  	}
    98  
    99  	shard.update(key, val)
   100  	return nil
   101  }
   102  
   103  // Will Set or Update said key depending if exists or not.
   104  func (c *Cache[K, V]) SetOrUpdate(key K, val V) {
   105  	shard := c.getShard(key)
   106  	if shard.has(key) {
   107  		shard.update(key, val)
   108  	}else{
   109  		shard.set(key, val)
   110  	}
   111  }
   112  
   113  func (c *Cache[K, V]) Renew(key K) {
   114  	shard := c.getShard(key)
   115  	shard.renew(key)
   116  }
   117  
   118  func (c *Cache[K, V]) Delete(key K) bool {
   119  	shard := c.getShard(key)
   120  	return shard.delete(key)
   121  }
   122  
   123  func (c *Cache[K, V]) ShardCount() uint64 {
   124  	return c.shardCount
   125  }
   126  
   127  func (c *Cache[K, V]) GetShardSize(key K) int {
   128  	shard := c.getShard(key)
   129  	return shard.Map.Count()
   130  }
   131  
   132  func (c *Cache[K, V]) GetShardMaxSize(key K) int {
   133  	shard := c.getShard(key)
   134  	return shard.Map.MaxCapacity()
   135  }
   136  
   137  func (c *Cache[K, V]) GetShardCapacity(key K) int {
   138  	shard := c.getShard(key)
   139  	return shard.Map.Capacity()
   140  }
   141  
   142  // Gets the current amount of elements in the cache.
   143  func (c *Cache[K, V]) Count() (count int) {
   144  	for i := 0; i < len(c.shards); i++ {
   145  		shard := c.shards[i]
   146  		count = count + shard.Map.Count()
   147  	}
   148  	return
   149  }
   150  
   151  // Clears the cache with calling OnEviction callback
   152  func (c *Cache[K, V]) Flush() {
   153  	for i := 0; i < len(c.shards); i++ {
   154  		shard := c.shards[i]
   155  		shard.flush(c.OnEvicted)
   156  	}
   157  }
   158  
   159  // Clears the cache without calling OnEviction callback
   160  func (c *Cache[K, V]) Clear() {
   161  	for i := 0; i < len(c.shards); i++ {
   162  		shard := c.shards[i]
   163  		shard.clear()
   164  	}
   165  }
   166  
   167  func (c *Cache[K, V]) ForEach(f func(key K, val item[V])) {
   168  	for i := 0; i < len(c.shards); i++ {
   169  		shard := c.shards[i]
   170  		shard.Lock()
   171  
   172  		shard.Map.Iter(func(key K, val item[V]) (stop bool) {
   173  			f(key, val)
   174  
   175  			if stop {
   176  				shard.Unlock()
   177  				return
   178  			}
   179  
   180  			return
   181  		})
   182  
   183  		shard.Unlock()
   184  	}
   185  }
   186  
   187  func (c *Cache[K,V]) DeleteExpired() {
   188  	for i := 0; i < len(c.shards); i++ {
   189  		shard := c.shards[i]
   190  		shard.evictExpired(c.OnEvicted)
   191  	}
   192  }
   193  
   194  func (c *Cache[K,V]) IsExpired(key K) bool {
   195  	shard := c.getShard(key)
   196  	return shard.isExpired(key)
   197  }