/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* */ /* */ /* Licensed Materials - Property of IBM */ /* */ /* (C) COPYRIGHT International Business Machines Corp. 1996,2019 */ /* All Rights Reserved */ /* */ /* US Government Users Restricted Rights - Use, duplication or */ /* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /* */ /* IBM_PROLOG_END_TAG */ /*===========================================================================*/ /* @(#)43 1.9 src/rsct/pem/emtools/rmapi_samples/rmapi_smpdae.c, emtools, rsct_rady, rady2035a 6/5/98 11:25:36 */ #include #include #include #include #include #include #include #include #include /* * rmapi_smpdae.c * * This program presents an example of using the Resource Monitor Application * Programming Interface (RMAPI). The configuration data for this monitor * is in the file RmapiSample.loadsdr. This monitor is an example of server * monitor (Resource Monitor Managers connect to the monitor) function that * could be incorporated into a daemon or subsystem. * * Event Management objects defined for this monitor: * * Monitor: * IBM.PSSP.SampleDaeMon # server monitor definition * * Class: * IBM.PSSP.SampleDaeClass # variable class * * Variables: * IBM.PSSP.SampleDaeMon.StaticVars.static_var1 # valuetype quantity, datatype long * Resource Identifiers: NodeNum # used as locator field of var * IBM.PSSP.SampleDaeMon.StaticVars.static_var2 # valuetype quantity, datatype long * Resource Identifiers: NodeNum # used as locator field of var * IBM.PSSP.SampleDaeMon.StaticVars.static_var3 # valuetype quantity, datatype long * Resource Identifiers: NodeNum # used as locator field of var * IBM.PSSP.SampleDaeMon.InstVars.inst_var1 # valuetype quantity, datatype long * Resource Identifiers: NodeNum # used as locator field of var * Name # instance name of the resource * IBM.PSSP.SampleDaeMon.InstVars.inst_var2 # valuetype quantity, datatype long * Resource Identifiers: NodeNum # used as locator field of var * Name # instance name of the resource * * What this monitor does: rmapi_smpdae provides an example of a server monitor * that has 3 non-instantiable and 2 instantiable Quantity variables which * are updated with random values on a fixed interval defined in the variable class. * When the monitor is started, it creates and registers the static and 1 set of the * instantiable variables. To further demonstrate instantiation, new instances are * created and registered on the 5th and 12th call to the function send_values(). * * The monitor will continue executing, adding/deleting and sending values for the * variables as requested by control messages sent from the Event Management daemon * through the RMAPI. This monitor uses select notification protocol to determine when a * connection is ready to accept on the server socket created by ha_rr_makserv() or * when a message is ready to be read through the RMAPI from one of the monitor's * client sessions. * * The monitor ends execution when it receives a terminating signal, or when all * all clients have closed their connections. * * This program also provides an example of executing multiple copies of a resource * monitor at the same time. The monitor may be started from the command line, and is * not configured to be started by resource monitor managers. The following command * line arguments may be used when starting the monitor: * * -i Optional: start the requested number of monitor copies, * where is in the range 1 - HA_RR_RM_INSTID_MAX. * -h Displays command line help. * -H Optional: Specifies the name of the HACMP domain the * monitor is to execute in. * -S Optional: Specifies the name of the SP domain (system * partition name) the monitor is to execute in. * * The [-H, -S] options are mutually exclusive. If neither is supplied, the monitor * will assume it is executing in the default system partition of a SP environment. * * The static variables are intended to represent global values which are common * to all instances of the resource being monitored. Since by definition only one * instance of the each static variable may exist on a node, they are supplied only * by the resource monitor whose monitor instance id is 0. This ensures that they are * available for both performance and event monitoring. Each monitor copy contrives * unique values for the Name resource ID element of the instantiable variables. * The intention is to provide an example of multiple copies of a monitor, each * monitoring a set of instances of the same resource. * * Examples: * * # rmapi_smpdae * - Will start one copy of the monitor in the default system partition of the * local SP node. * * # rmapi_smpdae -i 4 -P x10s * - Will start four copies of the monitor which will execute in the system * partition named "x10s" on the local SP node. * * This program can be compiled with the following command: * * cc -O rmapi_smpdae.c -o rmapi_smpdae -lha_rr */ /* local defines PROGNAME - Name of this program. MAX_INTERVAL - Max number of seconds before ha_rr_send_value or ha_rr_touch must be called. RESOURCE_MONITOR_NAME - Name of this monitor as defined in the config data. MONITOR_CLASS_NAME - Class name as defined in the config data. SOCKET_TABLE_SIZE - HA_RR_MAX_SESSIONS + 1 for the RMAPI server socket. RMAPI_SERVER_INDEX - Index in the socket call table for the RMAPI server socket. STATIC_VAR_NAME_PREFIX - Common portion of the static vars as defined in the config data. INST_VAR_NAME_PREFIX - Common portion of the inst vars as defined in the config data. INST_VAR_RESID_FORMAT - Resource ID format for instantiable vars. INITIAL_VALUE - Variable initial value used on ha_rr_add_var(). MAX_VALUE - Maximum variable value. NUM_STATIC_VARS - Number of static variables defined for monitor. NUM_INST_VARS - Number of instantiable variables defined for monitor. */ #define PROGNAME "rmapi_smpdae" #define MAX_INTERVAL 500 #define RESOURCE_MONITOR_NAME "IBM.PSSP.SampleDaeMon" #define MONITOR_CLASS_NAME "IBM.PSSP.SampleDaeClass" #define SOCKET_TABLE_SIZE (HA_RR_MAX_SESSIONS + 1) #define RMAPI_SERVER_INDEX (HA_RR_MAX_SESSIONS) #define STATIC_VAR_NAME_PREFIX "IBM.PSSP.SampleDaeMon.StaticVars.static_var" #define INST_VAR_NAME_PREFIX "IBM.PSSP.SampleDaeMon.InstVars.inst_var" #define INST_VAR_RESID_FORMAT "InstName=Resource%d" #define INITIAL_VALUE 10 #define MAX_VALUE 500 #define NUM_STATIC_VARS 3 #define NUM_INST_VARS 2 /* local structs */ struct sock_table_entry { int socket_fd; /* fd for manager session or RMAPI server socket. */ void (*sock_funcp)(int); /* function to be called for this socket fd. */ }; struct local_vars { char var_name[128]; /* Variable name (as in the CDB). */ char var_resid[32]; /* Qualified resource ID (for instantiable variables). */ long value; /* variables value. */ void *var_handle; /* place for RMAPI to store the var handle. */ }; /* local functions */ void display_rmapi_err(struct ha_em_err_blk *errblk); void server_socket_handler(int table_index); void session_socket_handler(int table_index); void end_session(int table_index); void register_variables(); void add_variables(int sock_fd, struct ha_rr_ctrl_msg *ctrl_msg); void del_variables(int sock_fd, struct ha_rr_ctrl_msg *ctrl_msg); void send_values(); void control_loop(); void set_signals(); void catch_alrm_signal(int); void catch_exit_signal(int); void mon_exit(int); /* globals */ int NumMgrs = 0; /* number of resource managers connected. */ struct ha_rr_variable *Variables = (struct ha_rr_variable *)0; /* RMAPI variable array. */ struct ha_rr_val *Values = (struct ha_rr_val *)0; /* RMAPI value array. */ struct sock_table_entry SocketTable[SOCKET_TABLE_SIZE]; /* RMAPI server and session sockets. */ struct ha_em_err_blk ErrBlock; /* global error block for RMAPI calls. */ struct local_vars *LocalVars = (struct local_vars *)0; /* array of local variables. */ static sigset_t SignalMask; /* mask for signals. */ timer_t IntervalTimerId; /* ID for var update interval timer. */ int Interval; /* Update interval for this monitor. */ int SampleTime = 0; /* flag set by interval alrm sig. */ int Terminate = 0; /* flag set by terminate signal. */ int SigCaught = 0; /* signal caught by term. */ int TimeOut = MAX_INTERVAL; /* time out counter to call ha_rr_touch. */ int NumVariables = 0; /* Number of variables in arrays. */ int MonitorInstanceID; /* Instance ID of the running monitor */ int Pid; /* resource monitor process id. */ char DomainHACMP[] = "HA_DOMAIN_TYPE=HACMP"; /* string for HACMP domain type. */ char DomainSP[] = "HA_DOMAIN_TYPE=SP"; /* string for HACMP domain type. */ int RmapiInit = 0; /* flag to inidicate RMAPI initialized */ /******************************************************************************/ /* Main - Main - Main - Main - Main - Main - Main - Main - Main - Main - Main */ /******************************************************************************/ main(int argc, char **argv) { int c, i, rc; int num_rm_insts = 1; struct itimerstruc_t itimer; char *domain_name = NULL, *domain_type = NULL, *bp; struct ha_rr_args rr_args; while ((c = getopt(argc, argv, "i:hH:S:")) != EOF) { switch (c) { case 'i': num_rm_insts = atoi(optarg); if ((num_rm_insts < 1) || (num_rm_insts > HA_RR_RM_INSTID_MAX)) { fprintf(stderr, "%s(%d): Invalid number of monitor instances, %d. " "Allowable 1-%d.\n", PROGNAME,Pid,num_rm_insts,HA_RR_RM_INSTID_MAX); mon_exit(1); } break; case 'H': if (domain_name != NULL) { fprintf(stderr, "%s(%d): Specify either the -S or -H options once.\n", PROGNAME,Pid); mon_exit(1); } domain_name = optarg; domain_type = DomainHACMP; break; case 'S': if (domain_name != NULL) { fprintf(stderr, "%s(%d): Specify either the -S or -H options once.\n", PROGNAME,Pid); mon_exit(1); } domain_name = optarg; domain_type = DomainSP; break; case 'h': default: fprintf(stdout, "Usage:\t%s [-h] [-i number] [-H domain_name | -S domain_name]\n" "\t\t-h\tDisplays this help message\n" "\t\t-i\tCreate the number of monitor instances specified\n" "\t\t-H\tUse the HACMP domain name\n" "\t\t-S\tUse the SP domain name\n", PROGNAME); exit(0); } } Pid = getpid(); fprintf(stdout,"%s(%d): %s resource monitor started. %d instance(s) of the monitor requested.\n", PROGNAME,Pid,RESOURCE_MONITOR_NAME,num_rm_insts); /* * Set up the domain type and name environment variables (if * supplied on the command line). Make the default domain * type "SP". */ if (domain_type == NULL) domain_type = DomainSP; if (putenv(domain_type)) { fprintf(stderr, "%s(%d): putenv() failed, errno=%d.\n",PROGNAME,Pid,errno); mon_exit(1); } if (domain_name != NULL) { bp = (char *)malloc(strlen(domain_name) + strlen("HA_DOMAIN_NAME=") + 1); if (bp == NULL) { fprintf(stderr, "%s(%d): malloc() failed.\n",PROGNAME,Pid); mon_exit(1); } sprintf(bp,"HA_DOMAIN_NAME=%s",domain_name); if (putenv(bp)) { fprintf(stderr, "%s(%d): putenv() failed, errno=%d.\n",PROGNAME,Pid,errno); mon_exit(1); } } fprintf(stdout, "%s(%d): Resource monitor environment: DomainType=%s DomainName=%s.\n", PROGNAME,Pid,getenv("HA_DOMAIN_TYPE"),getenv("HA_DOMAIN_NAME")); /* * Setup signal handlers. */ set_signals(); /* * Initialize the socket table. Socket file descriptors are initialized to -1. */ for (i=0;i 1 ? HA_RR_RM_INSTID_ANY : 0; rc = ha_rr_rm_ctl(&rr_args,HA_RR_RM_ARGS_SET_INSTID,&ErrBlock); if (rc == HA_RR_FAIL) { display_rmapi_err(&ErrBlock); mon_exit(1); } fflush(stdout); if (num_rm_insts > 1) { /* * fork() multiple copies of the monitor. */ for (i=0;i 0) { /* * Child RM, break from the loop. */ break; } } } Pid = getpid(); /* * Initialize the RMAPI. */ rc = ha_rr_init(RESOURCE_MONITOR_NAME, &ErrBlock); if (rc == HA_RR_FAIL) { display_rmapi_err(&ErrBlock); mon_exit(1); } RmapiInit = 1; /* * Query and report the monitor instance number and domain name. */ rc = ha_rr_rm_ctl(&rr_args,HA_RR_RM_ARGS_GET,&ErrBlock); if (rc == HA_RR_FAIL) { display_rmapi_err(&ErrBlock); mon_exit(1); } MonitorInstanceID = rr_args.rr_instance_id; fprintf(stdout,"%s(%d): Resource monitor instance id=%d domain=%s.\n", PROGNAME,Pid,rr_args.rr_instance_id,rr_args.rr_domain_name); /* * Query the update interval from the RMAPI. */ Interval = ha_rr_get_interval(MONITOR_CLASS_NAME,&ErrBlock); if (Interval == HA_RR_FAIL) { display_rmapi_err(&ErrBlock); mon_exit(1); } fprintf(stdout,"%s(%d): Interval for class %s is %d.\n", PROGNAME,Pid,MONITOR_CLASS_NAME,Interval); /* * Register variables with the RMAPI */ register_variables(); /* * Make this Resource Monitor a server. */ rc = SocketTable[RMAPI_SERVER_INDEX].socket_fd = ha_rr_makserv(HA_RR_NOTIFY_SELECT, &ErrBlock); if (rc == HA_RR_FAIL) { display_rmapi_err(&ErrBlock); mon_exit(1); } fprintf(stdout,"%s(%d): Assigned RMAPI server socket_fd(%d) to table index(%d).\n", PROGNAME,Pid,rc,RMAPI_SERVER_INDEX); /* * Set up sampling timer. */ IntervalTimerId = gettimerid(TIMERID_REAL, DELIVERY_SIGNALS); itimer.it_value.tv_sec = Interval; itimer.it_value.tv_nsec = 0; itimer.it_interval.tv_sec = Interval; itimer.it_interval.tv_nsec = 0; if (incinterval(IntervalTimerId, &itimer, (struct itimerstruc_t *)0) < 0) { fprintf(stderr,"%s(%d): incinterval() failed with errno=%d.\n", PROGNAME,Pid,errno); mon_exit(1); } /* * Start the control loop - should never return. */ control_loop(); /* * Should never get here. */ mon_exit(0); } /* * Sets the signal handlers. */ void set_signals() { struct sigaction sigactn; sigemptyset(&SignalMask); sigaddset(&SignalMask, SIGALRM); sigaddset(&SignalMask, SIGTERM); /* * SIGALRM caught on the interval boundary. * Handler sets a global flag to do sampling. */ sigactn.sa_handler = catch_alrm_signal; sigactn.sa_mask = SignalMask; sigactn.sa_flags = 0; if (sigaction(SIGALRM, &sigactn, (struct sigaction *)0) < 0) { fprintf(stderr,"%s(%d): sigaction() failed for ALRM signal. errno=%d.\n", PROGNAME,Pid,errno); mon_exit(1); } /* * Need terminate handler to cleanup RMAPI on exit. */ sigactn.sa_handler = catch_exit_signal; sigactn.sa_mask = SignalMask; sigactn.sa_flags = 0; if (sigaction(SIGTERM, &sigactn, (struct sigaction *)0) < 0) { fprintf(stderr,"%s(%d): sigaction() failed for TERM signal. errno=%d.\n", PROGNAME,Pid,errno); mon_exit(1); } /* * Set signal mask, i.e. block SIGALRM, SIGTERM */ if (sigprocmask(SIG_SETMASK, &SignalMask, (sigset_t *)0) < 0) { fprintf(stderr,"%s(%d): sigprocmask() failed. errno=%d.\n",PROGNAME,Pid,errno); mon_exit(1); } } /* * Sends new values to the RMAPI - called when SIGALRM is caught. */ void send_values() { int i, rc; int num_vals_to_send = 0; static int times_called = 0; times_called++; for (i=0;i= 0);i++); if (i < HA_RR_MAX_SESSIONS) { /* * Save the mgr socket fd returned by the RMAPI. * The socket function was initialized in main. */ SocketTable[i].socket_fd = mgr_sock; NumMgrs++; fprintf(stdout,"%s(%d): New session accepted to index(%d) socket_fd(%d).\n", PROGNAME,Pid,i,mgr_sock); } else { /* * Should never get here, RMAPI handles too many sessions. */ rc = ha_rr_end_session(mgr_sock,&ErrBlock); } } /* * Handles a message being received from the manager session * specified by [table_index]. Called following select. */ void session_socket_handler(int table_index) { int rc, session_sock; struct ha_rr_ctrl_msg *ctrl_msg; /* * Get the socket file descriptor for this session. */ if ((session_sock = SocketTable[table_index].socket_fd) < 0) { return; } /* * Call ha_rr_get_ctrl_msg to read the command from the manager. */ fprintf(stdout,"%s(%d): Calling ha_rr_get_ctrlmsg for session(%d) socket_fd(%d).\n", PROGNAME,Pid,table_index,session_sock); rc = ha_rr_get_ctrlmsg(session_sock, &ctrl_msg, &ErrBlock); if (rc == 0) { /* * Message was for the RMAPI or was incomplete. */ return; } if (rc == HA_RR_FAIL) { display_rmapi_err(&ErrBlock); if (ErrBlock.em_errno == HA_RR_EDISCONNECT) { end_session(table_index); } else if (ErrBlock.em_errno != HA_RR_EAGAIN) { /* * Severe RMAPI error. */ mon_exit(1); } return; } switch (ctrl_msg->rr_ctrl_cmd) { case HA_RR_CMD_ADDALL : case HA_RR_CMD_ADDV : add_variables(table_index,ctrl_msg); break; case HA_RR_CMD_DELALL : case HA_RR_CMD_DELV : del_variables(table_index,ctrl_msg); break; default : /* * Unknown or unsupported msg - ignore it. */ fprintf(stderr,"%s(%d): Received an unexpected cmd(%d) from socket_fd(%d), ignoring...\n", PROGNAME,Pid,ctrl_msg->rr_ctrl_cmd,session_sock); break; } /* * Free the message allocated by the RMAPI. */ free(ctrl_msg); } /* * Adds the variables referenced in the control message to * the manager session specified by [table_index]. */ void add_variables(int table_index, struct ha_rr_ctrl_msg *ctrl_msg) { int i; int sock_fd; int inst_id; int num_added, num_to_add = 0; sock_fd = SocketTable[table_index].socket_fd; switch (ctrl_msg->rr_ctrl_cmd) { case HA_RR_CMD_ADDALL : /* * Add all variables to this manager session. */ fprintf(stdout,"%s(%d): Processing cmd HA_RR_CMD_ADDALL to add all variables to session_fd %d.\n", PROGNAME,Pid,sock_fd); for (i=0;irr_ctrl_num_vars,sock_fd); for (i=0;i < ctrl_msg->rr_ctrl_num_vars;i++) { /* * The inst id field in the ctrl message is * the index into the LocalVars array. */ inst_id = ctrl_msg->rr_ctrlv.rr_ctrl_vari[i]; if (inst_id < NumVariables) { /* * Copy the variable to the next RMAPI structure. */ Variables[num_to_add].rr_var_name = LocalVars[inst_id].var_name; Variables[num_to_add].rr_var_rsrc_ID = LocalVars[inst_id].var_resid; Variables[num_to_add].rr_varu.rr_var_hndl = &(LocalVars[inst_id].var_handle); Variables[num_to_add].rr_value = &(LocalVars[inst_id].value); num_to_add++; } } break; default : break; } if (num_to_add) { /* * Add the variables by calling ha_rr_add_var. */ num_added = ha_rr_add_var(sock_fd, Variables, num_to_add, 1, &ErrBlock); if (num_added == HA_RR_FAIL) { display_rmapi_err(&ErrBlock); if (ErrBlock.em_errno == HA_RR_EDISCONNECT) { /* * Session closed by manager. */ end_session(table_index); } else { mon_exit(1); } } else { fprintf(stdout,"%s(%d): ha_rr_add_var() added %d vars to session_fd %d.\n", PROGNAME,Pid,num_added,sock_fd); if (num_to_add != num_added) { /* * Loop through the variables that were attempted * to be added and report any that had errors. */ for (i=0;irr_ctrl_cmd; } switch (ctrl_cmd) { case HA_RR_CMD_DELALL : fprintf(stdout,"%s(%d): Processing cmd HA_RR_CMD_DELALL to delete all vars for session_fd %d.\n", PROGNAME,Pid,sock_fd); /* * Delete all variables for this manager session. */ for (i=0;irr_ctrl_num_vars,sock_fd); /* * Delete a vector of variables for this manager session. */ for (i = 0; i < ctrl_msg->rr_ctrl_num_vars; i++) { inst_id = ctrl_msg->rr_ctrlv.rr_ctrl_vari[i]; if ((inst_id < NumVariables) && (LocalVars[inst_id].var_handle != (void *)0)) { /* * Copy the variable to the next RMAPI structure. */ Variables[num_to_del].rr_varu.rr_var_hndl = &(LocalVars[inst_id].var_handle); /* * Increment the count of variables to be deleted. */ num_to_del++; } } break; default : break; } if (num_to_del) { /* * Delete the variables by calling ha_rr_del_var. */ num_deleted = ha_rr_del_var(sock_fd, Variables, num_to_del, &ErrBlock); if (num_deleted == HA_RR_FAIL) { display_rmapi_err(&ErrBlock); if (ErrBlock.em_errno == HA_RR_EDISCONNECT) { /* * Session closed by manager. */ end_session(table_index); } else { mon_exit(1); } } /* * rc>0 from ha_rr_del_var is the number of variables that no longer need * their values updated. The RMAPI will have set their handles to NULL. */ fprintf(stdout,"%s(%d): %d variables no longer need to be updated.\n", PROGNAME,Pid,num_deleted); } } /* * Ends the manager session indexed by the [table_index] parameter * in the socket table. */ void end_session(int table_index) { int rc; fprintf(stdout,"%s(%d): Ending session index(%d) session_fd(%d).\n", PROGNAME,Pid,table_index,SocketTable[table_index].socket_fd); /* * Make sure this is a valid session. */ if ((table_index < 0) || (table_index > HA_RR_MAX_SESSIONS) || (SocketTable[table_index].socket_fd < 0)) { return; } /* * Delete all variables for this manager. */ del_variables(table_index, (struct ha_rr_ctrl_msg *)0); /* * Call RMAPI to end the session. */ rc = ha_rr_end_session(SocketTable[table_index].socket_fd, &ErrBlock); if (rc == HA_RR_FAIL) { display_rmapi_err(&ErrBlock); mon_exit(1); } /* * Reset the socket file descriptor in the SocketTable and * decrement the manager count. */ SocketTable[table_index].socket_fd = -1; NumMgrs--; } /* * Registers variables with the RMAPI. */ void register_variables() { int i, j, num_var; int num_registered, num_to_reg = 0; static int times_called = 0; fprintf(stdout,"%s(%d): Call number %d to register_variables().\n", PROGNAME,Pid,times_called); times_called++; if (times_called == 1) { /* * First time called, allocate the LocalVars, Variables and * Value arrays. Only register the StaticVars if this is * resource monitor instance 0. Since only 1 monitor will * supply these non-instantiable common attributes, we want it to * be instance 0, so that the variables are made available to * both the EM daemon and PTPE. */ NumVariables = NUM_INST_VARS; if (MonitorInstanceID == 0) NumVariables += NUM_STATIC_VARS; fprintf(stdout,"%s(%d): Creating %d initial variables.\n", PROGNAME,Pid,NumVariables); LocalVars = (struct local_vars *)malloc(sizeof(struct local_vars) * NumVariables); Variables = (struct ha_rr_variable *)malloc(sizeof(struct ha_rr_variable) * NumVariables); Values = (struct ha_rr_val *)malloc(sizeof(struct ha_rr_val) * NumVariables); /* * Initialize the arrays. */ memset(LocalVars,0,sizeof(struct local_vars) * NumVariables); memset(Variables,0,sizeof(struct ha_rr_variable) * NumVariables); memset(Values,0,sizeof(struct ha_rr_val) * NumVariables); if (MonitorInstanceID == 0) { /* * Initialize the local variable structures and copy the name, resource ID * and value pointers to the RMAPI variables for registration. */ for (i=0;i where is the number of the call to * this routine plus the instance id of the monitor times 100. There * is no significance to this naming scheme - it is only used to * generate unique instances between multiple copies of the monitor. */ sprintf(LocalVars[num_to_reg].var_name,"%s%d",INST_VAR_NAME_PREFIX,i+1); sprintf(LocalVars[num_to_reg].var_resid,INST_VAR_RESID_FORMAT, times_called + (MonitorInstanceID * 100)); LocalVars[num_to_reg].value = INITIAL_VALUE; Variables[num_to_reg].rr_var_name = LocalVars[num_to_reg].var_name; Variables[num_to_reg].rr_var_rsrc_ID = LocalVars[num_to_reg].var_resid; Variables[num_to_reg].rr_var_iid = num_to_reg; num_to_reg++; } } else { /* * Subsequent call to this routine. This is an example of new instantations * being created during normal execution. A new set of instantiable variables * will be registered using the current number of times this routine was called * in the resource ID. */ fprintf(stdout,"%s(%d): Creating %d new variables.\n", PROGNAME,Pid,NUM_INST_VARS); /* * Get the new number of variables. */ num_var = NumVariables + NUM_INST_VARS; /* * realloc the arrays to the new size and initialize the local array. */ LocalVars = (struct local_vars *)realloc(LocalVars, sizeof(struct local_vars) * num_var); Variables = (struct ha_rr_variable *)realloc(Variables, sizeof(struct ha_rr_variable) * num_var); Values = (struct ha_rr_val *)realloc(Values, sizeof(struct ha_rr_val) * num_var); memset(LocalVars+NumVariables,0,sizeof(struct local_vars) * NUM_INST_VARS); for (i=NumVariables,j=0;i= 0) FD_SET(SocketTable[i].socket_fd,&sockfd_set); } CallSockFunctions = 0; /* * Unblock the SIGTERM and SIGALRM signals. */ if (sigprocmask(SIG_UNBLOCK, &SignalMask, (sigset_t *)0) < 0) { /* * sigprocmask sys call failed. */ fprintf(stderr,"%s(%d): Cannot unblock signals. sigprocmask() errno=%d.\n", PROGNAME,Pid,errno); mon_exit(1); } /* * Only select if not terminating or SIGALRM caught to sample values. */ if (!(SampleTime || Terminate)) { sock = select(FD_SETSIZE, &sockfd_set, NULL, NULL, NULL); if (sock > 0) { CallSockFunctions = 1; } else if (sock < 0) { /* * select() call failed - exit if not an interrupt. */ if (errno != EINTR) { fprintf(stderr,"%s(%d): select() failed with errno=%d.\n", PROGNAME,Pid,errno); mon_exit(1); } continue; } } /* * Block the SIGTERM and SIGALRM sigs. */ if (sigprocmask(SIG_BLOCK, &SignalMask, (sigset_t *)0) < 0) { fprintf(stderr,"%s(%d): Cannot block signals. sigprocmask() errno=%d.\n", PROGNAME,Pid,errno); mon_exit(1); } if (Terminate) { /* * SIGTERM caught - call mon_exit() to clean up. */ fprintf(stdout,"%s(%d): Caught signal(%d)...calling exit...\n", PROGNAME,Pid,SigCaught); mon_exit(SigCaught); } if (CallSockFunctions) { /* * Call the socket function for each socket returned by select. */ for (i=0;i=0 && FD_ISSET(SocketTable[i].socket_fd,&sockfd_set)) { fprintf(stdout,"%s(%d): Calling socket function for session(%d) socket_fd(%d).\n", PROGNAME,Pid,i,SocketTable[i].socket_fd); (SocketTable[i].sock_funcp)(i); } } } if (SampleTime) { /* * SIGALRM caught - call send_values() * and reset the sample flag. */ send_values(); SampleTime = 0; } } } /* * Routine to terminate the monitor. */ void mon_exit(int s) { static int recursively_called = 0; int i, rc; /* * Check for recursive call - some routines mon_exit() * calls can likewise call mon_exit(). */ if (recursively_called) return; recursively_called = 1; if (RmapiInit) { /* * Gracefully close all sessions. */ for (i=0;i= 0) { end_session(i); } } /* * Terminate the RMAPI. */ rc = ha_rr_terminate(&ErrBlock); if (rc) { display_rmapi_err(&ErrBlock); } } fprintf(stdout,"%s(%d): %s resource monitor exiting.\n", PROGNAME,Pid,RESOURCE_MONITOR_NAME); exit(s); } /* * Display an RMAPI error. */ void display_rmapi_err(struct ha_em_err_blk *errblk) { fprintf(stderr, "%s(%d): RMAPI Error: File(%s) Version(%s) Line(%d) Errno(%d)\n\t%s", PROGNAME,Pid, errblk->em_errfile, errblk->em_errlevel, errblk->em_errline, errblk->em_errno, errblk->em_errmsg); }