forked from xellio/whois
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cache.go
125 lines (102 loc) · 2.12 KB
/
cache.go
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
package whois
import (
"encoding/gob"
"os"
"time"
)
//
// kvCacheItem
//
type kvCacheItem struct {
value QueryResult
lastUpdate time.Time
lastAccess time.Time
}
//
// KVCache a simple key Value structure with ttl.
//
type KVCache struct {
ttl int
data map[string]*kvCacheItem
}
//
// Add appends an additional key to the current KVCache.
// If the entry already exist the value and lastUpdate will be updated.
// Returns true if the key did not exist before otherwise false.
//
func (c *KVCache) Add(key string, value QueryResult) bool {
val, ok := c.data[key]
if ok {
val.value = value
val.lastUpdate = time.Now()
val.lastAccess = time.Now()
} else {
c.data[key] = &kvCacheItem{
value: value,
lastUpdate: time.Now(),
lastAccess: time.Now(),
}
return true
}
return false
}
//
// Get returns the value for the given key
// If the key's lastUpdate is older than the ttl allows default/empty is returned
//
func (c *KVCache) Get(key string) (result QueryResult, found bool) {
val, ok := c.data[key]
if !ok {
return
}
now := time.Now().Add(time.Duration(-1*c.ttl) * time.Second)
if now.After(val.lastUpdate) {
return
}
return val.value, true
}
//
// Clean removes all entries which are not accassed more than the given time.
//
func (c *KVCache) Clean(ttl time.Duration) {
now := time.Now().Add(-ttl)
for k, v := range c.data {
if v.lastAccess.Before(now) {
delete(c.data, k)
}
}
}
//
// NewCache creates a new KVCache instance.
//
func NewCache(ttl int) *KVCache {
return &KVCache{
ttl: ttl,
data: make(map[string]*kvCacheItem),
}
}
//
// LoadFromFile restores the cache from a previous saved file.
//
func LoadFromFile(filepath string) (*KVCache, error) {
file, err := os.Open(filepath)
ret := NewCache(0)
if err == nil {
decoder := gob.NewDecoder(file)
err = decoder.Decode(ret)
}
file.Close()
return ret, err
}
//
// SaveToFile saves the current cache into a file.
//
func SaveToFile(filepath string, cache *KVCache) error {
file, err := os.Create(filepath)
if err == nil {
encoder := gob.NewEncoder(file)
encoder.Encode(cache)
}
file.Close()
return err
}