zeek/src/Timer.cc

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;
}
}