support new dir structure
Costa Tsaousis (ktsaou) committed
Mar 16, 2015 at 19:20 UTC
490a75489433aab6e9c94c9b311f6419a12ac594
6 files changed
+737
-76
Makefile
deleted
-51
@@ -1,51 +0,0 @@
1
-
2
-CONFIG_DIR = "conf.d"
3
-LOG_DIR = "log"
4
-PLUGINS_DIR = "plugins.d"
5
-
6
-COMMON_FLAGS = -DCONFIG_DIR='$(CONFIG_DIR)' -DLOG_DIR='$(LOG_DIR)' -DPLUGINS_DIR='$(PLUGINS_DIR)'
7
-
8
-ifdef debug
9
-CFLAGS = $(COMMON_FLAGS) -Wall -Wextra -ggdb
10
-else
11
-CFLAGS = $(COMMON_FLAGS) -Wall -Wextra -O3
12
-endif
13
-
14
-all: netdata plugins
15
- @echo
16
- @echo "Compilation Done!"
17
- @echo "You can 'make getconf' to get the config file conf.d/netdata.conf from the netdata server."
18
- @echo
19
-
20
-plugins: plugins.d/apps.plugin
21
-
22
-netdata: netdata.c
23
- @echo
24
- @echo "Compiling netdata server..."
25
- $(CC) $(CFLAGS) -o netdata netdata.c -lpthread -lz
26
-
27
-plugins.d/apps.plugin: apps_plugin.c
28
- @echo
29
- @echo "Compiling apps.plugin..."
30
- $(CC) $(CFLAGS) -o plugins.d/apps.plugin apps_plugin.c
31
- @-if [ ! "$$USER" = "root" ]; \
32
- then \
33
- echo; \
34
- echo " >>> apps.plugin requires root access to access files in /proc"; \
35
- echo " >>> Please authorize it!"; \
36
- echo; \
37
- sudo chown root plugins.d/apps.plugin; \
38
- sudo chmod 4775 plugins.d/apps.plugin; \
39
- else \
40
- chown root plugins.d/apps.plugin; \
41
- chmod 4775 plugins.d/apps.plugin; \
42
- fi
43
-
44
-
45
-clean:
46
- -rm -f *.o netdata plugins.d/apps.plugin core
47
-
48
-getconf:
49
- wget -O conf.d/netdata.conf.new "http://localhost:19999/netdata.conf"
50
- mv conf.d/netdata.conf conf.d/netdata.conf.old
51
- mv conf.d/netdata.conf.new conf.d/netdata.conf
src/Makefile.save
deleted
-25
@@ -1,25 +0,0 @@
1
-# COMMON_FLAGS =
2
-
3
-ifdef final
4
-CFLAGS = -Wall -Wextra -I $(INCDIR) -O3 $(COMMON_FLAGS)
5
-else
6
-CFLAGS = -Wall -Wextra -ggdb -I $(INCDIR) $(COMMON_FLAGS)
7
-endif
8
-
9
-CC = gcc $(CFLAGS)
10
-
11
-sources = *.c
12
-headers = *.h
13
-objects = $(patsubst %.o,%.c,$(sources))
14
-
15
-all: netdata
16
-
17
-netdata: $(objects) $(headers) $(sources)
18
- echo "${sources}
19
- $(CC) -o netdata $(objects) -pthread -lzlib
20
-
21
-$(objects): %.c $(headers)
22
- $(CC) -c $< -o $@
23
-
24
-clean:
25
- rm -rfv *.o netdata core
src/old-and-tests/benchmark.c
new
+140
@@ -0,0 +1,140 @@
1
+#define _GNU_SOURCE
2
+
3
+#include <stdio.h>
4
+#include <stdlib.h>
5
+#include <unistd.h>
6
+#include <errno.h>
7
+#include <fcntl.h>
8
+#include <string.h>
9
+#include <malloc.h>
10
+#include <inttypes.h>
11
+
12
+#include <sys/types.h>
13
+#include <sys/stat.h>
14
+#include <sys/mman.h>
15
+
16
+#define FASTFILE_NORMAL 1
17
+
18
+#ifdef FASTFILE_NORMAL
19
+#define FASTFILE_BUFFER 65536
20
+#define FASTFILE_MAX_LINE_LENGTH 4096
21
+#endif
22
+
23
+typedef struct {
24
+ int fd;
25
+
26
+ ssize_t cursor;
27
+
28
+ char buffer[FASTFILE_BUFFER + 1];
29
+ ssize_t size;
30
+ int eof;
31
+} fastfile;
32
+
33
+fastfile *fastfile_open(const char *filename) {
34
+ fastfile *ff = malloc(sizeof(fastfile));
35
+ if(!ff) goto cleanup;
36
+
37
+ ff->fd = open(filename, O_RDONLY|O_NOATIME, 0666);
38
+ if(ff->fd == -1) goto cleanup;
39
+
40
+ ff->cursor = ff->size = ff->eof = 0;
41
+ ff->buffer[0] = '\0';
42
+
43
+ ssize_t r = read(ff->fd, &ff->buffer[ff->size], FASTFILE_BUFFER);
44
+ if(r != -1) {
45
+ ff->buffer[r + 1] = '\0';
46
+ ff->size = r;
47
+ if(r < FASTFILE_BUFFER) ff->eof = 1;
48
+ }
49
+ else goto cleanup;
50
+
51
+ return ff;
52
+
53
+cleanup:
54
+ if(ff) {
55
+ if(ff->fd != -1) close(ff->fd);
56
+ free(ff);
57
+ }
58
+ return NULL;
59
+}
60
+
61
+void fastfile_close(fastfile *ff) {
62
+ if(ff->fd != -1) close(ff->fd);
63
+ free(ff);
64
+}
65
+
66
+char *fastfile_getline(fastfile *ff) {
67
+ if( !ff->eof && ff->size == FASTFILE_BUFFER && ( ff->cursor + FASTFILE_MAX_LINE_LENGTH ) > ff->size ) {
68
+ // if(ff->size) fprintf(stderr, "Read more\n");
69
+
70
+ memmove(ff->buffer, &ff->buffer[ff->cursor], ff->size - ff->cursor + 1);
71
+ ff->size -= ff->cursor;
72
+ ff->cursor = 0;
73
+
74
+ ssize_t remaining = FASTFILE_BUFFER - ff->size;
75
+ // fprintf(stderr, "Reading up to %ld bytes\n", remaining);
76
+ ssize_t r = read(ff->fd, &ff->buffer[ff->size], remaining);
77
+ if(r != -1) {
78
+ ff->buffer[r + 1] = '\0';
79
+ ff->size = r;
80
+ // fprintf(stderr, "Read %ld bytes\n", r);
81
+ }
82
+
83
+ if(!r || r < remaining) {
84
+ // fprintf(stderr, "Read EOF\n");
85
+ ff->eof = 1;
86
+ }
87
+ }
88
+
89
+ //fprintf(stderr, "Line starts at %ld\n", ff->cursor);
90
+ if(ff->cursor >= ff->size) return NULL;
91
+
92
+ char *start = &ff->buffer[ff->cursor];
93
+ char *s = start;
94
+
95
+ while(*s != '\n' && *s != '\0') s++;
96
+ *s = '\0';
97
+ ff->cursor += ( s - start + 1 );
98
+ //fprintf(stderr, "Line ends at %ld\n", ff->cursor);
99
+
100
+ return start;
101
+}
102
+
103
+const char *filenames[] = {
104
+ "/proc/net/dev",
105
+ "/proc/diskstats",
106
+ "/proc/net/snmp",
107
+ "/proc/net/netstat",
108
+// "/proc/net/stat/nf_conntrack",
109
+// "/proc/net/ip_vs_stats",
110
+ "/proc/stat",
111
+ "/proc/meminfo",
112
+ "/proc/vmstat",
113
+ "/proc/self/mountstats",
114
+// "/var/log/messages",
115
+ NULL
116
+};
117
+
118
+int main(int argc, char **argv)
119
+{
120
+ int i, k = 0;
121
+ fastfile *ff;
122
+ char *s;
123
+
124
+ for(i = 0; i < 400000 ;i++, k++) {
125
+ if(filenames[k] == NULL) k = 0;
126
+
127
+ //fprintf(stderr, "\nOpening file '%s'\n", filenames[k]);
128
+ ff = fastfile_open(filenames[k]);
129
+ if(!ff) {
130
+ fprintf(stderr, "Cannot open file '%s', reason: %s\n", filenames[k], strerror(errno));
131
+ exit(1);
132
+ }
133
+
134
+ while((s = fastfile_getline(ff))) ;
135
+ // fprintf(stderr, "%s\n", s);
136
+
137
+ fastfile_close(ff);
138
+ }
139
+ return 0;
140
+}
src/old-and-tests/benchmark2.c
new
+597
@@ -0,0 +1,597 @@
1
+#define _GNU_SOURCE
2
+
3
+#include <stdio.h>
4
+#include <stdlib.h>
5
+#include <unistd.h>
6
+#include <errno.h>
7
+#include <fcntl.h>
8
+#include <string.h>
9
+#include <malloc.h>
10
+#include <inttypes.h>
11
+#include <ctype.h>
12
+#include <time.h>
13
+#include <sys/time.h>
14
+#include <sys/wait.h>
15
+
16
+#include <sys/types.h>
17
+#include <sys/stat.h>
18
+#include <sys/mman.h>
19
+
20
+/*
21
+ * This is a library for reading kernel files from /proc
22
+ *
23
+ * The idea is this:
24
+ *
25
+ * - every file is opened once.
26
+ * - to read updated contents, we rewind it (lseek() to 0) and read again.
27
+ * - for every file, we use a buffer that is adjusted to fit its entire
28
+ * contents in memory. This allows us to read it with a single read() call.
29
+ * (this provides atomicity / consistency on the data read from the kernel)
30
+ * - once the data are read, we update two arrays of pointers:
31
+ * - a words array, pointing to each word in the data read
32
+ * - a lines array, pointing to the first word for each line
33
+ * This is highly optimized. Both arrays are automatically adjusted to
34
+ * fit all contents and they are updated in a single pass on the data:
35
+ * - a raspberry Pi can process 5.000+ files / sec.
36
+ * - a J1900 celeron processor can process 23.000+ files / sec.
37
+*/
38
+
39
+#define PLUGIN_NAME "proc.plugin"
40
+
41
+int debug = 0;
42
+int update_every = 1;
43
+
44
+unsigned long long usecdiff(struct timeval *now, struct timeval *last) {
45
+ return ((((now->tv_sec * 1000000ULL) + now->tv_usec) - ((last->tv_sec * 1000000ULL) + last->tv_usec)));
46
+}
47
+
48
+// ----------------------------------------------------------------------------
49
+// An array of words
50
+
51
+typedef struct {
52
+ uint32_t len; // used entries
53
+ uint32_t size; // capacity
54
+ char *words[]; // array of pointers
55
+} ffwords;
56
+
57
+#define FFWORDS_INCREASE_STEP 200
58
+#define ffwords_get(fw, i) ((i < fw->size)?fw->words[i]:NULL)
59
+
60
+ffwords *ffwords_add(ffwords *fw, char *str) {
61
+ if(debug) fprintf(stderr, PLUGIN_NAME ": adding word No %d: '%s'\n", fw->len, str);
62
+
63
+ if(fw->len == fw->size) {
64
+ if(debug) fprintf(stderr, PLUGIN_NAME ": expanding words\n");
65
+
66
+ ffwords *new = realloc(fw, sizeof(ffwords) + (fw->size + FFWORDS_INCREASE_STEP) * sizeof(char *));
67
+ if(!new) {
68
+ fprintf(stderr, PLUGIN_NAME ": failed to expand words\n");
69
+ free(fw);
70
+ return NULL;
71
+ }
72
+ fw = new;
73
+ fw->size += FFWORDS_INCREASE_STEP;
74
+ }
75
+
76
+ fw->words[fw->len++] = str;
77
+
78
+ return fw;
79
+}
80
+
81
+ffwords *ffwords_new(void) {
82
+ if(debug) fprintf(stderr, PLUGIN_NAME ": initializing words\n");
83
+
84
+ ffwords *new = malloc(sizeof(ffwords) + FFWORDS_INCREASE_STEP * sizeof(char *));
85
+ if(!new) return NULL;
86
+
87
+ new->len = 0;
88
+ new->size = FFWORDS_INCREASE_STEP;
89
+ return new;
90
+}
91
+
92
+void ffwords_reset(ffwords *fw) {
93
+ if(debug) fprintf(stderr, PLUGIN_NAME ": reseting words\n");
94
+ fw->len = 0;
95
+}
96
+
97
+void ffwords_free(ffwords *fw) {
98
+ if(debug) fprintf(stderr, PLUGIN_NAME ": freeing words\n");
99
+
100
+ free(fw);
101
+}
102
+
103
+
104
+// ----------------------------------------------------------------------------
105
+// An array of lines
106
+
107
+typedef struct {
108
+ uint32_t words; // how many words this line has
109
+ uint32_t first; // the id of the first word of this line
110
+ // in the words array
111
+} ffline;
112
+
113
+typedef struct {
114
+ uint32_t len; // used entries
115
+ uint32_t size; // capacity
116
+ ffline lines[]; // array of lines
117
+} fflines;
118
+
119
+#define FFLINES_INCREASE_STEP 10
120
+
121
+fflines *fflines_add(fflines *fl, uint32_t first_word) {
122
+ if(debug) fprintf(stderr, PLUGIN_NAME ": adding line %d at word %d\n", fl->len, first_word);
123
+
124
+ if(fl->len == fl->size) {
125
+ if(debug) fprintf(stderr, PLUGIN_NAME ": expanding lines\n");
126
+
127
+ fflines *new = realloc(fl, sizeof(fflines) + (fl->size + FFLINES_INCREASE_STEP) * sizeof(ffline));
128
+ if(!new) {
129
+ fprintf(stderr, PLUGIN_NAME ": failed to expand lines\n");
130
+ free(fl);
131
+ return NULL;
132
+ }
133
+ fl = new;
134
+ fl->size += FFLINES_INCREASE_STEP;
135
+ }
136
+
137
+ fl->lines[fl->len].words = 0;
138
+ fl->lines[fl->len++].first = first_word;
139
+
140
+ return fl;
141
+}
142
+
143
+fflines *fflines_new(void) {
144
+ if(debug) fprintf(stderr, PLUGIN_NAME ": initializing lines\n");
145
+
146
+ fflines *new = malloc(sizeof(fflines) + FFLINES_INCREASE_STEP * sizeof(ffline));
147
+ if(!new) return NULL;
148
+
149
+ new->len = 0;
150
+ new->size = FFLINES_INCREASE_STEP;
151
+ return new;
152
+}
153
+
154
+void fflines_reset(fflines *fl) {
155
+ if(debug) fprintf(stderr, PLUGIN_NAME ": reseting lines\n");
156
+
157
+ fl->len = 0;
158
+}
159
+
160
+void fflines_free(fflines *fl) {
161
+ if(debug) fprintf(stderr, PLUGIN_NAME ": freeing lines\n");
162
+
163
+ free(fl);
164
+}
165
+
166
+
167
+// ----------------------------------------------------------------------------
168
+// The fastfile
169
+
170
+typedef struct {
171
+ char filename[FILENAME_MAX + 1];
172
+ int fd; // the file desriptor
173
+ ssize_t len; // the bytes we have placed into data
174
+ ssize_t size; // the bytes we have allocated for data
175
+ fflines *lines;
176
+ ffwords *words;
177
+ char separators[256];
178
+ char data[]; // allocated buffer to keep file contents
179
+} fastfile;
180
+
181
+#define FASTFILE_INITIAL_BUFFER 512
182
+#define FASTFILE_INCREMENT_BUFFER 1024
183
+
184
+#define CHAR_IS_SEPARATOR 0
185
+#define CHAR_IS_NEWLINE 1
186
+#define CHAR_IS_WORD 2
187
+
188
+void fastfile_close(fastfile *ff) {
189
+ if(debug) fprintf(stderr, PLUGIN_NAME ": Closing file '%s'. Reason: %s\n", ff->filename, strerror(errno));
190
+
191
+ if(ff->lines) fflines_free(ff->lines);
192
+ if(ff->words) ffwords_free(ff->words);
193
+
194
+ if(ff->fd != -1) close(ff->fd);
195
+ free(ff);
196
+}
197
+
198
+fastfile *fastfile_parser(fastfile *ff) {
199
+ if(debug) fprintf(stderr, PLUGIN_NAME ": Parsing file '%s'\n", ff->filename);
200
+
201
+ char *s = ff->data, *e = ff->data, *t = ff->data;
202
+ uint32_t l = 0, w = 0;
203
+ e += ff->len;
204
+
205
+ ff->lines = fflines_add(ff->lines, w);
206
+ if(!ff->lines) goto cleanup;
207
+
208
+ while(s < e) {
209
+ switch(ff->separators[(int)(*s)]) {
210
+ case CHAR_IS_SEPARATOR:
211
+ if(s == t) {
212
+ // skip all leading white spaces
213
+ t = ++s;
214
+ continue;
215
+ }
216
+
217
+ // end of word
218
+ *s = '\0';
219
+
220
+ ff->words = ffwords_add(ff->words, t);
221
+ if(!ff->words) goto cleanup;
222
+
223
+ ff->lines->lines[l].words++;
224
+ w++;
225
+
226
+ t = ++s;
227
+ continue;
228
+
229
+ case CHAR_IS_NEWLINE:
230
+ // end of line
231
+ *s = '\0';
232
+
233
+ ff->words = ffwords_add(ff->words, t);
234
+ if(!ff->words) goto cleanup;
235
+
236
+ ff->lines->lines[l].words++;
237
+ w++;
238
+
239
+ if(debug) fprintf(stderr, PLUGIN_NAME ": ended line %d with %d words\n", l, ff->lines->lines[l].words);
240
+
241
+ ff->lines = fflines_add(ff->lines, w);
242
+ if(!ff->lines) goto cleanup;
243
+ l++;
244
+
245
+ t = ++s;
246
+ continue;
247
+
248
+ default:
249
+ s++;
250
+ continue;
251
+ }
252
+ }
253
+
254
+ if(s != t) {
255
+ // the last word
256
+ if(ff->len < ff->size) *s = '\0';
257
+ else {
258
+ // we are going to loose the last byte
259
+ ff->data[ff->size - 1] = '\0';
260
+ }
261
+
262
+ ff->words = ffwords_add(ff->words, t);
263
+ if(!ff->words) goto cleanup;
264
+
265
+ ff->lines->lines[l].words++;
266
+ w++;
267
+ }
268
+
269
+ return ff;
270
+
271
+cleanup:
272
+ fprintf(stderr, PLUGIN_NAME ": Failed to parse file '%s'. Reason: %s\n", ff->filename, strerror(errno));
273
+ fastfile_close(ff);
274
+ return NULL;
275
+}
276
+
277
+fastfile *fastfile_readall(fastfile *ff) {
278
+ if(debug) fprintf(stderr, PLUGIN_NAME ": Reading file '%s'.\n", ff->filename);
279
+
280
+ ssize_t s = 0, r = ff->size, x = ff->size;
281
+ ff->len = 0;
282
+
283
+ while(r == x) {
284
+ if(s) {
285
+ if(debug) fprintf(stderr, PLUGIN_NAME ": Expanding data buffer for file '%s'.\n", ff->filename);
286
+
287
+ fastfile *new = realloc(ff, sizeof(fastfile) + ff->size + FASTFILE_INCREMENT_BUFFER);
288
+ if(!new) {
289
+ fprintf(stderr, PLUGIN_NAME ": Cannot allocate memory for file '%s'. Reason: %s\n", ff->filename, strerror(errno));
290
+ fastfile_close(ff);
291
+ return NULL;
292
+ }
293
+ ff = new;
294
+ ff->size += FASTFILE_INCREMENT_BUFFER;
295
+ x = FASTFILE_INCREMENT_BUFFER;
296
+ }
297
+
298
+ r = read(ff->fd, &ff->data[s], ff->size - s);
299
+ if(r == -1) {
300
+ fprintf(stderr, PLUGIN_NAME ": Cannot read from file '%s'. Reason: %s\n", ff->filename, strerror(errno));
301
+ fastfile_close(ff);
302
+ return NULL;
303
+ }
304
+
305
+ ff->len += r;
306
+ s = ff->len;
307
+ }
308
+
309
+ if(lseek(ff->fd, 0, SEEK_SET) == -1) {
310
+ fprintf(stderr, PLUGIN_NAME ": Cannot rewind on file '%s'.\n", ff->filename);
311
+ fastfile_close(ff);
312
+ return NULL;
313
+ }
314
+
315
+ fflines_reset(ff->lines);
316
+ ffwords_reset(ff->words);
317
+
318
+ ff = fastfile_parser(ff);
319
+
320
+ return ff;
321
+}
322
+
323
+fastfile *fastfile_open(const char *filename, const char *separators) {
324
+ if(debug) fprintf(stderr, PLUGIN_NAME ": Opening file '%s'\n", filename);
325
+
326
+ int fd = open(filename, O_RDONLY|O_NOATIME, 0666);
327
+ if(fd == -1) {
328
+ fprintf(stderr, PLUGIN_NAME ": Cannot open file '%s'. Reason: %s\n", filename, strerror(errno));
329
+ return NULL;
330
+ }
331
+
332
+ fastfile *ff = malloc(sizeof(fastfile) + FASTFILE_INITIAL_BUFFER);
333
+ if(!ff) {
334
+ fprintf(stderr, PLUGIN_NAME ": Cannot allocate memory for file '%s'. Reason: %s\n", ff->filename, strerror(errno));
335
+ close(fd);
336
+ return NULL;
337
+ }
338
+
339
+ strncpy(ff->filename, filename, FILENAME_MAX);
340
+ ff->filename[FILENAME_MAX] = '\0';
341
+
342
+ ff->fd = fd;
343
+ ff->size = FASTFILE_INITIAL_BUFFER;
344
+ ff->len = 0;
345
+
346
+ ff->lines = fflines_new();
347
+ ff->words = ffwords_new();
348
+
349
+ if(!ff->lines || !ff->words) {
350
+ fprintf(stderr, PLUGIN_NAME ": Cannot initialize parser for file '%s'. Reason: %s\n", ff->filename, strerror(errno));
351
+ fastfile_close(ff);
352
+ return NULL;
353
+ }
354
+
355
+ int i;
356
+ for(i = 0; i < 256 ;i++) {
357
+ if(i == '\n' || i == '\r') ff->separators[i] = CHAR_IS_NEWLINE;
358
+ else if(isspace(i) || !isprint(i)) ff->separators[i] = CHAR_IS_SEPARATOR;
359
+ else ff->separators[i] = CHAR_IS_WORD;
360
+ }
361
+
362
+ if(!separators) separators = " \t=|";
363
+ const char *s = separators;
364
+ while(*s) ff->separators[(int)*s++] = CHAR_IS_SEPARATOR;
365
+
366
+ return ff;
367
+}
368
+
369
+// ----------------------------------------------------------------------------
370
+/*
371
+#define NETDATA_COMMAND_GETOPTION
372
+#define NETDATA_COMMAND_CREATECHART
373
+#define NETDATA_COMMAND_VALUES
374
+
375
+typedef struct {
376
+ char magic[5];
377
+ uint16_t version;
378
+ uint32_t transaction;
379
+ uint32_t options;
380
+ uint8_t command;
381
+ uint32_t content_length;
382
+} netdata_msg_header;
383
+
384
+typedef struct {
385
+ netdata_msg_header header;
386
+ char section[NETDATA_CONFIG_SECTION_LEN + 1];
387
+ char option[NETDATA_CONFIG_OPTION_LEN + 1];
388
+ uint8_t type;
389
+ union default {
390
+ uint8_t boolean;
391
+
392
+ }
393
+} netdata_getoption;
394
+
395
+typedef struct {
396
+ netdata_header header;
397
+
398
+}
399
+*/
400
+
401
+// ----------------------------------------------------------------------------
402
+
403
+// return the number of lines present
404
+#define fastfile_lines(ff) (ff->lines->len)
405
+
406
+// return the Nth word of the file, or NULL
407
+#define fastfile_word(ff, word) (((word) < (ff)->words->len) ? (ff)->words->words[(word)] : NULL)
408
+
409
+// return the first word of the Nth line, or NULL
410
+#define fastfile_line(ff, line) (((line) < fastfile_lines(ff)) ? fastfile_word((ff), (ff)->lines->lines[(line)].first) : NULL)
411
+
412
+// return the number of words of the Nth line
413
+#define fastfile_linewords(ff, line) (((line) < fastfile_lines(ff)) ? (ff)->lines->lines[(line)].words : 0)
414
+
415
+// return the Nth word of the current line
416
+#define fastfile_lineword(ff, line, word) (((line) < fastfile_lines(ff) && (word) < fastfile_linewords(ff, (line))) ? fastfile_word((ff), (ff)->lines->lines[(line)].first + word) : NULL)
417
+
418
+// a basic processor to print the parsed file
419
+void print_processor(fastfile *ff, unsigned long long usec) {
420
+ uint32_t lines = fastfile_lines(ff), l;
421
+ uint32_t words, w;
422
+ char *s;
423
+
424
+ fprintf(stderr, PLUGIN_NAME ": File '%s' with %d lines and %d words\n", ff->filename, ff->lines->len, ff->words->len);
425
+
426
+ for(l = 0; l < lines ;l++) {
427
+ words = fastfile_linewords(ff, l);
428
+
429
+ fprintf(stderr, PLUGIN_NAME ": line %d starts at word %d and has %d words\n", l, ff->lines->lines[l].first, ff->lines->lines[l].words);
430
+
431
+ for(w = 0; w < words ;w++) {
432
+ s = fastfile_lineword(ff, l, w);
433
+ fprintf(stderr, PLUGIN_NAME ": [%d.%d] '%s'\n", l, w, s);
434
+ }
435
+ }
436
+}
437
+
438
+
439
+void proc_net_dev_processor(fastfile *ff, unsigned long long usec) {
440
+ uint32_t lines = fastfile_lines(ff), l;
441
+ uint32_t words;
442
+
443
+ for(l = 2; l < lines ;l++) {
444
+ words = fastfile_linewords(ff, l);
445
+ if(words < 17) continue;
446
+
447
+ fprintf(stdout, "BEGIN net.%s %llu\n", fastfile_lineword(ff, l, 0), usec);
448
+ fprintf(stdout, "SET received = %s\n", fastfile_lineword(ff, l, 1));
449
+ fprintf(stdout, "SET sent = %s\n", fastfile_lineword(ff, l, 9));
450
+ fprintf(stdout, "END\n");
451
+
452
+ fprintf(stdout, "BEGIN net_packets.%s %llu\n", fastfile_lineword(ff, l, 0), usec);
453
+ fprintf(stdout, "SET received = %s\n", fastfile_lineword(ff, l, 2));
454
+ fprintf(stdout, "SET sent = %s\n", fastfile_lineword(ff, l, 10));
455
+ fprintf(stdout, "END\n");
456
+
457
+ fprintf(stdout, "BEGIN net_errors.%s %llu\n", fastfile_lineword(ff, l, 0), usec);
458
+ fprintf(stdout, "SET received = %s\n", fastfile_lineword(ff, l, 3));
459
+ fprintf(stdout, "SET sent = %s\n", fastfile_lineword(ff, l, 11));
460
+ fprintf(stdout, "END\n");
461
+
462
+ fprintf(stdout, "BEGIN net_drops.%s %llu\n", fastfile_lineword(ff, l, 0), usec);
463
+ fprintf(stdout, "SET received = %s\n", fastfile_lineword(ff, l, 4));
464
+ fprintf(stdout, "SET sent = %s\n", fastfile_lineword(ff, l, 12));
465
+ fprintf(stdout, "END\n");
466
+
467
+ fprintf(stdout, "BEGIN net_fifo.%s %llu\n", fastfile_lineword(ff, l, 0), usec);
468
+ fprintf(stdout, "SET received = %s\n", fastfile_lineword(ff, l, 5));
469
+ fprintf(stdout, "SET sent = %s\n", fastfile_lineword(ff, l, 13));
470
+ fprintf(stdout, "END\n");
471
+
472
+ fprintf(stdout, "BEGIN net_compressed.%s %llu\n", fastfile_lineword(ff, l, 0), usec);
473
+ fprintf(stdout, "SET received = %s\n", fastfile_lineword(ff, l, 7));
474
+ fprintf(stdout, "SET sent = %s\n", fastfile_lineword(ff, l, 16));
475
+ fprintf(stdout, "END\n");
476
+
477
+ fprintf(stdout, "BEGIN net_other.%s %llu\n", fastfile_lineword(ff, l, 0), usec);
478
+ fprintf(stdout, "SET frames = %s\n", fastfile_lineword(ff, l, 6));
479
+ fprintf(stdout, "SET multicast = %s\n", fastfile_lineword(ff, l, 8));
480
+ fprintf(stdout, "SET collisions = %s\n", fastfile_lineword(ff, l, 14));
481
+ fprintf(stdout, "SET carrier = %s\n", fastfile_lineword(ff, l, 15));
482
+ fprintf(stdout, "END\n");
483
+ }
484
+}
485
+
486
+
487
+// ----------------------------------------------------------------------------
488
+
489
+
490
+
491
+typedef struct {
492
+ const char filename[FILENAME_MAX + 1];
493
+ const char separators[256];
494
+ void (*processor)(fastfile *, unsigned long long);
495
+ fastfile *ff;
496
+ int enabled;
497
+} proc_files;
498
+
499
+proc_files files[] = {
500
+ { "/proc/net/dev", " \t,:|", proc_net_dev_processor, NULL, 1 },
501
+ { "/proc/diskstats", " \t,:|", print_processor, NULL, 1 },
502
+ { "/proc/net/snmp", " \t,:|", print_processor, NULL, 1 },
503
+ { "/proc/net/netstat", " \t,:|", print_processor, NULL, 1 },
504
+ { "/proc/net/stat/nf_conntrack", " \t,:|", print_processor, NULL, 1 },
505
+ { "/proc/net/ip_vs_stats", " \t,:|", print_processor, NULL, 1 },
506
+ { "/proc/stat", " \t,:|", print_processor, NULL, 1 },
507
+ { "/proc/meminfo", " \t,:|", print_processor, NULL, 1 },
508
+ { "/proc/vmstat", " \t,:|", print_processor, NULL, 1 },
509
+ { "/proc/self/mountstats", " \t", print_processor, NULL, 1 },
510
+ { "/sys/class/thermal/thermal_zone0/temp", "", print_processor, NULL, 1 },
511
+ { "/sys/devices/system/cpu/cpu3/cpufreq/cpuinfo_cur_freq", "", print_processor, NULL, 1 },
512
+ { "", "", NULL, NULL, 0 },
513
+};
514
+
515
+void do_proc_files() {
516
+ int i;
517
+
518
+ unsigned long started_t = time(NULL), current_t;
519
+ unsigned long long usec = 0, susec = 0;
520
+ struct timeval last, now;
521
+ gettimeofday(&last, NULL);
522
+
523
+ while(1) {
524
+ gettimeofday(&now, NULL);
525
+ usec = usecdiff(&now, &last) - susec;
526
+
527
+ for(i = 0; files[i].filename[0] ;i++) {
528
+ if(!files[i].enabled) continue;
529
+
530
+ if(debug) fprintf(stderr, PLUGIN_NAME ": File '%s'\n", files[i].filename);
531
+
532
+ if(!files[i].ff) {
533
+ files[i].ff = fastfile_open(files[i].filename, files[i].separators);
534
+ if(!files[i].ff) {
535
+ files[i].enabled = 0;
536
+ continue;
537
+ }
538
+ }
539
+
540
+ if(files[i].ff) files[i].ff = fastfile_readall(files[i].ff);
541
+ if(files[i].ff) files[i].processor(files[i].ff, usec + susec);
542
+ }
543
+
544
+ fprintf(stderr, PLUGIN_NAME ": Last loop took %llu usec (worked for %llu, sleeped for %llu).\n", usec + susec, usec, susec);
545
+ if(debug) {
546
+ exit(1);
547
+ }
548
+
549
+ // if the last loop took less than half the time
550
+ // wait the rest of the time
551
+ if(usec < (update_every * 1000000ULL / 2)) susec = (update_every * 1000000ULL) - usec;
552
+ else susec = update_every * 1000000ULL / 2;
553
+
554
+ usleep(susec);
555
+ bcopy(&now, &last, sizeof(struct timeval));
556
+
557
+ current_t = time(NULL);
558
+ if(current_t - started_t > 3600) exit(0);
559
+ }
560
+}
561
+
562
+// ----------------------------------------------------------------------------
563
+// parse command line arguments
564
+
565
+void parse_args(int argc, char **argv)
566
+{
567
+ int i, freq = 0;
568
+
569
+ for(i = 1; i < argc; i++) {
570
+ if(!freq) {
571
+ int n = atoi(argv[i]);
572
+ if(n > 0) {
573
+ freq = n;
574
+ continue;
575
+ }
576
+ }
577
+
578
+ if(strcmp("debug", argv[i]) == 0) {
579
+ debug = 1;
580
+ continue;
581
+ }
582
+
583
+ fprintf(stderr, PLUGIN_NAME ": ERROR: cannot understand option %s\n", argv[i]);
584
+ exit(1);
585
+ }
586
+
587
+ if(freq > 0) update_every = freq;
588
+}
589
+
590
+int main(int argc, char **argv)
591
+{
592
+ parse_args(argc, argv);
593
+
594
+ // show_charts();
595
+ do_proc_files();
596
+ return 0;
597
+}