fixing double late join test fail

This commit is contained in:
DadaMonad 2015-02-17 19:23:27 +00:00
parent f609c22be8
commit 77b83cae2a
23 changed files with 225 additions and 166 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -10,7 +10,7 @@ adaptConnector = function(connector, engine, HB, execution_listener) {
}
connector.setIsBoundToY();
send_ = function(o) {
if ((o.uid.creator === HB.getUserId()) && (typeof o.uid.op_number !== "string") && (o.uid.doSync === "true" || o.uid.doSync === true) && (HB.getUserId() !== "_temp")) {
if ((o.uid.creator === HB.getUserId()) && (typeof o.uid.op_number !== "string") && (HB.getUserId() !== "_temp")) {
return connector.broadcast(o);
}
};

View File

@ -105,13 +105,13 @@ module.exports = {
/*
* Broadcast a message to all connected peers.
* @param message {Object} The message to broadcast.
*
#
broadcast: (message)->
throw new Error "You must implement broadcast!"
*
#
* Send a message to a peer, or set of peers
*
#
send: (peer_s, message)->
throw new Error "You must implement send!"
*/

View File

@ -13,9 +13,9 @@ if (typeof window !== "undefined" && window !== null) {
}
Engine = (function() {
function Engine(HB, types) {
this.HB = HB;
this.types = types;
function Engine(_at_HB, _at_types) {
this.HB = _at_HB;
this.types = _at_types;
this.unprocessed_ops = [];
}
@ -73,6 +73,7 @@ Engine = (function() {
op_json.fromHB = "true";
}
o = this.parseOperation(op_json);
o.parsed_from_json = op_json;
if (op_json.fromHB != null) {
o.fromHB = op_json.fromHB;
}

View File

@ -2,8 +2,8 @@ var HistoryBuffer,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
HistoryBuffer = (function() {
function HistoryBuffer(user_id) {
this.user_id = user_id;
function HistoryBuffer(_at_user_id) {
this.user_id = _at_user_id;
this.emptyGarbage = __bind(this.emptyGarbage, this);
this.operation_counter = {};
this.buffer = {};
@ -92,15 +92,14 @@ HistoryBuffer = (function() {
return this.garbageCollectTimeoutId = void 0;
};
HistoryBuffer.prototype.setGarbageCollectTimeout = function(garbageCollectTimeout) {
this.garbageCollectTimeout = garbageCollectTimeout;
HistoryBuffer.prototype.setGarbageCollectTimeout = function(_at_garbageCollectTimeout) {
this.garbageCollectTimeout = _at_garbageCollectTimeout;
};
HistoryBuffer.prototype.getReservedUniqueIdentifier = function() {
return {
creator: '_',
op_number: "_" + (this.reserved_identifier_counter++),
doSync: false
op_number: "_" + (this.reserved_identifier_counter++)
};
};
@ -143,9 +142,12 @@ HistoryBuffer = (function() {
_ref = this.buffer;
for (u_name in _ref) {
user = _ref[u_name];
if (u_name === "_") {
continue;
}
for (o_number in user) {
o = user[o_number];
if ((o.uid.noOperation == null) && o.uid.doSync && unknown(u_name, o_number)) {
if ((o.uid.noOperation == null) && unknown(u_name, o_number)) {
o_json = o._encode();
if (o.next_cl != null) {
o_next = o.next_cl;
@ -177,8 +179,7 @@ HistoryBuffer = (function() {
}
uid = {
'creator': user_id,
'op_number': this.operation_counter[user_id],
'doSync': true
'op_number': this.operation_counter[user_id]
};
this.operation_counter[user_id]++;
return uid;
@ -238,15 +239,18 @@ HistoryBuffer = (function() {
};
HistoryBuffer.prototype.addToCounter = function(o) {
if (this.operation_counter[o.uid.creator] == null) {
this.operation_counter[o.uid.creator] = 0;
var _base, _name;
if ((_base = this.operation_counter)[_name = o.uid.creator] == null) {
_base[_name] = 0;
}
if (typeof o.uid.op_number === 'number' && o.uid.creator !== this.getUserId()) {
if (o.uid.creator !== this.getUserId()) {
if (o.uid.op_number === this.operation_counter[o.uid.creator]) {
return this.operation_counter[o.uid.creator]++;
} else {
return this.invokeSync(o.uid.creator);
this.operation_counter[o.uid.creator]++;
}
while (this.buffer[o.uid.creator][this.operation_counter[o.uid.creator]] != null) {
this.operation_counter[o.uid.creator]++;
}
return void 0;
}
};

View File

@ -1,6 +1,6 @@
var __slice = [].slice,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__hasProp = {}.hasOwnProperty;
module.exports = function(HB) {
var execution_listener, types;
@ -79,8 +79,8 @@ module.exports = function(HB) {
return this.deleteAllObservers();
};
Operation.prototype.setParent = function(parent) {
this.parent = parent;
Operation.prototype.setParent = function(_at_parent) {
this.parent = _at_parent;
};
Operation.prototype.getParent = function() {
@ -95,7 +95,6 @@ module.exports = function(HB) {
if (this.uid.alt != null) {
map_uid = this.uid.alt.cloneUid();
map_uid.sub = this.uid.sub;
map_uid.doSync = false;
return map_uid;
} else {
return void 0;
@ -114,10 +113,6 @@ module.exports = function(HB) {
return uid;
};
Operation.prototype.dontSync = function() {
return this.uid.doSync = false;
};
Operation.prototype.execute = function() {
var l, _i, _len;
this.is_executed = true;
@ -135,7 +130,7 @@ module.exports = function(HB) {
};
Operation.prototype.saveOperation = function(name, op) {
if ((op != null ? op.execute : void 0) != null) {
if (((op != null ? op.execute : void 0) != null) || typeof op === "string") {
return this[name] = op;
} else if (op != null) {
if (this.unchecked == null) {
@ -296,6 +291,8 @@ module.exports = function(HB) {
this.prev_cl = this.parent.beginning;
}
if (this.origin == null) {
this.origin = this.prev_cl;
} else if (this.origin === "Delimiter") {
this.origin = this.parent.beginning;
}
if (this.next_cl == null) {
@ -389,8 +386,8 @@ module.exports = function(HB) {
types.ImmutableObject = (function(_super) {
__extends(ImmutableObject, _super);
function ImmutableObject(uid, content) {
this.content = content;
function ImmutableObject(uid, _at_content) {
this.content = _at_content;
ImmutableObject.__super__.constructor.call(this, uid);
}

View File

@ -1,6 +1,6 @@
var text_types_uninitialized,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__hasProp = {}.hasOwnProperty;
text_types_uninitialized = require("./TextTypes");

View File

@ -1,6 +1,6 @@
var basic_types_uninitialized,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__hasProp = {}.hasOwnProperty;
basic_types_uninitialized = require("./BasicTypes");
@ -159,9 +159,9 @@ module.exports = function(HB) {
types.ReplaceManager = (function(_super) {
__extends(ReplaceManager, _super);
function ReplaceManager(event_properties, event_this, uid, beginning, end) {
this.event_properties = event_properties;
this.event_this = event_this;
function ReplaceManager(_at_event_properties, _at_event_this, uid, beginning, end) {
this.event_properties = _at_event_properties;
this.event_this = _at_event_this;
if (this.event_properties['object'] == null) {
this.event_properties['object'] = this.event_this;
}
@ -326,10 +326,14 @@ module.exports = function(HB) {
'parent': this.parent.getUid(),
'prev': this.prev_cl.getUid(),
'next': this.next_cl.getUid(),
'origin': this.origin.getUid(),
'uid': this.getUid(),
'is_deleted': this.is_deleted
};
if (this.origin.type === "Delimiter") {
json.origin = "Delimiter";
} else if (this.origin !== this.prev_cl) {
json.origin = this.origin.getUid();
}
if (this.content instanceof types.Operation) {
json['content'] = this.content.getUid();
} else {

View File

@ -1,6 +1,6 @@
var structured_types_uninitialized,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__hasProp = {}.hasOwnProperty;
structured_types_uninitialized = require("./StructuredTypes");

View File

@ -1,6 +1,6 @@
var Engine, HistoryBuffer, adaptConnector, createY, json_types_uninitialized,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__hasProp = {}.hasOwnProperty;
json_types_uninitialized = require("./Types/JsonTypes");

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -76,8 +76,8 @@ gulp.task 'build_node', ->
gulp.task 'build', ['build_node', 'build_browser'], ->
gulp.task 'watch', ['build_browser'], ->
gulp.watch files.all, ['build_browser']
gulp.task 'watch', ['build'], ->
gulp.watch files.all, ['build']
gulp.task 'mocha', ->
gulp.src files.test, { read: false }

View File

@ -15,7 +15,6 @@ adaptConnector = (connector, engine, HB, execution_listener)->
send_ = (o)->
if (o.uid.creator is HB.getUserId()) and
(typeof o.uid.op_number isnt "string") and # TODO: i don't think that we need this anymore..
(o.uid.doSync is "true" or o.uid.doSync is true) and # TODO: ensure, that only true is valid
(HB.getUserId() isnt "_temp")
connector.broadcast o

View File

@ -66,9 +66,10 @@ class Engine
op_json_array = [op_json_array]
for op_json in op_json_array
if fromHB
op_json.fromHB = "true" # execute immediately, if
op_json.fromHB = "true" # execute immediately, if
# $parse_and_execute will return false if $o_json was parsed and executed, otherwise the parsed operadion
o = @parseOperation op_json
o.parsed_from_json = op_json
if op_json.fromHB?
o.fromHB = op_json.fromHB
# @HB.addOperation o

View File

@ -84,7 +84,6 @@ class HistoryBuffer
{
creator : '_'
op_number : "_#{@reserved_identifier_counter++}"
doSync: false
}
#
@ -116,8 +115,10 @@ class HistoryBuffer
for u_name,user of @buffer
# TODO next, if @state_vector[user] <= state_vector[user]
if u_name is "_"
continue
for o_number,o of user
if (not o.uid.noOperation?) and o.uid.doSync and unknown(u_name, o_number)
if (not o.uid.noOperation?) and unknown(u_name, o_number)
# its necessary to send it, and not known in state_vector
o_json = o._encode()
if o.next_cl? # applies for all ops but the most right delimiter!
@ -149,7 +150,6 @@ class HistoryBuffer
uid =
'creator' : user_id
'op_number' : @operation_counter[user_id]
'doSync' : true
@operation_counter[user_id]++
uid
@ -206,14 +206,14 @@ class HistoryBuffer
# Increment the operation_counter that defines the current state of the Engine.
#
addToCounter: (o)->
if not @operation_counter[o.uid.creator]?
@operation_counter[o.uid.creator] = 0
if typeof o.uid.op_number is 'number' and o.uid.creator isnt @getUserId()
@operation_counter[o.uid.creator] ?= 0
if o.uid.creator isnt @getUserId()
# TODO: check if operations are send in order
if o.uid.op_number is @operation_counter[o.uid.creator]
@operation_counter[o.uid.creator]++
else
@invokeSync o.uid.creator
while @buffer[o.uid.creator][@operation_counter[o.uid.creator]]?
@operation_counter[o.uid.creator]++
undefined
#if @operation_counter[o.uid.creator] isnt (o.uid.op_number + 1)
#console.log (@operation_counter[o.uid.creator] - (o.uid.op_number + 1))

View File

@ -114,7 +114,6 @@ module.exports = (HB)->
if @uid.alt? # could be (safely) undefined
map_uid = @uid.alt.cloneUid()
map_uid.sub = @uid.sub
map_uid.doSync = false
map_uid
else
undefined
@ -125,9 +124,6 @@ module.exports = (HB)->
uid[n] = v
uid
dontSync: ()->
@uid.doSync = false
#
# @private
# If not already done, set the uid
@ -172,8 +168,9 @@ module.exports = (HB)->
# We use duck-typing to check if op is instantiated since there
# could exist multiple classes of $Operation
#
if op?.execute?
# is instantiated
if op?.execute? or typeof op is "string"
# is instantiated, or op is string. Currently "Delimiter" is saved as string
# (in combination with @parent you can retrieve the delimiter..)
@[name] = op
else if op?
# not initialized. Do it when calling $validateSavedOperations()
@ -350,6 +347,8 @@ module.exports = (HB)->
if not @prev_cl?
@prev_cl = @parent.beginning
if not @origin?
@origin = @prev_cl
else if @origin is "Delimiter"
@origin = @parent.beginning
if not @next_cl?
@next_cl = @parent.end

View File

@ -320,10 +320,14 @@ module.exports = (HB)->
'parent' : @parent.getUid()
'prev': @prev_cl.getUid()
'next': @next_cl.getUid()
'origin' : @origin.getUid()
'uid' : @getUid()
'is_deleted': @is_deleted
}
if @origin.type is "Delimiter"
json.origin = "Delimiter"
else if @origin isnt @prev_cl
json.origin = @origin.getUid()
if @content instanceof types.Operation
json['content'] = @content.getUid()
else

View File

@ -36,7 +36,7 @@ class JsonTest extends Test
return root
elems = elems.filter (elem)->
(elem.type is "Array") or (elem.type is "Object")
elem? and ((elem.type is "Array") or (elem.type is "Object"))
if elems.length is 0
root
else
@ -110,10 +110,19 @@ describe "JsonFramework", ->
u2 = @yTest.users[1]
ops1 = u1.HB._encode()
ops2 = u2.HB._encode()
u1.HB.renewStateVector u2.HB.getOperationCounter()
u2.HB.renewStateVector u1.HB.getOperationCounter()
u1.engine.applyOps ops2
u2.engine.applyOps ops1
u1.engine.applyOp ops2, true
u2.engine.applyOp ops1, true
compare = (o1, o2)->
if o1.type? and o1.type isnt o2.type
throw new Error "different types"
else if o1.type is "Object"
for name, val of o1.val()
compare(val, o2.val(name))
else if o1.type?
compare(o1.val(), o2.val())
else if o1 isnt o2
throw new Error "different values"
compare u1, u2
expect(test.getContent(0)).to.deep.equal(@yTest.getContent(1))
it "can handle creaton of complex json (1)", ->

View File

@ -13,7 +13,7 @@ module.exports = class Test
constructor: (@name_suffix = "")->
@number_of_test_cases_multiplier = 1
@repeat_this = 3 * @number_of_test_cases_multiplier
@doSomething_amount = 123 * @number_of_test_cases_multiplier
@doSomething_amount = 1230 * @number_of_test_cases_multiplier
@number_of_engines = 5 + @number_of_test_cases_multiplier - 1
@time = 0 # denotes to the time when run was started
@ -36,7 +36,7 @@ module.exports = class Test
# is called by implementing class
makeNewUser: (user)->
user.HB.setManualGarbageCollect()
user.HB.stopGarbageCollection()
user
getSomeUser: ()->

File diff suppressed because one or more lines are too long

4
y.js

File diff suppressed because one or more lines are too long