]>
Commit | Line | Data |
---|---|---|
db137867 AC |
1 | /* |
2 | * ircd-ratbox: A slightly useful ircd. | |
3 | * event.c: Event functions. | |
4 | * | |
5 | * Copyright (C) 1998-2000 Regents of the University of California | |
6 | * Copyright (C) 2001-2002 Hybrid Development Team | |
7 | * Copyright (C) 2002-2005 ircd-ratbox development team | |
8 | * | |
9 | * Code borrowed from the squid web cache by Adrian Chadd. | |
10 | * Original header: | |
11 | * | |
12 | * DEBUG: section 41 Event Processing | |
13 | * AUTHOR: Henrik Nordstrom | |
14 | * | |
15 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ | |
16 | * ---------------------------------------------------------- | |
17 | * | |
18 | * Squid is the result of efforts by numerous individuals from the | |
19 | * Internet community. Development is led by Duane Wessels of the | |
20 | * National Laboratory for Applied Network Research and funded by the | |
21 | * National Science Foundation. Squid is Copyrighted (C) 1998 by | |
22 | * the Regents of the University of California. Please see the | |
23 | * COPYRIGHT file for full details. Squid incorporates software | |
24 | * developed and/or copyrighted by other sources. Please see the | |
25 | * CREDITS file for full details. | |
26 | * | |
27 | * This program is free software; you can redistribute it and/or modify | |
28 | * it under the terms of the GNU General Public License as published by | |
29 | * the Free Software Foundation; either version 2 of the License, or | |
30 | * (at your option) any later version. | |
31 | * | |
32 | * This program is distributed in the hope that it will be useful, | |
33 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
34 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
35 | * GNU General Public License for more details. | |
36 | * | |
37 | * You should have received a copy of the GNU General Public License | |
38 | * along with this program; if not, write to the Free Software | |
39 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 | |
40 | * USA | |
41 | * | |
db137867 AC |
42 | */ |
43 | ||
fe037171 EM |
44 | #include <librb_config.h> |
45 | #include <rb_lib.h> | |
db137867 AC |
46 | #include <commio-int.h> |
47 | #include <event-int.h> | |
48 | ||
3202e249 VY |
49 | #define EV_NAME_LEN 33 |
50 | static char last_event_ran[EV_NAME_LEN]; | |
db137867 AC |
51 | static rb_dlink_list event_list; |
52 | ||
53 | static time_t event_time_min = -1; | |
db137867 AC |
54 | |
55 | /* | |
55abcbb2 | 56 | * struct ev_entry * |
db137867 AC |
57 | * rb_event_find(EVH *func, void *arg) |
58 | * | |
59 | * Input: Event function and the argument passed to it | |
60 | * Output: Index to the slow in the event_table | |
61 | * Side Effects: None | |
62 | */ | |
63 | static struct ev_entry * | |
64 | rb_event_find(EVH * func, void *arg) | |
65 | { | |
66 | rb_dlink_node *ptr; | |
67 | struct ev_entry *ev; | |
68 | RB_DLINK_FOREACH(ptr, event_list.head) | |
69 | { | |
70 | ev = ptr->data; | |
71 | if((ev->func == func) && (ev->arg == arg)) | |
72 | return ev; | |
73 | } | |
74 | ||
75 | return NULL; | |
76 | } | |
77 | ||
8ace0906 SA |
78 | static |
79 | struct ev_entry * | |
80 | rb_event_add_common(const char *name, EVH * func, void *arg, time_t when, time_t frequency) | |
81 | { | |
82 | struct ev_entry *ev; | |
83 | ev = rb_malloc(sizeof(struct ev_entry)); | |
84 | ev->func = func; | |
85 | ev->name = rb_strndup(name, EV_NAME_LEN); | |
86 | ev->arg = arg; | |
87 | ev->when = rb_current_time() + when; | |
88 | ev->next = when; | |
89 | ev->frequency = frequency; | |
3576d1b4 | 90 | ev->dead = 0; |
8ace0906 SA |
91 | |
92 | if((ev->when < event_time_min) || (event_time_min == -1)) | |
93 | event_time_min = ev->when; | |
94 | ||
95 | rb_dlinkAdd(ev, &ev->node, &event_list); | |
96 | rb_io_sched_event(ev, when); | |
97 | return ev; | |
98 | } | |
99 | ||
db137867 | 100 | /* |
55abcbb2 | 101 | * struct ev_entry * |
db137867 AC |
102 | * rb_event_add(const char *name, EVH *func, void *arg, time_t when) |
103 | * | |
104 | * Input: Name of event, function to call, arguments to pass, and frequency | |
105 | * of the event. | |
106 | * Output: None | |
107 | * Side Effects: Adds the event to the event list. | |
108 | */ | |
109 | struct ev_entry * | |
110 | rb_event_add(const char *name, EVH * func, void *arg, time_t when) | |
111 | { | |
8db50c03 KB |
112 | if (rb_unlikely(when <= 0)) { |
113 | rb_lib_log("rb_event_add: tried to schedule %s event with a delay of " | |
114 | "%d seconds", name, (int) when); | |
115 | when = 1; | |
116 | } | |
db137867 | 117 | |
8ace0906 | 118 | return rb_event_add_common(name, func, arg, when, when); |
db137867 | 119 | } |
3202e249 | 120 | |
db137867 AC |
121 | struct ev_entry * |
122 | rb_event_addonce(const char *name, EVH * func, void *arg, time_t when) | |
123 | { | |
8db50c03 KB |
124 | if (rb_unlikely(when <= 0)) { |
125 | rb_lib_log("rb_event_addonce: tried to schedule %s event to run in " | |
126 | "%d seconds", name, (int) when); | |
127 | when = 1; | |
128 | } | |
db137867 | 129 | |
8ace0906 | 130 | return rb_event_add_common(name, func, arg, when, 0); |
db137867 AC |
131 | } |
132 | ||
133 | /* | |
134 | * void rb_event_delete(struct ev_entry *ev) | |
135 | * | |
136 | * Input: pointer to ev_entry for the event | |
137 | * Output: None | |
138 | * Side Effects: Removes the event from the event list | |
139 | */ | |
140 | void | |
141 | rb_event_delete(struct ev_entry *ev) | |
142 | { | |
143 | if(ev == NULL) | |
144 | return; | |
145 | ||
3576d1b4 EK |
146 | ev->dead = 1; |
147 | ||
db137867 | 148 | rb_io_unsched_event(ev); |
db137867 AC |
149 | } |
150 | ||
151 | /* | |
152 | * void rb_event_find_delete(EVH *func, void *arg) | |
153 | * | |
154 | * Input: pointer to func and data | |
155 | * Output: None | |
156 | * Side Effects: Removes the event from the event list | |
157 | */ | |
158 | void | |
3202e249 | 159 | rb_event_find_delete(EVH * func, void *arg) |
db137867 AC |
160 | { |
161 | rb_event_delete(rb_event_find(func, arg)); | |
162 | } | |
163 | ||
8ace0906 SA |
164 | static time_t |
165 | rb_event_frequency(time_t frequency) | |
166 | { | |
167 | if(frequency < 0) | |
168 | { | |
a1125230 | 169 | const time_t two_third = (2 * labs(frequency)) / 3; |
8ace0906 SA |
170 | frequency = two_third + ((rand() % 1000) * two_third) / 1000; |
171 | } | |
172 | return frequency; | |
173 | } | |
174 | ||
55abcbb2 | 175 | /* |
db137867 AC |
176 | * struct ev_entry * |
177 | * rb_event_addish(const char *name, EVH *func, void *arg, time_t delta_isa) | |
178 | * | |
179 | * Input: Name of event, function to call, arguments to pass, and frequency | |
180 | * of the event. | |
181 | * Output: None | |
182 | * Side Effects: Adds the event to the event list within +- 1/3 of the | |
183 | * specified frequency. | |
184 | */ | |
185 | struct ev_entry * | |
186 | rb_event_addish(const char *name, EVH * func, void *arg, time_t delta_ish) | |
187 | { | |
a1125230 | 188 | delta_ish = labs(delta_ish); |
db137867 | 189 | if(delta_ish >= 3.0) |
8ace0906 SA |
190 | delta_ish = -delta_ish; |
191 | return rb_event_add_common(name, func, arg, | |
192 | rb_event_frequency(delta_ish), delta_ish); | |
db137867 AC |
193 | } |
194 | ||
195 | ||
196 | void | |
0e651b14 | 197 | rb_run_one_event(struct ev_entry *ev) |
db137867 | 198 | { |
3202e249 | 199 | rb_strlcpy(last_event_ran, ev->name, sizeof(last_event_ran)); |
db137867 AC |
200 | ev->func(ev->arg); |
201 | if(!ev->frequency) | |
202 | { | |
1d393245 | 203 | rb_event_delete(ev); |
db137867 AC |
204 | return; |
205 | } | |
8ace0906 | 206 | ev->when = rb_current_time() + rb_event_frequency(ev->frequency); |
db137867 AC |
207 | if((ev->when < event_time_min) || (event_time_min == -1)) |
208 | event_time_min = ev->when; | |
209 | } | |
210 | ||
211 | /* | |
212 | * void rb_event_run(void) | |
213 | * | |
214 | * Input: None | |
215 | * Output: None | |
216 | * Side Effects: Runs pending events in the event list | |
217 | */ | |
218 | void | |
219 | rb_event_run(void) | |
220 | { | |
221 | rb_dlink_node *ptr, *next; | |
222 | struct ev_entry *ev; | |
3202e249 | 223 | |
db137867 AC |
224 | if(rb_io_supports_event()) |
225 | return; | |
226 | ||
227 | event_time_min = -1; | |
228 | RB_DLINK_FOREACH_SAFE(ptr, next, event_list.head) | |
229 | { | |
230 | ev = ptr->data; | |
3576d1b4 EK |
231 | if (ev->dead) |
232 | { | |
233 | rb_dlinkDelete(&ev->node, &event_list); | |
234 | rb_free(ev->name); | |
235 | rb_free(ev); | |
236 | continue; | |
237 | } | |
db137867 AC |
238 | if(ev->when <= rb_current_time()) |
239 | { | |
3202e249 | 240 | rb_strlcpy(last_event_ran, ev->name, sizeof(last_event_ran)); |
db137867 AC |
241 | ev->func(ev->arg); |
242 | ||
243 | /* event is scheduled more than once */ | |
3202e249 | 244 | if(ev->frequency) |
db137867 | 245 | { |
8ace0906 | 246 | ev->when = rb_current_time() + rb_event_frequency(ev->frequency); |
db137867 AC |
247 | if((ev->when < event_time_min) || (event_time_min == -1)) |
248 | event_time_min = ev->when; | |
249 | } | |
250 | else | |
251 | { | |
252 | rb_dlinkDelete(&ev->node, &event_list); | |
253 | rb_free(ev); | |
254 | } | |
3202e249 VY |
255 | } |
256 | else | |
257 | { | |
db137867 AC |
258 | if((ev->when < event_time_min) || (event_time_min == -1)) |
259 | event_time_min = ev->when; | |
260 | } | |
261 | } | |
262 | } | |
263 | ||
264 | void | |
265 | rb_event_io_register_all(void) | |
266 | { | |
267 | rb_dlink_node *ptr; | |
268 | struct ev_entry *ev; | |
030272f3 | 269 | |
db137867 AC |
270 | if(!rb_io_supports_event()) |
271 | return; | |
3202e249 | 272 | |
db137867 | 273 | RB_DLINK_FOREACH(ptr, event_list.head) |
3202e249 | 274 | { |
db137867 | 275 | ev = ptr->data; |
030272f3 | 276 | rb_io_sched_event(ev, ev->next); |
db137867 AC |
277 | } |
278 | } | |
3202e249 | 279 | |
db137867 AC |
280 | /* |
281 | * void rb_event_init(void) | |
282 | * | |
283 | * Input: None | |
284 | * Output: None | |
55abcbb2 | 285 | * Side Effects: Initializes the event system. |
db137867 AC |
286 | */ |
287 | void | |
288 | rb_event_init(void) | |
289 | { | |
3202e249 | 290 | rb_strlcpy(last_event_ran, "NONE", sizeof(last_event_ran)); |
db137867 AC |
291 | } |
292 | ||
293 | void | |
294 | rb_dump_events(void (*func) (char *, void *), void *ptr) | |
295 | { | |
296 | int len; | |
297 | char buf[512]; | |
298 | rb_dlink_node *dptr; | |
299 | struct ev_entry *ev; | |
300 | len = sizeof(buf); | |
3202e249 | 301 | |
5203cba5 | 302 | snprintf(buf, len, "Last event to run: %s", last_event_ran); |
3202e249 VY |
303 | func(buf, ptr); |
304 | ||
db137867 AC |
305 | rb_strlcpy(buf, "Operation Next Execution", len); |
306 | func(buf, ptr); | |
307 | ||
308 | RB_DLINK_FOREACH(dptr, event_list.head) | |
309 | { | |
310 | ev = dptr->data; | |
8ace0906 SA |
311 | snprintf(buf, len, "%-28s %-4ld seconds (frequency=%d)", ev->name, |
312 | ev->when - (long)rb_current_time(), (int)ev->frequency); | |
db137867 AC |
313 | func(buf, ptr); |
314 | } | |
315 | } | |
316 | ||
55abcbb2 | 317 | /* |
db137867 AC |
318 | * void rb_set_back_events(time_t by) |
319 | * Input: Time to set back events by. | |
320 | * Output: None. | |
321 | * Side-effects: Sets back all events by "by" seconds. | |
322 | */ | |
323 | void | |
324 | rb_set_back_events(time_t by) | |
325 | { | |
326 | rb_dlink_node *ptr; | |
327 | struct ev_entry *ev; | |
328 | RB_DLINK_FOREACH(ptr, event_list.head) | |
329 | { | |
330 | ev = ptr->data; | |
331 | if(ev->when > by) | |
332 | ev->when -= by; | |
333 | else | |
334 | ev->when = 0; | |
335 | } | |
336 | } | |
337 | ||
338 | void | |
339 | rb_event_update(struct ev_entry *ev, time_t freq) | |
340 | { | |
341 | if(ev == NULL) | |
342 | return; | |
343 | ||
344 | ev->frequency = freq; | |
345 | ||
8ace0906 | 346 | /* update when it's scheduled to run if it's higher |
db137867 AC |
347 | * than the new frequency |
348 | */ | |
8ace0906 SA |
349 | time_t next = rb_event_frequency(freq); |
350 | if((rb_current_time() + next) < ev->when) | |
351 | ev->when = rb_current_time() + next; | |
db137867 AC |
352 | return; |
353 | } | |
354 | ||
355 | time_t | |
356 | rb_event_next(void) | |
357 | { | |
358 | return event_time_min; | |
359 | } |