mirror of
https://github.com/matrix-construct/construct
synced 2024-11-25 16:22:35 +01:00
ea53aab823
* librb is no longer a separately configured subproject. * charybdis is now a standalone directory with a binary. * Include path layout now requires a directory ircd/ rb/ etc.
351 lines
8 KiB
C
351 lines
8 KiB
C
/*
|
|
* ircd-ratbox: A slightly useful ircd.
|
|
* event.c: Event functions.
|
|
*
|
|
* Copyright (C) 1998-2000 Regents of the University of California
|
|
* Copyright (C) 2001-2002 Hybrid Development Team
|
|
* Copyright (C) 2002-2005 ircd-ratbox development team
|
|
*
|
|
* Code borrowed from the squid web cache by Adrian Chadd.
|
|
* Original header:
|
|
*
|
|
* DEBUG: section 41 Event Processing
|
|
* AUTHOR: Henrik Nordstrom
|
|
*
|
|
* SQUID Internet Object Cache http://squid.nlanr.net/Squid/
|
|
* ----------------------------------------------------------
|
|
*
|
|
* Squid is the result of efforts by numerous individuals from the
|
|
* Internet community. Development is led by Duane Wessels of the
|
|
* National Laboratory for Applied Network Research and funded by the
|
|
* National Science Foundation. Squid is Copyrighted (C) 1998 by
|
|
* the Regents of the University of California. Please see the
|
|
* COPYRIGHT file for full details. Squid incorporates software
|
|
* developed and/or copyrighted by other sources. Please see the
|
|
* CREDITS file for full details.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
* USA
|
|
*
|
|
*/
|
|
|
|
#include <rb/rb.h>
|
|
#include <rb/commio_int.h>
|
|
#include <rb/event_int.h>
|
|
|
|
#define EV_NAME_LEN 33
|
|
static char last_event_ran[EV_NAME_LEN];
|
|
static rb_dlink_list event_list;
|
|
|
|
static time_t event_time_min = -1;
|
|
|
|
/*
|
|
* struct ev_entry *
|
|
* rb_event_find(EVH *func, void *arg)
|
|
*
|
|
* Input: Event function and the argument passed to it
|
|
* Output: Index to the slow in the event_table
|
|
* Side Effects: None
|
|
*/
|
|
static struct ev_entry *
|
|
rb_event_find(EVH * func, void *arg)
|
|
{
|
|
rb_dlink_node *ptr;
|
|
struct ev_entry *ev;
|
|
RB_DLINK_FOREACH(ptr, event_list.head)
|
|
{
|
|
ev = ptr->data;
|
|
if((ev->func == func) && (ev->arg == arg))
|
|
return ev;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static
|
|
struct ev_entry *
|
|
rb_event_add_common(const char *name, EVH * func, void *arg, time_t when, time_t frequency)
|
|
{
|
|
struct ev_entry *ev;
|
|
ev = rb_malloc(sizeof(struct ev_entry));
|
|
ev->func = func;
|
|
ev->name = rb_strndup(name, EV_NAME_LEN);
|
|
ev->arg = arg;
|
|
ev->when = rb_current_time() + when;
|
|
ev->next = when;
|
|
ev->frequency = frequency;
|
|
|
|
if((ev->when < event_time_min) || (event_time_min == -1))
|
|
event_time_min = ev->when;
|
|
|
|
rb_dlinkAdd(ev, &ev->node, &event_list);
|
|
rb_io_sched_event(ev, when);
|
|
return ev;
|
|
}
|
|
|
|
/*
|
|
* struct ev_entry *
|
|
* rb_event_add(const char *name, EVH *func, void *arg, time_t when)
|
|
*
|
|
* Input: Name of event, function to call, arguments to pass, and frequency
|
|
* of the event.
|
|
* Output: None
|
|
* Side Effects: Adds the event to the event list.
|
|
*/
|
|
struct ev_entry *
|
|
rb_event_add(const char *name, EVH * func, void *arg, time_t when)
|
|
{
|
|
if (rb_unlikely(when <= 0)) {
|
|
rb_lib_log("rb_event_add: tried to schedule %s event with a delay of "
|
|
"%d seconds", name, (int) when);
|
|
when = 1;
|
|
}
|
|
|
|
return rb_event_add_common(name, func, arg, when, when);
|
|
}
|
|
|
|
struct ev_entry *
|
|
rb_event_addonce(const char *name, EVH * func, void *arg, time_t when)
|
|
{
|
|
if (rb_unlikely(when <= 0)) {
|
|
rb_lib_log("rb_event_addonce: tried to schedule %s event to run in "
|
|
"%d seconds", name, (int) when);
|
|
when = 1;
|
|
}
|
|
|
|
return rb_event_add_common(name, func, arg, when, 0);
|
|
}
|
|
|
|
/*
|
|
* void rb_event_delete(struct ev_entry *ev)
|
|
*
|
|
* Input: pointer to ev_entry for the event
|
|
* Output: None
|
|
* Side Effects: Removes the event from the event list
|
|
*/
|
|
void
|
|
rb_event_delete(struct ev_entry *ev)
|
|
{
|
|
if(ev == NULL)
|
|
return;
|
|
|
|
rb_dlinkDelete(&ev->node, &event_list);
|
|
rb_io_unsched_event(ev);
|
|
rb_free(ev->name);
|
|
rb_free(ev);
|
|
}
|
|
|
|
/*
|
|
* void rb_event_find_delete(EVH *func, void *arg)
|
|
*
|
|
* Input: pointer to func and data
|
|
* Output: None
|
|
* Side Effects: Removes the event from the event list
|
|
*/
|
|
void
|
|
rb_event_find_delete(EVH * func, void *arg)
|
|
{
|
|
rb_event_delete(rb_event_find(func, arg));
|
|
}
|
|
|
|
static time_t
|
|
rb_event_frequency(time_t frequency)
|
|
{
|
|
if(frequency < 0)
|
|
{
|
|
const time_t two_third = (2 * labs(frequency)) / 3;
|
|
frequency = two_third + ((rand() % 1000) * two_third) / 1000;
|
|
}
|
|
return frequency;
|
|
}
|
|
|
|
/*
|
|
* struct ev_entry *
|
|
* rb_event_addish(const char *name, EVH *func, void *arg, time_t delta_isa)
|
|
*
|
|
* Input: Name of event, function to call, arguments to pass, and frequency
|
|
* of the event.
|
|
* Output: None
|
|
* Side Effects: Adds the event to the event list within +- 1/3 of the
|
|
* specified frequency.
|
|
*/
|
|
struct ev_entry *
|
|
rb_event_addish(const char *name, EVH * func, void *arg, time_t delta_ish)
|
|
{
|
|
delta_ish = labs(delta_ish);
|
|
if(delta_ish >= 3.0)
|
|
delta_ish = -delta_ish;
|
|
return rb_event_add_common(name, func, arg,
|
|
rb_event_frequency(delta_ish), delta_ish);
|
|
}
|
|
|
|
|
|
void
|
|
rb_run_one_event(struct ev_entry *ev)
|
|
{
|
|
rb_strlcpy(last_event_ran, ev->name, sizeof(last_event_ran));
|
|
ev->func(ev->arg);
|
|
if(!ev->frequency)
|
|
{
|
|
rb_event_delete(ev);
|
|
return;
|
|
}
|
|
ev->when = rb_current_time() + rb_event_frequency(ev->frequency);
|
|
if((ev->when < event_time_min) || (event_time_min == -1))
|
|
event_time_min = ev->when;
|
|
}
|
|
|
|
/*
|
|
* void rb_event_run(void)
|
|
*
|
|
* Input: None
|
|
* Output: None
|
|
* Side Effects: Runs pending events in the event list
|
|
*/
|
|
void
|
|
rb_event_run(void)
|
|
{
|
|
rb_dlink_node *ptr, *next;
|
|
struct ev_entry *ev;
|
|
|
|
if(rb_io_supports_event())
|
|
return;
|
|
|
|
event_time_min = -1;
|
|
RB_DLINK_FOREACH_SAFE(ptr, next, event_list.head)
|
|
{
|
|
ev = ptr->data;
|
|
if(ev->when <= rb_current_time())
|
|
{
|
|
rb_strlcpy(last_event_ran, ev->name, sizeof(last_event_ran));
|
|
ev->func(ev->arg);
|
|
|
|
/* event is scheduled more than once */
|
|
if(ev->frequency)
|
|
{
|
|
ev->when = rb_current_time() + rb_event_frequency(ev->frequency);
|
|
if((ev->when < event_time_min) || (event_time_min == -1))
|
|
event_time_min = ev->when;
|
|
}
|
|
else
|
|
{
|
|
rb_dlinkDelete(&ev->node, &event_list);
|
|
rb_free(ev);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if((ev->when < event_time_min) || (event_time_min == -1))
|
|
event_time_min = ev->when;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
rb_event_io_register_all(void)
|
|
{
|
|
rb_dlink_node *ptr;
|
|
struct ev_entry *ev;
|
|
|
|
if(!rb_io_supports_event())
|
|
return;
|
|
|
|
RB_DLINK_FOREACH(ptr, event_list.head)
|
|
{
|
|
ev = ptr->data;
|
|
rb_io_sched_event(ev, ev->next);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* void rb_event_init(void)
|
|
*
|
|
* Input: None
|
|
* Output: None
|
|
* Side Effects: Initializes the event system.
|
|
*/
|
|
void
|
|
rb_event_init(void)
|
|
{
|
|
rb_strlcpy(last_event_ran, "NONE", sizeof(last_event_ran));
|
|
}
|
|
|
|
void
|
|
rb_dump_events(void (*func) (char *, void *), void *ptr)
|
|
{
|
|
int len;
|
|
char buf[512];
|
|
rb_dlink_node *dptr;
|
|
struct ev_entry *ev;
|
|
len = sizeof(buf);
|
|
|
|
snprintf(buf, len, "Last event to run: %s", last_event_ran);
|
|
func(buf, ptr);
|
|
|
|
rb_strlcpy(buf, "Operation Next Execution", len);
|
|
func(buf, ptr);
|
|
|
|
RB_DLINK_FOREACH(dptr, event_list.head)
|
|
{
|
|
ev = dptr->data;
|
|
snprintf(buf, len, "%-28s %-4ld seconds (frequency=%d)", ev->name,
|
|
ev->when - (long)rb_current_time(), (int)ev->frequency);
|
|
func(buf, ptr);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* void rb_set_back_events(time_t by)
|
|
* Input: Time to set back events by.
|
|
* Output: None.
|
|
* Side-effects: Sets back all events by "by" seconds.
|
|
*/
|
|
void
|
|
rb_set_back_events(time_t by)
|
|
{
|
|
rb_dlink_node *ptr;
|
|
struct ev_entry *ev;
|
|
RB_DLINK_FOREACH(ptr, event_list.head)
|
|
{
|
|
ev = ptr->data;
|
|
if(ev->when > by)
|
|
ev->when -= by;
|
|
else
|
|
ev->when = 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
rb_event_update(struct ev_entry *ev, time_t freq)
|
|
{
|
|
if(ev == NULL)
|
|
return;
|
|
|
|
ev->frequency = freq;
|
|
|
|
/* update when it's scheduled to run if it's higher
|
|
* than the new frequency
|
|
*/
|
|
time_t next = rb_event_frequency(freq);
|
|
if((rb_current_time() + next) < ev->when)
|
|
ev->when = rb_current_time() + next;
|
|
return;
|
|
}
|
|
|
|
time_t
|
|
rb_event_next(void)
|
|
{
|
|
return event_time_min;
|
|
}
|