Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/tools/attrd.c b/tools/attrd.c
index 6d5107ee7b..d6736cad00 100644
--- a/tools/attrd.c
+++ b/tools/attrd.c
@@ -1,626 +1,628 @@
/* $Id: attrd.c,v 1.7 2006/05/16 14:46: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
*/
#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 <attrd.h>
#define OPTARGS "hV"
GMainLoop* mainloop = NULL;
const char *attrd_uname = NULL;
char *attrd_uuid = NULL;
ll_cluster_t *attrd_cluster_conn;
gboolean need_shutdown = FALSE;
GHashTable *attr_hash = NULL;
cib_t *cib_conn = NULL;
typedef struct attr_hash_entry_s
{
char *id;
char *set;
char *section;
char *value;
char *last_value;
int timeout;
char *dampen;
guint timer_id;
} attr_hash_entry_t;
static void
free_hash_entry(gpointer data)
{
attr_hash_entry_t *entry = data;
if (entry == NULL) {
return;
}
crm_free(entry->id);
crm_free(entry->set);
crm_free(entry->dampen);
crm_free(entry->section);
if(entry->value != entry->last_value) {
crm_free(entry->value);
crm_free(entry->last_value);
} else {
crm_free(entry->value);
}
crm_free(entry);
}
void attrd_ha_callback(HA_Message * msg, void* private_data);
void attrd_local_callback(HA_Message * msg);
gboolean attrd_timer_callback(void *user_data);
static gboolean
attrd_shutdown(int nsig, gpointer unused)
{
need_shutdown = TRUE;
crm_info("Exiting");
if (mainloop != NULL && g_main_is_running(mainloop)) {
g_main_quit(mainloop);
} else {
exit(0);
}
return FALSE;
}
static 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);
}
typedef struct attrd_client_s
{
char *id;
char *name;
IPC_Channel *channel;
GCHSource *source;
} attrd_client_t;
static void
stop_attrd_timer(attr_hash_entry_t *hash_entry)
{
if(hash_entry != NULL && hash_entry->timer_id != 0) {
crm_debug_2("Stopping %s timer", hash_entry->id);
Gmain_timeout_remove(hash_entry->timer_id);
hash_entry->timer_id = 0;
}
}
static gboolean
attrd_ipc_callback(IPC_Channel *client, gpointer user_data)
{
int lpc = 0;
HA_Message *msg = NULL;
attrd_client_t *curr_client = (attrd_client_t*)user_data;
gboolean stay_connected = TRUE;
crm_debug_2("Invoked: %s", curr_client->id);
while(IPC_ISRCONN(client)) {
if(client->ops->is_message_pending(client) == 0) {
break;
}
msg = msgfromIPC_noauth(client);
if (msg == NULL) {
crm_debug("%s: no message this time", curr_client->id);
continue;
}
lpc++;
crm_debug_2("Processing msg from %s", curr_client->id);
crm_log_message_adv(LOG_DEBUG_3, __PRETTY_FUNCTION__, msg);
attrd_local_callback(msg);
crm_msg_del(msg);
msg = NULL;
if(client->ch_status != IPC_CONNECT) {
break;
}
}
crm_debug_2("Processed %d messages", lpc);
if (client->ch_status != IPC_CONNECT) {
stay_connected = FALSE;
}
return stay_connected;
}
static void
attrd_connection_destroy(gpointer user_data)
{
attrd_client_t *client = user_data;
/* cib_process_disconnect */
if(client == NULL) {
return;
}
if(client->source != NULL) {
crm_debug_4("Deleting %s (%p) from mainloop",
client->name, client->source);
G_main_del_IPC_Channel(client->source);
client->source = NULL;
}
crm_debug_3("Destroying %s (%p)", client->name, client);
crm_free(client->name);
crm_free(client->id);
crm_free(client);
crm_debug_4("Freed the cib client");
return;
}
static gboolean
attrd_connect(IPC_Channel *channel, gpointer user_data)
{
attrd_client_t *new_client = NULL;
crm_debug_3("Connecting channel");
if(channel == NULL) {
crm_err("Channel was NULL");
return FALSE;
} else if(channel->ch_status != IPC_CONNECT) {
crm_err("Channel was disconnected");
return FALSE;
} else if(need_shutdown) {
crm_info("Ignoring connection request during shutdown");
return FALSE;
}
crm_malloc0(new_client, sizeof(attrd_client_t));
new_client->channel = channel;
crm_debug_3("Created channel %p for channel %s",
new_client, new_client->id);
/* channel->ops->set_recv_qlen(channel, 100); */
/* channel->ops->set_send_qlen(channel, 400); */
new_client->source = G_main_add_IPC_Channel(
G_PRIORITY_DEFAULT, channel, FALSE, attrd_ipc_callback,
new_client, attrd_connection_destroy);
crm_debug_3("Client %s connected", new_client->id);
return TRUE;
}
static gboolean
attrd_ha_dispatch(IPC_Channel *channel, gpointer user_data)
{
gboolean stay_connected = TRUE;
crm_debug_2("Invoked");
while(attrd_cluster_conn != NULL && IPC_ISRCONN(channel)) {
if(attrd_cluster_conn->llc_ops->msgready(attrd_cluster_conn) == 0) {
crm_debug_2("no message ready yet");
break;
}
/* invoke the callbacks but dont block */
attrd_cluster_conn->llc_ops->rcvmsg(attrd_cluster_conn, 0);
}
if (attrd_cluster_conn == NULL || channel->ch_status != IPC_CONNECT) {
if(need_shutdown == FALSE) {
crm_crit("Lost connection to heartbeat service.");
} else {
crm_info("Lost connection to heartbeat service.");
}
stay_connected = FALSE;
}
return stay_connected;
}
static void
attrd_ha_connection_destroy(gpointer user_data)
{
crm_debug_3("Invoked");
if(need_shutdown) {
/* we signed out, so this is expected */
crm_info("Heartbeat disconnection complete");
return;
}
crm_crit("Lost connection to heartbeat service!");
}
static gboolean
register_with_ha(void)
{
const char *const_attrd_uuid = NULL;
if(attrd_cluster_conn == NULL) {
attrd_cluster_conn = ll_cluster_new("heartbeat");
}
if(attrd_cluster_conn == NULL) {
crm_err("Cannot create heartbeat object");
return FALSE;
}
crm_debug("Signing in with Heartbeat");
if (attrd_cluster_conn->llc_ops->signon(attrd_cluster_conn, T_ATTRD)!= HA_OK) {
crm_err("Cannot sign on with heartbeat: %s",
attrd_cluster_conn->llc_ops->errmsg(attrd_cluster_conn));
return FALSE;
}
crm_debug_3("Be informed of CRM messages");
if (HA_OK != attrd_cluster_conn->llc_ops->set_msg_callback(
attrd_cluster_conn, T_ATTRD, attrd_ha_callback,
attrd_cluster_conn)) {
crm_err("Cannot set msg callback: %s",
attrd_cluster_conn->llc_ops->errmsg(attrd_cluster_conn));
return FALSE;
}
crm_debug_3("Adding channel to mainloop");
G_main_add_IPC_Channel(
G_PRIORITY_HIGH, attrd_cluster_conn->llc_ops->ipcchan(
attrd_cluster_conn),
FALSE, attrd_ha_dispatch, attrd_cluster_conn /* userdata */,
attrd_ha_connection_destroy);
crm_debug_3("Finding our node name");
attrd_uname = attrd_cluster_conn->llc_ops->get_mynodeid(
attrd_cluster_conn);
if (attrd_uname == NULL) {
crm_err("get_mynodeid() failed");
return FALSE;
}
crm_info("Hostname: %s", attrd_uname);
crm_debug_3("Finding our node uuid");
const_attrd_uuid = get_uuid(attrd_cluster_conn, attrd_uname);
if(const_attrd_uuid == NULL) {
crm_err("get_uuid_by_name() failed");
return FALSE;
}
/* copy it so that unget_uuid() doesn't trash the value on us */
attrd_uuid = crm_strdup(const_attrd_uuid);
crm_info("UUID: %s", attrd_uuid);
return TRUE;
}
int
main(int argc, char ** argv)
{
int flag;
int argerr = 0;
gboolean was_err = FALSE;
char *channel_name = crm_strdup(attrd_channel);
crm_log_init(T_ATTRD);
G_main_add_SignalHandler(
G_PRIORITY_HIGH, SIGTERM, attrd_shutdown, NULL, NULL);
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(T_ATTRD, LSB_EXIT_OK);
break;
default:
++argerr;
break;
}
}
if (optind > argc) {
++argerr;
}
if (argerr) {
usage(T_ATTRD, LSB_EXIT_GENERIC);
}
if(register_with_ha() == FALSE) {
crm_err("HA Signon failed");
was_err = TRUE;
}
if(was_err == FALSE) {
int lpc = 0;
int max_retry = 20;
enum cib_errors rc = cib_not_connected;
cib_conn = cib_new();
for(lpc = 0; lpc < max_retry && rc != cib_ok; lpc++) {
crm_debug("CIB signon attempt %d", lpc);
rc = cib_conn->cmds->signon(
cib_conn, T_ATTRD, cib_command);
sleep(5);
}
if(rc != cib_ok) {
crm_err("Signon to CIB failed: %s",
cib_error2string(rc));
was_err = TRUE;
}
}
if(was_err == FALSE) {
int rc = init_server_ipc_comms(
- crm_strdup(attrd_channel), attrd_connect,
+ channel_name, attrd_connect,
default_ipc_connection_destroy);
if(rc != 0) {
crm_err("Could not start IPC server");
was_err = TRUE;
}
}
if(was_err) {
crm_err("Aborting startup");
return 100;
}
attr_hash = g_hash_table_new_full(
g_str_hash, g_str_equal, NULL, free_hash_entry);
crm_info("Starting mainloop...");
mainloop = g_main_new(FALSE);
g_main_run(mainloop);
crm_info("Exiting...");
attrd_cluster_conn->llc_ops->signoff(attrd_cluster_conn, TRUE);
attrd_cluster_conn->llc_ops->delete(attrd_cluster_conn);
cib_conn->cmds->signoff(cib_conn);
cib_delete(cib_conn);
g_hash_table_destroy(attr_hash);
crm_free(channel_name);
crm_free(attrd_uuid);
empty_uuid_cache();
-
+
+#ifdef HA_MALLOC_TRACK
cl_malloc_dump_allocated(LOG_ERR, FALSE);
+#endif
return 0;
}
static void
attrd_cib_callback(const HA_Message *msg, int call_id, int rc,
crm_data_t *output, void *user_data)
{
char *attr = user_data;
if(rc == cib_NOTEXISTS) {
rc = cib_ok;
}
if(rc < cib_ok) {
crm_err("Update %d for %s failed: %s", call_id, attr, cib_error2string(rc));
} else {
crm_debug("Update %d for %s passed", call_id, attr);
}
crm_free(attr);
}
static attr_hash_entry_t *
find_hash_entry(HA_Message * msg)
{
const char *value = NULL;
const char *attr = ha_msg_value(msg, F_ATTRD_ATTRIBUTE);
attr_hash_entry_t *hash_entry = g_hash_table_lookup(attr_hash, attr);
if(hash_entry == NULL) {
/* create one and add it */
crm_info("Creating hash entry for %s", attr);
crm_malloc0(hash_entry, sizeof(attr_hash_entry_t));
hash_entry->id = crm_strdup(attr);
g_hash_table_insert(attr_hash, hash_entry->id, hash_entry);
hash_entry = g_hash_table_lookup(attr_hash, attr);
CRM_CHECK(hash_entry != NULL, return NULL);
}
value = ha_msg_value(msg, F_ATTRD_SET);
if(value != NULL) {
crm_free(hash_entry->set);
hash_entry->set = crm_strdup(value);
crm_debug("\t%s->set: %s", attr, value);
}
value = ha_msg_value(msg, F_ATTRD_SECTION);
if(value == NULL) {
value = XML_CIB_TAG_STATUS;
}
crm_free(hash_entry->section);
hash_entry->section = crm_strdup(value);
crm_debug("\t%s->section: %s", attr, value);
value = ha_msg_value(msg, F_ATTRD_DAMPEN);
if(value != NULL) {
crm_free(hash_entry->dampen);
hash_entry->dampen = crm_strdup(value);
hash_entry->timeout = crm_get_msec(value);
crm_debug("\t%s->timeout: %s", attr, value);
}
return hash_entry;
}
void
attrd_ha_callback(HA_Message * msg, void* private_data)
{
int rc = cib_ok;
attr_hash_entry_t *hash_entry = NULL;
const char *from = ha_msg_value(msg, F_ORIG);
const char *op = ha_msg_value(msg, F_ATTRD_TASK);
const char *attr = ha_msg_value(msg, F_ATTRD_ATTRIBUTE);
crm_info("%s message from %s", op, from);
hash_entry = find_hash_entry(msg);
stop_attrd_timer(hash_entry);
if(hash_entry->value == NULL) {
/* delete the attr */
rc = delete_attr(cib_conn, cib_none, hash_entry->section, attrd_uuid,
hash_entry->set, NULL, attr, NULL);
crm_info("Sent delete %d: %s %s %s",
rc, attr, hash_entry->set, hash_entry->section);
} else {
/* send update */
rc = update_attr(cib_conn, cib_none, hash_entry->section,
attrd_uuid, hash_entry->set, NULL,
hash_entry->id, hash_entry->value);
crm_info("Sent update %d: %s=%s", rc, hash_entry->id,hash_entry->value);
}
add_cib_op_callback(rc, FALSE, crm_strdup(attr), attrd_cib_callback);
return;
}
static void
update_for_hash_entry(gpointer key, gpointer value, gpointer user_data)
{
attrd_timer_callback(value);
}
void
attrd_local_callback(HA_Message * msg)
{
attr_hash_entry_t *hash_entry = NULL;
const char *from = ha_msg_value(msg, F_ORIG);
const char *op = ha_msg_value(msg, F_ATTRD_TASK);
const char *attr = ha_msg_value(msg, F_ATTRD_ATTRIBUTE);
const char *value = ha_msg_value(msg, F_ATTRD_VALUE);
if(safe_str_eq(op, "refresh")) {
crm_info("Sending full refresh");
g_hash_table_foreach(attr_hash, update_for_hash_entry, NULL);
return;
}
crm_debug("%s message from %s: %s=%s", op, from, attr, value);
hash_entry = find_hash_entry(msg);
crm_free(hash_entry->last_value);
hash_entry->last_value = hash_entry->value;
value = ha_msg_value(msg, F_ATTRD_VALUE);
if(value != NULL) {
hash_entry->value = crm_strdup(value);
} else {
hash_entry->value = NULL;
}
if(safe_str_eq(hash_entry->value, hash_entry->last_value)) {
crm_debug_2("Ignoring non-change");
return;
}
stop_attrd_timer(hash_entry);
if(hash_entry->timeout > 0) {
hash_entry->timer_id = Gmain_timeout_add(
hash_entry->timeout, attrd_timer_callback, hash_entry);
} else {
attrd_timer_callback(hash_entry);
}
return;
}
gboolean
attrd_timer_callback(void *user_data)
{
HA_Message *msg = NULL;
attr_hash_entry_t *hash_entry = user_data;
stop_attrd_timer(hash_entry);
/* send HA message to everyone */
crm_info("Sending flush op to all hosts for: %s", hash_entry->id);
msg = ha_msg_new(4);
ha_msg_add(msg, F_TYPE, T_ATTRD);
ha_msg_add(msg, F_ORIG, attrd_uname);
ha_msg_add(msg, F_ATTRD_TASK, "flush");
ha_msg_add(msg, F_ATTRD_ATTRIBUTE, hash_entry->id);
ha_msg_add(msg, F_ATTRD_SET, hash_entry->set);
ha_msg_add(msg, F_ATTRD_SECTION, hash_entry->section);
ha_msg_add(msg, F_ATTRD_DAMPEN, hash_entry->dampen);
send_ha_message(attrd_cluster_conn, msg, NULL, FALSE);
crm_msg_del(msg);
return TRUE;
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Nov 23, 3:02 AM (44 m, 22 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1018081
Default Alt Text
(15 KB)

Event Timeline