]>
Commit | Line | Data |
---|---|---|
b57f37fb WP |
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 | * | |
94b4fbf9 | 42 | * $Id: event.c 26092 2008-09-19 15:13:52Z androsyn $ |
b57f37fb WP |
43 | */ |
44 | ||
45 | #include <libratbox_config.h> | |
46 | #include <ratbox_lib.h> | |
47 | #include <commio-int.h> | |
48 | #include <event-int.h> | |
49 | ||
94b4fbf9 VY |
50 | #define EV_NAME_LEN 33 |
51 | static char last_event_ran[EV_NAME_LEN]; | |
b57f37fb WP |
52 | static rb_dlink_list event_list; |
53 | ||
54 | static time_t event_time_min = -1; | |
b57f37fb WP |
55 | |
56 | /* | |
57 | * struct ev_entry * | |
58 | * rb_event_find(EVH *func, void *arg) | |
59 | * | |
60 | * Input: Event function and the argument passed to it | |
61 | * Output: Index to the slow in the event_table | |
62 | * Side Effects: None | |
63 | */ | |
64 | static struct ev_entry * | |
65 | rb_event_find(EVH * func, void *arg) | |
66 | { | |
67 | rb_dlink_node *ptr; | |
68 | struct ev_entry *ev; | |
69 | RB_DLINK_FOREACH(ptr, event_list.head) | |
70 | { | |
71 | ev = ptr->data; | |
72 | if((ev->func == func) && (ev->arg == arg)) | |
73 | return ev; | |
74 | } | |
75 | ||
76 | return NULL; | |
77 | } | |
78 | ||
79 | /* | |
80 | * struct ev_entry * | |
81 | * rb_event_add(const char *name, EVH *func, void *arg, time_t when) | |
82 | * | |
83 | * Input: Name of event, function to call, arguments to pass, and frequency | |
84 | * of the event. | |
85 | * Output: None | |
86 | * Side Effects: Adds the event to the event list. | |
87 | */ | |
88 | struct ev_entry * | |
89 | rb_event_add(const char *name, EVH * func, void *arg, time_t when) | |
90 | { | |
91 | struct ev_entry *ev; | |
92 | ev = rb_malloc(sizeof(struct ev_entry)); | |
93 | ev->func = func; | |
94b4fbf9 | 94 | ev->name = rb_strndup(name, EV_NAME_LEN); |
b57f37fb WP |
95 | ev->arg = arg; |
96 | ev->when = rb_current_time() + when; | |
97 | ev->frequency = when; | |
98 | ||
99 | if((ev->when < event_time_min) || (event_time_min == -1)) | |
100 | { | |
101 | event_time_min = ev->when; | |
102 | } | |
103 | rb_dlinkAdd(ev, &ev->node, &event_list); | |
104 | rb_io_sched_event(ev, when); | |
105 | return ev; | |
106 | } | |
94b4fbf9 | 107 | |
b57f37fb WP |
108 | struct ev_entry * |
109 | rb_event_addonce(const char *name, EVH * func, void *arg, time_t when) | |
110 | { | |
111 | struct ev_entry *ev; | |
112 | ev = rb_malloc(sizeof(struct ev_entry)); | |
113 | ev->func = func; | |
94b4fbf9 | 114 | ev->name = rb_strndup(name, EV_NAME_LEN); |
b57f37fb WP |
115 | ev->arg = arg; |
116 | ev->when = rb_current_time() + when; | |
117 | ev->frequency = 0; | |
118 | ||
119 | if((ev->when < event_time_min) || (event_time_min == -1)) | |
120 | event_time_min = ev->when; | |
121 | ||
122 | rb_dlinkAdd(ev, &ev->node, &event_list); | |
123 | rb_io_sched_event(ev, when); | |
124 | return ev; | |
125 | } | |
126 | ||
127 | /* | |
128 | * void rb_event_delete(struct ev_entry *ev) | |
129 | * | |
130 | * Input: pointer to ev_entry for the event | |
131 | * Output: None | |
132 | * Side Effects: Removes the event from the event list | |
133 | */ | |
134 | void | |
135 | rb_event_delete(struct ev_entry *ev) | |
136 | { | |
137 | if(ev == NULL) | |
138 | return; | |
139 | ||
140 | rb_dlinkDelete(&ev->node, &event_list); | |
141 | rb_io_unsched_event(ev); | |
94b4fbf9 | 142 | rb_free(ev->name); |
b57f37fb WP |
143 | rb_free(ev); |
144 | } | |
145 | ||
146 | /* | |
147 | * void rb_event_find_delete(EVH *func, void *arg) | |
148 | * | |
149 | * Input: pointer to func and data | |
150 | * Output: None | |
151 | * Side Effects: Removes the event from the event list | |
152 | */ | |
153 | void | |
94b4fbf9 | 154 | rb_event_find_delete(EVH * func, void *arg) |
b57f37fb WP |
155 | { |
156 | rb_event_delete(rb_event_find(func, arg)); | |
157 | } | |
158 | ||
159 | /* | |
160 | * struct ev_entry * | |
161 | * rb_event_addish(const char *name, EVH *func, void *arg, time_t delta_isa) | |
162 | * | |
163 | * Input: Name of event, function to call, arguments to pass, and frequency | |
164 | * of the event. | |
165 | * Output: None | |
166 | * Side Effects: Adds the event to the event list within +- 1/3 of the | |
167 | * specified frequency. | |
168 | */ | |
169 | struct ev_entry * | |
170 | rb_event_addish(const char *name, EVH * func, void *arg, time_t delta_ish) | |
171 | { | |
172 | if(delta_ish >= 3.0) | |
173 | { | |
174 | const time_t two_third = (2 * delta_ish) / 3; | |
175 | delta_ish = two_third + ((rand() % 1000) * two_third) / 1000; | |
176 | /* | |
177 | * XXX I hate the above magic, I don't even know if its right. | |
178 | * Grr. -- adrian | |
179 | */ | |
180 | } | |
181 | return rb_event_add(name, func, arg, delta_ish); | |
182 | } | |
183 | ||
184 | ||
185 | void | |
186 | rb_run_event(struct ev_entry *ev) | |
187 | { | |
94b4fbf9 | 188 | rb_strlcpy(last_event_ran, ev->name, sizeof(last_event_ran)); |
b57f37fb WP |
189 | ev->func(ev->arg); |
190 | if(!ev->frequency) | |
191 | { | |
192 | rb_io_unsched_event(ev); | |
193 | rb_dlinkDelete(&ev->node, &event_list); | |
194 | rb_free(ev); | |
195 | return; | |
196 | } | |
197 | ev->when = rb_current_time() + ev->frequency; | |
198 | if((ev->when < event_time_min) || (event_time_min == -1)) | |
199 | event_time_min = ev->when; | |
200 | } | |
201 | ||
202 | /* | |
203 | * void rb_event_run(void) | |
204 | * | |
205 | * Input: None | |
206 | * Output: None | |
207 | * Side Effects: Runs pending events in the event list | |
208 | */ | |
209 | void | |
210 | rb_event_run(void) | |
211 | { | |
212 | rb_dlink_node *ptr, *next; | |
213 | struct ev_entry *ev; | |
94b4fbf9 | 214 | |
b57f37fb WP |
215 | if(rb_io_supports_event()) |
216 | return; | |
217 | ||
218 | event_time_min = -1; | |
219 | RB_DLINK_FOREACH_SAFE(ptr, next, event_list.head) | |
220 | { | |
221 | ev = ptr->data; | |
222 | if(ev->when <= rb_current_time()) | |
223 | { | |
94b4fbf9 | 224 | rb_strlcpy(last_event_ran, ev->name, sizeof(last_event_ran)); |
b57f37fb WP |
225 | ev->func(ev->arg); |
226 | ||
227 | /* event is scheduled more than once */ | |
94b4fbf9 | 228 | if(ev->frequency) |
b57f37fb WP |
229 | { |
230 | ev->when = rb_current_time() + ev->frequency; | |
231 | if((ev->when < event_time_min) || (event_time_min == -1)) | |
232 | event_time_min = ev->when; | |
233 | } | |
234 | else | |
235 | { | |
236 | rb_dlinkDelete(&ev->node, &event_list); | |
237 | rb_free(ev); | |
238 | } | |
94b4fbf9 VY |
239 | } |
240 | else | |
241 | { | |
b57f37fb WP |
242 | if((ev->when < event_time_min) || (event_time_min == -1)) |
243 | event_time_min = ev->when; | |
244 | } | |
245 | } | |
246 | } | |
247 | ||
248 | void | |
249 | rb_event_io_register_all(void) | |
250 | { | |
251 | rb_dlink_node *ptr; | |
252 | struct ev_entry *ev; | |
253 | int when; | |
254 | if(!rb_io_supports_event()) | |
255 | return; | |
94b4fbf9 | 256 | |
b57f37fb | 257 | RB_DLINK_FOREACH(ptr, event_list.head) |
94b4fbf9 | 258 | { |
b57f37fb WP |
259 | ev = ptr->data; |
260 | when = ev->when - rb_current_time(); | |
261 | rb_io_sched_event(ev, when); | |
262 | } | |
263 | } | |
94b4fbf9 | 264 | |
b57f37fb WP |
265 | /* |
266 | * void rb_event_init(void) | |
267 | * | |
268 | * Input: None | |
269 | * Output: None | |
270 | * Side Effects: Initializes the event system. | |
271 | */ | |
272 | void | |
273 | rb_event_init(void) | |
274 | { | |
94b4fbf9 | 275 | rb_strlcpy(last_event_ran, "NONE", sizeof(last_event_ran)); |
b57f37fb WP |
276 | } |
277 | ||
278 | void | |
279 | rb_dump_events(void (*func) (char *, void *), void *ptr) | |
280 | { | |
281 | int len; | |
282 | char buf[512]; | |
283 | rb_dlink_node *dptr; | |
284 | struct ev_entry *ev; | |
285 | len = sizeof(buf); | |
94b4fbf9 VY |
286 | |
287 | rb_snprintf(buf, len, "Last event to run: %s", last_event_ran); | |
288 | func(buf, ptr); | |
289 | ||
b57f37fb WP |
290 | rb_strlcpy(buf, "Operation Next Execution", len); |
291 | func(buf, ptr); | |
292 | ||
293 | RB_DLINK_FOREACH(dptr, event_list.head) | |
294 | { | |
295 | ev = dptr->data; | |
296 | rb_snprintf(buf, len, "%-28s %-4ld seconds", ev->name, | |
94b4fbf9 | 297 | ev->when - (long)rb_current_time()); |
b57f37fb WP |
298 | func(buf, ptr); |
299 | } | |
300 | } | |
301 | ||
302 | /* | |
303 | * void rb_set_back_events(time_t by) | |
304 | * Input: Time to set back events by. | |
305 | * Output: None. | |
306 | * Side-effects: Sets back all events by "by" seconds. | |
307 | */ | |
308 | void | |
309 | rb_set_back_events(time_t by) | |
310 | { | |
311 | rb_dlink_node *ptr; | |
312 | struct ev_entry *ev; | |
313 | RB_DLINK_FOREACH(ptr, event_list.head) | |
314 | { | |
315 | ev = ptr->data; | |
316 | if(ev->when > by) | |
317 | ev->when -= by; | |
318 | else | |
319 | ev->when = 0; | |
320 | } | |
321 | } | |
322 | ||
323 | void | |
324 | rb_event_update(struct ev_entry *ev, time_t freq) | |
325 | { | |
326 | if(ev == NULL) | |
327 | return; | |
328 | ||
329 | ev->frequency = freq; | |
330 | ||
331 | /* update when its scheduled to run if its higher | |
332 | * than the new frequency | |
333 | */ | |
334 | if((rb_current_time() + freq) < ev->when) | |
335 | ev->when = rb_current_time() + freq; | |
336 | return; | |
337 | } | |
338 | ||
339 | time_t | |
340 | rb_event_next(void) | |
341 | { | |
342 | return event_time_min; | |
343 | } |