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

SNMP编程

开发平台:

Unix_Linux

  1. #include <net-snmp/net-snmp-config.h>
  2. #if HAVE_STDLIB_H
  3. #include <stdlib.h>
  4. #endif
  5. #if HAVE_UNISTD_H
  6. #include <unistd.h>
  7. #endif
  8. #if HAVE_FCNTL_H
  9. #include <fcntl.h>
  10. #endif
  11. #include <signal.h>
  12. #if HAVE_MACHINE_PARAM_H
  13. #include <machine/param.h>
  14. #endif
  15. #if HAVE_SYS_PARAM_H
  16. #include <sys/param.h>
  17. #endif
  18. #if HAVE_SYS_VMMETER_H
  19. #if !(defined(bsdi2) || defined(netbsd1))
  20. #include <sys/vmmeter.h>
  21. #endif
  22. #endif
  23. #if HAVE_SYS_CONF_H
  24. #include <sys/conf.h>
  25. #endif
  26. #if HAVE_ASM_PAGE_H
  27. #include <asm/page.h>
  28. #endif
  29. #if HAVE_SYS_SWAP_H
  30. #include <sys/swap.h>
  31. #endif
  32. #if HAVE_SYS_FS_H
  33. #include <sys/fs.h>
  34. #else
  35. #if HAVE_UFS_FS_H
  36. #include <ufs/fs.h>
  37. #else
  38. #ifdef HAVE_SYS_STAT_H
  39. #include <sys/stat.h>
  40. #endif
  41. #ifdef HAVE_SYS_VNODE_H
  42. #include <sys/vnode.h>
  43. #endif
  44. #ifdef HAVE_UFS_UFS_QUOTA_H
  45. #include <ufs/ufs/quota.h>
  46. #endif
  47. #ifdef HAVE_UFS_UFS_INODE_H
  48. #include <ufs/ufs/inode.h>
  49. #endif
  50. #if HAVE_UFS_FFS_FS_H
  51. #include <ufs/ffs/fs.h>
  52. #endif
  53. #endif
  54. #endif
  55. #if HAVE_MTAB_H
  56. #include <mtab.h>
  57. #endif
  58. #include <errno.h>
  59. #if HAVE_FSTAB_H
  60. #include <fstab.h>
  61. #endif
  62. #if HAVE_SYS_STATFS_H
  63. #include <sys/statfs.h>
  64. #endif
  65. #if HAVE_SYS_STATVFS_H
  66. #include <sys/statvfs.h>
  67. #endif
  68. #if HAVE_SYS_VFS_H
  69. #include <sys/vfs.h>
  70. #endif
  71. #if (!defined(HAVE_STATVFS)) && defined(HAVE_STATFS)
  72. #if HAVE_SYS_MOUNT_H
  73. #include <sys/mount.h>
  74. #endif
  75. #if HAVE_SYS_SYSCTL_H
  76. #include <sys/sysctl.h>
  77. #endif
  78. #define statvfs statfs
  79. #endif
  80. #if HAVE_VM_VM_H
  81. #include <vm/vm.h>
  82. #endif
  83. #if HAVE_VM_SWAP_PAGER_H
  84. #include <vm/swap_pager.h>
  85. #endif
  86. #if HAVE_SYS_FIXPOINT_H
  87. #include <sys/fixpoint.h>
  88. #endif
  89. #if HAVE_SYS_LOADAVG_H
  90. #include <sys/loadavg.h>
  91. #endif
  92. #if HAVE_MALLOC_H
  93. #include <malloc.h>
  94. #endif
  95. #if HAVE_STRING_H
  96. #include <string.h>
  97. #endif
  98. #if TIME_WITH_SYS_TIME
  99. # ifdef WIN32
  100. #  include <sys/timeb.h>
  101. # else
  102. #  include <sys/time.h>
  103. # endif
  104. # include <time.h>
  105. #else
  106. # if HAVE_SYS_TIME_H
  107. #  include <sys/time.h>
  108. # else
  109. #  include <time.h>
  110. # endif
  111. #endif
  112. #if HAVE_WINSOCK_H
  113. #include <winsock.h>
  114. #endif
  115. #ifdef dynix
  116. #include <sys/mc_vmparam.h>
  117. #endif
  118. #if defined(hpux10) || defined(hpux11)
  119. #include <sys/pstat.h>
  120. #endif
  121. #if defined(aix4) || defined(aix5)
  122. #include <libperfstat.h>
  123. #endif
  124. #include <net-snmp/net-snmp-includes.h>
  125. #include <net-snmp/agent/net-snmp-agent-includes.h>
  126. #include <net-snmp/agent/auto_nlist.h>
  127. #include "struct.h"
  128. #include "loadave.h"
  129. #include "util_funcs.h"
  130. #include "kernel.h"
  131. double          maxload[3];
  132. void
  133. init_loadave(void)
  134. {
  135.     /*
  136.      * define the structure we're going to ask the agent to register our
  137.      * information at 
  138.      */
  139.     struct variable2 extensible_loadave_variables[] = {
  140.         {MIBINDEX, ASN_INTEGER, RONLY, var_extensible_loadave, 1,
  141.          {MIBINDEX}},
  142.         {ERRORNAME, ASN_OCTET_STR, RONLY, var_extensible_loadave, 1,
  143.          {ERRORNAME}},
  144.         {LOADAVE, ASN_OCTET_STR, RONLY, var_extensible_loadave, 1,
  145.          {LOADAVE}},
  146.         {LOADMAXVAL, ASN_OCTET_STR, RONLY, var_extensible_loadave, 1,
  147.          {LOADMAXVAL}},
  148.         {LOADAVEINT, ASN_INTEGER, RONLY, var_extensible_loadave, 1,
  149.          {LOADAVEINT}},
  150. #ifdef OPAQUE_SPECIAL_TYPES
  151.         {LOADAVEFLOAT, ASN_OPAQUE_FLOAT, RONLY, var_extensible_loadave, 1,
  152.          {LOADAVEFLOAT}},
  153. #endif
  154.         {ERRORFLAG, ASN_INTEGER, RONLY, var_extensible_loadave, 1,
  155.          {ERRORFLAG}},
  156.         {ERRORMSG, ASN_OCTET_STR, RONLY, var_extensible_loadave, 1,
  157.          {ERRORMSG}}
  158.     };
  159.     /*
  160.      * Define the OID pointer to the top of the mib tree that we're
  161.      * registering underneath 
  162.      */
  163.     oid             loadave_variables_oid[] =
  164.         { UCDAVIS_MIB, LOADAVEMIBNUM, 1 };
  165.     /*
  166.      * register ourselves with the agent to handle our mib tree 
  167.      */
  168.     REGISTER_MIB("ucd-snmp/loadave", extensible_loadave_variables,
  169.                  variable2, loadave_variables_oid);
  170.     snmpd_register_config_handler("load", loadave_parse_config,
  171.                                   loadave_free_config,
  172.                                   "max1 [max5] [max15]");
  173. }
  174. void
  175. loadave_parse_config(const char *token, char *cptr)
  176. {
  177.     int             i;
  178.     for (i = 0; i <= 2; i++) {
  179.         if (cptr != NULL)
  180.             maxload[i] = atof(cptr);
  181.         else
  182.             maxload[i] = maxload[i - 1];
  183.         cptr = skip_not_white(cptr);
  184.         cptr = skip_white(cptr);
  185.     }
  186. }
  187. void
  188. loadave_free_config(void)
  189. {
  190.     int             i;
  191.     for (i = 0; i <= 2; i++)
  192.         maxload[i] = DEFMAXLOADAVE;
  193. }
  194. /*
  195.  * try to get load average
  196.  * Inputs: pointer to array of doubles, number of elements in array
  197.  * Returns: 0=array has values, -1=error occurred.
  198.  */
  199. int
  200. try_getloadavg(double *r_ave, size_t s_ave)
  201. {
  202.     double         *pave = r_ave;
  203. #ifndef HAVE_GETLOADAVG
  204. #ifdef HAVE_SYS_FIXPOINT_H
  205.     fix             favenrun[3];
  206. #endif
  207. #if (defined(ultrix) || defined(sun) || defined(__alpha) || defined(dynix))
  208.     int             i;
  209. #if (defined(sun) || defined(__alpha) || defined(dynix))
  210.     long            favenrun[3];
  211.     if (s_ave > 3)              /* bounds check */
  212.         return (-1);
  213. #define FIX_TO_DBL(_IN) (((double) _IN)/((double) FSCALE))
  214. #endif
  215. #endif
  216. #if defined(aix4) || defined(aix5)
  217.     int             favenrun[3];
  218.     perfstat_cpu_total_t cs;
  219. #endif
  220. #if defined(hpux10) || defined(hpux11)
  221.   struct pst_dynamic pst_buf;
  222. #endif
  223. #endif /* HAVE_GETLOADAVG */
  224. #ifdef HAVE_GETLOADAVG
  225.     if (getloadavg(pave, s_ave) == -1)
  226.         return (-1);
  227. #elif defined(linux)
  228.     {
  229.         FILE           *in = fopen("/proc/loadavg", "r");
  230.         if (!in) {
  231.             snmp_log(LOG_ERR, "snmpd: cannot open /proc/loadavgn");
  232.             return (-1);
  233.         }
  234.         fscanf(in, "%lf %lf %lf", pave, (pave + 1), (pave + 2));
  235.         fclose(in);
  236.     }
  237. #elif (defined(ultrix) || defined(sun) || defined(__alpha) || defined(dynix))
  238.     if (auto_nlist(LOADAVE_SYMBOL, (char *) favenrun, sizeof(favenrun)) ==
  239.         0)
  240.         return (-1);
  241.     for (i = 0; i < s_ave; i++)
  242.         *(pave + i) = FIX_TO_DBL(favenrun[i]);
  243. #elif defined(hpux10) || defined(hpux11)
  244.     if (pstat_getdynamic(&pst_buf, sizeof(struct pst_dynamic), 1, 0) < 0)
  245.         return(-1);
  246.     r_ave[0] = pst_buf.psd_avg_1_min;
  247.     r_ave[1] = pst_buf.psd_avg_5_min;
  248.     r_ave[2] = pst_buf.psd_avg_15_min;
  249. #elif !defined(cygwin)
  250. #ifdef CAN_USE_NLIST
  251. #if defined(aix4) || defined(aix5)
  252.     if(perfstat_cpu_total((perfstat_id_t *)NULL, &cs, sizeof(perfstat_cpu_total_t), 1) > 0) {
  253.         r_ave[0] = cs.loadavg[0] / 65536.0;
  254.         r_ave[1] = cs.loadavg[1] / 65536.0;
  255.         r_ave[2] = cs.loadavg[2] / 65536.0;
  256.     }
  257.     return 0;
  258. #else
  259.     if (auto_nlist(LOADAVE_SYMBOL, (char *) pave, sizeof(double) * s_ave)
  260.         == 0)
  261. #endif
  262. #endif
  263.         return (-1);
  264. #endif
  265.     /*
  266.      * XXX
  267.      *   To calculate this, we need to compare
  268.      *   successive values of the kernel array
  269.      *   '_cp_times', and calculate the resulting
  270.      *   percentage changes.
  271.      *     This calculation needs to be performed
  272.      *   regularly - perhaps as a background process.
  273.      *
  274.      *   See the source to 'top' for full details.
  275.      *
  276.      * The linux SNMP HostRes implementation
  277.      *   uses 'avenrun[0]*100' as an approximation.
  278.      *   This is less than accurate, but has the
  279.      *   advantage of being simple to implement!
  280.      *
  281.      * I'm also assuming a single processor
  282.      */
  283.     return 0;
  284. }
  285. u_char         *
  286. var_extensible_loadave(struct variable * vp,
  287.                        oid * name,
  288.                        size_t * length,
  289.                        int exact,
  290.                        size_t * var_len, WriteMethod ** write_method)
  291. {
  292.     static long     long_ret;
  293.     static float    float_ret;
  294.     static char     errmsg[300];
  295.     double          avenrun[3];
  296.     if (header_simple_table
  297.         (vp, name, length, exact, var_len, write_method, 3))
  298.         return (NULL);
  299.     switch (vp->magic) {
  300.     case MIBINDEX:
  301.         long_ret = name[*length - 1];
  302.         return ((u_char *) (&long_ret));
  303.     case ERRORNAME:
  304.         sprintf(errmsg, "Load-%d", ((name[*length - 1] == 1) ? 1 :
  305.                                     ((name[*length - 1] == 2) ? 5 : 15)));
  306.         *var_len = strlen(errmsg);
  307.         return ((u_char *) (errmsg));
  308.     }
  309.     if (try_getloadavg(&avenrun[0], sizeof(avenrun) / sizeof(avenrun[0]))
  310.         == -1)
  311.         return (0);
  312.     switch (vp->magic) {
  313.     case LOADAVE:
  314.         sprintf(errmsg, "%.2f", avenrun[name[*length - 1] - 1]);
  315.         *var_len = strlen(errmsg);
  316.         return ((u_char *) (errmsg));
  317.     case LOADMAXVAL:
  318.         sprintf(errmsg, "%.2f", maxload[name[*length - 1] - 1]);
  319.         *var_len = strlen(errmsg);
  320.         return ((u_char *) (errmsg));
  321.     case LOADAVEINT:
  322.         long_ret = (u_long) (avenrun[name[*length - 1] - 1] * 100);
  323.         return ((u_char *) (&long_ret));
  324. #ifdef OPAQUE_SPECIAL_TYPES
  325.     case LOADAVEFLOAT:
  326.         float_ret = (float) avenrun[name[*length - 1] - 1];
  327.         *var_len = sizeof(float_ret);
  328.         return ((u_char *) (&float_ret));
  329. #endif
  330.     case ERRORFLAG:
  331.         long_ret = (maxload[name[*length - 1] - 1] != 0 &&
  332.                     avenrun[name[*length - 1] - 1] >=
  333.                     maxload[name[*length - 1] - 1]) ? 1 : 0;
  334.         return ((u_char *) (&long_ret));
  335.     case ERRORMSG:
  336.         if (maxload[name[*length - 1] - 1] != 0 &&
  337.             avenrun[name[*length - 1] - 1] >=
  338.             maxload[name[*length - 1] - 1]) {
  339.             sprintf(errmsg, "%d min Load Average too high (= %.2f)",
  340.                     (name[*length - 1] ==
  341.                      1) ? 1 : ((name[*length - 1] == 2) ? 5 : 15),
  342.                     avenrun[name[*length - 1] - 1]);
  343.         } else {
  344.             errmsg[0] = 0;
  345.         }
  346.         *var_len = strlen(errmsg);
  347.         return ((u_char *) errmsg);
  348.     }
  349.     return NULL;
  350. }