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

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