mirror of https://github.com/Icinga/icinga2.git
Fine-grained locks (WIP, Part 9).
This commit is contained in:
parent
404b1807e6
commit
2ef255b9f6
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
EXPORT_COMPONENT(checker, CheckerComponent);
|
REGISTER_COMPONENT("checker", CheckerComponent);
|
||||||
|
|
||||||
void CheckerComponent::Start(void)
|
void CheckerComponent::Start(void)
|
||||||
{
|
{
|
||||||
|
@ -59,12 +59,9 @@ void CheckerComponent::Stop(void)
|
||||||
|
|
||||||
void CheckerComponent::CheckThreadProc(void)
|
void CheckerComponent::CheckThreadProc(void)
|
||||||
{
|
{
|
||||||
|
boost::mutex::scoped_lock lock(m_Mutex);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
vector<Service::Ptr> services;
|
|
||||||
Service::Ptr service;
|
|
||||||
|
|
||||||
boost::mutex::scoped_lock lock(m_Mutex);
|
|
||||||
|
|
||||||
typedef nth_index<ServiceSet, 1>::type CheckTimeView;
|
typedef nth_index<ServiceSet, 1>::type CheckTimeView;
|
||||||
CheckTimeView& idx = boost::get<1>(m_IdleServices);
|
CheckTimeView& idx = boost::get<1>(m_IdleServices);
|
||||||
|
|
||||||
|
@ -75,7 +72,7 @@ void CheckerComponent::CheckThreadProc(void)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
CheckTimeView::iterator it = idx.begin();
|
CheckTimeView::iterator it = idx.begin();
|
||||||
service = it->lock();
|
Service::Ptr service = it->lock();
|
||||||
|
|
||||||
if (!service) {
|
if (!service) {
|
||||||
idx.erase(it);
|
idx.erase(it);
|
||||||
|
@ -131,20 +128,16 @@ void CheckerComponent::CheckThreadProc(void)
|
||||||
m_IdleServices.erase(service);
|
m_IdleServices.erase(service);
|
||||||
m_PendingServices.insert(service);
|
m_PendingServices.insert(service);
|
||||||
|
|
||||||
double rwait = service->GetNextCheck() - Utility::GetTime();
|
|
||||||
|
|
||||||
if (rwait < -5)
|
|
||||||
Logger::Write(LogWarning, "checker", "Check delayed: " + Convert::ToString(-rwait));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
service->BeginExecuteCheck(boost::bind(&CheckerComponent::CheckCompletedHandler, this, service));
|
olock.Unlock();
|
||||||
|
Service::BeginExecuteCheck(service, boost::bind(&CheckerComponent::CheckCompletedHandler, this, service));
|
||||||
} catch (const exception& ex) {
|
} catch (const exception& ex) {
|
||||||
|
olock.Lock();
|
||||||
Logger::Write(LogCritical, "checker", "Exception occured while checking service '" + service->GetName() + "': " + diagnostic_information(ex));
|
Logger::Write(LogCritical, "checker", "Exception occured while checking service '" + service->GetName() + "': " + diagnostic_information(ex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CheckerComponent::CheckCompletedHandler(const Service::Ptr& service)
|
void CheckerComponent::CheckCompletedHandler(const Service::Ptr& service)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(m_Mutex);
|
boost::mutex::scoped_lock lock(m_Mutex);
|
||||||
|
@ -217,4 +210,3 @@ void CheckerComponent::NextCheckChangedHandler(const Service::Ptr& service)
|
||||||
idx.insert(service);
|
idx.insert(service);
|
||||||
m_CV.notify_all();
|
m_CV.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
EXPORT_COMPONENT(compat, CompatComponent);
|
REGISTER_COMPONENT("compat", CompatComponent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hint: The reason why we're using "\n" rather than std::endl is because
|
* Hint: The reason why we're using "\n" rather than std::endl is because
|
||||||
|
@ -91,7 +91,7 @@ String CompatComponent::GetCommandPath(void) const
|
||||||
void CompatComponent::Start(void)
|
void CompatComponent::Start(void)
|
||||||
{
|
{
|
||||||
m_StatusTimer = boost::make_shared<Timer>();
|
m_StatusTimer = boost::make_shared<Timer>();
|
||||||
m_StatusTimer->SetInterval(60);
|
m_StatusTimer->SetInterval(15);
|
||||||
m_StatusTimer->OnTimerExpired.connect(boost::bind(&CompatComponent::StatusTimerHandler, this));
|
m_StatusTimer->OnTimerExpired.connect(boost::bind(&CompatComponent::StatusTimerHandler, this));
|
||||||
m_StatusTimer->Start();
|
m_StatusTimer->Start();
|
||||||
m_StatusTimer->Reschedule(0);
|
m_StatusTimer->Reschedule(0);
|
||||||
|
@ -323,11 +323,10 @@ void CompatComponent::DumpServiceStatusAttrs(ofstream& fp, const Service::Ptr& s
|
||||||
{
|
{
|
||||||
String output;
|
String output;
|
||||||
String perfdata;
|
String perfdata;
|
||||||
double schedule_start = -1, schedule_end = -1;
|
double schedule_end = -1;
|
||||||
double execution_start = -1, execution_end = -1;
|
|
||||||
|
|
||||||
Dictionary::Ptr cr;
|
Dictionary::Ptr cr;
|
||||||
int state;
|
int state, state_type;
|
||||||
Host::Ptr host;
|
Host::Ptr host;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -335,21 +334,16 @@ void CompatComponent::DumpServiceStatusAttrs(ofstream& fp, const Service::Ptr& s
|
||||||
|
|
||||||
cr = service->GetLastCheckResult();
|
cr = service->GetLastCheckResult();
|
||||||
state = service->GetState();
|
state = service->GetState();
|
||||||
|
state_type = service->GetStateType();
|
||||||
host = service->GetHost();
|
host = service->GetHost();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cr) {
|
if (cr) {
|
||||||
output = cr->Get("output");
|
output = cr->Get("output");
|
||||||
schedule_start = cr->Get("schedule_start");
|
|
||||||
schedule_end = cr->Get("schedule_end");
|
schedule_end = cr->Get("schedule_end");
|
||||||
execution_start = cr->Get("execution_start");
|
|
||||||
execution_end = cr->Get("execution_end");
|
|
||||||
perfdata = cr->Get("performance_data_raw");
|
perfdata = cr->Get("performance_data_raw");
|
||||||
}
|
}
|
||||||
|
|
||||||
double execution_time = (execution_end - execution_start);
|
|
||||||
double latency = (schedule_end - schedule_start) - execution_time;
|
|
||||||
|
|
||||||
if (state > StateUnknown)
|
if (state > StateUnknown)
|
||||||
state = StateUnknown;
|
state = StateUnknown;
|
||||||
|
|
||||||
|
@ -370,10 +364,10 @@ void CompatComponent::DumpServiceStatusAttrs(ofstream& fp, const Service::Ptr& s
|
||||||
<< "\t" << "retry_interval=" << service->GetRetryInterval() / 60.0 << "\n"
|
<< "\t" << "retry_interval=" << service->GetRetryInterval() / 60.0 << "\n"
|
||||||
<< "\t" << "has_been_checked=" << (service->GetLastCheckResult() ? 1 : 0) << "\n"
|
<< "\t" << "has_been_checked=" << (service->GetLastCheckResult() ? 1 : 0) << "\n"
|
||||||
<< "\t" << "should_be_scheduled=1" << "\n"
|
<< "\t" << "should_be_scheduled=1" << "\n"
|
||||||
<< "\t" << "check_execution_time=" << execution_time << "\n"
|
<< "\t" << "check_execution_time=" << Service::CalculateExecutionTime(cr) << "\n"
|
||||||
<< "\t" << "check_latency=" << latency << "\n"
|
<< "\t" << "check_latency=" << Service::CalculateLatency(cr) << "\n"
|
||||||
<< "\t" << "current_state=" << state << "\n"
|
<< "\t" << "current_state=" << state << "\n"
|
||||||
<< "\t" << "state_type=" << service->GetStateType() << "\n"
|
<< "\t" << "state_type=" << state_type << "\n"
|
||||||
<< "\t" << "plugin_output=" << output << "\n"
|
<< "\t" << "plugin_output=" << output << "\n"
|
||||||
<< "\t" << "performance_data=" << perfdata << "\n"
|
<< "\t" << "performance_data=" << perfdata << "\n"
|
||||||
<< "\t" << "last_check=" << schedule_end << "\n"
|
<< "\t" << "last_check=" << schedule_end << "\n"
|
||||||
|
@ -518,7 +512,8 @@ void CompatComponent::StatusTimerHandler(void)
|
||||||
<< "\t" << "passive_host_checks_enabled=0" << "\n"
|
<< "\t" << "passive_host_checks_enabled=0" << "\n"
|
||||||
<< "\t" << "check_service_freshness=0" << "\n"
|
<< "\t" << "check_service_freshness=0" << "\n"
|
||||||
<< "\t" << "check_host_freshness=0" << "\n"
|
<< "\t" << "check_host_freshness=0" << "\n"
|
||||||
<< "\t" << "enable_flap_detection=1" << "\n"
|
<< "\t" << "enable_notifications=1" << "\n"
|
||||||
|
<< "\t" << "enable_flap_detection=0" << "\n"
|
||||||
<< "\t" << "enable_failure_prediction=0" << "\n"
|
<< "\t" << "enable_failure_prediction=0" << "\n"
|
||||||
<< "\t" << "active_scheduled_service_check_stats=" << CIB::GetActiveChecksStatistics(60) << "," << CIB::GetActiveChecksStatistics(5 * 60) << "," << CIB::GetActiveChecksStatistics(15 * 60) << "\n"
|
<< "\t" << "active_scheduled_service_check_stats=" << CIB::GetActiveChecksStatistics(60) << "," << CIB::GetActiveChecksStatistics(5 * 60) << "," << CIB::GetActiveChecksStatistics(15 * 60) << "\n"
|
||||||
<< "\t" << "passive_service_check_stats=" << CIB::GetPassiveChecksStatistics(60) << "," << CIB::GetPassiveChecksStatistics(5 * 60) << "," << CIB::GetPassiveChecksStatistics(15 * 60) << "\n"
|
<< "\t" << "passive_service_check_stats=" << CIB::GetPassiveChecksStatistics(60) << "," << CIB::GetPassiveChecksStatistics(5 * 60) << "," << CIB::GetPassiveChecksStatistics(15 * 60) << "\n"
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
EXPORT_COMPONENT(compatido, CompatIdoComponent);
|
REGISTER_COMPONENT("compatido", CompatIdoComponent);
|
||||||
|
|
||||||
const String CompatIdoComponent::DefaultSocketAddress = "127.0.0.1";
|
const String CompatIdoComponent::DefaultSocketAddress = "127.0.0.1";
|
||||||
const String CompatIdoComponent::DefaultSocketPort = "5668";
|
const String CompatIdoComponent::DefaultSocketPort = "5668";
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
EXPORT_COMPONENT(delegation, DelegationComponent);
|
REGISTER_COMPONENT("delegation", DelegationComponent);
|
||||||
|
|
||||||
void DelegationComponent::Start(void)
|
void DelegationComponent::Start(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
EXPORT_COMPONENT(demo, DemoComponent);
|
REGISTER_COMPONENT("demo", DemoComponent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the component.
|
* Starts the component.
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
EXPORT_COMPONENT(notification, NotificationComponent);
|
REGISTER_COMPONENT("notification", NotificationComponent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the component.
|
* Starts the component.
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
EXPORT_COMPONENT(replication, ReplicationComponent);
|
REGISTER_COMPONENT("replication", ReplicationComponent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the component.
|
* Starts the component.
|
||||||
|
|
|
@ -210,7 +210,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
Component::AddSearchDir(Application::GetPkgLibDir());
|
Component::AddSearchDir(Application::GetPkgLibDir());
|
||||||
|
|
||||||
Utility::LoadIcingaLibrary("icinga", false);
|
(void) Utility::LoadIcingaLibrary("icinga", false);
|
||||||
|
|
||||||
if (g_AppParams.count("library")) {
|
if (g_AppParams.count("library")) {
|
||||||
BOOST_FOREACH(const String& libraryName, g_AppParams["library"].as<vector<String> >()) {
|
BOOST_FOREACH(const String& libraryName, g_AppParams["library"].as<vector<String> >()) {
|
||||||
|
|
|
@ -34,6 +34,8 @@ libbase_la_SOURCES = \
|
||||||
netstring.h \
|
netstring.h \
|
||||||
object.cpp \
|
object.cpp \
|
||||||
object.h \
|
object.h \
|
||||||
|
objectlock.cpp \
|
||||||
|
objectlock.h \
|
||||||
process.cpp \
|
process.cpp \
|
||||||
process-unix.cpp \
|
process-unix.cpp \
|
||||||
process-windows.cpp \
|
process-windows.cpp \
|
||||||
|
|
|
@ -120,8 +120,12 @@ void Application::ProfileTimerHandler(void)
|
||||||
|
|
||||||
void Application::ShutdownTimerHandler(void)
|
void Application::ShutdownTimerHandler(void)
|
||||||
{
|
{
|
||||||
if (m_ShuttingDown)
|
if (m_ShuttingDown) {
|
||||||
|
Application::GetInstance()->OnShutdown();
|
||||||
|
DynamicObject::DeactivateObjects();
|
||||||
GetEQ().Stop();
|
GetEQ().Stop();
|
||||||
|
m_ShuttingDown = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -424,8 +428,6 @@ int Application::Run(void)
|
||||||
|
|
||||||
result = Main();
|
result = Main();
|
||||||
|
|
||||||
DynamicObject::DeactivateObjects();
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,8 @@ public:
|
||||||
protected:
|
protected:
|
||||||
void RunEventLoop(void) const;
|
void RunEventLoop(void) const;
|
||||||
|
|
||||||
|
virtual void OnShutdown(void) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Application *m_Instance; /**< The application instance. */
|
static Application *m_Instance; /**< The application instance. */
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ public:
|
||||||
void Start(const CompletionCallback& completionCallback = CompletionCallback())
|
void Start(const CompletionCallback& completionCallback = CompletionCallback())
|
||||||
{
|
{
|
||||||
m_CompletionCallback = completionCallback;
|
m_CompletionCallback = completionCallback;
|
||||||
Utility::QueueAsyncCallback(boost::bind(&AsyncTask<TClass, TResult>::Run, this));
|
Utility::QueueAsyncCallback(boost::bind(&AsyncTask<TClass, TResult>::RunInternal, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -166,6 +166,18 @@ private:
|
||||||
Utility::QueueAsyncCallback(boost::bind(callback, GetSelf()));
|
Utility::QueueAsyncCallback(boost::bind(callback, GetSelf()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the Run() method and catches exceptions.
|
||||||
|
*/
|
||||||
|
void RunInternal(void)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Run();
|
||||||
|
} catch (const exception& ex) {
|
||||||
|
FinishException(boost::current_exception());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mutable boost::mutex m_Mutex;
|
mutable boost::mutex m_Mutex;
|
||||||
boost::condition_variable m_CV;
|
boost::condition_variable m_CV;
|
||||||
CompletionCallback m_CompletionCallback; /**< The completion callback. */
|
CompletionCallback m_CompletionCallback; /**< The completion callback. */
|
||||||
|
|
|
@ -23,6 +23,8 @@ using namespace icinga;
|
||||||
|
|
||||||
REGISTER_TYPE(Component, NULL);
|
REGISTER_TYPE(Component, NULL);
|
||||||
|
|
||||||
|
map<String, Component::Factory> Component::m_Factories;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the component class.
|
* Constructor for the component class.
|
||||||
*/
|
*/
|
||||||
|
@ -32,51 +34,20 @@ Component::Component(const Dictionary::Ptr& properties)
|
||||||
if (!IsLocal())
|
if (!IsLocal())
|
||||||
BOOST_THROW_EXCEPTION(runtime_error("Component objects must be local."));
|
BOOST_THROW_EXCEPTION(runtime_error("Component objects must be local."));
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
HMODULE
|
|
||||||
#else /* _WIN32 */
|
|
||||||
lt_dlhandle
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
hModule;
|
|
||||||
|
|
||||||
Logger::Write(LogInformation, "base", "Loading component '" + GetName() + "'");
|
Logger::Write(LogInformation, "base", "Loading component '" + GetName() + "'");
|
||||||
|
|
||||||
hModule = Utility::LoadIcingaLibrary(GetName(), true);
|
(void) Utility::LoadIcingaLibrary(GetName(), true);
|
||||||
|
|
||||||
CreateComponentFunction pCreateComponent;
|
map<String, Factory>::iterator it;
|
||||||
|
it = m_Factories.find(GetName());
|
||||||
|
|
||||||
#ifdef _WIN32
|
if (it == m_Factories.end())
|
||||||
pCreateComponent = reinterpret_cast<CreateComponentFunction>(GetProcAddress(hModule,
|
BOOST_THROW_EXCEPTION(invalid_argument("Unknown component: " + GetName()));
|
||||||
"CreateComponent"));
|
|
||||||
#else /* _WIN32 */
|
|
||||||
# ifdef __GNUC__
|
|
||||||
/* suppress compiler warning for void * cast */
|
|
||||||
__extension__
|
|
||||||
# endif
|
|
||||||
pCreateComponent = reinterpret_cast<CreateComponentFunction>(lt_dlsym(hModule,
|
|
||||||
"CreateComponent"));
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
IComponent::Ptr impl;
|
IComponent::Ptr impl = it->second();
|
||||||
|
|
||||||
try {
|
if (!impl)
|
||||||
if (pCreateComponent == NULL)
|
BOOST_THROW_EXCEPTION(runtime_error("Component factory returned NULL."));
|
||||||
BOOST_THROW_EXCEPTION(runtime_error("Loadable module does not contain "
|
|
||||||
"CreateComponent function"));
|
|
||||||
|
|
||||||
/* pCreateComponent returns a raw pointer which we must wrap in a shared_ptr */
|
|
||||||
impl = IComponent::Ptr(pCreateComponent());
|
|
||||||
|
|
||||||
if (!impl)
|
|
||||||
BOOST_THROW_EXCEPTION(runtime_error("CreateComponent function returned NULL."));
|
|
||||||
} catch (...) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
FreeLibrary(hModule);
|
|
||||||
#else /* _WIN32 */
|
|
||||||
lt_dlclose(hModule);
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Impl = impl;
|
m_Impl = impl;
|
||||||
}
|
}
|
||||||
|
@ -142,3 +113,11 @@ void IComponent::Stop(void)
|
||||||
{
|
{
|
||||||
/* Nothing to do in the default implementation. */
|
/* Nothing to do in the default implementation. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a component factory.
|
||||||
|
*/
|
||||||
|
void Component::Register(const String& name, const Component::Factory& factory)
|
||||||
|
{
|
||||||
|
m_Factories[name] = factory;
|
||||||
|
}
|
||||||
|
|
|
@ -59,6 +59,8 @@ public:
|
||||||
typedef shared_ptr<Component> Ptr;
|
typedef shared_ptr<Component> Ptr;
|
||||||
typedef weak_ptr<Component> WeakPtr;
|
typedef weak_ptr<Component> WeakPtr;
|
||||||
|
|
||||||
|
typedef function<IComponent::Ptr (void)> Factory;
|
||||||
|
|
||||||
Component(const Dictionary::Ptr& properties);
|
Component(const Dictionary::Ptr& properties);
|
||||||
~Component(void);
|
~Component(void);
|
||||||
|
|
||||||
|
@ -66,30 +68,43 @@ public:
|
||||||
|
|
||||||
static void AddSearchDir(const String& componentDirectory);
|
static void AddSearchDir(const String& componentDirectory);
|
||||||
|
|
||||||
|
static void Register(const String& name, const Factory& factory);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IComponent::Ptr m_Impl; /**< The implementation object for this
|
IComponent::Ptr m_Impl; /**< The implementation object for this
|
||||||
component. */
|
component. */
|
||||||
|
|
||||||
|
static map<String, Factory> m_Factories;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef IComponent *(*CreateComponentFunction)(void);
|
/**
|
||||||
|
* Helper class for registering Component implementation classes.
|
||||||
#ifdef _WIN32
|
*
|
||||||
# define SYM_CREATECOMPONENT(component) CreateComponent
|
* @ingroup base
|
||||||
#else /* _WIN32 */
|
*/
|
||||||
# define SYM_CREATECOMPONENT(component) component ## _LTX_CreateComponent
|
class RegisterComponentHelper
|
||||||
#endif /* _WIN32 */
|
{
|
||||||
|
public:
|
||||||
|
RegisterComponentHelper(const String& name, const Component::Factory& factory)
|
||||||
|
{
|
||||||
|
Component::Register(name, factory);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the loader function for a component.
|
* Factory function for IComponent-based classes.
|
||||||
*
|
*
|
||||||
* @param component The name of the component.
|
* @ingroup base
|
||||||
* @param klass The component class.
|
|
||||||
*/
|
*/
|
||||||
#define EXPORT_COMPONENT(component, klass) \
|
template<typename T>
|
||||||
extern "C" I2_EXPORT icinga::IComponent *SYM_CREATECOMPONENT(component)(void) \
|
IComponent::Ptr ComponentFactory(void)
|
||||||
{ \
|
{
|
||||||
return new klass(); \
|
return boost::make_shared<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define REGISTER_COMPONENT(name, klass) \
|
||||||
|
static RegisterComponentHelper g_RegisterSF_ ## type(name, ComponentFactory<klass>)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,13 @@ struct DictionaryKeyLessComparer
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the Dictionary class.
|
||||||
|
*/
|
||||||
|
Dictionary::Dictionary(void)
|
||||||
|
: m_Sealed(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restrieves a value from a dictionary.
|
* Restrieves a value from a dictionary.
|
||||||
*
|
*
|
||||||
|
@ -98,6 +105,8 @@ void Dictionary::Set(const String& key, const Value& value)
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
ObjectLock olock(this);
|
||||||
|
|
||||||
|
assert(!m_Sealed);
|
||||||
|
|
||||||
if (value.IsEmpty()) {
|
if (value.IsEmpty()) {
|
||||||
Remove(key);
|
Remove(key);
|
||||||
return;
|
return;
|
||||||
|
@ -213,6 +222,15 @@ void Dictionary::Remove(Dictionary::Iterator it)
|
||||||
m_Data.erase(it);
|
m_Data.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the dictionary as read-only. Attempting to modify a sealed
|
||||||
|
* dictionary is an error.
|
||||||
|
*/
|
||||||
|
void Dictionary::Seal(void)
|
||||||
|
{
|
||||||
|
m_Sealed = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a shallow copy of a dictionary.
|
* Makes a shallow copy of a dictionary.
|
||||||
*
|
*
|
||||||
|
|
|
@ -39,11 +39,14 @@ public:
|
||||||
*/
|
*/
|
||||||
typedef map<String, Value>::iterator Iterator;
|
typedef map<String, Value>::iterator Iterator;
|
||||||
|
|
||||||
|
Dictionary(void);
|
||||||
|
|
||||||
Value Get(const char *key) const;
|
Value Get(const char *key) const;
|
||||||
Value Get(const String& key) const;
|
Value Get(const String& key) const;
|
||||||
void Set(const String& key, const Value& value);
|
void Set(const String& key, const Value& value);
|
||||||
String Add(const Value& value);
|
String Add(const Value& value);
|
||||||
bool Contains(const String& key) const;
|
bool Contains(const String& key) const;
|
||||||
|
void Seal(void);
|
||||||
|
|
||||||
Iterator Begin(void);
|
Iterator Begin(void);
|
||||||
Iterator End(void);
|
Iterator End(void);
|
||||||
|
@ -60,6 +63,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
map<String, Value> m_Data; /**< The data for the dictionary. */
|
map<String, Value> m_Data; /**< The data for the dictionary. */
|
||||||
|
bool m_Sealed; /**< Whether the dictionary is read-only. */
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Dictionary::Iterator range_begin(Dictionary::Ptr x)
|
inline Dictionary::Iterator range_begin(Dictionary::Ptr x)
|
||||||
|
|
|
@ -122,6 +122,8 @@ Dictionary::Ptr DynamicObject::BuildUpdate(double sinceTx, int attributeTypes) c
|
||||||
attrs->Set(it->first, attr);
|
attrs->Set(it->first, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attrs->Seal();
|
||||||
|
|
||||||
Dictionary::Ptr update = boost::make_shared<Dictionary>();
|
Dictionary::Ptr update = boost::make_shared<Dictionary>();
|
||||||
update->Set("attrs", attrs);
|
update->Set("attrs", attrs);
|
||||||
|
|
||||||
|
@ -130,6 +132,8 @@ Dictionary::Ptr DynamicObject::BuildUpdate(double sinceTx, int attributeTypes) c
|
||||||
else if (attrs->GetLength() == 0)
|
else if (attrs->GetLength() == 0)
|
||||||
return Dictionary::Ptr();
|
return Dictionary::Ptr();
|
||||||
|
|
||||||
|
update->Seal();
|
||||||
|
|
||||||
return update;
|
return update;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,8 +247,12 @@ void DynamicObject::InternalSetAttribute(const String& name, const Value& data,
|
||||||
* object to the list of modified objects later on if we can't
|
* object to the list of modified objects later on if we can't
|
||||||
* do it here. */
|
* do it here. */
|
||||||
|
|
||||||
boost::mutex::scoped_lock lock(m_TransactionMutex);
|
DynamicObject::Ptr self = GetSelf();
|
||||||
m_ModifiedObjects.insert(GetSelf());
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock(m_TransactionMutex);
|
||||||
|
m_ModifiedObjects.insert(self);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use insert() rather than [] so we don't overwrite
|
/* Use insert() rather than [] so we don't overwrite
|
||||||
|
@ -496,7 +504,7 @@ void DynamicObject::RestoreObjects(const String& filename)
|
||||||
|
|
||||||
stringstream msgbuf;
|
stringstream msgbuf;
|
||||||
msgbuf << "Restored " << restored << " objects";
|
msgbuf << "Restored " << restored << " objects";
|
||||||
Logger::Write(LogDebug, "base", msgbuf.str());
|
Logger::Write(LogInformation, "base", msgbuf.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicObject::DeactivateObjects(void)
|
void DynamicObject::DeactivateObjects(void)
|
||||||
|
|
|
@ -81,7 +81,7 @@ void EventQueue::QueueThreadProc(void)
|
||||||
while (m_Events.empty() && !m_Stopped)
|
while (m_Events.empty() && !m_Stopped)
|
||||||
m_CV.wait(lock);
|
m_CV.wait(lock);
|
||||||
|
|
||||||
if (m_Stopped)
|
if (m_Events.empty() && m_Stopped)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
events.swap(m_Events);
|
events.swap(m_Events);
|
||||||
|
@ -94,7 +94,7 @@ void EventQueue::QueueThreadProc(void)
|
||||||
|
|
||||||
double et = Utility::GetTime();
|
double et = Utility::GetTime();
|
||||||
|
|
||||||
if (et - st > 1.0) {
|
if (et - st > 0.25) {
|
||||||
stringstream msgbuf;
|
stringstream msgbuf;
|
||||||
msgbuf << "Event call took " << et - st << " seconds.";
|
msgbuf << "Event call took " << et - st << " seconds.";
|
||||||
Logger::Write(LogWarning, "base", msgbuf.str());
|
Logger::Write(LogWarning, "base", msgbuf.str());
|
||||||
|
@ -118,7 +118,7 @@ void EventQueue::Post(const EventQueue::Callback& callback)
|
||||||
int pending = m_Events.size();
|
int pending = m_Events.size();
|
||||||
double now = Utility::GetTime();
|
double now = Utility::GetTime();
|
||||||
if (pending > 1000 && now - m_LastReport > 5) {
|
if (pending > 1000 && now - m_LastReport > 5) {
|
||||||
Logger::Write(LogWarning, "base", "More than 1000 pending events: " + Convert::ToString(pending));
|
Logger::Write(LogCritical, "base", "More than 1000 pending events: " + Convert::ToString(pending));
|
||||||
m_LastReport = now;
|
m_LastReport = now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,6 +190,7 @@ namespace signals2 = boost::signals2;
|
||||||
#include "qstring.h"
|
#include "qstring.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
|
#include "objectlock.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
#include "eventqueue.h"
|
#include "eventqueue.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
|
|
|
@ -106,38 +106,6 @@ private:
|
||||||
mutable recursive_mutex m_Mutex;
|
mutable recursive_mutex m_Mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* A scoped lock for Objects.
|
|
||||||
*/
|
|
||||||
struct ObjectLock {
|
|
||||||
public:
|
|
||||||
ObjectLock(void)
|
|
||||||
: m_Lock()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
ObjectLock(const Object::Ptr& object)
|
|
||||||
: m_Lock()
|
|
||||||
{
|
|
||||||
if (object)
|
|
||||||
m_Lock = recursive_mutex::scoped_lock(object->GetMutex());
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectLock(const Object *object)
|
|
||||||
: m_Lock()
|
|
||||||
{
|
|
||||||
if (object)
|
|
||||||
m_Lock = recursive_mutex::scoped_lock(object->GetMutex());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Unlock(void)
|
|
||||||
{
|
|
||||||
m_Lock = recursive_mutex::scoped_lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
recursive_mutex::scoped_lock m_Lock;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares a weak pointer with a raw pointer.
|
* Compares a weak pointer with a raw pointer.
|
||||||
*
|
*
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
int Process::m_TaskFd;
|
int Process::m_TaskFd;
|
||||||
|
Timer::Ptr Process::m_StatusTimer;
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
|
|
||||||
void Process::Initialize(void)
|
void Process::Initialize(void)
|
||||||
|
@ -37,7 +38,7 @@ void Process::Initialize(void)
|
||||||
if (pipe(fds) < 0)
|
if (pipe(fds) < 0)
|
||||||
BOOST_THROW_EXCEPTION(PosixException("pipe() failed.", errno));
|
BOOST_THROW_EXCEPTION(PosixException("pipe() failed.", errno));
|
||||||
|
|
||||||
/* Don't bother setting fds[1] to clo-exec as we'll only
|
/* Don't bother setting fds[0] to clo-exec as we'll only
|
||||||
* use it in the following dup() call. */
|
* use it in the following dup() call. */
|
||||||
|
|
||||||
Utility::SetCloExec(fds[1]);
|
Utility::SetCloExec(fds[1]);
|
||||||
|
@ -59,6 +60,11 @@ void Process::Initialize(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) close(fds[0]);
|
(void) close(fds[0]);
|
||||||
|
|
||||||
|
m_StatusTimer = boost::make_shared<Timer>();
|
||||||
|
m_StatusTimer->OnTimerExpired.connect(boost::bind(&Process::StatusTimerHandler));
|
||||||
|
m_StatusTimer->SetInterval(5);
|
||||||
|
m_StatusTimer->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::WorkerThreadProc(int taskFd)
|
void Process::WorkerThreadProc(int taskFd)
|
||||||
|
@ -314,4 +320,12 @@ bool Process::RunTask(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Process::StatusTimerHandler(void)
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock(m_Mutex);
|
||||||
|
if (m_Tasks.size() > 50)
|
||||||
|
Logger::Write(LogCritical, "base", "More than 50 waiting Process tasks: " +
|
||||||
|
Convert::ToString(m_Tasks.size()));
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
|
@ -24,7 +24,6 @@ using namespace icinga;
|
||||||
boost::once_flag Process::m_ThreadOnce = BOOST_ONCE_INIT;
|
boost::once_flag Process::m_ThreadOnce = BOOST_ONCE_INIT;
|
||||||
boost::mutex Process::m_Mutex;
|
boost::mutex Process::m_Mutex;
|
||||||
deque<Process::Ptr> Process::m_Tasks;
|
deque<Process::Ptr> Process::m_Tasks;
|
||||||
double Process::m_LastReport = 0;
|
|
||||||
|
|
||||||
Process::Process(const vector<String>& arguments, const Dictionary::Ptr& extraEnvironment)
|
Process::Process(const vector<String>& arguments, const Dictionary::Ptr& extraEnvironment)
|
||||||
: AsyncTask<Process, ProcessResult>(), m_Arguments(arguments), m_ExtraEnvironment(extraEnvironment)
|
: AsyncTask<Process, ProcessResult>(), m_Arguments(arguments), m_ExtraEnvironment(extraEnvironment)
|
||||||
|
@ -66,18 +65,9 @@ vector<String> Process::SplitCommand(const Value& command)
|
||||||
|
|
||||||
void Process::Run(void)
|
void Process::Run(void)
|
||||||
{
|
{
|
||||||
int count;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(m_Mutex);
|
boost::mutex::scoped_lock lock(m_Mutex);
|
||||||
m_Tasks.push_back(GetSelf());
|
m_Tasks.push_back(GetSelf());
|
||||||
count = m_Tasks.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count > 50 && Utility::GetTime() - m_LastReport > 5) {
|
|
||||||
Logger::Write(LogInformation, "base", "More than 50 pending Process tasks: " +
|
|
||||||
Convert::ToString(count));
|
|
||||||
m_LastReport = Utility::GetTime();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NotifyWorker();
|
NotifyWorker();
|
||||||
|
|
|
@ -69,10 +69,11 @@ private:
|
||||||
virtual void Run(void);
|
virtual void Run(void);
|
||||||
|
|
||||||
static boost::mutex m_Mutex;
|
static boost::mutex m_Mutex;
|
||||||
static double m_LastReport;
|
|
||||||
static deque<Process::Ptr> m_Tasks;
|
static deque<Process::Ptr> m_Tasks;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
static int m_TaskFd;
|
static int m_TaskFd;
|
||||||
|
|
||||||
|
static Timer::Ptr m_StatusTimer;
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
static void NotifyWorker(void);
|
static void NotifyWorker(void);
|
||||||
|
@ -83,6 +84,8 @@ private:
|
||||||
static void WorkerThreadProc(void);
|
static void WorkerThreadProc(void);
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
static void WorkerThreadProc(int taskFd);
|
static void WorkerThreadProc(int taskFd);
|
||||||
|
|
||||||
|
static void StatusTimerHandler(void);
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
void InitTask(void);
|
void InitTask(void);
|
||||||
|
|
|
@ -54,6 +54,38 @@ bool Value::IsObject(void) const
|
||||||
return !IsEmpty() && (m_Value.type() == typeid(Object::Ptr));
|
return !IsEmpty() && (m_Value.type() == typeid(Object::Ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value::operator double(void) const
|
||||||
|
{
|
||||||
|
if (m_Value.type() != typeid(double)) {
|
||||||
|
return boost::lexical_cast<double>(m_Value);
|
||||||
|
} else {
|
||||||
|
return boost::get<double>(m_Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::operator String(void) const
|
||||||
|
{
|
||||||
|
Object *object;
|
||||||
|
double integral, fractional;
|
||||||
|
|
||||||
|
switch (GetType()) {
|
||||||
|
case ValueEmpty:
|
||||||
|
return String();
|
||||||
|
case ValueNumber:
|
||||||
|
fractional = modf(boost::get<double>(m_Value), &integral);
|
||||||
|
|
||||||
|
if (fractional != 0)
|
||||||
|
return boost::lexical_cast<String>(m_Value);
|
||||||
|
else
|
||||||
|
return boost::lexical_cast<String>((long)integral);
|
||||||
|
case ValueString:
|
||||||
|
return boost::get<String>(m_Value);
|
||||||
|
case ValueObject:
|
||||||
|
object = boost::get<Object::Ptr>(m_Value).get();
|
||||||
|
return "Object of type '" + Utility::GetTypeName(typeid(*object)) + "'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a JSON object into a variant.
|
* Converts a JSON object into a variant.
|
||||||
*
|
*
|
||||||
|
|
|
@ -85,27 +85,8 @@ public:
|
||||||
m_Value = object;
|
m_Value = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator double(void) const
|
operator double(void) const;
|
||||||
{
|
operator String(void) const;
|
||||||
if (m_Value.type() != typeid(double)) {
|
|
||||||
return boost::lexical_cast<double>(m_Value);
|
|
||||||
} else {
|
|
||||||
return boost::get<double>(m_Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
operator String(void) const
|
|
||||||
{
|
|
||||||
if (IsEmpty())
|
|
||||||
return String();
|
|
||||||
|
|
||||||
if (m_Value.type() != typeid(String)) {
|
|
||||||
String result = boost::lexical_cast<String>(m_Value);
|
|
||||||
m_Value = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return boost::get<String>(m_Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
operator shared_ptr<T>(void) const
|
operator shared_ptr<T>(void) const
|
||||||
|
|
|
@ -386,7 +386,7 @@ static yyconst flex_int16_t yy_accept[193] =
|
||||||
54, 49, 42, 42, 42, 42, 42, 42, 42, 42,
|
54, 49, 42, 42, 42, 42, 42, 42, 42, 42,
|
||||||
42, 42, 42, 54, 18, 19, 12, 3, 2, 55,
|
42, 42, 42, 54, 18, 19, 12, 3, 2, 55,
|
||||||
15, 15, 21, 0, 0, 0, 0, 0, 42, 52,
|
15, 15, 21, 0, 0, 0, 0, 0, 42, 52,
|
||||||
50, 48, 51, 16, 0, 53, 0, 45, 46, 47,
|
50, 48, 51, 16, 20, 53, 0, 45, 46, 47,
|
||||||
0, 43, 42, 42, 42, 42, 42, 42, 42, 42,
|
0, 43, 42, 42, 42, 42, 42, 42, 42, 42,
|
||||||
42, 42, 42, 42, 42, 42, 0, 18, 17, 12,
|
42, 42, 42, 42, 42, 42, 0, 18, 17, 12,
|
||||||
11, 4, 5, 9, 10, 6, 8, 7, 0, 0,
|
11, 4, 5, 9, 10, 6, 8, 7, 0, 0,
|
||||||
|
@ -793,6 +793,10 @@ int yyget_lineno (yyscan_t yyscanner );
|
||||||
|
|
||||||
void yyset_lineno (int line_number ,yyscan_t yyscanner );
|
void yyset_lineno (int line_number ,yyscan_t yyscanner );
|
||||||
|
|
||||||
|
int yyget_column (yyscan_t yyscanner );
|
||||||
|
|
||||||
|
void yyset_column (int column_no ,yyscan_t yyscanner );
|
||||||
|
|
||||||
YYSTYPE * yyget_lval (yyscan_t yyscanner );
|
YYSTYPE * yyget_lval (yyscan_t yyscanner );
|
||||||
|
|
||||||
void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
|
void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
|
||||||
|
@ -948,7 +952,7 @@ YY_DECL
|
||||||
|
|
||||||
lex_buf string_buf;
|
lex_buf string_buf;
|
||||||
|
|
||||||
#line 952 "config_lexer.cc"
|
#line 956 "config_lexer.cc"
|
||||||
|
|
||||||
yylval = yylval_param;
|
yylval = yylval_param;
|
||||||
|
|
||||||
|
@ -1377,7 +1381,7 @@ YY_RULE_SETUP
|
||||||
#line 216 "config_lexer.ll"
|
#line 216 "config_lexer.ll"
|
||||||
ECHO;
|
ECHO;
|
||||||
YY_BREAK
|
YY_BREAK
|
||||||
#line 1381 "config_lexer.cc"
|
#line 1385 "config_lexer.cc"
|
||||||
case YY_STATE_EOF(INITIAL):
|
case YY_STATE_EOF(INITIAL):
|
||||||
case YY_STATE_EOF(C_COMMENT):
|
case YY_STATE_EOF(C_COMMENT):
|
||||||
case YY_STATE_EOF(STRING):
|
case YY_STATE_EOF(STRING):
|
||||||
|
|
|
@ -173,7 +173,7 @@ static void lb_append_char(lex_buf *lb, char new_char)
|
||||||
"*" /* ignore star */
|
"*" /* ignore star */
|
||||||
}
|
}
|
||||||
|
|
||||||
\/\/[^\n]+ /* ignore C++-style comments */
|
\/\/[^\n]* /* ignore C++-style comments */
|
||||||
[ \t\r\n]+ /* ignore whitespace */
|
[ \t\r\n]+ /* ignore whitespace */
|
||||||
|
|
||||||
<INITIAL>{
|
<INITIAL>{
|
||||||
|
|
|
@ -288,6 +288,8 @@ void Host::UpdateSlaveServices(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newServices->Seal();
|
||||||
|
|
||||||
Set("slave_services", newServices);
|
Set("slave_services", newServices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,23 +481,69 @@ set<Service::Ptr> Host::GetParentServices(void) const
|
||||||
return parents;
|
return parents;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary::Ptr Host::CalculateDynamicMacros(void) const
|
Dictionary::Ptr Host::CalculateDynamicMacros(const Host::Ptr& self)
|
||||||
{
|
{
|
||||||
Dictionary::Ptr macros = boost::make_shared<Dictionary>();
|
Dictionary::Ptr macros = boost::make_shared<Dictionary>();
|
||||||
|
|
||||||
macros->Set("HOSTNAME", GetName());
|
Service::Ptr hc;
|
||||||
macros->Set("HOSTALIAS", GetName());
|
|
||||||
macros->Set("HOSTDISPLAYNAME", GetDisplayName());
|
|
||||||
macros->Set("HOSTSTATE", "DERP");
|
|
||||||
|
|
||||||
Service::Ptr hostcheck = GetHostCheckService();
|
{
|
||||||
|
ObjectLock olock(self);
|
||||||
|
|
||||||
if (hostcheck) {
|
macros->Set("HOSTNAME", self->GetName());
|
||||||
macros->Set("HOSTSTATEID", 99);
|
macros->Set("HOSTDISPLAYNAME", self->GetDisplayName());
|
||||||
macros->Set("HOSTSTATETYPE", Service::StateTypeToString(hostcheck->GetStateType()));
|
macros->Set("HOSTALIAS", self->GetName());
|
||||||
macros->Set("HOSTATTEMPT", hostcheck->GetCurrentCheckAttempt());
|
|
||||||
macros->Set("MAXHOSTATTEMPT", hostcheck->GetMaxCheckAttempts());
|
hc = self->GetHostCheckService();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool reachable = Host::IsReachable(self);
|
||||||
|
|
||||||
|
Dictionary::Ptr cr;
|
||||||
|
|
||||||
|
if (hc) {
|
||||||
|
ObjectLock olock(hc);
|
||||||
|
|
||||||
|
String state;
|
||||||
|
int stateid;
|
||||||
|
|
||||||
|
switch (hc->GetState()) {
|
||||||
|
case StateOK:
|
||||||
|
case StateWarning:
|
||||||
|
state = "UP";
|
||||||
|
stateid = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
state = "DOWN";
|
||||||
|
stateid = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reachable) {
|
||||||
|
state = "UNREACHABLE";
|
||||||
|
stateid = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
macros->Set("HOSTSTATE", state);
|
||||||
|
macros->Set("HOSTSTATEID", stateid);
|
||||||
|
macros->Set("HOSTSTATETYPE", Service::StateTypeToString(hc->GetStateType()));
|
||||||
|
macros->Set("HOSTATTEMPT", hc->GetCurrentCheckAttempt());
|
||||||
|
macros->Set("MAXHOSTATTEMPT", hc->GetMaxCheckAttempts());
|
||||||
|
|
||||||
|
cr = hc->GetLastCheckResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cr) {
|
||||||
|
macros->Set("HOSTLATENCY", Service::CalculateLatency(cr));
|
||||||
|
macros->Set("HOSTEXECUTIONTIME", Service::CalculateExecutionTime(cr));
|
||||||
|
|
||||||
|
ObjectLock olock(cr);
|
||||||
|
|
||||||
|
macros->Set("HOSTOUTPUT", cr->Get("output"));
|
||||||
|
macros->Set("HOSTPERFDATA", cr->Get("performance_data_raw"));
|
||||||
|
}
|
||||||
|
|
||||||
|
macros->Seal();
|
||||||
|
|
||||||
return macros;
|
return macros;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ public:
|
||||||
Dictionary::Ptr GetServiceDependencies(void) const;
|
Dictionary::Ptr GetServiceDependencies(void) const;
|
||||||
String GetHostCheck(void) const;
|
String GetHostCheck(void) const;
|
||||||
|
|
||||||
Dictionary::Ptr CalculateDynamicMacros(void) const;
|
static Dictionary::Ptr CalculateDynamicMacros(const Host::Ptr& self);
|
||||||
|
|
||||||
shared_ptr<Service> GetHostCheckService(void) const;
|
shared_ptr<Service> GetHostCheckService(void) const;
|
||||||
set<Host::Ptr> GetParentHosts(void) const;
|
set<Host::Ptr> GetParentHosts(void) const;
|
||||||
|
|
|
@ -72,14 +72,20 @@ int IcingaApplication::Main(void)
|
||||||
|
|
||||||
RunEventLoop();
|
RunEventLoop();
|
||||||
|
|
||||||
DumpProgramState();
|
|
||||||
|
|
||||||
Logger::Write(LogInformation, "icinga", "Icinga has shut down.");
|
Logger::Write(LogInformation, "icinga", "Icinga has shut down.");
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IcingaApplication::DumpProgramState(void) {
|
void IcingaApplication::OnShutdown(void)
|
||||||
|
{
|
||||||
|
m_RetentionTimer->Stop();
|
||||||
|
|
||||||
|
DumpProgramState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IcingaApplication::DumpProgramState(void)
|
||||||
|
{
|
||||||
DynamicObject::DumpObjects(GetStatePath());
|
DynamicObject::DumpObjects(GetStatePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,3 +148,12 @@ shared_ptr<SSL_CTX> IcingaApplication::GetSSLContext(void) const
|
||||||
{
|
{
|
||||||
return m_SSLContext;
|
return m_SSLContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dictionary::Ptr IcingaApplication::CalculateDynamicMacros(const IcingaApplication::Ptr& self)
|
||||||
|
{
|
||||||
|
Dictionary::Ptr macros = boost::make_shared<Dictionary>();
|
||||||
|
|
||||||
|
macros->Set("TIMET", (long)Utility::GetTime());
|
||||||
|
|
||||||
|
return macros;
|
||||||
|
}
|
||||||
|
|
|
@ -51,6 +51,8 @@ public:
|
||||||
|
|
||||||
double GetStartTime(void) const;
|
double GetStartTime(void) const;
|
||||||
|
|
||||||
|
static Dictionary::Ptr CalculateDynamicMacros(const IcingaApplication::Ptr& self);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
shared_ptr<SSL_CTX> m_SSLContext;
|
shared_ptr<SSL_CTX> m_SSLContext;
|
||||||
|
|
||||||
|
@ -59,6 +61,8 @@ private:
|
||||||
Timer::Ptr m_RetentionTimer;
|
Timer::Ptr m_RetentionTimer;
|
||||||
|
|
||||||
void DumpProgramState(void);
|
void DumpProgramState(void);
|
||||||
|
|
||||||
|
virtual void OnShutdown(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,5 +88,7 @@ Dictionary::Ptr MacroProcessor::MergeMacroDicts(const vector<Dictionary::Ptr>& d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result->Seal();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,24 +70,94 @@ Dictionary::Ptr Notification::GetMacros(void) const
|
||||||
return Get("macros");
|
return Get("macros");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Notification::SendNotification(NotificationType type)
|
String Notification::NotificationTypeToString(NotificationType type)
|
||||||
{
|
{
|
||||||
vector<Value> arguments;
|
switch (type) {
|
||||||
arguments.push_back(static_cast<Notification::Ptr>(GetSelf()));
|
case NotificationDowntimeStart:
|
||||||
arguments.push_back(type);
|
return "DOWNTIMESTART";
|
||||||
|
case NotificationDowntimeEnd:
|
||||||
|
return "DOWNTIMEEND";
|
||||||
|
case NotificationDowntimeRemoved:
|
||||||
|
return "DOWNTIMECANCELLED";
|
||||||
|
case NotificationCustom:
|
||||||
|
return "DOWNTIMECUSTOM";
|
||||||
|
case NotificationProblem:
|
||||||
|
return "PROBLEM";
|
||||||
|
case NotificationRecovery:
|
||||||
|
return "RECOVERY";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN_NOTIFICATION";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ScriptTask::Ptr task = MakeMethodTask("notify", arguments);
|
void Notification::BeginExecuteNotification(const Notification::Ptr& self, NotificationType type)
|
||||||
|
{
|
||||||
|
|
||||||
if (!task) {
|
vector<Dictionary::Ptr> macroDicts;
|
||||||
Logger::Write(LogWarning, "icinga", "Notification object '" + GetName() + "' doesn't have a 'notify' method.");
|
|
||||||
|
|
||||||
return;
|
Dictionary::Ptr notificationMacros = boost::make_shared<Dictionary>();
|
||||||
|
notificationMacros->Set("NOTIFICATIONTYPE", NotificationTypeToString(type));
|
||||||
|
macroDicts.push_back(notificationMacros);
|
||||||
|
|
||||||
|
Service::Ptr service;
|
||||||
|
|
||||||
|
{
|
||||||
|
ObjectLock olock(self);
|
||||||
|
macroDicts.push_back(self->GetMacros());
|
||||||
|
service = self->GetService();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to keep the task object alive until the completion handler is called. */
|
Host::Ptr host;
|
||||||
m_Tasks.insert(task);
|
String service_name;
|
||||||
|
|
||||||
task->Start(boost::bind(&Notification::NotificationCompletedHandler, this, _1));
|
{
|
||||||
|
ObjectLock olock(service);
|
||||||
|
macroDicts.push_back(service->GetMacros());
|
||||||
|
service_name = service->GetName();
|
||||||
|
host = service->GetHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
macroDicts.push_back(Service::CalculateDynamicMacros(service));
|
||||||
|
|
||||||
|
{
|
||||||
|
ObjectLock olock(host);
|
||||||
|
macroDicts.push_back(host->GetMacros());
|
||||||
|
macroDicts.push_back(Host::CalculateDynamicMacros(host));
|
||||||
|
}
|
||||||
|
|
||||||
|
IcingaApplication::Ptr app = IcingaApplication::GetInstance();
|
||||||
|
|
||||||
|
{
|
||||||
|
ObjectLock olock(app);
|
||||||
|
macroDicts.push_back(app->GetMacros());
|
||||||
|
}
|
||||||
|
|
||||||
|
macroDicts.push_back(IcingaApplication::CalculateDynamicMacros(app));
|
||||||
|
|
||||||
|
Dictionary::Ptr macros = MacroProcessor::MergeMacroDicts(macroDicts);
|
||||||
|
|
||||||
|
vector<Value> arguments;
|
||||||
|
arguments.push_back(self);
|
||||||
|
arguments.push_back(macros);
|
||||||
|
arguments.push_back(type);
|
||||||
|
|
||||||
|
ScriptTask::Ptr task;
|
||||||
|
|
||||||
|
{
|
||||||
|
ObjectLock olock(self);
|
||||||
|
task = self->MakeMethodTask("notify", arguments);
|
||||||
|
|
||||||
|
if (!task) {
|
||||||
|
Logger::Write(LogWarning, "icinga", "Notification object '" + self->GetName() + "' doesn't have a 'notify' method.");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We need to keep the task object alive until the completion handler is called. */
|
||||||
|
self->m_Tasks.insert(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
task->Start(boost::bind(&Notification::NotificationCompletedHandler, self, _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Notification::NotificationCompletedHandler(const ScriptTask::Ptr& task)
|
void Notification::NotificationCompletedHandler(const ScriptTask::Ptr& task)
|
||||||
|
|
|
@ -34,7 +34,8 @@ enum NotificationType
|
||||||
NotificationDowntimeEnd,
|
NotificationDowntimeEnd,
|
||||||
NotificationDowntimeRemoved,
|
NotificationDowntimeRemoved,
|
||||||
NotificationCustom,
|
NotificationCustom,
|
||||||
NotificationStateChange
|
NotificationProblem,
|
||||||
|
NotificationRecovery
|
||||||
};
|
};
|
||||||
|
|
||||||
class Service;
|
class Service;
|
||||||
|
@ -60,7 +61,9 @@ public:
|
||||||
Value GetNotificationCommand(void) const;
|
Value GetNotificationCommand(void) const;
|
||||||
Dictionary::Ptr GetMacros(void) const;
|
Dictionary::Ptr GetMacros(void) const;
|
||||||
|
|
||||||
void SendNotification(NotificationType type);
|
static void BeginExecuteNotification(const Notification::Ptr& self, NotificationType type);
|
||||||
|
|
||||||
|
static String NotificationTypeToString(NotificationType type);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void OnAttributeChanged(const String& name, const Value& oldValue);
|
void OnAttributeChanged(const String& name, const Value& oldValue);
|
||||||
|
|
|
@ -32,37 +32,19 @@ void PluginCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Value
|
||||||
if (arguments.size() < 1)
|
if (arguments.size() < 1)
|
||||||
BOOST_THROW_EXCEPTION(invalid_argument("Missing argument: Service must be specified."));
|
BOOST_THROW_EXCEPTION(invalid_argument("Missing argument: Service must be specified."));
|
||||||
|
|
||||||
Value vservice = arguments[0];
|
if (arguments.size() < 2)
|
||||||
if (!vservice.IsObjectType<Service>())
|
BOOST_THROW_EXCEPTION(invalid_argument("Missing argument: Macros must be specified."));
|
||||||
BOOST_THROW_EXCEPTION(invalid_argument("Argument must be a service."));
|
|
||||||
|
Service::Ptr service = arguments[0];
|
||||||
|
Dictionary::Ptr macros = arguments[1];
|
||||||
|
|
||||||
vector<Dictionary::Ptr> macroDicts;
|
|
||||||
Value raw_command;
|
Value raw_command;
|
||||||
Host::Ptr host;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Service::Ptr service = vservice;
|
|
||||||
ObjectLock olock(service);
|
ObjectLock olock(service);
|
||||||
macroDicts.push_back(service->GetMacros());
|
|
||||||
macroDicts.push_back(service->CalculateDynamicMacros());
|
|
||||||
raw_command = service->GetCheckCommand();
|
raw_command = service->GetCheckCommand();
|
||||||
host = service->GetHost();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
ObjectLock olock(host);
|
|
||||||
macroDicts.push_back(host->GetMacros());
|
|
||||||
macroDicts.push_back(host->CalculateDynamicMacros());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
IcingaApplication::Ptr app = IcingaApplication::GetInstance();
|
|
||||||
ObjectLock olock(app);
|
|
||||||
macroDicts.push_back(app->GetMacros());
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary::Ptr macros = MacroProcessor::MergeMacroDicts(macroDicts);
|
|
||||||
|
|
||||||
Value command = MacroProcessor::ResolveMacros(raw_command, macros);
|
Value command = MacroProcessor::ResolveMacros(raw_command, macros);
|
||||||
|
|
||||||
Process::Ptr process = boost::make_shared<Process>(Process::SplitCommand(command), macros);
|
Process::Ptr process = boost::make_shared<Process>(Process::SplitCommand(command), macros);
|
||||||
|
|
|
@ -37,49 +37,30 @@ void PluginNotificationTask::ScriptFunc(const ScriptTask::Ptr& task, const vecto
|
||||||
BOOST_THROW_EXCEPTION(invalid_argument("Missing argument: Notification target must be specified."));
|
BOOST_THROW_EXCEPTION(invalid_argument("Missing argument: Notification target must be specified."));
|
||||||
|
|
||||||
if (arguments.size() < 2)
|
if (arguments.size() < 2)
|
||||||
|
BOOST_THROW_EXCEPTION(invalid_argument("Missing argument: Macros must be specified."));
|
||||||
|
|
||||||
|
if (arguments.size() < 3)
|
||||||
BOOST_THROW_EXCEPTION(invalid_argument("Missing argument: Notification type must be specified."));
|
BOOST_THROW_EXCEPTION(invalid_argument("Missing argument: Notification type must be specified."));
|
||||||
|
|
||||||
if (!arguments[0].IsObjectType<Notification>())
|
Notification::Ptr notification = arguments[0];
|
||||||
BOOST_THROW_EXCEPTION(invalid_argument("Argument must be a service."));
|
Dictionary::Ptr macros = arguments[1];
|
||||||
|
NotificationType type = static_cast<NotificationType>(static_cast<int>(arguments[2]));
|
||||||
|
|
||||||
NotificationType type = static_cast<NotificationType>(static_cast<int>(arguments[1]));
|
|
||||||
|
|
||||||
vector<Dictionary::Ptr> macroDicts;
|
|
||||||
Value raw_command;
|
Value raw_command;
|
||||||
Service::Ptr service;
|
|
||||||
Host::Ptr host;
|
|
||||||
String service_name;
|
String service_name;
|
||||||
|
Service::Ptr service;
|
||||||
|
|
||||||
{
|
{
|
||||||
Notification::Ptr notification = arguments[0];
|
|
||||||
ObjectLock olock(notification);
|
ObjectLock olock(notification);
|
||||||
macroDicts.push_back(notification->GetMacros());
|
|
||||||
raw_command = notification->GetNotificationCommand();
|
raw_command = notification->GetNotificationCommand();
|
||||||
service = notification->GetService();
|
service = notification->GetService();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ObjectLock olock(service);
|
ObjectLock olock(service);
|
||||||
macroDicts.push_back(service->GetMacros());
|
|
||||||
macroDicts.push_back(service->CalculateDynamicMacros());
|
|
||||||
service_name = service->GetName();
|
service_name = service->GetName();
|
||||||
host = service->GetHost();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
ObjectLock olock(host);
|
|
||||||
macroDicts.push_back(host->GetMacros());
|
|
||||||
macroDicts.push_back(host->CalculateDynamicMacros());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
IcingaApplication::Ptr app = IcingaApplication::GetInstance();
|
|
||||||
ObjectLock olock(app);
|
|
||||||
macroDicts.push_back(app->GetMacros());
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary::Ptr macros = MacroProcessor::MergeMacroDicts(macroDicts);
|
|
||||||
|
|
||||||
Value command = MacroProcessor::ResolveMacros(raw_command, macros);
|
Value command = MacroProcessor::ResolveMacros(raw_command, macros);
|
||||||
|
|
||||||
Process::Ptr process = boost::make_shared<Process>(Process::SplitCommand(command), macros);
|
Process::Ptr process = boost::make_shared<Process>(Process::SplitCommand(command), macros);
|
||||||
|
|
|
@ -287,6 +287,7 @@ void Service::ApplyCheckResult(const Dictionary::Ptr& cr)
|
||||||
ServiceState old_state = GetState();
|
ServiceState old_state = GetState();
|
||||||
ServiceStateType old_stateType = GetStateType();
|
ServiceStateType old_stateType = GetStateType();
|
||||||
bool hardChange = false;
|
bool hardChange = false;
|
||||||
|
bool recovery;
|
||||||
|
|
||||||
long attempt = GetCurrentCheckAttempt();
|
long attempt = GetCurrentCheckAttempt();
|
||||||
|
|
||||||
|
@ -298,6 +299,7 @@ void Service::ApplyCheckResult(const Dictionary::Ptr& cr)
|
||||||
SetStateType(StateTypeHard);
|
SetStateType(StateTypeHard);
|
||||||
|
|
||||||
attempt = 1;
|
attempt = 1;
|
||||||
|
recovery = true;
|
||||||
} else {
|
} else {
|
||||||
if (attempt >= GetMaxCheckAttempts()) {
|
if (attempt >= GetMaxCheckAttempts()) {
|
||||||
SetStateType(StateTypeHard);
|
SetStateType(StateTypeHard);
|
||||||
|
@ -307,6 +309,8 @@ void Service::ApplyCheckResult(const Dictionary::Ptr& cr)
|
||||||
SetStateType(StateTypeSoft);
|
SetStateType(StateTypeSoft);
|
||||||
attempt++;
|
attempt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recovery = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetCurrentCheckAttempt(attempt);
|
SetCurrentCheckAttempt(attempt);
|
||||||
|
@ -353,19 +357,19 @@ void Service::ApplyCheckResult(const Dictionary::Ptr& cr)
|
||||||
Flush();
|
Flush();
|
||||||
|
|
||||||
if (IsReachable(GetSelf()) && !IsInDowntime() && !IsAcknowledged())
|
if (IsReachable(GetSelf()) && !IsInDowntime() && !IsAcknowledged())
|
||||||
RequestNotifications(NotificationStateChange);
|
RequestNotifications(recovery ? NotificationRecovery : NotificationProblem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ServiceState Service::StateFromString(const String& state)
|
ServiceState Service::StateFromString(const String& state)
|
||||||
{
|
{
|
||||||
if (state == "ok")
|
if (state == "OK")
|
||||||
return StateOK;
|
return StateOK;
|
||||||
else if (state == "warning")
|
else if (state == "WARNING")
|
||||||
return StateWarning;
|
return StateWarning;
|
||||||
else if (state == "critical")
|
else if (state == "CRITICAL")
|
||||||
return StateCritical;
|
return StateCritical;
|
||||||
else if (state == "uncheckable")
|
else if (state == "UNCHECKABLE")
|
||||||
return StateUncheckable;
|
return StateUncheckable;
|
||||||
else
|
else
|
||||||
return StateUnknown;
|
return StateUnknown;
|
||||||
|
@ -375,22 +379,22 @@ String Service::StateToString(ServiceState state)
|
||||||
{
|
{
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case StateOK:
|
case StateOK:
|
||||||
return "ok";
|
return "OK";
|
||||||
case StateWarning:
|
case StateWarning:
|
||||||
return "warning";
|
return "WARNING";
|
||||||
case StateCritical:
|
case StateCritical:
|
||||||
return "critical";
|
return "CRITICAL";
|
||||||
case StateUncheckable:
|
case StateUncheckable:
|
||||||
return "uncheckable";
|
return "UNCHECKABLE";
|
||||||
case StateUnknown:
|
case StateUnknown:
|
||||||
default:
|
default:
|
||||||
return "unknown";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ServiceStateType Service::StateTypeFromString(const String& type)
|
ServiceStateType Service::StateTypeFromString(const String& type)
|
||||||
{
|
{
|
||||||
if (type == "soft")
|
if (type == "SOFT")
|
||||||
return StateTypeSoft;
|
return StateTypeSoft;
|
||||||
else
|
else
|
||||||
return StateTypeHard;
|
return StateTypeHard;
|
||||||
|
@ -399,9 +403,9 @@ ServiceStateType Service::StateTypeFromString(const String& type)
|
||||||
String Service::StateTypeToString(ServiceStateType type)
|
String Service::StateTypeToString(ServiceStateType type)
|
||||||
{
|
{
|
||||||
if (type == StateTypeSoft)
|
if (type == StateTypeSoft)
|
||||||
return "soft";
|
return "SOFT";
|
||||||
else
|
else
|
||||||
return "hard";
|
return "HARD";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Service::IsAllowedChecker(const String& checker) const
|
bool Service::IsAllowedChecker(const String& checker) const
|
||||||
|
@ -420,10 +424,14 @@ bool Service::IsAllowedChecker(const String& checker) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Service::BeginExecuteCheck(const function<void (void)>& callback)
|
void Service::BeginExecuteCheck(const Service::Ptr& self, const function<void (void)>& callback)
|
||||||
{
|
{
|
||||||
|
ObjectLock slock(self);
|
||||||
|
|
||||||
/* don't run another check if there is one pending */
|
/* don't run another check if there is one pending */
|
||||||
if (!Get("current_task").IsEmpty()) {
|
if (!self->Get("current_task").IsEmpty()) {
|
||||||
|
slock.Unlock();
|
||||||
|
|
||||||
/* we need to call the callback anyway */
|
/* we need to call the callback anyway */
|
||||||
callback();
|
callback();
|
||||||
|
|
||||||
|
@ -431,28 +439,59 @@ void Service::BeginExecuteCheck(const function<void (void)>& callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* keep track of scheduling info in case the check type doesn't provide its own information */
|
/* keep track of scheduling info in case the check type doesn't provide its own information */
|
||||||
Dictionary::Ptr scheduleInfo = boost::make_shared<Dictionary>();
|
Dictionary::Ptr checkInfo = boost::make_shared<Dictionary>();
|
||||||
scheduleInfo->Set("schedule_start", GetNextCheck());
|
checkInfo->Set("schedule_start", self->GetNextCheck());
|
||||||
scheduleInfo->Set("execution_start", Utility::GetTime());
|
checkInfo->Set("execution_start", Utility::GetTime());
|
||||||
|
|
||||||
|
vector<Dictionary::Ptr> macroDicts;
|
||||||
|
macroDicts.push_back(self->GetMacros());
|
||||||
|
macroDicts.push_back(Service::CalculateDynamicMacros(self));
|
||||||
|
|
||||||
|
Value raw_command = self->GetCheckCommand();
|
||||||
|
|
||||||
|
Host::Ptr host = self->GetHost();
|
||||||
|
|
||||||
|
slock.Unlock();
|
||||||
|
|
||||||
|
{
|
||||||
|
ObjectLock olock(host);
|
||||||
|
macroDicts.push_back(host->GetMacros());
|
||||||
|
macroDicts.push_back(Host::CalculateDynamicMacros(host));
|
||||||
|
}
|
||||||
|
|
||||||
|
IcingaApplication::Ptr app = IcingaApplication::GetInstance();
|
||||||
|
|
||||||
|
{
|
||||||
|
ObjectLock olock(app);
|
||||||
|
macroDicts.push_back(app->GetMacros());
|
||||||
|
}
|
||||||
|
|
||||||
|
macroDicts.push_back(IcingaApplication::CalculateDynamicMacros(app));
|
||||||
|
|
||||||
|
Dictionary::Ptr macros = MacroProcessor::MergeMacroDicts(macroDicts);
|
||||||
|
|
||||||
|
checkInfo->Set("macros", macros);
|
||||||
|
|
||||||
vector<Value> arguments;
|
vector<Value> arguments;
|
||||||
arguments.push_back(static_cast<Service::Ptr>(GetSelf()));
|
arguments.push_back(self);
|
||||||
|
arguments.push_back(macros);
|
||||||
|
|
||||||
ScriptTask::Ptr task = MakeMethodTask("check", arguments);
|
ScriptTask::Ptr task;
|
||||||
Set("current_task", task);
|
|
||||||
|
|
||||||
task->Start(boost::bind(&Service::CheckCompletedHandler, this, scheduleInfo, _1, callback));
|
{
|
||||||
|
ObjectLock olock(self);
|
||||||
|
task = self->MakeMethodTask("check", arguments);
|
||||||
|
self->Set("current_task", task);
|
||||||
|
}
|
||||||
|
|
||||||
|
task->Start(boost::bind(&Service::CheckCompletedHandler, self, checkInfo, _1, callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Service::CheckCompletedHandler(const Dictionary::Ptr& scheduleInfo,
|
void Service::CheckCompletedHandler(const Dictionary::Ptr& checkInfo,
|
||||||
const ScriptTask::Ptr& task, const function<void (void)>& callback)
|
const ScriptTask::Ptr& task, const function<void (void)>& callback)
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
checkInfo->Set("execution_end", Utility::GetTime());
|
||||||
|
checkInfo->Set("schedule_end", Utility::GetTime());
|
||||||
Set("current_task", Empty);
|
|
||||||
|
|
||||||
scheduleInfo->Set("execution_end", Utility::GetTime());
|
|
||||||
scheduleInfo->Set("schedule_end", Utility::GetTime());
|
|
||||||
|
|
||||||
Dictionary::Ptr result;
|
Dictionary::Ptr result;
|
||||||
|
|
||||||
|
@ -481,32 +520,43 @@ void Service::CheckCompletedHandler(const Dictionary::Ptr& scheduleInfo,
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
if (!result->Contains("schedule_start"))
|
if (!result->Contains("schedule_start"))
|
||||||
result->Set("schedule_start", scheduleInfo->Get("schedule_start"));
|
result->Set("schedule_start", checkInfo->Get("schedule_start"));
|
||||||
|
|
||||||
if (!result->Contains("schedule_end"))
|
if (!result->Contains("schedule_end"))
|
||||||
result->Set("schedule_end", scheduleInfo->Get("schedule_end"));
|
result->Set("schedule_end", checkInfo->Get("schedule_end"));
|
||||||
|
|
||||||
if (!result->Contains("execution_start"))
|
if (!result->Contains("execution_start"))
|
||||||
result->Set("execution_start", scheduleInfo->Get("execution_start"));
|
result->Set("execution_start", checkInfo->Get("execution_start"));
|
||||||
|
|
||||||
if (!result->Contains("execution_end"))
|
if (!result->Contains("execution_end"))
|
||||||
result->Set("execution_end", scheduleInfo->Get("execution_end"));
|
result->Set("execution_end", checkInfo->Get("execution_end"));
|
||||||
|
|
||||||
|
if (!result->Contains("macros"))
|
||||||
|
result->Set("macros", checkInfo->Get("macros"));
|
||||||
|
|
||||||
if (!result->Contains("active"))
|
if (!result->Contains("active"))
|
||||||
result->Set("active", 1);
|
result->Set("active", 1);
|
||||||
|
|
||||||
if (!result->Contains("checker"))
|
if (!result->Contains("checker")) {
|
||||||
result->Set("checker", EndpointManager::GetInstance()->GetIdentity());
|
EndpointManager::Ptr em = EndpointManager::GetInstance();
|
||||||
|
ObjectLock olock(em);
|
||||||
|
|
||||||
ProcessCheckResult(result);
|
result->Set("checker", em->GetIdentity());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* figure out when the next check is for this service; the call to
|
{
|
||||||
* ApplyCheckResult() should've already done this but lets do it again
|
ObjectLock olock(this);
|
||||||
* just in case there was no check result. */
|
if (result)
|
||||||
UpdateNextCheck();
|
ProcessCheckResult(result);
|
||||||
|
|
||||||
olock.Unlock();
|
Set("current_task", Empty);
|
||||||
|
|
||||||
|
/* 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();
|
callback();
|
||||||
}
|
}
|
||||||
|
@ -551,3 +601,40 @@ void Service::UpdateStatistics(const Dictionary::Ptr& cr)
|
||||||
else
|
else
|
||||||
CIB::UpdatePassiveChecksStatistics(ts, 1);
|
CIB::UpdatePassiveChecksStatistics(ts, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double Service::CalculateExecutionTime(const Dictionary::Ptr& cr)
|
||||||
|
{
|
||||||
|
ObjectLock olock(cr);
|
||||||
|
|
||||||
|
double execution_start = 0, execution_end = 0;
|
||||||
|
|
||||||
|
if (cr) {
|
||||||
|
ObjectLock olock(cr);
|
||||||
|
|
||||||
|
if (!cr->Contains("execution_start") || !cr->Contains("execution_end"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
execution_start = cr->Get("execution_start");
|
||||||
|
execution_end = cr->Get("execution_end");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (execution_end - execution_start);
|
||||||
|
}
|
||||||
|
|
||||||
|
double Service::CalculateLatency(const Dictionary::Ptr& cr)
|
||||||
|
{
|
||||||
|
double schedule_start = 0, schedule_end = 0;
|
||||||
|
|
||||||
|
if (cr) {
|
||||||
|
ObjectLock olock(cr);
|
||||||
|
|
||||||
|
if (!cr->Contains("schedule_start") || !cr->Contains("schedule_end"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
schedule_start = cr->Get("schedule_start");
|
||||||
|
schedule_end = cr->Get("schedule_end");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (schedule_end - schedule_start) - CalculateExecutionTime(cr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ void Service::SendNotifications(NotificationType type)
|
||||||
Logger::Write(LogInformation, "icinga", "Service '" + GetName() + "' does not have any notifications.");
|
Logger::Write(LogInformation, "icinga", "Service '" + GetName() + "' does not have any notifications.");
|
||||||
|
|
||||||
BOOST_FOREACH(const Notification::Ptr& notification, notifications) {
|
BOOST_FOREACH(const Notification::Ptr& notification, notifications) {
|
||||||
notification->SendNotification(type);
|
Notification::BeginExecuteNotification(notification, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetLastNotification(Utility::GetTime());
|
SetLastNotification(Utility::GetTime());
|
||||||
|
|
|
@ -76,10 +76,10 @@ String Service::GetDisplayName(void) const
|
||||||
{
|
{
|
||||||
String value = Get("display_name");
|
String value = Get("display_name");
|
||||||
|
|
||||||
if (!value.IsEmpty())
|
if (value.IsEmpty())
|
||||||
return value;
|
return GetShortName();
|
||||||
|
|
||||||
return GetName();
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -330,27 +330,36 @@ set<Service::Ptr> Service::GetParentServices(void) const
|
||||||
return parents;
|
return parents;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary::Ptr Service::CalculateDynamicMacros(void) const
|
Dictionary::Ptr Service::CalculateDynamicMacros(const Service::Ptr& self)
|
||||||
{
|
{
|
||||||
Dictionary::Ptr macros = boost::make_shared<Dictionary>();
|
Dictionary::Ptr macros = boost::make_shared<Dictionary>();
|
||||||
|
|
||||||
macros->Set("SERVICEDESC", GetShortName());
|
Dictionary::Ptr cr;
|
||||||
macros->Set("SERVICEDISPLAYNAME", GetDisplayName());
|
|
||||||
macros->Set("SERVICESTATE", StateToString(GetState()));
|
|
||||||
macros->Set("SERVICESTATEID", GetState());
|
|
||||||
macros->Set("SERVICESTATETYPE", StateTypeToString(GetStateType()));
|
|
||||||
macros->Set("SERVICEATTEMPT", GetCurrentCheckAttempt());
|
|
||||||
macros->Set("MAXSERVICEATTEMPT", GetMaxCheckAttempts());
|
|
||||||
|
|
||||||
Dictionary::Ptr cr = GetLastCheckResult();
|
{
|
||||||
|
ObjectLock olock(self);
|
||||||
|
macros->Set("SERVICEDESC", self->GetShortName());
|
||||||
|
macros->Set("SERVICEDISPLAYNAME", self->GetDisplayName());
|
||||||
|
macros->Set("SERVICESTATE", StateToString(self->GetState()));
|
||||||
|
macros->Set("SERVICESTATEID", self->GetState());
|
||||||
|
macros->Set("SERVICESTATETYPE", StateTypeToString(self->GetStateType()));
|
||||||
|
macros->Set("SERVICEATTEMPT", self->GetCurrentCheckAttempt());
|
||||||
|
macros->Set("MAXSERVICEATTEMPT", self->GetMaxCheckAttempts());
|
||||||
|
|
||||||
|
cr = self->GetLastCheckResult();
|
||||||
|
}
|
||||||
|
|
||||||
if (cr) {
|
if (cr) {
|
||||||
|
macros->Set("SERVICELATENCY", Service::CalculateLatency(cr));
|
||||||
|
macros->Set("SERVICEEXECUTIONTIME", Service::CalculateExecutionTime(cr));
|
||||||
|
|
||||||
|
ObjectLock olock(cr);
|
||||||
|
|
||||||
macros->Set("SERVICEOUTPUT", cr->Get("output"));
|
macros->Set("SERVICEOUTPUT", cr->Get("output"));
|
||||||
macros->Set("SERVICEPERFDATA", cr->Get("performance_data_raw"));
|
macros->Set("SERVICEPERFDATA", cr->Get("performance_data_raw"));
|
||||||
} else {
|
|
||||||
macros->Set("SERVICEOUTPUT", "");
|
|
||||||
macros->Set("SERVICEPERFDATA", "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macros->Seal();
|
||||||
|
|
||||||
return macros;
|
return macros;
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ public:
|
||||||
Dictionary::Ptr GetGroups(void) const;
|
Dictionary::Ptr GetGroups(void) const;
|
||||||
String GetShortName(void) const;
|
String GetShortName(void) const;
|
||||||
|
|
||||||
Dictionary::Ptr CalculateDynamicMacros(void) const;
|
static Dictionary::Ptr CalculateDynamicMacros(const Service::Ptr& self);
|
||||||
|
|
||||||
set<Host::Ptr> GetParentHosts(void) const;
|
set<Host::Ptr> GetParentHosts(void) const;
|
||||||
set<Service::Ptr> GetParentServices(void) const;
|
set<Service::Ptr> GetParentServices(void) const;
|
||||||
|
@ -171,9 +171,12 @@ public:
|
||||||
void ApplyCheckResult(const Dictionary::Ptr& cr);
|
void ApplyCheckResult(const Dictionary::Ptr& cr);
|
||||||
static void UpdateStatistics(const Dictionary::Ptr& cr);
|
static void UpdateStatistics(const Dictionary::Ptr& cr);
|
||||||
|
|
||||||
void BeginExecuteCheck(const function<void (void)>& callback);
|
static void BeginExecuteCheck(const Service::Ptr& self, const function<void (void)>& callback);
|
||||||
void ProcessCheckResult(const Dictionary::Ptr& cr);
|
void ProcessCheckResult(const Dictionary::Ptr& cr);
|
||||||
|
|
||||||
|
static double CalculateExecutionTime(const Dictionary::Ptr& cr);
|
||||||
|
static double CalculateLatency(const Dictionary::Ptr& cr);
|
||||||
|
|
||||||
static ServiceState StateFromString(const String& state);
|
static ServiceState StateFromString(const String& state);
|
||||||
static String StateToString(ServiceState state);
|
static String StateToString(ServiceState state);
|
||||||
|
|
||||||
|
@ -252,7 +255,7 @@ protected:
|
||||||
virtual void OnAttributeChanged(const String& name, const Value& oldValue);
|
virtual void OnAttributeChanged(const String& name, const Value& oldValue);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CheckCompletedHandler(const Dictionary::Ptr& scheduleInfo,
|
void CheckCompletedHandler(const Dictionary::Ptr& checkInfo,
|
||||||
const ScriptTask::Ptr& task, const function<void (void)>& callback);
|
const ScriptTask::Ptr& task, const function<void (void)>& callback);
|
||||||
|
|
||||||
/* Downtimes */
|
/* Downtimes */
|
||||||
|
|
|
@ -341,6 +341,8 @@ void EndpointManager::SubscriptionTimerHandler(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subscriptions->Seal();
|
||||||
|
|
||||||
if (m_Endpoint)
|
if (m_Endpoint)
|
||||||
m_Endpoint->SetSubscriptions(subscriptions);
|
m_Endpoint->SetSubscriptions(subscriptions);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue