📄 recoverymgrd.c
字号:
/* $Id: recoverymgrd.c,v 1.12 2005/02/20 03:02:43 alan Exp $ *//* * Generic Recovery manager implementation * * Copyright (c) 2002 Intel Corporation * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 * * This is a generic implementation of a recovery manager. * For the most basic case, the recovery manager will handle * recovery of an application that misses a heartbeat with the * apphbd. * * The recovery manager plug-in must be loaded by apphbd. * The apphbd will send notifications to the recovery manager via * the recovery manager plug-in. * */#include <portability.h>#include <sys/time.h>#include <stdlib.h>#include <signal.h>#include <stdio.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <sys/types.h>#include <sys/wait.h>#include <apphb.h>#include <clplumbing/cl_log.h>#include <clplumbing/ipc.h>#include <clplumbing/cl_signal.h>#include <clplumbing/longclock.h>#include <clplumbing/Gmain_timeout.h>#include <clplumbing/GSource.h>#include <clplumbing/cl_poll.h>#include <clplumbing/uids.h>#include <clplumbing/recoverymgr_cs.h>#include <clplumbing/lsb_exitcodes.h>#include <clplumbing/coredumps.h>#include <apphb_notify.h>#include <recoverymgr.h>#include "recoverymgrd.h"#include "configfile.h"/* indicates how many milliseconds between heartbeats */#define HBINTERVAL_MSEC 2000#define CONFIG_FILE "./recoverymgrd.conf"#define DEBUG #define DBGMIN 1#define DBGDETAIL 3int debug = 10;const char* cmdname = "recoverymgrd";extern FILE* yyin;/** The main event loop */GMainLoop* mainloop = NULL;GHashTable *scripts; /* location for recovery info */RecoveryInfo *current; /* used for inserting to hash table */int eventindex; int length;/* used for obtaining the basename of the script */char *tempname; void yyerror(const char *str){ fprintf(stderr,"error parsing config file: %s\n", str);}int yywrap(void){ return 1;}static void print_hash(gpointer key, gpointer value, gpointer userdata){ char* key_str = key; char* value_str = value; cl_log(LOG_INFO, "key[%s], value[%s]\n", key_str, value_str);}gbooleanparseConfigFile(const char* conf_file){ gboolean retval = TRUE; scripts = g_hash_table_new(g_str_hash, g_int_equal); if((yyin = fopen(conf_file,"r")) == NULL){ cl_log(LOG_ERR, "Cannot open configure file:[%s]" , conf_file); ; return(FALSE); } if(yyparse()){ retval = FALSE; }; fclose(yyin); if(debug > DBGMIN){ g_hash_table_foreach(scripts, print_hash, NULL); } return retval;}intmain(int argc, char *argv[]){ int rc; int retval = 0; const char* conf_file = CONFIG_FILE; cl_cdtocoredir(); if(argc == 2){ conf_file = argv[1]; }else if(argc > 2){ printf("Usage: %s [config_file]\n", cmdname); exit(LSB_EXIT_NOTCONFIGED); } cl_log_set_entity(argv[0]); cl_log_enable_stderr(TRUE); cl_log_set_facility(LOG_USER); cl_log(LOG_INFO, "Starting %s", argv[0]); signal(SIGCHLD, sigchld_handler); if(parseConfigFile(conf_file) == FALSE){ exit(LSB_EXIT_NOTCONFIGED); }; /* make self a daemon */#ifndef DEBUG daemon(0,0);#else printf("Debug mode -- non daemon\n");#endif /* register with apphbd as a client and send pings */ retval = register_hb(); if (0 != retval) { cl_perror("Error registering -- is apphbd running??"); exit(retval); } create_connection(); /* unregister and shutdown */ rc = apphb_unregister(); if (rc < 0) { cl_perror("apphb_unregister failure"); exit(3); } return 0; }/** * Sends a registration message to the apphbd * and sets the heartbeat interval. * Sets up a callback for sending heartbeats. */int register_hb(void){ int rc; rc = apphb_register("recovery manager", "normal"); if (rc < 0) { cl_perror("registration failure"); return 1; } rc = apphb_setinterval(HBINTERVAL_MSEC); if (rc < 0) { cl_perror("setinterval failure"); return 2; } setup_hb_callback(); return 0;}/** * Sets up apphb_hb as a signal handler for SIGALRM, * then sets up a timer to go off on the * heartbeat interval */int setup_hb_callback(void){ struct itimerval itimerValue; struct itimerval itimerOldValue; signal(SIGALRM, (void (*) (int)) (apphb_hb)); itimerValue.it_interval.tv_sec = 0; itimerValue.it_interval.tv_usec = HBINTERVAL_MSEC; itimerValue.it_value.tv_sec = 0; itimerValue.it_value.tv_usec = HBINTERVAL_MSEC; if (setitimer(ITIMER_REAL, &itimerValue, &itimerOldValue)!=0) { cl_log(LOG_CRIT, "error setting up hb callback"); return 1; } return 0;}/** * *@return non-zero on failure */int create_connection(void){ char path[] = IPC_PATH_ATTR; char commpath[] = RECOVERYMGRSOCKPATH; struct IPC_WAIT_CONNECTION* wconn; GHashTable* wconnattrs; /* Create a "waiting for connection" object */ wconnattrs = g_hash_table_new(g_str_hash, g_str_equal); g_hash_table_insert(wconnattrs, path, commpath); wconn = ipc_wait_conn_constructor(IPC_ANYTYPE, wconnattrs); if (wconn == NULL) { cl_log(LOG_CRIT, "Unable to create wcon of type %s", IPC_ANYTYPE); return 1; } /* Create a source to handle new connection requests */ G_main_add_IPC_WaitConnection(G_PRIORITY_HIGH, wconn , NULL, FALSE, pending_conn_dispatch, wconn, NULL); g_main_set_poll_func(cl_glibpoll); /* Create the mainloop and run it... */ mainloop = g_main_new(FALSE); g_main_run(mainloop); wconn->ops->destroy(wconn); /* free script hash table */ g_hash_table_foreach_remove(scripts, hash_remove_func, NULL); /*unlink(PIDFILE); */ return 0;}/** * Frees memory allocated in the parser for the hash table * contents. * */gbooleanhash_remove_func(gpointer key, gpointer value, gpointer user_data){ if (value) free(value); /* the key is a pointer to value->appname */ return TRUE;}/** * This function is called for every requested connection. * This is where we accept it or not. */static gboolean pending_conn_dispatch(IPC_Channel* src, gpointer user){ if (debug >= DBGMIN) { cl_log(LOG_DEBUG,"received connection request\n"); cl_log(LOG_DEBUG, "recoverymgr dispatch: IPC_channel: 0x%x" " pid=%d" , GPOINTER_TO_UINT(src) , src->farside_pid); } if (src != NULL) { /* This sets up comm channel w/client * Ignoring the result value is OK, because * the client registers itself w/event system. */ (void)recoverymgr_client_new(src); } else { cl_perror("accept_connection failed"); sleep(1); /* WHY IS THIS HERE? */ } return TRUE;}/** * Create new client (we don't know appname or pid yet) . * This is called when a connection is first established. */static recoverymgr_client_t*recoverymgr_client_new(struct IPC_CHANNEL* ch){ recoverymgr_client_t* ret; ret = g_new(recoverymgr_client_t, 1); memset(ret, 0, sizeof(*ret)); ret->appname = NULL; ret->appinst = NULL; ret->ch = ch; ret->pid = 0; ret->deleteme = FALSE; ret->rcmsg.msg_body = &ret->rc; ret->rcmsg.msg_len = sizeof(ret->rc); ret->rcmsg.msg_done = NULL; ret->rcmsg.msg_private = NULL; ret->rc.rc = 0; if (debug >= DBGMIN) { cl_log(LOG_DEBUG, "recoverymgr_client_new: channel: 0x%x" " pid=%d" , GPOINTER_TO_UINT(ch) , ch->farside_pid); } ret->source = G_main_add_IPC_Channel(G_PRIORITY_DEFAULT , ch, FALSE, recoverymgr_dispatch, (gpointer)ret , recoverymgr_client_remove); if (!ret->source) { memset(ret, 0, sizeof(*ret)); ret=NULL; return ret; } return ret;}/** * This function is called for every incoming message on an * existing connection. */static gbooleanrecoverymgr_dispatch(IPC_Channel* src, gpointer Client){ recoverymgr_client_t* client = Client; if (debug >= DBGDETAIL) { cl_log(LOG_DEBUG, "recoverymgr_dispatch: client: %ld" , (long)client->pid); } if (client->ch->ch_status == IPC_DISCONNECT) { client->deleteme = TRUE; return FALSE; } while (!client->deleteme && client->ch->ops->is_message_pending(client->ch)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -