blob: d4b13c4fbb420930f3d1aeb0c803117a1b3b81f2 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
/* Copyright (c) 2016-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "time-util.h"
#include "log-throttle.h"
struct log_throttle {
struct log_throttle_settings set;
log_throttle_callback_t *callback;
void *context;
struct timeval last_time;
unsigned int last_count;
struct timeout *to_throttled;
};
#undef log_throttle_init
struct log_throttle *
log_throttle_init(const struct log_throttle_settings *set,
log_throttle_callback_t *callback, void *context)
{
struct log_throttle *throttle;
i_assert(set->throttle_at_max_per_interval > 0);
i_assert(set->unthrottle_at_max_per_interval > 0);
throttle = i_new(struct log_throttle, 1);
throttle->set = *set;
if (throttle->set.interval_msecs == 0)
throttle->set.interval_msecs = 1000;
throttle->callback = callback;
throttle->context = context;
throttle->last_time = ioloop_timeval;
return throttle;
}
void log_throttle_deinit(struct log_throttle **_throttle)
{
struct log_throttle *throttle = *_throttle;
*_throttle = NULL;
timeout_remove(&throttle->to_throttled);
i_free(throttle);
}
static void log_throttle_callback(struct log_throttle *throttle)
{
if (throttle->last_count > 0)
throttle->callback(throttle->last_count, throttle->context);
if (throttle->last_count < throttle->set.unthrottle_at_max_per_interval)
timeout_remove(&throttle->to_throttled);
throttle->last_count = 0;
}
bool log_throttle_accept(struct log_throttle *throttle)
{
if (throttle->to_throttled != NULL) {
/* unthrottling and last_count resets are done only by
the callback */
throttle->last_count++;
return FALSE;
} else if (timeval_diff_msecs(&ioloop_timeval, &throttle->last_time) >=
(int)throttle->set.interval_msecs) {
throttle->last_time = ioloop_timeval;
throttle->last_count = 1;
return TRUE;
} else if (++throttle->last_count <= throttle->set.throttle_at_max_per_interval) {
return TRUE;
} else {
throttle->last_count = 1;
throttle->to_throttled =
timeout_add(throttle->set.interval_msecs,
log_throttle_callback, throttle);
return FALSE;
}
}
|