Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F2825140
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
71 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/crm/cib/main.c b/crm/cib/main.c
index 982c0dc4dd..c5eab4f473 100644
--- a/crm/cib/main.c
+++ b/crm/cib/main.c
@@ -1,479 +1,477 @@
-/* $Id: main.c,v 1.41 2006/04/03 10:01:35 andrew Exp $ */
+/* $Id: main.c,v 1.42 2006/04/10 16:18:08 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 <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <hb_api.h>
#include <heartbeat.h>
#include <clplumbing/cl_misc.h>
#include <clplumbing/uids.h>
#include <clplumbing/coredumps.h>
#include <clplumbing/Gmain_timeout.h>
/* #include <portability.h> */
#include <ocf/oc_event.h>
/* #include <ocf/oc_membership.h> */
#include <crm/crm.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/ipc.h>
#include <crm/common/ctrl.h>
#include <crm/common/xml.h>
#include <crm/common/msg.h>
#include <cibio.h>
#include <callbacks.h>
#include <crm/dmalloc_wrapper.h>
gboolean cib_shutdown_flag = FALSE;
extern void oc_ev_special(const oc_ev_t *, oc_ev_class_t , int );
GMainLoop* mainloop = NULL;
const char* crm_system_name = CRM_SYSTEM_CIB;
char *cib_our_uname = NULL;
oc_ev_t *cib_ev_token;
gboolean cib_writes_enabled = TRUE;
void usage(const char* cmd, int exit_status);
int init_start(void);
gboolean cib_register_ha(ll_cluster_t *hb_cluster, const char *client_name);
gboolean cib_shutdown(int nsig, gpointer unused);
void cib_ha_connection_destroy(gpointer user_data);
gboolean startCib(const char *filename);
extern gboolean cib_msg_timeout(gpointer data);
extern int write_cib_contents(gpointer p);
ll_cluster_t *hb_conn = NULL;
GTRIGSource *cib_writer = NULL;
#define OPTARGS "hV"
static void
cib_diskwrite_complete(gpointer userdata, int status, int signo, int exitcode)
{
if(exitcode != LSB_EXIT_OK || signo != 0 || status != 0) {
crm_err("Disk write failed: status=%d, signo=%d, exitcode=%d",
status, signo, exitcode);
if(cib_writes_enabled) {
crm_err("Disabling disk writes after write failure");
cib_writes_enabled = FALSE;
}
} else {
crm_debug_2("Disk write passed");
}
}
int
main(int argc, char ** argv)
{
int flag;
int argerr = 0;
crm_log_init(crm_system_name);
G_main_add_SignalHandler(
G_PRIORITY_HIGH, SIGTERM, cib_shutdown, NULL, NULL);
cib_writer = G_main_add_tempproc_trigger(
G_PRIORITY_LOW, write_cib_contents, "write_cib_contents",
NULL, NULL, NULL, cib_diskwrite_complete);
EnableProcLogging();
set_sigchld_proctrack(G_PRIORITY_HIGH);
client_list = g_hash_table_new(g_str_hash, g_str_equal);
peer_hash = g_hash_table_new(g_str_hash, g_str_equal);
while ((flag = getopt(argc, argv, OPTARGS)) != EOF) {
switch(flag) {
case 'V':
cl_log_enable_stderr(1);
alter_debug(DEBUG_INC);
break;
case 'h': /* Help message */
usage(crm_system_name, LSB_EXIT_OK);
break;
default:
++argerr;
break;
}
}
if (optind > argc) {
++argerr;
}
if (argerr) {
usage(crm_system_name,LSB_EXIT_GENERIC);
}
/* read local config file */
return init_start();
}
unsigned long cib_num_ops = 0;
const char *cib_stat_interval = "10min";
unsigned long cib_num_local = 0, cib_num_updates = 0, cib_num_fail = 0;
unsigned long cib_bad_connects = 0, cib_num_timeouts = 0;
longclock_t cib_call_time = 0;
gboolean cib_stats(gpointer data);
gboolean
cib_stats(gpointer data)
{
int local_log_level = LOG_DEBUG;
static unsigned long last_stat = 0;
unsigned int cib_calls_ms = 0;
static unsigned long cib_stat_interval_ms = 0;
if(cib_stat_interval_ms == 0) {
cib_stat_interval_ms = crm_get_msec(cib_stat_interval);
}
cib_calls_ms = longclockto_ms(cib_call_time);
if((cib_num_ops - last_stat) > 0) {
unsigned long calls_diff = cib_num_ops - last_stat;
double stat_1 = (1000*cib_calls_ms)/calls_diff;
local_log_level = LOG_INFO;
crm_log_maybe(local_log_level,
"Processed %lu operations"
" (%.2fus average, %lu%% utilization) in the last %s",
calls_diff, stat_1,
(100*cib_calls_ms)/cib_stat_interval_ms,
cib_stat_interval);
}
crm_log_maybe(local_log_level+1,
"\tDetail: %lu operations (%ums total)"
" (%lu local, %lu updates, %lu failures,"
" %lu timeouts, %lu bad connects)",
cib_num_ops, cib_calls_ms, cib_num_local, cib_num_updates,
cib_num_fail, cib_bad_connects, cib_num_timeouts);
last_stat = cib_num_ops;
cib_call_time = 0;
return TRUE;
}
int
init_start(void)
{
gboolean was_error = FALSE;
hb_conn = ll_cluster_new("heartbeat");
if(cib_register_ha(hb_conn, CRM_SYSTEM_CIB) == FALSE) {
crm_crit("Cannot sign in to heartbeat... terminating");
fprintf(stderr, "Cannot sign in to heartbeat... terminating");
exit(1);
}
if(startCib(CIB_FILENAME) == FALSE){
crm_crit("Cannot start CIB... terminating");
exit(1);
}
was_error = init_server_ipc_comms(
crm_strdup(cib_channel_callback), cib_client_connect_null,
default_ipc_connection_destroy);
was_error = was_error || init_server_ipc_comms(
crm_strdup(cib_channel_ro), cib_client_connect_rw_ro,
default_ipc_connection_destroy);
was_error = was_error || init_server_ipc_comms(
crm_strdup(cib_channel_rw), cib_client_connect_rw_ro,
default_ipc_connection_destroy);
was_error = was_error || init_server_ipc_comms(
crm_strdup(cib_channel_rw_synchronous), cib_client_connect_rw_synch,
default_ipc_connection_destroy);
was_error = was_error || init_server_ipc_comms(
crm_strdup(cib_channel_ro_synchronous), cib_client_connect_ro_synch,
default_ipc_connection_destroy);
if(was_error == FALSE) {
crm_debug_3("Be informed of CRM Client Status changes");
if (HA_OK != hb_conn->llc_ops->set_cstatus_callback(
hb_conn, cib_client_status_callback, hb_conn)) {
crm_err("Cannot set cstatus callback: %s",
hb_conn->llc_ops->errmsg(hb_conn));
was_error = TRUE;
} else {
crm_debug_3("Client Status callback set");
}
}
if(was_error == FALSE) {
gboolean did_fail = TRUE;
int num_ccm_fails = 0;
int max_ccm_fails = 30;
int ret;
int cib_ev_fd;
while(did_fail && was_error == FALSE) {
did_fail = FALSE;
crm_debug_3("Registering with CCM");
ret = oc_ev_register(&cib_ev_token);
if (ret != 0) {
crm_warn("CCM registration failed");
did_fail = TRUE;
}
if(did_fail == FALSE) {
crm_debug_3("Setting up CCM callbacks");
ret = oc_ev_set_callback(
cib_ev_token, OC_EV_MEMB_CLASS,
cib_ccm_msg_callback, NULL);
if (ret != 0) {
crm_warn("CCM callback not set");
did_fail = TRUE;
}
}
if(did_fail == FALSE) {
oc_ev_special(cib_ev_token, OC_EV_MEMB_CLASS, 0);
crm_debug_3("Activating CCM token");
ret = oc_ev_activate(cib_ev_token, &cib_ev_fd);
if (ret != 0){
crm_warn("CCM Activation failed");
did_fail = TRUE;
}
}
if(did_fail) {
num_ccm_fails++;
oc_ev_unregister(cib_ev_token);
if(num_ccm_fails < max_ccm_fails){
crm_warn("CCM Connection failed"
" %d times (%d max)",
num_ccm_fails, max_ccm_fails);
sleep(1);
} else {
crm_err("CCM Activation failed"
" %d (max) times",
num_ccm_fails);
was_error = TRUE;
}
}
}
crm_debug_3("CCM Activation passed... all set to go!");
G_main_add_fd(G_PRIORITY_HIGH, cib_ev_fd, FALSE,
cib_ccm_dispatch, cib_ev_token,
default_ipc_connection_destroy);
}
if(was_error == FALSE) {
/* Async get client status information in the cluster */
crm_debug_3("Requesting an initial dump of CIB client_status");
hb_conn->llc_ops->client_status(
hb_conn, NULL, CRM_SYSTEM_CIB, -1);
/* Create the mainloop and run it... */
mainloop = g_main_new(FALSE);
crm_info("Starting %s mainloop", crm_system_name);
Gmain_timeout_add(crm_get_msec("10s"), cib_msg_timeout, NULL);
Gmain_timeout_add(
crm_get_msec(cib_stat_interval), cib_stats, NULL);
g_main_run(mainloop);
return_to_orig_privs();
} else {
crm_err("Couldnt start all communication channels, exiting.");
}
return 0;
}
void
usage(const char* cmd, int exit_status)
{
FILE* stream;
stream = exit_status ? stderr : stdout;
fprintf(stream, "usage: %s [-srkh]"
"[-c configure file]\n", cmd);
/* fprintf(stream, "\t-d\tsets debug level\n"); */
/* fprintf(stream, "\t-s\tgets daemon status\n"); */
/* fprintf(stream, "\t-r\trestarts daemon\n"); */
/* fprintf(stream, "\t-k\tstops daemon\n"); */
/* fprintf(stream, "\t-h\thelp message\n"); */
fflush(stream);
exit(exit_status);
}
gboolean
cib_register_ha(ll_cluster_t *hb_cluster, const char *client_name)
{
const char *uname = NULL;
crm_info("Signing in with Heartbeat");
if (hb_cluster->llc_ops->signon(hb_cluster, client_name)!= HA_OK) {
crm_err("Cannot sign on with heartbeat: %s",
hb_cluster->llc_ops->errmsg(hb_cluster));
return FALSE;
}
- crm_set_ha_options(hb_cluster);
-
crm_debug_3("Be informed of CIB messages");
if (HA_OK != hb_cluster->llc_ops->set_msg_callback(
hb_cluster, T_CIB, cib_peer_callback, hb_cluster)){
crm_err("Cannot set msg callback: %s",
hb_cluster->llc_ops->errmsg(hb_cluster));
return FALSE;
}
crm_debug_3("Finding our node name");
if ((uname = hb_cluster->llc_ops->get_mynodeid(hb_cluster)) == NULL) {
crm_err("get_mynodeid() failed");
return FALSE;
}
cib_our_uname = crm_strdup(uname);
crm_info("FSA Hostname: %s", cib_our_uname);
crm_debug_3("Adding channel to mainloop");
G_main_add_IPC_Channel(
G_PRIORITY_DEFAULT, hb_cluster->llc_ops->ipcchan(hb_cluster),
FALSE, cib_ha_dispatch, hb_cluster /* userdata */,
cib_ha_connection_destroy);
return TRUE;
}
void
cib_ha_connection_destroy(gpointer user_data)
{
if(cib_shutdown_flag) {
crm_info("Heartbeat disconnection complete... exiting");
} else {
crm_err("Heartbeat connection lost! Exiting.");
}
if (mainloop != NULL && g_main_is_running(mainloop)) {
g_main_quit(mainloop);
} else {
exit(LSB_EXIT_OK);
}
}
static void
disconnect_cib_client(gpointer key, gpointer value, gpointer user_data)
{
cib_client_t *a_client = value;
crm_debug_2("Processing client %s/%s... send=%d, recv=%d",
a_client->name, a_client->channel_name,
(int)a_client->channel->send_queue->current_qlen,
(int)a_client->channel->recv_queue->current_qlen);
if(a_client->channel->ch_status == IPC_CONNECT) {
a_client->channel->ops->resume_io(a_client->channel);
if(a_client->channel->send_queue->current_qlen != 0
|| a_client->channel->recv_queue->current_qlen != 0) {
crm_info("Flushed messages to/from %s/%s... send=%d, recv=%d",
a_client->name, a_client->channel_name,
(int)a_client->channel->send_queue->current_qlen,
(int)a_client->channel->recv_queue->current_qlen);
}
}
if(a_client->channel->ch_status == IPC_CONNECT) {
crm_warn("Disconnecting %s/%s...",
a_client->name, a_client->channel_name);
a_client->channel->ops->disconnect(a_client->channel);
}
}
extern gboolean cib_process_disconnect(
IPC_Channel *channel, cib_client_t *cib_client);
gboolean
cib_shutdown(int nsig, gpointer unused)
{
if(cib_shutdown_flag == FALSE) {
cib_shutdown_flag = TRUE;
crm_debug("Disconnecting %d clients",
g_hash_table_size(client_list));
g_hash_table_foreach(client_list, disconnect_cib_client, NULL);
crm_info("Disconnected %d clients",
g_hash_table_size(client_list));
cib_process_disconnect(NULL, NULL);
} else {
crm_info("Waiting for %d clients to disconnect...",
g_hash_table_size(client_list));
}
return TRUE;
}
gboolean
startCib(const char *filename)
{
crm_data_t *cib = readCibXmlFile(filename);
if(cib == NULL) {
crm_warn("Cluster configuration not found: %s."
" Creating an empty one.", filename);
cib = createEmptyCib();
crm_xml_add(cib, XML_ATTR_GENERATION_ADMIN, "0");
crm_xml_add(cib, XML_ATTR_GENERATION, "0");
crm_xml_add(cib, XML_ATTR_NUMUPDATES, "0");
}
if(activateCibXml(cib, filename) != 0) {
return FALSE;
}
crm_info("CIB Initialization completed successfully");
return TRUE;
}
diff --git a/crm/crmd/control.c b/crm/crmd/control.c
index 8a0a9a8039..a274634493 100644
--- a/crm/crmd/control.c
+++ b/crm/crmd/control.c
@@ -1,768 +1,766 @@
/*
* 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 <heartbeat.h>
#include <crm/crm.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/ctrl.h>
#include <crmd.h>
#include <crmd_fsa.h>
#include <fsa_proto.h>
#include <crmd_messages.h>
#include <crmd_callbacks.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <crm/dmalloc_wrapper.h>
extern void crmd_ha_connection_destroy(gpointer user_data);
extern gboolean stop_all_resources(void);
gboolean crm_shutdown(int nsig, gpointer unused);
gboolean register_with_ha(ll_cluster_t *hb_cluster, const char *client_name);
void populate_cib_nodes(ll_cluster_t *hb_cluster, gboolean with_client_status);
GHashTable *ipc_clients = NULL;
GTRIGSource *fsa_source = NULL;
/* A_HA_CONNECT */
enum crmd_fsa_input
do_ha_control(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
gboolean registered = FALSE;
if(action & A_HA_DISCONNECT) {
if(fsa_cluster_conn != NULL) {
set_bit_inplace(fsa_input_register, R_HA_DISCONNECTED);
fsa_cluster_conn->llc_ops->signoff(
fsa_cluster_conn, FALSE);
fsa_cluster_conn->llc_ops->delete(fsa_cluster_conn);
fsa_cluster_conn = NULL;
}
crm_info("Disconnected from Heartbeat");
}
if(action & A_HA_CONNECT) {
if(fsa_cluster_conn == NULL) {
fsa_cluster_conn = ll_cluster_new("heartbeat");
}
/* make sure we are disconnected first */
fsa_cluster_conn->llc_ops->signoff(fsa_cluster_conn, FALSE);
registered = register_with_ha(
fsa_cluster_conn, crm_system_name);
if(registered == FALSE) {
register_fsa_error(C_FSA_INTERNAL, I_FAIL, NULL);
return I_NULL;
}
clear_bit_inplace(fsa_input_register, R_HA_DISCONNECTED);
crm_info("Connected to Heartbeat");
}
if(action & ~(A_HA_CONNECT|A_HA_DISCONNECT)) {
crm_err("Unexpected action %s in %s",
fsa_action2string(action), __FUNCTION__);
}
return I_NULL;
}
/* A_SHUTDOWN */
enum crmd_fsa_input
do_shutdown(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
int lpc = 0;
gboolean continue_shutdown = TRUE;
struct crm_subsystem_s *subsystems[] = {
pe_subsystem,
te_subsystem
};
/* just in case */
set_bit_inplace(fsa_input_register, R_SHUTDOWN);
for(lpc = 0; lpc < DIMOF(subsystems); lpc++) {
struct crm_subsystem_s *a_subsystem = subsystems[lpc];
if(is_set(fsa_input_register, a_subsystem->flag_connected)) {
crm_info("Terminating the %s", a_subsystem->name);
if(stop_subsystem(a_subsystem, TRUE) == FALSE) {
/* its gone... */
crm_err("Faking %s exit", a_subsystem->name);
clear_bit_inplace(fsa_input_register,
a_subsystem->flag_connected);
}
continue_shutdown = FALSE;
}
}
if(continue_shutdown == FALSE) {
crm_info("Waiting for subsystems to exit");
crmd_fsa_stall(NULL);
} else {
register_fsa_input(C_FSA_INTERNAL, I_TERMINATE, NULL);
}
return I_NULL;
}
/* A_SHUTDOWN_REQ */
enum crmd_fsa_input
do_shutdown_req(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
HA_Message *msg = NULL;
crm_info("Sending shutdown request to DC: %s", crm_str(fsa_our_dc));
msg = create_request(
CRM_OP_SHUTDOWN_REQ, NULL, NULL,
CRM_SYSTEM_DC, CRM_SYSTEM_CRMD, NULL);
/* set_bit_inplace(fsa_input_register, R_STAYDOWN); */
if(send_request(msg, NULL) == FALSE) {
if(AM_I_DC) {
crm_info("Processing shutdown locally");
} else {
register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
}
}
return I_NULL;
}
/* A_EXIT_0, A_EXIT_1 */
enum crmd_fsa_input
do_exit(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
int exit_code = 0;
int log_level = LOG_INFO;
const char *exit_type = "gracefully";
if(action & A_EXIT_1) {
exit_code = 1;
log_level = LOG_ERR;
exit_type = "forcefully";
}
crm_log_maybe(log_level, "Performing %s - %s exiting the CRMd",
fsa_action2string(action), exit_type);
if(is_set(fsa_input_register, R_IN_RECOVERY)) {
crm_err("Could not recover from internal error");
exit_code = 2;
} else if(is_set(fsa_input_register, R_STAYDOWN)) {
crm_warn("Inhibiting respawn by Heartbeat");
exit_code = 100;
}
crm_info("[%s] stopped (%d)", crm_system_name, exit_code);
exit(exit_code);
return I_NULL;
}
/* A_STARTUP */
enum crmd_fsa_input
do_startup(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
int was_error = 0;
int interval = 1; /* seconds between DC heartbeats */
crm_debug("Registering Signal Handlers");
G_main_add_SignalHandler(
G_PRIORITY_HIGH, SIGTERM, crm_shutdown, NULL, NULL);
fsa_source = G_main_add_TriggerHandler(
G_PRIORITY_HIGH, crm_fsa_trigger, NULL, NULL);
ipc_clients = g_hash_table_new(g_str_hash, g_str_equal);
if(was_error == 0) {
crm_debug("Init server comms");
was_error = init_server_ipc_comms(
crm_strdup(CRM_SYSTEM_CRMD), crmd_client_connect,
default_ipc_connection_destroy);
}
if(was_error == 0) {
crm_debug("Creating CIB object");
fsa_cib_conn = cib_new();
}
/* set up the timers */
crm_malloc0(integration_timer, sizeof(fsa_timer_t));
crm_malloc0(finalization_timer, sizeof(fsa_timer_t));
crm_malloc0(election_trigger, sizeof(fsa_timer_t));
crm_malloc0(election_timeout, sizeof(fsa_timer_t));
crm_malloc0(shutdown_escalation_timer, sizeof(fsa_timer_t));
crm_malloc0(wait_timer, sizeof(fsa_timer_t));
crm_malloc0(recheck_timer, sizeof(fsa_timer_t));
interval = interval * 1000;
if(election_trigger != NULL) {
election_trigger->source_id = 0;
election_trigger->period_ms = -1;
election_trigger->fsa_input = I_DC_TIMEOUT;
election_trigger->callback = crm_timer_popped;
election_trigger->repeat = FALSE;
} else {
was_error = TRUE;
}
if(election_timeout != NULL) {
election_timeout->source_id = 0;
election_timeout->period_ms = -1;
election_timeout->fsa_input = I_ELECTION_DC;
election_timeout->callback = crm_timer_popped;
election_timeout->repeat = FALSE;
} else {
was_error = TRUE;
}
if(integration_timer != NULL) {
integration_timer->source_id = 0;
integration_timer->period_ms = -1;
integration_timer->fsa_input = I_INTEGRATED;
integration_timer->callback = crm_timer_popped;
integration_timer->repeat = FALSE;
} else {
was_error = TRUE;
}
if(finalization_timer != NULL) {
finalization_timer->source_id = 0;
finalization_timer->period_ms = -1;
finalization_timer->fsa_input = I_FINALIZED;
finalization_timer->callback = crm_timer_popped;
finalization_timer->repeat = FALSE;
/* for possible enabling... a bug in the join protocol left
* a slave in S_PENDING while we think its in S_NOT_DC
*
* raising I_FINALIZED put us into a transition loop which is
* never resolved.
* in this loop we continually send probes which the node
* NACK's because its in S_PENDING
*
* if we have nodes where heartbeat is active but the
* CRM is not... then this will be handled in the
* integration phase
*/
finalization_timer->fsa_input = I_ELECTION;
} else {
was_error = TRUE;
}
if(shutdown_escalation_timer != NULL) {
shutdown_escalation_timer->source_id = 0;
shutdown_escalation_timer->period_ms = -1;
shutdown_escalation_timer->fsa_input = I_STOP;
shutdown_escalation_timer->callback = crm_timer_popped;
shutdown_escalation_timer->repeat = FALSE;
} else {
was_error = TRUE;
}
if(wait_timer != NULL) {
wait_timer->source_id = 0;
wait_timer->period_ms = 500;
wait_timer->fsa_input = I_NULL;
wait_timer->callback = crm_timer_popped;
wait_timer->repeat = FALSE;
} else {
was_error = TRUE;
}
if(recheck_timer != NULL) {
recheck_timer->source_id = 0;
recheck_timer->period_ms = -1;
recheck_timer->fsa_input = I_PE_CALC;
recheck_timer->callback = crm_timer_popped;
recheck_timer->repeat = FALSE;
} else {
was_error = TRUE;
}
/* set up the sub systems */
crm_malloc0(cib_subsystem, sizeof(struct crm_subsystem_s));
crm_malloc0(te_subsystem, sizeof(struct crm_subsystem_s));
crm_malloc0(pe_subsystem, sizeof(struct crm_subsystem_s));
if(cib_subsystem != NULL) {
cib_subsystem->pid = -1;
cib_subsystem->path = BIN_DIR;
cib_subsystem->name = CRM_SYSTEM_CIB;
cib_subsystem->command = BIN_DIR"/"CRM_SYSTEM_CIB;
cib_subsystem->args = "-VVc";
cib_subsystem->flag_connected = R_CIB_CONNECTED;
cib_subsystem->flag_required = R_CIB_REQUIRED;
} else {
was_error = TRUE;
}
if(te_subsystem != NULL) {
te_subsystem->pid = -1;
te_subsystem->path = BIN_DIR;
te_subsystem->name = CRM_SYSTEM_TENGINE;
te_subsystem->command = BIN_DIR"/"CRM_SYSTEM_TENGINE;
te_subsystem->args = NULL;
te_subsystem->flag_connected = R_TE_CONNECTED;
te_subsystem->flag_required = R_TE_REQUIRED;
} else {
was_error = TRUE;
}
if(pe_subsystem != NULL) {
pe_subsystem->pid = -1;
pe_subsystem->path = BIN_DIR;
pe_subsystem->name = CRM_SYSTEM_PENGINE;
pe_subsystem->command = BIN_DIR"/"CRM_SYSTEM_PENGINE;
pe_subsystem->args = NULL;
pe_subsystem->flag_connected = R_PE_CONNECTED;
pe_subsystem->flag_required = R_PE_REQUIRED;
} else {
was_error = TRUE;
}
if(was_error) {
register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
}
welcomed_nodes = g_hash_table_new_full(
g_str_hash, g_str_equal,
g_hash_destroy_str, g_hash_destroy_str);
integrated_nodes = g_hash_table_new_full(
g_str_hash, g_str_equal,
g_hash_destroy_str, g_hash_destroy_str);
finalized_nodes = g_hash_table_new_full(
g_str_hash, g_str_equal,
g_hash_destroy_str, g_hash_destroy_str);
confirmed_nodes = g_hash_table_new_full(
g_str_hash, g_str_equal,
g_hash_destroy_str, g_hash_destroy_str);
crmd_peer_state = g_hash_table_new_full(
g_str_hash, g_str_equal,
g_hash_destroy_str, g_hash_destroy_str);
set_sigchld_proctrack(G_PRIORITY_HIGH);
return I_NULL;
}
extern GHashTable *shutdown_ops;
/* A_STOP */
enum crmd_fsa_input
do_stop(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
crm_debug_2("Stopping all remaining local resources");
if(is_set(fsa_input_register, R_LRM_CONNECTED)) {
stop_all_resources();
} else {
crm_err("Exiting with no LRM connection..."
" resources may be active!");
}
if(g_hash_table_size(shutdown_ops) > 0) {
crm_info("Waiting on %d stop operations to complete",
g_hash_table_size(shutdown_ops));
crmd_fsa_stall(NULL);
return I_NULL;
}
return I_NULL;
}
/* A_STARTED */
enum crmd_fsa_input
do_started(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
if(is_set(fsa_input_register, R_CCM_DATA) == FALSE) {
crm_info("Delaying start, CCM (%.16llx) not connected",
R_CCM_DATA);
crmd_fsa_stall(NULL);
return I_NULL;
} else if(is_set(fsa_input_register, R_LRM_CONNECTED) == FALSE) {
crm_info("Delaying start, LRM (%.16llx) not connected",
R_LRM_CONNECTED);
crmd_fsa_stall(NULL);
return I_NULL;
} else if(is_set(fsa_input_register, R_CIB_CONNECTED) == FALSE) {
crm_info("Delaying start, CIB (%.16llx) not connected",
R_CIB_CONNECTED);
crmd_fsa_stall(NULL);
return I_NULL;
} else if(is_set(fsa_input_register, R_READ_CONFIG) == FALSE) {
crm_info("Delaying start, Config not read (%.16llx)",
R_READ_CONFIG);
crmd_fsa_stall(NULL);
return I_NULL;
} else if(is_set(fsa_input_register, R_PEER_DATA) == FALSE) {
HA_Message * msg = NULL;
/* try reading from HA */
crm_info("Delaying start, Peer data (%.16llx) not recieved",
R_PEER_DATA);
crm_debug_3("Looking for a HA message");
msg = fsa_cluster_conn->llc_ops->readmsg(fsa_cluster_conn, 0);
if(msg != NULL) {
crm_debug_3("There was a HA message");
crm_msg_del(msg);
}
crm_timer_start(wait_timer);
crmd_fsa_stall(NULL);
return I_NULL;
}
crm_info("The local CRM is operational");
clear_bit_inplace(fsa_input_register, R_STARTING);
register_fsa_input(msg_data->fsa_cause, I_PENDING, NULL);
return I_NULL;
}
/* A_RECOVER */
enum crmd_fsa_input
do_recover(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
set_bit_inplace(fsa_input_register, R_IN_RECOVERY);
crm_err("Action %s (%.16llx) not supported",
fsa_action2string(action), action);
register_fsa_input(C_FSA_INTERNAL, I_STOP, NULL);
return I_NULL;
}
static void
config_query_callback(const HA_Message *msg, int call_id, int rc,
crm_data_t *output, void *user_data)
{
crm_debug("Call %d : Parsing CIB options", call_id);
if(rc != cib_ok) {
fsa_data_t *msg_data = NULL;
crm_err("Local CIB query resulted in an error: %s",
cib_error2string(rc));
register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
return;
}
#if 0
/* disable until we can do it properly
* - most people use the defaults anyway
*/
crm_data_t *config = output;
xml_child_iter_filter(
config, iter, XML_CIB_TAG_NVPAIR,
const char *name = crm_element_value(iter, XML_NVPAIR_ATTR_NAME);
const char *value = crm_element_value(iter, XML_NVPAIR_ATTR_VALUE);
if(name == NULL || value == NULL) {
continue;
} else if(safe_str_eq(name, XML_CONFIG_ATTR_DC_DEADTIME)) {
election_trigger->period_ms = crm_get_msec(value);
} else if(safe_str_eq(name, XML_CONFIG_ATTR_FORCE_QUIT)) {
shutdown_escalation_timer->period_ms = crm_get_msec(value);
} else if(safe_str_eq(name, XML_CONFIG_ATTR_RECHECK)) {
recheck_timer->period_ms = crm_get_msec(value);
}
);
#endif
set_bit_inplace(fsa_input_register, R_READ_CONFIG);
crm_debug_3("Triggering FSA: %s", __FUNCTION__);
G_main_set_trigger(fsa_source);
}
/* A_READCONFIG */
enum crmd_fsa_input
do_read_config(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
char *param_val = NULL;
const char *param_name = NULL;
int call_id = fsa_cib_conn->cmds->query(
fsa_cib_conn, XML_CIB_TAG_CRMCONFIG, NULL, cib_scope_local);
add_cib_op_callback(call_id, FALSE, NULL, config_query_callback);
crm_debug_2("Querying the CIB... call %d", call_id);
/* defaults */
election_trigger->period_ms = crm_get_msec("5s");
election_timeout->period_ms = crm_get_msec("2min");
integration_timer->period_ms = crm_get_msec("3min");
finalization_timer->period_ms = crm_get_msec("3min");
shutdown_escalation_timer->period_ms = crm_get_msec("10min");
/* apparently we're not allowed to free the result of getenv */
param_name = ENV_PREFIX "" KEY_INITDEAD;
param_val = getenv(param_name);
if(param_val != NULL) {
int tmp = crm_get_msec(param_val) / 2;
if(tmp > election_trigger->period_ms) {
election_trigger->period_ms = tmp;
}
crm_debug("%s = %s", param_name, param_val);
param_val = NULL;
}
return I_NULL;
}
gboolean
crm_shutdown(int nsig, gpointer unused)
{
if (crmd_mainloop != NULL && g_main_is_running(crmd_mainloop)) {
if(is_set(fsa_input_register, R_SHUTDOWN)) {
crm_err("Escalating the shutdown");
register_fsa_input_before(C_SHUTDOWN, I_ERROR, NULL);
} else {
crm_info("Requesting shutdown");
set_bit_inplace(fsa_input_register, R_SHUTDOWN);
register_fsa_input(C_SHUTDOWN,I_SHUTDOWN,NULL);
/* cant rely on this... */
crm_timer_start(shutdown_escalation_timer);
}
} else {
crm_info("exit from shutdown");
exit(LSB_EXIT_OK);
}
return TRUE;
}
static void
default_cib_update_callback(const HA_Message *msg, int call_id, int rc,
crm_data_t *output, void *user_data)
{
if(rc != cib_ok) {
fsa_data_t *msg_data = NULL;
crm_err("CIB Update failed: %s", cib_error2string(rc));
crm_log_xml_warn(output, "update:failed");
register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
}
}
void
populate_cib_nodes(ll_cluster_t *hb_cluster, gboolean with_client_status)
{
int call_id = 0;
const char *ha_node = NULL;
crm_data_t *cib_node_list = NULL;
/* Async get client status information in the cluster */
crm_debug_2("Invoked");
if(with_client_status) {
crm_debug_3("Requesting an initial dump of CRMD client_status");
fsa_cluster_conn->llc_ops->client_status(
fsa_cluster_conn, NULL, CRM_SYSTEM_CRMD, -1);
}
crm_info("Requesting the list of configured nodes");
fsa_cluster_conn->llc_ops->init_nodewalk(fsa_cluster_conn);
cib_node_list = create_xml_node(NULL, XML_CIB_TAG_NODES);
do {
const char *ha_node_type = NULL;
const char *ha_node_uuid = NULL;
crm_data_t *cib_new_node = NULL;
ha_node = fsa_cluster_conn->llc_ops->nextnode(fsa_cluster_conn);
if(ha_node == NULL) {
continue;
}
ha_node_type = fsa_cluster_conn->llc_ops->node_type(
fsa_cluster_conn, ha_node);
if(safe_str_neq(NORMALNODE, ha_node_type)) {
crm_debug("Node %s: skipping '%s'",
ha_node, ha_node_type);
continue;
}
ha_node_uuid = get_uuid(fsa_cluster_conn, ha_node);
if(ha_node_uuid == NULL) {
crm_warn("Node %s: no uuid found", ha_node);
continue;
}
crm_notice("Node: %s (uuid: %s)", ha_node, ha_node_uuid);
cib_new_node = create_xml_node(cib_node_list, XML_CIB_TAG_NODE);
crm_xml_add(cib_new_node, XML_ATTR_ID, ha_node_uuid);
crm_xml_add(cib_new_node, XML_ATTR_UNAME, ha_node);
crm_xml_add(cib_new_node, XML_ATTR_TYPE, ha_node_type);
} while(ha_node != NULL);
fsa_cluster_conn->llc_ops->end_nodewalk(fsa_cluster_conn);
/* Now update the CIB with the list of nodes */
call_id = fsa_cib_conn->cmds->update(
fsa_cib_conn, XML_CIB_TAG_NODES, cib_node_list, NULL,
cib_scope_local|cib_quorum_override|cib_inhibit_bcast);
add_cib_op_callback(call_id, FALSE, NULL, default_cib_update_callback);
free_xml(cib_node_list);
crm_debug_2("Complete");
}
gboolean
register_with_ha(ll_cluster_t *hb_cluster, const char *client_name)
{
crm_debug("Signing in with Heartbeat");
if (hb_cluster->llc_ops->signon(hb_cluster, client_name)!= HA_OK) {
crm_err("Cannot sign on with heartbeat: %s",
hb_cluster->llc_ops->errmsg(hb_cluster));
return FALSE;
}
- crm_set_ha_options(hb_cluster);
-
crm_debug_3("Be informed of CRM messages");
if (HA_OK != hb_cluster->llc_ops->set_msg_callback(
hb_cluster, T_CRM, crmd_ha_msg_callback, hb_cluster)){
crm_err("Cannot set msg callback: %s",
hb_cluster->llc_ops->errmsg(hb_cluster));
return FALSE;
}
#if 0
crm_debug_3("Be informed of Node Status changes");
if (HA_OK != hb_cluster->llc_ops->set_nstatus_callback(
hb_cluster, crmd_ha_status_callback, hb_cluster)){
crm_err("Cannot set nstatus callback: %s",
hb_cluster->llc_ops->errmsg(hb_cluster));
return FALSE;
}
#endif
crm_debug_3("Be informed of CRM Client Status changes");
if (HA_OK != hb_cluster->llc_ops->set_cstatus_callback(
hb_cluster, crmd_client_status_callback, hb_cluster)) {
crm_err("Cannot set cstatus callback: %s",
hb_cluster->llc_ops->errmsg(hb_cluster));
return FALSE;
}
crm_debug_3("Adding channel to mainloop");
G_main_add_IPC_Channel(
G_PRIORITY_HIGH, hb_cluster->llc_ops->ipcchan(hb_cluster),
FALSE, crmd_ha_msg_dispatch, hb_cluster /* userdata */,
crmd_ha_connection_destroy);
crm_debug_3("Finding our node name");
if ((fsa_our_uname =
hb_cluster->llc_ops->get_mynodeid(hb_cluster)) == NULL) {
crm_err("get_mynodeid() failed");
return FALSE;
}
crm_info("Hostname: %s", fsa_our_uname);
crm_debug_3("Finding our node uuid");
fsa_our_uuid = get_uuid(fsa_cluster_conn, fsa_our_uname);
if(fsa_our_uuid == NULL) {
crm_err("get_uuid_by_name() failed");
return FALSE;
}
/* copy it so that unget_uuid() doesn't trash the value on us */
fsa_our_uuid = crm_strdup(fsa_our_uuid);
crm_info("UUID: %s", fsa_our_uuid);
populate_cib_nodes(hb_cluster, TRUE);
return TRUE;
}
diff --git a/include/crm/common/util.h b/include/crm/common/util.h
index 3bb3b735d5..d1a0e2043f 100644
--- a/include/crm/common/util.h
+++ b/include/crm/common/util.h
@@ -1,138 +1,136 @@
-/* $Id: util.h,v 1.32 2006/04/10 12:49:15 andrew Exp $ */
+/* $Id: util.h,v 1.33 2006/04/10 16:18:25 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
*/
#ifndef CRM_COMMON_UTIL__H
#define CRM_COMMON_UTIL__H
#include <signal.h>
#include <crm/common/xml.h>
#include <hb_api.h>
#include <ocf/oc_event.h>
#include <lrm/lrm_api.h>
#define DEBUG_INC SIGUSR1
#define DEBUG_DEC SIGUSR2
extern unsigned int crm_log_level;
extern gboolean crm_log_init(const char *entity);
extern void do_crm_log(int log_level, const char *file, const char *function,
const char *format, ...) G_GNUC_PRINTF(4,5);
/* returns the old value */
extern unsigned int set_crm_log_level(unsigned int level);
extern unsigned int get_crm_log_level(void);
extern char *crm_itoa(int an_int);
extern char *crm_strdup(const char *a);
extern char *generate_hash_key(const char *crm_msg_reference, const char *sys);
extern char *generate_hash_value(const char *src_node, const char *src_subsys);
extern gboolean decode_hash_value(gpointer value, char **node, char **subsys);
extern gboolean decodeNVpair(const char *srcstring,
char separator, char **name, char **value);
extern int compare_version(const char *version1, const char *version2);
extern char *generateReference(const char *custom1, const char *custom2);
extern void alter_debug(int nsig);
extern void g_hash_destroy_str(gpointer data);
extern const char *get_uuid(ll_cluster_t *hb, const char *uname);
extern const char *get_uname(ll_cluster_t *hb, const char *uuid);
extern void unget_uuid(const char *uname);
extern void set_uuid(
ll_cluster_t* hb, crm_data_t *node, const char *attr, const char *uname);
-extern void crm_set_ha_options(ll_cluster_t *hb_cluster);
-
extern gboolean crm_is_true(const char * s);
extern int crm_str_to_boolean(const char * s, int * ret);
extern long crm_get_msec(const char * input);
extern gboolean ccm_have_quorum(oc_ed_t event);
extern const char *ccm_event_name(oc_ed_t event);
extern const char *op_status2text(op_status_t status);
extern char *generate_op_key(
const char *rsc_id, const char *op_type, int interval);
extern char *generate_notify_key(
const char *rsc_id, const char *notify_type, const char *op_type);
extern gboolean crm_mem_stats(volatile cl_mem_stats_t *mem_stats);
extern void crm_zero_mem_stats(volatile cl_mem_stats_t *stats);
extern char *generate_transition_magic_v202(
const char *transition_key, int op_status);
extern char *generate_transition_magic(
const char *transition_key, int op_status, int op_rc);
extern gboolean decode_transition_magic(
const char *magic, char **uuid,
int *transition_id, int *op_status, int *op_rc);
extern char *generate_transition_key(int transition_id, const char *node);
extern gboolean decode_transition_key(
const char *key, char **uuid, int *transition_id);
extern char *crm_concat(const char *prefix, const char *suffix, char join);
extern gboolean decode_op_key(
const char *key, char **rsc_id, char **op_type, int *interval);
extern void filter_action_parameters(crm_data_t *param_set);
extern gboolean safe_str_eq(const char *a, const char *b);
extern gboolean safe_str_neq(const char *a, const char *b);
extern int crm_parse_int(const char *text, const char *default_text);
extern int crm_int_helper(const char *text, char **end_text);
#define crm_atoi(text, default_text) crm_parse_int(text, default_text)
extern void crm_abort(const char *file, const char *function, int line,
const char *condition, gboolean do_fork);
extern char *generate_series_filename(
const char *directory, const char *series, int sequence, gboolean bzip);
extern int get_last_sequence(const char *directory, const char *series);
extern void write_last_sequence(
const char *directory, const char *series, int sequence, int max);
extern void crm_make_daemon(
const char *name, gboolean daemonize, const char *pidfile);
#endif
diff --git a/lib/crm/common/utils.c b/lib/crm/common/utils.c
index 1a17fd6d14..b649d1feb4 100644
--- a/lib/crm/common/utils.c
+++ b/lib/crm/common/utils.c
@@ -1,1427 +1,1348 @@
-/* $Id: utils.c,v 1.45 2006/04/10 12:49:15 andrew Exp $ */
+/* $Id: utils.c,v 1.46 2006/04/10 16:18:08 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 <clplumbing/lsb_exitcodes.h>
#include <clplumbing/cl_pidfile.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_ASSERT(name != NULL && value != NULL);
*name = NULL;
*value = NULL;
crm_debug_4("Attempting to decode: [%s]", srcstring);
if (srcstring != NULL) {
len = strlen(srcstring);
while(lpc <= len) {
if (srcstring[lpc] == separator) {
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++;
}
}
if(*name != NULL) {
crm_free(*name);
}
*name = NULL;
*value = NULL;
return FALSE;
}
char *
crm_concat(const char *prefix, const char *suffix, char join)
{
int len = 0;
char *new_str = NULL;
CRM_ASSERT(prefix != NULL);
CRM_ASSERT(suffix != NULL);
len = strlen(prefix) + strlen(suffix) + 2;
crm_malloc0(new_str, sizeof(char)*(len));
sprintf(new_str, "%s%c%s", prefix, join, suffix);
new_str[len-1] = 0;
return new_str;
}
char *
generate_hash_key(const char *crm_msg_reference, const char *sys)
{
char *hash_key = crm_concat(sys?sys:"none", crm_msg_reference, '_');
crm_debug_3("created hash key: (%s)", hash_key);
return hash_key;
}
char *
generate_hash_value(const char *src_node, const char *src_subsys)
{
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 hash_value;
}
hash_value = crm_concat(src_node, src_subsys, '_');
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_CHECK(value != NULL, return FALSE);
CRM_CHECK(node != NULL, return FALSE);
CRM_CHECK(subsys != NULL, return FALSE);
*node = NULL;
*subsys = NULL;
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);
CRM_CHECK(*subsys != NULL, return FALSE);
crm_info("Decoded value: (%s:%d)", *subsys,
(int)strlen(*subsys));
return TRUE;
} else if (decodeNVpair(char_value, '_', node, subsys)) {
return TRUE;
}
crm_free(*node);
crm_free(*subsys);
*node = NULL;
*subsys = NULL;
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;
}
rest1 = crm_strdup(version1);
rest2 = crm_strdup(version2);
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 = crm_parse_int(step1, NULL);
}
if(step2 != NULL) {
step2_i = crm_parse_int(step2, NULL);
}
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_3("%s < %s", version1, version2);
return -1;
} else if(cmp > 0) {
crm_debug_3("%s > %s", version1, version2);
return 1;
}
}
crm_debug_3("%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++;
break;
case DEBUG_DEC:
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);
}
int
crm_int_helper(const char *text, char **end_text)
{
int atoi_result = -1;
char *local_end_text = NULL;
errno = 0;
if(text != NULL) {
if(end_text != NULL) {
atoi_result = (int)strtol(text, end_text, 10);
} else {
atoi_result = (int)strtol(text, &local_end_text, 10);
}
/* CRM_CHECK(errno != EINVAL); */
if(errno == EINVAL) {
crm_err("Conversion of %s failed", text);
atoi_result = -1;
} else {
if(errno == ERANGE) {
crm_err("Conversion of %s was clipped", text);
}
if(end_text == NULL && local_end_text[0] != '\0') {
crm_err("Characters left over after parsing "
"\"%s\": \"%s\"", text, local_end_text);
}
}
}
return atoi_result;
}
int
crm_parse_int(const char *text, const char *default_text)
{
int atoi_result = -1;
if(text != NULL) {
atoi_result = crm_int_helper(text, NULL);
if(errno == 0) {
return atoi_result;
}
}
if(default_text != NULL) {
atoi_result = crm_int_helper(default_text, NULL);
if(errno == 0) {
return atoi_result;
}
} else {
crm_err("No default conversion value supplied");
}
return -1;
}
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_CHECK(a != NULL, return NULL);
if(a != NULL) {
ret = cl_strdup(a);
} else {
crm_warn("Cannot dup NULL string");
}
return ret;
}
static GHashTable *crm_uuid_cache = NULL;
static GHashTable *crm_uname_cache = NULL;
void
unget_uuid(const char *uname)
{
if(crm_uuid_cache == NULL) {
return;
}
g_hash_table_remove(crm_uuid_cache, uname);
}
const char *
get_uuid(ll_cluster_t *hb, const char *uname)
{
cl_uuid_t uuid_raw;
char *uuid_calc = NULL;
const char *unknown = "00000000-0000-0000-0000-000000000000";
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_CHECK(uname != NULL, return NULL);
/* avoid blocking calls where possible */
uuid_calc = g_hash_table_lookup(crm_uuid_cache, uname);
if(uuid_calc != NULL) {
return uuid_calc;
}
if(hb->llc_ops->get_uuid_by_name(hb, uname, &uuid_raw) == HA_FAIL) {
crm_err("get_uuid_by_name() call failed for host %s", uname);
crm_free(uuid_calc);
return NULL;
}
crm_malloc0(uuid_calc, sizeof(char)*50);
if(uuid_calc == NULL) {
return NULL;
}
cl_uuid_unparse(&uuid_raw, uuid_calc);
if(safe_str_eq(uuid_calc, unknown)) {
crm_warn("Could not calculate UUID for %s", uname);
crm_free(uuid_calc);
return NULL;
}
g_hash_table_insert(crm_uuid_cache, crm_strdup(uname), uuid_calc);
uuid_calc = g_hash_table_lookup(crm_uuid_cache, uname);
return uuid_calc;
}
const char *
get_uname(ll_cluster_t *hb, const char *uuid)
{
char *uname = NULL;
if(crm_uuid_cache == NULL) {
crm_uname_cache = g_hash_table_new_full(
g_str_hash, g_str_equal,
g_hash_destroy_str, g_hash_destroy_str);
}
CRM_CHECK(uuid != NULL, return NULL);
/* avoid blocking calls where possible */
uname = g_hash_table_lookup(crm_uname_cache, uuid);
if(uname != NULL) {
return uname;
}
if(uuid != NULL) {
cl_uuid_t uuid_raw;
char *uuid_copy = crm_strdup(uuid);
cl_uuid_parse(uuid_copy, &uuid_raw);
if(hb->llc_ops->get_name_by_uuid(
hb, &uuid_raw, uname, 256) == HA_FAIL) {
crm_err("Could not calculate UUID for %s", uname);
uname = NULL;
crm_free(uuid_copy);
} else {
g_hash_table_insert(
crm_uuid_cache,
uuid_copy, crm_strdup(uname));
uname = g_hash_table_lookup(crm_uname_cache, uuid);
}
return uname;
}
return NULL;
}
void
set_uuid(ll_cluster_t *hb,crm_data_t *node,const char *attr,const char *uname)
{
const char *uuid_calc = get_uuid(hb, uname);
crm_xml_add(node, attr, uuid_calc);
return;
}
-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 = crm_parse_int(param_val, NULL);
- 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;
- 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);
if(param_val != NULL) {
int debug_level = crm_parse_int(param_val, NULL);
if(debug_level > 0 && (debug_level+LOG_INFO) > (int)crm_log_level) {
set_crm_log_level(LOG_INFO + debug_level);
}
crm_debug("%s = %s", param_name, param_val);
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;
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;
}
inherit_compress();
}
gboolean
crm_is_true(const char * s)
{
gboolean ret = FALSE;
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){
*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){
*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_CHECK(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_CHECK(rsc_id != NULL, return NULL);
CRM_CHECK(op_type != NULL, return NULL);
len += strlen(op_type);
len += strlen(rsc_id);
crm_malloc0(op_id, sizeof(char)*len);
CRM_CHECK(op_id != NULL, return 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_CHECK(rsc_id != NULL, return NULL);
CRM_CHECK(op_type != NULL, return NULL);
CRM_CHECK(notify_type != NULL, 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_v202(const char *transition_key, int op_status)
{
int len = 80;
char *fail_state = NULL;
CRM_CHECK(transition_key != NULL, 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;
}
char *
generate_transition_magic(const char *transition_key, int op_status, int op_rc)
{
int len = 80;
char *fail_state = NULL;
CRM_CHECK(transition_key != NULL, return NULL);
len += strlen(transition_key);
crm_malloc0(fail_state, sizeof(char)*len);
if(fail_state != NULL) {
snprintf(fail_state, len, "%d:%d;%s",
op_status, op_rc, transition_key);
}
return fail_state;
}
gboolean
decode_transition_magic(
const char *magic, char **uuid, int *transition_id,
int *op_status, int *op_rc)
{
char *rc = NULL;
char *key = NULL;
char *magic2 = NULL;
char *status = NULL;
if(decodeNVpair(magic, ':', &status, &magic2) == FALSE) {
crm_err("Couldn't find ':' in: %s", magic);
return FALSE;
}
if(decodeNVpair(magic2, ';', &rc, &key) == FALSE) {
crm_err("Couldn't find ';' in: %s", magic2);
return FALSE;
}
CRM_CHECK(decode_transition_key(key, uuid, transition_id), return FALSE);
*op_rc = crm_parse_int(rc, NULL);
*op_status = crm_parse_int(status, NULL);
crm_free(rc);
crm_free(key);
crm_free(magic2);
crm_free(status);
return TRUE;
}
char *
generate_transition_key(int transition_id, const char *node)
{
int len = 40;
char *fail_state = NULL;
CRM_CHECK(node != NULL, 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) {
crm_err("Couldn't find ':' in: %s", key);
return FALSE;
}
*transition_id = crm_parse_int(transition, NULL);
crm_free(transition);
return TRUE;
}
void
filter_action_parameters(crm_data_t *param_set)
{
const char *attr_filter[] = {
XML_ATTR_ID,
XML_LRM_ATTR_OP_DIGEST,
XML_ATTR_TE_TARGET_RC,
XML_ATTR_LRM_PROBE,
XML_RSC_ATTR_START,
XML_RSC_ATTR_NOTIFY,
XML_RSC_ATTR_UNIQUE,
XML_RSC_ATTR_MANAGED,
XML_ATTR_CRM_VERSION,
XML_RSC_ATTR_PRIORITY,
XML_RSC_ATTR_MULTIPLE,
XML_RSC_ATTR_STICKINESS,
XML_RSC_ATTR_FAIL_STICKINESS,
XML_RSC_ATTR_TARGET_ROLE,
/* ignore clone fields */
XML_RSC_ATTR_INCARNATION,
XML_RSC_ATTR_INCARNATION_MAX,
XML_RSC_ATTR_INCARNATION_NODEMAX,
XML_RSC_ATTR_MASTER_MAX,
XML_RSC_ATTR_MASTER_NODEMAX,
/* ignore master fields */
"crm_role",
/* ignore notify fields */
"notify_stop_resource",
"notify_stop_uname",
"notify_start_resource",
"notify_start_uname",
"notify_active_resource",
"notify_active_uname",
"notify_inactive_resource",
"notify_inactive_uname",
"notify_promote_resource",
"notify_promote_uname",
"notify_demote_resource",
"notify_demote_uname",
"notify_master_resource",
"notify_master_uname",
"notify_slave_resource",
"notify_slave_uname",
};
int lpc = 0;
if(param_set == NULL) {
return;
}
for(lpc = 0; lpc < DIMOF(attr_filter); lpc++) {
xml_remove_prop(param_set, attr_filter[lpc]);
}
}
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_CHECK(active_stats != NULL, ;);
#ifndef CRM_USE_MALLOC
if(active_stats->numalloc > active_stats->numfree) {
crm_warn("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;
}
void
crm_abort(const char *file, const char *function, int line,
const char *assert_condition, gboolean do_fork)
{
int pid = 0;
do_crm_log(LOG_ERR, file, function,
"Triggered %sfatal assert at %s:%d : %s",
do_fork?"non-":"", file, line, assert_condition);
if(do_fork) {
pid=fork();
}
switch(pid) {
case -1:
crm_err("Cannot fork!");
return;
default: /* Parent */
crm_debug("Child %d forked to record assert failure", pid);
return;
case 0: /* Child */
abort();
break;
}
}
char *
generate_series_filename(
const char *directory, const char *series, int sequence, gboolean bzip)
{
int len = 40;
char *filename = NULL;
const char *ext = "raw";
CRM_CHECK(directory != NULL, return NULL);
CRM_CHECK(series != NULL, return NULL);
len += strlen(directory);
len += strlen(series);
crm_malloc0(filename, sizeof(char)*len);
CRM_CHECK(filename != NULL, return NULL);
if(bzip) {
ext = "bz2";
}
sprintf(filename, "%s/%s-%d.%s", directory, series, sequence, ext);
return filename;
}
int
get_last_sequence(const char *directory, const char *series)
{
FILE *file_strm = NULL;
int start = 0, length = 0, read_len = 0;
char *series_file = NULL;
char *buffer = NULL;
int seq = 0;
int len = 36;
CRM_CHECK(directory != NULL, return 0);
CRM_CHECK(series != NULL, return 0);
len += strlen(directory);
len += strlen(series);
crm_malloc0(series_file, sizeof(char)*len);
CRM_CHECK(series_file != NULL, return 0);
sprintf(series_file, "%s/%s.last", directory, series);
file_strm = fopen(series_file, "r");
if(file_strm == NULL) {
crm_debug("%s does not exist", series_file);
crm_free(series_file);
return 0;
}
/* see how big the file is */
start = ftell(file_strm);
fseek(file_strm, 0L, SEEK_END);
length = ftell(file_strm);
fseek(file_strm, 0L, start);
CRM_ASSERT(start == ftell(file_strm));
crm_debug_3("Reading %d bytes from file", length);
crm_malloc0(buffer, sizeof(char) * (length+1));
read_len = fread(buffer, sizeof(char), length, file_strm);
if(read_len != length) {
crm_err("Calculated and read bytes differ: %d vs. %d",
length, read_len);
crm_free(buffer);
buffer = NULL;
} else if(length <= 0) {
crm_info("%s was not valid", series_file);
crm_free(buffer);
buffer = NULL;
}
crm_free(series_file);
seq = crm_parse_int(buffer, "0");
crm_free(buffer);
fclose(file_strm);
return seq;
}
void
write_last_sequence(
const char *directory, const char *series, int sequence, int max)
{
int rc = 0;
int len = 36;
char *buffer = NULL;
FILE *file_strm = NULL;
char *series_file = NULL;
CRM_CHECK(directory != NULL, return);
CRM_CHECK(series != NULL, return);
if(max == 0) {
return;
}
while(max > 0 && sequence > max) {
sequence -= max;
}
buffer = crm_itoa(sequence);
len += strlen(directory);
len += strlen(series);
crm_malloc0(series_file, sizeof(char)*len);
CRM_CHECK(series_file != NULL, return);
sprintf(series_file, "%s/%s.last", directory, series);
file_strm = fopen(series_file, "w");
if(file_strm == NULL) {
crm_err("%s does not exist", series_file);
crm_free(series_file);
return;
}
rc = fprintf(file_strm, "%s", buffer);
if(rc < 0) {
cl_perror("Cannot write output to %s", series_file);
}
fflush(file_strm);
fclose(file_strm);
crm_free(series_file);
crm_free(buffer);
}
void
crm_make_daemon(const char *name, gboolean daemonize, const char *pidfile)
{
long pid;
const char *devnull = "/dev/null";
if(daemonize == FALSE) {
return;
}
pid = fork();
if (pid < 0) {
fprintf(stderr, "%s: could not start daemon\n", name);
cl_perror("fork");
exit(LSB_EXIT_GENERIC);
} else if (pid > 0) {
exit(LSB_EXIT_OK);
}
if (cl_lock_pidfile(pidfile) < 0 ) {
pid = cl_read_pidfile_no_checking(pidfile);
crm_warn("%s: already running [pid %ld] (%s).\n",
name, pid, pidfile);
exit(LSB_EXIT_OK);
}
umask(022);
close(FD_STDIN);
(void)open(devnull, O_RDONLY); /* Stdin: fd 0 */
close(FD_STDOUT);
(void)open(devnull, O_WRONLY); /* Stdout: fd 1 */
close(FD_STDERR);
(void)open(devnull, O_WRONLY); /* Stderr: fd 2 */
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Jan 25, 11:32 AM (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1320472
Default Alt Text
(71 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment