Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ class CoreContext {
getCoreOffsetLocal(context, core) {
if (context === this) return core

const key = core === 0 ? context.core.key : context.cores[core - 1].key
const key = this.mappings.unresolve(core === 0 ? context.core.key : context.cores[core - 1].key)
const offset = this.getCoreOffsetLocalByKey(key)

if (offset > -1) return offset
Expand All @@ -185,6 +185,8 @@ class CoreContext {
async getCoreOffsetByKey(key, config) {
await this.core.ready()

key = this.mappings.unresolve(key)

let offset = this.getCoreOffsetLocalByKey(key)
if (offset > -1) return offset

Expand Down
8 changes: 8 additions & 0 deletions lib/mappings.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const b4a = require('b4a')
class Mappings {
constructor() {
this.known = new Map()
this.reverse = new Map()
this.dirty = false
this._flushed = null
}
Expand All @@ -13,12 +14,19 @@ class Mappings {
return known === undefined ? key : known
}

unresolve(key) {
if (this.reverse.size === 0) return key
const from = this.reverse.get(b4a.toString(key, 'hex'))
return from === undefined ? key : from
}

add(mappings, { persisted = false } = {}) {
for (const { from, to } of mappings) {
if (b4a.equals(from, to)) continue
const hex = b4a.toString(from, 'hex')
if (this.known.has(hex)) continue
this.known.set(hex, to)
this.reverse.set(b4a.toString(to, 'hex'), from)
this._flushed = null
if (!persisted) this.dirty = true
}
Expand Down
38 changes: 38 additions & 0 deletions test/map-core.js
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,44 @@ test('mappings - cores({ recursive: true }) walks the tables of every core reach
await b.close()
})

test('mappings - the core table keeps the keys as they were before the mapping', async function (t) {
const store = new Corestore(await t.tmp())
t.teardown(() => store.close())

const { a, w, copy, mappings } = await setup(store)
await w.write({ mappings }).flush()

// the tree moves onto the original, so it now reads through the copy
w.move({ key: a.core.key, length: a.core.length })
t.alike(w.core.key, copy.key, 'the tree sits on the copy')

const batch = w.write()
batch.tryPut(key(60), value(60))
await batch.flush()

const table = (keys) => keys.map(hex)
const local = w.context.getLocalContext()
t.ok(
table(local.cores.map((c) => c.key)).includes(hex(a.core.key)),
'the original is in the table'
)
t.absent(table(local.cores.map((c) => c.key)).includes(hex(copy.key)), 'the copy never is')
await w.close()

await a.core.clear(0, a.core.length)

const r = new Bee(store.namespace('w'), { writable: false })
await r.ready()
await r.cores()
t.absent(
table(r.context.cores.map((c) => c.key)).includes(hex(copy.key)),
'nor in the checkpoint written'
)
t.alike((await r.get(key(60))).value, value(60))
await readAll(r, 50, t, 'and every entry of the original reads through the mapping')
await r.close()
})

function replicateStores(a, b) {
const s1 = a.replicate(true)
const s2 = b.replicate(false)
Expand Down
Loading