@cryptotaxi247 / netdata-1 / commits / c55bc3e50

code cleanup

Costa Tsaousis (ktsaou) committed Nov 22, 2015 at 14:16 UTC c55bc3e5029e74a8dc99bd95faee5eceb2021081
6 files changed +195 -153
README.md
+3 -1
@@ -17,7 +17,9 @@ Check it live at:
17
18 Here is a screenshot:
19
20 -![image](https://cloud.githubusercontent.com/assets/2662304/10440038/b40bcb6c-7146-11e5-93ac-db2e177e39f8.png)
20 +![image](https://cloud.githubusercontent.com/assets/2662304/11323720/0ea2a5f4-9123-11e5-9c30-d57072b8e12c.png)
21 +
22 +![image](https://cloud.githubusercontent.com/assets/2662304/11323728/3cb6e810-9123-11e5-97b3-662fd6f35725.png)
23
24
25 # Features
src/appconfig.c
+7 -12
@@ -359,10 +359,9 @@ void generate_config(struct web_buffer *wb, int only_changed)
359 struct config_value *cv;
360
361 for(i = 0; i < 3 ;i++) {
362 - web_buffer_increase(wb, 500);
362 switch(i) {
363 case 0:
365 - web_buffer_printf(wb,
364 + web_buffer_strcat(wb,
365 "# NetData Configuration\n"
366 "# You can uncomment and change any of the options below.\n"
367 "# The value shown in the commented settings, is the default value.\n"
@@ -370,11 +369,11 @@ void generate_config(struct web_buffer *wb, int only_changed)
369 break;
370
371 case 1:
373 - web_buffer_printf(wb, "\n\n# per plugin configuration\n");
372 + web_buffer_strcat(wb, "\n\n# per plugin configuration\n");
373 break;
374
375 case 2:
377 - web_buffer_printf(wb, "\n\n# per chart configuration\n");
376 + web_buffer_strcat(wb, "\n\n# per chart configuration\n");
377 break;
378 }
379
@@ -397,21 +396,17 @@ void generate_config(struct web_buffer *wb, int only_changed)
396 if(only_changed && !changed) continue;
397
398 if(!used) {
400 - web_buffer_increase(wb, 500);
401 - web_buffer_printf(wb, "\n# node '%s' is not used.", co->name);
399 + web_buffer_snprintf(wb, CONFIG_FILE_LINE_MAX+1, "\n# node '%s' is not used.", co->name);
400 }
401
404 - web_buffer_increase(wb, CONFIG_FILE_LINE_MAX+1);
405 - web_buffer_printf(wb, "\n[%s]\n", co->name);
402 + web_buffer_snprintf(wb, CONFIG_FILE_LINE_MAX+1, "\n[%s]\n", co->name);
403
404 for(cv = co->values; cv ; cv = cv->next) {
405
406 if(used && !(cv->flags & CONFIG_VALUE_USED)) {
410 - web_buffer_increase(wb, CONFIG_FILE_LINE_MAX + 1);
411 - web_buffer_printf(wb, "\n\t# option '%s' is not used.\n", cv->name);
407 + web_buffer_snprintf(wb, CONFIG_FILE_LINE_MAX + 1, "\n\t# option '%s' is not used.\n", cv->name);
408 }
413 - web_buffer_increase(wb, CONFIG_FILE_LINE_MAX + 1);
414 - web_buffer_printf(wb, "\t%s%s = %s\n", ((!(cv->flags & CONFIG_VALUE_CHANGED)) && (cv->flags & CONFIG_VALUE_USED))?"# ":"", cv->name, cv->value);
409 + web_buffer_snprintf(wb, CONFIG_FILE_LINE_MAX + 1, "\t%s%s = %s\n", ((!(cv->flags & CONFIG_VALUE_CHANGED)) && (cv->flags & CONFIG_VALUE_USED))?"# ":"", cv->name, cv->value);
410 }
411 }
412 }
src/rrd2json.c
+35 -43
@@ -15,11 +15,10 @@ char *hostname = "unknown";
15 unsigned long rrd_stats_one_json(RRDSET *st, char *options, struct web_buffer *wb)
16 {
17 time_t now = time(NULL);
18 - web_buffer_increase(wb, 65536);
18
19 pthread_rwlock_rdlock(&st->rwlock);
20
22 - web_buffer_printf(wb,
21 + web_buffer_snprintf(wb, 65536,
22 "\t\t{\n"
23 "\t\t\t\"id\": \"%s\",\n"
24 "\t\t\t\"name\": \"%s\",\n"
@@ -70,11 +69,10 @@ unsigned long rrd_stats_one_json(RRDSET *st, char *options, struct web_buffer *w
69
70 RRDDIM *rd;
71 for(rd = st->dimensions; rd ; rd = rd->next) {
73 - web_buffer_increase(wb, 4096);
72
73 memory += rd->memsize;
74
77 - web_buffer_printf(wb,
75 + web_buffer_snprintf(wb, 4096,
76 "\t\t\t\t{\n"
77 "\t\t\t\t\t\"id\": \"%s\",\n"
78 "\t\t\t\t\t\"name\": \"%s\",\n"
@@ -107,7 +105,7 @@ unsigned long rrd_stats_one_json(RRDSET *st, char *options, struct web_buffer *w
105 );
106 }
107
110 - web_buffer_printf(wb,
108 + web_buffer_snprintf(wb, 200,
109 "\t\t\t],\n"
110 "\t\t\t\"memory\" : %lu\n"
111 "\t\t}"
@@ -123,34 +121,30 @@ unsigned long rrd_stats_one_json(RRDSET *st, char *options, struct web_buffer *w
121
122 void rrd_stats_graph_json(RRDSET *st, char *options, struct web_buffer *wb)
123 {
126 - web_buffer_increase(wb, 2048);
127 -
128 - web_buffer_printf(wb, RRD_GRAPH_JSON_HEADER);
124 + web_buffer_snprintf(wb, sizeof(RRD_GRAPH_JSON_HEADER), RRD_GRAPH_JSON_HEADER);
125 rrd_stats_one_json(st, options, wb);
130 - web_buffer_printf(wb, RRD_GRAPH_JSON_FOOTER);
126 + web_buffer_snprintf(wb, sizeof(RRD_GRAPH_JSON_FOOTER), RRD_GRAPH_JSON_FOOTER);
127 }
128
129 void rrd_stats_all_json(struct web_buffer *wb)
130 {
135 - web_buffer_increase(wb, 2048);
136 -
131 unsigned long memory = 0;
132 long c;
133 RRDSET *st;
134
141 - web_buffer_printf(wb, RRD_GRAPH_JSON_HEADER);
135 + web_buffer_snprintf(wb, sizeof(RRD_GRAPH_JSON_HEADER), RRD_GRAPH_JSON_HEADER);
136
137 pthread_rwlock_rdlock(&rrdset_root_rwlock);
138 for(st = rrdset_root, c = 0; st ; st = st->next) {
139 if(st->enabled) {
146 - if(c) web_buffer_printf(wb, "%s", ",\n");
140 + if(c) web_buffer_strcat(wb, ",\n");
141 memory += rrd_stats_one_json(st, NULL, wb);
142 c++;
143 }
144 }
145 pthread_rwlock_unlock(&rrdset_root_rwlock);
146
153 - web_buffer_printf(wb, "\n\t],\n"
147 + web_buffer_snprintf(wb, 4096, "\n\t],\n"
148 "\t\"hostname\": \"%s\",\n"
149 "\t\"update_every\": %d,\n"
150 "\t\"history\": %d,\n"
@@ -379,7 +373,8 @@ RRDR *rrd2rrdr(RRDSET *st, long points, time_t after, time_t before, int group_m
373 if(duration <= 0) return NULL;
374
375 // check the required points
382 - if(points <= 0) points = duration;
376 + if(points > duration / st->update_every) points = 0;
377 + if(points <= 0) points = duration / st->update_every;
378
379 // calculate proper grouping of source data
380 long group = duration / points;
@@ -622,7 +617,7 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
617 for( rd = st->dimensions ; rd ; rd = rd->next) dimensions++;
618 if(!dimensions) {
619 pthread_rwlock_unlock(&st->rwlock);
625 - web_buffer_printf(wb, "No dimensions yet.");
620 + web_buffer_strcat(wb, "No dimensions yet.");
621 return 0;
622 }
623
@@ -694,10 +689,10 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
689 // -------------------------------------------------------------------------
690 // print the JSON header
691
697 - web_buffer_printf(wb, "{\n %scols%s:\n [\n", kq, kq);
698 - web_buffer_printf(wb, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
699 - web_buffer_printf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
700 - web_buffer_printf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
692 + web_buffer_snprintf(wb, 1024, "{\n %scols%s:\n [\n", kq, kq);
693 + web_buffer_snprintf(wb, 1024, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
694 + web_buffer_snprintf(wb, 1024, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
695 + web_buffer_snprintf(wb, 1024, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
696
697 // print the header for each dimension
698 // and update the print_hidden array for the dimensions that should be hidden
@@ -705,15 +700,15 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
700 for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
701 if(!print_hidden[c]) {
702 pc++;
708 - web_buffer_printf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, rd->name, sq, kq, kq, sq, sq, kq, kq, sq, sq);
703 + web_buffer_snprintf(wb, 1024, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, rd->name, sq, kq, kq, sq, sq, kq, kq, sq, sq);
704 }
705 }
706 if(!pc) {
712 - web_buffer_printf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, "no data", sq, kq, kq, sq, sq, kq, kq, sq, sq);
707 + web_buffer_snprintf(wb, 1024, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, "no data", sq, kq, kq, sq, sq, kq, kq, sq, sq);
708 }
709
710 // print the begin of row data
716 - web_buffer_printf(wb, "\n ],\n %srows%s:\n [\n", kq, kq);
711 + web_buffer_snprintf(wb, 1024, "\n ],\n %srows%s:\n [\n", kq, kq);
712
713
714 // -------------------------------------------------------------------------
@@ -785,18 +780,15 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
780 break;
781 }
782
788 - // check if we may exceed the buffer provided
789 - web_buffer_increase(wb, line_size);
790 -
783 // generate the local date time
784 struct tm *tm = localtime(&now);
785 if(!tm) { error("localtime() failed."); continue; }
786 if(now > last_timestamp) last_timestamp = now;
787
796 - if(printed) web_buffer_strcpy(wb, "]},\n");
797 - web_buffer_strcpy(wb, pre_date);
788 + if(printed) web_buffer_strcat(wb, "]},\n");
789 + web_buffer_strcat(wb, pre_date);
790 web_buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
799 - web_buffer_strcpy(wb, post_date);
791 + web_buffer_strcat(wb, post_date);
792
793 print_this = 1;
794 }
@@ -832,26 +824,26 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
824 if(print_this) {
825 if(annotate_reset) {
826 annotation_count++;
835 - web_buffer_strcpy(wb, overflow_annotation);
827 + web_buffer_strcat(wb, overflow_annotation);
828 annotate_reset = 0;
829 }
830 else
839 - web_buffer_strcpy(wb, normal_annotation);
831 + web_buffer_strcat(wb, normal_annotation);
832
833 pc = 0;
834 for(c = 0 ; c < dimensions ; c++) {
835 if(found_non_existing[c] == group_count) {
836 // all entries are non-existing
837 pc++;
846 - web_buffer_strcpy(wb, pre_value);
847 - web_buffer_strcpy(wb, "null");
848 - web_buffer_strcpy(wb, post_value);
838 + web_buffer_strcat(wb, pre_value);
839 + web_buffer_strcat(wb, "null");
840 + web_buffer_strcat(wb, post_value);
841 }
842 else if(!print_hidden[c]) {
843 pc++;
852 - web_buffer_strcpy(wb, pre_value);
844 + web_buffer_strcat(wb, pre_value);
845 web_buffer_rrd_value(wb, group_values[c]);
854 - web_buffer_strcpy(wb, post_value);
846 + web_buffer_strcat(wb, post_value);
847
848 if(group_values[c]) found_non_zero[c]++;
849 }
@@ -863,9 +855,9 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
855
856 // if all dimensions are hidden, print a null
857 if(!pc) {
866 - web_buffer_strcpy(wb, pre_value);
867 - web_buffer_strcpy(wb, "null");
868 - web_buffer_strcpy(wb, post_value);
858 + web_buffer_strcat(wb, pre_value);
859 + web_buffer_strcat(wb, "null");
860 + web_buffer_strcat(wb, post_value);
861 }
862
863 printed++;
@@ -873,8 +865,8 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
865 }
866 }
867
876 - if(printed) web_buffer_printf(wb, "]}");
877 - web_buffer_printf(wb, "\n ]\n}\n");
868 + if(printed) web_buffer_strcat(wb, "]}");
869 + web_buffer_strcat(wb, "\n ]\n}\n");
870
871 if(only_non_zero && max_loop > 1) {
872 int changed = 0;
@@ -888,14 +880,14 @@ unsigned long rrd_stats_json(int type, RRDSET *st, struct web_buffer *wb, int po
880 }
881 }
882
891 - if(changed) web_buffer_reset(wb);
883 + if(changed) web_buffer_flush(wb);
884 else break;
885 }
886 else break;
887
888 } // max_loop
889
898 - debug(D_RRD_STATS, "RRD_STATS_JSON: %s total %ld bytes", st->name, wb->bytes);
890 + debug(D_RRD_STATS, "RRD_STATS_JSON: %s total %ld bytes", st->name, wb->len);
891
892 pthread_rwlock_unlock(&st->rwlock);
893 return last_timestamp;
src/web_buffer.c
+68 -11
@@ -2,6 +2,7 @@
2 #include <config.h>
3 #endif
4 #include <stdlib.h>
5 +#include <string.h>
6
7 #ifdef STORAGE_WITH_MATH
8 #include <math.h>
@@ -11,21 +12,72 @@
12 #include "web_buffer.h"
13 #include "log.h"
14
14 -void web_buffer_strcpy(struct web_buffer *wb, const char *txt)
15 +void web_buffer_reset(struct web_buffer *wb)
16 +{
17 + web_buffer_flush(wb);
18 +
19 + wb->sent = 0;
20 + wb->rlen = 0;
21 + wb->contenttype = CT_TEXT_PLAIN;
22 + wb->date = 0;
23 +}
24 +
25 +void web_buffer_char_replace(struct web_buffer *wb, char from, char to)
26 +{
27 + char *s = wb->buffer, *end = &wb->buffer[wb->len];
28 +
29 + while(s != end) {
30 + if(*s == from) *s = to;
31 + s++;
32 + }
33 +}
34 +
35 +
36 +void web_buffer_strcat(struct web_buffer *wb, const char *txt)
37 {
38 char *buffer = wb->buffer;
17 - long bytes = wb->bytes, size = wb->size, i = 0;
39 + const char *s = txt;
40 + long bytes = wb->len, size = wb->size;
41 +
42 + while(*s && bytes < size)
43 + buffer[bytes++] = *s++;
44
19 - while(txt[i] && bytes < size)
20 - buffer[bytes++] = txt[i++];
45 + wb->len = bytes;
46
22 - wb->bytes = bytes;
47 + if(*s) {
48 + web_buffer_need_bytes(wb, strlen(s));
49 + web_buffer_strcat(wb, s);
50 + }
51 + else {
52 + // terminate the string
53 + // without increasing the length
54 + web_buffer_need_bytes(wb, 1);
55 + wb->buffer[wb->len] = '\0';
56 + }
57 }
58
59 +
60 +void web_buffer_snprintf(struct web_buffer *wb, size_t len, const char *fmt, ...)
61 +{
62 + web_buffer_need_bytes(wb, len+1);
63 +
64 + va_list args;
65 + va_start(args, fmt);
66 + wb->len += vsnprintf(&wb->buffer[wb->len], len+1, fmt, args);
67 + va_end(args);
68 +
69 + // the buffer is \0 terminated by vsnprintf
70 +}
71 +
72 +
73 void web_buffer_rrd_value(struct web_buffer *wb, calculated_number value)
74 {
27 - if(wb->size - wb->bytes < 50) return;
28 - wb->bytes += print_calculated_number(&wb->buffer[wb->bytes], value);
75 + web_buffer_need_bytes(wb, 50);
76 + wb->len += print_calculated_number(&wb->buffer[wb->len], value);
77 +
78 + // terminate it
79 + web_buffer_need_bytes(wb, 1);
80 + wb->buffer[wb->len] = '\0';
81 }
82
83 // generate a javascript date, the fastest possible way...
@@ -35,9 +87,9 @@ void web_buffer_jsdate(struct web_buffer *wb, int year, int month, int day, int
87 // 01234567890123456789012345678901234
88 // Date(2014, 04, 01, 03, 28, 20, 065)
89
38 - if(wb->size - wb->bytes < 36) return;
90 + web_buffer_need_bytes(wb, 36);
91
40 - char *b = &wb->buffer[wb->bytes];
92 + char *b = &wb->buffer[wb->len];
93
94 int i = 0;
95 b[i++]='D';
@@ -72,7 +124,11 @@ void web_buffer_jsdate(struct web_buffer *wb, int year, int month, int day, int
124 b[i++]=')';
125 b[i]='\0';
126
75 - wb->bytes += i;
127 + wb->len += i;
128 +
129 + // terminate it
130 + web_buffer_need_bytes(wb, 1);
131 + wb->buffer[wb->len] = '\0';
132 }
133
134 struct web_buffer *web_buffer_create(long size)
@@ -109,9 +165,10 @@ void web_buffer_free(struct web_buffer *b)
165
166 void web_buffer_increase(struct web_buffer *b, long free_size_required)
167 {
112 - long left = b->size - b->bytes;
168 + long left = b->size - b->len;
169
170 if(left >= free_size_required) return;
171 +
172 long increase = free_size_required - left;
173 if(increase < WEB_DATA_LENGTH_INCREASE_STEP) increase = WEB_DATA_LENGTH_INCREASE_STEP;
174
src/web_buffer.h
+11 -5
@@ -9,11 +9,11 @@
9
10 struct web_buffer {
11 long size; // allocation size of buffer
12 - long bytes; // current data length in buffer
12 + long len; // current data length in buffer
13 long sent; // current data length sent to output
14 char *buffer; // the buffer
15 int contenttype;
16 - long rbytes; // if non-zero, the excepted size of ifd
16 + long rlen; // if non-zero, the excepted size of ifd
17 time_t date; // the date this content has been generated
18 };
19
@@ -33,10 +33,12 @@ struct web_buffer {
33 #define CT_APPLICATION_VND_MS_FONTOBJ 13
34 #define CT_IMAGE_SVG_XML 14
35
36 -#define web_buffer_printf(wb, args...) wb->bytes += snprintf(&wb->buffer[wb->bytes], (wb->size - wb->bytes), ##args)
37 -#define web_buffer_reset(wb) wb->buffer[wb->bytes = 0] = '\0'
36 +#define web_buffer_need_bytes(buffer, needed_free_size) do { if(unlikely((buffer)->size - (buffer)->len < (needed_free_size))) web_buffer_increase((buffer), (needed_free_size)); } while(0)
37
39 -void web_buffer_strcpy(struct web_buffer *wb, const char *txt);
38 +#define web_buffer_flush(wb) wb->buffer[wb->len = 0] = '\0'
39 +void web_buffer_reset(struct web_buffer *wb);
40 +
41 +void web_buffer_strcat(struct web_buffer *wb, const char *txt);
42 void web_buffer_rrd_value(struct web_buffer *wb, calculated_number value);
43
44 void web_buffer_jsdate(struct web_buffer *wb, int year, int month, int day, int hours, int minutes, int seconds);
@@ -45,4 +47,8 @@ struct web_buffer *web_buffer_create(long size);
47 void web_buffer_free(struct web_buffer *b);
48 void web_buffer_increase(struct web_buffer *b, long free_size_required);
49
50 +void web_buffer_snprintf(struct web_buffer *wb, size_t len, const char *fmt, ...);
51 +
52 +void web_buffer_char_replace(struct web_buffer *wb, char from, char to);
53 +
54 #endif /* NETDATA_WEB_BUFFER_H */
src/web_client.c
+71 -81
@@ -152,7 +152,7 @@ int mysendfile(struct web_client *w, char *filename)
152 // if the filename contains a / or a .., refuse to serve it
153 if(strchr(filename, '/') != 0 || strstr(filename, "..") != 0) {
154 debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename);
155 - web_buffer_printf(w->data, "File '%s' cannot be served. Filenames cannot contain / or ..", filename);
155 + web_buffer_snprintf(w->data, FILENAME_MAX + 1024, "File '%s' cannot be served. Filenames cannot contain / or ..", filename);
156 return 400;
157 }
158
@@ -164,14 +164,14 @@ int mysendfile(struct web_client *w, char *filename)
164 struct stat stat;
165 if(lstat(webfilename, &stat) != 0) {
166 error("%llu: File '%s' is not found.", w->id, webfilename);
167 - web_buffer_printf(w->data, "File '%s' does not exist, or is not accessible.", filename);
167 + web_buffer_snprintf(w->data, FILENAME_MAX + 1024, "File '%s' does not exist, or is not accessible.", filename);
168 return 404;
169 }
170
171 // check if the file is owned by us
172 if(stat.st_uid != getuid() && stat.st_uid != geteuid()) {
173 error("%llu: File '%s' is owned by user %d (I run as user %d). Access Denied.", w->id, webfilename, stat.st_uid, getuid());
174 - web_buffer_printf(w->data, "Access to file '%s' is not permitted.", filename);
174 + web_buffer_snprintf(w->data, FILENAME_MAX + 1024, "Access to file '%s' is not permitted.", filename);
175 return 403;
176 }
177
@@ -183,12 +183,12 @@ int mysendfile(struct web_client *w, char *filename)
183 if(errno == EBUSY || errno == EAGAIN) {
184 error("%llu: File '%s' is busy, sending 307 Moved Temporarily to force retry.", w->id, webfilename);
185 snprintf(w->response_header, MAX_HTTP_HEADER_SIZE, "Location: /" WEB_PATH_FILE "/%s\r\n", filename);
186 - web_buffer_printf(w->data, "The file '%s' is currently busy. Please try again later.", filename);
186 + web_buffer_snprintf(w->data, FILENAME_MAX + 1024, "The file '%s' is currently busy. Please try again later.", filename);
187 return 307;
188 }
189 else {
190 error("%llu: Cannot open file '%s'.", w->id, webfilename);
191 - web_buffer_printf(w->data, "Cannot open file '%s'.", filename);
191 + web_buffer_snprintf(w->data, FILENAME_MAX + 1024, "Cannot open file '%s'.", filename);
192 return 404;
193 }
194 }
@@ -212,9 +212,8 @@ int mysendfile(struct web_client *w, char *filename)
212 w->mode = WEB_CLIENT_MODE_FILECOPY;
213 w->wait_receive = 1;
214 w->wait_send = 0;
215 - w->data->bytes = 0;
216 - w->data->buffer[0] = '\0';
217 - w->data->rbytes = stat.st_size;
215 + web_buffer_flush(w->data);
216 + w->data->rlen = stat.st_size;
217 w->data->date = stat.st_mtim.tv_sec;
218
219 return 200;
@@ -225,13 +224,13 @@ void web_client_reset(struct web_client *w)
224 struct timeval tv;
225 gettimeofday(&tv, NULL);
226
228 - long sent = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->data->rbytes:w->data->bytes;
227 + long sent = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->data->rlen:w->data->len;
228
229 #ifdef NETDATA_WITH_ZLIB
230 if(likely(w->zoutput)) sent = (long)w->zstream.total_out;
231 #endif
232
234 - long size = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->data->rbytes:w->data->bytes;
233 + long size = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->data->rlen:w->data->len;
234
235 if(likely(w->last_url[0]))
236 log_access("%llu: (sent/all = %ld/%ld bytes %0.0f%%, prep/sent/total = %0.2f/%0.2f/%0.2f ms) %s: '%s'",
@@ -254,15 +253,11 @@ void web_client_reset(struct web_client *w)
253
254 w->last_url[0] = '\0';
255
257 - w->data->contenttype = CT_TEXT_PLAIN;
256 w->mode = WEB_CLIENT_MODE_NORMAL;
257
260 - w->data->rbytes = 0;
261 - w->data->bytes = 0;
262 - w->data->sent = 0;
263 -
258 w->response_header[0] = '\0';
265 - w->data->buffer[0] = '\0';
259 +
260 + web_buffer_reset(w->data);
261
262 w->wait_receive = 1;
263 w->wait_send = 0;
@@ -350,7 +345,7 @@ int web_client_data_request(struct web_client *w, char *url, int datasource_type
345 if(!st) {
346 // we don't have it
347 // try to send a file with that name
353 - w->data->bytes = 0;
348 + web_buffer_flush(w->data);
349 return(mysendfile(w, tok));
350 }
351
@@ -404,7 +399,7 @@ int web_client_data_request(struct web_client *w, char *url, int datasource_type
399 }
400
401 w->data->contenttype = CT_APPLICATION_JSON;
407 - w->data->bytes = 0;
402 + web_buffer_flush(w->data);
403
404 char *google_version = "0.6";
405 char *google_reqId = "0";
@@ -456,7 +451,7 @@ int web_client_data_request(struct web_client *w, char *url, int datasource_type
451
452 // check the client wants json
453 if(strcmp(google_out, "json") != 0) {
459 - w->data->bytes = snprintf(w->data->buffer, w->data->size,
454 + web_buffer_snprintf(w->data, 65536,
455 "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'invalid_query',message:'output format is not supported',detailed_message:'the format %s requested is not supported by netdata.'}]});",
456 google_responseHandler, google_version, google_reqId, google_out);
457 return 200;
@@ -465,7 +460,7 @@ int web_client_data_request(struct web_client *w, char *url, int datasource_type
460 }
461
462 if(datasource_type == DATASOURCE_GOOGLE_JSONP) {
468 - w->data->bytes = snprintf(w->data->buffer, w->data->size,
463 + web_buffer_snprintf(w->data, 65536,
464 "%s({version:'%s',reqId:'%s',status:'ok',sig:'%lu',table:",
465 google_responseHandler, google_version, google_reqId, st->last_updated.tv_sec);
466 }
@@ -475,11 +470,11 @@ int web_client_data_request(struct web_client *w, char *url, int datasource_type
470
471 if(datasource_type == DATASOURCE_GOOGLE_JSONP) {
472 if(timestamp_in_data > last_timestamp_in_data)
478 - w->data->bytes += snprintf(&w->data->buffer[w->data->bytes], w->data->size - w->data->bytes, "});");
473 + web_buffer_strcat(w->data, "});");
474
475 else {
476 // the client already has the latest data
482 - w->data->bytes = snprintf(w->data->buffer, w->data->size,
477 + web_buffer_snprintf(w->data, 65536,
478 "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});",
479 google_responseHandler, google_version, google_reqId);
480 }
@@ -549,7 +544,7 @@ void web_client_process(struct web_client *w) {
544 global_statistics_unlock();
545
546 gettimeofday(&w->tv_in, NULL);
552 - debug(D_WEB_DATA, "%llu: Processing data buffer of %d bytes: '%s'.", w->id, w->data->bytes, w->data->buffer);
547 + debug(D_WEB_DATA, "%llu: Processing data buffer of %d bytes: '%s'.", w->id, w->data->len, w->data->buffer);
548
549 // check if the client requested keep-alive HTTP
550 if(strcasestr(w->data->buffer, "Connection: keep-alive")) w->keepalive = 1;
@@ -614,19 +609,19 @@ void web_client_process(struct web_client *w) {
609 if(!st) {
610 // we don't have it
611 // try to send a file with that name
617 - w->data->bytes = 0;
612 + web_buffer_flush(w->data);
613 code = mysendfile(w, tok);
614 }
615 else {
616 code = 200;
617 debug(D_WEB_CLIENT_ACCESS, "%llu: Sending %s.json of RRD_STATS...", w->id, st->name);
618 w->data->contenttype = CT_APPLICATION_JSON;
624 - w->data->bytes = 0;
619 + web_buffer_flush(w->data);
620 rrd_stats_graph_json(st, url, w->data);
621 }
622 }
623 else if(strcmp(tok, "debug") == 0) {
629 - w->data->bytes = 0;
624 + web_buffer_flush(w->data);
625
626 // get the name of the data to show
627 tok = mystrsep(&url, "/?&");
@@ -637,14 +632,14 @@ void web_client_process(struct web_client *w) {
632 if(!st) st = rrdset_find(tok);
633 if(!st) {
634 code = 404;
640 - web_buffer_printf(w->data, "Chart %s is not found.\r\n", tok);
635 + web_buffer_snprintf(w->data, 1024, "Chart %s is not found.\r\n", tok);
636 debug(D_WEB_CLIENT_ACCESS, "%llu: %s is not found.", w->id, tok);
637 }
638 else {
639 code = 200;
640 debug_flags |= D_RRD_STATS;
641 st->debug = st->debug?0:1;
647 - web_buffer_printf(w->data, "Chart %s has now debug %s.\r\n", tok, st->debug?"enabled":"disabled");
642 + web_buffer_snprintf(w->data, 1024, "Chart %s has now debug %s.\r\n", tok, st->debug?"enabled":"disabled");
643 debug(D_WEB_CLIENT_ACCESS, "%llu: debug for %s is %s.", w->id, tok, st->debug?"enabled":"disabled");
644 }
645 }
@@ -654,9 +649,7 @@ void web_client_process(struct web_client *w) {
649 debug(D_WEB_CLIENT_ACCESS, "%llu: Mirroring...", w->id);
650
651 // replace the zero bytes with spaces
657 - int i;
658 - for(i = 0; i < w->data->size; i++)
659 - if(w->data->buffer[i] == '\0') w->data->buffer[i] = ' ';
652 + web_buffer_char_replace(w->data, '\0', ' ');
653
654 // just leave the buffer as is
655 // it will be copied back to the client
@@ -666,18 +659,18 @@ void web_client_process(struct web_client *w) {
659
660 debug(D_WEB_CLIENT_ACCESS, "%llu: Sending list of RRD_STATS...", w->id);
661
669 - w->data->bytes = 0;
662 + web_buffer_flush(w->data);
663 RRDSET *st = rrdset_root;
664
665 for ( ; st ; st = st->next )
673 - web_buffer_printf(w->data, "%s\n", st->name);
666 + web_buffer_snprintf(w->data, 1024, "%s\n", st->name);
667 }
668 else if(strcmp(tok, "all.json") == 0) {
669 code = 200;
670 debug(D_WEB_CLIENT_ACCESS, "%llu: Sending JSON list of all monitors of RRD_STATS...", w->id);
671
672 w->data->contenttype = CT_APPLICATION_JSON;
680 - w->data->bytes = 0;
673 + web_buffer_flush(w->data);
674 rrd_stats_all_json(w->data);
675 }
676 else if(strcmp(tok, "netdata.conf") == 0) {
@@ -685,7 +678,7 @@ void web_client_process(struct web_client *w) {
678 debug(D_WEB_CLIENT_ACCESS, "%llu: Sending netdata.conf ...", w->id);
679
680 w->data->contenttype = CT_TEXT_PLAIN;
688 - w->data->bytes = 0;
681 + web_buffer_flush(w->data);
682 generate_config(w->data, 0);
683 }
684 else if(strcmp(tok, WEB_PATH_FILE) == 0) { // "file"
@@ -693,17 +686,16 @@ void web_client_process(struct web_client *w) {
686 if(tok && *tok) code = mysendfile(w, tok);
687 else {
688 code = 400;
696 - w->data->bytes = 0;
697 - strcpy(w->data->buffer, "You have to give a filename to get.\r\n");
698 - w->data->bytes = strlen(w->data->buffer);
689 + web_buffer_flush(w->data);
690 + web_buffer_strcat(w->data, "You have to give a filename to get.\r\n");
691 }
692 }
693 else if(!tok[0]) {
702 - w->data->bytes = 0;
694 + web_buffer_flush(w->data);
695 code = mysendfile(w, "index.html");
696 }
697 else {
706 - w->data->bytes = 0;
698 + web_buffer_flush(w->data);
699 code = mysendfile(w, tok);
700 }
701
@@ -714,23 +706,21 @@ void web_client_process(struct web_client *w) {
706 if(buf) debug(D_WEB_CLIENT_ACCESS, "%llu: Cannot understand '%s'.", w->id, buf);
707
708 code = 500;
717 - w->data->bytes = 0;
718 - strcpy(w->data->buffer, "I don't understand you...\r\n");
719 - w->data->bytes = strlen(w->data->buffer);
709 + web_buffer_flush(w->data);
710 + web_buffer_strcat(w->data, "I don't understand you...\r\n");
711 }
712
713 // free url_decode() buffer
714 if(pointer_to_free) free(pointer_to_free);
715 }
725 - else if(w->data->bytes > 8192) {
716 + else if(w->data->len > 8192) {
717 strcpy(w->last_url, "too big request");
718
719 debug(D_WEB_CLIENT_ACCESS, "%llu: Received request is too big.", w->id);
720
721 code = 400;
731 - w->data->bytes = 0;
732 - strcpy(w->data->buffer, "Received request is too big.\r\n");
733 - w->data->bytes = strlen(w->data->buffer);
722 + web_buffer_flush(w->data);
723 + web_buffer_strcat(w->data, "Received request is too big.\r\n");
724 }
725 else {
726 // wait for more data
@@ -738,8 +728,8 @@ void web_client_process(struct web_client *w) {
728 return;
729 }
730
741 - if(w->data->bytes > w->data->size) {
742 - error("%llu: memory overflow encountered (size is %ld, written %ld).", w->data->size, w->data->bytes);
731 + if(w->data->len > w->data->size) {
732 + error("%llu: memory overflow encountered (size is %ld, written %ld).", w->data->size, w->data->len);
733 }
734
735 gettimeofday(&w->tv_ready, NULL);
@@ -875,10 +865,10 @@ void web_client_process(struct web_client *w) {
865 }
866
867 // if we know the content length, put it
878 - if(!w->zoutput && (w->data->bytes || w->data->rbytes))
868 + if(!w->zoutput && (w->data->len || w->data->rlen))
869 headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen,
870 "Content-Length: %ld\r\n"
881 - , w->data->bytes?w->data->bytes:w->data->rbytes
871 + , w->data->len?w->data->len:w->data->rlen
872 );
873 else if(!w->zoutput)
874 w->keepalive = 0; // content-length is required for keep-alive
@@ -913,18 +903,18 @@ void web_client_process(struct web_client *w) {
903 if(setsockopt(w->ofd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) != 0) error("%llu: failed to enable TCP_NODELAY on socket.", w->id);
904
905 // enable sending immediately if we have data
916 - if(w->data->bytes) w->wait_send = 1;
906 + if(w->data->len) w->wait_send = 1;
907 else w->wait_send = 0;
908
909 // pretty logging
910 switch(w->mode) {
911 case WEB_CLIENT_MODE_NORMAL:
922 - debug(D_WEB_CLIENT, "%llu: Done preparing the response. Sending data (%d bytes) to client.", w->id, w->data->bytes);
912 + debug(D_WEB_CLIENT, "%llu: Done preparing the response. Sending data (%d bytes) to client.", w->id, w->data->len);
913 break;
914
915 case WEB_CLIENT_MODE_FILECOPY:
926 - if(w->data->rbytes) {
927 - debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending data file of %d bytes to client.", w->id, w->data->rbytes);
916 + if(w->data->rlen) {
917 + debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending data file of %d bytes to client.", w->id, w->data->rlen);
918 w->wait_receive = 1;
919
920 /*
@@ -991,14 +981,14 @@ long web_client_send_chunk_finalize(struct web_client *w)
981 #ifdef NETDATA_WITH_ZLIB
982 long web_client_send_deflate(struct web_client *w)
983 {
994 - long bytes = 0, t = 0;
984 + long len = 0, t = 0;
985
986 // when using compression,
987 // w->data->sent is the amount of bytes passed through compression
988
989 // debug(D_DEFLATE, "%llu: TEST w->data->bytes = %d, w->data->sent = %d, w->zhave = %d, w->zsent = %d, w->zstream.avail_in = %d, w->zstream.avail_out = %d, w->zstream.total_in = %d, w->zstream.total_out = %d.", w->id, w->data->bytes, w->data->sent, w->zhave, w->zsent, w->zstream.avail_in, w->zstream.avail_out, w->zstream.total_in, w->zstream.total_out);
990
1001 - if(w->data->bytes - w->data->sent == 0 && w->zstream.avail_in == 0 && w->zhave == w->zsent && w->zstream.avail_out != 0) {
991 + if(w->data->len - w->data->sent == 0 && w->zstream.avail_in == 0 && w->zhave == w->zsent && w->zstream.avail_out != 0) {
992 // there is nothing to send
993
994 debug(D_WEB_CLIENT, "%llu: Out of output data.", w->id);
@@ -1011,7 +1001,7 @@ long web_client_send_deflate(struct web_client *w)
1001 // A. we have done everything
1002 // B. we temporarily have nothing to send, waiting for the buffer to be filled by ifd
1003
1014 - if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->ifd != w->ofd && w->data->rbytes && w->data->rbytes > w->data->bytes) {
1004 + if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->ifd != w->ofd && w->data->rlen && w->data->rlen > w->data->len) {
1005 // we have to wait, more data will come
1006 debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
1007 w->wait_send = 0;
@@ -1036,12 +1026,12 @@ long web_client_send_deflate(struct web_client *w)
1026 // close the previous open chunk
1027 if(w->data->sent != 0) t += web_client_send_chunk_close(w);
1028
1039 - debug(D_DEFLATE, "%llu: Compressing %d bytes starting from %d.", w->id, (w->data->bytes - w->data->sent), w->data->sent);
1029 + debug(D_DEFLATE, "%llu: Compressing %d bytes starting from %d.", w->id, (w->data->len - w->data->sent), w->data->sent);
1030
1031 // give the compressor all the data not passed through the compressor yet
1042 - if(w->data->bytes > w->data->sent) {
1032 + if(w->data->len > w->data->sent) {
1033 w->zstream.next_in = (Bytef *)&w->data->buffer[w->data->sent];
1044 - w->zstream.avail_in = (w->data->bytes - w->data->sent);
1034 + w->zstream.avail_in = (w->data->len - w->data->sent);
1035 }
1036
1037 // reset the compressor output buffer
@@ -1051,7 +1041,7 @@ long web_client_send_deflate(struct web_client *w)
1041 // ask for FINISH if we have all the input
1042 int flush = Z_SYNC_FLUSH;
1043 if(w->mode == WEB_CLIENT_MODE_NORMAL
1054 - || (w->mode == WEB_CLIENT_MODE_FILECOPY && w->data->bytes == w->data->rbytes)) {
1044 + || (w->mode == WEB_CLIENT_MODE_FILECOPY && w->data->len == w->data->rlen)) {
1045 flush = Z_FINISH;
1046 debug(D_DEFLATE, "%llu: Requesting Z_FINISH.", w->id);
1047 }
@@ -1070,7 +1060,7 @@ long web_client_send_deflate(struct web_client *w)
1060 w->zsent = 0;
1061
1062 // keep track of the bytes passed through the compressor
1073 - w->data->sent = w->data->bytes;
1063 + w->data->sent = w->data->len;
1064
1065 debug(D_DEFLATE, "%llu: Compression produced %d bytes.", w->id, w->zhave);
1066
@@ -1078,16 +1068,16 @@ long web_client_send_deflate(struct web_client *w)
1068 t += web_client_send_chunk_header(w, w->zhave);
1069 }
1070
1081 - bytes = send(w->ofd, &w->zbuffer[w->zsent], w->zhave - w->zsent, MSG_DONTWAIT);
1082 - if(bytes > 0) {
1083 - w->zsent += bytes;
1084 - if(t > 0) bytes += t;
1085 - debug(D_WEB_CLIENT, "%llu: Sent %d bytes.", w->id, bytes);
1071 + len = send(w->ofd, &w->zbuffer[w->zsent], w->zhave - w->zsent, MSG_DONTWAIT);
1072 + if(len > 0) {
1073 + w->zsent += len;
1074 + if(t > 0) len += t;
1075 + debug(D_WEB_CLIENT, "%llu: Sent %d bytes.", w->id, len);
1076 }
1087 - else if(bytes == 0) debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client.", w->id);
1077 + else if(len == 0) debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client.", w->id);
1078 else debug(D_WEB_CLIENT, "%llu: Failed to send data to client. Reason: %s", w->id, strerror(errno));
1079
1090 - return(bytes);
1080 + return(len);
1081 }
1082 #endif // NETDATA_WITH_ZLIB
1083
@@ -1099,7 +1089,7 @@ long web_client_send(struct web_client *w)
1089
1090 long bytes;
1091
1102 - if(unlikely(w->data->bytes - w->data->sent == 0)) {
1092 + if(unlikely(w->data->len - w->data->sent == 0)) {
1093 // there is nothing to send
1094
1095 debug(D_WEB_CLIENT, "%llu: Out of output data.", w->id);
@@ -1108,7 +1098,7 @@ long web_client_send(struct web_client *w)
1098 // A. we have done everything
1099 // B. we temporarily have nothing to send, waiting for the buffer to be filled by ifd
1100
1111 - if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->ifd != w->ofd && w->data->rbytes && w->data->rbytes > w->data->bytes) {
1101 + if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->ifd != w->ofd && w->data->rlen && w->data->rlen > w->data->len) {
1102 // we have to wait, more data will come
1103 debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
1104 w->wait_send = 0;
@@ -1126,7 +1116,7 @@ long web_client_send(struct web_client *w)
1116 return(0);
1117 }
1118
1129 - bytes = send(w->ofd, &w->data->buffer[w->data->sent], w->data->bytes - w->data->sent, MSG_DONTWAIT);
1119 + bytes = send(w->ofd, &w->data->buffer[w->data->sent], w->data->len - w->data->sent, MSG_DONTWAIT);
1120 if(likely(bytes > 0)) {
1121 w->data->sent += bytes;
1122 debug(D_WEB_CLIENT, "%llu: Sent %d bytes.", w->id, bytes);
@@ -1140,27 +1130,27 @@ long web_client_send(struct web_client *w)
1130 long web_client_receive(struct web_client *w)
1131 {
1132 // do we have any space for more data?
1143 - web_buffer_increase(w->data, WEB_DATA_LENGTH_INCREASE_STEP);
1133 + web_buffer_need_bytes(w->data, WEB_DATA_LENGTH_INCREASE_STEP);
1134
1145 - long left = w->data->size - w->data->bytes;
1135 + long left = w->data->size - w->data->len;
1136 long bytes;
1137
1138 if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY))
1149 - bytes = read(w->ifd, &w->data->buffer[w->data->bytes], (left-1));
1139 + bytes = read(w->ifd, &w->data->buffer[w->data->len], (left-1));
1140 else
1151 - bytes = recv(w->ifd, &w->data->buffer[w->data->bytes], left-1, MSG_DONTWAIT);
1141 + bytes = recv(w->ifd, &w->data->buffer[w->data->len], left-1, MSG_DONTWAIT);
1142
1143 if(likely(bytes > 0)) {
1154 - int old = w->data->bytes;
1155 - w->data->bytes += bytes;
1156 - w->data->buffer[w->data->bytes] = '\0';
1144 + int old = w->data->len;
1145 + w->data->len += bytes;
1146 + w->data->buffer[w->data->len] = '\0';
1147
1148 debug(D_WEB_CLIENT, "%llu: Received %d bytes.", w->id, bytes);
1149 debug(D_WEB_DATA, "%llu: Received data: '%s'.", w->id, &w->data->buffer[old]);
1150
1151 if(w->mode == WEB_CLIENT_MODE_FILECOPY) {
1152 w->wait_send = 1;
1163 - if(w->data->rbytes && w->data->bytes >= w->data->rbytes) w->wait_receive = 0;
1153 + if(w->data->rlen && w->data->len >= w->data->rlen) w->wait_receive = 0;
1154 }
1155 }
1156 else if(likely(bytes == 0)) {