blob: 1a2f45f1c0bd8fdadfd09000db1f7b48eaa2c26e [file] [log] [blame]
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +01001#!/usr/bin/env python3
2
3""" structured_task.py:
4
5 A generic abstraction class for executing a task with prerequesites and
6 post execution action """
7
8from __future__ import print_function
9
10__copyright__ = """
11/*
12 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
13 *
14 * SPDX-License-Identifier: BSD-3-Clause
15 *
16 */
17 """
18__author__ = "Minos Galanakis"
19__email__ = "minos.galanakis@linaro.org"
20__project__ = "Trusted Firmware-M Open CI"
21__status__ = "stable"
Minos Galanakisea421232019-06-20 17:11:28 +010022__version__ = "1.1"
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +010023
24import abc
25import time
26import multiprocessing
27
28
29class structuredTask(multiprocessing.Process):
30 """ A class that defined well structured chained execution of commands """
31
32 __metaclass__ = abc.ABCMeta
33
34 def __init__(self, name):
35
36 self._stopevent = multiprocessing.Event()
37 self._exec_sleep_period = 1.0
38 self._join_timeout = 1.0
39 self._exec_timeout = 0.0
40 self._task_name = name
41
42 # multiprocessing safe shared memory variables
43 self._mprc_manager = multiprocessing.Manager()
44
45 # Dictionary used to store objects between stages
46 self._mprc_stash = self._mprc_manager.dict()
47
48 # Integer variable that stores status of flow
49 self._mprc_status = multiprocessing.Value('i', False)
50 super(structuredTask, self).__init__(name=name)
51
52 # Perform initialization
53 # If user code raises exception, class memory will not be allocated
54 # Variables can be safely shared in the pre stages, use stash for
55 # next stages
56 self.pre_exec(self.pre_eval())
57
58 # Class API/Interface
59
60 @abc.abstractmethod
61 def pre_eval(self):
62 """ Tests that need to be run in set-up state """
63
64 @abc.abstractmethod
65 def pre_exec(self, eval_ret):
66 """ Tasks that set-up execution enviroment """
67
68 @abc.abstractmethod
69 def task_exec(self):
70 """ Main tasks """
71
72 @abc.abstractmethod
73 def post_eval(self, eval_ret):
74 """ Tests that need to be run after main task """
75
76 @abc.abstractmethod
77 def post_exec(self):
78 """ Tasks that are run after main task """
79
80 def stash(self, key, data):
81 """ Store object in a shared memory interface """
82
83 self._mprc_stash[key] = data
84
85 def unstash(self, key):
86 """ Retrieve object from a shared memory interface """
87
88 try:
89 return self._mprc_stash[key]
90 except KeyError:
91 return None
92
93 def get_name(self):
94 """" Return name label of class """
95 return self._task_name
96
97 def get_status(self):
98 """ Return the status of the execution flow """
99 with self._mprc_status.get_lock():
100 return self._mprc_status.value
101
102 def set_status(self, status):
103 """ Return the status of the execution flow """
104 with self._mprc_status.get_lock():
105 self._mprc_status.value = status
106
107 def run(self):
108 try:
109
110 # Run Core code
111 while not self._stopevent.is_set():
112 self.task_exec()
113 time.sleep(self._exec_sleep_period)
114 break
115 # print("Stop Event Detected")
116 # TODO Upgrade reporting to a similar format
117 print("%s ==> Stop Event Detected" % self.get_name())
118
119 # Post stage
120 # If something faifs in post the user should set the correct status
121 self.set_status(0)
122 print("%s ==> Stop Event Set OK Status" % self.get_name())
123 except Exception as exc:
124 print(("ERROR: Stopping %s "
125 "with Exception: \"%s\"") % (self.get_name(), exc))
126 self.set_status(1)
127 # Always call post, and determine success failed by get_status
128 self.post_exec(self.post_eval())
129
130 def _t_stop(self):
131 """ Internal class stop to be called through thread """
Minos Galanakisea421232019-06-20 17:11:28 +0100132
Minos Galanakisf4ca6ac2017-12-11 02:39:21 +0100133 if(self.is_alive()):
134 print("%s =========> STOP" % self.get_name())
135 self._stopevent.set()
136 print("Thead is alive %s" % self.is_alive())
137 print("Stop Event Triggered")
138
139 def stop(self):
140 """ External stop to be called by user code """
141
142 self._t_stop()
143 super(structuredTask, self).join(self._join_timeout)