diff --git a/include/crm/transition.h b/include/crm/transition.h index 2bacb0fcbc..a55048e0c2 100644 --- a/include/crm/transition.h +++ b/include/crm/transition.h @@ -1,151 +1,151 @@ /* * 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 */ typedef enum { action_type_pseudo, action_type_rsc, action_type_crm } action_type_e; typedef struct te_timer_s crm_action_timer_t; typedef struct synapse_s { int id; int priority; gboolean ready; gboolean executed; gboolean confirmed; GListPtr actions; /* crm_action_t* */ GListPtr inputs; /* crm_action_t* */ } synapse_t; typedef struct crm_action_s { int id; int timeout; int interval; GHashTable *params; action_type_e type; crm_action_timer_t *timer; synapse_t *synapse; gboolean sent_update; /* sent to the CIB */ gboolean executed; /* sent to the CRM */ gboolean confirmed; gboolean failed; gboolean can_fail; xmlNode *xml; } crm_action_t; enum timer_reason { timeout_action, timeout_action_warn, timeout_abort, }; struct te_timer_s { int source_id; int timeout; enum timer_reason reason; crm_action_t *action; }; /* order matters here */ enum transition_action { + tg_done, tg_stop, - tg_abort, tg_restart, tg_shutdown, }; typedef struct crm_graph_s { int id; int abort_priority; gboolean complete; const char *abort_reason; enum transition_action completion_action; int num_actions; int num_synapses; int batch_limit; int network_delay; int transition_timeout; GListPtr synapses; /* synpase_t* */ } crm_graph_t; typedef struct crm_graph_functions_s { gboolean (*pseudo)(crm_graph_t *graph, crm_action_t *action); gboolean (*rsc)(crm_graph_t *graph, crm_action_t *action); gboolean (*crmd)(crm_graph_t *graph, crm_action_t *action); gboolean (*stonith)(crm_graph_t *graph, crm_action_t *action); } crm_graph_functions_t; enum transition_status { transition_active, transition_pending, /* active but no actions performed this time */ transition_complete, transition_stopped, transition_terminated, transition_action_failed, transition_failed, }; extern void set_default_graph_functions(void); extern void set_graph_functions(crm_graph_functions_t *fns); extern crm_graph_t *unpack_graph(xmlNode *xml_graph); extern int run_graph(crm_graph_t *graph); extern gboolean update_graph(crm_graph_t *graph, crm_action_t *action); extern void destroy_graph(crm_graph_t *graph); extern const char *transition_status(enum transition_status state); extern void print_graph(unsigned int log_level, crm_graph_t *graph); extern void print_action( int log_level, const char *prefix, crm_action_t *action); extern void update_abort_priority( crm_graph_t *graph, int priority, enum transition_action action, const char *abort_reason); extern const char *actiontype2text(action_type_e type); #ifdef TESTING # define te_log_action(log_level, fmt, args...) { \ do_crm_log(log_level, fmt, ##args); \ fprintf(stderr, fmt"\n", ##args); \ } #else # define te_log_action(log_level, fmt, args...) do_crm_log(log_level, fmt, ##args) #endif diff --git a/lib/crm/transition/unpack.c b/lib/crm/transition/unpack.c index c526a4d8da..9ef4470729 100644 --- a/lib/crm/transition/unpack.c +++ b/lib/crm/transition/unpack.c @@ -1,266 +1,267 @@ /* * 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 #include /* #include */ #include #include #include static crm_action_t* unpack_action(synapse_t *parent, xmlNode *xml_action) { crm_action_t *action = NULL; xmlNode *action_copy = NULL; const char *value = crm_element_value(xml_action, XML_ATTR_ID); if(value == NULL) { crm_err("Actions must have an id!"); crm_log_xml_debug_3(xml_action, "Action with missing id"); return NULL; } action_copy = copy_xml(xml_action); crm_malloc0(action, sizeof(crm_action_t)); if(action == NULL) { return NULL; } action->id = crm_parse_int(value, NULL); action->type = action_type_rsc; action->xml = action_copy; action->synapse = parent; if(safe_str_eq(crm_element_name(action_copy), XML_GRAPH_TAG_RSC_OP)) { action->type = action_type_rsc; } else if(safe_str_eq(crm_element_name(action_copy), XML_GRAPH_TAG_PSEUDO_EVENT)) { action->type = action_type_pseudo; } else if(safe_str_eq(crm_element_name(action_copy), XML_GRAPH_TAG_CRM_EVENT)) { action->type = action_type_crm; } action->params = xml2list(action_copy); value = g_hash_table_lookup(action->params, "CRM_meta_timeout"); if(value != NULL) { action->timeout = crm_parse_int(value, NULL); } value = g_hash_table_lookup(action->params, "CRM_meta_interval"); if(value != NULL) { action->interval = crm_parse_int(value, NULL); } value = g_hash_table_lookup(action->params, "CRM_meta_can_fail"); if(value != NULL) { cl_str_to_boolean(value, &(action->can_fail)); } crm_debug_3("Action %d has timer set to %dms", action->id, action->timeout); return action; } static synapse_t * unpack_synapse(crm_graph_t *new_graph, xmlNode *xml_synapse) { const char *value = NULL; synapse_t *new_synapse = NULL; CRM_CHECK(xml_synapse != NULL, return NULL); crm_debug_3("looking in synapse %s", ID(xml_synapse)); crm_malloc0(new_synapse, sizeof(synapse_t)); new_synapse->id = crm_parse_int(ID(xml_synapse), NULL); value = crm_element_value(xml_synapse, XML_CIB_ATTR_PRIORITY); if(value != NULL) { new_synapse->priority = crm_parse_int(value, NULL); } new_graph->num_synapses++; CRM_CHECK(new_synapse->id >= 0, crm_free(new_synapse); return NULL); crm_debug_3("look for actions in synapse %s", crm_element_value(xml_synapse, XML_ATTR_ID)); xml_child_iter_filter( xml_synapse, action_set, "action_set", xml_child_iter( action_set, action, crm_action_t *new_action = unpack_action( new_synapse, action); new_graph->num_actions++; if(new_action == NULL) { continue; } crm_debug_3("Adding action %d to synapse %d", new_action->id, new_synapse->id); new_synapse->actions = g_list_append( new_synapse->actions, new_action); ); ); crm_debug_3("look for inputs in synapse %s", ID(xml_synapse)); xml_child_iter_filter( xml_synapse, inputs, "inputs", xml_child_iter( inputs, trigger, xml_child_iter( trigger, input, crm_action_t *new_input = unpack_action( new_synapse, input); if(new_input == NULL) { continue; } crm_debug_3("Adding input %d to synapse %d", new_input->id, new_synapse->id); new_synapse->inputs = g_list_append( new_synapse->inputs, new_input); ); ); ); return new_synapse; } crm_graph_t * unpack_graph(xmlNode *xml_graph) { /* id = -1; new_graph->abort_priority = 0; new_graph->network_delay = -1; new_graph->transition_timeout = -1; + new_graph->completion_action = tg_done; if(xml_graph != NULL) { t_id = crm_element_value(xml_graph, "transition_id"); CRM_CHECK(t_id != NULL, crm_free(new_graph); return NULL); new_graph->id = crm_parse_int(t_id, "-1"); time = crm_element_value(xml_graph, "cluster-delay"); CRM_CHECK(time != NULL, crm_free(new_graph); return NULL); new_graph->network_delay = crm_get_msec(time); new_graph->transition_timeout = new_graph->network_delay; t_id = crm_element_value(xml_graph, "batch-limit"); new_graph->batch_limit = crm_parse_int(t_id, "0"); } xml_child_iter_filter( xml_graph, synapse, "synapse", synapse_t *new_synapse = unpack_synapse(new_graph, synapse); if(new_synapse != NULL) { new_graph->synapses = g_list_append( new_graph->synapses, new_synapse); } ); crm_info("Unpacked transition %d: %d actions in %d synapses", new_graph->id, new_graph->num_actions,new_graph->num_synapses); return new_graph; } static void destroy_action(crm_action_t *action) { if(action->timer && action->timer->source_id != 0) { crm_warn("Cancelling timer for action %d (src=%d)", action->id, action->timer->source_id); Gmain_timeout_remove(action->timer->source_id); } g_hash_table_destroy(action->params); free_xml(action->xml); crm_free(action->timer); crm_free(action); } static void destroy_synapse(synapse_t *synapse) { while(g_list_length(synapse->actions) > 0) { crm_action_t *action = g_list_nth_data(synapse->actions, 0); synapse->actions = g_list_remove(synapse->actions, action); destroy_action(action); } while(g_list_length(synapse->inputs) > 0) { crm_action_t *action = g_list_nth_data(synapse->inputs, 0); synapse->inputs = g_list_remove(synapse->inputs, action); destroy_action(action); } crm_free(synapse); } void destroy_graph(crm_graph_t *graph) { if(graph == NULL) { return; } while(g_list_length(graph->synapses) > 0) { synapse_t *synapse = g_list_nth_data(graph->synapses, 0); graph->synapses = g_list_remove(graph->synapses, synapse); destroy_synapse(synapse); } crm_free(graph); }