memory.go
2.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package cache
import (
"encoding/json"
"errors"
"fmt"
"strconv"
"sync"
"time"
)
var (
DefaultEvery int = 60 // 1 minute
)
type MemoryItem struct {
val interface{}
Lastaccess time.Time
expired int
}
func (itm *MemoryItem) Access() interface{} {
itm.Lastaccess = time.Now()
return itm.val
}
type MemoryCache struct {
lock sync.RWMutex
dur time.Duration
items map[string]*MemoryItem
Every int // Run an expiration check Every seconds
}
// NewDefaultCache returns a new FileCache with sane defaults.
func NewMemoryCache() *MemoryCache {
cache := MemoryCache{items: make(map[string]*MemoryItem)}
return &cache
}
func (bc *MemoryCache) Get(name string) interface{} {
bc.lock.RLock()
defer bc.lock.RUnlock()
itm, ok := bc.items[name]
if !ok {
return nil
}
return itm.Access()
}
func (bc *MemoryCache) Put(name string, value interface{}, expired int) error {
bc.lock.Lock()
defer bc.lock.Unlock()
t := MemoryItem{val: value, Lastaccess: time.Now(), expired: expired}
if _, ok := bc.items[name]; ok {
return errors.New("the key is exist")
} else {
bc.items[name] = &t
}
return nil
}
func (bc *MemoryCache) Delete(name string) error {
bc.lock.Lock()
defer bc.lock.Unlock()
if _, ok := bc.items[name]; !ok {
return errors.New("key not exist")
}
delete(bc.items, name)
_, valid := bc.items[name]
if valid {
return errors.New("delete key error")
}
return nil
}
func (bc *MemoryCache) IsExist(name string) bool {
bc.lock.RLock()
defer bc.lock.RUnlock()
_, ok := bc.items[name]
return ok
}
func (bc *MemoryCache) ClearAll() error {
bc.lock.Lock()
defer bc.lock.Unlock()
bc.items = make(map[string]*MemoryItem)
return nil
}
// Start activates the file cache; it will
func (bc *MemoryCache) StartAndGC(config string) error {
var cf map[string]int
json.Unmarshal([]byte(config), &cf)
if _, ok := cf["every"]; !ok {
cf["interval"] = DefaultEvery
}
dur, err := time.ParseDuration(fmt.Sprintf("%ds", cf["interval"]))
if err != nil {
return err
}
bc.Every = cf["interval"]
bc.dur = dur
go bc.vaccuum()
return nil
}
func (bc *MemoryCache) vaccuum() {
if bc.Every < 1 {
return
}
for {
<-time.After(time.Duration(bc.dur))
if bc.items == nil {
return
}
for name, _ := range bc.items {
bc.item_expired(name)
}
}
}
// item_expired returns true if an item is expired.
func (bc *MemoryCache) item_expired(name string) bool {
bc.lock.Lock()
defer bc.lock.Unlock()
itm, ok := bc.items[name]
if !ok {
return true
}
dur := time.Now().Sub(itm.Lastaccess)
sec, err := strconv.Atoi(fmt.Sprintf("%0.0f", dur.Seconds()))
if err != nil {
delete(bc.items, name)
return true
} else if sec >= itm.expired {
delete(bc.items, name)
return true
}
return false
}
func init() {
Register("memory", NewMemoryCache())
}