forked from hashicorp/vault
-
Notifications
You must be signed in to change notification settings - Fork 0
/
inmem.go
142 lines (115 loc) · 2.97 KB
/
inmem.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
137
138
139
140
141
142
package physical
import (
"strings"
"sync"
log "github.com/mgutz/logxi/v1"
"github.com/armon/go-radix"
)
// InmemBackend is an in-memory only physical backend. It is useful
// for testing and development situations where the data is not
// expected to be durable.
type InmemBackend struct {
sync.RWMutex
root *radix.Tree
permitPool *PermitPool
logger log.Logger
}
type TransactionalInmemBackend struct {
InmemBackend
}
// NewInmem constructs a new in-memory backend
func NewInmem(logger log.Logger) *InmemBackend {
in := &InmemBackend{
root: radix.New(),
permitPool: NewPermitPool(DefaultParallelOperations),
logger: logger,
}
return in
}
// Basically for now just creates a permit pool of size 1 so only one operation
// can run at a time
func NewTransactionalInmem(logger log.Logger) *TransactionalInmemBackend {
in := &TransactionalInmemBackend{
InmemBackend: InmemBackend{
root: radix.New(),
permitPool: NewPermitPool(1),
logger: logger,
},
}
return in
}
// Put is used to insert or update an entry
func (i *InmemBackend) Put(entry *Entry) error {
i.permitPool.Acquire()
defer i.permitPool.Release()
i.Lock()
defer i.Unlock()
return i.PutInternal(entry)
}
func (i *InmemBackend) PutInternal(entry *Entry) error {
i.root.Insert(entry.Key, entry)
return nil
}
// Get is used to fetch an entry
func (i *InmemBackend) Get(key string) (*Entry, error) {
i.permitPool.Acquire()
defer i.permitPool.Release()
i.RLock()
defer i.RUnlock()
return i.GetInternal(key)
}
func (i *InmemBackend) GetInternal(key string) (*Entry, error) {
if raw, ok := i.root.Get(key); ok {
return raw.(*Entry), nil
}
return nil, nil
}
// Delete is used to permanently delete an entry
func (i *InmemBackend) Delete(key string) error {
i.permitPool.Acquire()
defer i.permitPool.Release()
i.Lock()
defer i.Unlock()
return i.DeleteInternal(key)
}
func (i *InmemBackend) DeleteInternal(key string) error {
i.root.Delete(key)
return nil
}
// List is used ot list all the keys under a given
// prefix, up to the next prefix.
func (i *InmemBackend) List(prefix string) ([]string, error) {
i.permitPool.Acquire()
defer i.permitPool.Release()
i.RLock()
defer i.RUnlock()
return i.ListInternal(prefix)
}
func (i *InmemBackend) ListInternal(prefix string) ([]string, error) {
var out []string
seen := make(map[string]interface{})
walkFn := func(s string, v interface{}) bool {
trimmed := strings.TrimPrefix(s, prefix)
sep := strings.Index(trimmed, "/")
if sep == -1 {
out = append(out, trimmed)
} else {
trimmed = trimmed[:sep+1]
if _, ok := seen[trimmed]; !ok {
out = append(out, trimmed)
seen[trimmed] = struct{}{}
}
}
return false
}
i.root.WalkPrefix(prefix, walkFn)
return out, nil
}
// Implements the transaction interface
func (t *TransactionalInmemBackend) Transaction(txns []TxnEntry) error {
t.permitPool.Acquire()
defer t.permitPool.Release()
t.Lock()
defer t.Unlock()
return genericTransactionHandler(t, txns)
}