2
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
9
* This software is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* General Public License for more details.
14
* You should have received a copy of the GNU General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
#include <lha_internal.h>
22
#include <crm/msg_xml.h>
23
#include <crm/common/xml.h>
24
#include <crm/transition.h>
25
/* #include <sys/param.h> */
26
/* #include <clplumbing/cl_misc.h> */
29
crm_graph_functions_t *graph_fns = NULL;
33
update_synapse_ready(synapse_t *synapse, int action_id)
35
gboolean updates = FALSE;
36
CRM_CHECK(synapse->executed == FALSE, return FALSE);
37
CRM_CHECK(synapse->confirmed == FALSE, return FALSE);
39
synapse->ready = TRUE;
41
prereq, crm_action_t, synapse->inputs, lpc,
43
crm_debug_3("Processing input %d", prereq->id);
45
if(prereq->id == action_id) {
46
crm_debug_2("Marking input %d of synapse %d confirmed",
47
action_id, synapse->id);
48
prereq->confirmed = TRUE;
51
} else if(prereq->confirmed == FALSE) {
52
synapse->ready = FALSE;
58
crm_debug_2("Updated synapse %d", synapse->id);
63
update_synapse_confirmed(synapse_t *synapse, int action_id)
65
gboolean updates = FALSE;
66
gboolean is_confirmed = TRUE;
68
CRM_CHECK(synapse->executed, return FALSE);
69
CRM_CHECK(synapse->confirmed == FALSE, return TRUE);
73
action, crm_action_t, synapse->actions, lpc,
75
crm_debug_3("Processing action %d", action->id);
77
if(action->id == action_id) {
78
crm_debug_2("Confirmed: Action %d of Synapse %d",
79
action_id, synapse->id);
80
action->confirmed = TRUE;
83
} else if(action->confirmed == FALSE) {
85
crm_debug_3("Synapse %d still not confirmed after action %d",
86
synapse->id, action_id);
91
if(is_confirmed && synapse->confirmed == FALSE) {
92
crm_debug_2("Confirmed: Synapse %d", synapse->id);
93
synapse->confirmed = TRUE;
98
crm_debug_3("Updated synapse %d", synapse->id);
104
update_graph(crm_graph_t *graph, crm_action_t *action)
107
gboolean updates = FALSE;
109
synapse, synapse_t, graph->synapses, lpc,
110
if (synapse->confirmed) {
111
crm_debug_2("Synapse complete");
113
} else if (synapse->executed) {
114
crm_debug_2("Synapse executed");
115
rc = update_synapse_confirmed(synapse, action->id);
117
} else if(action->failed == FALSE) {
118
rc = update_synapse_ready(synapse, action->id);
120
updates = updates || rc;
124
crm_debug_2("Updated graph with completed action %d",
132
should_fire_synapse(synapse_t *synapse)
134
CRM_CHECK(synapse->executed == FALSE, return FALSE);
135
CRM_CHECK(synapse->confirmed == FALSE, return FALSE);
137
crm_debug_3("Checking pre-reqs for %d", synapse->id);
139
synapse->ready = TRUE;
141
prereq, crm_action_t, synapse->inputs, lpc,
143
crm_debug_3("Processing input %d", prereq->id);
144
if(prereq->confirmed == FALSE) {
145
crm_debug_3("Inputs for synapse %d not satisfied",
147
synapse->ready = FALSE;
152
return synapse->ready;
157
initiate_action(crm_graph_t *graph, crm_action_t *action)
159
const char *id = NULL;
160
int tmp_time = 2 * action->timeout;
162
CRM_CHECK(action->executed == FALSE, return FALSE);
164
id = ID(action->xml);
165
CRM_CHECK(id != NULL, return FALSE);
167
if(tmp_time > graph->transition_timeout) {
168
crm_debug("Action %d: Increasing IDLE timer to %d",
169
action->id, tmp_time);
170
graph->transition_timeout = tmp_time;
173
action->executed = TRUE;
174
if(action->type == action_type_pseudo){
175
crm_debug_2("Executing pseudo-event: %d", action->id);
176
return graph_fns->pseudo(graph, action);
178
} else if(action->type == action_type_rsc) {
179
crm_debug_2("Executing rsc-event: %d", action->id);
180
return graph_fns->rsc(graph, action);
182
} else if(action->type == action_type_crm) {
183
const char *task = NULL;
184
task = crm_element_value(action->xml, XML_LRM_ATTR_TASK);
185
CRM_CHECK(task != NULL, return FALSE);
187
if(safe_str_eq(task, CRM_OP_FENCE)) {
188
crm_debug_2("Executing STONITH-event: %d",
190
return graph_fns->stonith(graph, action);
193
crm_debug_2("Executing crm-event: %d", action->id);
194
return graph_fns->crmd(graph, action);
197
te_log_action(LOG_ERR,
198
"Failed on unsupported command type: %s (id=%s)",
199
crm_element_name(action->xml), id);
204
fire_synapse(crm_graph_t *graph, synapse_t *synapse)
206
CRM_CHECK(synapse != NULL, return FALSE);
207
CRM_CHECK(synapse->ready, return FALSE);
208
CRM_CHECK(synapse->confirmed == FALSE, return TRUE);
210
crm_debug_2("Synapse %d fired", synapse->id);
211
synapse->executed = TRUE;
213
action, crm_action_t, synapse->actions, lpc,
215
/* allow some leeway */
216
gboolean passed = FALSE;
218
/* Invoke the action and start the timer */
219
passed = initiate_action(graph, action);
220
if(passed == FALSE) {
221
crm_err("Failed initiating <%s id=%d> in synapse %d",
222
crm_element_name(action->xml),
223
action->id, synapse->id);
224
synapse->confirmed = TRUE;
225
action->confirmed = TRUE;
226
action->failed = TRUE;
235
run_graph(crm_graph_t *graph)
240
int num_complete = 0;
241
int num_incomplete = 0;
243
int stat_log_level = LOG_DEBUG;
244
int pass_result = transition_active;
246
if(graph_fns == NULL) {
247
set_default_graph_functions();
250
return transition_complete;
253
crm_debug_2("Entering graph %d callback", graph->id);
256
synapse, synapse_t, graph->synapses, lpc,
257
if (synapse->confirmed) {
258
crm_debug_3("Synapse %d complete", synapse->id);
261
} else if (synapse->executed) {
262
int pending_log = LOG_DEBUG_2;
263
if(synapse->priority > graph->abort_priority) {
264
pending_log = LOG_DEBUG_3;
266
do_crm_log(pending_log,
267
"Synapse %d: confirmation pending",
270
/* Is this running approximation good enough for batch_limit? */
273
} else if(synapse->priority < graph->abort_priority) {
274
crm_debug_2("Skipping synapse %d: aborting",
279
if(should_fire_synapse(synapse)) {
280
crm_debug_2("Synapse %d fired", synapse->id);
282
CRM_CHECK(fire_synapse(graph, synapse),
283
stat_log_level = LOG_ERR;
284
graph->abort_priority = INFINITY;
288
if (synapse->confirmed == FALSE) {
293
crm_debug_2("Synapse %d cannot fire",
299
if(graph->batch_limit > 0 && num_pending > graph->batch_limit) {
300
crm_info("Throttling output: batch limit (%d) reached",
306
if(num_pending == 0 && num_fired == 0) {
307
graph->complete = TRUE;
308
stat_log_level = LOG_INFO;
309
pass_result = transition_complete;
311
if(num_incomplete != 0 && graph->abort_priority <= 0) {
312
stat_log_level = LOG_WARNING;
313
pass_result = transition_terminated;
315
} else if(num_skipped != 0) {
316
stat_log_level = LOG_NOTICE;
319
} else if(num_fired == 0) {
320
pass_result = transition_pending;
324
do_crm_log(stat_log_level+1,
325
"====================================================");
326
do_crm_log(stat_log_level,
327
"Transition %d: (Complete=%d, Pending=%d,"
328
" Fired=%d, Skipped=%d, Incomplete=%d)",
329
graph->id, num_complete, num_pending, num_fired,
330
num_skipped, num_incomplete);