Branch data Line data Source code
1 : : // $Id: Timer.cc 6219 2008-10-01 05:39:07Z vern $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "config.h"
6 : :
7 : : #include "util.h"
8 : : #include "Timer.h"
9 : : #include "Desc.h"
10 : : #include "Serializer.h"
11 : :
12 : : // Names of timers in same order than in TimerType.
13 : : const char* TimerNames[] = {
14 : : "BackdoorTimer",
15 : : "BreakpointTimer",
16 : : "ConnectionDeleteTimer",
17 : : "ConnectionExpireTimer",
18 : : "ConnectionInactivityTimer",
19 : : "ConnectionStatusUpdateTimer",
20 : : "DNSExpireTimer",
21 : : "FragTimer",
22 : : "IncrementalSendTimer",
23 : : "IncrementalWriteTimer",
24 : : "InterconnTimer",
25 : : "NetbiosExpireTimer",
26 : : "NetworkTimer",
27 : : "NTPExpireTimer",
28 : : "ProfileTimer",
29 : : "RotateTimer",
30 : : "RemoveConnection",
31 : : "RPCExpireTimer",
32 : : "ScheduleTimer",
33 : : "TableValTimer",
34 : : "TCPConnectionAttemptTimer",
35 : : "TCPConnectionDeleteTimer",
36 : : "TCPConnectionExpireTimer",
37 : : "TCPConnectionPartialClose",
38 : : "TCPConnectionResetTimer",
39 : : "TriggerTimer",
40 : : "TimerMgrExpireTimer",
41 : : };
42 : :
43 : 57396 : const char* timer_type_to_string(TimerType type)
44 : : {
45 : 57396 : return TimerNames[type];
46 : : }
47 : :
48 : 0 : void Timer::Describe(ODesc* d) const
49 : : {
50 : 0 : d->Add(TimerNames[type]);
51 : 0 : d->Add(" at " );
52 : 0 : d->Add(Time());
53 : 0 : }
54 : :
55 : 0 : bool Timer::Serialize(SerialInfo* info) const
56 : : {
57 : 0 : return SerialObj::Serialize(info);
58 : : }
59 : :
60 : 0 : Timer* Timer::Unserialize(UnserialInfo* info)
61 : : {
62 : 0 : Timer* timer = (Timer*) SerialObj::Unserialize(info, SER_TIMER);
63 [ # # ]: 0 : if ( ! timer )
64 : 0 : return 0;
65 : :
66 : 0 : timer_mgr->Add(timer);
67 : :
68 : 0 : return timer;
69 : : }
70 : :
71 : 0 : bool Timer::DoSerialize(SerialInfo* info) const
72 : : {
73 [ # # ][ # # ]: 0 : DO_SERIALIZE(SER_TIMER, SerialObj);
74 : 0 : char tmp = type;
75 [ # # ][ # # ]: 0 : return SERIALIZE(tmp) && SERIALIZE(time);
76 : : }
77 : :
78 : 0 : bool Timer::DoUnserialize(UnserialInfo* info)
79 : : {
80 [ # # ]: 0 : DO_UNSERIALIZE(SerialObj);
81 : :
82 : : char tmp;
83 [ # # ]: 0 : if ( ! UNSERIALIZE(&tmp) )
84 : 0 : return false;
85 : 0 : type = tmp;
86 : :
87 : 0 : return UNSERIALIZE(&time);
88 : : }
89 : :
90 : : unsigned int TimerMgr::current_timers[NUM_TIMER_TYPES];
91 : :
92 : 1 : TimerMgr::~TimerMgr()
93 : : {
94 : 1 : DBG_LOG(DBG_TM, "deleting timer mgr %p", this);
95 [ # # ][ # # ]: 1 : }
[ - + ]
96 : :
97 : 21347 : int TimerMgr::Advance(double arg_t, int max_expire)
98 : : {
99 [ + - ]: 21347 : DBG_LOG(DBG_TM, "advancing %stimer mgr %p to %.6f",
100 : : this == timer_mgr ? "global " : "", this, arg_t);
101 : :
102 : 21347 : t = arg_t;
103 : 21347 : last_timestamp = 0;
104 : 21347 : num_expired = 0;
105 : 21347 : last_advance = timer_mgr->Time();
106 : :
107 : 21347 : return DoAdvance(t, max_expire);
108 : : }
109 : :
110 : :
111 : 3 : PQ_TimerMgr::PQ_TimerMgr(const Tag& tag) : TimerMgr(tag)
112 : : {
113 : 3 : q = new PriorityQueue;
114 : 3 : }
115 : :
116 : 1 : PQ_TimerMgr::~PQ_TimerMgr()
117 : : {
118 [ + - ][ # # ]: 1 : delete q;
[ # # ]
119 [ + - ][ # # ]: 1 : }
[ # # ]
120 : :
121 : 29889 : void PQ_TimerMgr::Add(Timer* timer)
122 : : {
123 : 29889 : DBG_LOG(DBG_TM, "Adding timer %s to TimeMgr %p",
124 : : timer_type_to_string(timer->Type()), this);
125 : :
126 : : // Add the timer even if it's already expired - that way, if
127 : : // multiple already-added timers are added, they'll still
128 : : // execute in sorted order.
129 [ + - ][ - + ]: 29889 : if ( ! q->Add(timer) )
130 : 0 : internal_error("out of memory");
131 : :
132 : 29889 : ++current_timers[timer->Type()];
133 : 29889 : }
134 : :
135 : 2 : void PQ_TimerMgr::Expire()
136 : : {
137 : : Timer* timer;
138 [ + + ]: 46 : while ( (timer = Remove()) )
139 : : {
140 : 44 : DBG_LOG(DBG_TM, "Dispatching timer %s in TimeMgr %p",
141 : : timer_type_to_string(timer->Type()), this);
142 : 44 : timer->Dispatch(t, 1);
143 : 44 : --current_timers[timer->Type()];
144 [ + - ]: 44 : delete timer;
145 : : }
146 : 2 : }
147 : :
148 : 21347 : int PQ_TimerMgr::DoAdvance(double new_t, int max_expire)
149 : : {
150 : 21347 : Timer* timer = Top();
151 [ - + ][ # # ]: 48810 : for ( num_expired = 0; (num_expired < max_expire || max_expire == 0) &&
[ + - ][ + + ]
[ + + ]
152 : : timer && timer->Time() <= new_t; ++num_expired )
153 : : {
154 : 27463 : last_timestamp = timer->Time();
155 : 27463 : --current_timers[timer->Type()];
156 : :
157 : : // Remove it before dispatching, since the dispatch
158 : : // can otherwise delete it, and then we won't know
159 : : // whether we should delete it too.
160 : 27463 : (void) Remove();
161 : :
162 : 27463 : DBG_LOG(DBG_TM, "Dispatching timer %s in TimeMgr %p",
163 : : timer_type_to_string(timer->Type()), this);
164 : 27463 : timer->Dispatch(new_t, 0);
165 [ + - ]: 27463 : delete timer;
166 : :
167 : 27463 : timer = Top();
168 : : }
169 : :
170 : 21347 : return num_expired;
171 : : }
172 : :
173 : 2310 : void PQ_TimerMgr::Remove(Timer* timer)
174 : : {
175 [ + - ][ - + ]: 2310 : if ( ! q->Remove(timer) )
176 : 0 : internal_error("asked to remove a missing timer");
177 : :
178 : 2310 : --current_timers[timer->Type()];
179 [ + - ]: 2310 : delete timer;
180 : 2310 : }
181 : :
182 : 0 : CQ_TimerMgr::CQ_TimerMgr(const Tag& tag) : TimerMgr(tag)
183 : : {
184 : 0 : cq = cq_init(60.0, 1.0);
185 [ # # # # ]: 0 : if ( ! cq )
186 : 0 : internal_error("could not initialize calendar queue");
187 : 0 : }
188 : :
189 : 0 : CQ_TimerMgr::~CQ_TimerMgr()
190 : : {
191 : 0 : cq_destroy(cq);
192 [ # # ][ # # ]: 0 : }
[ # # ]
193 : :
194 : 0 : void CQ_TimerMgr::Add(Timer* timer)
195 : : {
196 : 0 : DBG_LOG(DBG_TM, "Adding timer %s to TimeMgr %p",
197 : : timer_type_to_string(timer->Type()), this);
198 : :
199 : : // Add the timer even if it's already expired - that way, if
200 : : // multiple already-added timers are added, they'll still
201 : : // execute in sorted order.
202 : 0 : double t = timer->Time();
203 : :
204 [ # # ]: 0 : if ( t <= 0.0 )
205 : : // Illegal time, which cq_enqueue won't like. For our
206 : : // purposes, just treat it as an old time that's already
207 : : // expired.
208 : 0 : t = network_time;
209 : :
210 [ # # ]: 0 : if ( cq_enqueue(cq, t, timer) < 0 )
211 : 0 : internal_error("problem queueing timer");
212 : :
213 : 0 : ++current_timers[timer->Type()];
214 : 0 : }
215 : :
216 : 0 : void CQ_TimerMgr::Expire()
217 : : {
218 : 0 : double huge_t = 1e20; // larger than any Unix timestamp
219 [ # # ]: 0 : for ( Timer* timer = (Timer*) cq_dequeue(cq, huge_t);
220 : : timer; timer = (Timer*) cq_dequeue(cq, huge_t) )
221 : : {
222 : 0 : DBG_LOG(DBG_TM, "Dispatching timer %s in TimeMgr %p",
223 : : timer_type_to_string(timer->Type()), this);
224 : 0 : timer->Dispatch(huge_t, 1);
225 : 0 : --current_timers[timer->Type()];
226 [ # # ]: 0 : delete timer;
227 : : }
228 : 0 : }
229 : :
230 : 0 : int CQ_TimerMgr::DoAdvance(double new_t, int max_expire)
231 : : {
232 : : Timer* timer;
233 [ # # ][ # # ]: 0 : while ( (num_expired < max_expire || max_expire == 0) &&
[ # # ][ # # ]
234 : : (timer = (Timer*) cq_dequeue(cq, new_t)) )
235 : : {
236 : 0 : last_timestamp = timer->Time();
237 : 0 : DBG_LOG(DBG_TM, "Dispatching timer %s in TimeMgr %p",
238 : : timer_type_to_string(timer->Type()), this);
239 : 0 : timer->Dispatch(new_t, 0);
240 : 0 : --current_timers[timer->Type()];
241 [ # # ]: 0 : delete timer;
242 : 0 : ++num_expired;
243 : : }
244 : :
245 : 0 : return num_expired;
246 : : }
247 : :
248 : 0 : unsigned int CQ_TimerMgr::MemoryUsage() const
249 : : {
250 : : // FIXME.
251 : 0 : return 0;
252 : : }
253 : :
254 : 0 : void CQ_TimerMgr::Remove(Timer* timer)
255 : : {
256 : : // This may fail if we cancel a timer which has already been removed.
257 : : // That's ok, but then we mustn't delete the timer.
258 [ # # ]: 0 : if ( cq_remove(cq, timer->Time(), timer) )
259 : : {
260 : 0 : --current_timers[timer->Type()];
261 [ # # ]: 0 : delete timer;
262 : : }
263 [ + - ][ + - ]: 6 : }
|