Fix an issue where expired Timer pointers caused other timers to be delayed.

Fixes #6179
This commit is contained in:
Gunnar Beutner 2014-05-09 19:26:31 +02:00
parent 4c235f7785
commit 042e4270bf
7 changed files with 25 additions and 41 deletions

View File

@ -32,37 +32,17 @@
using namespace icinga; using namespace icinga;
/** struct TimerHolder
* @ingroup base
*/
struct icinga::TimerNextExtractor
{ {
typedef double result_type; Timer::WeakPtr Object;
double Next;
/**
* Extracts the next timestamp from a Timer.
*
* Note: Caller must hold l_Mutex.
*
* @param wtimer Weak pointer to the timer.
* @returns The next timestamp
*/
double operator()(const weak_ptr<Timer>& wtimer) const
{
Timer::Ptr timer = wtimer.lock();
if (!timer)
return 0;
return timer->m_Next;
}
}; };
typedef boost::multi_index_container< typedef boost::multi_index_container<
Timer::WeakPtr, TimerHolder,
boost::multi_index::indexed_by< boost::multi_index::indexed_by<
boost::multi_index::ordered_unique<boost::multi_index::identity<Timer::WeakPtr> >, boost::multi_index::ordered_unique<boost::multi_index::member<TimerHolder, Timer::WeakPtr, &TimerHolder::Object> >,
boost::multi_index::ordered_non_unique<TimerNextExtractor> boost::multi_index::ordered_non_unique<boost::multi_index::member<TimerHolder, double, &TimerHolder::Next> >
> >
> TimerSet; > TimerSet;
@ -205,7 +185,11 @@ void Timer::Reschedule(double next)
if (m_Started) { if (m_Started) {
/* Remove and re-add the timer to update the index. */ /* Remove and re-add the timer to update the index. */
l_Timers.erase(GetSelf()); l_Timers.erase(GetSelf());
l_Timers.insert(GetSelf());
TimerHolder th;
th.Object = GetSelf();
th.Next = m_Next;
l_Timers.insert(th);
/* Notify the worker that we've rescheduled a timer. */ /* Notify the worker that we've rescheduled a timer. */
l_CV.notify_all(); l_CV.notify_all();
@ -242,8 +226,8 @@ void Timer::AdjustTimers(double adjustment)
std::vector<Timer::Ptr> timers; std::vector<Timer::Ptr> timers;
BOOST_FOREACH(const Timer::WeakPtr& wtimer, idx) { BOOST_FOREACH(const TimerHolder& th, idx) {
Timer::Ptr timer = wtimer.lock(); Timer::Ptr timer = th.Object.lock();
if (!timer) if (!timer)
continue; continue;
@ -257,7 +241,11 @@ void Timer::AdjustTimers(double adjustment)
BOOST_FOREACH(const Timer::Ptr& timer, timers) { BOOST_FOREACH(const Timer::Ptr& timer, timers) {
l_Timers.erase(timer); l_Timers.erase(timer);
l_Timers.insert(timer);
TimerHolder th;
th.Object = timer;
th.Next = timer->m_Next;
l_Timers.insert(th);
} }
/* Notify the worker that we've rescheduled some timers. */ /* Notify the worker that we've rescheduled some timers. */
@ -285,7 +273,7 @@ void Timer::TimerThreadProc(void)
break; break;
NextTimerView::iterator it = idx.begin(); NextTimerView::iterator it = idx.begin();
Timer::Ptr timer = it->lock(); Timer::Ptr timer = it->Object.lock();
if (!timer) { if (!timer) {
/* Remove the timer from the list if it's not alive anymore. */ /* Remove the timer from the list if it's not alive anymore. */

View File

@ -26,8 +26,6 @@
namespace icinga { namespace icinga {
struct TimerNextExtractor;
/** /**
* A timer that periodically triggers an event. * A timer that periodically triggers an event.
* *

View File

@ -39,6 +39,8 @@ boost::signals2::signal<void (const Checkable::Ptr&, const Downtime::Ptr&, const
boost::signals2::signal<void (const Checkable::Ptr&, const Downtime::Ptr&, const MessageOrigin&)> Checkable::OnDowntimeRemoved; boost::signals2::signal<void (const Checkable::Ptr&, const Downtime::Ptr&, const MessageOrigin&)> Checkable::OnDowntimeRemoved;
boost::signals2::signal<void (const Checkable::Ptr&, const Downtime::Ptr&)> Checkable::OnDowntimeTriggered; boost::signals2::signal<void (const Checkable::Ptr&, const Downtime::Ptr&)> Checkable::OnDowntimeTriggered;
INITIALIZE_ONCE(&Checkable::StartDowntimesExpiredTimer);
int Checkable::GetNextDowntimeID(void) int Checkable::GetNextDowntimeID(void)
{ {
boost::mutex::scoped_lock lock(l_DowntimeMutex); boost::mutex::scoped_lock lock(l_DowntimeMutex);

View File

@ -37,8 +37,6 @@ using namespace icinga;
REGISTER_TYPE(Checkable); REGISTER_TYPE(Checkable);
INITIALIZE_ONCE(&Checkable::StartDowntimesExpiredTimer);
boost::signals2::signal<void (const Checkable::Ptr&, const String&, const String&, AcknowledgementType, double, const MessageOrigin&)> Checkable::OnAcknowledgementSet; boost::signals2::signal<void (const Checkable::Ptr&, const String&, const String&, AcknowledgementType, double, const MessageOrigin&)> Checkable::OnAcknowledgementSet;
boost::signals2::signal<void (const Checkable::Ptr&, const MessageOrigin&)> Checkable::OnAcknowledgementCleared; boost::signals2::signal<void (const Checkable::Ptr&, const MessageOrigin&)> Checkable::OnAcknowledgementCleared;

View File

@ -37,8 +37,6 @@ using namespace icinga;
REGISTER_TYPE(Service); REGISTER_TYPE(Service);
INITIALIZE_ONCE(&Service::StartDowntimesExpiredTimer);
String ServiceNameComposer::MakeName(const String& shortName, const Dictionary::Ptr props) const { String ServiceNameComposer::MakeName(const String& shortName, const Dictionary::Ptr props) const {
if (!props) if (!props)
return ""; return "";

View File

@ -68,8 +68,8 @@ add_boost_test(base
base_string/find base_string/find
base_timer/construct base_timer/construct
base_timer/interval base_timer/interval
# base_timer/invoke base_timer/invoke
# base_timer/scope base_timer/scope
base_value/scalar base_value/scalar
base_value/convert base_value/convert
base_value/format base_value/format

View File

@ -58,7 +58,7 @@ static void Callback(int *counter)
(*counter)++; (*counter)++;
} }
/*BOOST_AUTO_TEST_CASE(invoke) BOOST_AUTO_TEST_CASE(invoke)
{ {
int counter; int counter;
Timer::Ptr timer = make_shared<Timer>(); Timer::Ptr timer = make_shared<Timer>();
@ -87,6 +87,6 @@ BOOST_AUTO_TEST_CASE(scope)
Utility::Sleep(5.5); Utility::Sleep(5.5);
BOOST_CHECK(counter >= 4 && counter <= 6); BOOST_CHECK(counter >= 4 && counter <= 6);
}*/ }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()