Various bugfixes.

This commit is contained in:
Gunnar Beutner 2013-03-06 11:03:50 +01:00
parent be95f3171d
commit 70fa21dfbc
33 changed files with 546 additions and 257 deletions

View File

@ -60,21 +60,27 @@ void NotificationComponent::NotificationTimerHandler(void)
Service::Ptr service = dynamic_pointer_cast<Service>(object);
bool reachable = service->IsReachable();
ObjectLock olock(service);
bool send_notification;
if (service->GetStateType() == StateTypeSoft)
continue;
{
ObjectLock olock(service);
if (service->GetState() == StateOK)
continue;
if (service->GetStateType() == StateTypeSoft)
continue;
if (service->GetNotificationInterval() <= 0)
continue;
if (service->GetState() == StateOK)
continue;
if (service->GetLastNotification() > now - service->GetNotificationInterval())
continue;
if (service->GetNotificationInterval() <= 0)
continue;
if (reachable && !service->IsInDowntime() && !service->IsAcknowledged())
if (service->GetLastNotification() > now - service->GetNotificationInterval())
continue;
send_notification = reachable && !service->IsInDowntime() && !service->IsAcknowledged();
}
if (send_notification)
service->RequestNotifications(NotificationProblem);
}
}
@ -99,5 +105,8 @@ void NotificationComponent::SendNotificationsRequestHandler(const Endpoint::Ptr&
Service::Ptr service = Service::GetByName(svc);
if (!service)
return;
service->SendNotifications(static_cast<NotificationType>(type));
}

View File

@ -75,8 +75,8 @@ AC_CHECK_FUNCS([backtrace_symbols execvpe pipe2])
AC_MSG_CHECKING(whether to enable debugging)
AC_ARG_ENABLE(debug, [ --enable-debug=[no/yes] turn on debugging (default=no)],, enable_debug=no)
if test "x$enable_debug" = "xyes"; then
CFLAGS="$CFLAGS -g -O0 -D_DEBUG"
CXXFLAGS="$CXXFLAGS -g -O0 -D_DEBUG"
CFLAGS="$CFLAGS -g -O0 -D_DEBUG -Wall -Wextra"
CXXFLAGS="$CXXFLAGS -g -O0 -D_DEBUG -Wall -Wextra"
else
CFLAGS="$CFLAGS -DNDEBUG"
CXXFLAGS="$CXXFLAGS -DNDEBUG"

View File

@ -109,6 +109,7 @@ void Application::ShutdownTimerHandler(void)
if (m_ShuttingDown) {
Logger::Write(LogInformation, "base", "Shutting down Icinga...");
Application::GetInstance()->OnShutdown();
DynamicObject::DeactivateObjects();
GetEQ().Stop();
m_ShuttingDown = false;
@ -285,17 +286,17 @@ void Application::SigIntHandler(int signum)
{
assert(signum == SIGINT);
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
sigaction(SIGINT, &sa, NULL);
Application::Ptr instance = Application::GetInstance();
if (!instance)
return;
instance->RequestShutdown();
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
sigaction(SIGINT, &sa, NULL);
}
/**
@ -307,6 +308,11 @@ void Application::SigAbrtHandler(int signum)
{
assert(signum == SIGABRT);
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
sigaction(SIGABRT, &sa, NULL);
std::cerr << "Caught SIGABRT." << std::endl;
Utility::PrintStacktrace(std::cerr, 1);
@ -337,6 +343,13 @@ BOOL WINAPI Application::CtrlHandler(DWORD type)
*/
void Application::ExceptionHandler(void)
{
#ifndef _WIN32
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
sigaction(SIGABRT, &sa, NULL);
#endif /* _WIN32 */
try {
throw;
} catch (const std::exception& ex) {
@ -349,13 +362,6 @@ void Application::ExceptionHandler(void)
DisplayBugMessage();
#ifndef _WIN32
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
sigaction(SIGABRT, &sa, NULL);
#endif /* _WIN32 */
abort();
}

View File

@ -128,7 +128,7 @@ void DynamicObject::ApplyUpdate(const Dictionary::Ptr& serializedUpdate,
boost::mutex::scoped_lock lock(m_AttributeMutex);
if ((allowedTypes & Attribute_Config) != 0 && !configTxValue.IsEmpty()) {
double oldConfigTx, configTx = configTxValue;
double configTx = configTxValue;
if (configTx > m_ConfigTx) {
DynamicObject::AttributeIterator at;
@ -226,7 +226,7 @@ void DynamicObject::Set(const String& name, const Value& data)
*/
void DynamicObject::Touch(const String& name)
{
assert(!OwnsLock());
assert(OwnsLock());
boost::mutex::scoped_lock lock(m_AttributeMutex);
@ -284,7 +284,7 @@ void DynamicObject::InternalSetAttribute(const String& name, const Value& data,
m_ConfigTx = tx;
}
if (m_Registered) {
if (IsRegistered()) {
/* We can't call GetSelf() in the constructor or destructor.
* The Register() function will take care of adding this
* object to the list of modified objects later on if we can't
@ -352,6 +352,7 @@ bool DynamicObject::IsAbstract(void) const
*/
bool DynamicObject::IsRegistered(void) const
{
ObjectLock olock(GetType());
return m_Registered;
}
@ -392,11 +393,6 @@ void DynamicObject::OnRegistrationCompleted(void)
{
assert(!OwnsLock());
{
ObjectLock olock(this);
m_Registered = true;
}
Start();
OnRegistered(GetSelf());
@ -406,11 +402,6 @@ void DynamicObject::OnUnregistrationCompleted(void)
{
assert(!OwnsLock());
{
ObjectLock olock(this);
m_Registered = false;
}
OnUnregistered(GetSelf());
}

View File

@ -117,7 +117,7 @@ private:
Attribute<String> m_Source;
Attribute<Dictionary::Ptr> m_Methods;
bool m_Registered;
bool m_Registered; /**< protected by the type mutex */
static double m_CurrentTx;

View File

@ -83,29 +83,37 @@ void DynamicType::RegisterObject(const DynamicObject::Ptr& object)
{
String name = object->GetName();
ObjectLock olock(this);
{
ObjectLock olock(this);
ObjectMap::iterator it = m_ObjectMap.find(name);
ObjectMap::iterator it = m_ObjectMap.find(name);
if (it != m_ObjectMap.end()) {
if (it->second == object)
return;
if (it != m_ObjectMap.end()) {
if (it->second == object)
return;
BOOST_THROW_EXCEPTION(runtime_error("RegisterObject() found existing object with the same name: " + name));
BOOST_THROW_EXCEPTION(runtime_error("RegisterObject() found existing object with the same name: " + name));
}
m_ObjectMap[name] = object;
m_ObjectSet.insert(object);
object->m_Registered = true;
}
m_ObjectMap[name] = object;
m_ObjectSet.insert(object);
object->OnRegistrationCompleted();
}
void DynamicType::UnregisterObject(const DynamicObject::Ptr& object)
{
ObjectLock olock(this);
{
ObjectLock olock(this);
m_ObjectMap.erase(object->GetName());
m_ObjectSet.erase(object);
m_ObjectMap.erase(object->GetName());
m_ObjectSet.erase(object);
object->m_Registered = false;
}
object->OnUnregistrationCompleted();
}

View File

@ -25,20 +25,20 @@ using namespace icinga;
* @threadsafety Always.
*/
EventQueue::EventQueue(void)
: m_Stopped(false), m_LastReport(0)
: m_Stopped(false)
{
int thread_count = thread::hardware_concurrency();
unsigned int threads = thread::hardware_concurrency();
if (thread_count < 4)
thread_count = 4;
if (threads == 0)
threads = 1;
for (int i = 0; i < thread_count; i++)
threads *= 8;
for (unsigned int i = 0; i < threads; i++)
m_Threads.create_thread(boost::bind(&EventQueue::QueueThreadProc, this));
m_ReportTimer = boost::make_shared<Timer>();
m_ReportTimer->OnTimerExpired.connect(boost::bind(&EventQueue::ReportTimerHandler, this));
m_ReportTimer->SetInterval(5);
m_ReportTimer->Start();
thread reportThread(boost::bind(&EventQueue::ReportThreadProc, this));
reportThread.detach();
}
/**
@ -46,8 +46,6 @@ EventQueue::EventQueue(void)
*/
EventQueue::~EventQueue(void)
{
m_ReportTimer->Stop();
Stop();
Join();
}
@ -95,17 +93,39 @@ void EventQueue::QueueThreadProc(void)
}
BOOST_FOREACH(const Callback& ev, events) {
#ifdef _DEBUG
struct rusage usage_start, usage_end;
double st = Utility::GetTime();
(void) getrusage(RUSAGE_THREAD, &usage_start);
#endif /* _DEBUG */
ev();
#ifdef _DEBUG
double et = Utility::GetTime();
(void) getrusage(RUSAGE_THREAD, &usage_end);
if (et - st > 0.25) {
double duser = (usage_end.ru_utime.tv_sec - usage_start.ru_utime.tv_sec) +
(usage_end.ru_utime.tv_usec - usage_start.ru_utime.tv_usec) / 1000000.0;
double dsys = (usage_end.ru_stime.tv_sec - usage_start.ru_stime.tv_sec) +
(usage_end.ru_stime.tv_usec - usage_start.ru_stime.tv_usec) / 1000000.0;
double dwait = (et - st) - (duser + dsys);
int dminfaults = usage_end.ru_minflt - usage_start.ru_minflt;
int dmajfaults = usage_end.ru_majflt - usage_start.ru_majflt;
int dvctx = usage_end.ru_nvcsw - usage_start.ru_nvcsw;
int divctx = usage_end.ru_nivcsw - usage_start.ru_nivcsw;
if (et - st > 0.5) {
stringstream msgbuf;
msgbuf << "Event call took " << et - st << " seconds.";
msgbuf << "Event call took user:" << duser << "s, system:" << dsys << "s, wait:" << dwait << "s, minor_faults:" << dminfaults << ", major_faults:" << dmajfaults << ", voluntary_csw:" << dvctx << ", involuntary_csw:" << divctx;
Logger::Write(LogWarning, "base", msgbuf.str());
}
#endif /* _DEBUG */
}
}
}
@ -123,15 +143,18 @@ void EventQueue::Post(const EventQueue::Callback& callback)
m_CV.notify_one();
}
void EventQueue::ReportTimerHandler(void)
void EventQueue::ReportThreadProc(void)
{
int pending;
for (;;) {
Utility::Sleep(5);
{
boost::mutex::scoped_lock lock(m_Mutex);
pending = m_Events.size();
int pending;
{
boost::mutex::scoped_lock lock(m_Mutex);
pending = m_Events.size();
}
Logger::Write(LogInformation, "base", "Pending tasks: " + Convert::ToString(pending));
}
if (pending > 1000)
Logger::Write(LogCritical, "base", "More than 1000 pending events: " + Convert::ToString(pending));
}

View File

@ -49,14 +49,11 @@ private:
boost::mutex m_Mutex;
condition_variable m_CV;
double m_LastReport;
shared_ptr<Timer> m_ReportTimer;
bool m_Stopped;
vector<Callback> m_Events;
void QueueThreadProc(void);
void ReportTimerHandler(void);
void ReportThreadProc(void);
};
}

View File

@ -117,7 +117,7 @@ private:
mutable MutexType m_Mutex;
friend class ObjectLock;
friend struct ObjectLock;
};
/**

View File

@ -56,7 +56,6 @@ void ObjectLock::Lock(void)
boost::mutex::scoped_lock lock(Object::m_DebugMutex);
m_Object->m_Locked = true;
m_Object->m_LockOwner = boost::this_thread::get_id();
m_TS = Utility::GetTime();
}
#endif /* _DEBUG */
}
@ -67,16 +66,8 @@ void ObjectLock::Unlock(void)
{
boost::mutex::scoped_lock lock(Object::m_DebugMutex);
if (m_Lock.owns_lock()) {
double dt = Utility::GetTime() - m_TS;
if (dt > 0.05) {
std::cerr << "Held object lock for " << dt << " seconds at:";
Utility::PrintStacktrace(std::cerr);
}
if (m_Lock.owns_lock())
m_Object->m_Locked = false;
}
}
#endif /* _DEBUG */

View File

@ -39,10 +39,6 @@ public:
private:
const Object *m_Object;
Object::MutexType::scoped_lock m_Lock;
#ifdef _DEBUG
double m_TS;
#endif /* _DEBUG */
};
}

View File

@ -24,6 +24,7 @@
using namespace icinga;
condition_variable Process::m_CV;
int Process::m_TaskFd;
Timer::Ptr Process::m_StatusTimer;
extern char **environ;
@ -47,7 +48,12 @@ void Process::Initialize(void)
m_TaskFd = fds[1];
for (int i = 0; i < thread::hardware_concurrency(); i++) {
unsigned int threads = thread::hardware_concurrency();
if (threads == 0)
threads = 2;
for (unsigned int i = 0; i < threads; i++) {
int childTaskFd = dup(fds[0]);
if (childTaskFd < 0)
@ -104,44 +110,63 @@ void Process::WorkerThreadProc(int taskFd)
if (rc == 0)
continue;
for (int i = 0; i < idx; i++) {
if ((pfds[i].revents & (POLLIN|POLLHUP)) == 0)
continue;
while (pfds[i].fd == taskFd && tasks.size() < MaxTasksPerThread) {
Process::Ptr task;
if (pfds[i].fd == taskFd) {
vector<Process::Ptr> new_tasks;
{
int want = MaxTasksPerThread - tasks.size();
if (want > m_Tasks.size())
want = m_Tasks.size();
if (want > 0) {
boost::mutex::scoped_lock lock(m_Mutex);
/* Read one byte for every task we take from the pending tasks list. */
char buffer;
int rc = read(taskFd, &buffer, sizeof(buffer));
char buffer[MaxTasksPerThread];
if (rc < 0) {
assert(want =< sizeof(buffer));
int have = read(taskFd, &buffer, want);
if (have < 0) {
if (errno == EAGAIN)
break; /* Someone else was faster and took our task. */
BOOST_THROW_EXCEPTION(PosixException("read() failed.", errno));
}
assert(!m_Tasks.empty());
while (have > 0) {
assert(!m_Tasks.empty());
task = m_Tasks.front();
m_Tasks.pop_front();
Process::Ptr task = m_Tasks.front();
m_Tasks.pop_front();
new_tasks.push_back(task);
have--;
}
m_CV.notify_all();
}
try {
task->InitTask();
BOOST_FOREACH(const Process::Ptr& task, new_tasks) {
try {
task->InitTask();
int fd = task->m_FD;
int fd = task->m_FD;
if (fd >= 0)
tasks[fd] = task;
} catch (...) {
task->FinishException(boost::current_exception());
if (fd >= 0)
tasks[fd] = task;
} catch (...) {
task->FinishException(boost::current_exception());
}
}
continue;
}
it = tasks.find(pfds[i].fd);
@ -161,14 +186,23 @@ void Process::WorkerThreadProc(int taskFd)
}
}
void Process::NotifyWorker(void)
void Process::QueueTask(void)
{
/**
* This little gem which is commonly known as the "self-pipe trick"
* takes care of waking up the select() call in the worker thread.
*/
if (write(m_TaskFd, "T", 1) < 0)
BOOST_THROW_EXCEPTION(PosixException("write() failed.", errno));
{
boost::mutex::scoped_lock lock(m_Mutex);
while (m_Tasks.size() >= PIPE_BUF)
m_CV.wait(lock);
m_Tasks.push_back(GetSelf());
/**
* This little gem which is commonly known as the "self-pipe trick"
* takes care of waking up the select() call in the worker thread.
*/
if (write(m_TaskFd, "T", 1) < 0)
BOOST_THROW_EXCEPTION(PosixException("write() failed.", errno));
}
}
void Process::InitTask(void)
@ -196,7 +230,7 @@ void Process::InitTask(void)
// build argv
char **argv = new char *[m_Arguments.size() + 1];
for (int i = 0; i < m_Arguments.size(); i++)
for (unsigned int i = 0; i < m_Arguments.size(); i++)
argv[i] = strdup(m_Arguments[i].CStr());
argv[m_Arguments.size()] = NULL;

View File

@ -32,7 +32,7 @@ void Process::WorkerThreadProc(void)
// TODO: implement
}
void Process::NotifyWorker(void)
void Process::QueueTask(void)
{
// TODO: implement
}

View File

@ -67,10 +67,5 @@ vector<String> Process::SplitCommand(const Value& command)
void Process::Run(void)
{
{
boost::mutex::scoped_lock lock(m_Mutex);
m_Tasks.push_back(GetSelf());
}
NotifyWorker();
QueueTask();
}

View File

@ -48,7 +48,7 @@ public:
typedef shared_ptr<Process> Ptr;
typedef weak_ptr<Process> WeakPtr;
static const deque<Process::Ptr>::size_type MaxTasksPerThread = 128;
static const deque<Process::Ptr>::size_type MaxTasksPerThread = 512;
Process(const vector<String>& arguments, const Dictionary::Ptr& extraEnvironment = Dictionary::Ptr());
@ -71,12 +71,13 @@ private:
static boost::mutex m_Mutex;
static deque<Process::Ptr> m_Tasks;
#ifndef _WIN32
static condition_variable m_CV;
static int m_TaskFd;
static Timer::Ptr m_StatusTimer;
#endif /* _WIN32 */
static void NotifyWorker(void);
void QueueTask(void);
void SpawnTask(void);

View File

@ -42,10 +42,10 @@ void RingBuffer::InsertValue(RingBuffer::SizeType tv, int num)
{
ObjectLock olock(this);
vector<int>::size_type offsetTarget = tv % m_Slots.size();
RingBuffer::SizeType offsetTarget = tv % m_Slots.size();
if (tv > m_TimeValue) {
vector<int>::size_type offset = m_TimeValue % m_Slots.size();
RingBuffer::SizeType offset = m_TimeValue % m_Slots.size();
/* walk towards the target offset, resetting slots to 0 */
while (offset != offsetTarget) {

View File

@ -44,7 +44,7 @@ public:
private:
vector<int> m_Slots;
int m_TimeValue;
SizeType m_TimeValue;
};
}

View File

@ -72,8 +72,6 @@ ScriptFunction::Ptr ScriptFunction::GetByName(const String& name)
*/
void ScriptFunction::Invoke(const ScriptTask::Ptr& task, const vector<Value>& arguments)
{
ObjectLock olock(this);
m_Callback(task, arguments);
}

View File

@ -94,8 +94,7 @@ void Timer::Call(void)
OnTimerExpired(self);
/* Re-enable the timer so it can be called again. */
Start();
Reschedule();
}
/**
@ -285,7 +284,6 @@ void Timer::TimerThreadProc(void)
/* Remove the timer from the list so it doesn't get called again
* until the current call is completed. */
timer->m_Started = false;
m_Timers.erase(timer);
lock.unlock();

View File

@ -87,7 +87,7 @@ void ExternalCommandProcessor::Execute(double time, const String& command, const
*/
void ExternalCommandProcessor::Initialize(void)
{
RegisterCommand("PROCESS_HOST_CHECK_RESULT", &ExternalCommandProcessor::ProcessServiceCheckResult);
RegisterCommand("PROCESS_HOST_CHECK_RESULT", &ExternalCommandProcessor::ProcessHostCheckResult);
RegisterCommand("PROCESS_SERVICE_CHECK_RESULT", &ExternalCommandProcessor::ProcessServiceCheckResult);
RegisterCommand("SCHEDULE_HOST_CHECK", &ExternalCommandProcessor::ScheduleHostCheck);
RegisterCommand("SCHEDULE_FORCED_HOST_CHECK", &ExternalCommandProcessor::ScheduleForcedHostCheck);
@ -167,8 +167,8 @@ void ExternalCommandProcessor::ProcessHostCheckResult(double time, const vector<
if (!hc->GetEnablePassiveChecks())
BOOST_THROW_EXCEPTION(invalid_argument("Got passive check result for host '" + arguments[0] + "' which has passive checks disabled."));
int exitStatus = Convert::ToDouble(arguments[2]);
Dictionary::Ptr result = PluginCheckTask::ParseCheckOutput(arguments[3]);
int exitStatus = Convert::ToDouble(arguments[1]);
Dictionary::Ptr result = PluginCheckTask::ParseCheckOutput(arguments[2]);
result->Set("state", PluginCheckTask::ExitStatusToState(exitStatus));
result->Set("schedule_start", time);
@ -180,10 +180,14 @@ void ExternalCommandProcessor::ProcessHostCheckResult(double time, const vector<
Logger::Write(LogInformation, "icinga", "Processing passive check result for host '" + arguments[0] + "'");
hc->ProcessCheckResult(result);
/* Reschedule the next check. The side effect of this is that for as long
* as we receive passive results for a service we won't execute any
* active checks. */
hc->SetNextCheck(Utility::GetTime() + hc->GetCheckInterval());
{
ObjectLock olock(hc);
/* Reschedule the next check. The side effect of this is that for as long
* as we receive passive results for a service we won't execute any
* active checks. */
hc->SetNextCheck(Utility::GetTime() + hc->GetCheckInterval());
}
}
void ExternalCommandProcessor::ProcessServiceCheckResult(double time, const vector<String>& arguments)
@ -209,10 +213,14 @@ void ExternalCommandProcessor::ProcessServiceCheckResult(double time, const vect
Logger::Write(LogInformation, "icinga", "Processing passive check result for service '" + arguments[1] + "'");
service->ProcessCheckResult(result);
/* Reschedule the next check. The side effect of this is that for as long
* as we receive passive results for a service we won't execute any
* active checks. */
service->SetNextCheck(Utility::GetTime() + service->GetCheckInterval());
{
ObjectLock olock(service);
/* Reschedule the next check. The side effect of this is that for as long
* as we receive passive results for a service we won't execute any
* active checks. */
service->SetNextCheck(Utility::GetTime() + service->GetCheckInterval());
}
}
void ExternalCommandProcessor::ScheduleHostCheck(double, const vector<String>& arguments)
@ -233,7 +241,12 @@ void ExternalCommandProcessor::ScheduleHostCheck(double, const vector<String>& a
}
Logger::Write(LogInformation, "icinga", "Rescheduling next check for host '" + arguments[0] + "'");
hc->SetNextCheck(planned_check);
{
ObjectLock olock(hc);
hc->SetNextCheck(planned_check);
}
}
void ExternalCommandProcessor::ScheduleForcedHostCheck(double, const vector<String>& arguments)
@ -246,8 +259,13 @@ void ExternalCommandProcessor::ScheduleForcedHostCheck(double, const vector<Stri
Service::Ptr hc = host->GetHostCheckService();
Logger::Write(LogInformation, "icinga", "Rescheduling next check for host '" + arguments[0] + "'");
hc->SetForceNextCheck(true);
hc->SetNextCheck(Convert::ToDouble(arguments[1]));
{
ObjectLock olock(hc);
hc->SetForceNextCheck(true);
hc->SetNextCheck(Convert::ToDouble(arguments[1]));
}
}
void ExternalCommandProcessor::ScheduleSvcCheck(double, const vector<String>& arguments)
@ -266,7 +284,12 @@ void ExternalCommandProcessor::ScheduleSvcCheck(double, const vector<String>& ar
}
Logger::Write(LogInformation, "icinga", "Rescheduling next check for service '" + arguments[1] + "'");
service->SetNextCheck(planned_check);
{
ObjectLock olock(service);
service->SetNextCheck(planned_check);
}
}
void ExternalCommandProcessor::ScheduleForcedSvcCheck(double, const vector<String>& arguments)
@ -277,8 +300,13 @@ void ExternalCommandProcessor::ScheduleForcedSvcCheck(double, const vector<Strin
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Rescheduling next check for service '" + arguments[1] + "'");
service->SetForceNextCheck(true);
service->SetNextCheck(Convert::ToDouble(arguments[2]));
{
ObjectLock olock(service);
service->SetForceNextCheck(true);
service->SetNextCheck(Convert::ToDouble(arguments[2]));
}
}
void ExternalCommandProcessor::EnableHostCheck(double, const vector<String>& arguments)
@ -291,8 +319,14 @@ void ExternalCommandProcessor::EnableHostCheck(double, const vector<String>& arg
Logger::Write(LogInformation, "icinga", "Enabling active checks for host '" + arguments[0] + "'");
Service::Ptr hc = host->GetHostCheckService();
if (hc)
if (!hc)
return;
{
ObjectLock olock(hc);
hc->SetEnableActiveChecks(true);
}
}
void ExternalCommandProcessor::DisableHostCheck(double, const vector<String>& arguments)
@ -305,8 +339,14 @@ void ExternalCommandProcessor::DisableHostCheck(double, const vector<String>& ar
Logger::Write(LogInformation, "icinga", "Disabling active checks for host '" + arguments[0] + "'");
Service::Ptr hc = host->GetHostCheckService();
if (hc)
if (!hc)
return;
{
ObjectLock olock(hc);
hc->SetEnableActiveChecks(false);
}
}
void ExternalCommandProcessor::EnableSvcCheck(double, const vector<String>& arguments)
@ -317,7 +357,12 @@ void ExternalCommandProcessor::EnableSvcCheck(double, const vector<String>& argu
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Enabling active checks for service '" + arguments[1] + "'");
service->SetEnableActiveChecks(true);
{
ObjectLock olock(service);
service->SetEnableActiveChecks(true);
}
}
void ExternalCommandProcessor::DisableSvcCheck(double, const vector<String>& arguments)
@ -328,7 +373,12 @@ void ExternalCommandProcessor::DisableSvcCheck(double, const vector<String>& arg
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Disabling active checks for service '" + arguments[1] + "'");
service->SetEnableActiveChecks(false);
{
ObjectLock olock(service);
service->SetEnableActiveChecks(false);
}
}
void ExternalCommandProcessor::ShutdownProcess(double, const vector<String>&)
@ -348,8 +398,13 @@ void ExternalCommandProcessor::ScheduleForcedHostSvcChecks(double, const vector<
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
Logger::Write(LogInformation, "icinga", "Rescheduling next check for service '" + service->GetName() + "'");
service->SetNextCheck(planned_check);
service->SetForceNextCheck(true);
{
ObjectLock olock(service);
service->SetNextCheck(planned_check);
service->SetForceNextCheck(true);
}
}
}
@ -370,7 +425,12 @@ void ExternalCommandProcessor::ScheduleHostSvcChecks(double, const vector<String
}
Logger::Write(LogInformation, "icinga", "Rescheduling next check for service '" + service->GetName() + "'");
service->SetNextCheck(planned_check);
{
ObjectLock olock(service);
service->SetNextCheck(planned_check);
}
}
}
@ -396,7 +456,12 @@ void ExternalCommandProcessor::DisableHostSvcChecks(double, const vector<String>
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
Logger::Write(LogInformation, "icinga", "Disabling active checks for service '" + service->GetName() + "'");
service->SetEnableActiveChecks(false);
{
ObjectLock olock(service);
service->SetEnableActiveChecks(false);
}
}
}
@ -413,7 +478,12 @@ void ExternalCommandProcessor::AcknowledgeSvcProblem(double, const vector<String
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' is OK."));
Logger::Write(LogInformation, "icinga", "Setting acknowledgement for service '" + service->GetName() + "'");
service->AcknowledgeProblem(sticky ? AcknowledgementSticky : AcknowledgementNormal);
{
ObjectLock olock(service);
service->AcknowledgeProblem(sticky ? AcknowledgementSticky : AcknowledgementNormal);
}
}
void ExternalCommandProcessor::AcknowledgeSvcProblemExpire(double, const vector<String>& arguments)
@ -430,7 +500,12 @@ void ExternalCommandProcessor::AcknowledgeSvcProblemExpire(double, const vector<
BOOST_THROW_EXCEPTION(invalid_argument("The service '" + arguments[1] + "' is OK."));
Logger::Write(LogInformation, "icinga", "Setting timed acknowledgement for service '" + service->GetName() + "'");
service->AcknowledgeProblem(sticky ? AcknowledgementSticky : AcknowledgementNormal, timestamp);
{
ObjectLock olock(service);
service->AcknowledgeProblem(sticky ? AcknowledgementSticky : AcknowledgementNormal, timestamp);
}
}
void ExternalCommandProcessor::RemoveSvcAcknowledgement(double, const vector<String>& arguments)
@ -441,7 +516,12 @@ void ExternalCommandProcessor::RemoveSvcAcknowledgement(double, const vector<Str
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Removing acknowledgement for service '" + service->GetName() + "'");
service->ClearAcknowledgement();
{
ObjectLock olock(service);
service->ClearAcknowledgement();
}
}
void ExternalCommandProcessor::AcknowledgeHostProblem(double, const vector<String>& arguments)
@ -456,6 +536,8 @@ void ExternalCommandProcessor::AcknowledgeHostProblem(double, const vector<Strin
Logger::Write(LogInformation, "icinga", "Setting acknowledgement for host '" + host->GetName() + "'");
Service::Ptr service = host->GetHostCheckService();
if (service) {
ObjectLock olock(service);
if (service->GetState() == StateOK)
BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' is OK."));
@ -476,6 +558,8 @@ void ExternalCommandProcessor::AcknowledgeHostProblemExpire(double, const vector
Logger::Write(LogInformation, "icinga", "Setting timed acknowledgement for host '" + host->GetName() + "'");
Service::Ptr service = host->GetHostCheckService();
if (service) {
ObjectLock olock(service);
if (service->GetState() == StateOK)
BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' is OK."));
@ -493,6 +577,8 @@ void ExternalCommandProcessor::RemoveHostAcknowledgement(double, const vector<St
Logger::Write(LogInformation, "icinga", "Removing acknowledgement for host '" + host->GetName() + "'");
Service::Ptr service = host->GetHostCheckService();
if (service) {
ObjectLock olock(service);
service->ClearAcknowledgement();
}
}
@ -507,7 +593,12 @@ void ExternalCommandProcessor::EnableHostgroupSvcChecks(double, const vector<Str
BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
Logger::Write(LogInformation, "icinga", "Enabling active checks for service '" + service->GetName() + "'");
service->SetEnableActiveChecks(true);
{
ObjectLock olock(service);
service->SetEnableActiveChecks(true);
}
}
}
}
@ -522,7 +613,12 @@ void ExternalCommandProcessor::DisableHostgroupSvcChecks(double, const vector<St
BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
Logger::Write(LogInformation, "icinga", "Disabling active checks for service '" + service->GetName() + "'");
service->SetEnableActiveChecks(false);
{
ObjectLock olock(service);
service->SetEnableActiveChecks(false);
}
}
}
}
@ -536,7 +632,12 @@ void ExternalCommandProcessor::EnableServicegroupSvcChecks(double, const vector<
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
Logger::Write(LogInformation, "icinga", "Enabling active checks for service '" + service->GetName() + "'");
service->SetEnableActiveChecks(true);
{
ObjectLock olock(service);
service->SetEnableActiveChecks(true);
}
}
}
@ -549,7 +650,12 @@ void ExternalCommandProcessor::DisableServicegroupSvcChecks(double, const vector
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
Logger::Write(LogInformation, "icinga", "Disabling active checks for service '" + service->GetName() + "'");
service->SetEnableActiveChecks(false);
{
ObjectLock olock(service);
service->SetEnableActiveChecks(false);
}
}
}
@ -563,8 +669,14 @@ void ExternalCommandProcessor::EnablePassiveHostChecks(double, const vector<Stri
Logger::Write(LogInformation, "icinga", "Enabling passive checks for host '" + arguments[0] + "'");
Service::Ptr hc = host->GetHostCheckService();
if (hc)
if (!hc)
return;
{
ObjectLock olock(hc);
hc->SetEnablePassiveChecks(true);
}
}
void ExternalCommandProcessor::DisablePassiveHostChecks(double, const vector<String>& arguments)
@ -577,8 +689,14 @@ void ExternalCommandProcessor::DisablePassiveHostChecks(double, const vector<Str
Logger::Write(LogInformation, "icinga", "Disabling passive checks for host '" + arguments[0] + "'");
Service::Ptr hc = host->GetHostCheckService();
if (hc)
if (!hc)
return;
{
ObjectLock olock(hc);
hc->SetEnablePassiveChecks(false);
}
}
void ExternalCommandProcessor::EnablePassiveSvcChecks(double, const vector<String>& arguments)
@ -589,7 +707,12 @@ void ExternalCommandProcessor::EnablePassiveSvcChecks(double, const vector<Strin
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Enabling passive checks for service '" + arguments[1] + "'");
service->SetEnablePassiveChecks(true);
{
ObjectLock olock(service);
service->SetEnablePassiveChecks(true);
}
}
void ExternalCommandProcessor::DisablePassiveSvcChecks(double, const vector<String>& arguments)
@ -600,7 +723,12 @@ void ExternalCommandProcessor::DisablePassiveSvcChecks(double, const vector<Stri
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Disabling passive checks for service '" + arguments[1] + "'");
service->SetEnablePassiveChecks(false);
{
ObjectLock olock(service);
service->SetEnablePassiveChecks(false);
}
}
void ExternalCommandProcessor::EnableServicegroupPassiveSvcChecks(double, const vector<String>& arguments)
@ -612,7 +740,12 @@ void ExternalCommandProcessor::EnableServicegroupPassiveSvcChecks(double, const
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
Logger::Write(LogInformation, "icinga", "Enabling passive checks for service '" + service->GetName() + "'");
service->SetEnablePassiveChecks(true);
{
ObjectLock olock(service);
service->SetEnablePassiveChecks(true);
}
}
}
@ -625,7 +758,12 @@ void ExternalCommandProcessor::DisableServicegroupPassiveSvcChecks(double, const
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
Logger::Write(LogInformation, "icinga", "Disabling passive checks for service '" + service->GetName() + "'");
service->SetEnablePassiveChecks(true);
{
ObjectLock olock(service);
service->SetEnablePassiveChecks(true);
}
}
}
@ -639,7 +777,12 @@ void ExternalCommandProcessor::EnableHostgroupPassiveSvcChecks(double, const vec
BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
Logger::Write(LogInformation, "icinga", "Enabling passive checks for service '" + service->GetName() + "'");
service->SetEnablePassiveChecks(true);
{
ObjectLock olock(service);
service->SetEnablePassiveChecks(true);
}
}
}
}
@ -654,7 +797,12 @@ void ExternalCommandProcessor::DisableHostgroupPassiveSvcChecks(double, const ve
BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
Logger::Write(LogInformation, "icinga", "Disabling passive checks for service '" + service->GetName() + "'");
service->SetEnablePassiveChecks(false);
{
ObjectLock olock(service);
service->SetEnablePassiveChecks(false);
}
}
}
}
@ -962,9 +1110,8 @@ void ExternalCommandProcessor::SendCustomHostNotification(double time, const vec
Logger::Write(LogInformation, "icinga", "Sending custom notification for host " + host->GetName());
Service::Ptr service = host->GetHostCheckService();
if (service) {
if (service)
service->RequestNotifications(NotificationCustom);
}
}
void ExternalCommandProcessor::SendCustomSvcNotification(double time, const vector<String>& arguments)
@ -986,9 +1133,14 @@ void ExternalCommandProcessor::DelayHostNotification(double time, const vector<S
Host::Ptr host = Host::GetByName(arguments[0]);
Logger::Write(LogInformation, "icinga", "Delaying notifications for host " + host->GetName());
Service::Ptr service = host->GetHostCheckService();
if (service) {
service->SetLastNotification(Convert::ToDouble(arguments[1]));
Service::Ptr hc = host->GetHostCheckService();
if (!hc)
return;
{
ObjectLock olock(hc);
hc->SetLastNotification(Convert::ToDouble(arguments[1]));
}
}
@ -1000,7 +1152,12 @@ void ExternalCommandProcessor::DelaySvcNotification(double time, const vector<St
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Delaying notifications for service " + service->GetName());
service->SetLastNotification(Convert::ToDouble(arguments[2]));
{
ObjectLock olock(service);
service->SetLastNotification(Convert::ToDouble(arguments[2]));
}
}
void ExternalCommandProcessor::EnableHostNotifications(double, const vector<String>& arguments)
@ -1013,8 +1170,14 @@ void ExternalCommandProcessor::EnableHostNotifications(double, const vector<Stri
Logger::Write(LogInformation, "icinga", "Enabling notifications for host '" + arguments[0] + "'");
Service::Ptr hc = host->GetHostCheckService();
if (hc)
if (!hc)
return;
{
ObjectLock olock(hc);
hc->SetEnableNotifications(true);
}
}
void ExternalCommandProcessor::DisableHostNotifications(double, const vector<String>& arguments)
@ -1027,8 +1190,14 @@ void ExternalCommandProcessor::DisableHostNotifications(double, const vector<Str
Logger::Write(LogInformation, "icinga", "Disabling notifications for host '" + arguments[0] + "'");
Service::Ptr hc = host->GetHostCheckService();
if (hc)
if (!hc)
return;
{
ObjectLock olock(hc);
hc->SetEnableNotifications(false);
}
}
void ExternalCommandProcessor::EnableSvcNotifications(double, const vector<String>& arguments)
@ -1039,7 +1208,12 @@ void ExternalCommandProcessor::EnableSvcNotifications(double, const vector<Strin
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Enabling notifications for service '" + arguments[1] + "'");
service->SetEnableNotifications(true);
{
ObjectLock olock(service);
service->SetEnableNotifications(true);
}
}
void ExternalCommandProcessor::DisableSvcNotifications(double, const vector<String>& arguments)
@ -1050,5 +1224,10 @@ void ExternalCommandProcessor::DisableSvcNotifications(double, const vector<Stri
Service::Ptr service = Service::GetByNamePair(arguments[0], arguments[1]);
Logger::Write(LogInformation, "icinga", "Disabling notifications for service '" + arguments[1] + "'");
service->SetEnableNotifications(false);
{
ObjectLock olock(service);
service->SetEnableNotifications(false);
}
}

View File

@ -23,7 +23,8 @@ using namespace icinga;
boost::mutex Host::m_ServiceMutex;
map<String, map<String, Service::WeakPtr> > Host::m_ServicesCache;
bool Host::m_ServicesCacheValid = true;
bool Host::m_ServicesCacheNeedsUpdate = false;
Timer::Ptr Host::m_ServicesCacheTimer;
REGISTER_SCRIPTFUNCTION("ValidateServiceDictionary", &Host::ValidateServiceDictionary);
@ -134,7 +135,7 @@ bool Host::IsReachable(void) const
set<Host::Ptr> parentHosts = GetParentHosts();
BOOST_FOREACH(const Host::Ptr& host, parentHosts) {
Service::Ptr hc = GetHostCheckService();
Service::Ptr hc = host->GetHostCheckService();
/* ignore hosts that don't have a hostcheck */
if (!hc)
@ -325,10 +326,17 @@ void Host::InvalidateServicesCache(void)
{
boost::mutex::scoped_lock lock(m_ServiceMutex);
if (m_ServicesCacheValid)
Utility::QueueAsyncCallback(boost::bind(&Host::RefreshServicesCache));
if (m_ServicesCacheNeedsUpdate)
return; /* Someone else has already requested a refresh. */
m_ServicesCacheValid = false;
if (!m_ServicesCacheTimer) {
m_ServicesCacheTimer = boost::make_shared<Timer>();
m_ServicesCacheTimer->SetInterval(0.5);
m_ServicesCacheTimer->OnTimerExpired.connect(boost::bind(&Host::RefreshServicesCache));
}
m_ServicesCacheTimer->Start();
m_ServicesCacheNeedsUpdate = true;
}
}
@ -337,12 +345,13 @@ void Host::RefreshServicesCache(void)
{
boost::mutex::scoped_lock lock(m_ServiceMutex);
if (m_ServicesCacheValid)
return;
m_ServicesCacheValid = true;
assert(m_ServicesCacheNeedsUpdate);
m_ServicesCacheTimer->Stop();
m_ServicesCacheNeedsUpdate = false;
}
Logger::Write(LogInformation, "icinga", "Updating services cache.");
map<String, map<String, Service::WeakPtr> > newServicesCache;
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {

View File

@ -80,7 +80,8 @@ private:
static boost::mutex m_ServiceMutex;
static map<String, map<String, weak_ptr<Service> > > m_ServicesCache;
static bool m_ServicesCacheValid;
static bool m_ServicesCacheNeedsUpdate;
static Timer::Ptr m_ServicesCacheTimer;
void UpdateSlaveServices(void);

View File

@ -23,7 +23,8 @@ using namespace icinga;
boost::mutex HostGroup::m_Mutex;
map<String, vector<Host::WeakPtr> > HostGroup::m_MembersCache;
bool HostGroup::m_MembersCacheValid = true;
bool HostGroup::m_MembersCacheNeedsUpdate = false;
Timer::Ptr HostGroup::m_MembersCacheTimer;
REGISTER_TYPE(HostGroup);
@ -120,10 +121,17 @@ void HostGroup::InvalidateMembersCache(void)
{
boost::mutex::scoped_lock lock(m_Mutex);
if (m_MembersCacheValid)
Utility::QueueAsyncCallback(boost::bind(&HostGroup::RefreshMembersCache));
if (m_MembersCacheNeedsUpdate)
return; /* Someone else has already requested a refresh. */
m_MembersCacheValid = false;
if (!m_MembersCacheTimer) {
m_MembersCacheTimer = boost::make_shared<Timer>();
m_MembersCacheTimer->SetInterval(0.5);
m_MembersCacheTimer->OnTimerExpired.connect(boost::bind(&HostGroup::RefreshMembersCache));
}
m_MembersCacheTimer->Start();
m_MembersCacheNeedsUpdate = true;
}
/**
@ -134,10 +142,9 @@ void HostGroup::RefreshMembersCache(void)
{
boost::mutex::scoped_lock lock(m_Mutex);
if (m_MembersCacheValid)
return;
m_MembersCacheValid = true;
assert(m_MembersCacheNeedsUpdate);
m_MembersCacheTimer->Stop();
m_MembersCacheNeedsUpdate = false;
}
map<String, vector<Host::WeakPtr> > newMembersCache;

View File

@ -57,7 +57,8 @@ private:
static boost::mutex m_Mutex;
static map<String, vector<Host::WeakPtr> > m_MembersCache;
static bool m_MembersCacheValid;
static bool m_MembersCacheNeedsUpdate;
static Timer::Ptr m_MembersCacheTimer;
static void RefreshMembersCache(void);
};

View File

@ -44,7 +44,7 @@ void PluginNotificationTask::ScriptFunc(const ScriptTask::Ptr& task, const vecto
Notification::Ptr notification = arguments[0];
Dictionary::Ptr macros = arguments[1];
NotificationType type = static_cast<NotificationType>(static_cast<int>(arguments[2]));
// NotificationType type = static_cast<NotificationType>(static_cast<int>(arguments[2]));
Value raw_command = notification->GetNotificationCommand();

View File

@ -334,6 +334,8 @@ void Service::SetForceNextCheck(bool forced)
*/
void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
{
bool reachable = IsReachable();
assert(!OwnsLock());
ObjectLock olock(this);
@ -413,6 +415,8 @@ void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
Service::UpdateStatistics(cr);
bool send_notification = hardChange && reachable && !IsInDowntime() && !IsAcknowledged();
olock.Unlock();
/* Flush the object so other instances see the service's
@ -431,7 +435,7 @@ void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
EndpointManager::GetInstance()->SendMulticastMessage(rm);
if (hardChange && IsReachable() && !IsInDowntime() && !IsAcknowledged())
if (send_notification)
RequestNotifications(recovery ? NotificationRecovery : NotificationProblem);
}
@ -521,16 +525,21 @@ bool Service::IsAllowedChecker(const String& checker) const
void Service::BeginExecuteCheck(const function<void (void)>& callback)
{
assert(!OwnsLock());
ObjectLock olock(this);
/* don't run another check if there is one pending */
if (m_CurrentTask) {
olock.Unlock();
{
ObjectLock olock(this);
/* we need to call the callback anyway */
callback();
/* don't run another check if there is one pending */
if (m_CheckRunning) {
olock.Unlock();
return;
/* we need to call the callback anyway */
callback();
return;
}
m_CheckRunning = true;
}
/* keep track of scheduling info in case the check type doesn't provide its own information */
@ -545,12 +554,12 @@ void Service::BeginExecuteCheck(const function<void (void)>& callback)
Host::Ptr host = GetHost();
olock.Unlock();
macroDicts.push_back(CalculateDynamicMacros());
macroDicts.push_back(host->GetMacros());
macroDicts.push_back(host->CalculateDynamicMacros());
if (host) {
macroDicts.push_back(host->GetMacros());
macroDicts.push_back(host->CalculateDynamicMacros());
}
IcingaApplication::Ptr app = IcingaApplication::GetInstance();
macroDicts.push_back(app->GetMacros());
@ -570,7 +579,7 @@ void Service::BeginExecuteCheck(const function<void (void)>& callback)
ScriptTask::Ptr task = MakeMethodTask("check", arguments);
{
ObjectLock slock(this);
ObjectLock olock(this);
self->m_CurrentTask = task;
}
@ -642,6 +651,7 @@ void Service::CheckCompletedHandler(const Dictionary::Ptr& checkInfo,
{
ObjectLock olock(this);
m_CurrentTask.reset();
m_CheckRunning = false;
}
/* figure out when the next check is for this service; the call to

View File

@ -25,7 +25,8 @@ int Service::m_NextCommentID = 1;
boost::mutex Service::m_CommentMutex;
map<int, String> Service::m_LegacyCommentsCache;
map<String, Service::WeakPtr> Service::m_CommentsCache;
bool Service::m_CommentsCacheValid = true;
bool Service::m_CommentsCacheNeedsUpdate = false;
Timer::Ptr Service::m_CommentsCacheTimer;
Timer::Ptr Service::m_CommentsExpireTimer;
/**
@ -176,10 +177,17 @@ void Service::InvalidateCommentsCache(void)
{
boost::mutex::scoped_lock lock(m_CommentMutex);
if (m_CommentsCacheValid)
Utility::QueueAsyncCallback(boost::bind(&Service::RefreshCommentsCache));
if (m_CommentsCacheNeedsUpdate)
return; /* Someone else has already requested a refresh. */
m_CommentsCacheValid = false;
if (!m_CommentsCacheTimer) {
m_CommentsCacheTimer = boost::make_shared<Timer>();
m_CommentsCacheTimer->SetInterval(0.5);
m_CommentsCacheTimer->OnTimerExpired.connect(boost::bind(&Service::RefreshCommentsCache));
}
m_CommentsCacheTimer->Start();
m_CommentsCacheNeedsUpdate = true;
}
/**
@ -190,10 +198,9 @@ void Service::RefreshCommentsCache(void)
{
boost::mutex::scoped_lock lock(m_CommentMutex);
if (m_CommentsCacheValid)
return;
m_CommentsCacheValid = true;
assert(m_CommentsCacheNeedsUpdate);
m_CommentsCacheTimer->Stop();
m_CommentsCacheNeedsUpdate = false;
}
map<int, String> newLegacyCommentsCache;

View File

@ -25,7 +25,8 @@ int Service::m_NextDowntimeID = 1;
boost::mutex Service::m_DowntimeMutex;
map<int, String> Service::m_LegacyDowntimesCache;
map<String, Service::WeakPtr> Service::m_DowntimesCache;
bool Service::m_DowntimesCacheValid = true;
bool Service::m_DowntimesCacheNeedsUpdate = false;
Timer::Ptr Service::m_DowntimesCacheTimer;
Timer::Ptr Service::m_DowntimesExpireTimer;
/**
@ -250,10 +251,17 @@ void Service::InvalidateDowntimesCache(void)
{
boost::mutex::scoped_lock lock(m_DowntimeMutex);
if (m_DowntimesCacheValid)
Utility::QueueAsyncCallback(boost::bind(&Service::RefreshDowntimesCache));
if (m_DowntimesCacheNeedsUpdate)
return; /* Someone else has already requested a refresh. */
m_DowntimesCacheValid = false;
if (!m_DowntimesCacheTimer) {
m_DowntimesCacheTimer = boost::make_shared<Timer>();
m_DowntimesCacheTimer->SetInterval(0.5);
m_DowntimesCacheTimer->OnTimerExpired.connect(boost::bind(&Service::RefreshNotificationsCache));
}
m_DowntimesCacheTimer->Start();
m_DowntimesCacheNeedsUpdate = true;
}
/**
@ -264,10 +272,9 @@ void Service::RefreshDowntimesCache(void)
{
boost::mutex::scoped_lock lock(m_DowntimeMutex);
if (m_DowntimesCacheValid)
return;
m_DowntimesCacheValid = true;
assert(m_DowntimesCacheNeedsUpdate);
m_DowntimesCacheTimer->Stop();
m_DowntimesCacheNeedsUpdate = false;
}
map<int, String> newLegacyDowntimesCache;

View File

@ -23,14 +23,18 @@ using namespace icinga;
boost::mutex Service::m_NotificationMutex;
map<String, set<Notification::WeakPtr> > Service::m_NotificationsCache;
bool Service::m_NotificationsCacheValid = true;
bool Service::m_NotificationsCacheNeedsUpdate = false;
Timer::Ptr Service::m_NotificationsCacheTimer;
/**
* @threadsafety Always.
*/
void Service::RequestNotifications(NotificationType type)
{
SetLastNotification(Utility::GetTime());
{
ObjectLock olock(this);
SetLastNotification(Utility::GetTime());
}
RequestMessage msg;
msg.SetMethod("icinga::SendNotifications");
@ -83,10 +87,17 @@ void Service::InvalidateNotificationsCache(void)
{
boost::mutex::scoped_lock lock(m_NotificationMutex);
if (m_NotificationsCacheValid)
Utility::QueueAsyncCallback(boost::bind(&Service::RefreshNotificationsCache));
if (m_NotificationsCacheNeedsUpdate)
return; /* Someone else has already requested a refresh. */
m_NotificationsCacheValid = false;
if (!m_NotificationsCacheTimer) {
m_NotificationsCacheTimer = boost::make_shared<Timer>();
m_NotificationsCacheTimer->SetInterval(0.5);
m_NotificationsCacheTimer->OnTimerExpired.connect(boost::bind(&Service::RefreshNotificationsCache));
}
m_NotificationsCacheTimer->Start();
m_NotificationsCacheNeedsUpdate = true;
}
/**
@ -97,10 +108,9 @@ void Service::RefreshNotificationsCache(void)
{
boost::mutex::scoped_lock lock(m_NotificationMutex);
if (m_NotificationsCacheValid)
return;
m_NotificationsCacheValid = true;
assert(m_NotificationsCacheNeedsUpdate);
m_NotificationsCacheTimer->Stop();
m_NotificationsCacheNeedsUpdate = false;
}
map<String, set<Notification::WeakPtr> > newNotificationsCache;

View File

@ -24,7 +24,7 @@ using namespace icinga;
REGISTER_TYPE(Service);
Service::Service(const Dictionary::Ptr& serializedObject)
: DynamicObject(serializedObject)
: DynamicObject(serializedObject), m_CheckRunning(false)
{
RegisterAttribute("display_name", Attribute_Config, &m_DisplayName);
@ -106,9 +106,6 @@ Service::Ptr Service::GetByName(const String& name)
{
DynamicObject::Ptr configObject = DynamicObject::GetObject("Service", name);
if (!configObject)
BOOST_THROW_EXCEPTION(invalid_argument("Service '" + name + "' does not exist."));
return dynamic_pointer_cast<Service>(configObject);
}
@ -250,6 +247,8 @@ bool Service::IsReachable(void) const
*/
AcknowledgementType Service::GetAcknowledgement(void)
{
assert(OwnsLock());
if (m_Acknowledgement.IsEmpty())
return AcknowledgementNone;

View File

@ -284,6 +284,7 @@ private:
Attribute<bool> m_ForceNextCheck;
ScriptTask::Ptr m_CurrentTask;
bool m_CheckRunning;
long m_SchedulingOffset;
void CheckCompletedHandler(const Dictionary::Ptr& checkInfo,
@ -297,7 +298,8 @@ private:
static boost::mutex m_DowntimeMutex;
static map<int, String> m_LegacyDowntimesCache;
static map<String, Service::WeakPtr> m_DowntimesCache;
static bool m_DowntimesCacheValid;
static bool m_DowntimesCacheNeedsUpdate;
static Timer::Ptr m_DowntimesCacheTimer;
static Timer::Ptr m_DowntimesExpireTimer;
static void DowntimesExpireTimerHandler(void);
@ -314,7 +316,8 @@ private:
static boost::mutex m_CommentMutex;
static map<int, String> m_LegacyCommentsCache;
static map<String, Service::WeakPtr> m_CommentsCache;
static bool m_CommentsCacheValid;
static bool m_CommentsCacheNeedsUpdate;
static Timer::Ptr m_CommentsCacheTimer;
static Timer::Ptr m_CommentsExpireTimer;
static void CommentsExpireTimerHandler(void);
@ -331,7 +334,8 @@ private:
static boost::mutex m_NotificationMutex;
static map<String, set<Notification::WeakPtr> > m_NotificationsCache;
static bool m_NotificationsCacheValid;
static bool m_NotificationsCacheNeedsUpdate;
static Timer::Ptr m_NotificationsCacheTimer;
static void RefreshNotificationsCache(void);
};

View File

@ -23,7 +23,8 @@ using namespace icinga;
boost::mutex ServiceGroup::m_Mutex;
map<String, vector<Service::WeakPtr> > ServiceGroup::m_MembersCache;
bool ServiceGroup::m_MembersCacheValid = true;
bool ServiceGroup::m_MembersCacheNeedsUpdate = false;
Timer::Ptr ServiceGroup::m_MembersCacheTimer;
REGISTER_TYPE(ServiceGroup);
@ -120,10 +121,17 @@ void ServiceGroup::InvalidateMembersCache(void)
{
boost::mutex::scoped_lock lock(m_Mutex);
if (m_MembersCacheValid)
Utility::QueueAsyncCallback(boost::bind(&ServiceGroup::RefreshMembersCache));
if (m_MembersCacheNeedsUpdate)
return; /* Someone else has already requested a refresh. */
m_MembersCacheValid = false;
if (!m_MembersCacheTimer) {
m_MembersCacheTimer = boost::make_shared<Timer>();
m_MembersCacheTimer->SetInterval(0.5);
m_MembersCacheTimer->OnTimerExpired.connect(boost::bind(&ServiceGroup::RefreshMembersCache));
}
m_MembersCacheTimer->Start();
m_MembersCacheNeedsUpdate = true;
}
/**
@ -134,10 +142,9 @@ void ServiceGroup::RefreshMembersCache(void)
{
boost::mutex::scoped_lock lock(m_Mutex);
if (m_MembersCacheValid)
return;
m_MembersCacheValid = true;
assert(m_MembersCacheNeedsUpdate);
m_MembersCacheTimer->Stop();
m_MembersCacheNeedsUpdate = false;
}
map<String, vector<Service::WeakPtr> > newMembersCache;

View File

@ -57,7 +57,8 @@ private:
static boost::mutex m_Mutex;
static map<String, vector<Service::WeakPtr> > m_MembersCache;
static bool m_MembersCacheValid;
static bool m_MembersCacheNeedsUpdate;
static Timer::Ptr m_MembersCacheTimer;
static void RefreshMembersCache(void);
};