b-tree
Version:
Async/Await I/O B-tree in pure JavaScript for Node.js.
96 lines (81 loc) • 2.77 kB
JavaScript
const assert = require('assert')
const Strata = { Error: require('./error') }
const find = require('./find')
class Cursor {
constructor (journalist, descent, key) {
this._entry = descent.entry
this.page = this._entry.value
this.found = descent.index >= 0
this.sought = key
this.index = descent.index < 0 ? ~descent.index : descent.index
this.items = this.page.items
this.ghosts = this.page.ghosts
this._journalist = journalist
this._promises = {}
}
// You must never use `indexOf` to scan backward for insert points, only to scan
// backward for reading. Actually, let's assume that scanning will operate
// directly on the `items` array and we're only going to use `indexOf` to search
// forward for insertion points, and only forward.
indexOf (key, index) {
if (this.page.deleted) {
return null
}
const comparator = this._journalist.comparator
index = find(comparator, this.page, key, index)
const unambiguous = -1 < index // <- TODO ?
|| ~ index < this.page.items.length
|| this.page.right == null
if (!unambiguous && comparator(key, page.right) >= 0) {
return null
}
return index
}
insert (value, key, index) {
Strata.Error.assert(
index > -1 &&
(
this.index > 0 ||
this.page.id == '0.1'
), 'invalid.insert.index', { index: this.index })
// Heft will be set when the record is serialized.
assert(key && value)
const record = { key: key, value: value, heft: 0 }
this._journalist.append({
id: this.page.id,
record: record,
header: { method: 'insert', index: index, key: key },
body: value
}, this._promises)
this.page.items.splice(index, 0, record)
}
remove (index) {
const ghost = this.page.id != '0.1' && index == 0
this._journalist.append({
id: this.page.id,
header: { method: 'delete', index: index },
body: null
}, this._promises)
if (ghost) {
this.page.ghosts++
this.ghosts++
} else {
const [ spliced ] = this.page.items.splice(index, 1)
this._entry.heft -= spliced.heft
}
}
async flush () {
const promises = []
for (let id in this._promises) {
promises.push(this._promises[id])
}
this._promises = {}
for (let promise of promises) {
await promise
}
}
release () {
this._entry.release()
}
}
module.exports = Cursor