hyperbee2 0.0.1 → 1.0.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/index.js CHANGED
@@ -12,7 +12,7 @@ class Hyperbee {
12
12
  const {
13
13
  key = null,
14
14
  core = key ? store.get(key) : store.get({ key, name: 'bee' }),
15
- context = new CoreContext(store, core),
15
+ context = new CoreContext(store, core, core),
16
16
  maxCacheSize = 4096,
17
17
  cache = new NodeCache(maxCacheSize),
18
18
  root = null,
@@ -64,9 +64,9 @@ class Hyperbee {
64
64
  return this.store.replicate(...opts)
65
65
  }
66
66
 
67
- _makeView(root, writable, unbatch) {
67
+ _makeView(context, root, writable, unbatch) {
68
68
  return new Hyperbee(this.store, {
69
- context: this.context,
69
+ context,
70
70
  cache: this.cache,
71
71
  root,
72
72
  view: true,
@@ -78,15 +78,15 @@ class Hyperbee {
78
78
  checkout({ length = this.core.length, key = null, writable = false } = {}) {
79
79
  const context = key ? this.context.getContextByKey(key) : this.context
80
80
  const root = length === 0 ? EMPTY : new TreeNodePointer(context, 0, length - 1, 0, false, null)
81
- return this._makeView(root, writable, 0)
81
+ return this._makeView(context, root, writable, 0)
82
82
  }
83
83
 
84
84
  snapshot() {
85
- return this._makeView(this.root, false, 0)
85
+ return this._makeView(this.context, this.root, false, 0)
86
86
  }
87
87
 
88
88
  undo(n) {
89
- return this._makeView(this.root, true, n)
89
+ return this._makeView(this.context, this.root, true, n)
90
90
  }
91
91
 
92
92
  write(opts) {
package/lib/context.js CHANGED
@@ -2,8 +2,9 @@ const b4a = require('b4a')
2
2
  const { decodeBlock } = require('./encoding.js')
3
3
 
4
4
  class CoreContext {
5
- constructor(store, core, other = new Map()) {
5
+ constructor(store, local, core, other = new Map()) {
6
6
  this.store = store
7
+ this.local = local
7
8
  this.core = core
8
9
  this.other = other
9
10
  this.length = 0
@@ -48,14 +49,14 @@ class CoreContext {
48
49
 
49
50
  // TODO: prop use a map...
50
51
  for (let i = 0; i < this.cores.length; i++) {
51
- const k = this.cores[i]
52
+ const k = this.cores[i].key
52
53
  if (b4a.equals(k, key)) {
53
54
  return i + 1
54
55
  }
55
56
  }
56
57
 
57
58
  this.changed = true
58
- this.cores.push(key)
59
+ this.cores.push({ key, fork: 0, length: 0, treeHash: null })
59
60
  return this.cores.length
60
61
  }
61
62
 
@@ -65,7 +66,7 @@ class CoreContext {
65
66
  if (b4a.equals(key, this.core.key)) return 0
66
67
 
67
68
  for (let i = 0; i < this.cores.length; i++) {
68
- const k = this.cores[i]
69
+ const k = this.cores[i].key
69
70
  if (b4a.equals(k, key)) {
70
71
  return i + 1
71
72
  }
@@ -74,22 +75,23 @@ class CoreContext {
74
75
  await this.update(activeRequests)
75
76
 
76
77
  for (let i = 0; i < this.cores.length; i++) {
77
- const k = this.cores[i]
78
+ const k = this.cores[i].key
78
79
  if (b4a.equals(k, key)) {
79
80
  return i + 1
80
81
  }
81
82
  }
82
83
 
83
84
  this.changed = true
84
- this.cores.push(key)
85
+ this.cores.push({ key, fork: 0, length: 0, treeHash: null })
85
86
  return this.cores.length
86
87
  }
87
88
 
88
89
  getCore(index) {
89
90
  if (index === 0) return this.core
90
91
  if (index > this.cores.length) throw new Error('Bad core index: ' + index)
91
- if (this.opened[index - 1] === null)
92
- this.opened[index - 1] = this.store.get(this.cores[index - 1])
92
+ if (this.opened[index - 1] === null) {
93
+ this.opened[index - 1] = this.store.get(this.cores[index - 1].key)
94
+ }
93
95
  return this.opened[index - 1]
94
96
  }
95
97
 
@@ -101,13 +103,17 @@ class CoreContext {
101
103
  return block
102
104
  }
103
105
 
106
+ getLocalContext() {
107
+ return this.getContextByKey(this.local.key)
108
+ }
109
+
104
110
  getContextByKey(key) {
105
111
  if (b4a.equals(key, this.core.key)) return this
106
112
 
107
113
  const hex = b4a.toString(key, 'hex')
108
114
  if (this.other.has(hex)) return this.other.get(hex)
109
115
 
110
- const ctx = new CoreContext(this.store, this.store.get(key))
116
+ const ctx = new CoreContext(this.store, this.local, this.store.get(key))
111
117
  this.other.set(hex, ctx)
112
118
  return ctx
113
119
  }
@@ -117,11 +123,11 @@ class CoreContext {
117
123
  if (core > this.cores.length) await this.update(activeRequests)
118
124
  if (core > this.cores.length) throw new Error('Bad core index: ' + core)
119
125
 
120
- const hex = b4a.toString(this.cores[core - 1], 'hex')
126
+ const hex = b4a.toString(this.cores[core - 1].key, 'hex')
121
127
  if (this.other.has(hex)) return this.other.get(hex)
122
128
 
123
129
  const hc = this.getCore(core)
124
- const ctx = new CoreContext(this.store, hc)
130
+ const ctx = new CoreContext(this.store, this.local, hc)
125
131
  this.other.set(hex, ctx)
126
132
  return ctx
127
133
  }
package/lib/write.js CHANGED
@@ -288,8 +288,9 @@ module.exports = class WriteBatch {
288
288
  const update = { node: [], keys: [] }
289
289
  const batch = [update]
290
290
  const stack = [{ update, node: this.root }]
291
+ const context = this.tree.context.getLocalContext()
291
292
 
292
- await this.tree.context.update(this.tree.activeRequests)
293
+ await context.update(this.tree.activeRequests)
293
294
 
294
295
  while (stack.length > 0) {
295
296
  const { update, node } = stack.pop()
@@ -301,12 +302,8 @@ module.exports = class WriteBatch {
301
302
  const k = node.value.keys[i]
302
303
 
303
304
  if (!k.changed) {
304
- k.core = await this.tree.context.getCoreOffset(
305
- k.context,
306
- k.core,
307
- this.tree.activeRequests
308
- )
309
- k.context = this.tree.context
305
+ k.core = await context.getCoreOffset(k.context, k.core, this.tree.activeRequests)
306
+ k.context = context
310
307
  continue
311
308
  }
312
309
 
@@ -320,12 +317,8 @@ module.exports = class WriteBatch {
320
317
  const n = node.value.children[i]
321
318
 
322
319
  if (!n.changed) {
323
- n.core = await this.tree.context.getCoreOffset(
324
- n.context,
325
- n.core,
326
- this.tree.activeRequests
327
- )
328
- n.context = this.tree.context
320
+ n.core = await context.getCoreOffset(n.context, n.core, this.tree.activeRequests)
321
+ n.context = context
329
322
  continue
330
323
  }
331
324
 
@@ -340,7 +333,7 @@ module.exports = class WriteBatch {
340
333
  }
341
334
  }
342
335
 
343
- const length = this.tree.core.length
336
+ const length = context.core.length
344
337
  const blocks = new Array(batch.length)
345
338
 
346
339
  for (let i = 0; i < batch.length; i++) {
@@ -361,7 +354,7 @@ module.exports = class WriteBatch {
361
354
  if (block.data === null) block.data = []
362
355
 
363
356
  k.core = 0
364
- k.context = this.tree.context
357
+ k.context = context
365
358
  k.seq = seq
366
359
  k.offset = block.data.length
367
360
  block.data.push(k)
@@ -371,7 +364,7 @@ module.exports = class WriteBatch {
371
364
  if (block.tree === null) block.tree = []
372
365
 
373
366
  n.core = 0
374
- n.context = this.tree.context
367
+ n.context = context
375
368
  n.seq = seq
376
369
  n.offset = block.tree.length
377
370
  block.tree.push(n.value)
@@ -384,20 +377,20 @@ module.exports = class WriteBatch {
384
377
 
385
378
  if (blocks.length > 0 && this.length > 0) {
386
379
  const core = this.key
387
- ? await this.tree.context.getCoreOffsetByKey(this.key, this.tree.activeRequests)
380
+ ? await context.getCoreOffsetByKey(this.key, this.tree.activeRequests)
388
381
  : 0
389
382
  blocks[blocks.length - 1].previous = { core, seq: this.length - 1 }
390
383
  }
391
384
 
392
385
  // TODO: make this transaction safe
393
- if (this.tree.context.changed) {
394
- this.tree.context.changed = false
395
- this.tree.context.checkpoint = this.tree.core.length + blocks.length
396
- blocks[blocks.length - 1].cores = this.tree.context.cores
386
+ if (context.changed) {
387
+ context.changed = false
388
+ context.checkpoint = context.core.length + blocks.length
389
+ blocks[blocks.length - 1].cores = context.cores
397
390
  }
398
391
 
399
392
  for (let i = 0; i < blocks.length; i++) {
400
- blocks[i].checkpoint = this.tree.context.checkpoint
393
+ blocks[i].checkpoint = context.checkpoint
401
394
  buffers[i] = c.encode(Block, blocks[i])
402
395
  }
403
396
 
@@ -405,7 +398,7 @@ module.exports = class WriteBatch {
405
398
  throw new Error('Write batch is closed')
406
399
  }
407
400
 
408
- await this.tree.core.append(buffers)
401
+ await context.core.append(buffers)
409
402
 
410
403
  for (let i = 0; i < batch.length; i++) {
411
404
  const update = batch[i]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperbee2",
3
- "version": "0.0.1",
3
+ "version": "1.0.0",
4
4
  "description": "btree",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -125,15 +125,48 @@ const encoding4 = {
125
125
  }
126
126
  }
127
127
 
128
+ // @bee/core
129
+ const encoding5 = {
130
+ preencode(state, m) {
131
+ c.fixed32.preencode(state, m.key)
132
+ state.end++ // max flag is 4 so always one byte
133
+
134
+ if (m.fork) c.uint.preencode(state, m.fork)
135
+ if (m.length) c.uint.preencode(state, m.length)
136
+ if (m.treeHash) c.fixed32.preencode(state, m.treeHash)
137
+ },
138
+ encode(state, m) {
139
+ const flags = (m.fork ? 1 : 0) | (m.length ? 2 : 0) | (m.treeHash ? 4 : 0)
140
+
141
+ c.fixed32.encode(state, m.key)
142
+ c.uint.encode(state, flags)
143
+
144
+ if (m.fork) c.uint.encode(state, m.fork)
145
+ if (m.length) c.uint.encode(state, m.length)
146
+ if (m.treeHash) c.fixed32.encode(state, m.treeHash)
147
+ },
148
+ decode(state) {
149
+ const r0 = c.fixed32.decode(state)
150
+ const flags = c.uint.decode(state)
151
+
152
+ return {
153
+ key: r0,
154
+ fork: (flags & 1) !== 0 ? c.uint.decode(state) : 0,
155
+ length: (flags & 2) !== 0 ? c.uint.decode(state) : 0,
156
+ treeHash: (flags & 4) !== 0 ? c.fixed32.decode(state) : null
157
+ }
158
+ }
159
+ }
160
+
128
161
  // @bee/block.tree
129
- const encoding5_4 = c.array(encoding3)
162
+ const encoding6_4 = c.array(encoding3)
130
163
  // @bee/block.data
131
- const encoding5_5 = c.array(encoding4)
164
+ const encoding6_5 = c.array(encoding4)
132
165
  // @bee/block.cores
133
- const encoding5_6 = c.array(c.fixed32)
166
+ const encoding6_6 = c.array(encoding5)
134
167
 
135
168
  // @bee/block
136
- const encoding5 = {
169
+ const encoding6 = {
137
170
  preencode(state, m) {
138
171
  c.uint.preencode(state, m.type)
139
172
  c.uint.preencode(state, m.checkpoint)
@@ -141,9 +174,9 @@ const encoding5 = {
141
174
  state.end++ // max flag is 8 so always one byte
142
175
 
143
176
  if (m.previous) encoding1.preencode(state, m.previous)
144
- if (m.tree) encoding5_4.preencode(state, m.tree)
145
- if (m.data) encoding5_5.preencode(state, m.data)
146
- if (m.cores) encoding5_6.preencode(state, m.cores)
177
+ if (m.tree) encoding6_4.preencode(state, m.tree)
178
+ if (m.data) encoding6_5.preencode(state, m.data)
179
+ if (m.cores) encoding6_6.preencode(state, m.cores)
147
180
  },
148
181
  encode(state, m) {
149
182
  const flags = (m.previous ? 1 : 0) | (m.tree ? 2 : 0) | (m.data ? 4 : 0) | (m.cores ? 8 : 0)
@@ -154,9 +187,9 @@ const encoding5 = {
154
187
  c.uint.encode(state, flags)
155
188
 
156
189
  if (m.previous) encoding1.encode(state, m.previous)
157
- if (m.tree) encoding5_4.encode(state, m.tree)
158
- if (m.data) encoding5_5.encode(state, m.data)
159
- if (m.cores) encoding5_6.encode(state, m.cores)
190
+ if (m.tree) encoding6_4.encode(state, m.tree)
191
+ if (m.data) encoding6_5.encode(state, m.data)
192
+ if (m.cores) encoding6_6.encode(state, m.cores)
160
193
  },
161
194
  decode(state) {
162
195
  const r0 = c.uint.decode(state)
@@ -169,9 +202,9 @@ const encoding5 = {
169
202
  checkpoint: r1,
170
203
  batch: r2,
171
204
  previous: (flags & 1) !== 0 ? encoding1.decode(state) : null,
172
- tree: (flags & 2) !== 0 ? encoding5_4.decode(state) : null,
173
- data: (flags & 4) !== 0 ? encoding5_5.decode(state) : null,
174
- cores: (flags & 8) !== 0 ? encoding5_6.decode(state) : null
205
+ tree: (flags & 2) !== 0 ? encoding6_4.decode(state) : null,
206
+ data: (flags & 4) !== 0 ? encoding6_5.decode(state) : null,
207
+ cores: (flags & 8) !== 0 ? encoding6_6.decode(state) : null
175
208
  }
176
209
  }
177
210
  }
@@ -209,8 +242,10 @@ function getEncoding(name) {
209
242
  return encoding3
210
243
  case '@bee/data':
211
244
  return encoding4
212
- case '@bee/block':
245
+ case '@bee/core':
213
246
  return encoding5
247
+ case '@bee/block':
248
+ return encoding6
214
249
  default:
215
250
  throw new Error('Encoder not found ' + name)
216
251
  }
@@ -109,6 +109,35 @@
109
109
  }
110
110
  ]
111
111
  },
112
+ {
113
+ "name": "core",
114
+ "namespace": "bee",
115
+ "compact": true,
116
+ "flagsPosition": 1,
117
+ "fields": [
118
+ {
119
+ "name": "key",
120
+ "required": true,
121
+ "type": "fixed32",
122
+ "version": 1
123
+ },
124
+ {
125
+ "name": "fork",
126
+ "type": "uint",
127
+ "version": 1
128
+ },
129
+ {
130
+ "name": "length",
131
+ "type": "uint",
132
+ "version": 1
133
+ },
134
+ {
135
+ "name": "treeHash",
136
+ "type": "fixed32",
137
+ "version": 1
138
+ }
139
+ ]
140
+ },
112
141
  {
113
142
  "name": "block",
114
143
  "namespace": "bee",
@@ -153,7 +182,7 @@
153
182
  {
154
183
  "name": "cores",
155
184
  "array": true,
156
- "type": "fixed32",
185
+ "type": "@bee/core",
157
186
  "version": 1
158
187
  }
159
188
  ]