diff --git a/autosubmit/autosubmit.py b/autosubmit/autosubmit.py index 08c1da8a50ad97077b2f5df527a39a6502d3b9d8..8653285dc8b542c65076e3918e27ee40cce9847e 100644 --- a/autosubmit/autosubmit.py +++ b/autosubmit/autosubmit.py @@ -4697,7 +4697,7 @@ class Autosubmit: job_list.generate(as_conf,date_list, member_list, num_chunks, chunk_ini, parameters, date_format, as_conf.get_retrials(), as_conf.get_default_job_type(), - wrapper_jobs, run_only_members=run_only_members, force=force) + wrapper_jobs, run_only_members=run_only_members, force=force, create=True) if str(rerun).lower() == "true": job_list.rerun(as_conf.get_rerun_jobs(),as_conf) diff --git a/autosubmit/job/job_list.py b/autosubmit/job/job_list.py index 505ce8dd2dd19dc4c926b0ca11e84c4aca7586c7..eca3aa9ca330e08a837bbbeaa83eb574b1970e71 100644 --- a/autosubmit/job/job_list.py +++ b/autosubmit/job/job_list.py @@ -160,7 +160,7 @@ class JobList(object): def generate(self, as_conf, date_list, member_list, num_chunks, chunk_ini, parameters, date_format, default_retrials, default_job_type, wrapper_jobs=dict(), new=True, run_only_members=[], show_log=True, monitor=False, - force=False): + force=False, create = False): """ Creates all jobs needed for the current workflow. :param as_conf: AutosubmitConfig object @@ -193,6 +193,7 @@ class JobList(object): :type monitor: bool """ if force: + Log.debug("Resetting the workflow graph to a zero state") if os.path.exists(os.path.join(self._persistence_path, self._persistence_file + ".pkl")): os.remove(os.path.join(self._persistence_path, self._persistence_file + ".pkl")) if os.path.exists(os.path.join(self._persistence_path, self._persistence_file + "_backup.pkl")): @@ -233,6 +234,8 @@ class JobList(object): # Force to use the last known job_list when autosubmit monitor is running. self._dic_jobs.last_experiment_data = as_conf.last_experiment_data else: + if not create: + raise AutosubmitCritical("Autosubmit couldn't load the workflow graph. Please run autosubmit create first. If the pkl file exists and was generated with Autosubmit v4.1+, try again.",7013) # Remove the previous pkl, if it exists. if not new: Log.info( diff --git a/autosubmit/job/job_list_persistence.py b/autosubmit/job/job_list_persistence.py index 592fcc1961fa16be4f8b8513e96906e0d662752f..bb884ba439ef5cde85ff6b3d25e7710236fb4acd 100644 --- a/autosubmit/job/job_list_persistence.py +++ b/autosubmit/job/job_list_persistence.py @@ -19,7 +19,7 @@ import os import pickle from sys import setrecursionlimit - +import shutil from autosubmit.database.db_manager import DbManager from log.log import Log @@ -67,8 +67,12 @@ class JobListPersistencePkl(JobListPersistence): """ path = os.path.join(persistence_path, persistence_file + '.pkl') if os.path.exists(path): - with open(path, 'rb') as fd: + # copy the path to a tmp file randomseed to avoid corruption + path_tmp = f'{path}.tmp_{os.urandom(8).hex()}' + shutil.copy(path, path_tmp) + with open(path_tmp, 'rb') as fd: graph = pickle.load(fd) + os.remove(path_tmp) for u in ( node for node in graph ): # Set after the dependencies are set graph.nodes[u]["job"].children = set() @@ -90,12 +94,16 @@ class JobListPersistencePkl(JobListPersistence): :param persistence_path: str """ - path = os.path.join(persistence_path, persistence_file + '.pkl') + + path = os.path.join(persistence_path, persistence_file + '.pkl' + '.tmp') + if os.path.exists(path): + os.remove(path) setrecursionlimit(500000000) Log.debug("Saving JobList: " + path) with open(path, 'wb') as fd: pickle.dump(graph, fd, pickle.HIGHEST_PROTOCOL) - Log.debug('Job list saved') + os.replace(path, path[:-4]) + Log.debug(f'JobList saved in {path[:-4]}') class JobListPersistenceDb(JobListPersistence):