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