This source file includes following definitions.
- update_synapse_ready
- update_synapse_confirmed
- update_graph
- should_fire_synapse
- initiate_action
- fire_synapse
- run_graph
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <crm_internal.h>
20
21 #include <crm/crm.h>
22 #include <crm/msg_xml.h>
23 #include <crm/common/xml.h>
24 #include <crm/transition.h>
25
26
27
28 crm_graph_functions_t *graph_fns = NULL;
29
30 static gboolean
31 update_synapse_ready(synapse_t * synapse, int action_id)
32 {
33 GListPtr lpc = NULL;
34 gboolean updates = FALSE;
35
36 CRM_CHECK(synapse->executed == FALSE, return FALSE);
37 CRM_CHECK(synapse->confirmed == FALSE, return FALSE);
38
39 synapse->ready = TRUE;
40 for (lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
41 crm_action_t *prereq = (crm_action_t *) lpc->data;
42
43 crm_trace("Processing input %d", prereq->id);
44
45 if (prereq->id == action_id) {
46 crm_trace("Marking input %d of synapse %d confirmed", action_id, synapse->id);
47 prereq->confirmed = TRUE;
48 updates = TRUE;
49
50 } else if (prereq->confirmed == FALSE) {
51 synapse->ready = FALSE;
52 }
53
54 }
55
56 if (updates) {
57 crm_trace("Updated synapse %d", synapse->id);
58 }
59 return updates;
60 }
61
62 static gboolean
63 update_synapse_confirmed(synapse_t * synapse, int action_id)
64 {
65 GListPtr lpc = NULL;
66 gboolean updates = FALSE;
67 gboolean is_confirmed = TRUE;
68
69 CRM_CHECK(synapse->executed, return FALSE);
70 CRM_CHECK(synapse->confirmed == FALSE, return TRUE);
71
72 is_confirmed = TRUE;
73 for (lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
74 crm_action_t *action = (crm_action_t *) lpc->data;
75
76 crm_trace("Processing action %d", action->id);
77
78 if (action->id == action_id) {
79 crm_trace("Confirmed: Action %d of Synapse %d", action_id, synapse->id);
80 action->confirmed = TRUE;
81 updates = TRUE;
82
83 } else if (action->confirmed == FALSE) {
84 is_confirmed = FALSE;
85 crm_trace("Synapse %d still not confirmed after action %d", synapse->id, action_id);
86 }
87 }
88
89 if (is_confirmed && synapse->confirmed == FALSE) {
90 crm_trace("Confirmed: Synapse %d", synapse->id);
91 synapse->confirmed = TRUE;
92 updates = TRUE;
93 }
94
95 if (updates) {
96 crm_trace("Updated synapse %d", synapse->id);
97 }
98 return updates;
99 }
100
101 gboolean
102 update_graph(crm_graph_t * graph, crm_action_t * action)
103 {
104 gboolean rc = FALSE;
105 gboolean updates = FALSE;
106 GListPtr lpc = NULL;
107
108 for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
109 synapse_t *synapse = (synapse_t *) lpc->data;
110
111 if (synapse->confirmed || synapse->failed) {
112 crm_trace("Synapse complete");
113
114 } else if (synapse->executed) {
115 crm_trace("Synapse executed");
116 rc = update_synapse_confirmed(synapse, action->id);
117
118 } else if (action->failed == FALSE || synapse->priority == INFINITY) {
119 rc = update_synapse_ready(synapse, action->id);
120 }
121 updates = updates || rc;
122 }
123
124 if (updates) {
125 crm_trace("Updated graph with completed action %d", action->id);
126 }
127 return updates;
128 }
129
130 static gboolean
131 should_fire_synapse(crm_graph_t * graph, synapse_t * synapse)
132 {
133 GListPtr lpc = NULL;
134
135 CRM_CHECK(synapse->executed == FALSE, return FALSE);
136 CRM_CHECK(synapse->confirmed == FALSE, return FALSE);
137
138 crm_trace("Checking pre-reqs for synapse %d", synapse->id);
139
140 synapse->ready = TRUE;
141 for (lpc = synapse->inputs; lpc != NULL; lpc = lpc->next) {
142 crm_action_t *prereq = (crm_action_t *) lpc->data;
143
144 crm_trace("Processing input %d", prereq->id);
145 if (prereq->confirmed == FALSE) {
146 crm_trace("Input %d for synapse %d not satisfied: not confirmed", prereq->id, synapse->id);
147 synapse->ready = FALSE;
148 break;
149 } else if(prereq->failed && prereq->can_fail == FALSE) {
150 crm_trace("Input %d for synapse %d not satisfied: failed", prereq->id, synapse->id);
151 synapse->ready = FALSE;
152 break;
153 }
154 }
155
156 for (lpc = synapse->actions; synapse->ready && lpc != NULL; lpc = lpc->next) {
157 crm_action_t *a = (crm_action_t *) lpc->data;
158
159 if (a->type == action_type_pseudo) {
160
161
162 } else if (synapse->priority < graph->abort_priority) {
163 crm_trace("Skipping synapse %d: abort level %d", synapse->id, graph->abort_priority);
164 graph->skipped++;
165 return FALSE;
166
167 } else if(graph_fns->allowed && graph_fns->allowed(graph, a) == FALSE) {
168 crm_trace("Deferring synapse %d: allowed", synapse->id);
169 return FALSE;
170 }
171 }
172
173 return synapse->ready;
174 }
175
176 static gboolean
177 initiate_action(crm_graph_t * graph, crm_action_t * action)
178 {
179 const char *id = NULL;
180
181 CRM_CHECK(action->executed == FALSE, return FALSE);
182
183 id = ID(action->xml);
184 CRM_CHECK(id != NULL, return FALSE);
185
186 action->executed = TRUE;
187 if (action->type == action_type_pseudo) {
188 crm_trace("Executing pseudo-event: %s (%d)", id, action->id);
189 return graph_fns->pseudo(graph, action);
190
191 } else if (action->type == action_type_rsc) {
192 crm_trace("Executing rsc-event: %s (%d)", id, action->id);
193 return graph_fns->rsc(graph, action);
194
195 } else if (action->type == action_type_crm) {
196 const char *task = NULL;
197
198 task = crm_element_value(action->xml, XML_LRM_ATTR_TASK);
199 CRM_CHECK(task != NULL, return FALSE);
200
201 if (safe_str_eq(task, CRM_OP_FENCE)) {
202 crm_trace("Executing STONITH-event: %s (%d)", id, action->id);
203 return graph_fns->stonith(graph, action);
204 }
205
206 crm_trace("Executing crm-event: %s (%d)", id, action->id);
207 return graph_fns->crmd(graph, action);
208 }
209
210 crm_err("Failed on unsupported command type: %s (id=%s)", crm_element_name(action->xml), id);
211 return FALSE;
212 }
213
214 static gboolean
215 fire_synapse(crm_graph_t * graph, synapse_t * synapse)
216 {
217 GListPtr lpc = NULL;
218
219 CRM_CHECK(synapse != NULL, return FALSE);
220 CRM_CHECK(synapse->ready, return FALSE);
221 CRM_CHECK(synapse->confirmed == FALSE, return TRUE);
222
223 crm_trace("Synapse %d fired", synapse->id);
224 synapse->executed = TRUE;
225 for (lpc = synapse->actions; lpc != NULL; lpc = lpc->next) {
226 crm_action_t *action = (crm_action_t *) lpc->data;
227
228
229 gboolean passed = FALSE;
230
231
232 passed = initiate_action(graph, action);
233 if (passed == FALSE) {
234 crm_err("Failed initiating <%s id=%d> in synapse %d",
235 crm_element_name(action->xml), action->id, synapse->id);
236 synapse->confirmed = TRUE;
237 action->confirmed = TRUE;
238 action->failed = TRUE;
239 return FALSE;
240 }
241 }
242
243 return TRUE;
244 }
245
246 int
247 run_graph(crm_graph_t * graph)
248 {
249 GListPtr lpc = NULL;
250 int stat_log_level = LOG_DEBUG;
251 int pass_result = transition_active;
252
253 const char *status = "In-progress";
254
255 if (graph_fns == NULL) {
256 set_default_graph_functions();
257 }
258 if (graph == NULL) {
259 return transition_complete;
260 }
261
262 graph->fired = 0;
263 graph->pending = 0;
264 graph->skipped = 0;
265 graph->completed = 0;
266 graph->incomplete = 0;
267 crm_trace("Entering graph %d callback", graph->id);
268
269
270 for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
271 synapse_t *synapse = (synapse_t *) lpc->data;
272
273 if (synapse->confirmed) {
274 crm_trace("Synapse %d complete", synapse->id);
275 graph->completed++;
276
277 } else if (synapse->failed == FALSE && synapse->executed) {
278 crm_trace("Synapse %d: confirmation pending", synapse->id);
279 graph->pending++;
280 }
281 }
282
283
284 for (lpc = graph->synapses; lpc != NULL; lpc = lpc->next) {
285 synapse_t *synapse = (synapse_t *) lpc->data;
286
287 if (graph->batch_limit > 0 && graph->pending >= graph->batch_limit) {
288 crm_debug("Throttling output: batch limit (%d) reached", graph->batch_limit);
289 break;
290 } else if (synapse->failed) {
291 graph->skipped++;
292 continue;
293
294 } else if (synapse->confirmed || synapse->executed) {
295
296 continue;
297 }
298
299 if (should_fire_synapse(graph, synapse)) {
300 crm_trace("Synapse %d fired", synapse->id);
301 graph->fired++;
302 if(fire_synapse(graph, synapse) == FALSE) {
303 crm_err("Synapse %d failed to fire", synapse->id);
304 stat_log_level = LOG_ERR;
305 graph->abort_priority = INFINITY;
306 graph->incomplete++;
307 graph->fired--;
308 }
309
310 if (synapse->confirmed == FALSE) {
311 graph->pending++;
312 }
313
314 } else {
315 crm_trace("Synapse %d cannot fire", synapse->id);
316 graph->incomplete++;
317 }
318 }
319
320 if (graph->pending == 0 && graph->fired == 0) {
321 graph->complete = TRUE;
322 stat_log_level = LOG_NOTICE;
323 pass_result = transition_complete;
324 status = "Complete";
325
326 if (graph->incomplete != 0 && graph->abort_priority <= 0) {
327 stat_log_level = LOG_WARNING;
328 pass_result = transition_terminated;
329 status = "Terminated";
330
331 } else if (graph->skipped != 0) {
332 status = "Stopped";
333 }
334
335 } else if (graph->fired == 0) {
336 pass_result = transition_pending;
337 }
338
339 do_crm_log(stat_log_level,
340 "Transition %d (Complete=%d, Pending=%d,"
341 " Fired=%d, Skipped=%d, Incomplete=%d, Source=%s): %s",
342 graph->id, graph->completed, graph->pending, graph->fired,
343 graph->skipped, graph->incomplete, graph->source, status);
344
345 return pass_result;
346 }