@@ -3,6 +3,7 @@ package leveldb
3
3
import (
4
4
"os"
5
5
"path/filepath"
6
+ "sync"
6
7
7
8
ds "github.com/ipfs/go-datastore"
8
9
dsq "github.com/ipfs/go-datastore/query"
@@ -16,8 +17,9 @@ import (
16
17
17
18
type Datastore struct {
18
19
* accessor
19
- DB * leveldb.DB
20
- path string
20
+ DB * leveldb.DB
21
+ path string
22
+ closeLk sync.RWMutex
21
23
}
22
24
23
25
var _ ds.Datastore = (* Datastore )(nil )
@@ -52,11 +54,13 @@ func NewDatastore(path string, opts *Options) (*Datastore, error) {
52
54
return nil , err
53
55
}
54
56
55
- return & Datastore {
57
+ ds := Datastore {
56
58
accessor : & accessor {ldb : db , syncWrites : true },
57
59
DB : db ,
58
60
path : path ,
59
- }, nil
61
+ }
62
+ ds .accessor .closeLk = & ds .closeLk
63
+ return & ds , nil
60
64
}
61
65
62
66
// An extraction of the common interface between LevelDB Transactions and the DB itself.
@@ -74,9 +78,12 @@ type levelDbOps interface {
74
78
type accessor struct {
75
79
ldb levelDbOps
76
80
syncWrites bool
81
+ closeLk * sync.RWMutex
77
82
}
78
83
79
84
func (a * accessor ) Put (key ds.Key , value []byte ) (err error ) {
85
+ a .closeLk .RLock ()
86
+ defer a .closeLk .RUnlock ()
80
87
return a .ldb .Put (key .Bytes (), value , & opt.WriteOptions {Sync : a .syncWrites })
81
88
}
82
89
@@ -85,6 +92,8 @@ func (a *accessor) Sync(prefix ds.Key) error {
85
92
}
86
93
87
94
func (a * accessor ) Get (key ds.Key ) (value []byte , err error ) {
95
+ a .closeLk .RLock ()
96
+ defer a .closeLk .RUnlock ()
88
97
val , err := a .ldb .Get (key .Bytes (), nil )
89
98
if err != nil {
90
99
if err == leveldb .ErrNotFound {
@@ -96,18 +105,26 @@ func (a *accessor) Get(key ds.Key) (value []byte, err error) {
96
105
}
97
106
98
107
func (a * accessor ) Has (key ds.Key ) (exists bool , err error ) {
108
+ a .closeLk .RLock ()
109
+ defer a .closeLk .RUnlock ()
99
110
return a .ldb .Has (key .Bytes (), nil )
100
111
}
101
112
102
- func (d * accessor ) GetSize (key ds.Key ) (size int , err error ) {
103
- return ds .GetBackedSize (d , key )
113
+ func (a * accessor ) GetSize (key ds.Key ) (size int , err error ) {
114
+ a .closeLk .RLock ()
115
+ defer a .closeLk .RUnlock ()
116
+ return ds .GetBackedSize (a , key )
104
117
}
105
118
106
119
func (a * accessor ) Delete (key ds.Key ) (err error ) {
120
+ a .closeLk .RLock ()
121
+ defer a .closeLk .RUnlock ()
107
122
return a .ldb .Delete (key .Bytes (), & opt.WriteOptions {Sync : a .syncWrites })
108
123
}
109
124
110
125
func (a * accessor ) Query (q dsq.Query ) (dsq.Results , error ) {
126
+ a .closeLk .RLock ()
127
+ defer a .closeLk .RUnlock ()
111
128
var rnge * util.Range
112
129
113
130
// make a copy of the query for the fallback naive query implementation.
@@ -159,6 +176,8 @@ func (a *accessor) Query(q dsq.Query) (dsq.Results, error) {
159
176
// DiskUsage returns the current disk size used by this levelDB.
160
177
// For in-mem datastores, it will return 0.
161
178
func (d * Datastore ) DiskUsage () (uint64 , error ) {
179
+ d .closeLk .RLock ()
180
+ defer d .closeLk .RUnlock ()
162
181
if d .path == "" { // in-mem
163
182
return 0 , nil
164
183
}
@@ -182,19 +201,23 @@ func (d *Datastore) DiskUsage() (uint64, error) {
182
201
183
202
// LevelDB needs to be closed.
184
203
func (d * Datastore ) Close () (err error ) {
204
+ d .closeLk .Lock ()
205
+ defer d .closeLk .Unlock ()
185
206
return d .DB .Close ()
186
207
}
187
208
188
209
type leveldbBatch struct {
189
210
b * leveldb.Batch
190
211
db * leveldb.DB
212
+ closeLk * sync.RWMutex
191
213
syncWrites bool
192
214
}
193
215
194
216
func (d * Datastore ) Batch () (ds.Batch , error ) {
195
217
return & leveldbBatch {
196
218
b : new (leveldb.Batch ),
197
219
db : d .DB ,
220
+ closeLk : & d .closeLk ,
198
221
syncWrites : d .syncWrites ,
199
222
}, nil
200
223
}
@@ -205,6 +228,8 @@ func (b *leveldbBatch) Put(key ds.Key, value []byte) error {
205
228
}
206
229
207
230
func (b * leveldbBatch ) Commit () error {
231
+ b .closeLk .RLock ()
232
+ defer b .closeLk .RUnlock ()
208
233
return b .db .Write (b .b , & opt.WriteOptions {Sync : b .syncWrites })
209
234
}
210
235
@@ -220,18 +245,24 @@ type transaction struct {
220
245
}
221
246
222
247
func (t * transaction ) Commit () error {
248
+ t .closeLk .RLock ()
249
+ defer t .closeLk .RUnlock ()
223
250
return t .tx .Commit ()
224
251
}
225
252
226
253
func (t * transaction ) Discard () {
254
+ t .closeLk .RLock ()
255
+ defer t .closeLk .RUnlock ()
227
256
t .tx .Discard ()
228
257
}
229
258
230
259
func (d * Datastore ) NewTransaction (readOnly bool ) (ds.Txn , error ) {
260
+ d .closeLk .RLock ()
261
+ defer d .closeLk .RUnlock ()
231
262
tx , err := d .DB .OpenTransaction ()
232
263
if err != nil {
233
264
return nil , err
234
265
}
235
- accessor := & accessor {ldb : tx , syncWrites : false }
266
+ accessor := & accessor {ldb : tx , syncWrites : false , closeLk : & d . closeLk }
236
267
return & transaction {accessor , tx }, nil
237
268
}
0 commit comments