diff options
author | Igor Sysoev <igor@sysoev.ru> | 2017-01-17 20:00:00 +0300 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2017-01-17 20:00:00 +0300 |
commit | 16cbf3c076a0aca6d47adaf3f719493674cf2363 (patch) | |
tree | e6530480020f62a2bdbf249988ec3e2a751d3927 /src/nxt_log_moderation.c | |
download | unit-16cbf3c076a0aca6d47adaf3f719493674cf2363.tar.gz unit-16cbf3c076a0aca6d47adaf3f719493674cf2363.tar.bz2 |
Initial version.
Diffstat (limited to 'src/nxt_log_moderation.c')
-rw-r--r-- | src/nxt_log_moderation.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/nxt_log_moderation.c b/src/nxt_log_moderation.c new file mode 100644 index 00000000..bba379de --- /dev/null +++ b/src/nxt_log_moderation.c @@ -0,0 +1,96 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) NGINX, Inc. + */ + +#include <nxt_main.h> + + +static void nxt_log_moderate_timer_handler(nxt_thread_t *thr, void *obj, + void *data); + + +nxt_bool_t +nxt_log_moderate_allow(nxt_log_moderation_t *mod) +{ + nxt_uint_t n; + nxt_time_t now; + nxt_bool_t allow, timer; + nxt_thread_t *thr; + + thr = nxt_thread(); + now = nxt_thread_time(thr); + + allow = 0; + timer = 0; + + nxt_thread_spin_lock(&mod->lock); + + n = mod->count++; + + if (now != mod->last) { + + if (n <= mod->limit) { + mod->last = now; + mod->count = 1; + allow = 1; + } + + /* "n > mod->limit" means that timer has already been set. */ + + } else { + + if (n < mod->limit) { + allow = 1; + + } else if (n == mod->limit) { + /* + * There is a race condition on 32-bit many core system + * capable to fail an operation 2^32 times per second. + * This can be fixed by storing mod->count as uint64_t. + */ + timer = 1; + mod->pid = nxt_pid; + } + } + + nxt_thread_spin_unlock(&mod->lock); + + if (timer) { + mod->timer.work_queue = &thr->work_queue.main; + mod->timer.handler = nxt_log_moderate_timer_handler; + mod->timer.log = &nxt_main_log; + + nxt_event_timer_add(thr->engine, &mod->timer, 1000); + } + + return allow; +} + + +static void +nxt_log_moderate_timer_handler(nxt_thread_t *thr, void *obj, void *data) +{ + nxt_bool_t msg; + nxt_atomic_uint_t n; + nxt_event_timer_t *ev; + nxt_log_moderation_t *mod; + + ev = obj; + mod = nxt_event_timer_data(ev, nxt_log_moderation_t, timer); + + nxt_thread_spin_lock(&mod->lock); + + mod->last = nxt_thread_time(thr); + n = mod->count; + mod->count = 0; + msg = (mod->pid == nxt_pid); + + nxt_thread_spin_unlock(&mod->lock); + + if (msg) { + nxt_log_error(mod->level, &nxt_main_log, "%s %uA times", + mod->msg, n - mod->limit); + } +} |