event.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9/* DEBUG: section 41 Event Processing */
10
11#include "squid.h"
12#include "base/Random.h"
13#include "event.h"
14#include "mgr/Registration.h"
15#include "Store.h"
16#include "tools.h"
17
18#include <cmath>
19
20/* The list of event processes */
21
23static const char *last_event_ran = nullptr;
24
25// This AsyncCall dialer can be configured to check that the event cbdata is
26// valid before calling the event handler
28{
29public:
31
32 EventDialer(EVH *aHandler, void *anArg, bool lockedArg);
33 EventDialer(const EventDialer &d);
34 virtual ~EventDialer();
35
36 virtual void print(std::ostream &os) const;
37 virtual bool canDial(AsyncCall &call);
38
40
41private:
43 void *theArg;
45};
46
47EventDialer::EventDialer(EVH *aHandler, void *anArg, bool lockedArg):
48 theHandler(aHandler), theArg(anArg), isLockedArg(lockedArg)
49{
50 if (isLockedArg)
52}
53
55 theHandler(d.theHandler), theArg(d.theArg), isLockedArg(d.isLockedArg)
56{
57 if (isLockedArg)
59}
60
62{
63 if (isLockedArg)
65}
66
67bool
69{
70 // TODO: add Parent::canDial() that always returns true
71 //if (!Parent::canDial())
72 // return false;
73
75 return call.cancel("stale handler data");
76
77 return true;
78}
79
80void
81EventDialer::print(std::ostream &os) const
82{
83 os << '(';
84 if (theArg)
85 os << theArg << (isLockedArg ? "*?" : "");
86 os << ')';
87}
88
89ev_entry::ev_entry(char const * aName, EVH * aFunction, void * aArgument, double evWhen, int aWeight, bool haveArg) :
90 name(aName),
91 func(aFunction),
92 arg(haveArg ? cbdataReference(aArgument) : aArgument),
93 when(evWhen),
94 weight(aWeight),
95 cbdata(haveArg),
96 next(nullptr)
97{
98}
99
101{
102 if (cbdata)
104}
105
106void
107eventAdd(const char *name, EVH * func, void *arg, double when, int weight, bool cbdata)
108{
109 EventScheduler::GetInstance()->schedule(name, func, arg, when, weight, cbdata);
110}
111
112/* same as eventAdd but adds a random offset within +-1/3 of delta_ish */
113void
114eventAddIsh(const char *name, EVH * func, void *arg, double delta_ish, int weight)
115{
116 if (delta_ish >= 3.0) {
117 static std::mt19937 rng(RandomSeed32());
118 auto third = (delta_ish/3.0);
119 xuniform_real_distribution<> thirdIsh(delta_ish - third, delta_ish + third);
120 delta_ish = thirdIsh(rng);
121 }
122
123 eventAdd(name, func, arg, delta_ish, weight);
124}
125
126void
127eventDelete(EVH * func, void *arg)
128{
130}
131
132void
134{
135 Mgr::RegisterAction("events", "Event Queue", eventDump, 0, 1);
136}
137
138static void
140{
142}
143
144int
145eventFind(EVH * func, void *arg)
146{
147 return EventScheduler::GetInstance()->find(func, arg);
148}
149
151
153{}
154
156{
157 clean();
158}
159
160void
161EventScheduler::cancel(EVH * func, void *arg)
162{
163 ev_entry **E;
164 ev_entry *event;
165
166 for (E = &tasks; (event = *E) != nullptr; E = &(*E)->next) {
167 if (event->func != func)
168 continue;
169
170 if (arg && event->arg != arg)
171 continue;
172
173 *E = event->next;
174
175 delete event;
176
177 if (arg)
178 return;
179 /*
180 * DPW 2007-04-12
181 * Since this method may now delete multiple events (when
182 * arg is NULL) it no longer returns after a deletion and
183 * we have a potential NULL pointer problem. If we just
184 * deleted the last event in the list then *E is now equal
185 * to NULL. We need to break here or else we'll get a NULL
186 * pointer dereference in the last clause of the for loop.
187 */
188 if (nullptr == *E)
189 break;
190 }
191
192 if (arg)
193 debug_trap("eventDelete: event not found");
194}
195
196// The event API does not guarantee exact timing, but guarantees that no event
197// is fired before it is due. We may delay firing, but never fire too early.
198int
200{
201 if (!tasks)
202 return EVENT_IDLE;
203
204 if (tasks->when <= current_dtime) // we are on time or late
205 return 0; // fire the event ASAP
206
207 const double diff = tasks->when - current_dtime; // microseconds
208 // Round UP: If we come back a nanosecond earlier, we will wait again!
209 const int timeLeft = static_cast<int>(ceil(1000*diff)); // milliseconds
210 // Avoid hot idle: A series of rapid select() calls with zero timeout.
211 const int minDelay = 1; // millisecond
212 return max(minDelay, timeLeft);
213}
214
215int
217{
218 int result = timeRemaining();
219 if (result != 0)
220 return result;
221
222 do {
223 ev_entry *event = tasks;
224 assert(event);
225
226 /* XXX assumes event->name is static memory! */
227 AsyncCall::Pointer call = asyncCall(41,5, event->name,
228 EventDialer(event->func, event->arg, event->cbdata));
229 ScheduleCallHere(call);
230
231 last_event_ran = event->name; // XXX: move this to AsyncCallQueue
232 const bool heavy = event->weight &&
233 (!event->cbdata || cbdataReferenceValid(event->arg));
234
235 tasks = event->next;
236 delete event;
237
238 result = timeRemaining();
239
240 // XXX: We may be called again during the same event loop iteration.
241 // Is there a point in breaking now?
242 if (heavy)
243 break; // do not dequeue events following a heavy event
244 } while (result == 0);
245
246 return result;
247}
248
249void
251{
252 while (ev_entry * event = tasks) {
253 tasks = event->next;
254 delete event;
255 }
256
257 tasks = nullptr;
258}
259
260void
262{
263 if (last_event_ran)
264 out->appendf("Last event to run: %s\n\n", last_event_ran);
265
266 out->appendf("%-25s\t%-15s\t%s\t%s\n",
267 "Operation",
268 "Next Execution",
269 "Weight",
270 "Callback Valid?");
271
272 for (auto *e = tasks; e; e = e->next) {
273 out->appendf("%-25s\t%0.3f sec\t%5d\t %s\n",
274 e->name, (e->when ? e->when - current_dtime : 0), e->weight,
275 (e->arg && e->cbdata) ? cbdataReferenceValid(e->arg) ? "yes" : "no" : "N/A");
276 }
277}
278
279bool
280EventScheduler::find(EVH * func, void * arg)
281{
282
283 ev_entry *event;
284
285 for (event = tasks; event != nullptr; event = event->next) {
286 if (event->func == func && event->arg == arg)
287 return true;
288 }
289
290 return false;
291}
292
295{
296 return &_instance;
297}
298
299void
300EventScheduler::schedule(const char *name, EVH * func, void *arg, double when, int weight, bool cbdata)
301{
302 // Use zero timestamp for when=0 events: Many of them are async calls that
303 // must fire in the submission order. We cannot use current_dtime for them
304 // because it may decrease if system clock is adjusted backwards.
305 const double timestamp = when > 0.0 ? current_dtime + when : 0;
306 ev_entry *event = new ev_entry(name, func, arg, timestamp, weight, cbdata);
307
308 ev_entry **E;
309 debugs(41, 7, "schedule: Adding '" << name << "', in " << when << " seconds");
310 /* Insert after the last event with the same or earlier time */
311
312 for (E = &tasks; *E; E = &(*E)->next) {
313 if ((*E)->when > event->when)
314 break;
315 }
316
317 event->next = *E;
318 *E = event;
319}
320
#define ScheduleCallHere(call)
Definition: AsyncCall.h:164
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:154
#define assert(EX)
Definition: assert.h:19
std::mt19937::result_type RandomSeed32()
Definition: Random.cc:12
int cbdataReferenceValid(const void *p)
Definition: cbdata.cc:398
#define cbdataReferenceDone(var)
Definition: cbdata.h:350
#define cbdataReference(var)
Definition: cbdata.h:341
bool cancel(const char *reason)
Definition: AsyncCall.cc:56
EventDialer(EVH *aHandler, void *anArg, bool lockedArg)
Definition: event.cc:47
bool isLockedArg
Definition: event.cc:44
EVH * theHandler
Definition: event.cc:42
virtual bool canDial(AsyncCall &call)
Definition: event.cc:68
virtual void print(std::ostream &os) const
Definition: event.cc:81
CallDialer Parent
Definition: event.cc:30
void dial(AsyncCall &)
Definition: event.cc:39
virtual ~EventDialer()
Definition: event.cc:61
void * theArg
Definition: event.cc:43
static EventScheduler * GetInstance()
Definition: event.cc:294
~EventScheduler()
Definition: event.cc:155
int checkEvents(int timeout)
Definition: event.cc:216
bool find(EVH *func, void *arg)
Definition: event.cc:280
EventScheduler()
Definition: event.cc:152
void schedule(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata=true)
Definition: event.cc:300
ev_entry * tasks
Definition: event.h:68
void clean()
Definition: event.cc:250
static EventScheduler _instance
Definition: event.h:67
void cancel(EVH *func, void *arg)
Definition: event.cc:161
void dump(Packable *)
Definition: event.cc:261
int timeRemaining() const
Definition: event.cc:199
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition: Packable.h:61
Definition: cbdata.cc:60
Definition: event.h:27
ev_entry(char const *name, EVH *func, void *arg, double when, int weight, bool cbdata=true)
Definition: event.cc:89
~ev_entry()
Definition: event.cc:100
EVH * func
Definition: event.h:34
ev_entry * next
Definition: event.h:41
double when
Definition: event.h:36
void * arg
Definition: event.h:35
A const & max(A const &lhs, A const &rhs)
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:196
static char E[KS]
Definition: encrypt.c:92
void eventAddIsh(const char *name, EVH *func, void *arg, double delta_ish, int weight)
Definition: event.cc:114
int eventFind(EVH *func, void *arg)
Definition: event.cc:145
static const char * last_event_ran
Definition: event.cc:23
void eventInit(void)
Definition: event.cc:133
static OBJH eventDump
Definition: event.cc:22
void eventDelete(EVH *func, void *arg)
Definition: event.cc:127
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
Definition: event.cc:107
void EVH(void *)
Definition: event.h:18
void OBJH(StoreEntry *)
Definition: forward.h:44
void RegisterAction(char const *action, char const *desc, OBJH *handler, int pw_req_flag, int atomic)
Definition: Registration.cc:16
double current_dtime
the current UNIX time in seconds (with microsecond precision)
Definition: stub_libtime.cc:19
void debug_trap(const char *message)
Definition: tools.cc:455

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors