diff --git a/crm/cib/cib.c b/crm/cib/cib.c index d1e3cd8ec2..bb4bda3e26 100644 --- a/crm/cib/cib.c +++ b/crm/cib/cib.c @@ -1,335 +1,337 @@ -/* $Id: cib.c,v 1.30 2004/04/13 13:26:44 andrew Exp $ */ +/* $Id: cib.c,v 1.31 2004/04/15 00:34:06 msoffen Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * 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 - #include #include #include #include #include #include #include +#include + #include #include #include #include #include #include #include #include #include gboolean startCib(const char *filename) { xmlNodePtr cib = readCibXmlFile(filename); if (initializeCib(cib)) { cl_log(LOG_INFO, "CIB Initialization completed successfully"); } else { // free_xml(cib); cl_log(LOG_WARNING, "CIB Initialization failed, " "starting with an empty default."); activateCibXml(createEmptyCib(), filename); } return TRUE; } xmlNodePtr get_cib_copy() { return copy_xml_node_recursive(get_the_CIB()); } /* * The caller should never free the return value */ xmlNodePtr get_object_root(const char *object_type, xmlNodePtr the_root) { const char *node_stack[2]; xmlNodePtr tmp_node = NULL; FNIN(); node_stack[0] = XML_CIB_TAG_CONFIGURATION; node_stack[1] = object_type; if(object_type == NULL || strlen(object_type) == 0) { FNRET(the_root); /* get the whole cib */ } else if(strcmp(object_type, XML_CIB_TAG_STATUS) == 0) { node_stack[0] = XML_CIB_TAG_STATUS; node_stack[1] = NULL; /* these live in a different place */ } tmp_node = find_xml_node_nested(the_root, node_stack, 2); if (tmp_node == NULL) { cl_log(LOG_ERR, "[cib] Section cib[%s[%s]] not present", node_stack[0], node_stack[1]); } FNRET(tmp_node); } FILE *msg_cib_strm = NULL; xmlNodePtr process_cib_message(xmlNodePtr message, gboolean auto_reply) { + xmlNodePtr data; + xmlNodePtr reply; enum cib_result result = CIBRES_OK; xmlNodePtr fragment = find_xml_node(message, XML_TAG_FRAGMENT); xmlNodePtr options = find_xml_node(message, XML_TAG_OPTIONS); const char *op = get_xml_attr (message, XML_TAG_OPTIONS, XML_ATTR_OP, TRUE); #ifdef MSG_LOG if(msg_cib_strm == NULL) { msg_cib_strm = fopen("/tmp/cib.log", "w"); } fprintf(msg_cib_strm, "[Input ]\t%s\n", dump_xml_node(message, FALSE)); fflush(msg_cib_strm); #endif - xmlNodePtr data = cib_process_request(op, options, fragment, &result); + data = cib_process_request(op, options, fragment, &result); CRM_DEBUG2("[cib] operation returned result %d", result); if(auto_reply) { - - xmlNodePtr reply = create_reply(message, data); + reply = create_reply(message, data); free_xml(data); #ifdef MSG_LOG fprintf(msg_cib_strm, "[Reply ]\t%s\n", dump_xml_node(reply, FALSE)); fflush(msg_cib_strm); #endif set_xml_attr(reply, XML_TAG_OPTIONS, XML_ATTR_RESULT, "ok", TRUE); // put real result in here return reply; } #ifdef MSG_LOG fprintf(msg_cib_strm, "[Output]\t%s\n", dump_xml_node(data, FALSE)); fflush(msg_cib_strm); #endif return data; } xmlNodePtr process_cib_request(const char *op, const xmlNodePtr options, const xmlNodePtr fragment) { enum cib_result result = CIBRES_OK; return cib_process_request(op, options, fragment, &result); } xmlNodePtr create_cib_fragment(xmlNodePtr update, const char *section) { gboolean whole_cib = FALSE; xmlNodePtr fragment = create_xml_node(NULL, XML_TAG_FRAGMENT); xmlNodePtr cib = NULL; + xmlNodePtr object_root = NULL; char *auto_section = pluralSection(update->name); if(update == NULL) { cl_log(LOG_ERR, "No update to create a fragment for"); cl_free(auto_section); return NULL; } else if(section == NULL) { section = auto_section; } else if(strcmp(auto_section, section) != 0) { cl_log(LOG_ERR, "Values for update (tag=%s) and section (%s)" " were not consistent", update->name, section); cl_free(auto_section); return NULL; } if(strcmp(section, "all")==0 && strcmp(update->name, XML_TAG_CIB)==0) { whole_cib = TRUE; } set_xml_property_copy(fragment, XML_ATTR_SECTION, section); if(whole_cib == FALSE) { cib = createEmptyCib(); - xmlNodePtr object_root = get_object_root(section, cib); + object_root = get_object_root(section, cib); add_node_copy(object_root, update); } else { cib = copy_xml_node_recursive(update); } xmlAddChild(fragment, cib); CRM_DEBUG("Fragment created"); xml_message_debug(fragment, "created fragment"); cl_free(auto_section); return fragment; } char * pluralSection(const char *a_section) { char *a_section_parent = NULL; if (a_section == NULL) { a_section_parent = cl_strdup("all"); } else if(strcmp(a_section, XML_TAG_CIB) == 0) { a_section_parent = cl_strdup("all"); } else if(strcmp(a_section, XML_CIB_TAG_NODE) == 0) { a_section_parent = cl_strdup(XML_CIB_TAG_NODES); } else if(strcmp(a_section, XML_CIB_TAG_STATE) == 0) { a_section_parent = cl_strdup(XML_CIB_TAG_STATUS); } else if(strcmp(a_section, XML_CIB_TAG_CONSTRAINT) == 0) { a_section_parent = cl_strdup(XML_CIB_TAG_CONSTRAINTS); } else if(strcmp(a_section, XML_CIB_TAG_RESOURCE) == 0) { a_section_parent = cl_strdup(XML_CIB_TAG_RESOURCES); } else { cl_log(LOG_ERR, "Unknown section %s", a_section); a_section_parent = cl_strdup("all"); } CRM_DEBUG2("Plural is %s", a_section_parent); return a_section_parent; } const char * cib_error2string(enum cib_result return_code) { const char *error_msg = NULL; switch(return_code) { case CIBRES_MISSING_ID: error_msg = "The id field is missing"; break; case CIBRES_MISSING_TYPE: error_msg = "The type field is missing"; break; case CIBRES_MISSING_FIELD: error_msg = "A required field is missing"; break; case CIBRES_OBJTYPE_MISMATCH: error_msg = "CIBRES_OBJTYPE_MISMATCH"; break; case CIBRES_FAILED_EXISTS: error_msg = "The object already exists"; break; case CIBRES_FAILED_NOTEXISTS: error_msg = "The object does not exist"; break; case CIBRES_CORRUPT: error_msg = "The CIB is corrupt"; break; case CIBRES_FAILED_NOOBJECT: error_msg = "The update was empty"; break; case CIBRES_FAILED_NOPARENT: error_msg = "The parent object does not exist"; break; case CIBRES_FAILED_NODECOPY: error_msg = "Failed while copying update"; break; case CIBRES_OTHER: error_msg = "CIBRES_OTHER"; break; case CIBRES_OK: error_msg = "ok"; break; case CIBRES_FAILED: error_msg = "Failed"; break; case CIBRES_FAILED_STALE: error_msg = "Discarded old update"; break; case CIBRES_FAILED_ACTIVATION: error_msg = "Activation Failed"; break; case CIBRES_FAILED_NOSECTION: error_msg = "Required section was missing"; break; case CIBRES_FAILED_NOTSUPPORTED: error_msg = "Supplied information is not supported"; break; } if(error_msg == NULL) { cl_log(LOG_ERR, "Unknown CIB Error %d", return_code); error_msg = ""; } return error_msg; } const char * cib_op2string(enum cib_op operation) { const char *operation_msg = NULL; switch(operation) { case 0: operation_msg = "none"; break; case 1: operation_msg = "add"; break; case 2: operation_msg = "modify"; break; case 3: operation_msg = "delete"; break; case CIB_OP_MAX: operation_msg = "invalid operation"; break; } if(operation_msg == NULL) { cl_log(LOG_ERR, "Unknown CIB operation %d", operation); operation_msg = ""; } return operation_msg; } diff --git a/crm/cib/cibio.c b/crm/cib/cibio.c index dd03b5f87e..367a9a9eca 100644 --- a/crm/cib/cibio.c +++ b/crm/cib/cibio.c @@ -1,431 +1,432 @@ -/* $Id: cibio.c,v 1.19 2004/04/13 13:26:44 andrew Exp $ */ +/* $Id: cibio.c,v 1.20 2004/04/15 00:34:06 msoffen Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * 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 - #include #include #include #include #include #include #include #include #include +#include + #include #include #include #include // for getNow() #include #include #include 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; xmlNodePtr the_cib = NULL; xmlNodePtr node_search = NULL; xmlNodePtr resource_search = NULL; xmlNodePtr constraint_search = NULL; xmlNodePtr status_search = NULL; /* * It is the callers responsibility to free both the new CIB (output) * and the new CIB (input) */ xmlNodePtr createEmptyCib(void) { xmlNodePtr cib_root = NULL, config = NULL, status = NULL; cib_root = create_xml_node(NULL, XML_TAG_CIB); config = create_xml_node(cib_root, XML_CIB_TAG_CONFIGURATION); status = create_xml_node(cib_root, XML_CIB_TAG_STATUS); set_node_tstamp(cib_root); set_node_tstamp(config); set_node_tstamp(status); set_xml_property_copy(cib_root, "version", "1"); set_xml_property_copy(cib_root, "generated", "true"); create_xml_node(config, XML_CIB_TAG_NODES); create_xml_node(config, XML_CIB_TAG_RESOURCES); create_xml_node(config, XML_CIB_TAG_CONSTRAINTS); if (verifyCibXml(cib_root)) { FNRET(cib_root); } cl_log(LOG_CRIT, "The generated CIB did not pass integrity testing!!" " All hope is lost."); FNRET(NULL); } gboolean verifyCibXml(xmlNodePtr cib) { gboolean is_valid = TRUE; xmlNodePtr tmp_node = NULL; FNIN(); if (cib == NULL) { cl_log(LOG_ERR, "XML Buffer was empty."); FNRET(FALSE); } tmp_node = get_object_root(XML_CIB_TAG_NODES, cib); if (tmp_node == NULL) is_valid = FALSE; tmp_node = get_object_root(XML_CIB_TAG_RESOURCES, cib); if (tmp_node == NULL) is_valid = FALSE; tmp_node = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); if (tmp_node == NULL) is_valid = FALSE; tmp_node = get_object_root(XML_CIB_TAG_STATUS, cib); if (tmp_node == NULL) is_valid = FALSE; // more integrity tests FNRET(is_valid); } /* * It is the callers responsibility to free the output of this function */ xmlNodePtr readCibXml(char *buffer) { xmlNodePtr root = string2xml(buffer); if (verifyCibXml(root) == FALSE) { free_xml(root); FNRET(createEmptyCib()); } FNRET(root); } /* * It is the callers responsibility to free the output of this function */ xmlNodePtr readCibXmlFile(const char *filename) { int s_res = -1; struct stat buf; xmlNodePtr root = NULL; FNIN(); if(filename != NULL) { s_res = stat(filename, &buf); } if (s_res == 0) { FILE *cib_file = fopen(filename, "r"); root = file2xml(cib_file); set_xml_property_copy(root, "generated", "false"); fclose(cib_file); } else { cl_log(LOG_WARNING, "Stat of (%s) failed, file does not exist.", CIB_FILENAME); } if (verifyCibXml(root) == FALSE) { free_xml(root); // FNRET(createEmptyCib()); root = NULL; } FNRET(root); } /* * The caller should never free the return value */ xmlNodePtr get_the_CIB(void) { FNIN(); FNRET(the_cib); } gboolean uninitializeCib(void) { xmlNodePtr tmp_cib = the_cib; FNIN(); if(tmp_cib == NULL) { cl_log(LOG_ERR, "The CIB has already been deallocated."); FNRET(FALSE); } initialized = FALSE; the_cib = NULL; node_search = NULL; resource_search = NULL; constraint_search = NULL; status_search = NULL; cl_log(LOG_WARNING, "Deallocating the CIB."); free_xml(tmp_cib); cl_log(LOG_WARNING, "The CIB has been deallocated."); FNRET(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(xmlNodePtr new_cib) { 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; CRM_DEBUG("CIB initialized"); FNRET(TRUE); } else { cl_log(LOG_ERR, "CIB Verification failed"); } FNRET(FALSE); } 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); FNIN(); cl_log(LOG_INFO, "Stat of %s (code: %d).", newname, s_res); 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"); FNRET(-1); } } } s_res = stat(oldname, &tmp); cl_log(LOG_INFO, "Stat of %s (code: %d).", oldname, s_res); if (s_res >= 0) { res = link(oldname, newname); if (res < 0) { perror("Could not create backup of current Cib"); FNRET(-2); } res = unlink(oldname); if (res < 0) { perror("Could not unlink the current Cib"); FNRET(-3); } } FNRET(0); } int activateCibBuffer(char *buffer, const char *filename) { int result = -1; xmlNodePtr local_cib = NULL; FNIN(); local_cib = readCibXml(buffer); result = activateCibXml(local_cib, filename); FNRET(result); } /* * This method will free the old CIB pointer on success and the new one * on failure. */ int activateCibXml(xmlNodePtr new_cib, const char *filename) { int error_code = 0; xmlNodePtr saved_cib = get_the_CIB(); const char *filename_bak = CIB_BACKUP; // calculate + xmlDocPtr foo; FNIN(); if (initializeCib(new_cib) == TRUE) { int res = moveFile(filename, filename_bak, FALSE, NULL); if (res < 0) { cl_log(LOG_INFO, "Could not make backup of the current Cib " "(code: %d)... aborting update.", res); error_code = -1; } else { cl_log(LOG_INFO, "Writing CIB out to %s", CIB_FILENAME); if (new_cib->doc == NULL) { cl_log(LOG_INFO, "Writing of a node tree with a NULL " "document will fail, creating a new " "back link."); - xmlDocPtr foo = xmlNewDoc("1.0"); + foo = xmlNewDoc("1.0"); xmlDocSetRootElement(foo, new_cib); xmlSetTreeDoc(new_cib,foo); } /* save it. * set arg 3 to 0 to disable line breaks,1 to enable * res == num bytes saved */ res = xmlSaveFormatFile(filename, new_cib->doc, 1); /* for some reason, reading back after saving with * line-breaks doesnt go real well */ cl_log(LOG_INFO, "Saved %d bytes to the Cib as XML", res); if (res < 0) { // assume 0 is good if (moveFile(filename_bak, filename, FALSE, NULL) < -1) { cl_log(LOG_CRIT, "Could not restore the " "backup of the current Cib " "(code: %d)... panic!", res); error_code = -2; // should probably exit here } else if (initializeCib(saved_cib) == FALSE) { // oh we are so dead cl_log(LOG_CRIT, "Could not re-initialize " "with the old CIB. " "Everything is about to go " "pear shaped"); error_code = -3; } else { cl_log(LOG_CRIT, "Update of Cib failed " "(code: %d)... reverted to " "last known valid version", res); error_code = -4; } } } } else { cl_log(LOG_INFO, "Ignoring invalid or NULL Cib"); error_code = -5; } // Make sure memory is cleaned up appropriately if (error_code != 0) { // CRM_DEBUG2("Freeing new CIB %p", new_cib); free_xml(new_cib); } else { // CRM_DEBUG2("Freeing saved CIB %p", saved_cib); free_xml(saved_cib); } FNRET(error_code); } diff --git a/crm/cib/cibmain.c b/crm/cib/cibmain.c index ed10594139..8b84a6df27 100644 --- a/crm/cib/cibmain.c +++ b/crm/cib/cibmain.c @@ -1,349 +1,356 @@ -/* $Id: cibmain.c,v 1.14 2004/03/26 14:14:25 andrew Exp $ */ +/* $Id: cibmain.c,v 1.15 2004/04/15 00:34:06 msoffen Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * 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 - #include #include #include #include #include #include #include #include #include +#include + #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* #define REALTIME_SUPPORT 0 */ #define PID_FILE WORKING_DIR"/cib.pid" #define DAEMON_LOG LOG_DIR"/cib.log" #define DAEMON_DEBUG LOG_DIR"/cib.debug" GMainLoop* mainloop = NULL; const char* crm_system_name = CRM_SYSTEM_CIB; void usage(const char* cmd, int exit_status); int init_start(void); void shutdown(int nsig); gboolean cib_msg_callback(IPC_Channel *client, gpointer user_data); #define OPTARGS "skrh" int main(int argc, char ** argv) { - cl_log_set_entity(crm_system_name); - cl_log_enable_stderr(TRUE); - cl_log_set_facility(LOG_USER); - int req_comms_restart = FALSE; int req_restart = FALSE; int req_status = FALSE; int req_stop = FALSE; int argerr = 0; int flag; + cl_log_set_entity(crm_system_name); + cl_log_enable_stderr(TRUE); + cl_log_set_facility(LOG_USER); + while ((flag = getopt(argc, argv, OPTARGS)) != EOF) { switch(flag) { case 's': /* Status */ req_status = TRUE; break; case 'k': /* Stop (kill) */ req_stop = TRUE; break; case 'r': /* Restart */ req_restart = TRUE; break; case 'c': /* Restart */ req_comms_restart = TRUE; 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 if (req_status){ FNRET(init_status(PID_FILE, crm_system_name)); } if (req_stop){ FNRET(init_stop(PID_FILE)); } if (req_restart) { init_stop(PID_FILE); } FNRET(init_start()); } int init_start(void) { long pid; + ll_cluster_t *hb_fd; + int facility; + IPC_Channel *crm_ch = NULL; +#ifdef REALTIME_SUPPORT + static int crm_realtime = 1; +#endif if ((pid = get_running_pid(PID_FILE, NULL)) > 0) { cl_log(LOG_CRIT, "already running: [pid %ld].", pid); exit(LSB_EXIT_OK); } cl_log(LOG_INFO, "Register PID"); register_pid(PID_FILE, FALSE, shutdown); xmlInitParser(); // only do this once cl_log_set_logfile(DAEMON_LOG); // if (crm_debug()) { cl_log_set_debugfile(DAEMON_DEBUG); // } - ll_cluster_t *hb_fd = ll_cluster_new("heartbeat"); + hb_fd = ll_cluster_new("heartbeat"); - int facility; cl_log(LOG_INFO, "Switching to Heartbeat logger"); if ((facility = hb_fd->llc_ops->get_logfacility(hb_fd))>0) { cl_log_set_facility(facility); } if(startCib(CIB_FILENAME) == FALSE){ cl_log(LOG_CRIT, "Cannot start CIB... terminating"); exit(1); } - IPC_Channel *crm_ch = init_client_ipc_comms(CRM_SYSTEM_CRMD, + crm_ch = init_client_ipc_comms(CRM_SYSTEM_CRMD, cib_msg_callback, NULL); if(crm_ch != NULL) { send_hello_message(crm_ch, "-", CRM_SYSTEM_CIB, "0", "1"); /* Create the mainloop and run it... */ mainloop = g_main_new(FALSE); cl_log(LOG_INFO, "Starting %s", crm_system_name); /* G_main_add_IPC_Channel(G_PRIORITY_LOW, */ /* crm_ch, */ /* FALSE, */ /* cib_msg_callback, */ /* crm_ch, */ /* default_ipc_input_destroy); */ #ifdef REALTIME_SUPPORT - static int crm_realtime = 1; if (crm_realtime == 1) { cl_enable_realtime(); } else if (crm_realtime == 0) { cl_disable_realtime(); } cl_make_realtime(SCHED_RR, 5, 64, 64); #endif g_main_run(mainloop); return_to_orig_privs(); } else { cl_log(LOG_ERR, "Connection to CRM not valid, exiting."); } if (unlink(PID_FILE) == 0) { cl_log(LOG_INFO, "[%s] stopped", crm_system_name); } FNRET(0); } gboolean cib_msg_callback(IPC_Channel *sender, void *user_data) { int lpc = 0; char *buffer = NULL; xmlDocPtr doc = NULL; IPC_Message *msg = NULL; gboolean all_is_well = TRUE; xmlNodePtr answer = NULL, root_xml_node = NULL; + const char *sys_to; + const char *type; + FNIN(); while(sender->ops->is_message_pending(sender)) { if (sender->ch_status == IPC_DISCONNECT) { /* The message which was pending for us is that * the IPC status is now IPC_DISCONNECT */ break; } if (sender->ops->recv(sender, &msg) != IPC_OK) { perror("Receive failure:"); FNRET(!all_is_well); } if (msg == NULL) { cl_log(LOG_ERR, "No message this time"); continue; } lpc++; /* the docs say only do this once, but in their code * they do it every time! */ // xmlInitParser(); buffer = (char*)msg->msg_body; cl_log(LOG_DEBUG, "Message %d [text=%s]", lpc, buffer); doc = xmlParseMemory(cl_strdup(buffer), strlen(buffer)); if(doc == NULL) { cl_log(LOG_INFO, "XML Buffer was not valid...\n Buffer: (%s)", buffer); } root_xml_node = xmlDocGetRootElement(doc); - const char *sys_to= xmlGetProp(root_xml_node, XML_ATTR_SYSTO); - const char *type = xmlGetProp(root_xml_node, XML_ATTR_MSGTYPE); + sys_to= xmlGetProp(root_xml_node, XML_ATTR_SYSTO); + type = xmlGetProp(root_xml_node, XML_ATTR_MSGTYPE); if (root_xml_node == NULL) { cl_log(LOG_ERR, "Root node was NULL!!"); } else if(sys_to == NULL) { cl_log(LOG_ERR, "Value of %s was NULL!!", XML_ATTR_SYSTO); } else if(type == NULL) { cl_log(LOG_ERR, "Value of %s was NULL!!", XML_ATTR_MSGTYPE); } else if(strcmp(type, XML_ATTR_REQUEST) != 0) { cl_log(LOG_INFO, "Message was a response not a request." " Discarding"); } else if (strcmp(sys_to, CRM_SYSTEM_CIB) == 0 || strcmp(sys_to, CRM_SYSTEM_DCIB) == 0) { answer = process_cib_message(root_xml_node, TRUE); if (send_xmlipc_message(sender, answer)==FALSE) cl_log(LOG_WARNING, "Cib answer could not be sent"); } else { cl_log(LOG_WARNING, "Received a message destined for %s by mistake", sys_to); } if(answer != NULL) free_xml(answer); msg->msg_done(msg); msg = NULL; } // clean up after a break if(msg != NULL) msg->msg_done(msg); if(root_xml_node != NULL) free_xml(root_xml_node); CRM_DEBUG2("Processed %d messages", lpc); if (sender->ch_status == IPC_DISCONNECT) { cl_log(LOG_ERR, "The server has left us: Shutting down...NOW"); exit(1); // shutdown properly later FNRET(!all_is_well); } FNRET(all_is_well); } 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); } void shutdown(int nsig) { static int shuttingdown = 0; CL_SIGNAL(nsig, shutdown); if (!shuttingdown) { shuttingdown = 1; } if (mainloop != NULL && g_main_is_running(mainloop)) { g_main_quit(mainloop); } else { exit(LSB_EXIT_OK); } } diff --git a/crm/cib/cibmessages.c b/crm/cib/cibmessages.c index 0257db685d..7b1133042f 100644 --- a/crm/cib/cibmessages.c +++ b/crm/cib/cibmessages.c @@ -1,459 +1,463 @@ -/* $Id: cibmessages.c,v 1.30 2004/04/13 13:26:44 andrew Exp $ */ +/* $Id: cibmessages.c,v 1.31 2004/04/15 00:34:06 msoffen Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * 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 - #include #include #include #include #include #include #include +#include + #include #include #include #include #include #include #include #include #include #include #include #include enum cib_result updateList(xmlNodePtr local_cib, xmlNodePtr update_command, xmlNodePtr failed, int operation, const char *section); xmlNodePtr createCibFragmentAnswer(const char *section, xmlNodePtr failed); gboolean replace_section(const char *section, xmlNodePtr tmpCib, xmlNodePtr command); gboolean check_generation(xmlNodePtr newCib, xmlNodePtr oldCib); gboolean update_results(xmlNodePtr failed, xmlNodePtr target, int operation, int return_code); xmlNodePtr cib_process_request(const char *op, const xmlNodePtr options, const xmlNodePtr fragment, enum cib_result *result) { const char *verbose = NULL; const char *section = NULL; const char *output_section = NULL; xmlNodePtr failed = NULL; xmlNodePtr cib_answer = NULL; gboolean update_the_cib = FALSE; int cib_update_op = CIB_OP_NONE; + xmlNodePtr tmpCib; + char *new_value = NULL; + char *old_value = NULL; + int int_value = -1; FNIN(); *result = CIBRES_OK; verbose = xmlGetProp(options, XML_ATTR_VERBOSE); section = xmlGetProp(options, XML_ATTR_FILTER_TYPE); failed = create_xml_node(NULL, XML_TAG_FAILED); cl_log(LOG_DEBUG, "[cib] Processing \"%s\" event", op); if(op == NULL) { *result = CIBRES_FAILED; cl_log(LOG_ERR, "No operation specified\n"); } else if(strcmp("noop", op) == 0) { ; } else if(strcmp("quit", op) == 0) { cl_log(LOG_WARNING, "The CRMd has asked us to exit... complying"); exit(0); } else if (strcmp(CRM_OPERATION_PING, op) == 0) { cib_answer = createPingAnswerFragment(CRM_SYSTEM_CIB, "ok"); } else if (strcmp(CRM_OPERATION_BUMP, op) == 0) { - xmlNodePtr tmpCib = get_cib_copy(); + tmpCib = get_cib_copy(); CRM_DEBUG3("Handling a %s for section=%s of the cib", CRM_OPERATION_BUMP, section); // modify the timestamp set_node_tstamp(tmpCib); - char *new_value = NULL; - char *old_value = + old_value = xmlGetProp(get_the_CIB(), XML_ATTR_GENERATION); - int int_value = -1; if(old_value != NULL) { new_value = (char*)cl_malloc(128*(sizeof(char))); int_value = atoi(old_value); sprintf(new_value, "%d", ++int_value); } else { new_value = cl_strdup("0"); } cl_log(LOG_DEBUG, "Generation %d(%s)->%s", int_value, old_value, new_value); set_xml_property_copy(tmpCib, XML_ATTR_GENERATION, new_value); cl_free(new_value); if(activateCibXml(tmpCib, CIB_FILENAME) >= 0) { verbose = "true"; } else { *result = CIBRES_FAILED; } } else if (strcmp("query", op) == 0) { CRM_DEBUG2("Handling a query for section=%s of the cib", section); /* force a pick-up of the relevant section before * returning */ verbose = "true"; } else if (strcmp(CRM_OPERATION_ERASE, op) == 0) { xmlNodePtr new_cib = createEmptyCib(); // Preserve generation counters etc copy_in_properties(new_cib, get_the_CIB()); if (activateCibXml(new_cib, CIB_FILENAME) < 0) { *result = CIBRES_FAILED; } } else if (strcmp(CRM_OPERATION_CREATE, op) == 0) { update_the_cib = TRUE; cib_update_op = CIB_OP_ADD; } else if (strcmp(CRM_OPERATION_UPDATE, op) == 0 || strcmp(CRM_OPERATION_WELCOME, op) == 0 || strcmp(CRM_OPERATION_SHUTDOWN_REQ, op) == 0) { update_the_cib = TRUE; cib_update_op = CIB_OP_MODIFY; } else if (strcmp(CRM_OPERATION_DELETE, op) == 0) { update_the_cib = TRUE; cib_update_op = CIB_OP_DELETE; } else if (strcmp(CRM_OPERATION_REPLACE, op) == 0) { CRM_DEBUG2("Replacing section=%s of the cib", section); - xmlNodePtr tmpCib = NULL; section = xmlGetProp(fragment, XML_ATTR_SECTION); if (section == NULL || strlen(section) == 0 || strcmp("all", section) == 0) { tmpCib = copy_xml_node_recursive( find_xml_node(fragment, XML_TAG_CIB)); } else { tmpCib = copy_xml_node_recursive(get_the_CIB()); replace_section(section, tmpCib, fragment); } /*if(check_generation(cib_updates, tmpCib) == FALSE) *result = "discarded old update"; else */ if (activateCibXml(tmpCib, CIB_FILENAME) < 0) *result = CIBRES_FAILED; } else { *result = CIBRES_FAILED_NOTSUPPORTED; cl_log(LOG_ERR, "Action [%s] is not supported by the CIB", op); } if (update_the_cib) { CRM_DEBUG("Backing up CIB"); - xmlNodePtr tmpCib = copy_xml_node_recursive(get_the_CIB()); + tmpCib = copy_xml_node_recursive(get_the_CIB()); section = xmlGetProp(fragment, XML_ATTR_SECTION); CRM_DEBUG3("Updating section=%s of the cib (op=%s)", section, op); // should we be doing this? // do logging // make changes to a temp copy then activate if(section == NULL) { cl_log(LOG_ERR, "No section specified in %s", XML_ATTR_FILTER_TYPE); *result = CIBRES_FAILED_NOSECTION; } else if(strcmp("all", section) == 0 && cib_update_op == CIB_OP_DELETE) { // delete /* order is no longer important here */ updateList(tmpCib, fragment, failed, cib_update_op, XML_CIB_TAG_STATUS); updateList(tmpCib, fragment, failed, cib_update_op, XML_CIB_TAG_CONSTRAINTS); updateList(tmpCib, fragment, failed, cib_update_op, XML_CIB_TAG_RESOURCES); updateList(tmpCib, fragment, failed, cib_update_op, XML_CIB_TAG_NODES); } else if(strcmp("all", section) == 0) { /* order is no longer important here */ updateList(tmpCib, fragment, failed, cib_update_op, XML_CIB_TAG_NODES); updateList(tmpCib, fragment, failed, cib_update_op, XML_CIB_TAG_RESOURCES); updateList(tmpCib, fragment, failed, cib_update_op, XML_CIB_TAG_CONSTRAINTS); updateList(tmpCib, fragment, failed, cib_update_op, XML_CIB_TAG_STATUS); } else { *result = updateList(tmpCib, fragment, failed, cib_update_op, section); } CRM_DEBUG("Activating temporary CIB"); /* if(check_generation(cib_updates, tmpCib) == FALSE) */ /* status = "discarded old update"; */ /* else */ if (activateCibXml(tmpCib, CIB_FILENAME) < 0) { *result = CIBRES_FAILED_ACTIVATION; } else if (failed->children != NULL) { *result = CIBRES_FAILED; } CRM_DEBUG2("CIB update status: %d", *result); } output_section = section; if (failed->children != NULL || *result != CIBRES_OK) { cib_answer = createCibFragmentAnswer(NULL /*"all"*/, failed); } else if (verbose != NULL && strcmp("true", verbose) == 0) { cib_answer = createCibFragmentAnswer(output_section, failed); } free_xml(failed); FNRET(cib_answer); } gboolean replace_section(const char *section, xmlNodePtr tmpCib, xmlNodePtr fragment) { xmlNodePtr parent = NULL, cib_updates = NULL, new_section = NULL, old_section = NULL; FNIN(); cib_updates = find_xml_node(fragment, XML_TAG_CIB); /* find the old and new versions of the section */ new_section = get_object_root(section, cib_updates); old_section = get_object_root(section, tmpCib); if(old_section == NULL) { cl_log(LOG_ERR, "The CIB is corrupt, cannot replace missing section %s", section); FNRET(FALSE); } else if(new_section == NULL) { cl_log(LOG_ERR, "The CIB is corrupt, cannot set section %s to nothing", section); FNRET(FALSE); } parent = old_section->parent; /* unlink and free the old one */ unlink_xml_node(old_section); free_xml(old_section); /* add the new copy */ add_node_copy(parent, new_section); FNRET(TRUE); } enum cib_result updateList(xmlNodePtr local_cib, xmlNodePtr update_fragment, xmlNodePtr failed, int operation, const char *section) { xmlNodePtr child = NULL; xmlNodePtr this_section = get_object_root(section, local_cib); xmlNodePtr cib_updates = find_xml_node(update_fragment, XML_TAG_CIB); xmlNodePtr xml_section = get_object_root(section, cib_updates); if (section == NULL || xml_section == NULL) { cl_log(LOG_ERR, "Section %s not found in message." " CIB update is corrupt, ignoring.", section); return CIBRES_FAILED_NOSECTION; } if(CIB_OP_NONE > operation > CIB_OP_MAX) { cl_log(LOG_ERR, "Invalid operation on section %s", section); return CIBRES_FAILED; } set_node_tstamp(this_section); child = xml_section->children; while(child != NULL) { if(operation == CIB_OP_DELETE) { update_results(failed, child, operation, delete_cib_object(this_section, child)); } else if(operation == CIB_OP_MODIFY) { update_results(failed, child, operation, update_cib_object(this_section, child, FALSE)); } else { update_results(failed, child, operation, add_cib_object(this_section, child)); } child = child->next; } if (failed->children != NULL) return CIBRES_FAILED; else return CIBRES_OK; } xmlNodePtr createCibFragmentAnswer(const char *section, xmlNodePtr failed) { xmlNodePtr fragment = create_xml_node(NULL, XML_TAG_FRAGMENT); FNIN(); set_xml_property_copy(fragment, XML_ATTR_SECTION, section); if (section == NULL || strlen(section) == 0 || strcmp("all", section) == 0) { add_node_copy(fragment, get_the_CIB()); } else { xmlNodePtr cib = create_xml_node(fragment, XML_TAG_CIB); add_node_copy(cib, get_object_root(section, get_the_CIB())); copy_in_properties(cib, get_the_CIB()); } if (failed != NULL && failed->children != NULL) { add_node_copy(fragment, failed); } FNRET(fragment); } gboolean check_generation(xmlNodePtr newCib, xmlNodePtr oldCib) { char *new_value = xmlGetProp(newCib, XML_ATTR_GENERATION); char *old_value = xmlGetProp(oldCib, XML_ATTR_GENERATION); int int_new_value = -1; int int_old_value = -1; if(old_value != NULL) int_old_value = atoi(old_value); if(new_value != NULL) int_new_value = atoi(new_value); if(int_new_value >= int_old_value) { return TRUE; } else { cl_log(LOG_ERR, "Generation from update (%d) is older than %d", int_new_value, int_old_value); } return FALSE; } gboolean update_results(xmlNodePtr failed, xmlNodePtr target, int operation, int return_code) { - FNIN(); gboolean was_error = FALSE; + const char *error_msg = NULL; + const char *operation_msg = NULL; + xmlNodePtr xml_node; + FNIN(); if (return_code != CIBRES_OK) { - const char *error_msg = cib_error2string(return_code); - const char *operation_msg = cib_op2string(operation); + error_msg = cib_error2string(return_code); + operation_msg = cib_op2string(operation); - xmlNodePtr xml_node = create_xml_node(failed, + xml_node = create_xml_node(failed, XML_FAIL_TAG_CIB); was_error = TRUE; set_xml_property_copy(xml_node, XML_FAILCIB_ATTR_ID, ID(target)); set_xml_property_copy(xml_node, XML_FAILCIB_ATTR_OBJTYPE, TYPE(target)); set_xml_property_copy(xml_node, XML_FAILCIB_ATTR_OP, operation_msg); set_xml_property_copy(xml_node, XML_FAILCIB_ATTR_REASON, error_msg); cl_log(LOG_DEBUG, "Action %s failed: %s (cde=%d)", operation_msg, error_msg, return_code); } FNRET(was_error); } diff --git a/crm/cib/cibprimatives.c b/crm/cib/cibprimatives.c index 1932a1b574..3a485a68ee 100644 --- a/crm/cib/cibprimatives.c +++ b/crm/cib/cibprimatives.c @@ -1,555 +1,577 @@ -/* $Id: cibprimatives.c,v 1.23 2004/04/06 16:23:03 andrew Exp $ */ +/* $Id: cibprimatives.c,v 1.24 2004/04/15 00:34:06 msoffen Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * 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 - #include #include #include #include #include #include #include +#include + #include #include #include #include #include #include #include /* * In case of confusion, this is the memory management policy for * all functions in this file. * * All add/modify functions use copies of supplied data. * It is therefore appropriate that the callers free the supplied data * at some point after the function has finished. * * All delete functions will handle the freeing of deleted data * but not the function arguments. */ void update_node_state(xmlNodePtr existing_node, xmlNodePtr update); //--- Resource int addResource(xmlNodePtr cib, xmlNodePtr anXmlNode) { const char *id = ID(anXmlNode); + xmlNodePtr root; if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } CRM_DEBUG2("Adding " XML_CIB_TAG_RESOURCE " (%s)...", id); - xmlNodePtr root = get_object_root(XML_CIB_TAG_RESOURCES, cib); + root = get_object_root(XML_CIB_TAG_RESOURCES, cib); return add_cib_object(root, anXmlNode); } xmlNodePtr findResource(xmlNodePtr cib, const char *id) { xmlNodePtr root = NULL, ret = NULL; FNIN(); root = get_object_root(XML_CIB_TAG_RESOURCES, cib); ret = find_entity(root, XML_CIB_TAG_RESOURCE, id, FALSE); FNRET(ret); } int updateResource(xmlNodePtr cib, xmlNodePtr anXmlNode) { const char *id = ID(anXmlNode); + xmlNodePtr root; + if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } CRM_DEBUG2("Updating " XML_CIB_TAG_RESOURCE " (%s)...", id); - xmlNodePtr root = get_object_root(XML_CIB_TAG_RESOURCES, cib); + root = get_object_root(XML_CIB_TAG_RESOURCES, cib); return update_cib_object(root, anXmlNode, FALSE); } int delResource(xmlNodePtr cib, xmlNodePtr delete_spec) { const char *id = ID(delete_spec); + xmlNodePtr root; + if(id == NULL || strlen(id) == 0) { return CIBRES_MISSING_ID; } CRM_DEBUG2("Deleting " XML_CIB_TAG_RESOURCE " (%s)...", id); - xmlNodePtr root = get_object_root(XML_CIB_TAG_RESOURCES, cib); + root = get_object_root(XML_CIB_TAG_RESOURCES, cib); return delete_cib_object(root, delete_spec); } //--- Constraint int addConstraint(xmlNodePtr cib, xmlNodePtr anXmlNode) { const char *id = ID(anXmlNode); + xmlNodePtr root; + if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } CRM_DEBUG2("Adding " XML_CIB_TAG_CONSTRAINT " (%s)...", id); - xmlNodePtr root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); + root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); return add_cib_object(root, anXmlNode); } xmlNodePtr findConstraint(xmlNodePtr cib, const char *id) { xmlNodePtr root = NULL, ret = NULL; FNIN(); root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); ret = find_entity(root, XML_CIB_TAG_CONSTRAINT, id, FALSE); FNRET(ret); } int updateConstraint(xmlNodePtr cib, xmlNodePtr anXmlNode) { const char *id = ID(anXmlNode); + xmlNodePtr root; if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } CRM_DEBUG2("Updating " XML_CIB_TAG_CONSTRAINT " (%s)...", id); - xmlNodePtr root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); + root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); return update_cib_object(root, anXmlNode, FALSE); } int delConstraint(xmlNodePtr cib, xmlNodePtr delete_spec) { const char *id = ID(delete_spec); + xmlNodePtr root; + if(id == NULL || strlen(id) == 0) { return CIBRES_MISSING_ID; } CRM_DEBUG2("Deleting " XML_CIB_TAG_CONSTRAINT " (%s)...", id); - xmlNodePtr root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); + root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); return delete_cib_object(root, delete_spec); } //--- HaNode int addHaNode(xmlNodePtr cib, xmlNodePtr anXmlNode) { const char *id = ID(anXmlNode); + xmlNodePtr root; + if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } CRM_DEBUG2("Adding " XML_CIB_TAG_NODE " (%s)...", id); - xmlNodePtr root = get_object_root(XML_CIB_TAG_NODES, cib); + root = get_object_root(XML_CIB_TAG_NODES, cib); return add_cib_object(root, anXmlNode); } xmlNodePtr findHaNode(xmlNodePtr cib, const char *id) { xmlNodePtr root = NULL, ret = NULL; FNIN(); root = get_object_root(XML_CIB_TAG_NODES, cib); ret = find_entity(root, XML_CIB_TAG_NODE, id, FALSE); FNRET(ret); } int updateHaNode(xmlNodePtr cib, cibHaNode *anXmlNode) { const char *id = ID(anXmlNode); + xmlNodePtr root; + if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } CRM_DEBUG2("Updating " XML_CIB_TAG_NODE " (%s)...", id); - xmlNodePtr root = get_object_root(XML_CIB_TAG_NODES, cib); + root = get_object_root(XML_CIB_TAG_NODES, cib); return update_cib_object(root, anXmlNode, FALSE); } int delHaNode(xmlNodePtr cib, xmlNodePtr delete_spec) { const char *id = ID(delete_spec); + xmlNodePtr root; + if(id == NULL || strlen(id) == 0) { return CIBRES_MISSING_ID; } CRM_DEBUG2("Deleting " XML_CIB_TAG_NODE " (%s)...", id); - xmlNodePtr root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); + root = get_object_root(XML_CIB_TAG_CONSTRAINTS, cib); return delete_cib_object(root, delete_spec); } //--- Status int addStatus(xmlNodePtr cib, xmlNodePtr anXmlNode) { const char *id = ID(anXmlNode); + xmlNodePtr root; + if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } CRM_DEBUG2("Adding " XML_CIB_TAG_NODE " (%s)...", id); - xmlNodePtr root = get_object_root(XML_CIB_TAG_STATUS, cib); + root = get_object_root(XML_CIB_TAG_STATUS, cib); return add_cib_object(root, anXmlNode); } xmlNodePtr findStatus(xmlNodePtr cib, const char *id) { xmlNodePtr root = NULL, ret = NULL; root = get_object_root(XML_CIB_TAG_STATUS, cib); ret = find_entity(root, XML_CIB_TAG_STATE, id, FALSE); FNRET(ret); } int updateStatus(xmlNodePtr cib, xmlNodePtr anXmlNode) { const char *id = ID(anXmlNode); + xmlNodePtr root; + if (id == NULL || strlen(id) < 1) { return CIBRES_MISSING_ID; } CRM_DEBUG2("Updating " XML_CIB_TAG_NODE " (%s)...", id); - xmlNodePtr root = get_object_root(XML_CIB_TAG_STATUS, cib); + root = get_object_root(XML_CIB_TAG_STATUS, cib); return update_cib_object(root, anXmlNode, FALSE); } int delStatus(xmlNodePtr cib, xmlNodePtr delete_spec) { const char *id = ID(delete_spec); + xmlNodePtr root; + if(id == NULL || strlen(id) == 0) { return CIBRES_MISSING_ID; } CRM_DEBUG2("Deleting " XML_CIB_TAG_STATE " (%s)...", id); - xmlNodePtr root = get_object_root(XML_CIB_TAG_STATUS, cib); + root = get_object_root(XML_CIB_TAG_STATUS, cib); return delete_cib_object(root, delete_spec); } int delete_cib_object(xmlNodePtr parent, xmlNodePtr delete_spec) { const char *object_name = NULL; const char *object_id = NULL; xmlNodePtr equiv_node = NULL; xmlNodePtr children = NULL; int result = CIBRES_OK; if(delete_spec == NULL) { return CIBRES_FAILED_NOOBJECT; } else if(parent == NULL) { return CIBRES_FAILED_NOPARENT; } object_name = delete_spec->name; object_id = xmlGetProp(delete_spec, XML_ATTR_ID); children = delete_spec->children; if(object_id == NULL) { // placeholder object equiv_node = find_xml_node(parent, object_name); } else { equiv_node = find_entity(parent, object_name, object_id, FALSE); } if(equiv_node == NULL) { return CIBRES_FAILED_NOTEXISTS; } else if(children == NULL) { // only leaves are deleted unlink_xml_node(equiv_node); free_xml(equiv_node); } else { while(children != NULL) { int tmp_result = delete_cib_object(equiv_node, children); // only the first error is likely to be interesting if(tmp_result != CIBRES_OK && result == CIBRES_OK) { result = tmp_result; } children = children->next; } } return result; } int add_cib_object(xmlNodePtr parent, xmlNodePtr new_obj) { const char *object_name = NULL; const char *object_id = NULL; xmlNodePtr equiv_node = NULL; xmlNodePtr children = NULL; if(new_obj == NULL) { return CIBRES_FAILED_NOOBJECT; } else if(parent == NULL) { return CIBRES_FAILED_NOPARENT; } object_name = new_obj->name; object_id = xmlGetProp(new_obj, XML_ATTR_ID); children = new_obj->children; if(object_id == NULL) { // placeholder object equiv_node = find_xml_node(parent, object_name); } else { equiv_node = find_entity(parent, object_name, object_id, FALSE); } if(equiv_node != NULL) { return CIBRES_FAILED_EXISTS; } else if(add_node_copy(parent, new_obj) == NULL) { return CIBRES_FAILED_NODECOPY; } return CIBRES_OK; } int update_cib_object(xmlNodePtr parent, xmlNodePtr new_obj, gboolean force) { const char *object_name = NULL; const char *object_id = NULL; xmlNodePtr equiv_node = NULL; xmlNodePtr children = NULL; int result = CIBRES_OK; if(new_obj == NULL) { return CIBRES_FAILED_NOOBJECT; } else if(parent == NULL) { return CIBRES_FAILED_NOPARENT; } object_name = new_obj->name; object_id = xmlGetProp(new_obj, XML_ATTR_ID); children = new_obj->children; if(object_id == NULL) { // placeholder object equiv_node = find_xml_node(parent, object_name); } else { equiv_node = find_entity(parent, object_name, object_id, FALSE); } if(equiv_node != NULL) { if(force == FALSE) { const char *ts_existing = NULL; const char *ts_new = NULL; /* default to false? * * that would mean every node would have to * carry a timestamp */ gboolean is_update = TRUE; ts_existing = TSTAMP(equiv_node); ts_new = TSTAMP(new_obj); if(ts_new != NULL && ts_existing != NULL) { is_update = (strcmp(ts_new, ts_existing) > 0); } if(is_update == FALSE) { cl_log(LOG_ERR, "Ignoring old update to <%s id=\"%s\">" "(%s vs. %s)", object_name, object_id, ts_new, ts_existing); return CIBRES_FAILED_STALE; } } if(safe_str_eq(XML_CIB_TAG_STATE, object_name)){ update_node_state(equiv_node, new_obj); } else { copy_in_properties(equiv_node, new_obj); } while(children != NULL) { int tmp_result = update_cib_object(equiv_node, children,force); // only the first error is likely to be interesting if(tmp_result != CIBRES_OK && result == CIBRES_OK) { result = tmp_result; } children = children->next; } } else if(add_node_copy(parent, new_obj) == NULL) { return CIBRES_FAILED_NODECOPY; } return result; } void update_node_state(xmlNodePtr target, xmlNodePtr update) { gboolean any_updates = FALSE; const char *old_state = xmlGetProp(target, "state"); const char *old_unclean = xmlGetProp(target, "unclean"); const char *source = NULL; const char *unclean = NULL; const char *exp_state = NULL; const char *state = NULL; xmlAttrPtr prop_iter = NULL; FNIN(); prop_iter = update->properties; while(prop_iter != NULL) { const char *local_prop_name = prop_iter->name; const char *local_prop_value = xmlGetProp(update, local_prop_name); if(local_prop_name == NULL) { // error } else if(strcmp(local_prop_name, "source") == 0) { source = local_prop_value; } else if(strcmp(local_prop_name, "state") == 0) { state = local_prop_value; } else { any_updates = TRUE; set_xml_property_copy(target, local_prop_name, local_prop_value); } prop_iter = prop_iter->next; } unclean = xmlGetProp(target, "unclean"); exp_state = xmlGetProp(target, "exp_state"); if(safe_str_eq(state, "in_ccm")) { if(safe_str_eq(old_state, "active")) { state = "active"; } else { any_updates = TRUE; } } else if(safe_str_eq(state, "down")) { any_updates = TRUE; if(safe_str_neq(exp_state, "down")) { // TODO: Set the actual time // TODO: Only if not set? if(old_unclean == NULL) { set_xml_property_copy(target, "unclean", "time"); } // TODO: unset source? } } else if(state != NULL) { any_updates = TRUE; } set_xml_property_copy(target, "state", state); if(any_updates) { set_node_tstamp(target); set_xml_property_copy(target, "source", source); } } diff --git a/crm/common/crmutils.c b/crm/common/crmutils.c index 3eb4174b02..21aca878fe 100644 --- a/crm/common/crmutils.c +++ b/crm/common/crmutils.c @@ -1,284 +1,289 @@ -/* $Id: crmutils.c,v 1.11 2004/04/13 13:26:44 andrew Exp $ */ +/* $Id: crmutils.c,v 1.12 2004/04/15 00:35:19 msoffen Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * 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 #include + #include #include #include #include #include #include #include +#include + #include #include #include #include #include static int wdt_interval_ms = 10000; gboolean tickle_apphb_template(gpointer data) { char app_instance[APPNAME_LEN]; int rc = 0; sprintf(app_instance, "%s_%ld", "our_system_name", (long)getpid()); rc = apphb_hb(); if (rc < 0) { cl_perror("%s apphb_hb failure", app_instance); exit(3); } return TRUE; } void register_pid(const char *pid_file, gboolean do_fork, void (*shutdown)(int nsig)) { int j; long pid; FILE * lockfd; if (do_fork) { pid = fork(); if (pid < 0) { cl_log(LOG_CRIT, "cannot start daemon"); exit(LSB_EXIT_GENERIC); }else if (pid > 0) { exit(LSB_EXIT_OK); } } lockfd = fopen(pid_file, "w"); if (lockfd == NULL) { cl_log(LOG_CRIT, "cannot create pid file: %s", pid_file); exit(LSB_EXIT_GENERIC); }else{ pid = getpid(); fprintf(lockfd, "%ld\n", pid); fclose(lockfd); } umask(022); for (j=0; j < 3; ++j) { close(j); (void)open("/dev/null", j == 0 ? O_RDONLY : O_RDONLY); } // CL_IGNORE_SIG(SIGINT); // CL_IGNORE_SIG(SIGHUP); CL_SIGNAL(SIGTERM, shutdown); } long get_running_pid(const char *pid_file, gboolean* anypidfile) { long pid; FILE * lockfd; lockfd = fopen(pid_file, "r"); if (anypidfile) { *anypidfile = (lockfd != NULL); } if (lockfd != NULL && fscanf(lockfd, "%ld", &pid) == 1 && pid > 0) { if (CL_PID_EXISTS((pid_t)pid)) { fclose(lockfd); return(pid); } } if (lockfd != NULL) { fclose(lockfd); } return(-1L); } int init_stop(const char *pid_file) { + long pid; + int rc = LSB_EXIT_OK; + FNIN(); if (pid_file == NULL) { cl_log(LOG_ERR, "No pid file specified to kill process"); return LSB_EXIT_GENERIC; } - long pid; - int rc = LSB_EXIT_OK; pid = get_running_pid(pid_file, NULL); if (pid > 0) { if (CL_KILL((pid_t)pid, SIGTERM) < 0) { rc = (errno == EPERM ? LSB_EXIT_EPERM : LSB_EXIT_GENERIC); fprintf(stderr, "Cannot kill pid %ld\n", pid); }else{ cl_log(LOG_INFO, "Signal sent to pid=%ld," " waiting for process to exit", pid); while (CL_PID_EXISTS(pid)) { sleep(1); } } } FNRET(rc); } int init_status(const char *pid_file, const char *client_name) { gboolean anypidfile; long pid = get_running_pid(pid_file, &anypidfile); if (pid > 0) { fprintf(stderr, "%s is running [pid: %ld]\n" , client_name, pid); return LSB_STATUS_OK; } if (anypidfile) { fprintf(stderr, "%s is stopped [pidfile exists]\n" , client_name); return LSB_STATUS_VAR_PID; } fprintf(stderr, "%s is stopped.\n", client_name); return LSB_STATUS_STOPPED; } gboolean register_with_ha(ll_cluster_t *hb_cluster, const char *client_name, gboolean (*dispatch_method)(int fd, gpointer user_data), void (*message_callback)(const struct ha_msg* msg, void* private_data), GDestroyNotify cleanup_method) { + const char* ournode = NULL; + cl_log(LOG_INFO, "Signing in with Heartbeat"); if (hb_cluster->llc_ops->signon(hb_cluster, client_name)!= HA_OK) { cl_log(LOG_ERR, "Cannot sign on with heartbeat"); cl_log(LOG_ERR, "REASON: %s", hb_cluster->llc_ops->errmsg(hb_cluster)); return FALSE; } - const char* ournode = NULL; cl_log(LOG_DEBUG, "Finding our node name"); if ((ournode = hb_cluster->llc_ops->get_mynodeid(hb_cluster)) == NULL) { cl_log(LOG_ERR, "get_mynodeid() failed"); return FALSE; } cl_log(LOG_INFO, "Hostname: %s", ournode); /* cl_log(LOG_INFO, "Be informed of link status changes"); */ /* if (hb_cluster->llc_ops->set_ifstatus_callback(hb_cluster, LinkStatus, NULL) */ /* !=HA_OK){ */ /* cl_log(LOG_ERR, "Cannot set if status callback"); */ /* cl_log(LOG_ERR, "REASON: %s", hb_cluster->llc_ops->errmsg(hb_cluster)); */ /* return FALSE; */ /* } */ cl_log(LOG_DEBUG, "Be informed of CRM messages"); if (hb_cluster->llc_ops->set_msg_callback(hb_cluster, "CRM", message_callback, hb_cluster) !=HA_OK){ cl_log(LOG_ERR, "Cannot set CRM message callback"); cl_log(LOG_ERR, "REASON: %s", hb_cluster->llc_ops->errmsg(hb_cluster)); return FALSE; } G_main_add_fd(G_PRIORITY_HIGH, hb_cluster->llc_ops->inputfd(hb_cluster), FALSE, dispatch_method, hb_cluster, // usrdata cleanup_method); /* it seems we need to poke the message receiving stuff in order for it to * start seeing messages. Its like it gets blocked or something. */ dispatch_method(0, hb_cluster); return TRUE; } void register_with_apphb(const char *client_name, gboolean(*tickle_fn)(gpointer data)) { - // Register with apphb - cl_log(LOG_INFO, "Signing in with AppHb"); char app_instance[APPNAME_LEN]; int hb_intvl_ms = wdt_interval_ms * 2; int rc = 0; + + // Register with apphb + cl_log(LOG_INFO, "Signing in with AppHb"); sprintf(app_instance, "%s_%ld", client_name, (long)getpid()); cl_log(LOG_INFO, "Client %s registering with apphb", app_instance); rc = apphb_register(client_name, app_instance); if (rc < 0) { cl_perror("%s registration failure", app_instance); exit(1); } cl_log(LOG_DEBUG, "Client %s registered with apphb", app_instance); cl_log(LOG_INFO, "Client %s setting %d ms apphb heartbeat interval" , app_instance, hb_intvl_ms); rc = apphb_setinterval(hb_intvl_ms); if (rc < 0) { cl_perror("%s setinterval failure", app_instance); exit(2); } // regularly tell apphb that we are alive cl_log(LOG_INFO, "Setting up AppHb Heartbeat"); Gmain_timeout_add(wdt_interval_ms, tickle_fn, NULL); } char * crm_itoa(int an_int) { int len = 32; char *buffer = cl_malloc(sizeof(char)*(len+1)); snprintf(buffer, len, "%d", an_int); return buffer; } diff --git a/crm/common/ipcutils.c b/crm/common/ipcutils.c index 063502cd31..529b8f21ba 100644 --- a/crm/common/ipcutils.c +++ b/crm/common/ipcutils.c @@ -1,532 +1,552 @@ -/* $Id: ipcutils.c,v 1.21 2004/04/09 16:22:50 andrew Exp $ */ +/* $Id: ipcutils.c,v 1.22 2004/04/15 00:35:19 msoffen Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * 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 - #include + #include #include #include #include #include #include +#include + #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include // for getNow() #include +/* +#include +#include +*/ #include #include #include #include FILE *msg_out_strm = NULL; IPC_Message *create_simple_message(char *text, IPC_Channel *ch); void LinkStatus(const char * node, const char * lnk, const char * status ,void * private) { // put something here } gboolean send_xmlipc_message(IPC_Channel *ipc_client, xmlNodePtr msg) { char *xml_message = NULL; + IPC_Message *cib_dump = NULL; + gboolean res; FNIN(); xml_message = dump_xml(msg); - IPC_Message *cib_dump = + cib_dump = create_simple_message(xml_message, ipc_client); - gboolean res = send_ipc_message(ipc_client, cib_dump); + res = send_ipc_message(ipc_client, cib_dump); cl_free(xml_message); xml_message_debug(msg, "Sent IPC Message"); FNRET(res); } gboolean send_xmlha_message(ll_cluster_t *hb_fd, xmlNodePtr root) { gboolean broadcast = FALSE; gboolean all_is_good = TRUE; int send_result = -1; int xml_len = -1; const char *host_to = NULL; const char *sys_to = NULL; + struct ha_msg *msg = NULL; + char *xml_text; +#ifdef MSG_LOG + char *msg_text = NULL; +#endif + FNIN(); if (root == NULL) { cl_log(LOG_ERR, "Attempt to send NULL Message via HA failed."); all_is_good = FALSE; } host_to = xmlGetProp(root, XML_ATTR_HOSTTO); sys_to = xmlGetProp(root, XML_ATTR_SYSTO); if (sys_to != NULL && strcmp("dc", sys_to) == 0) { cl_log(LOG_INFO, "Resetting the value of %s to null from %s", XML_ATTR_HOSTTO, host_to); // xmlSetProp(root, XML_ATTR_HOSTTO, ""); } - struct ha_msg *msg = NULL; if (all_is_good) { msg = ha_msg_new(4); ha_msg_add(msg, F_TYPE, "CRM"); ha_msg_add(msg, F_COMMENT, "A CRM xml message"); - char *xml_text = dump_xml(root); + xml_text = dump_xml(root); xml_len = strlen(xml_text); if (xml_text == NULL || xml_len <= 0) { cl_log(LOG_ERR, "Failed sending an invalid XML Message via HA"); all_is_good = FALSE; xml_message_debug(root, "Bad message was"); } else { if(ha_msg_add(msg, "xml", xml_text) == HA_FAIL) { cl_log(LOG_ERR, "Could not add xml to HA message"); all_is_good = FALSE; } } } if (all_is_good) { if (sys_to == NULL || strlen(sys_to) == 0) { cl_log(LOG_ERR, "You did not specify a destination sub-system" " for this message."); all_is_good = FALSE; } } /* There are a number of messages may not need to be ordered. * At a later point perhaps we should detect them and send them * as unordered messages. */ if (all_is_good) { if (host_to == NULL || strlen(host_to) == 0 || strcmp("dc", sys_to) == 0) { broadcast = TRUE; send_result = hb_fd->llc_ops->send_ordered_clustermsg(hb_fd, msg); } else { send_result = hb_fd->llc_ops->send_ordered_nodemsg(hb_fd, msg, host_to); } if(send_result != HA_OK) all_is_good = FALSE; } if(!all_is_good) { cl_log(LOG_ERR, "Sending %s HA message (ref=%s, len=%d) to %s@%s %s.", broadcast?"broadcast":"directed", xmlGetProp(root, XML_ATTR_REFERENCE), xml_len, sys_to, host_to==NULL?"":host_to, all_is_good?"succeeded":"failed"); } else { xmlNodePtr opts = find_xml_node(root, XML_TAG_OPTIONS); const char *op = xmlGetProp(opts, XML_ATTR_OP); if(op == NULL || strcmp(op, CRM_OPERATION_HBEAT) != 0) { cl_log(LOG_DEBUG, "Sent %s HA message (ref=%s, len=%d) to %s@%s", broadcast?"broadcast":"directed", xmlGetProp(root, XML_ATTR_REFERENCE), xml_len, sys_to, host_to==NULL?"":host_to); } } #ifdef MSG_LOG - - char *msg_text = dump_xml(root); + msg_text = dump_xml(root); if(msg_out_strm == NULL) { msg_out_strm = fopen("/tmp/outbound.log", "w"); } fprintf(msg_out_strm, "[%d HA (%s:%d)]\t%s\n", all_is_good, xmlGetProp(root, XML_ATTR_REFERENCE), send_result, msg_text); fflush(msg_out_strm); cl_free(msg_text); - #endif FNRET(all_is_good); } gboolean send_ipc_message(IPC_Channel *ipc_client, IPC_Message *msg) { - FNIN(); gboolean all_is_good = TRUE; + int lpc = 0; + FNIN(); if (msg == NULL) { cl_log(LOG_WARNING, "cant send NULL message"); all_is_good = FALSE; } else if (msg->msg_len <= 0) { cl_log(LOG_WARNING, "cant send 0 sized message"); all_is_good = FALSE; } else if (msg->msg_len > MAXDATASIZE) { cl_log(LOG_WARNING, "cant send msg... too big"); all_is_good = FALSE; } /* CRM_DEBUG2("Sending message: %s", (char*)msg->msg_body); */ CRM_DEBUG2("Message is%s valid to send", all_is_good?"":" not"); if (ipc_client == NULL) { all_is_good = FALSE; } CRM_DEBUG2("IPC Client is%s set.", all_is_good?"":" not"); - int lpc = 0; if (all_is_good) { while(lpc++ < MAX_IPC_FAIL && ipc_client->ops->send(ipc_client, msg) == IPC_FAIL) { cl_log(LOG_WARNING, "ipc channel blocked"); cl_shortsleep(); } } if (lpc == MAX_IPC_FAIL) { cl_log(LOG_ERR, "Could not send IPC, message. Channel is dead."); FNRET(!all_is_good); } CRM_DEBUG2("Sending of IPC message %s.", all_is_good?"succeeded":"failed"); FNRET(all_is_good); } IPC_Message * create_simple_message(char *text, IPC_Channel *ch) { - FNIN(); - if (text == NULL) FNRET(NULL); - // char str[256]; IPC_Message *ack_msg = NULL; + FNIN(); + if (text == NULL) FNRET(NULL); + ack_msg = (IPC_Message *)cl_malloc(sizeof(IPC_Message)); ack_msg->msg_private = NULL; ack_msg->msg_done = NULL; ack_msg->msg_body = text; ack_msg->msg_ch = ch; ack_msg->msg_len = strlen(text)+1; FNRET(ack_msg); } gboolean default_ipc_input_dispatch(IPC_Channel *client, gpointer user_data) { xmlNodePtr root; + xmlNodePtr options; IPC_Message *msg = NULL; + const char *op; FNIN(); msg = get_ipc_message(client); if (msg) { root = find_xml_in_ipcmessage(msg, TRUE); validate_crm_message(root, NULL, NULL, NULL); - xmlNodePtr options = find_xml_node(root, XML_TAG_OPTIONS); - const char *op = xmlGetProp(options, XML_ATTR_OP); + options = find_xml_node(root, XML_TAG_OPTIONS); + op = xmlGetProp(options, XML_ATTR_OP); if(op != NULL && strcmp(op, "quit") == 0) { cl_log(LOG_WARNING, "The CRMd has asked us to exit... complying"); exit(0); } } else if (client->ch_status == IPC_DISCONNECT) { cl_log(LOG_ERR, "The server has left us: Shutting down...NOW"); exit(1); /* Server disconnects should be fatal, * but I will do it a little more gracefully :) */ FNRET(FALSE); /* This conection is hosed */ } FNRET(TRUE); /* TOBEDONE */ } xmlNodePtr find_xml_in_hamessage(const struct ha_msg* msg) { + const char *xml; + xmlDocPtr doc; + xmlNodePtr root; + FNIN(); if (msg == NULL) { cl_log(LOG_INFO, "**** ha_crm_msg_callback called on a NULL message"); FNRET(NULL); } #if 0 cl_log(LOG_DEBUG, "[F_TYPE=%s]", ha_msg_value(msg, F_TYPE)); cl_log(LOG_DEBUG, "[F_ORIG=%s]", ha_msg_value(msg, F_ORIG)); cl_log(LOG_DEBUG, "[F_TO=%s]", ha_msg_value(msg, F_TO)); cl_log(LOG_DEBUG, "[F_COMMENT=%s]", ha_msg_value(msg, F_COMMENT)); cl_log(LOG_DEBUG, "[F_XML=%s]", ha_msg_value(msg, "xml")); // cl_log(LOG_DEBUG, "[F_=%s]", ha_msg_value(ha_msg, F_)); #endif if (strcmp("CRM", ha_msg_value(msg, F_TYPE)) != 0) { cl_log(LOG_INFO, "Received a (%s) message by mistake.", ha_msg_value(msg, F_TYPE)); FNRET(NULL); } - const char *xml = ha_msg_value(msg, "xml"); + xml = ha_msg_value(msg, "xml"); if (xml == NULL) { cl_log(LOG_INFO, "No XML attached to this message."); FNRET(NULL); } - - xmlDocPtr doc = xmlParseMemory(xml, strlen(xml)); + doc = xmlParseMemory(xml, strlen(xml)); if (doc == NULL) { cl_log(LOG_INFO, "XML Buffer was not valid."); FNRET(NULL); } - - xmlNodePtr root = xmlDocGetRootElement(doc); + root = xmlDocGetRootElement(doc); if (root == NULL) { cl_log(LOG_INFO, "Root node was NULL."); FNRET(NULL); } FNRET(root); } xmlNodePtr find_xml_in_ipcmessage(IPC_Message *msg, gboolean do_free) { + char *buffer = NULL; + xmlDocPtr doc; + xmlNodePtr root; + FNIN(); if (msg == NULL) { CRM_DEBUG("IPC Message was empty..."); FNRET(NULL); } - char *buffer = (char*)msg->msg_body; - xmlDocPtr doc = xmlParseMemory(buffer, strlen(buffer)); + buffer = (char*)msg->msg_body; + doc = xmlParseMemory(buffer, strlen(buffer)); if (do_free) msg->msg_done(msg); if (doc == NULL) { cl_log(LOG_INFO, "IPC Message did not contain an XML buffer..."); FNRET(NULL); } - xmlNodePtr root = xmlDocGetRootElement(doc); + root = xmlDocGetRootElement(doc); if (root == NULL) { cl_log(LOG_INFO, "Root node was NULL."); FNRET(NULL); } FNRET(root); } void default_ipc_input_destroy(gpointer user_data) { FNIN(); FNOUT(); } int init_server_ipc_comms( const char *child, gboolean (*channel_client_connect)(IPC_Channel *newclient, gpointer user_data), void (*channel_input_destroy)(gpointer user_data)) { - FNIN(); - /* the clients wait channel is the other source of events. * This source delivers the clients connection events. * listen to this source at a relatively lower priority. */ char commpath[SOCKET_LEN]; - sprintf(commpath, WORKING_DIR "/%s", child); - IPC_WaitConnection *wait_ch; + FNIN(); + sprintf(commpath, WORKING_DIR "/%s", child); + wait_ch = wait_channel_init(commpath); if (wait_ch == NULL) FNRET(1); G_main_add_IPC_WaitConnection(G_PRIORITY_LOW, wait_ch, NULL, FALSE, channel_client_connect, wait_ch, // user data passed to ?? channel_input_destroy); cl_log(LOG_DEBUG, "Listening on: %s", commpath); FNRET(0); } IPC_Channel * init_client_ipc_comms(const char *child, gboolean (*dispatch)(IPC_Channel* source_data ,gpointer user_data), crmd_client_t *client_data) { - FNIN(); IPC_Channel *ch; GHashTable * attrs; GCHSource *the_source = NULL; void *callback_data = client_data; static char path[] = IPC_PATH_ATTR; - + char *commpath = NULL; int local_socket_len = 2; // 2 = '/' + '\0' + + FNIN(); local_socket_len += strlen(child); local_socket_len += strlen(WORKING_DIR); - char *commpath = (char*)cl_malloc(sizeof(char)*local_socket_len); + commpath = (char*)cl_malloc(sizeof(char)*local_socket_len); sprintf(commpath, WORKING_DIR "/%s", child); commpath[local_socket_len - 1] = '\0'; cl_log(LOG_DEBUG, "Attempting to talk on: %s", commpath); attrs = g_hash_table_new(g_str_hash,g_str_equal); g_hash_table_insert(attrs, path, commpath); ch = ipc_channel_constructor(IPC_ANYTYPE, attrs); g_hash_table_destroy(attrs); if (ch == NULL) { cl_log(LOG_CRIT, "Could not access channel on: %s", commpath); } else if (ch->ops->initiate_connection(ch) != IPC_OK) { cl_log(LOG_CRIT, "Could not init comms on: %s", commpath); FNRET(NULL); } if(callback_data == NULL) callback_data = ch; ch->ops->set_recv_qlen(ch, 100); ch->ops->set_send_qlen(ch, 100); the_source = G_main_add_IPC_Channel(G_PRIORITY_LOW, ch, FALSE, dispatch, callback_data, default_ipc_input_destroy); if(client_data != NULL) { client_data->client_source = the_source; client_data->client_channel = ch; } FNRET(ch); } IPC_WaitConnection * wait_channel_init(char daemonsocket[]) { - FNIN(); IPC_WaitConnection *wait_ch; mode_t mask; char path[] = IPC_PATH_ATTR; - - GHashTable * attrs = g_hash_table_new(g_str_hash,g_str_equal); + GHashTable * attrs; + + FNIN(); + attrs = g_hash_table_new(g_str_hash,g_str_equal); g_hash_table_insert(attrs, path, daemonsocket); mask = umask(0); wait_ch = ipc_wait_conn_constructor(IPC_ANYTYPE, attrs); if (wait_ch == NULL) { cl_perror("Can't create wait channel of type %s", IPC_ANYTYPE); exit(1); } mask = umask(mask); g_hash_table_destroy(attrs); FNRET(wait_ch); } IPC_Message * get_ipc_message(IPC_Channel *a_channel) { - FNIN(); IPC_Message *msg = NULL; + + FNIN(); if(a_channel->ops->is_message_pending(a_channel) == TRUE) { if (a_channel->ch_status == IPC_DISCONNECT) { /* The pending message was IPC_DISCONNECT */ cl_log(LOG_INFO, "get_ipc_message: received HUP"); FNRET(msg); } if(a_channel->ops->recv(a_channel, &msg) != IPC_OK) { perror("Receive failure:"); FNRET(msg); } cl_log(LOG_INFO, "Got message [body=%s]", (char*)msg->msg_body); } FNRET(msg); } diff --git a/crm/common/msgutils.c b/crm/common/msgutils.c index 6325005ca0..5726141bf6 100644 --- a/crm/common/msgutils.c +++ b/crm/common/msgutils.c @@ -1,708 +1,736 @@ -/* $Id: msgutils.c,v 1.25 2004/03/26 14:14:25 andrew Exp $ */ +/* $Id: msgutils.c,v 1.26 2004/04/15 00:35:19 msoffen Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * 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 - #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include xmlNodePtr create_common_message(xmlNodePtr original_request, xmlNodePtr xml_response_data); xmlNodePtr createPingAnswerFragment(const char *from, const char *status) { xmlNodePtr ping = NULL; FNIN(); ping = create_xml_node(NULL, XML_CRM_TAG_PING); set_xml_property_copy(ping, XML_PING_ATTR_STATUS, status); set_xml_property_copy(ping, XML_PING_ATTR_SYSFROM, from); FNRET(ping); } xmlNodePtr createPingRequest(const char *crm_msg_reference, const char *to) { xmlNodePtr root_xml_node = NULL; + int sub_type_len; + int msg_type_len; + char *sub_type_target; + char *msg_type_target; + FNIN(); // 2 = "_" + '\0' - int sub_type_len = strlen(to) + strlen(XML_ATTR_REQUEST) + 2; - char *sub_type_target = + sub_type_len = strlen(to) + strlen(XML_ATTR_REQUEST) + 2; + sub_type_target = (char*)cl_malloc(sizeof(char)*(sub_type_len)); sprintf(sub_type_target, "%s_%s", to, XML_ATTR_REQUEST); root_xml_node = create_xml_node(NULL, sub_type_target); set_xml_property_copy(root_xml_node, XML_ATTR_REFERENCE, crm_msg_reference); - int msg_type_len = strlen(to) + 10 + 1; // + "_operation" + '\0' - char *msg_type_target = + msg_type_len = strlen(to) + 10 + 1; // + "_operation" + '\0' + msg_type_target = (char*)cl_malloc(sizeof(char)*(msg_type_len)); sprintf(msg_type_target, "%s_operation", to); set_xml_property_copy(root_xml_node, msg_type_target, CRM_OPERATION_PING); cl_free(msg_type_target); FNRET(root_xml_node); } static uint ref_counter = 0; const 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; FNIN(); 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); - char *since_epoch = (char*)cl_malloc(reference_len*(sizeof(char))); + since_epoch = (char*)cl_malloc(reference_len*(sizeof(char))); FNIN(); sprintf(since_epoch, "%s-%s-%ld-%u", local_cust1, local_cust2, (unsigned long)time(NULL), ref_counter++); FNRET(since_epoch); } xmlNodePtr validate_crm_message(xmlNodePtr root_xml_node, const char *sys, const char *uuid, const char *msg_type) { const char *from = NULL; const char *to = NULL; const char *type = NULL; const char *crm_msg_reference = NULL; xmlNodePtr action = NULL; + const char *true_sys; FNIN(); if (root_xml_node == NULL) FNRET(NULL); from = xmlGetProp(root_xml_node, XML_ATTR_SYSFROM); to = xmlGetProp(root_xml_node, XML_ATTR_SYSTO); type = xmlGetProp(root_xml_node, XML_ATTR_MSGTYPE); crm_msg_reference = xmlGetProp(root_xml_node, XML_ATTR_REFERENCE); /* cl_log(LOG_DEBUG, "Recieved XML message with (version=%s)", xmlGetProp(root_xml_node, XML_ATTR_VERSION)); cl_log(LOG_DEBUG, "Recieved XML message with (from=%s)", from); cl_log(LOG_DEBUG, "Recieved XML message with (to=%s)" , to); cl_log(LOG_DEBUG, "Recieved XML message with (type=%s)", type); cl_log(LOG_DEBUG, "Recieved XML message with (ref=%s)" , crm_msg_reference); */ action = root_xml_node; - const char *true_sys = sys; + true_sys = sys; + if (uuid != NULL) true_sys = generate_hash_key(sys, uuid); if (to == NULL) { cl_log(LOG_INFO, "No sub-system defined."); action = NULL; } else if (true_sys != NULL && strcmp(to, true_sys) != 0) { cl_log(LOG_DEBUG, "The message is not for this sub-system (%s != %s).", to, true_sys); action = NULL; } if (type == NULL) { cl_log(LOG_INFO, "No message type defined."); FNRET(NULL); } else if (msg_type != NULL && strcmp(msg_type, type) != 0) { cl_log(LOG_INFO, "Expecting a (%s) message but receieved a (%s).", msg_type, type); action = NULL; } if (crm_msg_reference == NULL) { cl_log(LOG_INFO, "No message crm_msg_reference defined."); action = NULL; } /* if(action != NULL) cl_log(LOG_DEBUG, "XML is valid and node with message type (%s) found.", type); cl_log(LOG_DEBUG, "Returning node (%s)", xmlGetNodePath(action)); */ FNRET(action); } gboolean decodeNVpair(const char *srcstring, char separator, char **name, char **value) { - FNIN(); int lpc = 0; + int len = 0; const char *temp = NULL; + FNIN(); + CRM_DEBUG2("Attempting to decode: [%s]", srcstring); if (srcstring != NULL) { - int len = strlen(srcstring); + len = strlen(srcstring); while(lpc < len) { if (srcstring[lpc++] == separator) { *name = (char*)cl_malloc(sizeof(char)*lpc); CRM_DEBUG2("Malloc ok %d", lpc); strncpy(*name, srcstring, lpc-1); CRM_DEBUG2("Strcpy ok %d", lpc-1); (*name)[lpc-1] = '\0'; CRM_DEBUG2("Found token [%s]", *name); // this sucks but as the strtok *is* a bug len = len-lpc+1; *value = (char*)cl_malloc(sizeof(char)*len); CRM_DEBUG2("Malloc ok %d", len); temp = srcstring+lpc; CRM_DEBUG("Doing str copy"); strncpy(*value, temp, len-1); (*value)[len-1] = '\0'; CRM_DEBUG2("Found token [%s]", *value); FNRET(TRUE); } } } *name = NULL; *value = NULL; FNRET(FALSE); } char * generate_hash_key(const char *crm_msg_reference, const char *sys) { - FNIN(); int ref_len = strlen(sys) + strlen(crm_msg_reference) + 2; char *hash_key = (char*)cl_malloc(sizeof(char)*(ref_len)); + + FNIN(); sprintf(hash_key, "%s_%s", sys, crm_msg_reference); hash_key[ref_len-1] = '\0'; cl_log(LOG_INFO, "created hash key: (%s)", hash_key); FNRET(hash_key); } char * generate_hash_value(const char *src_node, const char *src_subsys) { - FNIN(); int ref_len; char *hash_value; + FNIN(); if (src_node == NULL || src_subsys == NULL) { FNRET(NULL); } if (strcmp("dc", src_subsys) == 0) { hash_value = cl_strdup(src_subsys); if (!hash_value) { cl_log(LOG_ERR, "memory allocation failed in " "generate_hash_value()\n"); FNRET(NULL); } FNRET(hash_value); } ref_len = strlen(src_subsys) + strlen(src_node) + 2; hash_value = (char*)cl_malloc(sizeof(char)*(ref_len)); if (!hash_value) { cl_log(LOG_ERR, "memory allocation failed in " "generate_hash_value()\n"); FNRET(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 cl_log(LOG_INFO, "created hash value: (%s)", hash_value); FNRET(hash_value); } gboolean decode_hash_value(gpointer value, char **node, char **subsys) { - FNIN(); char *char_value = (char*)value; int value_len = strlen(char_value); + + FNIN(); cl_log(LOG_INFO, "Decoding hash value: (%s:%d)", char_value, value_len); if (strcmp("dc", (char*)value) == 0) { *node = NULL; *subsys = (char*)cl_strdup(char_value); if (!*subsys) { cl_log(LOG_ERR, "memory allocation failed in " "decode_hash_value()\n"); FNRET(FALSE); } cl_log(LOG_INFO, "Decoded value: (%s:%d)", *subsys, (int)strlen(*subsys)); FNRET(TRUE); } else if (char_value != NULL) { if (decodeNVpair(char_value, '_', node, subsys)) { FNRET(TRUE); } else { *node = NULL; *subsys = NULL; FNRET(FALSE); } } FNRET(FALSE); } void send_hello_message(IPC_Channel *ipc_client, const char *uuid, const char *client_name, const char *major_version, const char *minor_version) { xmlNodePtr hello_node = NULL; FNIN(); if (uuid == NULL || strlen(uuid) == 0 || client_name == NULL || strlen(client_name) == 0 || major_version == NULL || strlen(major_version) == 0 || minor_version == NULL || strlen(minor_version) == 0) { cl_log(LOG_ERR, "Missing fields, Hello message will not be valid."); return; } hello_node = create_xml_node(NULL, "hello"); set_xml_property_copy(hello_node, "major_version", major_version); set_xml_property_copy(hello_node, "minor_version", minor_version); set_xml_property_copy(hello_node, "client_name", client_name); set_xml_property_copy(hello_node, "client_uuid", uuid); send_xmlipc_message(ipc_client, hello_node); free_xml(hello_node); } gboolean process_hello_message(IPC_Message *hello_message, char **uuid, char **client_name, char **major_version, char **minor_version) { + xmlNodePtr hello; + xmlDocPtr hello_doc; + char *local_uuid; + char *local_client_name; + char *local_major_version; + char *local_minor_version; + FNIN(); *uuid = NULL; *client_name = NULL; *major_version = NULL; *minor_version = NULL; if (hello_message == NULL || hello_message->msg_body == NULL) { FNRET(FALSE); } - xmlDocPtr hello_doc = xmlParseMemory( + hello_doc = xmlParseMemory( hello_message->msg_body, strlen(hello_message->msg_body)); if (hello_doc == NULL) { cl_log(LOG_ERR, "Expected a Hello message, Got: %s", (char*)hello_message->msg_body); FNRET(FALSE); } - xmlNodePtr hello = xmlDocGetRootElement(hello_doc); + hello = xmlDocGetRootElement(hello_doc); if (hello == NULL) { FNRET(FALSE); } else if (strcmp("hello", hello->name) != 0) { FNRET(FALSE); } - char *local_uuid = xmlGetProp(hello, "client_uuid"); - char *local_client_name = xmlGetProp(hello, "client_name"); - char *local_major_version = xmlGetProp(hello, "major_version"); - char *local_minor_version = xmlGetProp(hello, "minor_version"); + local_uuid = xmlGetProp(hello, "client_uuid"); + local_client_name = xmlGetProp(hello, "client_name"); + local_major_version = xmlGetProp(hello, "major_version"); + local_minor_version = xmlGetProp(hello, "minor_version"); if (local_uuid == NULL || strlen(local_uuid) == 0) { cl_log(LOG_ERR, "Hello message was not valid (field %s not found): %s", "uuid", (char*)hello_message->msg_body); FNRET(FALSE); } else if (local_client_name==NULL || strlen(local_client_name)==0){ cl_log(LOG_ERR, "Hello message was not valid (field %s not found): %s", "client name", (char*)hello_message->msg_body); FNRET(FALSE); } else if(local_major_version == NULL || strlen(local_major_version) == 0){ cl_log(LOG_ERR, "Hello message was not valid (field %s not found): %s", "major version", (char*)hello_message->msg_body); FNRET(FALSE); } else if (local_minor_version == NULL || strlen(local_minor_version) == 0){ cl_log(LOG_ERR, "Hello message was not valid (field %s not found): %s", "minor version", (char*)hello_message->msg_body); FNRET(FALSE); } *uuid = cl_strdup(local_uuid); *client_name = cl_strdup(local_client_name); *major_version = cl_strdup(local_major_version); *minor_version = cl_strdup(local_minor_version); FNRET(TRUE); } gboolean forward_ipc_request(IPC_Channel *ipc_channel, xmlNodePtr xml_request, xmlNodePtr xml_response_data, const char *sys_to, const char *sys_from) { - FNIN(); gboolean was_sent = FALSE; - xmlNodePtr forward = create_forward(xml_request, + xmlNodePtr forward; + + FNIN(); + forward = create_forward(xml_request, xml_response_data, sys_to); if (forward != NULL) { was_sent = send_xmlipc_message(ipc_channel, forward); free_xml(forward); } FNRET(was_sent); } /* * This method adds a copy of xml_response_data */ gboolean send_ipc_request(IPC_Channel *ipc_channel, xmlNodePtr msg_options, xmlNodePtr msg_data, const char *host_to, const char *sys_to, const char *sys_from, const char *uuid_from, const char *crm_msg_reference) { gboolean was_sent = FALSE; xmlNodePtr request = NULL; FNIN(); request = create_request(msg_options, msg_data, host_to, sys_to, sys_from, uuid_from, crm_msg_reference); // xml_message_debug(request, "Final request..."); was_sent = send_xmlipc_message(ipc_channel, request); free_xml(request); FNRET(was_sent); } /* * This method adds a copy of xml_response_data */ gboolean send_ha_request(ll_cluster_t *hb_fd, xmlNodePtr msg_options, xmlNodePtr msg_data, const char *host_to, const char *sys_to, const char *sys_from, const char *uuid_from, const char *crm_msg_reference) { gboolean was_sent = FALSE; xmlNodePtr request = NULL; FNIN(); request = create_request(msg_options, msg_data, host_to, sys_to, sys_from, uuid_from, crm_msg_reference); // xml_message_debug(request, "Final request..."); was_sent = send_xmlha_message(hb_fd, request); free_xml(request); FNRET(was_sent); } xmlNodePtr create_request(xmlNodePtr msg_options, xmlNodePtr msg_data, const char *host_to, const char *sys_to, const char *sys_from, const char *uuid_from, const char *crm_msg_reference) { const char *true_from = sys_from; + xmlNodePtr request; + FNIN(); if (uuid_from != NULL) true_from = generate_hash_key(sys_from, uuid_from); // else make sure we are internal else { if (strcmp(CRM_SYSTEM_LRMD, sys_from) != 0 && strcmp(CRM_SYSTEM_PENGINE, sys_from) != 0 && strcmp(CRM_SYSTEM_TENGINE, sys_from) != 0 && strcmp(CRM_SYSTEM_DC, sys_from) != 0 && strcmp(CRM_SYSTEM_CRMD, sys_from) != 0) { cl_log(LOG_ERR, "only internal systems can leave uuid_from blank"); FNRET(FALSE); } } if (crm_msg_reference == NULL) { crm_msg_reference = generateReference( xmlGetProp(msg_options,XML_ATTR_OP),sys_from); } // host_from will get set for us if necessary by CRMd when routed - xmlNodePtr request = create_xml_node(NULL, XML_MSG_TAG); + request = create_xml_node(NULL, XML_MSG_TAG); set_node_tstamp(request); set_xml_property_copy(request, XML_ATTR_VERSION, CRM_VERSION); set_xml_property_copy(request, XML_ATTR_MSGTYPE, XML_ATTR_REQUEST); set_xml_property_copy(request, XML_ATTR_SYSTO, sys_to); set_xml_property_copy(request, XML_ATTR_SYSFROM, true_from); set_xml_property_copy(request, XML_ATTR_REFERENCE, crm_msg_reference); if(host_to != NULL && strlen(host_to) > 0) set_xml_property_copy(request, XML_ATTR_HOSTTO, host_to); if (msg_options != NULL) { add_node_copy(request, msg_options); } if (msg_data != NULL) { add_node_copy(request, msg_data); } FNRET(request); } /* * This method adds a copy of xml_response_data */ gboolean send_ipc_reply(IPC_Channel *ipc_channel, xmlNodePtr xml_request, xmlNodePtr xml_response_data) { - FNIN(); gboolean was_sent = FALSE; - xmlNodePtr reply = create_reply(xml_request, xml_response_data); + xmlNodePtr reply; + FNIN(); + + reply = create_reply(xml_request, xml_response_data); // xml_message_debug(reply, "Final reply..."); if (reply != NULL) { was_sent = send_xmlipc_message(ipc_channel, reply); free_xml(reply); } FNRET(was_sent); } // required? or just send to self an let relay_message do its thing? /* * This method adds a copy of xml_response_data */ gboolean send_ha_reply(ll_cluster_t *hb_cluster, xmlNodePtr xml_request, xmlNodePtr xml_response_data) { - FNIN(); gboolean was_sent = FALSE; - xmlNodePtr reply = create_reply(xml_request, xml_response_data); + xmlNodePtr reply; + + FNIN(); + was_sent = FALSE; + reply = create_reply(xml_request, xml_response_data); if (reply != NULL) { was_sent = send_xmlha_message(hb_cluster, reply); free_xml(reply); } FNRET(was_sent); } /* * This method adds a copy of xml_response_data */ xmlNodePtr create_reply(xmlNodePtr original_request, xmlNodePtr xml_response_data) { const char *host_from = NULL; const char *sys_from = NULL; const char *sys_to = NULL; + xmlNodePtr reply; FNIN(); host_from = xmlGetProp(original_request, XML_ATTR_HOSTFROM); sys_from = xmlGetProp(original_request, XML_ATTR_SYSFROM); sys_to = xmlGetProp(original_request, XML_ATTR_SYSTO); - xmlNodePtr reply = create_common_message(original_request, + reply = create_common_message(original_request, xml_response_data); set_xml_property_copy(reply, XML_ATTR_MSGTYPE, XML_ATTR_RESPONSE); /* since this is a reply, we reverse the from and to */ // HOSTTO will be ignored if it is to the DC anyway. if(host_from != NULL && strlen(host_from) > 0) set_xml_property_copy(reply, XML_ATTR_HOSTTO, host_from); set_xml_property_copy(reply, XML_ATTR_SYSTO, sys_from); set_xml_property_copy(reply, XML_ATTR_SYSFROM, sys_to); FNRET(reply); } /* * This method adds a copy of xml_response_data */ xmlNodePtr create_forward(xmlNodePtr original_request, xmlNodePtr xml_response_data, const char *sys_to) { const char *host_from = NULL; const char *host_to = NULL; const char *sys_from = NULL; + xmlNodePtr forward; FNIN(); host_from = xmlGetProp(original_request, XML_ATTR_HOSTFROM); host_to = xmlGetProp(original_request, XML_ATTR_HOSTTO); sys_from = xmlGetProp(original_request, XML_ATTR_SYSFROM); - - xmlNodePtr forward = create_common_message(original_request, + forward = create_common_message(original_request, xml_response_data); set_xml_property_copy(forward, XML_ATTR_MSGTYPE, XML_ATTR_REQUEST); // HOSTTO will be ignored if it is to the DC anyway. if(host_to != NULL && strlen(host_to) > 0) set_xml_property_copy(forward, XML_ATTR_HOSTTO, host_to); if(host_from != NULL) set_xml_property_copy(forward, XML_ATTR_HOSTFROM, host_from); set_xml_property_copy(forward, XML_ATTR_SYSTO, sys_to); set_xml_property_copy(forward, XML_ATTR_SYSFROM, sys_from); FNRET(forward); } xmlNodePtr create_common_message(xmlNodePtr original_request, xmlNodePtr xml_response_data) { - xmlNodePtr options = NULL; const char *crm_msg_reference = NULL; const char *type = NULL; const char *operation = NULL; + xmlNodePtr options = NULL; + xmlNodePtr new_message; FNIN(); crm_msg_reference = xmlGetProp(original_request, XML_ATTR_REFERENCE); type = xmlGetProp(original_request, XML_ATTR_MSGTYPE); operation = xmlGetProp(original_request, XML_ATTR_OP); if (type == NULL) { cl_log(LOG_ERR, "Cannot create new_message," " no message type in original message"); FNRET(NULL); #if 0 } else if (strcmp(XML_ATTR_REQUEST, type) != 0) { cl_log(LOG_ERR, "Cannot create new_message," " original message was not a request"); FNRET(NULL); #endif } - - xmlNodePtr new_message = create_xml_node(NULL, XML_MSG_TAG); + new_message = create_xml_node(NULL, XML_MSG_TAG); set_node_tstamp(new_message); set_xml_property_copy(new_message, XML_ATTR_VERSION, CRM_VERSION); set_xml_property_copy(new_message, XML_ATTR_OP, operation); set_xml_property_copy(new_message, XML_ATTR_REFERENCE, crm_msg_reference); if (xml_response_data != NULL) { add_node_copy(new_message, xml_response_data); } options = find_xml_node(original_request, XML_TAG_OPTIONS); if (options != NULL) { add_node_copy(new_message, options); } FNRET(new_message); } diff --git a/crm/common/xmlutils.c b/crm/common/xmlutils.c index 1400582293..295f2d4374 100644 --- a/crm/common/xmlutils.c +++ b/crm/common/xmlutils.c @@ -1,814 +1,823 @@ -/* $Id: xmlutils.c,v 1.25 2004/04/13 13:26:44 andrew Exp $ */ +/* $Id: xmlutils.c,v 1.26 2004/04/15 00:35:19 msoffen Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include void dump_array(int log_level, const char *message, const char **array, int depth); xmlNodePtr find_xml_node_nested(xmlNodePtr root, const char **search_path, int len) { int j; + xmlNodePtr child; + xmlNodePtr lastMatch; FNIN(); if (root == NULL) { FNRET(NULL); } if(search_path == NULL) { CRM_DEBUG("Will never find NULL :)"); FNRET(NULL); } #ifdef XML_TRACE dump_array(LOG_DEBUG, "Looking for.", search_path, len); #endif - - xmlNodePtr child = root->children, lastMatch = NULL; + child = root->children, lastMatch = NULL; for (j=0; j < len; ++j) { gboolean is_found = FALSE; if (search_path[j] == NULL) { len = j; /* a NULL also means stop searching */ break; } while(child != NULL) { const char * child_name = (const char*)child->name; #ifdef XML_TRACE CRM_DEBUG3("comparing (%s) with (%s).", search_path[j], child->name); #endif if (strcmp(child_name, search_path[j]) == 0) { lastMatch = child; child = lastMatch->children; #ifdef XML_TRACE CRM_DEBUG3("found node (%s) @line (%ld).", search_path[j], xmlGetLineNo(child)); #endif is_found = TRUE; break; } child = child->next; } if (is_found == FALSE) { #ifdef XML_TRACE CRM_DEBUG2( "No more siblings left... %s cannot be found.", search_path[j]); #endif break; } } if (j == len && lastMatch != NULL && strcmp(lastMatch->name, search_path[j-1]) == 0) { #ifdef XML_TRACE CRM_DEBUG2("returning node (%s).", xmlGetNodePath(lastMatch)); #endif FNRET(lastMatch); } dump_array(LOG_WARNING, "Could not find the full path to the node you specified.", search_path, len); cl_log(LOG_WARNING,"Closest point was node (%s).", xmlGetNodePath(lastMatch)); FNRET(NULL); } const char * get_xml_attr(xmlNodePtr parent, const char *node_name, const char *attr_name, gboolean error) { if(node_name == NULL) { // get it from the current node return get_xml_attr_nested(parent, NULL, 0, attr_name, error); } return get_xml_attr_nested(parent, &node_name, 1, attr_name, error); } const char * get_xml_attr_nested(xmlNodePtr parent, const char **node_path, int length, const char *attr_name, gboolean error) { const char *attr_value = NULL; xmlNodePtr attr_parent = NULL; if(parent == NULL) { cl_log(LOG_ERR, "Can not find attribute %s in NULL parent", attr_name); return NULL; } if(attr_name == NULL || strlen(attr_name) == 0) { cl_log(LOG_ERR, "Can not find attribute with no name in %s", xmlGetNodePath(parent)); return NULL; } if(length == 0) { attr_parent = parent; } else { attr_parent = find_xml_node_nested(parent, node_path, length); if(attr_parent == NULL && error) { cl_log(LOG_ERR, "No node at the path you specified."); return NULL; } } attr_value = xmlGetProp(attr_parent, attr_name); if((attr_value == NULL || strlen(attr_value) == 0) && error) { cl_log(LOG_ERR, "No value present for %s at %s", attr_name, xmlGetNodePath(attr_parent)); return NULL; } return attr_value; } xmlNodePtr set_xml_attr(xmlNodePtr parent, const char *node_name, const char *attr_name, const char *attr_value, gboolean create) { if(node_name == NULL) { // set it on the current node return set_xml_attr_nested(parent, NULL, 0, attr_name, attr_value, create); } return set_xml_attr_nested(parent, &node_name, 1, attr_name, attr_value, create); } xmlNodePtr set_xml_attr_nested(xmlNodePtr parent, const char **node_path, int length, const char *attr_name, const char *attr_value, gboolean create) { xmlAttrPtr result = NULL; xmlNodePtr attr_parent = NULL; xmlNodePtr create_parent = NULL; + xmlNodePtr tmp; if(parent == NULL && create == FALSE) { cl_log(LOG_ERR, "Can not set attribute in NULL parent"); return NULL; } if(attr_name == NULL || strlen(attr_name) == 0) { cl_log(LOG_ERR, "Can not set attribute to %s with no name", attr_value); return NULL; } if(length == 0 && parent != NULL) { attr_parent = parent; } else if(length == 0 || node_path == NULL || *node_path == NULL || strlen(*node_path) == 0) { cl_log(LOG_ERR, "Can not create parent to set attribute %s=%s on", attr_name, attr_value); return NULL; } else { attr_parent = find_xml_node_nested(parent, node_path, length); } if(create && attr_parent == NULL) { int j = 0; attr_parent = parent; for (j=0; j < length; ++j) { if (node_path[j] == NULL) { break; } - xmlNodePtr tmp = + tmp = find_xml_node(attr_parent, node_path[j]); if(tmp == NULL) { attr_parent = create_xml_node(attr_parent, node_path[j]); if(j==0) { create_parent = attr_parent; } } else { attr_parent = tmp; } } } else if(attr_parent == NULL) { cl_log(LOG_ERR, "Can not find parent to set attribute on"); return NULL; } result = set_xml_property_copy(attr_parent, attr_name, attr_value); if(result == NULL) { cl_log(LOG_WARNING, "Could not set %s=%s at %s", attr_name, attr_value, xmlGetNodePath(attr_parent)); } if(create_parent != NULL) { return create_parent; } return parent; } xmlNodePtr find_xml_node(xmlNodePtr root, const char * search_path) { if(root == NULL) return NULL; return find_xml_node_nested(root, &search_path, 1); } xmlNodePtr find_entity(xmlNodePtr parent, const char *node_name, const char *id, gboolean siblings) { return find_entity_nested(parent, node_name, NULL, NULL, id, siblings); } xmlNodePtr find_entity_nested(xmlNodePtr parent, const char *node_name, const char *elem_filter_name, const char *elem_filter_value, const char *id, gboolean siblings) { xmlNodePtr child; FNIN(); #ifdef XML_TRACE cl_log(LOG_DEBUG, "Looking for %s elem with id=%s.", node_name, id); #endif while(parent != NULL) { #ifdef XML_TRACE CRM_DEBUG2("examining (%s).", xmlGetNodePath(parent)); #endif child = parent->children; while(child != NULL) { #ifdef XML_TRACE CRM_DEBUG2("looking for (%s) [name].", node_name); #endif if (node_name != NULL && strcmp(child->name, node_name) != 0) { #ifdef XML_TRACE CRM_DEBUG3( "skipping entity (%s=%s) [node_name].", xmlGetNodePath(child), child->name); #endif break; } else if (elem_filter_name != NULL && elem_filter_value != NULL) { const char* child_value = (const char*) xmlGetProp(child, elem_filter_name); #ifdef XML_TRACE cl_log(LOG_DEBUG, "comparing (%s) with (%s) [attr_value].", child_value, elem_filter_value); #endif if (strcmp(child_value, elem_filter_value)) { #ifdef XML_TRACE CRM_DEBUG2("skipping entity (%s) [attr_value].", xmlGetNodePath(child)); #endif break; } } #ifdef XML_TRACE cl_log(LOG_DEBUG, "looking for entity (%s) in %s.", id, xmlGetNodePath(child)); #endif while(child != NULL) { #ifdef XML_TRACE cl_log(LOG_DEBUG, "looking for entity (%s) in %s.", id, xmlGetNodePath(child)); #endif xmlChar *child_id = xmlGetProp(child, "id"); if (child_id == NULL) { cl_log(LOG_CRIT, "Entity (%s) has id=NULL..." "Cib not valid!", xmlGetNodePath(child)); } else if (strcmp(id, child_id) == 0) { #ifdef XML_TRACE CRM_DEBUG2("found entity (%s).", id); #endif FNRET(child); } child = child->next; } } if (siblings == TRUE) { #ifdef XML_TRACE CRM_DEBUG("Nothing yet... checking siblings"); #endif parent = parent->next; } else parent = NULL; } cl_log(LOG_INFO, "Couldnt find anything appropriate for %s elem with id=%s.", node_name, id); FNRET(NULL); } void copy_in_properties(xmlNodePtr target, xmlNodePtr src) { if(src == NULL) { cl_log(LOG_WARNING, "No node to copy properties from"); } else if (src->properties == NULL) { cl_log(LOG_INFO, "No properties to copy"); } else if (target == NULL) { cl_log(LOG_WARNING, "No node to copy properties into"); } else { #ifndef USE_BUGGY_LIBXML xmlAttrPtr prop_iter = NULL; FNIN(); prop_iter = src->properties; while(prop_iter != NULL) { const char *local_prop_name = prop_iter->name; const char *local_prop_value = xmlGetProp(src, local_prop_name); set_xml_property_copy(target, local_prop_name, local_prop_value); prop_iter = prop_iter->next; } #else xmlCopyPropList(target, src->properties); #endif } FNOUT(); } char * dump_xml(xmlNodePtr msg) { FNIN(); FNRET(dump_xml_node(msg, FALSE)); } void xml_message_debug(xmlNodePtr msg, const char *text) { + char *msg_buffer; + FNIN(); if(msg == NULL) { CRM_DEBUG3("%s: %s", text==NULL?"":text,""); FNOUT(); } - char *msg_buffer = dump_xml_node(msg, FALSE); + msg_buffer = dump_xml_node(msg, FALSE); CRM_DEBUG3("%s: %s", text==NULL?"":text, msg_buffer==NULL?"":msg_buffer); cl_free(msg_buffer); FNOUT(); } char * dump_xml_node(xmlNodePtr msg, gboolean whole_doc) { int lpc = 0; int msg_size = -1; - FNIN(); - xmlChar *xml_message = NULL; + xmlBufferPtr xml_buffer; + + FNIN(); if (msg == NULL) FNRET(NULL); xmlInitParser(); if (whole_doc) { if (msg->doc == NULL) { xmlDocPtr foo = xmlNewDoc("1.0"); xmlDocSetRootElement(foo, msg); xmlSetTreeDoc(msg,foo); } xmlDocDumpMemory(msg->doc, &xml_message, &msg_size); } else { #ifdef XML_TRACE CRM_DEBUG2("mem used by xml: %d", xmlMemUsed()); #endif xmlMemoryDump (); - xmlBufferPtr xml_buffer = xmlBufferCreate(); + xml_buffer = xmlBufferCreate(); msg_size = xmlNodeDump(xml_buffer, msg->doc, msg, 0, 0); xml_message = (xmlChar*)cl_strdup(xmlBufferContent(xml_buffer)); xmlBufferFree(xml_buffer); if (!xml_message) { cl_log(LOG_ERR, "memory allocation failed in dump_xml_node()"); } } // HA wont send messages with newlines in them. for(; xml_message != NULL && lpc < msg_size; lpc++) if (xml_message[lpc] == '\n') xml_message[lpc] = ' '; FNRET((char*)xml_message); } xmlNodePtr add_node_copy(xmlNodePtr new_parent, xmlNodePtr xml_node) { xmlNodePtr node_copy = NULL; FNIN(); if(xml_node != NULL && new_parent != NULL) { node_copy = copy_xml_node_recursive(xml_node); xmlAddChild(new_parent, node_copy); } else if(xml_node == NULL) { cl_log(LOG_ERR, "Could not add copy of NULL node"); } else { cl_log(LOG_ERR, "Could not add copy of node to NULL parent"); } FNRET(node_copy); } xmlAttrPtr set_xml_property_copy(xmlNodePtr node, const xmlChar *name, const xmlChar *value) { const char *parent_name = NULL; const char *local_name = NULL; const char *local_value = NULL; xmlAttrPtr ret_value = NULL; FNIN(); if(node != NULL) { parent_name = node->name; } #ifdef XML_TRACE CRM_DEBUG4("[%s] Setting %s to %s", parent_name, name, value); #endif if (name == NULL || strlen(name) <= 0) { ret_value = NULL; } else if(node == NULL) { ret_value = NULL; } else if (value == NULL || strlen(value) <= 0) { ret_value = NULL; xmlUnsetProp(node, local_name); } else { local_value = cl_strdup(value); local_name = cl_strdup(name); ret_value = xmlSetProp(node, local_name, local_value); } FNRET(ret_value); } xmlNodePtr create_xml_node(xmlNodePtr parent, const char *name) { const char *local_name = NULL; const char *parent_name = NULL; xmlNodePtr ret_value = NULL; FNIN(); if (name == NULL || strlen(name) < 1) { ret_value = NULL; } else { local_name = cl_strdup(name); if(parent == NULL) ret_value = xmlNewNode(NULL, local_name); else { parent_name = parent->name; ret_value = xmlNewChild(parent, NULL, local_name, NULL); } } #ifdef XML_TRACE CRM_DEBUG3("Created node [%s [%s]]", parent_name, local_name); #endif FNRET(ret_value); } void unlink_xml_node(xmlNodePtr node) { xmlUnlinkNode(node); /* this helps us with frees and really should be being done by * the library call */ node->doc = NULL; } void free_xml(xmlNodePtr a_node) { FNIN(); if (a_node == NULL) ; // nothing to do else if (a_node->doc != NULL) xmlFreeDoc(a_node->doc); else { /* make sure the node is unlinked first */ xmlUnlinkNode(a_node); #if 0 /* set a new doc, wont delete without one? */ xmlDocPtr foo = xmlNewDoc("1.0"); xmlDocSetRootElement(foo, a_node); xmlSetTreeDoc(a_node,foo); xmlFreeDoc(foo); #else xmlFreeNode(a_node); #endif } FNOUT(); } void set_node_tstamp(xmlNodePtr a_node) { char *since_epoch = (char*)cl_malloc(128*(sizeof(char))); FNIN(); sprintf(since_epoch, "%ld", (unsigned long)time(NULL)); set_xml_property_copy(a_node, XML_ATTR_TSTAMP, since_epoch); cl_free(since_epoch); } xmlNodePtr copy_xml_node_recursive(xmlNodePtr src_node) { #if XML_TRACE const char *local_name = NULL; xmlNodePtr local_node = NULL, node_iter = NULL, local_child = NULL; xmlAttrPtr prop_iter = NULL; FNIN(); if(src_node != NULL && src_node->name != NULL) { local_node = create_xml_node(NULL, src_node->name); prop_iter = src_node->properties; while(prop_iter != NULL) { const char *local_prop_name = prop_iter->name; const char *local_prop_value = xmlGetProp(src_node, local_prop_name); set_xml_property_copy(local_node, local_prop_name, local_prop_value); prop_iter = prop_iter->next; } node_iter = src_node->children; while(node_iter != NULL) { local_child = copy_xml_node_recursive(node_iter); if(local_child != NULL) { xmlAddChild(local_node, local_child); CRM_DEBUG3("Copied node [%s [%s]", local_name, local_child->name); } node_iter = node_iter->next; } CRM_DEBUG2("Returning [%s]", local_node->name); FNRET(local_node); } CRM_DEBUG("Returning null"); FNRET(NULL); #else return xmlCopyNode(src_node, 1); #endif } xmlNodePtr string2xml(const char *input) { char ch = 0; int lpc = 0, input_len = strlen(input); gboolean more = TRUE; gboolean inTag = FALSE; + xmlNodePtr xml_object = NULL; + const char *the_xml; + xmlDocPtr doc; + xmlBufferPtr xml_buffer = xmlBufferCreate(); for(lpc = 0; (lpc < input_len) && more; lpc++) { ch = input[lpc]; switch(ch) { case EOF: case 0: ch = 0; more = FALSE; xmlBufferAdd(xml_buffer, &ch, 1); break; case '>': case '<': inTag = TRUE; if(ch == '>') inTag = FALSE; xmlBufferAdd(xml_buffer, &ch, 1); break; case '\n': case '\t': case ' ': ch = ' '; if(inTag) { xmlBufferAdd(xml_buffer, &ch, 1); } break; default: xmlBufferAdd(xml_buffer, &ch, 1); break; } } - xmlNodePtr xml_object = NULL; - const char *the_xml = xmlBufferContent(xml_buffer); - xmlDocPtr doc = xmlParseMemory(the_xml, strlen(the_xml)); + the_xml = xmlBufferContent(xml_buffer); + doc = xmlParseMemory(the_xml, strlen(the_xml)); if (doc == NULL) { cl_log(LOG_ERR, "Malformed XML [xml=%s]", the_xml); return NULL; } xml_object = xmlDocGetRootElement(doc); xml_message_debug(xml_object, "Created fragment"); return xml_object; } xmlNodePtr file2xml(FILE *input) { char ch = 0; gboolean more = TRUE; gboolean inTag = FALSE; + xmlNodePtr xml_object = NULL; xmlBufferPtr xml_buffer = xmlBufferCreate(); + const char *the_xml; + xmlDocPtr doc; if(input == NULL) { cl_log(LOG_ERR, "File pointer was NULL"); return NULL; } while (more) { ch = fgetc(input); // cl_log(LOG_DEBUG, "Got [%c]", ch); switch(ch) { case EOF: case 0: ch = 0; more = FALSE; xmlBufferAdd(xml_buffer, &ch, 1); break; case '>': case '<': inTag = TRUE; if(ch == '>') inTag = FALSE; xmlBufferAdd(xml_buffer, &ch, 1); break; case '\n': case '\t': case ' ': ch = ' '; if(inTag) { xmlBufferAdd(xml_buffer, &ch, 1); } break; default: xmlBufferAdd(xml_buffer, &ch, 1); break; } } - - xmlNodePtr xml_object = NULL; - const char *the_xml = xmlBufferContent(xml_buffer); - xmlDocPtr doc = xmlParseMemory(the_xml, strlen(the_xml)); + the_xml = xmlBufferContent(xml_buffer); + doc = xmlParseMemory(the_xml, strlen(the_xml)); if (doc == NULL) { cl_log(LOG_ERR, "Malformed XML [xml=%s]", the_xml); return NULL; } xml_object = xmlDocGetRootElement(doc); xml_message_debug(xml_object, "Created fragment"); return xml_object; } void dump_array(int log_level, const char *message, const char **array, int depth) { int j; if(message != NULL) { cl_log(log_level, "%s", message); } cl_log(log_level, "Contents of the array:"); if(array == NULL || array[0] == NULL || depth == 0) { cl_log(log_level, "\t"); } for (j=0; j < depth && array[j] != NULL; j++) { if (array[j] == NULL) break; cl_log(log_level, "\t--> (%s).", array[j]); } } diff --git a/crm/crmd/crmdmain.c b/crm/crmd/crmdmain.c index 722913f142..fd3a9be139 100644 --- a/crm/crmd/crmdmain.c +++ b/crm/crmd/crmdmain.c @@ -1,211 +1,210 @@ -/* $Id: crmdmain.c,v 1.12 2004/03/24 10:18:22 andrew Exp $ */ +/* $Id: crmdmain.c,v 1.13 2004/04/15 00:37:09 msoffen Exp $ */ /* * Copyright (C) 2004 Andrew Beekhof * * 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 - #include #include #include #include #include #include #include #include #include +#include + #include #include #include #include #include #include #include #include #include #include const char* crm_system_name = "crmd"; #include #include #include #include #include #define PID_FILE WORKING_DIR"/crm.pid" #define OPTARGS "skrh" void usage(const char* cmd, int exit_status); int init_start(void); void crmd_hamsg_callback(const struct ha_msg* msg, void* private_data); gboolean crmd_tickle_apphb(gpointer data); GMainLoop* crmd_mainloop = NULL; int main(int argc, char ** argv) { - cl_log_set_entity(crm_system_name); - cl_log_enable_stderr(TRUE); - cl_log_set_facility(LOG_USER); - int req_restart = FALSE; int req_status = FALSE; int req_stop = FALSE; int argerr = 0; int flag; + cl_log_set_entity(crm_system_name); + cl_log_enable_stderr(TRUE); + cl_log_set_facility(LOG_USER); while ((flag = getopt(argc, argv, OPTARGS)) != EOF) { switch(flag) { case 's': /* Status */ req_status = TRUE; break; case 'k': /* Stop (kill) */ req_stop = TRUE; break; case 'r': /* Restart */ req_restart = TRUE; 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 if (req_status){ FNRET(init_status(PID_FILE, crm_system_name)); } if (req_stop){ FNRET(init_stop(PID_FILE)); } if (req_restart) { init_stop(PID_FILE); } FNRET(init_start()); } int init_start(void) { long pid; if ((pid = get_running_pid(PID_FILE, NULL)) > 0) { cl_log(LOG_CRIT, "already running: [pid %ld].", pid); exit(LSB_EXIT_OK); } xmlInitParser(); fsa_state = S_PENDING; enum crmd_fsa_state state = s_crmd_fsa(C_STARTUP, I_STARTUP, NULL); if (state == S_PENDING) { /* Create the mainloop and run it... */ crmd_mainloop = g_main_new(FALSE); cl_log(LOG_INFO, "Starting %s", crm_system_name); #ifdef REALTIME_SUPPORT static int crm_realtime = 1; if (crm_realtime == 1){ cl_enable_realtime(); }else if (crm_realtime == 0){ cl_disable_realtime(); } cl_make_realtime(SCHED_RR, 5, 64, 64); #endif g_main_run(crmd_mainloop); return_to_orig_privs(); } else { cl_log(LOG_ERR, "Startup of CRMd failed. Current state: %s", fsa_state2string(state)); } if (unlink(PID_FILE) == 0) { cl_log(LOG_INFO, "[%s] stopped", crm_system_name); } FNRET(state != S_PENDING); } 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 crmd_tickle_apphb(gpointer data) { char app_instance[APPNAME_LEN]; int rc = 0; sprintf(app_instance, "%s_%ld", crm_system_name, (long)getpid()); rc = apphb_hb(); if (rc < 0) { cl_perror("%s apphb_hb failure", app_instance); exit(3); } return TRUE; }