@@ -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"
@@ -52,11 +53,12 @@ func NewDatastore(path string, opts *Options) (*Datastore, error) {
52
53
return nil , err
53
54
}
54
55
55
- return & Datastore {
56
- accessor : & accessor {ldb : db , syncWrites : true },
56
+ ds := Datastore {
57
+ accessor : & accessor {ldb : db , syncWrites : true , closeLk : new (sync. RWMutex ) },
57
58
DB : db ,
58
59
path : path ,
59
- }, nil
60
+ }
61
+ return & ds , nil
60
62
}
61
63
62
64
// An extraction of the common interface between LevelDB Transactions and the DB itself.
@@ -74,9 +76,12 @@ type levelDbOps interface {
74
76
type accessor struct {
75
77
ldb levelDbOps
76
78
syncWrites bool
79
+ closeLk * sync.RWMutex
77
80
}
78
81
79
82
func (a * accessor ) Put (key ds.Key , value []byte ) (err error ) {
83
+ a .closeLk .RLock ()
84
+ defer a .closeLk .RUnlock ()
80
85
return a .ldb .Put (key .Bytes (), value , & opt.WriteOptions {Sync : a .syncWrites })
81
86
}
82
87
@@ -85,6 +90,8 @@ func (a *accessor) Sync(prefix ds.Key) error {
85
90
}
86
91
87
92
func (a * accessor ) Get (key ds.Key ) (value []byte , err error ) {
93
+ a .closeLk .RLock ()
94
+ defer a .closeLk .RUnlock ()
88
95
val , err := a .ldb .Get (key .Bytes (), nil )
89
96
if err != nil {
90
97
if err == leveldb .ErrNotFound {
@@ -96,18 +103,24 @@ func (a *accessor) Get(key ds.Key) (value []byte, err error) {
96
103
}
97
104
98
105
func (a * accessor ) Has (key ds.Key ) (exists bool , err error ) {
106
+ a .closeLk .RLock ()
107
+ defer a .closeLk .RUnlock ()
99
108
return a .ldb .Has (key .Bytes (), nil )
100
109
}
101
110
102
- func (d * accessor ) GetSize (key ds.Key ) (size int , err error ) {
103
- return ds .GetBackedSize (d , key )
111
+ func (a * accessor ) GetSize (key ds.Key ) (size int , err error ) {
112
+ return ds .GetBackedSize (a , key )
104
113
}
105
114
106
115
func (a * accessor ) Delete (key ds.Key ) (err error ) {
116
+ a .closeLk .RLock ()
117
+ defer a .closeLk .RUnlock ()
107
118
return a .ldb .Delete (key .Bytes (), & opt.WriteOptions {Sync : a .syncWrites })
108
119
}
109
120
110
121
func (a * accessor ) Query (q dsq.Query ) (dsq.Results , error ) {
122
+ a .closeLk .RLock ()
123
+ defer a .closeLk .RUnlock ()
111
124
var rnge * util.Range
112
125
113
126
// make a copy of the query for the fallback naive query implementation.
@@ -135,6 +148,8 @@ func (a *accessor) Query(q dsq.Query) (dsq.Results, error) {
135
148
}
136
149
r := dsq .ResultsFromIterator (q , dsq.Iterator {
137
150
Next : func () (dsq.Result , bool ) {
151
+ a .closeLk .RLock ()
152
+ defer a .closeLk .RUnlock ()
138
153
if ! next () {
139
154
return dsq.Result {}, false
140
155
}
@@ -149,6 +164,8 @@ func (a *accessor) Query(q dsq.Query) (dsq.Results, error) {
149
164
return dsq.Result {Entry : e }, true
150
165
},
151
166
Close : func () error {
167
+ a .closeLk .RLock ()
168
+ defer a .closeLk .RUnlock ()
152
169
i .Release ()
153
170
return nil
154
171
},
@@ -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