/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* bos720 src/bos/usr/ccs/lib/libperfstat/simple_virdiskadapter.c 1.2     */
/*                                                                        */
/* Licensed Materials - Property of IBM                                   */
/*                                                                        */
/* Restricted Materials of IBM                                            */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2012,2013              */
/* 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                                                     */
static char *sccsid = "@(#)65 1.2     src/bos/usr/ccs/lib/libperfstat/simple_virdiskadapter.c, libperfstat, bos720 1/8/13 03:51:36 ";

/* The sample program display the metrics *
 * related to each and every Individual   * 
 * Virtual SCSI/SAS adapter stats in the VIOS */

#include <stdio.h> 
#include <stdlib.h>
#include <libperfstat.h>
#include <net/if_types.h>

/* define default interval and count values */
#define INTERVAL_DEFAULT 1
#define COUNT_DEFAULT    1

/* Check value returned by malloc for NULL */

#define CHECK_FOR_MALLOC_NULL(X) {  if ((X) == NULL) {\
                                       perror ("malloc");\
                                       exit(2);\
                                     }\
                  }

int count = COUNT_DEFAULT, interval = INTERVAL_DEFAULT, tot;
int returncode;

/* support for remote node statistics collection in a cluster environment */
perfstat_id_node_t nodeid;
static char nodename[MAXHOSTNAMELEN] = "";
static int collect_remote_node_stats = 0;

/* store the data structures */

static perfstat_diskadapter_t *statp ,*statq;

/*
 * NAME: showusage
 *       to display the usage
 *
 */

void showusage(char *cmd)
{
    fprintf (stderr, "usage: %s [-i <interval in seconds> ] [-c <number of iterations> ] [-n <node name in the cluster> ]\n", cmd);
    exit(1);
}


/*
 * NAME: do_initialization
 *       This function initializes the data structues.
 *       It also collects initial set of values.
 *
 * RETURNS:
 * On successful completion:
 *   - returns 0.
 * In case of error
 *    - exits with code 1.
 */

int do_initialization(void)
{
    /* check how many perfstat_vhost_adapter_t structures are available */
  
    if(collect_remote_node_stats) {
        strncpy(nodeid.u.nodename, nodename, MAXHOSTNAMELEN);
        nodeid.spec = NODENAME;
        tot = perfstat_virtualdiskadapter_node(&nodeid, NULL, sizeof(perfstat_diskadapter_t), 0);
    } else {
        tot = perfstat_virtualdiskadapter(NULL, NULL, sizeof(perfstat_diskadapter_t), 0);
    }
    
    if (tot == 0) {
        printf("There is no net adapter\n");
        exit(0);
    }
    if (tot < 0) {
        perror("perfstat_vhost_adapter: ");
        exit(1);
    }

    /* allocate enough memory for all the structures */

    statp = (perfstat_diskadapter_t *)malloc(tot * sizeof(perfstat_diskadapter_t));
    CHECK_FOR_MALLOC_NULL(statp);

    statq = (perfstat_diskadapter_t *)malloc(tot * sizeof(perfstat_diskadapter_t));
    CHECK_FOR_MALLOC_NULL(statq);


    return(0);
}

/*
 *Name: display_metrics
 *       collect the metrics and display them
 *
 */
void display_metrics()
{
    perfstat_id_t first;
    int ret, i;

    if(collect_remote_node_stats) {
        strncpy(nodeid.u.nodename, nodename, MAXHOSTNAMELEN);
        nodeid.spec = NODENAME;

        strcpy(nodeid.name , FIRST_VHOST);
        ret = perfstat_virtualdiskadapter_node(&nodeid, statq, sizeof(perfstat_diskadapter_t), tot);
    } else {
        strcpy(first.name , FIRST_VHOST);
        ret = perfstat_virtualdiskadapter( &first,  statq, sizeof(perfstat_diskadapter_t), tot);
    }
    if (ret < 0) {
        free(statp);
        free(statq);
        perror("perfstat_vhost_adapter: ");
        exit(1);
    }

    while (count)
    {
        sleep (interval);

        if(collect_remote_node_stats) {
           ret = perfstat_virtualdiskadapter_node(&nodeid, statp, sizeof(perfstat_diskadapter_t), tot);
        } else {
           ret = perfstat_virtualdiskadapter(&first, statp, sizeof(perfstat_diskadapter_t),tot);
        }
       /* print statistics for each of the interfaces */
        for (i = 0; i < ret; i++) {
            printf(" Adapter name: %s \n",  statp[i].name);
            printf(" Adapter Type:%d \n",statp[i].adapter_type);
            printf(" Total number of transfers via adapter :%lld \n",statp[i].xfers - statq[i].xfers);
            printf(" Blocks written to disk: %lld \n",statp[i].wblks - statq[i].wblks);
            printf(" Blocks read from disk: %lld \n",statp[i].rblks - statq[i].rblks);
            printf(" Block size: %lld \n",statp[i].dk_bsize);
            printf(" Number of transfers from disk : %lld \n",statp[i].dk_rxfers - statq[i].dk_rxfers);
            printf(" Read or receive service time : %lld \n",statp[i].dk_rserv - statq[i].dk_rserv);
            printf(" Write or send service time : %lld \n",statp[i].dk_wserv - statq[i].dk_wserv);
            
            printf(" ===========================================================\n");

        }

        memcpy(statq, statp, (tot * sizeof(perfstat_diskadapter_t)));
        count--;
    }
}

/*
 *Name: main
 *
 */

int main(int argc, char *argv[])
{
    int i, rc;
    /* get the interval and count values */

    /* Process the arguments */
    while ((i = getopt(argc, argv, "i:c:n:")) != EOF)
    {
        switch(i)
        {
           case 'i':               /* Interval */
                    interval = atoi(optarg);
                    if( interval <= 0 )
                        interval = INTERVAL_DEFAULT;
                    break;
           case 'c':               /* Number of interations */
                    count = atoi(optarg);
                    if( count <= 0 )
                        count = COUNT_DEFAULT;
                    break;
           case 'n':               /* Node name in a cluster environment */
                    strncpy(nodename, optarg, MAXHOSTNAMELEN);
                    nodename[MAXHOSTNAMELEN-1] = '\0';
                    collect_remote_node_stats = 1;
                    break;
           default:
                   /* Invalid arguments. Print the usage and terminate */
                   showusage(argv[0]);
        }
    }

    if(collect_remote_node_stats)
    {   /* perfstat_config needs to be called to enable cluster statistics collection */
        rc = perfstat_config(PERFSTAT_ENABLE|PERFSTAT_CLUSTER_STATS, NULL);
        if (rc == -1)
        {
            perror("cluster statistics collection is not available");
            exit(-1);
        }
    }

    do_initialization();
    display_metrics();

    if(collect_remote_node_stats)
    {   /* Now disable cluster statistics by calling perfstat_config */
        perfstat_config(PERFSTAT_DISABLE|PERFSTAT_CLUSTER_STATS, NULL);
    }
    free(statp);
    free(statq);
    return 0;
}


