From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 30-NOV-1989 11:39
To:	MRGATE::"ARISIA::EVERHART"
Subj:	PerfMeter V2.0 for DECWindows/VMS, Part 2 of 5 Parts

Received: From CRASH.CS.UMASS.EDU by GIZMO.SRI.COM with TCP; Thu, 30 NOV 89 06:34:59 PDT
Received: from vax3.cs.umass.edu by crash.cs.umass.edu (5.61/Ultrix2.0-B)
	id AA08106; Thu, 30 Nov 89 09:31:48 -0500
Message-Id: <8911301431.AA08106@crash.cs.umass.edu>
Date: Thu, 30 Nov 89 09:30 EST
From: "From the screen of Deneva...  30-Nov-1989 0929" <HELLER@cs.umass.EDU>
Subject: PerfMeter V2.0 for DECWindows/VMS, Part 2 of 5 Parts
To: info-vax@kl.sri.COM
X-Vms-To: coins::in%"info-vax@kl.sri.com"

$ File_is="PERF_METER.C"
$ Check_Sum_is=542159023
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X/* -*-c-mode-*- */
X/*------------------------------------------------------
X *  PERF_METER.C - Performance Meter display for DECWindows
X *  Robert Heller Created on Wed Nov  8 10:39:17 1989
X *  Last mod -
X *      Mark Pizzolato 11/22/89 - mark@infopiz.uucp (uunet!lupine!infopiz!mark)
X *	Robert Heller Mon Nov 27 12:27:53 1989 - fixed for invert displays
X *------------------------------------------------------*/
X
X#include <stdio.h>                              /* For printf and so on. */
X#include <ctype.h>
X#include <descrip.h>
X#include <ssdef.h>
X#include <jpidef.h>
X#include <dvidef.h>
X#include <syidef.h>
X#include "cpudef.h"
X
Xglobalref long int EXE$GL_ABSTIM_TICS;
Xglobalref long int SMP$GL_ACTIVE_CPUS;
Xglobalref $CPU *SMP$GL_CPU_DATA[1];
X
Xglobalref long int PMS$GL_FAULTS;
Xglobalref long int PMS$GL_PREADS;
Xglobalref long int PMS$GL_PREADIO;
Xglobalref long int PMS$GL_PWRITES;
Xglobalref long int PMS$GL_PWRITIO;
Xglobalref long int PMS$GL_DZROFLTS;
X
X
Xglobalref long int SCH$GL_FREECNT;
Xglobalref long int SCH$GL_MFYCNT;
X
X#define current_faults (PMS$GL_FAULTS)
X#define current_pageio (PMS$GL_PREADIO + PMS$GL_PWRITIO)
X#define current_freepages (SCH$GL_FREECNT)
X#define current_modpages (SCH$GL_MFYCNT)
X
X
X#ifdef VMS
X#include <decw$include/DwtAppl.h>       /* DECwindows Toolkit */
X#else
X#include <X11/DwtAppl.h>                /* DECwindows Toolkit */
X#endif
X
X#define FAILED(status) (((status)&1) == 0)
X#define SIGNAL_ERROR(status) 				\
X    {							\
X    int ___status = status;				\
X							\
X    if (FAILED(___status))				\
X	lib$signal(___status);				\
X    }
X
X#include "perf_meter_const.h"
X
X
X#define MAX_WIDGETS (MAX_WIDGET + 1)
X
X/*
X * Global data
X */
X
Xstatic Widget toplevel_widget,          /* Root widget ID of our */
X                                        /* application. */
X  main_window_widget,                   /* Root widget ID of main */
X                                        /* DRM fetch */
X  generic_message_widget,		/* generic message box */
X  generic_caution_widget,		/* generic caution box */
X  generic_wip_widget;			/* generic WIP box */
Xnoshare widget_array[MAX_WIDGETS];            /* Place to keep all other */
X                                        /* widget IDs */
X
Xstatic Display *cpu_graph_disp, *state_graph_disp;
Xstatic Window   cpu_graph_wind = 0,  state_graph_wind = 0;
Xstatic GC       cpu_graph_gc1,    state_graph_gc1;
Xstatic GC       cpu_graph_gc0,    state_graph_gc0;
X
X
Xstatic DwtCompString latin_create;      /* Variables for */
Xstatic DwtCompString latin_dismiss;     /* compound strings. */
Xstatic DwtCompString latin_space;
Xstatic DwtCompString latin_zero;
Xstatic DRMHierarchy s_DRMHierarchy;     /* DRM database hierarchy ID */
Xstatic DRMType *dummy_class;            /* and class variable. */
Xstatic char *db_filename_vec[] =        /* DRM heirachy file list. */
X  {"pfm$data:perf_meter.uid"		                /* There is only one UID file for */
X  };                                    /* this application. */
Xstatic int db_filename_num =
X                (sizeof db_filename_vec / sizeof db_filename_vec [0]);
X
X#define PFM_CUSTOMIZE_FILE "DECW$USER_DEFAULTS:DECW$PFM.DAT"
X#define SYS_PFM_CUSTOMIZE_FILE "DECW$SYSTEM_DEFAULTS:DECW$PFM.DAT"
X
Xstatic int  main_xpos = 0, main_ypos = 50;
Xstatic int update_period = 5;
Xstatic long int N10PerSec = -1*(10*1000*1000);
Xstatic int TIMER_EFN;
Xstatic int  settings_modified_p = FALSE;
X
Xstatic readonly struct {
X	char *parameter_name;
X	int  parameter_type;
X#define PARAM_STRING 0
X#define PARAM_INTEGER 1
X	char *parameter_value;
X	int parameter_size;
X	} parameter_specs[] = {
X	{"PerfMeter.XPos", PARAM_INTEGER, &main_xpos, sizeof(main_xpos)},
X	{"PerfMeter.YPos", PARAM_INTEGER, &main_ypos, sizeof(main_ypos)},
X	{"PerfMeter.UpdatePeriod", PARAM_INTEGER, &update_period,
X	 sizeof(update_period)},
X	{NULL, 0, NULL, 0}
X	};
X
X/*
X * Forward declarations
X */
X
Xvoid s_error();
Xvoid get_something();
Xstatic void set_something();
X
Xstatic void activate_proc();
Xstatic void create_proc();
Xstatic void cancel_proc();
Xstatic void update();
X
Xstatic GC MakeGC();
X
X/* The names and addresses of things that DRM has to bind.  The names do
X * not have to be in alphabetical order.  */
X
Xstatic DRMRegisterArg reglist[] = {
X	{"ACTIVATE_PROC", (caddr_t) activate_proc},
X	{"CREATE_PROC", (caddr_t) create_proc},
X	{"CANCEL_PROC", (caddr_t) cancel_proc}
X};
X
Xstatic int reglist_num = (sizeof reglist / sizeof reglist [0]);
X
Xstatic char nodename[16];
Xstatic $DESCRIPTOR(NODE,nodename);
X
X/*
X * OS transfer point.  The main routine does all the one-time setup and
X * then calls XtMainLoop.
X */
X
Xunsigned int main(argc, argv)
Xunsigned int argc;                  /* Command line argument count. */
Xchar *argv[];                       /* Pointers to command line args. */
X    {
X    static long int utime[2];
X    register int status, i;
X    long int timeup_p;
X    XEvent event;
X    static char header[128];
X    static unsigned short int nlen;
X    static struct {
X	unsigned short blen, icode;
X	char *baddr;
X	unsigned short int *rlen;
X	} syi_itmlst[] = {
X	{sizeof(nodename)-2, SYI$_SCSNODE, nodename, &nlen},
X	{0, 0, NULL, NULL} };
X
X
X    sys$getsyiw(0,0,0,syi_itmlst,0,0,0);
X
X    for (i = nlen; i >= 0 && nodename[i] == ' '; i--) nodename[i] = '\0';
X    sprintf(header,"System Performance Meters (V2.0) on %s",nodename);
X    NODE.dsc$w_length = strlen(nodename);
X
X
X    read_sys_customization_file();
X    read_customization_file();
X
X    DwtInitializeDRM();                 /* Initialize DRM before initializing
X                                        /* the X Toolkit. */
X
X    /* If we had user-defined widgets, we would register them with DRM here. */
X
X    /* Initialize the X Toolkit. We get back a top level shell widget. */
X
X    toplevel_widget = XtInitialize(header,      /* Main window banner text. */
X				   "PerfMeter", /* Root class name. */
X				   NULL,        /* No option list. */
X				   0,           /* Number of options. */
X				   &argc,       /* Address of argc */
X				   argv);       /* argv */
X
X
X    /* Open the UID files (the output of the UIL compiler) in the hierarchy*/
X
X    if (DwtOpenHierarchy(db_filename_num, /* Number of files. */
X		         db_filename_vec, /* Array of file names.  */
X			 NULL,            /* Default OS extenstion. */
X			 &s_DRMHierarchy) /* Pointer to returned DRM ID */
X				         !=DRMSuccess)
X        s_error("can't open hierarchy");
X
X    init_application();
X
X    /* Register the items DRM needs to bind for us. */
X
X    DwtRegisterDRMNames(reglist, reglist_num);
X
X    /* Go get the main part of the application. */
X    if (DwtFetchWidget(s_DRMHierarchy, "PERF_METER_MAIN", toplevel_widget,
X      &main_window_widget, &dummy_class) != DRMSuccess)
X        s_error("can't fetch main window");
X
X    /* Manage the main part and realize everything.  The interface comes up
X     * on the display now. */
X
X    XtManageChild(main_window_widget);
X    set_something(toplevel_widget,DwtNx,main_xpos);
X    set_something(toplevel_widget,DwtNy,main_ypos);
X    XtRealizeWidget(toplevel_widget);
X
X    XtAddTimeOut(update_period*1000, update, 0);
X
X    XtMainLoop();
X    }
X
X/*
X * One-time initialization of application data structures.
X */
X
Xstatic int init_application()
X    {
X    int k;
X
X    /* Initialize the application data structures. */
X    for (k = 0; k < MAX_WIDGETS; k++)
X        widget_array[k] = NULL;
X    init_cpu_times();
X    }
X
Xread_customization_file()
X    {
X    register char *p, *q;
X    char *fgets();
X    FILE *custfile;
X    static char temp[1024];
X
X    custfile = fopen(PFM_CUSTOMIZE_FILE,"r");
X    if (custfile != NULL) {
X	while ((p = fgets(temp,1024,custfile)) != NULL) {
X	    q = strchr(p,'!'); if (q != NULL) *q = '\0';
X	    q = strchr(p,'\n'); if (q != NULL) *q = '\0';
X	    process_cust_line(p);
X	    }
X	fclose(custfile);
X	}
X    }
X
Xread_sys_customization_file()
X    {
X    register char *p, *q;
X    char *fgets();
X    FILE *custfile;
X    static char temp[1024];
X
X    main_xpos = 0; main_ypos =  95;
X    update_period = 5;
X    custfile = fopen(SYS_PFM_CUSTOMIZE_FILE,"r");
X    if (custfile != NULL) {
X	while ((p = fgets(temp,1024,custfile)) != NULL) {
X	    q = strchr(p,'!'); if (q != NULL) *q = '\0';
X	    q = strchr(p,'\n'); if (q != NULL) *q = '\0';
X	    process_cust_line(p);
X	    }
X	fclose(custfile);
X	}
X    }
X
Xstatic process_cust_line(p)
Xregister char *p;
X    {
X    register int i;
X    register char *eq;
X    char *compare_param();
X
X    while (*p != '\0' && isspace(*p)) p++;
X    if (*p == '\0') return;
X    for (i = 0; parameter_specs[i].parameter_name != NULL; i++) {
X	eq = compare_param(p,parameter_specs[i].parameter_name);
X	if (eq != NULL) {
X	    switch (parameter_specs[i].parameter_type) {
X		case PARAM_STRING:
X		    strncpy(parameter_specs[i].parameter_value,eq+1,parameter_specs[i].parameter_size-1);
X		    parameter_specs[i].parameter_value[parameter_specs[i].parameter_size-1] = '\0';
X		    break;
X		case PARAM_INTEGER:
X		    *((int *) parameter_specs[i].parameter_value) = atoi(eq+1);
X		    break;
X	    	}
X	    break;
X	    }
X	}
X    }
X
Xstatic char *compare_param(test,pname)
Xregister char *test, *pname;
X    {
X    register char *p, *q;
X
X    for (p = test, q = pname; *q != '\0'; q++) {
X        if (*p == *q) p++;
X	else if (*p == '\0') return(NULL);
X	else if (*p == '=') return(NULL);
X	else if (*p == '*') {
X	    while (*(p+1) == '*') p++;
X	    if (*(q+1) == '\0') p++;
X	    else if (*(q+1) == *(p+1)) p++;
X	    }
X	else if (*p == '%') p++;
X	else return(NULL);
X	}
X    while (*p != '\0' && isspace(*p)) p++;
X    if (*p == '=') return(p);
X    else return(NULL);
X    }
X
X/***************************************************************************
X *
X * These are some little utilities used by the callback routines.
X */
X
X
X/*
X * All errors are fatal.
X */
X
Xstatic void s_error(problem_string)
Xchar *problem_string;
X    {
X    printf("%s\n", problem_string);
X    exit(0);
X    }
X
X/*
X * Simplified SET VALUE routine to use only when changing a single attribute.
X * If we need to change more than one, all new values should be put
X * into one arglist and we should make one XtSetValues call (which is MUCH
X * more efficient).
X */
X
Xstatic void set_something(w, resource, value)
XWidget w;
Xchar *resource, *value;
X    {
X    Arg al[1];
X
X    XtSetArg(al[0], resource, value);
X    XtSetValues(w, al, 1);
X    }
X
X
X/*
X * Simplified GET VALUE routine to use only when retrieving a single attribute.
X * If we need to retrieve more than one, all values should be put
X * into one arglist and we should make one XtGetValues call (which is MUCH
X * more efficient).
X */
X
Xstatic void get_something(w, resource, value)
XWidget w;
Xchar *resource, *value;
X    {
X    Arg al[1];
X
X    XtSetArg(al[0], resource, value);
X    XtGetValues(w, al, 1);
X    }
X
X
Xint get_widget_if_needed (index, name)
Xint index;
Xchar *name;
X    {
X    if (widget_array[index] == NULL) {
X	if (DwtFetchWidget(s_DRMHierarchy,name,toplevel_widget,
X			   &widget_array[index],&dummy_class) != DRMSuccess)
X	    return(FALSE);
X	}
X    return(TRUE);
X    }
X
X/*
X * All widgets that are created call back to this procedure. We just log the
X * ID in the global array.
X */
X
Xstatic void create_proc(w, tag, reason)
XWidget w;
Xint *tag;
Xunsigned long *reason;
X    {
X    int widget_num = *tag;
X
X    widget_array[widget_num] = w;
X
X    switch (widget_num) {
X	case PFM_CPU_GRAPH:
X	    cpu_graph_disp = XtDisplay(w);
X	    break;
X	case PFM_STATE_GRAPH:
X	    state_graph_disp = XtDisplay(w);
X	    break;
X	case PFM_DEVICE_0_IOCOUNT_NAME:
X	    update_disk_name_label(w, 0);
X	    break;
X	case PFM_DEVICE_1_IOCOUNT_NAME:
X	    update_disk_name_label(w, 1);
X	    break;
X	case PFM_DEVICE_2_IOCOUNT_NAME:
X	    update_disk_name_label(w, 2);
X	    break;
X	case PFM_DEVICE_3_IOCOUNT_NAME:
X	    update_disk_name_label(w, 3);
X	    break;
X        default:
X            break;
X	}
X
X    }
X
X/*
X * All push buttons in this application call back to this routine.  We
X * use the tag to tell us what widget it is, then react accordingly.
X */
X
Xstatic void activate_proc(w, tag, reason)
XWidget w;
Xint *tag;
Xunsigned long *reason;
X    {
X    int widget_num = *tag;              /* Convert tag to widget number. */
X
X    switch (widget_num) {
X	case PFM_EXIT_BUTTON: exit();
X	default: break;
X	}
X    }
X
Xstatic void cancel_proc(w, tag, reason)
XWidget w;
Xint *tag;
Xunsigned long *reason;
X    {
X    int widget_num = *tag;              /* Convert tag to widget number. */
X
X    switch (widget_num) {
X	default: break;
X	}
X    }
X
Xstatic int CPUPercent[101] = {
X    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
X    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
X    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
X    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
X    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
X    0};
X
Xstatic int Device_0_IO = -1,
X	   Device_1_IO = -1,
X	   Device_2_IO = -1,
X	   Device_3_IO = -1;
X
Xstatic int PageFaults = -1,
X	   PageIO = -1,
X	   FreePages = -1,
X	   ModPages = -1;
X
X
X#define CompTimeX  2
X#define NullTimeX 12
X#define UserTimeX 22
X#define SupeTimeX 32
X#define ExecTimeX 42
X#define KernTimeX 52
X#define InteTimeX 62
X
X#define StateBarWidth 7
X
Xstatic void update()
X    {
X    static int NewNullTime,
X	   NewUserTime,
X	   NewSupeTime,
X	   NewExecTime,
X	   NewKernTime,
X	   NewInteTime,
X	   NewCompTime,
X	   NewDevice_0_IO, DeltaDevice_0_IO, LastDeltaDevice_0_IO = -1,
X	   NewDevice_1_IO, DeltaDevice_1_IO, LastDeltaDevice_1_IO = -1,

