rocksdb-native 3.0.2 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +62 -52
- package/lib/batch.js +52 -37
- package/lib/iterator.js +15 -21
- package/lib/snapshot.js +2 -5
- package/lib/state.js +38 -21
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const { ReadBatch, WriteBatch } = require('./lib/batch')
|
|
2
1
|
const ColumnFamily = require('./lib/column-family')
|
|
3
2
|
const Iterator = require('./lib/iterator')
|
|
4
3
|
const Snapshot = require('./lib/snapshot')
|
|
@@ -9,13 +8,19 @@ class RocksDB {
|
|
|
9
8
|
const {
|
|
10
9
|
columnFamily,
|
|
11
10
|
state = new DBState(this, path, opts),
|
|
12
|
-
snapshot = null
|
|
11
|
+
snapshot = null,
|
|
12
|
+
keyEncoding = null,
|
|
13
|
+
valueEncoding = null
|
|
13
14
|
} = opts
|
|
14
15
|
|
|
15
16
|
this._state = state
|
|
16
17
|
this._snapshot = snapshot
|
|
17
18
|
this._columnFamily = state.getColumnFamily(columnFamily)
|
|
18
|
-
this.
|
|
19
|
+
this._keyEncoding = keyEncoding
|
|
20
|
+
this._valueEncoding = valueEncoding
|
|
21
|
+
this._index = -1
|
|
22
|
+
|
|
23
|
+
this._state.addSession(this)
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
get opened() {
|
|
@@ -36,25 +41,23 @@ class RocksDB {
|
|
|
36
41
|
|
|
37
42
|
session({
|
|
38
43
|
columnFamily = this._columnFamily,
|
|
39
|
-
snapshot = this._snapshot !== null
|
|
44
|
+
snapshot = this._snapshot !== null,
|
|
45
|
+
keyEncoding = this._keyEncoding,
|
|
46
|
+
valueEncoding = this._valueEncoding
|
|
40
47
|
} = {}) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (snapshot) {
|
|
44
|
-
snap = this._snapshot
|
|
45
|
-
if (snap === null) snap = new Snapshot(this._state)
|
|
46
|
-
else snap.ref()
|
|
47
|
-
}
|
|
48
|
+
maybeClosed(this)
|
|
48
49
|
|
|
49
50
|
return new RocksDB(null, {
|
|
50
51
|
state: this._state,
|
|
51
52
|
columnFamily,
|
|
52
|
-
snapshot:
|
|
53
|
+
snapshot: snapshot ? this._snapshot || new Snapshot(this._state) : null,
|
|
54
|
+
keyEncoding,
|
|
55
|
+
valueEncoding
|
|
53
56
|
})
|
|
54
57
|
}
|
|
55
58
|
|
|
56
|
-
columnFamily(name) {
|
|
57
|
-
return this.session({ columnFamily: name })
|
|
59
|
+
columnFamily(name, opts) {
|
|
60
|
+
return this.session({ ...opts, columnFamily: name })
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
snapshot() {
|
|
@@ -70,11 +73,7 @@ class RocksDB {
|
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
async close({ force } = {}) {
|
|
73
|
-
if (this._index !== -1)
|
|
74
|
-
this._state.removeSession(this)
|
|
75
|
-
this._index = -1
|
|
76
|
-
if (this._snapshot) this._snapshot.unref()
|
|
77
|
-
}
|
|
76
|
+
if (this._index !== -1) this._state.removeSession(this)
|
|
78
77
|
|
|
79
78
|
if (force) {
|
|
80
79
|
for (let i = this._state.sessions.length - 1; i >= 0; i--) {
|
|
@@ -86,22 +85,28 @@ class RocksDB {
|
|
|
86
85
|
}
|
|
87
86
|
|
|
88
87
|
suspend() {
|
|
88
|
+
maybeClosed(this)
|
|
89
|
+
|
|
89
90
|
return this._state.suspend()
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
resume() {
|
|
94
|
+
maybeClosed(this)
|
|
95
|
+
|
|
93
96
|
return this._state.resume()
|
|
94
97
|
}
|
|
95
98
|
|
|
96
99
|
isIdle() {
|
|
97
|
-
return this._state.
|
|
100
|
+
return this._state.activity.isIdle()
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
idle() {
|
|
101
|
-
return this._state.
|
|
104
|
+
return this._state.activity.idle()
|
|
102
105
|
}
|
|
103
106
|
|
|
104
107
|
iterator(range, opts) {
|
|
108
|
+
maybeClosed(this)
|
|
109
|
+
|
|
105
110
|
return new Iterator(this, { ...range, ...opts })
|
|
106
111
|
}
|
|
107
112
|
|
|
@@ -114,54 +119,59 @@ class RocksDB {
|
|
|
114
119
|
}
|
|
115
120
|
|
|
116
121
|
read(opts) {
|
|
117
|
-
|
|
122
|
+
maybeClosed(this)
|
|
123
|
+
|
|
124
|
+
return this._state.createReadBatch(this, opts)
|
|
118
125
|
}
|
|
119
126
|
|
|
120
127
|
write(opts) {
|
|
121
|
-
|
|
128
|
+
maybeClosed(this)
|
|
129
|
+
|
|
130
|
+
return this._state.createWriteBatch(this, opts)
|
|
122
131
|
}
|
|
123
132
|
|
|
124
133
|
async get(key, opts) {
|
|
125
|
-
const batch = this.read({ ...opts, capacity: 1 })
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return await value
|
|
130
|
-
} finally {
|
|
131
|
-
batch.destroy()
|
|
132
|
-
}
|
|
134
|
+
const batch = this.read({ ...opts, capacity: 1, autoDestroy: true })
|
|
135
|
+
const value = batch.get(key)
|
|
136
|
+
batch.tryFlush()
|
|
137
|
+
return value
|
|
133
138
|
}
|
|
134
139
|
|
|
135
140
|
async put(key, value, opts) {
|
|
136
|
-
const batch = this.write({ ...opts, capacity: 1 })
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
await batch.flush()
|
|
140
|
-
} finally {
|
|
141
|
-
batch.destroy()
|
|
142
|
-
}
|
|
141
|
+
const batch = this.write({ ...opts, capacity: 1, autoDestroy: true })
|
|
142
|
+
batch.tryPut(key, value)
|
|
143
|
+
await batch.flush()
|
|
143
144
|
}
|
|
144
145
|
|
|
145
146
|
async delete(key, opts) {
|
|
146
|
-
const batch = this.write({ ...opts, capacity: 1 })
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
await batch.flush()
|
|
150
|
-
} finally {
|
|
151
|
-
batch.destroy()
|
|
152
|
-
}
|
|
147
|
+
const batch = this.write({ ...opts, capacity: 1, autoDestroy: true })
|
|
148
|
+
batch.tryDelete(key)
|
|
149
|
+
await batch.flush()
|
|
153
150
|
}
|
|
154
151
|
|
|
155
152
|
async deleteRange(start, end, opts) {
|
|
156
|
-
const batch = this.write({ ...opts, capacity: 1 })
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
153
|
+
const batch = this.write({ ...opts, capacity: 1, autoDestroy: true })
|
|
154
|
+
batch.tryDeleteRange(start, end)
|
|
155
|
+
await batch.flush()
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// used by iterators/batches to ensure no gc/close when active
|
|
159
|
+
|
|
160
|
+
_ref() {
|
|
161
|
+
if (this._snapshot) this._snapshot.ref()
|
|
162
|
+
this._state.activity.inc()
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
_unref() {
|
|
166
|
+
if (this._snapshot) this._snapshot.unref()
|
|
167
|
+
this._state.activity.dec()
|
|
163
168
|
}
|
|
164
169
|
}
|
|
165
170
|
|
|
166
171
|
module.exports = exports = RocksDB
|
|
167
172
|
exports.ColumnFamily = ColumnFamily
|
|
173
|
+
|
|
174
|
+
function maybeClosed(db) {
|
|
175
|
+
if (db._state.closing || db._destroyed)
|
|
176
|
+
throw new Error('RocksDB session is closed')
|
|
177
|
+
}
|
package/lib/batch.js
CHANGED
|
@@ -6,26 +6,16 @@ const resolved = Promise.resolve()
|
|
|
6
6
|
|
|
7
7
|
class RocksDBBatch {
|
|
8
8
|
constructor(db, opts = {}) {
|
|
9
|
-
const {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
valueEncoding = encoding
|
|
15
|
-
} = opts
|
|
16
|
-
|
|
17
|
-
db._state.ref()
|
|
18
|
-
|
|
19
|
-
this._state = db._state
|
|
20
|
-
this._columnFamily = columnFamily
|
|
9
|
+
const { capacity = 8, autoDestroy = false } = opts
|
|
10
|
+
|
|
11
|
+
db._ref()
|
|
12
|
+
|
|
13
|
+
this._db = db
|
|
21
14
|
this._destroyed = false
|
|
22
15
|
this._capacity = capacity
|
|
23
16
|
this._operations = []
|
|
24
17
|
this._promises = []
|
|
25
18
|
|
|
26
|
-
this._keyEncoding = keyEncoding
|
|
27
|
-
this._valueEncoding = valueEncoding
|
|
28
|
-
|
|
29
19
|
this._enqueuePromise = this._enqueuePromise.bind(this)
|
|
30
20
|
|
|
31
21
|
this._request = null
|
|
@@ -33,8 +23,19 @@ class RocksDBBatch {
|
|
|
33
23
|
|
|
34
24
|
this._handle = null
|
|
35
25
|
this._buffer = null
|
|
26
|
+
this._autoDestroy = autoDestroy
|
|
27
|
+
|
|
28
|
+
if (db._state.opened === true) this.ready()
|
|
29
|
+
}
|
|
36
30
|
|
|
37
|
-
|
|
31
|
+
_reuse(db, opts = {}) {
|
|
32
|
+
const { autoDestroy = false } = opts
|
|
33
|
+
|
|
34
|
+
db._ref()
|
|
35
|
+
|
|
36
|
+
this._db = db
|
|
37
|
+
this._destroyed = false
|
|
38
|
+
this._autoDestroy = autoDestroy
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
_onfinished() {
|
|
@@ -45,6 +46,7 @@ class RocksDBBatch {
|
|
|
45
46
|
this._request = null
|
|
46
47
|
this._resolve = null
|
|
47
48
|
|
|
49
|
+
if (this._autoDestroy === true) this.destroy()
|
|
48
50
|
if (resolve !== null) resolve()
|
|
49
51
|
}
|
|
50
52
|
|
|
@@ -61,7 +63,7 @@ class RocksDBBatch {
|
|
|
61
63
|
async ready() {
|
|
62
64
|
if (this._handle !== null) return
|
|
63
65
|
|
|
64
|
-
if (this._state.opened === false) await this._state.ready()
|
|
66
|
+
if (this._db._state.opened === false) await this._db._state.ready()
|
|
65
67
|
|
|
66
68
|
this._init()
|
|
67
69
|
}
|
|
@@ -72,7 +74,22 @@ class RocksDBBatch {
|
|
|
72
74
|
|
|
73
75
|
this._destroyed = true
|
|
74
76
|
|
|
75
|
-
this.
|
|
77
|
+
if (this._promises.length) this._abort()
|
|
78
|
+
|
|
79
|
+
this._db._unref()
|
|
80
|
+
this._onfree()
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
_onfree() {
|
|
84
|
+
this._db._state.freeBatch(this, false)
|
|
85
|
+
this._db = null
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
_abort() {
|
|
89
|
+
for (let i = 0; i < this._promises.length; i++) {
|
|
90
|
+
const promise = this._promises[i]
|
|
91
|
+
if (promise !== null) promise.reject(new Error('Batch is destroyed'))
|
|
92
|
+
}
|
|
76
93
|
}
|
|
77
94
|
|
|
78
95
|
flush() {
|
|
@@ -105,31 +122,25 @@ class RocksDBBatch {
|
|
|
105
122
|
}
|
|
106
123
|
|
|
107
124
|
_encodeKey(k) {
|
|
108
|
-
if (this._keyEncoding) return c.encode(this._keyEncoding, k)
|
|
125
|
+
if (this._db._keyEncoding) return c.encode(this._db._keyEncoding, k)
|
|
109
126
|
if (typeof k === 'string') return Buffer.from(k)
|
|
110
127
|
return k
|
|
111
128
|
}
|
|
112
129
|
|
|
113
130
|
_encodeValue(v) {
|
|
114
|
-
if (this._valueEncoding) return c.encode(this._valueEncoding, v)
|
|
131
|
+
if (this._db._valueEncoding) return c.encode(this._db._valueEncoding, v)
|
|
115
132
|
if (v === null) return empty
|
|
116
133
|
if (typeof v === 'string') return Buffer.from(v)
|
|
117
134
|
return v
|
|
118
135
|
}
|
|
119
136
|
|
|
120
137
|
_decodeValue(b) {
|
|
121
|
-
if (this._valueEncoding) return c.decode(this._valueEncoding, b)
|
|
138
|
+
if (this._db._valueEncoding) return c.decode(this._db._valueEncoding, b)
|
|
122
139
|
return b
|
|
123
140
|
}
|
|
124
141
|
}
|
|
125
142
|
|
|
126
143
|
exports.ReadBatch = class RocksDBReadBatch extends RocksDBBatch {
|
|
127
|
-
constructor(db, opts) {
|
|
128
|
-
super(db, opts)
|
|
129
|
-
|
|
130
|
-
this._snapshot = db._snapshot
|
|
131
|
-
}
|
|
132
|
-
|
|
133
144
|
_init() {
|
|
134
145
|
this._handle = binding.readInit()
|
|
135
146
|
this._buffer = binding.readBuffer(this._handle, this._capacity)
|
|
@@ -145,10 +156,10 @@ exports.ReadBatch = class RocksDBReadBatch extends RocksDBBatch {
|
|
|
145
156
|
await super._flush()
|
|
146
157
|
|
|
147
158
|
binding.read(
|
|
148
|
-
this._state.handle,
|
|
159
|
+
this._db._state.handle,
|
|
149
160
|
this._handle,
|
|
150
161
|
this._operations,
|
|
151
|
-
this._snapshot ? this._snapshot._handle : null,
|
|
162
|
+
this._db._snapshot ? this._db._snapshot._handle : null,
|
|
152
163
|
this,
|
|
153
164
|
this._onread
|
|
154
165
|
)
|
|
@@ -179,7 +190,7 @@ exports.ReadBatch = class RocksDBReadBatch extends RocksDBBatch {
|
|
|
179
190
|
const promise = new Promise(this._enqueuePromise)
|
|
180
191
|
|
|
181
192
|
this._operations.push(
|
|
182
|
-
new RocksDBGet(this._encodeKey(key), this._columnFamily)
|
|
193
|
+
new RocksDBGet(this._encodeKey(key), this._db._columnFamily)
|
|
183
194
|
)
|
|
184
195
|
|
|
185
196
|
this._resize()
|
|
@@ -200,11 +211,15 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
|
|
|
200
211
|
}
|
|
201
212
|
}
|
|
202
213
|
|
|
214
|
+
_onfree() {
|
|
215
|
+
this._db._state.freeBatch(this, true)
|
|
216
|
+
}
|
|
217
|
+
|
|
203
218
|
async _flush() {
|
|
204
219
|
await super._flush()
|
|
205
220
|
|
|
206
221
|
binding.write(
|
|
207
|
-
this._state.handle,
|
|
222
|
+
this._db._state.handle,
|
|
208
223
|
this._handle,
|
|
209
224
|
this._operations,
|
|
210
225
|
this,
|
|
@@ -233,7 +248,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
|
|
|
233
248
|
new RocksDBPut(
|
|
234
249
|
this._encodeKey(key),
|
|
235
250
|
this._encodeValue(value),
|
|
236
|
-
this._columnFamily
|
|
251
|
+
this._db._columnFamily
|
|
237
252
|
)
|
|
238
253
|
)
|
|
239
254
|
|
|
@@ -249,7 +264,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
|
|
|
249
264
|
new RocksDBPut(
|
|
250
265
|
this._encodeKey(key),
|
|
251
266
|
this._encodeValue(value),
|
|
252
|
-
this._columnFamily
|
|
267
|
+
this._db._columnFamily
|
|
253
268
|
)
|
|
254
269
|
)
|
|
255
270
|
|
|
@@ -264,7 +279,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
|
|
|
264
279
|
const promise = new Promise(this._enqueuePromise)
|
|
265
280
|
|
|
266
281
|
this._operations.push(
|
|
267
|
-
new RocksDBDelete(this._encodeKey(key), this._columnFamily)
|
|
282
|
+
new RocksDBDelete(this._encodeKey(key), this._db._columnFamily)
|
|
268
283
|
)
|
|
269
284
|
|
|
270
285
|
this._resize()
|
|
@@ -276,7 +291,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
|
|
|
276
291
|
if (this._request) throw new Error('Request already in progress')
|
|
277
292
|
|
|
278
293
|
this._operations.push(
|
|
279
|
-
new RocksDBDelete(this._encodeKey(key), this._columnFamily)
|
|
294
|
+
new RocksDBDelete(this._encodeKey(key), this._db._columnFamily)
|
|
280
295
|
)
|
|
281
296
|
|
|
282
297
|
this._promises.push(null)
|
|
@@ -293,7 +308,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
|
|
|
293
308
|
new RocksDBDeleteRange(
|
|
294
309
|
this._encodeKey(start),
|
|
295
310
|
this._encodeKey(end),
|
|
296
|
-
this._columnFamily
|
|
311
|
+
this._db._columnFamily
|
|
297
312
|
)
|
|
298
313
|
)
|
|
299
314
|
|
|
@@ -309,7 +324,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
|
|
|
309
324
|
new RocksDBDeleteRange(
|
|
310
325
|
this._encodeKey(start),
|
|
311
326
|
this._encodeKey(end),
|
|
312
|
-
this._columnFamily
|
|
327
|
+
this._db._columnFamily
|
|
313
328
|
)
|
|
314
329
|
)
|
|
315
330
|
|
package/lib/iterator.js
CHANGED
|
@@ -7,28 +7,20 @@ const empty = Buffer.alloc(0)
|
|
|
7
7
|
module.exports = class RocksDBIterator extends Readable {
|
|
8
8
|
constructor(db, opts = {}) {
|
|
9
9
|
const {
|
|
10
|
-
columnFamily = db.defaultColumnFamily,
|
|
11
10
|
gt = null,
|
|
12
11
|
gte = null,
|
|
13
12
|
lt = null,
|
|
14
13
|
lte = null,
|
|
15
14
|
reverse = false,
|
|
16
15
|
limit = Infinity,
|
|
17
|
-
capacity = 8
|
|
18
|
-
encoding = null,
|
|
19
|
-
keyEncoding = encoding,
|
|
20
|
-
valueEncoding = encoding
|
|
16
|
+
capacity = 8
|
|
21
17
|
} = opts
|
|
22
18
|
|
|
23
19
|
super()
|
|
24
20
|
|
|
25
|
-
db.
|
|
21
|
+
db._ref()
|
|
26
22
|
|
|
27
|
-
this.
|
|
28
|
-
this._columnFamily = columnFamily
|
|
29
|
-
|
|
30
|
-
this._keyEncoding = keyEncoding
|
|
31
|
-
this._valueEncoding = valueEncoding
|
|
23
|
+
this._db = db
|
|
32
24
|
|
|
33
25
|
this._gt = gt ? this._encodeKey(gt) : empty
|
|
34
26
|
this._gte = gte ? this._encodeKey(gte) : empty
|
|
@@ -38,7 +30,6 @@ module.exports = class RocksDBIterator extends Readable {
|
|
|
38
30
|
this._reverse = reverse
|
|
39
31
|
this._limit = limit < 0 ? Infinity : limit
|
|
40
32
|
this._capacity = capacity
|
|
41
|
-
this._snapshot = db._snapshot
|
|
42
33
|
|
|
43
34
|
this._pendingOpen = null
|
|
44
35
|
this._pendingRead = null
|
|
@@ -47,7 +38,7 @@ module.exports = class RocksDBIterator extends Readable {
|
|
|
47
38
|
this._buffer = null
|
|
48
39
|
this._handle = null
|
|
49
40
|
|
|
50
|
-
if (this._state.opened === true) this.ready()
|
|
41
|
+
if (this._db._state.opened === true) this.ready()
|
|
51
42
|
}
|
|
52
43
|
|
|
53
44
|
_onopen(err) {
|
|
@@ -80,7 +71,7 @@ module.exports = class RocksDBIterator extends Readable {
|
|
|
80
71
|
_onclose(err) {
|
|
81
72
|
const cb = this._pendingDestroy
|
|
82
73
|
this._pendingDestroy = null
|
|
83
|
-
this.
|
|
74
|
+
this._db._unref()
|
|
84
75
|
cb(err)
|
|
85
76
|
}
|
|
86
77
|
|
|
@@ -93,7 +84,7 @@ module.exports = class RocksDBIterator extends Readable {
|
|
|
93
84
|
async ready() {
|
|
94
85
|
if (this._handle !== null) return
|
|
95
86
|
|
|
96
|
-
if (this._state.opened === false) await this._state.ready()
|
|
87
|
+
if (this._db._state.opened === false) await this._db._state.ready()
|
|
97
88
|
|
|
98
89
|
this._init()
|
|
99
90
|
}
|
|
@@ -109,15 +100,15 @@ module.exports = class RocksDBIterator extends Readable {
|
|
|
109
100
|
this._pendingOpen = cb
|
|
110
101
|
|
|
111
102
|
binding.iteratorOpen(
|
|
112
|
-
this._state.handle,
|
|
103
|
+
this._db._state.handle,
|
|
113
104
|
this._handle,
|
|
114
|
-
this._columnFamily._handle,
|
|
105
|
+
this._db._columnFamily._handle,
|
|
115
106
|
this._gt,
|
|
116
107
|
this._gte,
|
|
117
108
|
this._lt,
|
|
118
109
|
this._lte,
|
|
119
110
|
this._reverse,
|
|
120
|
-
this._snapshot ? this._snapshot._handle : null,
|
|
111
|
+
this._db._snapshot ? this._db._snapshot._handle : null,
|
|
121
112
|
this,
|
|
122
113
|
this._onopen,
|
|
123
114
|
this._onclose,
|
|
@@ -140,18 +131,21 @@ module.exports = class RocksDBIterator extends Readable {
|
|
|
140
131
|
}
|
|
141
132
|
|
|
142
133
|
_encodeKey(k) {
|
|
143
|
-
if (this._keyEncoding
|
|
134
|
+
if (this._db._keyEncoding !== null)
|
|
135
|
+
return c.encode(this._db._keyEncoding, k)
|
|
144
136
|
if (typeof k === 'string') return Buffer.from(k)
|
|
145
137
|
return k
|
|
146
138
|
}
|
|
147
139
|
|
|
148
140
|
_decodeKey(b) {
|
|
149
|
-
if (this._keyEncoding
|
|
141
|
+
if (this._db._keyEncoding !== null)
|
|
142
|
+
return c.decode(this._db._keyEncoding, b)
|
|
150
143
|
return b
|
|
151
144
|
}
|
|
152
145
|
|
|
153
146
|
_decodeValue(b) {
|
|
154
|
-
if (this._valueEncoding
|
|
147
|
+
if (this._db._valueEncoding !== null)
|
|
148
|
+
return c.decode(this._db._valueEncoding, b)
|
|
155
149
|
return b
|
|
156
150
|
}
|
|
157
151
|
}
|
package/lib/snapshot.js
CHANGED
|
@@ -3,12 +3,11 @@ const binding = require('../binding')
|
|
|
3
3
|
module.exports = class RocksDBSnapshot {
|
|
4
4
|
constructor(state) {
|
|
5
5
|
this._state = state
|
|
6
|
-
this._state.snapshots.add(this)
|
|
7
6
|
|
|
8
7
|
this._handle = null
|
|
9
|
-
this._refs =
|
|
8
|
+
this._refs = 0 // starts unreffed, easier, must be reffed in first tick
|
|
10
9
|
|
|
11
|
-
if (state.
|
|
10
|
+
if (state.deferSnapshotInit === false) this._init()
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
_init() {
|
|
@@ -22,8 +21,6 @@ module.exports = class RocksDBSnapshot {
|
|
|
22
21
|
unref() {
|
|
23
22
|
if (--this._refs > 0) return
|
|
24
23
|
|
|
25
|
-
this._state.snapshots.delete(this)
|
|
26
|
-
|
|
27
24
|
if (this._handle === null) return
|
|
28
25
|
|
|
29
26
|
binding.snapshotDestroy(this._handle)
|
package/lib/state.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
const ReadyResource = require('ready-resource')
|
|
2
2
|
const RefCounter = require('refcounter')
|
|
3
|
+
const { ReadBatch, WriteBatch } = require('./batch')
|
|
3
4
|
const ColumnFamily = require('./column-family')
|
|
4
5
|
const binding = require('../binding')
|
|
5
6
|
|
|
7
|
+
const MAX_BATCH_REUSE = 64
|
|
8
|
+
|
|
6
9
|
module.exports = class DBState extends ReadyResource {
|
|
7
10
|
constructor(db, path, opts) {
|
|
8
11
|
super()
|
|
@@ -19,15 +22,16 @@ module.exports = class DBState extends ReadyResource {
|
|
|
19
22
|
|
|
20
23
|
this.path = path
|
|
21
24
|
this.db = db
|
|
22
|
-
this.
|
|
23
|
-
this.sessionRefs = new RefCounter()
|
|
25
|
+
this.activity = new RefCounter()
|
|
24
26
|
this.sessions = []
|
|
25
27
|
this.columnFamilies = [columnFamily]
|
|
26
|
-
this.
|
|
28
|
+
this.deferSnapshotInit = true
|
|
27
29
|
|
|
28
30
|
this._suspending = null
|
|
29
31
|
this._resuming = null
|
|
30
32
|
this._columnsFlushed = false
|
|
33
|
+
this._readBatches = []
|
|
34
|
+
this._writeBatches = []
|
|
31
35
|
|
|
32
36
|
for (const col of columnFamilies) {
|
|
33
37
|
this.columnFamilies.push(
|
|
@@ -47,24 +51,36 @@ module.exports = class DBState extends ReadyResource {
|
|
|
47
51
|
)
|
|
48
52
|
}
|
|
49
53
|
|
|
50
|
-
|
|
51
|
-
this.
|
|
52
|
-
|
|
54
|
+
createReadBatch(db, opts) {
|
|
55
|
+
if (this._readBatches.length === 0) return new ReadBatch(db, opts)
|
|
56
|
+
const batch = this._readBatches.pop()
|
|
57
|
+
batch._reuse(db, opts)
|
|
58
|
+
return batch
|
|
53
59
|
}
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
this.
|
|
57
|
-
const
|
|
58
|
-
|
|
61
|
+
createWriteBatch(db, opts) {
|
|
62
|
+
if (this._writeBatches.length === 0) return new WriteBatch(db, opts)
|
|
63
|
+
const batch = this._writeBatches.pop()
|
|
64
|
+
batch._reuse(db, opts)
|
|
65
|
+
return batch
|
|
59
66
|
}
|
|
60
67
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
68
|
+
freeBatch(batch, writable) {
|
|
69
|
+
const queue = writable ? this._writeBatches : this._readBatches
|
|
70
|
+
if (queue.length >= MAX_BATCH_REUSE) return
|
|
71
|
+
queue.push(batch)
|
|
64
72
|
}
|
|
65
73
|
|
|
66
|
-
|
|
67
|
-
this.
|
|
74
|
+
addSession(db) {
|
|
75
|
+
db._index = this.sessions.push(db) - 1
|
|
76
|
+
if (db._snapshot) db._snapshot.ref()
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
removeSession(db) {
|
|
80
|
+
const head = this.sessions.pop()
|
|
81
|
+
if (head !== db) this.sessions[(head._index = db._index)] = head
|
|
82
|
+
db._index = -1
|
|
83
|
+
if (db._snapshot) db._snapshot.unref()
|
|
68
84
|
}
|
|
69
85
|
|
|
70
86
|
upsertColumnFamily(c) {
|
|
@@ -121,7 +137,10 @@ module.exports = class DBState extends ReadyResource {
|
|
|
121
137
|
|
|
122
138
|
await promise
|
|
123
139
|
|
|
124
|
-
|
|
140
|
+
this.deferSnapshotInit = false
|
|
141
|
+
for (const session of this.sessions) {
|
|
142
|
+
if (session._snapshot) session._snapshot._init()
|
|
143
|
+
}
|
|
125
144
|
|
|
126
145
|
function onopen(err) {
|
|
127
146
|
if (err) req.reject(new Error(err))
|
|
@@ -130,13 +149,11 @@ module.exports = class DBState extends ReadyResource {
|
|
|
130
149
|
}
|
|
131
150
|
|
|
132
151
|
async _close() {
|
|
133
|
-
while (!this.
|
|
134
|
-
|
|
135
|
-
await this.
|
|
136
|
-
}
|
|
152
|
+
while (!this.activity.isIdle()) await this.activity.idle()
|
|
153
|
+
for (let i = this.sessions.length - 1; i >= 0; i--)
|
|
154
|
+
await this.sessions[i].close()
|
|
137
155
|
|
|
138
156
|
for (const columnFamily of this.columnFamilies) columnFamily.destroy()
|
|
139
|
-
for (const snapshot of this.snapshots) snapshot.destroy()
|
|
140
157
|
|
|
141
158
|
const req = { resolve: null, reject: null, handle: null }
|
|
142
159
|
|