Skip to content
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e3f5828
commit acquires lock directly
chm-diederichs Oct 2, 2024
e42acdb
check conditions after acquiring lock
chm-diederichs Oct 7, 2024
e3279a4
update dependency in place and delete blocks
chm-diederichs Oct 8, 2024
081e489
memory overlay has head as dependency
chm-diederichs Oct 8, 2024
5d2b300
support snapshots
chm-diederichs Oct 9, 2024
e07c718
update dependency on truncate and clear if necessary
chm-diederichs Oct 9, 2024
d3fd4bc
add memory overlay test
chm-diederichs Oct 9, 2024
c9f1329
fix put
chm-diederichs Oct 9, 2024
48a392c
implement memory overlay block deletion
chm-diederichs Oct 9, 2024
be252c6
add memory overlay block deletion tests
chm-diederichs Oct 9, 2024
6f1d030
move tip list to abstraction and add tests
chm-diederichs Oct 9, 2024
8847def
treeNodes use tip list
chm-diederichs Oct 9, 2024
8892730
move memory overlay to hypercore-on-the-rocks
chm-diederichs Oct 10, 2024
dfe556e
rename peak to peek
chm-diederichs Oct 10, 2024
717fd18
use dependencies to compute flushed length
chm-diederichs Oct 18, 2024
a23a3ba
add overwrite option to commit
chm-diederichs Oct 18, 2024
4d53643
bit-interlude supports multiple deletions
chm-diederichs Oct 18, 2024
b5effbf
make core compat with bit interlude changes
chm-diederichs Oct 18, 2024
74db1ba
add explicit state overwrite method
chm-diederichs Oct 18, 2024
26b771e
memory overlay always has flushedLength as -1
chm-diederichs Oct 18, 2024
d418634
core.js commit method uses overwrite
chm-diederichs Oct 18, 2024
93d947f
commit writes data directly
chm-diederichs Oct 23, 2024
b92d09f
delete reconcile method
chm-diederichs Oct 23, 2024
65a18e5
copyPrologue uses bitfield constants
chm-diederichs Oct 23, 2024
a166e37
signature is verified against committed tree
chm-diederichs Oct 23, 2024
28afbcb
use flat-tree patch method
chm-diederichs Oct 26, 2024
c322b87
Merge branch 'rocksdb-commit-fill-tree' into rocksdb-commit-updates-d…
chm-diederichs Nov 12, 2024
fbe4a66
Merge branch 'rocksdb' into rocksdb-commit-updates-dependency
chm-diederichs Nov 12, 2024
8646195
snapshotLength is -1 for default
chm-diederichs Nov 12, 2024
f0136d8
review from @mafintosh
chm-diederichs Nov 12, 2024
0b154a4
only one call to splice
chm-diederichs Nov 12, 2024
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
5 changes: 4 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,10 @@ class Hypercore extends EventEmitter {

get flushedLength () {
if (this.opened === false) return 0
return this.state === this.core.state ? this.core.tree.length : this.state.treeLength
if (this.state === this.core.state) return this.core.tree.length
const flushed = this.state.flushedLength()

return flushed === -1 ? this.state.tree.length : flushed
}

/**
Expand Down
77 changes: 49 additions & 28 deletions lib/bit-interlude.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
const assert = require('nanoassert')
const b4a = require('b4a')
const quickbit = require('./compat').quickbit

module.exports = class BitInterlude {
constructor (bitfield) {
this.drop = false
this.bitfield = bitfield
this.ranges = []
}

contiguousLength (from) {
if (this.drop && this.ranges.length > 0 && this.ranges[0].start < from) {
return this.ranges[0].start
for (const r of this.ranges) {
if (r.start > from) break
if (!r.value && r.start <= from) return r.start
}

// TODO: be smarter
Expand All @@ -38,25 +37,35 @@ module.exports = class BitInterlude {
continue
}

return this.drop === false
return r.value
}

return this.bitfield.get(index)
}

setRange (start, end, value) {
assert(this.drop !== value || this.ranges.length === 0)
assert(value === true || this.ranges.length === 0)

this.drop = value === false
if (start === end) return

let r = null

for (let i = 0; i < this.ranges.length; i++) {
r = this.ranges[i]

// if already inside, stop
if (r.start <= start && end <= r.end) return
if (r.start <= start && end <= r.end) {
if (value === r.value) return

const lower = { start: r.start, end: start, value: r.value }
const upper = { start: end, end: r.end, value: r.value }

let remove = 1

if (lower.start < lower.end) this.ranges.splice(i++, remove--, lower)
this.ranges.splice(i++, remove, { start, end, value })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the ++ is sus to me, we use i again below but normally you'd i-- it as you are removing from the array

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only one of them removes from the array, but they all add to it, so it ends up being:

  arr = [0]
  arr.splice(i++, 1, 1)
  arr.splice(i++, 0, 2)
  arr.splice(i, 0, 3)

  // arr === [1, 2, 3]

if (upper.start < upper.end) this.ranges.splice(i, 0, upper)

return
}

// we wanna overun the interval
if (start > r.end) {
Expand All @@ -65,25 +74,32 @@ module.exports = class BitInterlude {

// we overran but this interval is ending after us, move it back
if (end >= r.start && end <= r.end) {
r.start = start
r.start = r.value === value ? start : end
if (r.value !== value) this.ranges.splice(i, 0, { start, end, value })
return
}

// we overran but our start is contained in this interval, move start back
if (start >= r.start && start <= r.end) {
if (r.value !== value) {
this.ranges.splice(++i, 0, { start, end, value })
r.end = start
return
}

start = r.start
}

let remove = 0

for (let j = i; j < this.ranges.length; j++) {
const n = this.ranges[j]
if (n.start > end) break
if (n.start > end || n.value !== value) break
if (n.start <= end && n.end > end) end = n.end
remove++
}

this.ranges.splice(i, remove, { start, end })
this.ranges.splice(i, remove, { start, end, value })
return
}

Expand All @@ -97,41 +113,49 @@ module.exports = class BitInterlude {
if (r.end > start) return
}

this.ranges.push({ start, end })
this.ranges.push({ start, end, value })
}

flush (writer, debug) {
if (!this.ranges.length) return { ranges: [], drop: this.drop }
if (!this.ranges.length) return []

let index = this.ranges[0].start
const final = this.ranges[this.ranges.length - 1].end

let i = 0

while (index < final) {
const page = this.bitfield.getPage(index, this.drop === false)
const buf = b4a.allocUnsafe(page.bitfield.byteLength)
const page = this.bitfield.getBitfield(index) // read only
const pageIndex = page ? page.index : this.bitfield.getPageIndex(index)

const buf = b4a.allocUnsafe(this.bitfield.getPageByteLength())

const view = new DataView(
buf.buffer,
buf.byteOffset,
buf.byteLength
)

for (let i = 0; i < page.bitfield.length; i++) {
view.setUint32(i * 4, page.bitfield[i], true)
if (page) {
for (let i = 0; i < page.bitfield.length; i++) {
view.setUint32(i * 4, page.bitfield[i], true)
}
}

const last = (page.index + 1) * (buf.byteLength << 3)
const offset = page.index * buf.byteLength << 3
const last = (pageIndex + 1) * (buf.byteLength << 3)
const offset = pageIndex * buf.byteLength << 3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add parens around the buf.. << 3 part


let hasValue = false

while (i < this.ranges.length) {
const { start, end } = this.ranges[i]
const { start, end, value } = this.ranges[i]

if (!hasValue && value) hasValue = true

const from = start < index ? index : start
const to = end < last ? end : last

quickbit.fill(buf, this.drop === false, from - offset, to - offset)
quickbit.fill(buf, value, from - offset, to - offset)

index = to

Expand All @@ -140,12 +164,9 @@ module.exports = class BitInterlude {
i++
}

writer.putBitfieldPage(page.index, buf)
if (page || hasValue) writer.putBitfieldPage(pageIndex, buf)
}

return {
ranges: this.ranges,
drop: this.drop
}
return this.ranges
}
}
24 changes: 17 additions & 7 deletions lib/bitfield.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ class BitfieldSegment {
}

module.exports = class Bitfield {
static BITS_PER_PAGE = BITS_PER_PAGE
static BYTES_PER_PAGE = BYTES_PER_PAGE

constructor (buffer) {
this.resumed = !!(buffer && buffer.byteLength >= 0)

Expand Down Expand Up @@ -239,8 +242,7 @@ module.exports = class Bitfield {
}

getBitfield (index) {
const j = index & (BITS_PER_PAGE - 1)
const i = (index - j) / BITS_PER_PAGE
const i = this.getPageIndex(index)

const p = this._pages.get(i)
return p || null
Expand Down Expand Up @@ -270,9 +272,17 @@ module.exports = class Bitfield {
return p ? p.get(j) : false
}

getPage (index, create) {
getPageByteLength () {
return BYTES_PER_PAGE
}

getPageIndex (index) {
const j = index & (BITS_PER_PAGE - 1)
const i = (index - j) / BITS_PER_PAGE
return (index - j) / BITS_PER_PAGE
}

getPage (index, create) {
const i = this.getPageIndex(index)

let p = this._pages.get(i)

Expand Down Expand Up @@ -453,9 +463,9 @@ module.exports = class Bitfield {
// })
// }

onupdate ({ ranges, drop }) {
for (const r of ranges) {
this.setRange(r.start, r.end - r.start, drop === false)
onupdate (ranges) {
for (const { start, end, value } of ranges) {
this.setRange(start, end - start, value)
}
}

Expand Down
5 changes: 3 additions & 2 deletions lib/copy-prologue.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const crypto = require('hypercore-crypto')
const flat = require('flat-tree')
const b4a = require('b4a')
const quickbit = require('quickbit-universal')
const Bitfield = require('./bitfield')

const MAX_BATCH_USED = 4 * 1024 * 1024
const MIN_BATCH_USED = 512 * 1024
Expand Down Expand Up @@ -192,11 +193,11 @@ function prologueToTree (prologue) {
}

function getBitfieldPage (index) {
return Math.floor(index / 32768)
return Math.floor(index / Bitfield.BITS_PER_PAGE)
}

function getBitfieldOffset (index) {
return index & 32767
return index & (Bitfield.BITS_PER_PAGE - 1)
}

function walkTree (stack, target, batch) {
Expand Down
Loading
Loading