This repository has been archived by the owner on Jul 29, 2020. It is now read-only.
/
memory_database.go
executable file
·168 lines (140 loc) · 3.5 KB
/
memory_database.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
package database
import (
"bytes"
"sort"
"sync"
"github.com/libonomy/libonomy-p2p/common/util"
)
// MemDatabase is a test memory database. Do not use for any production it does not get persisted
type MemDatabase struct {
db map[string][]byte
lock sync.RWMutex
}
// NewMemDatabase returns a memory database instance
func NewMemDatabase() *MemDatabase {
return &MemDatabase{
db: make(map[string][]byte),
}
}
// Put inserts value value by provided key
func (db *MemDatabase) Put(key []byte, value []byte) error {
db.lock.Lock()
defer db.lock.Unlock()
db.db[string(key)] = util.CopyBytes(value)
return nil
}
// Has returns a boolean if key is in db or not
func (db *MemDatabase) Has(key []byte) (bool, error) {
db.lock.RLock()
defer db.lock.RUnlock()
_, ok := db.db[string(key)]
return ok, nil
}
// Get gets the value for the given key, returns an error if key wasn't found
func (db *MemDatabase) Get(key []byte) ([]byte, error) {
db.lock.RLock()
defer db.lock.RUnlock()
if entry, ok := db.db[string(key)]; ok {
return util.CopyBytes(entry), nil
}
return nil, ErrNotFound
}
// Keys returns all keys found in database
func (db *MemDatabase) Keys() [][]byte {
db.lock.RLock()
defer db.lock.RUnlock()
keys := [][]byte{}
for key := range db.db {
keys = append(keys, []byte(key))
}
return keys
}
// Delete removes the key from db
func (db *MemDatabase) Delete(key []byte) error {
db.lock.Lock()
defer db.lock.Unlock()
delete(db.db, string(key))
return nil
}
// Close closes the database
func (db *MemDatabase) Close() {}
// NewBatch returns batch object to aggregate writes to db
func (db *MemDatabase) NewBatch() Batch {
return &memBatch{db: db}
}
// Len returns number of items in database
func (db *MemDatabase) Len() int { return len(db.db) }
// NewMemDatabaseIterator iterator for memory database iterating all items in database
func (db *MemDatabase) NewMemDatabaseIterator() *MemDatabaseIterator {
keys := make([][]byte, 0, len(db.db))
for k := range db.db {
keys = append(keys, []byte(k))
}
sort.Slice(keys, func(i, j int) bool {
return string(keys[i]) < string(keys[j])
})
return &MemDatabaseIterator{
keys: keys,
db: db.db,
index: -1,
}
}
// Iterator returns iterator for memory database iterating all items in database
func (db *MemDatabase) Iterator() Iterator {
return db.NewMemDatabaseIterator()
}
// Find returns iterator iterating items with given key as prefix
func (db *MemDatabase) Find(key []byte) Iterator {
keys := make([][]byte, 0, len(db.db))
for k := range db.db {
if bytes.HasPrefix([]byte(k), key) {
keys = append(keys, []byte(k))
}
}
sort.Slice(keys, func(i, j int) bool {
return string(keys[i]) < string(keys[j])
})
return &MemDatabaseIterator{
keys: keys,
db: db.db,
index: -1,
}
}
type kv struct {
k, v []byte
del bool
}
type memBatch struct {
db *MemDatabase
writes []kv
size int
}
func (b *memBatch) Put(key, value []byte) error {
b.writes = append(b.writes, kv{util.CopyBytes(key), util.CopyBytes(value), false})
b.size += len(value)
return nil
}
func (b *memBatch) Delete(key []byte) error {
b.writes = append(b.writes, kv{util.CopyBytes(key), nil, true})
b.size++
return nil
}
func (b *memBatch) Write() error {
b.db.lock.Lock()
defer b.db.lock.Unlock()
for _, kv := range b.writes {
if kv.del {
delete(b.db.db, string(kv.k))
continue
}
b.db.db[string(kv.k)] = kv.v
}
return nil
}
func (b *memBatch) ValueSize() int {
return b.size
}
func (b *memBatch) Reset() {
b.writes = b.writes[:0]
b.size = 0
}