/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* perf720 src/perf/perfagent/usr/samples/perfagent/server/SpmiPeek.c 1.4 */
/*                                                                        */
/*                                                                        */
/*                                                                        */
/* OBJECT CODE ONLY SOURCE MATERIALS                                      */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 1992,1993              */
/* All Rights Reserved                                                    */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/*
 *   COMPONENT_NAME: PERFAGENT
 *
 *   FUNCTIONS: findstats
 *		lststats
 *		main
 *
 *   ORIGINS: 30
 *
 *
 *   (C) COPYRIGHT International Business Machines Corp. 1992,1993
 *   All Rights Reserved
 *   Licensed Materials - Property of IBM
 *   US Government Users Restricted Rights - Use, duplication or
 *   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 *
 *       NOTICE TO USERS OF THE SOURCE CODE EXAMPLES
 *
 * THE SOURCE CODE EXAMPLES PROVIDED BY IBM ARE ONLY INTENDED TO ASSIST IN THE
 * DEVELOPMENT OF A WORKING SOFTWARE PROGRAM.  THE SOURCE CODE EXAMPLES DO NOT
 * FUNCTION AS WRITTEN:  ADDITIONAL CODE IS REQUIRED.  IN ADDITION, THE SOURCE
 * CODE EXAMPLES MAY NOT COMPILE AND/OR BIND SUCCESSFULLY AS WRITTEN.
 * 
 * INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THE SOURCE CODE
 * EXAMPLES, BOTH INDIVIDUALLY AND AS ONE OR MORE GROUPS, "AS IS" WITHOUT
 * WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
 * LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
 * OF THE SOURCE CODE EXAMPLES, BOTH INDIVIDUALLY AND AS ONE OR MORE GROUPS,
 * IS WITH YOU.  SHOULD ANY PART OF THE SOURCE CODE EXAMPLES PROVE
 * DEFECTIVE, YOU (AND NOT IBM OR AN AUTHORIZED RISC System/6000* WORKSTATION
 * DEALER) ASSUME THE ENTIRE COST OF ALL NECESSARY SERVICING, REPAIR OR
 * CORRECTION.
 * 
 * IBM does not warrant that the contents of the source code examples, whether
 * individually or as one or more groups, will meet your requirements or that
 * the source code examples are error-free.
 * 
 * IBM may make improvements and/or changes in the source code examples at
 * any time.
 * 
 * Changes may be made periodically to the information in the source code
 * examples; these changes may be reported, for the sample device drivers
 * included herein, in new editions of the examples.
 * 
 * References in the source code examples to IBM products, programs, or
 * services do not imply that IBM intends to make these available in all
 * countries in which IBM operates.  Any reference to an IBM licensed
 * program in the source code examples is not intended to state or imply
 * that only IBM's licensed program may be used.  Any functionally equivalent
 * program may be used.
 * 
 * RISC System/6000 is a trademark of International Business Machines
 * Corporation.
 *
 */

static char *Sccs_id = "@(#)18  1.3  src/perf/perfagent/usr/samples/perfagent/server/SpmiPeek.c, perfagent, perf411, 9430C411a 7/29/94 17:32:53";

/* EXECUTION NOTES:  
 * SpmiPeek is a sample program.  If SpmiPeek is invoked without any options,
 * information about the statistics and contexts are output to the screen.
 *
 * The output will look similar to the following:
 * CPU                           Central processor statistics
 * CPU/cpu0                           Central processor #0
 * CPU/cpu0/user                        Time executing in user mode (percent)
 *                                       Data Type(Float)  Value Type(Quantity)
 *                                       min = 0   max = 100
 * CPU/cpu0/kern                         Time executing in kernel mode (percent)
 *                                       Data Type(Float)  Value Type(Quantity)
 *                                       min = 0   max = 100
 * Mem                           Memory statistics
 * Mem/Real                          Physical memory statistics
 * Mem/Real/size                         Size of physical memory (4K pages)
 *                                       Data Type(Long)   Value Type(Quantity)
 *                                       min = 0   max = 20000
 *
 * SpmiPeek has one option (-l).  This option will only display a list of
 * the statistics name.  No information is displayed about these stats.  
 * This list can be re-directed to an output file, and then used as input 
 * to the SpmiLogger program.  The SpmiLogger program only takes a maximum of 
 * 28 statistics, so the user will need to modify the SpmiLogger input file.
 */

#include <sys/types.h>
#include <sys/errno.h>
#include <stdio.h>
#include <sys/Spmidef.h>

extern char  	SpmiErrmsg[];             /* Error Msg array */
extern int      SpmiErrno;		  /* Error Number */

char		stats[256];              /* statistic name info */
char		cxt[256];                /* context name info */
char		subcxt[256];    	 /* text holder */
char		*blanks="                                                  ";
char		*blank2="                                          ";
int		instantiable=0;
int		listflag=0;

/*============================= findstats() ===============================*/
/* findstats is a function that traverses recursively down a context link. */
/* When the end of the context link is found, findstats traverses down the */
/* statistics links and writes the statistic name to stdout.               */
/* findstats is originally passed the context handle for the TOP context.  */
/*=========================================================================*/

#ifdef _NO_PROTO
void findstats(cxhdl)
SpmiCxHdl cxhdl;
#else
void findstats(SpmiCxHdl cxhdl)
#endif
{
   struct SpmiCxLink	*cxlink;
   struct SpmiStatLink	*statlink;
   struct SpmiCx	*spmicx, *spmicxparent;
   struct SpmiStat	*spmistat;
   char			*statname;
   char			num_string[30];
   int			cxtlen1, cxtlen2, descplace;

   /* Get first context */
   if (cxlink = SpmiFirstCx(cxhdl))
   {
      while (cxlink)
      {
         /* output context name */
         spmicx = SpmiGetCx(cxlink->context);
         if (spmicx == NULL)
         {
             printf("ERROR:  SpmiGetCx Failed\n");
             if (strlen(SpmiErrmsg))
                 printf("%s\n", SpmiErrmsg);
             exit(-1);
         }

         /* if the subcxt is a child of another context */
         if (!subcxt[0])
         {
             strcat(subcxt,"/");
             strcat(subcxt,spmicx->name);
         }
         else
             strcpy(subcxt,spmicx->name);

         cxtlen1 = strlen(spmicx->name);
         cxtlen2 = strlen(subcxt);

         /* determine if the context's parent is instantiable */
         /* because we don't want to have to print stats twice */
         spmicxparent = SpmiGetCx(spmicx->parent);
         if (spmicxparent == NULL)
         {
             printf("ERROR:  SpmiGetCx Failed\n");
             if (strlen(SpmiErrmsg))
                 printf("%s\n", SpmiErrmsg);
             exit(-1);
         }
         if ( spmicxparent->inst_freq == SiContInst )
             instantiable++;
         else
             instantiable = 0;

         /* only want to print out the stats for any contexts */
         /* whose parents aren't instantiable.  If the parent */
         /* is instantiable then you only want to print out   */
         /* the stats for the first instance of that parent. */
         if (instantiable <= 1)
         {
             strcpy(cxt,subcxt);
             if (!instantiable)
             {
                 if (cxtlen1 == cxtlen2)
                     descplace = 30 - cxtlen2;
                 else
                     descplace = 35 - cxtlen2;
                 strncat(cxt,blanks,descplace);
                 strcat(cxt,spmicx->description);
             }

	     if (!listflag)
             	printf("%s\n",cxt);

             /* Traverse the stats list for the context */
             if (statlink = SpmiFirstStat(cxlink->context))
             {
                 while (statlink)
                 {
                    spmistat = SpmiGetStat(statlink->stat);
                    if (spmistat == NULL)
                    {
                        printf("ERROR:  SpmiGetStat Failed\n");
                        if (strlen(SpmiErrmsg))
                            printf("%s\n", SpmiErrmsg);
                        exit(-1);
                     }
                     statname = SpmiStatGetPath(cxlink->context, 
                                                statlink->stat, 10);
                     if (statname == NULL)
                     {
                         printf("ERROR:  SpmiStatGetPath Failed\n");
                         if (strlen(SpmiErrmsg))
                             printf("%s\n", SpmiErrmsg);
                         exit(-1);
                     }

                     /* output statistic name */
                     strcpy(stats, statname);
		     if (!listflag)
		     {
                     	descplace = strlen(stats);
                     	descplace = 40 - descplace;
                     	strncat(stats, blanks,descplace);
                     	strcat(stats, spmistat->description);
		     }
                     printf("%s\n",stats);

                     /* output stat info */
		     if (!listflag)
		     {
                     	strcpy(stats, "Data Type(");
                     	if (spmistat->data_type == SiLong)
                         	strcat(stats, "Long) ");
                     	else
                         	strcat(stats, "Float)");
                     	strcat(stats, "  Value Type(");
                     	if (spmistat->value_type == SiCounter)
                         	strcat(stats, "Counter)");
                     	else
                         	strcat(stats, "Quantity)");
                     	printf("%s%s\n", blank2, stats);

                     	/* output max/min info */
                     	sprintf(num_string,"min = %ld   max = %ld",
                                         spmistat->min, spmistat->max);
                     	strcpy(stats, num_string);
                     	printf("%s%s\n", blank2, stats);
		     }
					
                     /* Go to next statistic */
                     statlink = SpmiNextStat(statlink);
                 }  /* end while(statlink) */
             }  /* end if (statlink) */
         }  /* end if (instantiable) */
         else
         {
             /* print out stat name info for stats with */
             /* instantiable parents */
	     if (!listflag) 
	     {
             	strcpy(cxt, spmicxparent->name);
             	strcat(cxt, "/");
             	strcat(cxt, spmicx->name);
             	strcat(cxt, "/.....");
             	cxtlen1 = strlen(spmicx->name) + 6;

             	printf("%s\n", cxt);
             }
         }

         /* recursive call to function */
         /* this gets the next context link */
         findstats(cxlink->context);

         if (cxtlen2 == cxtlen1)
             subcxt[0] = '\0';
         else
             subcxt[cxtlen2-cxtlen1-1] = '\0';

         /* Go to next context */
         cxlink = SpmiNextCx(cxlink);
      }  /* end while(cxlink) */
   }  /* end if (cxlink) */
   return;
}

/*============================= lststats() ===============================*/
/*  lststats gets the TOP context handle.  This handle is then passed to  */
/*  the findstats routine                                                 */
/*========================================================================*/

void lststats()
{
	SpmiCxHdl  cxhdl;

	if ((cxhdl = SpmiPathGetCx(NULL, NULL)) == NULL)
	{
		printf("ERROR:  SpmiPathGetCx Failed.\n");
		if (strlen(SpmiErrmsg))
			printf("%s", SpmiErrmsg);
		return;
	}
	
	/* routine to traverse the context links */
	findstats(cxhdl);

	return;
}

/*================================  main()  ============================*/

#ifdef _NO_PROTO
main(argc, argv)
int argc;
char **argv;
#else
main(int argc, char **argv)
#endif
{
	int spmierr = 0;
        int errflag = 0;
        int c;

        while ((c = getopt(argc, argv, "l")) != EOF)
        {
                switch (c)
                {
                    case 'l':
                               listflag++;
                               break;
                    case '?':
                               errflag++;
                               break;
                }
        }

        if (errflag)
        {
      	    printf("Usage:  SpmiPeek [-l ]\n");
            printf("        Flags:  -l  Generates a statistics list.\n");
	    exit(0);
        }

        /* Initialize SPMI interface */
        if ((spmierr = SpmiInit(15)) != 0)
        {
                printf("ERROR:  SpmiInit Failed\n");
                if (strlen(SpmiErrmsg))
                    printf("%s", SpmiErrmsg);
                exit(-98);
        }

	/* Traversal routine. */
	lststats();
 
	/* Exit SPMI Interface */
	SpmiExit();
	if (SpmiErrno)
	{
		printf("ERROR:  SpmiExit Failed.\n");
		if (strlen(SpmiErrmsg))
		    printf("%s", SpmiErrmsg);
	}

	exit(0);
}
