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

📄 raexeclsb.c

📁 在LINUX下实现HA的源代码
💻 C
字号:
/*  * 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 * * File: raexeclsb.c * Author: Sun Jiang Dong <sunjd@cn.ibm.com> * Copyright (c) 2004 International Business Machines * * This code implements the Resource Agent Plugin Module for LSB style. * It's a part of Local Resource Manager. Currently it's used by lrmd only. */#include <portability.h>#include <stdio.h>		#include <string.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/wait.h>#include <glib.h>#include <clplumbing/cl_log.h>#include <pils/plugin.h>#include <lrm/raexec.h>#define PIL_PLUGINTYPE		RA_EXEC_TYPE#define PIL_PLUGIN		lsb#define PIL_PLUGINTYPE_S	"RAExec"#define PIL_PLUGIN_S		"lsb"#define PIL_PLUGINLICENSE	LICENSE_PUBDOM#define PIL_PLUGINLICENSEURL	URL_PUBDOM/* The begin of exported function list */static int execra(const char * ra_name,  		  const char * op,	 	  GHashTable * cmd_params,		  GHashTable * env_params,		  gboolean need_metadata,		  int * call_key);static int post_query_result(int exec_key, int * result, char ** meta_data);/* The end of exported function list *//* The begin of internal used function & data list */#define MAX_PARAMETER_NUM 40 typedef char * RA_ARGV[MAX_PARAMETER_NUM];static GHashTable * post_query_ops = NULL;static int prepare_cmd_parameters(const char * raname, const char * op, 	GHashTable * params, RA_ARGV params_argv);  static void params_hash_to_argv(gpointer key, gpointer value, 				gpointer user_data);static int raexec_setenv(GHashTable * env_params);static int fork_and_execra(const char * ra_name, const char * op, 			RA_ARGV ra_argv, GHashTable * env_params, 			gboolean need_metadata);static int read_pipe(int fd, char ** meta_data);static int * g_intdup(gint value); static void set_env(gpointer key, gpointer value, gpointer user_data);/* The end of internal function & data list *//* Rource agent execution plugin operations */static struct RAExecOps raops ={	execra,	post_query_result};/* * The following two functions are only exported to the plugin infrastructure. *//* * raexec_closepi is called as part of shutting down the plugin. * If there was any global data allocated, or file descriptors opened, etc. * which is associated with the plugin, and not a single interface * in particular, here's our chance to clean it up. */static void raexec_closepi(PILPlugin *pi){	if ( post_query_ops != NULL ) {		g_hash_table_destroy(post_query_ops);	}}/* * raexec_close_intf called as part of shutting down the md5 HBauth interface. * If there was any global data allocated, or file descriptors opened, etc. * which is associated with the md5 implementation, here's our chance * to clean it up. */static PIL_rc raexec_closeintf(PILInterface *pi, void *pd){	return PIL_OK;}PIL_PLUGIN_BOILERPLATE("1.0", Debug, raexec_closepi);static const PILPluginImports*  PluginImports;static PILPlugin*               OurPlugin;static PILInterface*		OurInterface;static void*			OurImports;static void*			interfprivate;/* * Our plugin initialization and registration function * It gets called when the plugin gets loaded. */PIL_rcPIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports* imports);PIL_rcPIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports* imports){	/* Force the compiler to do a little type checking */	(void)(PILPluginInitFun)PIL_PLUGIN_INIT;	PluginImports = imports;	OurPlugin = us;	/* Register ourself as a plugin */	imports->register_plugin(us, &OurPIExports);  	post_query_ops = g_hash_table_new(g_int_hash, g_int_equal);	/*  Register our interfaces */ 	return imports->register_interface(us, PIL_PLUGINTYPE_S,  PIL_PLUGIN_S,			&raops, raexec_closeintf, &OurInterface, &OurImports,		interfprivate); }/* *	Real work starts here ;-) */static int execra( const char * ra_name, const char * op, GHashTable * cmd_params,	GHashTable * env_params, gboolean need_metadata, int * call_key){	RA_ARGV params_argv;	cl_log(LOG_DEBUG, "To execute a RA %s.", ra_name);	/* Prepare the call parameter */	if (0 > prepare_cmd_parameters(ra_name, op, cmd_params, params_argv)) {		cl_log(LOG_ERR, "lsb RA: Error of preparing parameters");		return -1;	}	/* Fork a child and execute the RA */	*call_key = fork_and_execra(ra_name, op, params_argv, env_params, 					need_metadata);	if (*call_key <= 0) {		return -1;	}	else {		return 0;  /* return ok */	}}static intpost_query_result(int exec_key, int * result, char ** meta_data){	int ret;	gpointer org_key, org_value;	gboolean found = FALSE;	if ( post_query_ops == NULL )  {		return -1;	}	found = g_hash_table_lookup_extended(post_query_ops, 			&exec_key, &org_key, &org_value); 			if ( !found ) { 		cl_log(LOG_ERR,"No this child %d need post query.", exec_key);		return -1;	}	ret = waitpid(exec_key, result, WNOHANG);	if ( ret == 0 ) {		cl_log(LOG_DEBUG, "process %d don't exit yet.", exec_key);                /* return at once to avoid remove item in 'post_query_ops' */		return 0;  	}	if ( ret == -1 ) {		cl_log(LOG_ERR, "error when fetching %d  exit status.", 			exec_key);	}	if ((ret > 0) && (*(int*)org_value > 0) && ( meta_data != NULL )) {		read_pipe(*(int*)org_value, meta_data);	}	g_free(org_key);	g_free(org_value);	g_hash_table_remove(post_query_ops, &exec_key);		return ret;}static int prepare_cmd_parameters(const char * raname, const char * op, 			GHashTable * params_ht, RA_ARGV params_argv){	/* For lsb init scripts, no corresponding definite specification	 * But for lsb none-init scripts, maybe need it.	 */ 	int ht_size = 0;	int tmp_len;	if (params_ht) {		ht_size = g_hash_table_size(params_ht);	}	if ( ht_size+3 > MAX_PARAMETER_NUM ) {		cl_log(LOG_ERR, "Too many parameters");		return -1;	}		tmp_len = strnlen(raname, 160) + 1;	params_argv[0] = g_new(gchar, tmp_len); 	strncpy(params_argv[0], raname, tmp_len);	tmp_len = strnlen(op, 160) + 1;	params_argv[1] = g_new(gchar, tmp_len); 	strncpy(params_argv[1], op, tmp_len);	params_argv[ht_size+2] = NULL; 		if (params_ht) {		g_hash_table_foreach(params_ht, 				params_hash_to_argv, params_argv);	}	return 0;}static voidparams_hash_to_argv(gpointer key, gpointer value, gpointer user_data){	int param_index;        RA_ARGV * ra_argv  = user_data;        if (*ra_argv == NULL ) {                return;        }	/* the parameter index start from 1 */	/* and start from 2 in argv array */	param_index = atoi((char *)key);	(*ra_argv)[param_index + 1] = g_new(gchar, 21);	*((*ra_argv)[param_index + 1] + 20) = '\0';        strncpy((*ra_argv)[param_index +1], (char*)value,                strnlen((char*)value, 20));}static int raexec_setenv(GHashTable * env_params){	/* For lsb init scripts, no corresponding definite specification	 * But for lsb none-init scripts, maybe need it.	 */         if (env_params) {        	g_hash_table_foreach(env_params, set_env, NULL);        }        return 0;}static voidset_env(gpointer key, gpointer value, gpointer user_data){        setenv((const char *)key, (const char *)value, 1);        /*Need to free the memory to which key and value point?*/}/* Possible bug for pipe using ??  */static int fork_and_execra(const char * ra_name, const char * op, RA_ARGV ra_argv,		GHashTable * env_params, gboolean need_metadata){	int cpid;	int fd[2];		cl_log(LOG_DEBUG, "Will to execute RA %s.", ra_name);	if (need_metadata == TRUE) {		if ( pipe(fd) < 0 ) {			cl_log(LOG_ERR,"pipe create error when to execute %s.",				 ra_name);			return -1;		}	}	if ( (cpid=fork()) < 0 ) {		cl_log(LOG_ERR, "Fork failed when to execute %s.", ra_name);		return -1;	}	if ( cpid > 0 ) {		/* In parent process */		/* close write fd */		if ( need_metadata == TRUE ) {			close(fd[1]);			g_hash_table_insert(post_query_ops, 				g_intdup(cpid), g_intdup(fd[0]));		} else {			g_hash_table_insert(post_query_ops, 				g_intdup(cpid), g_intdup(0));		}		return cpid;	} else {		/* in child process */		/* close read fd */		cl_log(LOG_DEBUG, "In forked child %d.", getpid());		if ( need_metadata == TRUE ) {			close(fd[0]);			if ( fd[1] != STDOUT_FILENO ) {				if (dup2(fd[1], STDOUT_FILENO)!=STDOUT_FILENO) {					cl_log(LOG_ERR,"dup2 error when to "\						"execute RA.");					exit(-1);				}			}			close(fd[1]);		}	/* For lsb init scripts, no corresponding definite specification	 * Not set calling parameterscl. But for lsb none-init scripts,	 * should need	 */		raexec_setenv(env_params);		if ( execv(ra_name, ra_argv) < 0 ) {			cl_log(LOG_ERR, "execl error when to execute RA %s.", 				ra_name);		}		exit(-1);     	} }static intread_pipe(int fd, char ** meta_data){	const int BUFFLEN = 81;	char buffer[BUFFLEN];	int readlen;	GString * gstr_tmp;	*meta_data = NULL;	gstr_tmp = g_string_new("");	do {		memset(buffer, 0, BUFFLEN);		readlen = read(fd, buffer, BUFFLEN - 1);		if ( readlen > 0 ) {			g_string_append(gstr_tmp, buffer);		}	} while (readlen == BUFFLEN - 1); 	close(fd);	if (readlen < 0) {		cl_log(LOG_ERR, "read pipe error when execute RA."); 		return -1;	}	if ( gstr_tmp->len == 0 ) {		cl_log(LOG_INFO, "read 0 byte from this pipe when execute RA."); 		return 0;	}	*meta_data = malloc(gstr_tmp->len + 1);	if ( *meta_data == NULL ) {		cl_log(LOG_ERR, "malloc error in read_pipe.");		return -1;	} 	(*meta_data)[0] = '\0'; 	(*meta_data)[gstr_tmp->len] = '\0'; 	strncpy(*meta_data, gstr_tmp->str, gstr_tmp->len);	g_string_free(gstr_tmp, TRUE);		return 0;}static int * g_intdup(gint value){	gint * tmp;	tmp = g_new(gint, 1);	*tmp = value;	return tmp;}

⌨️ 快捷键说明

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