hypercore-storage 0.0.36 → 0.0.38
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 +138 -35
- package/lib/dependency-stream.js +1 -1
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -162,7 +162,7 @@ class WriteBatch {
|
|
|
162
162
|
|
|
163
163
|
flush () {
|
|
164
164
|
if (this.atom) return this.atom.flush()
|
|
165
|
-
return this.write
|
|
165
|
+
return flushAndDestroy(this.write)
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
|
|
@@ -259,15 +259,32 @@ class ReadBatch {
|
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
flush () {
|
|
262
|
-
return this.read
|
|
262
|
+
return flushAndDestroy(this.read)
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
tryFlush () {
|
|
266
|
-
this.read
|
|
266
|
+
tryFlushAndDestroy(this.read)
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
-
class
|
|
270
|
+
class Lock {
|
|
271
|
+
constructor (mutex) {
|
|
272
|
+
this.mutex = mutex
|
|
273
|
+
this.refs = 0
|
|
274
|
+
this.promise = null
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
acquire () {
|
|
278
|
+
if (this.refs++ === 0) this.promise = this.mutex.lock()
|
|
279
|
+
return this
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
release () {
|
|
283
|
+
if (--this.refs === 0) return this.mutex.unlock()
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
class Atom {
|
|
271
288
|
constructor (db) {
|
|
272
289
|
this.db = db
|
|
273
290
|
this.batch = null
|
|
@@ -276,6 +293,11 @@ class Atomizer {
|
|
|
276
293
|
this.flushing = null
|
|
277
294
|
this.resolve = null
|
|
278
295
|
this.reject = null
|
|
296
|
+
|
|
297
|
+
this._executing = null
|
|
298
|
+
this._waiting = []
|
|
299
|
+
this._queue = []
|
|
300
|
+
this._enqueue = (lock, resolve, reject) => this._queue.push({ lock, resolve, reject })
|
|
279
301
|
}
|
|
280
302
|
|
|
281
303
|
enter () {
|
|
@@ -286,6 +308,43 @@ class Atomizer {
|
|
|
286
308
|
if (--this.refs === 0) this._commit()
|
|
287
309
|
}
|
|
288
310
|
|
|
311
|
+
acquire (mutex) {
|
|
312
|
+
const lock = this._lock(mutex)
|
|
313
|
+
return new Promise(this._enqueue.bind(this, lock))
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
_lock (mutex) {
|
|
317
|
+
for (const lock of this._waiting) {
|
|
318
|
+
if (lock.mutex === mutex) return lock.acquire()
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const lock = new Lock(mutex)
|
|
322
|
+
this._waiting.push(lock)
|
|
323
|
+
|
|
324
|
+
if (this._executing === null) this._executing = this._execute()
|
|
325
|
+
|
|
326
|
+
return lock.acquire()
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
async _execute () {
|
|
330
|
+
this.enter()
|
|
331
|
+
for (const { promise } of this._waiting) await promise
|
|
332
|
+
|
|
333
|
+
const queue = this._queue
|
|
334
|
+
|
|
335
|
+
this._waiting = []
|
|
336
|
+
this._queue = []
|
|
337
|
+
this._executing = null
|
|
338
|
+
|
|
339
|
+
for (const { lock, resolve, reject } of queue) {
|
|
340
|
+
if (this.destroyed) reject(new Error('Atomizer destroyed'))
|
|
341
|
+
else resolve(lock)
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
this._ensureTick() // allow caller to enter
|
|
345
|
+
this.exit()
|
|
346
|
+
}
|
|
347
|
+
|
|
289
348
|
createBatch () {
|
|
290
349
|
if (this.refs === 0) this._ensureTick()
|
|
291
350
|
this.enter()
|
|
@@ -299,6 +358,8 @@ class Atomizer {
|
|
|
299
358
|
}
|
|
300
359
|
|
|
301
360
|
async _commit () {
|
|
361
|
+
if (this.batch === null) return
|
|
362
|
+
|
|
302
363
|
const batch = this.batch
|
|
303
364
|
const resolve = this.resolve
|
|
304
365
|
const reject = this.reject
|
|
@@ -317,10 +378,12 @@ class Atomizer {
|
|
|
317
378
|
try {
|
|
318
379
|
await batch.flush()
|
|
319
380
|
} catch (err) {
|
|
381
|
+
batch.destroy()
|
|
320
382
|
reject(err)
|
|
321
383
|
return
|
|
322
384
|
}
|
|
323
385
|
|
|
386
|
+
batch.destroy()
|
|
324
387
|
resolve()
|
|
325
388
|
}
|
|
326
389
|
|
|
@@ -350,7 +413,7 @@ class Atomizer {
|
|
|
350
413
|
|
|
351
414
|
module.exports = class CoreStorage {
|
|
352
415
|
constructor (dir) {
|
|
353
|
-
this.db = new RocksDB(dir)
|
|
416
|
+
this.db = typeof dir === 'object' ? dir : new RocksDB(dir)
|
|
354
417
|
this.mutex = new RW()
|
|
355
418
|
}
|
|
356
419
|
|
|
@@ -372,7 +435,7 @@ module.exports = class CoreStorage {
|
|
|
372
435
|
try {
|
|
373
436
|
const b = this.db.write()
|
|
374
437
|
b.tryPut(b4a.from([TL.LOCAL_SEED]), seed)
|
|
375
|
-
await b
|
|
438
|
+
await flushAndDestroy(b)
|
|
376
439
|
|
|
377
440
|
return true
|
|
378
441
|
} finally {
|
|
@@ -420,14 +483,14 @@ module.exports = class CoreStorage {
|
|
|
420
483
|
return this.db.close()
|
|
421
484
|
}
|
|
422
485
|
|
|
423
|
-
|
|
424
|
-
return new
|
|
486
|
+
atom () {
|
|
487
|
+
return new Atom(this.db)
|
|
425
488
|
}
|
|
426
489
|
|
|
427
490
|
async clear () {
|
|
428
491
|
const b = this.db.write()
|
|
429
492
|
b.tryDeleteRange(b4a.from([TL.STORAGE_INFO]), INF)
|
|
430
|
-
await b
|
|
493
|
+
await flushAndDestroy(b)
|
|
431
494
|
}
|
|
432
495
|
|
|
433
496
|
async has (discoveryKey) {
|
|
@@ -495,6 +558,7 @@ class HypercoreStorage {
|
|
|
495
558
|
this.root = root
|
|
496
559
|
this.db = root.db
|
|
497
560
|
this.dbSnapshot = snapshot
|
|
561
|
+
this.dbRead = snapshot || this.db
|
|
498
562
|
this.mutex = root.mutex
|
|
499
563
|
|
|
500
564
|
this.discoveryKey = discoveryKey
|
|
@@ -512,8 +576,8 @@ class HypercoreStorage {
|
|
|
512
576
|
return this.dbSnapshot !== null
|
|
513
577
|
}
|
|
514
578
|
|
|
515
|
-
|
|
516
|
-
return this.root.
|
|
579
|
+
atom () {
|
|
580
|
+
return this.root.atom()
|
|
517
581
|
}
|
|
518
582
|
|
|
519
583
|
dependencyLength () {
|
|
@@ -535,14 +599,14 @@ class HypercoreStorage {
|
|
|
535
599
|
return storage
|
|
536
600
|
}
|
|
537
601
|
|
|
538
|
-
async registerBatch (name, head) {
|
|
602
|
+
async registerBatch (name, head, atom) {
|
|
539
603
|
await this.mutex.write.lock()
|
|
540
604
|
|
|
541
605
|
const storage = new HypercoreStorage(this.root, this.discoveryKey, this.corePointer, this.dataPointer, null)
|
|
542
606
|
|
|
543
607
|
try {
|
|
544
608
|
const info = await getStorageInfo(this.db)
|
|
545
|
-
const write = this.db.write()
|
|
609
|
+
const write = atom ? atom.createBatch() : this.db.write()
|
|
546
610
|
|
|
547
611
|
storage.dataPointer = info.free++
|
|
548
612
|
|
|
@@ -556,7 +620,8 @@ class HypercoreStorage {
|
|
|
556
620
|
batch.setBatchPointer(name, storage.dataPointer)
|
|
557
621
|
if (head.rootHash) batch.setCoreHead(head) // if no root hash its the empty core - no head yet
|
|
558
622
|
|
|
559
|
-
await
|
|
623
|
+
if (atom) await atom.flush()
|
|
624
|
+
else await flushAndDestroy(write)
|
|
560
625
|
|
|
561
626
|
storage.dependencies = await addDependencies(this.db, storage.dataPointer, head.length)
|
|
562
627
|
return storage
|
|
@@ -583,7 +648,7 @@ class HypercoreStorage {
|
|
|
583
648
|
|
|
584
649
|
snapshot () {
|
|
585
650
|
assert(this.destroyed === false)
|
|
586
|
-
const s = new HypercoreStorage(this.root, this.discoveryKey, this.corePointer, this.dataPointer, this.
|
|
651
|
+
const s = new HypercoreStorage(this.root, this.discoveryKey, this.corePointer, this.dataPointer, this.dbRead.snapshot())
|
|
587
652
|
|
|
588
653
|
for (const { data, length } of this.dependencies) s.dependencies.push({ data, length })
|
|
589
654
|
|
|
@@ -616,18 +681,35 @@ class HypercoreStorage {
|
|
|
616
681
|
createReadBatch (opts) {
|
|
617
682
|
assert(this.destroyed === false)
|
|
618
683
|
|
|
619
|
-
|
|
620
|
-
return new ReadBatch(this, this.db.read({ snapshot }))
|
|
684
|
+
return new ReadBatch(this, this.dbRead.read())
|
|
621
685
|
}
|
|
622
686
|
|
|
623
|
-
createWriteBatch (
|
|
687
|
+
createWriteBatch (atom) {
|
|
624
688
|
assert(this.destroyed === false)
|
|
625
689
|
|
|
626
|
-
if (
|
|
690
|
+
if (atom) return new WriteBatch(this, atom.createBatch(), atom)
|
|
627
691
|
|
|
628
692
|
return new WriteBatch(this, this.db.write(), null)
|
|
629
693
|
}
|
|
630
694
|
|
|
695
|
+
// helper for atomic flows
|
|
696
|
+
async createWriteBatchAndLock (atomizer, lock) {
|
|
697
|
+
assert(this.destroyed === false)
|
|
698
|
+
if (atomizer) atomizer.enter()
|
|
699
|
+
|
|
700
|
+
try {
|
|
701
|
+
await lock.lock()
|
|
702
|
+
} catch (err) {
|
|
703
|
+
if (atomizer) atomizer.exit()
|
|
704
|
+
throw err
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
const batch = this.createWriteBatch(atomizer)
|
|
708
|
+
if (atomizer) atomizer.exit()
|
|
709
|
+
|
|
710
|
+
return batch
|
|
711
|
+
}
|
|
712
|
+
|
|
631
713
|
createBlockStream (opts = {}) {
|
|
632
714
|
assert(this.destroyed === false)
|
|
633
715
|
return createStream(this, createBlockStream, opts)
|
|
@@ -636,8 +718,8 @@ class HypercoreStorage {
|
|
|
636
718
|
createUserDataStream (opts = {}) {
|
|
637
719
|
assert(this.destroyed === false)
|
|
638
720
|
|
|
639
|
-
const r = encodeUserDataRange(this.dataPointer, DATA.USER_DATA,
|
|
640
|
-
const s = this.
|
|
721
|
+
const r = encodeUserDataRange(this.dataPointer, DATA.USER_DATA, opts)
|
|
722
|
+
const s = this.dbRead.iterator(r)
|
|
641
723
|
s._readableState.map = mapStreamUserData
|
|
642
724
|
return s
|
|
643
725
|
}
|
|
@@ -645,8 +727,8 @@ class HypercoreStorage {
|
|
|
645
727
|
createTreeNodeStream (opts = {}) {
|
|
646
728
|
assert(this.destroyed === false)
|
|
647
729
|
|
|
648
|
-
const r = encodeIndexRange(this.dataPointer, DATA.TREE,
|
|
649
|
-
const s = this.
|
|
730
|
+
const r = encodeIndexRange(this.dataPointer, DATA.TREE, opts)
|
|
731
|
+
const s = this.dbRead.iterator(r)
|
|
650
732
|
s._readableState.map = mapStreamTreeNode
|
|
651
733
|
return s
|
|
652
734
|
}
|
|
@@ -654,8 +736,8 @@ class HypercoreStorage {
|
|
|
654
736
|
createBitfieldPageStream (opts = {}) {
|
|
655
737
|
assert(this.destroyed === false)
|
|
656
738
|
|
|
657
|
-
const r = encodeIndexRange(this.dataPointer, DATA.BITFIELD,
|
|
658
|
-
const s = this.
|
|
739
|
+
const r = encodeIndexRange(this.dataPointer, DATA.BITFIELD, opts)
|
|
740
|
+
const s = this.dbRead.iterator(r)
|
|
659
741
|
s._readableState.map = mapStreamBitfieldPage
|
|
660
742
|
return s
|
|
661
743
|
}
|
|
@@ -663,7 +745,7 @@ class HypercoreStorage {
|
|
|
663
745
|
async peekLastTreeNode () {
|
|
664
746
|
assert(this.destroyed === false)
|
|
665
747
|
|
|
666
|
-
const last = await this.
|
|
748
|
+
const last = await this.dbRead.peek(encodeIndexRange(this.dataPointer, DATA.TREE, { reverse: true }))
|
|
667
749
|
if (last === null) return null
|
|
668
750
|
return c.decode(m.TreeNode, last.value)
|
|
669
751
|
}
|
|
@@ -671,7 +753,7 @@ class HypercoreStorage {
|
|
|
671
753
|
async peekLastBitfieldPage () {
|
|
672
754
|
assert(this.destroyed === false)
|
|
673
755
|
|
|
674
|
-
const last = await this.
|
|
756
|
+
const last = await this.dbRead.peek(encodeIndexRange(this.dataPointer, DATA.BITFIELD, { reverse: true }))
|
|
675
757
|
if (last === null) return null
|
|
676
758
|
return mapStreamBitfieldPage(last)
|
|
677
759
|
}
|
|
@@ -680,19 +762,19 @@ class HypercoreStorage {
|
|
|
680
762
|
if (this.destroyed) return
|
|
681
763
|
this.destroyed = true
|
|
682
764
|
|
|
683
|
-
if (this.dbSnapshot) this.dbSnapshot.
|
|
765
|
+
if (this.dbSnapshot) this.dbSnapshot.close().catch(noop)
|
|
684
766
|
this.dbSnapshot = null
|
|
685
767
|
}
|
|
686
768
|
}
|
|
687
769
|
|
|
688
770
|
function createStream (storage, createStreamType, opts) {
|
|
689
771
|
return storage.dependencies.length === 0
|
|
690
|
-
? createStreamType(storage.db, storage.
|
|
772
|
+
? createStreamType(storage.db, storage.dataPointer, opts)
|
|
691
773
|
: new DependencyStream(storage, createStreamType, opts)
|
|
692
774
|
}
|
|
693
775
|
|
|
694
|
-
function createBlockStream (db,
|
|
695
|
-
const r = encodeIndexRange(data, DATA.BLOCK,
|
|
776
|
+
function createBlockStream (db, data, opts) {
|
|
777
|
+
const r = encodeIndexRange(data, DATA.BLOCK, opts)
|
|
696
778
|
const s = db.iterator(r)
|
|
697
779
|
s._readableState.map = mapStreamBlock
|
|
698
780
|
return s
|
|
@@ -766,8 +848,8 @@ function ensureSlab (size) {
|
|
|
766
848
|
return SLAB
|
|
767
849
|
}
|
|
768
850
|
|
|
769
|
-
function encodeIndexRange (pointer, type,
|
|
770
|
-
const bounded = {
|
|
851
|
+
function encodeIndexRange (pointer, type, opts) {
|
|
852
|
+
const bounded = { gt: null, gte: null, lte: null, lt: null, reverse: !!opts.reverse, limit: toLimit(opts.limit) }
|
|
771
853
|
|
|
772
854
|
if (opts.gt || opts.gt === 0) bounded.gt = encodeDataIndex(pointer, type, opts.gt)
|
|
773
855
|
else if (opts.gte) bounded.gte = encodeDataIndex(pointer, type, opts.gte)
|
|
@@ -780,8 +862,8 @@ function encodeIndexRange (pointer, type, snapshot, opts) {
|
|
|
780
862
|
return bounded
|
|
781
863
|
}
|
|
782
864
|
|
|
783
|
-
function encodeUserDataRange (pointer, type,
|
|
784
|
-
const bounded = {
|
|
865
|
+
function encodeUserDataRange (pointer, type, opts) {
|
|
866
|
+
const bounded = { gt: null, gte: null, lte: null, lt: null, reverse: !!opts.reverse, limit: toLimit(opts.limit) }
|
|
785
867
|
|
|
786
868
|
if (opts.gt || opts.gt === 0) bounded.gt = encodeUserDataIndex(pointer, type, opts.gt)
|
|
787
869
|
else if (opts.gte) bounded.gte = encodeUserDataIndex(pointer, type, opts.gte)
|
|
@@ -904,3 +986,24 @@ function initialiseCoreData (db, { userData } = {}) {
|
|
|
904
986
|
}
|
|
905
987
|
}
|
|
906
988
|
}
|
|
989
|
+
|
|
990
|
+
function noop () {}
|
|
991
|
+
|
|
992
|
+
async function tryFlushAndDestroy (batch) {
|
|
993
|
+
try {
|
|
994
|
+
await batch.flush()
|
|
995
|
+
} catch {}
|
|
996
|
+
|
|
997
|
+
batch.destroy()
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
async function flushAndDestroy (batch) {
|
|
1001
|
+
try {
|
|
1002
|
+
await batch.flush()
|
|
1003
|
+
} catch (err) {
|
|
1004
|
+
batch.destroy()
|
|
1005
|
+
throw err
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
batch.destroy()
|
|
1009
|
+
}
|
package/lib/dependency-stream.js
CHANGED
|
@@ -93,7 +93,7 @@ module.exports = class DependencyStream extends Readable {
|
|
|
93
93
|
_nextStream () {
|
|
94
94
|
const { data, gte, lt } = this._streams[this._next++]
|
|
95
95
|
|
|
96
|
-
const stream = this.createStream(this.storage.
|
|
96
|
+
const stream = this.createStream(this.storage.dbRead, data, {
|
|
97
97
|
reverse: this._reverse,
|
|
98
98
|
limit: this._limit,
|
|
99
99
|
gte,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hypercore-storage",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.38",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"files": [
|
|
6
6
|
"index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"queue-tick": "^1.0.1",
|
|
23
23
|
"read-write-mutexify": "^2.1.0",
|
|
24
24
|
"resolve-reject-promise": "^1.0.0",
|
|
25
|
-
"rocksdb-native": "^
|
|
25
|
+
"rocksdb-native": "^3.0.0",
|
|
26
26
|
"streamx": "^2.20.1"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|