/*
 *========================================================================
 * $Id: values.h 31 2004-02-12 18:04:42Z rgb $
 *
 * See copyright in copyright.h and the accompanying file COPYING
 *========================================================================
 */


/* We use these for certain buffer sizes */
#define K 1024
#define K4 4096
#define K64 65536

/*
 * structs and enums to hold value(s) vector(s).
 */

 typedef struct {
   /* 
    * These are the raw values, and will also serve as the
    * last values in the evaluation of the rates below.
    */
   long int user;
   long int nice;
   long int sys;
   long int idle;
   long int tot;
   /*
    * These are the rates that we actually display.
    */
   double user_rate;
   double nice_rate;
   double sys_rate;
   double idle_rate;
   double tot_rate;
 } Cpu;

 typedef struct {
   /* 
    * Interface identifiers
    */
   char devtype[K];
   char devid[K];
   char name[K];
   char host[K];
   char ip[K];

   /* 
    * Receive numbers.  Note all these are UNSIGNED long ints...
    */
   unsigned long int rx_bytes;
   unsigned long int rx_packets;
   unsigned long int rx_errs;
   unsigned long int rx_drop;
   unsigned long int rx_fifo;
   unsigned long int rx_frame;
   unsigned long int rx_compressed;
   unsigned long int rx_multicast;

   /* 
    * Transmit numbers
    */
   unsigned long int tx_bytes;
   unsigned long int tx_packets;
   unsigned long int tx_errs;
   unsigned long int tx_drop;
   unsigned long int tx_fifo;
   unsigned long int tx_collisions;
   unsigned long int tx_compressed;

   /*
    * These are the rates that we actually display.  We can add the rest
    * if we ever want to build a display to show them.
    */
   double rx_bytes_rate;
   double rx_packets_rate;
   double rx_errs_rate;
   double tx_bytes_rate;
   double tx_packets_rate;
   double tx_errs_rate;

 } Interface;

 /*
  * May not ever use this.  Eliminate if/when cruft.
  */
 typedef enum { 
   COUNT,	/* just count them, ignore the type */
   STRING,
   CHAR,
   INT,
   LONG,
   UNSIGNED_LONG,
   FLOAT,
   DOUBLE,
   N_TYPES
 } Types;

/*
 * I don't think there is a "good" way to do this.  Every way I can
 * think of has elements that won't scale well, in part because like
 * it or not, much of what we wish to present is made by a "recipe"
 * from ingredients in /proc or elsewhere.  Sure, some values are
 * presentable raw, others are static and don't need to be re-extracted
 * after the init, but we pretty much need individual, per-host indexed
 * storage for field we plan to use in a recipe (or at least for the
 * result of applying the recipe itself to fields directly extracted from
 * the xml document(s)).
 *
 * SO, we're going to at least start by creating a massive "values" struct
 * some of the elements of which (e.g. cpu, eth) are themselves structs
 * or struct vectors.  We can then allocate the whole damned thing at
 * once in startup().
 *
 * Note that there is considerable redundancy in the values below.  For
 * example, hostname is defined in the parent host struct (used to contact
 * the host), again in <identity>, and yet again in a <net><interface>.
 * This is really unavoidable.  Memory is cheap, and even the CPU required
 * to fill it isn't that costly.  We'll start this way, at any rate.
 *
 * Perhaps the experience of doing this will help us learn a more portable
 * and scalable way of doing this for a future revision.
 *
 * In the meantime, we may as well start at the top xmlsysd and work down.
 * We'll triply echo the <xmlsysd> tag structure -- Value, enum and path,
 * plus we'll add attributes and auxiliary variables to Value as required.
 *
 * All strings MUST be of K length so we have an idea of how long to make
 * the returns... 
 */

 typedef struct {

 /* tags under <system> */

   /* <identity> */
   unsigned long int identity_tv_sec;
   unsigned long int identity_tv_usec;
   char hostname[K];
   char hostip[K];

   /* <time> */
   unsigned long int time_tv_sec;
   unsigned long int time_tv_usec;
   char time[K];

   /* cpuinfo */
   unsigned long int cpuinfo_tv_sec;
   unsigned long int cpuinfo_tv_usec;
   char cpuinfo_model_name[K];
   double cpuinfo_clock;
   long int cpuinfo_cachesize;

   /* <users> */
   unsigned long int users_tv_sec;
   unsigned long int users_tv_usec;
   long int users;

 /* tags under <proc> */

   /* <stat> */
   unsigned long int stat_tv_sec;
   unsigned long int stat_tv_usec;
   /* 
    * We count the number of cpus and save it for this host, then
    * allocate just the right about of space for the cpu struct vector.
    * Note that there are always at least TWO entries, one for cpu_tot
    * and one for cpu0.  cpu_tot goes at cpu[-1] in the vector below.
    * num_cpus, however is the true number of cpus in /proc/stat.
    */
   long int num_cpus;
   Cpu *cpu;
   /* page: two raw values, two float rates */
   long int page_in;
   long int page_out;
   double page_in_rate;
   double page_out_rate;
   /* swap: two raw values, two float rates */
   long int swap_in;
   long int swap_out;
   double swap_in_rate;
   double swap_out_rate;
   /* intr: we only present total, one raw, one float rate */
   long int intr;
   double intr_rate;
   /* ctxt: we only present total, one raw, one float rate */
   long int ctxt;
   double ctxt_rate;
   /* processes: one raw, one float rate */
   long int processes;
   double processes_rate;

   /* <loadavg> */
   unsigned long int loadavg_tv_sec;
   unsigned long int loadavg_tv_usec;
   double load1;
   double load5;
   double load15;

   /* <meminfo> */
   unsigned long int meminfo_tv_sec;
   unsigned long int meminfo_tv_usec;
   unsigned long int mem_total;
   unsigned long int mem_used;
   unsigned long int mem_free;
   unsigned long int mem_shared;
   unsigned long int mem_buffers;
   unsigned long int mem_cached;
   unsigned long int swap_total;
   unsigned long int swap_used;
   unsigned long int swap_free;

   /* <net> */
   unsigned long int netdev_tv_sec;
   unsigned long int netdev_tv_usec;
   /*
    * interfaces are the contents of <net><dev>
    */
   long int num_interfaces;   
   Interface *interface;
   /* tcp sockets in use */
   long int tcp_inuse;

   /* <sysvipc> */
   unsigned long int sysvipc_tv_sec;
   unsigned long int sysvipc_tv_usec;

   /* uptime */
   unsigned long int uptime_tv_sec;
   unsigned long int uptime_tv_usec;
   double uptime_up;
   double uptime_idle;
   double duty_cycle;
   char uptime[K];

   /* version */
   unsigned long int version_tv_sec;
   unsigned long int version_tv_usec;
   char version[K];

   /* <pids> */
   long int pids_tv_sec;
   long int pids_tv_usec;

 } Value;

typedef enum {
   IDENTITY,
   HOSTNAME,
   HOSTIP,
   TIME,
   USERS,
   STAT,
   CPU,
   CPU_ID,
   CPU_USER,
   CPU_NICE,
   CPU_SYS,
   CPU_TOT,
   PAGE_IN,
   PAGE_OUT,
   SWAP_IN,
   SWAP_OUT,
   INTR,
   CTXT,
   PROCESSES,
   LOADAVG,
   LOAD1,
   LOAD5,
   LOAD15,
   MEMINFO,
   MEM_TOTAL,
   MEM_USED,
   MEM_FREE,
   MEM_SHARED,
   MEM_BUFFERS,
   MEM_CACHED,
   SWAP_TOTAL,
   SWAP_USED,
   SWAP_FREE,
   NETDEV,
   INTERFACE,
   TCP_INUSE,
   CPUINFO,
   CPUINFO_MODEL_NAME,
   CPUINFO_CLOCK,
   CPUINFO_CACHESIZE,
   SYSVIPC,
   SYSVIPC_MSGBUFS,
   SYSVIPC_MSGTOT,
   SYSVIPC_SEMBUFS,
   SYSVIPC_SEMTOT,
   SYSVIPC_SHMBUFS,
   SYSVIPC_SHMTOT,
   UPTIME,
   UPTIME_UP,
   UPTIME_IDLE,
   VERSION,
   PIDS,
 } Values;

 static char *value_xpath[] = {
  "/xmlsysd/system/identity",
  "/xmlsysd/system/identity/hostname",
  "/xmlsysd/system/identity/hostip",
  "/xmlsysd/system/time",
  "/xmlsysd/system/users",
  "/xmlsysd/proc/stat",
  "/xmlsysd/proc/stat/cpu",
  "/xmlsysd/proc/stat/cpu/cpuid",
  "/xmlsysd/proc/stat/cpu/user",
  "/xmlsysd/proc/stat/cpu/nice",
  "/xmlsysd/proc/stat/cpu/sys",
  "/xmlsysd/proc/stat/cpu/tot",
  "/xmlsysd/proc/stat/page/in",
  "/xmlsysd/proc/stat/page/out",
  "/xmlsysd/proc/stat/swap/in",
  "/xmlsysd/proc/stat/swap/out",
  "/xmlsysd/proc/stat/intr",
  "/xmlsysd/proc/stat/ctxt",
  "/xmlsysd/proc/stat/processes",
  "/xmlsysd/proc/loadavg",
  "/xmlsysd/proc/loadavg/load1",
  "/xmlsysd/proc/loadavg/load5",
  "/xmlsysd/proc/loadavg/load15",
  "/xmlsysd/proc/meminfo",
  "/xmlsysd/proc/meminfo/memory/total",
  "/xmlsysd/proc/meminfo/memory/used",
  "/xmlsysd/proc/meminfo/memory/free",
  "/xmlsysd/proc/meminfo/memory/shared",
  "/xmlsysd/proc/meminfo/memory/buffers",
  "/xmlsysd/proc/meminfo/memory/cached",
  "/xmlsysd/proc/meminfo/swap/total",
  "/xmlsysd/proc/meminfo/swap/used",
  "/xmlsysd/proc/meminfo/swap/free",
  "/xmlsysd/proc/net/dev",
  "/xmlsysd/proc/net/dev/interface",
  "/xmlsysd/proc/net/sockstat/tcp/inuse",
  "/xmlsysd/proc/cpuinfo",
  "/xmlsysd/proc/cpuinfo/processor[@id='0']/model_name",
  "/xmlsysd/proc/cpuinfo/processor[@id='0']/clock",
  "/xmlsysd/proc/cpuinfo/processor[@id='0']/cachesize",
  "/xmlsysd/proc/sysvipc",
  "/xmlsysd/proc/sysvipc/msgbufs",
  "/xmlsysd/proc/sysvipc/msgtot",
  "/xmlsysd/proc/sysvipc/sembufs",
  "/xmlsysd/proc/sysvipc/semtot",
  "/xmlsysd/proc/sysvipc/shmbufs",
  "/xmlsysd/proc/sysvipc/shmtot",
  "/xmlsysd/proc/uptime",
  "/xmlsysd/proc/uptime/up",
  "/xmlsysd/proc/uptime/idle",
  "/xmlsysd/proc/version",
  "/xmlsysd/pids",
  "n_values"
 };


