implementing new insertion struct (unfinished)

This commit is contained in:
Kevin Jahns 2016-04-05 10:43:57 +01:00
parent fe75ed6208
commit 1c32067908
4 changed files with 114 additions and 28 deletions

View File

@ -25,7 +25,7 @@ g.g = g
g.YConcurrency_TestingMode = true g.YConcurrency_TestingMode = true
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000 jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000
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

@ -41,7 +41,8 @@ module.exports = function (Y/* :any */) {
}, },
Insert: { Insert: {
/* { /* {
content: any, content: [any],
opContent: Id,
id: Id, id: Id,
left: Id, left: Id,
origin: Id, origin: Id,
@ -96,13 +97,13 @@ module.exports = function (Y/* :any */) {
return 0 return 0
} else { } else {
var d = 0 var d = 0
var o = yield* this.getOperation(op.left) var o = yield* this.getInsertion(op.left)
while (!Y.utils.compareIds(op.origin, (o ? o.id : null))) { while (!Y.utils.compareIds(op.origin, (o ? o.id : null))) {
d++ d++
if (o.left == null) { if (o.left == null) {
break break
} else { } else {
o = yield* this.getOperation(o.left) o = yield* this.getInsertion(o.left)
} }
} }
return d return d
@ -130,7 +131,7 @@ module.exports = function (Y/* :any */) {
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)
var origin = yield* this.getOperation(op.origin) var origin = yield* this.getInsertionCleanEnd(op.origin)
if (origin.originOf == null) { if (origin.originOf == null) {
origin.originOf = [] origin.originOf = []
} }
@ -145,8 +146,8 @@ 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.getOperation(op.left) o = yield* this.getInsertionCleanEnd(op.left)
o = (o.right == null) ? null : yield* this.getOperation(o.right) o = (o.right == null) ? null : yield* this.getInsertionCleanStart(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
@ -175,7 +176,7 @@ module.exports = function (Y/* :any */) {
} }
i++ i++
if (o.right != null) { if (o.right != null) {
o = yield* this.getOperation(o.right) o = yield* this.getInsertionCleanStart(o.right)
} else { } else {
o = null o = null
} }
@ -194,15 +195,24 @@ 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.getOperation(op.left) left = yield* this.getOperation(op.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) {
// extend left
left.content = left.content.concat(op.content)
op = left
} else {
// link left
op.right = left.right op.right = left.right
left.right = op.id left.right = op.id
yield* this.setOperation(left) yield* this.setOperation(left)
}
} else { } else {
// 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
} }
// reconnect right // reconnect right
if (op.right != null) { if (op.right != null) {
// TODO: wanna connect right too?
right = yield* this.getOperation(op.right) right = yield* this.getOperation(op.right)
right.left = op.id right.left = op.id
@ -367,7 +377,7 @@ module.exports = function (Y/* :any */) {
if (res == null || res.deleted) { if (res == null || res.deleted) {
return void 0 return void 0
} else if (res.opContent == null) { } else if (res.opContent == null) {
return res.content return res.content[0]
} else { } else {
return yield* this.getType(res.opContent) return yield* this.getType(res.opContent)
} }

View File

@ -176,7 +176,7 @@ module.exports = function (Y/* :any */) {
Mark an operation as deleted, and add it to the GC, if possible. Mark an operation as deleted, and add it to the GC, if possible.
*/ */
* deleteOperation (targetId, preventCallType) /* :Generator<any, any, any> */ { * deleteOperation (targetId, preventCallType) /* :Generator<any, any, any> */ {
var target = yield* this.getOperation(targetId) var target = yield* this.getInsertionCleanStartEnd(targetId)
var callType = false var callType = false
if (target == null || !target.deleted) { if (target == null || !target.deleted) {
@ -751,11 +751,75 @@ module.exports = function (Y/* :any */) {
this.store.y.connector.broadcastOps([op]) this.store.y.connector.broadcastOps([op])
} }
} }
* getOperation (id/* :any */)/* :Transaction<any> */ { * getInsertion (id) {
var o = yield* this.os.find(id) var ins = yield* this.os.findWithUpperBound(id)
if (o != null || id[0] !== '_') { var len = ins.content != null ? ins.content.length : 1 // in case of opContent
return o if (ins != null && id[0] === ins.id[0] && id[1] < ins.id[1] + len) {
return ins
} else { } else {
return null
}
}
* getInsertionCleanStartEnd (id) {
yield* this.getInsertionCleanStart(id)
yield* this.getInsertionCleanEnd(id)
}
// Return an insertion such that id is the first element of content
// This function manipulates an operation, if necessary
* getInsertionCleanStart (id) {
var ins = yield* this.getInsertion(id)
if (ins != null) {
if (ins.id[1] === id[1]) {
return ins
} else {
var left = Y.utils.copyObject(ins)
ins.content = left.content.splice(ins.id[1] - id[1])
ins.id = id
ins.origin = left.id
left.originOf = [ins.id]
left.right = ins.id
ins.left = left.id
debugger // check
yield* this.setOperation(left)
yield* this.setOperation(ins)
return ins
}
} else {
return null
}
}
// Return an insertion such that id is the last element of content
// This function manipulates an operation, if necessary
* getInsertionCleanEnd (id) {
var ins = yield* this.getInsertion(id)
if (ins != null) {
if (ins.content == null || (ins.id[1] + ins.content.length - 1 === id[1])) {
return ins
} else {
var right = Y.utils.copyObject(ins)
right.content = ins.content.splice(-(ins.id[1] + ins.content.length - 1 - id[1])) // cut off remainder
right.id = [id[0], id[1] + 1]
right.origin = ins.id
ins.originOf = [right.id]
ins.right = right.id
right.left = ins.id
debugger // check
yield* this.setOperation(right)
yield* this.setOperation(ins)
return ins
}
} else {
return null
}
}
* getOperation (id/* :any */)/* :Transaction<any> */ {
if (id.length > 2) {
id = [id[0], id[1]]
}
var o = yield* this.os.find(id)
if (id[0] !== '_' || o != null) {
return o
} else { // type is string
// generate this operation? // generate this operation?
var comp = id[1].split('_') var comp = id[1].split('_')
if (comp.length > 1) { if (comp.length > 1) {
@ -770,7 +834,6 @@ module.exports = function (Y/* :any */) {
debugger // eslint-disable-line debugger // eslint-disable-line
return null return null
} }
return null
} }
} }
* removeOperation (id) { * removeOperation (id) {

View File

@ -249,12 +249,15 @@ module.exports = function (Y /* : any*/) {
} }
return false return false
} }
if (id1[0] === id2[0] && id1[1] === id2[1]) { if (id1[0] === id2[0]) {
var add1 = id1.length > 2 ? id1[2] : 0
var add2 = id2.length > 2 ? id2[2] : 0
if (id1[1] + add1 === id2[1] + add2) {
return true return true
} else {
return false
} }
} }
return false
}
Y.utils.compareIds = compareIds Y.utils.compareIds = compareIds
function createEmptyOpsArray (n) { function createEmptyOpsArray (n) {
@ -374,14 +377,24 @@ module.exports = function (Y /* : any*/) {
yield* this.flush() yield* this.flush()
yield* super.delete(id) yield* super.delete(id)
} }
* findWithLowerBound () { * findWithLowerBound (id) {
var o = yield* this.find(id)
if (o != null) {
return o
} else {
yield* this.flush() yield* this.flush()
return yield* super.findWithLowerBound.apply(this, arguments) return yield* super.findWithLowerBound.apply(this, arguments)
} }
* findWithUpperBound () { }
* findWithUpperBound (id) {
var o = yield* this.find(id)
if (o != null) {
return o
} else {
yield* this.flush() yield* this.flush()
return yield* super.findWithUpperBound.apply(this, arguments) return yield* super.findWithUpperBound.apply(this, arguments)
} }
}
* findNext () { * findNext () {
yield* this.flush() yield* this.flush()
return yield* super.findNext.apply(this, arguments) return yield* super.findNext.apply(this, arguments)