예제 #1
0
    def session_detach(self):
        """
        Detach object from session, i.e. remove reference from current session provided to current object,
	    'dear garbage-collector, the current session is not using this object anymore'
        """
        getRuntime().detach_object_from_session(self.get_object_id(),
                                                self.get_hint())
예제 #2
0
 def _post_stealing(self, stolen_object):
     """Once an object has been stolen, perform the movement."""
     # FIXME: We should not assume that this is server-side
     from dataclay.commonruntime.Runtime import getRuntime
     from dataclay.commonruntime.Settings import settings
     getRuntime().move_object(stolen_object, settings.storage_id)
     return stolen_object
예제 #3
0
    def __get__(self, obj, type_=None):
        """Getter for the dataClay property

        If the object is loaded, perform the getter to the local instance (this
        is the scenario for local instances and Execution Environment fully
        loaded instances).

        If the object is not loaded, perform a remote execution (this is the
        scenario for client remote instances and also Execution Environment
        non-loaded instances, which may either "not-yet-loaded" or remote)
        """
        is_exec_env = getRuntime().is_exec_env()
        logger.debug(
            "Calling getter for property %s in %s", self.p_name,
            "an execution environment" if is_exec_env else "the client")
        if (is_exec_env and obj.is_loaded()) or (not is_exec_env
                                                 and not obj.is_persistent()):
            try:
                obj.set_dirty(
                    True
                )  # set dirty = true for language types like lists, dicts, that are get and modified. TODO: improve this.
                return object.__getattribute__(
                    obj, "%s%s" % (DCLAY_PROPERTY_PREFIX, self.p_name))
            except AttributeError:
                logger.warning(
                    "Received AttributeError while accessing property %s on object %r",
                    self.p_name, obj)
                logger.debug("Internal dictionary of the object: %s",
                             obj.__dict__)
                raise
        else:
            return getRuntime().execute_implementation_aux(
                DCLAY_GETTER_PREFIX + self.p_name, obj, (), obj.get_hint())
예제 #4
0
 def make_persistent(self, alias=None, backend_id=None, recursive=True):
     if alias == "":
         raise AttributeError('Alias cannot be empty')
     getRuntime().make_persistent(self,
                                  alias=alias,
                                  backend_id=backend_id,
                                  recursive=recursive)
예제 #5
0
    def __set__(self, obj, value):
        """Setter for the dataClay property

        See the __get__ method for the basic behavioural explanation.
        """
        logger.debug("Calling replicated setter for property %s", self.p_name)

        is_client = not getRuntime().is_exec_env()
        if is_client and not obj.is_persistent():
            object.__setattr__(obj,
                               "%s%s" % (DCLAY_PROPERTY_PREFIX, self.p_name),
                               value)
        elif not is_client and not obj.is_loaded():
            getRuntime().execute_implementation_aux(
                DCLAY_SETTER_PREFIX + self.p_name, obj, (value, ),
                obj.get_hint())
        else:
            if self.inMaster:
                logger.debug(
                    "Calling update in master [%s] for property %s with value %s",
                    obj.get_master_location, self.p_name, value)
                getRuntime().execute_implementation_aux(
                    '__setUpdate__', obj,
                    (obj, self.p_name, value, self.beforeUpdate,
                     self.afterUpdate), obj.get_master_location())
            else:
                logger.debug(
                    "Calling update locally for property %s with value %s",
                    self.p_name, value)
                obj.__setUpdate__(obj, self.p_name, value, self.beforeUpdate,
                                  self.afterUpdate)
            obj.set_dirty(True)
예제 #6
0
 def dc_put(self, alias, backend_id=None, recursive=True):
     if alias is None or alias is "":
         raise AttributeError('Alias cannot be null or empty')
     getRuntime().make_persistent(self,
                                  alias=alias,
                                  backend_id=backend_id,
                                  recursive=recursive)
예제 #7
0
    def split(self, split_class=None):
        # TODO: this could be improved, library could cache stuff, or a joint call could be added
        from dataclay.commonruntime.Runtime import getRuntime
        location_chunks = sorted((
            # Overly complex way to get a single ExecutionEnvironmentID
            # works in both Python2 & Python3
            next(
                iter(((getRuntime().get_all_locations(ch.get_object_id())
                       ).keys()))),
            ch) for ch in self.get_chunks())

        result = list()

        # FIXME: once support for imports has been implemented and tested, clean this up
        from itertools import groupby
        from operator import itemgetter
        from dataclay.contrib import splitting

        if split_class is None:
            split_class = splitting.GenericSplit
        elif isinstance(split_class, basestring):
            split_class = getattr(splitting, split_class)
        else:
            raise NotImplementedError(
                "I could not understand %s (of type %s)" %
                (split_class, type(split_class)))

        unused_exec_envs = set(
            getRuntime().get_execution_environments_info().keys())

        # FIXME: **********************************************************************************
        # FIXME: not using real split_class due to registration issues, but should be done that way
        # FIXME: **********************************************************************************

        for loc, chunks in groupby(location_chunks, key=itemgetter(0)):
            # Previous code using split intelligently:
            # split_object = split_class(map(itemgetter(1), chunks), loc)
            # split_object.make_persistent(backend_id=loc)
            # unused_exec_envs.remove(loc)
            # result.append(split_object)

            # Hacked around code:
            result.append(map(itemgetter(1), chunks))

        # Remove this
        return result

        # FIXME This is useful for WorkStealingSplit, but not for the others...
        for ee in unused_exec_envs:
            split_object = split_class(list(), ee)
            split_object.make_persistent(backend_id=ee)
            result.append(split_object)

        for split_object in result:
            # Note that this result is implicitly copied given that split is persistent
            # (maybe do the copy explicit? even when it is useless?)
            split_object.split_brothers = result

        return result
예제 #8
0
 def initialize_object(self, new_object_id=None):
     """ 
     @postcondition: Initialize the object 
     @param new_object_id: Object Id of the object
     """
     if new_object_id is not None:  # TODO: remove this if once ExecutionGateway is not initializing object id twice
         self.set_object_id(new_object_id)
     getRuntime().add_to_heap(self)
예제 #9
0
 def dc_update(self, from_object):
     """
     @postcondition: Updates all fields of this object with the values of the specified object
     @param from_object: instance from which values must be retrieved to set fields of current object
     """
     if from_object is None:
         return
     else:
         getRuntime().update_object(self, from_object)
예제 #10
0
 def federate(self, ext_dataclay_id, recursive=True):
     """
     @postcondition: Federates this object with an external dataClay instance
     @param ext_dataclay_id: id of the external dataClay instance
     @param recursive: Indicates if all sub-objects must be federated as well.
     """
     getRuntime().federate_object(self.get_object_id(), ext_dataclay_id,
                                  recursive,
                                  self.get_class_extradata().class_id,
                                  self.get_hint())
예제 #11
0
 def _update_object_id(self, new_object_id):
     """
     @postcondition: Set a new object id for the object and
                     calls an update of its heap references
     @param new_object_id: object id
     """
     if self.is_persistent():
         raise DataClayException(
             "Cannot change the id of a persistent object")
     old_object_id = self.get_object_id()
     self.__dclay_instance_extradata.object_id = new_object_id
     getRuntime().update_object_id(old_object_id, new_object_id)
예제 #12
0
 def unfederate(self, ext_dataclay_id=None, recursive=True):
     """
     @postcondition: Unfederate this object with an external dataClay instance
     @param ext_dataclay_id: id of the external dataClay instance (none means to unfederate with all dcs)
     @param recursive: Indicates if all sub-objects must be unfederated as well.
     """
     if ext_dataclay_id is not None:
         getRuntime().unfederate_object(self.get_object_id(),
                                        ext_dataclay_id, recursive)
     else:
         getRuntime().unfederate_object_with_all_dcs(
             self.get_object_id(), recursive)
예제 #13
0
 def initialize_object_as_volatile(self):
     """
     @postcondition: Initialize object with state 'volatile' with proper flags. Usually, volatile state is created by a stub, app, exec
     class,.. See same function in DataClayExecutionObject for a different initialization. This design is intended to be
     clear with object state.
     """
     # TODO: improve this using an specialization (dgasull)
     if getRuntime().is_exec_env():
         # *** Execution Environment flags
         self.set_persistent(True)  # All objects in the EE are persistent
         self.set_loaded(True)
         self.set_pending_to_register(True)
         self.set_hint(getRuntime().get_hint())
         self.set_owner_session_id(getRuntime().get_session_id())
예제 #14
0
def _dclayMethod(f, self, *args, **kwargs):
    """Helper function for DataClayObject method decoration"""
    logger.verbose("Calling function %s", f.__name__)
    is_exec_env = getRuntime().is_exec_env()
    try:
        if (is_exec_env and self.is_loaded()) \
                or (not is_exec_env and not self.is_persistent())\
                or f._dclay_local:
            return f(self, *args, **kwargs)
        else:
            return getRuntime().execute_implementation_aux(
                f.__name__, self, args, self.get_hint())
    except Exception:
        traceback.print_exc()
        raise
예제 #15
0
파일: api.py 프로젝트: kpavel/pyclay
def getByID(object_strid):
    """Get a Persistent Object from its OID.
    :param object_strid: The string identifying object (contains both ObjectID and hint)
    :return: The (Persistent) DataClayObject
    """
    try:
        object_id, hint, class_id = object_strid.split(":")
        ret = getRuntime().get_object_by_id(uuid.UUID(object_id),
                                            class_id=uuid.UUID(class_id),
                                            hint=uuid.UUID(hint))
    except ValueError:  # this can fail for both [not enough semicolons]|[invalid uuid]
        # Fallback behaviour: no extra fields, the whole string is the ObjectID UUID
        object_id = object_strid
        ret = getRuntime().get_object_by_id(uuid.UUID(object_id))

    return ret
예제 #16
0
    def test(self):
        """Test. note that all test method names must begin with 'test.'"""
        """WARNING: IT IS HIGHLY RECOMMENDED TO HAVE ONE TEST ONLY TO ISOLATE FUNCTIONAL TESTS FROM EACH OTHER. i.e. 
        Start a new Python Interpreter and JVM for each test. In the end, it means only one test in this class. """
        from dataclay.api import init

        logger.debug('**Starting init**')
        init()
        
        """ 
        Imports. Imports must be located here in order to simulate "import" order in a real scenario. 
        VERY IMPORTANT: Imports must be located AFTER init
        """
        from model.classes import Person
        from dataclay.commonruntime.Runtime import getRuntime
        self.session_initialized = True
    
        """
        Test. From now on, the Functional Test itself. 
        """
        p = Person('foo', 100)

        execution_environments = list(getRuntime().get_execution_environments_info().keys())

        self.assertTrue(len(execution_environments) > 1) 

        p.make_persistent(backend_id=execution_environments[0])

        p.new_replica(backend_id=execution_environments[1])
        
        self.assertEqual(p.run_remote(execution_environments[0], 'getMyMasterLocation', None), execution_environments[0])
        self.assertEqual(p.run_remote(execution_environments[1], 'getMyMasterLocation', None), execution_environments[0])
        
        logger.debug("Test OK!")
예제 #17
0
 def get_federation_targets(self):
     """ Retrieve dataClay instances ids where the object is federated
     :return: dataClay instances ids where this object is federated
     :rtype: set of UUID
     """
     return getRuntime().get_dataclays_object_is_federated_with(
         self.get_object_id())
예제 #18
0
 def get_federation_source(self):
     """ Retrieve dataClay instance id where the object comes from or NULL
     :return: dataClay instance ids where this object is federated
     :rtype: UUID
     """
     return getRuntime().get_external_source_of_dataclay_object(
         self.get_object_id())
예제 #19
0
def _dclayEmptyMethod(f, self, *args, **kwargs):
    """Similar to dclayMethod, but without actual Python implementation."""
    logger.verbose("Calling (languageless) function %s", f.__name__)

    # Let it fail elsewhere, if the user hacks around into an invalid state
    # (like a loaded&local non-persistent instance with an dclayEmptyMethod,
    #  something that should not happen normally)
    return getRuntime().execute_implementation_aux(f.__name__, self, args, self.get_hint())
예제 #20
0
 def get_external_dataclay_info(self, dataclay_id):
     """ Get external dataClay information
     :param dataclay_id: external dataClay ID
     :return: DataClayInstance information
     :type dataclay_id: UUID
     :rtype: DataClayInstance
     """
     return getRuntime().get_external_dataclay_info(dataclay_id)
예제 #21
0
    def __set__(self, obj, value):
        """Setter for the dataClay property

        See the __get__ method for the basic behavioural explanation.
        """
        logger.debug("Calling setter for property %s", self.p_name)

        is_exec_env = getRuntime().is_exec_env()
        if (is_exec_env and obj.is_loaded()) or (not is_exec_env
                                                 and not obj.is_persistent()):
            object.__setattr__(obj,
                               "%s%s" % (DCLAY_PROPERTY_PREFIX, self.p_name),
                               value)
            if is_exec_env:
                obj.set_dirty(True)
        else:
            getRuntime().execute_implementation_aux(
                DCLAY_SETTER_PREFIX + self.p_name, obj, (value, ),
                obj.get_hint())
예제 #22
0
    def serialize_reference_counting(self, dc_obj, io_file):
        """ TODO: IMPORTANT: this should be removed in new serialization by using paddings to directly access reference counters inside
         metadata. """
        """
        @postcondition: Serialize reference counting (garbage collector information)
        @param dc_obj: dc object with ref counting
        @param io_file: Buffer in which to serialize
        @param reference_counting: Reference counting to serialize
        """
        self.external_references = 0
        if dc_obj.get_alias() is not None and dc_obj.get_alias() != "":
            logger.trace("Found alias reference")
            self.external_references = self.external_references + 1

        cur_dataclay_id = getRuntime().get_dataclay_id()
        if dc_obj.get_replica_locations() is not None and len(
                dc_obj.get_replica_locations()) != 0:
            for replica_loc in dc_obj.get_replica_locations():
                replica_dataclay_id = getRuntime(
                ).get_execution_environment_info(
                    replica_loc).dataclay_instance_id
                if replica_dataclay_id != cur_dataclay_id:
                    logger.trace("Found federation reference")
                    self.external_references = self.external_references + 1
                    break
        logger.trace(
            f"Serializing reference counting external references = {self.external_references}"
        )
        IntegerWrapper().write(io_file, self.external_references)
        IntegerWrapper().write(io_file, len(self.reference_counting))
        for location, ref_counting_in_loc in self.reference_counting.items():
            if location is None:
                BooleanWrapper().write(io_file, True)
            else:
                BooleanWrapper().write(io_file, False)
                StringWrapper().write(io_file, str(location))

            IntegerWrapper().write(io_file, len(ref_counting_in_loc))
            for oid, counter in ref_counting_in_loc.items():
                StringWrapper().write(io_file, str(oid))
                IntegerWrapper().write(io_file, counter)
예제 #23
0
def load_metaclass_info(metaclass_id):
    """Load the namespace and class name for a certain MetaClassID.
    :param metaclass_id: The dataClay UUID of the MetaClass.
    :return: A tuple (class_name, namespace).
    """
    try:
        return cached_metaclass_info[metaclass_id]
    except KeyError:
        class_name, namespace = getRuntime(
        ).ready_clients["@LM"].get_classname_and_namespace_for_ds(metaclass_id)
        cached_metaclass_info[metaclass_id] = (class_name, namespace)
        return class_name, namespace
예제 #24
0
    def test(self):
        """Test. note that all test method names must begin with 'test.'"""
        """WARNING: IT IS HIGHLY RECOMMENDED TO HAVE ONE TEST ONLY TO ISOLATE FUNCTIONAL TESTS FROM EACH OTHER. i.e. 
        Start a new Python Interpreter and JVM for each test. In the end, it means only one test in this class. """
        from dataclay.api import init

        logger.debug('**Starting init**')
        init()
        """ 
        Imports. Imports must be located here in order to simulate "import" order in a real scenario. 
        VERY IMPORTANT: Imports must be located AFTER init
        """
        from model.classes import Person
        from dataclay.DataClayObjProperties import DCLAY_GETTER_PREFIX
        from dataclay.commonruntime.Runtime import getRuntime
        self.session_initialized = True
        """
        Test. From now on, the Functional Test itself. 
        """
        p = Person('foo', 100)

        execution_environments = list(
            getRuntime().get_execution_environments_info().keys())

        self.assertTrue(len(execution_environments) > 1)

        p.make_persistent(backend_id=execution_environments[0])

        p.new_replica(backend_id=execution_environments[1])

        # Name is a replicated attribute so the after method should be called after the setter
        p.name = 'aaa'

        # Assert that the attribute 'name' was properly changed in both dataservices
        self.assertEqual(
            p.run_remote(execution_environments[0],
                         DCLAY_GETTER_PREFIX + 'name', None), 'aaa')
        self.assertEqual(
            p.run_remote(execution_environments[1],
                         DCLAY_GETTER_PREFIX + 'name', None), 'aaa')

        # Assert that the attribute 'years' was changed only in one dataservice
        p.years = 1000
        years0 = p.run_remote(execution_environments[0],
                              DCLAY_GETTER_PREFIX + 'years', None)
        years1 = p.run_remote(execution_environments[1],
                              DCLAY_GETTER_PREFIX + 'years', None)
        self.assertEqual(abs(years0 - years1), 900)

        logger.debug("Test OK!")
예제 #25
0
    def initialize_object_as_persistent(self):
        """
        @postcondition: object is initialized as a persistent object.
        Flags for "persistent" state might be different in EE and client.
        """
        # TODO: improve this using an specialization (dgasull)
        if getRuntime().is_exec_env():
            # *** Execution Environment flags
            self.set_persistent(True)

            # by default, loaded = true for volatiles created inside executions
            # this function (initialize as persistent) is used for objects being
            # deserialized and therefore they might be unloaded
            # same happens for pending to register flag.
            self.set_loaded(False)
            self.set_pending_to_register(False)

        else:
            # *** Client flags
            self.set_persistent(True)
예제 #26
0
def track_local_available_classes():
    """Track the available classes into the commonruntime.local_available_classes.

    Note that no deployment is done in this function: the deployment should be
    done beforehand through the deploy_stubs function.

    This function returns all the contracts that have been found.
    """
    babel_data = load_babel_data()
    contracts = set()

    for class_data in babel_data:
        contracts.update(class_data.contracts)
        namespace = class_data.namespace
        full_name = class_data.className

        getRuntime().local_available_classes[class_data.classID] = \
            "%s.%s" % (namespace, full_name)

    logger.verbose("Using the following contracts: %s", contracts)
    return contracts
예제 #27
0
 def ass_client(self):
     self.client = getRuntime().ready_clients["@STORAGE"]
예제 #28
0
    def deserialize(self, io_file, iface_bitmaps, metadata,
                    cur_deserialized_python_objs):
        """Reciprocal to serialize."""
        logger.verbose("Deserializing object %s", str(self.get_object_id()))

        # Put slow debugging info inside here:
        #
        # NOTE: new implementation of ExecutionGateway assert is not needed and wrong
        # if logger.isEnabledFor(DEBUG):
        #     klass = self.__class__
        #     logger.debug("Deserializing instance %r from class %s",
        #                  self, klass.__name__)
        #     logger.debug("The previous class is from module %s, in file %s",
        #                  klass.__module__, inspect.getfile(klass))
        #     logger.debug("The class extradata is:\n%s", klass._dclay_class_extradata)
        #     assert klass._dclay_class_extradata == self._dclay_class_extradata
        #
        # LOADED FLAG = TRUE only once deserialization is finished to avoid concurrent problems!
        # # This may be due to race conditions. It may need to do some extra locking
        # if self.__dclay_instance_extradata.loaded_flag:
        #     logger.debug("Loaded Flag is True")
        # else:
        #     self.__dclay_instance_extradata.loaded_flag = True
        """ reference counting """
        """ discard padding """
        IntegerWrapper().read(io_file)
        """ deserialize master_location """
        des_master_loc_str = StringWrapper().read(io_file)
        if des_master_loc_str == "x":
            self.__dclay_instance_extradata.master_location = None
        else:
            self.__dclay_instance_extradata.master_location = UUID(
                des_master_loc_str)

        if hasattr(self, "__setstate__"):
            # The object has a user-defined deserialization method.

            # Use pickle, and use that method instead
            if six.PY2:
                import cPickle as pickle
            elif six.PY3:
                import _pickle as pickle

            state = pickle.loads(StringWrapper(mode="binary").read(io_file))
            self.__setstate__(state)

        else:
            # Regular dataClay provided deserialization

            # Start by getting the properties
            properties = sorted(self.get_class_extradata().properties.values(),
                                key=attrgetter('position'))

            logger.trace("Tell io_file before loop: %s", io_file.tell())
            logger.verbose("Deserializing list of properties: %s", properties)

            for p in properties:

                logger.trace("Tell io_file in loop: %s", io_file.tell())
                not_null = BooleanWrapper().read(io_file)
                value = None
                if not_null:
                    logger.debug("Not null property %s", p.name)
                    if isinstance(p.type, UserType):
                        try:
                            logger.debug("Property %s is an association",
                                         p.name)
                            value = DeserializationLibUtilsSingleton.deserialize_association(
                                io_file, iface_bitmaps, metadata,
                                cur_deserialized_python_objs, getRuntime())
                        except KeyError as e:
                            logger.error('Failed to deserialize association',
                                         exc_info=True)
                    else:
                        try:
                            upck = Unpickler(io_file)
                            upck.persistent_load = PersistentLoadPicklerHelper(
                                metadata, cur_deserialized_python_objs,
                                getRuntime())
                            value = upck.load()
                        except:
                            traceback.print_exc()

                logger.debug("Setting value %s for property %s", value, p.name)

                object.__setattr__(self,
                                   "%s%s" % (DCLAY_PROPERTY_PREFIX, p.name),
                                   value)
        """ reference counting bytes here """
        """ TODO: discard bytes? """
예제 #29
0
 def set_in_dataclay_instance(self, dc_info, field_name, params):
     from dataclay.DataClayObjProperties import DCLAY_SETTER_PREFIX
     getRuntime().synchronize_federated(self, params,
                                        DCLAY_SETTER_PREFIX + field_name,
                                        dc_info)
예제 #30
0
 def set_in_backend(self, backend_id, field_name, value):
     from dataclay.DataClayObjProperties import DCLAY_SETTER_PREFIX
     return getRuntime().run_remote(self.get_object_id(), backend_id,
                                    DCLAY_SETTER_PREFIX + field_name, value)