// Assign default values
memset((void*)filename, 0, sizeof(filename));
memset((void*)dg_info, 0, sizeof(dg_info));
// If daperf is entered without any options, print the usage page
if (argc == 1) {
printf("%s", DAPERF_USAGE);
exit(0);
}
// Loop through all the command-line options
while (1) {
res_getopt = getopt_long_only(argc, argv, "-h", long_options, &option_index);
if (res_getopt == -1)
break;
switch (res_getopt) {
}
}
end while
// Assign the default for points (60 for long-term, 100 for short-term)
if (points_flg == 0)
points = (longterm_flg != 0) ? MAX_ELEMENTS : CIRC_BUFFER_ELEMENT_CNT - 1;
// If the user specified the number of points, check if valid
else {
// Long-term points should be 1-60
if (longterm_flg != 0) {
if ((points < 1) || (points > MAX_ELEMENTS)) {
printf("Error: The points (%d) are out of range [1-%d] for long-term data.\n",
points, MAX_ELEMENTS);
exit(DAPERF_INVALID_POINTS);
}
}
// Short-term points should be 1-100
else {
if ((points < 1) || (points > (CIRC_BUFFER_ELEMENT_CNT - 1))) {
printf("Error: The specified points (%d) are out of range [1-%d].\n",
points, CIRC_BUFFER_ELEMENT_CNT-1);
exit(DAPERF_INVALID_POINTS);
}
}
}
action_cnt = datarate_flg + readrate_flg + writerate_flg +
comptime_flg + readcomptime_flg + writecomptime_flg +
lba_flg + readlba_flg + writelba_flg +
iscsibusy_flg + readiscsibusy_flg + writeiscsibusy_flg +
alert_range.datarate_range_flg + alert_range.readrate_range_flg +
alert_range.writerate_range_flg + alert_range.comptime_range_flg +
alert_range.lba_range_flg + alert_range.iscsibusy_range_flg;
// If user wants to see VD data, the number of -vd options must match the number of -dg options.
// The user must also specify an action.
if (vd_cnt != 0) {
if (vd_option_cnt != dg_cnt) {
printf("Error: The number of -vd options (%d) and -dg options (%d) do not agree.\n",
vd_option_cnt, dg_cnt);
exit(DAPERF_VD_OPTION_MISMATCH);
}
if (action_cnt == 0) {
printf("Error: The option list does not include an action, such as -readrate.\n");
exit(DAPERF_DGVD_NO_ACTION);
}
// Only allow one VD for long-term data because each VD may not have the same timestamps,
// so a separate time column would have to be printed for each VD.
if ((longterm_flg != 0) && (vd_cnt > 1)) {
printf("Error: Only one vd may be specified for long-term data.\n");
exit(DAPERF_LONGTERM_VDCNT_ERR);
}
}
// If the user wants to see DG data, then the user must specify an action.
else if (dg_cnt != 0) {
if (action_cnt == 0) {
printf("Error: The option list does not include an action, such as -readrate.\n");
exit(DAPERF_DGVD_NO_ACTION);
}
// Start perfd on local controller (and remote if it exists) and update the perfd status files
if (start_flg != 0) {
rc = handle_start(writing_interval, remote_id, remote_present, longterm_flg);
exit(rc);
}
// Stop perfd on local controller (and remote if it exists) and update the perfd status files
if (stop_flg != 0) {
rc = handle_stop(remote_id, remote_present);
exit(rc);
}
// Start local perfd if local status file says it should be running. Called by bootup script on
// controller that comes up first.
if (slfl_flg != 0) {
rc = handle_start_local_from_local();
exit(rc);
}
// Start local perfd if remote status file says it should be running. Called by bootup script on
// controller that comes up last, so that it agrees with the other controller.
if (slfr_flg != 0) {
rc = handle_start_local_from_remote(remote_id, remote_present);
exit(rc);
}
// Read and display the writing interval
if (showinterval_flg != 0) {
rc = handle_showinterval(remote_id, remote_present);
exit(rc);
}
// Copy the alert config file from the remote controller to the local
if (syncalertconfig_flg != 0) {
rc = handle_sync_alert_config(remote_id);
exit(rc);
}
// Remove the VD and DG entries in the alert config file for VDs and DGs that
// do not exist in the interface file
if (cleanup_flg != 0) {
rc = cleanup_alert_file(remote_id, remote_present);
exit(rc);
}
// Handle a single range parameter, such as -cpuidle_range 5-95
if (single_range_flg != 0) {
#ifndef USE_LONGTERM_DG_DATA
if ((vd_cnt == 0) && (dg_cnt != 0)) {
printf("Error: The system does not allow ranges for dg data.\n");
exit(DAPERF_DG_RANGE_ERR);
}
#endif
rc = handle_single_range(remote_present, remote_id, &alert_range,
local_id, vd_cnt, dg_cnt, dg_info);
exit(rc);
}
// For operations below this point, the perfd and idled daemons must be running. It would
// be nice to check the remote daemons as well, but this will require additional rssh calls,
// which will lead to additional TCP connections in the TIME_WAIT state, which will limit
// the number of simultaneous web-browser connections. Therefore, only check the local
// daemons.
perfd_local_is_running = check_local_perfd();
idled_local_is_running = check_local_idled();
//show function #
int32_t check_local_perfd(void)
{
char cmd[200];
sprintf(cmd, "/sbin/pidof perfd 1> /dev/null 2>&1");
if (WEXITSTATUS(system(cmd)) == 0)
return(1);
return(0);
}
int32_t start_perfd_local(int32_t writing_interval)
{
char cmd[200];
sprintf(cmd, "/usr/sbin/perfd %d < /dev/null 1> /dev/null 2>&1 &", writing_interval);
if (WEXITSTATUS(system(cmd)) != 0) {
printf("Error: Unable to start the local perfd daemon to capture performance data.\n");
return(PERFD_LOCAL_START_ERROR);
}
return(0);
}
int32_t stop_perfd_local(void)
{
char cmd[200];
sprintf(cmd, "/usr/bin/pkill perfd 1> /dev/null 2>&1");
if (WEXITSTATUS(system(cmd)) != 0) {
printf("Error: Unable to stop the local perfd daemon.\n");
return(PERFD_LOCAL_STOP_ERROR);
}
return(0);
}
int32_t check_local_idled(void)
{
char cmd[200];
sprintf(cmd, "/sbin/pidof -x idled 1> /dev/null 2>&1");
if (WEXITSTATUS(system(cmd)) == 0)
return(1);
return(0);
}
//end for show
// Return if both perfd and idled are not running locally
if ((perfd_local_is_running == 0) && (idled_local_is_running == 0)) {
printf("Error: The performance daemons are not running. Please run daperf -start.\n");
exit(PERFD_BOTH_STOPPED_ERROR);
}
// Return if either perfd or idled is not running locally
if ((perfd_local_is_running == 0) || (idled_local_is_running == 0)) {
printf("Error: The performance daemons are not running. Please stop and then start.\n");
exit(PERFD_LOCAL_STOPPED_ERROR);
}
// Assign flag indicating local access of circular buffers, remote access, or both
rc = assign_local_remote_flg(bothctlr_flg, c0_flg, c1_flg, local_id, remote_present, &local_remote_flg);
if (rc != 0)
exit(rc);
// Assign components of params structure to help with parameter passing
memset(¶ms, 0, sizeof(params));
params.datatype = 0;
params.points = points;
params.local_remote_flg = local_remote_flg;
params.local_id = local_id;
params.remote_id = remote_id;
params.filename = filename;
params.noheader_flg = noheader_flg;
params.longterm_flg = longterm_flg;
params.time_flg = time_flg;
params.time_str = time_str;
params.increment = increment;
if ((owneronly_flg == 0) && (otheronly_flg == 0))
params.owner_other_flg = ACCESS_OWNER | ACCESS_OTHER;
else {
params.owner_other_flg = 0;
if (owneronly_flg != 0)
params.owner_other_flg = ACCESS_OWNER;
if (otheronly_flg != 0)
params.owner_other_flg = params.owner_other_flg | ACCESS_OTHER;
}
// Assign a default timestamp, if necessary, for long-term data. The timestamp is way in
// the future (1/1/2199), so that when the user does not enter a timestamp, the most recent data
// will be accessed. In addition, the user can still enter a negative increment and access
// data further in the past.
if (longterm_flg != 0) {
if (params.time_flg == 0) {
memset(params.time_str, 0, sizeof(params.time_str));
//sprintf(params.time_str, "20140101_010101");
sprintf(params.time_str, "21990101_010101");
}
}