1# coding: utf-8
2"""
3Error handlers for errors originating from the Submission systems.
4"""
5
6__author__ = "Michiel van Setten"
7__copyright__ = " "
8__version__ = "0.9"
9__maintainer__ = "Michiel van Setten"
10__email__ = "mjvansetten@gmail.com"
11__date__ = "May 2014"
12
13from abipy.flowtk.scheduler_error_parsers import get_parser
14try:
15    from custodian.custodian import ErrorHandler
16except ImportError:
17    ErrorHandler = object
18
19
20class SchedulerErrorHandler(ErrorHandler):
21    """
22    Custodian error handler for scheduler related errors
23      scheduler_adapter takes the scheduler, it should at least provide a .name attribute indentifying the scheduler,
24      currently 'slurm' is supported.
25      If the scheduler adapter also provides the methods defined in CorrectorProtocolScheduler, problems can also be
26      fixed by .apply_corrections.
27      If a application_adapter is also provided and it provides the methods defined in CorrectorProtocolApplication
28      problems can also be fixed a the level of the application, e.g. making the application require less memory.
29    """
30    def __init__(self, scheduler_adapter, application_adapter=None, err_file='queue.err', out_file='queue.out',
31                 run_err_file='run.err', batch_err_file='batch.err'):
32        self.scheduler_adapter = scheduler_adapter
33        self.application_adapter = application_adapter
34        self.err_file = err_file
35        self.out_file = out_file
36        self.run_err_file = run_err_file
37        self.batch_err_file = batch_err_file
38        self.errors = []
39        self.corrections = {}
40
41    def check(self):
42        """
43        Check for the defined errors, put all found errors in self.errors, return True if any were found False if no
44        errors were found
45        """
46        parser = get_parser(self.scheduler_adapter.name, err_file=self.err_file, out_file=self.out_file,
47                            run_err_file=self.run_err_file, batch_err_file=self.batch_err_file)
48        parser.parse()
49        self.errors = parser.errors
50        if len(self.errors) == 0:
51            return False
52        else:
53            return True
54
55    def correct(self):
56        """
57        For custodian compatibility
58        """
59        self.return_corrections()
60
61    def return_corrections(self):
62
63        for error in self.errors:
64            self.corrections.update({error: {'scheduler_adapter_solutions': [], 'aplication_adapter_solutions': []}})
65            self.corrections[error]['scheduler_adapter_solutions'].append(error.scheduler_adapter_solutions)
66            self.corrections[error]['application_adapter_solutions'].append(error.application_adapter_solutions)
67        return self.corrections
68
69    def apply_corrections(self):
70        """
71        Method to directly apply the corrections.
72        """
73        for error in self.errors:
74            for solution in error.scheduler_adapter_solutions:
75                if self.scheduler_adapter is not None:
76                    if self.scheduler_adapter.__getattribut__(solution[0].__name__)(solution[1]):
77                        return True
78            for solution in error.application_adapter_solutions:
79                if self.application_adapter is not None:
80                    if self.application_adapter.__getattribut__(solution[0].__name__)(solution[1]):
81                        return True
82        return False
83