]> jfr.im git - irc/rqf/shadowircd.git/blame - libratbox/src/event.c
Fix up grammar in ShadowIRCd MOTD for great good!
[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 *
b57f37fb
WP
42 */
43
44#include <libratbox_config.h>
45#include <ratbox_lib.h>
46#include <commio-int.h>
47#include <event-int.h>
48
94b4fbf9
VY
49#define EV_NAME_LEN 33
50static char last_event_ran[EV_NAME_LEN];
b57f37fb
WP
51static rb_dlink_list event_list;
52
53static time_t event_time_min = -1;
b57f37fb
WP
54
55/*
56 * struct ev_entry *
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 */
63static struct ev_entry *
64rb_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
78/*
79 * struct ev_entry *
80 * rb_event_add(const char *name, EVH *func, void *arg, time_t when)
81 *
82 * Input: Name of event, function to call, arguments to pass, and frequency
83 * of the event.
84 * Output: None
85 * Side Effects: Adds the event to the event list.
86 */
87struct ev_entry *
88rb_event_add(const char *name, EVH * func, void *arg, time_t when)
89{
90 struct ev_entry *ev;
91 ev = rb_malloc(sizeof(struct ev_entry));
92 ev->func = func;
94b4fbf9 93 ev->name = rb_strndup(name, EV_NAME_LEN);
b57f37fb
WP
94 ev->arg = arg;
95 ev->when = rb_current_time() + when;
f030cae8 96 ev->next = when;
b57f37fb
WP
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
108struct ev_entry *
109rb_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;
f030cae8 117 ev->next = when;
b57f37fb
WP
118 ev->frequency = 0;
119
120 if((ev->when < event_time_min) || (event_time_min == -1))
121 event_time_min = ev->when;
122
123 rb_dlinkAdd(ev, &ev->node, &event_list);
124 rb_io_sched_event(ev, when);
125 return ev;
126}
127
128/*
129 * void rb_event_delete(struct ev_entry *ev)
130 *
131 * Input: pointer to ev_entry for the event
132 * Output: None
133 * Side Effects: Removes the event from the event list
134 */
135void
136rb_event_delete(struct ev_entry *ev)
137{
138 if(ev == NULL)
139 return;
140
141 rb_dlinkDelete(&ev->node, &event_list);
142 rb_io_unsched_event(ev);
94b4fbf9 143 rb_free(ev->name);
b57f37fb
WP
144 rb_free(ev);
145}
146
147/*
148 * void rb_event_find_delete(EVH *func, void *arg)
149 *
150 * Input: pointer to func and data
151 * Output: None
152 * Side Effects: Removes the event from the event list
153 */
154void
94b4fbf9 155rb_event_find_delete(EVH * func, void *arg)
b57f37fb
WP
156{
157 rb_event_delete(rb_event_find(func, arg));
158}
159
160/*
161 * struct ev_entry *
162 * rb_event_addish(const char *name, EVH *func, void *arg, time_t delta_isa)
163 *
164 * Input: Name of event, function to call, arguments to pass, and frequency
165 * of the event.
166 * Output: None
167 * Side Effects: Adds the event to the event list within +- 1/3 of the
168 * specified frequency.
169 */
170struct ev_entry *
171rb_event_addish(const char *name, EVH * func, void *arg, time_t delta_ish)
172{
173 if(delta_ish >= 3.0)
174 {
175 const time_t two_third = (2 * delta_ish) / 3;
176 delta_ish = two_third + ((rand() % 1000) * two_third) / 1000;
177 /*
178 * XXX I hate the above magic, I don't even know if its right.
179 * Grr. -- adrian
180 */
181 }
182 return rb_event_add(name, func, arg, delta_ish);
183}
184
185
186void
187rb_run_event(struct ev_entry *ev)
188{
94b4fbf9 189 rb_strlcpy(last_event_ran, ev->name, sizeof(last_event_ran));
b57f37fb
WP
190 ev->func(ev->arg);
191 if(!ev->frequency)
192 {
193 rb_io_unsched_event(ev);
194 rb_dlinkDelete(&ev->node, &event_list);
195 rb_free(ev);
196 return;
197 }
198 ev->when = rb_current_time() + ev->frequency;
199 if((ev->when < event_time_min) || (event_time_min == -1))
200 event_time_min = ev->when;
201}
202
203/*
204 * void rb_event_run(void)
205 *
206 * Input: None
207 * Output: None
208 * Side Effects: Runs pending events in the event list
209 */
210void
211rb_event_run(void)
212{
213 rb_dlink_node *ptr, *next;
214 struct ev_entry *ev;
94b4fbf9 215
b57f37fb
WP
216 if(rb_io_supports_event())
217 return;
218
219 event_time_min = -1;
220 RB_DLINK_FOREACH_SAFE(ptr, next, event_list.head)
221 {
222 ev = ptr->data;
223 if(ev->when <= rb_current_time())
224 {
94b4fbf9 225 rb_strlcpy(last_event_ran, ev->name, sizeof(last_event_ran));
b57f37fb
WP
226 ev->func(ev->arg);
227
228 /* event is scheduled more than once */
94b4fbf9 229 if(ev->frequency)
b57f37fb
WP
230 {
231 ev->when = rb_current_time() + ev->frequency;
232 if((ev->when < event_time_min) || (event_time_min == -1))
233 event_time_min = ev->when;
234 }
235 else
236 {
237 rb_dlinkDelete(&ev->node, &event_list);
238 rb_free(ev);
239 }
94b4fbf9
VY
240 }
241 else
242 {
b57f37fb
WP
243 if((ev->when < event_time_min) || (event_time_min == -1))
244 event_time_min = ev->when;
245 }
246 }
247}
248
249void
250rb_event_io_register_all(void)
251{
252 rb_dlink_node *ptr;
253 struct ev_entry *ev;
f030cae8 254
b57f37fb
WP
255 if(!rb_io_supports_event())
256 return;
94b4fbf9 257
b57f37fb 258 RB_DLINK_FOREACH(ptr, event_list.head)
94b4fbf9 259 {
b57f37fb 260 ev = ptr->data;
f030cae8 261 rb_io_sched_event(ev, ev->next);
b57f37fb
WP
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 */
272void
273rb_event_init(void)
274{
94b4fbf9 275 rb_strlcpy(last_event_ran, "NONE", sizeof(last_event_ran));
b57f37fb
WP
276}
277
278void
279rb_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 */
308void
309rb_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
323void
324rb_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
339time_t
340rb_event_next(void)
341{
342 return event_time_min;
343}