/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* bos720 src/bos/usr/ccs/lib/libperfstat/simpleclusterstat.c 1.2         */
/*                                                                        */
/* Licensed Materials - Property of IBM                                   */
/*                                                                        */
/* Restricted Materials of IBM                                            */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2010                   */
/* 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                                                     */
#include <stdio.h>
#include <libperfstat.h>

typedef enum {
	DISPLAY_DEFAULT = 0,
	DISPLAY_NODE_DATA = 1,
	DISPLAY_DISK_DATA = 2
} display_t;

int main(int argc, char* argv[])
{
    perfstat_cluster_total_t cstats;
    perfstat_node_data_t *node_details;
    perfstat_disk_data_t *disk_details;
    perfstat_id_node_t nodeid;
    display_t display = DISPLAY_DEFAULT;
    int num_nodes;
    int i, rc;

    /* Process the arguments */
    while ((i = getopt(argc, argv, "lnd")) != EOF)
    {
       switch(i)
       {
           case 'n':               /* Request to display node data */
                    display |= DISPLAY_NODE_DATA;
                    break;
           case 'd':               /* Request to diplay disk data */
                    display |= DISPLAY_DISK_DATA;
                    break;
           case 'h':               /* Print help message */
           default:
                   /* Print the usage and terminate */
                   fprintf (stderr, "usage: %s [-n] [-d]\n", argv[0]);
                   exit(-1);
       }
    }

    /* 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);
    }

    /* Collect cluster statistics */
    strncpy(nodeid.u.nodename, FIRST_CLUSTERNAME, MAXHOSTNAMELEN);
    nodeid.spec = CLUSTERNAME;
    cstats.node_data = NULL;  /* To indicate we are not interested in node details */
    cstats.disk_data = NULL;  /* To indicate we are not interested in disk details */
    rc = perfstat_cluster_total(&nodeid, &cstats, sizeof(perfstat_cluster_total_t), 1);    
    if (rc == -1)
    {
        perror("perfstat_cluster_total failed");
        exit(-1);
    }
    fprintf(stdout, "Cluster statistics\n");
    fprintf(stdout, "------------------\n");
    fprintf(stdout, "Cluster Name    : %s\n", cstats.name);
    fprintf(stdout, "Cluster type    : ");
    if (cstats.type.b.is_local)
        fprintf(stdout, "LOCAL\n");
    else if (cstats.type.b.is_zone)
        fprintf(stdout, "ZONE\n");
    else if (cstats.type.b.is_link)
        fprintf(stdout, "LINK\n");
    fprintf(stdout, "Number of nodes : %u\n", cstats.num_nodes);
    fprintf(stdout, "Number of disks : %u\n", cstats.num_disks);

    /* check if the user requested node data */
    if(((display & DISPLAY_NODE_DATA) && (cstats.num_nodes > 0)) ||
       ((display & DISPLAY_DISK_DATA) && (cstats.num_disks > 0)))
    {
        if(display & DISPLAY_NODE_DATA)
        {
            cstats.sizeof_node_data = sizeof(perfstat_node_data_t);
            /* Make sure you allocate atleast cstats.num_nodes */
            /* Otherwise, perfstat_cluster_total() fails with ENOSPC */
            cstats.node_data = (perfstat_node_data_t *) malloc(cstats.sizeof_node_data * cstats.num_nodes);
            if(cstats.node_data == NULL)
            {
                perror("malloc failed for node_data");
                exit(-1);
            }
        }
        if(display & DISPLAY_DISK_DATA)
        {
            cstats.sizeof_disk_data = sizeof(perfstat_disk_data_t);
            /* Make sure you allocate atleast cstats.num_disks */
            /* Otherwise, perfstat_cluster_total() fails with ENOSPC */
            cstats.disk_data = (perfstat_disk_data_t *) malloc(cstats.sizeof_disk_data * cstats.num_disks);
            if(cstats.disk_data == NULL)
            {
                perror("malloc failed for disk_data");
                exit(-1);
            }
        }

        rc = perfstat_cluster_total(&nodeid, &cstats, sizeof(perfstat_cluster_total_t), 1);    
        if (rc == -1)
        {
            perror("perfstat_cluster_total failed");
            exit(-1);
        }
        if(display & DISPLAY_NODE_DATA)
        {
            fprintf(stdout, "\nNode details:\n");
            fprintf(stdout, "-------------\n");
            node_details = cstats.node_data;
            for (i = 0; i < cstats.num_nodes; i++, node_details++)
            {
                fprintf(stdout, "Node name                                    : %s\n", node_details->name);
                fprintf(stdout, "Node shorthand id                            : %llu\n", node_details->shorthand_id);
                fprintf(stdout, "Status of the node                           : ");
                if (node_details->status.b.is_up)
                    fprintf(stdout, "UP\n");
                else if (node_details->status.b.is_down)
                    fprintf(stdout, "DOWN\n");
                fprintf(stdout, "Number of clusters the node is participating : %u\n", node_details->num_clusters);
                fprintf(stdout, "Number of zones the node is participating    : %u\n", node_details->num_zones);
                fprintf(stdout, "Number of points of contact to the node      : %u\n", node_details->num_points_of_contact);
                fprintf(stdout, "\n");
            }
        }

        if(display & DISPLAY_DISK_DATA)
        {
            fprintf(stdout, "\nDisk details:\n");
            fprintf(stdout, "-------------\n");
            disk_details = cstats.disk_data;
            for (i = 0; i < cstats.num_disks; i++, disk_details++)
            {
                fprintf(stdout, "Disk name                                    : %s\n", disk_details->name);
                fprintf(stdout, "Status of the disk                           :");
                if (disk_details->status.b.is_found)
                {
                    fprintf(stdout, " FOUND");
                    if (disk_details->status.b.is_ready)
                        fprintf(stdout, " | READY");
                    else
                        fprintf(stdout, " | NOT READY");
                }
                else
                    fprintf(stdout, " NOT FOUND");
                fprintf(stdout, "\n");
                fprintf(stdout, "\n");
            }
        }
    }

     /* Now disable cluster statistics by calling perfstat_config */
     perfstat_config(PERFSTAT_DISABLE|PERFSTAT_CLUSTER_STATS, NULL);
}