Solstice Enterprise Manager 4.1 Customizing Guide |
Configuring CMIP MPA Overload
This chapter describes how to detect overload conditions for Common Management Information Protocol (CMIP) Management Protocol Adapter (MPA), and what action(s) must be taken when overload conditions exist.
This chapter describes the following topics:
- Section 13.1 Understanding CMIP MPA Overload
- Section 13.2 Configuration Parameters
- Section 13.3 Management Information Tree of Overload Control Objects
- Section 13.4 GDMO Classes
13.1 Understanding CMIP MPA Overload
Occasionally the Solstice Enterprise Manager (Solstice EM) network management system may experience network overload conditions caused by event storming. Under such conditions, the process size grows very fast and the CPU usage would be very high eventually causing the system to hang or crash. It is very important to ensure that Solstice EM handles this condition and that no Solstice EM platform component crashes.
In Solstice EM releases 3.0 and above, the CMIP MPA implements the overload control mechanism to handle this situation. The CMIP is configured in the following way:
- If the threshold of a particular severity level for the CMIP agent is crossed, the mpaOverloadAlarm notification will be emitted.
- If the overload instruction is configured to abortAssociations, the CMIP MPA automatically sets the administrative state of all the CMIP agents, whose threshold is crossed, to locked.
- Upon receiving the the attributeValueChange event of the administrative state of the CMIP agent, the CMIP MPA issues an ABORT_ASSOCIATION request to these agents.
The threshold levels are used to indicate the level of the overload. Following are the threshold levels used:
- Critical
- Major
- Minor
- Warning
- Cleared
13.2 Configuration Parameters
The overload control feature in the CMIP MPA requires configuration parameters to be stored in the EM-config file in /var/opt/SUNWconn/em/conf and GDMO objects (overload.gdmo and overload.asn1). These parameters in EM-config file are used for the initial value if the mpaOverloadController object does not exist in the MIS. The parameters in EM-config can be dynamically changed through PMI or em_obed.
Once the mpaOverloadController object is created, any modification to the EM-config file will have no effect unless you delete the existing overload object and bring up the em_cmip again.
The CMIP MPA will implement this overload control mechanism through the following parameters:
- Overload Control Parameter
- Overload Notification Parameter
- Overload Threshold Parameter
- Minimum Threshold Parameter
- Overload Instruction Parameter
- Poll Interval Parameter
Note The CMIP agents must be configured in the MIS before enabling the overload control feature.
13.2.1 Overload Control Parameter
This parameter determines whether the overload control feature is enabled or needful disabled. The valid values are ENABLED and DISABLED. The default is DISABLED.
EM_MPA_OVERLOAD_CONTROL: DISABLED
13.2.2 Overload Notification Parameter
The following parameters determine whether or not the notification is emitted when the threshold is crossed. In addition, whether or not the notification is emitted also depends on the overload state. Notification will not be emitted if the previous and current overload states are same. This will minimize the traffic between the CMIP MPA and the EDS. The valid values are ENABLED and DISABLED. The default is DISABLED.
- EM_MPA_CRITICAL_NOTIFICATION: DISABLED
- EM_MPA_MAJOR_NOTIFICATION: DISABLED
- EM_MPA_MINOR_NOTIFICATION: DISABLED
- EM_MPA_WARNING_NOTIFICATION: DISABLED
- EM_MPA_CLEAR_NOTIFICATION: DISABLED
13.2.3 Overload Threshold Parameter
The following parameters indicate the threshold value of overload conditions in the units of events per second. The valid value is a positive integer. The default value for these parameters is 0. The threshold parameter will not be checked if its value is equal to 0.
- EM_MPA_CRITICAL_THRESHOLD_RATE_PER_MPA: 0
- EM_MPA_MAJOR_THRESHOLD_RATE_PER_MPA: 0
- EM_MPA_MINOR_THRESHOLD_RATE_PER_MPA: 0
- EM_MPA_WARNING_THRESHOLD_RATE_PER_MPA: 0
- EM_MPA_CRITICAL_THRESHOLD_RATE_PER_AGENT: 0
- EM_MPA_MAJOR_THRESHOLD_RATE_PER_AGENT: 0
- EM_MPA_MINOR_THRESHOLD_RATE_PER_AGENT: 0
- EM_MPA_WARNING_THRESHOLD_RATE_PER_AGENT: 0
13.2.4 Minimum Threshold Parameter
The minimum threshold parameter is a low water mark set up for each threshold to avoid ping-pong between threshold levels. The default and the minimum value
is 5.13.2.5 Overload Instruction Parameter
This parameter indicates what kind of action is taken in case the level of a particular threshold is crossed. The supported actions are, do nothing or abort associations of the agent. The valid values are DO_NOTHING and ABORT_ASSOCIATIONS. The default value is DO_NOTHING.
When the CMIP MPA reaches a particular threshold level and the action is ABORT_ASSOCIATIONS, the CMIP MPA will abort all the open associations to the CMIP agents.
- EM_MPA_CRITICAL_OVERLOAD_INSTRUCTION: DO_NOTHING
- EM_MPA_MAJOR_OVERLOAD_INSTRUCTION: DO_NOTHING
- EM_MPA_MINOR_OVERLOAD_INSTRUCTION: DO_NOTHING
- EM_MPA_WARNING_OVERLOAD_INSTRUCTION: DO_NOTHING
13.2.6 Poll Interval Parameter
The poll interval parameter EM_MPA_OVERLOAD_POLL_INTERVAL:30 indicates how frequently the CMIP MPA checks overload conditions (in seconds). The minimum value is 30 seconds. If the value is less than 30 seconds, it defaults to 30 seconds.
13.3 Management Information Tree of Overload Control Objects
The following figure illustrates the Management InformationTree (MIT) of Overload Control Objects.
FIGURE 13-1 Management Information Tree of Overload Control Objects13.4 GDMO Classes
13.4.1 Mapping Between Attributes of the GDMO Classes and Configuration Parameters
13.4.2 emOverloadControlContainer Class
This GDMO class serves as a container for objects used to implement the overload control feature. The attribute value of overloadControlContainerName is set to OVERLOAD_CONTROL when the object is created during Solstice EM installation.
13.4.3 emOverloadController Class
This GDMO class is used to represent the Solstice EM server process which has defined the overload control objects. The CMIP MPA will be able to listen for the events of the creation/deletion/attribute value change of this class.
13.4.4 mpaOverloadController Class
This GDMO class is derived from emOverloadController GDMO class, used to represent the MPA. This defines the threshold rate per agent attribute managed by the MIS. The class also generates notifications called agentOverloadAlarm, mpaOverloadAlarm, and abortAssocNotification. Each CMIP MPA will have its own instance of mpaOverloadController object class named by "CMIP MPA:mpa_host:mpa_port". This class defines mpaStateInfo action used to query CMIP MPA to retrieve the overload state information for the CMIP MPA as well as for the CMIP agents. This action is designed for performance since the CMIP MPA keeps track of the overload state information in C++ class and the CMIP MPA does not maintain the mpaOverloadController objects.
mpaOverloadAlarm Notification
This alarm notification is sent by the instance of mpaOverloadController object class. It is used to report an alarm of overload condition when the threshold of the CMIP MPA is crossed. The alarm information consists of the alarm information of the CMIP MPA as well as of each CMIP agent. This notification is mapped to mpaOverloadAlarmRecord log record.
agentOverloadAlarm Notification
This alarm notification is sent by the instance of mpaOverloadController object class. It is used to report an alarm of overload condition when the threshold of the individual agent is crossed. The alarm information consists of the alarm information of each CMIP agent. This notification is mapped to agentOverloadAlarmRecord log record.
abortAssocNotification Notification
This notification is sent when the associations of the CMIP agent have been aborted due to the threshold of the CMIP MPA, or of the CMIP agent is crossed and whose overload instruction is ABORT_ASSOCIATIONS. The modification information includes the CMIP agent's MOI and text stating what action has been taken.
13.4.5 Overload Sample Programs
This section contains the sample programs for the overload control mechanism implemented in the CMIP MPA. See the following table.
13.4.5.1 get_agent_admin_state
Purpose: Get the administrative state of the CMIP agent Id and print it.
Syntax: get_agent_admin_state -agent <CMIP agent Id> -o <object class>\
[-host <host>] [-help]where <CMIP agent Id> is the CMIP agent Id.
<object class> is the object class of the CMIP agent.
<host> is the MIS host
CODE EXAMPLE 13-2 Main Program for get_agent_admin_state
main(int argc, char **argv) { Platform plat(duEM); RWCString dn; RWCString agent_name; RWCString class_name; RWCString attribute_name = "administrativeState"; RWCString host; // Get the host name. char * env_host = GETENV("EM_SERVER"); if (!env_host) { char system_host[MAXHOSTNAMELEN + 1]; sysinfo(SI_HOSTNAME, system_host, MAXHOSTNAMELEN); host = system_host; } else host = env_host; // Parse the cmd line for options. Boolean o_specified = FALSE; Boolean a_specified = FALSE; argv++; argc--; // get command line inputs void get_command_line_options(int,char **,Boolean *,Boolean *,RWCString&,RWCString&,RWCString&); get_command_line_options(argc,argv,&a_specified,&o_specified,host,agent_name,class_name); // Check if all params have been properly provided if (!a_specified || !o_specified) { usage(); exit(1); } // construct dn dn = agent_rdn + RWCString ("'") + agent_name + RWCString("'"); cout << "\n" << endl; cout << "=========================================================" << endl; cout << "The object name is " << endl; cout << dn << endl; cout << "=========================================================" << endl; // Connect to platform. cout << "Connecting to ... " << host << endl; if (!plat.connect((char *) (const char *) host, "em_sample")) { cout << "Failed to Connect to " << host << endl; cout << plat.get_error_string() << endl; exit(2); } cout << "Connected." << endl; // Declare cmipAgent/cmipAgentEntity image. Image im = Image((char *) (const char *) dn, (char *) (const char *) class_name); // Could not boot image if (!im.boot()) { cout << "Failed to boot " << dn << endl; cout << im.get_error_string() << endl; exit(3); } // print the header cout << "\nAttribute Value"; cout << "\n--------- -----" << endl; // Get attribute value and print it. cout << attribute_name; cout << " " << im.get_str((char *) (const char *) attribute_name).chp() << endl; exit(0); } /********************************************************** Method:substring General Description: Returns true if all of sub_string matches the main_string from the beginning of main_string. e.g. there is a match if main_string is "help" substring is "he" No match when: main_string is "he" sub_string is "help" or main_string is "host" sub_string is "he" Arguments: Return Value: Algorithm: Usage: WARNING: An empty sub_string ("") will return TRUE. Exceptions: ***********************************************************/ Boolean substring( const char * main_string, const char * sub_string) { while (*sub_string != 0) { if (*sub_string++ != *main_string++) return FALSE; } return TRUE; } // // Get command line inputs. // void get_command_line_options(int argc, char **argv, Boolean *a_specified, Boolean *o_specified, RWCString &host, RWCString &agent_name, RWCString &class_name) { while (argc > 0 && argv[0][0] == '-') { switch (argv[0][1]) { case 'a': { if (!substring("agent", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; agent_name = argv[0]; *a_specified = TRUE; } break; case 'o': if (!substring("object_class", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; class_name = argv[0]; *o_specified = TRUE; break; case 'h': if (strlen(&(argv[0][1])) < 2) { // can not distinguish between -help and -host usage(); exit(1); } if (substring("help", &(argv[0][1]))) { usage(); exit(0); } if (!substring("host", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; host = argv[0]; break; case '?': usage(); exit(1); } argv++; argc--; } }13.4.5.2 overload_action
Purpose: This program demonstrates how to invoke mpaOverloadController object action mpaStateInfo. GDMO class mpaOverloadController supports action mpaStateInfo which retrieves the overload state of the CMIP MPA and the remote agents.
Usage: overload_action -n <emControllerName> -l <action parameter> [-host <host>] [-help]
where <emControllerName> is the emControllerName in the form of "CMIP MPA:mpa_host:mpa_port" <action parameter> is the MpaStateInfoRequest asn1 syntax of mpaStateInfo action <host> is the host connect to (see overload.asn1).
CODE EXAMPLE 13-3 Sample for overload_action
// // %overload_action -n 'CMIP MPA:thomaseng:5557' -l 'default : NULL' // %overload_action -n 'CMIP MPA:thomaseng:5557' -l 'agentId : { { { systemId, "thomaseng" } }, { { agentTableType, "CMIP" } }, { { agentId, "miami" } } }' // %overload_action -n 'CMIP MPA:thomaseng:5557' -l 'agentId : localDistinguishedName : { { { agentId, "miami" } } }' // // #include <netdb.h> #include <sys/systeminfo.h> #include <hi.hh> #include <iostream.h> #include <rw/cstring.h> #include <unistd.h> const char *overload_container_name = "overloadControlContainerName='OVERLOAD_CONTROL'/emControllerName="; void usage();
CODE EXAMPLE 13-4 Main Program for overload_action
main(int argc, char **argv) { RWCString dn; RWCString action_name = "mpaStateInfo"; RWCString action_para; RWCString mpa_name; // Get the host name char *host = getenv("EM_SERVER"); if (!host) { host = new char[MAXHOSTNAMELEN+1]; sysinfo(SI_HOSTNAME, host, MAXHOSTNAMELEN-1); } // Parse the cmd line for options. Boolean n_specified = FALSE; Boolean l_specified = FALSE; argv++; argc--; // get command line inputs void get_command_line_options(int,char**,Boolean*,Boolean*,char *,RWCString&,RWCString&); get_command_line_options(argc, argv, &n_specified,&l_specified, host, mpa_name, action_para); // Check if all params have been properly provided if (!n_specified || !l_specified) { usage(); exit(1); } cout << endl; cout << " hostname = " << host << endl; cout << " mpaname = " << mpa_name << endl; cout << " action name = " << action_name << endl; cout << " action parameter = " << action_para << endl; cout << endl << endl; // Set up connect to MIS Platform plat = Platform(duEM); if (plat.get_error_type() != PMI_SUCCESS) { cout << plat.get_error_string() << endl; exit(2); } cout << "Connecting to ... " << host << endl; if (!plat.connect(host, "em_sample")) { cout << "Failed to connect to " << host << endl; cout << plat.get_error_string() << endl; exit(4); } cout << "Connected." << host << endl; // Construct dn dn = overload_container_name + RWCString ("'") + mpa_name + RWCString("'"); Image ov_image = Image((char *)(const char *)dn); if (ov_image.get_error_type() != PMI_SUCCESS) { cout << ov_image.get_error_string() << endl; exit(2); } // Boot mpaOverloadController object. if (!ov_image.boot()) { cout << ov_image.get_error_string() << endl; exit(2); } // Use action name to get input syntax. Syntax syn_input = ov_image.get_param_syntax((char *)(const char *)action_name); if (syn_input.get_error_type() != PMI_SUCCESS) { cout << syn_input.get_error_string() << endl; exit(2); } // Use action name to get result syntax. Syntax syn_result = ov_image.get_result_syntax((char *)(const char *)action_name); if (syn_result.get_error_type() != PMI_SUCCESS) { cout << syn_result.get_error_string() << endl; exit(2); } // Print the syntaxes. cout << "Input Syntax is " << syn_input.get().chp(); cout << endl; cout << "Result Syntax is " << syn_result.get().chp(); cout << endl; // Invoke the action and get the result data. DU action_data = ov_image.call((char *)(const char *)action_name, (char *)(const char *)action_para); // Use input syntax and action parameter to get input morf. Morf morf_input(syn_input, (char *)(const char *)action_para); if (morf_input.get_error_type() != PMI_SUCCESS) { cout << morf_input.get_error_string() << endl; exit(2); } cout << "Input Morf--> " << morf_input.get().chp() << endl; // User input morf and action name to get the result. Morf morf_result = ov_image.call_raw((char *)(const char *)action_name, morf_input); if (morf_result.get_error_type() != PMI_SUCCESS) { cout << morf_result.get_error_string() << endl; exit(2); } // Print the result. cout << "Result --> " << morf_result.get().chp() << endl; return 0; } void usage() { cout << "\nUsage: "; cout << "overload_action -n <emControllerName> -l <action parameter> [-host <host>] [-help]" << endl; cout << " -n <emControllerName> : emControllerName in the form of"<<endl ; cout << " 'CMIP MPA:mpa_host:mpa_port'"<< endl; cout << " -l <action parameter> : MpaStateInfoRequest asn1 syntax of " << endl; cout << " mpaStateInfo action" << endl; cout << " -host <host> : host to connect to " << endl; cout << " -help : print this message and exit" << endl; }
CODE EXAMPLE 13-5 Exceptions
const char * main_string, const char * sub_string ) { while (*sub_string != 0) { if (*sub_string++ != *main_string++) return FALSE; } return TRUE; } // // Get command line inputs // void get_command_line_options(int argc, char **argv, Boolean *n_specified, Boolean *l_specified, char *host, RWCString &mpa_name, RWCString &action_para) { while (argc > 0 && argv[0][0] == '-') { switch (argv[0][1]) { case 'n': { if (!substring("n", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; mpa_name = argv[0]; *n_specified = TRUE; } break; case 'l': if (!substring("l", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; action_para = argv[0]; *l_specified = TRUE; break; case 'h': if (strlen(&(argv[0][1])) < 2) { // can not distinguish between -help and -host usage(); exit(1); } if (substring("help", &(argv[0][1]))) { usage(); exit(0); } if (!substring("host", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; strcpy(host,argv[0]); break; case '?': usage(); exit(1); } argv++; argc--; } }13.4.5.3 overload_alarm
Purpose: Listen for mpaOverloadAlarm and agentOverloadAlarm events which are generated from the CMIP MPA if the overload control mechanism is enabled and the threshold is crossed. If the overload instruction of particular threshold level is releaseAssociations, update the administrativeState of the CMIP agent to locked. The CMIP MPA will listen for this attribute change event and sends the RELEASE_ASSOCIATION REQUEST to the agent. If the overload instruction of particular threshold level is doNothing, no action will be taken.
CODE EXAMPLE 13-6 Syntax for overload_alarm
// [-mn_action <action>] [-wn_action <action>] // [-host <MIS host>] [-help] // // where xx_action - the threshold level and // action - the overload instruction. The valid values // are doNothing/releaseAssociations. // host - MIS host // help - print command line options and exit // (refer to overload.gdmo/overload.asn1) // // Notes: 1. This program never exits; it enters an infinite listening loop. // Use Control-C to terminate it. // 2. If no argument is supplied, no overload action will be taken. // // Examples: // %overload_alarm -cr_action releaseAssociations -wn_action doNothing // %overload_alarm -mj_action releaseAssociations -mn_action doNothing // %overload_alarm // #include <netdb.h> #include <sys/systeminfo.h> #include <hi.hh> #include <message.hh> const Oid mpaOverloadAlarmOid = Oid("1.3.6.1.4.1.42.2.2.2.11.10.1"); const Oid agentOverloadAlarmOid = Oid("1.3.6.1.4.1.42.2.2.2.11.10.2"); void raw_cb( Ptr, Ptr calldata); enum AGENT_TYPE {mpa, cmip_agent}; enum SEVERITY {critical, major, minor, warning, cleared}; enum ADMIN_STATE {unlocked, locked}; const char *sev_str[] = {"Critical", "Major", "Minor", "Warning", "Cleared", "Unknown"}; const DU mpaOverloadAlarmDU = "mpaOverloadAlarm"; const DU agentOverloadAlarmDU = "agentOverloadAlarm"; const DU AgentTableDU = "agentCmip"; const DU ExtAgentTableDU = "agentCmipEntity"; char *cr_action="doNothing"; char *mj_action="doNothing"; char *mn_action="doNothing"; char *wn_action="doNothing"; Boolean cr_action_specified=FALSE, mj_action_specified=FALSE; Boolean mn_action_specified=FALSE, wn_action_specified=FALSE; void usage() { cout << "\nUsage: " ; cout << "./overload_alarm [-cr_action <action>] [-mj_action <action>] [mn_action <action>] [wn_action <action>] [-host <host>] [-help] " << endl; cout << " -cr_action <action> : overload instruction for critical threshold " << endl; cout << " (doNothing/releaseAssociations)" << endl; cout << " -mj_action <action> : overload instruction for major threshold " << endl; cout << " (doNothing/releaseAssociations)" << endl; cout << " -mn_action <action> : overload instruction for minor threshold " << endl; cout << " (doNothing/releaseAssociations)" << endl; cout << " -wn_action <action> : overload instruction for warning threshold " << endl; cout << " (doNothing/releaseAssociations)" << endl; cout << " -help : print this message and exit" << endl; cout << " -host <host> : host to connect to" << endl;
CODE EXAMPLE 13-7 Main Program for overload_alarm
int main(int argc, char **argv) { // Setup the connection to the MIS . Platform plat = Platform(duEM); if (plat.get_error_type()!=PMI_SUCCESS) { cout << plat.get_error_string() << endl; exit(1); } // Get the host name. char *host = getenv("EM_SERVER"); if (!host) { host = new char[MAXHOSTNAMELEN+1]; sysinfo(SI_HOSTNAME, host, MAXHOSTNAMELEN-1); } argv++; argc--; // get command line inputs void get_command_line_options(int, char**, char *); get_command_line_options(argc,argv,host); /* if (argc > 0 && (!cr_action_specified || !mj_action_specified || !mn_action_specified || !wn_action_specified)) { usage(); exit(1); } */ cout << "Connecting to ... " << host << endl; if (!plat.connect(host, "em_sample")) { cout << "Failed to connect to " << host << endl; cout << plat.get_error_string() << endl; exit(2); } cout << "Connected." << endl << endl; // Only interested in this specified object class. Array(DU) classes(1); classes[0] = "mpaOverloadController"; Array(DU) events(2); events[0] = mpaOverloadAlarmDU; events[1] = agentOverloadAlarmDU; if(!plat.replace_discriminator_classes(classes, events)) { cout << plat.get_error_string(); exit(4); } if (!plat.when("RAW_EVENT", Callback(raw_cb, 0))) { // Say when to call raw_cb(). cout << plat.get_error_string() << endl; exit(5); } cout << "Waiting for events...... " << endl << endl; while(1) { // Enter the infinite listen loop. dispatch_recursive(TRUE); } exit(0); } // // Check the overload instruction: // Return true if the action is releaseAssociations, otherwise, return false. // Boolean need_change_state(I32 sev) { switch (sev-1) { case critical: if (cr_action_specified && !strcmp(cr_action, "releaseAssociations")) return TRUE; break; case major: if (mj_action_specified && !strcmp(mj_action, "releaseAssociations")) return TRUE; break; case minor: if (mn_action_specified && !strcmp(mn_action, "releaseAssociations")) return TRUE; break; case warning: if (wn_action_specified && !strcmp(wn_action, "releaseAssociations")) return TRUE; break; default: return FALSE; } return FALSE; } // // Change administrativeState of cmip agent. // void change_admin_state_of_agent(const Asn1Value oi, ADMIN_STATE state) { DU fdn = oi2fdn(oi); Image agent_im = Image(fdn); if (!agent_im.boot()) { cout << "Can't boot agent image" << endl; exit(3); } if (!agent_im.exists()) { cout << "Agent image does not exist" << endl; exit(3); } char *state_str; if (state == unlocked) state_str = "unlocked"; else if (state == locked) state_str = "locked"; if (!agent_im.set_str("administrativeState", state_str)) { cout << "Failed to set administrative state of the agent ( " << fdn.chp() << ") " << endl; exit(3); } if (!agent_im.store()) { cout << "Failed to store administrative state of the agent (" << fdn.chp() << ") " << endl; exit(3); } else { cout << "\n\n=========================================================" << endl; cout << "SET the administrative state to locked for agent: "<<endl; cout << "<" << fdn.chp() << "> " << endl; cout << "=========================================================\n\n" << endl; } } // // Decode alarm information of each cmip agent. // void decode_agent_info(const Asn1Value &agent_info) { Asn1Value ava, ava2, agent_moi; U32 num = agent_info.num_comps(); for (int i=0; i < num; i++) { if (i == 0) { VTRYINV(agent_info.first_component(ava)); VTRYINV(ava.first_component(agent_moi)); // moi of agent Id change_admin_state_of_agent(agent_moi, locked); } else if (i != 0) { VTRYINV(agent_info.next_component(ava, ava2)); VTRYINV(ava2.first_component(agent_moi)); // moi of agent Id change_admin_state_of_agent(agent_moi, locked); } } } // // Print out the useful alarm information such as what severity of // alarm received, where does it come from, and the action to be taken. // void print_alarm_info(SEVERITY sev, AGENT_TYPE type, Asn1Value agent_oi) { // convert oi to fdn DU fdn = oi2fdn(agent_oi); // check unknown severity if (sev < critical || sev > cleared) sev = SEVERITY(5); cout << "\n\n=========================================================" << endl; if (type == mpa) { cout << "Received <" << sev_str[sev] << "> alarm from CMIP MPA " << endl; } else { // type == cmip_agent cout << "Received <" << sev_str[sev] << "> alarm from CMIP Agent " << endl; } cout << " <" << fdn.chp() << ">" << endl; switch (sev) { case critical: cout << "Action taken: <" << cr_action << ">" << endl; break; case major: cout << "Action taken: <" << mj_action << ">" << endl; break; case minor: cout << "Action taken: <" << mn_action << ">" << endl; break; case warning: cout << "Action taken: <" << wn_action << ">" << endl; break; default: cout << "Action taken: <" << sev_str[sev] << ">" << endl; break; } cout << "=========================================================\n\n" << endl; } // // Decode mpaOverloadAlarm and agentOverloadAlarm. /* Here's the asn1 syntax for these alarms. -- -- mpa overload alarm information including all agents overload alarm -- information. The moi of the mpa is in the event message. MpaOverloadAlarmInfo ::= SEQUENCE { threshold Threshold, probableCause ProbableCause, perceivedSeverity EMPerceivedSeverity, additionalText AdditionalText, agentsOverloadAlarmInfo AgentsOverloadAlarmInfo } AgentsOverloadAlarmInfo ::= SET OF SEQUENCE { agentMOI AgentMOI, threshold Threshold, probableCause ProbableCause, perceivedSeverity EMPerceivedSeverity, additionalText AdditionalText } AgentMOI ::= ObjectInstance -- -- agent overload alarm information; The agent moi is in the event message -- AgentOverloadAlarmInfo ::= SEQUENCE { threshold Threshold, probableCause ProbableCause, perceivedSeverity EMPerceivedSeverity, additionalText AdditionalText } Threshold ::= INTEGER */ void decode_message(CurrentEvent ce) { ObjReqMess *req = (ObjReqMess *)ce.get_message(); EventReq *evt_req = (EventReq *)req; Asn1Value ava; Oid evt_oid; if (evt_req->event_type.decode_oid(evt_oid) != OK) { cout << "Can't decode event oid" << endl; } else { I32 sev; // Decode threshold VTRYINV(evt_req->event_info.first_component(ava)); // Decode probableCause VTRYINV(evt_req->event_info.next_component(ava,ava)); // Decode perceivedSeverity VTRYINV(evt_req->event_info.next_component(ava,ava)); // mpaOverloadAlarm if (evt_oid == mpaOverloadAlarmOid) { Asn1Value agent_info; Boolean found = FALSE; VTRYINV(ava.decode_int(sev)); if (need_change_state(sev)) { print_alarm_info(SEVERITY(sev-1), mpa, req->oi); while (!found) { VTRYINV(evt_req->event_info.next_component(ava,ava)); if (ava.tag() == TAG_SET) found = TRUE; } if (found) { agent_info = ava; decode_agent_info(agent_info); } } } // agentOverloadAlarm else if (evt_oid == agentOverloadAlarmOid) { VTRYINV(ava.decode_int(sev)); if (need_change_state(sev)) { print_alarm_info(SEVERITY(sev-1), cmip_agent, req->oi); change_admin_state_of_agent(req->oi, locked); } } } } // // Define a function to do something with an event notification. // void raw_cb(Ptr, Ptr calldata) { // // Print interesting things about the event. // CurrentEvent ce(calldata); DU tmp; cout << "****** RAW_EVENT received ******" << endl; tmp=ce.get_event(); if (ce.get_error_type() != PMI_SUCCESS) { cout << ce.get_error_string() << endl; return; } else { cout << "EVENT = " << tmp.chp() << endl << endl; } // Decode event message if action specified if (cr_action_specified || mj_action_specified || mn_action_specified || wn_action_specified) decode_message(ce); return; } /********************************************************** Method:substring General Description: Returns true if all of sub_string matches the main_string from the beginning of main_string. e.g. there is a match if main_string is "help" substring is "he" No match when: main_string is "he" sub_string is "help" or main_string is "host" sub_string is "he" Arguments: Return Value: Algorithm: Usage: WARNING: An empty sub_string ("") will return TRUE. Exceptions: ******************************************************** ***/ Boolean substring( const char * main_string, const char * sub_string ) { while (*sub_string != 0) { if (*sub_string++ != *main_string++) return FALSE; } return TRUE; } // // Get command line inputs. // void get_command_line_options(int argc, char **argv, char *host) { while (argc > 0 && argv[0][0] == '-') { switch (argv[0][1]) { case 'c': { if (!substring("cr_action", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; cr_action = argv[0]; cr_action_specified = TRUE; } break; case 'w': if (!substring("wn_action", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; wn_action = argv[0]; wn_action_specified = TRUE; break; case 'm': if (strlen(&(argv[0][1])) < 2) { // can not distinguish between -mj_action and -mn_action usage(); exit(1); } if (substring("mj_action", &(argv[0][1]))) { mj_action_specified = TRUE; } else if (!substring("mn_action", &(argv[0][1]))) { usage(); exit(1); } else mn_action_specified = TRUE; argc --; if (!argc) { usage(); exit(1); } argv ++; if (mj_action_specified) mj_action = argv[0]; else if (mn_action_specified) mn_action = argv[0]; break; case 'h': if (strlen(&(argv[0][1])) < 2) { // can not distinguish between -help and -host usage(); exit(1); } if (substring("help", &(argv[0][1]))) { usage(); exit(0); } if (!substring("host", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; strcpy(host,argv[0]); break; case '?': usage(); exit(1); default : usage(); exit(1); } argv++; argc--; } }13.4.5.4 overload_get
Purpose: Get and print attributes of the mpaOverloadController object.
CODE EXAMPLE 13-8 Syntax for overload_get
// [-host <hostname>] [-help] // // where <n> is emControllerName of the CMIP MPA. // <attribute> is the attribute of the object // <host> is the MIS host // <help> is to print the command line options // // Note: // User MUST specify emControllerName in the form of // "CMIP MPA:mpa_host:mpa_port". // If no attribute is specified, get and print all attributes of // mpaOverloadController object of specified emControllerName. // // Example 1: Get and print all attributes of the mpaOverloadController // object named. // // ./overload_get -n 'CMIP MPA:thomaseng:5557' -a 'emControllerName' // ./overload_get -n 'CMIP MPA:thomaseng:5557' -a 'minimumThreshold' // ./overload_get -n 'CMIP MPA:thomaseng:5557' -a 'notificationEnabledStatus' // ./overload_get -n 'CMIP MPA:thomaseng:5557' -a 'overloadInstruction' // ./overload_get -n 'CMIP MPA:thomaseng:5557' -a 'overloadPollInterval' // ./overload_get -n 'CMIP MPA:thomaseng:5557' -a 'thresholdRatePerAgent' // ./overload_get -n 'CMIP MPA:thomaseng:5557' -a 'thresholdRatePerMPA' // ./overload_get -n 'CMIP MPA:thomaseng:5557' -a 'administrativeState' // ./overload_get -n 'CMIP MPA:thomaseng:5557' -a 'nameBinding' // ./overload_get -n 'CMIP MPA:thomaseng:5557' -a 'objectClass' // // Example 2: Get and print all attributes. // // ./overload_get -n 'CMIP MPA:thomaseng:5557' // #include <limits.h> // LINE_MAX #include <netdb.h> #include <sys/systeminfo.h> #include <rw/cstring.h> #include <hi.hh> #include <installation.hh> // GETENV const char *overload_container_name = "overloadControlContainerName='OVERLOAD_CONTROL'/emControllerName="; void usage() { cout << "./overload_get -n <emControllerName in 'CMIP MPA:mpa_host:mpa_port'> "; cout << "[ -attribute <attribute> ] [-host <host>] [-help]" << endl; cout << " -n <emControllerName> : emControllerName in the form of " << endl; cout << " 'CMIP MPA:mpa_host:mpa_port' " << endl; cout << " -attribute <attribute> : attribute name" << endl; cout << " -host <host> : host to connect to" << endl; cout << " -help : print this message and exit" << endl; }
CODE EXAMPLE 13-9 Main Program for overload_get
main(int argc, char **argv) { Platform plat(duEM); RWCString dn; RWCString mpa_name; RWCString class_name = "mpaOverloadController"; RWCString attribute_name; RWCString host; // Get the host name. char * env_host = GETENV("EM_SERVER"); if (!env_host) { char system_host[MAXHOSTNAMELEN + 1]; sysinfo(SI_HOSTNAME, system_host, MAXHOSTNAMELEN); host = system_host; } else host = env_host; // Parse the cmd line for options. Boolean n_specified = FALSE; Boolean a_specified = FALSE; argv++; argc--; // Get command line inputs void get_command_line_options(int argc,char **argv, Boolean *,Boolean *, RWCString &, RWCString &, RWCString &); get_command_line_options(argc, argv, &n_specified,&a_specified, host, mpa_name, attribute_name); // Check if all params have been properly provided if (!n_specified) { usage(); exit(1); } // construct dn dn = overload_container_name + RWCString ("'") + mpa_name + RWCString("'"); cout << "\n" << endl; cout << "=========================================================" << endl; cout << "The object name is " << endl; cout << dn << endl; cout << "=========================================================" << endl; // Connect to platform. cout << "Connecting to ... " << host << endl; if (!plat.connect((char *) (const char *) host, "em_sample")) { cout << "Failed to Connect to " << host << endl; cout << plat.get_error_string() << endl; exit(2); } cout << "Connected." << endl; // Declare mpaOverloadController image. Image im = Image((char *) (const char *) dn, (char *) (const char *) class_name); // Could not boot image if (!im.boot()) { cout << "Failed to boot " << dn << endl; cout << im.get_error_string() << endl; exit(3); } // Perform a get on each attribute to get its value // Note we have stripped off the document name to make // the attribute value pairs more readable // the chp() method of the DataUnit is necessary to null // terminate the DataUnit. // print the header cout << "\nAttribute Value"; cout << "\n--------- -----" << endl; // If an attribute is specified, get it, print it. if (strlen(attribute_name)) { cout << attribute_name; cout << " " << im.get_str((char *) (const char *) attribute_name).chp() << endl; } else { // Create array attr_names of DataUnits; get attribute names, copy to array. Array(DU) attr_names = im.get_attr_names(); for (int i = 0; i < attr_names.size; i++) { DU& name = attr_names[i]; // Get name as DataUnit. char *short_name = strrchr(attr_names[i].chp(),':'); // Name as str // Print attribute cout << ++short_name << " "; // Print value. cout << im.get_str(name, USE_EXPLICIT_CHOICE | OMIT_NEWLINES).chp(); cout << endl; } } exit(0); } /******************************************************* *** Method:substring General Description: Returns true if all of sub_string matches the main_string from the beginning of main_string. e.g. there is a match if main_string is "help" substring is "he" No match when: main_string is "he" sub_string is "help" or main_string is "host" sub_string is "he" Arguments: Return Value: Algorithm: Usage: WARNING: An empty sub_string ("") will return TRUE. Exceptions: ******************************************************** ***/ Boolean substring( const char * main_string, const char * sub_string) { while (*sub_string != 0) { if (*sub_string++ != *main_string++) return FALSE; } return TRUE; } // // Get command line inputs // void get_command_line_options(int argc, char **argv, Boolean *n_specified, Boolean *a_specified, RWCString &host, RWCString &mpa_name, RWCString &attribute_name) { while (argc > 0 && argv[0][0] == '-') { switch (argv[0][1]) { case 'n': { if (!substring("n", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; mpa_name = argv[0]; *n_specified = TRUE; } break; case 'a': if (!substring("attribute", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; attribute_name = argv[0]; *a_specified = TRUE; break; case 'h': if (strlen(&(argv[0][1])) < 2) { // can not distinguish between -help and -host usage(); exit(1); } if (substring("help", &(argv[0][1]))) { usage(); exit(0); } if (!substring("host", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; host = argv[0]; break; case '?': usage(); exit(1); } argv++; argc--; } }13.4.5.5 overload_set
Purpose: Set and print attributes of the mpaOverloadController object.
CODE EXAMPLE 13-10 Syntax for overload_set
// -value <attributeValue [-host <hostname>] [-help] // // where <n> is emControllerName of the CMIP MPA. // <attribute> specifies the attribute of the object // <attributeValue> specifies the attribute value of the object // <host> specifies the MIS host // <help> indicate to print the command line options // // Note: // User MUST specify emControllerName in the form of // "CMIP MPA:mpa_host:mpa_port". // User MUST specify the attribute value to change to. // // Example 1: // // ./overload_set -n 'CMIP MPA:thomaseng:5557' -a 'minimumThreshold' // -v 20 // ./overload_set -n 'CMIP MPA:thomaseng:5557' -a 'notificationEnabledStatus' // -v '{ { critical, disabled }, { major, disabled }, { minor, disabled }, { warning, disabled }, { cleared, disabled } }' // ./overload_set -n 'CMIP MPA:thomaseng:5557' -a 'overloadInstruction' // -v '{ { critical, doNothing }, { major, doNothing }, { minor, doNothing }, { warning, doNothing } }' // ./overload_set -n 'CMIP MPA:thomaseng:5557' -a 'overloadPollInterval' // -v 60 // ./overload_set -n 'CMIP MPA:thomaseng:5557' -a 'thresholdRatePerAgent' // -v '{ { critical, 100 }, { major, 80 }, { minor, 60 }, { warning, 40 } }' // ./overload_set -n 'CMIP MPA:thomaseng:5557' -a 'thresholdRatePerMPA' // -v '{ { critical, 100 }, { major, 80 }, { minor, 60 }, { warning, 40 } }' // ./overload_set -n 'CMIP MPA:thomaseng:5557' -a 'administrativeState' // -v locked // #include <limits.h> // LINE_MAX #include <netdb.h> #include <sys/systeminfo.h> #include <rw/cstring.h> #include <hi.hh> #include <installation.hh> // GETENV const char *overload_container_name = "overloadControlContainerName='OVERLOAD_CONTROL'/emControllerName="; void usage() { cout << "./overload_set -n <emControllerName in 'CMIP MPA:mpa_host:mpa_port'> "; cout << " -attribute <attribute> -value <attributeValue> [-host <host>] [-help]" << endl; cout << " -n <emControllerName> : emControllerName in 'CMIP MPA:mpa_host:mpa_port'" << endl; cout << " -attribute <attribute> : attribute name" << endl; cout << " -value <attributeValue>: attribute value" << endl; cout << " -host <host> : host to connect to" << endl; cout << " -help : print this message and exit" << endl; }
CODE EXAMPLE 13-11 Main Program for overload_set
main(int argc, char **argv) { Platform plat(duEM); RWCString dn; RWCString mpa_name; RWCString class_name = "mpaOverloadController"; RWCString attribute_name; RWCString attribute_value; RWCString host; // Get the host name. char * env_host = GETENV("EM_SERVER"); if (!env_host) { char system_host[MAXHOSTNAMELEN + 1]; sysinfo(SI_HOSTNAME, system_host, MAXHOSTNAMELEN); host = system_host; } else host = env_host; // Parse the cmd line for options. Boolean n_specified = FALSE; Boolean a_specified = FALSE; Boolean v_specified = FALSE; argv++; argc--; // Get command line inputs void get_command_line_options(int,char **,Boolean*, Boolean *, Boolean *, RWCString &, RWCString &, RWCString &, RWCString &); get_command_line_options(argc,argv,&n_specified,&a_specified,&v_specified, host,mpa_name,attribute_name,attribute_value); // Check if all params have been properly provided if (!n_specified || !a_specified || !v_specified) { usage(); exit(3); } // Construct dn dn = overload_container_name + RWCString ("'") + mpa_name + RWCString("'"); cout << "\n" << endl; cout << "=========================================================" << endl; cout << "The object name is " << endl; cout << dn << endl; cout << "=========================================================" << endl; // Connect to platform. cout << "Connecting to ... " << host << endl; if (!plat.connect((char *) (const char *) host, "em_sample")) { cout << "Failed to Connect to " << host << endl; cout << plat.get_error_string() << endl; exit(4); } cout << "Connected. " << endl; // Declare mpaOverloadController image. Image im = Image((char *) (const char *) dn, (char *) (const char *) class_name); // Could not boot image if (!im.boot()) { cout << "Failed to boot " << dn << endl; cout << im.get_error_string() << endl; exit(5); } // Now set the attribute. // Set the attribute value to the object image at application side. // The attribute value does not actually get changed in the MIS // until the store function is successfully completed. cout << "Set attribute " << attribute_name; cout << " to " << attribute_value << endl; DU prev_val = im.get_str((char *) (const char *)attribute_name); if (!prev_val) { cout << "Failed to get the attribute value "; cout << im.get_error_string() << endl; exit(5); } cout << "Before the set operation the attribute "; cout << attribute_name << " value is "; cout << prev_val.chp() << endl; // Set attribute value for the object image. if(!im.set_str((char *)(const char *)attribute_name, (char *)(const char *)attribute_value)) { cout << "Failed to set. "; cout << im.get_error_string() << endl; exit(6); } cout << "Store the attribute value to the MIS..." << endl; // Store the object image back to the MIS. if(!im.store()) { cout << "Failed to store. "; cout << im.get_error_string() << endl; exit(7); } // Get and print the new attribute value. cout << "After the set operation the attribute "; cout << attribute_name << " value is "; cout << (im.get_str(attribute_name.data())).chp() << endl; exit(0); } /********************************************************** Method:substring General Description: Returns true if all of sub_string matches the main_string from the beginning of main_string. e.g. there is a match if main_string is "help" substring is "he" No match when: main_string is "he" sub_string is "help" or main_string is "host" sub_string is "he" Arguments: Return Value: Algorithm: Usage: WARNING: An empty sub_string ("") will return TRUE. Exceptions: ***********************************************************/ Boolean substring( const char * main_string, const char * sub_string) { while (*sub_string != 0) { if (*sub_string++ != *main_string++) return FALSE; } return TRUE; } // // Get command line input // void get_command_line_options(int argc, char **argv, Boolean *n_specified, Boolean *a_specified, Boolean *v_specified, RWCString &host, RWCString &mpa_name, RWCString &attribute_name, RWCString &attribute_value) { while (argc > 0 && argv[0][0] == '-') { switch (argv[0][1]) { case 'n': { if (!substring("n", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; mpa_name = argv[0]; *n_specified = TRUE; } break; case 'a': if (!substring("attribute", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; attribute_name = argv[0]; *a_specified = TRUE; break; case 'v': if (!substring("value", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; attribute_value = argv[0]; *v_specified = TRUE; break; case 'h': if (strlen(&(argv[0][1])) < 2) { // can not distinguish between -help and -host usage(); exit(1); } if (substring("help", &(argv[0][1]))) { usage(); exit(0); } if (!substring("host", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; host = argv[0]; break; case '?': usage(); exit(1); } argv++; argc--; } }13.4.5.6 set_agent_admin_state
Purpose: Set the administrative state of the CMIP agent id and print it.
CODE EXAMPLE 13-12 Syntax for set_agent_admin_state
// -value <value of admin. state> [-host <host>] [-help] // // where <agentId> is cmip agent id. // <object class> specifies the object class of the cmip agent, // either cmipAgent or cmipAgentEntity // <attributeValue> specifies the administrative state // attribute value of the agent // <host> specifies the MIS host // <help> indicate to print the command line options // // User MUST specify the attribute value to change to. // // Example 1: // // ./set_agent_admin_state -agent 'emperf' -v locked // ./set_agent_admin_state -agent 'emperf' -v unlocked // #include <limits.h> // LINE_MAX #include <netdb.h> #include <sys/systeminfo.h> #include <rw/cstring.h> #include <hi.hh> #include <installation.hh> // GETENV const char *agent_rdn = "agentTableType='CMIP'/agentId=id:"; void usage() { cout << "\nUsage:" ; cout << "./set_agent_admin_state -agent <cmip agent id> " ; cout << "-o <object class>" ; cout << " -value <attributeValue> [-host <host>] [-help]" << endl; cout << " -agent <cmip agent id> : CMIP agent Id (e.g.'emperf') " << endl; cout << " -o <object class> : object class of CMIP agent Id " << endl; cout << " -value <attributeValue> : attribute value of administrative state " << endl; cout << " -host <host> : host to connect to" << endl; cout << " -help : print this message and exit" << endl; }
CODE EXAMPLE 13-13 Main Program for set_agent_admin_state
main(int argc, char **argv) { Platform plat(duEM); RWCString dn; RWCString agent_name; RWCString class_name; RWCString attribute_name = "administrativeState"; RWCString attribute_value; RWCString host; // Get the host name. char * env_host = GETENV("EM_SERVER"); if (!env_host) { char system_host[MAXHOSTNAMELEN + 1]; sysinfo(SI_HOSTNAME, system_host, MAXHOSTNAMELEN); host = system_host; } else host = env_host; // Parse the cmd line for options. Boolean a_specified = FALSE; Boolean o_specified = FALSE; Boolean v_specified = FALSE; argv++; argc--; // get command line inputs void get_command_line_options(int,char **,Boolean*,Boolean*,Boolean *, RWCString &, RWCString&,RWCString&, RWCString&); get_command_line_options(argc,argv,&a_specified,&o_sp ecified,&v_specified, host,class_name,agent_name,attribute_value); // Check if all params have been properly provided if (!a_specified || !o_specified || !v_specified) { usage(); exit(1); } // Construct dn dn = agent_rdn + RWCString ("'") + agent_name + RWCString("'"); cout << "\n" << endl; cout << "=========================================================" << endl; cout << "The object name is " << endl; cout << dn << endl; cout << "=========================================================" << endl; // Connect to platform. cout << "Connecting to ... " << host << endl; if (!plat.connect((char *) (const char *) host, "em_sample")) { cout << "Failed to Connect to " << host << endl; cout << plat.get_error_string() << endl; exit(4); } cout << "Connected. " << endl; // Declare cmip agent image. Image im = Image((char *) (const char *) dn, (char *) (const char *) class_name); // Could not boot image if (!im.boot()) { cout << "Failed to boot " << dn << endl; cout << im.get_error_string() << endl; exit(5); } // Now set the attribute. // Set the attribute value to the object image at application side. // The attribute value does not actually get changed in the MIS // until the store function is successfully completed. cout << "Set attribute " << attribute_name; cout << " to " << attribute_value << endl; DU prev_val = im.get_str((char *) (const char *)attribute_name); if (!prev_val) { cout << "Failed to get the attribute value "; cout << im.get_error_string() << endl; exit(5); } cout << "Before the set operation the attribute "; cout << attribute_name << " value is "; cout << prev_val.chp() << endl; // Set attribute value for the object image. if(!im.set_str((char *)(const char *)attribute_name, (char *)(const char *)attribute_value)) { cout << "Failed to set. "; cout << im.get_error_string() << endl; exit(6); } cout << "Store the attribute value to the MIS..." << endl; // Store the object image back to the MIS. if(!im.store()) { cout << "Failed to store. "; cout << im.get_error_string() << endl; exit(7); } // Get and print the new attribute value. cout << "After the set operation the attribute "; cout << attribute_name << " value is "; cout << (im.get_str(attribute_name.data())).chp() << endl; exit(0); } /******************************************************* *** Method:substring General Description: Returns true if all of sub_string matches the main_string from the beginning of main_string. e.g. there is a match if main_string is "help" substring is "he" No match when: main_string is "he" sub_string is "help" or main_string is "host" sub_string is "he" Arguments: Return Value: Algorithm: Usage: WARNING: An empty sub_string ("") will return TRUE. Exceptions: ******************************************************** ***/ Boolean substring( const char * main_string, const char * sub_string) { while (*sub_string != 0) { if (*sub_string++ != *main_string++) return FALSE; } return TRUE; } void get_command_line_options(int argc, char **argv, Boolean *a_specified, Boolean *o_specified, Boolean *v_specified, RWCString &host, RWCString &class_name, RWCString &agent_name, RWCString &attribute_value) { while (argc > 0 && argv[0][0] == '-') { switch (argv[0][1]) { case 'a': { if (!substring("agent", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; agent_name = argv[0]; *a_specified = TRUE; } break; case 'o': if (!substring("object_class", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; class_name = argv[0]; *o_specified = TRUE; break; case 'v': if (!substring("value", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; attribute_value = argv[0]; *v_specified = TRUE; break; case 'h': if (strlen(&(argv[0][1])) < 2) { // can not distinguish between -help and -host usage(); exit(1); } if (substring("help", &(argv[0][1]))) { usage(); exit(0); } if (!substring("host", &(argv[0][1]))) { usage(); exit(1); } argc --; if (!argc) { usage(); exit(1); } argv ++; host = argv[0]; break; case '?': usage(); exit(1); } argv++; argc--; } }
Sun Microsystems, Inc. Copyright information. All rights reserved. |
Doc Set | Contents | Previous | Next | Index |