commit f3dea7908cfcc61e83b765b8bda68f6ce1ba31d3 Author: Gao,Yan Date: Fri Mar 23 11:40:56 2012 +0800 High: PE: Move the ticket state section to "/cib/status/tickets/ticket_state" Move the ticket state section: --- "/cib/status/tickets/instance_attributes" +++ "/cib/status/tickets/ticket_state" Pengine still recognizes the deprecated section. If there's any attribute appears in the new tickets_state section, it'll take over precedence over the one in the deprecated section. Actually, even more, once crm_ticket is invoked to set an attribute, it'll clear the one in the deprecated section. Index: pacemaker/include/crm/msg_xml.h =================================================================== --- pacemaker.orig/include/crm/msg_xml.h +++ pacemaker/include/crm/msg_xml.h @@ -297,7 +297,8 @@ # define XML_ACL_ATTR_XPATH "xpath" # define XML_ACL_ATTR_ATTRIBUTE "attribute" -# define XML_CIB_TAG_TICKETS "tickets" +# define XML_CIB_TAG_TICKETS "tickets" +# define XML_CIB_TAG_TICKET_STATE "ticket_state" # include Index: pacemaker/include/crm/pengine/status.h =================================================================== --- pacemaker.orig/include/crm/pengine/status.h +++ pacemaker/include/crm/pengine/status.h @@ -294,6 +294,8 @@ struct ticket_s { char *id; gboolean granted; time_t last_granted; + gboolean standby; + GHashTable *state; }; gboolean cluster_status(pe_working_set_t * data_set); Index: pacemaker/lib/pengine/unpack.c =================================================================== --- pacemaker.orig/lib/pengine/unpack.c +++ pacemaker/lib/pengine/unpack.c @@ -412,10 +412,95 @@ unpack_resources(xmlNode * xml_resources return TRUE; } +/* The ticket state section: + * "/cib/status/tickets/ticket_state" */ +static gboolean +unpack_ticket_state(xmlNode * xml_ticket, pe_working_set_t * data_set) +{ + const char *ticket_id = NULL; + const char *granted = NULL; + const char *last_granted = NULL; + const char *standby = NULL; + xmlAttrPtr xIter = NULL; + + ticket_t *ticket = NULL; + + ticket_id = ID(xml_ticket); + if (ticket_id == NULL || strlen(ticket_id) == 0) { + return FALSE; + } + + crm_trace("Processing ticket state for %s", ticket_id); + + ticket = g_hash_table_lookup(data_set->tickets, ticket_id); + if (ticket == NULL) { + ticket = ticket_new(ticket_id, data_set); + if (ticket == NULL) { + return FALSE; + } + } + + for (xIter = xml_ticket->properties; xIter; xIter = xIter->next) { + const char *prop_name = (const char *)xIter->name; + const char *prop_value = crm_element_value(xml_ticket, prop_name); + + if(crm_str_eq(prop_name, XML_ATTR_ID, TRUE)) { + continue; + } + g_hash_table_replace(ticket->state, crm_strdup(prop_name), crm_strdup(prop_value)); + } + + granted = g_hash_table_lookup(ticket->state, "granted"); + if (granted && crm_is_true(granted)) { + ticket->granted = TRUE; + crm_info("We have ticket '%s'", ticket->id); + } else { + ticket->granted = FALSE; + crm_info("We do not have ticket '%s'", ticket->id); + } + + last_granted = g_hash_table_lookup(ticket->state, "last-granted"); + if (last_granted) { + ticket->last_granted = crm_parse_int(last_granted, 0); + } + + standby = g_hash_table_lookup(ticket->state, "standby"); + if (standby && crm_is_true(standby)) { + ticket->standby = TRUE; + if (ticket->granted) { + crm_info("Granted ticket '%s' is in standby-mode", ticket->id); + } + } else { + ticket->standby = FALSE; + } + + crm_trace("Done with ticket state for %s", ticket_id); + + return TRUE; +} + +static gboolean +unpack_tickets_state(xmlNode * xml_tickets, pe_working_set_t * data_set) +{ + xmlNode *xml_obj = NULL; + + for (xml_obj = __xml_first_child(xml_tickets); xml_obj != NULL; xml_obj = __xml_next(xml_obj)) { + if (crm_str_eq((const char *)xml_obj->name, XML_CIB_TAG_TICKET_STATE, TRUE) == FALSE) { + continue; + } + unpack_ticket_state(xml_obj, data_set); + } + + return TRUE; +} + +/* Compatibility with the deprecated ticket state section: + * "/cib/status/tickets/instance_attributes" */ static void -get_ticket_state(gpointer key, gpointer value, gpointer user_data) +get_ticket_state_legacy(gpointer key, gpointer value, gpointer user_data) { - const char *attr_key = key; + const char *long_key = key; + char *state_key = NULL; const char *granted_prefix = "granted-ticket-"; const char *last_granted_prefix = "last-granted-"; @@ -425,9 +510,10 @@ get_ticket_state(gpointer key, gpointer const char *ticket_id = NULL; const char *is_granted = NULL; const char *last_granted = NULL; + const char *sep = NULL; ticket_t *ticket = NULL; - GHashTable *tickets = user_data; + pe_working_set_t *data_set = user_data; if (granted_prefix_strlen == 0) { granted_prefix_strlen = strlen(granted_prefix); @@ -437,37 +523,41 @@ get_ticket_state(gpointer key, gpointer last_granted_prefix_strlen = strlen(last_granted_prefix); } - if (strstr(attr_key, granted_prefix) == attr_key) { - ticket_id = attr_key + granted_prefix_strlen; + if (strstr(long_key, granted_prefix) == long_key) { + ticket_id = long_key + granted_prefix_strlen; if (strlen(ticket_id)) { + state_key = crm_strdup("granted"); is_granted = value; } - } else if (strstr(attr_key, last_granted_prefix) == attr_key) { - ticket_id = attr_key + last_granted_prefix_strlen; + } else if (strstr(long_key, last_granted_prefix) == long_key) { + ticket_id = long_key + last_granted_prefix_strlen; if (strlen(ticket_id)) { + state_key = crm_strdup("last-granted"); last_granted = value; } + } else if ((sep = strrchr(long_key, '-'))) { + ticket_id = sep + 1; + state_key = strndup(long_key, strlen(long_key) - strlen(sep)); } if (ticket_id == NULL || strlen(ticket_id) == 0) { return; } - ticket = g_hash_table_lookup(tickets, ticket_id); + if (state_key == NULL || strlen(state_key) == 0) { + return; + } + + ticket = g_hash_table_lookup(data_set->tickets, ticket_id); if (ticket == NULL) { - crm_malloc0(ticket, sizeof(ticket_t)); + ticket = ticket_new(ticket_id, data_set); if (ticket == NULL) { - crm_config_err("Cannot allocate ticket '%s'", ticket_id); return; } - - ticket->id = crm_strdup(ticket_id); - ticket->granted = FALSE; - ticket->last_granted = -1; - - g_hash_table_insert(tickets, crm_strdup(ticket->id), ticket); } + g_hash_table_replace(ticket->state, state_key, crm_strdup(value)); + if (is_granted) { if (crm_is_true(is_granted)) { ticket->granted = TRUE; @@ -482,15 +572,6 @@ get_ticket_state(gpointer key, gpointer } } -static void -destroy_ticket(gpointer data) -{ - ticket_t *ticket = data; - - crm_free(ticket->id); - crm_free(ticket); -} - /* remove nodes that are down, stopping */ /* create +ve rsc_to_node constraints between resources and the nodes they are running on */ /* anything else? */ @@ -508,24 +589,32 @@ unpack_status(xmlNode * status, pe_worki crm_debug_3("Beginning unpack"); - data_set->tickets = - g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, destroy_ticket); + if (data_set->tickets == NULL) { + data_set->tickets = + g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, destroy_ticket); + } for (state = __xml_first_child(status); state != NULL; state = __xml_next(state)) { if (crm_str_eq((const char *)state->name, XML_CIB_TAG_TICKETS, TRUE)) { - xmlNode *tickets = state; - GHashTable *attrs_hash = - g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, + xmlNode *xml_tickets = state; + GHashTable *state_hash = NULL; + + /* Compatibility with the deprecated ticket state section: + * Unpack the attributes in the deprecated "/cib/status/tickets/instance_attributes" if it exists. */ + state_hash = g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, g_hash_destroy_str); - unpack_instance_attributes(data_set->input, tickets, XML_TAG_ATTR_SETS, NULL, - attrs_hash, NULL, TRUE, data_set->now); + unpack_instance_attributes(data_set->input, xml_tickets, XML_TAG_ATTR_SETS, NULL, + state_hash, NULL, TRUE, data_set->now); - g_hash_table_foreach(attrs_hash, get_ticket_state, data_set->tickets); + g_hash_table_foreach(state_hash, get_ticket_state_legacy, data_set); - if (attrs_hash) { - g_hash_table_destroy(attrs_hash); + if (state_hash) { + g_hash_table_destroy(state_hash); } + + /* Unpack the new "/cib/status/tickets/ticket_state"s */ + unpack_tickets_state(xml_tickets, data_set); } if (crm_str_eq((const char *)state->name, XML_CIB_TAG_STATE, TRUE)) { Index: pacemaker/lib/pengine/utils.c =================================================================== --- pacemaker.orig/lib/pengine/utils.c +++ pacemaker/lib/pengine/utils.c @@ -1373,3 +1373,53 @@ get_target_role(resource_t * rsc, enum r *role = local_role; return TRUE; } + +void +destroy_ticket(gpointer data) +{ + ticket_t *ticket = data; + + if (ticket->state) { + g_hash_table_destroy(ticket->state); + } + crm_free(ticket->id); + crm_free(ticket); +} + +ticket_t * +ticket_new(const char *ticket_id, pe_working_set_t * data_set) +{ + ticket_t *ticket = NULL; + + if (ticket_id == NULL || strlen(ticket_id) == 0) { + return NULL; + } + + if (data_set->tickets == NULL) { + data_set->tickets = + g_hash_table_new_full(crm_str_hash, g_str_equal, g_hash_destroy_str, destroy_ticket); + } + + ticket = g_hash_table_lookup(data_set->tickets, ticket_id); + if (ticket == NULL) { + + crm_malloc0(ticket, sizeof(ticket_t)); + if (ticket == NULL) { + crm_err("Cannot allocate ticket '%s'", ticket_id); + return NULL; + } + + crm_trace("Creaing ticket entry for %s", ticket_id); + + ticket->id = crm_strdup(ticket_id); + ticket->granted = FALSE; + ticket->last_granted = -1; + ticket->standby = FALSE; + ticket->state = g_hash_table_new_full(crm_str_hash, g_str_equal, + g_hash_destroy_str, g_hash_destroy_str); + + g_hash_table_insert(data_set->tickets, crm_strdup(ticket->id), ticket); + } + + return ticket; +} Index: pacemaker/lib/pengine/utils.h =================================================================== --- pacemaker.orig/lib/pengine/utils.h +++ pacemaker/lib/pengine/utils.h @@ -162,4 +162,7 @@ extern gboolean get_target_role(resource extern resource_t *find_clone_instance(resource_t * rsc, const char *sub_id, pe_working_set_t * data_set); +extern void destroy_ticket(gpointer data); +extern ticket_t *ticket_new(const char * ticket_id, pe_working_set_t * data_set); + #endif Index: pacemaker/pengine/constraints.c =================================================================== --- pacemaker.orig/pengine/constraints.c +++ pacemaker/pengine/constraints.c @@ -2000,17 +2000,10 @@ unpack_rsc_ticket(xmlNode * xml_obj, pe_ } if (ticket == NULL) { - crm_malloc0(ticket, sizeof(ticket_t)); + ticket = ticket_new(ticket_str, data_set); if (ticket == NULL) { - crm_config_err("Cannot allocate ticket '%s'", ticket_str); return FALSE; } - - ticket->id = crm_strdup(ticket_str); - ticket->granted = FALSE; - ticket->last_granted = -1; - - g_hash_table_insert(data_set->tickets, crm_strdup(ticket->id), ticket); } unpack_rsc_ticket_template(xml_obj, &expanded_xml, data_set);