-
Notifications
You must be signed in to change notification settings - Fork 46
/
Copy pathhelpers.go
187 lines (154 loc) · 4.03 KB
/
helpers.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package store
import "github.com/iov-one/weave/errors"
////////////////////////////////////////////////
// Slice -> Iterator
// SliceIterator wraps an Iterator over a slice of models
//
// TODO: make this private and only expose Iterator interface????
type SliceIterator struct {
data []Model
idx int
}
var _ Iterator = (*SliceIterator)(nil)
// NewSliceIterator creates a new Iterator over this slice
func NewSliceIterator(data []Model) *SliceIterator {
return &SliceIterator{
data: data,
}
}
func (s *SliceIterator) Next() (key, value []byte, err error) {
if s.idx >= len(s.data) {
return nil, nil, errors.Wrap(errors.ErrIteratorDone, "slice iterator")
}
val := s.data[s.idx]
s.idx++
return val.Key, val.Value, nil
}
// Release releases the Iterator.
func (s *SliceIterator) Release() {
s.data = nil
}
/////////////////////////////////////////////////////
// Empty KVStore
// EmptyKVStore never holds any data, used as a base layer to test caching
type EmptyKVStore struct{}
var _ KVStore = EmptyKVStore{}
// Get always returns nil
func (e EmptyKVStore) Get(key []byte) ([]byte, error) { return nil, nil }
// Has always returns false
func (e EmptyKVStore) Has(key []byte) (bool, error) { return false, nil }
// Set is a noop
func (e EmptyKVStore) Set(key, value []byte) error { return nil }
// Delete is a noop
func (e EmptyKVStore) Delete(key []byte) error { return nil }
// Iterator is always empty
func (e EmptyKVStore) Iterator(start, end []byte) (Iterator, error) {
return NewSliceIterator(nil), nil
}
// ReverseIterator is always empty
func (e EmptyKVStore) ReverseIterator(start, end []byte) (Iterator, error) {
return NewSliceIterator(nil), nil
}
// NewBatch returns a batch that can write to this tree later
func (e EmptyKVStore) NewBatch() Batch {
return NewNonAtomicBatch(e)
}
////////////////////////////////////////////////////
// Non-atomic batch (dummy implementation)
type opKind int32
const (
setKind opKind = iota + 1
delKind
)
// Op is either set or delete
type Op struct {
kind opKind
key []byte
value []byte // only for set
}
// Apply performs the stored operation on a writable store
func (o Op) Apply(out SetDeleter) error {
switch o.kind {
case setKind:
return out.Set(o.key, o.value)
case delKind:
return out.Delete(o.key)
default:
return errors.Wrapf(errors.ErrDatabase, "Unknown kind: %d", o.kind)
}
}
// IsSetOp returns true if it is setting (false implies delete)
func (o Op) IsSetOp() bool {
return o.kind == setKind
}
// Key returns a copy of the Key
func (o Op) Key() []byte {
return append([]byte(nil), o.key...)
}
// SetOp is a helper to create a set operation
func SetOp(key, value []byte) Op {
return Op{
kind: setKind,
key: key,
value: value,
}
}
// DelOp is a helper to create a del operation
func DelOp(key []byte) Op {
return Op{
kind: delKind,
key: key,
}
}
// NonAtomicBatch just piles up ops and executes them later
// on the underlying store. Can be used when there is no better
// option (for in-memory stores).
type NonAtomicBatch struct {
out SetDeleter
ops []Op
}
var _ Batch = (*NonAtomicBatch)(nil)
// NewNonAtomicBatch creates an empty batch to be later written
// to the KVStore
func NewNonAtomicBatch(out SetDeleter) *NonAtomicBatch {
return &NonAtomicBatch{
out: out,
}
}
// Set adds a set operation to the batch
func (b *NonAtomicBatch) Set(key, value []byte) error {
set := Op{
kind: setKind,
key: key,
value: value,
}
b.ops = append(b.ops, set)
return nil
}
// Delete adds a delete operation to the batch
func (b *NonAtomicBatch) Delete(key []byte) error {
del := Op{
kind: delKind,
key: key,
}
b.ops = append(b.ops, del)
return nil
}
// Write writes all the ops to the underlying store and resets
func (b *NonAtomicBatch) Write() error {
for _, Op := range b.ops {
err := Op.Apply(b.out)
if err != nil {
return err
}
}
b.ops = nil
return nil
}
// ShowOps is instrumentation for testing,
// it returns a copy of the internal Ops list
func (b *NonAtomicBatch) ShowOps() []Op {
ops := make([]Op, len(b.ops))
copy(ops, b.ops)
return ops
}