Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F2825346
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
57 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment