-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgdstore.go
162 lines (145 loc) · 4.24 KB
/
gdstore.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
package gdstore
import (
"bufio"
"os"
"strconv"
"sync"
)
type GDStore struct {
// FilePath is the path to the file used to persist
FilePath string
// useBuffer lets the user define if GDStore should use a buffer, or write directly to the file.
//
// Writing to a buffer is much faster, but failure to close to the store (GDStore.Close()) will
// result in a buffer that hasn't been flushed, meaning some entries may be lost.
// You can manually flush the buffer by using GDStore.Flush().
//
// In contrast, writing to the file without a buffer is slower, but more reliable if your
// application is prone to suddenly crashing
//
// Defaults to false
useBuffer bool
// persistence lets the user set whether to persist data to the file or not. Meant to be used for testing without
// having to clean up the file.
//
// (default) If set to true, data is available both in-memory and persisted to the file found at FilePath.
// If set to false, data is available only in-memory, and upon destruction, all data will be lost.
//
// Defaults to true
persistence bool
file *os.File
writer *bufio.Writer
data map[string][]byte
mux sync.RWMutex
}
// New creates a new GDStore
func New(filePath string) *GDStore {
store := &GDStore{
FilePath: filePath,
data: make(map[string][]byte),
persistence: true,
}
err := store.loadFromDisk()
if err != nil {
panic(err)
}
return store
}
// WithBuffer sets GDStore's useBuffer parameter to the value passed as parameter
//
// The default value for useBuffer is false
func (store *GDStore) WithBuffer(useBuffer bool) *GDStore {
store.useBuffer = useBuffer
return store
}
// WithPersistence sets GDStore's persistence parameter to the value passed as parameter
//
// The ability to set persistence to false is there mainly for testing purposes
//
// The default value for persistence is true
func (store *GDStore) WithPersistence(persistence bool) *GDStore {
store.persistence = persistence
return store
}
// Get returns the value of a key as well as a bool that indicates whether an entry exists for that key.
//
// The bool is particularly useful if you want to differentiate between a key that has a nil value, and a
// key that doesn't exist
func (store *GDStore) Get(key string) (value []byte, ok bool) {
store.mux.RLock()
value, ok = store.data[key]
store.mux.RUnlock()
return
}
// GetString does the same thing as Get, but converts the value to a string
func (store *GDStore) GetString(key string) (valueAsString string, ok bool) {
var value []byte
value, ok = store.Get(key)
if ok {
valueAsString = string(value)
}
return
}
// GetInt does the same thing as Get, but converts the value to an int
func (store *GDStore) GetInt(key string) (valueAsInt int, ok bool, err error) {
var value string
value, ok = store.GetString(key)
if ok {
valueAsInt, err = strconv.Atoi(value)
}
return
}
// Put creates an entry or updates the value of an existing key
func (store *GDStore) Put(key string, value []byte) error {
store.mux.Lock()
defer store.mux.Unlock()
store.data[key] = value
return store.appendEntryToFile(newEntry(ActionPut, key, value))
}
// PutAll creates or updates a map of entries
func (store *GDStore) PutAll(entries map[string][]byte) error {
store.mux.Lock()
defer store.mux.Unlock()
for key, value := range entries {
store.data[key] = value
}
return store.appendEntriesToFile(newBulkEntries(ActionPut, entries))
}
// Delete removes a key from the store
func (store *GDStore) Delete(key string) error {
store.mux.Lock()
defer store.mux.Unlock()
delete(store.data, key)
return store.appendEntryToFile(newEntry(ActionDelete, key, nil))
}
// Count returns the total number of entries in the store
func (store *GDStore) Count() int {
store.mux.RLock()
length := len(store.data)
store.mux.RUnlock()
return length
}
// Keys returns a list of all keys
func (store *GDStore) Keys() []string {
store.mux.Lock()
keys := make([]string, len(store.data))
i := 0
for k := range store.data {
keys[i] = k
i++
}
store.mux.Unlock()
return keys
}
// Values returns a list of all values
func (store *GDStore) Values() [][]byte {
store.mux.Lock()
values := make([][]byte, len(store.data))
i := 0
for _, v := range store.data {
values[i] = v
i++
}
store.mux.Unlock()
return values
}