l = strlen(line);
// Call the callback
- r = callback(self->ctx, lineno++, line, l, data);
+ r = callback(self->ctx, self, lineno++, line, l, data);
if (r < 0)
- break;
+ goto ERROR;
}
- // Cleanup
+ERROR:
if (line)
free(line);
return r;
}
+static int collecty_file_check_pattern(collecty_file* self, const char* s) {
+ const char* p = s;
+ int counter = 0;
+
+ // Count all %
+ switch (*p++) {
+ case '%':
+ counter++;
+ break;
+
+ default:
+ break;
+ }
+
+ return counter;
+}
+
+static int collecty_file_check_parser(collecty_file* self, collecty_file_parser* parser) {
+ // Check all elements
+ for (collecty_file_parser* p = parser; p->s; p++) {
+ switch (collecty_file_check_pattern(self, p->s)) {
+ // Complain if there is no format character, but we can continue here
+ case 0:
+ ERROR(self->ctx, "Parser pattern has no value defined: %s\n", p->s);
+ break;
+
+ // We require exactly one format character
+ case 1:
+ if (unlikely(!p->v)) {
+ ERROR(self->ctx, "Pattern has no target defined: %s\n", p->s);
+ return -EINVAL;
+ }
+ break;
+
+ default:
+ ERROR(self->ctx, "Too many values defined: %s\n", p->s);
+ return -EINVAL;
+ }
+ }
+
+ // All good!
+ return 0;
+}
+
+static int __collecty_file_parse(collecty_ctx* ctx, collecty_file* self,
+ unsigned long lineno, char* line, size_t length, void* data) {
+ collecty_file_parser* parser = data;
+ int r;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+
+ // Run the parser
+ for (collecty_file_parser* p = parser; p->s; p++) {
+ r = sscanf(line, p->s, p->v);
+ if (r < 0)
+ return -errno;
+
+ // If the field could be matched, we return
+ if (r == 1)
+ return 0;
+ }
+
+#pragma GCC diagnostic pop
+
+ return 0;
+}
+
+int collecty_file_parse(collecty_file* self, collecty_file_parser* parser) {
+ int r;
+
+ // Check the parser
+ r = collecty_file_check_parser(self, parser);
+ if (r < 0)
+ return r;
+
+ // Run the parser
+ return collecty_file_walk(self, __collecty_file_parse, parser);
+}
+
int collecty_read_uint64(collecty_ctx* ctx, const char* path, uint64_t* number) {
collecty_file* file = NULL;
int r;
return r;
}
+
+int collecty_parse(collecty_ctx* ctx, const char* path, collecty_file_parser* parser) {
+ collecty_file* file = NULL;
+ int r;
+
+ // Open the file
+ r = collecty_file_open_path(&file, ctx, path);
+ if (r < 0)
+ goto ERROR;
+
+ // Run the parser
+ r = collecty_file_parse(file, parser);
+ if (r < 0)
+ goto ERROR;
+
+ERROR:
+ if (file)
+ collecty_file_unref(file);
+
+ return r;
+}
#include "string.h"
int collecty_proc_read_meminfo(collecty_ctx* ctx, collecty_proc_meminfo* meminfo) {
- unsigned long v;
- FILE* f = NULL;
- char k[64];
+ collecty_file_parser parser[] = {
+ { "MemTotal: %lu kB", &meminfo->mem_total, },
+ { "MemFree: %lu kB", &meminfo->mem_free, },
+ { "MemAvailable: %lu kB", &meminfo->mem_available, },
+ { "Cached: %lu kB", &meminfo->cached, },
+ { "Buffers: %lu kB", &meminfo->buffers, },
+ { "Active: %lu kB", &meminfo->active, },
+ { "Inactive: %lu kB", &meminfo->inactive, },
+ { "Active(anon): %lu kB", &meminfo->active_anon, },
+ { "Inactive(anon): %lu kB", &meminfo->inactive_anon, },
+ { "Active(file): %lu kB", &meminfo->active_file, },
+ { "Inactive(file): %lu kB", &meminfo->inactive_file, },
+ { "SwapTotal: %lu kB", &meminfo->swap_total, },
+ { "SwapFree: %lu kB", &meminfo->swap_free, },
+ { "Shmem: %lu kB", &meminfo->shmem, },
+ { "Slab: %lu kB", &meminfo->slab, },
+ { "SReclaimable: %lu kB", &meminfo->sreclaimable, },
+ { "SUnreclaim: %lu kB", &meminfo->sunreclaim, },
+ { NULL },
+ };
int r;
- // Open /proc/meminfo
- f = fopen("/proc/meminfo", "r");
- if (!f)
- return -errno;
-
- // Read line by line
- for (;;) {
- r = fscanf(f, "%63s %lu kB\n", k, &v);
- if (r < 0)
- break;
-
- // Skip any lines that could not be parsed
- if (r < 2)
- continue;
-
- // Convert the value from kB into Bytes
- v *= 1024;
-
- // Store the values
- if (collecty_string_equals("MemTotal:", k))
- meminfo->mem_total = v;
- else if (collecty_string_equals("MemFree:", k))
- meminfo->mem_free = v;
- else if (collecty_string_equals("MemAvailable:", k))
- meminfo->mem_available = v;
- else if (collecty_string_equals("Cached:", k))
- meminfo->cached = v;
- else if (collecty_string_equals("Buffers:", k))
- meminfo->buffers = v;
- else if (collecty_string_equals("Active:", k))
- meminfo->active = v;
- else if (collecty_string_equals("Inactive:", k))
- meminfo->inactive = v;
- else if (collecty_string_equals("Active(anon):", k))
- meminfo->active_anon = v;
- else if (collecty_string_equals("Inactive(anon):", k))
- meminfo->inactive_anon = v;
- else if (collecty_string_equals("Active(file):", k))
- meminfo->active_file = v;
- else if (collecty_string_equals("Inactive(file):", k))
- meminfo->inactive_file = v;
- else if (collecty_string_equals("SwapTotal:", k))
- meminfo->swap_total = v;
- else if (collecty_string_equals("SwapFree:", k))
- meminfo->swap_free = v;
- else if (collecty_string_equals("Shmem:", k))
- meminfo->shmem = v;
- else if (collecty_string_equals("Slab:", k))
- meminfo->slab = v;
- else if (collecty_string_equals("SReclaimable:", k))
- meminfo->sreclaimable = v;
- else if (collecty_string_equals("SUnreclaim:", k))
- meminfo->sunreclaim = v;
- }
-
- // Success
- r = 0;
+ // Parse /proc/meminfo
+ r = collecty_parse(ctx, "/proc/meminfo", parser);
+ if (r < 0)
+ return r;
- // Cleanup
- if (f)
- fclose(f);
+ // Convert all values to bytes
+ meminfo->mem_free *= 1024;
+ meminfo->mem_available *= 1024;
+ meminfo->cached *= 1024;
+ meminfo->buffers *= 1024;
+ meminfo->active *= 1024;
+ meminfo->inactive *= 1024;
+ meminfo->active_anon *= 1024;
+ meminfo->inactive_anon *= 1024;
+ meminfo->active_file *= 1024;
+ meminfo->inactive_file *= 1024;
+ meminfo->swap_total *= 1024;
+ meminfo->swap_free *= 1024;
+ meminfo->shmem *= 1024;
+ meminfo->slab *= 1024;
+ meminfo->sreclaimable *= 1024;
+ meminfo->sunreclaim *= 1024;
- return r;
+ return 0;
}
static int collecty_proc_read_stat_line(collecty_ctx* ctx,
unsigned long lineno;
} collecty_proc_softirq_state;
-static int collecty_proc_softirq_line(collecty_ctx* ctx,
+static int collecty_proc_softirq_line(collecty_ctx* ctx, collecty_file* file,
unsigned long lineno, char* line, size_t length, void* data) {
collecty_proc_softirq_state* state = data;
uint64_t n = 0;