/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* bos720 src/bos/usr/ccs/lib/libperfstat/perfdump.c 1.3                  */
/*                                                                        */
/* Licensed Materials - Property of IBM                                   */
/*                                                                        */
/* Restricted Materials of IBM                                            */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2008,2009              */
/* 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[] = "@(#)70        1.3  src/bos/usr/ccs/lib/libperfstat/perfdump.c, libperfstat, bos720 4/17/09 01:55:45";


/* Sample program to Display the all raw values returned by perfstat_cpu  */ 
/* perfstat_cpu_total, perfstat_memory_total , perfstat_partition_total   */  
/* and perfstat_disk_total calls in global				  */ 

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/errno.h>
#include <sys/proc.h>
#include <wpars/wparcfg.h>
#include <libperfstat.h>


/* Check value returned by malloc for NULL */

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

/* WPAR ID for global will always be zero */

#define IS_GLOBAL(X) (!(X))

/* declare interval and count with default value with 1 */ 
int interval = 1;
int count    = 1;
 
/* Define the default interval and count values */

/*
 *Name: showusage
 *      function to display the correct usage 
 *
 */

void showusage()
{
   printf(" Usage:perfdump cpu | cpu_total | memory_total | partition_total | disk_total [interval] [count]\n");
   exit(1);
}

void display_metrics_cpu()
{
   int ncpu, rc, i;
   perfstat_cpu_t *cpu;
   perfstat_id_t id;
   
   /* get the number of cpus in ncpu */  
   ncpu = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0);

   if (ncpu <= 0){
       perror("perfstat_cpu");
       exit(1);
   }

   /* allocate enough memory to hold the ncpu structures */
   cpu = (perfstat_cpu_t *)malloc(ncpu * sizeof(perfstat_cpu_t));
   CHECK_FOR_MALLOC_NULL(cpu);

   while (count){ 
       /* collect all the cpu metrics */ 
       strcpy(id.name, "");
       rc = perfstat_cpu(&id, cpu, sizeof(perfstat_cpu_t), ncpu);
 
       if (rc <= 0){
           perror("perfstat_cpu");
           exit(1);
       }
       /* display the cpu metrics for all cpus */
       for (i = 0;i < ncpu; i++)
            printf("name              = %s\n"
                   "user              = %llu\n"
                   "sys               = %llu\n" 
                   "idle              = %llu\n"
                   "wait              = %llu\n"
                   "pswitch           = %llu\n"
                   "syscall           = %llu\n"
                   "sysread           = %llu\n"
                   "syswrite          = %llu\n"
                   "sysfork           = %llu\n"
                   "sysexec           = %llu\n"
                   "readch            = %llu\n"
                   "writech           = %llu\n"
                   "bread             = %llu\n"
                   "bwrite            = %llu\n"
                   "lread             = %llu\n"
                   "lwrite            = %llu\n"
                   "phread            = %llu\n"
                   "phwrite           = %llu\n"
                   "iget              = %llu\n"
                   "namei             = %llu\n"
                   "dirblk            = %llu\n"
                   "msg               = %llu\n"
                   "sema              = %llu\n"
                   "minfaults         = %llu\n"
                   "majfaults         = %llu\n"
                   "puser             = %llu\n"
                   "psys              = %llu\n"
                   "pidle             = %llu\n"
                   "pwait             = %llu\n"
                   "redisp_sd0        = %llu\n"
                   "redisp_sd1        = %llu\n"
                   "redisp_sd2        = %llu\n"
                   "redisp_sd3        = %llu\n"
                   "redisp_sd4        = %llu\n"
                   "redisp_sd5        = %llu\n"
                   "migration_push    = %llu\n"
                   "migration_S3grq   = %llu\n"
                   "migration_S3pul   = %llu\n"
                   "invol_cswitch     = %llu\n"
                   "vol_cswitch       = %llu\n"
                   "runque            = %llu\n"
                   "bound             = %llu\n"
                   "decrintrs         = %llu\n"
                   "mpcrintrs         = %llu\n"
                   "mpcsintrs         = %llu\n"
                   "devintrs          = %llu\n"
                   "softintrs         = %llu\n"
                   "phantintrs        = %llu\n"
                   "idle_donated_purr = %llu\n"
                   "idle_donated_spurr= %llu\n"
                   "busy_donated_purr = %llu\n"
                   "busy_donated_spurr= %llu\n"
                   "idle_stolen_purr  = %llu\n"
                   "idle_stolen_spurr = %llu\n"
                   "busy_stolen_purr  = %llu\n"
                   "busy_stolen_spurr = %llu\n\n",cpu[i].name, cpu[i].user, cpu[i].sys, cpu[i].idle, cpu[i].wait, cpu[i].pswitch, cpu[i].syscall, cpu[i].sysread,
                                                  cpu[i].syswrite,  cpu[i].sysfork, cpu[i].sysexec, cpu[i].readch, cpu[i].writech, cpu[i].bread, cpu[i].bwrite,
                                                  cpu[i].lread, cpu[i].lwrite, cpu[i].phread, cpu[i].phwrite, cpu[i].iget, cpu[i].namei, cpu[i].dirblk,
                                                  cpu[i].msg, cpu[i].sema, cpu[i].minfaults, cpu[i].majfaults, cpu[i].puser, cpu[i].psys, cpu[i].pidle,
                                                  cpu[i].pwait, cpu[i].redisp_sd0, cpu[i].redisp_sd1, cpu[i].redisp_sd2, cpu[i].redisp_sd3, cpu[i].redisp_sd4,
                                                  cpu[i].redisp_sd5, cpu[i].migration_push, cpu[i].migration_S3grq, cpu[i].migration_S3pul, cpu[i].invol_cswitch,
                                                  cpu[i].vol_cswitch, cpu[i].runque, cpu[i].bound, cpu[i].decrintrs, cpu[i].mpcrintrs, cpu[i].mpcsintrs,
                                                  cpu[i].devintrs, cpu[i].softintrs, cpu[i].phantintrs, cpu[i].idle_donated_purr, cpu[i].idle_donated_spurr,
                                                  cpu[i].busy_donated_purr, cpu[i].busy_donated_spurr, cpu[i].idle_stolen_purr, cpu[i].idle_stolen_spurr,
                                                  cpu[i].busy_stolen_purr, cpu[i].busy_stolen_spurr);
         count--;
         sleep(interval);
   }
   free(cpu);      
   
}  
   

void display_metrics_cpu_total()
{
   int rc, i;
   perfstat_cpu_total_t cpu;
   
   while(count){
       /* collect the total cpu statistics */
       rc = perfstat_cpu_total(NULL, &cpu, sizeof(perfstat_cpu_total_t), 1);

       if (rc <= 0){
           perror("perfstat_cpu_total");
           exit(1);
       }
       /* print the statistics */ 
       printf("ncpus             = %d\n"
              "ncpus_cfg         = %d\n"
              "description       = %s\n"
              "processorHZ       = %llu\n"
              "user              = %llu\n"
              "sys               = %llu\n"
              "idle              = %llu\n"
              "wait              = %llu\n"
              "pswitch           = %llu\n"
              "syscall           = %llu\n"
              "sysread           = %llu\n"
              "syswrite          = %llu\n"
              "sysfork           = %llu\n"
              "sysexec           = %llu\n"
              "readch            = %llu\n"
              "writech           = %llu\n"
              "devintrs          = %llu\n"
              "softintrs         = %llu\n"
              "lbolt             = %d\n"
              "loadavg[0]        = %llu\n"
              "loadavg[1]        = %llu\n"
              "loadavg[2]        = %llu\n"
              "runque            = %llu\n"
              "swpque            = %llu\n"
              "bread             = %llu\n"
              "bwrite            = %llu\n"
              "lread             = %llu\n"
              "lwrite            = %llu\n"
              "phread            = %llu\n"
              "phwrite           = %llu\n"
              "runocc            = %llu\n"
              "swpocc            = %llu\n"
              "iget              = %llu\n"
              "namei             = %llu\n"
              "dirblk            = %llu\n"
              "msg               = %llu\n"
              "sema              = %llu\n"
              "rcvint            = %llu\n"
              "xmtint            = %llu\n"
              "mdmint            = %llu\n"
              "tty_rawinch       = %llu\n"
              "tty_caninch       = %llu\n"
              "tty_rawoutch      = %llu\n"
              "ksched            = %llu\n"
              "koverf            = %llu\n"
              "kexit             = %llu\n"
              "rbread            = %llu\n"
              "rcread            = %llu\n"
              "rbwrt             = %llu\n"
              "rcwrt             = %llu\n"
              "traps             = %llu\n"
              "ncpus_high        = %d\n"
              "puser             = %llu\n"
              "psys              = %llu\n"
              "pidle             = %llu\n"
              "pwait             = %llu\n"
              "decrintrs         = %llu\n"
              "mpcrintrs         = %llu\n"
              "mpcsintrs         = %llu\n"
              "phantintrs        = %llu\n"
              "idle_donated_purr = %llu\n"
              "idle_donated_spurr= %llu\n"
              "busy_donated_purr = %llu\n"
              "busy_donated_spurr= %llu\n"
              "idle_stolen_purr  = %llu\n"
              "idle_stolen_spurr = %llu\n"
              "busy_stolen_purr  = %llu\n"
              "busy_stolen_spurr = %llu\n\n",cpu.ncpus, cpu.ncpus_cfg, cpu.description, cpu.processorHZ, cpu.user, cpu.sys, cpu.idle, cpu.wait, cpu.pswitch,
                                            cpu.syscall, cpu.sysread, cpu.syswrite, cpu.sysfork, cpu.sysexec, cpu.readch, cpu.writech, cpu.devintrs,
                                            cpu.softintrs, cpu.lbolt, cpu.loadavg[0], cpu.loadavg[1], cpu.loadavg[2], cpu.runque,
                                            cpu.swpque, cpu.bread, cpu.bwrite, cpu.lread, cpu.lwrite, cpu.phread, cpu.phwrite, cpu.runocc, cpu.swpocc,
                                            cpu.iget, cpu.namei, cpu.dirblk, cpu.msg, cpu.sema, cpu.rcvint, cpu.xmtint, cpu.mdmint, cpu.tty_rawinch,
                                            cpu.tty_caninch, cpu.tty_rawoutch, cpu.ksched, cpu.koverf, cpu.kexit, cpu.rbread, cpu.rcread, cpu.rbwrt,
                                            cpu.rcwrt, cpu.traps, cpu.ncpus_high, cpu.puser, cpu.psys, cpu.pidle, cpu.pwait, cpu.decrintrs,
                                            cpu.mpcrintrs, cpu.mpcsintrs ,cpu.phantintrs, cpu.idle_donated_purr, cpu.idle_donated_spurr, 
                                            cpu.busy_donated_purr, cpu.busy_donated_spurr, cpu.idle_stolen_purr, cpu.idle_stolen_spurr,
                                            cpu.busy_stolen_purr, cpu.busy_stolen_spurr); 

      count--;
      sleep(interval);

   }
}


void display_metrics_partition_total()
{
   int rc, i;
   perfstat_partition_total_t partition;
  
   while (count){
       /* collect the partition wide statistics*/
       rc = perfstat_partition_total(NULL, &partition, sizeof(perfstat_partition_total_t), 1);

       if (rc <= 0){
           perror("perfstat_partition_total");
           exit(1);
       }

       printf("name                   = %s\n"
              "lpar_id                = %d\n"                       
              "group_id               = %d\n"
              "pool_id                = %d\n"
              "online_cpus            = %d\n"
              "max_cpus               = %d\n"
              "min_cpus               = %d\n"
              "online_memory          = %llu\n"
              "max_memory             = %llu\n"
              "min_memory             = %llu\n"
              "entitled_proc_capacity = %d\n"
              "max_proc_capacity      = %d\n"
              "min_proc_capacity      = %d\n"
              "proc_capacity_increment= %d\n"
              "unalloc_proc_capacity  = %d\n"
              "var_proc_capacity_weight        = %d\n"
              "unalloc_var_proc_capacity_weight= %d\n"
              "online_phys_cpus_sys   = %d\n"
              "max_phys_cpus_sys      = %d\n"
              "phys_cpus_pool         = %d\n"
              "puser                  = %llu\n"
              "psys                   = %llu\n"
              "pidle                  = %llu\n"
              "pwait                  = %llu\n"
              "pool_idle_time         = %llu\n"
              "phantintrs             = %llu\n"
              "invol_virt_cswitch     = %llu\n"
              "vol_virt_cswitch       = %llu\n"
              "timebase_last          = %llu\n"
              "reserved_pages         = %llu\n"
              "reserved_pagesize      = %llu\n"
              "idle_donated_purr      = %llu\n"
              "idle_donated_spurr     = %llu\n"
              "busy_donated_purr      = %llu\n"
              "busy_donated_spurr     = %llu\n"
              "idle_stolen_purr       = %llu\n"
              "idle_stolen_spurr      = %llu\n"
              "busy_stolen_purr       = %llu\n"
              "busy_stolen_spurr      = %llu\n"
              "shcpus_in_sys          = %llu\n"
              "max_pool_capacity      = %llu\n"
              "entitled_pool_capacity = %llu\n"
              "pool_max_time          = %llu\n"
              "pool_busy_time         = %llu\n"
              "pool_scaled_busy_time  = %llu\n"
              "shcpu_tot_time         = %llu\n"
              "shcpu_busy_time        = %llu\n"
              "shcpu_scaled_busy_time = %llu\n\n",partition.name, partition.lpar_id, partition.group_id, partition.pool_id, partition.online_cpus,
                                                 partition.max_cpus, partition.min_cpus, partition.online_memory, partition.max_memory,
                                                 partition.min_memory, partition.entitled_proc_capacity, partition.max_proc_capacity,
                                                 partition.min_proc_capacity, partition.proc_capacity_increment, partition.unalloc_proc_capacity,
                                                 partition.var_proc_capacity_weight, partition.var_proc_capacity_weight,
                                                 partition.online_phys_cpus_sys, partition.max_phys_cpus_sys, partition.phys_cpus_pool,
                                                 partition.puser, partition.psys, partition.pidle, partition.pwait, partition.pool_idle_time,
                                                 partition.phantintrs, partition.invol_virt_cswitch, partition.vol_virt_cswitch,
                                                 partition.timebase_last, partition.reserved_pages,partition.reserved_pagesize,
                                                 partition.idle_donated_purr, partition.idle_donated_spurr, partition.busy_donated_purr,
                                                 partition.busy_donated_spurr, partition.idle_stolen_purr, partition.idle_stolen_spurr,
                                                 partition.busy_stolen_purr, partition.busy_stolen_spurr, partition.shcpus_in_sys,
                                                 partition.max_pool_capacity, partition.entitled_pool_capacity, partition.pool_max_time,
                                                 partition.pool_busy_time, partition.pool_scaled_busy_time, partition.shcpu_tot_time,
                                                 partition.shcpu_busy_time, partition.shcpu_scaled_busy_time);

       count--;
       sleep(interval);
   }

}

void display_metrics_memory_total()
{
   int rc, i;
   perfstat_memory_total_t memory;
   
   while (count){
       /* collect the memory statistics */
       rc = perfstat_memory_total(NULL, &memory, sizeof(perfstat_memory_total_t), 1);

       if (rc <= 0){
           perror("perfstat_memory_total");
           exit(1);
       }
       /* print the statistics */ 
       printf("virt_total    = %llu\n"
              "real_total    = %llu\n"
              "real_free     = %llu\n"
              "real_pinned   = %llu\n"
              "real_inuse    = %llu\n"
              "pgbad         = %llu\n"
              "pgexct        = %llu\n"
              "pgins         = %llu\n"
              "pgouts        = %llu\n"
              "pgspins       = %llu\n"
              "pgspouts      = %llu\n"
              "scans         = %llu\n"
              "cycles        = %llu\n"
              "pgsteals      = %llu\n"
              "numperm       = %llu\n"
              "pgsp_total    = %llu\n"
              "pgsp_free     = %llu\n"
              "pgsp_rsvd     = %llu\n"
              "real_system   = %llu\n"
              "real_user     = %llu\n"
              "real_process  = %llu\n",memory.virt_total, memory.real_total, memory.real_free, memory.real_pinned, memory.real_inuse, memory.pgbad,
                                       memory.pgexct, memory.pgins, memory.pgouts, memory.pgspins, memory.pgspouts, memory.scans, memory.cycles,
                                       memory.pgsteals, memory.numperm, memory.pgsp_total, memory.pgsp_free, memory.pgsp_rsvd, memory.real_system,
                                       memory.real_user, memory.real_process);
   
      count--;
     
      sleep(interval);
   }
           
}


void display_metrics_disk_total()
{
   int rc, i;
   perfstat_disk_total_t disk;

   while(count){
       /* collect the disk_total metrics */
       rc = perfstat_disk_total(NULL, &disk, sizeof(perfstat_disk_total_t), 1);

       /* if any error exit with error message */ 
       if (rc <= 0){
           perror("perfstat_disk_total");
           exit(1);
       }

       /* print all the metrics */
       printf("number     = %d\n"
              "size       = %llu\n"
              "free       = %llu\n"
              "xrate      = %llu\n"
              "xfers      = %llu\n"
              "rblks      = %llu\n"
              "wblks      = %llu\n"
              "time       = %llu\n\n",disk.number, disk.size, disk.free, disk.xrate, disk.xfers, disk.rblks, disk.wblks, disk.time);
      
       /* reduce the count and wait for the interval period */ 
       count--;
       sleep(interval);
   }

}
           
/* 
 *Name: main
 *
 */

int main(int argc, char *argv[]) 
{
   int cid;
   
   /* get the corralid of the current corral */
   cid = corral_getcid();
   
   /*exit with a error message if running inside a wpar */
   if(!IS_GLOBAL(cid)){
      printf("perfdump displays metrics only in global.\n");
      exit(1);
   }
  
   /* get all the arguments and validate them */
   if (argc < 2)
       showusage();

   /* get the interval and count values */
   if ( argc == 3 ) {
           if ((interval = atoi(argv[2])) <= 0)
            showusage();
   }
   else if (argc == 4) {
        if ((interval = atoi(argv[2])) <= 0)
            showusage();
        if ((count = atoi(argv[3])) <= 0)
            showusage();
   }

   /*check which metrics need to be returned and move to that particular function */ 
   if (!strcmp(argv[1], "cpu"))
       display_metrics_cpu();
   
   else if (!strcmp(argv[1], "cpu_total"))
       display_metrics_cpu_total();

   else if (!strcmp(argv[1], "partition_total"))
       display_metrics_partition_total();
  
   else if (!strcmp(argv[1], "memory_total"))
       display_metrics_memory_total();

   else if (!strcmp(argv[1], "disk_total"))
       display_metrics_disk_total();

   else{
       showusage();
       exit(1);
   } 
   
   return(0);    
}

