summaryrefslogtreecommitdiff
path: root/src/pmdas/linux/linux_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmdas/linux/linux_table.c')
-rw-r--r--src/pmdas/linux/linux_table.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/pmdas/linux/linux_table.c b/src/pmdas/linux/linux_table.c
new file mode 100644
index 0000000..d04f454
--- /dev/null
+++ b/src/pmdas/linux/linux_table.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2012 Red Hat.
+ * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "linux_table.h"
+
+extern int linux_table_lookup(const char *field, struct linux_table *table, uint64_t *val);
+extern struct linux_table *linux_table_clone(struct linux_table *table);
+extern int linux_table_scan(FILE *fp, struct linux_table *table);
+
+inline int
+linux_table_lookup(const char *field, struct linux_table *table, uint64_t *val)
+{
+ struct linux_table *t;
+
+ for (t=table; t && t->field; t++) {
+ if (strncmp(field, t->field, t->field_len) == 0) {
+ if (t->valid) {
+ *val = t->val;
+ return 1;
+ }
+ /* Invalid */
+ return 0;
+ }
+ }
+
+ fprintf(stderr, "Warning: linux_table_lookup failed for \"%s\"\n", field);
+ return 0;
+}
+
+inline struct linux_table *
+linux_table_clone(struct linux_table *table)
+{
+ struct linux_table *ret;
+ struct linux_table *t;
+ int len;
+
+ if (!table)
+ return NULL;
+ for (len=1, t=table; t->field; t++)
+ len++;
+ ret = (struct linux_table *)malloc(len * sizeof(struct linux_table));
+ if (!ret)
+ return NULL;
+ memcpy(ret, table, len * sizeof(struct linux_table));
+
+ /* Initialize the table */
+ for (t=ret; t && t->field; t++) {
+ if (!t->field_len)
+ t->field_len = strlen(t->field);
+ t->valid = LINUX_TABLE_INVALID;
+ }
+
+ return ret;
+}
+
+inline int
+linux_table_scan(FILE *fp, struct linux_table *table)
+{
+ char *p;
+ struct linux_table *t;
+ char buf[1024];
+ int ret = 0;
+
+ while(fgets(buf, sizeof(buf), fp) != NULL) {
+ for (t=table; t && t->field; t++) {
+ if ((p = strstr(buf, t->field)) != NULL) {
+ /* first digit after the matched field */
+ for (p += t->field_len; *p; p++) {
+ if (isdigit((int)*p))
+ break;
+ }
+ if (isdigit((int)*p)) {
+ t->this = strtoul(p, NULL, 10);
+ t->valid = LINUX_TABLE_VALID;
+ ret++;
+ break;
+ }
+ }
+ }
+ }
+
+ /* calculate current value, accounting for counter wrap */
+ for (t=table; t && t->field; t++) {
+ if (t->maxval == 0)
+ /* instantaneous value */
+ t->val = t->this;
+ else {
+ /* counter value */
+ if (t->this >= t->prev)
+ t->val += t->this - t->prev;
+ else
+ t->val += t->this + (t->maxval - t->prev);
+ t->prev = t->this;
+ }
+ }
+
+ return ret;
+}