-
Notifications
You must be signed in to change notification settings - Fork 394
/
common.go
174 lines (137 loc) · 5.1 KB
/
common.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
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package storage
import (
"bytes"
"context"
"errors"
"github.com/zeebo/errs"
monkit "gopkg.in/spacemonkeygo/monkit.v2"
)
var mon = monkit.Package()
// Delimiter separates nested paths in storage
const Delimiter = '/'
//ErrKeyNotFound used when something doesn't exist
var ErrKeyNotFound = errs.Class("key not found")
// ErrEmptyKey is returned when an empty key is used in Put or in CompareAndSwap
var ErrEmptyKey = errs.Class("empty key")
// ErrValueChanged is returned when the current value of the key does not match the oldValue in CompareAndSwap
var ErrValueChanged = errs.Class("value changed")
// ErrEmptyQueue is returned when attempting to Dequeue from an empty queue
var ErrEmptyQueue = errs.Class("empty queue")
// ErrLimitExceeded is returned when request limit is exceeded
var ErrLimitExceeded = errors.New("limit exceeded")
// Key is the type for the keys in a `KeyValueStore`
type Key []byte
// Value is the type for the values in a `ValueValueStore`
type Value []byte
// Keys is the type for a slice of keys in a `KeyValueStore`
type Keys []Key
// Values is the type for a slice of Values in a `KeyValueStore`
type Values []Value
// Items keeps all ListItem
type Items []ListItem
// DefaultLookupLimit is the default lookup limit for storage implementations
const DefaultLookupLimit = 10000
// ListItem returns Key, Value, IsPrefix
type ListItem struct {
Key Key
Value Value
IsPrefix bool
}
// KeyValueStore describes key/value stores like redis and boltdb
type KeyValueStore interface {
// Put adds a value to store
Put(context.Context, Key, Value) error
// Get gets a value to store
Get(context.Context, Key) (Value, error)
// GetAll gets all values from the store
GetAll(context.Context, Keys) (Values, error)
// Delete deletes key and the value
Delete(context.Context, Key) error
// List lists all keys starting from start and upto limit items
List(ctx context.Context, start Key, limit int) (Keys, error)
// Iterate iterates over items based on opts
Iterate(ctx context.Context, opts IterateOptions, fn func(context.Context, Iterator) error) error
// CompareAndSwap atomically compares and swaps oldValue with newValue
CompareAndSwap(ctx context.Context, key Key, oldValue, newValue Value) error
// Close closes the store
Close() error
// LookupLimit returns the maximum limit that is allowed.
LookupLimit() int
}
// IterateOptions contains options for iterator
type IterateOptions struct {
// Prefix ensure
Prefix Key
// First will be the first item iterator returns or the next item (previous when reverse)
First Key
// Recurse, do not collapse items based on Delimiter
Recurse bool
// The maximum number of elements to be returned
Limit int
}
// Iterator iterates over a sequence of ListItems
type Iterator interface {
// Next prepares the next list item.
// It returns true on success, or false if there is no next result row or an error happened while preparing it.
Next(ctx context.Context, item *ListItem) bool
}
// IsZero returns true if the value struct is it's zero value
func (value Value) IsZero() bool {
return len(value) == 0
}
// IsZero returns true if the key struct is it's zero value
func (key Key) IsZero() bool {
return len(key) == 0
}
// MarshalBinary implements the encoding.BinaryMarshaler interface for the Value type
func (value Value) MarshalBinary() ([]byte, error) {
return value, nil
}
// MarshalBinary implements the encoding.BinaryMarshaler interface for the Key type
func (key Key) MarshalBinary() ([]byte, error) {
return key, nil
}
// ByteSlices converts a `Keys` struct to a slice of byte-slices (i.e. `[][]byte`)
func (keys Keys) ByteSlices() [][]byte {
result := make([][]byte, len(keys))
for key, val := range keys {
result[key] = []byte(val)
}
return result
}
// String implements the Stringer interface
func (key Key) String() string { return string(key) }
// Strings returns everything as strings
func (keys Keys) Strings() []string {
strs := make([]string, 0, len(keys))
for _, key := range keys {
strs = append(strs, string(key))
}
return strs
}
// GetKeys gets all the Keys in []ListItem and converts them to Keys
func (items Items) GetKeys() Keys {
if len(items) == 0 {
return nil
}
var keys Keys
for _, item := range items {
keys = append(keys, item.Key)
}
return keys
}
// Len is the number of elements in the collection.
func (items Items) Len() int { return len(items) }
// Less reports whether the element with
// index i should sort before the element with index j.
func (items Items) Less(i, k int) bool { return items[i].Less(items[k]) }
// Swap swaps the elements with indexes i and j.
func (items Items) Swap(i, k int) { items[i], items[k] = items[k], items[i] }
// Less returns whether item should be sorted before b
func (item ListItem) Less(b ListItem) bool { return item.Key.Less(b.Key) }
// Less returns whether key should be sorted before b
func (key Key) Less(b Key) bool { return bytes.Compare([]byte(key), []byte(b)) < 0 }
// Equal returns whether key and b are equal
func (key Key) Equal(b Key) bool { return bytes.Equal([]byte(key), []byte(b)) }