From 90b7b01e9aa8f9e62f4d8482b0e4cb143e6480b0 Mon Sep 17 00:00:00 2001 From: Kevin Jahns <kevin.jahns@rwth-aachen.de> Date: Fri, 22 Apr 2016 22:09:49 +0100 Subject: [PATCH] fixes #49 --- src/Connector.js | 1 - src/Database.js | 97 ++++++++++++++++++++-------------------------- src/Struct.js | 27 +++++-------- src/Transaction.js | 6 +-- src/Utils.js | 9 +++-- 5 files changed, 58 insertions(+), 82 deletions(-) diff --git a/src/Connector.js b/src/Connector.js index 37726bca..26846dac 100644 --- a/src/Connector.js +++ b/src/Connector.js @@ -225,7 +225,6 @@ module.exports = function (Y/* :any */) { return } if (message.type === 'sync step 1') { - // TODO: make transaction, stream the ops let conn = this let m = message this.y.db.requestTransaction(function *() { diff --git a/src/Database.js b/src/Database.js index 2ff87f6b..90ede86c 100644 --- a/src/Database.js +++ b/src/Database.js @@ -80,8 +80,7 @@ module.exports = function (Y /* :any */) { return os.whenTransactionsFinished().then(function () { if (os.gc1.length > 0 || os.gc2.length > 0) { if (!os.y.isConnected()) { - debugger - console.log('gc should be empty when disconnected!') + console.warn('gc should be empty when disconnected!') } return new Promise((resolve) => { os.requestTransaction(function * () { @@ -379,68 +378,54 @@ module.exports = function (Y /* :any */) { } // called by a transaction when an operation is added * operationAdded (transaction, op) { - if (op.struct === 'Delete') { - throw new Error('this section shouldnt be entered anymore!') - var target = yield* transaction.getOperation(op.target) - if (target != null) { - var type = transaction.store.initializedTypes[JSON.stringify(target.parent)] - if (type != null) { - yield* type._changed(transaction, { - struct: 'Delete', - target: op.target - }) - } - } - } else { - // increase SS - yield* transaction.updateState(op.id[0]) + // increase SS + yield* transaction.updateState(op.id[0]) - var opLen = op.content != null ? op.content.length : 1 - for (var i = 0; i < opLen; i++) { - // notify whenOperation listeners (by id) - var sid = JSON.stringify([op.id[0], op.id[1] + i]) - var l = this.listenersById[sid] - delete this.listenersById[sid] - - if (l != null) { - for (var key in l) { - var listener = l[key] - if (--listener.missing === 0) { - this.whenOperationsExist([], listener.op) - } + var opLen = op.content != null ? op.content.length : 1 + for (let i = 0; i < opLen; i++) { + // notify whenOperation listeners (by id) + var sid = JSON.stringify([op.id[0], op.id[1] + i]) + var l = this.listenersById[sid] + delete this.listenersById[sid] + + if (l != null) { + for (var key in l) { + var listener = l[key] + if (--listener.missing === 0) { + this.whenOperationsExist([], listener.op) } } } - var t = this.initializedTypes[JSON.stringify(op.parent)] + } + var t = this.initializedTypes[JSON.stringify(op.parent)] - // if parent is deleted, mark as gc'd and return - if (op.parent != null) { - var parentIsDeleted = yield* transaction.isDeleted(op.parent) - if (parentIsDeleted) { - yield* transaction.deleteList(op.id) - return - } + // if parent is deleted, mark as gc'd and return + if (op.parent != null) { + var parentIsDeleted = yield* transaction.isDeleted(op.parent) + if (parentIsDeleted) { + yield* transaction.deleteList(op.id) + return } + } - // notify parent, if it was instanciated as a custom type - if (t != null) { - let o = Y.utils.copyObject(op) - yield* t._changed(transaction, o) - } - if (!op.deleted) { - // Delete if DS says this is actually deleted - var len = op.content != null ? op.content.length : 1 - var startId = op.id // You must not use op.id in the following loop, because op will change when deleted - for (var i = 0; i < len; i++) { - var id = [startId[0], startId[1] + i] - var opIsDeleted = yield* transaction.isDeleted(id) - if (opIsDeleted) { - var delop = { - struct: 'Delete', - target: id - } - yield* this.tryExecute.call(transaction, delop) + // notify parent, if it was instanciated as a custom type + if (t != null) { + let o = Y.utils.copyObject(op) + yield* t._changed(transaction, o) + } + if (!op.deleted) { + // Delete if DS says this is actually deleted + var len = op.content != null ? op.content.length : 1 + var startId = op.id // You must not use op.id in the following loop, because op will change when deleted + for (let i = 0; i < len; i++) { + var id = [startId[0], startId[1] + i] + var opIsDeleted = yield* transaction.isDeleted(id) + if (opIsDeleted) { + var delop = { + struct: 'Delete', + target: id } + yield* this.tryExecute.call(transaction, delop) } } } diff --git a/src/Struct.js b/src/Struct.js index 82bed80a..fb9a60e8 100644 --- a/src/Struct.js +++ b/src/Struct.js @@ -126,11 +126,11 @@ module.exports = function (Y/* :any */) { */ execute: function * (op) { var i // loop counter - + // during this function some ops may get split into two pieces (e.g. with getInsertionCleanEnd) // We try to merge them later, if possible var tryToRemergeLater = [] - + if (op.origin != null) { // TODO: !== instead of != // we save in origin that op originates in it // we need that later when we eventually garbage collect origin (see transaction) @@ -165,13 +165,13 @@ module.exports = function (Y/* :any */) { start = startId == null ? null : yield* this.getOperation(startId) o = start } - + // make sure to split op.right if necessary (also add to tryCombineWithLeft) if (op.right != null) { tryToRemergeLater.push(op.right) yield* this.getInsertionCleanStart(op.right) } - + // handle conflicts while (true) { if (o != null && !Y.utils.compareIds(o.id, op.right)) { @@ -212,18 +212,11 @@ module.exports = function (Y/* :any */) { // reconnect left and set right of op if (op.left != null) { left = yield* this.getInsertion(op.left) - // TODO: remove false!! - if (false && op.content != null && left.content != null && left.id[0] === op.id[0] && left.id[1] + left.content.length === op.id[1] && left.originOf == null && left.deleted !== true && left.gc !== true) { - // extend left - left.content = left.content.concat(op.content) - op = left - } else { - // link left - op.right = left.right - left.right = op.id + // link left + op.right = left.right + left.right = op.id - yield* this.setOperation(left) - } + yield* this.setOperation(left) } else { // set op.right from parent, if necessary op.right = op.parentSub ? parent.map[op.parentSub] || null : parent.start @@ -266,9 +259,9 @@ module.exports = function (Y/* :any */) { yield* this.setOperation(parent) } } - + // try to merge original op.left and op.origin - for (var i = 0; i < tryToRemergeLater.length; i++) { + for (let i = 0; i < tryToRemergeLater.length; i++) { var m = yield* this.getOperation(tryToRemergeLater[i]) yield* this.tryCombineWithLeft(m) } diff --git a/src/Transaction.js b/src/Transaction.js index 4bf4eca4..b4790719 100644 --- a/src/Transaction.js +++ b/src/Transaction.js @@ -736,9 +736,7 @@ module.exports = function (Y/* :any */) { } if (this.store.forwardAppliedOperations) { var ops = [] - for (let c = del[1]; c < del[1] + del[2]; c++) { - ops.push({struct: 'Delete', target: [d[0], c]}) // TODO: implement Delete with deletion length! - } + ops.push({struct: 'Delete', target: [d[0], d[1]], length: del[2]}) this.store.y.connector.broadcastOps(ops) } } @@ -798,7 +796,7 @@ module.exports = function (Y/* :any */) { !op.gc && !op.deleted ) { // combine! - if (op.originOf != null){ + if (op.originOf != null) { left.originOf = op.originOf } else { delete left.originOf diff --git a/src/Utils.js b/src/Utils.js index f15ca718..d50b51ee 100644 --- a/src/Utils.js +++ b/src/Utils.js @@ -247,7 +247,7 @@ module.exports = function (Y /* : any*/) { return id1 === id2 } else { return id1[0] === id2[0] && id1[1] === id2[1] - } + } } Y.utils.compareIds = compareIds @@ -265,7 +265,7 @@ module.exports = function (Y /* : any*/) { } } Y.utils.matchesId = matchesId - + function getLastId (op) { if (op.content == null || op.content.length === 1) { return op.id @@ -298,8 +298,9 @@ module.exports = function (Y /* : any*/) { I tried to optimize this for performance, therefore no highlevel operations. */ class SmallLookupBuffer extends Store { - constructor () { - super(...arguments) + constructor (arg) { + // super(...arguments) -- do this when this is supported by stable nodejs + super(arg) this.writeBuffer = createEmptyOpsArray(5) this.readBuffer = createEmptyOpsArray(10) } -- GitLab