vmstat_solaris2.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:24k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  *  vmstat_solaris2.c
  3.  *  UCD SNMP module for systemStats section of UCD-SNMP-MIB for SunOS/Solaris
  4.  *  Jochen Kmietsch <kmietsch@jochen.de>
  5.  *  with fixes and additions from the UCD-SNMP community
  6.  *  Uses some ideas from xosview and top
  7.  *  Some comments paraphrased from the SUN man pages 
  8.  *  Version 0.1 initial release (Dec 1999)
  9.  *  Version 0.2 added support for multiprocessor machines (Jan 2000)
  10.  *  Version 0.3 some reliability enhancements and compile time fixes (Feb 2000)
  11.  *  Version 0.4 portability issue and raw cpu value support (Jun 2000)
  12.  *  Version 0.5 64-bit Solaris support and new data gathering routine (Aug 2000)
  13.  *  Version 0.6 Memory savings, overroll precautions and lint checks (Aug 2000)
  14.  *  Version 0.7 More raw counters and some cosmetic changes (Jan 2001)
  15.  *
  16.  */
  17. /*
  18.  * To make lint skip the debug code and stop complaining 
  19.  */
  20. #ifdef __lint
  21. #define SNMP_NO_DEBUGGING 1
  22. #endif
  23. /*
  24.  * Includes start here 
  25.  */
  26. /*
  27.  * Standard includes 
  28.  */
  29. #include <stdlib.h>
  30. #include <unistd.h>
  31. #include <sys/types.h>
  32. #include <sys/time.h>
  33. #include <string.h>
  34. /*
  35.  * kstat and sysinfo structs 
  36.  */
  37. #include <kstat.h>
  38. #include <sys/sysinfo.h>
  39. #include <net-snmp/net-snmp-config.h>
  40. #include <net-snmp/net-snmp-includes.h>
  41. #include <net-snmp/agent/net-snmp-agent-includes.h>
  42. #include "mibdefs.h"
  43. #include "util_funcs.h"
  44. /*
  45.  * Header file for this module 
  46.  */
  47. #include "vmstat.h"
  48. #include "vmstat_solaris2.h"
  49. /*
  50.  * Includes end here 
  51.  */
  52. /*
  53.  * Global structures start here 
  54.  */
  55. /*
  56.  * A structure to save data gathered from the kernel kstat interface to.  
  57.  * We used to have the sys/sysinfo.h cpu_stat_t here but we did not need 
  58.  * all of it, some in a different size and some additional ones so we build 
  59.  * our own 
  60.  */
  61. struct cpu_stat_snapshot {
  62.     hrtime_t        css_time;
  63.     unsigned int    css_cpus;
  64.     unsigned long long css_swapin;
  65.     unsigned long long css_swapout;
  66.     unsigned long long css_blocks_read;
  67.     unsigned long long css_blocks_write;
  68.     unsigned long long css_interrupts;
  69.     unsigned long long css_context_sw;
  70.     unsigned long long css_cpu[CPU_STATES];
  71. };
  72. /*
  73.  * Global structures end here 
  74.  */
  75. /*
  76.  * Global variables start here 
  77.  */
  78. /*
  79.  * From kstat.h: 
  80.  * Provides access to the kernel statistics library by 
  81.  * initializing a kstat control structure and returning a pointer 
  82.  * to this structure.  This pointer must be used as the kc argument in  
  83.  * following function calls from libkstat (here kc is called kstat_fd). 
  84.  * Pointer to structure to be opened with kstat_open in main procedure. 
  85.  * We share this one with memory_solaris2 and kernel_sunos5, where it's 
  86.  * defined. 
  87.  */
  88. extern kstat_ctl_t *kstat_fd;
  89. /*
  90.  * Variables for the calculated values, filled in update_stats    
  91.  * Need to be global since we need them in more than one function 
  92.  */
  93. static ulong    swapin;
  94. static ulong    swapout;
  95. static ulong    blocks_read;
  96. static ulong    blocks_write;
  97. static ulong    interrupts;
  98. static ulong    context_sw;
  99. /*
  100.  * Since MIB wants CPU_SYSTEM, which is CPU_KERNEL + CPU_WAIT 
  101.  */
  102. static long     cpu_perc[CPU_STATES + 1];
  103. /*
  104.  * How many snapshots we have already taken, needed for the first 
  105.  * POLL_INTERVAL * POLL_VALUES seconds of agent running 
  106.  */
  107. static unsigned int number_of_snapshots;
  108. /*
  109.  * The place to store the snapshots of system data in 
  110.  */
  111. static struct cpu_stat_snapshot snapshot[POLL_VALUES + 1];
  112. /*
  113.  * And one for the raw counters, which we fill when the raw values are 
  114.  * requested, as opposed to the absolute values, which are taken every 
  115.  * POLL_INTERVAL seconds and calculated over POLL_INTERVAL * POLL_VALUES time 
  116.  */
  117. static struct cpu_stat_snapshot raw_values;
  118. /*
  119.  * Global variables end here 
  120.  */
  121. /*
  122.  * Functions start here 
  123.  */
  124. /*
  125.  * Function prototype 
  126.  */
  127. static void     update_stats(unsigned int registrationNumber,
  128.                              void *clientarg);
  129. static int      take_snapshot(struct cpu_stat_snapshot *css);
  130. /*
  131.  * init_vmstat_solaris2 starts here 
  132.  * Init function for this module, from prototype 
  133.  * Defines variables handled by this module, defines root OID for 
  134.  * this module and registers it with the agent 
  135.  */
  136. FindVarMethod var_extensible_vmstat;
  137. void
  138. init_vmstat_solaris2(void)
  139. {
  140.     /*
  141.      * Which variables do we service ? 
  142.      */
  143.     struct variable2 extensible_vmstat_variables[] = {
  144.         {MIBINDEX, ASN_INTEGER, RONLY, var_extensible_vmstat, 1,
  145.          {MIBINDEX}},
  146.         {ERRORNAME, ASN_OCTET_STR, RONLY, var_extensible_vmstat, 1,
  147.          {ERRORNAME}},
  148.         {SWAPIN, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {SWAPIN}},
  149.         {SWAPOUT, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {SWAPOUT}},
  150.         {IOSENT, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {IOSENT}},
  151.         {IORECEIVE, ASN_INTEGER, RONLY, var_extensible_vmstat, 1,
  152.          {IORECEIVE}},
  153.         {SYSINTERRUPTS, ASN_INTEGER, RONLY, var_extensible_vmstat, 1,
  154.          {SYSINTERRUPTS}},
  155.         {SYSCONTEXT, ASN_INTEGER, RONLY, var_extensible_vmstat, 1,
  156.          {SYSCONTEXT}},
  157.         {CPUUSER, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {CPUUSER}},
  158.         {CPUSYSTEM, ASN_INTEGER, RONLY, var_extensible_vmstat, 1,
  159.          {CPUSYSTEM}},
  160.         {CPUIDLE, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {CPUIDLE}},
  161.         {CPURAWUSER, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
  162.          {CPURAWUSER}},
  163.         {CPURAWSYSTEM, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
  164.          {CPURAWSYSTEM}},
  165.         {CPURAWIDLE, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
  166.          {CPURAWIDLE}},
  167.         {CPURAWWAIT, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
  168.          {CPURAWWAIT}},
  169.         {CPURAWKERNEL, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
  170.          {CPURAWKERNEL}},
  171.         {IORAWSENT, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
  172.          {IORAWSENT}},
  173.         {IORAWRECEIVE, ASN_COUNTER, RONLY, var_extensible_vmstat, 1,
  174.          {IORAWRECEIVE}},
  175.         /*
  176.          * Future use: 
  177.          * {ERRORFLAG, ASN_INTEGER, RONLY, var_extensible_vmstat, 1, {ERRORFLAG }},
  178.          * {ERRORMSG, ASN_OCTET_STR, RONLY, var_extensible_vmstat, 1, {ERRORMSG }}
  179.          */
  180.     };
  181.     /*
  182.      * Define the OID pointer to the top of the mib tree that we're 
  183.      * registering underneath 
  184.      */
  185.     oid             vmstat_variables_oid[] = { UCDAVIS_MIB, 11 };
  186.     /*
  187.      * register ourselves with the agent to handle our mib tree 
  188.      * LINTED Trust me, I know what I'm doing 
  189.      */
  190.     REGISTER_MIB("ucd-snmp/vmstat", extensible_vmstat_variables, variable2,
  191.                  vmstat_variables_oid);
  192.     /*
  193.      * First check whether shared kstat contol is NULL, if so, try to open our 
  194.      * own. 
  195.      */
  196.     if (kstat_fd == NULL) {
  197.         kstat_fd = kstat_open();
  198.     }
  199.     /*
  200.      * Then check whether either shared kstat was found or we succeeded in 
  201.      * opening our own. 
  202.      */
  203.     if (kstat_fd == NULL) {
  204.         snmp_log(LOG_ERR,
  205.                  "vmstat_solaris2 (init): kstat_open() failed and no shared kstat control found.n");
  206.     }
  207.     /*
  208.      * Start with some useful data 
  209.      */
  210.     update_stats(0, NULL);
  211.     /*
  212.      * update_stats is run every POLL_INTERVAL seconds using this routine 
  213.      * (see 'man snmp_alarm') 
  214.      * This is only executed once to get some useful data in the beginning 
  215.      */
  216.     if (snmp_alarm_register(5, NULL, update_stats, NULL) == 0) {
  217.         snmp_log(LOG_WARNING,
  218.                  "vmstat_solaris2 (init): snmp_alarm_register failed.n");
  219.     }
  220.     /*
  221.      * This is the one that runs update_stats every POLL_INTERVAL seconds 
  222.      */
  223.     if (snmp_alarm_register(POLL_INTERVAL, SA_REPEAT, update_stats, NULL)
  224.         == 0) {
  225.         snmp_log(LOG_ERR,
  226.                  "vmstat_solaris2 (init): snmp_alarm_register failed, cannot service requests.n");
  227.     }
  228. }                               /* init_vmstat_solaris2 ends here */
  229. /*
  230.  * Data collection function take_snapshot starts here 
  231.  * Get data from kernel and save into the snapshot strutcs 
  232.  * Argument is the snapshot struct to save to. Global anyway, but looks nicer 
  233.  */
  234. static int
  235. take_snapshot(struct cpu_stat_snapshot *css)
  236. {
  237.     /*
  238.      * Variables start here 
  239.      */
  240.     /*
  241.      * From sys/kstat.h (included from kstat.h): 
  242.      * Pointer to current kstat 
  243.      */
  244.     kstat_t        *ksp;
  245.     /*
  246.      * Counters 
  247.      */
  248.     unsigned int    cpu_num = 0;
  249.     /*
  250.      * High resolution time counter 
  251.      */
  252.     hrtime_t        current_time;
  253.     /*
  254.      * see sys/sysinfo.h, holds CPU data 
  255.      */
  256.     cpu_stat_t      cs;
  257.     /*
  258.      * The usual stuff to count on, err, by 
  259.      */
  260.     int             i;
  261.     /*
  262.      * Variables end here 
  263.      */
  264.     /*
  265.      * Function starts here 
  266.      */
  267.     /*
  268.      * Get time 
  269.      */
  270.     current_time = gethrtime();
  271.     /*
  272.      * If we have just gotten the data, return the values from last run (skip if-clause) 
  273.      * This happens on a snmpwalk request.  No need to read the kstat again 
  274.      * if we just did it less than 2 seconds ago 
  275.      * Jumps into if-clause either when snapshot is empty or when too old 
  276.      */
  277.     if ((css->css_time == 0)
  278.         || (current_time > css->css_time + 2000000000)) {
  279.         /*
  280.          * Make sure we clean up before we put new data into snapshot 
  281.          */
  282.         memset(css, 0, sizeof *css);
  283.         /*
  284.          * Update timer 
  285.          */
  286.         css->css_time = current_time;
  287.         /*
  288.          * Look thru all the cpu slots on the machine whether they holds a CPU 
  289.          * and if so, get the data from that CPU 
  290.          * We walk through the whole kstat chain and sum up all the found cpu_stat kstats, 
  291.          * there's one for every CPU in a machine 
  292.          */
  293.         for (ksp = kstat_fd->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
  294.             /*
  295.              * If we encounter an invalid kstat, skip it and continue with next one 
  296.              */
  297.             if (ksp->ks_flags & KSTAT_FLAG_INVALID) {
  298.                 continue;
  299.             }
  300.             if (strcmp(ksp->ks_module, "cpu_stat") == 0) {
  301.                 /*
  302.                  * Yeah, we found a CPU. 
  303.                  */
  304.                 cpu_num++;
  305.                 /*
  306.                  * Read data from kstat into cs structure 
  307.                  * kstat_fd is the control structure, ksp the kstat we are reading 
  308.                  * and cs the buffer we are writing to. 
  309.                  */
  310.                 if ((ksp->ks_type != KSTAT_TYPE_RAW) ||
  311.                     (ksp->ks_data_size != sizeof cs) ||
  312.                     (kstat_read(kstat_fd, ksp, &cs) == -1)) {
  313.                     snmp_log(LOG_ERR,
  314.                              "vmstat_solaris2 (take_snapshot): could not read cs structure.n");
  315.                     return (-1);
  316.                 }
  317.                 /*
  318.                  * Get the data from the cs structure and sum it up in our own structure 
  319.                  */
  320.                 css->css_swapin +=
  321.                     (unsigned long long) cs.cpu_vminfo.swapin;
  322.                 css->css_swapout +=
  323.                     (unsigned long long) cs.cpu_vminfo.swapout;
  324.                 css->css_blocks_read +=
  325.                     (unsigned long long) cs.cpu_sysinfo.bread;
  326.                 css->css_blocks_write +=
  327.                     (unsigned long long) cs.cpu_sysinfo.bwrite;
  328.                 css->css_interrupts +=
  329.                     (unsigned long long) cs.cpu_sysinfo.intr;
  330.                 css->css_context_sw +=
  331.                     (unsigned long long) cs.cpu_sysinfo.pswitch;
  332.                 /*
  333.                  * We need a for-loop for the CPU values 
  334.                  */
  335. cs.cpu_sysinfo.cpu[CPU_WAIT] = cs.cpu_sysinfo.wait[W_IO] +
  336.                                cs.cpu_sysinfo.wait[W_PIO];
  337.                 for (i = 0; i < CPU_STATES; i++) {
  338.                     css->css_cpu[i] +=
  339.                         (unsigned long long) cs.cpu_sysinfo.cpu[i];
  340.                 }               /* end for */
  341.             }                   /* end if */
  342.         }                       /* end for */
  343.         /*
  344.          * Increment number of CPUs we gathered data from, for future use 
  345.          */
  346.         css->css_cpus = cpu_num;
  347.     }
  348.     /*
  349.      * All engines running at warp speed, no problems (if there are any engines, that is) 
  350.      */
  351.     return (cpu_num > 0 ? 0 : -1);
  352. }                               /* take_snapshot ends here */
  353. /*
  354.  * This gets called every POLL_INTERVAL seconds to update the snapshots.  It takes a new snapshot and 
  355.  * drops the oldest one.  This way we move the time window so we always take the values over 
  356.  * POLL_INTERVAL * POLL_VALUES seconds and update the data used every POLL_INTERVAL seconds 
  357.  * The alarm timer is in the init function of this module (snmp_alarm_register) 
  358.  * ARGSUSED0 
  359.  */
  360. static void
  361. update_stats(unsigned int registrationNumber, void *clientarg)
  362. {
  363.     /*
  364.      * The time between the samples we compare 
  365.      */
  366.     hrtime_t        time_diff;
  367.     /*
  368.      * Easier to use these than the snapshots, short hand pointers 
  369.      */
  370.     struct cpu_stat_snapshot *css_old, *css_new;
  371.     /*
  372.      * The usual stuff to count on, err, by 
  373.      */
  374.     int             i;
  375.     /*
  376.      * Kstat chain id, to check whether kstat chain changed 
  377.      */
  378.     kid_t           kid;
  379.     /*
  380.      * The sum of the CPU ticks that have passed on the different CPU states, so we can calculate 
  381.      * the percentages of each state 
  382.      */
  383.     unsigned long long cpu_sum = 0;
  384.     DEBUGMSGTL(("ucd-snmp/vmstat_solaris2.c:update_stats",
  385.                 "updating statsn"));
  386.     /*
  387.      * Just in case someone added (or removed) some CPUs during operation (or other kstat chain changes) 
  388.      */
  389.     kid = kstat_chain_update(kstat_fd);
  390.     if (kid != 0) {
  391.         if (kid == -1) {
  392.             snmp_log(LOG_WARNING,
  393.                      "vmstat_solaris2 (update_stats): Could not update kstat chain.n");
  394.         } else {
  395.             /*
  396.              * On some machines this floods the logfile, thus commented out 
  397.              * snmp_log(LOG_INFO, "vmstat_solaris2 (update_stats): Kstat chain changed."); 
  398.              */
  399.         }
  400.     }
  401.     /*
  402.      * Take the current snapshot 
  403.      */
  404.     if (take_snapshot(&snapshot[0]) == -1) {
  405.         snmp_log(LOG_WARNING,
  406.                  "vmstat_solaris2 (update_stats): Something went wrong with take_snapshot.n");
  407.         return;
  408.     }
  409.     /*
  410.      * Do we have some data we can use ?  An issue right after the start of the agent 
  411.      */
  412.     if (number_of_snapshots > 0) {
  413.         /*
  414.          * Huh, the number of CPUs changed during run time.  That is indeed s.th. worth noting, we 
  415.          * output a humorous (more or less) syslog message and need to retake the snapshots 
  416.          */
  417.         if (snapshot[0].css_cpus != snapshot[1].css_cpus) {
  418.             if (snapshot[0].css_cpus > snapshot[1].css_cpus) {
  419.                 snmp_log(LOG_NOTICE,
  420.                          "vmstat_solaris2 (update_stats): Cool ! Number of CPUs increased, must be hot-pluggable.n");
  421.             } else {
  422.                 snmp_log(LOG_NOTICE,
  423.                          "vmstat_solaris2 (update_stats): Lost at least one CPU, RIP.n");
  424.             }
  425.             /*
  426.              * Make all snapshots but the current one invalid 
  427.              */
  428.             number_of_snapshots = 1;
  429.             /*
  430.              * Move the current one in the "first" [1] slot 
  431.              */
  432.             memmove(&snapshot[1], &snapshot[0], sizeof snapshot[0]);
  433.             /*
  434.              * Erase the current one 
  435.              */
  436.             memset(&snapshot[0], 0, sizeof snapshot[0]);
  437.             /*
  438.              * Try to get a new snapshot in five seconds so we can return s.th. useful 
  439.              */
  440.             if (snmp_alarm_register(5, NULL, update_stats, NULL) == 0) {
  441.                 snmp_log(LOG_WARNING,
  442.                          "vmstat_solaris2 (update_stats): snmp_alarm_register failed.n");
  443.             }
  444.             return;
  445.         }
  446.         /*
  447.          * Short hand pointers 
  448.          */
  449.         css_new = &snapshot[0];
  450.         css_old = &snapshot[number_of_snapshots];
  451.         /*
  452.          * How much time has passed between the snapshots we get the values from ? 
  453.          * Time is in nanoseconds so a few zeros here to juggle with 
  454.          * But the hrtime is not subject to change (s.b. setting the clock), unlike the normal time 
  455.          */
  456.         time_diff =
  457.             (snapshot[0].css_time -
  458.              snapshot[number_of_snapshots].css_time) / 1000000;
  459.         DEBUGMSGTL(("ucd-snmp/vmstat_solaris2.c:update_stats",
  460.                     "time_diff: %lldn", time_diff));
  461.         /*
  462.          * swapin and swapout are in pages, MIB wants kB/s,so we just need to get kB and seconds 
  463.          * For the others we need to get value per second 
  464.          * getpagesize() returns pagesize in bytes 
  465.          * decided to use sysconf(_SC_PAGESIZE) instead to get around an #ifndef (I don't like those) 
  466.          * that was needed b/c some old Solaris versions don't have getpagesize() 
  467.          */
  468.         /*
  469.          * LINTED cast needed, really 
  470.          */
  471.         swapin =
  472.             (uint_t) ((css_new->css_swapin -
  473.                        css_old->css_swapin) * (hrtime_t) 1000 *
  474.                       sysconf(_SC_PAGESIZE) / 1024 / time_diff);
  475.         /*
  476.          * LINTED cast needed, really 
  477.          */
  478.         swapout =
  479.             (uint_t) ((css_new->css_swapout -
  480.                        css_old->css_swapout) * (hrtime_t) 1000 *
  481.                       sysconf(_SC_PAGESIZE) / 1024 / time_diff);
  482.         /*
  483.          * LINTED cast needed, really 
  484.          */
  485.         blocks_read =
  486.             (uint_t) ((css_new->css_blocks_read -
  487.                        css_old->css_blocks_read) * (hrtime_t) 1000 /
  488.                       time_diff);
  489.         /*
  490.          * LINTED cast needed, really 
  491.          */
  492.         blocks_write =
  493.             (uint_t) ((css_new->css_blocks_write -
  494.                        css_old->css_blocks_write) * (hrtime_t) 1000 /
  495.                       time_diff);
  496.         /*
  497.          * LINTED cast needed, really 
  498.          */
  499.         interrupts =
  500.             (uint_t) ((css_new->css_interrupts -
  501.                        css_old->css_interrupts) * (hrtime_t) 1000 /
  502.                       time_diff);
  503.         /*
  504.          * LINTED cast needed, really 
  505.          */
  506.         context_sw =
  507.             (uint_t) ((css_new->css_context_sw -
  508.                        css_old->css_context_sw) * (hrtime_t) 1000 /
  509.                       time_diff);
  510.         /*
  511.          * Loop thru all the CPU_STATES and get the differences 
  512.          */
  513.         for (i = 0; i < CPU_STATES; i++) {
  514.             cpu_sum += (css_new->css_cpu[i] - css_old->css_cpu[i]);
  515.         }
  516.         /*
  517.          * Now calculate the absolute percentage values 
  518.          * Looks somewhat complicated sometimes but tries to get around using floats to increase speed 
  519.          */
  520.         for (i = 0; i < CPU_STATES; i++) {
  521.             /*
  522.              * Since we don't return fractions we use + 0.5 to get between 99 and 101 percent adding the values 
  523.              * together, otherwise we would get less than 100 most of the time 
  524.              */
  525.             /*
  526.              * LINTED has to be 'long' 
  527.              */
  528.             cpu_perc[i] =
  529.                 (long) (((css_new->css_cpu[i] -
  530.                           css_old->css_cpu[i]) * 100 +
  531.                          (cpu_sum / 2)) / cpu_sum);
  532.         }
  533.         /*
  534.          * As said before, MIB wants CPU_SYSTEM which is CPU_KERNEL + CPU_WAIT 
  535.          */
  536.         /*
  537.          * LINTED has to be 'long' 
  538.          */
  539.         cpu_perc[CPU_SYSTEM] =
  540.             (long) ((((css_new->css_cpu[CPU_KERNEL] -
  541.                        css_old->css_cpu[CPU_KERNEL])
  542.                       + (css_new->css_cpu[CPU_WAIT] -
  543.                          css_old->css_cpu[CPU_WAIT]))
  544.                      * 100 + (cpu_sum / 2)) / cpu_sum);
  545.     }
  546.     /*
  547.      * Make the current one the first one and move the whole thing one place down 
  548.      */
  549.     memmove(&snapshot[1], &snapshot[0],
  550.             (size_t) (((char *) &snapshot[POLL_VALUES]) -
  551.                       ((char *) &snapshot[0])));
  552.     /*
  553.      * Erase the current one 
  554.      */
  555.     memset(&snapshot[0], 0, sizeof snapshot[0]);
  556.     /*
  557.      * Only important on start up, we keep track of how many snapshots we have taken so far 
  558.      */
  559.     if (number_of_snapshots < POLL_VALUES) {
  560.         number_of_snapshots++;
  561.     }
  562. }                               /* update_stats ends here */
  563. /*
  564.  * *var_extensible_vmstat starts here 
  565.  * The guts of the module, this routine gets called to service a request 
  566.  */
  567. unsigned char *
  568. var_extensible_vmstat(struct variable *vp,
  569.                       oid * name,
  570.                       size_t * length,
  571.                       int exact,
  572.                       size_t * var_len, WriteMethod ** write_method)
  573. {
  574.     /*
  575.      * Needed for returning the values 
  576.      */
  577.     static long     long_ret;
  578.     static char     errmsg[300];
  579.     /*
  580.      * set to 0 as default 
  581.      */
  582.     long_ret = 0;
  583.     /*
  584.      * generic check whether the options passed make sense and whether the 
  585.      * right variable is requested 
  586.      */
  587.     if (header_generic(vp, name, length, exact, var_len, write_method) !=
  588.         MATCH_SUCCEEDED) {
  589.         return (NULL);
  590.     }
  591.     /*
  592.      * The function that actually returns s.th. 
  593.      */
  594.     switch (vp->magic) {
  595.     case MIBINDEX:
  596.         long_ret = 1;
  597.         return ((u_char *) (&long_ret));
  598.     case ERRORNAME:            /* dummy name */
  599.         sprintf(errmsg, "systemStats");
  600.         *var_len = strlen(errmsg);
  601.         return ((u_char *) (errmsg));
  602.     case SWAPIN:
  603.         return ((u_char *) (&swapin));
  604.     case SWAPOUT:
  605.         return ((u_char *) (&swapout));
  606.     case IOSENT:
  607.         return ((u_char *) (&blocks_write));
  608.     case IORECEIVE:
  609.         return ((u_char *) (&blocks_read));
  610.     case SYSINTERRUPTS:
  611.         return ((u_char *) (&interrupts));
  612.     case SYSCONTEXT:
  613.         return ((u_char *) (&context_sw));
  614.     case CPUUSER:
  615.         return ((u_char *) (&cpu_perc[CPU_USER]));
  616.     case CPUSYSTEM:
  617.         return ((u_char *) (&cpu_perc[CPU_SYSTEM]));
  618.     case CPUIDLE:
  619.         return ((u_char *) (&cpu_perc[CPU_IDLE]));
  620.     case CPURAWUSER:
  621.         take_snapshot(&raw_values);
  622.         /*
  623.          * LINTED has to be 'long' 
  624.          */
  625.         long_ret =
  626.             (long) (raw_values.css_cpu[CPU_USER] / raw_values.css_cpus);
  627.         return ((u_char *) (&long_ret));
  628.         /*
  629.          * We are missing CPURAWNICE, Solaris does not account for this in the kernel so this OID can not 
  630.          * be returned.  Also, these values will roll over sooner or later and then return inaccurate data 
  631.          * but the MIB wants Integer32 so we cannot put a counter here 
  632.          * (Has been changed to Counter32 in the latest MIB version!) 
  633.          */
  634.     case CPURAWSYSTEM:
  635.         take_snapshot(&raw_values);
  636.         /*
  637.          * LINTED has to be 'long' 
  638.          */
  639.         long_ret =
  640.             (long) ((raw_values.css_cpu[CPU_KERNEL] +
  641.                      raw_values.css_cpu[CPU_WAIT]) / raw_values.css_cpus);
  642.         return ((u_char *) (&long_ret));
  643.     case CPURAWIDLE:
  644.         take_snapshot(&raw_values);
  645.         /*
  646.          * LINTED has to be 'long' 
  647.          */
  648.         long_ret =
  649.             (long) (raw_values.css_cpu[CPU_IDLE] / raw_values.css_cpus);
  650.         return ((u_char *) (&long_ret));
  651.     case CPURAWWAIT:
  652.         take_snapshot(&raw_values);
  653.         /*
  654.          * LINTED has to be 'long' 
  655.          */
  656.         long_ret =
  657.             (long) (raw_values.css_cpu[CPU_WAIT] / raw_values.css_cpus);
  658.         return ((u_char *) (&long_ret));
  659.     case CPURAWKERNEL:
  660.         take_snapshot(&raw_values);
  661.         /*
  662.          * LINTED has to be 'long' 
  663.          */
  664.         long_ret =
  665.             (long) (raw_values.css_cpu[CPU_KERNEL] / raw_values.css_cpus);
  666.         return ((u_char *) (&long_ret));
  667.     case IORAWSENT:
  668.         long_ret = (long) (raw_values.css_blocks_write);
  669.         return ((u_char *) (&long_ret));
  670.     case IORAWRECEIVE:
  671.         long_ret = (long) (raw_values.css_blocks_read);
  672.         return ((u_char *) (&long_ret));
  673.         /*
  674.          * reserved for future use 
  675.          */
  676.         /*
  677.          * case ERRORFLAG:
  678.          * return((u_char *) (&long_ret));
  679.          * case ERRORMSG:
  680.          * return((u_char *) (&long_ret));
  681.          */
  682.     default:
  683.         snmp_log(LOG_ERR,
  684.                  "vmstat_solaris2: Error in request, no match for %d.n",
  685.  vp->magic);
  686.     }
  687.     return (NULL);
  688. }                               /* *var_extensible_vmstat ends here */
  689. /*
  690.  * Functions end here 
  691.  */
  692. /*
  693.  * Program ends here 
  694.  */