Adding to HB is now handled by Operation.execute. engine changed. Currently fixing errors and working on memory menagement for large HB tables

This commit is contained in:
DadaMonad
2014-12-16 11:21:57 +00:00
parent 7696864841
commit 2cf899418a
64 changed files with 3013 additions and 10106 deletions

View File

@@ -19,22 +19,14 @@ module.exports = (HB)->
class Operation
#
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
# @see HistoryBuffer.getNextOperationIdentifier
# @param {Object} uid A unique identifier.
# If uid is undefined, a new uid will be created before at the end of the execution sequence
#
constructor: (uid)->
@is_deleted = false
@doSync = true
@garbage_collected = false
if not uid?
uid = HB.getNextOperationIdentifier()
if not uid.doSync?
uid.doSync = not isNaN(parseInt(uid.op_number))
{
'creator': @creator
'op_number' : @op_number
'doSync' : @doSync
} = uid
if uid?
@uid = uid
type: "Insert"
@@ -123,20 +115,28 @@ module.exports = (HB)->
# Computes a unique identifier (uid) that identifies this operation.
#
getUid: ()->
{ 'creator': @creator, 'op_number': @op_number , 'sync': @doSync}
@uid
dontSync: ()->
@doSync = false
#
# @private
# If not already done, set the uid
# Add this to the HB
# Notify the all the listeners.
#
execute: ()->
@is_executed = true
if not @uid?
# When this operation was created without a uid, then set it here.
# There is only one other place, where this can be done - before an Insertion
# is executed (because we need the creator_id)
@uid = HB.getNextOperationIdentifier()
HB.addOperation @
for l in execution_listener
l @_encode()
@
@
#
# @private
@@ -261,8 +261,6 @@ module.exports = (HB)->
# @param {Operation} prev_cl The predecessor of this operation in the complete-list (cl)
# @param {Operation} next_cl The successor of this operation in the complete-list (cl)
#
# @see HistoryBuffer.getNextOperationIdentifier
#
constructor: (uid, prev_cl, next_cl, origin)->
@saveOperation 'prev_cl', prev_cl
@saveOperation 'next_cl', next_cl
@@ -360,7 +358,7 @@ module.exports = (HB)->
# $o happened concurrently
if o.getDistanceToOrigin() is i
# case 1
if o.creator < @creator
if o.uid.creator < @uid.creator
@prev_cl = o
distance_to_origin = i + 1
else
@@ -465,8 +463,6 @@ module.exports = (HB)->
# @param {Operation} prev_cl The predecessor of this operation in the complete-list (cl)
# @param {Operation} next_cl The successor of this operation in the complete-list (cl)
#
# @see HistoryBuffer.getNextOperationIdentifier
#
constructor: (uid, prev_cl, next_cl, origin)->
@saveOperation 'prev_cl', prev_cl
@saveOperation 'next_cl', next_cl
@@ -504,10 +500,10 @@ module.exports = (HB)->
else if @prev_cl? and not @prev_cl.next_cl?
delete @prev_cl.unchecked.next_cl
@prev_cl.next_cl = @
else if @prev_cl? or @next_cl?
else if @prev_cl? or @next_cl? or true # TODO: are you sure? This can happen right?
super
else
throw new Error "Delimiter is unsufficient defined!"
#else
# throw new Error "Delimiter is unsufficient defined!"
#
# @private

View File

@@ -98,19 +98,6 @@ module.exports = (HB)->
#
class JsonType extends types.MapManager
#
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
# @param {Object} initial_value Create this operation with an initial value.
# @param {String|Boolean} Whether the initial_value should be created as mutable. (Optional - see setMutableDefault)
#
constructor: (uid, initial_value, mutable)->
super uid
if initial_value?
if typeof initial_value isnt "object"
throw new Error "The initial value of JsonTypes must be of type Object! (current type: #{typeof initial_value})"
for name,o of initial_value
@val name, o, mutable
#
# Identifies this class.
# Use it to check whether this is a json-type or something else.
@@ -158,7 +145,7 @@ module.exports = (HB)->
# this event is not created by Yatta.
that.val(event.name, event.object[event.name])
that.on 'change', (event_name, property_name, op)->
if this is that and op.creator isnt HB.getUserId()
if this is that and op.uid.creator isnt HB.getUserId()
notifier = Object.getNotifier(that.bound_json)
oldVal = that.bound_json[property_name]
if oldVal?
@@ -170,7 +157,7 @@ module.exports = (HB)->
type: 'update'
name: property_name
oldValue: oldVal
changed_by: op.creator
changed_by: op.uid.creator
else
notifier.performChange 'add', ()->
that.bound_json[property_name] = that.val(property_name)
@@ -180,7 +167,7 @@ module.exports = (HB)->
type: 'add'
name: property_name
oldValue: oldVal
changed_by: op.creator
changed_by: op.uid.creator
@bound_json
#
@@ -236,11 +223,13 @@ module.exports = (HB)->
#
val: (name, content, mutable)->
if typeof name is 'object'
# Special case. First argument is an object. Then the second arg is mutable.
# Special case. First argument is an object. Then the second arg is mutable.
# (I refer to var name and content here)
# Keep that in mind when reading the following..
json = new JsonType undefined, name, content
HB.addOperation(json).execute()
@replace_manager.replace json
jt = new JsonType()
@replace_manager.replace jt.execute()
for n,o of name
jt.val n, o, mutable
@
else if name? and arguments.length > 1
if mutable?
@@ -253,15 +242,16 @@ module.exports = (HB)->
if typeof content is 'function'
@ # Just do nothing
else if (not content?) or (((not mutable) or typeof content is 'number') and content.constructor isnt Object)
obj = HB.addOperation(new types.ImmutableObject undefined, content).execute()
super name, obj
super name, (new types.ImmutableObject undefined, content).execute()
else
if typeof content is 'string'
word = HB.addOperation(new types.WordType undefined).execute()
word = (new types.WordType undefined).execute()
word.insertText 0, content
super name, word
else if content.constructor is Object
json = HB.addOperation(new JsonType undefined, content, mutable).execute()
json = new JsonType().execute()
for n,o of content
json.val n, o, mutable
super name, json
else
throw new Error "You must not set #{typeof content}-types in collaborative Json-objects!"

View File

@@ -34,7 +34,13 @@ module.exports = (HB)->
val: (name, content)->
if content?
if not @map[name]?
HB.addOperation(new AddName undefined, @, name).execute()
(new AddName undefined, @, name).execute()
## TODO: del this
if @map[name] == null
qqq = @
x = new AddName undefined, @, name
x.execute()
## endtodo
@map[name].replace content
@
else if name?
@@ -88,16 +94,23 @@ module.exports = (HB)->
if not @validateSavedOperations()
return false
else
uid_r = @map_manager.getUid()
# helper for cloning an object
clone = (o)->
p = {}
for name,value of o
p[name] = value
p
uid_r = clone(@map_manager.getUid())
uid_r.doSync = false
uid_r.op_number = "_#{uid_r.op_number}_RM_#{@name}"
if not HB.getOperation(uid_r)?
uid_beg = @map_manager.getUid()
uid_beg = clone(uid_r)
uid_beg.op_number = "_#{uid_beg.op_number}_RM_#{@name}_beginning"
uid_end = @map_manager.getUid()
uid_end = clone(uid_r)
uid_end.op_number = "_#{uid_end.op_number}_RM_#{@name}_end"
beg = HB.addOperation(new types.Delimiter uid_beg, undefined, uid_end).execute()
end = HB.addOperation(new types.Delimiter uid_end, beg, undefined).execute()
@map_manager.map[@name] = HB.addOperation(new ReplaceManager undefined, uid_r, beg, end)
beg = (new types.Delimiter uid_beg, undefined, uid_end).execute()
end = (new types.Delimiter uid_end, beg, undefined).execute()
@map_manager.map[@name] = new ReplaceManager undefined, uid_r, beg, end
@map_manager.map[@name].setParent @map_manager, @name
(@map_manager.map[@name].add_name_ops ?= []).push @
@map_manager.map[@name].execute()
@@ -138,8 +151,8 @@ module.exports = (HB)->
@saveOperation 'beginning', beginning
@saveOperation 'end', end
else
@beginning = HB.addOperation new types.Delimiter undefined, undefined, undefined
@end = HB.addOperation new types.Delimiter undefined, @beginning, undefined
@beginning = new types.Delimiter undefined, undefined, undefined
@end = new types.Delimiter undefined, @beginning, undefined
@beginning.next_cl = @end
@beginning.execute()
@end.execute()
@@ -240,8 +253,7 @@ module.exports = (HB)->
#
replace: (content, replaceable_uid)->
o = @getLastOperation()
op = new Replaceable content, @, replaceable_uid, o, o.next_cl
HB.addOperation(op).execute()
(new Replaceable content, @, replaceable_uid, o, o.next_cl).execute()
undefined
#

View File

@@ -23,7 +23,7 @@ module.exports = (HB)->
# @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.
#
constructor: (content, uid, prev, next, origin)->
if content?.creator?
if content?.uid?.creator
@saveOperation 'content', content
else
@content = content
@@ -140,13 +140,10 @@ module.exports = (HB)->
left = left.prev_cl # find the first character to the left, that is not deleted. Case position is 0, its the Delimiter.
right = left.next_cl
if content.type?
op = new TextInsert content, undefined, left, right
HB.addOperation(op).execute()
(new TextInsert content, undefined, left, right).execute()
else
for c in content
op = new TextInsert c, undefined, left, right
HB.addOperation(op).execute()
left = op
left = (new TextInsert c, undefined, left, right).execute()
@
#
# Inserts a string into the word.
@@ -171,7 +168,7 @@ module.exports = (HB)->
for i in [0...length]
if o instanceof types.Delimiter
break
d = HB.addOperation(new TextDelete undefined, o).execute()
d = (new TextDelete undefined, o).execute()
o = o.next_cl
while not (o instanceof types.Delimiter) and o.isDeleted()
o = o.next_cl
@@ -188,7 +185,7 @@ module.exports = (HB)->
# Can only be used if the ReplaceManager was set!
# @see WordType.setReplaceManager
if @replace_manager?
word = HB.addOperation(new WordType undefined).execute()
word = (new WordType undefined).execute()
word.insertText 0, text
@replace_manager.replace(word)
word