mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-31 01:10:20 -06:00
102 lines
1.9 KiB
Go
102 lines
1.9 KiB
Go
package cache
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
)
|
|
|
|
// Entry represents an entry on the cache. You can type assert on V.
|
|
type Entry struct {
|
|
V interface{}
|
|
Valid bool
|
|
}
|
|
|
|
// Cache is a barebones cache implementation.
|
|
type Cache struct {
|
|
entries map[string]map[string]Entry
|
|
size int
|
|
m sync.Mutex
|
|
}
|
|
|
|
// NewCache returns a new instance of Cache.
|
|
func NewCache(o ...Option) Cache {
|
|
opts := newOptions(o...)
|
|
|
|
return Cache{
|
|
size: opts.size,
|
|
entries: map[string]map[string]Entry{},
|
|
}
|
|
}
|
|
|
|
// Get gets an entry on a service `svcKey` by a give `key`.
|
|
func (c *Cache) Get(svcKey, key string) (*Entry, error) {
|
|
var value Entry
|
|
ok := true
|
|
|
|
c.m.Lock()
|
|
defer c.m.Unlock()
|
|
|
|
if value, ok = c.entries[svcKey][key]; !ok {
|
|
return nil, fmt.Errorf("invalid service key: `%v`", key)
|
|
}
|
|
|
|
return &value, nil
|
|
}
|
|
|
|
// Set sets a key / value. It lets a service add entries on a request basis.
|
|
func (c *Cache) Set(svcKey, key string, val interface{}) error {
|
|
c.m.Lock()
|
|
defer c.m.Unlock()
|
|
|
|
if !c.fits() {
|
|
return fmt.Errorf("cache is full")
|
|
}
|
|
|
|
if _, ok := c.entries[svcKey]; !ok {
|
|
c.entries[svcKey] = map[string]Entry{}
|
|
}
|
|
|
|
if _, ok := c.entries[svcKey][key]; ok {
|
|
return fmt.Errorf("key `%v` already exists", key)
|
|
}
|
|
|
|
c.entries[svcKey][key] = Entry{
|
|
V: val,
|
|
Valid: true,
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Invalidate invalidates a cache Entry by key.
|
|
func (c *Cache) Invalidate(svcKey, key string) error {
|
|
r, err := c.Get(svcKey, key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
r.Valid = false
|
|
c.entries[svcKey][key] = *r
|
|
return nil
|
|
}
|
|
|
|
// Evict frees memory from the cache by removing invalid keys. It is a noop.
|
|
func (c *Cache) Evict() {
|
|
for _, v := range c.entries {
|
|
for k, svcEntry := range v {
|
|
if !svcEntry.Valid {
|
|
delete(v, k)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Length returns the amount of entries per service key.
|
|
func (c *Cache) Length(k string) int {
|
|
return len(c.entries[k])
|
|
}
|
|
|
|
func (c *Cache) fits() bool {
|
|
return c.size >= len(c.entries)
|
|
}
|