diff options
Diffstat (limited to 'web/server')
-rw-r--r-- | web/server/static/static-threaded.c | 149 | ||||
-rw-r--r-- | web/server/web_client.c | 17 | ||||
-rw-r--r-- | web/server/web_client.h | 6 |
3 files changed, 100 insertions, 72 deletions
diff --git a/web/server/static/static-threaded.c b/web/server/static/static-threaded.c index ff10cb881..8b9122f87 100644 --- a/web/server/static/static-threaded.c +++ b/web/server/static/static-threaded.c @@ -7,6 +7,20 @@ int web_client_timeout = DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS; int web_client_first_request_timeout = DEFAULT_TIMEOUT_TO_RECEIVE_FIRST_WEB_REQUEST; long web_client_streaming_rate_t = 0L; +#define WORKER_JOB_ADD_CONNECTION 0 +#define WORKER_JOB_DEL_COLLECTION 1 +#define WORKER_JOB_ADD_FILE 2 +#define WORKER_JOB_DEL_FILE 3 +#define WORKER_JOB_READ_FILE 4 +#define WORKER_JOB_WRITE_FILE 5 +#define WORKER_JOB_RCV_DATA 6 +#define WORKER_JOB_SND_DATA 7 +#define WORKER_JOB_PROCESS 8 + +#if (WORKER_UTILIZATION_MAX_JOB_TYPES < 9) +#error Please increase WORKER_UTILIZATION_MAX_JOB_TYPES to at least 8 +#endif + /* * -------------------------------------------------------------------------------------------------------------------- * Build web_client state from the pollinfo that describes an accepted connection. @@ -71,11 +85,15 @@ static inline int web_server_check_client_status(struct web_client *w) { static void *web_server_file_add_callback(POLLINFO *pi, short int *events, void *data) { struct web_client *w = (struct web_client *)data; + worker_is_busy(WORKER_JOB_ADD_FILE); + worker_private->files_read++; debug(D_WEB_CLIENT, "%llu: ADDED FILE READ ON FD %d", w->id, pi->fd); *events = POLLIN; pi->data = w; + + worker_is_idle(); return w; } @@ -83,27 +101,36 @@ static void web_server_file_del_callback(POLLINFO *pi) { struct web_client *w = (struct web_client *)pi->data; debug(D_WEB_CLIENT, "%llu: RELEASE FILE READ ON FD %d", w->id, pi->fd); + worker_is_busy(WORKER_JOB_DEL_FILE); + w->pollinfo_filecopy_slot = 0; if(unlikely(!w->pollinfo_slot)) { debug(D_WEB_CLIENT, "%llu: CROSS WEB CLIENT CLEANUP (iFD %d, oFD %d)", w->id, pi->fd, w->ofd); web_client_release(w); } + + worker_is_idle(); } static int web_server_file_read_callback(POLLINFO *pi, short int *events) { + int retval = -1; struct web_client *w = (struct web_client *)pi->data; + worker_is_busy(WORKER_JOB_READ_FILE); + // if there is no POLLINFO linked to this, it means the client disconnected // stop the file reading too if(unlikely(!w->pollinfo_slot)) { debug(D_WEB_CLIENT, "%llu: PREVENTED ATTEMPT TO READ FILE ON FD %d, ON CLOSED WEB CLIENT", w->id, pi->fd); - return -1; + retval = -1; + goto cleanup; } if(unlikely(w->mode != WEB_CLIENT_MODE_FILECOPY || w->ifd == w->ofd)) { debug(D_WEB_CLIENT, "%llu: PREVENTED ATTEMPT TO READ FILE ON FD %d, ON NON-FILECOPY WEB CLIENT", w->id, pi->fd); - return -1; + retval = -1; + goto cleanup; } debug(D_WEB_CLIENT, "%llu: READING FILE ON FD %d", w->id, pi->fd); @@ -121,18 +148,25 @@ static int web_server_file_read_callback(POLLINFO *pi, short int *events) { if(unlikely(ret <= 0 || w->ifd == w->ofd)) { debug(D_WEB_CLIENT, "%llu: DONE READING FILE ON FD %d", w->id, pi->fd); - return -1; + retval = -1; + goto cleanup; } *events = POLLIN; - return 0; + retval = 0; + +cleanup: + worker_is_idle(); + return retval; } static int web_server_file_write_callback(POLLINFO *pi, short int *events) { (void)pi; (void)events; + worker_is_busy(WORKER_JOB_WRITE_FILE); error("Writing to web files is not supported!"); + worker_is_idle(); return -1; } @@ -143,6 +177,7 @@ static int web_server_file_write_callback(POLLINFO *pi, short int *events) { static void *web_server_add_callback(POLLINFO *pi, short int *events, void *data) { (void)data; // Suppress warning on unused argument + worker_is_busy(WORKER_JOB_ADD_CONNECTION); worker_private->connected++; size_t concurrent = worker_private->connected - worker_private->disconnected; @@ -177,7 +212,7 @@ static void *web_server_add_callback(POLLINFO *pi, short int *events, void *data //this means that the mensage was not completely read, so //I cannot identify it yet. sock_setnonblock(w->ifd); - return w; + goto cleanup; } //The next two ifs are not together because I am reusing SSL structure @@ -191,7 +226,7 @@ static void *web_server_add_callback(POLLINFO *pi, short int *events, void *data if (test[0] < 0x18){ WEB_CLIENT_IS_DEAD(w); sock_setnonblock(w->ifd); - return w; + goto cleanup; } } } @@ -217,11 +252,16 @@ static void *web_server_add_callback(POLLINFO *pi, short int *events, void *data #endif debug(D_WEB_CLIENT, "%llu: ADDED CLIENT FD %d", w->id, pi->fd); + +cleanup: + worker_is_idle(); return w; } // TCP client disconnected static void web_server_del_callback(POLLINFO *pi) { + worker_is_busy(WORKER_JOB_DEL_COLLECTION); + worker_private->disconnected++; struct web_client *w = (struct web_client *)pi->data; @@ -240,20 +280,33 @@ static void web_server_del_callback(POLLINFO *pi) { debug(D_WEB_CLIENT, "%llu: CLOSING CLIENT FD %d", w->id, pi->fd); web_client_release(w); } + + worker_is_idle(); } static int web_server_rcv_callback(POLLINFO *pi, short int *events) { + int ret = -1; + worker_is_busy(WORKER_JOB_RCV_DATA); + worker_private->receptions++; struct web_client *w = (struct web_client *)pi->data; int fd = pi->fd; - if(unlikely(web_client_receive(w) < 0)) - return -1; + if(unlikely(web_client_receive(w) < 0)) { + ret = -1; + goto cleanup; + } debug(D_WEB_CLIENT, "%llu: processing received data on fd %d.", w->id, fd); + worker_is_idle(); + worker_is_busy(WORKER_JOB_PROCESS); web_client_process_request(w); + if (unlikely(w->mode == WEB_CLIENT_MODE_STREAM)) { + web_client_send(w); + } + if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY)) { if(w->pollinfo_filecopy_slot == 0) { debug(D_WEB_CLIENT, "%llu: FILECOPY DETECTED ON FD %d", w->id, pi->fd); @@ -282,7 +335,8 @@ static int web_server_rcv_callback(POLLINFO *pi, short int *events) { w->pollinfo_filecopy_slot = fpi->slot; else { error("Failed to add filecopy fd. Closing client."); - return -1; + ret = -1; + goto cleanup; } } } @@ -295,10 +349,17 @@ static int web_server_rcv_callback(POLLINFO *pi, short int *events) { if(unlikely(w->ofd == fd && web_client_has_wait_send(w))) *events |= POLLOUT; - return web_server_check_client_status(w); + ret = web_server_check_client_status(w); + +cleanup: + worker_is_idle(); + return ret; } static int web_server_snd_callback(POLLINFO *pi, short int *events) { + int retval = -1; + worker_is_busy(WORKER_JOB_SND_DATA); + worker_private->sends++; struct web_client *w = (struct web_client *)pi->data; @@ -306,8 +367,12 @@ static int web_server_snd_callback(POLLINFO *pi, short int *events) { debug(D_WEB_CLIENT, "%llu: sending data on fd %d.", w->id, fd); - if(unlikely(web_client_send(w) < 0)) - return -1; + int ret = web_client_send(w); + + if(unlikely(ret < 0)) { + retval = -1; + goto cleanup; + } if(unlikely(w->ifd == fd && web_client_has_wait_receive(w))) *events |= POLLIN; @@ -315,50 +380,11 @@ static int web_server_snd_callback(POLLINFO *pi, short int *events) { if(unlikely(w->ofd == fd && web_client_has_wait_send(w))) *events |= POLLOUT; - return web_server_check_client_status(w); -} + retval = web_server_check_client_status(w); -static void web_server_tmr_callback(void *timer_data) { - worker_private = (struct web_server_static_threaded_worker *)timer_data; - - static __thread RRDSET *st = NULL; - static __thread RRDDIM *rd_user = NULL, *rd_system = NULL; - - if(unlikely(netdata_exit)) return; - - if(unlikely(!st)) { - char id[100 + 1]; - char title[100 + 1]; - - snprintfz(id, 100, "web_thread%d_cpu", worker_private->id + 1); - snprintfz(title, 100, "Netdata web server thread CPU usage"); - - st = rrdset_create_localhost( - "netdata" - , id - , NULL - , "web" - , "netdata.web_cpu" - , title - , "milliseconds/s" - , "web" - , "stats" - , 132000 + worker_private->id - , default_rrd_update_every - , RRDSET_TYPE_STACKED - ); - - rd_user = rrddim_add(st, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); - rd_system = rrddim_add(st, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); - } - else - rrdset_next(st); - - struct rusage rusage; - getrusage(RUSAGE_THREAD, &rusage); - rrddim_set_by_pointer(st, rd_user, rusage.ru_utime.tv_sec * 1000000ULL + rusage.ru_utime.tv_usec); - rrddim_set_by_pointer(st, rd_system, rusage.ru_stime.tv_sec * 1000000ULL + rusage.ru_stime.tv_usec); - rrdset_done(st); +cleanup: + worker_is_idle(); + return retval; } // ---------------------------------------------------------------------------- @@ -379,11 +405,22 @@ static void socket_listen_main_static_threaded_worker_cleanup(void *ptr) { ); worker_private->running = 0; + worker_unregister(); } void *socket_listen_main_static_threaded_worker(void *ptr) { worker_private = (struct web_server_static_threaded_worker *)ptr; worker_private->running = 1; + worker_register("WEB"); + worker_register_job_name(WORKER_JOB_ADD_CONNECTION, "connect"); + worker_register_job_name(WORKER_JOB_DEL_COLLECTION, "disconnect"); + worker_register_job_name(WORKER_JOB_ADD_FILE, "file start"); + worker_register_job_name(WORKER_JOB_DEL_FILE, "file end"); + worker_register_job_name(WORKER_JOB_READ_FILE, "file read"); + worker_register_job_name(WORKER_JOB_WRITE_FILE, "file write"); + worker_register_job_name(WORKER_JOB_RCV_DATA, "receive"); + worker_register_job_name(WORKER_JOB_SND_DATA, "send"); + worker_register_job_name(WORKER_JOB_PROCESS, "process"); netdata_thread_cleanup_push(socket_listen_main_static_threaded_worker_cleanup, ptr); @@ -392,7 +429,7 @@ void *socket_listen_main_static_threaded_worker(void *ptr) { , web_server_del_callback , web_server_rcv_callback , web_server_snd_callback - , web_server_tmr_callback + , NULL , web_allow_connections_from , web_allow_connections_dns , NULL diff --git a/web/server/web_client.c b/web/server/web_client.c index e61dc0a54..d287cec03 100644 --- a/web/server/web_client.c +++ b/web/server/web_client.c @@ -496,6 +496,11 @@ void buffer_data_options2string(BUFFER *wb, uint32_t options) { if(count++) buffer_strcat(wb, " "); buffer_strcat(wb, "unaligned"); } + + if(options & RRDR_OPTION_ANOMALY_BIT) { + if(count++) buffer_strcat(wb, " "); + buffer_strcat(wb, "anomaly-bit"); + } } static inline int check_host_and_call(RRDHOST *host, struct web_client *w, char *url, int (*func)(RRDHOST *, struct web_client *, char *)) { @@ -1011,7 +1016,7 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) { // copy the URL - we are going to overwrite parts of it // TODO -- ideally we we should avoid copying buffers around - strncpyz(w->last_url, w->decoded_url, NETDATA_WEB_REQUEST_URL_SIZE); + snprintfz(w->last_url, NETDATA_WEB_REQUEST_URL_SIZE, "%s%s", w->decoded_url, w->decoded_query_string); #ifdef ENABLE_HTTPS if ( (!web_client_check_unix(w)) && (netdata_srv_ctx) ) { if ((w->ssl.conn) && ((w->ssl.flags & NETDATA_SSL_NO_HANDSHAKE) && (web_client_is_using_ssl_force(w) || web_client_is_using_ssl_default(w)) && (w->mode != WEB_CLIENT_MODE_STREAM)) ) { @@ -1309,15 +1314,7 @@ static inline int web_client_switch_host(RRDHOST *host, struct web_client *w, ch host = sql_create_host_by_uuid(tok); if (likely(host)) { int rc = web_client_process_url(host, w, url); - freez(host->hostname); - freez((char *)host->os); - freez((char *)host->tags); - freez((char *)host->timezone); - freez(host->program_name); - freez(host->program_version); - freez(host->registry_hostname); - freez(host->system_info); - freez(host); + free_temporary_host(host); return rc; } } diff --git a/web/server/web_client.h b/web/server/web_client.h index e859e1136..f1c02c782 100644 --- a/web/server/web_client.h +++ b/web/server/web_client.h @@ -68,15 +68,9 @@ typedef enum web_client_flags { WEB_CLIENT_CHUNKED_TRANSFER = 1 << 10, // chunked transfer (used with zlib compression) } WEB_CLIENT_FLAGS; -//#ifdef HAVE_C___ATOMIC -//#define web_client_flag_check(w, flag) (__atomic_load_n(&((w)->flags), __ATOMIC_SEQ_CST) & flag) -//#define web_client_flag_set(w, flag) __atomic_or_fetch(&((w)->flags), flag, __ATOMIC_SEQ_CST) -//#define web_client_flag_clear(w, flag) __atomic_and_fetch(&((w)->flags), ~flag, __ATOMIC_SEQ_CST) -//#else #define web_client_flag_check(w, flag) ((w)->flags & (flag)) #define web_client_flag_set(w, flag) (w)->flags |= flag #define web_client_flag_clear(w, flag) (w)->flags &= ~flag -//#endif #define WEB_CLIENT_IS_DEAD(w) web_client_flag_set(w, WEB_CLIENT_FLAG_DEAD) #define web_client_check_dead(w) web_client_flag_check(w, WEB_CLIENT_FLAG_DEAD) |