def func_turn_into_waldo_var(
        self,val,force_copy,active_event, host_uuid,new_peered,
        ext_args_array,new_multi_threaded):
        '''
        turn_into_waldo_var works for all non-function types.
        function-types require additional information (which arguments
        are and are not external) to populate their ext_args_array.
        This is passed in in this function.
        '''
        if isinstance(val,wVariables.WaldoFunctionVariable):
            if force_copy:
                # means that it was a WaldoVariable: just call its copy
                # method
                return val.copy(active_event,new_peered,new_multi_threaded)
            # otherwise, just return val
            return val
        elif hasattr(val,'__call__'):
            # python function
            pass
        #### DEBUG
        else:
            util.logger_assert(
                'incorrect type passed into func_turn_into_waldo_var')
        #### END DEBUG

        waldo_func = wVariables.WaldoFunctionVariable(
            'garbage',
            host_uuid,
            new_peered,
            val).set_external_args_array(ext_args_array)

        return waldo_func
Example #2
0
 def var_type():
     '''
     @returns {String} --- Each subtype of _ReferenceBase has a
     unique name.
     '''
     util.logger_assert(
         'var_type is pure virtual in _ReferenceBase.')
    def update_val_of_key_during_deserialize(
        self,invalid_listener,key,val):
        '''
        @param {Text,Number,TrueFalse} key --- The index of the
        internal map or list (if list, then key is just a number)

        @param {Anything} val --- Can be a python value or pointers to
        additional Waldo variables.

        Called when deserializing nested maps/lists.  See case 4 in
        the comments for the method
        waldoNetworkSerializer.deserialize_peered_object_into_variables.
        '''
        #### DEBUG
        # note only should be serializing and deserializing peered data
        if not self.peered:
            util.logger_assert(
                'Should not be updating value and version for a ' +
                'non-peered data item.')
        #### END DEBUG
        self._lock()
        self._add_invalid_listener(invalid_listener)
        dirty_element = self._dirty_map[invalid_listener.uuid]
        dirty_element.val[key] = val
        self._unlock()
Example #4
0
 def is_value_type(self):
     '''
     @returns {bool} --- True if the reference base points at a
     value type (Text, Bool, Number).  False otherwise.
     '''
     util.logger_assert(
         'is_value_type is pure virtual in _ReferenceBase.')
Example #5
0
    def call_func_obj(
        self,active_event,func_obj,*args):
        '''
        @param {wVariable.WaldoFunctionVariable} func_obj --- The
        wrapped function that we are calling.

        @param {*args} --- The actual arguments that get passed to the
        function.
        '''
        # {list} external_arg_list --- Each element is a number.
        # If a number is in this list, then that means that the
        # corresponding argument to func_obj is external and therefore
        # should not be de_waldo-ified.  If an argument does not have
        # its corresponding index in the array, then dewaldo-ify it.
        external_arg_list = func_obj.ext_args_array

        if external_arg_list == None:
            util.logger_assert(
                'No external arg array for function object')
        
        call_arg_list = []
        for counter in range(0,len(args)):
            to_append = args[counter]
            if counter not in external_arg_list:
                to_append = self.de_waldoify(to_append,active_event)

            call_arg_list.append(to_append)

            
        internal_func = func_obj.get_val(active_event)
        return internal_func(
            active_event.local_endpoint,*call_arg_list)
def create_new_variable_wrapper_from_serialized(
    host_uuid,serial_obj_named_tuple):
    '''
    @param {collections.namedtuple} serial_obj_named_tuple --- @see
    util._generate_serialization_named_tuple.  Should have elements
    var_name, var_type,var_data, version_obj_data.    

    When we are deserializing sequence local objects from messages
    sent from partner endpoint, we may not already have a
    waldoVariable to deserialize the variable into using
    deserialize_peered_object_into_variable.  In this case, we should
    first create a new _WaldoVariable to serialize into.

    This function takes a serial_obj_named_tuple, and returns a new
    variable with corresponding type to its var_type
    '''
    var_name = serial_obj_named_tuple.var_name
    var_type = serial_obj_named_tuple.var_type
    #### DEBUG: Testing whether got a valid type
    if var_type not in ReferenceTypeConstructorDict:
        util.logger_assert(
            'Error when in waldoNetworkSerializer.create_new_variable_' +
            'wrapper_from_serialized.  ' +
            'Unknown Waldo type requested for deserialization.')
    #### END DEBUG

    var_constructor = ReferenceTypeConstructorDict[var_type]
    if var_type == wVariables.WaldoUserStructVariable.var_type():
        # user structs require dict initializers.  for the time being,
        # it's okay to just write in an empt dict because we know we
        # will overwrite it anyways.
        return var_constructor(var_name,host_uuid,True,{})
        
    return var_constructor(var_name,host_uuid,True)
Example #7
0
    def __init__(self, filename, name, host_uuid, peered=False, init_val=None):
        self.filename = filename

        if peered:
            util.logger_assert("Cannot peer a file")

        WaldoTextVariable.__init__(self, name, host_uuid, False, init_val)
        self.flush_file(self.val)
Example #8
0
 def de_waldoify(self,invalid_listener):
     '''
     Returns a Python-ized version of this object accessed by the
     current invalid listener.  Eg., if it was a Waldo number that
     wrapped 2, then it just returns 2.  Lists, maps and strings
     are more complex.
     '''
     util.logger_assert(
         'de_waldoify is pure virtual in _ReferenceBase.')
Example #9
0
 def copy(self,invalid_listener,peered):
     '''
     Returns a deep copy of this object.  Useful when assigning
     to/from a peered variable.  Eg., if have a peered map of
     lists, any list that we assign into the map should be copied
     as peered first.  This way, avoid problem of sharing references.
     '''
     util.logger_assert(
         'copy is pure virtual in _ReferenceBase.')
    def add_to_delta_list(self,delta_to_add_to,current_internal_val,action_event):
        '''
        @param delta_to_add_to --- Either
        varStoreDeltas.SingleMapDelta or
        varStoreDeltas.SingleListDelta

        We log all operations on this variable 
        '''
        util.logger_assert(
            'Pure virutal add_to_delta_list in waldoReferenceContainerBase')
Example #11
0
    def __init__(self, name, host_uuid, peered=False, init_val=None):
        """
        @param {dict} init_val --- Required to be non-None.  Contains
        a mapping of names to WaldoVariables.  Each name corresponds
        to one of the variable fields in the struct.  
        """
        if not isinstance(init_val, dict):
            util.logger_assert("User structs must always have init_vals.  " + "Otherwise, not initializing struct data")

        WaldoMapVariable.__init__(self, name, host_uuid, peered, init_val)
Example #12
0
def _map_get_delete_key_incorporate_deltas(container_deleted_action):
    if container_deleted_action.HasField('deleted_key_text'):
        index_to_del_from = container_deleted_action.deleted_key_text
    elif container_deleted_action.HasField('deleted_key_num'):
        index_to_del_from = container_deleted_action.deleted_key_num
    elif container_deleted_action.HasField('deleted_key_tf'):
        index_to_del_from = container_deleted_action.deleted_key_tf
    #### DEBUG
    else:
        util.logger_assert('Error in delete: unknown key type.')
    #### END DEBUG

    return index_to_del_from
Example #13
0
def _map_get_add_key_incorporate_deltas(container_added_action):
    if container_added_action.HasField('added_key_text'):
        index_to_add_to = container_added_action.added_key_text
    elif container_added_action.HasField('added_key_num'):
        index_to_add_to = container_added_action.added_key_num
    elif container_added_action.HasField('added_key_tf'):
        index_to_add_to = container_added_action.added_key_tf
    #### DEBUG
    else:
        util.logger_assert('Unknown map index')
    #### END DEBUG

    return index_to_add_to
Example #14
0
    def add_var(self,unique_name,waldo_variable):
        '''
        @param {String} unique_name ---

        @param {_WaldoVariable} waldo_variable 
        '''
        #### DEBUG
        if self.get_var_if_exists(unique_name) != None:
            util.logger_assert(
                'Already had an entry for variable trying to ' +
                'insert into store.')
        #### END DEBUG
            
        self._name_to_var_map[unique_name] = waldo_variable
Example #15
0
    def serializable_var_tuple_for_network(
        self,parent_delta,var_name,invalid_listener,force):
        '''
        @see waldoReferenceBase.serializable_var_tuple_for_network
        '''
        self._lock()
        self._add_invalid_listener(invalid_listener)
        dirty_element = self._dirty_map[invalid_listener.uuid]
        self._unlock()

        version_obj = dirty_element.version_obj

        is_var_store = False
        if parent_delta.parent_type == VarStoreDeltas.VAR_STORE_DELTA:
            is_var_store = True
            struct_delta = parent_delta.struct_deltas.add()
        elif parent_delta.parent_type  == VarStoreDeltas.CONTAINER_WRITTEN:            
            struct_delta = parent_delta.what_written_map
        elif parent_delta.parent_type  == VarStoreDeltas.CONTAINER_ADDED:
            struct_delta = parent_delta.added_what_map
        elif parent_delta.parent_type == VarStoreDeltas.SUB_ELEMENT_ACTION:
            struct_delta = parent_delta.struct_delta
        else:
            util.logger_assert('Unexpected parent container type when serializing map')
            
        struct_delta.parent_type = VarStoreDeltas.STRUCT_CONTAINER
        struct_delta.var_name = var_name
        struct_delta.has_been_written = version_obj.has_been_written_since_last_message

        # reset has been written to
        written_since_last_message = version_obj.has_been_written_since_last_message
        version_obj.has_been_written_since_last_message = False

        
        var_data = dirty_element.val
        internal_has_been_written = var_data.serializable_var_tuple_for_network(
            struct_delta,'',invalid_listener,
            # must force the write when we have written a new value over list
            force or written_since_last_message)
        

        # FIXME: check to ensure that second part of condition will
        # still hide elements that do not change
        if (not internal_has_been_written) and is_var_store and (not written_since_last_message):
            # remove the newly added map delta because there were no
            # changes that it encoded
            del parent_delta.struct_deltas[-1]

        return internal_has_been_written or written_since_last_message or force
Example #16
0
    def call_func_obj(
        self,active_event,func_obj,*args):
        '''
        @param {wVariable.WaldoFunctionVariable} func_obj --- The
        wrapped function that we are calling.

        @param {*args} --- The actual arguments that get passed to the
        function.
        '''
        # {list} external_arg_list --- Each element is a number.
        # If a number is in this list, then that means that the
        # corresponding argument to func_obj is external and therefore
        # should not be de_waldo-ified.  If an argument does not have
        # its corresponding index in the array, then dewaldo-ify it.
        external_arg_list = func_obj.ext_args_array

        if external_arg_list == None:
            util.logger_assert(
                'No external arg array for function object')
        
        call_arg_list = []
        for counter in range(0,len(args)):
            to_append = args[counter]
            if counter not in external_arg_list:
                to_append = self.de_waldoify(to_append,active_event)

            call_arg_list.append(to_append)

        internal_func = func_obj.get_val(active_event)
        returned_val = internal_func(
            active_event.local_endpoint,*call_arg_list)

        if isinstance(returned_val,list):
            return wVariables.WaldoSingleThreadListVariable(
                'garbage', # actual name of variable isn't important
                active_event.local_endpoint._host_uuid,
                False, # not peered
                returned_val# used as initial value
                )

        elif isinstance(returned_val,dict):
            return wVariables.WaldoSingleThreadMapVariable(
                'garbage', # actual name of variable isn't important
                active_event.local_endpoint._host_uuid,
                False, # not peered
                returned_val# used as initial value
                )        
        
        return returned_val
 def update_version_obj_during_deserialize(
     self,invalid_listener,new_version_obj):
     '''
     @see update_val_of_key_during_deserialize
     '''
     #### DEBUG        
     # note only should be serializing and deserializing peered data
     if not self.peered:
         util.logger_assert(
             'Should not be updating value and version for a ' +
             'non-peered data item.')
     #### END DEBUG
     self._lock()
     self._add_invalid_listener(invalid_listener)
     dirty_element = self._dirty_map[invalid_listener.uuid]
     dirty_element.version_obj = new_version_obj
     self._unlock()
Example #18
0
    def get_for_iter(self,to_iter_over,active_event):
        '''
        When call for loop on Waldo variables, need to get item to
        iterate over
        '''

        if (isinstance(to_iter_over,dict) or
            isinstance(to_iter_over,list) or
            util.is_string(to_iter_over)):
            return iter(to_iter_over)

        if wVariables.is_non_ext_text_var(to_iter_over):
            return iter(to_iter_over.get_val(active_event))

        if wVariables.is_non_ext_map_var(to_iter_over):
            return iter(to_iter_over.get_val(active_event).get_keys(active_event))

        if wVariables.is_non_ext_list_var(to_iter_over):
            # FIXME: This is an inefficient way of reading all values
            # over list.
            to_return = []
            for i in range(0, to_iter_over.get_val(active_event).get_len(active_event)):
                to_append = to_iter_over.get_val(active_event).get_val_on_key(active_event,i)

                # The reason that we do this here is that in a for
                # loop, the operation we perform in the compiled code
                # immediately following the actual for header is
                # assign to another Waldo variable the variable being
                # held by to_append.  (We do this through a write_val
                # call.  write_val must take in InternalMaps or
                # InternalLists.  Therefore, get_val on the
                # WaldoList/WaldoMap first.  Note this is unnecessary
                # for all other for iterations because none of the
                # others possibly return a WaldoObject to iterate over.
                if (wVariables.is_non_ext_list_var(to_append) or
                    wVariables.is_non_ext_map_var(to_append)):
                    to_append = to_append.get_val(active_event)
                
                to_return.append(to_append)

            return iter(to_return)

        util.logger_assert(
            'Calling get_for_iter on an object that does not support iteration')
def get_constructed_obj(
    var_type,var_name,host_uuid,peered,init_data,invalidation_listener):
    '''
    @returns {WaldoReferenceObject} --- Either a wVariable or an
    InternalList or InternalMap.
    '''
    #### DEBUG
    if var_type not in ReferenceTypeConstructorDict:
        util.logger_assert(
            'Unknown variable type to deserialize')
    #### END DEBUG

    if var_type == wVariables.WaldoUserStructVariable.var_type():
        # we are constructing a user struct: in this case, init_data
        # will be an internal map.  can just deserialize the map into

        #### DEBUG
        if not isinstance(init_data,waldoInternalMap.InternalMap):
            util.logger_assert(
                'Must initialize user struct data with internal map')
        #### END DEBUG

        # FIXME: it is unclear if we just created an internal map for
        # no reason here.  maybe just serialize and deserialize
        # internal values of structs as dicts.
            
        # FIXME: it is gross that reaching into the internal map this
        # way.
        init_data._lock()
        if invalidation_listener.uuid not in init_data._dirty_map:
            new_init_data = init_data.val
        else:
            new_init_data = init_data._dirty_map[invalidation_listener.uuid].val
        init_data._unlock()
        init_data = new_init_data
        
    var_constructor = ReferenceTypeConstructorDict[var_type]
    
    if requires_name_arg_in_constructor(var_type):
        return var_constructor(var_name,host_uuid,peered,init_data)
    
    return var_constructor(host_uuid,peered,init_data)    
    def promote_multithreaded(self,peered):
        '''
        Whenever we assign a single threaded variable, A, into a
        multithreaded variable, B, we need to "promote" the single
        threaded variable to be a multithreaded variable.  This is so
        that reads/writes to A.B from multiple threads do not cause
        read-write conflicts.

        This method returns a multithreaded version of this variable
        containing the same data within it.

        Importantly, it does not genearte a new multithreaded version
        of itself each time.  This is to account for assigning the
        same single threaded variable to more than one multithreaded
        connection.
        '''

        util.logger_assert(
            'In Waldo single threaded container, promote_multithreaded ' +
            'is pure virtual.  Must overload.')
Example #21
0
    def __init__(self, name, host_uuid, peered=False, init_val=None):

        if peered:
            util.logger_assert("Function variables may not be peered")

        def _default_helper_func(*args, **kwargs):
            pass

        if init_val == None:
            init_val = _default_helper_func

        _WaldoVariable.__init__(self, name, host_uuid, peered, init_val)

        # {Array} --- Each element is an int.  When making a call to a
        # function object, the function object takes in arguments.
        # For non-externals, we de-waldoify these arguments.  However,
        # for external arguments, we do not.  If an argument is
        # supposed to be an external, then we just pass it through
        # directly
        self.ext_args_array = None
Example #22
0
    def handle_len(self,what_calling_len_on, active_event):
        '''
        Can support python lists, dicts, strings, or waldo lists, waldo maps,
        waldo texts.
        
        @returns {int}
        '''
        if (isinstance(what_calling_len_on, dict) or
            isinstance(what_calling_len_on, list) or
            util.is_string(what_calling_len_on)):
            return len(what_calling_len_on)

        if wVariables.is_non_ext_text_var(what_calling_len_on):
            return len(what_calling_len_on.get_val(active_event))


        if (wVariables.is_non_ext_list_var(what_calling_len_on) or
            wVariables.is_non_ext_map_var(what_calling_len_on)):
            return what_calling_len_on.get_val(active_event).get_len(active_event)

        util.logger_assert(
            'Calling len on an object that does not support the function')
Example #23
0
    def handle_in_check(self,lhs,rhs,active_event):
        '''
        Call has form:
            lhs in rhs
        
        rhs can have three basic types: it can be a list, a map, or a
        string.  That means that it can either be a WaldoMapVariable,
        a WaldoListVariable, a WaldoStringVariable, or a Python
        string.

        Instead of using static type inference at compile time to
        determine, for sake of development, just doing dynamic check
        to determine which type it is and do the in processing here.

        FIXME: it is faster to do the static checks with type
        inference, etc. at compile time rather than at run time.
        '''
        lhs_val = self.get_val_if_waldo(lhs,active_event)

        # handles Python string case
        if util.is_string(rhs):
        # if isinstance(rhs,basestring):
            return lhs_val in rhs

        elif isinstance(rhs,wVariables.WaldoTextVariable):
            return lhs_val in rhs.get_val(active_event)

        elif isinstance(rhs,wVariables.WaldoMapVariable):
            return rhs.get_val(active_event).contains_key_called(
                active_event,lhs_val)

        elif isinstance(rhs,wVariables.WaldoListVariable):
            return rhs.get_val(active_event).contains_val_called(
                active_event,lhs_val)

        util.logger_assert(
            'Error when calling in: unknown right hand side of expression')
Example #24
0
 def del_key(self, to_del):
     util.logger_assert("Cannot call del_key on list.  Use del_key_list instead.")
def deserialize_peered_object_into_variable(
    host_uuid,serial_obj_named_tuple,invalidation_listener,waldo_reference):
    '''
    @param {uuid} host_uuid --- The uuid of the host currently on.
    
    @param {collections.namedtuple} serial_obj_named_tuple --- @see
    util._generate_serialization_named_tuple.  Should have elements
    var_name, var_type,var_data, version_obj_data.    

    @param {_InvalidationListener} invalidation_listener --- The event
    that we are serializing to.

    @param {_ReferenceValue} waldo_reference --- We write the value
    and version found in serial_obj_named_tuple into the
    dirtymapelement corresponding to invalidation_listener in
    waldo_reference.  (Put another way, we try to append any changes
    that have happened to waldo_reference on the other endpoint to
    waldo_reference on this endpoint.)

    @returns {Nothing} --- Changes will be propagated through
    arguments.
    '''

    # FIXME: probably do not need "var_name"
    var_name = serial_obj_named_tuple.var_name

    serial_vobj = serial_obj_named_tuple.version_obj_data
    version_obj = RefVers.deserialize_version_obj_from_network_data(
        serial_vobj)

    var_type = serial_obj_named_tuple.var_type
    #### DEBUG: Testing whether got a valid type
    if var_type not in ReferenceTypeConstructorDict:
        util.logger_assert(
            'Error when in waldoNetworkSerializer.deserialize_peered_object' +
            '.  Unknown Waldo type requested for deserialization.')
    #### END DEBUG


    # var_data can either be a python value (string,bool,number) or a
    # python list/map or a SerializationHelperNamedTuple.  If it is a
    # list or map, it either has elements that are python values or it
    # has elements that are SerializationHelperNamedTuple-s.
    #
    # CASE 1: We have python values
    #   Put var_data directly into the dirty_map_element associated
    #   with invalidation_listener in waldo_reference.  Similarly copy
    #   over the version object.  (We cannot do this for
    #   SerializationHelperNamedTuples because these represent
    #   pointers to additional InternalMaps/Lists/Structs.  If we just
    #   copied over the values of these, then they would refer to
    #   different objects on the endpoint than they initially did.
    #   And we wouldn't be able to detect conflicts.)
    #
    # CASE 2: We have lists/maps of python values
    #   Do same as in Case 1.
    #
    # CASE 3: We have a single SerializationHelperNamedTuple
    #   This means that we are currently deserializing a
    #   WaldoVariable.  (One of the classes defined in wVariables.py.)
    #   There can be two cases for what happens.
    #   a: The WaldoVariable has not been written to.
    #      We want the changes to point to the same variable that we
    #      have been using.  Get the associated Waldo reference that
    #      waldo_reference points to and write the contents of the
    #      SerializationHelperNamedTuple into its dirty map element's
    #      val and version object.  This ensures that the changes that
    #      we are making will be made to the same waldo object on one
    #      endpoint as they were being made to the waldo object on the
    #      other endpoint.
    #   b: The WaldoVariable has been written to.
    #      What this means is that, at some point in this event, we
    #      re-defined the Waldo object that the peered variable was
    #      pointing to.  (Ie, we assigned the peered variable to
    #      another map/list/user struct.)  In this case, we should
    #      just do what we did in Case 1/Case 2.  We do NOT want our
    #      new changes to point to the same old reference.  We want
    #      them to point to a new reference.  
    #
    # CASE 4: We have a map/list of SerializationHelperNamedTuple-s
    #
    #  Here's why we need to keep track of whether each element was
    #  written to or read from.  Assume that we have a map of maps:
    #    Map(from: Text, to: Map(from: Text, to: Text)) m
    #
    #  It is important to distinguish:
    #     m['a'] = { 'other_a': 'other_a'}
    #  from
    #     m['a']['other_a'] = 'other_a' (assuming m['a'] is already defined)
    #  because if we have another operation
    #     m['a']['b'] = 'b'
    #  for the first case, there's a conflict, for the second they
    #  can execute in parallel
        
    # To determine whether written to or read from, use version_obj,
    # which will have type
    # waldoReferenceContainerBase._ReferenceContainerVersion.  For
    # each key within it that was written, added, or deleted, treat
    # the index similarly to 3b above.  For others, treat as 3a above.
        

    var_data = serial_obj_named_tuple.var_data
    if not isinstance(var_data,util._SerializationHelperNamedTuple):
        case1_or_case2 = True
        
        if isinstance(var_data,list):
            if ((len(var_data) != 0) and # it's fine to treat empty
                                         # lists as a list of python
                                         # values (instead of an empty
                                         # list of
                                         # SerHelperNamedTuple-s.
                                         # This is because we aren't
                                         # over-writing any pointed to
                                         # references by copying over
                                         # it.
                (isinstance(var_data[0],util._SerializationHelperNamedTuple))):
                case1_or_case2 = False
                
        if isinstance(var_data,dict):
            if ((len(var_data) != 0) and # see len comment in if
                                         # statement above.
                (isinstance(
                        next(iter(var_data.values())),
                        # var_data.itervalues().next(),
                        util._SerializationHelperNamedTuple))):
                case1_or_case2 = False

        if case1_or_case2:
            # CASE 1/2 above ... overwrite val and version object of
            # the variable's associated dirty map element.
            waldo_reference.update_version_and_val(
                invalidation_listener,version_obj,var_data)
            return
        
    else:
        # CASE 3 above: we have a single SerializationHelperNamedTuple
        # means that we must have a _ReferenceValue
        
        if not version_obj.has_been_written_to:
            # case 3a above
            nested_reference = waldo_reference.get_val(
                invalidation_listener)

            deserialize_peered_object_into_variable(
                host_uuid,var_data,invalidation_listener,nested_reference)
        else:
            # case 3b above
            
            # FIXME: It is correct to just create a new object here.
            # However, we do not necessarily need to create a new
            # object if we had written to the data object much earlier
            # in the event and have since updated both sides.  Could
            # incur a performance penalty doing this.

            new_obj = new_obj_from_serialized(
                host_uuid,var_data,invalidation_listener)

            waldo_reference.update_version_and_val(
                invalidation_listener,version_obj,new_obj)
            
        return

    # CASE 4 above: list/map of SerializationHelperNamedTuple-s
    
    # make it able to handle maps or lists.
    all_keys = range(0,len(var_data))
    if isinstance(var_data, dict):
        all_keys = list(var_data.keys())

    for key in all_keys:
        if ((key in version_obj.written_values_keys) or
            (key in version_obj.added_keys) or
            (key in version_obj.deleted_keys)):
            # handle same as 3b above

            # waldo_reference is an InternalMap/InternalDict and we
            # must notify it that this object has been
            # deleted/written/added
            new_obj = new_obj_from_serialized(
                host_uuid,var_data[key],invalidation_listener)
            waldo_reference.update_val_of_key_during_deserialize(
                invalidation_listener,key,new_obj)
        elif key in version_obj.read_values_keys:
            # only add others if have been read.  do not willy-nilly
            # add references.
            
            # handle same as 3a above...except getting val for target
            # key
            nested_reference = waldo_reference.get_val_on_key(
                invalidation_listener,key)
            # recurse
            deserialize_peered_object_into_variable(
                host_uuid,var_data[key],invalidation_listener,
                nested_reference)

    # remove any elements that may have been deleted by the other side
    if isinstance(var_data,dict):
        # it's a map.  look for keys that are not in all keys
        local_keys = waldo_reference.get_keys(invalidation_listener)
        for key in local_keys:
            if key not in all_keys:
                waldo_reference.del_key_called(invalidation_listener,key)
    if isinstance(var_data,list):
        if len(local_keys) > len(all_keys):
            # FIXME: if do something more intelligent about sliding
            # elements in the list down when they are not modified,
            # then may have to do something more intelligent than just
            # deleting off the end.
            num_times_to_delete = len(all_keys) - len(local_keys)
            for i in range(0,num_times_to_delete):
                # keep deleting the spot just beyond how long the list
                # should be.
                waldo_reference.del_key_called(
                    invalidation_listener,len(all_keys))
            
    # either way, reset the version obj of overall internal list/map
    waldo_reference.update_version_obj_during_deserialize(
        invalidation_listener,version_obj)
Example #26
0
 def get_keys(self, invalid_listener):
     util.logger_assert("Cannot call get_keys on a list")
Example #27
0
 def contains_key(self, invalid_listener, key):
     util.logger_assert("Cannot call contains_key on list")
Example #28
0
    def serializable_var_tuple_for_network(
        self,parent_delta,var_name,invalid_listener,force):
        '''
        The runtime automatically synchronizes data between both
        endpoints.  When one side has updated a peered variable, the
        other side needs to attempt to apply those changes before
        doing further work.  This method grabs the val and version
        object of the dirty element associated with invalid_listener.
        Using these data, plus var_name, it constructs a named tuple
        for serialization.  (@see
        util._generate_serialization_named_tuple)

        Note: if the val of this object is another Reference object,
        then we recursively keep generating named tuples and embed
        them in the one we return.

        Note: we only serialize peered data.  No other data gets sent
        over the network; therefore, it should not be serialized.

        @param {*Delta or VarStoreDeltas} parent_delta --- Append any
        message that we create here to this message.
        
        @param {String} var_name --- Both sides of the connection need
        to agree on a common name for the variable being serialized.
        This is to ensure that when the data are received by the other
        side we know which variable to put them into.  This value is
        only really necessary for the outermost wrapping of the named
        type tuple, but we pass it through anyways.

        @param {bool} force --- True if regardless of whether modified
        or not we should serialize.  False otherwise.  (We migth want
        to force for instance the first time we send sequence data.)
        
        @returns {bool} --- True if some subelement was modified,
        False otherwise.
        '''
        self._lock()
        self._add_invalid_listener(invalid_listener)
        dirty_element = self._dirty_map[invalid_listener.uuid]
        self._unlock()
        version_obj = dirty_element.version_obj

        # a val can either point to a waldo reference, a python value,
        # or a list/map of waldo references or a list/map of python
        # values.
        var_data = dirty_element.val

        
        if (not force) and (not version_obj.has_been_written_since_last_message):
            if (isinstance(var_data,numbers.Number) or
                util.is_string(var_data) or isinstance(var_data,bool)):
                # nothing to do because this value has not been
                # written.  NOTE: for list/dict types, must actually
                # go through to ensure no subelements were written.
                return False

        sub_element_modified = False
        if self.py_val_serialize(parent_delta,var_data,var_name):
            sub_element_modified = True
        
        elif isinstance(var_data,list):
            list_delta = parent_delta.internal_list_delta
            list_delta.parent_type = VarStoreDeltas.INTERNAL_LIST_CONTAINER

            if force:
                # perform each operation as a write...
                version_obj.add_all_data_to_delta_list(
                    list_delta,var_data,invalid_listener)
                sub_element_modified = True
            else:
                # if all subelements have not been modified, then we
                # do not need to keep track of these changes.
                # wVariable.waldoMap, wVariable.waldoList, or
                # wVariable.WaldoUserStruct will get rid of it later.
                sub_element_modified = version_obj.add_to_delta_list(
                    list_delta,var_data,invalid_listener)


        elif isinstance(var_data,dict):
            map_delta = parent_delta.internal_map_delta
            map_delta.parent_type = VarStoreDeltas.INTERNAL_MAP_CONTAINER

            if force:
                # perform each operation as a write...
                version_obj.add_all_data_to_delta_list(
                    map_delta,var_data,invalid_listener)
                sub_element_modified = True
            else:
                # if all subelements have not been modified, then we
                # do not need to keep track of these changes.
                # wVariable.waldoMap, wVariable.waldoList, or
                # wVariable.WaldoUserStruct will get rid of it later.
                sub_element_modified = version_obj.add_to_delta_list(
                    map_delta,var_data,invalid_listener)

                
        else:
            # creating deltas for cases where internal data are waldo
            # references.... should have been overridden in
            # wVariables.py
            util.logger_assert('Serializing unknown type.')

        version_obj.has_been_written_since_last_message = False
        return sub_element_modified
Example #29
0
 def modified(self,invalidation_listener):
     '''
     Returns True if the object has been modified, False otherwise.
     '''
     util.logger_assert(
         'modified is pure virtual in _ReferenceVersion class.')
Example #30
0
    def py_val_serialize(self,parent,var_data,var_name):
        '''
        @param {} parent --- Either a ContainerAction a VarStoreDeltas.

        FIXME: unclear if actually need var_name for all elements
        py_serialize-ing, or just py variables that are in the
        top-level.

        @returns {bool} --- True if var_data was a python value type
        and we put it into parent.  False otherwise.
        
        If is python value type, then adds a delta message to
        parent.  Otherwise, does nothing.
        '''
        is_value_type = False
        delta = None
        if isinstance(var_data, numbers.Number):
            # can only add a pure number to var store a holder or to
            # an added key
            if parent.parent_type == VarStoreDeltas.VAR_STORE_DELTA:
                delta = parent.num_deltas.add()
            elif parent.parent_type == VarStoreDeltas.CONTAINER_ADDED:
                parent.added_what_num = var_data
            elif parent.parent_type == VarStoreDeltas.CONTAINER_WRITTEN:
                parent.what_written_num = var_data
            #### DEBUG
            else:
                util.logger_assert('Unexpected parent type in py_serialize')
            #### END DEBUG
                
            is_value_type = True
            
        elif util.is_string(var_data):
            if parent.parent_type == VarStoreDeltas.VAR_STORE_DELTA:
                delta = parent.text_deltas.add()
            elif parent.parent_type == VarStoreDeltas.CONTAINER_ADDED:
                parent.added_what_text = var_data
            elif parent.parent_type == VarStoreDeltas.CONTAINER_WRITTEN:
                parent.what_written_text = var_data
                
            #### DEBUG
            else:
                util.logger_assert('Unexpected parent type in py_serialize')
            #### END DEBUG                
                
            is_value_type = True
            
        elif isinstance(var_data,bool):
            if parent.parent_type == VarStoreDeltas.VAR_STORE_DELTA:
                delta = parent.true_false_deltas.add()
            elif parent.parent_type == VarStoreDeltas.CONTAINER_ADDED:
                parent.added_what_tf = var_data
            elif parent.parent_type == VarStoreDeltas.CONTAINER_WRITTEN:
                parent.what_written_tf = var_data                
            #### DEBUG
            else:
                util.logger_assert('Unexpected parent type in py_serialize')
            #### END DEBUG                

                
            is_value_type = True

        if delta != None:
            # all value types have same format
            delta.var_name = var_name
            delta.var_data = var_data
            
        return is_value_type