]> arthur.barton.de Git - netdata.git/commitdiff
Merge remote-tracking branch 'upstream/master'
authorCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Sat, 21 May 2016 11:08:00 +0000 (14:08 +0300)
committerCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Sat, 21 May 2016 11:08:00 +0000 (14:08 +0300)
src/dictionary.c
src/dictionary.h
src/global_statistics.c
src/global_statistics.h
src/plugin_proc.c
src/url.c
src/url.h
src/web_client.c
src/web_client.h

index 1543f4d0e7334bce5ad63e2b5469e5b47b0dffb8..d3576412b5dc1264a1068db2eeb1c1adca7a0542 100644 (file)
@@ -46,15 +46,15 @@ static int name_value_compare(void* a, void* b) {
        else return strcmp(((NAME_VALUE *)a)->name, ((NAME_VALUE *)b)->name);
 }
 
-#define dictionary_name_value_index_add_nolock(dict, nv) do { (dict)->inserts++; avl_insert(&((dict)->values_index), (avl *)(nv)); } while(0)
-#define dictionary_name_value_index_del_nolock(dict, nv) do { (dict)->deletes++; avl_remove(&(dict->values_index), (avl *)(nv)); } while(0)
+#define dictionary_name_value_index_add_nolock(dict, nv) do { NETDATA_DICTIONARY_STATS_INSERTS_PLUS1(dict); avl_insert(&((dict)->values_index), (avl *)(nv)); } while(0)
+#define dictionary_name_value_index_del_nolock(dict, nv) do { NETDATA_DICTIONARY_STATS_DELETES_PLUS1(dict); avl_remove(&(dict->values_index), (avl *)(nv)); } while(0)
 
 static inline NAME_VALUE *dictionary_name_value_index_find_nolock(DICTIONARY *dict, const char *name, uint32_t hash) {
        NAME_VALUE tmp;
        tmp.hash = (hash)?hash:simple_hash(name);
        tmp.name = (char *)name;
 
-       dict->searches++;
+       NETDATA_DICTIONARY_STATS_SEARCHES_PLUS1(dict);
        return (NAME_VALUE *)avl_search(&(dict->values_index), (avl *) &tmp);
 }
 
@@ -89,7 +89,7 @@ static NAME_VALUE *dictionary_name_value_create_nolock(DICTIONARY *dict, const c
 
        // index it
        dictionary_name_value_index_add_nolock(dict, nv);
-       dict->entries++;
+       NETDATA_DICTIONARY_STATS_ENTRIES_PLUS1(dict);
 
        return nv;
 }
@@ -99,7 +99,7 @@ static void dictionary_name_value_destroy_nolock(DICTIONARY *dict, NAME_VALUE *n
 
        dictionary_name_value_index_del_nolock(dict, nv);
 
-       dict->entries--;
+       NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(dict);
 
        if(!(dict->flags & DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE)) {
                debug(D_REGISTRY, "Dictionary freeing value of '%s'", nv->name);
index 575f2827105c443644bfe6349769383bab58db47..fe44d8146093f3c3e2fe0dc472b04880b14bbce1 100644 (file)
@@ -21,14 +21,30 @@ typedef struct dictionary {
 
        uint8_t flags;
 
+#ifdef NETDATA_DICTIONARY_WITH_STATISTICS
        unsigned long long inserts;
        unsigned long long deletes;
        unsigned long long searches;
        unsigned long long entries;
+#endif /* NETDATA_DICTIONARY_WITH_STATISTICS */
 
        pthread_rwlock_t rwlock;
 } DICTIONARY;
 
+#ifdef NETDATA_DICTIONARY_WITH_STATISTICS
+#define NETDATA_DICTIONARY_STATS_INSERTS_PLUS1(dict) (dict)->inserts++
+#define NETDATA_DICTIONARY_STATS_DELETES_PLUS1(dict) (dict)->deletes++
+#define NETDATA_DICTIONARY_STATS_SEARCHES_PLUS1(dict) (dict)->searches++
+#define NETDATA_DICTIONARY_STATS_ENTRIES_PLUS1(dict) (dict)->entries++
+#define NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(dict) (dict)->entries--
+#else /* NETDATA_DICTIONARY_WITH_STATISTICS */
+#define NETDATA_DICTIONARY_STATS_INSERTS_PLUS1(dict)
+#define NETDATA_DICTIONARY_STATS_DELETES_PLUS1(dict)
+#define NETDATA_DICTIONARY_STATS_SEARCHES_PLUS1(dict)
+#define NETDATA_DICTIONARY_STATS_ENTRIES_PLUS1(dict)
+#define NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(dict)
+#endif /* NETDATA_DICTIONARY_WITH_STATISTICS */
+
 #define DICTIONARY_FLAG_DEFAULT                                        0x00000000
 #define DICTIONARY_FLAG_SINGLE_THREADED                        0x00000001
 #define DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE  0x00000002
index d4a04efd2d067aa32c7bf6d085a998e3522c449c..d813f66c9b9d4d31838a6d7fb44f664cdd412b9a 100644 (file)
@@ -5,7 +5,7 @@
 
 #include "global_statistics.h"
 
-struct global_statistics global_statistics = { 0ULL, 0ULL, 0ULL, 0ULL };
+struct global_statistics global_statistics = { 0, 0ULL, 0ULL, 0ULL, 0ULL};
 
 pthread_mutex_t global_statistics_mutex = PTHREAD_MUTEX_INITIALIZER;
 
index ce3c3490e95c30e179a4e26a851e80bd9430cb0b..b618191656fc3d9537002ded68e4e812da8836f1 100644 (file)
@@ -5,11 +5,11 @@
 // global statistics
 
 struct global_statistics {
-       unsigned long long connected_clients;
-       unsigned long long web_requests;
-       unsigned long long bytes_received;
-       unsigned long long bytes_sent;
-
+       unsigned long volatile connected_clients;
+       unsigned long long volatile web_requests;
+       unsigned long long volatile web_usec;
+       unsigned long long volatile bytes_received;
+       unsigned long long volatile bytes_sent;
 };
 
 extern struct global_statistics global_statistics;
index a147d971f8128609d1e9416309ef7e35138e8765..5ecd7b9e459a3e7e1daa4114bb63e3f626930061 100644 (file)
@@ -18,7 +18,8 @@
 
 void *proc_main(void *ptr)
 {
-       if(ptr) { ; }
+       static unsigned long long old_web_requests = 0, old_web_usec = 0;
+       (void)ptr;
 
        info("PROC Plugin thread created with task id %d", gettid());
 
@@ -77,7 +78,7 @@ void *proc_main(void *ptr)
        unsigned long long sunext = (time(NULL) - (time(NULL) % rrd_update_every) + rrd_update_every) * 1000000ULL;
        unsigned long long sunow;
 
-       RRDSET *stcpu = NULL, *stcpu_thread = NULL, *stclients = NULL, *streqs = NULL, *stbytes = NULL;
+       RRDSET *stcpu = NULL, *stcpu_thread = NULL, *stclients = NULL, *streqs = NULL, *stbytes = NULL, *stduration = NULL;
 
        for(;1;) {
                if(unlikely(netdata_exit)) break;
@@ -310,6 +311,30 @@ void *proc_main(void *ptr)
 
                        // ----------------------------------------------------------------
 
+                       if(!stduration) stduration = rrdset_find("netdata.response_time");
+                       if(!stduration) {
+                               stduration = rrdset_create("netdata", "response_time", NULL, "netdata", NULL, "NetData Average API Response Time", "ms/request", 130400, rrd_update_every, RRDSET_TYPE_LINE);
+
+                               rrddim_add(stduration, "response_time", "response time",  1, 1000, RRDDIM_ABSOLUTE);
+                       }
+                       else rrdset_next(stduration);
+
+                       unsigned long long gweb_usec     = global_statistics.web_usec;
+                       unsigned long long gweb_requests = global_statistics.web_requests;
+
+                       unsigned long long web_usec     = gweb_usec     - old_web_usec;
+                       unsigned long long web_requests = gweb_requests - old_web_requests;
+
+                       old_web_usec     = gweb_usec;
+                       old_web_requests = gweb_requests;
+
+                       if(!web_requests) web_requests = 1;
+
+                       rrddim_set(stduration, "response_time", web_usec / web_requests);
+                       rrdset_done(stduration);
+
+                       // ----------------------------------------------------------------
+
                        registry_statistics();
                }
        }
index 010b07dddc69a8a88253d6cc7bf16d28ca665332..bd22b8187fe05d335d3400a26386bd6c0c7cdbd8 100644 (file)
--- a/src/url.c
+++ b/src/url.c
@@ -63,31 +63,37 @@ char *url_encode(char *str) {
 /* Returns a url-decoded version of str */
 /* IMPORTANT: be sure to free() the returned string after use */
 char *url_decode(char *str) {
-       char *pstr = str,
-               *buf = malloc(strlen(str) + 1),
-               *pbuf = buf;
+       size_t size = strlen(str) + 1;
 
+       char *buf = malloc(size);
        if(!buf)
-               fatal("Cannot allocate memory.");
+               fatal("Cannot allocate %zu bytes of memory.", size);
+
+       return url_decode_r(buf, str, size);
+}
+
+char *url_decode_r(char *to, char *url, size_t size) {
+       char *s = url,           // source
+                *d = to,            // destination
+                *e = &to[size - 1]; // destination end
 
-       while (*pstr) {
-               if (*pstr == '%') {
-                       if (pstr[1] && pstr[2]) {
-                               *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
-                               pstr += 2;
+       while(*s && d < e) {
+               if(unlikely(*s == '%')) {
+                       if(likely(s[1] && s[2])) {
+                               *d++ = from_hex(s[1]) << 4 | from_hex(s[2]);
+                               s += 2;
                        }
                }
-               else if (*pstr == '+')
-                       *pbuf++ = ' ';
+               else if(unlikely(*s == '+'))
+                       *d++ = ' ';
 
                else
-                       *pbuf++ = *pstr;
+                       *d++ = *s;
 
-               pstr++;
+               s++;
        }
 
-       *pbuf = '\0';
+       *d = '\0';
 
-       return buf;
+       return to;
 }
-
index f79a20ea0c0f7973e4fe92a42522b008d7abe3e2..fa44d49a8e856d081f1907b85ae06dad45a37281 100644 (file)
--- a/src/url.h
+++ b/src/url.h
@@ -19,4 +19,6 @@ extern char *url_encode(char *str);
 /* IMPORTANT: be sure to free() the returned string after use */
 extern char *url_decode(char *str);
 
+extern char *url_decode_r(char *to, char *url, size_t size);
+
 #endif /* NETDATA_URL_H */
index 601dda083ae0172e4b65be9d0e9ecd3f19cc6264..d78624c9c37693513ba7fa459527a2eddeb7f475 100644 (file)
@@ -146,6 +146,19 @@ void web_client_reset(struct web_client *w)
        struct timeval tv;
        gettimeofday(&tv, NULL);
 
+       debug(D_WEB_CLIENT, "%llu: Reseting client.", w->id);
+
+       if(w->stats_received_bytes || w->stats_sent_bytes) {
+               global_statistics_lock();
+               global_statistics.web_requests++;
+               global_statistics.web_usec += usecdiff(&tv, &w->tv_in);
+               global_statistics.bytes_received += w->stats_received_bytes;
+               global_statistics.bytes_sent += w->stats_sent_bytes;
+               global_statistics_unlock();
+       }
+       w->stats_received_bytes = 0;
+       w->stats_sent_bytes = 0;
+
        long sent = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->response.rlen:w->response.data->len;
 
 #ifdef NETDATA_WITH_ZLIB
@@ -166,8 +179,6 @@ void web_client_reset(struct web_client *w)
                        w->last_url
                );
 
-       debug(D_WEB_CLIENT, "%llu: Reseting client.", w->id);
-
        if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY)) {
                debug(D_WEB_CLIENT, "%llu: Closing filecopy input file.", w->id);
                close(w->ifd);
@@ -183,10 +194,7 @@ void web_client_reset(struct web_client *w)
        w->mode = WEB_CLIENT_MODE_NORMAL;
        w->enable_gzip = 0;
        w->keepalive = 0;
-       if(w->decoded_url) {
-               free(w->decoded_url);
-               w->decoded_url = NULL;
-       }
+       w->decoded_url[0] = '\0';
 
        buffer_reset(w->response.header_output);
        buffer_reset(w->response.header);
@@ -1235,7 +1243,7 @@ static inline char *http_header_parse(struct web_client *w, char *s) {
 // http_request_validate()
 // returns:
 // = 0 : all good, process the request
-// > 0 : request is complete, but is not supported
+// > 0 : request is not supported
 // < 0 : request is incomplete - wait for more data
 
 static inline int http_request_validate(struct web_client *w) {
@@ -1257,7 +1265,7 @@ static inline int http_request_validate(struct web_client *w) {
 
        // find the SPACE + "HTTP/"
        while(*s) {
-               // find the space
+               // find the next space
                while (*s && *s != ' ') s++;
 
                // is it SPACE + "HTTP/" ?
@@ -1266,7 +1274,7 @@ static inline int http_request_validate(struct web_client *w) {
        }
 
        // incomplete requests
-       if(!*s) {
+       if(unlikely(!*s)) {
                w->wait_receive = 1;
                return -2;
        }
@@ -1274,32 +1282,37 @@ static inline int http_request_validate(struct web_client *w) {
        // we have the end of encoded_url - remember it
        char *ue = s;
 
+       // make sure we have complete request
+       // complete requests contain: \r\n\r\n
        while(*s) {
                // find a line feed
-               while (*s && *s != '\r') s++;
+               while(*s && *s++ != '\r');
 
                // did we reach the end?
                if(unlikely(!*s)) break;
 
                // is it \r\n ?
-               if (likely(s[1] == '\n')) {
+               if(likely(*s++ == '\n')) {
 
                        // is it again \r\n ? (header end)
-                       if(unlikely(s[2] == '\r' && s[3] == '\n')) {
+                       if(unlikely(*s == '\r' && s[1] == '\n')) {
                                // a valid complete HTTP request found
 
                                *ue = '\0';
-                               w->decoded_url = url_decode(encoded_url);
+                               url_decode_r(w->decoded_url, encoded_url, URL_MAX + 1);
                                *ue = ' ';
+                               
+                               // copy the URL - we are going to overwrite parts of it
+                               // FIXME -- we should avoid it
+                               strncpyz(w->last_url, w->decoded_url, URL_MAX);
 
                                w->wait_receive = 0;
                                return 0;
                        }
 
                        // another header line
-                       s = http_header_parse(w, &s[2]);
+                       s = http_header_parse(w, s);
                }
-               else s++;
        }
 
        // incomplete request
@@ -1341,14 +1354,6 @@ void web_client_process(struct web_client *w) {
        else { // what_to_do == 0
                gettimeofday(&w->tv_in, NULL);
 
-               global_statistics_lock();
-               global_statistics.web_requests++;
-               global_statistics_unlock();
-
-               // copy the URL - we are going to overwrite parts of it
-               // FIXME -- we should avoid it
-               strncpyz(w->last_url, w->decoded_url, URL_MAX);
-
                if(w->mode == WEB_CLIENT_MODE_OPTIONS) {
                        code = 200;
                        w->response.data->contenttype = CT_TEXT_PLAIN;
@@ -1736,11 +1741,8 @@ void web_client_process(struct web_client *w) {
                                , w->id
                                , buffer_strlen(w->response.header_output)
                                , bytes);
-       else {
-               global_statistics_lock();
-               global_statistics.bytes_sent += bytes;
-               global_statistics_unlock();
-       }
+       else 
+               w->stats_sent_bytes += bytes;
 
        // enable TCP_NODELAY, to send all data immediately at the next send()
        flag = 1;
@@ -2107,10 +2109,8 @@ void *web_client_main(void *ptr)
                                errno = 0;
                                break;
                        }
-
-                       global_statistics_lock();
-                       global_statistics.bytes_sent += bytes;
-                       global_statistics_unlock();
+                       else
+                               w->stats_sent_bytes += bytes;
                }
 
                if(w->wait_receive && FD_ISSET(w->ifd, &ifds)) {
@@ -2120,6 +2120,8 @@ void *web_client_main(void *ptr)
                                errno = 0;
                                break;
                        }
+                       else
+                               w->stats_received_bytes += bytes;
 
                        if(w->mode == WEB_CLIENT_MODE_NORMAL) {
                                debug(D_WEB_CLIENT, "%llu: Attempting to process received data (%ld bytes).", w->id, bytes);
@@ -2127,9 +2129,6 @@ void *web_client_main(void *ptr)
                                web_client_process(w);
                        }
 
-                       global_statistics_lock();
-                       global_statistics.bytes_received += bytes;
-                       global_statistics_unlock();
                }
        }
 
index f663be4a1d28eec1279ae90cc8798bd642762782..da3707d20a3910c01c92e794b874fdc9144c19e8 100644 (file)
@@ -57,7 +57,8 @@ struct web_client {
        char client_ip[NI_MAXHOST+1];
        char client_port[NI_MAXSERV+1];
 
-       char last_url[URL_MAX+1];
+       char decoded_url[URL_MAX + 1];  // we decode the URL in this buffer
+       char last_url[URL_MAX+1];               // we keep a copy of the decoded URL here
 
        struct timeval tv_in, tv_ready;
 
@@ -68,7 +69,6 @@ struct web_client {
        int mode;
        int keepalive;
        int enable_gzip;
-       char *decoded_url;
 
        struct sockaddr_storage clientaddr;
 
@@ -83,6 +83,9 @@ struct web_client {
        int wait_receive;
        int wait_send;
 
+       unsigned long stats_received_bytes;
+       unsigned long stats_sent_bytes;
+
        struct web_client *prev;
        struct web_client *next;
 };