1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2 /*
3  * Copyright (c) 2011-2015 Los Alamos National Security, LLC. All rights
4  *                         reserved.
5  * Copyright (c) 2017      Intel, Inc. All rights reserved.
6  * $COPYRIGHT$
7  *
8  * Additional copyrights may follow
9  *
10  * $HEADER$
11  */
12 
13 /****    ORTE STATE MACHINE    ****/
14 
15 /* States are treated as events so that the event
16  * library can sequence them. Each state consists
17  * of an event, a job or process state, a pointer
18  * to the respective object, and a callback function
19  * to be executed for that state. Events can be defined
20  * at different priorities - e.g., SYS priority for
21  * events associated with launching jobs, and ERR priority
22  * for events associated with abnormal termination of
23  * a process.
24  *
25  * The state machine consists of a list of state objects,
26  * each defining a state-cbfunc pair. At startup, a default
27  * list is created by the base functions which is then
28  * potentially customized by selected components within
29  * the various ORTE frameworks. For example, a PLM component
30  * may need to insert states in the launch procedure, or may
31  * want to redirect a particular state callback to a custom
32  * function.
33  *
34  * For convenience, an ANY state can be defined along with a generic
35  * callback function, with the corresponding state object
36  * placed at the end of the state machine. Setting the
37  * machine to a state that has not been explicitly defined
38  * will cause this default action to be executed. Thus, you
39  * don't have to explicitly define a state-cbfunc pair
40  * for every job or process state.
41  */
42 
43 #ifndef _ORTE_STATE_H_
44 #define _ORTE_STATE_H_
45 
46 #include "orte_config.h"
47 
48 #include "opal/class/opal_list.h"
49 #include "opal/mca/event/event.h"
50 
51 #include "orte/mca/errmgr/errmgr.h"
52 #include "orte/mca/plm/plm_types.h"
53 #include "orte/runtime/orte_globals.h"
54 
55 #include "orte/mca/state/state_types.h"
56 
57 BEGIN_C_DECLS
58 
59 /*
60  * MCA Framework - put here to access the opal_output channel
61  * in the macros
62  */
63 ORTE_DECLSPEC extern mca_base_framework_t orte_state_base_framework;
64 
65 /* For ease in debugging the state machine, it is STRONGLY recommended
66  * that the functions be accessed using the following macros
67  */
68 #define ORTE_FORCED_TERMINATE(x)                                                    \
69     do {                                                                            \
70         if (!orte_abnormal_term_ordered) {                                          \
71             orte_errmgr.abort((x), "%s FORCE-TERMINATE AT %s:%d - error %s(%d)",    \
72                                 ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),                 \
73                                 ORTE_ERROR_NAME((x)), (x),                          \
74                                 __FILE__, __LINE__);                                \
75         }                                                                           \
76     } while(0);
77 
78 #define ORTE_ACTIVATE_JOB_STATE(j, s)                                       \
79     do {                                                                    \
80         orte_job_t *shadow=(j);                                             \
81         opal_output_verbose(1, orte_state_base_framework.framework_output,  \
82                             "%s ACTIVATE JOB %s STATE %s AT %s:%d",         \
83                             ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),             \
84                             (NULL == shadow) ? "NULL" :                     \
85                             ORTE_JOBID_PRINT(shadow->jobid),                \
86                             orte_job_state_to_str((s)),                     \
87                             __FILE__, __LINE__);                            \
88         orte_state.activate_job_state(shadow, (s));                         \
89     } while(0);
90 
91 #define ORTE_ACTIVATE_PROC_STATE(p, s)                                      \
92     do {                                                                    \
93         orte_process_name_t *shadow=(p);                                    \
94         opal_output_verbose(1, orte_state_base_framework.framework_output,  \
95                             "%s ACTIVATE PROC %s STATE %s AT %s:%d",        \
96                             ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),             \
97                             (NULL == shadow) ? "NULL" :                     \
98                             ORTE_NAME_PRINT(shadow),                        \
99                             orte_proc_state_to_str((s)),                    \
100                             __FILE__, __LINE__);                            \
101         orte_state.activate_proc_state(shadow, (s));                        \
102     } while(0);
103 
104 /**
105  * Module initialization function.
106  *
107  * @retval ORTE_SUCCESS The operation completed successfully
108  * @retval ORTE_ERROR   An unspecifed error occurred
109  */
110 typedef int (*orte_state_base_module_init_fn_t)(void);
111 
112 /**
113  * Module finalization function.
114  *
115  * @retval ORTE_SUCCESS The operation completed successfully
116  * @retval ORTE_ERROR   An unspecifed error occurred
117  */
118 typedef int (*orte_state_base_module_finalize_fn_t)(void);
119 
120 /****    JOB STATE APIs    ****/
121 /* Job states are accessed via orte_job_t objects as they are only
122  * used in ORTE tools and not application processes. APIs are provided
123  * for assembling and editing the state machine, as well as activating
124  * a specific job state
125  *
126  * Note the inherent assumption in this design that any customization
127  * of the state machine will at least start with the base states - i.e.,
128  * that one would start with the default machine and edit it to add,
129  * remove, or modify callbacks as required. Alternatively, one could
130  * just clear the list entirely and assemble a fully custom state
131  * machine - both models are supported.
132  */
133 
134 /* Activate a state in the job state machine.
135  *
136  * Creates and activates an event with the callback corresponding to the
137  * specified job state. If the specified state is not found:
138  *
139  * 1. if a state machine entry for ORTE_JOB_STATE_ERROR was given, and
140  *    the state is an error state (i.e., ORTE_JOB_STATE_ERROR <= state),
141  *    then the callback for the ERROR state will be used
142  *
143  * 2. if a state machine entry for ORTE_JOB_STATE_ANY was given, and
144  *    the state is not an error state (i.e., state < ORTE_JOB_STATE_ERROR),
145  *    then the callback for the ANY state will be used
146  *
147  * 3. if neither of the above is true, then the call will be ignored.
148  */
149 typedef void (*orte_state_base_module_activate_job_state_fn_t)(orte_job_t *jdata,
150                                                                orte_job_state_t state);
151 
152 /* Add a state to the job state machine.
153  *
154  */
155 typedef int (*orte_state_base_module_add_job_state_fn_t)(orte_job_state_t state,
156                                                          orte_state_cbfunc_t cbfunc,
157                                                          int priority);
158 
159 /* Set the callback function for a state in the job state machine.
160  *
161  */
162 typedef int (*orte_state_base_module_set_job_state_callback_fn_t)(orte_job_state_t state,
163                                                                   orte_state_cbfunc_t cbfunc);
164 
165 /* Set the event priority for a state in the job state machine.
166  *
167  */
168 typedef int (*orte_state_base_module_set_job_state_priority_fn_t)(orte_job_state_t state,
169                                                                   int priority);
170 
171 /* Remove a state from the job state machine.
172  *
173  */
174 typedef int (*orte_state_base_module_remove_job_state_fn_t)(orte_job_state_t state);
175 
176 
177 /****    Proc STATE APIs  ****/
178 /* Proc states are accessed via orte_process_name_t as the state machine
179  * must be available to both application processes and ORTE tools. APIs are
180  * providedfor assembling and editing the state machine, as well as activating
181  * a specific proc state
182  *
183  * Note the inherent assumption in this design that any customization
184  * of the state machine will at least start with the base states - i.e.,
185  * that one would start with the default machine and edit it to add,
186  * remove, or modify callbacks as required. Alternatively, one could
187  * just clear the list entirely and assemble a fully custom state
188  * machine - both models are supported.
189  */
190 
191 /* Activate a proc state.
192  *
193  * Creates and activates an event with the callback corresponding to the
194  * specified proc state. If the specified state is not found:
195  *
196  * 1. if a state machine entry for ORTE_PROC_STATE_ERROR was given, and
197  *    the state is an error state (i.e., ORTE_PROC_STATE_ERROR <= state),
198  *    then the callback for the ERROR state will be used
199  *
200  * 2. if a state machine entry for ORTE_PROC_STATE_ANY was given, and
201  *    the state is not an error state (i.e., state < ORTE_PROC_STATE_ERROR),
202  *    then the callback for the ANY state will be used
203  *
204  * 3. if neither of the above is true, then the call will be ignored.
205  */
206 typedef void (*orte_state_base_module_activate_proc_state_fn_t)(orte_process_name_t *proc,
207                                                                 orte_proc_state_t state);
208 
209 /* Add a state to the proc state machine.
210  *
211  */
212 typedef int (*orte_state_base_module_add_proc_state_fn_t)(orte_proc_state_t state,
213                                                           orte_state_cbfunc_t cbfunc,
214                                                           int priority);
215 
216 /* Set the callback function for a state in the proc state machine.
217  *
218  */
219 typedef int (*orte_state_base_module_set_proc_state_callback_fn_t)(orte_proc_state_t state,
220                                                                    orte_state_cbfunc_t cbfunc);
221 
222 /* Set the event priority for a state in the proc state machine.
223  *
224  */
225 typedef int (*orte_state_base_module_set_proc_state_priority_fn_t)(orte_proc_state_t state,
226                                                                    int priority);
227 
228 /* Remove a state from the proc state machine.
229  *
230  */
231 typedef int (*orte_state_base_module_remove_proc_state_fn_t)(orte_proc_state_t state);
232 
233 
234 /*
235  * Module Structure
236  */
237 struct orte_state_base_module_1_0_0_t {
238     /** Initialization Function */
239     orte_state_base_module_init_fn_t                      init;
240     /** Finalization Function */
241     orte_state_base_module_finalize_fn_t                  finalize;
242     /* Job state APIs */
243     orte_state_base_module_activate_job_state_fn_t        activate_job_state;
244     orte_state_base_module_add_job_state_fn_t             add_job_state;
245     orte_state_base_module_set_job_state_callback_fn_t    set_job_state_callback;
246     orte_state_base_module_set_job_state_priority_fn_t    set_job_state_priority;
247     orte_state_base_module_remove_job_state_fn_t          remove_job_state;
248     /* Proc state APIs */
249     orte_state_base_module_activate_proc_state_fn_t       activate_proc_state;
250     orte_state_base_module_add_proc_state_fn_t            add_proc_state;
251     orte_state_base_module_set_proc_state_callback_fn_t   set_proc_state_callback;
252     orte_state_base_module_set_proc_state_priority_fn_t   set_proc_state_priority;
253     orte_state_base_module_remove_proc_state_fn_t         remove_proc_state;
254 };
255 typedef struct orte_state_base_module_1_0_0_t orte_state_base_module_1_0_0_t;
256 typedef orte_state_base_module_1_0_0_t orte_state_base_module_t;
257 ORTE_DECLSPEC extern orte_state_base_module_t orte_state;
258 
259 /*
260  * State Component
261  */
262 struct orte_state_base_component_1_0_0_t {
263     /** MCA base component */
264     mca_base_component_t base_version;
265     /** MCA base data */
266     mca_base_component_data_t base_data;
267 };
268 typedef struct orte_state_base_component_1_0_0_t orte_state_base_component_1_0_0_t;
269 typedef orte_state_base_component_1_0_0_t orte_state_base_component_t;
270 
271 /*
272  * Macro for use in components that are of type state
273  */
274 #define ORTE_STATE_BASE_VERSION_1_0_0 \
275     ORTE_MCA_BASE_VERSION_2_1_0("state", 1, 0, 0)
276 
277 END_C_DECLS
278 #endif
279