Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/crm/cib/io.c b/crm/cib/io.c
index 5af16f24c6..fc0b65d2a5 100644
--- a/crm/cib/io.c
+++ b/crm/cib/io.c
@@ -1,527 +1,528 @@
-/* $Id: io.c,v 1.28 2005/07/11 12:13:07 andrew Exp $ */
+/* $Id: io.c,v 1.29 2005/08/17 09:03:23 andrew Exp $ */
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* 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 <portability.h>
#include <sys/param.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <heartbeat.h>
#include <crm/crm.h>
#include <cibio.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/xml.h>
#include <crm/common/util.h>
+#include <clplumbing/cl_misc.h>
#include <cibprimatives.h>
#include <crm/dmalloc_wrapper.h>
const char * local_resource_path[] =
{
XML_CIB_TAG_STATUS,
};
const char * resource_path[] =
{
XML_CIB_TAG_RESOURCES,
};
const char * node_path[] =
{
XML_CIB_TAG_NODES,
};
const char * constraint_path[] =
{
XML_CIB_TAG_CONSTRAINTS,
};
gboolean initialized = FALSE;
crm_data_t *the_cib = NULL;
crm_data_t *node_search = NULL;
crm_data_t *resource_search = NULL;
crm_data_t *constraint_search = NULL;
crm_data_t *status_search = NULL;
gboolean cib_writes_enabled = TRUE;
extern char *ccm_transition_id;
extern gboolean cib_have_quorum;
extern GHashTable *peer_hash;
int set_connected_peers(crm_data_t *xml_obj);
void GHFunc_count_peers(gpointer key, gpointer value, gpointer user_data);
/*
* It is the callers responsibility to free the output of this function
*/
crm_data_t*
readCibXml(char *buffer)
{
crm_data_t *root = NULL;
if(buffer != NULL) {
root = string2xml(buffer);
}
do_id_check(root);
if (verifyCibXml(root) == FALSE) {
free_xml(root);
root = createEmptyCib();
crm_xml_add(root, XML_ATTR_GENERATION_ADMIN, "0");
crm_xml_add(root, XML_ATTR_GENERATION, "0");
crm_xml_add(root, XML_ATTR_NUMUPDATES, "0");
}
return root;
}
/*
* It is the callers responsibility to free the output of this function
*/
crm_data_t*
readCibXmlFile(const char *filename)
{
int s_res = -1;
struct stat buf;
crm_data_t *root = NULL;
if(filename != NULL) {
s_res = stat(filename, &buf);
}
if (s_res == 0) {
FILE *cib_file = fopen(filename, "r");
root = file2xml(cib_file);
crm_xml_add(root, "generated", XML_BOOLEAN_FALSE);
fclose(cib_file);
} else {
crm_warn("Stat of (%s) failed, file does not exist.",
CIB_FILENAME);
}
if(root != NULL) {
int lpc = 0;
const char *value = NULL;
const char *name = NULL;
crm_data_t *status = get_object_root(XML_CIB_TAG_STATUS, root);
for (; status != NULL && lpc < status->nfields; ) {
if(status->types[lpc] != FT_STRUCT) {
lpc++;
continue;
}
CRM_DEV_ASSERT(cl_msg_remove_offset(status, lpc) == HA_OK);
/* dont get stuck in an infinite loop */
if(crm_assert_failed) {
lpc++;
}
}
name = XML_ATTR_GENERATION_ADMIN;
value = crm_element_value(root, name);
if(value == NULL) {
crm_xml_add(root, name, "0");
}
name = XML_ATTR_GENERATION;
value = crm_element_value(root, name);
if(value == NULL) {
crm_xml_add(root, name, "0");
}
name = XML_ATTR_NUMUPDATES;
value = crm_element_value(root, name);
if(value == NULL) {
crm_xml_add(root, name, "0");
}
do_id_check(root);
}
if (verifyCibXml(root) == FALSE) {
free_xml(root);
root = NULL;
}
return root;
}
/*
* The caller should never free the return value
*/
crm_data_t*
get_the_CIB(void)
{
return the_cib;
}
gboolean
uninitializeCib(void)
{
crm_data_t *tmp_cib = the_cib;
if(tmp_cib == NULL) {
crm_err("The CIB has already been deallocated.");
return FALSE;
}
initialized = FALSE;
the_cib = NULL;
node_search = NULL;
resource_search = NULL;
constraint_search = NULL;
status_search = NULL;
crm_err("Deallocating the CIB.");
free_xml(tmp_cib);
crm_err("The CIB has been deallocated.");
return TRUE;
}
/*
* This method will not free the old CIB pointer or the new one.
* We rely on the caller to have saved a pointer to the old CIB
* and to free the old/bad one depending on what is appropriate.
*/
gboolean
initializeCib(crm_data_t *new_cib)
{
#if 0
if(new_cib != NULL) {
crm_set_element_parent(new_cib, NULL);
}
#endif
if (verifyCibXml(new_cib)) {
initialized = FALSE;
the_cib = new_cib;
/* update search paths */
/* not used yet...
node_search =
get_object_root(XML_CIB_TAG_NODES, new_cib);
resource_search =
get_object_root(XML_CIB_TAG_RESOURCES, new_cib);
constraint_search =
get_object_root(XML_CIB_TAG_CONSTRAINTS, new_cib);
status_search =
get_object_root(XML_CIB_TAG_STATUS, new_cib);
*/
initialized = TRUE;
}
if(initialized == FALSE) {
crm_warn("CIB Verification failed");
the_cib = NULL;
} else {
const char *option = "suppress_cib_writes";
const char *value = NULL;
crm_data_t *config = get_object_root(
XML_CIB_TAG_CRMCONFIG, new_cib);
crm_data_t * a_default = find_entity(
config, XML_CIB_TAG_NVPAIR, option);
if(a_default != NULL) {
value = crm_element_value(
a_default, XML_NVPAIR_ATTR_VALUE);
}
if(value == NULL) {
crm_warn("Option %s not set", option);
if(cib_writes_enabled == FALSE) {
crm_debug("Disk writes to %s enabled",
CIB_FILENAME);
}
cib_writes_enabled = TRUE;
} else {
gboolean suppress = FALSE;
- crm_str_to_boolean(value, &suppress);
+ cl_str_to_boolean(value, &suppress);
if(cib_writes_enabled == suppress) {
cib_writes_enabled = !suppress;
if(cib_writes_enabled) {
crm_debug("Disk writes to %s enabled",
CIB_FILENAME);
} else {
crm_notice("Disabling CIB disk writes");
}
}
}
crm_debug_2("Disk writes to %s %s", CIB_FILENAME,
cib_writes_enabled?"enabled":"DISABLED");
set_connected_peers(the_cib);
set_transition(the_cib);
if(cib_have_quorum) {
crm_xml_add(
the_cib,XML_ATTR_HAVE_QUORUM,XML_BOOLEAN_TRUE);
} else {
crm_xml_add(
the_cib,XML_ATTR_HAVE_QUORUM,XML_BOOLEAN_FALSE);
}
}
return initialized;
}
int
moveFile(const char *oldname,
const char *newname,
gboolean backup,
char *ext)
{
/* move 'oldname' to 'newname' by creating a hard link to it
* and then removing the original hard link
*/
int res = 0;
struct stat tmp;
int s_res = stat(newname, &tmp);
if (s_res >= 0)
{
if (backup == TRUE) {
char backname[1024];
static const char *back_ext = "bak";
if (ext != NULL) { back_ext = (char*)ext; }
snprintf(backname, sizeof(backname)-1,
"%s.%s", newname, back_ext);
moveFile(newname, backname, FALSE, NULL);
} else {
res = unlink(newname);
if (res < 0) {
perror("Could not remove the current backup of Cib");
return -1;
}
}
}
s_res = stat(oldname, &tmp);
if (s_res >= 0) {
res = link(oldname, newname);
if (res < 0) {
perror("Could not create backup of current Cib");
return -2;
}
res = unlink(oldname);
if (res < 0) {
perror("Could not unlink the current Cib");
return -3;
}
}
return 0;
}
int
activateCibBuffer(char *buffer, const char *filename)
{
int result = -1;
crm_data_t *local_cib = NULL;
local_cib = readCibXml(buffer);
result = activateCibXml(local_cib, filename);
return result;
}
/*
* This method will free the old CIB pointer on success and the new one
* on failure.
*/
#define ACTIVATION_DIFFS 0
int
activateCibXml(crm_data_t *new_cib, const char *filename)
{
int error_code = cib_ok;
crm_data_t *diff = NULL;
crm_data_t *saved_cib = get_the_CIB();
const char *filename_bak = CIB_BACKUP; /* calculate */
crm_log_xml_debug_3(new_cib, "Attempting to activate CIB");
CRM_ASSERT(new_cib != saved_cib);
crm_validate_data(new_cib);
if(saved_cib != NULL) {
crm_validate_data(saved_cib);
}
if (initializeCib(new_cib) == FALSE) {
crm_warn("Ignoring invalid or NULL Cib");
error_code = -5;
} else if(cib_writes_enabled) {
if(saved_cib != NULL) {
CRM_DEV_ASSERT(0 >= moveFile(filename,
filename_bak,
FALSE, NULL));
if (crm_assert_failed) {
crm_warn("Could not make backup of the current"
" Cib... aborting update.");
error_code = -1;
}
}
if(error_code == cib_ok) {
crm_debug_3("Writing CIB out to %s", CIB_FILENAME);
CRM_DEV_ASSERT(new_cib != NULL);
CRM_DEV_ASSERT(write_xml_file(
new_cib, CIB_FILENAME) >= 0);
if (crm_assert_failed) {
error_code = -4;
}
}
if(error_code == -4 && saved_cib != NULL) {
CRM_DEV_ASSERT(moveFile(filename_bak,
filename, FALSE, NULL) >= 0);
if (crm_assert_failed){
crm_crit("Could not restore the backup of the "
" current Cib... panic!");
error_code = -2;
/* should probably exit here */
}
}
CRM_DEV_ASSERT(saved_cib != NULL || error_code == cib_ok);
if(crm_assert_failed) {
/* oh we are so dead */
crm_crit("Could not write out new CIB and no saved"
" version to revert to");
error_code = -3;
} else if(error_code != cib_ok) {
crm_crit("Update of Cib failed (%d)... reverting"
" to last known valid version",
error_code);
CRM_DEV_ASSERT(initializeCib(saved_cib));
if (crm_assert_failed) {
/* oh we are so dead */
crm_crit("Could not re-initialize with the old"
" CIB. Can anyone say corruption?");
error_code = -3;
}
}
}
#if ACTIVATION_DIFFS
/* Make sure memory is cleaned up appropriately */
if(saved_cib != NULL && new_cib != NULL) {
diff = diff_cib_object(saved_cib, new_cib, -1);
}
if (error_code != cib_ok) {
crm_err("Changes could not be activated: %s",
cib_error2string(error_code));
log_cib_diff(LOG_WARNING, diff, __FUNCTION__);
free_xml(new_cib);
} else if(saved_cib != NULL) {
crm_debug_2("Changes activated");
log_cib_diff(LOG_DEBUG, diff, __FUNCTION__);
crm_validate_data(saved_cib);
free_xml(saved_cib);
}
free_xml(diff);
#else
if (error_code != cib_ok) {
crm_err("Changes could not be activated: %s",
cib_error2string(error_code));
free_xml(new_cib);
} else if(saved_cib != NULL) {
crm_debug_2("Changes activated");
crm_validate_data(saved_cib);
free_xml(saved_cib);
}
#endif
diff = NULL;
return error_code;
}
void
set_transition(crm_data_t *xml_obj)
{
const char *current = crm_element_value(
xml_obj, XML_ATTR_CCM_TRANSITION);
if(safe_str_neq(current, ccm_transition_id)) {
crm_debug("Set transition to %s", ccm_transition_id);
crm_xml_add(the_cib, XML_ATTR_CCM_TRANSITION,ccm_transition_id);
}
}
int
set_connected_peers(crm_data_t *xml_obj)
{
int active = 0;
int current = 0;
char *peers_s = NULL;
const char *current_s = crm_element_value(
xml_obj, XML_ATTR_NUMPEERS);
g_hash_table_foreach(peer_hash, GHFunc_count_peers, &active);
current = crm_atoi(current_s, "0");
if(current != active) {
peers_s = crm_itoa(active);
crm_xml_add(xml_obj, XML_ATTR_NUMPEERS, peers_s);
crm_debug("Set peers to %s", peers_s);
crm_free(peers_s);
}
return active;
}
void GHFunc_count_peers(gpointer key, gpointer value, gpointer user_data)
{
int *active = user_data;
if(safe_str_eq(value, ONLINESTATUS)) {
(*active)++;
} else if(safe_str_eq(value, JOINSTATUS)) {
(*active)++;
}
}
diff --git a/crm/pengine/stages.c b/crm/pengine/stages.c
index 52d3294b75..9d38afb771 100644
--- a/crm/pengine/stages.c
+++ b/crm/pengine/stages.c
@@ -1,459 +1,460 @@
-/* $Id: stages.c,v 1.71 2005/08/03 14:54:27 andrew Exp $ */
+/* $Id: stages.c,v 1.72 2005/08/17 09:03:24 andrew Exp $ */
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* 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 <portability.h>
#include <sys/param.h>
#include <crm/crm.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/xml.h>
#include <crm/common/msg.h>
+#include <clplumbing/cl_misc.h>
#include <glib.h>
#include <pengine.h>
#include <pe_utils.h>
node_t *choose_fencer(action_t *stonith, node_t *node, GListPtr resources);
void order_actions(action_t *lh, action_t *rh, order_constraint_t *order);
const char* transition_idle_timeout = NULL;
/*
* Unpack everything
* At the end you'll have:
* - A list of nodes
* - A list of resources (each with any dependencies on other resources)
* - A list of constraints between resources and nodes
* - A list of constraints between start/stop actions
* - A list of nodes that need to be stonith'd
* - A list of nodes that need to be shutdown
* - A list of the possible stop/start actions (without dependencies)
*/
gboolean
stage0(pe_working_set_t *data_set)
{
/* int lpc; */
crm_data_t * config = get_object_root(
XML_CIB_TAG_CRMCONFIG, data_set->input);
crm_data_t * cib_nodes = get_object_root(
XML_CIB_TAG_NODES, data_set->input);
crm_data_t * cib_resources = get_object_root(
XML_CIB_TAG_RESOURCES, data_set->input);
crm_data_t * cib_status = get_object_root(
XML_CIB_TAG_STATUS, data_set->input);
crm_data_t * cib_constraints = get_object_root(
XML_CIB_TAG_CONSTRAINTS, data_set->input);
const char *value = crm_element_value(
data_set->input, XML_ATTR_HAVE_QUORUM);
crm_debug_3("Beginning unpack");
/* reset remaining global variables */
transition_idle_timeout = "60s"; /* 1 minute */
if(data_set->input == NULL) {
return FALSE;
}
if(data_set->input != NULL
&& crm_element_value(data_set->input, XML_ATTR_DC_UUID) != NULL) {
/* this should always be present */
data_set->dc_uuid = crm_element_value_copy(
data_set->input, XML_ATTR_DC_UUID);
}
unpack_config(config, data_set);
if(value != NULL) {
- crm_str_to_boolean(value, &data_set->have_quorum);
+ cl_str_to_boolean(value, &data_set->have_quorum);
}
if(data_set->have_quorum == FALSE
&& data_set->no_quorum_policy != no_quorum_ignore) {
crm_warn("We do not have quorum"
" - fencing and resource management disabled");
}
unpack_nodes(cib_nodes, data_set);
unpack_resources(cib_resources, data_set);
unpack_status(cib_status, data_set);
unpack_constraints(cib_constraints, data_set);
return TRUE;
}
/*
* Count how many valid nodes we have (so we know the maximum number of
* colors we can resolve).
*
* Apply node constraints (ie. filter the "allowed_nodes" part of resources
*/
gboolean
stage1(pe_working_set_t *data_set)
{
crm_debug_3("Applying placement constraints");
slist_iter(
node, node_t, data_set->nodes, lpc,
if(node == NULL) {
/* error */
} else if(node->weight >= 0.0 /* global weight */
&& node->details->online
&& node->details->type == node_member) {
data_set->max_valid_nodes++;
}
);
apply_placement_constraints(data_set);
return TRUE;
}
/*
* Choose a color for all resources from highest priority and XML_STRENGTH_VAL_MUST
* dependencies to lowest, creating new colors as necessary (returned
* as "colors").
*
* Some nodes may be colored as a "no_color" meaning that it was unresolvable
* given the current node stati and constraints.
*/
gboolean
stage2(pe_working_set_t *data_set)
{
crm_debug_3("Coloring resources");
crm_debug_5("create \"no color\"");
data_set->no_color = create_color(data_set, NULL, NULL);
/* Take (next) highest resource */
slist_iter(
lh_resource, resource_t, data_set->resources, lpc,
/* if resource.provisional == FALSE, repeat */
if(lh_resource->provisional == FALSE) {
/* already processed this resource */
continue;
}
color_resource(lh_resource, data_set);
/* next resource */
);
return TRUE;
}
/*
* not sure if this is a good idea or not, but eventually we might like
* to utilize as many nodes as possible... and this might be a convienient
* hook
*/
gboolean
stage3(pe_working_set_t *data_set)
{
/* not sure if this is a good idea or not */
if((ssize_t)g_list_length(data_set->colors) > data_set->max_valid_nodes) {
/* we need to consolidate some */
} else if((ssize_t)g_list_length(data_set->colors) < data_set->max_valid_nodes) {
/* we can create a few more */
}
return TRUE;
}
/*
* Choose a node for each (if possible) color
*/
gboolean
stage4(pe_working_set_t *data_set)
{
crm_debug_3("Assigning nodes to colors");
slist_iter(
color, color_t, data_set->colors, lpc,
crm_debug_4("assigning node to color %d", color->id);
if(color == NULL) {
pe_err("NULL color detected");
continue;
} else if(color->details->pending == FALSE) {
continue;
}
choose_node_from_list(color);
if(color->details->chosen_node == NULL) {
crm_debug_2("No node available for color %d", color->id);
} else {
crm_debug_4("assigned %s to color %d",
color->details->chosen_node->details->uname,
color->id);
}
slist_iter(
rsc, resource_t, color->details->allocated_resources, lpc2,
slist_iter(
constraint, rsc_colocation_t, rsc->rsc_cons, lpc,
rsc->fns->rsc_colocation_lh(constraint);
);
);
);
crm_debug_3("done");
return TRUE;
}
/*
* Attach nodes to the actions that need to be taken
*
* Mark actions XML_LRM_ATTR_OPTIONAL if possible (Ie. if the start and stop are
* for the same node)
*
* Mark unrunnable actions
*/
gboolean
stage5(pe_working_set_t *data_set)
{
crm_debug_3("Creating actions and internal ording constraints");
slist_iter(
rsc, resource_t, data_set->resources, lpc,
rsc->fns->create_actions(rsc, data_set);
rsc->fns->internal_constraints(rsc, data_set);
);
return TRUE;
}
/*
* Create dependacies for stonith and shutdown operations
*/
gboolean
stage6(pe_working_set_t *data_set)
{
action_t *down_op = NULL;
action_t *stonith_op = NULL;
crm_debug_3("Processing fencing and shutdown cases");
slist_iter(
node, node_t, data_set->nodes, lpc,
if(node->details->online && node->details->shutdown) {
crm_info("Scheduling Node %s for shutdown",
node->details->uname);
down_op = custom_action(
NULL, crm_strdup(CRM_OP_SHUTDOWN),
CRM_OP_SHUTDOWN, node, FALSE, data_set);
down_op->runnable = TRUE;
shutdown_constraints(
node, down_op, data_set);
}
if(node->details->unclean
&& data_set->stonith_enabled == FALSE) {
pe_err("Node %s is unclean!", node->details->uname);
pe_warn("YOUR RESOURCES ARE NOW LIKELY COMPROMISED");
pe_warn("ENABLE STONITH TO KEEP YOUR RESOURCES SAFE");
} else if(node->details->unclean && data_set->stonith_enabled
&& (data_set->have_quorum
|| data_set->no_quorum_policy == no_quorum_ignore)) {
pe_warn("Scheduling Node %s for STONITH",
node->details->uname);
stonith_op = custom_action(
NULL, crm_strdup(CRM_OP_FENCE),
CRM_OP_FENCE, node, FALSE, data_set);
stonith_op->runnable = TRUE;
add_hash_param(
stonith_op->extra, XML_LRM_ATTR_TARGET,
node->details->uname);
add_hash_param(
stonith_op->extra, XML_LRM_ATTR_TARGET_UUID,
node->details->id);
if(down_op != NULL) {
down_op->failure_is_fatal = FALSE;
}
}
if(node->details->unclean) {
stonith_constraints(
node, stonith_op, down_op, data_set);
}
);
return TRUE;
}
/*
* Determin the sets of independant actions and the correct order for the
* actions in each set.
*
* Mark dependencies of un-runnable actions un-runnable
*
*/
gboolean
stage7(pe_working_set_t *data_set)
{
crm_debug_3("Applying ordering constraints");
slist_iter(
order, order_constraint_t, data_set->ordering_constraints, lpc,
/* try rsc_action-to-rsc_action */
resource_t *rsc = order->lh_rsc;
if(rsc == NULL && order->lh_action) {
rsc = order->lh_action->rsc;
}
if(rsc != NULL) {
rsc->fns->rsc_order_lh(rsc, order);
continue;
}
/* try action-to-rsc_action */
/* que off the rh resource */
rsc = order->rh_rsc;
if(rsc == NULL && order->rh_action) {
rsc = order->rh_action->rsc;
}
if(rsc != NULL) {
rsc->fns->rsc_order_rh(order->lh_action, rsc, order);
} else {
/* fall back to action-to-action */
order_actions(
order->lh_action, order->rh_action, order);
}
);
update_action_states(data_set->actions);
return TRUE;
}
static int transition_id = -1;
/*
* Create a dependency graph to send to the transitioner (via the CRMd)
*/
gboolean
stage8(pe_working_set_t *data_set)
{
char *transition_id_s = NULL;
transition_id++;
transition_id_s = crm_itoa(transition_id);
crm_info("Creating transition graph %d.", transition_id);
data_set->graph = create_xml_node(NULL, XML_TAG_GRAPH);
crm_xml_add(data_set->graph, "global_timeout", transition_idle_timeout);
crm_xml_add(data_set->graph, "transition_id", transition_id_s);
crm_free(transition_id_s);
/* errors...
slist_iter(action, action_t, action_list, lpc,
if(action->optional == FALSE && action->runnable == FALSE) {
print_action("Ignoring", action, TRUE);
}
);
*/
slist_iter(
rsc, resource_t, data_set->resources, lpc,
crm_debug_4("processing actions for rsc=%s", rsc->id);
rsc->fns->expand(rsc, data_set);
);
crm_log_xml_debug_3(
data_set->graph, "created resource-driven action list");
/* catch any non-resource specific actions */
crm_debug_4("processing non-resource actions");
slist_iter(
action, action_t, data_set->actions, lpc,
graph_element_from_action(action, data_set);
);
crm_log_xml_debug_3(data_set->graph, "created generic action list");
return TRUE;
}
gboolean
choose_node_from_list(color_t *color)
{
/*
1. Sort by weight
2. color.chosen_node = the node (of those with the highest wieght)
with the fewest resources
3. remove color.chosen_node from all other colors
*/
GListPtr nodes = color->details->candidate_nodes;
node_t *chosen = NULL;
crm_debug_4("Choosing node for color %d", color->id);
color->details->candidate_nodes = g_list_sort(nodes, sort_node_weight);
chosen = g_list_nth_data(color->details->candidate_nodes, 0);
color->details->chosen_node = NULL;
color->details->pending = FALSE;
if(chosen == NULL) {
crm_debug_2("Could not allocate a node for color %d", color->id);
return FALSE;
} else if(chosen->details->unclean || chosen->details->shutdown) {
crm_debug_2("Even highest ranked node for color %d"
" is unclean or shutting down",
color->id);
return FALSE;
} else if(chosen->weight < 0) {
crm_debug_2("Even highest ranked node for color %d, had weight %f",
color->id, chosen->weight);
return FALSE;
}
/* todo: update the old node for each resource to reflect its
* new resource count
*/
chosen->details->num_resources += color->details->num_resources;
color->details->chosen_node = node_copy(chosen);
return TRUE;
}
diff --git a/crm/tengine/unpack.c b/crm/tengine/unpack.c
index 2e3f9e9421..5eedd090cb 100644
--- a/crm/tengine/unpack.c
+++ b/crm/tengine/unpack.c
@@ -1,359 +1,360 @@
-/* $Id: unpack.c,v 1.43 2005/07/18 11:17:23 andrew Exp $ */
+/* $Id: unpack.c,v 1.44 2005/08/17 09:03:24 andrew Exp $ */
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* 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 <portability.h>
#include <sys/param.h>
#include <crm/crm.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/msg.h>
#include <crm/common/xml.h>
#include <tengine.h>
#include <heartbeat.h>
#include <clplumbing/Gmain_timeout.h>
#include <lrm/lrm_api.h>
#include <sys/stat.h>
+#include <clplumbing/cl_misc.h>
cib_t *te_cib_conn = NULL;
action_t* unpack_action(crm_data_t *xml_action);
crm_data_t *create_shutdown_event(const char *node, int op_status);
void set_timer_value(te_timer_t *timer, const char *time, int time_default);
extern int transition_counter;
void
set_timer_value(te_timer_t *timer, const char *time, int time_default)
{
int tmp_time;
if(timer == NULL) {
return;
}
timer->timeout = time_default;
tmp_time = crm_get_msec(time);
if(tmp_time > 0) {
timer->timeout = tmp_time;
}
}
gboolean
unpack_graph(crm_data_t *xml_graph)
{
/*
<transition_graph>
<synapse>
<action_set>
<rsc_op id="2"
...
<inputs>
<rsc_op id="2"
...
*/
int num_synapses = 0;
int num_actions = 0;
const char *t_id = crm_element_value(xml_graph, "transition_id");
const char *time = crm_element_value(xml_graph, "global_timeout");
CRM_DEV_ASSERT(t_id != NULL);
CRM_DEV_ASSERT(time != NULL);
transition_timer->timeout = crm_get_msec(time);
transition_idle_timeout = transition_timer->timeout;
transition_counter = crm_atoi(t_id, "-1");
crm_info("Beginning transition %d : timeout set to %dms",
transition_counter, transition_timer->timeout);
xml_child_iter(
xml_graph, synapse, "synapse",
synapse_t *new_synapse = NULL;
crm_debug_3("looking in synapse %s",
crm_element_value(synapse, XML_ATTR_ID));
crm_malloc0(new_synapse, sizeof(synapse_t));
new_synapse->id = num_synapses++;
new_synapse->complete = FALSE;
new_synapse->confirmed = FALSE;
new_synapse->actions = NULL;
new_synapse->inputs = NULL;
graph = g_list_append(graph, new_synapse);
crm_debug_3("look for actions in synapse %s",
crm_element_value(synapse, XML_ATTR_ID));
xml_child_iter(
synapse, actions, "action_set",
xml_child_iter(
actions, action, NULL,
action_t *new_action = unpack_action(action);
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",
crm_element_value(synapse, XML_ATTR_ID));
xml_child_iter(
synapse, inputs, "inputs",
xml_child_iter(
inputs, trigger, NULL,
xml_child_iter(
trigger, input, NULL,
action_t *new_input =
unpack_action(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);
);
);
);
);
crm_info("Unpacked %d actions in %d synapses",
num_actions, num_synapses);
if(num_actions > 0) {
return TRUE;
} else {
/* indicate to caller that there's nothing to do */
return FALSE;
}
}
action_t*
unpack_action(crm_data_t *xml_action)
{
const char *tmp = crm_element_value(xml_action, XML_ATTR_ID);
action_t *action = NULL;
crm_data_t *action_copy = NULL;
crm_data_t *nvpair_list = NULL;
if(tmp == 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(action_t));
if(action == NULL) {
return NULL;
}
action->id = atoi(tmp);
action->timeout = 0;
action->interval = 0;
action->timer = NULL;
action->invoked = FALSE;
action->sent_update = FALSE;
action->complete = FALSE;
action->can_fail = FALSE;
action->type = action_type_rsc;
action->xml = action_copy;
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;
}
nvpair_list = find_xml_node(action_copy, XML_TAG_ATTRS, FALSE);
if(nvpair_list == NULL) {
crm_debug_2("No attributes in %s",
crm_element_name(action_copy));
}
xml_child_iter(
nvpair_list, node_iter, XML_CIB_TAG_NVPAIR,
const char *key = crm_element_value(
node_iter, XML_NVPAIR_ATTR_NAME);
const char *value = crm_element_value(
node_iter, XML_NVPAIR_ATTR_VALUE);
if(safe_str_eq(key, "timeout")) {
action->timeout = crm_get_msec(value);
} else if(safe_str_eq(key, "interval")) {
action->interval = crm_get_msec(value);
}
);
crm_debug_3("Action %d has timer set to %dms",
action->id, action->timeout);
crm_malloc0(action->timer, sizeof(te_timer_t));
action->timer->timeout = 2 * action->timeout;
action->timer->source_id = -1;
action->timer->reason = timeout_action;
action->timer->action = action;
tmp = crm_element_value(action_copy, "can_fail");
- crm_str_to_boolean(tmp, &(action->can_fail));
+ cl_str_to_boolean(tmp, &(action->can_fail));
return action;
}
gboolean
extract_event(crm_data_t *msg)
{
const char *event_node = NULL;
struct abort_blob_s
{
const char *text;
crm_data_t *update;
te_reason_t reason;
};
struct abort_blob_s blob = { NULL, NULL, 0 };
blob.reason = te_update;
/*
[cib fragment]
...
<status>
<node_state id="node1" state=CRMD_STATE_ACTIVE exp_state="active">
<lrm>
<lrm_resources>
<rsc_state id="" rsc_id="rsc4" node_id="node1" rsc_state="stopped"/>
*/
crm_debug_4("Extracting event from %s", crm_element_name(msg));
xml_child_iter(
msg, node_state, XML_CIB_TAG_STATE,
crm_data_t *resources = NULL;
const char *ccm_state = crm_element_value(
node_state, XML_CIB_ATTR_INCCM);
const char *crmd_state = crm_element_value(
node_state, XML_CIB_ATTR_CRMDSTATE);
blob.update = node_state;
event_node = crm_element_value(node_state, XML_ATTR_ID);
crm_log_xml_debug_3(node_state,"Processing");
if(crm_element_value(node_state, XML_CIB_ATTR_SHUTDOWN) != NULL) {
blob.text = "Aborting on "XML_CIB_ATTR_SHUTDOWN" attribute";
break;
}
resources = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE);
resources = find_xml_node(
resources, XML_LRM_TAG_RESOURCES, FALSE);
/*
* node state update... possibly from a shutdown we requested
*/
crm_debug_3("Processing state update");
if(safe_str_eq(ccm_state, XML_BOOLEAN_FALSE)
|| safe_str_eq(crmd_state, CRMD_JOINSTATE_DOWN)) {
int action_id = -1;
crm_debug_3("A shutdown we requested?");
action_id = match_down_event(
event_node, NULL, LRM_OP_DONE);
if(action_id >= 0) {
process_trigger(action_id);
check_for_completion();
} else {
blob.text="Stonith/shutdown event not matched";
break;
}
}
/* LRM resource update... */
xml_child_iter(
resources, rsc, NULL,
xml_child_iter(
rsc, rsc_op, NULL,
crm_log_xml_debug_3(
rsc_op, "Processing resource update");
if(!process_graph_event(rsc_op, event_node)) {
/* the transition has already been
* aborted and with better details
*/
return TRUE;
}
);
);
);
if(blob.text != NULL) {
send_complete(blob.text, blob.update, blob.reason, i_cancel);
}
return TRUE;
}
crm_data_t*
create_shutdown_event(const char *node, int op_status)
{
crm_data_t *event = create_xml_node(NULL, XML_CIB_TAG_STATE);
char *code = crm_itoa(op_status);
crm_xml_add(event, XML_LRM_ATTR_TARGET_UUID, node);
/* event_rsc = crm_xml_add(event, XML_ATTR_ID); */
crm_xml_add(event, XML_LRM_ATTR_RC, "0");
crm_xml_add(event, XML_LRM_ATTR_LASTOP, XML_CIB_ATTR_SHUTDOWN);
crm_xml_add(event, XML_LRM_ATTR_RSCSTATE, CRMD_ACTION_GENERIC_OK);
crm_xml_add(event, XML_LRM_ATTR_OPSTATUS, code);
crm_free(code);
return event;
}
diff --git a/lib/crm/common/utils.c b/lib/crm/common/utils.c
index 718314fe4e..a10523fe68 100644
--- a/lib/crm/common/utils.c
+++ b/lib/crm/common/utils.c
@@ -1,1025 +1,1028 @@
-/* $Id: utils.c,v 1.22 2005/08/11 14:43:30 andrew Exp $ */
+/* $Id: utils.c,v 1.23 2005/08/17 09:03:24 andrew Exp $ */
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* 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 <portability.h>
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <sys/param.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <heartbeat.h>
#include <ha_msg.h>
#include <clplumbing/cl_log.h>
#include <clplumbing/cl_signal.h>
#include <clplumbing/cl_syslog.h>
+#include <clplumbing/cl_misc.h>
#include <clplumbing/coredumps.h>
#include <time.h>
#include <clplumbing/Gmain_timeout.h>
#include <crm/crm.h>
#include <crm/msg_xml.h>
#include <crm/common/xml.h>
#include <crm/common/util.h>
#include <crm/dmalloc_wrapper.h>
#ifndef MAXLINE
# define MAXLINE 512
#endif
static uint ref_counter = 0;
gboolean crm_assert_failed = FALSE;
unsigned int crm_log_level = LOG_INFO;
void crm_set_env_options(void);
char *
generateReference(const char *custom1, const char *custom2)
{
const char *local_cust1 = custom1;
const char *local_cust2 = custom2;
int reference_len = 4;
char *since_epoch = NULL;
reference_len += 20; /* too big */
reference_len += 40; /* too big */
if(local_cust1 == NULL) { local_cust1 = "_empty_"; }
reference_len += strlen(local_cust1);
if(local_cust2 == NULL) { local_cust2 = "_empty_"; }
reference_len += strlen(local_cust2);
crm_malloc0(since_epoch, reference_len*(sizeof(char)));
if(since_epoch != NULL) {
sprintf(since_epoch, "%s-%s-%ld-%u",
local_cust1, local_cust2,
(unsigned long)time(NULL), ref_counter++);
}
return since_epoch;
}
gboolean
decodeNVpair(const char *srcstring, char separator, char **name, char **value)
{
int lpc = 0;
int len = 0;
const char *temp = NULL;
crm_debug_4("Attempting to decode: [%s]", srcstring);
if (srcstring != NULL) {
len = strlen(srcstring);
while(lpc <= len) {
if (srcstring[lpc] == separator
|| srcstring[lpc] == '\0') {
crm_malloc0(*name, sizeof(char)*lpc+1);
if(*name == NULL) {
break; /* and return FALSE */
}
strncpy(*name, srcstring, lpc);
(*name)[lpc] = '\0';
/* this sucks but as the strtok manpage says..
* it *is* a bug
*/
len = len-lpc; len--;
if(len <= 0) {
*value = NULL;
} else {
crm_malloc0(*value, sizeof(char)*len+1);
if(*value == NULL) {
crm_free(*name);
break; /* and return FALSE */
}
temp = srcstring+lpc+1;
strncpy(*value, temp, len);
(*value)[len] = '\0';
}
return TRUE;
}
lpc++;
}
}
*name = NULL;
*value = NULL;
return FALSE;
}
char *
generate_hash_key(const char *crm_msg_reference, const char *sys)
{
int ref_len = strlen(sys?sys:"none") + strlen(crm_msg_reference) + 2;
char *hash_key = NULL;
crm_malloc0(hash_key, sizeof(char)*(ref_len));
if(hash_key != NULL) {
sprintf(hash_key, "%s_%s", sys?sys:"none", crm_msg_reference);
hash_key[ref_len-1] = '\0';
crm_debug_3("created hash key: (%s)", hash_key);
}
return hash_key;
}
char *
generate_hash_value(const char *src_node, const char *src_subsys)
{
int ref_len;
char *hash_value = NULL;
if (src_node == NULL || src_subsys == NULL) {
return NULL;
}
if (strcmp(CRM_SYSTEM_DC, src_subsys) == 0) {
hash_value = crm_strdup(src_subsys);
if (!hash_value) {
crm_err("memory allocation failed in "
"generate_hash_value()");
return NULL;
}
return hash_value;
}
ref_len = strlen(src_subsys) + strlen(src_node) + 2;
crm_malloc0(hash_value, sizeof(char)*(ref_len));
if (!hash_value) {
crm_err("memory allocation failed in "
"generate_hash_value()");
return NULL;
}
snprintf(hash_value, ref_len-1, "%s_%s", src_node, src_subsys);
hash_value[ref_len-1] = '\0';/* make sure it is null terminated */
crm_info("created hash value: (%s)", hash_value);
return hash_value;
}
gboolean
decode_hash_value(gpointer value, char **node, char **subsys)
{
char *char_value = (char*)value;
int value_len = strlen(char_value);
crm_info("Decoding hash value: (%s:%d)", char_value, value_len);
if (strcmp(CRM_SYSTEM_DC, (char*)value) == 0) {
*node = NULL;
*subsys = (char*)crm_strdup(char_value);
if (*subsys == NULL) {
crm_err("memory allocation failed in "
"decode_hash_value()");
return FALSE;
}
crm_info("Decoded value: (%s:%d)", *subsys,
(int)strlen(*subsys));
return TRUE;
} else if (char_value != NULL) {
if (decodeNVpair(char_value, '_', node, subsys)) {
return TRUE;
} else {
*node = NULL;
*subsys = NULL;
return FALSE;
}
}
return FALSE;
}
char *
crm_itoa(int an_int)
{
int len = 32;
char *buffer = NULL;
crm_malloc0(buffer, sizeof(char)*(len+1));
if(buffer != NULL) {
snprintf(buffer, len, "%d", an_int);
}
return buffer;
}
extern int LogToLoggingDaemon(int priority, const char * buf, int bstrlen, gboolean use_pri_str);
gboolean
crm_log_init(const char *entity)
{
/* const char *test = "Testing log daemon connection"; */
/* Redirect messages from glib functions to our handler */
/* cl_malloc_forced_for_glib(); */
g_log_set_handler(NULL,
G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL
| G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE
| G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG
| G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL,
cl_glib_msg_handler, NULL);
/* and for good measure... - this enum is a bit field (!) */
g_log_set_always_fatal((GLogLevelFlags)0); /*value out of range*/
cl_log_set_entity(entity);
cl_log_set_facility(LOG_LOCAL7);
cl_set_corerootdir(HA_COREDIR);
cl_cdtocoredir();
crm_set_env_options();
CL_SIGNAL(DEBUG_INC, alter_debug);
CL_SIGNAL(DEBUG_DEC, alter_debug);
return TRUE;
}
/* returns the old value */
unsigned int
set_crm_log_level(unsigned int level)
{
unsigned int old = crm_log_level;
while(crm_log_level < level) {
alter_debug(DEBUG_INC);
}
while(crm_log_level > level) {
alter_debug(DEBUG_DEC);
}
return old;
}
unsigned int
get_crm_log_level(void)
{
return crm_log_level;
}
void
crm_log_message_adv(int level, const char *prefix, const HA_Message *msg)
{
if((int)crm_log_level >= level) {
do_crm_log(level, NULL, NULL, "#========= %s message start ==========#", prefix?prefix:"");
if(level > LOG_DEBUG) {
cl_log_message(LOG_DEBUG, msg);
} else {
cl_log_message(level, msg);
}
}
}
void
do_crm_log(int log_level, const char *file, const char *function,
const char *fmt, ...)
{
int log_as = log_level;
gboolean do_log = FALSE;
if(log_level <= (int)crm_log_level) {
do_log = TRUE;
if(log_level > LOG_INFO) {
log_as = LOG_DEBUG;
}
}
if(do_log) {
va_list ap;
int nbytes;
char buf[MAXLINE];
va_start(ap, fmt);
nbytes=vsnprintf(buf, MAXLINE, fmt, ap);
va_end(ap);
log_level -= LOG_INFO;
if(log_level > 1) {
if(file == NULL && function == NULL) {
cl_log(log_as, "[%d] %s", log_level, buf);
} else {
cl_log(log_as, "mask(%s%s%s [%d]): %s",
file?file:"",
(file !=NULL && function !=NULL)?":":"",
function?function:"", log_level, buf);
}
} else {
if(file == NULL && function == NULL) {
cl_log(log_as, "%s", buf);
} else {
cl_log(log_as, "mask(%s%s%s): %s",
file?file:"",
(file !=NULL && function !=NULL)?":":"",
function?function:"", buf);
}
}
if(nbytes > MAXLINE) {
cl_log(LOG_WARNING, "Log from %s() was truncated",
crm_str(function));
}
}
}
int
compare_version(const char *version1, const char *version2)
{
int lpc = 0;
char *step1 = NULL, *step2 = NULL;
char *rest1 = NULL, *rest2 = NULL;
if(version1 == NULL && version2 == NULL) {
return 0;
} else if(version1 == NULL) {
return -1;
} else if(version2 == NULL) {
return 1;
}
if(version1 != NULL) {
rest1 = crm_strdup(version1);
} else {
version1 = "<null>";
}
if(version2 != NULL) {
rest2 = crm_strdup(version2);
} else {
version2 = "<null>";
}
while(1) {
int cmp = 0;
int step1_i = 0;
int step2_i = 0;
char *tmp1 = NULL, *tmp2 = NULL;
decodeNVpair(rest1, '.', &step1, &tmp1);
decodeNVpair(rest2, '.', &step2, &tmp2);
if(step1 != NULL) {
step1_i = atoi(step1);
}
if(step2 != NULL) {
step2_i = atoi(step2);
}
if(step1_i < step2_i){
cmp = -1;
} else if (step1_i > step2_i){
cmp = 1;
}
crm_debug_4("compare[%d (%d)]: %d(%s) %d(%s)",
lpc++, cmp,
step1_i, crm_str(step1),
step2_i, crm_str(step2));
crm_free(rest1);
crm_free(rest2);
rest1 = tmp1;
rest2 = tmp2;
if(step1 == NULL && step2 == NULL) {
break;
}
crm_free(step1);
crm_free(step2);
if(cmp < 0) {
crm_debug_2("%s < %s", version1, version2);
return -1;
} else if(cmp > 0) {
crm_debug_2("%s > %s", version1, version2);
return 1;
}
}
crm_debug_2("%s == %s", version1, version2);
return 0;
}
gboolean do_stderr = FALSE;
void
alter_debug(int nsig)
{
CL_SIGNAL(DEBUG_INC, alter_debug);
CL_SIGNAL(DEBUG_DEC, alter_debug);
switch(nsig) {
case DEBUG_INC:
crm_log_level++;
crm_debug("Upped log level to %d", crm_log_level);
break;
case DEBUG_DEC:
crm_log_level--;
crm_debug("Reduced log level to %d", crm_log_level);
break;
default:
fprintf(stderr, "Unknown signal %d\n", nsig);
cl_log(LOG_ERR, "Unknown signal %d", nsig);
break;
}
}
void g_hash_destroy_str(gpointer data)
{
crm_free(data);
}
gboolean
safe_str_eq(const char *a, const char *b)
{
if(a == b) {
return TRUE;
} else if(a == NULL || b == NULL) {
return FALSE;
} else if(strcmp(a, b) == 0) {
return TRUE;
}
return FALSE;
}
gboolean
safe_str_neq(const char *a, const char *b)
{
if(a == b) {
return FALSE;
} else if(a==NULL || b==NULL) {
return TRUE;
} else if(strcmp(a, b) == 0) {
return FALSE;
}
return TRUE;
}
char *
crm_strdup(const char *a)
{
char *ret = NULL;
CRM_DEV_ASSERT(a != NULL);
if(a != NULL) {
ret = cl_strdup(a);
} else {
crm_warn("Cannot dup NULL string");
}
return ret;
}
static GHashTable *crm_uuid_cache = NULL;
void
set_uuid(ll_cluster_t *hb,crm_data_t *node,const char *attr,const char *uname)
{
char *uuid_calc = NULL;
if(crm_uuid_cache == NULL) {
crm_uuid_cache = g_hash_table_new_full(
g_str_hash, g_str_equal,
g_hash_destroy_str, g_hash_destroy_str);
}
CRM_DEV_ASSERT(uname != NULL);
/* avoid blocking calls where possible */
uuid_calc = g_hash_table_lookup(crm_uuid_cache, uname);
if(uuid_calc != NULL) {
crm_xml_add(node, attr, uuid_calc);
return;
}
crm_malloc0(uuid_calc, sizeof(char)*50);
if(uuid_calc != NULL) {
cl_uuid_t uuid_raw;
if(hb->llc_ops->get_uuid_by_name(
hb, uname, &uuid_raw) == HA_FAIL) {
crm_err("Could not calculate UUID for %s", uname);
crm_free(uuid_calc);
uuid_calc = crm_strdup(uname);
} else {
cl_uuid_unparse(&uuid_raw, uuid_calc);
g_hash_table_insert(
crm_uuid_cache,
crm_strdup(uname), crm_strdup(uuid_calc));
}
crm_xml_add(node, attr, uuid_calc);
}
crm_free(uuid_calc);
}/*memory leak*/ /* BEAM BUG - this is not a memory leak */
void
crm_set_ha_options(ll_cluster_t *hb_cluster)
{
#if 0
int facility;
char *param_val = NULL;
const char *param_name = NULL;
if(hb_cluster == NULL) {
crm_set_env_options();
return;
}
/* change the logging facility to the one used by heartbeat daemon */
crm_debug("Switching to Heartbeat logger");
if (( facility =
hb_cluster->llc_ops->get_logfacility(hb_cluster)) > 0) {
cl_log_set_facility(facility);
}
crm_debug_2("Facility: %d", facility);
param_name = KEY_LOGFILE;
param_val = hb_cluster->llc_ops->get_parameter(hb_cluster, param_name);
crm_debug_3("%s = %s", param_name, param_val);
if(param_val != NULL) {
cl_log_set_logfile(param_val);
cl_free(param_val);
param_val = NULL;
}
param_name = KEY_DBGFILE;
param_val = hb_cluster->llc_ops->get_parameter(hb_cluster, param_name);
crm_debug_3("%s = %s", param_name, param_val);
if(param_val != NULL) {
cl_log_set_debugfile(param_val);
cl_free(param_val);
param_val = NULL;
}
param_name = KEY_DEBUGLEVEL;
param_val = hb_cluster->llc_ops->get_parameter(hb_cluster, param_name);
crm_debug_3("%s = %s", param_name, param_val);
if(param_val != NULL) {
int debug_level = atoi(param_val);
if(debug_level > 0 && (debug_level+LOG_INFO) > (int)crm_log_level) {
set_crm_log_level(LOG_INFO + debug_level);
}
cl_free(param_val);
param_val = NULL;
}
param_name = KEY_LOGDAEMON;
param_val = hb_cluster->llc_ops->get_parameter(hb_cluster, param_name);
crm_debug_3("%s = %s", param_name, param_val);
if(param_val != NULL) {
int uselogd;
- crm_str_to_boolean(param_val, &uselogd);
+ cl_str_to_boolean(param_val, &uselogd);
cl_log_set_uselogd(uselogd);
if(cl_log_get_uselogd()) {
cl_set_logging_wqueue_maxlen(500);
}
cl_free(param_val);
param_val = NULL;
}
param_name = KEY_CONNINTVAL;
param_val = hb_cluster->llc_ops->get_parameter(hb_cluster, param_name);
crm_debug_3("%s = %s", param_name, param_val);
if(param_val != NULL) {
int logdtime;
logdtime = crm_get_msec(param_val);
cl_log_set_logdtime(logdtime);
cl_free(param_val);
param_val = NULL;
}
#endif
}
#define ENV_PREFIX "HA_"
void
crm_set_env_options(void)
{
char *param_val = NULL;
const char *param_name = NULL;
/* apparently we're not allowed to free the result of getenv */
param_name = ENV_PREFIX "" KEY_DEBUGLEVEL;
param_val = getenv(param_name);
crm_debug("%s = %s", param_name, param_val);
if(param_val != NULL) {
int debug_level = atoi(param_val);
if(debug_level > 0 && (debug_level+LOG_INFO) > (int)crm_log_level) {
set_crm_log_level(LOG_INFO + debug_level);
}
param_val = NULL;
}
param_name = ENV_PREFIX "" KEY_FACILITY;
param_val = getenv(param_name);
crm_debug("%s = %s", param_name, param_val);
if(param_val != NULL) {
int facility = cl_syslogfac_str2int(param_val);
if(facility > 0) {
cl_log_set_facility(facility);
}
param_val = NULL;
}
param_name = ENV_PREFIX "" KEY_LOGFILE;
param_val = getenv(param_name);
crm_debug("%s = %s", param_name, param_val);
if(param_val != NULL) {
if(safe_str_eq("/dev/null", param_val)) {
param_val = NULL;
}
cl_log_set_logfile(param_val);
param_val = NULL;
}
param_name = ENV_PREFIX "" KEY_DBGFILE;
param_val = getenv(param_name);
crm_debug("%s = %s", param_name, param_val);
if(param_val != NULL) {
if(safe_str_eq("/dev/null", param_val)) {
param_val = NULL;
}
cl_log_set_debugfile(param_val);
param_val = NULL;
}
param_name = ENV_PREFIX "" KEY_LOGDAEMON;
param_val = getenv(param_name);
crm_debug("%s = %s", param_name, param_val);
if(param_val != NULL) {
int uselogd;
- crm_str_to_boolean(param_val, &uselogd);
+ cl_str_to_boolean(param_val, &uselogd);
cl_log_set_uselogd(uselogd);
if(uselogd) {
cl_set_logging_wqueue_maxlen(500);
cl_log_set_logd_channel_source(NULL, NULL);
}
param_val = NULL;
}
param_name = ENV_PREFIX "" KEY_CONNINTVAL;
param_val = getenv(param_name);
crm_debug("%s = %s", param_name, param_val);
if(param_val != NULL) {
int logdtime;
logdtime = crm_get_msec(param_val);
cl_log_set_logdtime(logdtime);
param_val = NULL;
}
}
gboolean
crm_is_true(const char * s)
{
gboolean ret = FALSE;
- crm_str_to_boolean(s, &ret);
+ if(s != NULL) {
+ cl_str_to_boolean(s, &ret);
+ }
return ret;
}
int
crm_str_to_boolean(const char * s, int * ret)
{
if(s == NULL) {
return -1;
} else if (strcasecmp(s, "true") == 0
- || strcasecmp(s, "on") == 0
- || strcasecmp(s, "yes") == 0
- || strcasecmp(s, "y") == 0
- || strcasecmp(s, "1") == 0){
+ || strcasecmp(s, "on") == 0
+ || strcasecmp(s, "yes") == 0
+ || strcasecmp(s, "y") == 0
+ || strcasecmp(s, "1") == 0){
*ret = TRUE;
return 1;
} else if (strcasecmp(s, "false") == 0
- || strcasecmp(s, "off") == 0
- || strcasecmp(s, "no") == 0
- || strcasecmp(s, "n") == 0
- || strcasecmp(s, "0") == 0){
+ || strcasecmp(s, "off") == 0
+ || strcasecmp(s, "no") == 0
+ || strcasecmp(s, "n") == 0
+ || strcasecmp(s, "0") == 0){
*ret = FALSE;
return 1;
}
return -1;
}
#ifndef NUMCHARS
# define NUMCHARS "0123456789."
#endif
#ifndef WHITESPACE
# define WHITESPACE " \t\n\r\f"
#endif
long
crm_get_msec(const char * input)
{
const char * cp = input;
const char * units;
long multiplier = 1000;
long divisor = 1;
long ret = -1;
double dret;
if(input == NULL) {
return 0;
}
cp += strspn(cp, WHITESPACE);
units = cp + strspn(cp, NUMCHARS);
units += strspn(units, WHITESPACE);
if (strchr(NUMCHARS, *cp) == NULL) {
return ret;
}
if (strncasecmp(units, "ms", 2) == 0
|| strncasecmp(units, "msec", 4) == 0) {
multiplier = 1;
divisor = 1;
}else if (strncasecmp(units, "us", 2) == 0
|| strncasecmp(units, "usec", 4) == 0) {
multiplier = 1;
divisor = 1000;
}else if (strncasecmp(units, "s", 1) == 0
|| strncasecmp(units, "sec", 3) == 0) {
multiplier = 1000;
divisor = 1;
}else if (strncasecmp(units, "m", 1) == 0
|| strncasecmp(units, "min", 3) == 0) {
multiplier = 60*1000;
divisor = 1;
}else if (*units != EOS && *units != '\n'
&& *units != '\r') {
return ret;
}
dret = atof(cp);
dret *= (double)multiplier;
dret /= (double)divisor;
dret += 0.5;
ret = (long)dret;
return(ret);
}
gboolean
ccm_have_quorum(oc_ed_t event)
{
if(event==OC_EV_MS_NEW_MEMBERSHIP) {
return TRUE;
}
return FALSE;
}
const char *
ccm_event_name(oc_ed_t event)
{
if(event==OC_EV_MS_NEW_MEMBERSHIP) {
return "NEW MEMBERSHIP";
} else if(event==OC_EV_MS_NOT_PRIMARY) {
return "NOT PRIMARY";
} else if(event==OC_EV_MS_PRIMARY_RESTORED) {
return "PRIMARY RESTORED";
} else if(event==OC_EV_MS_EVICTED) {
return "EVICTED";
} else if(event==OC_EV_MS_INVALID) {
return "INVALID";
}
return "NO QUORUM MEMBERSHIP";
}
const char *
op_status2text(op_status_t status)
{
switch(status) {
case LRM_OP_PENDING:
return "pending";
break;
case LRM_OP_DONE:
return "complete";
break;
case LRM_OP_ERROR:
return "ERROR";
break;
case LRM_OP_TIMEOUT:
return "TIMED OUT";
break;
case LRM_OP_NOTSUPPORTED:
return "NOT SUPPORTED";
break;
case LRM_OP_CANCELLED:
return "cancelled";
break;
}
CRM_DEV_ASSERT(status >= LRM_OP_PENDING && status <= LRM_OP_CANCELLED);
crm_err("Unknown status: %d", status);
return "UNKNOWN!";
}
char *
generate_op_key(const char *rsc_id, const char *op_type, int interval)
{
int len = 35;
char *op_id = NULL;
CRM_DEV_ASSERT(rsc_id != NULL); if(crm_assert_failed) { return NULL; }
CRM_DEV_ASSERT(op_type != NULL); if(crm_assert_failed) { return NULL; }
len += strlen(op_type);
len += strlen(rsc_id);
crm_malloc0(op_id, sizeof(char)*len);
if(op_id != NULL) {
sprintf(op_id, "%s_%s_%d", rsc_id, op_type, interval);
}
return op_id;
}
char *
generate_notify_key(const char *rsc_id, const char *notify_type, const char *op_type)
{
int len = 12;
char *op_id = NULL;
CRM_DEV_ASSERT(rsc_id != NULL); if(crm_assert_failed) { return NULL; }
CRM_DEV_ASSERT(op_type != NULL); if(crm_assert_failed) { return NULL; }
CRM_DEV_ASSERT(notify_type != NULL); if(crm_assert_failed) { return NULL; }
len += strlen(op_type);
len += strlen(rsc_id);
len += strlen(notify_type);
crm_malloc0(op_id, sizeof(char)*len);
if(op_id != NULL) {
sprintf(op_id, "%s_%s_notify_%s_0", rsc_id, notify_type, op_type);
}
return op_id;
}
char *
generate_transition_magic(const char *transition_key, int op_status)
{
int len = 40;
char *fail_state = NULL;
CRM_DEV_ASSERT(transition_key != NULL);
if(crm_assert_failed) { return NULL; }
len += strlen(transition_key);
crm_malloc0(fail_state, sizeof(char)*len);
if(fail_state != NULL) {
snprintf(fail_state, len, "%d:%s", op_status, transition_key);
}
return fail_state;
}
gboolean
decode_transition_magic(
const char *magic, char **uuid, int *transition_id, int *op_status)
{
char *key = NULL;
char *status = NULL;
if(decodeNVpair(magic, ':', &status, &key) == FALSE) {
return FALSE;
}
if(decode_transition_key(key, uuid, transition_id) == FALSE) {
return FALSE;
}
*op_status = atoi(status);
crm_free(key);
crm_free(status);
return TRUE;
}
char *
generate_transition_key(int transition_id, const char *node)
{
int len = 40;
char *fail_state = NULL;
CRM_DEV_ASSERT(node != NULL); if(crm_assert_failed) { return NULL; }
len += strlen(node);
crm_malloc0(fail_state, sizeof(char)*len);
if(fail_state != NULL) {
snprintf(fail_state, len, "%d:%s", transition_id, node);
}
return fail_state;
}
gboolean
decode_transition_key(const char *key, char **uuid, int *transition_id)
{
char *transition = NULL;
if(decodeNVpair(key, ':', &transition, uuid) == FALSE) {
return FALSE;
}
*transition_id = atoi(transition);
crm_free(transition);
return TRUE;
}
gboolean
crm_mem_stats(volatile cl_mem_stats_t *mem_stats)
{
volatile cl_mem_stats_t *active_stats = mem_stats;
if(active_stats == NULL) {
active_stats = cl_malloc_getstats();
}
CRM_DEV_ASSERT(active_stats != NULL);
#ifndef CRM_USE_MALLOC
if(active_stats->numalloc > active_stats->numfree) {
crm_err("Potential memory leak detected:"
" %lu alloc's vs. %lu free's (%lu)"
" (%lu bytes not freed: req=%lu, alloc'd=%lu)",
active_stats->numalloc, active_stats->numfree,
active_stats->numalloc - active_stats->numfree,
active_stats->nbytes_alloc, active_stats->nbytes_req,
active_stats->mallocbytes);
return TRUE;
} else if(active_stats->numalloc < active_stats->numfree) {
crm_debug("Process shrank: %lu alloc's vs. %lu free's (%lu)",
active_stats->numalloc, active_stats->numfree,
active_stats->numalloc - active_stats->numfree);
}
#endif
return FALSE;
}
void
crm_zero_mem_stats(volatile cl_mem_stats_t *stats)
{
volatile cl_mem_stats_t *active_stats = NULL;
if(stats != NULL) {
cl_malloc_setstats(stats);
}
active_stats = cl_malloc_getstats();
active_stats->numalloc = 0;
active_stats->numfree = 0;
active_stats->numrealloc = 0;
active_stats->nbytes_req = 0;
active_stats->nbytes_alloc = 0;
active_stats->mallocbytes = 0;
active_stats->arena = 0;
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Jan 25, 12:17 PM (20 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1322527
Default Alt Text
(57 KB)

Event Timeline