diff --git a/src/Conn.cc b/src/Conn.cc index 0126db55b0..855f14558c 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -115,8 +115,8 @@ Connection::Connection(NetSessions* s, const ConnIDKey& k, double t, const ConnI ++current_connections; ++total_connections; - TimerMgr::Tag* tag = current_iosrc->GetCurrentTag(); - conn_timer_mgr = tag ? new TimerMgr::Tag(*tag) : 0; + std::string* tag = current_iosrc->GetCurrentTag(); + conn_timer_mgr = tag ? new std::string(*tag) : nullptr; if ( arg_encap ) encapsulation = new EncapsulationStack(*arg_encap); diff --git a/src/Conn.h b/src/Conn.h index 3bfe6a1109..41b8fc8283 100644 --- a/src/Conn.h +++ b/src/Conn.h @@ -321,7 +321,7 @@ protected: bool key_valid; // Timer manager to use for this conn (or nil). - TimerMgr::Tag* conn_timer_mgr; + std::string* conn_timer_mgr; timer_list timers; IPAddr orig_addr; diff --git a/src/Sessions.cc b/src/Sessions.cc index a078612762..984a8df754 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -1338,7 +1338,7 @@ bool NetSessions::WantConnection(uint16_t src_port, uint16_t dst_port, return true; } -TimerMgr* NetSessions::LookupTimerMgr(const TimerMgr::Tag* tag, bool create) +TimerMgr* NetSessions::LookupTimerMgr(const std::string* tag, bool create) { if ( ! tag ) { diff --git a/src/Sessions.h b/src/Sessions.h index f2120ba694..c627393e5d 100644 --- a/src/Sessions.h +++ b/src/Sessions.h @@ -104,7 +104,7 @@ public: // Looks up timer manager associated with tag. If tag is unknown and // "create" is true, creates new timer manager and stores it. Returns // global timer manager if tag is nil. - TimerMgr* LookupTimerMgr(const TimerMgr::Tag* tag, bool create = true); + TimerMgr* LookupTimerMgr(const std::string* tag, bool create = true); void ExpireTimerMgrs(); @@ -245,8 +245,8 @@ protected: PacketProfiler* pkt_profiler; // We may use independent timer managers for different sets of related - // activity. The managers are identified by an unique tag. - typedef std::map TimerMgrMap; + // activity. The managers are identified by a unique tag. + typedef std::map TimerMgrMap; TimerMgrMap timer_mgrs; }; diff --git a/src/Timer.cc b/src/Timer.cc index 838ae6ad08..a16ee3bf33 100644 --- a/src/Timer.cc +++ b/src/Timer.cc @@ -5,7 +5,11 @@ #include "util.h" #include "Timer.h" #include "Desc.h" +#include "Net.h" +#include "NetVar.h" #include "broker/Manager.h" +#include "iosource/Manager.h" +#include "iosource/PktSrc.h" // Names of timers in same order than in TimerType. const char* TimerNames[] = { @@ -55,6 +59,17 @@ void Timer::Describe(ODesc* d) const unsigned int TimerMgr::current_timers[NUM_TIMER_TYPES]; +TimerMgr::TimerMgr(const std::string& arg_tag) + { + t = 0.0; + num_expired = 0; + last_advance = last_timestamp = 0; + tag = arg_tag; + + if ( iosource_mgr ) + iosource_mgr->Register(this, true); + } + TimerMgr::~TimerMgr() { DBG_LOG(DBG_TM, "deleting timer mgr %p", this); @@ -74,8 +89,28 @@ int TimerMgr::Advance(double arg_t, int max_expire) return DoAdvance(t, max_expire); } +void TimerMgr::Process() + { + // If we don't have a source, or the source is closed, or we're reading live (which includes + // pseudo-realtime), advance the timer here to the current time since otherwise it won't + // move forward and the timers won't fire correctly. + iosource::PktSrc* pkt_src = iosource_mgr->GetPktSrc(); + if ( ! pkt_src || ! pkt_src->IsOpen() || reading_live ) + net_update_time(current_time()); -PQ_TimerMgr::PQ_TimerMgr(const Tag& tag) : TimerMgr(tag) + // Just advance the timer manager based on the current network time. This won't actually + // change the time, but will dispatch any timers that need dispatching. + current_dispatched += Advance(network_time, max_timer_expires - current_dispatched); + } + +void TimerMgr::InitPostScript() + { + if ( iosource_mgr ) + iosource_mgr->Register(this, true); + } + + +PQ_TimerMgr::PQ_TimerMgr(const std::string& tag) : TimerMgr(tag) { q = new PriorityQueue; } @@ -145,3 +180,12 @@ void PQ_TimerMgr::Remove(Timer* timer) --current_timers[timer->Type()]; delete timer; } + +double PQ_TimerMgr::GetNextTimeout() + { + Timer* top = Top(); + if ( top ) + return std::max(0.0, top->Time() - ::network_time); + + return -1; + } diff --git a/src/Timer.h b/src/Timer.h index 21b21fc5ee..8f73041416 100644 --- a/src/Timer.h +++ b/src/Timer.h @@ -2,10 +2,9 @@ #pragma once -#include - #include #include "PriorityQueue.h" +#include "iosource/IOSource.h" // If you add a timer here, adjust TimerNames in Timer.cc. enum TimerType : uint8_t { @@ -48,10 +47,10 @@ class ODesc; class Timer : public PQ_Element { public: - Timer(double t, TimerType arg_type) : PQ_Element(t), type(arg_type) { } + Timer(double t, TimerType arg_type) : PQ_Element(t), type(arg_type) {} ~Timer() override { } - TimerType Type() const { return (TimerType) type; } + TimerType Type() const { return type; } // t gives the dispatch time. is_expire is true if the // timer is being dispatched because we're expiring all @@ -65,53 +64,73 @@ protected: TimerType type; }; -class TimerMgr { +class TimerMgr : public iosource::IOSource { public: virtual ~TimerMgr(); virtual void Add(Timer* timer) = 0; - // Advance the clock to time t, expiring at most max_expire timers. - // Returns number of timers expired. + /** + * Advance the clock to time t, expiring at most max_expire timers. + * + * @param t the new time. + * @param max_expire the maximum number of timers to expire. + * @return the number of timers expired. + */ int Advance(double t, int max_expire); - // Returns the number of timers expired (so far) during the current - // or most recent advance. + /** + * Returns the number of timers expired (so far) during the current + * or most recent advance. + */ int NumExpiredDuringCurrentAdvance() { return num_expired; } - // Expire all timers. + /** + * Expire all timers. + */ virtual void Expire() = 0; - // Cancel() is a method separate from Remove because - // (1) Remove is protected, but, more importantly, (2) in some - // timer schemes we have wound up separating timer cancelation - // from removing it from the manager's data structures, because - // the manager lacked an efficient way to find it. + /** + * Removes a timer. Cancel() is a method separate from Remove() + * because (1) Remove is protected, but, more importantly, (2) + * in some timer schemes we have wound up separating timer + * cancelation from removing it from the manager's data structures, + * because the manager lacked an efficient way to find it. + * + * @param timer the timer to cancel + */ void Cancel(Timer* timer) { Remove(timer); } double Time() const { return t ? t : 1; } // 1 > 0 - typedef std::string Tag; - const Tag& GetTag() const { return tag; } + const std::string& GetTag() const { return tag; } virtual int Size() const = 0; virtual int PeakSize() const = 0; virtual uint64_t CumulativeNum() const = 0; double LastTimestamp() const { return last_timestamp; } - // Returns time of last advance in global network time. + + /** + * Returns time of last advance in global network time + */ double LastAdvance() const { return last_advance; } static unsigned int* CurrentTimers() { return current_timers; } + // IOSource API methods + virtual double GetNextTimeout() override { return -1; } + virtual void Process() override; + virtual const char* Tag() override { return fmt("TimerMgr %s", tag.c_str()); } + + /** + * Performs some extra initialization on a timer manager. This shouldn't + * need to be called for managers other than the global one. + */ + void InitPostScript(); + protected: - explicit TimerMgr(const Tag& arg_tag) - { - t = 0.0; - num_expired = 0; - last_advance = last_timestamp = 0; - tag = arg_tag; - } + explicit TimerMgr(const std::string& arg_tag); virtual int DoAdvance(double t, int max_expire) = 0; virtual void Remove(Timer* timer) = 0; @@ -119,7 +138,7 @@ protected: double t; double last_timestamp; double last_advance; - Tag tag; + std::string tag; int num_expired; @@ -128,7 +147,7 @@ protected: class PQ_TimerMgr : public TimerMgr { public: - explicit PQ_TimerMgr(const Tag& arg_tag); + explicit PQ_TimerMgr(const std::string& arg_tag); ~PQ_TimerMgr() override; void Add(Timer* timer) override; @@ -137,6 +156,7 @@ public: int Size() const override { return q->Size(); } int PeakSize() const override { return q->PeakSize(); } uint64_t CumulativeNum() const override { return q->CumulativeNum(); } + double GetNextTimeout() override; protected: int DoAdvance(double t, int max_expire) override; diff --git a/src/main.cc b/src/main.cc index 72a1b5ce79..6e9ad81d05 100644 --- a/src/main.cc +++ b/src/main.cc @@ -294,12 +294,10 @@ void terminate_bro() plugin_mgr->FinishPlugins(); delete zeekygen_mgr; - delete timer_mgr; delete event_registry; delete analyzer_mgr; delete file_mgr; - // broker_mgr is deleted via iosource_mgr - // supervisor is deleted via iosource_mgr + // broker_mgr, timer_mgr, and supervisor are deleted via iosource_mgr delete iosource_mgr; delete log_mgr; delete reporter; @@ -550,7 +548,6 @@ int main(int argc, char** argv) #endif timer_mgr = new PQ_TimerMgr(""); - // timer_mgr = new CQ_TimerMgr(); auto zeekygen_cfg = options.zeekygen_config_file.value_or(""); zeekygen_mgr = new zeekygen::Manager(zeekygen_cfg, bro_argv[0]); @@ -671,6 +668,7 @@ int main(int argc, char** argv) plugin_mgr->InitPostScript(); zeekygen_mgr->InitPostScript(); broker_mgr->InitPostScript(); + timer_mgr->InitPostScript(); if ( options.print_plugins ) {