hypercore 10.0.0-alpha.50 → 10.0.0-alpha.53

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 CHANGED
@@ -1,5 +1,5 @@
1
1
  const { EventEmitter } = require('events')
2
- const raf = require('random-access-file')
2
+ const RAF = require('random-access-file')
3
3
  const isOptions = require('is-options')
4
4
  const hypercoreCrypto = require('hypercore-crypto')
5
5
  const c = require('compact-encoding')
@@ -9,8 +9,6 @@ const NoiseSecretStream = require('@hyperswarm/secret-stream')
9
9
  const Protomux = require('protomux')
10
10
  const codecs = require('codecs')
11
11
 
12
- const fsctl = requireMaybe('fsctl') || { lock: noop, sparse: noop }
13
-
14
12
  const Replicator = require('./lib/replicator')
15
13
  const Core = require('./lib/core')
16
14
  const BlockEncryption = require('./lib/block-encryption')
@@ -162,14 +160,25 @@ module.exports = class Hypercore extends EventEmitter {
162
160
  }
163
161
 
164
162
  static defaultStorage (storage, opts = {}) {
165
- if (typeof storage !== 'string') return storage
163
+ if (typeof storage !== 'string') {
164
+ if (!isRandomAccessClass(storage)) return storage
165
+ const Cls = storage // just to satisfy standard...
166
+ return name => new Cls(name)
167
+ }
168
+
166
169
  const directory = storage
167
170
  const toLock = opts.lock || 'oplog'
168
- return function createFile (name) {
169
- const locked = name === toLock || name.endsWith('/' + toLock)
170
- const lock = locked ? fsctl.lock : null
171
- const sparse = locked ? null : null // fsctl.sparse, disable sparse on windows - seems to fail for some people. TODO: investigate
172
- return raf(name, { directory, lock, sparse })
171
+
172
+ return createFile
173
+
174
+ function createFile (name) {
175
+ const lock = isFile(name, toLock)
176
+ const sparse = isFile(name, 'data') || isFile(name, 'bitfield') || isFile(name, 'tree')
177
+ return new RAF(name, { directory, lock, sparse })
178
+ }
179
+
180
+ function isFile (name, n) {
181
+ return name === n || name.endsWith('/' + n)
173
182
  }
174
183
  }
175
184
 
@@ -852,12 +861,8 @@ function isStream (s) {
852
861
  return typeof s === 'object' && s && typeof s.pipe === 'function'
853
862
  }
854
863
 
855
- function requireMaybe (name) {
856
- try {
857
- return require(name)
858
- } catch (_) {
859
- return null
860
- }
864
+ function isRandomAccessClass (fn) {
865
+ return !!(typeof fn === 'function' && fn.prototype && typeof fn.prototype.open === 'function')
861
866
  }
862
867
 
863
868
  function toHex (buf) {
@@ -1,11 +1,13 @@
1
1
  const flat = require('flat-tree')
2
2
  const crypto = require('hypercore-crypto')
3
3
  const c = require('compact-encoding')
4
+ const Xache = require('xache')
4
5
  const b4a = require('b4a')
5
6
  const caps = require('./caps')
6
7
 
7
8
  const BLANK_HASH = b4a.alloc(32)
8
9
  const OLD_TREE = b4a.from([5, 2, 87, 2, 0, 0, 40, 7, 66, 76, 65, 75, 69, 50, 98])
10
+ const TREE_CACHE = 128 // speeds up linear scans by A LOT
9
11
 
10
12
  class NodeQueue {
11
13
  constructor (nodes, extra = null) {
@@ -140,6 +142,7 @@ class MerkleTreeBatch {
140
142
  : this.ancestors
141
143
 
142
144
  this.tree.truncated = true
145
+ this.tree.cache = new Xache({ maxSize: this.tree.cache.maxSize })
143
146
  truncateMap(this.tree.unflushed, this.ancestors)
144
147
  if (this.tree.flushing !== null) truncateMap(this.tree.flushing, this.ancestors)
145
148
  }
@@ -350,6 +353,7 @@ module.exports = class MerkleTree {
350
353
 
351
354
  this.storage = storage
352
355
  this.unflushed = new Map()
356
+ this.cache = new Xache({ maxSize: TREE_CACHE })
353
357
  this.flushing = null
354
358
  this.truncated = false
355
359
  this.truncateTo = 0
@@ -403,6 +407,9 @@ module.exports = class MerkleTree {
403
407
  }
404
408
 
405
409
  get (index, error = true) {
410
+ const c = this.cache.get(index)
411
+ if (c) return c
412
+
406
413
  let node = this.unflushed.get(index)
407
414
 
408
415
  if (this.flushing !== null && node === undefined) {
@@ -422,7 +429,7 @@ module.exports = class MerkleTree {
422
429
  return Promise.resolve(node)
423
430
  }
424
431
 
425
- return getStoredNode(this.storage, index, error)
432
+ return getStoredNode(this.storage, index, this.cache, error)
426
433
  }
427
434
 
428
435
  async flush () {
@@ -495,6 +502,7 @@ module.exports = class MerkleTree {
495
502
  }
496
503
 
497
504
  clear () {
505
+ this.cache = new Xache({ maxSize: this.cache.maxSize })
498
506
  this.truncated = true
499
507
  this.truncateTo = 0
500
508
  this.roots = []
@@ -754,7 +762,7 @@ module.exports = class MerkleTree {
754
762
 
755
763
  const roots = []
756
764
  for (const index of flat.fullRoots(2 * length)) {
757
- roots.push(await getStoredNode(storage, index, true))
765
+ roots.push(await getStoredNode(storage, index, null, true))
758
766
  }
759
767
 
760
768
  return new MerkleTree(storage, roots, opts.fork || 0, opts.signature || null)
@@ -1085,7 +1093,7 @@ function blankNode (index) {
1085
1093
 
1086
1094
  // Storage methods
1087
1095
 
1088
- function getStoredNode (storage, index, error) {
1096
+ function getStoredNode (storage, index, cache, error) {
1089
1097
  return new Promise((resolve, reject) => {
1090
1098
  storage.read(40 * index, 40, (err, data) => {
1091
1099
  if (err) {
@@ -1103,7 +1111,9 @@ function getStoredNode (storage, index, error) {
1103
1111
  return
1104
1112
  }
1105
1113
 
1106
- resolve({ index, size, hash })
1114
+ const node = { index, size, hash }
1115
+ if (cache !== null) cache.set(index, node)
1116
+ resolve(node)
1107
1117
  })
1108
1118
  })
1109
1119
  }
@@ -1122,7 +1132,7 @@ async function autoLength (storage) {
1122
1132
  if (!nodes) return 0
1123
1133
  const ite = flat.iterator(nodes - 1)
1124
1134
  let index = nodes - 1
1125
- while (await getStoredNode(storage, ite.parent(), false)) index = ite.index
1135
+ while (await getStoredNode(storage, ite.parent(), null, false)) index = ite.index
1126
1136
  return flat.rightSpan(index) / 2 + 1
1127
1137
  }
1128
1138
 
package/lib/replicator.js CHANGED
@@ -1191,7 +1191,7 @@ module.exports = class Replicator {
1191
1191
  for (let i = 0; i < this._ranges.length; i++) {
1192
1192
  const r = this._ranges[i]
1193
1193
 
1194
- while (r.start < r.end && this.core.bitfield.get(mapIndex(r.blocks, r.start)) === true) r.start++
1194
+ while ((r.end === -1 || r.start < r.end) && this.core.bitfield.get(mapIndex(r.blocks, r.start)) === true) r.start++
1195
1195
  while (r.start < r.end && this.core.bitfield.get(mapIndex(r.blocks, r.end - 1)) === true) r.end--
1196
1196
 
1197
1197
  if (r.end !== -1 && r.start >= r.end) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercore",
3
- "version": "10.0.0-alpha.50",
3
+ "version": "10.0.0-alpha.53",
4
4
  "description": "Hypercore 10",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -43,22 +43,19 @@
43
43
  "hypercore-crypto": "^3.2.1",
44
44
  "is-options": "^1.0.1",
45
45
  "protomux": "^3.2.0",
46
- "random-access-file": "^2.1.4",
46
+ "random-access-file": "^3.0.1",
47
47
  "random-array-iterator": "^1.0.0",
48
48
  "safety-catch": "^1.0.1",
49
49
  "sodium-universal": "^3.0.4",
50
50
  "streamx": "^2.12.4",
51
- "xache": "^1.0.0"
51
+ "xache": "^1.1.0"
52
52
  },
53
53
  "devDependencies": {
54
54
  "brittle": "^2.0.0",
55
- "hyperswarm": "next",
56
- "random-access-memory": "^4.1.0",
57
- "random-access-memory-overlay": "^1.0.0",
55
+ "hyperswarm": "^4.1.1",
56
+ "random-access-memory": "^5.0.0",
57
+ "random-access-memory-overlay": "^2.0.0",
58
58
  "standard": "^16.0.3",
59
59
  "tmp-promise": "^3.0.2"
60
- },
61
- "optionalDependencies": {
62
- "fsctl": "^1.0.0"
63
60
  }
64
61
  }