fixed some gc bugs, improved applyDeleteSet

This commit is contained in:
Kevin Jahns 2016-04-18 16:13:29 +02:00
parent 01031d27c3
commit 153ec811e2
4 changed files with 66 additions and 60 deletions

View File

@ -167,20 +167,28 @@ module.exports = function (Y /* :any */) {
returns true iff op was added to GC returns true iff op was added to GC
*/ */
addToGarbageCollector (op, left) { * addToGarbageCollector (op, left) {
if ( if (
op.gc == null && op.gc == null &&
op.deleted === true && op.deleted === true
this.y.connector.isSynced &&
left != null &&
left.deleted === true
) { ) {
op.gc = true var gc = false
this.gc1.push(op.id) if (left != null && left.deleted === true) {
return true gc = true
} else { } else if (op.content != null && op.content.length > 1) {
return false op = yield* this.getInsertionCleanStart([op.id[0], op.id[1] + 1])
gc = true
} }
if (gc) {
op.gc = true
yield* this.setOperation(op)
if (this.store.y.connector.isSynced) {
this.store.gc1.push(op.id)
}
return true
}
}
return false
} }
removeFromGarbageCollector (op) { removeFromGarbageCollector (op) {
function filter (o) { function filter (o) {

View File

@ -25,7 +25,7 @@ g.g = g
g.YConcurrency_TestingMode = true g.YConcurrency_TestingMode = true
jasmine.DEFAULT_TIMEOUT_INTERVAL = 50000 jasmine.DEFAULT_TIMEOUT_INTERVAL = 200000
g.describeManyTimes = function describeManyTimes (times, name, f) { g.describeManyTimes = function describeManyTimes (times, name, f) {
for (var i = 0; i < times; i++) { for (var i = 0; i < times; i++) {

View File

@ -233,10 +233,10 @@ module.exports = function (Y/* :any */) {
// is a child of a map struct. // is a child of a map struct.
// Then also make sure that only the most left element is not deleted // Then also make sure that only the most left element is not deleted
if (op.right != null) { if (op.right != null) {
yield* this.deleteOperation(op.right, true) yield* this.deleteOperation(op.right, 1)
} }
if (op.left != null) { if (op.left != null) {
yield* this.deleteOperation(op.id, true) yield* this.deleteOperation(op.id, 1)
} }
} else { } else {
if (right == null || left == null) { if (right == null || left == null) {

View File

@ -167,13 +167,6 @@ module.exports = function (Y/* :any */) {
} }
if (this.store.y.connector.isSynced) { if (this.store.y.connector.isSynced) {
this.store.gc1.push(start.id) this.store.gc1.push(start.id)
for (var i = 0; i < delLength; i++) {
if (i === 0) {
this.store.gc1.push(start.id)
} else {
this.store.gc1.push([start.id[0], start.id[1] + i])
}
}
} }
} }
start = start.right start = start.right
@ -248,8 +241,6 @@ module.exports = function (Y/* :any */) {
left = null left = null
} }
this.store.addToGarbageCollector(target, left)
// set here because it was deleted and/or gc'd // set here because it was deleted and/or gc'd
yield* this.setOperation(target) yield* this.setOperation(target)
@ -264,12 +255,6 @@ module.exports = function (Y/* :any */) {
} else { } else {
right = null right = null
} }
if (
right != null &&
this.store.addToGarbageCollector(right, target)
) {
yield* this.setOperation(right)
}
if (callType) { if (callType) {
var type = this.store.initializedTypes[JSON.stringify(target.parent)] var type = this.store.initializedTypes[JSON.stringify(target.parent)]
if (type != null) { if (type != null) {
@ -280,6 +265,11 @@ module.exports = function (Y/* :any */) {
}) })
} }
} }
// need to gc in the end!
yield* this.store.addToGarbageCollector.call(this, target, left)
if (right != null) {
yield* this.store.addToGarbageCollector.call(this, right, target)
}
} }
} }
} }
@ -288,6 +278,7 @@ module.exports = function (Y/* :any */) {
*/ */
* markGarbageCollected (id, len) { * markGarbageCollected (id, len) {
// this.mem.push(["gc", id]); // this.mem.push(["gc", id]);
this.store.addToDebug('yield* this.markGarbageCollected(', id, len, ')')
var n = yield* this.markDeleted(id, len) var n = yield* this.markDeleted(id, len)
if (n.id[1] < id[1] && !n.gc) { if (n.id[1] < id[1] && !n.gc) {
// un-extend left // un-extend left
@ -432,13 +423,7 @@ module.exports = function (Y/* :any */) {
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 var opLength = op.content != null ? op.content.length : 1
if (op.gc) { if (op.gc) {
for (var i = 0; i < opLength; i++) {
if (i === 0) {
this.store.gc1.push(op.id) this.store.gc1.push(op.id)
} else {
this.store.gc1.push([op.id[0], op.id[1] + i])
}
}
} else { } else {
if (op.parent != null) { if (op.parent != null) {
var parentDeleted = yield* this.isDeleted(op.parent) var parentDeleted = yield* this.isDeleted(op.parent)
@ -463,19 +448,16 @@ module.exports = function (Y/* :any */) {
} }
} }
yield* this.setOperation(op) yield* this.setOperation(op)
for (var i = 0; i < opLength; i++) {
if (i === 0) {
this.store.gc1.push(op.id) this.store.gc1.push(op.id)
} else {
this.store.gc1.push([op.id[0], op.id[1] + i])
}
}
return return
} }
} }
if (op.deleted && op.left != null) { if (op.deleted) {
var left = yield* this.getInsertion(op.left) var left = null
this.store.addToGarbageCollector(op, left) if (op.left != null) {
left = yield* this.getInsertion(op.left)
}
yield* this.store.addToGarbageCollector.call(this, op, left)
} }
} }
}) })
@ -491,17 +473,10 @@ module.exports = function (Y/* :any */) {
*/ */
* garbageCollectOperation (id) { * garbageCollectOperation (id) {
this.store.addToDebug('yield* this.garbageCollectOperation(', id, ')') this.store.addToDebug('yield* this.garbageCollectOperation(', id, ')')
var o = yield* this.getOperation(id) // TODO! like this? or rather cleanstartend var o = yield* this.getOperation(id)
yield* this.markGarbageCollected(id, (o != null && o.content != null) ? o.content.lengh : 1) // always mark gc'd yield* this.markGarbageCollected(id, (o != null && o.content != null) ? o.content.length : 1) // always mark gc'd
// if op exists, then clean that mess up.. // if op exists, then clean that mess up..
if (o != null) { if (o != null) {
/*
if (!o.deleted) {
yield* this.deleteOperation(id)
o = yield* this.getOperation(id)
}
*/
var deps = [] var deps = []
if (o.opContent != null) { if (o.opContent != null) {
deps.push(o.opContent) deps.push(o.opContent)
@ -736,12 +711,29 @@ module.exports = function (Y/* :any */) {
// always try to delete.. // always try to delete..
var state = yield* this.getState(del[0]) var state = yield* this.getState(del[0])
if (del[1] < state.clock) { if (del[1] < state.clock) {
for (let c = del[1]; c < del[1] + del[2]; c++) { yield* this.deleteOperation([del[0], del[1]], del[2])
var id = [del[0], c]
yield* this.deleteOperation(id)
if (del[3]) { if (del[3]) {
// gc // gc..
yield* this.garbageCollectOperation(id) yield* this.markGarbageCollected([del[0], del[1]], del[2]) // always mark gc'd
// remove operation..
var counter = del[1] + del[2]
while (counter >= del[1]) {
var o = yield* this.os.findWithUpperBound([del[0], counter - 1])
var oLen = o.content != null ? o.content.length : 1
if (o.id[0] !== del[0] || del[1] < o.id[1] + oLen) {
// not in range
break
}
if (o.id[1] + oLen > del[1] + del[2]) {
// overlaps right
o = yield* this.getInsertionCleanEnd([del[0], del[1] + del[2] - 1])
}
if (o.id[1] < del[1]) {
// overlaps left
o = yield* this.getInsertionCleanStart([del[0], del[1]])
}
yield* this.garbageCollectOperation(o.id)
counter = o.id[1]
} }
} }
} else { } else {
@ -844,6 +836,9 @@ module.exports = function (Y/* :any */) {
// debugger // check // debugger // check
yield* this.setOperation(left) yield* this.setOperation(left)
yield* this.setOperation(ins) yield* this.setOperation(ins)
if (left.gc) {
this.store.gc1.push(ins.id)
}
return ins return ins
} }
} else { } else {
@ -869,6 +864,9 @@ module.exports = function (Y/* :any */) {
// debugger // check // debugger // check
yield* this.setOperation(right) yield* this.setOperation(right)
yield* this.setOperation(ins) yield* this.setOperation(ins)
if (ins.gc) {
this.store.gc1.push(right.id)
}
return ins return ins
} }
} else { } else {