Howdy Ganglia Developers,

Doh!!!!

When I downloaded 2.5 on Thursday and noticed the lack of HP-UX support,
I should've checked the developers list to see if anyone was doing
such a thing.

Browsing the archives, I see someone already has.

Anyway, I've attached my take thus far on an hpux.c.  I haven't looked
at Martin's code yet so I don't know if it is helpful or how the
two can be merged.

It requires the use of -D_PSTAT64 on 64-bit wide HP-SUX 11.0.
Or it will.

The code was/is still in transition.  Needs cleanup in a few places
and I still haven't figured out what coding style is used in most
the ganglia code and therefore not sure how to best clean it up...
I tried to use the style in linux.c but it was irksome and I know
I have places that don't follow it.

Just thought I'd toss it out and perhaps between me an
Martin we can nail it down.

What I have works on are R390 and I'm sure once I recompile
it wide, it will work on our V2200, but I'm stopping work
on it for the day (or so I think).

HIH,

jack 
[EMAIL PROTECTED]

#include <time.h>
#include <unistd.h>
#include <sys/pstat.h>
#include <sys/utsname.h>
#include "ganglia.h"
#include "metric_typedefs.h"

/*
#include "set_metric_val.h"
*/

#define OSNAME "HP-UX"
#define OSNAME_LEN strlen(OSNAME)

/* buffer and keep global some info */
struct pst_static staticinfo;
int cpu_num_func_cpu_num = 0;


/*
 * This function is called only once by the gmond.  Use to 
 * initialize data structures, etc or just return SYNAPSE_SUCCESS;
 */
g_val_t
metric_init(void)
{
   g_val_t rval;

   if( -1 == pstat_getstatic( &staticinfo, sizeof(struct pst_static), 1, 0)){
     err_msg("metric_init() got an error from pstat_getstatic()");
     rval.int32 = SYNAPSE_FAILURE;
     return rval;
   }
   rval.int32 = SYNAPSE_SUCCESS;
   return rval;
}


#ifdef NOTYETJKP
g_val_t
pkts_in_func ( void )
{
   char *p;
   register int i;
   static g_val_t val;
   int size;
   static int stamp;
   static double        last_bytes_in,
                last_bytes_out,
                last_pkts_in,
                last_pkts_out;
   double bytes_in, bytes_out, pkts_in, pkts_out, t = 0;
   unsigned long                diff;
   p = update_file(&proc_net_dev);
   if (proc_net_dev.last_read != stamp) {

     size = ( index (p, 0x00) ) - p;
   /*  skip past the two-line header ... */
     p = index (p, '\n')+1;
     p = index (p, '\n')+1;
     p = index (p, '\n')+1;  // and skip loopback, which is always the first one
     while (*p != 0x00 )
       {
       p = index(p, ':')+1; /*  skip past the interface tag portion of this 
line */
       if ( (*p-1 != 'o') && (*p-2 != 'l') )
          {
          t = strtod( p, &p );
          bytes_in += t;
          t = strtod( p, &p );
          pkts_in += t;
          for (i = 0; i < 6; i++) strtol(p, &p, 10);
          t == strtod( p, &p );
          bytes_out += t;
         pkts_out += strtod( p, &p );
          }
          p = index (p, '\n') + 1;    // skips a line
       }
       (unsigned long) diff = pkts_in - last_pkts_in;
       if ( diff )
         {
         t = proc_net_dev.last_read - stamp;
         t = diff / t;
         debug_msg("Returning value: %f\n",t);
         }
       else
         t = 0;
       val.f = t;

       last_bytes_in  = bytes_in;
       last_pkts_in = pkts_in;
       last_pkts_out = pkts_out;
       last_bytes_out = bytes_out;

       stamp = proc_net_dev.last_read;

     }
   return val;
}

g_val_t
pkts_out_func ( void )
{
   char *p;
   register int i;
   static g_val_t val;
   int size;
   static int stamp;
   static double        last_bytes_in,
                last_bytes_out,
                last_pkts_in,
                last_pkts_out;
   double bytes_in, bytes_out, pkts_in, pkts_out, t = 0;
   unsigned long                diff;
   p = update_file(&proc_net_dev);
   if (proc_net_dev.last_read != stamp) {

     size = ( index (p, 0x00) ) - p;
   /*  skip past the two-line header ... */
     p = index (p, '\n')+1;
     p = index (p, '\n')+1;
     p = index (p, '\n')+1;  // and skip loopback, which is always the first one
     while (*p != 0x00 )
       {
       p = index(p, ':')+1; /*  skip past the interface tag portion of this 
line */
       if ( (*p-1 != 'o') && (*p-2 != 'l') )
          {
          t = strtod( p, &p );
          bytes_in += t;
          t = strtod( p, &p );
          pkts_in += t;
          for (i = 0; i < 6; i++) strtol(p, &p, 10);
          t == strtod( p, &p );
          bytes_out += t;
         pkts_out += strtod( p, &p );
          }
          p = index (p, '\n') + 1;    // skips a line
       }
       (unsigned long) diff = pkts_out - last_pkts_out;
       if ( diff )
         {
         t = proc_net_dev.last_read - stamp;
         t = diff / t;
         }
       else
         t = 0;
       val.f = t;

       last_bytes_in  = bytes_in;
       last_pkts_in = pkts_in;
       last_pkts_out = pkts_out;
       last_bytes_out = bytes_out;

       stamp = proc_net_dev.last_read;

     }
   return val;
}

g_val_t
bytes_out_func ( void )
{
   char *p;
   register int i;
   static g_val_t val;
   int size;
   static int stamp;
   static double        last_bytes_in,
                last_bytes_out,
                last_pkts_in,
                last_pkts_out;
   double bytes_in, bytes_out, pkts_in, pkts_out, t = 0;
   unsigned long                diff;
   p = update_file(&proc_net_dev);
   if (proc_net_dev.last_read != stamp) {

     size = ( index (p, 0x00) ) - p;
   /*  skip past the two-line header ... */
     p = index (p, '\n')+1;
     p = index (p, '\n')+1;
     p = index (p, '\n')+1;  // and skip loopback, which is always the first one
     while (*p != 0x00 )
       {
       p = index(p, ':')+1; /*  skip past the interface tag portion of this 
line */
       if ( (*p-1 != 'o') && (*p-2 != 'l') )
          {
          t = strtod( p, &p );
          bytes_in += t;
          t = strtod( p, &p );
          pkts_in += t;
          for (i = 0; i < 6; i++) strtol(p, &p, 10);
          t == strtod( p, &p );
          bytes_out += t;
         pkts_out += strtod( p, &p );
          }
          p = index (p, '\n') + 1;    // skips a line
       }
       (unsigned long) diff = bytes_out - last_bytes_out;
       if ( diff )
         {
         t = proc_net_dev.last_read - stamp;
         t = diff / t;
         }
       else
         t = 0;
       val.f = t;

       last_bytes_in  = bytes_in;
       last_pkts_in = pkts_in;
       last_pkts_out = pkts_out;
       last_bytes_out = bytes_out;

       stamp = proc_net_dev.last_read;

     }
   debug_msg(" **********  BYTES_OUT RETURN:  %f", val.f);
   return val;
}

g_val_t
bytes_in_func ( void )
{
   char *p;
   register int i;
   static g_val_t val;
   int size;
   static int stamp;
   static double last_bytes_in,
     last_bytes_out,
     last_pkts_in,
     last_pkts_out;
   double bytes_in, bytes_out, pkts_in, pkts_out, t = 0;
   unsigned long    diff;
   p = update_file(&proc_net_dev);
   if (proc_net_dev.last_read != stamp) {

     size = ( index (p, 0x00) ) - p;
   /*  skip past the two-line header ... */
     p = index (p, '\n')+1;
     p = index (p, '\n')+1;
     p = index (p, '\n')+1;  // and skip loopback, which is always the first one
     while (*p != 0x00 )
       {
       p = index(p, ':')+1; /*  skip past the interface tag portion of this 
line */
       debug_msg(" Last two chars: %c%c\n", *p-2, *p-1 );
       if ( (*p-1 != 'o') && (*p-2 != 'l') )
          {
          debug_msg(" Last two chars: %c%c\n", *p-2, *p-1 );
          t = strtod( p, &p );
          bytes_in += t;
          t = strtod( p, &p );
          pkts_in += t;
          for (i = 0; i < 6; i++) strtol(p, &p, 10);
          t == strtod( p, &p );
          bytes_out += t;
          pkts_out += strtod( p, &p );
          }
          p = index (p, '\n') + 1;    // skips a line
       }
       (unsigned long) diff = bytes_in - last_bytes_in;
       if ( diff )
         {
         t = proc_net_dev.last_read - stamp;
         t = diff / t;
         }
       else
         t = 0;
       val.f = t;

       last_bytes_in  = bytes_in;
       last_pkts_in = pkts_in;
       last_pkts_out = pkts_out;
       last_bytes_out = bytes_out;

       stamp = proc_net_dev.last_read;

     }
   return val;
}
#endif

g_val_t
cpu_num_func ( void )
{
   g_val_t val;
   struct pst_dynamic p;

   /* Only need to do this once */
   if (! cpu_num_func_cpu_num) {
      if( 1 == pstat_getdynamic( &p, sizeof(struct pst_dynamic), 1, 0)) 
cpu_num_func_cpu_num = p.psd_max_proc_cnt;
      else cpu_num_func_cpu_num = -1;
   }
   val.uint16 = cpu_num_func_cpu_num;

   return val;
}

g_val_t
cpu_speed_func ( void )
{
   static g_val_t val = {0};

   val.uint32 = 0;
   return val;
}

g_val_t
mem_total_func ( void )
{
   g_val_t val;

   val.uint32 = (staticinfo.physical_memory / 1024) * staticinfo.page_size;
   return val;
}

g_val_t
swap_total_func ( void )
{
   g_val_t val;

   val.uint32 = 0;
   return val;
}

g_val_t
boottime_func ( void )
{
   g_val_t val;

   val.uint32 = staticinfo.boot_time;
   return val;
}

g_val_t
sys_clock_func ( void )
{
   g_val_t val;

   val.uint32 = time(NULL);
   return val;
}

g_val_t
machine_type_func ( void )
{
   g_val_t val;
 
#ifdef __ia64__
   snprintf(val.str, MAX_G_STRING_SIZE, "ia64");
#endif
#ifdef __m68k__
   snprintf(val.str, MAX_G_STRING_SIZE, "m68k");
#endif
#ifdef __hppa__
   snprintf(val.str, MAX_G_STRING_SIZE, "hppa");
#endif

   return val;
}

g_val_t
os_name_func ( void )
{
   g_val_t val;

   snprintf(val.str, MAX_G_STRING_SIZE, "HP-UX");
   return val;
}

g_val_t
os_release_func ( void )
{
   g_val_t val;
   struct utsname uts;
   if ( uname( &uts ) == -1 )
      {
        ( void )perror ( "uname" );
        strcpy( uts.release, "uname() error");
      }

   snprintf(val.str, MAX_G_STRING_SIZE, "%s", uts.release);
   return val;
}

/* we want five states... in order... USER NICE SYS IDLE WAIT */
enum {CPU_USER, CPU_NICE, CPU_SYS, CPU_IDLE, CPU_WAIT, CPUSTATESWEWANT};

/*
 * A helper function to return the total number of cpu cycles
 */
unsigned long
#if !defined(_PSTAT64)
total_cycles_func ( uint32_t totals[])
#else
total_cycles_func ( uint64_t totals[])
#endif
{
#if !defined(_PSTAT64)
   uint32_t total_cycles = 0;
#else
   uint64_t total_cycles = 0L;
#endif
   struct pst_processor p;
   int i,j;

   for( i = 0; i < cpu_num_func_cpu_num; i++) {
     if( -1 == pstat_getprocessor( &p, sizeof(struct pst_processor), 1, 0)){
       err_msg("load_one_func() got an error from pstat_getprocessor()");
       return 0;
     }
     for( j = 0; j < CPUSTATESWEWANT; j++) {
       if( !i) totals[j] = 0;
       totals[j] += p.psp_cpu_time[j];
     }
   }
   for( j = 0; j < CPUSTATESWEWANT; j++) total_cycles += totals[j];
   return total_cycles; 
}   

g_val_t
cpu_func (int which)
{
   int j, alltime=0;
   g_val_t val;
   /* static int stamp; */
   time_t stamp;
   static time_t laststamp;
   double diff;
#if !defined(_PSTAT64)
   static uint32_t total_cycles, last_total_cycles,
                   cycles[CPUSTATESWEWANT], last_cycles[CPUSTATESWEWANT];
#else
   static uint64_t total_cycles, last_total_cycles,
                   cycles[CPUSTATESWEWANT], last_cycles[CPUSTATESWEWANT];
#endif

   if( which >= CPUSTATESWEWANT)
      {
      alltime = 1;
      which   -= CPUSTATESWEWANT;  /* idle */
      }
   stamp = time(NULL); 
   /* don't call total_cycles_func() more than once per second */ 
   if(  stamp != laststamp) 
      {
      total_cycles = total_cycles_func(cycles);
/*      printf("tot:%ld - %ld %ld %ld %ld %ld\n", total_cycles, 
        cycles[0], cycles[1], cycles[2], cycles[3], cycles[4]); */
      }

   val.f = 0.0;
   if( alltime) /* percentage since systems has been up */
      {
      if( total_cycles != 0) 
         val.f = (cycles[which]*100.0)/total_cycles;
      }
   else /* percentage in last time slice */
      {
      diff = total_cycles - last_total_cycles;
      if( diff != 0.0) 
         val.f = ((cycles[which] - last_cycles[which])/diff)*100;
      }
     
   if( stamp != laststamp)
      {     
      laststamp = stamp;
      last_total_cycles = total_cycles;
      for( j = 0; j < CPUSTATESWEWANT; j++) 
         last_cycles[j] = cycles[j];
      }

   return val;
}

g_val_t
cpu_user_func ( void )
{
  return cpu_func(CPU_USER);
}

g_val_t
cpu_nice_func ( void )
{
   return cpu_func(CPU_NICE);
}

g_val_t 
cpu_system_func ( void )
{
   return cpu_func(CPU_SYS);
}

g_val_t 
cpu_idle_func ( void )
{
   return cpu_func(CPU_IDLE);
}

g_val_t 
cpu_aidle_func ( uint32_t i )
{
   return cpu_func(CPU_IDLE + CPUSTATESWEWANT);
}

g_val_t
load_one_func ( void )
{
   g_val_t val;
   struct pst_dynamic p;

   if( -1 == pstat_getdynamic( &p, sizeof(struct pst_dynamic), 1, 0)){
     err_msg("load_one_func() got an error from pstat_getdynamic()");
     val.f = 0;
     return val;
   }
   val.f = p.psd_avg_1_min;
   return val;
}

g_val_t
load_five_func ( void )
{
   g_val_t val;
   struct pst_dynamic p;

   if( -1 == pstat_getdynamic( &p, sizeof(struct pst_dynamic), 1, 0)){
     err_msg("load_five_func() got an error from pstat_getdynamic()");
     val.f = 0;
     return val;
   }
   val.f = p.psd_avg_5_min;
   return val;
}

g_val_t
load_fifteen_func ( void )
{
   g_val_t val;
   struct pst_dynamic p;

   if( -1 == pstat_getdynamic( &p, sizeof(struct pst_dynamic), 1, 0)){
     err_msg("load_fifteen_func() got an error from pstat_getdynamic()");
     val.f = 0;
     return val;
   }
   val.f = p.psd_avg_15_min;

   return val;
}

#define PROC_CHUNK      256
g_val_t
proc_func(int pstate){
   g_val_t val;
   unsigned int i, got, sum = 0, index = 0;
   struct pst_status p[PROC_CHUNK];

   do
      {
      got = pstat_getproc( p, sizeof(struct pst_status), PROC_CHUNK, index);
      if( -1 == got) {
         err_msg("proc_func() got an error from pstat_getproc()");
         val.uint32 = 0;
         return val;
      }
      index += got;
      if( !pstate) 
         sum += got;  /* total */
      else
         for( i = 0; i < got; i++)
            if(pstate == p[i].pst_stat) /* total by state */
               ++sum;
      }
   while( got == PROC_CHUNK);
   val.uint32 = sum;
   return val;
}

g_val_t
proc_run_func( void )
{
   return proc_func(PS_RUN);
}

g_val_t
proc_total_func ( void )
{
   return proc_func(0);
}

g_val_t
mem_free_func ( void )
{
   g_val_t val;
   struct pst_dynamic p;

   if( -1 == pstat_getdynamic( &p, sizeof(struct pst_dynamic), 1, 0)){
     err_msg("mem_free_func() got an error from pstat_getdynamic()");
     val.uint32 = 0;
     return val;
   }
   val.uint32 = (p.psd_free / 1024) * staticinfo.page_size;
   return val;
}

g_val_t
mem_shared_func ( void )
{
   char *p;
   g_val_t val;
/*
   p = strstr( update_file(&proc_meminfo), "MemShared:" );
   p = skip_token(p);
   val.uint32 = strtol( p, (char **)NULL, 10 );
*/
   val.uint32 = 0;
   return val;
}

g_val_t
mem_buffers_func ( void )
{
   char *p;
   g_val_t val;
/*
   p = strstr( update_file(&proc_meminfo), "Buffers:" );
   p = skip_token(p);
   val.uint32 = strtol( p, (char **)NULL, 10 ); 
*/
   val.uint32 = 0;
   return val;
}

g_val_t
mem_cached_func ( void )
{
   char *p;
   g_val_t val;
/*
   p = strstr( update_file(&proc_meminfo), "Cached:");
   p = skip_token(p);
   val.uint32 = strtol( p, (char **)NULL, 10 );
*/
   val.uint32 = 0;
   return val;
}

g_val_t
swap_free_func ( void )
{
   char *p;
   g_val_t val;
/*
   p = strstr( update_file(&proc_meminfo), "SwapFree:" );
   p = skip_token(p);
   val.uint32 = strtol( p, (char **)NULL, 10 ); 
*/
   val.uint32 = 0;
   return val;
}

/* ===================================================== */
/* Using the UNIX-independant libdnet library */
#include "dnet.h"

static int
find_mtu(const struct intf_entry *entry, void *arg)
{
   unsigned int mtu;
   unsigned int *min = (unsigned int *) arg;

   /* Only consider interfaces that are up. */
   if (! entry->intf_flags & INTF_FLAG_UP)
      return 0;

   mtu=entry->intf_mtu;
   if ( !*min || *min>mtu)
      *min=mtu;

   return 0;
}

/* --------------------------------------------------------------------------- 
*/
g_val_t
mtu_func ( void )
{
   /* We want to find the minimum MTU (Max packet size) over all UP interfaces. 
*/
   unsigned int min=0;
   g_val_t val;

   intf_t *intf;
   intf = intf_open();
   intf_loop(intf, find_mtu, &min);
   intf_close(intf);
   val.uint32 = min;

   /* A val of 0 means there are no UP interfaces. Shouldn't happen. */
   return val;
}

/* ===================================================== */
/* Disk Usage. Using fsusage.c from the GNU fileutils-4.1.5 package. */
#include <inttypes.h>
#include <ganglia/fsusage.h>

/* Linux Specific, but we are in the Linux machine file. */
#define MOUNTS "/proc/mounts"

struct nlist {
   struct nlist *next;
   char *name;
};

#define DFHASHSIZE 101
static struct nlist *DFhashvector[DFHASHSIZE];

/* --------------------------------------------------------------------------- 
*/
unsigned int DFhash(const char *s)
{
   unsigned int hashval;
   for (hashval=0; *s != '\0'; s++)
      hashval = *s + 31 * hashval;
   return hashval % DFHASHSIZE;
}

/* --------------------------------------------------------------------------- 
*/
/* From K&R C book, pp. 144-145 */
struct nlist * seen_before(const char *name)
{
   struct nlist *found=0, *np;
   unsigned int hashval;

   /* lookup */
   hashval=DFhash(name);
   for (np=DFhashvector[hashval]; np; np=np->next) {
      if (!strcmp(name,np->name)) {
         found=np;
         break;
      }
   }
   if (!found) {    /* not found */
      np = (struct nlist *) malloc(sizeof(*np));
      if (!np || !(np->name = (char *) strdup(name)))
         return NULL;
      np->next = DFhashvector[hashval];
      DFhashvector[hashval] = np;
      return NULL;
   }
   else /* found name */
      return found;
}

/* --------------------------------------------------------------------------- 
*/
void DFcleanup()
{
   struct nlist *np, *next;
   int i;
   for (i=0; i<DFHASHSIZE; i++) {
      /* Non-standard for loop. Note the last clause happens at the end of the 
loop. */
      for (np = DFhashvector[i]; np; np=next) {
         next=np->next;
         free(np->name);
         free(np);
      }
      DFhashvector[i] = 0;
   }
}

/* --------------------------------------------------------------------------- 
*/
int remote_mount(const char *device, const char *type)
{
   /* From ME_REMOTE macro in mountlist.h:
   A file system is `remote' if its Fs_name contains a `:'
   or if (it is of type smbfs and its Fs_name starts with `//'). */
   return ((strchr(device,':') != 0)
      || (!strcmp(type, "smbfs") && device[0]=='/' && device[1]=='/')
      || (!strcmp(type, "autofs")));
}

#ifdef NOTYETJKP
/* --------------------------------------------------------------------------- 
*/
float device_space(char *mount, char *device, double *total_size, double 
*total_free)
{
   struct fs_usage fsu;
   uint32_t blocksize;
   uint32_t free;
   uint32_t size;
   double reported_total, reported_free;
   /* We report in GB = 1e9 bytes. */
   double reported_units = 1e9;
   /* The percent used: used/total * 100 */
   float pct=0.0;

   /* Avoid multiply-mounted disks - not done in df. */
   if (seen_before(device)) return pct;

   if (get_fs_usage(mount, device, &fsu)) {
      /* Ignore funky devices... */
      return pct;
   }

   free = fsu.fsu_bavail;
   /* Is the space available negative? */
   if (fsu.fsu_bavail_top_bit_set) free = 0;
   size = fsu.fsu_blocks;
   blocksize = fsu.fsu_blocksize;
   /* Keep running sum of total used, free local disk space. */
   *total_size += size * (double) blocksize;
   *total_free += free * (double) blocksize;
   /* The percentage of space used on this partition. */
   pct = size ? ((size - free) / (float) size) * 100 : 0.0;
   return pct;
}

/* --------------------------------------------------------------------------- 
*/
float find_disk_space(double *total_size, double *total_free)
{
   FILE *mounts;
   char procline[256];
   char mount[128], device[128], type[32];
   /* We report in GB = 1e9 bytes. */
   double reported_units = 1e9;
   /* Track the most full disk partition, report with a percentage. */
   float thispct, max=0.0;
   int i, rc;
   struct nlist *np, *next;

   /* Read all currently mounted filesystems. */
   mounts=fopen(MOUNTS,"r");
   if (!mounts) {
      debug_msg("Df Error: could not open mounts file %s. Are we on the right 
OS?\n", MOUNTS);
      return max;
   }
   while ( fgets(procline, sizeof(procline), mounts) ) {
      rc=sscanf(procline, "%s %s %s ", device, mount, type);
      if (!rc) continue;
      if (remote_mount(device, type)) continue;
      thispct = device_space(mount, device, total_size, total_free);
      if (!max || max<thispct)
         max = thispct;
   }
   fclose(mounts);

   *total_size = *total_size / reported_units;
   *total_free = *total_free / reported_units;
   /* debug_msg("For all disks: %.3f GB total, %.3f GB free for users.", 
*total_size, *total_free); */

   DFcleanup();
   return max;
}

/* --------------------------------------------------------------------------- 
*/
g_val_t
disk_free_func( void )
{
   double total_free=0.0;
   double total_size=0.0;
   g_val_t val;

   find_disk_space(&total_size, &total_free);

   val.d = total_free;
   return val;
}


/* --------------------------------------------------------------------------- 
*/
g_val_t
disk_total_func( void )
{
   double total_free=0.0;
   double total_size=0.0;
   g_val_t val;

   find_disk_space(&total_size, &total_free);

   val.d = total_size;
   return val;
}

/* --------------------------------------------------------------------------- 
*/
g_val_t
part_max_used_func( void )
{
   double total_free=0.0;
   double total_size=0.0;
   float most_full;
   g_val_t val;

   most_full = find_disk_space(&total_size, &total_free);

   val.f = most_full;
   return val;
}

#endif


Reply via email to