diff --git a/lib/crm/transition/graph.c b/lib/crm/transition/graph.c index 04072df22b..253c2ab368 100644 --- a/lib/crm/transition/graph.c +++ b/lib/crm/transition/graph.c @@ -1,316 +1,318 @@ -/* $Id: graph.c,v 1.12 2006/04/27 11:27:48 andrew Exp $ */ +/* $Id: graph.c,v 1.13 2006/05/08 09:58:57 andrew Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include /* #include */ /* #include */ crm_graph_functions_t *graph_fns = NULL; static gboolean update_synapse_ready(synapse_t *synapse, int action_id) { gboolean updates = FALSE; CRM_CHECK(synapse->executed == FALSE, return FALSE); CRM_CHECK(synapse->confirmed == FALSE, return FALSE); synapse->ready = TRUE; slist_iter( prereq, crm_action_t, synapse->inputs, lpc, crm_debug_3("Processing input %d", prereq->id); if(prereq->id == action_id) { crm_debug_2("Marking input %d of synapse %d confirmed", action_id, synapse->id); prereq->confirmed = TRUE; updates = TRUE; } else if(prereq->confirmed == FALSE) { synapse->ready = FALSE; } ); if(updates) { crm_debug_2("Updated synapse %d", synapse->id); } return updates; } static gboolean update_synapse_confirmed(synapse_t *synapse, int action_id) { gboolean updates = FALSE; gboolean is_confirmed = TRUE; CRM_CHECK(synapse->executed, return FALSE); CRM_CHECK(synapse->confirmed == FALSE, return TRUE); is_confirmed = TRUE; slist_iter( action, crm_action_t, synapse->actions, lpc, crm_debug_3("Processing action %d", action->id); if(action->id == action_id) { crm_debug_2("Confirmed: Action %d of Synapse %d", action_id, synapse->id); action->confirmed = TRUE; updates = TRUE; } else if(action->confirmed == FALSE) { is_confirmed = FALSE; crm_debug_3("Synapse %d still not confirmed after action %d", synapse->id, action_id); } ); if(is_confirmed && synapse->confirmed == FALSE) { crm_debug_2("Confirmed: Synapse %d", synapse->id); synapse->confirmed = TRUE; updates = TRUE; } if(updates) { crm_debug_3("Updated synapse %d", synapse->id); } return updates; } gboolean update_graph(crm_graph_t *graph, crm_action_t *action) { gboolean rc = FALSE; gboolean updates = FALSE; slist_iter( synapse, synapse_t, graph->synapses, lpc, if (synapse->confirmed) { crm_debug_2("Synapse complete"); } else if (synapse->executed) { crm_debug_2("Synapse executed"); rc = update_synapse_confirmed(synapse, action->id); } else if(action->failed == FALSE) { rc = update_synapse_ready(synapse, action->id); } updates = updates || rc; ); if(updates) { crm_debug_2("Updated graph with completed action %d", action->id); } return updates; } static gboolean should_fire_synapse(synapse_t *synapse) { CRM_CHECK(synapse->executed == FALSE, return FALSE); CRM_CHECK(synapse->confirmed == FALSE, return FALSE); crm_debug_3("Checking pre-reqs for %d", synapse->id); /* lookup prereqs */ synapse->ready = TRUE; slist_iter( prereq, crm_action_t, synapse->inputs, lpc, crm_debug_3("Processing input %d", prereq->id); if(prereq->confirmed == FALSE) { crm_debug_3("Inputs for synapse %d not satisfied", synapse->id); synapse->ready = FALSE; break; } ); return synapse->ready; } static gboolean initiate_action(crm_graph_t *graph, crm_action_t *action) { const char *id = NULL; int tmp_time = 2 * action->timeout; CRM_CHECK(action->executed == FALSE, return FALSE); id = ID(action->xml); CRM_CHECK(id != NULL, return FALSE); if(tmp_time > graph->transition_timeout) { crm_debug("Action %d: Increasing IDLE timer to %d", action->id, tmp_time); graph->transition_timeout = tmp_time; } action->executed = TRUE; if(action->type == action_type_pseudo){ crm_debug_2("Executing pseudo-event: %d", action->id); return graph_fns->pseudo(graph, action); } else if(action->type == action_type_rsc) { crm_debug_2("Executing rsc-event: %d", action->id); return graph_fns->rsc(graph, action); } else if(action->type == action_type_crm) { const char *task = NULL; task = crm_element_value(action->xml, XML_LRM_ATTR_TASK); CRM_CHECK(task != NULL, return FALSE); if(safe_str_eq(task, CRM_OP_FENCE)) { crm_debug_2("Executing STONITH-event: %d", action->id); return graph_fns->stonith(graph, action); } crm_debug_2("Executing crm-event: %d", action->id); return graph_fns->crmd(graph, action); } te_log_action(LOG_ERR, "Failed on unsupported command type: %s (id=%s)", crm_element_name(action->xml), id); return FALSE; } static gboolean fire_synapse(crm_graph_t *graph, synapse_t *synapse) { CRM_CHECK(synapse != NULL, return FALSE); CRM_CHECK(synapse->ready, return FALSE); CRM_CHECK(synapse->confirmed == FALSE, return TRUE); crm_debug_2("Synapse %d fired", synapse->id); synapse->executed = TRUE; slist_iter( action, crm_action_t, synapse->actions, lpc, /* allow some leeway */ gboolean passed = FALSE; /* Invoke the action and start the timer */ passed = initiate_action(graph, action); if(passed == FALSE) { crm_err("Failed initiating <%s id=%d> in synapse %d", crm_element_name(action->xml), action->id, synapse->id); return FALSE; } ); return TRUE; } int run_graph(crm_graph_t *graph) { int num_fired = 0; int num_pending = 0; int num_skipped = 0; int num_complete = 0; int num_incomplete = 0; int stat_log_level = LOG_DEBUG; int pass_result = transition_active; if(graph_fns == NULL) { set_default_graph_functions(); } if(graph == NULL) { return transition_complete; } crm_debug_2("Entering graph %d callback", graph->id); slist_iter( synapse, synapse_t, graph->synapses, lpc, if (synapse->confirmed) { crm_debug_3("Synapse %d complete", synapse->id); num_complete++; } else if (synapse->executed) { int pending_log = LOG_DEBUG_2; if(synapse->priority > graph->abort_priority) { pending_log = LOG_DEBUG_3; } crm_log_maybe(pending_log, "Synapse %d: confirmation pending", synapse->id); num_pending++; } else if(synapse->priority < graph->abort_priority) { crm_debug_2("Skipping synapse %d: aborting", synapse->id); num_skipped++; } else { crm_debug_2("Synapse %d pending", synapse->id); if(should_fire_synapse(synapse)) { if(fire_synapse(graph, synapse) == FALSE) { return transition_failed; } num_fired++; } else { + crm_debug_2("Synapse %d cannot fire", + synapse->id); num_incomplete++; } } ); if(num_pending == 0 && num_fired == 0) { graph->complete = TRUE; stat_log_level = LOG_INFO; pass_result = transition_complete; - if(num_incomplete != 0) { + if(num_incomplete != 0 && graph->abort_priority <= 0) { stat_log_level = LOG_WARNING; pass_result = transition_terminated; } else if(num_skipped != 0) { stat_log_level = LOG_NOTICE; } } else if(num_fired == 0) { pass_result = transition_pending; } crm_log_maybe(stat_log_level+1, "===================================================="); crm_log_maybe(stat_log_level, "Transition %d: (Complete=%d, Pending=%d," " Fired=%d, Skipped=%d, Incomplete=%d)", graph->id, num_complete, num_pending, num_fired, num_skipped, num_incomplete); return pass_result; }