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