fixed first two random cases, (gc seems still to be an issue ..)

This commit is contained in:
Kevin Jahns 2016-04-21 18:04:46 +02:00
parent feae0d51bd
commit bffd130b92
3 changed files with 89 additions and 58 deletions

View File

@ -367,30 +367,7 @@ module.exports = function (Y /* :any */) {
yield* this.store.operationAdded(this, op) yield* this.store.operationAdded(this, op)
// if insertion, try to combine with left // if insertion, try to combine with left
if (op.left != null && yield* this.tryCombineWithLeft(op)
op.content != null &&
op.left[0] === op.id[0] &&
Y.utils.compareIds(op.left, op.origin)
) {
var left = yield* this.getInsertion(op.left)
if (left.content != null &&
left.id[1] + left.content.length === op.id[1] &&
left.originOf.length === 1 &&
!left.gc && !left.deleted &&
!op.gc && !op.deleted
) {
// combine!
if (op.originOf != null){
left.originOf = op.originOf
} else {
delete left.originOf
}
left.content = left.content.concat(op.content)
left.right = op.right
yield* this.os.delete(op.id)
yield* this.setOperation(left)
}
}
} }
} }
} }

View File

@ -124,9 +124,12 @@ module.exports = function (Y/* :any */) {
# case 3: $origin > $o.origin # case 3: $origin > $o.origin
# $this insert_position is to the left of $o (forever!) # $this insert_position is to the left of $o (forever!)
*/ */
execute: function *(op) { execute: function * (op) {
var i // loop counter var i // loop counter
var distanceToOrigin = i = yield* Struct.Insert.getDistanceToOrigin.call(this, op) // most cases: 0 (starts from 0)
// 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 != 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
@ -137,7 +140,11 @@ module.exports = function (Y/* :any */) {
} }
origin.originOf.push(op.id) origin.originOf.push(op.id)
yield* this.setOperation(origin) yield* this.setOperation(origin)
if (origin.right != null) {
tryToRemergeLater.push(origin.right)
}
} }
var distanceToOrigin = i = yield* Struct.Insert.getDistanceToOrigin.call(this, op) // most cases: 0 (starts from 0)
// now we begin to insert op in the list of insertions.. // now we begin to insert op in the list of insertions..
var o var o
@ -147,7 +154,11 @@ module.exports = function (Y/* :any */) {
// find o. o is the first conflicting operation // find o. o is the first conflicting operation
if (op.left != null) { if (op.left != null) {
o = yield* this.getInsertionCleanEnd(op.left) o = yield* this.getInsertionCleanEnd(op.left)
o = (o.right == null) ? null : yield* this.getInsertionCleanStart(o.right) if (!Y.utils.compareIds(op.left, op.origin) && o.right != null) {
// only if not added previously
tryToRemergeLater.push(o.right)
}
o = (o.right == null) ? null : yield* this.getOperation(o.right)
} else { // left == null } else { // left == null
parent = yield* this.getOperation(op.parent) parent = yield* this.getOperation(op.parent)
let startId = op.parentSub ? parent.map[op.parentSub] : parent.start let startId = op.parentSub ? parent.map[op.parentSub] : parent.start
@ -155,6 +166,12 @@ module.exports = function (Y/* :any */) {
o = start 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 // 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)) {
@ -176,7 +193,7 @@ module.exports = function (Y/* :any */) {
} }
i++ i++
if (o.right != null) { if (o.right != null) {
o = yield* this.getInsertionCleanStart(o.right) o = yield* this.getInsertion(o.right)
} else { } else {
o = null o = null
} }
@ -249,6 +266,12 @@ module.exports = function (Y/* :any */) {
yield* this.setOperation(parent) yield* this.setOperation(parent)
} }
} }
// try to merge original op.left and op.origin
for (var i = 0; i < tryToRemergeLater.length; i++) {
var m = yield* this.getOperation(tryToRemergeLater[i])
yield* this.tryCombineWithLeft(m)
}
} }
}, },
List: { List: {

View File

@ -421,38 +421,37 @@ module.exports = function (Y/* :any */) {
*/ */
* garbageCollectAfterSync () { * garbageCollectAfterSync () {
yield* this.os.iterate(this, null, null, function * (op) { yield* this.os.iterate(this, null, null, function * (op) {
var opLength = op.content != null ? op.content.length : 1
if (op.gc) { if (op.gc) {
this.store.gc1.push(op.id) delete op.gc
} else { yield* this.setOperation(op)
if (op.parent != null) { }
var parentDeleted = yield* this.isDeleted(op.parent) if (op.parent != null) {
if (parentDeleted) { var parentDeleted = yield* this.isDeleted(op.parent)
op.gc = true if (parentDeleted) {
if (!op.deleted) { op.gc = true
yield* this.markDeleted(op.id, opLength) if (!op.deleted) {
op.deleted = true yield* this.markDeleted(op.id, op.content != null ? op.content.length : 1)
if (op.opContent != null) { op.deleted = true
yield* this.deleteOperation(op.opContent) if (op.opContent != null) {
} yield* this.deleteOperation(op.opContent)
if (op.requires != null) { }
for (var i = 0; i < op.requires.length; i++) { if (op.requires != null) {
yield* this.deleteOperation(op.requires[i]) for (var i = 0; i < op.requires.length; i++) {
} yield* this.deleteOperation(op.requires[i])
} }
} }
yield* this.setOperation(op)
this.store.gc1.push(op.id)
return
} }
yield* this.setOperation(op)
this.store.gc1.push(op.id)
return
} }
if (op.deleted) { }
var left = null if (op.deleted) {
if (op.left != null) { var left = null
left = yield* this.getInsertion(op.left) if (op.left != null) {
} left = yield* this.getInsertion(op.left)
yield* this.store.addToGarbageCollector.call(this, op, left)
} }
yield* this.store.addToGarbageCollector.call(this, op, left)
} }
}) })
} }
@ -715,8 +714,11 @@ module.exports = function (Y/* :any */) {
var counter = del[1] + del[2] var counter = del[1] + del[2]
while (counter >= del[1]) { while (counter >= del[1]) {
var o = yield* this.os.findWithUpperBound([del[0], counter - 1]) var o = yield* this.os.findWithUpperBound([del[0], counter - 1])
if (o == null) {
break
}
var oLen = o.content != null ? o.content.length : 1 var oLen = o.content != null ? o.content.length : 1
if (o.id[0] !== del[0] || del[1] < o.id[1] + oLen) { if (o.id[0] !== del[0] || o.id[1] + oLen <= del[1]) {
// not in range // not in range
break break
} }
@ -728,8 +730,8 @@ module.exports = function (Y/* :any */) {
// overlaps left // overlaps left
o = yield* this.getInsertionCleanStart([del[0], del[1]]) o = yield* this.getInsertionCleanStart([del[0], del[1]])
} }
yield* this.garbageCollectOperation(o.id)
counter = o.id[1] counter = o.id[1]
yield* this.garbageCollectOperation(o.id)
} }
} }
} else { } else {
@ -796,6 +798,35 @@ module.exports = function (Y/* :any */) {
this.store.y.connector.broadcastOps([op]) this.store.y.connector.broadcastOps([op])
} }
} }
// if insertion, try to combine with left insertion (if both have content property)
* tryCombineWithLeft (op) {
if (
op != null &&
op.left != null &&
op.content != null &&
op.left[0] === op.id[0] &&
Y.utils.compareIds(op.left, op.origin)
) {
var left = yield* this.getInsertion(op.left)
if (left.content != null &&
left.id[1] + left.content.length === op.id[1] &&
left.originOf.length === 1 &&
!left.gc && !left.deleted &&
!op.gc && !op.deleted
) {
// combine!
if (op.originOf != null){
left.originOf = op.originOf
} else {
delete left.originOf
}
left.content = left.content.concat(op.content)
left.right = op.right
yield* this.os.delete(op.id)
yield* this.setOperation(left)
}
}
}
* getInsertion (id) { * getInsertion (id) {
var ins = yield* this.os.findWithUpperBound(id) var ins = yield* this.os.findWithUpperBound(id)
if (ins == null) { if (ins == null) {