(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0 || this.store.gc2.length > 0) { console.warn('GC1|2 not empty!', this.store.gc1, this.store.gc2) } if (JSON.stringify(this.store.listenersById) !== '{}') { console.warn('listenersById not empty!') } if (JSON.stringify(this.store.listenersByIdExecuteNow) !== '[]') { console.warn('listenersByIdExecuteNow not empty!') } if (this.store.transactionInProgress) { console.warn('Transaction still in progress!') } }, true) } transact (makeGen) { var t = new Transaction(this) while (makeGen !== null) { var gen = makeGen.call(t) var res = gen.next() while (!res.done) { res = gen.next(res.value) } makeGen = this.getNextRequest() } } * destroy () { super.destroy() delete this.os delete this.ss delete this.ds } } Y.extend('memory', Database) } module.exports = extend if (typeof Y !== 'undefined') { extend(Y) } },{"./RedBlackTree.js":2}],2:[function(require,module,exports){ 'use strict' /* This file contains a not so fancy implemantion of a Red Black Tree. */ module.exports = function (Y) { class N { // A created node is always red! constructor (val) { this.val = val this.color = true this._left = null this._right = null this._parent = null if (val.id === null) { throw new Error('You must define id!') } } isRed () { return this.color } isBlack () { return !this.color } redden () { this.color = true; return this } blacken () { this.color = false; return this } get grandparent () { return this.parent.parent } get parent () { return this._parent } get sibling () { return (this === this.parent.left) ? this.parent.right : this.parent.left } get left () { return this._left } get right () { return this._right } set left (n) { if (n !== null) { n._parent = this } this._left = n } set right (n) { if (n !== null) { n._parent = this } this._right = n } rotateLeft (tree) { var parent = this.parent var newParent = this.right var newRight = this.right.left newParent.left = this this.right = newRight if (parent === null) { tree.root = newParent newParent._parent = null } else if (parent.left === this) { parent.left = newParent } else if (parent.right === this) { parent.right = newParent } else { throw new Error('The elements are wrongly connected!') } } next () { if (this.right !== null) { // search the most left node in the right tree var o = this.right while (o.left !== null) { o = o.left } return o } else { var p = this while (p.parent !== null && p !== p.parent.left) { p = p.parent } return p.parent } } prev () { if (this.left !== null) { // search the most right node in the left tree var o = this.left while (o.right !== null) { o = o.right } return o } else { var p = this while (p.parent !== null && p !== p.parent.right) { p = p.parent } return p.parent } } rotateRight (tree) { var parent = this.parent var newParent = this.left var newLeft = this.left.right newParent.right = this this.left = newLeft if (parent === null) { tree.root = newParent newParent._parent = null } else if (parent.left === this) { parent.left = newParent } else if (parent.right === this) { parent.right = newParent } else { throw new Error('The elements are wrongly connected!') } } getUncle () { // we can assume that grandparent exists when this is called! if (this.parent === this.parent.parent.left) { return this.parent.parent.right } else { return this.parent.parent.left } } } class RBTree { constructor () { this.root = null this.length = 0 } * findNext (id) { return yield* this.findWithLowerBound([id[0], id[1] + 1]) } * findPrev (id) { return yield* this.findWithUpperBound([id[0], id[1] - 1]) } findNodeWithLowerBound (from) { if (from === void 0) { throw new Error('You must define from!') } var o = this.root if (o === null) { return null } else { while (true) { if ((from === null || Y.utils.smaller(from, o.val.id)) && o.left !== null) { // o is included in the bound // try to find an element that is closer to the bound o = o.left } else if (from !== null && Y.utils.smaller(o.val.id, from)) { // o is not within the bound, maybe one of the right elements is.. if (o.right !== null) { o = o.right } else { // there is no right element. Search for the next bigger element, // this should be within the bounds return o.next() } } else { return o } } } } findNodeWithUpperBound (to) { if (to === void 0) { throw new Error('You must define from!') } var o = this.root if (o === null) { return null } else { while (true) { if ((to === null || Y.utils.smaller(o.val.id, to)) && o.right !== null) { // o is included in the bound // try to find an element that is closer to the bound o = o.right } else if (to !== null && Y.utils.smaller(to, o.val.id)) { // o is not within the bound, maybe one of the left elements is.. if (o.left !== null) { o = o.left } else { // there is no left element. Search for the prev smaller element, // this should be within the bounds return o.prev() } } else { return o } } } } * findWithLowerBound (from) { var n = this.findNodeWithLowerBound(from) return n == null ? null : n.val } * findWithUpperBound (to) { var n = this.findNodeWithUpperBound(to) return n == null ? null : n.val } * iterate (t, from, to, f) { var o = this.findNodeWithLowerBound(from) while (o !== null && (to === null || Y.utils.smaller(o.val.id, to) || Y.utils.compareIds(o.val.id, to))) { yield* f.call(t, o.val) o = o.next() } return true } * logTable (from, to, filter) { if (filter == null) { filter = function () { return true } } if (from == null) { from = null } if (to == null) { to = null } var os = [] yield* this.iterate(this, from, to, function * (o) { if (filter(o)) { var o_ = {} for (var key in o) { if (typeof o[key] === 'object') { o_[key] = JSON.stringify(o[key]) } else { o_[key] = o[key] } } os.push(o_) } }) if (console.table != null) { console.table(os) } } * find (id) { var n return (n = this.findNode(id)) ? n.val : null } findNode (id) { if (id == null || id.constructor !== Array) { throw new Error('Expect id to be an array!') } var o = this.root if (o === null) { return false } else { while (true) { if (o === null) { return false } if (Y.utils.smaller(id, o.val.id)) { o = o.left } else if (Y.utils.smaller(o.val.id, id)) { o = o.right } else { return o } } } } * delete (id) { if (id == null || id.constructor !== Array) { throw new Error('id is expected to be an Array!') } var d = this.findNode(id) if (d == null) { throw new Error('Element does not exist!') } this.length-- if (d.left !== null && d.right !== null) { // switch d with the greates element in the left subtree. // o should have at most one child. var o = d.left // find while (o.right !== null) { o = o.right } // switch d.val = o.val d = o } // d has at most one child // let n be the node that replaces d var isFakeChild var child = d.left || d.right if (child === null) { isFakeChild = true child = new N({id: 0}) child.blacken() d.right = child } else { isFakeChild = false } if (d.parent === null) { if (!isFakeChild) { this.root = child child.blacken() child._parent = null } else { this.root = null } return } else if (d.parent.left === d) { d.parent.left = child } else if (d.parent.right === d) { d.parent.right = child } else { throw new Error('Impossible!') } if (d.isBlack()) { if (child.isRed()) { child.blacken() } else { this._fixDelete(child) } } this.root.blacken() if (isFakeChild) { if (child.parent.left === child) { child.parent.left = null } else if (child.parent.right === child) { child.parent.right = null } else { throw new Error('Impossible #3') } } } _fixDelete (n) { function isBlack (node) { return node !== null ? node.isBlack() : true } function isRed (node) { return node !== null ? node.isRed() : false } if (n.parent === null) { // this can only be called after the first iteration of fixDelete. return } // d was already replaced by the child // d is not the root // d and child are black var sibling = n.sibling if (isRed(sibling)) { // make sibling the grandfather n.parent.redden() sibling.blacken() if (n === n.parent.left) { n.parent.rotateLeft(this) } else if (n === n.parent.right) { n.parent.rotateRight(this) } else { throw new Error('Impossible #2') } sibling = n.sibling } // parent, sibling, and children of n are black if (n.parent.isBlack() && sibling.isBlack() && isBlack(sibling.left) && isBlack(sibling.right) ) { sibling.redden() this._fixDelete(n.parent) } else if (n.parent.isRed() && sibling.isBlack() && isBlack(sibling.left) && isBlack(sibling.right) ) { sibling.redden() n.parent.blacken() } else { if (n === n.parent.left && sibling.isBlack() && isRed(sibling.left) && isBlack(sibling.right) ) { sibling.redden() sibling.left.blacken() sibling.rotateRight(this) sibling = n.sibling } else if (n === n.parent.right && sibling.isBlack() && isRed(sibling.right) && isBlack(sibling.left) ) { sibling.redden() sibling.right.blacken() sibling.rotateLeft(this) sibling = n.sibling } sibling.color = n.parent.color n.parent.blacken() if (n === n.parent.left) { sibling.right.blacken() n.parent.rotateLeft(this) } else { sibling.left.blacken() n.parent.rotateRight(this) } } } * put (v) { if (v == null || v.id == null || v.id.constructor !== Array) { throw new Error('v is expected to have an id property which is an Array!') } var node = new N(v) if (this.root !== null) { var p = this.root // p abbrev. parent while (true) { if (Y.utils.smaller(node.val.id, p.val.id)) { if (p.left === null) { p.left = node break } else { p = p.left } } else if (Y.utils.smaller(p.val.id, node.val.id)) { if (p.right === null) { p.right = node break } else { p = p.right } } else { p.val = node.val return p } } this._fixInsert(node) } else { this.root = node } this.length++ this.root.blacken() return node } _fixInsert (n) { if (n.parent === null) { n.blacken() return } else if (n.parent.isBlack()) { return } var uncle = n.getUncle() if (uncle !== null && uncle.isRed()) { // Note: parent: red, uncle: red n.parent.blacken() uncle.blacken() n.grandparent.redden() this._fixInsert(n.grandparent) } else { // Note: parent: red, uncle: black or null // Now we transform the tree in such a way that // either of these holds: // 1) grandparent.left.isRed // and grandparent.left.left.isRed // 2) grandparent.right.isRed // and grandparent.right.right.isRed if (n === n.parent.right && n.parent === n.grandparent.left) { n.parent.rotateLeft(this) // Since we rotated and want to use the previous // cases, we need to set n in such a way that // n.parent.isRed again n = n.left } else if (n === n.parent.left && n.parent === n.grandparent.right) { n.parent.rotateRight(this) // see above n = n.right } // Case 1) or 2) hold from here on. // Now traverse grandparent, make parent a black node // on the highest level which holds two red nodes. n.parent.blacken() n.grandparent.redden() if (n === n.parent.left) { // Case 1 n.grandparent.rotateRight(this) } else { // Case 2 n.grandparent.rotateLeft(this) } } } } Y.utils.RBTree = RBTree } },{}]},{},[1])