/common/fh_sysmon.c

https://github.com/csinitiative/fhce · C · 258 lines · 165 code · 44 blank · 49 comment · 52 complexity · 9367ec6a99f297a111b4c7a8535214d1 MD5 · raw file

  1. /*
  2. * Copyright (C) 2008, 2009, 2010 The Collaborative Software Foundation.
  3. *
  4. * This file is part of FeedHandlers (FH).
  5. *
  6. * FH is free software: you can redistribute it and/or modify it under the terms of the
  7. * GNU Lesser General Public License as published by the Free Software Foundation, either version 3
  8. * of the License, or (at your option) any later version.
  9. *
  10. * FH is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
  11. * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public License
  15. * along with FH. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. /*
  18. * System includes
  19. */
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <sys/sysinfo.h>
  24. /*
  25. * FH includes
  26. */
  27. #include "fh_log.h"
  28. #include "fh_util.h"
  29. #include "fh_sysmon.h"
  30. /*
  31. * fh_mon_mem_stats
  32. *
  33. * Get the VM stats for the system.
  34. */
  35. FH_STATUS fh_mon_mem_stats(fh_mon_mem_t *mem)
  36. {
  37. #define NUM_FIELDS (4)
  38. char *fields[NUM_FIELDS];
  39. FILE *fh;
  40. char buffer[1024];
  41. int numfields;
  42. fh = fopen("/proc/meminfo", "r");
  43. if (!fh) {
  44. FH_LOG(CSI, ERR, ("Failed to open /proc/meminfo: %m"));
  45. return FH_ERROR;
  46. }
  47. while (fgets(buffer, sizeof(buffer), fh) != NULL) {
  48. uint64_t *val;
  49. if (strncasecmp(buffer, "MemTotal:", 9) == 0)
  50. val = &mem->mem_total;
  51. else if (strncasecmp(buffer, "MemFree:", 8) == 0)
  52. val = &mem->mem_free;
  53. else if (strncasecmp (buffer, "Buffers:", 8) == 0)
  54. val = &mem->mem_buffered;
  55. else if (strncasecmp(buffer, "Cached:", 7) == 0)
  56. val = &mem->mem_cached;
  57. else
  58. break;
  59. numfields = fh_strsplit(buffer, fields, NUM_FIELDS);
  60. if (numfields < 2) continue;
  61. *val = atoll(fields[1]) * 1024LL;
  62. }
  63. fclose(fh);
  64. return FH_OK;
  65. #undef NUM_FIELDS
  66. }
  67. /*
  68. * fh_mon_cpu_stats
  69. *
  70. * System and CPU statistics
  71. */
  72. FH_STATUS fh_mon_cpu_stats(fh_mon_sys_t *sys, fh_mon_cpu_t *cpu_table, int max_cpus)
  73. {
  74. #define NUM_FIELDS (10)
  75. FILE *fh;
  76. char buffer[1024];
  77. char *fields[NUM_FIELDS];
  78. int numfields;
  79. int numcpus = 0;
  80. static uint16_t cpu_count = 0;
  81. static uint32_t clock_rate = 0;
  82. /*
  83. * Read the CPU clock rate and total number of CPUs in the system only once
  84. */
  85. if (cpu_count == 0) {
  86. clock_rate = sysconf(_SC_CLK_TCK);
  87. cpu_count = sysconf(_SC_NPROCESSORS_CONF);
  88. }
  89. memset(sys, 0, sizeof(fh_mon_sys_t));
  90. memset(cpu_table, 0, sizeof(fh_mon_cpu_t) * max_cpus);
  91. sys->sys_num_cpus = cpu_count;
  92. sys->sys_clock_rate = clock_rate;
  93. {
  94. struct sysinfo info;
  95. sysinfo(&info);
  96. sys->sys_procs_total = info.procs;
  97. }
  98. fh = fopen("/proc/stat", "r");
  99. if (!fh) {
  100. FH_LOG(CSI, ERR, ("Failed to open /proc/stat: %m"));
  101. return FH_ERROR;
  102. }
  103. while (fgets(buffer, sizeof(buffer), fh) != NULL) {
  104. numfields = fh_strsplit(buffer, fields, NUM_FIELDS);
  105. if (strncmp(buffer, "cpu", 3)) {
  106. if (strncmp(buffer, "intr", 4) == 0) {
  107. sys->sys_intr = atoll(fields[1]);
  108. }
  109. else if (strncmp(buffer, "ctxt", 4) == 0) {
  110. sys->sys_ctxt = atoll(fields[1]);
  111. }
  112. else if (strncmp(buffer, "procs_running", 13) == 0) {
  113. sys->sys_procs_running = atoll(fields[1]);
  114. }
  115. else if (strncmp(buffer, "procs_blocked", 13) == 0) {
  116. sys->sys_procs_blocked = atoll(fields[1]);
  117. }
  118. else if (strncmp(buffer, "procs", 6) == 0) {
  119. sys->sys_procs = atoll(fields[1]);
  120. }
  121. continue;
  122. }
  123. if (buffer[3] < '0' || buffer[3] > '9') {
  124. continue;
  125. }
  126. if (numcpus < max_cpus) {
  127. fh_mon_cpu_t *cpu;
  128. cpu = &cpu_table[numcpus];
  129. cpu->cpu_num = atoi (fields[0] + 3);
  130. cpu->cpu_user = atoll(fields[1]);
  131. cpu->cpu_nice = atoll(fields[2]);
  132. cpu->cpu_system = atoll(fields[3]);
  133. cpu->cpu_idle = atoll(fields[4]);
  134. cpu->cpu_wait = atoll(fields[5]);
  135. cpu->cpu_hintr = atoll(fields[6]);
  136. cpu->cpu_sintr = atoll(fields[7]);
  137. if (numfields == 9) {
  138. cpu->cpu_steal = atoll(fields[8]);
  139. }
  140. else {
  141. cpu->cpu_steal = 0;
  142. }
  143. numcpus ++;
  144. }
  145. }
  146. fclose(fh);
  147. return FH_OK;
  148. #undef NUM_FIELDS
  149. }
  150. /*
  151. * fh_mon_proc_stats
  152. *
  153. * Get the process statistics for a given PID and Thread ID (TID).
  154. */
  155. FH_STATUS fh_mon_proc_stats(fh_mon_proc_t *proc, int pid, int tid)
  156. {
  157. #define NUM_FIELDS (100)
  158. static int64_t pagesize = 0;
  159. char buffer[1024];
  160. char filename[256];
  161. char *fields[NUM_FIELDS];
  162. FILE *fp = NULL;
  163. if (pagesize == 0) {
  164. pagesize = sysconf(_SC_PAGESIZE);
  165. }
  166. memset(proc, 0, sizeof(fh_mon_proc_t));
  167. /*
  168. * Fill in the process PID and TID
  169. */
  170. proc->proc_pid = pid;
  171. proc->proc_tid = tid;
  172. /*
  173. * Look for CPU statistics for this particular process
  174. */
  175. sprintf(filename, "/proc/%d/task/%d/stat", pid, tid);
  176. fp = fopen(filename, "r");
  177. if (!fp) {
  178. FH_LOG(CSI, ERR, ("Failed to open %s: %m", filename));
  179. return FH_ERROR;
  180. }
  181. if (fgets(buffer, sizeof(buffer), fp) != NULL) {
  182. int numfields = fh_strsplit(buffer, fields, NUM_FIELDS);
  183. if (numfields > 15) {
  184. proc->proc_lcpu = atoi(fields[38]);
  185. proc->proc_utime = atoll(fields[13]);
  186. proc->proc_stime = atoll(fields[14]);
  187. }
  188. }
  189. fclose(fp);
  190. /*
  191. * Get the memory usage of the process
  192. */
  193. sprintf(filename, "/proc/%d/task/%d/statm", pid, tid);
  194. fp = fopen(filename, "r");
  195. if (!fp) {
  196. FH_LOG(CSI, ERR, ("Failed to open %s: %m", filename));
  197. return FH_ERROR;
  198. }
  199. if (fgets(buffer, sizeof(buffer), fp) != NULL) {
  200. int numfields = fh_strsplit(buffer, fields, NUM_FIELDS);
  201. if (numfields == 7) {
  202. proc->proc_size = atoll(fields[0]) * pagesize;
  203. proc->proc_resident = atoll(fields[1]) * pagesize;
  204. proc->proc_share = atoll(fields[2]) * pagesize;
  205. proc->proc_text = atoll(fields[3]) * pagesize;
  206. proc->proc_lib = atoll(fields[4]) * pagesize;
  207. proc->proc_data = atoll(fields[5]) * pagesize;
  208. proc->proc_dirty = atoll(fields[6]) * pagesize;
  209. }
  210. }
  211. fclose(fp);
  212. return FH_OK;
  213. #undef NUM_FIELDS
  214. }