sigar-test 0.7.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/NOTICE +117 -0
  4. data/README +2 -0
  5. data/Rakefile +105 -0
  6. data/bindings/SigarBuild.pm +301 -0
  7. data/bindings/SigarWrapper.pm +3025 -0
  8. data/bindings/ruby/extconf.rb +131 -0
  9. data/bindings/ruby/rbsigar.c +888 -0
  10. data/include/sigar.h +984 -0
  11. data/include/sigar_fileinfo.h +157 -0
  12. data/include/sigar_format.h +65 -0
  13. data/include/sigar_getline.h +18 -0
  14. data/include/sigar_log.h +80 -0
  15. data/include/sigar_private.h +429 -0
  16. data/include/sigar_ptql.h +53 -0
  17. data/include/sigar_util.h +197 -0
  18. data/src/os/aix/aix_sigar.c +2168 -0
  19. data/src/os/aix/sigar_os.h +73 -0
  20. data/src/os/darwin/Info.plist.in +27 -0
  21. data/src/os/darwin/darwin_sigar.c +3718 -0
  22. data/src/os/darwin/sigar_os.h +80 -0
  23. data/src/os/hpux/hpux_sigar.c +1361 -0
  24. data/src/os/hpux/sigar_os.h +49 -0
  25. data/src/os/linux/linux_sigar.c +2810 -0
  26. data/src/os/linux/sigar_os.h +82 -0
  27. data/src/os/solaris/get_mib2.c +321 -0
  28. data/src/os/solaris/get_mib2.h +127 -0
  29. data/src/os/solaris/kstats.c +181 -0
  30. data/src/os/solaris/procfs.c +97 -0
  31. data/src/os/solaris/sigar_os.h +224 -0
  32. data/src/os/solaris/solaris_sigar.c +2732 -0
  33. data/src/os/win32/peb.c +212 -0
  34. data/src/os/win32/sigar.rc.in +40 -0
  35. data/src/os/win32/sigar_os.h +685 -0
  36. data/src/os/win32/sigar_pdh.h +47 -0
  37. data/src/os/win32/win32_sigar.c +4109 -0
  38. data/src/sigar.c +2444 -0
  39. data/src/sigar_cache.c +253 -0
  40. data/src/sigar_fileinfo.c +815 -0
  41. data/src/sigar_format.c +696 -0
  42. data/src/sigar_getline.c +1849 -0
  43. data/src/sigar_ptql.c +1976 -0
  44. data/src/sigar_signal.c +216 -0
  45. data/src/sigar_util.c +1060 -0
  46. data/src/sigar_version.c.in +22 -0
  47. data/src/sigar_version_autoconf.c.in +22 -0
  48. data/version.properties +11 -0
  49. metadata +91 -0
data/src/sigar_util.c ADDED
@@ -0,0 +1,1060 @@
1
+ /*
2
+ * Copyright (c) 2004-2009 Hyperic, Inc.
3
+ * Copyright (c) 2009 SpringSource, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #include <stdio.h>
19
+ #include <stdlib.h>
20
+ #include <errno.h>
21
+ #include <fcntl.h>
22
+ #include <assert.h>
23
+
24
+ #include "sigar.h"
25
+ #include "sigar_private.h"
26
+ #include "sigar_util.h"
27
+ #include "sigar_os.h"
28
+
29
+ #ifndef WIN32
30
+
31
+ #include <dirent.h>
32
+ #include <sys/stat.h>
33
+
34
+ SIGAR_INLINE char *sigar_uitoa(char *buf, unsigned int n, int *len)
35
+ {
36
+ char *start = buf + UITOA_BUFFER_SIZE - 1;
37
+
38
+ *start = 0;
39
+
40
+ do {
41
+ *--start = '0' + (n % 10);
42
+ ++*len;
43
+ n /= 10;
44
+ } while (n);
45
+
46
+ return start;
47
+ }
48
+
49
+ SIGAR_INLINE char *sigar_skip_line(char *buffer, int buflen)
50
+ {
51
+ char *ptr = buflen ?
52
+ (char *)memchr(buffer, '\n', buflen) : /* bleh */
53
+ strchr(buffer, '\n');
54
+ return ++ptr;
55
+ }
56
+
57
+ SIGAR_INLINE char *sigar_skip_token(char *p)
58
+ {
59
+ while (sigar_isspace(*p)) p++;
60
+ while (*p && !sigar_isspace(*p)) p++;
61
+ return p;
62
+ }
63
+
64
+ SIGAR_INLINE char *sigar_skip_multiple_token(char *p, int count)
65
+ {
66
+ int i;
67
+
68
+ for (i = 0; i < count; i++) {
69
+ p = sigar_skip_token(p);
70
+ }
71
+
72
+ return p;
73
+ }
74
+
75
+ char *sigar_getword(char **line, char stop)
76
+ {
77
+ char *pos = *line;
78
+ int len;
79
+ char *res;
80
+
81
+ while ((*pos != stop) && *pos) {
82
+ ++pos;
83
+ }
84
+
85
+ len = pos - *line;
86
+ res = malloc(len + 1);
87
+ memcpy(res, *line, len);
88
+ res[len] = 0;
89
+
90
+ if (stop) {
91
+ while (*pos == stop) {
92
+ ++pos;
93
+ }
94
+ }
95
+
96
+ *line = pos;
97
+
98
+ return res;
99
+ }
100
+
101
+ /* avoiding sprintf */
102
+
103
+ char *sigar_proc_filename(char *buffer, int buflen,
104
+ sigar_pid_t bigpid,
105
+ const char *fname, int fname_len)
106
+ {
107
+ int len = 0;
108
+ char *ptr = buffer;
109
+ unsigned int pid = (unsigned int)bigpid; /* XXX -- This isn't correct */
110
+ char pid_buf[UITOA_BUFFER_SIZE];
111
+ char *pid_str = sigar_uitoa(pid_buf, pid, &len);
112
+
113
+ assert((unsigned int)buflen >=
114
+ (SSTRLEN(PROCP_FS_ROOT) + UITOA_BUFFER_SIZE + fname_len + 1));
115
+
116
+ memcpy(ptr, PROCP_FS_ROOT, SSTRLEN(PROCP_FS_ROOT));
117
+ ptr += SSTRLEN(PROCP_FS_ROOT);
118
+
119
+ memcpy(ptr, pid_str, len);
120
+ ptr += len;
121
+
122
+ memcpy(ptr, fname, fname_len);
123
+ ptr += fname_len;
124
+ *ptr = '\0';
125
+
126
+ return buffer;
127
+ }
128
+
129
+ int sigar_proc_file2str(char *buffer, int buflen,
130
+ sigar_pid_t pid,
131
+ const char *fname,
132
+ int fname_len)
133
+ {
134
+ int retval;
135
+
136
+ buffer = sigar_proc_filename(buffer, buflen, pid,
137
+ fname, fname_len);
138
+
139
+ retval = sigar_file2str(buffer, buffer, buflen);
140
+
141
+ if (retval != SIGAR_OK) {
142
+ switch (retval) {
143
+ case ENOENT:
144
+ retval = ESRCH; /* no such process */
145
+ default:
146
+ break;
147
+ }
148
+ }
149
+
150
+ return retval;
151
+ }
152
+
153
+ int sigar_proc_list_procfs_get(sigar_t *sigar,
154
+ sigar_proc_list_t *proclist)
155
+ {
156
+ DIR *dirp = opendir("/proc");
157
+ struct dirent *ent;
158
+ #ifdef HAVE_READDIR_R
159
+ struct dirent dbuf;
160
+ #endif
161
+
162
+ if (!dirp) {
163
+ return errno;
164
+ }
165
+
166
+ #ifdef HAVE_READDIR_R
167
+ while (readdir_r(dirp, &dbuf, &ent) == 0) {
168
+ if (ent == NULL) {
169
+ break;
170
+ }
171
+ #else
172
+ while ((ent = readdir(dirp))) {
173
+ #endif
174
+ if (!sigar_isdigit(*ent->d_name)) {
175
+ continue;
176
+ }
177
+
178
+ /* XXX: more sanity checking */
179
+
180
+ SIGAR_PROC_LIST_GROW(proclist);
181
+
182
+ proclist->data[proclist->number++] =
183
+ strtoul(ent->d_name, NULL, 10);
184
+ }
185
+
186
+ closedir(dirp);
187
+
188
+ return SIGAR_OK;
189
+ }
190
+
191
+ int sigar_proc_fd_count(sigar_t *sigar, sigar_pid_t pid,
192
+ sigar_uint64_t *total)
193
+ {
194
+ DIR *dirp;
195
+ struct dirent *ent;
196
+ #ifdef HAVE_READDIR_R
197
+ struct dirent dbuf;
198
+ #endif
199
+ char name[BUFSIZ];
200
+
201
+ (void)SIGAR_PROC_FILENAME(name, pid, "/fd");
202
+
203
+ *total = 0;
204
+
205
+ if (!(dirp = opendir(name))) {
206
+ return errno;
207
+ }
208
+
209
+ #ifdef HAVE_READDIR_R
210
+ while (readdir_r(dirp, &dbuf, &ent) == 0) {
211
+ if (ent == NULL) {
212
+ break;
213
+ }
214
+ #else
215
+ while ((ent = readdir(dirp))) {
216
+ #endif
217
+ if (!sigar_isdigit(*ent->d_name)) {
218
+ continue;
219
+ }
220
+
221
+ (*total)++;
222
+ }
223
+
224
+ closedir(dirp);
225
+
226
+ return SIGAR_OK;
227
+ }
228
+
229
+ int sigar_procfs_args_get(sigar_t *sigar, sigar_pid_t pid,
230
+ sigar_proc_args_t *procargs)
231
+ {
232
+ char buffer[9086], *buf=NULL, *ptr;
233
+ int fd, len, total=0;
234
+
235
+ (void)SIGAR_PROC_FILENAME(buffer, pid, "/cmdline");
236
+
237
+ if ((fd = open(buffer, O_RDONLY)) < 0) {
238
+ if (errno == ENOENT) {
239
+ return ESRCH;
240
+ }
241
+ return errno;
242
+ }
243
+
244
+ buffer[0] = '\0';
245
+
246
+ /* XXX: possible to get rid of some mallocs here.
247
+ * but, unlikely this will be called often so it
248
+ * might not even matter much.
249
+ */
250
+ while ((len = read(fd, buffer, sizeof(buffer)-1)) > 0) {
251
+ if (len == 0) {
252
+ break;
253
+ }
254
+ buf = realloc(buf, total+len+1);
255
+ memcpy(buf+total, buffer, len);
256
+ total += len;
257
+ }
258
+
259
+ close(fd);
260
+
261
+ /* e.g. /proc/2/cmdline */
262
+ if (total == 0) {
263
+ procargs->number = 0;
264
+ return SIGAR_OK;
265
+ }
266
+
267
+ buf[total] = '\0';
268
+ ptr = buf;
269
+
270
+ while (total > 0) {
271
+ int alen = strlen(ptr)+1;
272
+ char *arg = malloc(alen);
273
+
274
+ SIGAR_PROC_ARGS_GROW(procargs);
275
+ memcpy(arg, ptr, alen);
276
+
277
+ procargs->data[procargs->number++] = arg;
278
+
279
+ total -= alen;
280
+ if (total > 0) {
281
+ ptr += alen;
282
+ }
283
+ }
284
+
285
+ free(buf);
286
+
287
+ return SIGAR_OK;
288
+ }
289
+
290
+ #endif /* WIN32 */
291
+
292
+ /* from httpd/server/util.c */
293
+ char *sigar_strcasestr(const char *s1, const char *s2)
294
+ {
295
+ char *p1, *p2;
296
+ if (*s2 == '\0') {
297
+ /* an empty s2 */
298
+ return((char *)s1);
299
+ }
300
+ while(1) {
301
+ for ( ; (*s1 != '\0') && (sigar_tolower(*s1) != sigar_tolower(*s2)); s1++);
302
+ if (*s1 == '\0') {
303
+ return(NULL);
304
+ }
305
+ /* found first character of s2, see if the rest matches */
306
+ p1 = (char *)s1;
307
+ p2 = (char *)s2;
308
+ for (++p1, ++p2; sigar_tolower(*p1) == sigar_tolower(*p2); ++p1, ++p2) {
309
+ if (*p1 == '\0') {
310
+ /* both strings ended together */
311
+ return((char *)s1);
312
+ }
313
+ }
314
+ if (*p2 == '\0') {
315
+ /* second string ended, a match */
316
+ break;
317
+ }
318
+ /* didn't find a match here, try starting at next character in s1 */
319
+ s1++;
320
+ }
321
+ return((char *)s1);
322
+ }
323
+
324
+ int sigar_mem_calc_ram(sigar_t *sigar, sigar_mem_t *mem)
325
+ {
326
+ sigar_int64_t total = mem->total / 1024, diff;
327
+ sigar_uint64_t lram = (mem->total / (1024 * 1024));
328
+ int ram = (int)lram; /* must cast after division */
329
+ int remainder = ram % 8;
330
+
331
+ if (remainder > 0) {
332
+ ram += (8 - remainder);
333
+ }
334
+
335
+ mem->ram = ram;
336
+
337
+ diff = total - (mem->actual_free / 1024);
338
+ mem->used_percent =
339
+ (double)(diff * 100) / total;
340
+
341
+ diff = total - (mem->actual_used / 1024);
342
+ mem->free_percent =
343
+ (double)(diff * 100) / total;
344
+
345
+ return ram;
346
+ }
347
+
348
+ #ifndef WIN32
349
+
350
+ sigar_iodev_t *sigar_iodev_get(sigar_t *sigar,
351
+ const char *dirname)
352
+ {
353
+ sigar_cache_entry_t *entry;
354
+ struct stat sb;
355
+ sigar_uint64_t id;
356
+ sigar_file_system_list_t fslist;
357
+ int i, status, is_dev=0;
358
+ int debug = SIGAR_LOG_IS_DEBUG(sigar);
359
+ char dev_name[SIGAR_FS_NAME_LEN];
360
+
361
+ if (!sigar->fsdev) {
362
+ sigar->fsdev = sigar_cache_new(15);
363
+ }
364
+
365
+ if (*dirname != '/') {
366
+ snprintf(dev_name, sizeof(dev_name),
367
+ SIGAR_DEV_PREFIX "%s", dirname);
368
+ dirname = dev_name;
369
+ is_dev = 1;
370
+ }
371
+ else if (SIGAR_NAME_IS_DEV(dirname)) {
372
+ is_dev = 1;
373
+ }
374
+
375
+ if (stat(dirname, &sb) < 0) {
376
+ if (debug) {
377
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
378
+ "[iodev] stat(%s) failed",
379
+ dirname);
380
+ }
381
+ return NULL;
382
+ }
383
+
384
+ id = SIGAR_FSDEV_ID(sb);
385
+
386
+ entry = sigar_cache_get(sigar->fsdev, id);
387
+
388
+ if (entry->value != NULL) {
389
+ return (sigar_iodev_t *)entry->value;
390
+ }
391
+
392
+ if (is_dev) {
393
+ sigar_iodev_t *iodev;
394
+ entry->value = iodev = malloc(sizeof(*iodev));
395
+ SIGAR_ZERO(iodev);
396
+ SIGAR_SSTRCPY(iodev->name, dirname);
397
+ if (debug) {
398
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
399
+ "[iodev] %s is_dev=true", dirname);
400
+ }
401
+ return iodev;
402
+ }
403
+
404
+ status = sigar_file_system_list_get(sigar, &fslist);
405
+
406
+ if (status != SIGAR_OK) {
407
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
408
+ "[iodev] file_system_list failed: %s",
409
+ sigar_strerror(sigar, status));
410
+ return NULL;
411
+ }
412
+
413
+ for (i=0; i<fslist.number; i++) {
414
+ sigar_file_system_t *fsp = &fslist.data[i];
415
+
416
+ if (fsp->type == SIGAR_FSTYPE_LOCAL_DISK) {
417
+ int retval = stat(fsp->dir_name, &sb);
418
+ sigar_cache_entry_t *ent;
419
+
420
+ if (retval < 0) {
421
+ if (debug) {
422
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
423
+ "[iodev] inode stat(%s) failed",
424
+ fsp->dir_name);
425
+ }
426
+ continue; /* cant cache w/o inode */
427
+ }
428
+
429
+ ent = sigar_cache_get(sigar->fsdev, SIGAR_FSDEV_ID(sb));
430
+ if (ent->value) {
431
+ continue; /* already cached */
432
+ }
433
+
434
+ if (SIGAR_NAME_IS_DEV(fsp->dev_name)) {
435
+ sigar_iodev_t *iodev;
436
+ ent->value = iodev = malloc(sizeof(*iodev));
437
+ SIGAR_ZERO(iodev);
438
+ iodev->is_partition = 1;
439
+ SIGAR_SSTRCPY(iodev->name, fsp->dev_name);
440
+
441
+ if (debug) {
442
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
443
+ "[iodev] map %s -> %s",
444
+ fsp->dir_name, iodev->name);
445
+ }
446
+ }
447
+ }
448
+ }
449
+
450
+ sigar_file_system_list_destroy(sigar, &fslist);
451
+
452
+ if (entry->value &&
453
+ (((sigar_iodev_t *)entry->value)->name[0] != '\0'))
454
+ {
455
+ return (sigar_iodev_t *)entry->value;
456
+ }
457
+ else {
458
+ return NULL;
459
+ }
460
+ }
461
+ #endif
462
+
463
+ double sigar_file_system_usage_calc_used(sigar_t *sigar,
464
+ sigar_file_system_usage_t *fsusage)
465
+ {
466
+ /*
467
+ * win32 will not convert __uint64 to double.
468
+ * convert to KB then do unsigned long -> double.
469
+ */
470
+ sigar_uint64_t b_used = (fsusage->total - fsusage->free) / 1024;
471
+ sigar_uint64_t b_avail = fsusage->avail / 1024;
472
+ unsigned long utotal = b_used + b_avail;
473
+ unsigned long used = b_used;
474
+
475
+ if (utotal != 0) {
476
+ unsigned long u100 = used * 100;
477
+ double pct = u100 / utotal +
478
+ ((u100 % utotal != 0) ? 1 : 0);
479
+ return pct / 100;
480
+ }
481
+
482
+ return 0;
483
+ }
484
+
485
+ typedef struct {
486
+ sigar_uint32_t eax;
487
+ sigar_uint32_t ebx;
488
+ sigar_uint32_t ecx;
489
+ sigar_uint32_t edx;
490
+ } sigar_cpuid_t;
491
+
492
+ #if defined(__GNUC__) && !defined(__sun)
493
+
494
+ # if defined(__i386__)
495
+ # define SIGAR_HAS_CPUID
496
+ static void sigar_cpuid(sigar_uint32_t request, sigar_cpuid_t *id)
497
+ {
498
+ /* derived from: */
499
+ /* http://svn.red-bean.com/repos/minor/trunk/gc/barriers-ia-32.c */
500
+ asm volatile ("mov %%ebx, %%esi\n\t"
501
+ "cpuid\n\t"
502
+ "xchgl %%ebx, %%esi"
503
+ : "=a" (id->eax),
504
+ "=S" (id->ebx),
505
+ "=c" (id->ecx),
506
+ "=d" (id->edx)
507
+ : "0" (request)
508
+ : "memory");
509
+ }
510
+ # elif defined(__amd64__)
511
+ # define SIGAR_HAS_CPUID
512
+ static void sigar_cpuid(sigar_uint32_t request,
513
+ sigar_cpuid_t *id)
514
+ {
515
+ /* http://svn.red-bean.com/repos/minor/trunk/gc/barriers-amd64.c */
516
+ asm volatile ("cpuid\n\t"
517
+ : "=a" (id->eax),
518
+ "=b" (id->ebx),
519
+ "=c" (id->ecx),
520
+ "=d" (id->edx)
521
+ : "0" (request)
522
+ : "memory");
523
+ }
524
+ # endif
525
+ #elif defined(WIN32)
526
+ # ifdef _M_X64
527
+ # include <intrin.h>
528
+ # define SIGAR_HAS_CPUID
529
+ static void sigar_cpuid(sigar_uint32_t request,
530
+ sigar_cpuid_t *id)
531
+ {
532
+ sigar_uint32_t info[4];
533
+ __cpuid(info, request); /* as of MSVC 7 */
534
+ memcpy(id, &info[0], sizeof(info));
535
+ }
536
+ # else
537
+ # define SIGAR_HAS_CPUID
538
+ static void sigar_cpuid(sigar_uint32_t request,
539
+ sigar_cpuid_t *id)
540
+ {
541
+ __asm {
542
+ mov edi, id
543
+ mov eax, [edi].eax
544
+ mov ecx, [edi].ecx
545
+ cpuid
546
+ mov [edi].eax, eax
547
+ mov [edi].ebx, ebx
548
+ mov [edi].ecx, ecx
549
+ mov [edi].edx, edx
550
+ }
551
+ }
552
+ # endif
553
+ #endif
554
+
555
+ #define INTEL_ID 0x756e6547
556
+ #define AMD_ID 0x68747541
557
+
558
+ int sigar_cpu_core_count(sigar_t *sigar)
559
+ {
560
+ #if defined(SIGAR_HAS_CPUID)
561
+ sigar_cpuid_t id;
562
+
563
+ if (sigar->lcpu == -1) {
564
+ sigar->lcpu = 1;
565
+
566
+ sigar_cpuid(0, &id);
567
+
568
+ if ((id.ebx == INTEL_ID) || (id.ebx == AMD_ID)) {
569
+ sigar_cpuid(1, &id);
570
+
571
+ if (id.edx & (1<<28)) {
572
+ sigar->lcpu = (id.ebx & 0x00FF0000) >> 16;
573
+ }
574
+ }
575
+
576
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
577
+ "[cpu] %d cores per socket", sigar->lcpu);
578
+ }
579
+
580
+ return sigar->lcpu;
581
+ #elif defined(__sun) || defined(__hpux) || defined(_AIX)
582
+ return 1;
583
+ #else
584
+ sigar->lcpu = 1;
585
+ return sigar->lcpu;
586
+ #endif
587
+ }
588
+
589
+ int sigar_cpu_core_rollup(sigar_t *sigar)
590
+ {
591
+ #ifdef SIGAR_HAS_CPUID
592
+ int log_rollup =
593
+ SIGAR_LOG_IS_DEBUG(sigar) &&
594
+ (sigar->lcpu == -1);
595
+
596
+ (void)sigar_cpu_core_count(sigar);
597
+
598
+ if (sigar->cpu_list_cores) {
599
+ if (log_rollup && (sigar->lcpu > 1)) {
600
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
601
+ "[cpu] treating cores as-is");
602
+ }
603
+ }
604
+ else {
605
+ if (log_rollup && (sigar->lcpu > 1)) {
606
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
607
+ "[cpu] rolling up cores to sockets");
608
+ return 1;
609
+ }
610
+ }
611
+ #endif
612
+ return 0;
613
+ }
614
+
615
+ #define IS_CPU_R(p) \
616
+ ((*p == '(') && (*(p+1) == 'R') && (*(p+2) == ')'))
617
+
618
+ typedef struct {
619
+ char *name; /* search */
620
+ int len;
621
+ char *rname; /* replace */
622
+ int rlen;
623
+ } cpu_model_str_t;
624
+
625
+ /* to later replace 's' with 'r' */
626
+ #define CPU_MODEL_ENT_R(s, r) \
627
+ { s, sizeof(s)-1, r, sizeof(r) }
628
+
629
+ #define CPU_MODEL_ENT(s) \
630
+ CPU_MODEL_ENT_R(s, s)
631
+
632
+ /* after the vendor part of the string is removed,
633
+ * looking for startsWith the entries below
634
+ * to remove the crap after the model name, see
635
+ * ../exp/intel_amd_cpu_models.txt
636
+ */
637
+ static const cpu_model_str_t cpu_models[] = {
638
+ /* intel */
639
+ CPU_MODEL_ENT("Xeon"),
640
+ CPU_MODEL_ENT_R("XEON", "Xeon"),
641
+ CPU_MODEL_ENT("Pentium III"),
642
+ CPU_MODEL_ENT("Pentium II"),
643
+ CPU_MODEL_ENT_R("Pentium(R) III", "Pentium III"),
644
+ CPU_MODEL_ENT_R("Pentium(R) 4", "Pentium 4"),
645
+ CPU_MODEL_ENT_R("Pentium(R) M", "Pentium M"),
646
+ CPU_MODEL_ENT("Pentium Pro"),
647
+ CPU_MODEL_ENT("Celeron"),
648
+
649
+ /* amd */
650
+ CPU_MODEL_ENT("Opteron"),
651
+ CPU_MODEL_ENT("Athlon"),
652
+ CPU_MODEL_ENT("Duron"),
653
+ CPU_MODEL_ENT_R("K6(tm)-III", "K6 III"),
654
+ CPU_MODEL_ENT_R("K6(tm) 3D+", "K6 3D+"),
655
+ { NULL }
656
+ };
657
+
658
+ /* common to win32 and linux */
659
+ void sigar_cpu_model_adjust(sigar_t *sigar, sigar_cpu_info_t *info)
660
+ {
661
+ int len, i;
662
+ char model[128], *ptr=model, *end;
663
+
664
+ memcpy(model, info->model, sizeof(model));
665
+
666
+ /* trim leading and trailing spaces */
667
+ len = strlen(model);
668
+ end = &model[len-1];
669
+ while (*ptr == ' ') ++ptr;
670
+ while (*end == ' ') *end-- = '\0';
671
+
672
+ /* remove vendor from model name */
673
+ len = strlen(info->vendor);
674
+ if (strnEQ(ptr, info->vendor, len)) {
675
+ ptr += len;
676
+ if (IS_CPU_R(ptr)) {
677
+ ptr += 3; /* remove (R) */
678
+ }
679
+ while (*ptr == ' ') ++ptr;
680
+ }
681
+
682
+ if (*ptr == '-') {
683
+ ++ptr; /* e.g. was AMD-K6... */
684
+ }
685
+
686
+ for (i=0; cpu_models[i].name; i++) {
687
+ const cpu_model_str_t *cpu_model = &cpu_models[i];
688
+
689
+ if (strnEQ(ptr, cpu_model->name, cpu_model->len)) {
690
+ memcpy(info->model, cpu_model->rname, cpu_model->rlen);
691
+ return;
692
+ }
693
+ }
694
+
695
+ strcpy(info->model, ptr);
696
+ }
697
+
698
+ /* attempt to derive MHz from model name
699
+ * currently works for certain intel strings
700
+ * see exp/intel_amd_cpu_models.txt
701
+ */
702
+ int sigar_cpu_mhz_from_model(char *model)
703
+ {
704
+ int mhz = SIGAR_FIELD_NOTIMPL;
705
+ char *ptr = model;
706
+
707
+ while (*ptr && (ptr = strchr(ptr, ' '))) {
708
+ while(*ptr && !sigar_isdigit(*ptr)) {
709
+ ptr++;
710
+ }
711
+ mhz = sigar_strtoul(ptr);
712
+
713
+ if (*ptr == '.') {
714
+ /* e.g. "2.40GHz" */
715
+ ++ptr;
716
+ mhz *= 100;
717
+ mhz += sigar_strtoul(ptr);
718
+ break;
719
+ }
720
+ else if (strnEQ(ptr, "GHz", 3) ||
721
+ strnEQ(ptr, "MHz", 3))
722
+ {
723
+ /* e.g. "1500MHz" */
724
+ break;
725
+ }
726
+ else {
727
+ mhz = SIGAR_FIELD_NOTIMPL;
728
+ }
729
+ }
730
+
731
+ if (mhz != SIGAR_FIELD_NOTIMPL) {
732
+ if (strnEQ(ptr, "GHz", 3)) {
733
+ mhz *= 10;
734
+ }
735
+ }
736
+
737
+ return mhz;
738
+ }
739
+
740
+ #if !defined(WIN32) && !defined(NETWARE)
741
+ #include <netdb.h>
742
+ #include <rpc/rpc.h>
743
+ #include <rpc/pmap_prot.h>
744
+ #include <rpc/pmap_clnt.h>
745
+ #ifdef SIGAR_HPUX
746
+ #include <nfs/nfs.h>
747
+ #endif
748
+ #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__sun) || defined(DARWIN)
749
+ #include <arpa/inet.h>
750
+ #endif
751
+ #if defined(__sun) || defined(SIGAR_HPUX)
752
+ #include <rpc/clnt_soc.h>
753
+ #endif
754
+ #if defined(_AIX) || defined(SIGAR_HPUX) || defined(__OpenBSD__) || defined(__NetBSD__)
755
+ #include <sys/socket.h>
756
+ #endif
757
+
758
+ static enum clnt_stat get_sockaddr(struct sockaddr_in *addr, char *host)
759
+ {
760
+ register struct hostent *hp;
761
+ sigar_hostent_t data;
762
+
763
+ memset(addr, 0, sizeof(struct sockaddr_in));
764
+ addr->sin_family = AF_INET;
765
+
766
+ if ((addr->sin_addr.s_addr = inet_addr(host)) == -1) {
767
+ if (!(hp = sigar_gethostbyname(host, &data))) {
768
+ return RPC_UNKNOWNHOST;
769
+ }
770
+ memcpy(&addr->sin_addr, hp->h_addr, hp->h_length);
771
+ }
772
+
773
+ return RPC_SUCCESS;
774
+ }
775
+
776
+ char *sigar_rpc_strerror(int err)
777
+ {
778
+ return (char *)clnt_sperrno(err);
779
+ }
780
+
781
+ SIGAR_DECLARE(int) sigar_rpc_ping(char *host,
782
+ int protocol,
783
+ unsigned long program,
784
+ unsigned long version)
785
+ {
786
+ CLIENT *client;
787
+ struct sockaddr_in addr;
788
+ int sock;
789
+ struct timeval timeout;
790
+ unsigned short port = 0;
791
+ enum clnt_stat rpc_stat;
792
+
793
+ rpc_stat = get_sockaddr(&addr, host);
794
+ if (rpc_stat != RPC_SUCCESS) {
795
+ return rpc_stat;
796
+ }
797
+
798
+ timeout.tv_sec = 2;
799
+ timeout.tv_usec = 0;
800
+ addr.sin_port = htons(port);
801
+ sock = RPC_ANYSOCK;
802
+
803
+ if (protocol == SIGAR_NETCONN_UDP) {
804
+ client =
805
+ clntudp_create(&addr, program, version,
806
+ timeout, &sock);
807
+ }
808
+ else if (protocol == SIGAR_NETCONN_TCP) {
809
+ client =
810
+ clnttcp_create(&addr, program, version,
811
+ &sock, 0, 0);
812
+ }
813
+ else {
814
+ return RPC_UNKNOWNPROTO;
815
+ }
816
+
817
+ if (!client) {
818
+ return rpc_createerr.cf_stat;
819
+ }
820
+
821
+ timeout.tv_sec = 10;
822
+ timeout.tv_usec = 0;
823
+ rpc_stat = clnt_call(client, NULLPROC, (xdrproc_t)xdr_void, NULL,
824
+ (xdrproc_t)xdr_void, NULL, timeout);
825
+
826
+ clnt_destroy(client);
827
+
828
+ return rpc_stat;
829
+ }
830
+ #endif
831
+
832
+ int sigar_file2str(const char *fname, char *buffer, int buflen)
833
+ {
834
+ int len, status;
835
+ int fd = open(fname, O_RDONLY);
836
+
837
+ if (fd < 0) {
838
+ return ENOENT;
839
+ }
840
+
841
+ if ((len = read(fd, buffer, buflen)) < 0) {
842
+ status = errno;
843
+ }
844
+ else {
845
+ status = SIGAR_OK;
846
+ buffer[len] = '\0';
847
+ }
848
+ close(fd);
849
+
850
+ return status;
851
+ }
852
+
853
+ #ifdef WIN32
854
+ #define vsnprintf _vsnprintf
855
+ #endif
856
+
857
+ #ifdef WIN32
858
+ # define rindex strrchr
859
+ #endif
860
+
861
+ static int proc_module_get_self(void *data, char *name, int len)
862
+ {
863
+ sigar_t *sigar = (sigar_t *)data;
864
+ char *ptr = rindex(name, '/');
865
+
866
+ if (!ptr) {
867
+ return SIGAR_OK;
868
+ }
869
+
870
+ if (strnEQ(ptr+1, "libsigar-", 9)) {
871
+ int offset = ptr - name;
872
+
873
+ sigar->self_path = sigar_strdup(name);
874
+ *(sigar->self_path + offset) = '\0'; /* chop libsigar-*.so */
875
+
876
+ if (SIGAR_LOG_IS_DEBUG(sigar)) {
877
+ sigar_log_printf(sigar, SIGAR_LOG_DEBUG,
878
+ "detected sigar-lib='%s'",
879
+ sigar->self_path);
880
+ }
881
+
882
+ return !SIGAR_OK; /* break loop */
883
+ }
884
+
885
+ return SIGAR_OK;
886
+ }
887
+
888
+ char *sigar_get_self_path(sigar_t *sigar)
889
+ {
890
+ if (!sigar->self_path) {
891
+ sigar_proc_modules_t procmods;
892
+ char *self_path = getenv("SIGAR_PATH");
893
+
894
+ if (self_path) {
895
+ sigar->self_path = sigar_strdup(self_path);
896
+ return sigar->self_path;
897
+ }
898
+
899
+ procmods.module_getter = proc_module_get_self;
900
+ procmods.data = sigar;
901
+
902
+ sigar_proc_modules_get(sigar,
903
+ sigar_pid_get(sigar),
904
+ &procmods);
905
+
906
+ if (!sigar->self_path) {
907
+ /* dont try again */
908
+ sigar->self_path = sigar_strdup(".");
909
+ }
910
+ }
911
+
912
+ return sigar->self_path;
913
+ }
914
+
915
+ #ifdef SIGAR_HAS_DLINFO_MODULES
916
+
917
+ static int sigar_dlinfo_get(sigar_t *sigar, const char *func,
918
+ void **handle, Link_map **map)
919
+ {
920
+ Dl_info dli;
921
+
922
+ if (!dladdr((void *)((uintptr_t)sigar_dlinfo_get), &dli)) {
923
+ sigar_log_printf(sigar, SIGAR_LOG_ERROR,
924
+ "[%s] dladdr(%s) = %s",
925
+ func, SIGAR_FUNC, dlerror());
926
+ return ESRCH;
927
+ }
928
+
929
+ if (!(*handle = dlopen(dli.dli_fname, RTLD_LAZY))) {
930
+ sigar_log_printf(sigar, SIGAR_LOG_ERROR,
931
+ "[%s] dlopen(%s) = %s",
932
+ func, dli.dli_fname, dlerror());
933
+ return ESRCH;
934
+ }
935
+
936
+ dlinfo(*handle, RTLD_DI_LINKMAP, map);
937
+
938
+ if (!map) {
939
+ sigar_log_printf(sigar, SIGAR_LOG_ERROR,
940
+ "[%s] dlinfo = %s",
941
+ func, dlerror());
942
+ return ESRCH;
943
+ }
944
+
945
+ return SIGAR_OK;
946
+ }
947
+
948
+ int sigar_dlinfo_modules(sigar_t *sigar, sigar_proc_modules_t *procmods)
949
+ {
950
+ int status;
951
+ void *handle;
952
+ Link_map *map;
953
+
954
+ status = sigar_dlinfo_get(sigar, SIGAR_FUNC, &handle, &map);
955
+ if (status != SIGAR_OK) {
956
+ return status;
957
+ }
958
+
959
+ while (map->l_prev != NULL) {
960
+ map = map->l_prev;
961
+ }
962
+
963
+ do {
964
+ int status =
965
+ procmods->module_getter(procmods->data,
966
+ (char *)map->l_name,
967
+ strlen(map->l_name));
968
+
969
+ if (status != SIGAR_OK) {
970
+ /* not an error; just stop iterating */
971
+ break;
972
+ }
973
+ } while ((map = map->l_next));
974
+
975
+ dlclose(handle);
976
+
977
+ return SIGAR_OK;
978
+ }
979
+ #endif
980
+
981
+ SIGAR_DECLARE(void) sigar_log_printf(sigar_t *sigar, int level,
982
+ const char *format, ...)
983
+ {
984
+ va_list args;
985
+ char buffer[8192];
986
+
987
+ if (level > sigar->log_level) {
988
+ return;
989
+ }
990
+
991
+ if (!sigar->log_impl) {
992
+ return;
993
+ }
994
+
995
+ va_start(args, format);
996
+ vsnprintf(buffer, sizeof(buffer), format, args);
997
+ va_end(args);
998
+
999
+ sigar->log_impl(sigar, sigar->log_data, level, buffer);
1000
+ }
1001
+
1002
+ SIGAR_DECLARE(void) sigar_log(sigar_t *sigar, int level, char *message)
1003
+ {
1004
+ if (level > sigar->log_level) {
1005
+ return;
1006
+ }
1007
+
1008
+ if (!sigar->log_impl) {
1009
+ return;
1010
+ }
1011
+
1012
+ sigar->log_impl(sigar, sigar->log_data, level, message);
1013
+ }
1014
+
1015
+ SIGAR_DECLARE(void) sigar_log_impl_set(sigar_t *sigar, void *data,
1016
+ sigar_log_impl_t impl)
1017
+ {
1018
+ sigar->log_data = data;
1019
+ sigar->log_impl = impl;
1020
+ }
1021
+
1022
+ SIGAR_DECLARE(int) sigar_log_level_get(sigar_t *sigar)
1023
+ {
1024
+ return sigar->log_level;
1025
+ }
1026
+
1027
+ static const char *log_levels[] = {
1028
+ "FATAL",
1029
+ "ERROR",
1030
+ "WARN",
1031
+ "INFO",
1032
+ "DEBUG",
1033
+ "TRACE"
1034
+ };
1035
+
1036
+ SIGAR_DECLARE(const char *) sigar_log_level_string_get(sigar_t *sigar)
1037
+ {
1038
+ return log_levels[sigar->log_level];
1039
+ }
1040
+
1041
+ SIGAR_DECLARE(void) sigar_log_level_set(sigar_t *sigar, int level)
1042
+ {
1043
+ sigar->log_level = level;
1044
+ }
1045
+
1046
+ SIGAR_DECLARE(void) sigar_log_impl_file(sigar_t *sigar, void *data,
1047
+ int level, char *message)
1048
+ {
1049
+ FILE *fp = (FILE*)data;
1050
+ fprintf(fp, "[%s] %s\n", log_levels[level], message);
1051
+ }
1052
+
1053
+ #ifndef WIN32
1054
+ sigar_int64_t sigar_time_now_millis(void)
1055
+ {
1056
+ struct timeval tv;
1057
+ gettimeofday(&tv, NULL);
1058
+ return ((tv.tv_sec * SIGAR_USEC) + tv.tv_usec) / SIGAR_MSEC;
1059
+ }
1060
+ #endif