2 Star 0 Fork 0

nrgo/cache

Create your Gitee Account
Explore and code with more than 13.5 million developers,Free private repositories !:)
Sign up
文件
Clone or Download
builtin.go 3.61 KB
Copy Edit Raw Blame History
tm authored 2021-02-21 11:49 +08:00 . migrate
package cache
import (
"container/list"
"sync"
"time"
"gitee.com/nrgo/conv"
"gitee.com/nrgo/options"
)
// NewBuiltinCache 初始化一个内建内存型缓存
func NewBuiltinCache(opts ...*options.Options) Cache {
c := &builtinCache{
opts: options.NewOptions(),
l: list.New(),
mc: make(map[string]*list.Element),
}
if len(opts) > 0 {
c.opts.Append(opts...)
}
if c.opts.Value(OPTIONS_DEFAULT_EXPIRES_NAME) == nil {
c.defaultExpires = DEFAULT_EXPIRES
} else {
c.defaultExpires = c.opts.Value(OPTIONS_DEFAULT_EXPIRES_NAME).(time.Duration)
}
c.defaultCapacity = conv.DefaultInt(c.opts.Value(OPTIONS_DEFAULT_CAPACITY_NAME), DEFAULT_CAPACITY)
return c
}
type node struct {
key string
value interface{}
deadline int64
}
// BuiltinCache 内建的内存型缓存,通过LRU及过期算法淘汰缓存
type builtinCache struct {
sync.RWMutex
opts *options.Options
l *list.List
mc map[string]*list.Element
defaultExpires time.Duration
defaultCapacity int
}
// Open 打开Cache服务
func (c *builtinCache) Open() error {
// do nothing
return nil
}
// Close 关闭Cache服务
func (c *builtinCache) Close() error {
c.Lock()
defer c.Unlock()
// 清空 map
for k := range c.mc {
delete(c.mc, k)
}
// 清空 list
last := c.l.Back()
for last != nil {
c.l.Remove(last)
last = c.l.Back()
}
return nil
}
// Set 设置指定kv到缓存中,如存在key则覆盖
func (c *builtinCache) Set(key string, value interface{}, expires ...time.Duration) {
exp := c.defaultExpires
if len(expires) > 0 {
exp = expires[0]
}
c.RLock()
// 查找是否已存在,存在则更新deadline,并返回
if ele, found := c.mc[key]; found {
c.l.MoveToFront(ele)
ele.Value.(*node).value = value
ele.Value.(*node).deadline = time.Now().Add(exp).Unix()
c.RUnlock()
return
}
c.RUnlock()
c.Lock()
// 如果不存在则写入新节点
ele := c.l.PushFront(&node{
key: key,
value: value,
deadline: time.Now().Add(exp).Unix(),
})
c.mc[key] = ele
c.Unlock()
c.removeOverCapacity()
}
// Get 获取指定key的value值
func (c *builtinCache) Get(key string) (interface{}, error) {
n, err := c.getNode(key)
if err != nil {
return nil, err
}
return n.value, nil
}
// Exists 查询缓存中是否存在指定key
func (c *builtinCache) Exists(key string) bool {
c.RLock()
_, found := c.mc[key]
c.RUnlock()
return found
}
// Expires 设置某个key的超时设置
func (c *builtinCache) Expires(key string, expires time.Duration) {
c.RLock()
if ele, found := c.mc[key]; found {
c.l.MoveToFront(ele)
ele.Value.(*node).deadline = time.Now().Add(expires).Unix()
}
c.RUnlock()
}
// Delete 从缓存中移除某个key
func (c *builtinCache) Delete(key string) {
c.Lock()
if ele, found := c.mc[key]; found {
n := ele.Value.(*node)
delete(c.mc, n.key)
c.l.Remove(ele)
}
c.Unlock()
}
// Keys 返回缓存中的所有key
func (c *builtinCache) Keys() []string {
c.RLock()
ks := make([]string, 0)
for k := range c.mc {
ks = append(ks, k)
}
c.RUnlock()
return ks
}
// Size 返回缓存大小
func (c *builtinCache) Size() int {
return c.l.Len()
}
func (c *builtinCache) getNode(key string) (*node, error) {
if !c.Exists(key) {
return nil, ErrKeyNotExists
}
c.RLock()
ele := c.mc[key]
n := ele.Value.(*node)
// 如果已过期,直接删除
if n.deadline < time.Now().Unix() {
c.RUnlock()
c.Delete(key)
return nil, ErrKeyExpired
}
c.l.MoveToFront(ele)
c.RUnlock()
return n, nil
}
func (c *builtinCache) removeOverCapacity() {
if c.Size() > c.defaultCapacity {
last := c.l.Back()
if last != nil {
c.Delete(last.Value.(*node).key)
}
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/nrgo/cache.git
git@gitee.com:nrgo/cache.git
nrgo
cache
cache
v0.1.0

Search