[Orca-checkins] r412 - trunk/orca/lib/SE/3.4

dmberezin at hotmail.com dmberezin at hotmail.com
Wed Feb 9 12:15:55 PST 2005


Author: dmberezin at hotmail.com
Date: Wed Feb  9 12:08:55 2005
New Revision: 412

Added:
   trunk/orca/lib/SE/3.4/
   trunk/orca/lib/SE/3.4/live_rules.se
   trunk/orca/lib/SE/3.4/orca_p_netstat_class.se
   trunk/orca/lib/SE/3.4/orca_p_vmstat_class.se
   trunk/orca/lib/SE/3.4/orca_process_class.se
   trunk/orca/lib/SE/3.4/workinfo_class.se
Log:
Add support for SE 3.4

* lib/SE/3.4/live_rules.se
* lib/SE/3.4/orca_p_netstat_class.se
* lib/SE/3.4/workinfo_class.se
* lib/SE/3.4/orca_p_vmstat_class.se
* lib/SE/3.4/orca_process_class.se
  Copy all files from version 3.3.1 except for tapeinfo.se - it is now
  included with SE.


Added: trunk/orca/lib/SE/3.4/live_rules.se
==============================================================================
--- (empty file)
+++ trunk/orca/lib/SE/3.4/live_rules.se	Wed Feb  9 12:08:55 2005
@@ -0,0 +1,977 @@
+//
+//    Copyright (c) 1995-1998, by Sun Microsystems, Inc. 
+//      All Rights Reserved
+//
+
+#ifndef _LIVE_RULES_SE_
+#define _LIVE_RULES_SE_
+
+/*
+
+Written by Adrian Cockcroft, based on Appendix A of "Sun Performance
+and Tuning", ISBN 0-13-095249-4
+
+Version 1.8	31 May 99	Added disk errors to disk rule
+Version 1.7	19 Mar 99	Make GLOBAL_disk a dynamic array
+Version 1.6	17 Feb 99	Fixes to partition exclusion code
+Version 1.5	25 Jul 98	Updated mutex rule data feed
+Version 1.4	26 Dec 97	Fixes for disk_count in 2.6 disk rule
+Version 1.3	 7 Nov 97	Fixed handspread for ram rule
+Version 1.2	23 Oct 97	Fixes for 2.6 partitions
+Version 1.1	 8 Oct 96	Use explanations from pure rules
+Version 1.00	 9 Aug 96	Extra info for new net_rule
+Version 0.20	23 Aug 95	Added data rates to lr_rpcclient
+Version 0.19	22 Aug 95	Added hme ethernet device
+Version 0.18	 8 Aug 95	Fixed init of kmem
+Version 0.17	29 May 95	Added extra data to kmem rule
+Version 0.16	16 May 95	Added print_lr_disk
+Version 0.15	14 May 95	Bugfix dnlc and inode rules
+Version 0.14	10 May 95	Fixed kmem to work on 2.3
+Version 0.13	 7 May 95	Added new live rules, and thresh code
+Version 0.12	24 Apr 95	Modified to remove live thresholds
+Version 0.11	14 Apr 95	Added vmglobal_total function
+Version 0.10	18 Mar 95	Added debug defines, fixed bugs
+Version 0.9	16 Mar 95	Made local into GLOBAL storage - Adrian
+Version 0.8	24 Feb 95	Fixes by Rich to recognise smc ethernets
+Version 0.7	25 Jan 95	Made source classes global, added mutex
+Version 0.6	18 Dec 94	Added swapspace and ram rules
+Version 0.5     13 Dec 94       Added rpcc rule, fixed some bugs
+Version 0.4     15 Nov 94       Created, matching pure_rules version
+
+Live Rules use the rules found in pure_rules.se but contain the code
+to obtain the measurements and feed them into the rules using current
+data measured on the live system. Each live rule is a class, with
+output variables, threshold variables, private variables and code. No inputs
+should be required apart from changes to any special live-only thresholds.
+
+Thresholds for the underlying pure rules are read from environment
+variables when the pure rule is reset. Resetting the live rule causes
+the pure rule to be reset. Use putenv if you must tweak them...
+
+Each rule has a state and an action, the state is the evaluated condition,
+the action is a short text string that may indicate what should be done.
+A longer string called an explanation may span multiple lines.
+
+Each live rule class type is lr_xxxx_t with active prefix lr_xxxx$
+for the code section. Each matches a pr_xxxx_t pure rule.
+
+The live_rules read directly from the vmstat_class and iostat_class etc,
+to make the raw data available to programs that read a rule, and want to
+show the same underlying numbers, the classes and temporary copies are
+defined globally. Rich doesn't like globals, so I put GLOBAL in the
+name of each variable to make it obvious that they are special.
+Each GLOBAL active class has a GLOBAL_update_time so that multiple rules
+that use it know that they don't have to reevaluate the data more often
+than the specified UPDATE_RATE
+
+Include file dependencies - these should be included by the application:
+#include <stdio.se>
+#include <stdlib.se>
+#include <unistd.se>
+#include <string.se>
+#include <kstat.se>
+#include <sysdepend.se>
+#include <netif.se>
+#include <dirent.se>
+#include <inst_to_path.se>
+#include <p_iostat_class.se>
+#include <p_netstat_class.se>
+#include <p_vmstat_class.se>
+#include <pure_rules.se> 
+*/
+
+/* common string to use */
+string uninit = "Rule initializing...";
+
+/* global iostat class and recorded data available for use */
+p_iostat p_iostat$GLOBAL_disk;
+ks_sderr kstat$sderr;
+ulong	 GLOBAL_disk_update_time;	/* when last evaluated */
+#define  DISK_UPDATE_RATE	2	/* 2 seconds between samples */
+/* GLOBAL_disk[0].disk_count indicates how many entries are valid */
+p_iostat GLOBAL_disk[];	/* on 2.6 partition data is excluded */
+ks_sderr GLOBAL_sderr[];/* MAX_DISK is bigger than needed */
+int	 GLOBAL_sderr_state[];  /* rule status */
+int	 GLOBAL_sderr_errcnt[]; /* total error count */
+int      GLOBAL_disk_size = MAX_DISK;
+int	 GLOBAL_sderr_size = MAX_DISK;
+int	 GLOBAL_disk_count;
+
+/* global net class and recorded data available for use */
+p_netstat p_netstat$GLOBAL_net;
+ulong    GLOBAL_net_update_time;        /* when last evaluated */
+#define  NET_UPDATE_RATE	2	/* 2 seconds between samples */
+/* GLOBAL_net[0].net_count indicates how many entries are valid */
+p_netstat GLOBAL_net[MAX_IF];
+
+/* global client rpc class available for use */
+ks_rpc_client kstat$GLOBAL_ks_rpc_client;
+ulong     GLOBAL_ks_rpc_client_update_time;
+#define  KS_RPC_CLIENT_UPDATE_RATE 1	/* 1 second between samples */
+ks_rpc_client GLOBAL_last_rpcc;
+ks_rpc_client GLOBAL_this_rpcc;
+
+/* global per-cpu vmstat class and recorded data */
+p_vmstat p_vmstat$GLOBAL_pvm;
+ulong    GLOBAL_pvm_update_time;        /* when last evaluated */
+#define  PVM_UPDATE_RATE	2	/* 2 seconds between samples */
+int	 GLOBAL_pvm_ncpus;		/* number of valid entries */
+p_vmstat GLOBAL_pvm[MAX_CPU];
+
+/* function to total up global per_cpu data into vmstat form */
+p_vmstat vmglobal_total() {
+  int i;
+  double total;
+  p_vmstat pvm;
+
+  pvm = GLOBAL_pvm[0];
+  for(i=1; i < GLOBAL_pvm_ncpus; i++) {
+    pvm.pages_in += GLOBAL_pvm[i].pages_in;
+    pvm.pages_out += GLOBAL_pvm[i].pages_out;
+    pvm.interrupts += GLOBAL_pvm[i].interrupts;
+    pvm.system_calls += GLOBAL_pvm[i].system_calls;
+    pvm.context_switches += GLOBAL_pvm[i].context_switches;
+    pvm.user_time += GLOBAL_pvm[i].user_time;
+    pvm.system_time += GLOBAL_pvm[i].system_time;
+    pvm.wait_time += GLOBAL_pvm[i].wait_time;
+    pvm.idle_time += GLOBAL_pvm[i].idle_time;
+    pvm.scan += GLOBAL_pvm[i].scan;
+    pvm.smtx += GLOBAL_pvm[i].smtx;
+  }
+  if (GLOBAL_pvm_ncpus > 1) {
+    /* average over cpu count */
+    pvm.user_time        /= GLOBAL_pvm_ncpus;
+    pvm.system_time      /= GLOBAL_pvm_ncpus;
+    pvm.wait_time        /= GLOBAL_pvm_ncpus;
+    pvm.idle_time        /= GLOBAL_pvm_ncpus;
+#if MINOR_VERSION < 70
+    /* reduce wait time - only one CPU can ever be waiting - others are idle */
+    /* system counts all idle CPUs as waiting if any I/O is outstanding */
+    pvm.wait_time        /= GLOBAL_pvm_ncpus;
+#endif
+  }
+  total = pvm.user_time + pvm.system_time + pvm.wait_time + pvm.idle_time;
+  if (total < 100.0) {
+    pvm.idle_time += (100.0 - total);
+  }
+
+  /* Make sure that total is never greater than 100%.  Better less
+   * than 100% than greater than 100%.  */
+  total = pvm.user_time + pvm.system_time + pvm.wait_time + pvm.idle_time;
+  if (total > 100.0) {
+    pvm.idle_time -= (total - 100.0);
+  }
+  return pvm;
+}
+
+/* Disk I/O live rule - special extra disk type thresholds */
+rule_thresh_dbl slowfd_thr = {"LR_DISK_SLOW_FD", 10.0, "x", 4, 1,
+	"derate slow floppys" }; 
+rule_thresh_dbl slowcd_thr = {"LR_DISK_SLOW_CD", 10.0, "x", 4, 1, 
+	"derate slow CDs" }; 
+rule_thresh_str fdname = {"LR_DISK_FLOPPY", "fd0", "", 6, "default floppy device" };
+rule_thresh_str cdname = {"LR_DISK_CDROM", "c0t6d0", "", 6, "default CD device" };
+rule_thresh_str diskerr_thr = {"LR_DISK_ERROR", "new", "", 4, "report on <any> since boot, or only <new> errors" };
+
+print_lr_disk(ulong f) {
+   print_thresh_dbl(f, slowfd_thr);
+   print_thresh_dbl(f, slowcd_thr); 
+   print_thresh_str(f, fdname); 
+   print_thresh_str(f, cdname); 
+   print_thresh_str(f, diskerr_thr);
+}
+
+class lr_disk_t {
+  /* output variables */
+  int state;
+  string action;
+  string explanation;
+  int disk_count;	/* inicates how many entries are valid */
+  int states[MAX_DISK]; /* per-disk state */
+  string names[MAX_DISK]; /* dynamic arrays don't work here */
+  /* threshold variables */
+  string floppy;	/* don't include floppy and CD in normal rules */
+  string cdrom;
+  string diskerr_mode;
+  double slowfd; /* assume floppy and CD are slower */
+  double slowcd;
+
+  lr_disk$() {
+    pr_disk_t disk_rule;
+    ulong lasttime = 0;             /* previous timestamp */
+    ulong timestamp = 0;
+    int i;
+    int update;
+    int d;
+    int e;
+    int n;
+    string dname;
+    char dummy[32];
+
+#ifdef LIVE_DISK_DEBUG
+    debug_on();
+#endif
+    if (timestamp == 0) {       /* reset defaults */
+      p_iostat$GLOBAL_disk.number$ = 0;
+      GLOBAL_disk = new p_iostat[GLOBAL_disk_size];
+      GLOBAL_disk_count = 0;
+      for(i=0; ; i++) {
+        if (GLOBAL_disk_count == GLOBAL_disk_size) {
+          GLOBAL_disk_size += 4;
+          GLOBAL_disk = renew GLOBAL_disk[GLOBAL_disk_size];
+        }
+        p_iostat$GLOBAL_disk.number$ = i;
+        GLOBAL_disk[GLOBAL_disk_count] = p_iostat$GLOBAL_disk;
+        if (GLOBAL_disk[GLOBAL_disk_count].number$ == -1) {
+	  break;	/* we have run out of io kstats */
+        }
+        // ignore slices
+        if (strchr(GLOBAL_disk[GLOBAL_disk_count].info.long_name, 's') == nil) {
+          GLOBAL_disk_count++;
+        }
+      }
+      disk_count = GLOBAL_disk_count;
+      disk_rule.ndisks = GLOBAL_disk_count;
+      disk_rule.timestamp = 0;	/* reset pure rule */
+      refresh$(disk_rule);
+      state = ST_WHITE;
+      for(i=0; i < MAX_DISK; i++){
+        states[i] = ST_WHITE;
+      }
+      action = uninit;
+      explanation = uninit;
+      slowfd = get_thresh_dbl(slowfd_thr);
+      slowcd = get_thresh_dbl(slowcd_thr);
+      floppy = get_thresh_str(fdname);
+      cdrom = get_thresh_str(cdname);
+
+      diskerr_mode = get_thresh_str(diskerr_thr);
+      GLOBAL_sderr = new ks_sderr[GLOBAL_sderr_size];
+      GLOBAL_sderr_state = new int[GLOBAL_sderr_size]; 
+      GLOBAL_sderr_errcnt = new int[GLOBAL_sderr_size]; 
+
+      timestamp = time(0);
+      lasttime = timestamp;
+      GLOBAL_disk_update_time = timestamp;
+#ifdef LIVE_DISK_DEBUG 
+      debug_off();
+#endif
+      return;
+    }
+    timestamp = time(0);
+    if (timestamp == lasttime) {
+      return;	/* wait at least a second between rule invocations */
+    }
+
+    if (timestamp - GLOBAL_disk_update_time >= DISK_UPDATE_RATE) {
+      update = 1;
+    } else {
+      update = 0;
+    }
+    /* use the disk rule  - if there are no disks then one appears then */
+    /* this code never sees it until the live_rule is reinitialized */
+    /* its unlikely to happen so I kept the code simpler - Adrian */
+    for(i=0; ; i++) {
+      /* some other rule may have already updated the GLOBAL recently */
+      /* so don't reread the data, but do use the existing data */
+      if (update == 1) {
+        if (i == GLOBAL_disk_size) {
+          GLOBAL_disk_size += 4;
+          GLOBAL_disk = renew GLOBAL_disk[GLOBAL_disk_size];
+        }
+        p_iostat$GLOBAL_disk.number$ = GLOBAL_disk[i].number$;
+        GLOBAL_disk[i] = p_iostat$GLOBAL_disk;
+        GLOBAL_disk_update_time = timestamp;
+        if (GLOBAL_disk[i].number$ == -1) {
+          GLOBAL_disk_count = i;
+          break;
+        } else {
+          // skip it if it's a slice
+          if (strchr(GLOBAL_disk[i].info.long_name,'s') != nil) {
+	    continue;	/* go find another I/O record */
+          }
+        }
+      }
+
+      /* check that there is good data */
+      if (GLOBAL_disk[i].number$ == -1) {
+        GLOBAL_disk_count = i;
+        break;
+      }
+      names[i] = GLOBAL_disk[i].info.long_name;
+      disk_rule.busy[i] = GLOBAL_disk[i].run_percent;
+
+/* note previous error and throughput, if no activity since error then
+stay black, count new errors black, media/soft errors red */
+
+      if (names[i] == cdrom) {
+        disk_rule.svc_t[i] = GLOBAL_disk[i].service / slowcd;
+      } else {
+        if (names[i] == floppy) {
+          disk_rule.svc_t[i] = GLOBAL_disk[i].service / slowfd;
+        } else {
+          disk_rule.svc_t[i] = GLOBAL_disk[i].service;
+        }
+      }
+    }
+    disk_rule.timestamp = timestamp;
+    refresh$(disk_rule);
+    state = disk_rule.state;
+    action = disk_rule.action;
+    explanation = disk_rule.explanation;
+    disk_count = GLOBAL_disk_count;
+    for(i=0; i < disk_count; i++){
+      states[i] = disk_rule.states[i];
+    } 
+#ifdef LIVE_PRINTOUT
+    printf("\nDisk       %-5s %s\n", state_string(state), action);
+    printf("disk      r/s  w/s   Kr/s   Kw/s wait actv  svc_t  %%w  %%b State\n");
+    for(i=0; i < GLOBAL_disk[0].disk_count; i++) {
+      printf("%-8.8s %4.1f %4.1f %6.1f %6.1f %4.1f %4.1f %6.1f %3.0f %3.0f %-5s\n",
+        names[i],
+        GLOBAL_disk[i].reads, GLOBAL_disk[i].writes,
+        GLOBAL_disk[i].kreads, GLOBAL_disk[i].kwrites,
+        GLOBAL_disk[i].avg_wait, GLOBAL_disk[i].avg_run,
+        GLOBAL_disk[i].service,
+        GLOBAL_disk[i].wait_percent, GLOBAL_disk[i].run_percent,
+	state_string(states[i]));
+    }
+#endif
+
+    /* now check for disk errors */
+    /* if we find one then figure out which disk it is later */
+    for(i=0; ; i++) {	/* grab new data */
+      if (i == GLOBAL_sderr_size) {
+        GLOBAL_sderr_size += 4;       /* grow the arrays a bit  */
+        GLOBAL_sderr = renew GLOBAL_sderr[GLOBAL_sderr_size];
+	GLOBAL_sderr_state = renew GLOBAL_sderr_state[GLOBAL_sderr_size];
+	GLOBAL_sderr_errcnt = renew GLOBAL_sderr_errcnt[GLOBAL_sderr_size];
+      }
+      kstat$sderr.number$ = i;
+      GLOBAL_sderr[i] = kstat$sderr;
+      if (GLOBAL_sderr[i].number$ == -1) {
+        break;
+      }
+      e = GLOBAL_sderr[i].Soft_Errors + GLOBAL_sderr[i].Hard_Errors
+	+ GLOBAL_sderr[i].Transport_Errors;
+      if (e > (diskerr_mode == "new" ? GLOBAL_sderr_errcnt[i]: 0)) {
+	/* this disk needs a closer look */
+	GLOBAL_sderr_errcnt[i] = e;
+	/* work out which disk it really is */
+	d = strcspn(GLOBAL_sderr[i].name$, ",");
+	dname = strncpy(dummy, GLOBAL_sderr[i].name$, d); /* chop ,err */
+#ifdef FIND_INST
+	d = find_inst(dname); /* fast but buggy */
+#else
+	for(n=0; n < GLOBAL_disk_count; n++) {
+	  if (dname == GLOBAL_disk[n].info.short_name) {
+	    d = n;
+	    break;
+	  }
+	}
+#endif
+	if (d != -1) {
+		dname = GLOBAL_disk[d].info.long_name;
+	}
+	/* process rules in order of increasing error level */
+	if (GLOBAL_sderr[i].No_Device > 0) {
+	  explanation = sprintf("%s\n\t%s\t%s\t%3d %s", explanation,
+		dname, GLOBAL_sderr[i].Product,
+		GLOBAL_sderr[i].No_Device, "green Warning - No Device - cprboot spinup?");
+	  GLOBAL_sderr_state[i] = ST_GREEN;
+	}
+        if (GLOBAL_sderr[i].Recoverable > 0) {
+          explanation = sprintf("%s\n\t%s\t%s\t%3d %s", explanation,
+                dname, GLOBAL_sderr[i].Product,
+		GLOBAL_sderr[i].Recoverable, "amber - Recoverable Error Retry");
+          GLOBAL_sderr_state[i] = ST_AMBER;
+        }
+        if (GLOBAL_sderr[i].Predictive_Failure_Analysis > 0) {
+          explanation = sprintf("%s\n\t%s\t%s\t%3d %s", explanation,
+                dname, GLOBAL_sderr[i].Product,
+		GLOBAL_sderr[i].Predictive_Failure_Analysis, "red   - Predictive_Failure_Analysis - Replace Disk");
+          GLOBAL_sderr_state[i] = ST_RED;
+        }
+	// it's not uncommon for the CD to not be ready... richp
+        if (GLOBAL_sderr[i].Device_Not_Ready > 0 && dname != cdrom) {
+          explanation = sprintf("%s\n\t%s\t%s\t%3d %s", explanation,
+                dname, GLOBAL_sderr[i].Product,
+		GLOBAL_sderr[i].Device_Not_Ready, "black - Device Not Ready - disk offline?");
+          GLOBAL_sderr_state[i] = ST_BLACK;
+        }
+        if (GLOBAL_sderr[i].Media_Error > 0) {
+          explanation = sprintf("%s\n\t%s\t%s\t%3d %s", explanation,
+                dname, GLOBAL_sderr[i].Product,
+		GLOBAL_sderr[i].Media_Error, "black - Media Error - replace disk");
+          GLOBAL_sderr_state[i] = ST_BLACK;
+        }
+        if (GLOBAL_sderr[i].Illegal_Request > 0) {
+          explanation = sprintf("%s\n\t%s\t%s\t%3d %s", explanation,
+                dname, GLOBAL_sderr[i].Product,
+		GLOBAL_sderr[i].Illegal_Request, "black - Illegal Request Error");
+          GLOBAL_sderr_state[i] = ST_BLACK;
+        }
+	/* update disk state */
+	if (d != -1) {
+	  if (states[d] < GLOBAL_sderr_state[i]) {
+	    states[d] = GLOBAL_sderr_state[i];
+	    if (state < states[d]) {
+	      state = states[d];
+	    }
+	    switch(GLOBAL_sderr_state[i]) {
+	      case ST_AMBER:
+		action = "Disk error warning - check disk";
+		break;
+	      case ST_RED:
+		action = "Disk error problem - replace disk";
+		break;
+	      case ST_BLACK:
+		action = "Disk failed - check cables or replace disk";
+	    }
+	  }
+	}
+      }
+    }
+
+    lasttime = timestamp;
+#ifdef LIVE_DISK_DEBUG 
+    debug_off();
+#endif
+  }
+};
+
+/* Network live rule - picks out ethernets only for now */
+/* reports anything else as green */
+
+class lr_net_t {
+  /* output variables */
+  int state;
+  string action;
+  string explanation;
+  int net_count;
+  int states[MAX_IF]; /* per-net state */
+  string names[MAX_IF];
+  int speeds[MAX_IF]; /* network speed in bytes/sec */
+  /* make snapshot of pure rule available */
+  pr_enet_t net_rule;
+
+  lr_net$() {
+    ulong lasttime = 0;             /* previous timestamp */
+    ulong timestamp = 0;
+    int i;
+    int update;
+    char ifname[12];
+    int enet_count;
+    int net[MAX_IF];	/* index between ethernets and all nets */
+ 
+    if (timestamp == 0) {       /* reset defaults */
+      GLOBAL_net[0] = p_netstat$GLOBAL_net;
+      net_count = GLOBAL_net[0].net_count;
+      for(i=1; i < GLOBAL_net[0].net_count; i++){
+        p_netstat$GLOBAL_net.number$ = i;
+        GLOBAL_net[i] = p_netstat$GLOBAL_net;
+      }  
+      net_rule.enet_count = net_count;
+      net_rule.timestamp = 0;	/* force pure rule to reset */
+      refresh$(net_rule);
+      state = ST_GREEN;	/* non-ethernets should default to ST_GREEN */
+      for(i=0; i < MAX_IF; i++){
+        states[i] = ST_GREEN;
+      }  
+      action = uninit;
+      explanation = action;
+      timestamp = time(0);
+      lasttime = timestamp;
+      GLOBAL_net_update_time = timestamp;
+      return;
+    }
+    timestamp = time(0);
+    if (timestamp == lasttime) {
+      return;   /* wait at least a second between rule invocations */
+    }
+
+    if (timestamp - GLOBAL_net_update_time >= NET_UPDATE_RATE) {
+      update = 1;
+    } else {
+      update = 0;
+    }
+    enet_count = 0;
+    for(i=0; i < GLOBAL_net[0].net_count; i++) {
+      if (update == 1) {
+        p_netstat$GLOBAL_net.number$ = i;
+        GLOBAL_net[i] = p_netstat$GLOBAL_net;
+        GLOBAL_net_update_time = timestamp;
+      }
+      names[i] = GLOBAL_net[i].name$;
+      ifname = GLOBAL_net[i].name$;
+      speeds[i] = GLOBAL_net[i].ifspeed;
+      if (GLOBAL_net[i].iftype == NT_CSMACD) {
+        net_rule.opackets[enet_count] = GLOBAL_net[i].opackets;
+        net_rule.collpercent[enet_count] = GLOBAL_net[i].collpercent;
+        net_rule.errors[i] = GLOBAL_net[i].ierrors + GLOBAL_net[i].oerrors;
+        net_rule.defer[i] = GLOBAL_net[i].defer;
+        net_rule.nocanput[i] = GLOBAL_net[i].nocanput;
+        net[enet_count++] = i;
+      } else {
+	/* XXX: add code to check FDDI, ATM, token ring here */
+        states[i] = ST_GREEN;	/* not an ethernet so assume its OK */
+      }
+    }  
+    net_rule.enet_count = enet_count;
+    net_rule.timestamp = timestamp;
+    refresh$(net_rule);
+    state = net_rule.state;
+    action = net_rule.action;
+    explanation = net_rule.explanation;
+    net_count = GLOBAL_net[0].net_count;
+    for(i=0; i < enet_count; i++){
+      states[net[i]] = net_rule.states[i];
+    }
+    lasttime = timestamp;
+  }
+};
+
+
+/* NFS client RPC live rule */
+
+class lr_rpcclient_t {
+  /* output variables */
+  int state;
+  string action;
+  string explanation;
+  double calls;		/* per second rates for info */
+  double timeouts;
+  double badxids;
+
+  lr_rpcclient$()
+  { 
+    ulong lasttime = 0;             /* previous timestamp */
+    ulong timestamp = 0;
+    pr_rpcclient_t rpcc_rule;
+    double ttmp;
+    double dtmp;
+ 
+    if (timestamp == 0) {
+      rpcc_rule.timestamp = 0;
+      refresh$(rpcc_rule);
+      GLOBAL_last_rpcc = kstat$GLOBAL_ks_rpc_client;
+      action = uninit;
+      explanation = action;
+      state = ST_WHITE;
+      calls = 0.0;
+      timeouts = 0.0;
+      badxids = 0.0;
+      timestamp = time(0);
+      lasttime = timestamp;
+      GLOBAL_ks_rpc_client_update_time = lasttime;
+      return;
+    }
+    timestamp = time(0);
+    if (timestamp == lasttime) {
+      return;   /* wait at least a second between rule invocations */
+    }
+    /* use the rule */
+    if (timestamp - GLOBAL_ks_rpc_client_update_time >= 
+		KS_RPC_CLIENT_UPDATE_RATE) {
+      GLOBAL_this_rpcc = kstat$GLOBAL_ks_rpc_client;
+      GLOBAL_ks_rpc_client_update_time = lasttime; 
+    }
+    ttmp = timestamp - lasttime;       /* double temporaries */
+    dtmp = GLOBAL_this_rpcc.calls - GLOBAL_last_rpcc.calls;
+    calls = dtmp / ttmp;
+    rpcc_rule.calls = calls;
+    dtmp = GLOBAL_this_rpcc.timeouts - GLOBAL_last_rpcc.timeouts;
+    timeouts = dtmp / ttmp;
+    rpcc_rule.timeouts = timeouts;
+    dtmp = GLOBAL_this_rpcc.badxids - GLOBAL_last_rpcc.badxids;
+    badxids = dtmp / ttmp;
+    rpcc_rule.badxids = badxids;
+    rpcc_rule.timestamp = timestamp;
+    refresh$(rpcc_rule);
+    state = rpcc_rule.state;
+    action = rpcc_rule.action;
+    explanation = rpcc_rule.explanation;
+    lasttime = timestamp;
+    GLOBAL_last_rpcc = GLOBAL_this_rpcc;
+  }
+};
+
+
+/* shared function to update the global pvm data */
+pvm_update(ulong timestamp) {
+  int i;
+
+  if (timestamp == 0 || timestamp - GLOBAL_pvm_update_time >= PVM_UPDATE_RATE) {
+    GLOBAL_pvm_ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+    for(i = 0; i < GLOBAL_pvm_ncpus; i++) {
+      p_vmstat$GLOBAL_pvm.number$ = i;
+      GLOBAL_pvm[i] = p_vmstat$GLOBAL_pvm;
+    }
+    GLOBAL_pvm_update_time = timestamp;
+  }
+}
+
+/* Virtual Memory - Swap Space - live rule */
+class lr_swapspace_t {
+  /* output variables */
+  int state;
+  string action;
+  string explanation;
+ 
+  lr_swapspace$()
+  {
+    ulong lasttime = 0;             /* previous timestamp */
+    ulong timestamp = 0;
+    pr_swapspace_t swap_rule;
+ 
+    if (timestamp == 0) {
+      timestamp = time(0);
+      pvm_update(timestamp);
+      swap_rule.swap_avail = GLOBAL_pvm[0].swap_avail;
+      swap_rule.timestamp = timestamp;
+      refresh$(swap_rule);
+      action = uninit;
+      explanation = uninit;
+      state = ST_WHITE;
+      lasttime = timestamp;
+      return;
+    }
+    timestamp = time(0);
+    if (timestamp == lasttime) {
+      return;   /* wait at least a second between rule invocations */
+    }
+    /* use the rule */
+    pvm_update(timestamp);
+    swap_rule.swap_avail = GLOBAL_pvm[0].swap_avail;
+    swap_rule.timestamp = timestamp;
+    refresh$(swap_rule);
+    state = swap_rule.state;
+    action = swap_rule.action;
+    explanation = swap_rule.explanation;
+    lasttime = timestamp;
+  }
+};
+
+
+/* Real Memory - RAM page residency - live rule using improved pure_rule */
+class lr_ram_t {
+  /* output variables */
+  int state;
+  string action;
+  string explanation;
+  int restime;
+  ulong handspreadpages;	/* estimated on startup, can be set if known */
+
+  lr_ram$()
+  {
+    ulong lasttime = 0;             /* previous timestamp */
+    ulong timestamp = 0;
+    pr_ram_t ram_rule;
+    ulong pages;
+ 
+    if (timestamp == 0) {
+      ram_rule.timestamp = 0;
+      /* default max handspread is 64MB worth of pages */
+      handspreadpages = 64 * 1048576 / sysconf(_SC_PAGESIZE);
+      pages = sysconf(_SC_PHYS_PAGES);
+      if (handspreadpages > pages / 4) {
+        handspreadpages = pages / 4;
+      }
+      ram_rule.handspread = handspreadpages;
+      refresh$(ram_rule);
+      action = uninit;
+      explanation = action;
+      state = ST_WHITE;
+      timestamp = time(0);
+      lasttime = timestamp;
+      pvm_update(timestamp);
+      return;
+    }
+    timestamp = time(0);
+    if (timestamp == lasttime) {
+      return;   /* wait at least a second between rule invocations */
+    }
+    /* use the rule */
+    pvm_update(timestamp);
+    ram_rule.handspread = handspreadpages; /* allow it to be changed */
+    ram_rule.scan = GLOBAL_pvm[0].scan;
+    ram_rule.timestamp = timestamp;
+    refresh$(ram_rule);
+    state = ram_rule.state;
+    action = ram_rule.action;
+    explanation = ram_rule.explanation;
+    restime = ram_rule.restime;
+    lasttime = timestamp;
+  }
+};
+
+/* Kernel memory live rule */
+class lr_kmem_t {
+  /* output variables */
+  int state;
+  string action;
+  string explanation;
+  ulong kmem_errors;
+
+  lr_kmem$()
+  {
+    ulong lasttime = 0;             /* previous timestamp */
+    ulong timestamp = 0;
+#if MINOR_VERSION < 80
+    ks_kmem_misc kmem;
+#else
+    ks_cache kmem;
+#endif
+    pr_kmem_t kmem_rule;
+    int pagesize = sysconf(_SC_PAGESIZE) / 1024;
+
+    if (timestamp == 0) {
+      kmem_rule.timestamp = 0;
+      kmem_rule.freemem = 0;
+      refresh$(kmem);
+#if MINOR_VERSION < 80
+      kmem_errors = kmem.huge_alloc_fail + kmem.perm_alloc_fail;
+#else
+      for(kmem_errors=0, kmem.number$=0, refresh$(kmem);
+          kmem.number$ != -1; kmem.number$++, refresh$(kmem)) {
+        if (kmem.name$ =~ "kmem_alloc.*") {
+          kmem_errors += kmem.alloc_fail;
+        }
+      }
+#endif
+      kmem_rule.kmem_errs = kmem_errors;
+      refresh$(kmem_rule);
+      action = uninit;
+      explanation = action;
+      state = ST_WHITE;
+      timestamp = time(0);
+      lasttime = timestamp;
+      pvm_update(timestamp);
+      return;
+    }
+    timestamp = time(0);
+    if (timestamp == lasttime) {
+      return;   /* wait at least a second between rule invocations */
+    }
+    /* use the rule */
+    pvm_update(timestamp);
+    refresh$(kmem);
+#if MINOR_VERSION < 80
+    kmem_errors = kmem.huge_alloc_fail + kmem.perm_alloc_fail;
+#else
+    for(kmem_errors=0, kmem.number$=0, refresh$(kmem);
+        kmem.number$ != -1; kmem.number$++, refresh$(kmem)) {
+      if (kmem.name$ =~ "kmem_alloc.*") {
+        kmem_errors += kmem.alloc_fail;
+      }
+    }
+#endif
+    kmem_rule.kmem_errs = kmem_errors;
+    kmem_rule.freemem = GLOBAL_pvm[0].freemem / pagesize;
+    kmem_rule.timestamp = timestamp;
+    refresh$(kmem_rule);
+    state = kmem_rule.state;
+    action = kmem_rule.action;
+    explanation = kmem_rule.explanation;
+    lasttime = timestamp;
+  }
+};
+
+
+/* CPU power - live rule */
+class lr_cpu_t {
+  /* output variables */
+  int state;
+  string action;
+  string explanation;
+
+  lr_cpu$()
+  {
+    ulong lasttime = 0;             /* previous timestamp */
+    ulong timestamp = 0;
+    pr_cpu_t cpu_rule;
+
+    if (timestamp == 0) {
+      timestamp = time(0);
+      pvm_update(timestamp);
+      cpu_rule.ncpus = GLOBAL_pvm_ncpus;
+      cpu_rule.timestamp = 0;
+      refresh$(cpu_rule);
+      action = uninit;
+      explanation = action;
+      state = ST_WHITE;
+      lasttime = timestamp;
+      return;
+    }
+    timestamp = time(0);  
+    if (timestamp == lasttime) { 
+      return;   /* wait at least a second between rule invocations */
+    }
+    /* use the rule */
+    pvm_update(timestamp);
+    cpu_rule.runque = GLOBAL_pvm[0].runque;
+    cpu_rule.timestamp = timestamp;  
+    refresh$(cpu_rule);
+    state = cpu_rule.state;
+    action = cpu_rule.action;
+    explanation = cpu_rule.explanation;
+    lasttime = timestamp;   
+  }
+};
+
+/* mutex contention - live rule */
+class lr_mutex_t {
+  /* output variables */
+  int state;
+  int states[MAX_CPU];
+  string action;
+  string explanation;
+  int smtx;  /* back compatible sum of p_vmstat.smtx for all cpus */
+  int ncpus;     /* i.e. sysconf(_SC_NPROCESSORS_ONLN) */
+ 
+  lr_mutex$()
+  { 
+    ulong lasttime = 0;             /* previous timestamp */
+    ulong timestamp = 0;
+    pr_mutex_t mutex_rule;
+    int i;
+ 
+    if (timestamp == 0) {
+      timestamp = time(0);
+      pvm_update(timestamp);
+      ncpus = GLOBAL_pvm_ncpus;
+      mutex_rule.ncpus = ncpus;
+      mutex_rule.timestamp = 0;
+      refresh$(mutex_rule);
+      smtx = 0;
+      action = uninit;
+      explanation = action;
+      state = ST_WHITE;
+      lasttime = timestamp;
+      return;
+    }
+    timestamp = time(0);
+    if (timestamp == lasttime) {
+      return;   /* wait at least a second between rule invocations */
+    }
+    pvm_update(timestamp);
+    /* use the rule */
+    ncpus = GLOBAL_pvm_ncpus;
+    smtx = 0;
+    for(i = 0; i < ncpus; i++) {
+      smtx += GLOBAL_pvm[i].smtx;
+      mutex_rule.smtx[i] = GLOBAL_pvm[i].smtx;
+      mutex_rule.usr[i] = GLOBAL_pvm[i].user_time;
+      mutex_rule.sys[i] = GLOBAL_pvm[i].system_time;
+    }
+    mutex_rule.ncpus = ncpus;
+    mutex_rule.timestamp = timestamp;
+    refresh$(mutex_rule);
+    state = mutex_rule.state;
+    for(i = 0; i < ncpus; i++) {
+      states[i] = mutex_rule.states[i];
+    }
+    action = mutex_rule.action;
+    explanation = mutex_rule.explanation;
+    lasttime = timestamp;
+  }
+};
+
+/*  Directory Name Lookup Cache hit rate */
+class lr_dnlc_t {
+  /* output variables */
+  int state;
+  string action;
+  string explanation;
+  double refrate;               /* current DNLC reference rate */
+  double hitrate;               /* current DNLC hit rate */
+ 
+  lr_dnlc$()
+  { 
+    ulong lasttime = 0;             /* previous timestamp */
+    ulong timestamp = 0;
+    pr_dnlc_t dnlc_rule;
+#if MINOR_VERSION > 70
+    ks_dnlcstats ncstats;
+#else
+    ks_ncstats ncstats;
+#endif
+    int i;
+ 
+    if (timestamp == 0) {
+      timestamp = time(0);
+      dnlc_rule.timestamp = 0;
+      refresh$(dnlc_rule);
+      action = uninit;
+      explanation = action;
+      state = ST_WHITE;
+      lasttime = timestamp;
+      return;
+    }
+    timestamp = time(0);
+    if (timestamp == lasttime) {
+      return;   /* wait at least a second between rule invocations */
+    }
+    /* use the rule */
+    refresh$(ncstats);
+    dnlc_rule.hits = ncstats.hits;
+    dnlc_rule.misses = ncstats.misses;
+    dnlc_rule.timestamp = timestamp;
+    refresh$(dnlc_rule);
+    state = dnlc_rule.state;
+    action = dnlc_rule.action;
+    explanation = dnlc_rule.explanation;
+    refrate = dnlc_rule.refrate;
+    hitrate = dnlc_rule.hitrate;
+    lasttime = timestamp;
+  }
+};
+
+/*  Inode Cache hit rate */
+class lr_inode_t {
+  /* output variables */
+  int state;
+  string action;
+  string explanation;
+  double refrate;               /* current inode cache reference rate */
+  double hitrate;               /* current inode cache hit rate */
+  double iprate;		/* current inode w/page steal rate */
+
+  lr_inode$()
+  {
+    ulong lasttime = 0;             /* previous timestamp */
+    ulong timestamp = 0;
+    pr_inode_t inode_rule;
+    ks_inode_cache inostats;
+    int i;
+
+    if (timestamp == 0) {
+      timestamp = time(0);
+      inode_rule.timestamp = 0;
+      refresh$(inode_rule);
+      action = uninit;
+      explanation = action;
+      state = ST_WHITE;
+      lasttime = timestamp;
+      return;
+    }
+    timestamp = time(0);
+    if (timestamp == lasttime) {
+      return;   /* wait at least a second between rule invocations */
+    }
+    /* use the rule */
+    refresh$(inostats);
+    inode_rule.hits = inostats.hits;
+    inode_rule.misses = inostats.misses;
+    inode_rule.timestamp = timestamp;
+    refresh$(inode_rule);
+    state = inode_rule.state;
+    action = inode_rule.action;
+    explanation = inode_rule.explanation;
+    refrate = inode_rule.refrate;
+    hitrate = inode_rule.hitrate;
+    lasttime = timestamp;
+  }
+};
+
+#endif

Added: trunk/orca/lib/SE/3.4/orca_p_netstat_class.se
==============================================================================
--- (empty file)
+++ trunk/orca/lib/SE/3.4/orca_p_netstat_class.se	Wed Feb  9 12:08:55 2005
@@ -0,0 +1,247 @@
+//
+// Copyright (c) 1993-2001 by Richard Pettit. All rights reserved.
+//
+// Some of this work was derived from include files containing the following
+// copyrights.
+//
+//   Copyright (c) 1986-1994 by Sun Microsystems, Inc.
+//   Copyright (c) 1983-1989 by AT&T
+//   Copyright (c) 1980-1993 by The Regents of the University of California.
+//
+// The work as a whole represents unique intellectual property and is
+// copyright by Richard Pettit as shown on the first line.
+//
+
+#ifndef _P_NETSTAT_CLASS_SE_
+#define _P_NETSTAT_CLASS_SE_
+
+#include <unistd.se>
+#include <time.se>
+#include <string.se>
+#include <kstat.se>
+#include <sysdepend.se>
+#include <netif.se>
+
+#define NANODOUBLE 0.000000001	/* converts gethrtime to seconds */
+
+/* robust difference generator for wrapping 32bit counters */
+/* unsigned to double difference */
+
+#define UD_DIFF(now, then) (((double) now) >= ((double) then) ? \
+                             (now - then) :  \
+                            ((double) now) + 4294967296.0 - ((double) then))
+
+// All this crap must be global 'cause I can't fix the interpreter bug.
+
+double pnetGLOB_net_ipackets[]; /* these are rates */
+double pnetGLOB_net_idtsize[];
+double pnetGLOB_net_ihdrovhd[];
+double pnetGLOB_net_ierrors[];
+double pnetGLOB_net_opackets[];
+double pnetGLOB_net_odtsize[];
+double pnetGLOB_net_ohdrovhd[];
+double pnetGLOB_net_oerrors[];
+double pnetGLOB_net_collisions[];
+double pnetGLOB_net_defer[];
+double pnetGLOB_net_nocanput[];
+double pnetGLOB_net_ioctets[];
+double pnetGLOB_net_ooctets[];
+netif  pnetGLOB_save_nets[];    /* these are absolute values */
+double pnetGLOB_save_et[];
+
+int    pnetGLOB_net_size = MAX_IF;
+
+pnetGLOB_realloc()
+{
+  pnetGLOB_net_ipackets = renew pnetGLOB_net_ipackets[pnetGLOB_net_size];
+  pnetGLOB_net_idtsize = renew pnetGLOB_net_idtsize[pnetGLOB_net_size];
+  pnetGLOB_net_ihdrovhd = renew pnetGLOB_net_ihdrovhd[pnetGLOB_net_size];
+  pnetGLOB_net_ierrors = renew pnetGLOB_net_ierrors[pnetGLOB_net_size];
+  pnetGLOB_net_opackets = renew pnetGLOB_net_opackets[pnetGLOB_net_size];
+  pnetGLOB_net_odtsize = renew pnetGLOB_net_odtsize[pnetGLOB_net_size];
+  pnetGLOB_net_ohdrovhd = renew pnetGLOB_net_ohdrovhd[pnetGLOB_net_size];
+  pnetGLOB_net_oerrors = renew pnetGLOB_net_oerrors[pnetGLOB_net_size];
+  pnetGLOB_net_collisions = renew pnetGLOB_net_collisions[pnetGLOB_net_size];
+  pnetGLOB_net_defer = renew pnetGLOB_net_defer[pnetGLOB_net_size];
+  pnetGLOB_net_nocanput = renew pnetGLOB_net_nocanput[pnetGLOB_net_size];
+  pnetGLOB_net_ioctets = renew pnetGLOB_net_ioctets[pnetGLOB_net_size];
+  pnetGLOB_net_ooctets = renew pnetGLOB_net_ooctets[pnetGLOB_net_size];
+  pnetGLOB_save_nets = renew pnetGLOB_save_nets[pnetGLOB_net_size];
+  pnetGLOB_save_et = renew pnetGLOB_save_et[pnetGLOB_net_size];
+}
+
+class p_netstat {
+
+  int number$;
+  char name$[12];
+
+  int     net_count;
+  double  ipackets;
+  double  ierrors;
+  double  idtsize;
+  double  ihdrovhd;
+  double  opackets;
+  double  oerrors;
+  double  odtsize;
+  double  ohdrovhd;
+  double  collisions;
+  double  collpercent;
+  double  nocanput;
+  double  defer;
+  double  ioctets;
+  double  ooctets;
+  ulong_t ifspeed;
+  int     iftype;
+  double  utilization;
+
+  p_netstat$()
+  {
+    int i;
+    int initialized = 0;
+    netif interface;
+    double et;
+    double now;
+
+    /* do initialization code */
+    if (initialized == 0) {
+
+      pnetGLOB_net_ipackets = new double[pnetGLOB_net_size];
+      pnetGLOB_net_idtsize = new double[pnetGLOB_net_size];
+      pnetGLOB_net_ihdrovhd = new double[pnetGLOB_net_size];
+      pnetGLOB_net_ierrors = new double[pnetGLOB_net_size];
+      pnetGLOB_net_opackets = new double[pnetGLOB_net_size];
+      pnetGLOB_net_odtsize = new double[pnetGLOB_net_size];
+      pnetGLOB_net_ohdrovhd = new double[pnetGLOB_net_size];
+      pnetGLOB_net_oerrors = new double[pnetGLOB_net_size];
+      pnetGLOB_net_collisions = new double[pnetGLOB_net_size];
+      pnetGLOB_net_defer = new double[pnetGLOB_net_size];
+      pnetGLOB_net_nocanput = new double[pnetGLOB_net_size];
+      pnetGLOB_net_ioctets = new double[pnetGLOB_net_size];
+      pnetGLOB_net_ooctets = new double[pnetGLOB_net_size];
+      pnetGLOB_save_nets = new netif[pnetGLOB_net_size];
+      pnetGLOB_save_et = new double[pnetGLOB_net_size];
+
+      /* grab initial info from netif class */
+      for(refresh$(interface), i=0; i<interface.if_count;
+          i++, interface.number$ = i, refresh$(interface)) {
+        if (interface.number$ == pnetGLOB_net_size) {
+          pnetGLOB_net_size += 4;
+          pnetGLOB_realloc();
+        }
+        pnetGLOB_save_et[interface.number$] = gethrtime() * NANODOUBLE;
+        pnetGLOB_save_nets[interface.number$] = interface;
+        net_count++;
+      }
+      ipackets = pnetGLOB_save_nets[i].ipackets;
+      ierrors = pnetGLOB_save_nets[i].ierrors;
+      opackets = pnetGLOB_save_nets[i].opackets;
+      oerrors = pnetGLOB_save_nets[i].oerrors;
+      collisions = pnetGLOB_save_nets[i].collisions;
+      if (opackets != 0) {
+        collpercent = (collisions * 100.0) / opackets;
+      } else {
+        collpercent = 0.0;
+      }
+      nocanput = pnetGLOB_save_nets[i].nocanput;
+      defer = pnetGLOB_save_nets[i].defer;
+      ioctets = pnetGLOB_save_nets[i].ioctets;
+      ooctets = pnetGLOB_save_nets[i].ooctets;
+      idtsize = 0.0;
+      ihdrovhd = 0.0;
+      odtsize = 0.0;
+      ohdrovhd = 0.0;
+      ifspeed = pnetGLOB_save_nets[i].ifspeed;
+      iftype  = pnetGLOB_save_nets[i].iftype;
+      utilization = 0.0; // this will always be around 0.000000000000000001
+      initialized = 1;
+      return;
+    }
+
+    /* bounds check */
+    i = number$;
+    if ((i < 0) || (i >= net_count)) {
+      number$ = -1;
+      return;
+    }
+
+    /* find out how many seconds have elapsed */
+    now = gethrtime() * NANODOUBLE;
+    et = (now - pnetGLOB_save_et[i]);
+
+    /* do computes if at least a second has gone by */
+    if (et > 1.0) {
+      /* save the time */
+      pnetGLOB_save_et[i] = now;
+
+      /* grab the info for this net */
+      interface.number$ = i;
+      refresh$(interface);
+  
+      /* compute new values */
+      pnetGLOB_net_ipackets[i]   =
+        UD_DIFF(interface.ipackets,   pnetGLOB_save_nets[i].ipackets) / et;
+      pnetGLOB_net_ierrors[i]    =
+        UD_DIFF(interface.ierrors,    pnetGLOB_save_nets[i].ierrors)  / et;
+      pnetGLOB_net_opackets[i]   =
+        UD_DIFF(interface.opackets,   pnetGLOB_save_nets[i].opackets) / et;
+      pnetGLOB_net_oerrors[i]    =
+        UD_DIFF(interface.oerrors,    pnetGLOB_save_nets[i].oerrors)  / et;
+      pnetGLOB_net_collisions[i] =
+        UD_DIFF(interface.collisions, pnetGLOB_save_nets[i].collisions) / et;
+      pnetGLOB_net_nocanput[i] =
+        UD_DIFF(interface.nocanput,   pnetGLOB_save_nets[i].nocanput) / et;
+      pnetGLOB_net_defer[i] =
+        UD_DIFF(interface.defer,      pnetGLOB_save_nets[i].defer)   / et;
+      pnetGLOB_net_ioctets[i] =
+        UD_DIFF(interface.ioctets,    pnetGLOB_save_nets[i].ioctets) / et;
+      pnetGLOB_net_ooctets[i] =
+        UD_DIFF(interface.ooctets,    pnetGLOB_save_nets[i].ooctets) / et;
+      if ( pnetGLOB_net_ipackets[i] == 0.0 ) {
+         pnetGLOB_net_idtsize[i] = 0.0;
+         pnetGLOB_net_ihdrovhd[i] = 0.0;
+      } else {
+         pnetGLOB_net_idtsize[i] = pnetGLOB_net_ioctets[i] / pnetGLOB_net_ipackets[i];
+         pnetGLOB_net_ihdrovhd[i] = 100 * (40 * pnetGLOB_net_ipackets[i] / ( 40 * pnetGLOB_net_ipackets[i] + pnetGLOB_net_ioctets[i] ));
+      }
+      if ( pnetGLOB_net_opackets[i] == 0.0 ) {
+         pnetGLOB_net_odtsize[i] = 0.0;
+         pnetGLOB_net_ohdrovhd[i] = 0.0;
+      } else {
+         pnetGLOB_net_odtsize[i] = pnetGLOB_net_ooctets[i] / pnetGLOB_net_opackets[i];
+         pnetGLOB_net_ohdrovhd[i] = 100 * (40 * pnetGLOB_net_opackets[i] / ( 40 * pnetGLOB_net_opackets[i] + pnetGLOB_net_ooctets[i] ));
+      }
+      /* save old */
+      pnetGLOB_save_nets[i] = interface;
+    }
+  
+    /* update and return */
+    strncpy(name$, pnetGLOB_save_nets[i].name$, 12);
+    ipackets    = pnetGLOB_net_ipackets[i];
+    ierrors     = pnetGLOB_net_ierrors[i];
+    opackets    = pnetGLOB_net_opackets[i];
+    oerrors     = pnetGLOB_net_oerrors[i];
+    collisions  = pnetGLOB_net_collisions[i];
+    if (opackets > 0.0) {
+      collpercent = collisions * 100.0 / opackets;
+    } else {
+      collpercent = 0.0;
+    }
+    nocanput	= pnetGLOB_net_nocanput[i];
+    defer       = pnetGLOB_net_defer[i];
+    ioctets     = pnetGLOB_net_ioctets[i];
+    ooctets     = pnetGLOB_net_ooctets[i];
+    idtsize     = pnetGLOB_net_idtsize[i];
+    ihdrovhd    = pnetGLOB_net_ihdrovhd[i];
+    odtsize     = pnetGLOB_net_odtsize[i];
+    ohdrovhd    = pnetGLOB_net_ohdrovhd[i];
+    ifspeed     = pnetGLOB_save_nets[i].ifspeed;
+    iftype      = pnetGLOB_save_nets[i].iftype;
+    if (ifspeed != 0) {
+      utilization = (((ioctets + ooctets) * 8) * 100.0) / ifspeed;
+    } else {
+      utilization = 0.0;
+    }
+  }
+};
+
+#endif _P_NETSTAT_CLASS_SE_

Added: trunk/orca/lib/SE/3.4/orca_p_vmstat_class.se
==============================================================================
--- (empty file)
+++ trunk/orca/lib/SE/3.4/orca_p_vmstat_class.se	Wed Feb  9 12:08:55 2005
@@ -0,0 +1,386 @@
+//
+// Copyright (c) 1993-2001 by Richard Pettit. All rights reserved.
+//
+// Some of this work was derived from include files containing the following
+// copyrights.
+//
+//   Copyright (c) 1986-1994 by Sun Microsystems, Inc.
+//   Copyright (c) 1983-1989 by AT&T
+//   Copyright (c) 1980-1993 by The Regents of the University of California.
+//
+// The work as a whole represents unique intellectual property and is
+// copyright by Richard Pettit as shown on the first line.
+//
+
+#ifndef _P_VMSTAT_CLASS_SE_
+#define _P_VMSTAT_CLASS_SE_
+
+#include <unistd.se>
+#include <kstat.se>
+#include <sysdepend.se>
+
+/* for memory computation */
+#define PGTOK(n)            (((n) * pagesize) / 1024)
+#define DELTA(name)         (new_vminfo.name - old_vminfo.name)
+#define COMPUTE(name)       PGTOK(DELTA(name) / updates)
+
+/* make the code easier on the eye */
+#define CSI_DIFF(name) \
+  pvmGLOB_cpu_sysinfo[i].name = \
+    (csi.name - pvmGLOB_old_cpu_sysinfo[i].name)
+#define CSI_PCT(name) \
+  pvmGLOB_cpu_sysinfo[i].name = (pvmGLOB_cpu_sysinfo[i].name / total) * 100.0
+
+#define CSIPCT(name) (100.0 * name / (hz * pvmGLOB_etime[i]))
+
+#define CVI_DIFF(name) \
+  pvmGLOB_cpu_vminfo[i].name = \
+    (cvi.name - pvmGLOB_old_cpu_vminfo[i].name)
+
+double         pvmGLOB_etime[];
+ulong          pvmGLOB_old_time[];
+ks_cpu_sysinfo pvmGLOB_cpu_sysinfo[];
+ks_cpu_sysinfo pvmGLOB_old_cpu_sysinfo[];
+ks_cpu_vminfo  pvmGLOB_cpu_vminfo[];
+ks_cpu_vminfo  pvmGLOB_old_cpu_vminfo[];
+
+int            pvmGLOB_cpu_size;
+
+pvmGLOB_realloc()
+{
+  pvmGLOB_etime           = renew pvmGLOB_etime [pvmGLOB_cpu_size];
+  pvmGLOB_old_time        = renew pvmGLOB_old_time [pvmGLOB_cpu_size];
+  pvmGLOB_cpu_sysinfo     = renew pvmGLOB_cpu_sysinfo [pvmGLOB_cpu_size];
+  pvmGLOB_old_cpu_sysinfo = renew pvmGLOB_old_cpu_sysinfo [pvmGLOB_cpu_size];
+  pvmGLOB_cpu_vminfo      = renew pvmGLOB_cpu_vminfo [pvmGLOB_cpu_size];
+  pvmGLOB_old_cpu_vminfo  = renew pvmGLOB_old_cpu_vminfo [pvmGLOB_cpu_size];
+}
+
+class p_vmstat {
+
+  /* which cpu */
+  int number$;
+  int instance;   /* instance number from the kernel */
+  int ncpus;	  /* current total number of CPUs */
+
+  /* these values are numbers of procs */
+  double runque;
+  double waiting;
+  double swpque;
+
+  /* these values are in Kbytes */
+  int swap_avail;
+  int freemem;
+
+  double pgrec;        /* page reclaims (include pageout)    */
+  double pgfrec;       /* page reclaims from free list       */
+  double pgin;         /* pageins                            */
+  double pgout;        /* pageouts                           */
+  double pgswapin;     /* pages swapped in                   */
+  double pgswapout;    /* pages swapped out                  */
+  double dfree;        /* pages freed by daemon or auto      */
+
+  double hat_fault;    /* minor page faults via hat_fault()  */
+  double as_fault;     /* minor page faults via as_fault()   */
+  double maj_fault;    /* major page faults                  */
+  double prot_fault;   /* protection faults                  */
+  double cow_fault;    /* copy-on-write faults               */
+  double zfod;         /* pages zero filled on demand        */
+
+  double sysfork;      /* forks                              */
+  double sysvfork;     /* vforks                             */
+  double sysexec;      /* execs                              */
+
+  double namei;        /* pathname lookups                   */
+  double ufsiget;      /* pathname lookups                   */
+  double ufsdirblk;    /* directory block read               */
+
+  double ufsinopage;   /* inodes taken with no attached pgs  */
+
+  /* these values are per second */
+  double pages_in;     /* pages paged in       */
+  double pages_out;    /* pages paged out      */
+  double swapins;      /* swap-in occurrences  */
+  double swapouts;     /* swap-out occurrences */
+  double scan;	       /* pages scanned        */
+  double pgrrun;       /* how many times did pageout run */
+
+  double smtx;		/* sleeps on a mutex per sec - mutex adaptive enter */
+  double interrupts;    /* interrupts including clock */
+  double intrthread;    /* interrupts as threads (below clock) */
+  double system_calls;
+  double context_switches;
+  double invol_switches;
+  double trap;
+
+  /* these are percentages of total over the last period */
+  double user_time;
+  double system_time;
+  double wait_time;
+  double idle_time;
+
+  p_vmstat$()
+  {
+    int i;
+    int n;
+    double updates;
+    int initialized = 0;
+    int last_number;
+    double hz = sysconf(_SC_CLK_TCK);
+    long pagesize = sysconf(_SC_PAGESIZE);
+    double total;
+    ulong itime;
+    ulong new_time;
+    ks_cpu_sysinfo csi;
+    ks_cpu_vminfo cvi;
+    ks_system_misc kstat$misc;
+    ks_sysinfo kstat$info;
+    ks_sysinfo old_sysinfo;
+    ks_sysinfo new_sysinfo;
+    ks_vminfo kstat$vminfo;
+    ks_vminfo old_vminfo;
+    ks_vminfo new_vminfo;
+
+    // allow this to change each time
+    ncpus = sysconf(_SC_NPROCESSORS_ONLN);
+
+    /* grab initial values */
+    if (initialized == 0) {
+      pvmGLOB_cpu_size = ncpus;
+
+      pvmGLOB_etime           = new double[pvmGLOB_cpu_size];
+      pvmGLOB_old_time        = new ulong[pvmGLOB_cpu_size];
+      pvmGLOB_cpu_sysinfo     = new ks_cpu_sysinfo[pvmGLOB_cpu_size];
+      pvmGLOB_old_cpu_sysinfo = new ks_cpu_sysinfo[pvmGLOB_cpu_size];
+      pvmGLOB_cpu_vminfo      = new ks_cpu_vminfo[pvmGLOB_cpu_size];
+      pvmGLOB_old_cpu_vminfo  = new ks_cpu_vminfo[pvmGLOB_cpu_size];
+
+      n = kstat$misc.clk_intr;
+      for(i=0; i<ncpus; i++) {
+        csi.number$ = i;
+        refresh$(csi);
+        pvmGLOB_old_cpu_sysinfo[i] = csi;
+        cvi.number$ = i;
+        refresh$(cvi);
+        pvmGLOB_old_cpu_vminfo[i] = cvi;
+        pvmGLOB_old_time[i] = n;
+        pvmGLOB_etime[i] = n / hz;
+      }
+
+      /* memory values */
+      old_vminfo = kstat$vminfo;
+      old_sysinfo = kstat$info;
+  
+      initialized = 1;
+      last_number = number$;
+
+      return;
+    }
+
+    // keep up with ncpus
+    if (ncpus > pvmGLOB_cpu_size) {
+      pvmGLOB_cpu_size = ncpus;
+      pvmGLOB_realloc();
+    }
+
+    /* select which cpu */
+    i = number$;
+    if (i < 0 || i >= ncpus) {
+      number$ = -1;
+      return;
+    }
+    instance = pvmGLOB_old_cpu_sysinfo[i].instance$;
+
+    /* how much time has gone by */
+    new_time = kstat$misc.clk_intr;
+    itime = new_time - pvmGLOB_old_time[i];
+
+    /* no time has gone by, return */
+    if (itime == 0) {
+      if (i != last_number) {
+        smtx        = pvmGLOB_cpu_sysinfo[i].mutex_adenters/pvmGLOB_etime[i];
+        interrupts       = pvmGLOB_cpu_sysinfo[i].intr/pvmGLOB_etime[i];
+        intrthread       = pvmGLOB_cpu_sysinfo[i].intrthread/pvmGLOB_etime[i];
+        system_calls     = pvmGLOB_cpu_sysinfo[i].syscall/pvmGLOB_etime[i];
+        trap            = pvmGLOB_cpu_sysinfo[i].trap/pvmGLOB_etime[i];
+        context_switches = pvmGLOB_cpu_sysinfo[i].pswitch/pvmGLOB_etime[i];
+        invol_switches   = pvmGLOB_cpu_sysinfo[i].inv_swtch/pvmGLOB_etime[i];
+        user_time        = CSIPCT(pvmGLOB_cpu_sysinfo[i].cpu[CPU_USER]);
+        system_time      = CSIPCT(pvmGLOB_cpu_sysinfo[i].cpu[CPU_KERNEL]);
+        wait_time        = CSIPCT(pvmGLOB_cpu_sysinfo[i].cpu[CPU_WAIT]);
+        idle_time        = CSIPCT(pvmGLOB_cpu_sysinfo[i].cpu[CPU_IDLE]);
+
+        sysfork   = pvmGLOB_cpu_sysinfo[i].sysfork/pvmGLOB_etime[i];
+        sysvfork  = pvmGLOB_cpu_sysinfo[i].sysvfork/pvmGLOB_etime[i];
+        sysexec   = pvmGLOB_cpu_sysinfo[i].sysexec/pvmGLOB_etime[i];
+  
+        namei     = pvmGLOB_cpu_sysinfo[i].namei/pvmGLOB_etime[i];
+        ufsiget   = pvmGLOB_cpu_sysinfo[i].ufsiget/pvmGLOB_etime[i];
+        ufsdirblk = pvmGLOB_cpu_sysinfo[i].ufsdirblk/pvmGLOB_etime[i];
+
+        ufsinopage = pvmGLOB_cpu_sysinfo[i].ufsinopage/pvmGLOB_etime[i];
+
+        pgrec  = pvmGLOB_cpu_vminfo[i].pgrec/pvmGLOB_etime[i];
+        pgfrec = pvmGLOB_cpu_vminfo[i].pgfrec/pvmGLOB_etime[i];
+        pgin   = pvmGLOB_cpu_vminfo[i].pgin/pvmGLOB_etime[i];
+        pgout  = pvmGLOB_cpu_vminfo[i].pgout/pvmGLOB_etime[i];
+        dfree  = pvmGLOB_cpu_vminfo[i].dfree/pvmGLOB_etime[i];
+
+        hat_fault    = pvmGLOB_cpu_vminfo[i].hat_fault/pvmGLOB_etime[i];
+        as_fault     = pvmGLOB_cpu_vminfo[i].as_fault/pvmGLOB_etime[i];
+        maj_fault    = pvmGLOB_cpu_vminfo[i].maj_fault/pvmGLOB_etime[i];
+        prot_fault   = pvmGLOB_cpu_vminfo[i].prot_fault/pvmGLOB_etime[i];
+        cow_fault    = pvmGLOB_cpu_vminfo[i].cow_fault/pvmGLOB_etime[i];
+        zfod         = pvmGLOB_cpu_vminfo[i].zfod/pvmGLOB_etime[i];
+
+        pages_in  = pvmGLOB_cpu_vminfo[i].pgpgin/pvmGLOB_etime[i];
+        pages_out = pvmGLOB_cpu_vminfo[i].pgpgout/pvmGLOB_etime[i];
+        swapins   = pvmGLOB_cpu_vminfo[i].swapin/pvmGLOB_etime[i];
+        swapouts  = pvmGLOB_cpu_vminfo[i].swapout/pvmGLOB_etime[i];
+        scan      = pvmGLOB_cpu_vminfo[i].scan/pvmGLOB_etime[i];
+        pgrrun    = pvmGLOB_cpu_vminfo[i].pgrrun/pvmGLOB_etime[i];
+
+        last_number = i;
+      }
+      return;
+    }
+    pvmGLOB_etime[i] = itime / hz;
+    pvmGLOB_old_time[i] = new_time;
+  
+    csi.number$ = i;
+    refresh$(csi);
+
+    cvi.number$ = i;
+    refresh$(cvi);
+
+    new_sysinfo = kstat$info;
+    updates = new_sysinfo.updates - old_sysinfo.updates;
+    if (updates > 0.0) {
+      new_vminfo = kstat$vminfo;
+    }
+
+    /* compute cpu sysinfo diffs */
+    CSI_DIFF(mutex_adenters);
+    CSI_DIFF(intr);
+    CSI_DIFF(intrthread);
+    CSI_DIFF(syscall);
+    CSI_DIFF(pswitch);
+    CSI_DIFF(inv_swtch);
+    CSI_DIFF(trap);
+    CSI_DIFF(cpu[CPU_USER]);
+    CSI_DIFF(cpu[CPU_KERNEL]);
+    CSI_DIFF(cpu[CPU_WAIT]);
+    CSI_DIFF(cpu[CPU_IDLE]);
+    CSI_DIFF(wait[W_IO]);
+    CSI_DIFF(wait[W_SWAP]);
+    CSI_DIFF(wait[W_PIO]);
+
+    CSI_DIFF(sysfork);
+    CSI_DIFF(sysvfork);
+    CSI_DIFF(sysexec);
+
+    CSI_DIFF(namei);
+    CSI_DIFF(ufsiget);
+    CSI_DIFF(ufsdirblk);
+
+    CSI_DIFF(ufsinopage);
+
+    /* compute percentages 
+    total = pvmGLOB_cpu_sysinfo[i].cpu[CPU_USER] +
+            pvmGLOB_cpu_sysinfo[i].cpu[CPU_KERNEL] +
+            pvmGLOB_cpu_sysinfo[i].cpu[CPU_WAIT] +
+            pvmGLOB_cpu_sysinfo[i].cpu[CPU_IDLE];
+    CSI_PCT(cpu[CPU_USER]);
+    CSI_PCT(cpu[CPU_KERNEL]);
+    CSI_PCT(cpu[CPU_WAIT]);
+    CSI_PCT(cpu[CPU_IDLE]);
+    */
+
+    /* save new values */
+    pvmGLOB_old_cpu_sysinfo[i] = csi;
+
+    CVI_DIFF(pgrec);
+    CVI_DIFF(pgfrec);
+    CVI_DIFF(pgin);
+    CVI_DIFF(pgout);
+    CVI_DIFF(dfree);
+
+    CVI_DIFF(hat_fault);
+    CVI_DIFF(as_fault);
+    CVI_DIFF(maj_fault);
+    CVI_DIFF(prot_fault);
+    CVI_DIFF(zfod);
+    CVI_DIFF(cow_fault);
+
+    /* compute page/swap values */
+    pvmGLOB_cpu_vminfo[i].pgpgin =
+      ((cvi.pgpgin - pvmGLOB_old_cpu_vminfo[i].pgpgin) * pagesize) / 1024;
+    pvmGLOB_cpu_vminfo[i].pgpgout =
+      ((cvi.pgpgout - pvmGLOB_old_cpu_vminfo[i].pgpgout) * pagesize) / 1024;
+    CVI_DIFF(swapin);
+    CVI_DIFF(swapout);
+    CVI_DIFF(scan);
+    CVI_DIFF(pgrrun);
+
+    /* save new values */
+    pvmGLOB_old_cpu_vminfo[i] = cvi;
+
+    /* update and return */
+    smtx             = pvmGLOB_cpu_sysinfo[i].mutex_adenters/pvmGLOB_etime[i];
+    interrupts       = pvmGLOB_cpu_sysinfo[i].intr/pvmGLOB_etime[i];
+    intrthread       = pvmGLOB_cpu_sysinfo[i].intrthread/pvmGLOB_etime[i];
+    system_calls     = pvmGLOB_cpu_sysinfo[i].syscall/pvmGLOB_etime[i];
+    context_switches = pvmGLOB_cpu_sysinfo[i].pswitch/pvmGLOB_etime[i];
+    invol_switches   = pvmGLOB_cpu_sysinfo[i].inv_swtch/pvmGLOB_etime[i];
+    trap             = pvmGLOB_cpu_sysinfo[i].trap/pvmGLOB_etime[i];
+    user_time        = CSIPCT(pvmGLOB_cpu_sysinfo[i].cpu[CPU_USER]);
+    system_time      = CSIPCT(pvmGLOB_cpu_sysinfo[i].cpu[CPU_KERNEL]);
+    wait_time        = CSIPCT(pvmGLOB_cpu_sysinfo[i].cpu[CPU_WAIT]);
+    idle_time        = CSIPCT(pvmGLOB_cpu_sysinfo[i].cpu[CPU_IDLE]);
+
+    sysfork  = pvmGLOB_cpu_sysinfo[i].sysfork/pvmGLOB_etime[i];
+    sysvfork = pvmGLOB_cpu_sysinfo[i].sysvfork/pvmGLOB_etime[i];
+    sysexec  = pvmGLOB_cpu_sysinfo[i].sysexec/pvmGLOB_etime[i];
+
+    namei     = pvmGLOB_cpu_sysinfo[i].namei/pvmGLOB_etime[i];
+    ufsiget   = pvmGLOB_cpu_sysinfo[i].ufsiget/pvmGLOB_etime[i];
+    ufsdirblk = pvmGLOB_cpu_sysinfo[i].ufsdirblk/pvmGLOB_etime[i];
+
+    ufsinopage = pvmGLOB_cpu_sysinfo[i].ufsinopage/pvmGLOB_etime[i];
+
+    pgrec   = pvmGLOB_cpu_vminfo[i].pgrec/pvmGLOB_etime[i];
+    pgfrec  = pvmGLOB_cpu_vminfo[i].pgfrec/pvmGLOB_etime[i];
+    pgin    = pvmGLOB_cpu_vminfo[i].pgin/pvmGLOB_etime[i];
+    pgout   = pvmGLOB_cpu_vminfo[i].pgout/pvmGLOB_etime[i];
+    dfree   = pvmGLOB_cpu_vminfo[i].dfree/pvmGLOB_etime[i];
+
+    hat_fault    = pvmGLOB_cpu_vminfo[i].hat_fault/pvmGLOB_etime[i];
+    as_fault     = pvmGLOB_cpu_vminfo[i].as_fault/pvmGLOB_etime[i];
+    maj_fault    = pvmGLOB_cpu_vminfo[i].maj_fault/pvmGLOB_etime[i];
+    prot_fault   = pvmGLOB_cpu_vminfo[i].prot_fault/pvmGLOB_etime[i];
+    cow_fault    = pvmGLOB_cpu_vminfo[i].cow_fault/pvmGLOB_etime[i];
+    zfod         = pvmGLOB_cpu_vminfo[i].zfod/pvmGLOB_etime[i];
+
+    pages_in  = pvmGLOB_cpu_vminfo[i].pgpgin/pvmGLOB_etime[i];
+    pages_out = pvmGLOB_cpu_vminfo[i].pgpgout/pvmGLOB_etime[i];
+    swapins   = pvmGLOB_cpu_vminfo[i].swapin/pvmGLOB_etime[i];
+    swapouts  = pvmGLOB_cpu_vminfo[i].swapout/pvmGLOB_etime[i];
+    scan      = pvmGLOB_cpu_vminfo[i].scan/pvmGLOB_etime[i];
+    pgrrun    = pvmGLOB_cpu_vminfo[i].pgrrun/pvmGLOB_etime[i];
+
+    if (updates > 0.0) {
+      freemem    = COMPUTE(freemem);
+      swap_avail = COMPUTE(swap_avail);
+
+      runque  = (new_sysinfo.runque  - old_sysinfo.runque)  / updates;
+      waiting = (new_sysinfo.waiting - old_sysinfo.waiting) / updates;
+      swpque  = (new_sysinfo.swpque  - old_sysinfo.swpque)  / updates;
+
+      /* save old memory values */
+      old_sysinfo = new_sysinfo;
+      old_vminfo  = new_vminfo;
+    }
+  }
+};
+
+#endif /* _P_VMSTAT_CLASS_SE_ */

Added: trunk/orca/lib/SE/3.4/orca_process_class.se
==============================================================================
--- (empty file)
+++ trunk/orca/lib/SE/3.4/orca_process_class.se	Wed Feb  9 12:08:55 2005
@@ -0,0 +1,912 @@
+//
+//    Copyright (c) 1995-1998, by Sun Microsystems, Inc. 
+//      All Rights Reserved
+//
+
+#ifndef _PROCESS_CLASS_SE_
+#define _PROCESS_CLASS_SE_
+
+// 16 Oct 01 richp - more clean ups, some fields not being computed
+// 19 Sep 01 richp - replaced struct_fill and changed long to pointer_t
+// process class 19 Feb 98 Adrian - 2.6 extras added
+// measured and sampled cpu comparison version 18/5/98
+// vmem_delta added for process_rules 27 Nov 98
+// added processor set info 16 Apr 99
+// merged rules version 22 Apri 99
+// added lwp info 5-27-99 Rick Weisner
+// added PCUNSET 11-05-99 Rick Weisner
+// added se_trees 08-2000 Rick Weisner
+// patched linked list login Jul 2001 Rick Weisner
+
+// Obtain data averaged over the interval between updates
+// return one process at a time, snapshot all good stuff
+// in one update then provide index$, pid$ methods to extract groups
+// of processes.
+// Store data in raw form taken from psinfo and pusage ioctls, and
+// process it when called up by class. Feeds data to workload_class.se
+
+
+#if MINOR_VERSION < 60
+# error "process_class only works on 2.6 or newer"
+#endif
+
+#include <se_trees.se>
+
+long msaccton[2]  = { PCSET, PR_MSACCT | PR_MSFORK };
+long msacctoff[2] = { PCUNSET, PR_MSACCT };
+
+// codes for action$
+#define PROC_ACTION_INIT        0       // starting point -> next index
+#define PROC_ACTION_PID         1       // get the specified pid
+                                        // do not sample all PIDS
+#define PROC_ACTION_NEXT_INDEX  2       // index order is based on /proc
+#define PROC_ACTION_NEXT_PID    3       // search for pid and return data
+                                        // do sample all PIDS
+#define PROC_ACTION_NEXT_LWP    4       // search for lwp and return data
+
+// index$ returns -1 if no more data
+// proc data updates if index$ is -1
+
+struct pr_header_t {
+  long number_lwps;
+  size_t size_of_entries;
+};
+
+struct lwp_prusage {
+  prusage_t lwp_pru;
+  long next_lwp_pru;
+};
+
+struct raw_proc_info_t {       // all the per process info
+  pointer_t       orp;         // old prusage_t pointer
+  pointer_t       nrp;         // new prusage_t pointer
+  long            nextpid;     // next pid in list
+  long            gencnt;      // update generation counter
+  // stuff from prpsinfo_t
+  long            pr_flag;     // process flags
+  long            pr_size;     // size of process image in pages
+  long            pr_oldsize;  // previous size of process image
+  long            pr_rssize;   // resident set size in pages
+  long            pr_pri;      // priority, high value is high priority
+  char            pr_nice;     // nice for cpu usage
+  char            pr_sname;    // printable character representing pr_state
+  timestruc_t     o_pr_time;   // old sampled user+system CPU time
+  timestruc_t     n_pr_time;   // sampled user+system CPU time
+  timestruc_t     o_pr_ctime;  // old usr+sys cpu time for reaped children
+  timestruc_t     n_pr_ctime;  // new usr+sys cpu time for reaped children
+  long            pr_uid;      // real user id
+  long            pr_ppid;     // process id of parent
+  int             pr_bindpset; // processor set binding
+#define PRCLSZ 8
+  char            pr_clname[PRCLSZ]; // scheduling class name
+#define PRFNSZ 16
+  char            pr_fname[PRFNSZ];  // last component of execed pathname
+#define PRARGSZ 80
+  char            pr_psargs[PRARGSZ];// initial characters of arg list
+  int             lwp_count;
+  pointer_t       olwp;  // pointers to prev. lwp prusage linked list
+  pointer_t       nlwp;  // pointers to current lwp prusage linked list
+};
+
+struct  lwp_pr_info {
+  int     lwp_id;         // always contains  lwp_id
+  double  timestamp;      // last time lwp was measured
+  double  creation;       // lwp start time
+  double  termination;    // lwp termination time stamp
+  double  user_time;      // user time in this interval
+  double  system_time;    // system call time in this interval
+  double  trap_time;      // system trap time in interval
+  double  text_pf_time;   // text page fault wait in interval
+  double  data_pf_time;   // data page fault wait in interval
+  double  kernel_pf_time; // kernel page fault wait in interval
+  double  user_lock_time; // user lock wait in interval
+  double  sleep_time;     // all other sleep time
+  double  cpu_wait_time;  // time on runqueue waiting for CPU
+  double  stoptime;       // time stopped from ^Z
+  ulong   syscalls;       // syscall/interval for this process
+  ulong   maj_faults;     // majf/interval
+  ulong   min_faults;     // minf/interval
+  ulong   total_swaps;    // swapout count
+  ulong   inblocks;       // input blocks/interval
+  ulong   outblocks;      // output blocks/interval
+  ulong   messages;       // msgin+msgout/interval
+  ulong   signals;        // signals/interval
+  ulong   vcontexts;      // voluntary context switches/interval
+  ulong   icontexts;      // in-ditto
+  ulong   charios;        // characters in and out/interval
+  ulong   next_class;
+};
+// the process class that does all the real work
+
+// get both types of hires timestamp into a common more useful form
+#define timestruc(t) (t.tv_sec + (t.tv_nsec / 1000000000.0))
+#define timeval(t) (t.tv_sec + (t.tv_usec / 1000000.0))
+#define hr_min_sec(t) sprintf("%.3f", timestruc(t))
+
+// double timestruc(timestruc_t ts_time) {
+//   return ts_time.tv_sec + (ts_time.tv_nsec / 1000000000.0);
+// }
+
+// double timeval(timeval_t tv_time) {
+//   return tv_time.tv_sec + (tv_time.tv_usec / 1000000.0);
+// }
+
+// string hr_min_sec(timestruc_t ts) {
+//   char buf[80];
+//   double tmp;
+//   tmp = timestruc(ts);
+//   buf = sprintf("%.3f", tmp);
+//   return buf;
+// }
+
+msprint(prusage_t pru, int pid, string cmd, string arg) {
+    puts("\n--------------- BEGIN ----------------");
+    printf("%d %s %s\n", pid, cmd, arg);
+    printf("Elapsed time        %12s  ", hr_min_sec(pru.pr_rtime));
+    printf("Create time %s Timestamp %s\n", hr_min_sec(pru.pr_create),
+            hr_min_sec(pru.pr_tstamp));
+    printf("User CPU time       %12s  ", hr_min_sec(pru.pr_utime));
+    printf("System call time    %12s\n", hr_min_sec(pru.pr_stime));
+    printf("System trap time    %12s  ", hr_min_sec(pru.pr_ttime));
+    printf("Text pfault sleep   %12s\n", hr_min_sec(pru.pr_tftime));
+    printf("Data pfault sleep   %12s  ", hr_min_sec(pru.pr_dftime));
+    printf("Kernel pfault sleep %12s\n", hr_min_sec(pru.pr_kftime));
+    printf("User lock sleep     %12s  ", hr_min_sec(pru.pr_ltime));
+    printf("Other sleep time    %12s\n", hr_min_sec(pru.pr_slptime));
+    printf("Wait for CPU time   %12s  ", hr_min_sec(pru.pr_wtime));
+    printf("Stopped time        %12s\n", hr_min_sec(pru.pr_stoptime));
+    printf("pf %d mf %d sw %d inb %d oub %d ms %d mr %d\n",
+            pru.pr_minf, pru.pr_majf, pru.pr_nswap, pru.pr_inblk, pru.pr_oublk,
+            pru.pr_msnd, pru.pr_mrcv);
+    printf("sig %d vctx %d ictx %d sysc %d ioch %d\n",
+            pru.pr_sigs, pru.pr_vctx, pru.pr_ictx, pru.pr_sysc, pru.pr_ioch);
+    puts("---------------- END -----------------");
+}
+
+class proc_class_t {
+  // input controls
+  int     index$;         // always contains current index or -1
+  int     pid$;           // always contains current pid
+  // for ACTION_PID mode set pid$ and set index$ to -1 to get new data
+  int     action$;
+  int     off$;
+  int     wantlwp$;       // 0 = do not want lwps, 1 = want lsps
+  // summary totals
+  double  lasttime;       // timestamp for the end of the last update
+  int     nproc;          // current number of processes
+  int     newproc;
+  int     deadproc;
+  int     missedproc;     // number of fork+vfork - newproc
+  // output data for specified process
+  long    flags;          // latest pr_flag for the process
+  double  interval;       // measured time interval for averages
+  double  timestamp;      // last time process was measured
+  double  creation;       // process start time
+  double  termination;    // process termination time stamp
+  double  elapsed;        // elapsed time for all lwps in process
+  double  total_user;     // current totals in seconds
+  double  total_system;
+  double  total_sampled_cpu;
+  double  total_child;
+  double  user_time;      // user time in this interval
+  double  system_time;    // system call time in this interval
+  double  sampled_cpu;    // total sampled cpu time
+  double  trap_time;      // system trap time in interval
+  double  child_time;     // child CPU in this interval
+  double  text_pf_time;   // text page fault wait in interval
+  double  data_pf_time;   // data page fault wait in interval
+  double  kernel_pf_time; // kernel page fault wait in interval
+  double  user_lock_time; // user lock wait in interval
+  double  sleep_time;     // all other sleep time
+  double  cpu_wait_time;  // time on runqueue waiting for CPU
+  double  stoptime;       // time stopped from ^Z
+  ulong   syscalls;       // syscall/interval for this process
+  ulong   inblocks;       // input blocks/interval
+  ulong   outblocks;      // output blocks/interval
+  ulong   vmem_size;      // size in KB
+  long    vmem_delta;     // size change in KB
+  ulong   rmem_size;      // RSS in KB
+#ifdef XMAP
+  ulong   pmem_size;      // private mem in KB
+  ulong   smem_size;      // shared mem in KB
+#endif
+  ulong   maj_faults;     // majf/interval
+  ulong   min_faults;     // minf/interval
+  ulong   total_swaps;    // swapout count
+  long    priority;       // current sched priority
+  long    niceness;       // current nice value
+  char    sched_class[PRCLSZ];    // name of class
+  ulong   messages;       // msgin+msgout/interval
+  ulong   signals;        // signals/interval
+  ulong   vcontexts;      // voluntary context switches/interval
+  ulong   icontexts;      // in-ditto
+  ulong   charios;        // characters in and out/interval
+  ulong   lwp_count;      // number of lwps for the process
+  ulong   lwp_max;        // number of contributing lwps for the process
+  int     uid;            // current uid
+  long    ppid;           // parent pid
+  int     bindpset;       // processor set binding
+  char    fname[PRFNSZ];  // last components of exec'd pathname
+  char    args[PRARGSZ];  // initial part of arg list
+  ulong   lwp_class_ptr;  // head of linked list of lwp_class_ptrs
+
+  proc$() {
+    ulong_t MAX_PID;
+    ulong_t pp;             // pointer to malloc for raw proc info
+    ulong_t pp_tmp;         // temp pointer to malloc for raw proc info
+    ulong_t pp_ret;         // temp pointer to malloc for raw proc info
+                            // chained using nextpid
+    ulong_t pp_tree;
+    raw_proc_info_t rpi;
+    raw_proc_info_t t_rpi;
+    prusage_t   ou;         // old and new usage data
+#define NU      nu[0]
+    prusage_t   nu[1];      // array of one for read and ioctl
+#define PS      ps[0]
+    psinfo_t    ps[1];      // format changes when read used
+    pr_header_t prh;
+    prusage_t   plwp;
+    ulong pnu;
+    ulong pps;
+    int   i;
+    dirent_t directory_data;
+    ulong directory_pointer;
+    ulong directory_entry;
+    ulong_t tag;
+    int process_number;   // current link in chain
+    int first_process;    // fixed first link in search chain
+    int previous_process; // last one used to build chain
+    int next_process;     // next pid
+    int broken_chain;     // flag that chain changed this time
+    int cleaning_chain;   // flag that we are in cleanup mode
+    int pfd;
+    int lfd; // file descriptor for /prod/PID/lusage
+    char procname[64];
+    char lwpname[64];     // String for /prod/PID/lusage
+    long gen;             // number of generations of update
+    int err;
+    int new_entry;
+    ulong tmp;
+    double dtmp;
+    timeval_t tmp_tval[1];
+    int pg_to_kb;
+
+    // lwp working storage
+    prusage_t lwp_info;
+    pointer_t lwp_t_ptr;
+    pointer_t olwp_t_ptr;
+    lwp_prusage lwp_t_struct;
+    lwp_prusage olwp_t_struct;
+    lwp_pr_info lwp_t_class;
+    long lwp_t_class_ptr;
+    int ircw;
+
+// **********************************************************
+
+    if (action$ == PROC_ACTION_INIT) {
+      action$ = PROC_ACTION_NEXT_INDEX;
+      // open the directory containing the process data
+      directory_pointer = opendir("/proc");
+      index$ = -1;
+      off$ = 0 ;
+      gen = -1;
+      wantlwp$ = 0;
+      first_process=-1;
+      gettimeofday(tmp_tval,0);
+      lasttime = timeval(tmp_tval[0]);
+      pg_to_kb = sysconf(_SC_PAGESIZE) / 1024;
+      pp_tree= int2int_init();
+      if (pnu == 0 || pps == 0) {
+        pnu = malloc(sizeof(nu));
+        pps = malloc(sizeof(ps));
+      }
+      return;
+    }
+
+    if (index$ == -1) {   // update the data from /proc
+      // read the first entry in the directory
+      rewinddir(directory_pointer);
+      directory_entry = readdir(directory_pointer); // read .
+      directory_entry = readdir(directory_pointer); // read ..
+      directory_entry = readdir(directory_pointer);
+      MAX_PID=0;
+      nproc = 0;
+      newproc = 0;
+      deadproc = 0;
+      gen++;
+      previous_process = -1;
+      broken_chain = 0;
+      cleaning_chain = 0;
+      while(directory_entry != NULL) {
+        directory_data = *((dirent_t *) directory_entry);
+        // get the process number and open the data file
+        // only look at specified process
+        if (action$ == PROC_ACTION_PID) {
+          process_number = pid$;
+          directory_entry = NULL;
+        } else {
+          process_number = atoi(directory_data.d_name);
+        }
+        procname = sprintf("/proc/%d/usage", process_number);
+        pfd = open(procname, O_RDONLY, 0);
+        // file cannot be accessed if pfd = -1; ignore this process
+        // may be that there is no permission or just died
+        if (pfd != -1) { // start of good pfd
+          if ( process_number > MAX_PID ) {
+            MAX_PID = process_number ;
+          }
+          tag = process_number;
+          pp_tmp = NULL ;
+          pp_ret = int2int_get(pp_tree, tag);
+          if ( pp_ret != NULL) {
+            pp_tmp = ((ulong_t) *((ulong_t *) pp_ret));
+            // Process Found
+          }
+          if (pp_tmp == NULL) {
+            // load the tree , new process
+            pp = malloc(sizeof(rpi));
+            memset(pp, 0, sizeof(rpi));
+            new_entry = 1;
+            broken_chain = 1;
+            pp_ret= int2int_put(pp_tree, tag, pp);
+            if ( pp_ret < 0 ) {
+              printf(" Error unable to insert into tree %d, %d , %x\n",
+                       pp_ret, tag, pp);
+              exit(1);
+            }
+            pp_ret = int2int_get(pp_tree, tag);
+            pp_tmp = ((ulong_t) *((ulong_t *) pp_ret));
+            if ( pp != pp_tmp) {
+              printf(" Error pointers do not match %x, %x \n",
+                       pp, pp_tmp);
+              exit(1);
+            }
+          } else {
+            new_entry = 0;
+            // Process Found
+          }
+
+          // get the existing or blank data
+          tag = process_number;
+          pp_ret = int2int_get(pp_tree, tag);
+          if ( pp_ret== NULL) {
+            printf(" Error pointer not found for process_number %d\n",
+                     tag);
+            exit(1);
+          }
+          pp = ((ulong_t) *((ulong_t *) pp_ret));
+          if ( pp == NULL) {
+            printf("process_number %d  invalid2 \n", process_number);
+            exit(1);
+          }
+          rpi = *((raw_proc_info_t *) pp);
+
+          // read usage info directly
+          // 2.6 specific, can read usage and psinfo without needing
+          // ownership or permissions on /proc entry but can't read
+          // directly into SE structure so go via malloc buffers
+
+          err = read(pfd, pnu, sizeof(nu));
+          close(pfd);
+
+          // turn on msacct
+
+          procname = sprintf("/proc/%d/ctl", process_number);
+          pfd = open(procname, O_WRONLY, 0);
+          if (pfd != -1) {
+            if ( off$ == 0 ) {
+              write(pfd, &msaccton, sizeof(msaccton));
+            } else {
+              printf("%d ms accounting off \n", process_number );
+              write(pfd, &msacctoff, sizeof(msaccton));
+            }
+            close(pfd);
+          }
+
+          // get usage
+          procname = sprintf("/proc/%d/psinfo", process_number);
+          pfd = open(procname, O_RDONLY, 0);
+          err += read(pfd, pps, sizeof(ps));
+          NU = *((prusage_t *) pnu);
+          PS = *((psinfo_t *) pps);
+          close(pfd);
+          if (err == 0) {
+            // process went away since directory was opened
+            // unlikely but still need to tidy up mallocs
+            // when it is a new entry
+            if ( new_entry == 1 ) {
+              deadproc++;
+              free(pp);
+              tag = process_number;
+              pp_ret=int2int_put(pp_tree, tag, NULL);
+              if ( pp_ret < 0 ) {
+                printf("unable to free tag = %d \n",tag);
+                exit(1);
+              }
+            }
+            if (action$ == PROC_ACTION_PID) {
+              directory_entry = NULL;
+            } else {
+              directory_entry = readdir(directory_pointer);
+            }
+            continue;
+          } else { // good pfd
+
+// ***************************************************************
+
+            if ( wantlwp$ == 1 ) {
+              // read the lwp info
+              lwpname = sprintf("/proc/%d/lusage", process_number);
+              lfd = open(lwpname, O_RDONLY, 0);
+              if ( lfd > 0 ) {
+                lwp_t_ptr = malloc(sizeof(prh));
+                err = read(lfd, lwp_t_ptr, sizeof(prh));
+                prh = *((pr_header_t *) lwp_t_ptr);
+                free(lwp_t_ptr);
+                if (err <= 0) {
+                  printf("Error reading pr_header %s error code = %d \n",
+                          lwpname, err);
+                } else { // good read of pr_head
+                  // if there is an old lwp linked list free it
+                  lwp_t_ptr = rpi.olwp ;
+                  while ( lwp_t_ptr != NULL ) {
+                    lwp_t_struct = *((lwp_prusage *) lwp_t_ptr);
+                    free(lwp_t_ptr);
+                    lwp_t_ptr = lwp_t_struct.next_lwp_pru ;
+                  }
+                  rpi.olwp = rpi.nlwp;
+                  rpi.nlwp = NULL;
+                  // create new lwp linked list
+                  for (ircw=0; ircw<prh.number_lwps; ircw++) {
+                    lwp_t_ptr = malloc(prh.size_of_entries);
+                    err = read(lfd, lwp_t_ptr, prh.size_of_entries);
+                    if (err <= 0 ) {
+                      printf("Error reading pr lwp %d/n", i);
+                      free(lwp_t_ptr);
+                    } else {
+                      if ( ircw != -1 ) {
+                        lwp_info = *((prusage_t *) lwp_t_ptr);
+                        free(lwp_t_ptr);
+                        lwp_t_ptr=malloc(sizeof(lwp_t_struct));
+                        memset(lwp_t_ptr, NULL, sizeof(lwp_t_struct));
+                        struct_empty(lwp_info, lwp_t_ptr);
+                        lwp_t_struct = *((lwp_prusage *) lwp_t_ptr);
+                        lwp_t_struct.next_lwp_pru = rpi.nlwp;
+                        struct_empty(lwp_t_struct, lwp_t_ptr);
+                        rpi.nlwp = lwp_t_ptr;
+                      } else {
+                        free(lwp_t_ptr);
+                      }
+                    }
+                  } // end for
+
+                  close(lfd);
+
+                } // end else on bad pr header read
+              } // good open on lfd
+            } // end of wantlwp
+// ********** lwp info read **************************************
+          } // good read on pfd
+
+          if (new_entry == 1 ) {
+            rpi.nextpid = first_process;
+            first_process = process_number;
+          }
+
+          // check to see if we are still dealing with the same process
+          //  we had before, and update and
+          if (new_entry == 1 || timestruc(PS.pr_start) > lasttime) {
+            newproc++;
+            if (new_entry == 0) {
+              // leftover from an old process at same pid
+              if (rpi.orp != NULL) {
+                free(rpi.orp);
+                rpi.orp = NULL;   // dump old rp, and overwrite new
+              }
+// ***************** delete old lwp info *********************
+              if ( wantlwp$ == 1 ) {
+                lwp_t_ptr = rpi.olwp ;
+                rpi.olwp = NULL;
+                while ( lwp_t_ptr != NULL ) {
+                  lwp_t_struct = *((lwp_prusage *) lwp_t_ptr);
+                  free(lwp_t_ptr);
+                  lwp_t_ptr = lwp_t_struct.next_lwp_pru ;
+                }
+              }
+// ***************** end delete old lwp info *********************
+            }
+            // static psinfo needs updating
+            rpi.pr_uid = PS.pr_uid;
+            rpi.pr_ppid = PS.pr_ppid;
+            rpi.pr_bindpset = PS.pr_lwp.pr_bindpset;
+            rpi.pr_clname = PS.pr_lwp.pr_clname;
+            rpi.pr_fname = PS.pr_fname;
+            rpi.pr_psargs = PS.pr_psargs;
+          }
+          // update usage data
+          tmp = rpi.orp;  // hang on to malloced data
+          rpi.orp = rpi.nrp;      // switch new to old
+          if (tmp == NULL) {
+            rpi.nrp = malloc(sizeof(ou));
+          } else {
+            rpi.nrp = tmp;
+          }
+          struct_empty(NU, rpi.nrp);      // save whole block
+          // update dynamic psinfo data
+          rpi.pr_oldsize = rpi.pr_size;
+          rpi.pr_size = PS.pr_size;
+          rpi.pr_rssize = PS.pr_rssize;
+          rpi.pr_pri = PS.pr_lwp.pr_pri;
+          rpi.pr_nice = PS.pr_lwp.pr_nice;
+          rpi.pr_sname = PS.pr_lwp.pr_sname;
+          rpi.pr_flag = PS.pr_flag;
+          rpi.o_pr_time = rpi.n_pr_time;
+          rpi.n_pr_time = PS.pr_time;
+          rpi.o_pr_ctime = rpi.n_pr_ctime;
+          rpi.n_pr_ctime = PS.pr_ctime;
+          rpi.lwp_count = PS.pr_nlwp;
+          rpi.gencnt = gen;
+          struct_empty(rpi, pp);
+          nproc++;
+          // printf("processed %d \n" , process_number );
+        } // end of good pfd
+        // step through the files in the directory ...
+        if (action$ == PROC_ACTION_PID) {
+          directory_entry = NULL;
+        } else {
+          directory_entry = readdir(directory_pointer);
+        }
+      } // end of directory
+// **************************************************************
+      // go through list and remove deadwood
+      // printf("first process_number %d  \n",first_process);
+      process_number = first_process;
+      next_process = -1;
+      previous_process = -1;
+      while ( process_number > 0 ) {
+        // printf("processing %d  \n",process_number);
+        if (process_number > 0 ) {
+          pp_ret = int2int_get(pp_tree, process_number);
+          if ( pp_ret == NULL) {
+            printf("unable to get process_number  %d \n", process_number);
+            exit(1);
+          }
+          pp = ((ulong_t) *((ulong_t *) pp_ret));
+          if ( pp == NULL) {
+            printf("process_number %d  invalid4 \n",process_number);
+            exit(1);
+          }
+          rpi = *((raw_proc_info_t *) pp); // rpi <- pp
+          next_process = rpi.nextpid;
+          // printf("next process %d  \n",next_process);
+          // unhook dead processes
+          if (rpi.gencnt != gen) {
+            deadproc++;
+            if (rpi.orp != NULL) {
+              free(rpi.orp);
+              rpi.orp = NULL;
+            }
+            if (rpi.nrp != NULL) {
+              free(rpi.nrp);
+              rpi.nrp = NULL;
+            }
+            if ( wantlwp$ == 1 ) {
+              lwp_t_ptr = rpi.olwp ;
+              while ( lwp_t_ptr != NULL ) {
+                lwp_t_struct = *((lwp_prusage *) lwp_t_ptr);
+                free(lwp_t_ptr);
+                lwp_t_ptr = lwp_t_struct.next_lwp_pru ;
+              }
+              lwp_t_ptr = t_rpi.nlwp ;
+              while ( lwp_t_ptr != NULL ) {
+                lwp_t_struct = *((lwp_prusage *) lwp_t_ptr);
+                free(lwp_t_ptr);
+                lwp_t_ptr = lwp_t_struct.next_lwp_pru ;
+              }
+            }
+            free(pp);
+            pp_ret = int2int_put(pp_tree, process_number , NULL);
+            if ( pp_ret < 0 ) {
+              printf("unable to free process_number \n");
+              exit(1);
+            }
+            if ( previous_process > 0 ) { // there was a previous process
+              pp_tmp = int2int_get(pp_tree, previous_process);
+              if ( pp_tmp == NULL) {
+                printf("unable to get process_number %d \n",
+                          previous_process);
+                exit(1);
+              }
+              pp = ((ulong_t) *((ulong_t *) pp_tmp));
+              if ( pp == NULL) {
+                 printf("process_number %d invalid5 \n",
+                         previous_process);
+                 exit(1);
+              }
+              rpi = *((raw_proc_info_t *) pp); // rpi <- pp
+              // printf("previous process %d  \n",previous_process);
+              rpi.nextpid = next_process;
+              struct_empty(rpi, pp);
+            } else {
+              first_process = next_process;
+            }
+          } else {
+            // update previous process ptr
+            previous_process = process_number;
+          }
+        }
+        process_number = next_process;
+      }
+      // printf(" end of deadwood removal \n");
+      gettimeofday(tmp_tval,0);
+      lasttime = timeval(tmp_tval[0]);
+      process_number = first_process;
+      index$ = -1;
+    }
+    // printf("done updating \n");
+    // printf("MAX_PID = %d \n", MAX_PID);
+// ****************************** end of update section *******************
+
+    if (action$ == PROC_ACTION_NEXT_INDEX ) {
+      // printf("PROC_ACTION_NEXT_INDEX \n");
+      if (index$ == -1) {
+        process_number = first_process;
+      } else {
+        process_number = rpi.nextpid;
+      }
+      if (process_number < 0 || process_number > MAX_PID) {
+        // ran out of data
+        process_number = -1;
+        index$ = -1;
+        pid$ = -1;
+        // printf(" thats all there is \n");
+        return;
+      }
+      index$++;
+    }
+
+    if (action$ == PROC_ACTION_NEXT_PID) {
+      // printf("PROC_ACTION_NEXT_PID \n");
+      if (index$ == -1) {
+        process_number = 0;
+      } else {
+        process_number++;
+      }
+      index$++;
+      // look for the next data
+      pp = NULL;
+      pp_ret=int2int_get(pp_tree,process_number);
+      if ( pp_ret != NULL ) {
+        pp = ((ulong_t) *((ulong_t *) pp_ret));
+      }
+      while (process_number < MAX_PID && pp == NULL) {
+        process_number++;
+        pp = NULL;
+        pp_ret=int2int_get(pp_tree,process_number);
+        if ( pp_ret != NULL ) {
+          pp = ((ulong_t) *((ulong_t *) pp_ret));
+        }
+      }
+      if (process_number < 0 || process_number > MAX_PID) {
+        // ran out of data
+        process_number = -1;
+        index$ = -1;
+        pid$ = -1;
+        // printf(" ran out of data NEXT PID \n");
+        return;
+      }
+    }
+
+    if (action$ == PROC_ACTION_PID) {
+      process_number = pid$;
+      index$ = 0;
+    }
+
+    // common code to update class once process has been chosen
+
+    pp_ret=int2int_get(pp_tree,process_number);
+    pp = NULL;
+    if (pp_ret != NULL) {
+      pp = ((ulong_t) *((ulong_t *) pp_ret));
+    }
+    if ( pp != NULL) {
+      rpi = *((raw_proc_info_t *) pp);
+      // make sure that all class data is updated
+      // index$ is already set
+      pid$ = process_number;
+      uid = rpi.pr_uid;
+      // nproc, , are already set
+      missedproc = rpi.nextpid; // for debug until fork counting
+
+      // nrp will always be set
+      NU = *((prusage_t *) rpi.nrp);
+      creation = timestruc(NU.pr_create);
+      timestamp = timestruc(NU.pr_tstamp);
+      termination = 0.0; // set later if process is dead
+      elapsed = timestruc(NU.pr_rtime);
+      total_user = timestruc(NU.pr_utime);
+      total_system = timestruc(NU.pr_stime);
+      total_child = timestruc(rpi.n_pr_ctime);
+      total_sampled_cpu = timestruc(rpi.n_pr_time);
+      flags = rpi.pr_flag;
+#ifdef PDEBUG
+      msprint(NU, pid$, rpi.pr_fname, rpi.pr_psargs);
+#endif
+      if (rpi.orp != NULL) {
+        ou = *((prusage_t *) rpi.orp);
+        interval = timestamp - timestruc(ou.pr_tstamp);
+        // interval should never be zero
+        if (interval == 0.0) {
+          printf("zero interval on pid %d state %c\n", pid$, rpi.pr_sname);
+          msprint(ou, pid$, fname, args);
+          interval = 1.0;
+        }
+        user_time = total_user - timestruc(ou.pr_utime);
+        system_time = total_system - timestruc(ou.pr_stime);
+        sampled_cpu = total_sampled_cpu - timestruc(rpi.o_pr_time);
+        trap_time = timestruc(NU.pr_ttime) - timestruc(ou.pr_ttime);
+        child_time = total_child - timestruc(rpi.o_pr_ctime);
+        text_pf_time = timestruc(NU.pr_tftime) - timestruc(ou.pr_tftime);
+        data_pf_time = timestruc(NU.pr_dftime) - timestruc(ou.pr_dftime);
+        kernel_pf_time = timestruc(NU.pr_kftime) - timestruc(ou.pr_kftime);
+        user_lock_time = timestruc(NU.pr_ltime) - timestruc(ou.pr_ltime);
+        sleep_time = timestruc(NU.pr_slptime) - timestruc(ou.pr_slptime);
+        cpu_wait_time = timestruc(NU.pr_wtime) - timestruc(ou.pr_wtime);
+        stoptime = timestruc(NU.pr_stoptime) - timestruc(ou.pr_stoptime);
+        syscalls = NU.pr_sysc - ou.pr_sysc;
+        inblocks = NU.pr_inblk - ou.pr_inblk;
+        outblocks = NU.pr_oublk - ou.pr_oublk;
+        maj_faults = NU.pr_majf - ou.pr_majf;
+        min_faults = NU.pr_minf - ou.pr_minf;
+        messages = (NU.pr_msnd + NU.pr_mrcv) - (ou.pr_msnd + ou.pr_mrcv);
+        signals = NU.pr_sigs - ou.pr_sigs;
+        vcontexts = NU.pr_vctx - ou.pr_vctx;
+        icontexts = NU.pr_ictx - ou.pr_ictx;
+        charios = NU.pr_ioch - ou.pr_ioch;
+      } else {
+        // new process will only have rpi.nrp set
+        interval = timestamp - creation; // elapsed time so far
+        if (interval == 0.0) {
+          printf("zero interval on pid %d state %c\n", pid$, rpi.pr_sname);
+          msprint(NU, pid$, fname, args);
+          interval = 1.0;
+        }
+        user_time = total_user;
+        system_time = total_system;
+        sampled_cpu = total_sampled_cpu;
+        trap_time = timestruc(NU.pr_ttime);
+        child_time = total_child;
+        text_pf_time = timestruc(NU.pr_tftime);
+        data_pf_time = timestruc(NU.pr_dftime);
+        kernel_pf_time = timestruc(NU.pr_kftime);
+        user_lock_time = timestruc(NU.pr_ltime);
+        sleep_time = timestruc(NU.pr_slptime);
+        cpu_wait_time = timestruc(NU.pr_wtime);
+        stoptime = timestruc(NU.pr_stoptime);
+        syscalls = NU.pr_sysc;
+        inblocks = NU.pr_inblk;
+        outblocks = NU.pr_oublk;
+        maj_faults = NU.pr_majf;
+        min_faults = NU.pr_minf;
+        messages = NU.pr_msnd + NU.pr_mrcv;
+        signals = NU.pr_sigs;
+        vcontexts = NU.pr_vctx;
+        icontexts = NU.pr_ictx;
+        charios = NU.pr_ioch;
+      }
+      vmem_size = rpi.pr_size;
+      vmem_delta = rpi.pr_size - rpi.pr_oldsize;
+      rmem_size = rpi.pr_rssize;
+      total_swaps = NU.pr_nswap;
+      priority = rpi.pr_pri;
+      niceness = rpi.pr_nice;
+      sched_class = rpi.pr_clname;
+      lwp_max = NU.pr_count;
+      lwp_count = rpi.lwp_count;
+      ppid = rpi.pr_ppid;
+      bindpset = rpi.pr_bindpset;
+      fname = rpi.pr_fname;
+      if (fname == "" && rpi.pr_sname == 'Z') {
+        fname = "Zombie";
+        bindpset = -1;        // no pset, but Zomb defaults to 0
+      }
+      args = rpi.pr_psargs;
+      // bug in sched pid 0 gives 100% system time
+      if (pid$ == 0) {
+        total_system = 0.0;
+        system_time = 0.0;
+      }
+#ifdef PDEBUG
+      printf("interval %.5f\n", interval);
+#endif
+// *******************************************************
+      if ( wantlwp$ == 1 ) {
+        // process lwp info
+        lwp_t_ptr = lwp_class_ptr;
+        lwp_class_ptr = NULL;
+        // if there is an old lwp class linked list free it
+        while ( lwp_t_ptr != NULL ) {
+          lwp_t_class = *((lwp_pr_info *) lwp_t_ptr);
+          free(lwp_t_ptr);
+          lwp_t_ptr = lwp_t_class.next_class ;
+        }
+        // Process lwp information
+        if ( rpi.nlwp != NULL ) {
+          lwp_t_ptr = rpi.nlwp ;
+          while ( lwp_t_ptr != NULL) {
+            lwp_t_struct = *((lwp_prusage *) lwp_t_ptr);
+            lwp_t_class.lwp_id = lwp_t_struct.lwp_pru.pr_lwpid;
+            lwp_t_class.timestamp = timestruc(lwp_t_struct.lwp_pru.pr_tstamp);
+            lwp_t_class.creation = timestruc(lwp_t_struct.lwp_pru.pr_create);
+            lwp_t_class.termination = timestruc(lwp_t_struct.lwp_pru.pr_term);
+            lwp_t_class.user_time = timestruc(lwp_t_struct.lwp_pru.pr_utime);
+            lwp_t_class.system_time = timestruc(lwp_t_struct.lwp_pru.pr_stime) + timestruc(lwp_t_struct.lwp_pru.pr_ttime);
+            lwp_t_class.text_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_tftime) ;
+            lwp_t_class.data_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_dftime) ;
+            lwp_t_class.kernel_pf_time = timestruc(lwp_t_struct.lwp_pru.pr_kftime) ;
+            lwp_t_class.user_lock_time = timestruc(lwp_t_struct.lwp_pru.pr_ltime) ;
+            lwp_t_class.sleep_time = timestruc(lwp_t_struct.lwp_pru.pr_slptime) ;
+            lwp_t_class.cpu_wait_time = timestruc(lwp_t_struct.lwp_pru.pr_wtime) ;
+            lwp_t_class.stoptime = timestruc(lwp_t_struct.lwp_pru.pr_stoptime) ;
+            lwp_t_class.min_faults = lwp_t_struct.lwp_pru.pr_minf ;
+            lwp_t_class.maj_faults = lwp_t_struct.lwp_pru.pr_majf ;
+            lwp_t_class.total_swaps = lwp_t_struct.lwp_pru.pr_nswap;
+            lwp_t_class.inblocks = lwp_t_struct.lwp_pru.pr_inblk ;
+            lwp_t_class.outblocks = lwp_t_struct.lwp_pru.pr_oublk ;
+            lwp_t_class.messages = lwp_t_struct.lwp_pru.pr_msnd + lwp_t_struct.lwp_pru.pr_mrcv;
+            lwp_t_class.signals = lwp_t_struct.lwp_pru.pr_sigs;
+            lwp_t_class.vcontexts = lwp_t_struct.lwp_pru.pr_vctx;
+            lwp_t_class.icontexts = lwp_t_struct.lwp_pru.pr_ictx;
+            lwp_t_class.syscalls = lwp_t_struct.lwp_pru.pr_sysc;
+            lwp_t_class.charios = lwp_t_struct.lwp_pru.pr_ioch;
+
+            olwp_t_ptr = rpi.olwp;
+            while ( olwp_t_ptr != NULL ) {
+              olwp_t_struct = *((lwp_prusage *) olwp_t_ptr);
+              if ( olwp_t_struct.lwp_pru.pr_lwpid ==
+                    lwp_t_struct.lwp_pru.pr_lwpid) {
+                break;
+              }
+              olwp_t_ptr = olwp_t_struct.next_lwp_pru ;
+            }
+            if ( olwp_t_ptr != NULL) {
+              lwp_t_class.user_time =  lwp_t_class.user_time - timestruc(olwp_t_struct.lwp_pru.pr_utime);
+              lwp_t_class.system_time = lwp_t_class.system_time - timestruc(olwp_t_struct.lwp_pru.pr_stime) - timestruc(olwp_t_struct.lwp_pru.pr_ttime);
+              lwp_t_class.text_pf_time = lwp_t_class.text_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_tftime) ;
+              lwp_t_class.data_pf_time = lwp_t_class.data_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_dftime) ;
+              lwp_t_class.kernel_pf_time = lwp_t_class.kernel_pf_time - timestruc(olwp_t_struct.lwp_pru.pr_kftime) ;
+              lwp_t_class.user_lock_time = lwp_t_class.user_lock_time  - timestruc(olwp_t_struct.lwp_pru.pr_ltime) ;
+              lwp_t_class.sleep_time = lwp_t_class.sleep_time - timestruc(olwp_t_struct.lwp_pru.pr_slptime) ;
+              lwp_t_class.cpu_wait_time = lwp_t_class.cpu_wait_time - timestruc(olwp_t_struct.lwp_pru.pr_wtime) ;
+              lwp_t_class.stoptime = lwp_t_class.stoptime - timestruc(olwp_t_struct.lwp_pru.pr_stoptime) ;
+              lwp_t_class.min_faults = lwp_t_class.min_faults  - olwp_t_struct.lwp_pru.pr_minf ;
+              lwp_t_class.maj_faults = lwp_t_class.maj_faults - olwp_t_struct.lwp_pru.pr_majf ;
+              lwp_t_class.total_swaps = lwp_t_class.total_swaps  - olwp_t_struct.lwp_pru.pr_nswap;
+              lwp_t_class.inblocks = lwp_t_class.inblocks  - olwp_t_struct.lwp_pru.pr_inblk ;
+              lwp_t_class.outblocks = lwp_t_class.outblocks - olwp_t_struct.lwp_pru.pr_oublk ;
+              lwp_t_class.messages = lwp_t_class.messages - olwp_t_struct.lwp_pru.pr_msnd + lwp_t_struct.lwp_pru.pr_mrcv;
+              lwp_t_class.signals = lwp_t_class.signals - olwp_t_struct.lwp_pru.pr_sigs;
+              lwp_t_class.vcontexts = lwp_t_class.vcontexts  - olwp_t_struct.lwp_pru.pr_vctx;
+              lwp_t_class.icontexts = lwp_t_class.icontexts - olwp_t_struct.lwp_pru.pr_ictx;
+              lwp_t_class.syscalls = lwp_t_class.syscalls - olwp_t_struct.lwp_pru.pr_sysc;
+              lwp_t_class.charios = lwp_t_class.charios - olwp_t_struct.lwp_pru.pr_ioch;
+
+            } // end of if old pointer
+            lwp_t_class_ptr = malloc(sizeof(lwp_t_class));
+            memset(lwp_t_class_ptr, NULL, sizeof(lwp_t_class));
+            lwp_t_class.next_class = lwp_class_ptr;
+            lwp_class_ptr = lwp_t_class_ptr;
+            struct_empty(lwp_t_class, lwp_t_class_ptr);
+            lwp_t_ptr = lwp_t_struct.next_lwp_pru ;
+          } // end of while
+        } // end of if we have lwps
+      } // end of we want lwps
+    } else { // End if valid pp
+      process_number = -1;
+      index$ = -1;
+      pid$ = -1;
+    }
+  }
+};
+
+#endif

Added: trunk/orca/lib/SE/3.4/workinfo_class.se
==============================================================================
--- (empty file)
+++ trunk/orca/lib/SE/3.4/workinfo_class.se	Wed Feb  9 12:08:55 2005
@@ -0,0 +1,342 @@
+#ifndef _WORKINFO_CLASS_SE_
+#define _WORKINFO_CLASS_SE_
+
+/***********************************************************
+*                                                          *
+*  Workinfo class is based on Adrian's workload class      *
+*                                                          *
+***********************************************************/
+
+/**************************************************************************
+Usage notes -
+This class is designed to collect process statistics for any group of
+processes defined by executed command, command arguments, executing user,
+and processor set binding.
+This class looks for WORKLOAD_INFO environment variable to initialize.
+
+To initialize workload information set WORKLOAD_INFO in the environment
+in the following way:
+WORKLOAD_INFO=name,command,args,user,exact,cnt,pset;...;...
+export WORKLOAD_INFO
+
+DO NOT use quotes ("") around string values (name,command,args,user).
+To skip one of the parameters use a SINGLE space. Missing or skipped
+parameters are ignored during process matching.
+Missing name defaults to WorkloadN, where N is workload number.
+Missing command, args, or user are skipped.
+By default pset is set to -1, cnt and exact are set to 0;
+
+Set pset to -1 to unset matching on processor set.
+Set exact to non-zero for exact matching, or 0 for pattern matching.
+Set cnt to non-zero to only count the number of processes and threads
+in a given workload. Other data is neither collected nor printed.
+
+If there is not enough process parameters defined in a set, workload
+parameters initialized in order with supplied data and the rest of the
+parameters are set to their default values.
+
+Set WORKLOAD_FIRSTMATCH=0 in the environment to match each process
+for all workloads.
+Set WORKLOAD_FIRSTMATCH=1 in the environment to match each process
+for one workload only.
+
+If WORKINFO_PRINT is defined, workload information is printed after
+initialization to allow for verification of workload data.
+
+Examples:
+export WORKLOAD_INFO='SE,se.sparc'
+Defines one workload with the name SE, command se.sparc, args and user
+empty string, exact 0 (match patterns), and no processor set.
+
+export WORKLOAD_INFO='SE,se.sparc, , ,1'
+The same as the above except matching is exact
+
+export WORKLOAD_INFO='SE,se.sparc;Ora, , ,oracle,1,1'
+Defines two workloads. In addition to SE workload, defines a workload named Ora
+that counts all processes owned by user oracle.
+
+Class usage example:
+########################################
+
+#include <workinfo_class.se>
+
+measure_workload()
+{
+  work_info_class_t ww;
+
+  ww.number = -1;
+#ifdef WORKLOAD_NO_TOTAL
+  refresh$(ww);
+#endif // WORKLOAD_NO_TOTAL
+  for (refresh$(ww); ww.number != -1; refresh$(ww)) {
+    printf("Wrkld=%s, number of procs=%d\n",ww.w.name,ww.w.count);
+    printf("Wrkld=%s, number of threads=%d\n",ww.w.name,ww.w.info.lwp_count);
+    // Get other data if not just counting processes
+    if (ww.w.cnt == 0) {
+      printf("Wrkld=%s, cpu_usr=%d\n",ww.w.name,100.0*ww.w.info.user_time);
+      printf("Wrkld=%s, cpu_sys=%d\n",ww.w.name,100.0*(ww.w.info.system_time+
+                                                       ww.w.info.trap_time));
+      printf("Wrkld=%s, cpu_wait=%d\n",ww.w.name,100.0*ww.w.info.cpu_wait_time);
+      <...>
+    }
+  }
+<...>
+}
+########################################
+
+**************************************************************************/
+
+#include <unistd.se>
+#include <dirent.se>
+#include <fcntl.se>
+#include <proc.se>
+#include <orca_process_class.se>
+#include <pwd.se>
+
+struct work_info_t {
+  string       name;    // Used by orcallator for header names for this workload
+  string       command; // String to match against command name
+  string       args;    // String to match against command args
+  string       user;    // String to match against user name
+  int          exact;   // Set to match exact names instead of patterns
+  int          cnt;     // Set to count processes and threads only
+  int          pset;    // Processor set to match against
+  int          count;   // Number of processes that matched
+  proc_class_t info;    // Use same data type to accumulate data
+};
+
+int match_proc(proc_class_t p, work_info_t w) {
+  passwd_t     pw;
+  pointer_t    ppw;
+
+  if (w.command != "") {                // If command is defined and...
+    if(w.exact == 0) {                  // pattern matching and...
+      if(!(p.fname =~ w.command)) {     // pattern does not match -
+        return 0;                       // exit and signal no match
+      }
+    } else {                            // exact command matching and...
+      if(p.fname != w.command) {        // command does not match -
+        return 0;                       // exit and signal no match
+      }
+    }
+  }
+
+  if (w.args != "") {                   // If args is defined and...
+    if(w.exact == 0) {                  // pattern matching and...
+      if(!(p.args =~ w.args)) {         // pattern does not match -
+        return 0;                       // exit and signal no match
+      }
+    } else {                            // exact args matching and...
+      if(p.args != w.args) {            // args does not match -
+        return 0;                       // exit and signal no match
+      }
+    }
+  }
+
+  if (w.user != "") {                   // If user name is defined and...
+    ppw = getpwuid(p.uid);              // Get user information for this process
+    if (ppw == 0) {                     // If unsuccessful...
+      return 0;                         // return no match
+    }
+    pw = *((passwd_t *) ppw);
+    if(w.exact == 0) {                  // pattern matching and...
+      if(!(pw.pw_name =~ w.user)) {     // pattern does not match -
+        return 0;                       // exit and signal no match
+      }
+    } else {                            // exact user name  matching and...
+      if(pw.pw_name != w.user) {        // user name does not match -
+        return 0;                       // exit and signal no match
+      }
+    }
+  }
+
+  if ((w.pset != -1) && (p.bindpset != w.pset)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+class work_info_class_t {
+  int            number;        // Current workload
+  work_info_t    w;             // Data for current workload
+
+  work_info$() {
+    work_info_t  wi[];          // Workload data dynamic array
+    int          wc = 0;        // Number of workloads
+    int          firstmatch;    // Set to use first workload that matches only
+    string       fmstring;
+    proc_class_t pp;            // Underlying process class data (snapshot)
+    proc_class_t ppzero;        // Used to zero out by copying
+    double       iv;
+    int          i;
+    string       wstring;
+    string       wstr;
+    string       dstr;
+    ulong        pwstring;
+    ulong        pwstr;
+    int          initialized = 0;
+
+    if (initialized == 0) {                     // Initialize class
+      refresh$(pp);                             // Setup proc_class
+      fmstring = getenv("WORKLOAD_FIRSTMATCH"); // Load user defined matching policy
+      wstring = getenv("WORKLOAD_INFO");        // Load user defined data for matching
+
+      // Set matching policy
+      if (fmstring != nil) {
+        firstmatch = atoi(fmstring);
+      } else {
+        // Default to each process in one workload only
+        firstmatch = 1;                         
+      }
+
+      // Allocate memory for collecting totals
+      wi = new work_info_t[1];
+      wi[wc].name = "Total";
+      wi[wc].command = "";
+      wi[wc].args = "";
+      wi[wc].user = "";
+      wi[wc].pset = -1;
+
+      // Parse wstring into individual workloads
+      for (wstr = strtok_r(wstring, ";", &pwstring); wstr != nil; wstr = strtok_r(nil, ";", &pwstring)) {
+        // Allocate memory for this workload
+        wi = renew wi[++wc+1];
+        wi[wc].name = strtok_r(wstr, ",", &pwstr);    // Get name
+        if (wi[wc].name == nil || wi[wc].name == " ") {
+          wi[wc].name = sprintf("Workload%d", wc);
+        }
+        wi[wc].command = strtok_r(nil, ",", &pwstr);  // Get command
+        if (wi[wc].command == nil || wi[wc].command == " ") {
+          wi[wc].command = "";
+        }
+        wi[wc].args = strtok_r(nil, ",", &pwstr);     // Get args
+        if (wi[wc].args == nil || wi[wc].args == " ") {
+          wi[wc].args = "";
+        }
+        wi[wc].user = strtok_r(nil, ",", &pwstr);     // Get user
+        if (wi[wc].user == nil || wi[wc].user == " ") {
+          wi[wc].user = "";
+        }
+        dstr = strtok_r(nil, ",", &pwstr);            // Get exact
+        if (dstr != nil) {
+          wi[wc].exact = atoi(dstr);
+        }
+        dstr = strtok_r(nil, ",", &pwstr);            // Get cnt
+        if (dstr != nil) {
+          wi[wc].cnt = atoi(dstr);
+        }
+        dstr = strtok_r(nil, ",", &pwstr);            // Get pset
+        if (dstr == nil || dstr == " ") {
+          wi[wc].pset = -1;
+        } else {
+          wi[wc].pset = atoi(dstr);
+        }
+      }
+
+#ifdef WORKINFO_PRINT
+      printf("\nWorkinfo class is initialized with the following data\n");
+      printf("Number of workloads = %d, firstmatch = %d (%s)\n",
+              wc, firstmatch, (firstmatch == 0 ? "Match all workloads" : "Match each process only once"));
+      for(i=1; i <= wc; i++) {
+        printf("Workload number %3d\n-------------------\n", i);
+        printf("name ....................  %s\n", wi[i].name);
+        printf("command .................  %s\n", wi[i].command);
+        printf("args ....................  %s\n", wi[i].args);
+        printf("user ....................  %s\n", wi[i].user);
+        printf("exact ...................  %d\n", wi[i].exact);
+        printf("pset ....................  %d\n", wi[i].pset);
+        printf("Only count the number of\nprocesses and threads ...  %s\n\n",
+                (wi[i].cnt == 0 ? "No" : "Yes"));
+      }
+#endif // WORKINFO_PRINT
+
+      number = -1;
+      initialized = 1;
+      return;
+    }
+
+    if (number != -1) {                            // Data is available
+      if (number > -1 && number < wc) {
+        w = wi[++number];                          // Return next workload data
+      } else {
+        w = wi[0];                                 // Set w to Total data
+        number = -1;                               // Signal end of data
+      }
+      return;
+    }
+
+    for(i=0; i <= wc; i++) {                       // Reset counters
+      wi[i].count = 0;
+      wi[i].info = ppzero;                         // Not easy to use memset instead
+    }
+    refresh$(pp);                                  // Get the snapshot
+    while (pp.index$ != -1) {
+      if (pp.termination != 0.0) {
+        continue;                                  // Don't add in dead processes
+      }
+      for(i=0; i <= wc; i++) {
+        if (i == 0 ||                              // Accumulate totals
+            (match_proc(pp, wi[i]) != 0)) {
+          wi[i].info.interval = pp.interval;       // Take the last interval seen
+          iv = pp.interval;
+          if (iv == 0.0) { iv = 1.0; }             // Safety net
+          if (pp.creation < wi[i].info.creation) { // Take the earliest creation
+            wi[i].info.creation = pp.creation;
+          }
+          if (wi[i].cnt == 0) {
+            // Track individual times
+            wi[i].info.lasttime = pp.lasttime;
+            wi[i].info.total_user += pp.total_user;
+            wi[i].info.total_system += pp.total_system;
+            wi[i].info.total_child += pp.total_child;
+            // Intervals vary, so accumulate here
+            wi[i].info.user_time += pp.user_time/iv;
+            wi[i].info.system_time += pp.system_time/iv;
+            wi[i].info.trap_time += pp.trap_time/iv;
+            wi[i].info.child_time += pp.child_time/iv;
+            wi[i].info.text_pf_time += pp.text_pf_time/iv;
+            wi[i].info.data_pf_time += pp.data_pf_time/iv;
+            wi[i].info.kernel_pf_time += pp.kernel_pf_time/iv;
+            wi[i].info.user_lock_time += pp.user_lock_time/iv;
+            wi[i].info.sleep_time += pp.sleep_time/iv;
+            wi[i].info.cpu_wait_time += pp.cpu_wait_time/iv;
+            wi[i].info.stoptime += pp.stoptime/iv;
+            wi[i].info.syscalls += pp.syscalls/iv;
+            wi[i].info.inblocks += pp.inblocks/iv;
+            wi[i].info.outblocks += pp.outblocks/iv;
+            // Next four are sizes not rates
+            wi[i].info.vmem_size += pp.vmem_size;
+            wi[i].info.rmem_size += pp.rmem_size;
+#ifdef XMAP
+            wi[i].info.pmem_size += pp.pmem_size;
+            wi[i].info.smem_size += pp.smem_size;
+#endif
+            wi[i].info.maj_faults += pp.maj_faults/iv;
+            wi[i].info.min_faults += pp.min_faults/iv;
+            wi[i].info.total_swaps += pp.total_swaps/iv;
+            wi[i].info.messages += pp.messages/iv;
+            wi[i].info.signals += pp.signals/iv;
+            wi[i].info.vcontexts += pp.vcontexts/iv;
+            wi[i].info.icontexts += pp.icontexts/iv;
+            wi[i].info.charios += pp.charios/iv;
+            // Divide these three by wi[i].count
+            wi[i].info.priority += pp.priority;
+            wi[i].info.niceness += pp.niceness;
+          }
+          wi[i].info.lwp_max += pp.lwp_max;
+          wi[i].info.lwp_count += pp.lwp_count;
+          wi[i].count++;
+          if (firstmatch == 1 && i > 0) {         // First match only counts
+            break;
+          }
+        }
+      }
+      refresh$(pp);                                // Next process
+    }
+    number = 0;
+    w = wi[number];
+  }
+};
+
+#endif



More information about the Orca-checkins mailing list