Skip to content

Commit

Permalink
remove dependencyLength property (#635)
Browse files Browse the repository at this point in the history
* kill dependency length

* checkout sessions simply truncate

* remove length argument from checkout session

* make finding dependency truncate aware

* read dependency length from storage

* standard fix

* remove unused condition
  • Loading branch information
chm-diederichs authored Feb 11, 2025
1 parent 8c151c9 commit cc340d4
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 67 deletions.
18 changes: 9 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -344,18 +344,20 @@ class Hypercore extends EventEmitter {
const state = this.state

if (opts.atom) {
this.state = await parent.state.createSession(null, checkout, false, opts.atom)
this.state = await parent.state.createSession(null, false, opts.atom)
if (state) state.unref()
} else if (opts.name) {
// todo: need to make named sessions safe before ready
// atm we always copy the state in passCapabilities
this.state = await parent.state.createSession(opts.name, checkout, !!opts.overwrite, null)
this.state = await parent.state.createSession(opts.name, !!opts.overwrite, null)
if (state) state.unref() // ref'ed above in setup session
}

if (checkout !== -1 && checkout < this.state.length) {
await this.state.truncate(checkout, this.fork)
}
} else if (this.state === null) {
if (this.state && checkout !== -1 && checkout < this.state.length) {
await this.state.truncate(checkout, this.fork)
}

if (this.state === null) {
this.state = this.core.state.ref()
}

Expand Down Expand Up @@ -520,9 +522,7 @@ class Hypercore extends EventEmitter {
get signedLength () {
if (this.opened === false) return 0
if (this.state === this.core.state) return this.core.state.length
const flushed = this.state.flushedLength()

return flushed === -1 ? this.state.length : flushed
return this.state.flushedLength()
}

/**
Expand Down
91 changes: 33 additions & 58 deletions lib/session-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const assert = require('nanoassert')
const flat = require('flat-tree')
const quickbit = require('quickbit-universal')

const { STORAGE_CONFLICT, INVALID_OPERATION, INVALID_SIGNATURE } = require('hypercore-errors')
const { INVALID_OPERATION, INVALID_SIGNATURE } = require('hypercore-errors')

const Mutex = require('./mutex')
const Bitfield = require('./bitfield')
Expand Down Expand Up @@ -38,10 +38,6 @@ module.exports = class SessionState {
this.prologue = treeInfo.prologue || null
this.signature = treeInfo.signature || null

const deps = this.storage.dependencies
this.dependencyLength = deps.length ? deps[deps.length - 1].length : 0

if (treeInfo.length < this.dependencyLength) this.dependencyLength = treeInfo.length
if (treeInfo.roots.length) this.setRoots(treeInfo.roots)

this.snapshotCompatLength = this.isSnapshot() ? this.length : -1
Expand Down Expand Up @@ -85,7 +81,9 @@ module.exports = class SessionState {

flushedLength () {
if (this.isDefault() || this.isSnapshot()) return this.length
return this.dependencyLength
const deps = this.storage.dependencies
if (deps.length) return deps[deps.length - 1].length
return 0
}

unref () {
Expand Down Expand Up @@ -161,11 +159,8 @@ module.exports = class SessionState {
}

updateDependency (tx, length) {
const dependency = updateDependency(this, length)
if (dependency) {
this.dependencyLength = dependency.length
tx.setDependency(dependency)
}
const dependency = updateDependency(this, length, false)
if (dependency) tx.setDependency(dependency)

return dependency
}
Expand Down Expand Up @@ -232,16 +227,19 @@ module.exports = class SessionState {
signature: this.signature
}

if (src.dependencyLength > this.dependencyLength) {
this.dependencyLength = src.dependencyLength
this.storage.updateDependencyLength(src.dependencyLength)
const rx = src.storage.read()
const dependencyPromise = rx.getDependency()

rx.tryFlush()

const dependency = await dependencyPromise
if (dependency && dependency.length > this.flushedLength()) {
this.storage.updateDependencyLength(dependency.length, false, true)
}

const truncated = (bitfield && bitfield.truncated !== -1)
? bitfield.truncated
: src.dependencyLength
const truncated = bitfield ? bitfield.truncated : -1

if (truncated < currLength) {
if (truncated !== -1 && truncated < currLength) {
this.ontruncate(tree, truncated, currLength, true)
if (!bitfield || bitfield.length === 0) return
}
Expand Down Expand Up @@ -351,7 +349,7 @@ module.exports = class SessionState {
this.roots = roots
this.signature = tree.signature

if (dependency) this.storage.updateDependencyLength(this.dependencyLength)
if (dependency) this.storage.updateDependencyLength(dependency.length, true)

this.ontruncate(tree, tree.length, batch.treeLength, flushed)
} finally {
Expand All @@ -376,7 +374,7 @@ module.exports = class SessionState {
this.roots = batch.roots
this.signature = batch.signature

if (dependency) this.storage.updateDependencyLength(this.dependencyLength)
if (dependency) this.storage.updateDependencyLength(dependency.length, true)

this.ontruncate(tree, batch.ancestors, batch.treeLength, flushed)
} finally {
Expand All @@ -399,9 +397,9 @@ module.exports = class SessionState {
if (tree) storage.setHead(tree)

const truncated = batch.length < this.flushedLength()
const dependency = truncated ? updateDependency(this, batch.length) : null
const dependency = truncated ? updateDependency(this, batch.length, true) : null

if (dependency) this.dependencyLength = dependency.length
if (dependency) storage.setDependency(dependency)

if (this.isDefault()) {
await storeBitfieldRange(this.storage, storage, batch.ancestors, batch.treeLength, false)
Expand All @@ -420,13 +418,11 @@ module.exports = class SessionState {

this.blocks.clear(tx, start, end)

const dependency = start < this.flushedLength() ? updateDependency(this, start) : null

if (dependency) this.dependencyLength = dependency.length
const dependency = start < this.flushedLength() ? updateDependency(this, start, true) : null

const flushed = await this.flush()

if (dependency) this.storage.updateDependencyLength(this.dependencyLength)
if (dependency) this.storage.updateDependencyLength(dependency.length, true)

// todo: atomic event handle
if (this.isDefault() && flushed) {
Expand Down Expand Up @@ -659,9 +655,7 @@ module.exports = class SessionState {

if (upgraded) tx.setHead(tree)

const dependency = isDependent ? updateDependency(this, length) : null

if (dependency) this.dependencyLength = dependency.length
const dependency = isDependent ? updateDependency(this, length, true) : null

const flushed = await this.flush()

Expand All @@ -670,7 +664,7 @@ module.exports = class SessionState {
this.length = length
this.signature = signature

if (dependency) this.storage.updateDependencyLength(this.dependencyLength)
if (dependency) this.storage.updateDependencyLength(dependency.length, true)

return { tree, flushed }
}
Expand Down Expand Up @@ -732,10 +726,7 @@ module.exports = class SessionState {

await state.flush(tx)

if (dependency) {
state.storage.updateDependencyLength(dependency.length)
state.dependencyLength = dependency.length
}
if (dependency) state.storage.updateDependencyLength(dependency.length, false)
}

const bitfield = { start: treeLength, length: length - treeLength, drop: false }
Expand Down Expand Up @@ -783,10 +774,6 @@ module.exports = class SessionState {
this.core = core
this.index = this.core.sessionStates.push(this) - 1

// storage was updated
const deps = this.storage.dependencies
this.dependencyLength = deps[deps.length - 1].length

for (let i = this.sessions.length - 1; i >= 0; i--) this.sessions[i].transferSession(this.core)
}

Expand Down Expand Up @@ -831,7 +818,7 @@ module.exports = class SessionState {
if (truncation) {
const { dependency, tree } = truncation

if (dependency) this.storage.updateDependencyLength(this.dependencyLength)
if (dependency) this.storage.updateDependencyLength(dependency.length, true)
this.ontruncate(tree, tree.length, treeLength, true)
}
}
Expand All @@ -848,20 +835,17 @@ module.exports = class SessionState {
}
}

async createSession (name, length, overwrite, atom) {
async createSession (name, overwrite, atom) {
let storage = null
let treeInfo = null

if (!atom && !overwrite && this.storage) {
storage = await this.storage.resumeSession(name)

if (storage !== null) {
treeInfo = (await getCoreHead(storage)) || getDefaultTree()
if (length !== -1 && treeInfo.length !== length) throw STORAGE_CONFLICT('Different batch stored here')
}
if (storage !== null) treeInfo = (await getCoreHead(storage)) || getDefaultTree()
}

if (length === -1) length = treeInfo ? treeInfo.length : this.length
const length = treeInfo ? treeInfo.length : this.length

if (storage === null) {
treeInfo = await this._getTreeHeadAt(length)
Expand Down Expand Up @@ -962,25 +946,16 @@ async function truncateAndFlush (s, length) {
}
}

function updateDependency (state, length) {
const dependency = findDependency(state.storage, length)
if (dependency === null) return null // skip default state and overlays of default
function updateDependency (state, length, truncated) {
const i = state.storage.findDependencyIndex(length, truncated)
if (i === -1) return null // skip default state and overlays of default

return {
dataPointer: dependency.dataPointer,
dataPointer: state.storage.dependencies[i].dataPointer,
length
}
}

function findDependency (storage, length) {
for (let i = storage.dependencies.length - 1; i >= 0; i--) {
const dep = storage.dependencies[i]
if (dep.length < length) return dep
}

return null
}

function getDefaultTree () {
return {
fork: 0,
Expand Down

0 comments on commit cc340d4

Please sign in to comment.