mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 15:48:19 +00:00
263 lines
5.6 KiB
C++
263 lines
5.6 KiB
C++
// $Id: Timer.cc 6219 2008-10-01 05:39:07Z vern $
|
|
//
|
|
// See the file "COPYING" in the main distribution directory for copyright.
|
|
|
|
#include "config.h"
|
|
|
|
#include "util.h"
|
|
#include "Timer.h"
|
|
#include "Desc.h"
|
|
#include "Serializer.h"
|
|
|
|
// Names of timers in same order than in TimerType.
|
|
const char* TimerNames[] = {
|
|
"BackdoorTimer",
|
|
"BreakpointTimer",
|
|
"ConnectionDeleteTimer",
|
|
"ConnectionExpireTimer",
|
|
"ConnectionInactivityTimer",
|
|
"ConnectionStatusUpdateTimer",
|
|
"DNSExpireTimer",
|
|
"FragTimer",
|
|
"IncrementalSendTimer",
|
|
"IncrementalWriteTimer",
|
|
"InterconnTimer",
|
|
"NetbiosExpireTimer",
|
|
"NetworkTimer",
|
|
"NTPExpireTimer",
|
|
"ProfileTimer",
|
|
"RotateTimer",
|
|
"RemoveConnection",
|
|
"RPCExpireTimer",
|
|
"ScheduleTimer",
|
|
"TableValTimer",
|
|
"TCPConnectionAttemptTimer",
|
|
"TCPConnectionDeleteTimer",
|
|
"TCPConnectionExpireTimer",
|
|
"TCPConnectionPartialClose",
|
|
"TCPConnectionResetTimer",
|
|
"TriggerTimer",
|
|
"TimerMgrExpireTimer",
|
|
};
|
|
|
|
const char* timer_type_to_string(TimerType type)
|
|
{
|
|
return TimerNames[type];
|
|
}
|
|
|
|
void Timer::Describe(ODesc* d) const
|
|
{
|
|
d->Add(TimerNames[type]);
|
|
d->Add(" at " );
|
|
d->Add(Time());
|
|
}
|
|
|
|
bool Timer::Serialize(SerialInfo* info) const
|
|
{
|
|
return SerialObj::Serialize(info);
|
|
}
|
|
|
|
Timer* Timer::Unserialize(UnserialInfo* info)
|
|
{
|
|
Timer* timer = (Timer*) SerialObj::Unserialize(info, SER_TIMER);
|
|
if ( ! timer )
|
|
return 0;
|
|
|
|
timer_mgr->Add(timer);
|
|
|
|
return timer;
|
|
}
|
|
|
|
bool Timer::DoSerialize(SerialInfo* info) const
|
|
{
|
|
DO_SERIALIZE(SER_TIMER, SerialObj);
|
|
char tmp = type;
|
|
return SERIALIZE(tmp) && SERIALIZE(time);
|
|
}
|
|
|
|
bool Timer::DoUnserialize(UnserialInfo* info)
|
|
{
|
|
DO_UNSERIALIZE(SerialObj);
|
|
|
|
char tmp;
|
|
if ( ! UNSERIALIZE(&tmp) )
|
|
return false;
|
|
type = tmp;
|
|
|
|
return UNSERIALIZE(&time);
|
|
}
|
|
|
|
unsigned int TimerMgr::current_timers[NUM_TIMER_TYPES];
|
|
|
|
TimerMgr::~TimerMgr()
|
|
{
|
|
DBG_LOG(DBG_TM, "deleting timer mgr %p", this);
|
|
}
|
|
|
|
int TimerMgr::Advance(double arg_t, int max_expire)
|
|
{
|
|
DBG_LOG(DBG_TM, "advancing %stimer mgr %p to %.6f",
|
|
this == timer_mgr ? "global " : "", this, arg_t);
|
|
|
|
t = arg_t;
|
|
last_timestamp = 0;
|
|
num_expired = 0;
|
|
last_advance = timer_mgr->Time();
|
|
|
|
return DoAdvance(t, max_expire);
|
|
}
|
|
|
|
|
|
PQ_TimerMgr::PQ_TimerMgr(const Tag& tag) : TimerMgr(tag)
|
|
{
|
|
q = new PriorityQueue;
|
|
}
|
|
|
|
PQ_TimerMgr::~PQ_TimerMgr()
|
|
{
|
|
delete q;
|
|
}
|
|
|
|
void PQ_TimerMgr::Add(Timer* timer)
|
|
{
|
|
DBG_LOG(DBG_TM, "Adding timer %s to TimeMgr %p",
|
|
timer_type_to_string(timer->Type()), this);
|
|
|
|
// Add the timer even if it's already expired - that way, if
|
|
// multiple already-added timers are added, they'll still
|
|
// execute in sorted order.
|
|
if ( ! q->Add(timer) )
|
|
internal_error("out of memory");
|
|
|
|
++current_timers[timer->Type()];
|
|
}
|
|
|
|
void PQ_TimerMgr::Expire()
|
|
{
|
|
Timer* timer;
|
|
while ( (timer = Remove()) )
|
|
{
|
|
DBG_LOG(DBG_TM, "Dispatching timer %s in TimeMgr %p",
|
|
timer_type_to_string(timer->Type()), this);
|
|
timer->Dispatch(t, 1);
|
|
--current_timers[timer->Type()];
|
|
delete timer;
|
|
}
|
|
}
|
|
|
|
int PQ_TimerMgr::DoAdvance(double new_t, int max_expire)
|
|
{
|
|
Timer* timer = Top();
|
|
for ( num_expired = 0; (num_expired < max_expire || max_expire == 0) &&
|
|
timer && timer->Time() <= new_t; ++num_expired )
|
|
{
|
|
last_timestamp = timer->Time();
|
|
--current_timers[timer->Type()];
|
|
|
|
// Remove it before dispatching, since the dispatch
|
|
// can otherwise delete it, and then we won't know
|
|
// whether we should delete it too.
|
|
(void) Remove();
|
|
|
|
DBG_LOG(DBG_TM, "Dispatching timer %s in TimeMgr %p",
|
|
timer_type_to_string(timer->Type()), this);
|
|
timer->Dispatch(new_t, 0);
|
|
delete timer;
|
|
|
|
timer = Top();
|
|
}
|
|
|
|
return num_expired;
|
|
}
|
|
|
|
void PQ_TimerMgr::Remove(Timer* timer)
|
|
{
|
|
if ( ! q->Remove(timer) )
|
|
internal_error("asked to remove a missing timer");
|
|
|
|
--current_timers[timer->Type()];
|
|
delete timer;
|
|
}
|
|
|
|
CQ_TimerMgr::CQ_TimerMgr(const Tag& tag) : TimerMgr(tag)
|
|
{
|
|
cq = cq_init(60.0, 1.0);
|
|
if ( ! cq )
|
|
internal_error("could not initialize calendar queue");
|
|
}
|
|
|
|
CQ_TimerMgr::~CQ_TimerMgr()
|
|
{
|
|
cq_destroy(cq);
|
|
}
|
|
|
|
void CQ_TimerMgr::Add(Timer* timer)
|
|
{
|
|
DBG_LOG(DBG_TM, "Adding timer %s to TimeMgr %p",
|
|
timer_type_to_string(timer->Type()), this);
|
|
|
|
// Add the timer even if it's already expired - that way, if
|
|
// multiple already-added timers are added, they'll still
|
|
// execute in sorted order.
|
|
double t = timer->Time();
|
|
|
|
if ( t <= 0.0 )
|
|
// Illegal time, which cq_enqueue won't like. For our
|
|
// purposes, just treat it as an old time that's already
|
|
// expired.
|
|
t = network_time;
|
|
|
|
if ( cq_enqueue(cq, t, timer) < 0 )
|
|
internal_error("problem queueing timer");
|
|
|
|
++current_timers[timer->Type()];
|
|
}
|
|
|
|
void CQ_TimerMgr::Expire()
|
|
{
|
|
double huge_t = 1e20; // larger than any Unix timestamp
|
|
for ( Timer* timer = (Timer*) cq_dequeue(cq, huge_t);
|
|
timer; timer = (Timer*) cq_dequeue(cq, huge_t) )
|
|
{
|
|
DBG_LOG(DBG_TM, "Dispatching timer %s in TimeMgr %p",
|
|
timer_type_to_string(timer->Type()), this);
|
|
timer->Dispatch(huge_t, 1);
|
|
--current_timers[timer->Type()];
|
|
delete timer;
|
|
}
|
|
}
|
|
|
|
int CQ_TimerMgr::DoAdvance(double new_t, int max_expire)
|
|
{
|
|
Timer* timer;
|
|
while ( (num_expired < max_expire || max_expire == 0) &&
|
|
(timer = (Timer*) cq_dequeue(cq, new_t)) )
|
|
{
|
|
last_timestamp = timer->Time();
|
|
DBG_LOG(DBG_TM, "Dispatching timer %s in TimeMgr %p",
|
|
timer_type_to_string(timer->Type()), this);
|
|
timer->Dispatch(new_t, 0);
|
|
--current_timers[timer->Type()];
|
|
delete timer;
|
|
++num_expired;
|
|
}
|
|
|
|
return num_expired;
|
|
}
|
|
|
|
unsigned int CQ_TimerMgr::MemoryUsage() const
|
|
{
|
|
// FIXME.
|
|
return 0;
|
|
}
|
|
|
|
void CQ_TimerMgr::Remove(Timer* timer)
|
|
{
|
|
// This may fail if we cancel a timer which has already been removed.
|
|
// That's ok, but then we mustn't delete the timer.
|
|
if ( cq_remove(cq, timer->Time(), timer) )
|
|
{
|
|
--current_timers[timer->Type()];
|
|
delete timer;
|
|
}
|
|
}
|