replace zxq.co/ripple/hanayo
This commit is contained in:
117
vendor/github.com/thehowl/cieca/cieca.go
generated
vendored
Normal file
117
vendor/github.com/thehowl/cieca/cieca.go
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
// Package cieca is an in-memory Key-Value datastore for Go. The main purpose
|
||||
// is to easily cache data in the RAM for a certain amount of time.
|
||||
package cieca
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type element struct {
|
||||
data []byte
|
||||
expire time.Time
|
||||
cancel chan struct{}
|
||||
}
|
||||
|
||||
// DataStore is the datastore containing all the data.
|
||||
type DataStore struct {
|
||||
data map[string]element
|
||||
mutex *sync.RWMutex
|
||||
}
|
||||
|
||||
// Get retrieves a value in the datastore. If it is not found, nil is returned.
|
||||
func (d *DataStore) Get(key string) []byte {
|
||||
v, _ := d.GetWithExist(key)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetWithExist retrieves the value of a key, and a boolean indicating whether
|
||||
// the value existed in the store.
|
||||
func (d *DataStore) GetWithExist(key string) ([]byte, bool) {
|
||||
d.setup()
|
||||
d.mutex.RLock()
|
||||
defer d.mutex.RUnlock()
|
||||
el, ex := d.data[key]
|
||||
return el.data, ex
|
||||
}
|
||||
|
||||
// Expiration gets the time of expiration of a key.
|
||||
func (d *DataStore) Expiration(key string) *time.Time {
|
||||
d.setup()
|
||||
d.mutex.RLock()
|
||||
defer d.mutex.RUnlock()
|
||||
el, exist := d.data[key]
|
||||
if !exist || el.cancel == nil {
|
||||
return nil
|
||||
}
|
||||
t := el.expire
|
||||
return &t
|
||||
}
|
||||
|
||||
// Delete removes an element from the datastore.
|
||||
func (d *DataStore) Delete(key string) {
|
||||
d.setup()
|
||||
d.mutex.Lock()
|
||||
defer d.mutex.Unlock()
|
||||
exp := d.data[key].cancel
|
||||
if exp != nil && time.Now().Sub(d.data[key].expire) <= 0 {
|
||||
exp <- struct{}{}
|
||||
close(exp)
|
||||
}
|
||||
delete(d.data, key)
|
||||
}
|
||||
|
||||
// Set sets a key in the datastore with no expiration.
|
||||
func (d *DataStore) Set(key string, value []byte) {
|
||||
d.SetWithExpiration(key, value, -1)
|
||||
}
|
||||
|
||||
// SetWithExpiration sets a key in the datastore with a certain value.
|
||||
func (d *DataStore) SetWithExpiration(key string, value []byte, expiration time.Duration) {
|
||||
d.setup()
|
||||
var c chan struct{}
|
||||
if expiration >= 0 {
|
||||
c = make(chan struct{})
|
||||
}
|
||||
el := element{
|
||||
data: value,
|
||||
expire: time.Now().Add(expiration),
|
||||
cancel: c,
|
||||
}
|
||||
d.Delete(key)
|
||||
d.mutex.Lock()
|
||||
defer d.mutex.Unlock()
|
||||
d.data[key] = el
|
||||
if c != nil {
|
||||
go d.queueDeletion(expiration, c, key)
|
||||
}
|
||||
}
|
||||
|
||||
// Clean clears the datastore. Not so thread-safe. Use with care.
|
||||
func (d *DataStore) Clean() {
|
||||
if d == nil {
|
||||
return
|
||||
}
|
||||
for el := range d.data {
|
||||
d.Delete(el)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DataStore) queueDeletion(dur time.Duration, canc <-chan struct{}, key string) {
|
||||
select {
|
||||
case <-time.NewTimer(dur).C:
|
||||
d.Delete(key)
|
||||
case <-canc:
|
||||
// useless, but explicits what we're doing
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DataStore) setup() {
|
||||
if d.data == nil {
|
||||
d.data = make(map[string]element)
|
||||
}
|
||||
if d.mutex == nil {
|
||||
d.mutex = &sync.RWMutex{}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user