-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvault.go
136 lines (120 loc) · 2.72 KB
/
vault.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
126
127
128
129
130
131
132
133
134
135
136
package globalsign
import (
"sync"
"time"
)
// VaultItem represents a record identity
type VaultItem struct {
sync.RWMutex
data *DSSIdentity
expires *time.Time
}
// immediate expiration
func (item *VaultItem) expire() {
item.Lock()
expiration := time.Now()
item.expires = &expiration
item.Unlock()
}
func (item *VaultItem) touch(duration time.Duration) {
item.Lock()
expiration := time.Now().Add(duration)
item.expires = &expiration
item.Unlock()
}
func (item *VaultItem) expired() bool {
var value bool
item.RLock()
if item.expires == nil {
value = true
} else {
value = item.expires.Before(time.Now())
}
item.RUnlock()
return value
}
// ExpiredIdentityFunc is a callback which will be called once identity expired
type ExpiredIdentityFunc func(key string, identity *DSSIdentity)
// IdentityVault store DSS identity until its expired
type IdentityVault struct {
mutex sync.RWMutex
ttl time.Duration
items map[string]*VaultItem
expfunc ExpiredIdentityFunc
}
// Set is a thread-safe way to add identity to cache
func (cache *IdentityVault) Set(key string, identity *DSSIdentity) {
cache.mutex.Lock()
item := &VaultItem{data: identity}
item.touch(cache.ttl)
cache.items[key] = item
cache.mutex.Unlock()
}
// Get is a thread-safe way to lookup items
func (cache *IdentityVault) Get(key string) (data *DSSIdentity, found bool) {
cache.mutex.Lock()
item, exists := cache.items[key]
if !exists || item.expired() {
data = nil
found = false
} else {
data = item.data
found = true
}
cache.mutex.Unlock()
return
}
// Count returns the number of items in the cache
// (helpful for tracking memory leaks)
func (cache *IdentityVault) Count() int {
cache.mutex.RLock()
count := len(cache.items)
cache.mutex.RUnlock()
return count
}
// Del remove item without trigger callback
func (cache *IdentityVault) Del(key string) {
cache.mutex.Lock()
_, exists := cache.items[key]
if exists {
delete(cache.items, key)
}
cache.mutex.Unlock()
return
}
func (cache *IdentityVault) cleanup() {
cache.mutex.Lock()
for key, item := range cache.items {
if item.expired() {
delete(cache.items, key)
if cache.expfunc != nil {
cache.expfunc(key, item.data)
}
}
}
cache.mutex.Unlock()
}
func (cache *IdentityVault) startCleanupTimer() {
duration := cache.ttl / 2
if duration < time.Second {
duration = time.Second
}
ticker := time.Tick(duration)
go (func() {
for {
select {
case <-ticker:
cache.cleanup()
}
}
})()
}
// NewIdentityVault is a helper to create instance of the indetities vault struct
func NewIdentityVault(duration time.Duration) *IdentityVault {
cache := &IdentityVault{
ttl: duration,
items: map[string]*VaultItem{},
}
cache.startCleanupTimer()
return cache
}