xref: /unit/src/nxt_log_moderation.c (revision 1457:af93c866b4f0)
10Sigor@sysoev.ru 
20Sigor@sysoev.ru /*
30Sigor@sysoev.ru  * Copyright (C) Igor Sysoev
40Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
50Sigor@sysoev.ru  */
60Sigor@sysoev.ru 
70Sigor@sysoev.ru #include <nxt_main.h>
80Sigor@sysoev.ru 
90Sigor@sysoev.ru 
101Sigor@sysoev.ru static void nxt_log_moderate_timer_handler(nxt_task_t *task, void *obj,
110Sigor@sysoev.ru     void *data);
120Sigor@sysoev.ru 
130Sigor@sysoev.ru 
140Sigor@sysoev.ru nxt_bool_t
nxt_log_moderate_allow(nxt_log_moderation_t * mod)150Sigor@sysoev.ru nxt_log_moderate_allow(nxt_log_moderation_t *mod)
160Sigor@sysoev.ru {
170Sigor@sysoev.ru     nxt_uint_t    n;
180Sigor@sysoev.ru     nxt_time_t    now;
190Sigor@sysoev.ru     nxt_bool_t    allow, timer;
200Sigor@sysoev.ru     nxt_thread_t  *thr;
210Sigor@sysoev.ru 
220Sigor@sysoev.ru     thr = nxt_thread();
230Sigor@sysoev.ru     now = nxt_thread_time(thr);
240Sigor@sysoev.ru 
250Sigor@sysoev.ru     allow = 0;
260Sigor@sysoev.ru     timer = 0;
270Sigor@sysoev.ru 
280Sigor@sysoev.ru     nxt_thread_spin_lock(&mod->lock);
290Sigor@sysoev.ru 
300Sigor@sysoev.ru     n = mod->count++;
310Sigor@sysoev.ru 
320Sigor@sysoev.ru     if (now != mod->last) {
330Sigor@sysoev.ru 
340Sigor@sysoev.ru         if (n <= mod->limit) {
350Sigor@sysoev.ru             mod->last = now;
360Sigor@sysoev.ru             mod->count = 1;
370Sigor@sysoev.ru             allow = 1;
380Sigor@sysoev.ru         }
390Sigor@sysoev.ru 
400Sigor@sysoev.ru         /* "n > mod->limit" means that timer has already been set. */
410Sigor@sysoev.ru 
420Sigor@sysoev.ru     } else {
430Sigor@sysoev.ru 
440Sigor@sysoev.ru         if (n < mod->limit) {
450Sigor@sysoev.ru             allow = 1;
460Sigor@sysoev.ru 
470Sigor@sysoev.ru         } else if (n == mod->limit) {
480Sigor@sysoev.ru             /*
490Sigor@sysoev.ru              * There is a race condition on 32-bit many core system
500Sigor@sysoev.ru              * capable to fail an operation 2^32 times per second.
510Sigor@sysoev.ru              * This can be fixed by storing mod->count as uint64_t.
520Sigor@sysoev.ru              */
530Sigor@sysoev.ru             timer = 1;
540Sigor@sysoev.ru             mod->pid = nxt_pid;
550Sigor@sysoev.ru         }
560Sigor@sysoev.ru     }
570Sigor@sysoev.ru 
580Sigor@sysoev.ru     nxt_thread_spin_unlock(&mod->lock);
590Sigor@sysoev.ru 
600Sigor@sysoev.ru     if (timer) {
614Sigor@sysoev.ru         mod->timer.work_queue = &thr->engine->fast_work_queue;
620Sigor@sysoev.ru         mod->timer.handler = nxt_log_moderate_timer_handler;
630Sigor@sysoev.ru         mod->timer.log = &nxt_main_log;
64*1457Sigor@sysoev.ru         mod->timer.task = &nxt_main_task;
650Sigor@sysoev.ru 
666Sigor@sysoev.ru         nxt_timer_add(thr->engine, &mod->timer, 1000);
670Sigor@sysoev.ru     }
680Sigor@sysoev.ru 
690Sigor@sysoev.ru     return allow;
700Sigor@sysoev.ru }
710Sigor@sysoev.ru 
720Sigor@sysoev.ru 
730Sigor@sysoev.ru static void
nxt_log_moderate_timer_handler(nxt_task_t * task,void * obj,void * data)741Sigor@sysoev.ru nxt_log_moderate_timer_handler(nxt_task_t *task, void *obj, void *data)
750Sigor@sysoev.ru {
760Sigor@sysoev.ru     nxt_bool_t            msg;
776Sigor@sysoev.ru     nxt_timer_t           *ev;
780Sigor@sysoev.ru     nxt_atomic_uint_t     n;
790Sigor@sysoev.ru     nxt_log_moderation_t  *mod;
800Sigor@sysoev.ru 
810Sigor@sysoev.ru     ev = obj;
826Sigor@sysoev.ru     mod = nxt_timer_data(ev, nxt_log_moderation_t, timer);
830Sigor@sysoev.ru 
840Sigor@sysoev.ru     nxt_thread_spin_lock(&mod->lock);
850Sigor@sysoev.ru 
861Sigor@sysoev.ru     mod->last = nxt_thread_time(task->thread);
870Sigor@sysoev.ru     n = mod->count;
880Sigor@sysoev.ru     mod->count = 0;
890Sigor@sysoev.ru     msg = (mod->pid == nxt_pid);
900Sigor@sysoev.ru 
910Sigor@sysoev.ru     nxt_thread_spin_unlock(&mod->lock);
920Sigor@sysoev.ru 
930Sigor@sysoev.ru     if (msg) {
940Sigor@sysoev.ru         nxt_log_error(mod->level, &nxt_main_log, "%s %uA times",
950Sigor@sysoev.ru                       mod->msg, n - mod->limit);
960Sigor@sysoev.ru     }
970Sigor@sysoev.ru }
98