This commit is contained in:
Kevin Jahns 2016-04-22 22:09:49 +01:00
parent 895ec86ff6
commit 90b7b01e9a
5 changed files with 64 additions and 88 deletions

View File

@ -225,7 +225,6 @@ module.exports = function (Y/* :any */) {
return return
} }
if (message.type === 'sync step 1') { if (message.type === 'sync step 1') {
// TODO: make transaction, stream the ops
let conn = this let conn = this
let m = message let m = message
this.y.db.requestTransaction(function *() { this.y.db.requestTransaction(function *() {

View File

@ -80,8 +80,7 @@ module.exports = function (Y /* :any */) {
return os.whenTransactionsFinished().then(function () { return os.whenTransactionsFinished().then(function () {
if (os.gc1.length > 0 || os.gc2.length > 0) { if (os.gc1.length > 0 || os.gc2.length > 0) {
if (!os.y.isConnected()) { if (!os.y.isConnected()) {
debugger console.warn('gc should be empty when disconnected!')
console.log('gc should be empty when disconnected!')
} }
return new Promise((resolve) => { return new Promise((resolve) => {
os.requestTransaction(function * () { os.requestTransaction(function * () {
@ -379,68 +378,54 @@ module.exports = function (Y /* :any */) {
} }
// called by a transaction when an operation is added // called by a transaction when an operation is added
* operationAdded (transaction, op) { * operationAdded (transaction, op) {
if (op.struct === 'Delete') { // increase SS
throw new Error('this section shouldnt be entered anymore!') yield* transaction.updateState(op.id[0])
var target = yield* transaction.getOperation(op.target)
if (target != null) { var opLen = op.content != null ? op.content.length : 1
var type = transaction.store.initializedTypes[JSON.stringify(target.parent)] for (let i = 0; i < opLen; i++) {
if (type != null) { // notify whenOperation listeners (by id)
yield* type._changed(transaction, { 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)]
// 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 (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', struct: 'Delete',
target: op.target target: id
})
}
}
} else {
// 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 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
}
}
// 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)
} }
yield* this.tryExecute.call(transaction, delop)
} }
} }
} }

View File

@ -126,11 +126,11 @@ module.exports = function (Y/* :any */) {
*/ */
execute: function * (op) { execute: function * (op) {
var i // loop counter var i // loop counter
// during this function some ops may get split into two pieces (e.g. with getInsertionCleanEnd) // during this function some ops may get split into two pieces (e.g. with getInsertionCleanEnd)
// We try to merge them later, if possible // We try to merge them later, if possible
var tryToRemergeLater = [] var tryToRemergeLater = []
if (op.origin != null) { // TODO: !== instead of != if (op.origin != null) { // TODO: !== instead of !=
// we save in origin that op originates in it // we save in origin that op originates in it
// we need that later when we eventually garbage collect origin (see transaction) // 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) start = startId == null ? null : yield* this.getOperation(startId)
o = start o = start
} }
// make sure to split op.right if necessary (also add to tryCombineWithLeft) // make sure to split op.right if necessary (also add to tryCombineWithLeft)
if (op.right != null) { if (op.right != null) {
tryToRemergeLater.push(op.right) tryToRemergeLater.push(op.right)
yield* this.getInsertionCleanStart(op.right) yield* this.getInsertionCleanStart(op.right)
} }
// handle conflicts // handle conflicts
while (true) { while (true) {
if (o != null && !Y.utils.compareIds(o.id, op.right)) { 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 // reconnect left and set right of op
if (op.left != null) { if (op.left != null) {
left = yield* this.getInsertion(op.left) left = yield* this.getInsertion(op.left)
// TODO: remove false!! // link left
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) { op.right = left.right
// extend left left.right = op.id
left.content = left.content.concat(op.content)
op = left
} else {
// link left
op.right = left.right
left.right = op.id
yield* this.setOperation(left) yield* this.setOperation(left)
}
} else { } else {
// set op.right from parent, if necessary // set op.right from parent, if necessary
op.right = op.parentSub ? parent.map[op.parentSub] || null : parent.start op.right = op.parentSub ? parent.map[op.parentSub] || null : parent.start
@ -266,9 +259,9 @@ module.exports = function (Y/* :any */) {
yield* this.setOperation(parent) yield* this.setOperation(parent)
} }
} }
// try to merge original op.left and op.origin // 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]) var m = yield* this.getOperation(tryToRemergeLater[i])
yield* this.tryCombineWithLeft(m) yield* this.tryCombineWithLeft(m)
} }

View File

@ -736,9 +736,7 @@ module.exports = function (Y/* :any */) {
} }
if (this.store.forwardAppliedOperations) { if (this.store.forwardAppliedOperations) {
var ops = [] var ops = []
for (let c = del[1]; c < del[1] + del[2]; c++) { ops.push({struct: 'Delete', target: [d[0], d[1]], length: del[2]})
ops.push({struct: 'Delete', target: [d[0], c]}) // TODO: implement Delete with deletion length!
}
this.store.y.connector.broadcastOps(ops) this.store.y.connector.broadcastOps(ops)
} }
} }
@ -798,7 +796,7 @@ module.exports = function (Y/* :any */) {
!op.gc && !op.deleted !op.gc && !op.deleted
) { ) {
// combine! // combine!
if (op.originOf != null){ if (op.originOf != null) {
left.originOf = op.originOf left.originOf = op.originOf
} else { } else {
delete left.originOf delete left.originOf

View File

@ -247,7 +247,7 @@ module.exports = function (Y /* : any*/) {
return id1 === id2 return id1 === id2
} else { } else {
return id1[0] === id2[0] && id1[1] === id2[1] return id1[0] === id2[0] && id1[1] === id2[1]
} }
} }
Y.utils.compareIds = compareIds Y.utils.compareIds = compareIds
@ -265,7 +265,7 @@ module.exports = function (Y /* : any*/) {
} }
} }
Y.utils.matchesId = matchesId Y.utils.matchesId = matchesId
function getLastId (op) { function getLastId (op) {
if (op.content == null || op.content.length === 1) { if (op.content == null || op.content.length === 1) {
return op.id return op.id
@ -298,8 +298,9 @@ module.exports = function (Y /* : any*/) {
I tried to optimize this for performance, therefore no highlevel operations. I tried to optimize this for performance, therefore no highlevel operations.
*/ */
class SmallLookupBuffer extends Store { class SmallLookupBuffer extends Store {
constructor () { constructor (arg) {
super(...arguments) // super(...arguments) -- do this when this is supported by stable nodejs
super(arg)
this.writeBuffer = createEmptyOpsArray(5) this.writeBuffer = createEmptyOpsArray(5)
this.readBuffer = createEmptyOpsArray(10) this.readBuffer = createEmptyOpsArray(10)
} }