Logo Search packages:      
Sourcecode: pcp version File versions  Download package

pmda.c

/*
 * MacOS X kernel PMDA
 * "darwin" is easier to type than "macosx",  especially for Aussies. ;-)
 * Copyright (c) 2004 Silicon Graphics, Inc.  All Rights Reserved.
 * 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 * 
 * Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
 * Mountain View, CA 94043, USA, or: http://www.sgi.com
 */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <syslog.h>
#include <unistd.h>
#include <sys/mount.h>
#include <sys/utsname.h>
#include <mach/mach.h>
#include "pmapi.h"
#include "impl.h"
#include "pmda.h"
#include "domain.h"

#include "disk.h"
#include "network.h"


#define page_count_to_kb(x) (((__uint64_t)(x) << mach_page_shift) >> 10)
#define page_count_to_mb(x) (((__uint64_t)(x) << mach_page_shift) >> 20)

static pmdaInterface          dispatch;
static int              _isDSO = 1; /* =0 I am a daemon */

mach_port_t       mach_host = 0;
unsigned int            mach_page_size = 0;
unsigned int            mach_page_shift = 0;

unsigned int            mach_hertz = 0;
extern int refresh_hertz(unsigned int *);

int               mach_uname_error = 0;
struct utsname          mach_uname = { { 0 } };
extern int refresh_uname(struct utsname *);

int               mach_loadavg_error = 0;
float             mach_loadavg[3] = { 0,0,0 };
extern int refresh_loadavg(float *);

int               mach_cpuload_error = 0;
struct host_cpu_load_info     mach_cpuload = { { 0 } };
extern int refresh_cpuload(struct host_cpu_load_info *);

int               mach_vmstat_error = 0;
struct vm_statistics    mach_vmstat = { 0 };
extern int refresh_vmstat(struct vm_statistics *);

int               mach_fs_error = 0;
struct statfs           *mach_fs = NULL;
extern int refresh_filesys(struct statfs **, pmdaIndom *);

int               mach_disk_error = 0;
struct diskstats  mach_disk = { 0 };
extern int refresh_disks(struct diskstats *, pmdaIndom *);

int               mach_cpu_error = 0;
struct processor_cpu_load_info      *mach_cpu = NULL;
extern int refresh_cpus(struct processor_cpu_load_info **, pmdaIndom *);

int               mach_uptime_error = 0;
unsigned int            mach_uptime = 0;
extern int refresh_uptime(unsigned int *);

int               mach_net_error = 0;
struct netstats         mach_net = { 0 };
extern int refresh_network(struct netstats *, pmdaIndom *);
extern void init_network(void);

int               mach_nfs_error = 0;
struct nfsstats         mach_nfs = { 0 };
extern int refresh_nfs(struct nfsstats *);

/*
 * Metric Instance Domains (statically initialized ones only)
 */
static pmdaInstid loadavg_indom_id[] = {
    { 1, "1 minute" },  { 5, "5 minute" },      { 15, "15 minute" }
};
#define LOADAVG_COUNT   (sizeof(loadavg_indom_id)/sizeof(pmdaInstid))

static pmdaInstid nfs3_indom_id[] = {
    { 0, "null" },      { 1, "getattr" }, { 2, "setattr" },
    { 3, "lookup" },    { 4, "access" },  { 5, "readlink" },
    { 6, "read" },      { 7, "write" },         { 8, "create" },
    { 9, "mkdir" },     { 10, "symlink" },      { 11, "mknod" },
    { 12, "remove" },   { 13, "rmdir" },  { 14, "rename" },
    { 15, "link" },     { 16, "readdir" },      { 17, "readdir+" },
    { 18, "statfs" },   { 19, "fsinfo" }, { 20, "pathconf" },
    { 21, "commit" },   { 22, "getlease" },     { 23, "vacate" },
    { 24, "evict" }
};
#define NFS3_RPC_COUNT  (sizeof(nfs3_indom_id)/sizeof(pmdaInstid))

/*
 * Metric Instance Domain table
 */
enum {
    LOADAVG_INDOM,            /* 0 - 1, 5, 15 minute run queue averages */
    FILESYS_INDOM,            /* 1 - set of all mounted filesystems */
    DISK_INDOM,               /* 2 - set of all disk devices */
    CPU_INDOM,                /* 3 - set of all processors */
    NETWORK_INDOM,            /* 4 - set of all network interfaces */
    NFS3_INDOM,               /* 6 - nfs v3 operations */
    NUM_INDOMS                /* total number of instance domains */
};

static pmdaIndom indomtab[] = {
    { LOADAVG_INDOM,    3, loadavg_indom_id },
    { FILESYS_INDOM,    0, NULL },
    { DISK_INDOM, 0, NULL },
    { CPU_INDOM,  0, NULL },
    { NETWORK_INDOM,    0, NULL },
    { NFS3_INDOM, NFS3_RPC_COUNT, nfs3_indom_id },
};

/*
 * Fetch clusters and metric table
 */
enum {
    CLUSTER_INIT = 0,         /*  0 = values we know at startup */
    CLUSTER_VMSTAT,           /*  1 = mach memory statistics */
    CLUSTER_KERNEL_UNAME,     /*  2 = utsname information */
    CLUSTER_LOADAVG,          /*  3 = run queue averages */
    CLUSTER_HINV,       /*  4 = hardware inventory */
    CLUSTER_FILESYS,          /*  5 = mounted filesystems */
    CLUSTER_CPULOAD,          /*  6 = number of ticks in state */
    CLUSTER_DISK,       /*  7 = disk device statistics */
    CLUSTER_CPU,        /*  8 = per-cpu statistics */
    CLUSTER_UPTIME,           /*  9 = system uptime in seconds */
    CLUSTER_NETWORK,          /* 10 = networking statistics */
    CLUSTER_NFS,        /* 11 = nfs filesystem statistics */
    NUM_CLUSTERS        /* total number of clusters */
};

#ifdef HAVE_NQNFS_LEASES
#define NQNFS_LEASE(x) x
#define PM_TYPE_NQNFS_LEASE PM_TYPE_32
#else
static int lease;
#define NQNFS_LEASE(x) &lease
#define PM_TYPE_NQNFS_LEASE PM_TYPE_NOSUPPORT
#endif

static pmdaMetric metrictab[] = {

/* hinv.pagesize */
  { &mach_page_size, 
    { PMDA_PMID(CLUSTER_INIT,0), PM_TYPE_U32, PM_INDOM_NULL,
      PM_SEM_DISCRETE, PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, },
/* kernel.all.hz */
  { &mach_hertz,
    { PMDA_PMID(CLUSTER_INIT,1), PM_TYPE_U32, PM_INDOM_NULL,
      PM_SEM_DISCRETE, PMDA_PMUNITS(0,-1,1,0,PM_TIME_SEC,PM_COUNT_ONE) }, },

/* hinv.physmem */
  { NULL, 
    { PMDA_PMID(CLUSTER_VMSTAT,2), PM_TYPE_U32, PM_INDOM_NULL,
      PM_SEM_DISCRETE, PMDA_PMUNITS(1,0,0,PM_SPACE_MBYTE,0,0) }, },
/* mem.physmem */
  { NULL,
    { PMDA_PMID(CLUSTER_VMSTAT,3), PM_TYPE_U64, PM_INDOM_NULL,
      PM_SEM_DISCRETE, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* mem.freemem */
  { NULL,
    { PMDA_PMID(CLUSTER_VMSTAT,4), PM_TYPE_U64, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* mem.active */
  { NULL,
    { PMDA_PMID(CLUSTER_VMSTAT,5), PM_TYPE_U64, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* mem.inactive */
  { NULL,
    { PMDA_PMID(CLUSTER_VMSTAT,6), PM_TYPE_U64, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* mem.pages.free */
  { &mach_vmstat.free_count,
    { PMDA_PMID(CLUSTER_VMSTAT,7), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* mem.pages.active */
  { &mach_vmstat.active_count,
    { PMDA_PMID(CLUSTER_VMSTAT,8), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* mem.pages.inactive */
  { &mach_vmstat.inactive_count,
    { PMDA_PMID(CLUSTER_VMSTAT,9), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* mem.pages.reactivated */
  { &mach_vmstat.reactivations,
    { PMDA_PMID(CLUSTER_VMSTAT,10), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* mem.pages.wired */
  { &mach_vmstat.wire_count,
    { PMDA_PMID(CLUSTER_VMSTAT,11), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* mem.pages.faults */
  { &mach_vmstat.faults,
    { PMDA_PMID(CLUSTER_VMSTAT,12), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* mem.pages.cow_faults */
  { &mach_vmstat.cow_faults,
    { PMDA_PMID(CLUSTER_VMSTAT,13), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* mem.pages.zero_filled */
  { &mach_vmstat.zero_fill_count,
    { PMDA_PMID(CLUSTER_VMSTAT,14), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* mem.pageins */
  { &mach_vmstat.pageins,
    { PMDA_PMID(CLUSTER_VMSTAT,15), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* mem.pageouts */
  { &mach_vmstat.pageouts,
    { PMDA_PMID(CLUSTER_VMSTAT,16), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* mem.cache_hits */
  { &mach_vmstat.hits,
    { PMDA_PMID(CLUSTER_VMSTAT,17), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* mem.cache_lookups */
  { &mach_vmstat.lookups,
    { PMDA_PMID(CLUSTER_VMSTAT,18), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* mem.util.wired */
  { NULL,
    { PMDA_PMID(CLUSTER_VMSTAT,19), PM_TYPE_U64, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* mem.util.active */
  { NULL,
    { PMDA_PMID(CLUSTER_VMSTAT,20), PM_TYPE_U64, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* mem.util.inactive */
  { NULL,
    { PMDA_PMID(CLUSTER_VMSTAT,21), PM_TYPE_U64, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* mem.util.free */
  { NULL,
    { PMDA_PMID(CLUSTER_VMSTAT,22), PM_TYPE_U64, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },

/* kernel.uname.release */
  { mach_uname.release,
    { PMDA_PMID(CLUSTER_KERNEL_UNAME, 23), PM_TYPE_STRING, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, },
/* kernel.uname.version */
  { mach_uname.version,
    { PMDA_PMID(CLUSTER_KERNEL_UNAME, 24), PM_TYPE_STRING, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, },
/* kernel.uname.sysname */
  { mach_uname.sysname,
    { PMDA_PMID(CLUSTER_KERNEL_UNAME, 25), PM_TYPE_STRING, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, },
/* kernel.uname.machine */
  { mach_uname.machine,
    { PMDA_PMID(CLUSTER_KERNEL_UNAME, 26), PM_TYPE_STRING, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, },
/* kernel.uname.nodename */
  { mach_uname.nodename,
    { PMDA_PMID(CLUSTER_KERNEL_UNAME, 27), PM_TYPE_STRING, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, },
/* pmda.uname */
  { NULL,
    { PMDA_PMID(CLUSTER_KERNEL_UNAME, 28), PM_TYPE_STRING, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, },
/* pmda.version */
  { NULL,
    { PMDA_PMID(CLUSTER_KERNEL_UNAME, 29), PM_TYPE_STRING, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, },

/* kernel.all.load */
  { NULL,
    { PMDA_PMID(CLUSTER_LOADAVG,30), PM_TYPE_FLOAT, LOADAVG_INDOM,
      PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, },

/* hinv.nfilesys */
  { NULL,
    { PMDA_PMID(CLUSTER_FILESYS,31), PM_TYPE_U32, PM_INDOM_NULL,
      PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* filesys.capacity */ 
  { NULL,
    { PMDA_PMID(CLUSTER_FILESYS,32), PM_TYPE_U64, FILESYS_INDOM,
      PM_SEM_DISCRETE, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* filesys.used */
  { NULL,
    { PMDA_PMID(CLUSTER_FILESYS,33), PM_TYPE_U64, FILESYS_INDOM,
      PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* filesys.free */
  { NULL,
     { PMDA_PMID(CLUSTER_FILESYS,34), PM_TYPE_U64, FILESYS_INDOM,
       PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* filesys.usedfiles */
  { NULL,
     { PMDA_PMID(CLUSTER_FILESYS,35), PM_TYPE_U32, FILESYS_INDOM,
       PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, },
/* filesys.freefiles */
  { NULL,
     { PMDA_PMID(CLUSTER_FILESYS,36), PM_TYPE_U32, FILESYS_INDOM,
       PM_SEM_INSTANT, PMDA_PMUNITS(0,0,0,0,0,0) }, },
/* filesys.mountdir */
  { NULL,
     { PMDA_PMID(CLUSTER_FILESYS,37), PM_TYPE_STRING, FILESYS_INDOM,
       PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,0,0,0,0) }, },
/* filesys.full */
  { NULL,
     { PMDA_PMID(CLUSTER_FILESYS,38), PM_TYPE_DOUBLE, FILESYS_INDOM,
       PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,0,0,0,0) }, },
/* filesys.blocksize */
  { NULL,
     { PMDA_PMID(CLUSTER_FILESYS,39), PM_TYPE_U32, FILESYS_INDOM,
       PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, },
/* filesys.avail */
  { NULL,
     { PMDA_PMID(CLUSTER_FILESYS,40), PM_TYPE_U64, FILESYS_INDOM,
       PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* filesys.type */
  { NULL,
     { PMDA_PMID(CLUSTER_FILESYS,41), PM_TYPE_STRING, FILESYS_INDOM,
       PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,0,0,0,0) }, },

/* kernel.all.cpu.user */
  { NULL,
    { PMDA_PMID(CLUSTER_CPULOAD,42), PM_TYPE_U32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
/* kernel.all.cpu.nice */
  { NULL,
    { PMDA_PMID(CLUSTER_CPULOAD,43), PM_TYPE_U32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
/* kernel.all.cpu.sys */
  { NULL,
    { PMDA_PMID(CLUSTER_CPULOAD,44), PM_TYPE_U32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
/* kernel.all.cpu.idle */
  { NULL,
    { PMDA_PMID(CLUSTER_CPULOAD,45), PM_TYPE_U32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },

/* hinv.ndisk */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,46), PM_TYPE_U32, PM_INDOM_NULL,
      PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* disk.dev.read */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,47), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* disk.dev.write */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,48), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* disk.dev.total */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,49), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* disk.dev.read_bytes */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,50), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
      PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* disk.dev.write_bytes */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,51), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
      PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* disk.dev.total_bytes */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,52), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
      PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* disk.dev.blkread */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,53), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* disk.dev.blkwrite */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,54), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* disk.dev.blktotal */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,55), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* disk.dev.read_time */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,56), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,1,0,0,PM_TIME_NSEC,0) }, },
/* disk.dev.write_time */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,57), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,1,0,0,PM_TIME_NSEC,0) }, },
/* disk.dev.total_time */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,58), PM_TYPE_U64, DISK_INDOM, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,1,0,0,PM_TIME_NSEC,0) }, },
/* disk.all.read */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,59), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* disk.all.write */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,60), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* disk.all.total */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,61), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* disk.all.read_bytes */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,62), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
      PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* disk.all.write_bytes */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,63), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
      PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* disk.all.total_bytes */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,64), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
      PMDA_PMUNITS(1,0,0,PM_SPACE_KBYTE,0,0) }, },
/* disk.all.blkread */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,65), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* disk.all.blkwrite */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,66), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* disk.all.blktotal */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,67), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* disk.all.read_time */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,68), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,1,0,0,PM_TIME_NSEC,0) }, },
/* disk.all.write_time */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,69), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,1,0,0,PM_TIME_NSEC,0) }, },
/* disk.all.total_time */
  { NULL,
    { PMDA_PMID(CLUSTER_DISK,70), PM_TYPE_U64, PM_INDOM_NULL, PM_SEM_COUNTER,
      PMDA_PMUNITS(0,1,0,0,PM_TIME_NSEC,0) }, },

/* hinv.ncpu */
  { NULL,
    { PMDA_PMID(CLUSTER_CPU,71), PM_TYPE_U32, PM_INDOM_NULL,
      PM_SEM_DISCRETE, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* kernel.percpu.cpu.user */
  { NULL,
    { PMDA_PMID(CLUSTER_CPU,72), PM_TYPE_U32, CPU_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
/* kernel.percpu.cpu.nice */
  { NULL,
    { PMDA_PMID(CLUSTER_CPU,73), PM_TYPE_U32, CPU_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
/* kernel.percpu.cpu.sys */
  { NULL,
    { PMDA_PMID(CLUSTER_CPU,74), PM_TYPE_U32, CPU_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },
/* kernel.percpu.cpu.idle */
  { NULL,
    { PMDA_PMID(CLUSTER_CPU,75), PM_TYPE_U32, CPU_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,1,0,0,PM_TIME_MSEC,0) }, },

/* kernel.all.uptime */
  { &mach_uptime,
    { PMDA_PMID(CLUSTER_UPTIME,76), PM_TYPE_U32, PM_INDOM_NULL,
      PM_SEM_INSTANT, PMDA_PMUNITS(0,1,1,0,PM_TIME_SEC,PM_COUNT_ONE) }, },

/* network.interface.in.bytes */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,77), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(1,0,0,PM_SPACE_BYTE,0,0) }, },
/* network.interface.in.packets */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,78), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* network.interface.in.errors */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,79), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* network.interface.in.drops */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,80), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* network.interface.in.mcasts */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,81), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* network.interface.out.bytes */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,82), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(1,0,0,0,PM_SPACE_BYTE,0) }, },
/* network.interface.out.packets */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,83), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* network.interface.out.errors */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,84), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* network.interface.out.mcasts */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,85), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* network.interface.collisions */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,86), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* network.interface.mtu */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,87), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,0,PM_SPACE_BYTE,0) }, },
/* network.interface.baudrate */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,88), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_INSTANT, PMDA_PMUNITS(1,0,0,0,PM_SPACE_BYTE,0) }, },
/* network.interface.total.bytes */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,89), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(1,0,0,0,PM_SPACE_BYTE,0) }, },
/* network.interface.total.packets */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,90), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* network.interface.total.errors */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,91), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* network.interface.total.drops */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,92), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* network.interface.total.mcasts */
  { NULL, 
    { PMDA_PMID(CLUSTER_NETWORK,93), PM_TYPE_U64, NETWORK_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },

/* nfs3.client.calls */
  { NULL,
    { PMDA_PMID(CLUSTER_NFS,94), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* nfs3.client.reqs */
  { NULL,
    { PMDA_PMID(CLUSTER_NFS,95), PM_TYPE_32, NFS3_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* nfs3.server.calls */
  { NULL,
    { PMDA_PMID(CLUSTER_NFS,96), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* nfs3.server.reqs */
  { NULL,
    { PMDA_PMID(CLUSTER_NFS,97), PM_TYPE_32, NFS3_INDOM,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.rpccnt */
  { &mach_nfs.rpcrequests,
    { PMDA_PMID(CLUSTER_NFS,98), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.rpcretrans */
  { &mach_nfs.rpcretries,
    { PMDA_PMID(CLUSTER_NFS,99), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.rpctimeouts */
  { &mach_nfs.rpctimeouts,
    { PMDA_PMID(CLUSTER_NFS,100), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.rpcinvalid */
  { &mach_nfs.rpcinvalid,
    { PMDA_PMID(CLUSTER_NFS,101), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.rpcunexpected */
  { &mach_nfs.rpcunexpected,
    { PMDA_PMID(CLUSTER_NFS,102), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.attrcache.hits */
  { &mach_nfs.attrcache_hits,
    { PMDA_PMID(CLUSTER_NFS,103), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.attrcache.misses */
  { &mach_nfs.attrcache_misses,
    { PMDA_PMID(CLUSTER_NFS,104), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.lookupcache.hits */
  { &mach_nfs.lookupcache_hits,
    { PMDA_PMID(CLUSTER_NFS,105), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.lookupcache.misses */
  { &mach_nfs.lookupcache_misses,
    { PMDA_PMID(CLUSTER_NFS,106), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.biocache.read.hits */
  { &mach_nfs.read_bios,
    { PMDA_PMID(CLUSTER_NFS,107), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.biocache.read.misses */
  { &mach_nfs.biocache_reads,
    { PMDA_PMID(CLUSTER_NFS,108), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.biocache.write.hits */
  { &mach_nfs.write_bios,
    { PMDA_PMID(CLUSTER_NFS,109), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.biocache.write.misses */
  { &mach_nfs.biocache_writes,
    { PMDA_PMID(CLUSTER_NFS,110), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.biocache.readlink.hits */
  { &mach_nfs.readlink_bios,
    { PMDA_PMID(CLUSTER_NFS,111), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.biocache.readlink.misses */
  { &mach_nfs.biocache_readlinks,
    { PMDA_PMID(CLUSTER_NFS,112), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.biocache.readdir.hits */
  { &mach_nfs.readdir_bios,
    { PMDA_PMID(CLUSTER_NFS,113), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.biocache.readdir.misses */
  { &mach_nfs.biocache_readdirs,
    { PMDA_PMID(CLUSTER_NFS,114), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.direofcache.hits */
  { &mach_nfs.direofcache_hits,
    { PMDA_PMID(CLUSTER_NFS,115), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.client.direofcache.misses */
  { &mach_nfs.direofcache_misses,
    { PMDA_PMID(CLUSTER_NFS,116), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.server.retfailed */
  { &mach_nfs.srvrpc_errs,
    { PMDA_PMID(CLUSTER_NFS,117), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.server.faults */
  { &mach_nfs.srvrpc_errs,
    { PMDA_PMID(CLUSTER_NFS,118), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.server.cache.inprog */
  { &mach_nfs.srvcache_inproghits,
    { PMDA_PMID(CLUSTER_NFS,119), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.server.cache.nonidem */
  { &mach_nfs.srvcache_nonidemdonehits,
    { PMDA_PMID(CLUSTER_NFS,120), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.server.cache.idem */
  { &mach_nfs.srvcache_idemdonehits,
    { PMDA_PMID(CLUSTER_NFS,121), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.server.cache.misses */
  { &mach_nfs.srvcache_misses,
    { PMDA_PMID(CLUSTER_NFS,122), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.server.nqnfs.leases */
  { NQNFS_LEASE(&mach_nfs.srvnqnfs_leases),
    { PMDA_PMID(CLUSTER_NFS,123), PM_TYPE_NQNFS_LEASE, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.server.nqnfs.maxleases */
  { NQNFS_LEASE(&mach_nfs.srvnqnfs_maxleases),
    { PMDA_PMID(CLUSTER_NFS,124), PM_TYPE_NQNFS_LEASE, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.server.nqnfs.getleases */
  { NQNFS_LEASE(&mach_nfs.srvnqnfs_getleases),
    { PMDA_PMID(CLUSTER_NFS,125), PM_TYPE_NQNFS_LEASE, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.server.vopwrites */
  { &mach_nfs.srvvop_writes,
    { PMDA_PMID(CLUSTER_NFS,126), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.server.pageins */
  { &mach_nfs.pageins,
    { PMDA_PMID(CLUSTER_NFS,127), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },
/* rpc.server.pageouts */
  { &mach_nfs.pageouts,
    { PMDA_PMID(CLUSTER_NFS,128), PM_TYPE_32, PM_INDOM_NULL,
      PM_SEM_COUNTER, PMDA_PMUNITS(0,0,1,0,0,PM_COUNT_ONE) }, },

};

static void
darwin_refresh(int *need_refresh)
{
    if (need_refresh[CLUSTER_LOADAVG])
      mach_loadavg_error = refresh_loadavg(mach_loadavg);
    if (need_refresh[CLUSTER_CPULOAD])
      mach_cpuload_error = refresh_cpuload(&mach_cpuload);
    if (need_refresh[CLUSTER_VMSTAT])
      mach_vmstat_error = refresh_vmstat(&mach_vmstat);
    if (need_refresh[CLUSTER_KERNEL_UNAME])
      mach_uname_error = refresh_uname(&mach_uname);
    if (need_refresh[CLUSTER_FILESYS])
      mach_fs_error = refresh_filesys(&mach_fs, &indomtab[FILESYS_INDOM]);
    if (need_refresh[CLUSTER_DISK])
      mach_disk_error = refresh_disks(&mach_disk, &indomtab[DISK_INDOM]);
    if (need_refresh[CLUSTER_CPU])
      mach_cpu_error = refresh_cpus(&mach_cpu, &indomtab[CPU_INDOM]);
    if (need_refresh[CLUSTER_UPTIME])
      mach_uptime_error = refresh_uptime(&mach_uptime);
    if (need_refresh[CLUSTER_NETWORK])
      mach_net_error = refresh_network(&mach_net, &indomtab[NETWORK_INDOM]);
    if (need_refresh[CLUSTER_NFS])
      mach_nfs_error = refresh_nfs(&mach_nfs);
}

static inline int
fetch_loadavg(unsigned int item, unsigned int inst, pmAtomValue *atom)
{
    if (mach_loadavg_error)
      return mach_loadavg_error;
    switch (item) {
    case 30:  /* kernel.all.load */
      if (inst == 1)
          atom->f = mach_loadavg[0];
      else if (inst == 5)
          atom->f = mach_loadavg[1];
      else if (inst == 15)
          atom->f = mach_loadavg[2];
      else
          return PM_ERR_INST; 
      return 1;
    }
    return PM_ERR_PMID;
}

static inline int
fetch_cpuload(unsigned int item, pmAtomValue *atom)
{
    if (mach_cpuload_error)
      return mach_cpuload_error;
    switch (item) {
    case 42: /* kernel.all.cpu.user */
      atom->ul = LOAD_SCALE * (double)
            mach_cpuload.cpu_ticks[CPU_STATE_USER] / mach_hertz;
        return 1;
    case 43: /* kernel.all.cpu.nice */
      atom->ul = LOAD_SCALE * (double)
            mach_cpuload.cpu_ticks[CPU_STATE_NICE] / mach_hertz;
        return 1;
    case 44: /* kernel.all.cpu.sys */
      atom->ul = LOAD_SCALE * (double)
            mach_cpuload.cpu_ticks[CPU_STATE_SYSTEM] / mach_hertz;
        return 1;
    case 45: /* kernel.all.cpu.idle */
      atom->ul = LOAD_SCALE * (double)
            mach_cpuload.cpu_ticks[CPU_STATE_IDLE] / mach_hertz;
        return 1;
    }
    return PM_ERR_PMID;
}

static inline int
fetch_vmstat(unsigned int item, unsigned int inst, pmAtomValue *atom)
{
    if (mach_vmstat_error)
      return mach_vmstat_error;
    switch (item) {
    case 2: /* hinv.physmem */
      atom->ul = (__uint32_t)page_count_to_mb(
                  mach_vmstat.free_count + mach_vmstat.wire_count +
                  mach_vmstat.active_count + mach_vmstat.inactive_count);
      return 1;
    case 3: /* mem.physmem */
      atom->ull = page_count_to_kb(
                  mach_vmstat.free_count + mach_vmstat.wire_count +
                  mach_vmstat.active_count + mach_vmstat.inactive_count);
      return 1;
    case 4: /* mem.freemem */
      atom->ull = page_count_to_kb(mach_vmstat.free_count);
      return 1;
    case 5: /* mem.active */
      atom->ull = page_count_to_kb(mach_vmstat.active_count);
      return 1;
    case 6: /* mem.inactive */
      atom->ull = page_count_to_kb(mach_vmstat.inactive_count);
      return 1;
    case 19: /* mem.util.wired */
      atom->ull = page_count_to_kb(mach_vmstat.free_count);
      return 1;
    case 20: /* mem.util.active */
      atom->ull = page_count_to_kb(mach_vmstat.active_count);
      return 1;
    case 21: /* mem.util.inactive */
      atom->ull = page_count_to_kb(mach_vmstat.inactive_count);
      return 1;
    case 22: /* mem.util.free */
      atom->ull = page_count_to_kb(mach_vmstat.free_count);
      return 1;
    }
    return PM_ERR_PMID;
}

static inline int
fetch_uname(unsigned int item, pmAtomValue *atom)
{
    static char mach_uname_all[(_SYS_NAMELEN*5)+8];

    if (mach_uname_error)
      return mach_uname_error;
    switch (item) {
    case 28: /* pmda.uname */
      snprintf(mach_uname_all, sizeof(mach_uname_all), "%s %s %s %s %s",
            mach_uname.sysname, mach_uname.nodename,
            mach_uname.release, mach_uname.version,
            mach_uname.machine);
      atom->cp = mach_uname_all;
      return 1;
    case 29: /* pmda.version */
      atom->cp = pmGetConfig("PCP_VERSION");
      return 1;
    }
    return PM_ERR_PMID;
}

static inline int
fetch_filesys(unsigned int item, unsigned int inst, pmAtomValue *atom)
{
    __uint64_t    ull, used;

    if (mach_fs_error)
      return mach_fs_error;
    if (item == 31) {   /* hinv.nfilesys */
      atom->ul = indomtab[FILESYS_INDOM].it_numinst;
      return 1;
    }
    if (indomtab[FILESYS_INDOM].it_numinst == 0)
      return 0;   /* no values available */
    if (inst < 0 || inst >= indomtab[FILESYS_INDOM].it_numinst)
      return PM_ERR_INST;
    switch (item) {
    case 32: /* filesys.capacity */
      ull = (__uint64_t)mach_fs[inst].f_blocks;
      atom->ull = ull * mach_fs[inst].f_bsize >> 10;
      return 1;
    case 33: /* filesys.used */
      used = (__uint64_t)(mach_fs[inst].f_blocks - mach_fs[inst].f_bfree);
      atom->ull = used * mach_fs[inst].f_bsize >> 10;
      return 1;
    case 34: /* filesys.free */
      ull = (__uint64_t)mach_fs[inst].f_bfree;
      atom->ull = ull * mach_fs[inst].f_bsize >> 10;
      return 1;
    case 35: /* filesys.usedfiles */
      atom->ul = mach_fs[inst].f_files;
      return 1;
    case 36: /* filesys.freefiles */
      atom->ul = mach_fs[inst].f_ffree;
      return 1;
    case 37: /* filesys.mountdir */
      atom->cp = mach_fs[inst].f_mntonname;
      return 1;
    case 38: /* filesys.full */
      used = (__uint64_t)(mach_fs[inst].f_blocks - mach_fs[inst].f_bfree);
      ull = used + (__uint64_t)mach_fs[inst].f_bavail;
      atom->d = (100.0 * (double)used) / (double)ull;
      return 1;
    case 39: /* filesys.blocksize */
      atom->ul = mach_fs[inst].f_bsize;
      return 1;
    case 40: /* filesys.avail */
      ull = (__uint64_t)mach_fs[inst].f_bavail;
      atom->ull = ull * mach_fs[inst].f_bsize >> 10;
      return 1;
    case 41: /* filesys.type */
      atom->cp = mach_fs[inst].f_fstypename;
      return 1;
    }
    return PM_ERR_PMID;
}

static inline int
fetch_disk(unsigned int item, unsigned int inst, pmAtomValue *atom)
{
    if (mach_disk_error)
      return mach_disk_error;
    if (item == 46) {   /* hinv.ndisk */
      atom->ul = indomtab[DISK_INDOM].it_numinst;
      return 1;
    }
    if (indomtab[DISK_INDOM].it_numinst == 0)
      return 0;   /* no values available */
    if (item < 59 && (inst < 0 || inst >= indomtab[DISK_INDOM].it_numinst))
      return PM_ERR_INST;
    switch (item) {
    case 47: /* disk.dev.read */
      atom->ull = mach_disk.disks[inst].read;
      return 1;
    case 48: /* disk.dev.write */
      atom->ull = mach_disk.disks[inst].write;
      return 1;
    case 49: /* disk.dev.total */
      atom->ull = mach_disk.disks[inst].read + mach_disk.disks[inst].write;
      return 1;
    case 50: /* disk.dev.read_bytes */
      atom->ull = mach_disk.disks[inst].read_bytes >> 10;
      return 1;
    case 51: /* disk.dev.write_bytes */
      atom->ull = mach_disk.disks[inst].write_bytes >> 10;
      return 1;
    case 52: /* disk.dev.total_bytes */
      atom->ull = (mach_disk.disks[inst].read_bytes +
                  mach_disk.disks[inst].write_bytes) >> 10;
      return 1;
    case 53: /* disk.dev.blkread */
      atom->ull = mach_disk.disks[inst].read_bytes /
                  mach_disk.disks[inst].blocksize;
      return 1;
    case 54: /* disk.dev.blkwrite */
      atom->ull = mach_disk.disks[inst].write_bytes /
                  mach_disk.disks[inst].blocksize;
      return 1;
    case 55: /* disk.dev.blktotal */
      atom->ull = (mach_disk.disks[inst].read_bytes +
                   mach_disk.disks[inst].write_bytes) /
                        mach_disk.disks[inst].blocksize;
      return 1;
    case 56: /* disk.dev.read_time */
      atom->ull = mach_disk.disks[inst].read_time;
      return 1;
    case 57: /* disk.dev.write_time */
      atom->ull = mach_disk.disks[inst].write_time;
      return 1;
    case 58: /* disk.dev.total_time */
      atom->ull = mach_disk.disks[inst].read_time +
                        mach_disk.disks[inst].write_time;
      return 1;
    case 59: /* disk.all.read */
      atom->ull = mach_disk.read;
      return 1;
    case 60: /* disk.all.write */
      atom->ull = mach_disk.write;
      return 1;
    case 61: /* disk.all.total */
      atom->ull = mach_disk.read + mach_disk.write;
      return 1;
    case 62: /* disk.all.read_bytes */
      atom->ull = mach_disk.read_bytes >> 10;
      return 1;
    case 63: /* disk.all.write_bytes */
      atom->ull = mach_disk.write_bytes >> 10;
      return 1;
    case 64: /* disk.all.total_bytes */
      atom->ull = (mach_disk.read_bytes + mach_disk.write_bytes) >> 10;
      return 1;
    case 65: /* disk.all.blkread */
      atom->ull = mach_disk.blkread;
      return 1;
    case 66: /* disk.all.blkwrite */
      atom->ull = mach_disk.blkwrite;
      return 1;
    case 67: /* disk.all.blktotal */
      atom->ull = mach_disk.blkread + mach_disk.blkwrite;
      return 1;
    case 68: /* disk.all.read_time */
      atom->ull = mach_disk.read_time;
      return 1;
    case 69: /* disk.all.write_time */
      atom->ull = mach_disk.write_time;
      return 1;
    case 70: /* disk.all.total_time */
      atom->ull = mach_disk.read_time + mach_disk.write_time;
      return 1;
    }
    return PM_ERR_PMID;
}

static inline int
fetch_cpu(unsigned int item, unsigned int inst, pmAtomValue *atom)
{
    if (mach_cpu_error)
      return mach_cpu_error;
    if (item == 71) {   /* hinv.ncpu */
      atom->ul = indomtab[CPU_INDOM].it_numinst;
      return 1;
    }
    if (indomtab[CPU_INDOM].it_numinst == 0)    /* uh-huh. */
      return 0;   /* no values available */
    if (inst < 0 || inst >= indomtab[CPU_INDOM].it_numinst)
      return PM_ERR_INST;
    switch (item) {
    case 72: /* kernel.percpu.cpu.user */
      atom->ul = LOAD_SCALE * (double)
                  mach_cpu[inst].cpu_ticks[CPU_STATE_USER] / mach_hertz;
      return 1;
    case 73: /* kernel.percpu.cpu.nice */
      atom->ul = LOAD_SCALE * (double)
                  mach_cpu[inst].cpu_ticks[CPU_STATE_NICE] / mach_hertz;
      return 1;
    case 74: /* kernel.percpu.cpu.sys */
      atom->ul = LOAD_SCALE * (double)
                  mach_cpu[inst].cpu_ticks[CPU_STATE_SYSTEM] / mach_hertz;
      return 1;
    case 75: /* kernel.percpu.cpu.idle */
      atom->ul = LOAD_SCALE * (double)
                  mach_cpu[inst].cpu_ticks[CPU_STATE_IDLE] / mach_hertz;
      return 1;
    }
    return PM_ERR_PMID;
}

static inline int
fetch_network(unsigned int item, unsigned int inst, pmAtomValue *atom)
{
    if (mach_net_error)
      return mach_net_error;
    if (indomtab[NETWORK_INDOM].it_numinst == 0)
      return 0;   /* no values available */
    if (inst < 0 || inst >= indomtab[NETWORK_INDOM].it_numinst)
      return PM_ERR_INST;
    switch (item) {
    case 77: /* network.interface.in.bytes */
      atom->ull = mach_net.interfaces[inst].ibytes;
      return 1;
    case 78: /* network.interface.in.packets */
      atom->ull = mach_net.interfaces[inst].ipackets;
      return 1;
    case 79: /* network.interface.in.errors */
      atom->ull = mach_net.interfaces[inst].ierrors;
      return 1;
    case 80: /* network.interface.in.drops */
      atom->ull = mach_net.interfaces[inst].iqdrops;
      return 1;
    case 81: /* network.interface.in.mcasts */
      atom->ull = mach_net.interfaces[inst].imcasts;
      return 1;
    case 82: /* network.interface.out.bytes */
      atom->ull = mach_net.interfaces[inst].obytes;
      return 1;
    case 83: /* network.interface.out.packets */
      atom->ull = mach_net.interfaces[inst].opackets;
      return 1;
    case 84: /* network.interface.out.errors */
      atom->ull = mach_net.interfaces[inst].oerrors;
      return 1;
    case 85: /* network.interface.out.mcasts */
      atom->ull = mach_net.interfaces[inst].omcasts;
      return 1;
    case 86: /* network.interface.collisions */
      atom->ull = mach_net.interfaces[inst].collisions;
      return 1;
    case 87: /* network.interface.mtu */
      atom->ull = mach_net.interfaces[inst].mtu;
      return 1;
    case 88: /* network.interface.baudrate */
      atom->ull = mach_net.interfaces[inst].baudrate;
      return 1;
    case 89: /* network.interface.total.bytes */
      atom->ull = mach_net.interfaces[inst].ibytes +
                mach_net.interfaces[inst].obytes;
      return 1;
    case 90: /* network.interface.total.packets */
      atom->ull = mach_net.interfaces[inst].ipackets +
                mach_net.interfaces[inst].opackets;
      return 1;
    case 91: /* network.interface.total.errors */
      atom->ull = mach_net.interfaces[inst].ierrors +
                mach_net.interfaces[inst].oerrors;
      return 1;
    case 92: /* network.interface.total.drops */
      atom->ull = mach_net.interfaces[inst].iqdrops;
      return 1;
    case 93: /* network.interface.total.mcasts */
      atom->ull = mach_net.interfaces[inst].imcasts +
                mach_net.interfaces[inst].omcasts;
      return 1;
    }
    return PM_ERR_PMID;
}

static inline int
fetch_nfs(unsigned int item, unsigned int inst, pmAtomValue *atom)
{
    if (mach_net_error)
      return mach_net_error;
    switch (item) {
    case 94: /* nfs3.client.calls */
      for (atom->l = 0, inst = 0; inst < NFS3_RPC_COUNT; inst++)
          atom->l += mach_nfs.rpccnt[inst];
      return 1;
    case 95: /* nfs3.client.reqs */
      if (inst < 0 || inst >= NFS3_RPC_COUNT)
          return PM_ERR_INST;
      atom->l = mach_nfs.rpccnt[inst];
      return 1;
    case 96: /* nfs3.server.calls */
      for (atom->l = 0, inst = 0; inst < NFS3_RPC_COUNT; inst++)
          atom->l += mach_nfs.srvrpccnt[inst];
      return 1;
    case 97: /* nfs3.server.reqs */
      if (inst < 0 || inst >= NFS3_RPC_COUNT)
          return PM_ERR_INST;
      atom->l = mach_nfs.srvrpccnt[inst];
      return 1;
    }
    return PM_ERR_PMID;
}


static int
darwin_fetchCallBack(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom)
{
    __pmID_int    *idp = (__pmID_int *)&(mdesc->m_desc.pmid);

    if (mdesc->m_user) {
      /*   
       * The metric value is extracted directly via the address specified
       * in metrictab.  Note: not all metrics support this - those that
       * don't have NULL for the m_user field in their respective
       * metrictab slot.
       */
      switch (mdesc->m_desc.type) {
        case PM_TYPE_32:      atom->l = *(__int32_t *)mdesc->m_user; break;
      case PM_TYPE_U32: atom->ul = *(__uint32_t *)mdesc->m_user; break;
      case PM_TYPE_64:  atom->ll = *(__int64_t *)mdesc->m_user; break;
      case PM_TYPE_U64: atom->ull = *(__uint64_t *)mdesc->m_user; break;
      case PM_TYPE_FLOAT:     atom->f = *(float *)mdesc->m_user; break;
      case PM_TYPE_DOUBLE:    atom->d = *(double *)mdesc->m_user; break;
      case PM_TYPE_STRING:    atom->cp = (char *)mdesc->m_user; break;
      case PM_TYPE_AGGREGATE_STATIC:
      case PM_TYPE_AGGREGATE: atom->vp = (void *)mdesc->m_user; break;
      case PM_TYPE_NOSUPPORT: return 0;
      case PM_TYPE_UNKNOWN:
      default:          fprintf(stderr,
                  "Error in fetchCallBack: unknown metric type %d\n",
                              mdesc->m_desc.type);
                        return 0;
      }
      return 1;
    }

    switch (idp->cluster) {
    case CLUSTER_LOADAVG:     return fetch_loadavg(idp->item, inst, atom);
    case CLUSTER_CPULOAD:     return fetch_cpuload(idp->item, atom);
    case CLUSTER_VMSTAT:      return fetch_vmstat(idp->item, inst, atom);
    case CLUSTER_KERNEL_UNAME:      return fetch_uname(idp->item, atom);
    case CLUSTER_FILESYS:     return fetch_filesys(idp->item, inst, atom);
    case CLUSTER_DISK:        return fetch_disk(idp->item, inst, atom);
    case CLUSTER_CPU:         return fetch_cpu(idp->item, inst, atom);
    case CLUSTER_NETWORK:     return fetch_network(idp->item, inst, atom);
    case CLUSTER_NFS:         return fetch_nfs(idp->item, inst, atom);
    }
    return 0;
}

static int
darwin_instance(pmInDom indom, int inst, char *name, __pmInResult **result, pmdaExt *pmda)
{
    __pmInDom_int *indomp = (__pmInDom_int *)&indom;
    int                 need_refresh[NUM_CLUSTERS] = { 0 };

    switch (indomp->serial) {
    case FILESYS_INDOM: need_refresh[CLUSTER_FILESYS]++; break;
    case DISK_INDOM:    need_refresh[CLUSTER_DISK]++; break;
    case CPU_INDOM:     need_refresh[CLUSTER_CPU]++; break;
    case NETWORK_INDOM: need_refresh[CLUSTER_NETWORK]++; break;
    }
    darwin_refresh(need_refresh);
    return pmdaInstance(indom, inst, name, result, pmda);
}

static int
darwin_fetch(int numpmid, pmID pmidlist[], pmResult **resp, pmdaExt *pmda)
{
    int     i, need_refresh[NUM_CLUSTERS] = { 0 };

    for (i = 0; i < numpmid; i++) {
      __pmID_int *idp = (__pmID_int *)&(pmidlist[i]);
      if (idp->cluster >= 0 && idp->cluster < NUM_CLUSTERS)
          need_refresh[idp->cluster]++;
    }
    darwin_refresh(need_refresh);
    return pmdaFetch(numpmid, pmidlist, resp, pmda);
}

void 
darwin_init(pmdaInterface *dp)
{
    if (dp->status != 0)
      return;

    if (_isDSO) {
      char helppath[MAXPATHLEN];
      sprintf(helppath, "%s/pmdas/darwin/help", pmGetConfig("PCP_VAR_DIR"));
      pmdaDSO(dp, PMDA_INTERFACE_3, "darwin DSO", helppath);
    }

    dp->version.two.instance = darwin_instance;
    dp->version.two.fetch = darwin_fetch;
    pmdaSetFetchCallBack(dp, darwin_fetchCallBack);

    pmdaInit(dp, indomtab, sizeof(indomtab)/sizeof(indomtab[0]),
            metrictab, sizeof(metrictab)/sizeof(metrictab[0]));
    /* Make sure we have a direct metric table lookup */
    if (!dp->version.two.ext->e_direct)
      abort();

    mach_host = mach_host_self();
    host_page_size(mach_host, &mach_page_size);
    mach_page_shift = ffs(mach_page_size) - 1;
    if (refresh_hertz(&mach_hertz) != 0)
      mach_hertz = 100;
    init_network();
}

static void
usage(void)
{
    fprintf(stderr, "Usage: %s [options]\n\n", pmProgname);
    fputs("Options:\n"
"  -d domain    use domain (numeric) for metrics domain of PMDA\n"
"  -l logfile   write log into logfile rather than using default log name\n"
"\nExactly one of the following options may appear:\n"
"  -i port      expect PMCD to connect on given inet port (number or name)\n"
"  -p           expect PMCD to supply stdin/stdout (pipe)\n"
"  -u socket    expect PMCD to connect on given unix domain socket\n",
        stderr);        
    exit(1);
}

int
main(int argc, char **argv)
{
    int                 errflag = 0;
    char          *p;
    char          helppath[MAXPATHLEN];

    for (p = pmProgname = argv[0]; *p; p++)
      if (*p == '/') pmProgname = p+1;

    _isDSO = 0;
    sprintf(helppath, "%s/pmdas/darwin/help", pmGetConfig("PCP_VAR_DIR"));
    pmdaDaemon(&dispatch, PMDA_INTERFACE_3, pmProgname, DARWIN, "darwin.log",
            helppath);

    if (pmdaGetOpt(argc, argv, "D:d:i:l:pu:?", &dispatch, &errflag) != EOF)
      errflag++;

    if (errflag)
      usage();

    pmdaOpenLog(&dispatch);
    darwin_init(&dispatch);
    pmdaConnect(&dispatch);
    pmdaMain(&dispatch);
    exit(0);
}

Generated by  Doxygen 1.6.0   Back to index