]> git.ipfire.org Git - thirdparty/squid.git/blame - src/event.cc
Split out cbdata fully, it now is an optional include and no Init call is needed.
[thirdparty/squid.git] / src / event.cc
CommitLineData
48f44632 1
2/*
aa839030 3 * $Id: event.cc,v 1.43 2006/08/21 00:50:41 robertc Exp $
48f44632 4 *
f43e2ec2 5 * DEBUG: section 41 Event Processing
48f44632 6 * AUTHOR: Henrik Nordstrom
7 *
2b6662ba 8 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 9 * ----------------------------------------------------------
48f44632 10 *
2b6662ba 11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
48f44632 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
cbdec147 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 33 *
48f44632 34 */
35
a553a5a3 36#include "event.h"
62ee09ca 37#include "CacheManager.h"
e6ccf245 38#include "Store.h"
48f44632 39
40/* The list of event processes */
62e76326 41
48f44632 42
4ba55996 43static OBJH eventDump;
236b1f2a 44static const char *last_event_ran = NULL;
48f44632 45
a553a5a3 46ev_entry::ev_entry(char const * name, EVH * func, void * arg, double when, int weight, bool cbdata) : name(name), func(func), arg(cbdata ? cbdataReference(arg) : arg), when(when), weight(weight), cbdata(cbdata)
47{}
48
48f44632 49void
601af4c6 50eventAdd(const char *name, EVH * func, void *arg, double when, int weight, bool cbdata)
48f44632 51{
a553a5a3 52 EventScheduler::GetInstance()->schedule(name, func, arg, when, weight, cbdata);
48f44632 53}
54
8f3db324 55/* same as eventAdd but adds a random offset within +-1/3 of delta_ish */
56void
52040193 57eventAddIsh(const char *name, EVH * func, void *arg, double delta_ish, int weight)
8f3db324 58{
52040193 59 if (delta_ish >= 3.0) {
62e76326 60 const double two_third = (2.0 * delta_ish) / 3.0;
61 delta_ish = two_third + (drand48() * two_third);
62 /*
63 * I'm sure drand48() isn't portable. Tell me what function
64 * you have that returns a random double value in the range 0,1.
65 */
8f3db324 66 }
62e76326 67
f720985e 68 eventAdd(name, func, arg, delta_ish, weight);
8f3db324 69}
70
93775f90 71void
582b6456 72eventDelete(EVH * func, void *arg)
93775f90 73{
a553a5a3 74 EventScheduler::GetInstance()->cancel(func, arg);
75}
62e76326 76
a553a5a3 77void
78eventInit(CacheManager &manager)
79{
80 manager.registerAction("events", "Event Queue", eventDump, 0, 1);
81}
62e76326 82
a553a5a3 83static void
84eventDump(StoreEntry * sentry)
85{
86 EventScheduler::GetInstance()->dump(sentry);
87}
88
89void
90eventFreeMemory(void)
91{
92 EventScheduler::GetInstance()->clean();
93}
94
95int
96eventFind(EVH * func, void *arg)
97{
98 return EventScheduler::GetInstance()->find(func, arg);
99}
100
101EventDispatcher EventDispatcher::_instance;
102
103EventDispatcher::EventDispatcher()
104{}
105
106void
107
108EventDispatcher::add
109 (ev_entry * event)
110{
111 queue.push_back(event);
112}
113
8ff3fa2e 114bool
a553a5a3 115EventDispatcher::dispatch()
116{
8ff3fa2e 117 bool result = queue.size() != 0;
118
a553a5a3 119 for (Vector<ev_entry *>::iterator i = queue.begin(); i != queue.end(); ++i) {
120 ev_entry * event = *i;
121 EVH *callback;
122 void *cbdata = event->arg;
123 callback = event->func;
124 event->func = NULL;
125
126 if (!event->cbdata || cbdataReferenceValidDone(event->arg, &cbdata)) {
127 /* XXX assumes ->name is static memory! */
128 last_event_ran = event->name;
129 debugs(41, 5, "EventDispatcher::dispatch: Running '" << event->name << "'");
130 callback(cbdata);
131 }
132
133 delete event;
134 }
135
136 queue.clean();
8ff3fa2e 137 return result;
a553a5a3 138}
139
140EventDispatcher *
141EventDispatcher::GetInstance()
142{
143 return &_instance;
144}
145
146EventScheduler EventScheduler::_instance(EventDispatcher::GetInstance());
147
148EventScheduler::EventScheduler(EventDispatcher *dispatcher) : dispatcher(dispatcher), tasks(NULL)
149{}
150
151EventScheduler::~EventScheduler()
152{
153 clean();
154}
155
156void
157EventScheduler::cancel(EVH * func, void *arg)
158{
159 ev_entry **E;
160 ev_entry *event;
62e76326 161
79d39a72 162 for (E = &tasks; (event = *E) != NULL; E = &(*E)->next) {
62e76326 163 if (event->func != func)
164 continue;
165
166 if (event->arg != arg)
167 continue;
168
169 *E = event->next;
170
601af4c6 171 if (event->cbdata)
172 cbdataReferenceDone(event->arg);
62e76326 173
62ee09ca 174 delete event;
62e76326 175
176 return;
93775f90 177 }
62e76326 178
93775f90 179 debug_trap("eventDelete: event not found");
180}
181
a553a5a3 182int
183EventScheduler::checkDelay()
184{
185 if (!tasks)
aa839030 186 return EVENT_IDLE;
a553a5a3 187
8ff3fa2e 188 int result = (int) ((tasks->when - current_dtime) * 1000);
189
190 if (result < 0)
191 return 0;
192
193 return result;
a553a5a3 194}
195
196int
8ff3fa2e 197EventScheduler::checkEvents(int timeout)
48f44632 198{
62e76326 199
48f44632 200 struct ev_entry *event = NULL;
62e76326 201
c43f5247 202 if (NULL == tasks)
a553a5a3 203 return checkDelay();
62e76326 204
c43f5247 205 if (tasks->when > current_dtime)
a553a5a3 206 return checkDelay();
62e76326 207
1d5161bd 208 PROF_start(eventRun);
209
a553a5a3 210 debugs(41, 5, "eventRun: \n");
62e76326 211
c43f5247 212 while ((event = tasks)) {
62e76326 213 if (event->when > current_dtime)
214 break;
215
a553a5a3 216 dispatcher->add
217 (event);
62e76326 218
219 tasks = event->next;
220
a553a5a3 221 if (!event->cbdata || cbdataReferenceValid(event->arg))
222 if (event->weight)
223 /* this event is marked as being 'heavy', so dont dequeue any others.
224 */
225 break;
d90c79ee 226 }
1d5161bd 227
228 PROF_stop(eventRun);
a553a5a3 229 return checkDelay();
48f44632 230}
231
a553a5a3 232void
233EventScheduler::clean()
48f44632 234{
a553a5a3 235 while (ev_entry * event = tasks) {
236 tasks = event->next;
62e76326 237
a553a5a3 238 if (event->cbdata)
239 cbdataReferenceDone(event->arg);
4ba55996 240
a553a5a3 241 delete event;
242 }
243
244 tasks = NULL;
4ba55996 245}
246
a553a5a3 247void
248EventScheduler::dump(StoreEntry * sentry)
4ba55996 249{
62e76326 250
4ba55996 251 struct ev_entry *e = tasks;
62e76326 252
236b1f2a 253 if (last_event_ran)
62e76326 254 storeAppendPrintf(sentry, "Last event to run: %s\n\n", last_event_ran);
255
39d5af29 256 storeAppendPrintf(sentry, "%s\t%s\t%s\t%s\n",
62e76326 257 "Operation",
258 "Next Execution",
259 "Weight",
260 "Callback Valid?");
261
4ba55996 262 while (e != NULL) {
62e76326 263 storeAppendPrintf(sentry, "%s\t%f seconds\t%d\t%s\n",
264 e->name, e->when - current_dtime, e->weight,
601af4c6 265 (e->arg && e->cbdata) ? cbdataReferenceValid(e->arg) ? "yes" : "no" : "N/A");
62e76326 266 e = e->next;
4ba55996 267 }
268}
f1fc2a8d 269
a553a5a3 270bool
271EventScheduler::find(EVH * func, void * arg)
f1fc2a8d 272{
62e76326 273
f1fc2a8d 274 struct ev_entry *event;
62e76326 275
a553a5a3 276 for (event = tasks; event != NULL; event = event->next) {
277 if (event->func == func && event->arg == arg)
278 return true;
f1fc2a8d 279 }
62e76326 280
a553a5a3 281 return false;
f1fc2a8d 282}
46ca5fc6 283
a553a5a3 284EventScheduler *
285EventScheduler::GetInstance()
46ca5fc6 286{
a553a5a3 287 return &_instance;
288}
62e76326 289
a553a5a3 290void
291EventScheduler::schedule(const char *name, EVH * func, void *arg, double when, int weight, bool cbdata)
292{
62e76326 293
a553a5a3 294 struct ev_entry *event = new ev_entry(name, func, arg, current_dtime + when, weight, cbdata);
295
296 struct ev_entry **E;
297 debugs(41, 7, "eventAdd: Adding '" << name << "', in " << when << " seconds");
298 /* Insert after the last event with the same or earlier time */
299
300 for (E = &tasks; *E; E = &(*E)->next) {
301 if ((*E)->when > event->when)
302 break;
46ca5fc6 303 }
62e76326 304
a553a5a3 305 event->next = *E;
306 *E = event;
46ca5fc6 307}