unrealircd- supernets unrealircd source & configuration |
git clone git://git.acid.vegas/unrealircd.git |
Log | Files | Refs | Archive | README | LICENSE |
api-event.c (5877B)
1 /************************************************************************ 2 * IRC - Internet Relay Chat, api-event.c 3 * (C) 2001- Carsten Munk (Techie/Stskeeps) <stskeeps@tspre.org> 4 * and the UnrealIRCd team 5 * 6 * See file AUTHORS in IRC package for additional names of 7 * the programmers. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 1, or (at your option) 12 * any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 */ 23 24 #include "unrealircd.h" 25 26 ID_Copyright("(C) Carsten Munk 2001"); 27 28 MODVAR Event *events = NULL; 29 30 /** Add an event, a function that will run at regular intervals. 31 * @param module Module that this event belongs to 32 * @param name Name of the event 33 * @param event The EVENT(function) to be called 34 * @param data The data to be passed to the function (or just NULL) 35 * @param every_msec Every <this> milliseconds the event will be called, but see notes. 36 * @param count After how many times we should stop calling this even (0 = infinite times) 37 * @returns an Event struct 38 * @note UnrealIRCd will try to call the event every 'every_msec' milliseconds. 39 * However, in case of low traffic the minimum time is at least SOCKETLOOP_MAX_DELAY 40 * which is 250ms at the time of writing. Also, we reject any value below 100 msecs. 41 * The actual calling time will not be quicker than the specified every_msec but 42 * can be later, in case of high load, in very extreme cases even up to 1000 or 2000 43 * msec later but that would be very unusual. Just saying, it's not a guarantee.. 44 */ 45 Event *EventAdd(Module *module, const char *name, vFP event, void *data, long every_msec, int count) 46 { 47 Event *newevent; 48 49 if (!name || (every_msec < 0) || (count < 0) || !event) 50 { 51 if (module) 52 module->errorcode = MODERR_INVALID; 53 return NULL; 54 } 55 56 newevent = safe_alloc(sizeof(Event)); 57 safe_strdup(newevent->name, name); 58 newevent->count = count; 59 newevent->every_msec = every_msec; 60 newevent->event = event; 61 newevent->data = data; 62 newevent->last_run.tv_sec = timeofday_tv.tv_sec; 63 newevent->last_run.tv_usec = timeofday_tv.tv_usec; 64 newevent->owner = module; 65 AddListItem(newevent,events); 66 if (module) 67 { 68 ModuleObject *eventobj = safe_alloc(sizeof(ModuleObject)); 69 eventobj->object.event = newevent; 70 eventobj->type = MOBJ_EVENT; 71 AddListItem(eventobj, module->objects); 72 module->errorcode = MODERR_NOERROR; 73 } 74 return newevent; 75 76 } 77 78 /** Mark the Event for deletion. 79 * The actual deletion of the event happens later on 80 * (which is of no concern to the caller). 81 */ 82 void EventDel(Event *e) 83 { 84 char buf[128]; 85 86 /* Mark for deletion */ 87 e->deleted = 1; 88 89 /* Replace the name so deleted events are clearly labeled */ 90 if (e->name) 91 { 92 snprintf(buf, sizeof(buf), "deleted:%s", e->name); 93 safe_strdup(e->name, buf); 94 } 95 96 /* Remove the event from the module, that is something we can safely do straight away */ 97 if (e->owner) 98 { 99 ModuleObject *eventobjs; 100 for (eventobjs = e->owner->objects; eventobjs; eventobjs = eventobjs->next) 101 { 102 if (eventobjs->type == MOBJ_EVENT && eventobjs->object.event == e) 103 { 104 DelListItem(eventobjs, e->owner->objects); 105 safe_free(eventobjs); 106 break; 107 } 108 } 109 e->owner = NULL; 110 } 111 } 112 113 /** Remove the event for real, used only via CleanupEvents(), not for end-users. */ 114 static void EventDelReal(Event *e) 115 { 116 if (!e->deleted) 117 { 118 unreal_log(ULOG_FATAL, "module", "BUG_EVENTDELREAL_ZERO", NULL, 119 "[BUG] EventDelReal called while e->deleted is 0. This cannot happen. Event name: $event_name", 120 log_data_string("event_name", e->name)); 121 abort(); 122 } 123 if (e->owner) 124 { 125 unreal_log(ULOG_FATAL, "module", "BUG_EVENTDELREAL_NULL", NULL, 126 "[BUG] EventDelReal called while e->owner is NULL. This cannot happen. Event name: $event_name", 127 log_data_string("event_name", e->name)); 128 abort(); 129 } 130 safe_free(e->name); 131 DelListItem(e, events); 132 safe_free(e); 133 } 134 135 /** Remove any events that were previously marked for deletion */ 136 static void CleanupEvents(void) 137 { 138 Event *e, *e_next; 139 for (e = events; e; e = e_next) 140 { 141 e_next = e->next; 142 if (e->deleted) 143 EventDelReal(e); 144 } 145 } 146 147 Event *EventFind(const char *name) 148 { 149 Event *eventptr; 150 151 for (eventptr = events; eventptr; eventptr = eventptr->next) 152 if (!strcmp(eventptr->name, name)) 153 return (eventptr); 154 return NULL; 155 } 156 157 int EventMod(Event *event, EventInfo *mods) 158 { 159 if (!event || !mods) 160 { 161 if (event && event->owner) 162 event->owner->errorcode = MODERR_INVALID; 163 return -1; 164 } 165 166 if (mods->flags & EMOD_EVERY) 167 event->every_msec = mods->every_msec; 168 if (mods->flags & EMOD_HOWMANY) 169 event->count = mods->count; 170 if (mods->flags & EMOD_NAME) 171 safe_strdup(event->name, mods->name); 172 if (mods->flags & EMOD_EVENT) 173 event->event = mods->event; 174 if (mods->flags & EMOD_DATA) 175 event->data = mods->data; 176 if (event->owner) 177 event->owner->errorcode = MODERR_NOERROR; 178 return 0; 179 } 180 181 void DoEvents(void) 182 { 183 Event *e; 184 185 for (e = events; e; e = e->next) 186 { 187 if (e->deleted) 188 continue; 189 if (e->count == -1) 190 { 191 EventDel(e); 192 continue; 193 } 194 if ((e->every_msec == 0) || minimum_msec_since_last_run(&e->last_run, e->every_msec)) 195 { 196 (*e->event)(e->data); 197 if (e->count > 0) 198 { 199 e->count--; 200 if (e->count == 0) 201 { 202 EventDel(e); 203 continue; 204 } 205 } 206 } 207 } 208 209 CleanupEvents(); 210 }