diff --git a/balancer.js b/balancer.js index 9cfc7e47..7592821b 100644 --- a/balancer.js +++ b/balancer.js @@ -271,7 +271,7 @@ Balancer.prototype.splitLeafAndUnlock = cadence(function (async, sheaf, address, offset = split.items.length - length index = offset - sheaf.splice(penultimate.page, penultimate.index + 1, 0, { + penultimate.page.splice(penultimate.index + 1, 0, { key: split.items[offset].key, heft: sheaf.serialize(split.items[offset].key, true).length, address: page.address @@ -282,7 +282,7 @@ Balancer.prototype.splitLeafAndUnlock = cadence(function (async, sheaf, address, ok(index < split.items.length) - sheaf.splice(page, page.items.length, 0, item) + page.splice(page.items.length, 0, item) index++ } @@ -292,7 +292,7 @@ Balancer.prototype.splitLeafAndUnlock = cadence(function (async, sheaf, address, key: page.items[0].key } }, function () { - sheaf.splice(split, offset, length) + split.splice(offset, length) script.rewriteLeaf(page) })() }, function () { @@ -357,9 +357,9 @@ Balancer.prototype.splitBranchAndUnlock = cadence(function (async, sheaf, addres var length = remainder-- > 0 ? records + 1 : records var offset = split.items.length - length - var cut = sheaf.splice(split, offset, length) + var cut = split.splice(offset, length) - sheaf.splice(parent.page, parent.index + 1, 0, { + parent.page.splice(parent.index + 1, 0, { key: cut[0].key, address: page.address, heft: cut[0].heft @@ -368,7 +368,7 @@ Balancer.prototype.splitBranchAndUnlock = cadence(function (async, sheaf, addres delete cut[0].key cut[0].heft = 0 - sheaf.splice(page, 0, 0, cut) + page.splice(0, 0, cut) } children.unshift(full.page) @@ -415,7 +415,7 @@ Balancer.prototype.drainRootAndUnlock = cadence(function (async, sheaf) { var length = remainder-- > 0 ? records + 1 : records var offset = root.items.length - length - var cut = sheaf.splice(root, offset, length) + var cut = root.splice(offset, length) lift.push({ key: cut[0].key, @@ -427,12 +427,12 @@ Balancer.prototype.drainRootAndUnlock = cadence(function (async, sheaf) { delete cut[0].key cut[0].heft = 0 - sheaf.splice(page, 0, 0, cut) + page.splice(0, 0, cut) } lift.reverse() - sheaf.splice(root, 0, 0, lift) + root.splice(0, 0, lift) children.forEach(function (page) { script.writeBranch(page) @@ -460,13 +460,13 @@ Balancer.prototype.exorcise = function (sheaf, pivot, page, corporal) { // todo: how is this not a race condition? I'm writing to the log, but I've // not updated the pivot page, not rewritten during `deleteGhosts`. - sheaf.splice(page, 0, 1, sheaf.splice(corporal, corporal.ghosts, 1)) + page.splice(0, 1, corporal.splice(corporal.ghosts, 1)) page.ghosts = 0 - var item = sheaf.splice(pivot.page, pivot.index, 1).shift() + var item = pivot.page.splice(pivot.index, 1).shift() item.key = page.items[0].key item.heft = page.items[0].heft - sheaf.splice(pivot.page, pivot.index, 0, item) + pivot.page.splice(pivot.index, 0, item) } Balancer.prototype.deleteGhost = cadence(function (async, sheaf, key) { @@ -623,19 +623,19 @@ Balancer.prototype.mergePagesAndUnlock = cadence(function ( }, function () { var index = parents.right.indexes[ancestor.address] - designation = sheaf.splice(ancestor, index, 1).shift() + designation = ancestor.splice(index, 1).shift() if (pivot.page.address != ancestor.address) { ok(!index, 'expected ancestor to be removed from zero index') ok(ancestor.items[index], 'expected ancestor to have right sibling') - designation = sheaf.splice(ancestor, index, 1).shift() - var hoist = sheaf.splice(pivot.page, pivot.index, 1).shift() - sheaf.splice(pivot.page, pivot.index, 0, { + designation = ancestor.splice(index, 1).shift() + var hoist = pivot.page.splice(pivot.index, 1).shift() + pivot.page.splice(pivot.index, 0, { key: designation.key, address: hoist.address, heft: designation.heft }) - sheaf.splice(ancestor, index, 0, { address: designation.address, heft: 0 }) + ancestor.splice(index, 0, { address: designation.address, heft: 0 }) } else{ ok(index, 'expected ancestor to be non-zero') } @@ -709,11 +709,11 @@ Balancer.prototype.mergeLeaves = function (sheaf, key, leftKey, unbalanced, ghos var loop = async(function () { if (index == count) return [ loop ] var item = leaves.right.page.items[index + ghosts] - sheaf.splice(leaves.left.page, leaves.left.page.items.length, 0, item) + leaves.left.page.splice(leaves.left.page.items.length, 0, item) index++ })() }, function () { - sheaf.splice(leaves.right.page, 0, leaves.right.page.items.length) + leaves.right.page.splice(0, leaves.right.page.items.length) if (leftKey) { leaves.referring.page.right.key = leaves.left.page.items[0].key script.rotate(leaves.referring.page) @@ -798,12 +798,12 @@ Balancer.prototype.mergeBranches = function (sheaf, key, heft, address, callback var merger = cadence(function (async, script, pages, ghosted) { ok(address == pages.right.page.address, 'unexpected address') - var cut = sheaf.splice(pages.right.page, 0, pages.right.page.items.length) + var cut = pages.right.page.splice(0, pages.right.page.items.length) cut[0].key = key cut[0].heft = heft - sheaf.splice(pages.left.page, pages.left.page.items.length, 0, cut) + pages.left.page.splice(pages.left.page.items.length, 0, cut) script.writeBranch(pages.left.page) @@ -831,11 +831,11 @@ Balancer.prototype.fillRoot = cadence(function (async, sheaf) { var cut ok(root.page.items.length == 1, 'only one address expected') - sheaf.splice(root.page, 0, root.page.items.length) + root.page.splice(0, root.page.items.length) - cut = sheaf.splice(child.page, 0, child.page.items.length) + cut = child.page.splice(0, child.page.items.length) - sheaf.splice(root.page, root.page.items.length, 0, cut) + root.page.splice(root.page.items.length, 0, cut) script.writeBranch(root.page) script.unlink(child.page) diff --git a/cursor.js b/cursor.js index f8f8f453..aefda9cf 100644 --- a/cursor.js +++ b/cursor.js @@ -117,7 +117,7 @@ Cursor.prototype.insert = function (record, key, index) { var length = this._appender.writeInsert(index, record) - this._sheaf.splice(this._page, index, 0, { + this._page.splice(index, 0, { key: key, record: record, heft: length @@ -140,7 +140,7 @@ Cursor.prototype.remove = function (index) { this._page.ghosts++ this.offset || this.offset++ } else { - this._sheaf.splice(this._page, index, 1) + this._page.splice(index, 1) } } diff --git a/locker.js b/locker.js index b713ae5c..1142f10e 100644 --- a/locker.js +++ b/locker.js @@ -30,6 +30,7 @@ Locker.prototype.lock = cadence(function (async, address, exclusive) { // todo: does there need to be differnt types anymore? page = this._sheaf.createPage(address % 2, address) cartridge.value.page = page + page.cartridge = cartridge locks.push(this._locks[address] = page.queue.createLock()) locks[0].exclude(async()) }, function () { @@ -64,7 +65,8 @@ Locker.prototype.lock = cadence(function (async, address, exclusive) { }) Locker.prototype.encache = function (page) { - this._magazine.hold(page.address, { page: page }) + var cartridge = this._magazine.hold(page.address, { page: page }) + page.cartridge = cartridge this._locks[page.address] = page.queue.createLock() this._locks[page.address].exclude(function () {}) return page diff --git a/page.js b/page.js new file mode 100644 index 00000000..4c5363b1 --- /dev/null +++ b/page.js @@ -0,0 +1,38 @@ +function Page (sheaf, address, modulus) { + if (address == null) { + while (sheaf.nextAddress % 2 !== modulus) sheaf.nextAddress++ + address = sheaf.nextAddress++ + } + this.address = address + this.entries = 0 + this.rotation = 0 + this.items = [] + this.queue = sheaf.sequester.createQueue() + this.cartridge = null + if (modulus === 1) { + this.right = { address: 0, key: null } + this.ghosts = 0 + } +} + +Page.prototype.splice = function (offset, length, insert) { + var items = this.items, cartridge = this.cartridge, heft, removals + + if (length) { + removals = items.splice(offset, length) + heft = removals.reduce(function (heft, item) { return heft + item.heft }, 0) + cartridge.adjustHeft(-heft) + } else { + removals = [] + } + + if (insert != null) { + if (! Array.isArray(insert)) insert = [ insert ] + heft = insert.reduce(function (heft, item) { return heft + item.heft }, 0) + cartridge.adjustHeft(heft) + items.splice.apply(items, [ offset, 0 ].concat(insert)) + } + return removals +} + +module.exports = Page diff --git a/player.js b/player.js index 580f0e1e..cb70275f 100644 --- a/player.js +++ b/player.js @@ -107,7 +107,7 @@ Player.prototype._play = function (sheaf, slice, start, page) { key: entry.body || null } if (entry.header[3] == 0 && page.ghosts) { - sheaf.splice(page, 0, 1) + page.splice(0, 1) page.ghosts = 0 } page.entries++ @@ -116,7 +116,7 @@ Player.prototype._play = function (sheaf, slice, start, page) { var index = header.index if (leaf) { if (index > 0) { - sheaf.splice(page, index - 1, 0, { + page.splice(index - 1, 0, { key: sheaf.extractor(entry.body), record: entry.body, heft: length @@ -125,7 +125,7 @@ Player.prototype._play = function (sheaf, slice, start, page) { ok(!page.ghosts, 'double ghosts') page.ghosts++ } else if (index < 0) { - sheaf.splice(page, -(index + 1), 1) + page.splice(-(index + 1), 1) } } else { var address = header.address, key = null, heft = 0 @@ -133,7 +133,7 @@ Player.prototype._play = function (sheaf, slice, start, page) { key = entry.body heft = length } - sheaf.splice(page, index - 1, 0, { + page.splice(index - 1, 0, { key: key, address: address, heft: heft }) } diff --git a/sheaf.js b/sheaf.js index ecfd100d..1955669b 100644 --- a/sheaf.js +++ b/sheaf.js @@ -8,6 +8,7 @@ require('cadence/loops') var Cache = require('magazine') var Locker = require('./locker') +var Page = require('./page') var Queue = require('./queue') var Script = require('./script') @@ -64,51 +65,10 @@ Sheaf.prototype.unbalanced = function (page, force) { } } -Sheaf.prototype.heft = function (page, s) { - this.magazine.get(page.address).adjustHeft(s) -} - -function Page (sheaf, address, modulus) { - if (address == null) { - while (sheaf.nextAddress % 2 !== modulus) sheaf.nextAddress++ - address = sheaf.nextAddress++ - } - this.address = address - this.entries = 0 - this.rotation = 0 - this.items = [] - this.queue = sheaf.sequester.createQueue() - if (modulus === 1) { - this.right = { address: 0, key: null } - this.ghosts = 0 - } -} - Sheaf.prototype.createPage = function (modulus, address) { return new Page(this, address, modulus) } -Sheaf.prototype.splice = function (page, offset, length, insert) { - ok(typeof page != 'string', 'page is string') - var items = page.items, heft, removals - - if (length) { - removals = items.splice(offset, length) - heft = removals.reduce(function (heft, item) { return heft + item.heft }, 0) - this.heft(page, -heft) - } else { - removals = [] - } - - if (insert != null) { - if (! Array.isArray(insert)) insert = [ insert ] - heft = insert.reduce(function (heft, item) { return heft + item.heft }, 0) - this.heft(page, heft) - items.splice.apply(items, [ offset, 0 ].concat(insert)) - } - return removals -} - Sheaf.prototype.createMagazine = function () { var magazine = this.cache.createMagazine() var dummy = magazine.hold(-2, { diff --git a/strata.js b/strata.js index c8460504..b11ee9da 100644 --- a/strata.js +++ b/strata.js @@ -61,7 +61,7 @@ Strata.prototype.create = cadence(function (async) { locker.unlock(leaf) }], function () { var script = this.sheaf.logger.createScript() - this.sheaf.splice(root, 0, 0, { address: leaf.address, heft: 0 }) + root.splice(0, 0, { address: leaf.address, heft: 0 }) script.writeBranch(root) script.rewriteLeaf(leaf) script.commit(async())