Ejemplo n.º 1
0
    def store(self, with_transaction=True):
        """
        Store a new node in the DB, also saving its repository directory
        and attributes.

        After being called attributes cannot be
        changed anymore! Instead, extras can be changed only AFTER calling
        this store() function.

        :note: After successful storage, those links that are in the cache, and
            for which also the parent node is already stored, will be
            automatically stored. The others will remain unstored.

        :parameter with_transaction: if False, no transaction is used. This
          is meant to be used ONLY if the outer calling function has already
          a transaction open!
        """
        # TODO: This needs to be generalized, allowing for flexible methods
        # for storing data and its attributes.
        from django.db import transaction
        from aiida.common.utils import EmptyContextManager
        from aiida.common.exceptions import ValidationError
        from aiida.backends.djsite.db.models import DbAttribute
        import aiida.orm.autogroup

        if with_transaction:
            context_man = transaction.commit_on_success()
        else:
            context_man = EmptyContextManager()

        if self._to_be_stored:

            # As a first thing, I check if the data is valid
            self._validate()

            # Verify that parents are already stored. Raises if this is not
            # the case.
            self._check_are_parents_stored()

            # I save the corresponding django entry
            # I set the folder
            # NOTE: I first store the files, then only if this is successful,
            # I store the DB entry. In this way,
            # I assume that if a node exists in the DB, its folder is in place.
            # On the other hand, periodically the user might need to run some
            # bookkeeping utility to check for lone folders.
            self._repository_folder.replace_with_folder(
                self._get_temp_folder().abspath, move=True, overwrite=True)

            # I do the transaction only during storage on DB to avoid timeout
            # problems, especially with SQLite
            try:
                with context_man:
                    # Save the row
                    self._dbnode.save()
                    # Save its attributes 'manually' without incrementing
                    # the version for each add.
                    DbAttribute.reset_values_for_node(
                        self.dbnode,
                        attributes=self._attrs_cache,
                        with_transaction=False)
                    # This should not be used anymore: I delete it to
                    # possibly free memory
                    del self._attrs_cache

                    self._temp_folder = None
                    self._to_be_stored = False

                    # Here, I store those links that were in the cache and
                    # that are between stored nodes.
                    self._store_cached_input_links()

            # This is one of the few cases where it is ok to do a 'global'
            # except, also because I am re-raising the exception
            except:
                # I put back the files in the sandbox folder since the
                # transaction did not succeed
                self._get_temp_folder().replace_with_folder(
                    self._repository_folder.abspath, move=True, overwrite=True)
                raise

            # Set up autogrouping used be verdi run
            autogroup = aiida.orm.autogroup.current_autogroup
            grouptype = aiida.orm.autogroup.VERDIAUTOGROUP_TYPE
            if autogroup is not None:
                if not isinstance(autogroup, aiida.orm.autogroup.Autogroup):
                    raise ValidationError(
                        "current_autogroup is not an AiiDA Autogroup")
                if autogroup.is_to_be_grouped(self):
                    group_name = autogroup.get_group_name()
                    if group_name is not None:
                        from aiida.orm import Group

                        g = Group.get_or_create(name=group_name,
                                                type_string=grouptype)[0]
                        g.add_nodes(self)

        # This is useful because in this way I can do
        # n = Node().store()
        return self
Ejemplo n.º 2
0
    def _db_store(self, with_transaction=True):
        """
        Store a new node in the DB, also saving its repository directory
        and attributes.

        After being called attributes cannot be
        changed anymore! Instead, extras can be changed only AFTER calling
        this store() function.

        :note: After successful storage, those links that are in the cache, and
            for which also the parent node is already stored, will be
            automatically stored. The others will remain unstored.

        :parameter with_transaction: if False, no transaction is used. This
          is meant to be used ONLY if the outer calling function has already
          a transaction open!

        :param bool use_cache: Whether I attempt to find an equal node in the DB.
        """
        # TODO: This needs to be generalized, allowing for flexible methods
        # for storing data and its attributes.
        from django.db import transaction
        from aiida.common.utils import EmptyContextManager
        from aiida.common.exceptions import ValidationError
        from aiida.backends.djsite.db.models import DbAttribute
        import aiida.orm.autogroup

        if with_transaction:
            context_man = transaction.atomic()
        else:
            context_man = EmptyContextManager()

        # I save the corresponding django entry
        # I set the folder
        # NOTE: I first store the files, then only if this is successful,
        # I store the DB entry. In this way,
        # I assume that if a node exists in the DB, its folder is in place.
        # On the other hand, periodically the user might need to run some
        # bookkeeping utility to check for lone folders.
        self._repository_folder.replace_with_folder(
            self._get_temp_folder().abspath, move=True, overwrite=True)

        # I do the transaction only during storage on DB to avoid timeout
        # problems, especially with SQLite
        try:
            with context_man:
                # Save the row
                self._dbnode.save()
                # Save its attributes 'manually' without incrementing
                # the version for each add.
                DbAttribute.reset_values_for_node(self._dbnode,
                                                  attributes=self._attrs_cache,
                                                  with_transaction=False)
                # This should not be used anymore: I delete it to
                # possibly free memory
                del self._attrs_cache

                self._temp_folder = None
                self._to_be_stored = False

                # Here, I store those links that were in the cache and
                # that are between stored nodes.
                self._store_cached_input_links()

        # This is one of the few cases where it is ok to do a 'global'
        # except, also because I am re-raising the exception
        except:
            # I put back the files in the sandbox folder since the
            # transaction did not succeed
            self._get_temp_folder().replace_with_folder(
                self._repository_folder.abspath, move=True, overwrite=True)
            raise

        from aiida.backends.djsite.db.models import DbExtra
        # I store the hash without cleaning and without incrementing the nodeversion number
        DbExtra.set_value_for_node(self._dbnode, _HASH_EXTRA_KEY, self.get_hash())

        return self