def delete_code(code): """ Delete a code from the DB. Check before that there are no output nodes. NOTE! Not thread safe... Do not use with many users accessing the DB at the same time. Implemented as a function on purpose, otherwise complicated logic would be needed to set the internal state of the object after calling computer.delete(). """ if not isinstance(code, Code): raise TypeError("code must be an instance of " "aiida.orm.computer.Code") existing_outputs = code.get_outputs() if len(existing_outputs) != 0: raise InvalidOperation( "Unable to delete the requested code because it " "has {} output links".format(len(existing_outputs))) else: repo_folder = code._repository_folder from aiida.backends.sqlalchemy import session session.begin(subtransactions=True) try: code.dbnode.delete() repo_folder.erase() session.commit() except: session.rollback() raise
def _replace_dblink_from(self, src, label, link_type): from aiida.backends.sqlalchemy import session try: self._add_dblink_from(src, label) except UniquenessError: # I have to replace the link; I do it within a transaction try: self._remove_dblink_from(label) self._add_dblink_from(src, label, link_type) session.commit() except: session.rollback() raise
def _do_create_link(self, src, label, link_type): from aiida.backends.sqlalchemy import session try: link = DbLink(input_id=src.dbnode.id, output_id=self.dbnode.id, label=label, type=link_type.value) session.add(link) session.commit() except SQLAlchemyError as e: session.rollback() raise UniquenessError("There is already a link with the same " "name (raw message was {})" "".format(e))
def _store_cached_input_links(self, with_transaction=True): """ Store all input links that are in the local cache, transferring them to the DB. :note: This can be called only if all parents are already stored. :note: Links are stored only after the input nodes are stored. Moreover, link storage is done in a transaction, and if one of the links cannot be stored, an exception is raised and *all* links will remain in the cache. :note: This function can be called only after the node is stored. After that, it can be called multiple times, and nothing will be executed if no links are still in the cache. :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! """ if self._to_be_stored: raise ModificationNotAllowed( "Node with pk= {} is not stored yet".format(self.id)) # This raises if there is an unstored node. self._check_are_parents_stored() # I have to store only those links where the source is already # stored links_to_store = list(self._inputlinks_cache.keys()) for label in links_to_store: src, link_type = self._inputlinks_cache[label] self._add_dblink_from(src, label, link_type) # If everything went smoothly, clear the entries from the cache. # I do it here because I delete them all at once if no error # occurred; otherwise, links will not be stored and I # should not delete them from the cache (but then an exception # would have been raised, and the following lines are not executed) self._inputlinks_cache.clear() from aiida.backends.sqlalchemy import session if with_transaction: try: session.commit() except SQLAlchemyError as e: session.rollback()
def store_all(self, with_transaction=True): """ Store the node, together with all input links, if cached, and also the linked nodes, if they were not stored yet. :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! """ if not self._to_be_stored: raise ModificationNotAllowed( "Node with pk= {} was already stored".format(self.id)) # For each parent, check that all its inputs are stored for link in self._inputlinks_cache: try: parent_node = self._inputlinks_cache[link][0] parent_node._check_are_parents_stored() except ModificationNotAllowed: raise ModificationNotAllowed( "Parent node (UUID={}) has " "unstored parents, cannot proceed (only direct parents " "can be unstored and will be stored by store_all, not " "grandparents or other ancestors".format(parent_node.uuid)) self._store_input_nodes() self.store(with_transaction=False) self._store_cached_input_links(with_transaction=False) from aiida.backends.sqlalchemy import session if with_transaction: try: session.commit() except SQLAlchemyError as e: session.rollback() return self