summaryrefslogtreecommitdiffstats
path: root/web/server
diff options
context:
space:
mode:
Diffstat (limited to 'web/server')
-rw-r--r--web/server/static/static-threaded.c149
-rw-r--r--web/server/web_client.c17
-rw-r--r--web/server/web_client.h6
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)