[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