hypercore-storage 1.5.1 → 1.6.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/migrations/0/index.js +137 -24
- package/package.json +1 -1
package/migrations/0/index.js
CHANGED
|
@@ -226,6 +226,65 @@ async function store (storage, { version, dryRun = true, gc = true }) {
|
|
|
226
226
|
if (gc) await rm(primaryKeyFile)
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
+
class BlockSlicer {
|
|
230
|
+
constructor (filename) {
|
|
231
|
+
this.stream = fs.createReadStream(filename)
|
|
232
|
+
this.closed = new Promise(resolve => this.stream.once('close', resolve))
|
|
233
|
+
this.offset = 0
|
|
234
|
+
this.overflow = null
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async take (offset, size) {
|
|
238
|
+
let buffer = null
|
|
239
|
+
if (offset < this.offset) throw new Error('overread')
|
|
240
|
+
|
|
241
|
+
const end = offset + size
|
|
242
|
+
|
|
243
|
+
while (true) {
|
|
244
|
+
let data = null
|
|
245
|
+
|
|
246
|
+
if (this.overflow) {
|
|
247
|
+
data = this.overflow
|
|
248
|
+
this.overflow = null
|
|
249
|
+
} else {
|
|
250
|
+
data = this.stream.read()
|
|
251
|
+
|
|
252
|
+
if (!data) {
|
|
253
|
+
await new Promise(resolve => this.stream.once('readable', resolve))
|
|
254
|
+
continue
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
let chunk = null
|
|
259
|
+
|
|
260
|
+
if (this.offset === offset || buffer) {
|
|
261
|
+
chunk = data
|
|
262
|
+
} else if (this.offset + data.byteLength > offset) {
|
|
263
|
+
chunk = data.subarray(offset - this.offset)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
this.offset += data.byteLength
|
|
267
|
+
if (!chunk) continue
|
|
268
|
+
|
|
269
|
+
if (buffer) buffer = b4a.concat([buffer, chunk])
|
|
270
|
+
else buffer = chunk
|
|
271
|
+
|
|
272
|
+
if (buffer.byteLength < size) continue
|
|
273
|
+
|
|
274
|
+
const result = buffer.subarray(0, size)
|
|
275
|
+
this.overflow = size === buffer.byteLength ? null : buffer.subarray(result.byteLength)
|
|
276
|
+
this.offset -= (this.overflow ? this.overflow.byteLength : 0)
|
|
277
|
+
return result
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
close () {
|
|
282
|
+
this.stream.on('error', noop)
|
|
283
|
+
this.stream.destroy()
|
|
284
|
+
return this.closed
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
229
288
|
class TreeSlicer {
|
|
230
289
|
constructor () {
|
|
231
290
|
this.buffer = null
|
|
@@ -359,7 +418,7 @@ async function core (core, { version, dryRun = true, gc = true }) {
|
|
|
359
418
|
const pages = new Map()
|
|
360
419
|
const headerBits = new Map()
|
|
361
420
|
|
|
362
|
-
const roots = await
|
|
421
|
+
const roots = await getRootsFromStorage(core, head.length)
|
|
363
422
|
|
|
364
423
|
for (const e of oplog.entries) {
|
|
365
424
|
if (!e.bitfield) continue
|
|
@@ -369,28 +428,35 @@ async function core (core, { version, dryRun = true, gc = true }) {
|
|
|
369
428
|
}
|
|
370
429
|
}
|
|
371
430
|
|
|
372
|
-
let
|
|
431
|
+
let batch = []
|
|
432
|
+
|
|
433
|
+
const cache = new Map()
|
|
434
|
+
const blocks = new BlockSlicer(files.data)
|
|
435
|
+
|
|
373
436
|
for (const index of allBits(bitfield)) {
|
|
374
437
|
if (headerBits.get(index) === false) continue
|
|
375
438
|
|
|
376
439
|
setBitInPage(index)
|
|
377
440
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
if (w.changes.length > 1024) {
|
|
381
|
-
await w.flush()
|
|
382
|
-
w = core.write()
|
|
383
|
-
}
|
|
441
|
+
batch.push(index)
|
|
442
|
+
if (batch.length < 1024) continue
|
|
384
443
|
|
|
385
|
-
|
|
444
|
+
await writeBlocksBatch()
|
|
445
|
+
continue
|
|
386
446
|
}
|
|
387
447
|
|
|
448
|
+
if (batch.length) await writeBlocksBatch()
|
|
449
|
+
|
|
450
|
+
await blocks.close()
|
|
451
|
+
|
|
452
|
+
const w = core.write()
|
|
453
|
+
|
|
388
454
|
for (const [index, bit] of headerBits) {
|
|
389
455
|
if (!bit) continue
|
|
390
456
|
|
|
391
457
|
setBitInPage(index)
|
|
392
458
|
|
|
393
|
-
const blk = await getBlockFromFile(files.data, index, roots,
|
|
459
|
+
const blk = await getBlockFromFile(files.data, core, index, roots, cache)
|
|
394
460
|
w.putBlock(index, blk)
|
|
395
461
|
}
|
|
396
462
|
|
|
@@ -441,11 +507,27 @@ async function core (core, { version, dryRun = true, gc = true }) {
|
|
|
441
507
|
page[b] |= v
|
|
442
508
|
}
|
|
443
509
|
|
|
444
|
-
function
|
|
510
|
+
async function writeBlocksBatch () {
|
|
445
511
|
const read = core.read()
|
|
446
|
-
const
|
|
512
|
+
const promises = []
|
|
513
|
+
for (const index of batch) promises.push(getByteRangeFromStorage(read, 2 * index, roots, cache))
|
|
447
514
|
read.tryFlush()
|
|
448
|
-
|
|
515
|
+
|
|
516
|
+
const r = await Promise.all(promises)
|
|
517
|
+
const tx = core.write()
|
|
518
|
+
|
|
519
|
+
for (let i = 0; i < r.length; i++) {
|
|
520
|
+
const index = batch[i]
|
|
521
|
+
const [offset, size] = r[i]
|
|
522
|
+
|
|
523
|
+
const blk = await blocks.take(offset, size)
|
|
524
|
+
tx.putBlock(index, blk)
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
batch = []
|
|
528
|
+
if (cache.size > 16384) cache.clear()
|
|
529
|
+
|
|
530
|
+
await tx.flush()
|
|
449
531
|
}
|
|
450
532
|
}
|
|
451
533
|
|
|
@@ -468,6 +550,20 @@ async function commitCoreMigration (auth, core, version) {
|
|
|
468
550
|
await View.flush(view.changes, core.db)
|
|
469
551
|
}
|
|
470
552
|
|
|
553
|
+
async function getBlockFromFile (file, core, index, roots, cache) {
|
|
554
|
+
const rx = core.read()
|
|
555
|
+
const promise = getByteRangeFromStorage(rx, 2 * index, roots, cache)
|
|
556
|
+
rx.tryFlush()
|
|
557
|
+
const [offset, size] = await promise
|
|
558
|
+
|
|
559
|
+
return new Promise(function (resolve) {
|
|
560
|
+
readAll(file, size, offset, function (err, buf) {
|
|
561
|
+
if (err) return resolve(null)
|
|
562
|
+
resolve(buf)
|
|
563
|
+
})
|
|
564
|
+
})
|
|
565
|
+
}
|
|
566
|
+
|
|
471
567
|
function getFiles (dir) {
|
|
472
568
|
return {
|
|
473
569
|
path: dir,
|
|
@@ -478,6 +574,16 @@ function getFiles (dir) {
|
|
|
478
574
|
}
|
|
479
575
|
}
|
|
480
576
|
|
|
577
|
+
async function getRootsFromStorage (core, length) {
|
|
578
|
+
const all = []
|
|
579
|
+
const rx = core.read()
|
|
580
|
+
for (const index of flat.fullRoots(2 * length)) {
|
|
581
|
+
all.push(rx.getTreeNode(index))
|
|
582
|
+
}
|
|
583
|
+
rx.tryFlush()
|
|
584
|
+
return Promise.all(all)
|
|
585
|
+
}
|
|
586
|
+
|
|
481
587
|
async function getRoots (length, getTreeNode) {
|
|
482
588
|
const all = []
|
|
483
589
|
for (const index of flat.fullRoots(2 * length)) {
|
|
@@ -486,19 +592,20 @@ async function getRoots (length, getTreeNode) {
|
|
|
486
592
|
return all
|
|
487
593
|
}
|
|
488
594
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
const
|
|
595
|
+
function getCached (read, cache, index) {
|
|
596
|
+
if (cache.has(index)) return cache.get(index)
|
|
597
|
+
const p = read.getTreeNode(index)
|
|
598
|
+
cache.set(index, p)
|
|
599
|
+
return p
|
|
600
|
+
}
|
|
492
601
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
})
|
|
498
|
-
})
|
|
602
|
+
async function getByteRangeFromStorage (read, index, roots, cache) {
|
|
603
|
+
const promises = [getCached(read, cache, index), getByteOffsetFromStorage(read, index, roots, cache)]
|
|
604
|
+
const [node, offset] = await Promise.all(promises)
|
|
605
|
+
return [offset, node.size]
|
|
499
606
|
}
|
|
500
607
|
|
|
501
|
-
async function
|
|
608
|
+
async function getByteOffsetFromStorage (rx, index, roots, cache) {
|
|
502
609
|
if (index === 0) return 0
|
|
503
610
|
if ((index & 1) === 1) index = flat.leftSpan(index)
|
|
504
611
|
|
|
@@ -514,16 +621,20 @@ async function getByteOffset (index, roots, getTreeNode) {
|
|
|
514
621
|
}
|
|
515
622
|
|
|
516
623
|
const ite = flat.iterator(node.index)
|
|
624
|
+
const promises = []
|
|
517
625
|
|
|
518
626
|
while (ite.index !== index) {
|
|
519
627
|
if (index < ite.index) {
|
|
520
628
|
ite.leftChild()
|
|
521
629
|
} else {
|
|
522
|
-
|
|
630
|
+
promises.push(getCached(rx, cache, ite.leftChild()))
|
|
523
631
|
ite.sibling()
|
|
524
632
|
}
|
|
525
633
|
}
|
|
526
634
|
|
|
635
|
+
const nodes = await Promise.all(promises)
|
|
636
|
+
for (const node of nodes) offset += node.size
|
|
637
|
+
|
|
527
638
|
return offset
|
|
528
639
|
}
|
|
529
640
|
|
|
@@ -687,3 +798,5 @@ function readOplog (oplog) {
|
|
|
687
798
|
})
|
|
688
799
|
})
|
|
689
800
|
}
|
|
801
|
+
|
|
802
|
+
function noop () {}
|