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