hypercore 10.0.0-alpha.44 → 10.0.0-alpha.47
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 +50 -13
- package/lib/caps.js +1 -3
- package/lib/core.js +6 -2
- package/lib/replicator.js +51 -12
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -113,6 +113,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
113
113
|
indent + ' opened: ' + opts.stylize(this.opened, 'boolean') + '\n' +
|
|
114
114
|
indent + ' closed: ' + opts.stylize(this.closed, 'boolean') + '\n' +
|
|
115
115
|
indent + ' snapshotted: ' + opts.stylize(this.snapshotted, 'boolean') + '\n' +
|
|
116
|
+
indent + ' sparse: ' + opts.stylize(this.sparse, 'boolean') + '\n' +
|
|
116
117
|
indent + ' writable: ' + opts.stylize(this.writable, 'boolean') + '\n' +
|
|
117
118
|
indent + ' length: ' + opts.stylize(this.length, 'number') + '\n' +
|
|
118
119
|
indent + ' byteLength: ' + opts.stylize(this.byteLength, 'number') + '\n' +
|
|
@@ -182,9 +183,11 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
182
183
|
throw SESSION_CLOSED('Cannot make sessions on a closing core')
|
|
183
184
|
}
|
|
184
185
|
|
|
186
|
+
const sparse = opts.sparse === false ? false : this.sparse
|
|
185
187
|
const Clz = opts.class || Hypercore
|
|
186
188
|
const s = new Clz(this.storage, this.key, {
|
|
187
189
|
...opts,
|
|
190
|
+
sparse,
|
|
188
191
|
_opening: this.opening,
|
|
189
192
|
_sessions: this.sessions
|
|
190
193
|
})
|
|
@@ -297,7 +300,8 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
297
300
|
crypto: this.crypto,
|
|
298
301
|
legacy: opts.legacy,
|
|
299
302
|
auth: opts.auth,
|
|
300
|
-
onupdate: this._oncoreupdate.bind(this)
|
|
303
|
+
onupdate: this._oncoreupdate.bind(this),
|
|
304
|
+
oncontigupdate: this._oncorecontigupdate.bind(this)
|
|
301
305
|
})
|
|
302
306
|
|
|
303
307
|
if (opts.userData) {
|
|
@@ -323,14 +327,27 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
323
327
|
}
|
|
324
328
|
}
|
|
325
329
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
330
|
+
_getSnapshot () {
|
|
331
|
+
if (this.sparse) {
|
|
332
|
+
return {
|
|
333
|
+
length: this.core.tree.length,
|
|
334
|
+
byteLength: this.core.tree.byteLength,
|
|
335
|
+
fork: this.core.tree.fork,
|
|
336
|
+
compatLength: this.core.tree.length
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return {
|
|
341
|
+
length: this.core.header.contiguousLength,
|
|
342
|
+
byteLength: 0,
|
|
331
343
|
fork: this.core.tree.fork,
|
|
332
|
-
compatLength: this.core.
|
|
344
|
+
compatLength: this.core.header.contiguousLength
|
|
333
345
|
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
_updateSnapshot () {
|
|
349
|
+
const prev = this._snapshot
|
|
350
|
+
const next = this._snapshot = this._getSnapshot()
|
|
334
351
|
|
|
335
352
|
if (!prev) return true
|
|
336
353
|
return prev.length !== next.length || prev.fork !== next.fork
|
|
@@ -484,9 +501,10 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
484
501
|
if (s._snapshot && bitfield.start < s._snapshot.compatLength) s._snapshot.compatLength = bitfield.start
|
|
485
502
|
}
|
|
486
503
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
504
|
+
// For sparse sessions, immediately emit appends. Non-sparse sessions
|
|
505
|
+
// are handled separately and only emit appends when their contiguous
|
|
506
|
+
// length is updated.
|
|
507
|
+
if (appended && s.sparse) s.emit('append')
|
|
490
508
|
}
|
|
491
509
|
|
|
492
510
|
this.replicator.onupgrade()
|
|
@@ -505,6 +523,16 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
505
523
|
}
|
|
506
524
|
}
|
|
507
525
|
|
|
526
|
+
_oncorecontigupdate () {
|
|
527
|
+
// For non-sparse sessions, emit appends only when the contiguous length is
|
|
528
|
+
// updated.
|
|
529
|
+
for (let i = 0; i < this.sessions.length; i++) {
|
|
530
|
+
const s = this.sessions[i]
|
|
531
|
+
|
|
532
|
+
if (!s.sparse) s.emit('append')
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
508
536
|
_onpeerupdate (added, peer) {
|
|
509
537
|
const name = added ? 'peer-add' : 'peer-remove'
|
|
510
538
|
|
|
@@ -561,10 +589,19 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
561
589
|
const activeRequests = (opts && opts.activeRequests) || this.activeRequests
|
|
562
590
|
const req = this.replicator.addUpgrade(activeRequests)
|
|
563
591
|
|
|
564
|
-
|
|
565
|
-
|
|
592
|
+
const upgraded = await req.promise
|
|
593
|
+
|
|
594
|
+
if (!this.sparse) {
|
|
595
|
+
// Download all available blocks in non-sparse mode
|
|
596
|
+
const start = this.length
|
|
597
|
+
const end = this.core.tree.length
|
|
598
|
+
|
|
599
|
+
await this.download({ start, end, ifAvailable: true }).downloaded()
|
|
600
|
+
}
|
|
566
601
|
|
|
567
|
-
|
|
602
|
+
if (!upgraded) return false
|
|
603
|
+
if (this.snapshotted) return this._updateSnapshot()
|
|
604
|
+
return true
|
|
568
605
|
}
|
|
569
606
|
|
|
570
607
|
async seek (bytes, opts) {
|
package/lib/caps.js
CHANGED
|
@@ -4,9 +4,7 @@ const b4a = require('b4a')
|
|
|
4
4
|
const c = require('compact-encoding')
|
|
5
5
|
|
|
6
6
|
// TODO: rename this to "crypto" and move everything hashing related etc in here
|
|
7
|
-
// Also lets move the tree stuff from hypercore-crypto here
|
|
8
|
-
// from the hashes there - they are not needed since we lock the indexes in the tree
|
|
9
|
-
// hash and just makes alignment etc harder in other languages
|
|
7
|
+
// Also lets move the tree stuff from hypercore-crypto here
|
|
10
8
|
|
|
11
9
|
const [TREE, REPLICATE_INITIATOR, REPLICATE_RESPONDER] = crypto.namespace('hypercore', 3)
|
|
12
10
|
|
package/lib/core.js
CHANGED
|
@@ -9,8 +9,9 @@ const { BAD_ARGUMENT, STORAGE_EMPTY, STORAGE_CONFLICT, INVALID_SIGNATURE } = req
|
|
|
9
9
|
const m = require('./messages')
|
|
10
10
|
|
|
11
11
|
module.exports = class Core {
|
|
12
|
-
constructor (header, crypto, oplog, tree, blocks, bitfield, auth, legacy, onupdate) {
|
|
12
|
+
constructor (header, crypto, oplog, tree, blocks, bitfield, auth, legacy, onupdate, oncontigupdate) {
|
|
13
13
|
this.onupdate = onupdate
|
|
14
|
+
this.oncontigupdate = oncontigupdate
|
|
14
15
|
this.header = header
|
|
15
16
|
this.crypto = crypto
|
|
16
17
|
this.oplog = oplog
|
|
@@ -164,7 +165,7 @@ module.exports = class Core {
|
|
|
164
165
|
}
|
|
165
166
|
}
|
|
166
167
|
|
|
167
|
-
return new this(header, crypto, oplog, tree, blocks, bitfield, auth, !!opts.legacy, opts.onupdate || noop)
|
|
168
|
+
return new this(header, crypto, oplog, tree, blocks, bitfield, auth, !!opts.legacy, opts.onupdate || noop, opts.oncontigupdate || noop)
|
|
168
169
|
}
|
|
169
170
|
|
|
170
171
|
_shouldFlush () {
|
|
@@ -202,6 +203,7 @@ module.exports = class Core {
|
|
|
202
203
|
while (this.bitfield.get(i)) i++
|
|
203
204
|
|
|
204
205
|
this.header.contiguousLength = i
|
|
206
|
+
this.oncontigupdate()
|
|
205
207
|
}
|
|
206
208
|
}
|
|
207
209
|
|
|
@@ -285,6 +287,7 @@ module.exports = class Core {
|
|
|
285
287
|
batch.commit()
|
|
286
288
|
|
|
287
289
|
this.header.contiguousLength = batch.length
|
|
290
|
+
this.oncontigupdate()
|
|
288
291
|
this.header.tree.length = batch.length
|
|
289
292
|
this.header.tree.rootHash = hash
|
|
290
293
|
this.header.tree.signature = batch.signature
|
|
@@ -472,6 +475,7 @@ module.exports = class Core {
|
|
|
472
475
|
const appended = batch.length > batch.ancestors
|
|
473
476
|
|
|
474
477
|
this.header.contiguousLength = Math.min(batch.ancestors, this.header.contiguousLength)
|
|
478
|
+
this.oncontigupdate()
|
|
475
479
|
this.header.tree.fork = batch.fork
|
|
476
480
|
this.header.tree.length = batch.length
|
|
477
481
|
this.header.tree.rootHash = batch.hash()
|
package/lib/replicator.js
CHANGED
|
@@ -102,12 +102,13 @@ class BlockRequest extends Attachable {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
class RangeRequest extends Attachable {
|
|
105
|
-
constructor (ranges, start, end, linear, blocks) {
|
|
105
|
+
constructor (ranges, start, end, linear, ifAvailable, blocks) {
|
|
106
106
|
super()
|
|
107
107
|
|
|
108
108
|
this.start = start
|
|
109
109
|
this.end = end
|
|
110
110
|
this.linear = linear
|
|
111
|
+
this.ifAvailable = ifAvailable
|
|
111
112
|
this.blocks = blocks
|
|
112
113
|
this.ranges = ranges
|
|
113
114
|
|
|
@@ -172,6 +173,10 @@ class InflightTracker {
|
|
|
172
173
|
this._free = []
|
|
173
174
|
}
|
|
174
175
|
|
|
176
|
+
get idle () {
|
|
177
|
+
return this._requests.length === this._free.length
|
|
178
|
+
}
|
|
179
|
+
|
|
175
180
|
* [Symbol.iterator] () {
|
|
176
181
|
for (const req of this._requests) {
|
|
177
182
|
if (req !== null) yield req
|
|
@@ -260,6 +265,7 @@ class Peer {
|
|
|
260
265
|
|
|
261
266
|
this.inflight = 0
|
|
262
267
|
this.maxInflight = DEFAULT_MAX_INFLIGHT
|
|
268
|
+
this.dataProcessing = 0
|
|
263
269
|
|
|
264
270
|
this.canUpgrade = true
|
|
265
271
|
|
|
@@ -515,6 +521,8 @@ class Peer {
|
|
|
515
521
|
|
|
516
522
|
if (reorg === true) return this.replicator._onreorgdata(this, req, data)
|
|
517
523
|
|
|
524
|
+
this.dataProcessing++
|
|
525
|
+
|
|
518
526
|
try {
|
|
519
527
|
if (!matchingRequest(req, data) || !(await this.core.verify(data, this))) {
|
|
520
528
|
this.replicator._onnodata(this, req)
|
|
@@ -523,6 +531,8 @@ class Peer {
|
|
|
523
531
|
} catch (err) {
|
|
524
532
|
this.replicator._onnodata(this, req)
|
|
525
533
|
throw err
|
|
534
|
+
} finally {
|
|
535
|
+
this.dataProcessing--
|
|
526
536
|
}
|
|
527
537
|
|
|
528
538
|
this.replicator._ondata(this, req, data)
|
|
@@ -909,13 +919,21 @@ module.exports = class Replicator {
|
|
|
909
919
|
return ref
|
|
910
920
|
}
|
|
911
921
|
|
|
912
|
-
addRange (session, { start = 0, end = -1, length = toLength(start, end), blocks = null, linear = false } = {}) {
|
|
922
|
+
addRange (session, { start = 0, end = -1, length = toLength(start, end), blocks = null, linear = false, ifAvailable = false } = {}) {
|
|
913
923
|
if (blocks !== null) { // if using blocks, start, end just acts as frames around the blocks array
|
|
914
924
|
start = 0
|
|
915
925
|
end = length = blocks.length
|
|
916
926
|
}
|
|
917
927
|
|
|
918
|
-
const r = new RangeRequest(
|
|
928
|
+
const r = new RangeRequest(
|
|
929
|
+
this._ranges,
|
|
930
|
+
start,
|
|
931
|
+
length === -1 ? -1 : start + length,
|
|
932
|
+
linear,
|
|
933
|
+
ifAvailable,
|
|
934
|
+
blocks
|
|
935
|
+
)
|
|
936
|
+
|
|
919
937
|
const ref = r.attach(session)
|
|
920
938
|
|
|
921
939
|
this._ranges.push(r)
|
|
@@ -1115,6 +1133,14 @@ module.exports = class Replicator {
|
|
|
1115
1133
|
return true
|
|
1116
1134
|
}
|
|
1117
1135
|
|
|
1136
|
+
_resolveRangeRequest (req, index) {
|
|
1137
|
+
const head = this._ranges.pop()
|
|
1138
|
+
|
|
1139
|
+
if (index < this._ranges.length) this._ranges[index] = head
|
|
1140
|
+
|
|
1141
|
+
req.resolve(true)
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1118
1144
|
_clearInflightBlock (tracker, req) {
|
|
1119
1145
|
const isBlock = tracker === this._blocks
|
|
1120
1146
|
const index = isBlock === true ? req.block.index : req.hash.index / 2
|
|
@@ -1168,14 +1194,9 @@ module.exports = class Replicator {
|
|
|
1168
1194
|
while (r.start < r.end && this.core.bitfield.get(mapIndex(r.blocks, r.start)) === true) r.start++
|
|
1169
1195
|
while (r.start < r.end && this.core.bitfield.get(mapIndex(r.blocks, r.end - 1)) === true) r.end--
|
|
1170
1196
|
|
|
1171
|
-
if (r.end
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
else this._ranges.pop()
|
|
1175
|
-
|
|
1176
|
-
i--
|
|
1177
|
-
|
|
1178
|
-
r.resolve(true)
|
|
1197
|
+
if (r.end !== -1 && r.start >= r.end) {
|
|
1198
|
+
this._resolveRangeRequest(r, i--)
|
|
1199
|
+
}
|
|
1179
1200
|
}
|
|
1180
1201
|
|
|
1181
1202
|
for (let i = 0; i < this._seeks.length; i++) {
|
|
@@ -1201,7 +1222,7 @@ module.exports = class Replicator {
|
|
|
1201
1222
|
else s.resolve(res)
|
|
1202
1223
|
}
|
|
1203
1224
|
|
|
1204
|
-
this.updateAll()
|
|
1225
|
+
if (this._inflight.idle) this.updateAll()
|
|
1205
1226
|
|
|
1206
1227
|
// No additional updates scheduled - return
|
|
1207
1228
|
if (--this._updatesPending === 0) return
|
|
@@ -1210,6 +1231,22 @@ module.exports = class Replicator {
|
|
|
1210
1231
|
}
|
|
1211
1232
|
}
|
|
1212
1233
|
|
|
1234
|
+
_maybeResolveIfAvailableRanges () {
|
|
1235
|
+
if (this._ifAvailable > 0 || !this._inflight.idle || !this._ranges.length) return
|
|
1236
|
+
|
|
1237
|
+
for (let i = 0; i < this.peers.length; i++) {
|
|
1238
|
+
if (this.peers[i].dataProcessing > 0) return
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
for (let i = 0; i < this._ranges.length; i++) {
|
|
1242
|
+
const r = this._ranges[i]
|
|
1243
|
+
|
|
1244
|
+
if (r.ifAvailable) {
|
|
1245
|
+
this._resolveRangeRequest(r, i--)
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1213
1250
|
_clearRequest (peer, req) {
|
|
1214
1251
|
if (req.block !== null) {
|
|
1215
1252
|
this._clearInflightBlock(this._blocks, req)
|
|
@@ -1407,6 +1444,7 @@ module.exports = class Replicator {
|
|
|
1407
1444
|
while (this._updatePeerNonPrimary(peer) === true);
|
|
1408
1445
|
|
|
1409
1446
|
this._checkUpgradeIfAvailable()
|
|
1447
|
+
this._maybeResolveIfAvailableRanges()
|
|
1410
1448
|
}
|
|
1411
1449
|
|
|
1412
1450
|
updateAll () {
|
|
@@ -1434,6 +1472,7 @@ module.exports = class Replicator {
|
|
|
1434
1472
|
}
|
|
1435
1473
|
|
|
1436
1474
|
this._checkUpgradeIfAvailable()
|
|
1475
|
+
this._maybeResolveIfAvailableRanges()
|
|
1437
1476
|
}
|
|
1438
1477
|
|
|
1439
1478
|
attachTo (protomux) {
|