⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 recoverymgrd.c

📁 linux集群服务器软件代码包
💻 C
📖 第 1 页 / 共 2 页
字号:
                if (client->ch->ch_status == IPC_DISCONNECT) {                        client->deleteme = TRUE;                }else{                        if (!recoverymgr_read_msg(client)) {                                break;                        }                }        }        return !client->deleteme;}/** * Shutdown the connection for this client */voidrecoverymgr_client_remove(gpointer Client){        recoverymgr_client_t* client = Client;        cl_log(LOG_INFO, "recoverymgr_client_remove: client: %ld\n"        ,       (long)client->pid);        if (debug >= DBGMIN) {                cl_log(LOG_DEBUG, "recoverymgr_client_remove: client pid: %ld\n"                ,       (long)client->pid);        }        G_main_del_IPC_Channel(client->source);        g_free(client->appname);        g_free(client->appinst);        memset(client, 0, sizeof(*client));}/** * Selects and calls the appropriate function to handle the message * This is called from the dispatch function for each * message. */static gbooleanrecoverymgr_read_msg(recoverymgr_client_t *client){        struct IPC_MESSAGE*     msg = NULL;        switch (client->ch->ops->recv(client->ch, &msg)) {                case IPC_OK:                recoverymgr_process_msg(client, msg->msg_body, msg->msg_len);                if (msg->msg_done) {                        msg->msg_done(msg);                }                return TRUE;                break;                case IPC_BROKEN:                client->deleteme = TRUE;                return FALSE;                break;                case IPC_FAIL:                return FALSE;                break;        }        return FALSE;}/* * Mappings between commands and strings */struct cmd {        const char *    msg;        gboolean        senderrno;        int             (*fun)(recoverymgr_client_t* client, void* msg, size_t len);};/** */struct cmd    cmds[] ={        {RECOVERYMGR_EVENT, TRUE, recoverymgr_client_event},        {RECOVERYMGR_CONNECT, TRUE, recoverymgr_client_connect},        {RECOVERYMGR_DISCONNECT, TRUE, recoverymgr_client_disconnect},};/** * Process a message from client process  */voidrecoverymgr_process_msg(recoverymgr_client_t* client, void* Msg,  size_t length){        struct recoverymgr_msg *      	msg = Msg;        const int               	sz1     = sizeof(msg->msgtype)-1;        int                     	rc      = EINVAL;        gboolean                	sendrc  = TRUE;        int                     	j;        if (length < sizeof(*msg)) {                return;        }        msg->msgtype[sz1] = EOS;        if (debug >= DBGDETAIL) {                cl_log(LOG_DEBUG, "recoverymgr_process_msg: client: 0x%x"                " type=%s"                ,       GPOINTER_TO_UINT(client)                ,       msg->msgtype);        }        for (j=0; j < DIMOF(cmds); ++j) {                if (strcmp(msg->msgtype, cmds[j].msg) == 0) {                        sendrc = cmds[j].senderrno;                        if (client->appname == NULL                        &&      cmds[j].fun != recoverymgr_client_connect) {                                rc = ESRCH;                                break;                        }                        rc = cmds[j].fun(client, Msg, length);                }        }        if (sendrc) {                if (debug >= DBGMIN) {                        cl_log(LOG_DEBUG, "recoverymgr_process_msg: client: 0x%x"                        " type=%s, rc=%d"                        ,       GPOINTER_TO_UINT(client)                        ,       msg->msgtype, rc);                }                recoverymgr_putrc(client, rc);        }}/** * Send return code from current operation back to client. */static voidrecoverymgr_putrc(recoverymgr_client_t* client, int rc){        client->rc.rc = rc;        if (client->ch->ops->send(client->ch, &client->rcmsg) != IPC_OK) {                client->deleteme = TRUE;        }}/** * This function is called when a client issues a connection message. * It occurs after a connection is established. * * @todo Ensure that the app connecting is appbhd (?) *  * @return EINVAL if message is not a recoverymgr_connectmsg */static intrecoverymgr_client_connect(recoverymgr_client_t *client, void *Msg, size_t length){        struct recoverymgr_connectmsg* 	msg = Msg;        int                     	namelen = -1;        /*uid_t                   	uidlist[1];        gid_t                   	gidlist[1];         IPC_Auth*               	clientauth;*/        if (debug >= DBGDETAIL) {		cl_log(LOG_DEBUG, "recoverymgr_client_connect\n");	}        if (client->appname) {                return EEXIST;        }        if (length < sizeof(*msg)        ||      (namelen = strnlen(msg->appname, sizeof(msg->appname))) < 1        ||      namelen >= (int)sizeof(msg->appname)        ||      strnlen(msg->appinstance, sizeof(msg->appinstance))        >=      sizeof(msg->appinstance)) {                return EINVAL;        }        if (msg->pid < 2 || (CL_KILL(msg->pid, 0) < 0 && errno != EPERM)        ||      (client->ch->farside_pid != msg->pid)) {                return EINVAL;        }        client->pid = msg->pid;#if 0        /* Make sure client is who they claim to be... */        uidlist[0] = msg->uid;        gidlist[0] = msg->gid;        clientauth = ipc_set_auth(uidlist, gidlist, 1, 1);        if (client->ch->ops->verify_auth(client->ch, clientauth) != IPC_OK) {                ipc_destroy_auth(clientauth);                return EINVAL;        }        ipc_destroy_auth(clientauth);#endif         client->appname = g_strdup(msg->appname);        client->appinst = g_strdup(msg->appinstance);        client->uid = msg->uid;        client->gid = msg->gid;        if (debug >= DBGMIN) {                cl_log(LOG_DEBUG                ,       "recoverymgr_client_connect: client: [%s]/[%s] pid %ld"                " (uid,gid) = (%ld,%ld)\n"                ,       client->appname                ,       client->appinst                ,       (long)client->pid                ,       (long)client->uid                ,       (long)client->gid);        }        return 0;}/** *  Client requested disconnect  */static intrecoverymgr_client_disconnect(recoverymgr_client_t* client , void * msg, size_t msgsize){        if (debug >= DBGDETAIL) {		cl_log(LOG_DEBUG, "recoverymgr_client_disconnect\n");	}        client->deleteme=TRUE;        return 0;}/** * This message is received when a client * of apphbd produces an event. *  * This function needs to determine if an action should * be taken, such as restarting the app, etc.  *  * @param client The connected client that sent the message * @param Msg The message * @param msgsize The size of the message  * * @return zero on success; * 	EINVAL if message size is not correct * * @todo Confirm that the client is the apphbd * @todo determine action to take on the given event * */static intrecoverymgr_client_event(recoverymgr_client_t *client, void *Msg, size_t msgsize){	struct recoverymgr_event_msg  	*msg = Msg; 	RecoveryInfo 			*info = NULL;        if (debug >= DBGDETAIL) 	{		cl_log(LOG_CRIT,"recoverymgr_client_event: event=%d\n", msg->event);	}	if (msgsize < sizeof(*msg))	{ 		return EINVAL;	}	/* FINISH HERE  -- confirm that client is the apphbd    	   or at least one that is permitted to request recovery (?)*/		        if (debug >= DBGMIN) {                cl_log(LOG_DEBUG                ,       "recoverymgr_client_event: client: [%s]/[%s] pid [%ld]"                " (uid,gid)(%ld,%ld)"		" message type [%s]"                ,       msg->appname                ,       msg->appinstance                ,       (long)msg->pid                ,       (long)msg->uid                ,       (long)msg->gid		,	msg->msgtype);        }		info = g_hash_table_lookup(scripts, msg->appname);	if (NULL == info)	 	{		cl_log(LOG_INFO, "No script available to recover %s\n", msg->appname);		return 0;	}	if (info->event[msg->event].inuse == FALSE) 	{		cl_log(LOG_INFO,"Script does not handle this event\n");		return 0;	}	        recover_app(info, msg->event);   	return 0;}/** * *@return 0 on success * 	-1  and errno is ENOMEM  */int recover_app(RecoveryInfo *info, int eventindex){	pid_t 	pid;	pid = fork();	if (pid < 0)	{		cl_log(LOG_CRIT,"Failed to fork recovery process\n");		return -1;	}	else if (0 == pid)	{		child_setup_function(info);        	if (debug >= DBGDETAIL) 		{   			cl_log(LOG_INFO, "current euid[%ld]", (long)geteuid());   			cl_log(LOG_INFO, "current egid[%ld]", (long)getegid());			cl_log(LOG_DEBUG,"script = %s\n", info->scriptname);			cl_log(LOG_DEBUG,"args = %s\n", info->event[eventindex].args);		}			if (eventindex > MAXEVENTS) {			eventindex = 0;		} 	 	if (execl(info->scriptname, info->scriptname,			  info->event[eventindex].args, (const char *)NULL) < 0)		{			cl_perror("Failed to exec recovery script for %s\n", info->appname);			_exit(EXIT_FAILURE);		}	}   	return 0;}/** *  Attempts to set the uid and gid of the executing script. * * @param a_user_data A pointer to a RecoveryInfo structure */void child_setup_function(RecoveryInfo *info){	if (info == NULL)   	{        	if (debug >= DBGDETAIL) 		{      			cl_log(LOG_INFO,"Unable to get app data for recovery.\n");		}      		return;   	}   	/* Change both uid, and euid since we are root */	if ( 0 != setgid(info->gid))   	{        	if (debug >= DBGDETAIL) 		{			cl_log(LOG_INFO, "error:[%s]", strerror(errno));      			cl_log(LOG_INFO, "Unable to setgid for recovery of %s\n", info->appname);		}   	}	if ( 0 != setuid(info->uid))   	{        	if (debug >= DBGDETAIL) 		{			cl_log(LOG_INFO, "error:[%s]", strerror(errno));			cl_log(LOG_INFO, "Unable to setuid for recovery of %s\n", info->appname);		}   	}}/** * Used to avoid zombie processes */voidsigchld_handler (int signum){	int pid;  	int status;  	while (1)    	{      		pid = waitpid ((-1), &status, WNOHANG);      		if (pid < 0)       		{          		break;        	}      		if (pid == 0)	        	break;    	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -