From 8c2ab8f5525f5fbb6e876722d78c72acf9c889c6 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Tue, 22 Jan 2013 11:07:09 +0100 Subject: [PATCH] Move service check code into the Service class. Fixes #3546 --- components/checker/checkercomponent.cpp | 67 +------------------- components/checker/checkercomponent.h | 2 +- lib/icinga/service.cpp | 83 +++++++++++++++++++++++++ lib/icinga/service.h | 7 +++ 4 files changed, 94 insertions(+), 65 deletions(-) diff --git a/components/checker/checkercomponent.cpp b/components/checker/checkercomponent.cpp index 8160ab600..747da37f4 100644 --- a/components/checker/checkercomponent.cpp +++ b/components/checker/checkercomponent.cpp @@ -64,9 +64,7 @@ void CheckerComponent::CheckTimerHandler(void) CheckTimeView::iterator it = idx.begin(); Service::Ptr service = *it; - double next_check = service->GetNextCheck(); - - if (next_check > now) + if (service->GetNextCheck() > now) break; idx.erase(it); @@ -87,18 +85,7 @@ void CheckerComponent::CheckTimerHandler(void) m_PendingServices.insert(service); - /* keep track of scheduling info in case the check type doesn't provide its own information */ - Dictionary::Ptr scheduleInfo = boost::make_shared(); - scheduleInfo->Set("schedule_start", next_check); - scheduleInfo->Set("execution_start", Utility::GetTime()); - - vector arguments; - arguments.push_back(service); - ScriptTask::Ptr task; - task = service->InvokeMethod("check", arguments, boost::bind(&CheckerComponent::CheckCompletedHandler, this, service, scheduleInfo, _1)); - assert(task); /* TODO: gracefully handle missing methods */ - - service->Set("current_task", task); + service->BeginExecuteCheck(boost::bind(&CheckerComponent::CheckCompletedHandler, this, service)); tasks++; } @@ -118,56 +105,8 @@ void CheckerComponent::CheckTimerHandler(void) } } -void CheckerComponent::CheckCompletedHandler(const Service::Ptr& service, const Dictionary::Ptr& scheduleInfo, const ScriptTask::Ptr& task) +void CheckerComponent::CheckCompletedHandler(const Service::Ptr& service) { - service->Set("current_task", Empty); - - scheduleInfo->Set("execution_end", Utility::GetTime()); - scheduleInfo->Set("schedule_end", Utility::GetTime()); - - try { - Value vresult = task->GetResult(); - - if (vresult.IsObjectType()) { - Dictionary::Ptr result = vresult; - - if (!result->Contains("schedule_start")) - result->Set("schedule_start", scheduleInfo->Get("schedule_start")); - - if (!result->Contains("schedule_end")) - result->Set("schedule_end", scheduleInfo->Get("schedule_end")); - - if (!result->Contains("execution_start")) - result->Set("execution_start", scheduleInfo->Get("execution_start")); - - if (!result->Contains("execution_end")) - result->Set("execution_end", scheduleInfo->Get("execution_end")); - - service->ApplyCheckResult(result); - - RequestMessage rm; - rm.SetMethod("checker::ServiceStateChange"); - - /* TODO: add _old_ state to message */ - ServiceStateChangeMessage params; - params.SetService(service->GetName()); - - rm.SetParams(params); - - EndpointManager::GetInstance()->SendMulticastMessage(m_Endpoint, rm); - } - } catch (const exception& ex) { - stringstream msgbuf; - msgbuf << "Exception occured during check for service '" - << service->GetName() << "': " << ex.what(); - Logger::Write(LogWarning, "checker", msgbuf.str()); - } - - /* figure out when the next check is for this service; the call to - * ApplyCheckResult() should've already done this but lets do it again - * just in case there was no check result. */ - service->UpdateNextCheck(); - /* remove the service from the list of pending services; if it's not in the * list this was a manual (i.e. forced) check and we must not re-add the * service to the services list because it's already there. */ diff --git a/components/checker/checkercomponent.h b/components/checker/checkercomponent.h index 2d12b31da..698cfdb72 100644 --- a/components/checker/checkercomponent.h +++ b/components/checker/checkercomponent.h @@ -69,7 +69,7 @@ private: void CheckTimerHandler(void); void ResultTimerHandler(void); - void CheckCompletedHandler(const Service::Ptr& service, const Dictionary::Ptr& scheduleInfo, const ScriptTask::Ptr& task); + void CheckCompletedHandler(const Service::Ptr& service); void AdjustCheckTimer(void); diff --git a/lib/icinga/service.cpp b/lib/icinga/service.cpp index c01b7640e..8e4e03e6c 100644 --- a/lib/icinga/service.cpp +++ b/lib/icinga/service.cpp @@ -480,3 +480,86 @@ void Service::OnAttributeChanged(const String& name, const Value& oldValue) if (name == "checker") OnCheckerChanged(GetSelf(), oldValue); } + +void Service::BeginExecuteCheck(const function& callback) +{ + /* don't run another check if there is one pending */ + if (Get("current_task")) { + /* we need to call the callback anyway */ + callback(); + + return; + } + + /* keep track of scheduling info in case the check type doesn't provide its own information */ + Dictionary::Ptr scheduleInfo = boost::make_shared(); + scheduleInfo->Set("schedule_start", GetNextCheck()); + scheduleInfo->Set("execution_start", Utility::GetTime()); + + vector arguments; + arguments.push_back(static_cast(GetSelf())); + ScriptTask::Ptr task; + task = InvokeMethod("check", arguments, boost::bind(&Service::CheckCompletedHandler, this, scheduleInfo, _1, callback)); + assert(task); /* TODO: gracefully handle missing methods */ + + Set("current_task", task); +} + +void Service::CheckCompletedHandler(const Dictionary::Ptr& scheduleInfo, + const ScriptTask::Ptr& task, const function& callback) +{ + Set("current_task", Empty); + + scheduleInfo->Set("execution_end", Utility::GetTime()); + scheduleInfo->Set("schedule_end", Utility::GetTime()); + + try { + Value vresult = task->GetResult(); + + if (vresult.IsObjectType()) { + Dictionary::Ptr result = vresult; + + if (!result->Contains("schedule_start")) + result->Set("schedule_start", scheduleInfo->Get("schedule_start")); + + if (!result->Contains("schedule_end")) + result->Set("schedule_end", scheduleInfo->Get("schedule_end")); + + if (!result->Contains("execution_start")) + result->Set("execution_start", scheduleInfo->Get("execution_start")); + + if (!result->Contains("execution_end")) + result->Set("execution_end", scheduleInfo->Get("execution_end")); + + ProcessCheckResult(result); + } + } catch (const exception& ex) { + stringstream msgbuf; + msgbuf << "Exception occured during check for service '" + << GetName() << "': " << ex.what(); + Logger::Write(LogWarning, "checker", msgbuf.str()); + } + + /* figure out when the next check is for this service; the call to + * ApplyCheckResult() should've already done this but lets do it again + * just in case there was no check result. */ + UpdateNextCheck(); + + callback(); +} + +void Service::ProcessCheckResult(const Dictionary::Ptr& cr) +{ + ApplyCheckResult(cr); + + RequestMessage rm; + rm.SetMethod("checker::ServiceStateChange"); + + /* TODO: add _old_ state to message */ + ServiceStateChangeMessage params; + params.SetService(GetName()); + + rm.SetParams(params); + + EndpointManager::GetInstance()->SendMulticastMessage(rm); +} diff --git a/lib/icinga/service.h b/lib/icinga/service.h index 8391cd6b6..8fc19559d 100644 --- a/lib/icinga/service.h +++ b/lib/icinga/service.h @@ -118,6 +118,9 @@ public: void ApplyCheckResult(const Dictionary::Ptr& cr); + void BeginExecuteCheck(const function& callback); + void ProcessCheckResult(const Dictionary::Ptr& cr); + static ServiceState StateFromString(const String& state); static String StateToString(ServiceState state); @@ -131,6 +134,10 @@ public: protected: virtual void OnAttributeChanged(const String& name, const Value& oldValue); + +private: + void CheckCompletedHandler(const Dictionary::Ptr& scheduleInfo, + const ScriptTask::Ptr& task, const function& callback); }; }