github.com/saintwish/kv@v1.0.4/kv2/kv2.go (about) 1 package kv2 2 3 import ( 4 "fmt" 5 6 "github.com/dolthub/maphash" 7 ) 8 9 type Cache[K comparable, V any] struct { 10 shards []shardCapacity[K, V] 11 shardCount uint64 12 hash maphash.Hasher[K] 13 14 OnEvicted 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("kv2: shard count must be smaller than cache size!") 20 } 21 22 cache := Cache[K, V] {} 23 cache.shards = make([]shardCapacity[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] = newShardCapacity[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) shardCapacity[K, V] { 41 sum := c.hash.Hash(key) 42 return c.shards[sum%c.shardCount] 43 } 44 45 func (c *Cache[K, V]) SetOnEvicted(f func(K, V)) { 46 c.OnEvicted = 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]) GetRenew(key K) V { 55 shard := c.getShard(key) 56 return shard.getRenew(key) 57 } 58 59 func (c *Cache[K, V]) GetHas(key K) (V, bool) { 60 shard := c.getShard(key) 61 return shard.getHas(key) 62 } 63 64 func (c *Cache[K, V]) GetHasRenew(key K) (V, bool) { 65 shard := c.getShard(key) 66 return shard.getHasRenew(key) 67 } 68 69 func (c *Cache[K, V]) Has(key K) bool { 70 shard := c.getShard(key) 71 return shard.has(key) 72 } 73 74 func (c *Cache[K, V]) Set(key K, val V) { 75 shard := c.getShard(key) 76 shard.set(key, val, c.OnEvicted) 77 } 78 79 func (c *Cache[K, V]) Add(key K, val V) error { 80 shard := c.getShard(key) 81 if shard.has(key) { 82 return fmt.Errorf("kv2: Data already exists with given key %T", key) 83 } 84 85 shard.set(key, val, c.OnEvicted) 86 return nil 87 } 88 89 func (c *Cache[K, V]) Update(key K, val V) error { 90 shard := c.getShard(key) 91 if !shard.has(key) { 92 return fmt.Errorf("kv2: Data doesn't exists with given key %T", key) 93 } 94 95 shard.update(key, val) 96 return nil 97 } 98 99 func (c *Cache[K, V]) SetOrUpdate(key K, val V) { 100 shard := c.getShard(key) 101 if shard.has(key) { 102 shard.update(key, val) 103 }else{ 104 shard.set(key, val, c.OnEvicted) 105 } 106 } 107 108 func (c *Cache[K, V]) Delete(key K) bool { 109 shard := c.getShard(key) 110 return shard.delete(key) 111 } 112 113 func (c *Cache[K, V]) DeleteCallback(key K) bool { 114 shard := c.getShard(key) 115 return shard.deleteCallback(key, c.OnEvicted) 116 } 117 118 func (c *Cache[K, V]) ShardCount() uint64 { 119 return c.shardCount 120 } 121 122 func (c *Cache[K, V]) GetShardSize(key K) int { 123 shard := c.getShard(key) 124 return shard.Map.Count() 125 } 126 127 func (c *Cache[K, V]) GetShardMaxSize(key K) int { 128 shard := c.getShard(key) 129 return shard.Map.MaxCapacity() 130 } 131 132 func (c *Cache[K, V]) GetShardCapacity(key K) int { 133 shard := c.getShard(key) 134 return shard.Map.Capacity() 135 } 136 137 // Clears the cache with calling OnEviction callback 138 func (c *Cache[K, V]) Flush() { 139 for i := 0; i < len(c.shards); i++ { 140 shard := c.shards[i] 141 shard.flush(c.OnEvicted) 142 } 143 } 144 145 // Clears the cache without calling OnEviction callback 146 func (c *Cache[K, V]) Clear() { 147 for i := 0; i < len(c.shards); i++ { 148 shard := c.shards[i] 149 shard.clear() 150 } 151 } 152 153 func (c *Cache[K, V]) ForEach(f func(key K, val V)) { 154 for i := 0; i < len(c.shards); i++ { 155 shard := c.shards[i] 156 shard.Lock() 157 158 shard.Map.Iter(func(key K, val item[V]) (stop bool) { 159 f(key, val.Object) 160 161 if stop { 162 shard.Unlock() 163 return 164 } 165 166 return 167 }) 168 169 shard.Unlock() 170 } 171 }