mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-31 01:24:19 +02:00
More lock refactoring. Yay.
This commit is contained in:
parent
572a477da3
commit
48485c5f26
@ -27,13 +27,9 @@ void CheckerComponent::Start(void)
|
||||
{
|
||||
m_Endpoint = Endpoint::MakeEndpoint("checker", false);
|
||||
|
||||
{
|
||||
ObjectLock olock(m_Endpoint);
|
||||
|
||||
/* dummy registration so the delegation module knows this is a checker
|
||||
TODO: figure out a better way for this */
|
||||
m_Endpoint->RegisterSubscription("checker");
|
||||
}
|
||||
/* dummy registration so the delegation module knows this is a checker
|
||||
TODO: figure out a better way for this */
|
||||
m_Endpoint->RegisterSubscription("checker");
|
||||
|
||||
Service::OnCheckerChanged.connect(bind(&CheckerComponent::CheckerChangedHandler, this, _1));
|
||||
Service::OnNextCheckChanged.connect(bind(&CheckerComponent::NextCheckChangedHandler, this, _1));
|
||||
@ -50,10 +46,7 @@ void CheckerComponent::Start(void)
|
||||
|
||||
void CheckerComponent::Stop(void)
|
||||
{
|
||||
{
|
||||
ObjectLock olock(m_Endpoint);
|
||||
m_Endpoint->Unregister();
|
||||
}
|
||||
m_Endpoint->Unregister();
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
@ -81,24 +74,14 @@ void CheckerComponent::CheckThreadProc(void)
|
||||
CheckTimeView::iterator it = idx.begin();
|
||||
Service::Ptr service = *it;
|
||||
|
||||
ObjectLock olock(service); /* also required for the key extractor. */
|
||||
|
||||
if (!service->IsRegistered()) {
|
||||
idx.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
double wait;
|
||||
|
||||
{
|
||||
ObjectLock olock(service);
|
||||
wait = service->GetNextCheck() - Utility::GetTime();
|
||||
}
|
||||
double wait = service->GetNextCheck() - Utility::GetTime();
|
||||
|
||||
if (wait > 0) {
|
||||
/* Release the object lock. */
|
||||
olock.Unlock();
|
||||
|
||||
/* Make sure the service we just examined can be destroyed while we're waiting. */
|
||||
service.reset();
|
||||
|
||||
@ -113,19 +96,17 @@ void CheckerComponent::CheckThreadProc(void)
|
||||
|
||||
/* reschedule the service if checks are currently disabled
|
||||
* for it and this is not a forced check */
|
||||
if (!service->GetEnableActiveChecks()) {
|
||||
if (!service->GetForceNextCheck()) {
|
||||
Logger::Write(LogDebug, "checker", "Ignoring service check for disabled service: " + service->GetName());
|
||||
if (!service->GetEnableActiveChecks() && !service->GetForceNextCheck()) {
|
||||
Logger::Write(LogDebug, "checker", "Ignoring service check for disabled service: " + service->GetName());
|
||||
|
||||
service->UpdateNextCheck();
|
||||
service->UpdateNextCheck();
|
||||
|
||||
typedef nth_index<ServiceSet, 1>::type CheckTimeView;
|
||||
CheckTimeView& idx = boost::get<1>(m_IdleServices);
|
||||
typedef nth_index<ServiceSet, 1>::type CheckTimeView;
|
||||
CheckTimeView& idx = boost::get<1>(m_IdleServices);
|
||||
|
||||
idx.insert(service);
|
||||
idx.insert(service);
|
||||
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
service->SetForceNextCheck(false);
|
||||
@ -136,18 +117,9 @@ void CheckerComponent::CheckThreadProc(void)
|
||||
m_PendingServices.insert(service);
|
||||
|
||||
try {
|
||||
olock.Unlock();
|
||||
|
||||
CheckerComponent::Ptr self;
|
||||
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
self = GetSelf();
|
||||
}
|
||||
|
||||
Service::BeginExecuteCheck(service, boost::bind(&CheckerComponent::CheckCompletedHandler, static_cast<CheckerComponent::Ptr>(self), service));
|
||||
CheckerComponent::Ptr self = GetSelf();
|
||||
Service::BeginExecuteCheck(service, boost::bind(&CheckerComponent::CheckCompletedHandler, self, service));
|
||||
} catch (const exception& ex) {
|
||||
olock.Lock();
|
||||
Logger::Write(LogCritical, "checker", "Exception occured while checking service '" + service->GetName() + "': " + diagnostic_information(ex));
|
||||
}
|
||||
}
|
||||
@ -156,7 +128,6 @@ void CheckerComponent::CheckThreadProc(void)
|
||||
void CheckerComponent::CheckCompletedHandler(const Service::Ptr& service)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
ObjectLock olock(service); /* required for the key extractor */
|
||||
|
||||
/* remove the service from the list of pending services; if it's not in the
|
||||
* list this was a manual (i.e. forced) check and we must not re-add the
|
||||
@ -191,19 +162,9 @@ void CheckerComponent::CheckerChangedHandler(const Service::Ptr& service)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
|
||||
ObjectLock olock(service); /* also required for the key extractor */
|
||||
String checker = service->GetCurrentChecker();
|
||||
|
||||
EndpointManager::Ptr em = EndpointManager::GetInstance();
|
||||
|
||||
String identity;
|
||||
|
||||
{
|
||||
ObjectLock elock(em);
|
||||
identity = em->GetIdentity();
|
||||
}
|
||||
|
||||
if (checker == identity || Endpoint::GetByName(checker) == m_Endpoint) {
|
||||
if (checker == EndpointManager::GetInstance()->GetIdentity() || Endpoint::GetByName(checker) == m_Endpoint) {
|
||||
if (m_PendingServices.find(service) != m_PendingServices.end())
|
||||
return;
|
||||
|
||||
@ -220,8 +181,6 @@ void CheckerComponent::NextCheckChangedHandler(const Service::Ptr& service)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
|
||||
ObjectLock olock(service); /* required for the key extractor */
|
||||
|
||||
/* remove and re-insert the service from the set in order to force an index update */
|
||||
typedef nth_index<ServiceSet, 0>::type ServiceView;
|
||||
ServiceView& idx = boost::get<0>(m_IdleServices);
|
||||
|
@ -31,7 +31,7 @@ struct ServiceNextCheckExtractor
|
||||
typedef double result_type;
|
||||
|
||||
/**
|
||||
* @threadsafety Caller must hold the mutex for the service.
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
double operator()(const Service::Ptr& service)
|
||||
{
|
||||
|
@ -38,8 +38,6 @@ String CompatComponent::GetStatusPath(void) const
|
||||
{
|
||||
DynamicObject::Ptr config = GetConfig();
|
||||
|
||||
ObjectLock olock(config);
|
||||
|
||||
Value statusPath = config->Get("status_path");
|
||||
if (statusPath.IsEmpty())
|
||||
return Application::GetLocalStateDir() + "/cache/icinga2/status.dat";
|
||||
@ -56,8 +54,6 @@ String CompatComponent::GetObjectsPath(void) const
|
||||
{
|
||||
DynamicObject::Ptr config = GetConfig();
|
||||
|
||||
ObjectLock olock(config);
|
||||
|
||||
Value objectsPath = config->Get("objects_path");
|
||||
if (objectsPath.IsEmpty())
|
||||
return Application::GetLocalStateDir() + "/cache/icinga2/objects.cache";
|
||||
@ -74,8 +70,6 @@ String CompatComponent::GetLogPath(void) const
|
||||
{
|
||||
DynamicObject::Ptr config = GetConfig();
|
||||
|
||||
ObjectLock olock(config);
|
||||
|
||||
Value logPath = config->Get("log_path");
|
||||
if (logPath.IsEmpty())
|
||||
return Application::GetLocalStateDir() + "/log/icinga2/compat";
|
||||
@ -92,8 +86,6 @@ String CompatComponent::GetCommandPath(void) const
|
||||
{
|
||||
DynamicObject::Ptr config = GetConfig();
|
||||
|
||||
ObjectLock olock(config);
|
||||
|
||||
Value commandPath = config->Get("command_path");
|
||||
if (commandPath.IsEmpty())
|
||||
return Application::GetLocalStateDir() + "/run/icinga.cmd";
|
||||
@ -107,7 +99,7 @@ String CompatComponent::GetCommandPath(void) const
|
||||
void CompatComponent::Start(void)
|
||||
{
|
||||
m_StatusTimer = boost::make_shared<Timer>();
|
||||
m_StatusTimer->SetInterval(5);
|
||||
m_StatusTimer->SetInterval(15);
|
||||
m_StatusTimer->OnTimerExpired.connect(boost::bind(&CompatComponent::StatusTimerHandler, this));
|
||||
m_StatusTimer->Start();
|
||||
m_StatusTimer->Reschedule(0);
|
||||
@ -170,31 +162,24 @@ void CompatComponent::CommandPipeThread(const String& commandPath)
|
||||
|
||||
String command = line;
|
||||
|
||||
ProcessCommand(command);
|
||||
try {
|
||||
Logger::Write(LogInformation, "compat", "Executing external command: " + command);
|
||||
|
||||
ExternalCommandProcessor::Execute(command);
|
||||
} catch (const exception& ex) {
|
||||
stringstream msgbuf;
|
||||
msgbuf << "External command failed: " << diagnostic_information(ex);
|
||||
Logger::Write(LogWarning, "compat", msgbuf.str());
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
void CompatComponent::ProcessCommand(const String& command)
|
||||
{
|
||||
try {
|
||||
Logger::Write(LogInformation, "compat", "Executing external command: " + command);
|
||||
|
||||
ExternalCommandProcessor::Execute(command);
|
||||
} catch (const exception& ex) {
|
||||
stringstream msgbuf;
|
||||
msgbuf << "External command failed: " << diagnostic_information(ex);
|
||||
Logger::Write(LogWarning, "compat", msgbuf.str());
|
||||
}
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
void CompatComponent::DumpComments(ostream& fp, const Service::Ptr& owner, CompatObjectType type)
|
||||
{
|
||||
ObjectLock olock(owner);
|
||||
|
||||
Service::Ptr service;
|
||||
Host::Ptr host;
|
||||
Dictionary::Ptr comments = owner->GetComments();
|
||||
@ -202,6 +187,8 @@ void CompatComponent::DumpComments(ostream& fp, const Service::Ptr& owner, Compa
|
||||
if (!comments)
|
||||
return;
|
||||
|
||||
ObjectLock olock(comments);
|
||||
|
||||
String id;
|
||||
Dictionary::Ptr comment;
|
||||
BOOST_FOREACH(tie(id, comment), comments) {
|
||||
@ -230,27 +217,17 @@ void CompatComponent::DumpComments(ostream& fp, const Service::Ptr& owner, Compa
|
||||
|
||||
void CompatComponent::DumpDowntimes(ostream& fp, const Service::Ptr& owner, CompatObjectType type)
|
||||
{
|
||||
Dictionary::Ptr downtimes;
|
||||
String short_name, host_name;
|
||||
Host::Ptr host;
|
||||
Host::Ptr host = owner->GetHost();
|
||||
|
||||
{
|
||||
ObjectLock olock(owner);
|
||||
if (!host)
|
||||
return;
|
||||
|
||||
downtimes = owner->GetDowntimes();
|
||||
short_name = owner->GetShortName();
|
||||
host = owner->GetHost();
|
||||
}
|
||||
|
||||
{
|
||||
ObjectLock olock(host);
|
||||
host_name = host->GetName();
|
||||
}
|
||||
Dictionary::Ptr downtimes = owner->GetDowntimes();
|
||||
|
||||
if (!downtimes)
|
||||
return;
|
||||
|
||||
ObjectLock dlock(downtimes);
|
||||
ObjectLock olock(downtimes);
|
||||
|
||||
String id;
|
||||
Dictionary::Ptr downtime;
|
||||
@ -264,14 +241,14 @@ void CompatComponent::DumpDowntimes(ostream& fp, const Service::Ptr& owner, Comp
|
||||
fp << "hostdowntime {" << "\n";
|
||||
else
|
||||
fp << "servicedowntime {" << "\n"
|
||||
<< "\t" << "service_description=" << short_name << "\n";
|
||||
<< "\t" << "service_description=" << owner->GetShortName() << "\n";
|
||||
|
||||
Dictionary::Ptr triggeredByObj = Service::GetDowntimeByID(downtime->Get("triggered_by"));
|
||||
int triggeredByLegacy = 0;
|
||||
if (triggeredByObj)
|
||||
triggeredByLegacy = triggeredByObj->Get("legacy_id");
|
||||
|
||||
fp << "\t" << "host_name=" << host_name << "\n"
|
||||
fp << "\t" << "host_name=" << host->GetName() << "\n"
|
||||
<< "\t" << "downtime_id=" << static_cast<String>(downtime->Get("legacy_id")) << "\n"
|
||||
<< "\t" << "entry_time=" << static_cast<double>(downtime->Get("entry_time")) << "\n"
|
||||
<< "\t" << "start_time=" << static_cast<double>(downtime->Get("start_time")) << "\n"
|
||||
@ -290,23 +267,19 @@ void CompatComponent::DumpDowntimes(ostream& fp, const Service::Ptr& owner, Comp
|
||||
|
||||
void CompatComponent::DumpHostStatus(ostream& fp, const Host::Ptr& host)
|
||||
{
|
||||
{
|
||||
ObjectLock olock(host);
|
||||
|
||||
fp << "hoststatus {" << "\n"
|
||||
<< "\t" << "host_name=" << host->GetName() << "\n";
|
||||
}
|
||||
fp << "hoststatus {" << "\n"
|
||||
<< "\t" << "host_name=" << host->GetName() << "\n";
|
||||
|
||||
ServiceState hcState = StateOK;
|
||||
|
||||
Service::Ptr hc = Host::GetHostCheckService(host);
|
||||
if (hc) {
|
||||
ObjectLock olock(hc);
|
||||
Service::Ptr hc = host->GetHostCheckService();
|
||||
ObjectLock olock(hc);
|
||||
|
||||
if (hc)
|
||||
hcState = hc->GetState();
|
||||
}
|
||||
|
||||
int state;
|
||||
if (!Host::IsReachable(host))
|
||||
if (!host->IsReachable())
|
||||
state = 2; /* unreachable */
|
||||
else if (hcState != StateOK)
|
||||
state = 1; /* down */
|
||||
@ -327,15 +300,11 @@ void CompatComponent::DumpHostStatus(ostream& fp, const Host::Ptr& host)
|
||||
|
||||
void CompatComponent::DumpHostObject(ostream& fp, const Host::Ptr& host)
|
||||
{
|
||||
{
|
||||
ObjectLock olock(host);
|
||||
fp << "define host {" << "\n"
|
||||
<< "\t" << "host_name" << "\t" << host->GetName() << "\n"
|
||||
<< "\t" << "display_name" << "\t" << host->GetDisplayName() << "\n";
|
||||
|
||||
fp << "define host {" << "\n"
|
||||
<< "\t" << "host_name" << "\t" << host->GetName() << "\n"
|
||||
<< "\t" << "display_name" << "\t" << host->GetDisplayName() << "\n";
|
||||
}
|
||||
|
||||
set<Host::Ptr> parents = Host::GetParentHosts(host);
|
||||
set<Host::Ptr> parents = host->GetParentHosts();
|
||||
|
||||
if (!parents.empty()) {
|
||||
fp << "\t" << "parents" << "\t";
|
||||
@ -343,7 +312,7 @@ void CompatComponent::DumpHostObject(ostream& fp, const Host::Ptr& host)
|
||||
fp << "\n";
|
||||
}
|
||||
|
||||
Service::Ptr hc = Host::GetHostCheckService(host);
|
||||
Service::Ptr hc = host->GetHostCheckService();
|
||||
if (hc) {
|
||||
ObjectLock olock(hc);
|
||||
|
||||
@ -372,94 +341,77 @@ void CompatComponent::DumpHostObject(ostream& fp, const Host::Ptr& host)
|
||||
|
||||
void CompatComponent::DumpServiceStatusAttrs(ostream& fp, const Service::Ptr& service, CompatObjectType type)
|
||||
{
|
||||
ObjectLock olock(service);
|
||||
|
||||
String output;
|
||||
String perfdata;
|
||||
double schedule_end = -1;
|
||||
|
||||
Dictionary::Ptr cr;
|
||||
int state, state_type;
|
||||
Host::Ptr host;
|
||||
|
||||
{
|
||||
ObjectLock olock(service);
|
||||
|
||||
cr = service->GetLastCheckResult();
|
||||
state = service->GetState();
|
||||
state_type = service->GetStateType();
|
||||
host = service->GetHost();
|
||||
}
|
||||
Dictionary::Ptr cr = service->GetLastCheckResult();
|
||||
|
||||
if (cr) {
|
||||
ObjectLock olock(cr);
|
||||
|
||||
output = cr->Get("output");
|
||||
schedule_end = cr->Get("schedule_end");
|
||||
perfdata = cr->Get("performance_data_raw");
|
||||
}
|
||||
|
||||
int state = service->GetState();
|
||||
|
||||
if (state > StateUnknown)
|
||||
state = StateUnknown;
|
||||
|
||||
if (type == CompatTypeHost) {
|
||||
if (state == StateOK || state == StateWarning)
|
||||
state = 0;
|
||||
state = 0; /* UP */
|
||||
else
|
||||
state = 1;
|
||||
state = 1; /* DOWN */
|
||||
|
||||
if (!Host::IsReachable(host))
|
||||
state = 2;
|
||||
Host::Ptr host = service->GetHost();
|
||||
|
||||
if (!host)
|
||||
return;
|
||||
|
||||
if (!host->IsReachable())
|
||||
state = 2; /* UNREACHABLE */
|
||||
}
|
||||
|
||||
{
|
||||
ObjectLock olock(service);
|
||||
|
||||
fp << "\t" << "check_interval=" << service->GetCheckInterval() / 60.0 << "\n"
|
||||
<< "\t" << "retry_interval=" << service->GetRetryInterval() / 60.0 << "\n"
|
||||
<< "\t" << "has_been_checked=" << (service->GetLastCheckResult() ? 1 : 0) << "\n"
|
||||
<< "\t" << "should_be_scheduled=1" << "\n"
|
||||
<< "\t" << "check_execution_time=" << Service::CalculateExecutionTime(cr) << "\n"
|
||||
<< "\t" << "check_latency=" << Service::CalculateLatency(cr) << "\n"
|
||||
<< "\t" << "current_state=" << state << "\n"
|
||||
<< "\t" << "state_type=" << state_type << "\n"
|
||||
<< "\t" << "plugin_output=" << output << "\n"
|
||||
<< "\t" << "performance_data=" << perfdata << "\n"
|
||||
<< "\t" << "last_check=" << schedule_end << "\n"
|
||||
<< "\t" << "next_check=" << service->GetNextCheck() << "\n"
|
||||
<< "\t" << "current_attempt=" << service->GetCurrentCheckAttempt() << "\n"
|
||||
<< "\t" << "max_attempts=" << service->GetMaxCheckAttempts() << "\n"
|
||||
<< "\t" << "last_state_change=" << service->GetLastStateChange() << "\n"
|
||||
<< "\t" << "last_hard_state_change=" << service->GetLastHardStateChange() << "\n"
|
||||
<< "\t" << "last_update=" << time(NULL) << "\n"
|
||||
<< "\t" << "notifications_enabled=" << (service->GetEnableNotifications() ? 1 : 0) << "\n"
|
||||
<< "\t" << "active_checks_enabled=" << (service->GetEnableActiveChecks() ? 1 : 0) <<"\n"
|
||||
<< "\t" << "passive_checks_enabled=" << (service->GetEnablePassiveChecks() ? 1 : 0) << "\n"
|
||||
<< "\t" << "problem_has_been_acknowledged=" << (service->GetAcknowledgement() != AcknowledgementNone ? 1 : 0) << "\n"
|
||||
<< "\t" << "acknowledgement_type=" << static_cast<int>(service->GetAcknowledgement()) << "\n"
|
||||
<< "\t" << "acknowledgement_end_time=" << service->GetAcknowledgementExpiry() << "\n"
|
||||
<< "\t" << "scheduled_downtime_depth=" << (service->IsInDowntime() ? 1 : 0) << "\n"
|
||||
<< "\t" << "last_notification=" << service->GetLastNotification() << "\n";
|
||||
}
|
||||
fp << "\t" << "check_interval=" << service->GetCheckInterval() / 60.0 << "\n"
|
||||
<< "\t" << "retry_interval=" << service->GetRetryInterval() / 60.0 << "\n"
|
||||
<< "\t" << "has_been_checked=" << (service->GetLastCheckResult() ? 1 : 0) << "\n"
|
||||
<< "\t" << "should_be_scheduled=1" << "\n"
|
||||
<< "\t" << "check_execution_time=" << Service::CalculateExecutionTime(cr) << "\n"
|
||||
<< "\t" << "check_latency=" << Service::CalculateLatency(cr) << "\n"
|
||||
<< "\t" << "current_state=" << state << "\n"
|
||||
<< "\t" << "state_type=" << service->GetStateType() << "\n"
|
||||
<< "\t" << "plugin_output=" << output << "\n"
|
||||
<< "\t" << "performance_data=" << perfdata << "\n"
|
||||
<< "\t" << "last_check=" << schedule_end << "\n"
|
||||
<< "\t" << "next_check=" << service->GetNextCheck() << "\n"
|
||||
<< "\t" << "current_attempt=" << service->GetCurrentCheckAttempt() << "\n"
|
||||
<< "\t" << "max_attempts=" << service->GetMaxCheckAttempts() << "\n"
|
||||
<< "\t" << "last_state_change=" << service->GetLastStateChange() << "\n"
|
||||
<< "\t" << "last_hard_state_change=" << service->GetLastHardStateChange() << "\n"
|
||||
<< "\t" << "last_update=" << time(NULL) << "\n"
|
||||
<< "\t" << "notifications_enabled=" << (service->GetEnableNotifications() ? 1 : 0) << "\n"
|
||||
<< "\t" << "active_checks_enabled=" << (service->GetEnableActiveChecks() ? 1 : 0) <<"\n"
|
||||
<< "\t" << "passive_checks_enabled=" << (service->GetEnablePassiveChecks() ? 1 : 0) << "\n"
|
||||
<< "\t" << "problem_has_been_acknowledged=" << (service->GetAcknowledgement() != AcknowledgementNone ? 1 : 0) << "\n"
|
||||
<< "\t" << "acknowledgement_type=" << static_cast<int>(service->GetAcknowledgement()) << "\n"
|
||||
<< "\t" << "acknowledgement_end_time=" << service->GetAcknowledgementExpiry() << "\n"
|
||||
<< "\t" << "scheduled_downtime_depth=" << (service->IsInDowntime() ? 1 : 0) << "\n"
|
||||
<< "\t" << "last_notification=" << service->GetLastNotification() << "\n";
|
||||
}
|
||||
|
||||
void CompatComponent::DumpServiceStatus(ostream& fp, const Service::Ptr& service)
|
||||
{
|
||||
String host_name, short_name;
|
||||
Host::Ptr host;
|
||||
Host::Ptr host = service->GetHost();
|
||||
|
||||
{
|
||||
ObjectLock olock(service);
|
||||
short_name = service->GetShortName();
|
||||
host = service->GetHost();
|
||||
}
|
||||
|
||||
{
|
||||
ObjectLock olock(host);
|
||||
host_name = host->GetName();
|
||||
}
|
||||
if (!host)
|
||||
return;
|
||||
|
||||
fp << "servicestatus {" << "\n"
|
||||
<< "\t" << "host_name=" << host_name << "\n"
|
||||
<< "\t" << "service_description=" << short_name << "\n";
|
||||
<< "\t" << "host_name=" << host->GetName() << "\n"
|
||||
<< "\t" << "service_description=" << service->GetShortName() << "\n";
|
||||
|
||||
DumpServiceStatusAttrs(fp, service, CompatTypeService);
|
||||
|
||||
@ -472,29 +424,17 @@ void CompatComponent::DumpServiceStatus(ostream& fp, const Service::Ptr& service
|
||||
|
||||
void CompatComponent::DumpServiceObject(ostream& fp, const Service::Ptr& service)
|
||||
{
|
||||
Host::Ptr host;
|
||||
String host_name, short_name;
|
||||
|
||||
{
|
||||
ObjectLock olock(service);
|
||||
host = service->GetHost();
|
||||
short_name = service->GetShortName();
|
||||
}
|
||||
Host::Ptr host = service->GetHost();
|
||||
|
||||
if (!host)
|
||||
return;
|
||||
|
||||
{
|
||||
ObjectLock olock(host);
|
||||
host_name = host->GetName();
|
||||
}
|
||||
|
||||
{
|
||||
ObjectLock olock(service);
|
||||
|
||||
fp << "define service {" << "\n"
|
||||
<< "\t" << "host_name" << "\t" << host_name << "\n"
|
||||
<< "\t" << "service_description" << "\t" << short_name << "\n"
|
||||
<< "\t" << "host_name" << "\t" << host->GetName() << "\n"
|
||||
<< "\t" << "service_description" << "\t" << service->GetShortName() << "\n"
|
||||
<< "\t" << "display_name" << "\t" << service->GetDisplayName() << "\n"
|
||||
<< "\t" << "check_command" << "\t" << "check_i2" << "\n"
|
||||
<< "\t" << "check_interval" << "\t" << service->GetCheckInterval() / 60.0 << "\n"
|
||||
@ -510,14 +450,22 @@ void CompatComponent::DumpServiceObject(ostream& fp, const Service::Ptr& service
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const Service::Ptr& parent, Service::GetParentServices(service)) {
|
||||
ObjectLock plock(parent);
|
||||
BOOST_FOREACH(const Service::Ptr& parent, service->GetParentServices()) {
|
||||
Host::Ptr host = service->GetHost();
|
||||
|
||||
if (!host)
|
||||
continue;
|
||||
|
||||
Host::Ptr parent_host = parent->GetHost();
|
||||
|
||||
if (!parent_host)
|
||||
continue;
|
||||
|
||||
fp << "define servicedependency {" << "\n"
|
||||
<< "\t" << "dependent_host_name" << "\t" << host_name << "\n"
|
||||
<< "\t" << "dependent_host_name" << "\t" << host->GetName() << "\n"
|
||||
<< "\t" << "dependent_service_description" << "\t" << service->GetShortName() << "\n"
|
||||
<< "\t" << "host_name" << "\t" << parent->GetHost()->GetName() << "\n"
|
||||
<< "\t" << "service_description" << "\t" << short_name << "\n"
|
||||
<< "\t" << "host_name" << "\t" << parent_host->GetName() << "\n"
|
||||
<< "\t" << "service_description" << "\t" << service->GetShortName() << "\n"
|
||||
<< "\t" << "execution_failure_criteria" << "\t" << "n" << "\n"
|
||||
<< "\t" << "notification_failure_criteria" << "\t" << "w,u,c" << "\n"
|
||||
<< "\t" << "}" << "\n"
|
||||
@ -552,18 +500,10 @@ void CompatComponent::StatusTimerHandler(void)
|
||||
<< "\t" << "}" << "\n"
|
||||
<< "\n";
|
||||
|
||||
double startTime;
|
||||
|
||||
{
|
||||
IcingaApplication::Ptr app = IcingaApplication::GetInstance();
|
||||
ObjectLock olock(app);
|
||||
startTime = app->GetStartTime();
|
||||
}
|
||||
|
||||
statusfp << "programstatus {" << "\n"
|
||||
<< "icinga_pid=" << Utility::GetPid() << "\n"
|
||||
<< "\t" << "daemon_mode=1" << "\n"
|
||||
<< "\t" << "program_start=" << startTime << "\n"
|
||||
<< "\t" << "program_start=" << IcingaApplication::GetInstance()->GetStartTime() << "\n"
|
||||
<< "\t" << "active_service_checks_enabled=1" << "\n"
|
||||
<< "\t" << "passive_service_checks_enabled=1" << "\n"
|
||||
<< "\t" << "active_host_checks_enabled=1" << "\n"
|
||||
@ -622,17 +562,13 @@ void CompatComponent::StatusTimerHandler(void)
|
||||
stringstream tempobjectfp;
|
||||
tempobjectfp << std::fixed;
|
||||
|
||||
{
|
||||
ObjectLock olock(hg);
|
||||
|
||||
tempobjectfp << "define hostgroup {" << "\n"
|
||||
<< "\t" << "hostgroup_name" << "\t" << hg->GetName() << "\n"
|
||||
<< "\t" << "notes_url" << "\t" << hg->GetNotesUrl() << "\n"
|
||||
<< "\t" << "action_url" << "\t" << hg->GetActionUrl() << "\n";
|
||||
}
|
||||
tempobjectfp << "define hostgroup {" << "\n"
|
||||
<< "\t" << "hostgroup_name" << "\t" << hg->GetName() << "\n"
|
||||
<< "\t" << "notes_url" << "\t" << hg->GetNotesUrl() << "\n"
|
||||
<< "\t" << "action_url" << "\t" << hg->GetActionUrl() << "\n";
|
||||
|
||||
tempobjectfp << "\t" << "members" << "\t";
|
||||
DumpNameList(tempobjectfp, HostGroup::GetMembers(hg));
|
||||
DumpNameList(tempobjectfp, hg->GetMembers());
|
||||
tempobjectfp << "\n"
|
||||
<< "\t" << "}" << "\n";
|
||||
|
||||
@ -659,35 +595,22 @@ void CompatComponent::StatusTimerHandler(void)
|
||||
stringstream tempobjectfp;
|
||||
tempobjectfp << std::fixed;
|
||||
|
||||
{
|
||||
ObjectLock olock(sg);
|
||||
|
||||
tempobjectfp << "define servicegroup {" << "\n"
|
||||
<< "\t" << "servicegroup_name" << "\t" << sg->GetName() << "\n"
|
||||
<< "\t" << "notes_url" << "\t" << sg->GetNotesUrl() << "\n"
|
||||
<< "\t" << "action_url" << "\t" << sg->GetActionUrl() << "\n";
|
||||
}
|
||||
tempobjectfp << "define servicegroup {" << "\n"
|
||||
<< "\t" << "servicegroup_name" << "\t" << sg->GetName() << "\n"
|
||||
<< "\t" << "notes_url" << "\t" << sg->GetNotesUrl() << "\n"
|
||||
<< "\t" << "action_url" << "\t" << sg->GetActionUrl() << "\n";
|
||||
|
||||
tempobjectfp << "\t" << "members" << "\t";
|
||||
|
||||
vector<String> sglist;
|
||||
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
|
||||
Host::Ptr host;
|
||||
String host_name, short_name;
|
||||
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
|
||||
Host::Ptr host = service->GetHost();
|
||||
|
||||
{
|
||||
ObjectLock olock(service);
|
||||
host = service->GetHost();
|
||||
short_name = service->GetShortName();
|
||||
}
|
||||
if (!host)
|
||||
continue;
|
||||
|
||||
{
|
||||
ObjectLock olock(host);
|
||||
host_name = host->GetName();
|
||||
}
|
||||
|
||||
sglist.push_back(host_name);
|
||||
sglist.push_back(short_name);
|
||||
sglist.push_back(host->GetName());
|
||||
sglist.push_back(service->GetShortName());
|
||||
}
|
||||
|
||||
DumpStringList(tempobjectfp, sglist);
|
||||
@ -704,19 +627,15 @@ void CompatComponent::StatusTimerHandler(void)
|
||||
stringstream tempobjectfp;
|
||||
tempobjectfp << std::fixed;
|
||||
|
||||
{
|
||||
ObjectLock olock(user);
|
||||
|
||||
tempobjectfp << "define contact {" << "\n"
|
||||
<< "\t" << "contact_name" << "\t" << user->GetName() << "\n"
|
||||
<< "\t" << "alias" << "\t" << user->GetDisplayName() << "\n"
|
||||
<< "\t" << "service_notification_options" << "\t" << "w,u,c,r,f,s" << "\n"
|
||||
<< "\t" << "host_notification_options" << "\t" << "d,u,r,f,s" << "\n"
|
||||
<< "\t" << "host_notifications_enabled" << "\t" << 1 << "\n"
|
||||
<< "\t" << "service_notifications_enabled" << "\t" << 1 << "\n"
|
||||
<< "\t" << "}" << "\n"
|
||||
<< "\n";
|
||||
}
|
||||
tempobjectfp << "define contact {" << "\n"
|
||||
<< "\t" << "contact_name" << "\t" << user->GetName() << "\n"
|
||||
<< "\t" << "alias" << "\t" << user->GetDisplayName() << "\n"
|
||||
<< "\t" << "service_notification_options" << "\t" << "w,u,c,r,f,s" << "\n"
|
||||
<< "\t" << "host_notification_options" << "\t" << "d,u,r,f,s" << "\n"
|
||||
<< "\t" << "host_notifications_enabled" << "\t" << 1 << "\n"
|
||||
<< "\t" << "service_notifications_enabled" << "\t" << 1 << "\n"
|
||||
<< "\t" << "}" << "\n"
|
||||
<< "\n";
|
||||
|
||||
objectfp << tempobjectfp.str();
|
||||
}
|
||||
@ -727,16 +646,12 @@ void CompatComponent::StatusTimerHandler(void)
|
||||
stringstream tempobjectfp;
|
||||
tempobjectfp << std::fixed;
|
||||
|
||||
{
|
||||
ObjectLock olock(ug);
|
||||
|
||||
tempobjectfp << "define contactgroup {" << "\n"
|
||||
<< "\t" << "contactgroup_name" << "\t" << ug->GetName() << "\n"
|
||||
<< "\t" << "alias" << "\t" << ug->GetDisplayName() << "\n";
|
||||
}
|
||||
tempobjectfp << "define contactgroup {" << "\n"
|
||||
<< "\t" << "contactgroup_name" << "\t" << ug->GetName() << "\n"
|
||||
<< "\t" << "alias" << "\t" << ug->GetDisplayName() << "\n";
|
||||
|
||||
tempobjectfp << "\t" << "members" << "\t";
|
||||
DumpNameList(tempobjectfp, UserGroup::GetMembers(ug));
|
||||
DumpNameList(tempobjectfp, ug->GetMembers());
|
||||
tempobjectfp << "\n"
|
||||
<< "\t" << "}" << "\n";
|
||||
|
||||
|
@ -43,7 +43,6 @@ private:
|
||||
thread m_CommandThread;
|
||||
|
||||
void CommandPipeThread(const String& commandPath);
|
||||
void ProcessCommand(const String& command);
|
||||
#endif /* _WIN32 */
|
||||
|
||||
Timer::Ptr m_StatusTimer;
|
||||
|
@ -46,8 +46,6 @@ set<Endpoint::Ptr> DelegationComponent::GetCheckerCandidates(const Service::Ptr&
|
||||
|
||||
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Endpoint")) {
|
||||
Endpoint::Ptr endpoint = dynamic_pointer_cast<Endpoint>(object);
|
||||
ObjectLock olock(endpoint);
|
||||
|
||||
String myIdentity = EndpointManager::GetInstance()->GetIdentity();
|
||||
|
||||
/* ignore local-only endpoints (unless this is a local-only instance) */
|
||||
@ -93,8 +91,8 @@ void DelegationComponent::DelegationTimerHandler(void)
|
||||
|
||||
services.push_back(service);
|
||||
|
||||
ObjectLock olock(service);
|
||||
String checker = service->GetCurrentChecker();
|
||||
|
||||
if (checker.IsEmpty())
|
||||
continue;
|
||||
|
||||
@ -112,8 +110,6 @@ void DelegationComponent::DelegationTimerHandler(void)
|
||||
|
||||
/* re-assign services */
|
||||
BOOST_FOREACH(const Service::Ptr& service, services) {
|
||||
ObjectLock olock(service);
|
||||
|
||||
String checker = service->GetCurrentChecker();
|
||||
|
||||
Endpoint::Ptr oldEndpoint = Endpoint::GetByName(checker);
|
||||
@ -141,8 +137,6 @@ void DelegationComponent::DelegationTimerHandler(void)
|
||||
/* don't re-assign service if the checker is still valid
|
||||
* and doesn't have too many services */
|
||||
|
||||
ObjectLock elock(oldEndpoint);
|
||||
|
||||
if (oldEndpoint && oldEndpoint->IsConnected() &&
|
||||
candidates.find(oldEndpoint) != candidates.end() &&
|
||||
histogram[oldEndpoint] <= avg_services + overflow_tolerance)
|
||||
@ -162,7 +156,6 @@ void DelegationComponent::DelegationTimerHandler(void)
|
||||
if (histogram[candidate] > avg_services)
|
||||
continue;
|
||||
|
||||
ObjectLock clock(candidate);
|
||||
service->SetCurrentChecker(candidate->GetName());
|
||||
histogram[candidate]++;
|
||||
|
||||
@ -189,6 +182,8 @@ void DelegationComponent::DelegationTimerHandler(void)
|
||||
cr->Set("state", StateUncheckable);
|
||||
cr->Set("output", "No checker is available for this service.");
|
||||
|
||||
cr->Seal();
|
||||
|
||||
service->ProcessCheckResult(cr);
|
||||
|
||||
Logger::Write(LogWarning, "delegation", "Can't delegate service: " + service->GetName());
|
||||
@ -203,8 +198,6 @@ void DelegationComponent::DelegationTimerHandler(void)
|
||||
Endpoint::Ptr endpoint;
|
||||
int count;
|
||||
BOOST_FOREACH(tie(endpoint, count), histogram) {
|
||||
ObjectLock olock(endpoint);
|
||||
|
||||
stringstream msgbuf;
|
||||
msgbuf << "histogram: " << endpoint->GetName() << " - " << count;
|
||||
Logger::Write(LogInformation, "delegation", msgbuf.str());
|
||||
|
@ -54,16 +54,12 @@ void DemoComponent::Stop(void)
|
||||
*/
|
||||
void DemoComponent::DemoTimerHandler(void)
|
||||
{
|
||||
Logger::Write(LogInformation, "demo", "Sending multicast 'hello"
|
||||
" world' message.");
|
||||
Logger::Write(LogInformation, "demo", "Sending multicast 'hello world' message.");
|
||||
|
||||
RequestMessage request;
|
||||
request.SetMethod("demo::HelloWorld");
|
||||
|
||||
EndpointManager::Ptr em = EndpointManager::GetInstance();
|
||||
|
||||
ObjectLock olock(em);
|
||||
em->SendMulticastMessage(m_Endpoint, request);
|
||||
EndpointManager::GetInstance()->SendMulticastMessage(m_Endpoint, request);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,13 +29,9 @@ REGISTER_COMPONENT("notification", NotificationComponent);
|
||||
void NotificationComponent::Start(void)
|
||||
{
|
||||
m_Endpoint = Endpoint::MakeEndpoint("notification", false);
|
||||
|
||||
{
|
||||
ObjectLock olock(m_Endpoint);
|
||||
m_Endpoint->RegisterTopicHandler("icinga::SendNotifications",
|
||||
boost::bind(&NotificationComponent::SendNotificationsRequestHandler, this, _2,
|
||||
_3));
|
||||
}
|
||||
m_Endpoint->RegisterTopicHandler("icinga::SendNotifications",
|
||||
boost::bind(&NotificationComponent::SendNotificationsRequestHandler, this, _2,
|
||||
_3));
|
||||
|
||||
m_NotificationTimer = boost::make_shared<Timer>();
|
||||
m_NotificationTimer->SetInterval(5);
|
||||
@ -48,6 +44,7 @@ void NotificationComponent::Start(void)
|
||||
*/
|
||||
void NotificationComponent::Stop(void)
|
||||
{
|
||||
m_Endpoint->Unregister();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -61,6 +58,8 @@ void NotificationComponent::NotificationTimerHandler(void)
|
||||
|
||||
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
|
||||
Service::Ptr service = dynamic_pointer_cast<Service>(object);
|
||||
bool reachable = service->IsReachable();
|
||||
|
||||
ObjectLock olock(service);
|
||||
|
||||
if (service->GetStateType() == StateTypeSoft)
|
||||
@ -75,7 +74,7 @@ void NotificationComponent::NotificationTimerHandler(void)
|
||||
if (service->GetLastNotification() > now - service->GetNotificationInterval())
|
||||
continue;
|
||||
|
||||
if (Service::IsReachable(service) && !service->IsInDowntime() && !service->IsAcknowledged())
|
||||
if (reachable && !service->IsInDowntime() && !service->IsAcknowledged())
|
||||
service->RequestNotifications(NotificationProblem);
|
||||
}
|
||||
}
|
||||
@ -100,5 +99,5 @@ void NotificationComponent::SendNotificationsRequestHandler(const Endpoint::Ptr&
|
||||
|
||||
Service::Ptr service = Service::GetByName(svc);
|
||||
|
||||
Service::SendNotifications(service, static_cast<NotificationType>(type));
|
||||
service->SendNotifications(static_cast<NotificationType>(type));
|
||||
}
|
||||
|
@ -79,9 +79,9 @@ Application::~Application(void)
|
||||
*
|
||||
* @returns The application object.
|
||||
*/
|
||||
Application *Application::GetInstance(void)
|
||||
Application::Ptr Application::GetInstance(void)
|
||||
{
|
||||
return m_Instance;
|
||||
return m_Instance->GetSelf();
|
||||
}
|
||||
|
||||
int Application::GetArgC(void)
|
||||
@ -285,7 +285,7 @@ void Application::SigIntHandler(int signum)
|
||||
{
|
||||
assert(signum == SIGINT);
|
||||
|
||||
Application *instance = Application::GetInstance();
|
||||
Application::Ptr instance = Application::GetInstance();
|
||||
|
||||
if (!instance)
|
||||
return;
|
||||
@ -320,7 +320,7 @@ void Application::SigAbrtHandler(int signum)
|
||||
*/
|
||||
BOOL WINAPI Application::CtrlHandler(DWORD type)
|
||||
{
|
||||
Application *instance = Application::GetInstance();
|
||||
Application::Ptr instance = Application::GetInstance();
|
||||
|
||||
if (!instance)
|
||||
return TRUE;
|
||||
@ -410,6 +410,8 @@ int Application::Run(void)
|
||||
*/
|
||||
void Application::UpdatePidFile(const String& filename)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
ClosePidFile();
|
||||
|
||||
/* There's just no sane way of getting a file descriptor for a
|
||||
@ -420,7 +422,15 @@ void Application::UpdatePidFile(const String& filename)
|
||||
BOOST_THROW_EXCEPTION(runtime_error("Could not open PID file '" + filename + "'"));
|
||||
|
||||
#ifndef _WIN32
|
||||
Utility::SetCloExec(fileno(m_PidFile));
|
||||
int fd = fileno(m_PidFile);
|
||||
|
||||
Utility::SetCloExec(fd);
|
||||
|
||||
if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
|
||||
Logger::Write(LogCritical, "base", "Could not lock PID file. Make sure that only one instance of the application is running.");
|
||||
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
fprintf(m_PidFile, "%d", Utility::GetPid());
|
||||
@ -432,6 +442,8 @@ void Application::UpdatePidFile(const String& filename)
|
||||
*/
|
||||
void Application::ClosePidFile(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_PidFile != NULL)
|
||||
fclose(m_PidFile);
|
||||
|
||||
|
@ -37,7 +37,7 @@ public:
|
||||
Application(const Dictionary::Ptr& serializedUpdate);
|
||||
~Application(void);
|
||||
|
||||
static Application *GetInstance(void);
|
||||
static Application::Ptr GetInstance(void);
|
||||
|
||||
int Run(void);
|
||||
|
||||
|
@ -23,6 +23,7 @@ using namespace icinga;
|
||||
|
||||
REGISTER_TYPE(Component);
|
||||
|
||||
boost::mutex Component::m_Mutex;
|
||||
map<String, Component::Factory> Component::m_Factories;
|
||||
|
||||
/**
|
||||
@ -38,18 +39,24 @@ Component::Component(const Dictionary::Ptr& properties)
|
||||
|
||||
(void) Utility::LoadIcingaLibrary(GetName(), true);
|
||||
|
||||
map<String, Factory>::iterator it;
|
||||
it = m_Factories.find(GetName());
|
||||
Component::Factory factory;
|
||||
|
||||
if (it == m_Factories.end())
|
||||
BOOST_THROW_EXCEPTION(invalid_argument("Unknown component: " + GetName()));
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
|
||||
IComponent::Ptr impl = it->second();
|
||||
map<String, Factory>::iterator it;
|
||||
it = m_Factories.find(GetName());
|
||||
|
||||
if (!impl)
|
||||
if (it == m_Factories.end())
|
||||
BOOST_THROW_EXCEPTION(invalid_argument("Unknown component: " + GetName()));
|
||||
|
||||
factory = it->second;
|
||||
}
|
||||
|
||||
m_Impl = factory();
|
||||
|
||||
if (!m_Impl)
|
||||
BOOST_THROW_EXCEPTION(runtime_error("Component factory returned NULL."));
|
||||
|
||||
m_Impl = impl;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,7 +74,9 @@ Component::~Component(void)
|
||||
*/
|
||||
void Component::Start(void)
|
||||
{
|
||||
m_Impl->m_Config = GetSelf();
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_Impl->SetConfig(GetSelf());
|
||||
m_Impl->Start();
|
||||
}
|
||||
|
||||
@ -95,9 +104,21 @@ void Component::AddSearchDir(const String& componentDirectory)
|
||||
*/
|
||||
DynamicObject::Ptr IComponent::GetConfig(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Config.lock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the configuration for this component.
|
||||
*/
|
||||
void IComponent::SetConfig(const DynamicObject::Ptr& config)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_Config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the component.
|
||||
*/
|
||||
@ -119,5 +140,7 @@ void IComponent::Stop(void)
|
||||
*/
|
||||
void Component::Register(const String& name, const Component::Factory& factory)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
|
||||
m_Factories[name] = factory;
|
||||
}
|
||||
|
@ -44,6 +44,8 @@ private:
|
||||
DynamicObject::WeakPtr m_Config; /**< The configuration object for this
|
||||
component. */
|
||||
|
||||
void SetConfig(const DynamicObject::Ptr& config);
|
||||
|
||||
friend class Component;
|
||||
};
|
||||
|
||||
@ -74,6 +76,7 @@ private:
|
||||
IComponent::Ptr m_Impl; /**< The implementation object for this
|
||||
component. */
|
||||
|
||||
static boost::mutex m_Mutex;
|
||||
static map<String, Factory> m_Factories;
|
||||
};
|
||||
|
||||
|
@ -33,7 +33,7 @@ signals2::signal<void (double, const set<DynamicObject::WeakPtr>&)> DynamicObjec
|
||||
signals2::signal<void (double, const DynamicObject::Ptr&)> DynamicObject::OnFlushObject;
|
||||
|
||||
DynamicObject::DynamicObject(const Dictionary::Ptr& serializedObject)
|
||||
: m_EventSafe(false), m_ConfigTx(0), m_Registered(false)
|
||||
: m_ConfigTx(0), m_Registered(false)
|
||||
{
|
||||
RegisterAttribute("__name", Attribute_Config, &m_Name);
|
||||
RegisterAttribute("__type", Attribute_Config, &m_Type);
|
||||
@ -115,7 +115,8 @@ Dictionary::Ptr DynamicObject::BuildUpdate(double sinceTx, int attributeTypes) c
|
||||
void DynamicObject::ApplyUpdate(const Dictionary::Ptr& serializedUpdate,
|
||||
int allowedTypes)
|
||||
{
|
||||
assert(OwnsLock());
|
||||
ObjectLock olock(this);
|
||||
|
||||
assert(serializedUpdate->IsSealed());
|
||||
|
||||
Value configTxValue = serializedUpdate->Get("configTx");
|
||||
@ -132,7 +133,7 @@ void DynamicObject::ApplyUpdate(const Dictionary::Ptr& serializedUpdate,
|
||||
assert(attrs->IsSealed());
|
||||
|
||||
{
|
||||
ObjectLock olock(attrs);
|
||||
ObjectLock alock(attrs);
|
||||
|
||||
Dictionary::Iterator it;
|
||||
for (it = attrs->Begin(); it != attrs->End(); it++) {
|
||||
@ -233,7 +234,7 @@ void DynamicObject::InternalSetAttribute(const String& name, const Value& data,
|
||||
m_ConfigTx = tx;
|
||||
}
|
||||
|
||||
if (GetEventSafe()) {
|
||||
if (m_Registered) {
|
||||
/* 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
|
||||
@ -365,17 +366,16 @@ String DynamicObject::GetSource(void) const
|
||||
|
||||
void DynamicObject::Register(void)
|
||||
{
|
||||
assert(OwnsLock());
|
||||
assert(!OwnsLock());
|
||||
|
||||
/* It's now safe to send us attribute events. */
|
||||
SetEventSafe(true);
|
||||
DynamicObject::Ptr self = GetSelf();
|
||||
|
||||
/* Add this new object to the list of modified objects.
|
||||
* We're doing this here because we can't construct
|
||||
* a while WeakPtr from within the object's constructor. */
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_TransactionMutex);
|
||||
m_ModifiedObjects.insert(GetSelf());
|
||||
m_ModifiedObjects.insert(self);
|
||||
}
|
||||
|
||||
{
|
||||
@ -384,7 +384,6 @@ void DynamicObject::Register(void)
|
||||
|
||||
DynamicObject::Ptr dobj = dtype->GetObject(GetName());
|
||||
|
||||
DynamicObject::Ptr self = GetSelf();
|
||||
assert(!dobj || dobj == self);
|
||||
|
||||
if (!dobj)
|
||||
@ -394,6 +393,8 @@ void DynamicObject::Register(void)
|
||||
|
||||
void DynamicObject::OnRegistrationCompleted(void)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
DynamicObject::Ptr object;
|
||||
|
||||
{
|
||||
@ -402,14 +403,24 @@ void DynamicObject::OnRegistrationCompleted(void)
|
||||
|
||||
Start();
|
||||
|
||||
Flush();
|
||||
|
||||
object = GetSelf();
|
||||
}
|
||||
|
||||
OnRegistered(object);
|
||||
}
|
||||
|
||||
void DynamicObject::OnUnregistrationCompleted(void)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
m_Registered = false;
|
||||
}
|
||||
|
||||
OnUnregistered(GetSelf());
|
||||
}
|
||||
|
||||
void DynamicObject::Start(void)
|
||||
{
|
||||
assert(OwnsLock());
|
||||
@ -419,25 +430,30 @@ void DynamicObject::Start(void)
|
||||
|
||||
void DynamicObject::Unregister(void)
|
||||
{
|
||||
assert(OwnsLock());
|
||||
assert(!OwnsLock());
|
||||
|
||||
DynamicObject::Ptr self = GetSelf();
|
||||
|
||||
DynamicType::Ptr dtype = GetType();
|
||||
ObjectLock olock(dtype);
|
||||
|
||||
if (!dtype || !dtype->GetObject(GetName()))
|
||||
if (!dtype)
|
||||
return;
|
||||
|
||||
dtype->UnregisterObject(GetSelf());
|
||||
|
||||
OnUnregistered(GetSelf());
|
||||
{
|
||||
ObjectLock olock(dtype);
|
||||
dtype->UnregisterObject(self);
|
||||
}
|
||||
}
|
||||
|
||||
ScriptTask::Ptr DynamicObject::MakeMethodTask(const String& method,
|
||||
const vector<Value>& arguments)
|
||||
{
|
||||
assert(OwnsLock());
|
||||
Dictionary::Ptr methods;
|
||||
|
||||
Dictionary::Ptr methods = m_Methods;
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
methods = m_Methods;
|
||||
}
|
||||
|
||||
String funcName = methods->Get(method);
|
||||
|
||||
@ -471,13 +487,6 @@ void DynamicObject::DumpObjects(const String& filename)
|
||||
sfp->Start();
|
||||
|
||||
BOOST_FOREACH(const DynamicType::Ptr& type, DynamicType::GetTypes()) {
|
||||
String type_name;
|
||||
|
||||
{
|
||||
ObjectLock olock(type);
|
||||
type_name = type->GetName();
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const DynamicObject::Ptr& object, type->GetObjects()) {
|
||||
ObjectLock olock(object);
|
||||
|
||||
@ -486,7 +495,7 @@ void DynamicObject::DumpObjects(const String& filename)
|
||||
|
||||
Dictionary::Ptr persistentObject = boost::make_shared<Dictionary>();
|
||||
|
||||
persistentObject->Set("type", type_name);
|
||||
persistentObject->Set("type", type->GetName());
|
||||
persistentObject->Set("name", object->GetName());
|
||||
|
||||
int types = Attribute_Local | Attribute_Replicated;
|
||||
@ -558,10 +567,8 @@ void DynamicObject::RestoreObjects(const String& filename)
|
||||
|
||||
if (hasConfig && !object) {
|
||||
object = DynamicType::CreateObject(dt, update);
|
||||
ObjectLock olock(object);
|
||||
object->Register();
|
||||
} else if (object) {
|
||||
ObjectLock olock(object);
|
||||
object->ApplyUpdate(update, Attribute_All);
|
||||
}
|
||||
|
||||
@ -579,7 +586,6 @@ void DynamicObject::DeactivateObjects(void)
|
||||
{
|
||||
BOOST_FOREACH(const DynamicType::Ptr& dt, DynamicType::GetTypes()) {
|
||||
BOOST_FOREACH(const DynamicObject::Ptr& object, dt->GetObjects()) {
|
||||
ObjectLock olock(object);
|
||||
object->Unregister();
|
||||
}
|
||||
}
|
||||
@ -624,31 +630,28 @@ void DynamicObject::NewTx(void)
|
||||
BOOST_FOREACH(const DynamicObject::WeakPtr& wobject, objects) {
|
||||
DynamicObject::Ptr object = wobject.lock();
|
||||
|
||||
if (!object)
|
||||
if (!object || !object->IsRegistered())
|
||||
continue;
|
||||
|
||||
map<String, Value, string_iless> attrs;
|
||||
bool event_safe;
|
||||
|
||||
{
|
||||
ObjectLock olock(object);
|
||||
attrs.swap(object->m_ModifiedAttributes);
|
||||
event_safe = object->GetEventSafe();
|
||||
}
|
||||
|
||||
/* Send attribute events if it's safe to do so. */
|
||||
if (event_safe) {
|
||||
map<String, Value, string_iless>::iterator it;
|
||||
for (it = attrs.begin(); it != attrs.end(); it++)
|
||||
object->OnAttributeChanged(it->first, it->second);
|
||||
}
|
||||
map<String, Value, string_iless>::iterator it;
|
||||
for (it = attrs.begin(); it != attrs.end(); it++)
|
||||
object->OnAttributeChanged(it->first, it->second);
|
||||
}
|
||||
|
||||
OnTransactionClosing(tx, objects);
|
||||
}
|
||||
|
||||
void DynamicObject::OnAttributeChanged(const String&, const Value&)
|
||||
{ }
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
}
|
||||
|
||||
/*
|
||||
* @threadsafety Always.
|
||||
@ -665,17 +668,3 @@ const DynamicObject::AttributeMap& DynamicObject::GetAttributes(void) const
|
||||
|
||||
return m_Attributes;
|
||||
}
|
||||
|
||||
void DynamicObject::SetEventSafe(bool safe)
|
||||
{
|
||||
assert(OwnsLock());
|
||||
|
||||
m_EventSafe = safe;
|
||||
}
|
||||
|
||||
bool DynamicObject::GetEventSafe(void) const
|
||||
{
|
||||
assert(OwnsLock());
|
||||
|
||||
return m_EventSafe;
|
||||
}
|
||||
|
@ -252,9 +252,6 @@ public:
|
||||
|
||||
const AttributeMap& GetAttributes(void) const;
|
||||
|
||||
void SetEventSafe(bool initialized);
|
||||
bool GetEventSafe(void) const;
|
||||
|
||||
static DynamicObject::Ptr GetObject(const String& type, const String& name);
|
||||
|
||||
static void DumpObjects(const String& filename);
|
||||
@ -265,6 +262,8 @@ public:
|
||||
|
||||
protected:
|
||||
virtual void OnRegistrationCompleted(void);
|
||||
virtual void OnUnregistrationCompleted(void);
|
||||
|
||||
virtual void OnAttributeChanged(const String& name, const Value& oldValue);
|
||||
|
||||
private:
|
||||
@ -284,7 +283,6 @@ private:
|
||||
Attribute<Dictionary::Ptr> m_Methods;
|
||||
|
||||
bool m_Registered;
|
||||
bool m_EventSafe;
|
||||
|
||||
static double m_CurrentTx;
|
||||
|
||||
|
@ -103,12 +103,11 @@ void DynamicType::RegisterObject(const DynamicObject::Ptr& object)
|
||||
|
||||
void DynamicType::UnregisterObject(const DynamicObject::Ptr& object)
|
||||
{
|
||||
ObjectLock olock(object);
|
||||
object->SetEventSafe(false);
|
||||
|
||||
assert(OwnsLock());
|
||||
m_ObjectMap.erase(object->GetName());
|
||||
m_ObjectSet.erase(object);
|
||||
|
||||
object->OnUnregistrationCompleted();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -21,7 +21,9 @@
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
#ifdef _DEBUG
|
||||
boost::mutex Object::m_DebugMutex;
|
||||
#endif /* _DEBUG */
|
||||
|
||||
/**
|
||||
* Default constructor for the Object class.
|
||||
@ -49,6 +51,7 @@ Object::SharedPtrHolder Object::GetSelf(void)
|
||||
return Object::SharedPtrHolder(shared_from_this());
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
/**
|
||||
* Checks if the calling thread owns the lock on this object or is currently
|
||||
* in the constructor or destructor and therefore implicitly owns the lock.
|
||||
@ -73,3 +76,4 @@ bool Object::OwnsLock(void) const
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif /* _DEBUG */
|
||||
|
@ -100,7 +100,9 @@ protected:
|
||||
|
||||
SharedPtrHolder GetSelf(void);
|
||||
|
||||
#ifdef _DEBUG
|
||||
bool OwnsLock(void) const;
|
||||
#endif /* _DEBUG */
|
||||
|
||||
private:
|
||||
Object(const Object& other);
|
||||
@ -110,7 +112,9 @@ private:
|
||||
mutable unsigned int m_LockCount;
|
||||
mutable boost::thread::id m_LockOwner;
|
||||
|
||||
#ifdef _DEBUG
|
||||
static boost::mutex m_DebugMutex;
|
||||
#endif /* _DEBUG */
|
||||
|
||||
friend class ObjectLock;
|
||||
};
|
||||
|
@ -21,6 +21,10 @@
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
#ifdef _DEBUG
|
||||
static __thread int g_LockCount;
|
||||
#endif /* _DEBUG */
|
||||
|
||||
ObjectLock::ObjectLock(void)
|
||||
: m_Object(NULL), m_Lock()
|
||||
{ }
|
||||
@ -50,21 +54,42 @@ void ObjectLock::Lock(void)
|
||||
|
||||
m_Lock = recursive_mutex::scoped_lock(m_Object->m_Mutex);
|
||||
|
||||
#ifdef _DEBUG
|
||||
{
|
||||
boost::mutex::scoped_lock lock(Object::m_DebugMutex);
|
||||
m_Object->m_LockCount++;
|
||||
m_Object->m_LockOwner = boost::this_thread::get_id();
|
||||
|
||||
if (m_Object->m_LockCount == 1) {
|
||||
g_LockCount++;
|
||||
m_TS = Utility::GetTime();
|
||||
}
|
||||
}
|
||||
#endif /* _DEBUG */
|
||||
}
|
||||
|
||||
void ObjectLock::Unlock(void)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
{
|
||||
boost::mutex::scoped_lock lock(Object::m_DebugMutex);
|
||||
|
||||
if (m_Lock.owns_lock())
|
||||
if (m_Lock.owns_lock()) {
|
||||
if (m_Object->m_LockCount == 1) {
|
||||
g_LockCount--;
|
||||
|
||||
double dt = Utility::GetTime() - m_TS;
|
||||
|
||||
if (dt > 0.05) {
|
||||
std::cerr << "Held object lock for " << dt << " seconds at:";
|
||||
Utility::PrintStacktrace(std::cerr);
|
||||
}
|
||||
}
|
||||
|
||||
m_Object->m_LockCount--;
|
||||
}
|
||||
}
|
||||
#endif /* _DEBUG */
|
||||
|
||||
m_Lock = recursive_mutex::scoped_lock();
|
||||
}
|
||||
|
@ -39,6 +39,9 @@ public:
|
||||
private:
|
||||
const Object *m_Object;
|
||||
recursive_mutex::scoped_lock m_Lock;
|
||||
#ifdef _DEBUG
|
||||
double m_TS;
|
||||
#endif /* _DEBUG */
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -35,6 +35,9 @@ Script::Script(const Dictionary::Ptr& properties)
|
||||
RegisterAttribute("code", Attribute_Config, &m_Code);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Script::Start(void)
|
||||
{
|
||||
assert(OwnsLock());
|
||||
@ -42,6 +45,9 @@ void Script::Start(void)
|
||||
SpawnInterpreter();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String Script::GetLanguage(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
@ -49,6 +55,9 @@ String Script::GetLanguage(void) const
|
||||
return m_Language;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String Script::GetCode(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
@ -56,12 +65,20 @@ String Script::GetCode(void) const
|
||||
return m_Code;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Script::OnAttributeUpdate(const String& name, const Value& oldValue)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
if (name == "language" || name == "code")
|
||||
SpawnInterpreter();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Script::SpawnInterpreter(void)
|
||||
{
|
||||
Logger::Write(LogInformation, "base", "Reloading script '" + GetName() + "'");
|
||||
|
@ -28,25 +28,37 @@ ScriptFunction::ScriptFunction(const Callback& function)
|
||||
: m_Callback(function)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void ScriptFunction::Register(const String& name, const ScriptFunction::Ptr& function)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(GetMutex());
|
||||
|
||||
InternalGetFunctions()[name] = function;
|
||||
OnRegistered(name, function);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void ScriptFunction::Unregister(const String& name)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(GetMutex());
|
||||
|
||||
InternalGetFunctions().erase(name);
|
||||
OnUnregistered(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
ScriptFunction::Ptr ScriptFunction::GetByName(const String& name)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(GetMutex());
|
||||
|
||||
map<String, ScriptFunction::Ptr>::iterator it;
|
||||
|
||||
boost::mutex::scoped_lock lock(GetMutex());
|
||||
it = InternalGetFunctions().find(name);
|
||||
|
||||
if (it == InternalGetFunctions().end())
|
||||
@ -55,6 +67,9 @@ ScriptFunction::Ptr ScriptFunction::GetByName(const String& name)
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void ScriptFunction::Invoke(const ScriptTask::Ptr& task, const vector<Value>& arguments)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
@ -62,9 +77,13 @@ void ScriptFunction::Invoke(const ScriptTask::Ptr& task, const vector<Value>& ar
|
||||
m_Callback(task, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
map<String, ScriptFunction::Ptr> ScriptFunction::GetFunctions(void)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(GetMutex());
|
||||
|
||||
return InternalGetFunctions(); /* makes a copy of the map */
|
||||
}
|
||||
|
||||
@ -77,6 +96,9 @@ map<String, ScriptFunction::Ptr>& ScriptFunction::InternalGetFunctions(void)
|
||||
return functions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
boost::mutex& ScriptFunction::GetMutex(void)
|
||||
{
|
||||
static boost::mutex mtx;
|
||||
|
@ -44,8 +44,6 @@ public:
|
||||
static void Unregister(const String& name);
|
||||
static ScriptFunction::Ptr GetByName(const String& name);
|
||||
|
||||
void Invoke(const shared_ptr<ScriptTask>& task, const vector<Value>& arguments);
|
||||
|
||||
static map<String, ScriptFunction::Ptr> GetFunctions(void);
|
||||
|
||||
static signals2::signal<void (const String&, const ScriptFunction::Ptr&)> OnRegistered;
|
||||
@ -56,6 +54,10 @@ private:
|
||||
|
||||
static map<String, ScriptFunction::Ptr>& InternalGetFunctions(void);
|
||||
static boost::mutex& GetMutex(void);
|
||||
|
||||
void Invoke(const shared_ptr<ScriptTask>& task, const vector<Value>& arguments);
|
||||
|
||||
friend class ScriptTask;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -29,12 +29,5 @@ ScriptTask::ScriptTask(const ScriptFunction::Ptr& function,
|
||||
|
||||
void ScriptTask::Run(void)
|
||||
{
|
||||
ScriptTask::Ptr self;
|
||||
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
self = GetSelf();
|
||||
}
|
||||
|
||||
m_Function->Invoke(self, m_Arguments);
|
||||
m_Function->Invoke(GetSelf(), m_Arguments);
|
||||
}
|
||||
|
@ -48,6 +48,8 @@ Socket::~Socket(void)
|
||||
*/
|
||||
void Socket::Start(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
assert(!m_ReadThread.joinable() && !m_WriteThread.joinable());
|
||||
assert(GetFD() != INVALID_SOCKET);
|
||||
|
||||
@ -68,6 +70,8 @@ void Socket::Start(void)
|
||||
*/
|
||||
void Socket::SetFD(SOCKET fd)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
/* mark the socket as non-blocking and close-on-exec */
|
||||
if (fd != INVALID_SOCKET) {
|
||||
Utility::SetNonBlockingSocket(fd);
|
||||
@ -86,27 +90,25 @@ void Socket::SetFD(SOCKET fd)
|
||||
*/
|
||||
SOCKET Socket::GetFD(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_FD;
|
||||
}
|
||||
|
||||
void Socket::CloseUnlocked(void)
|
||||
{
|
||||
if (m_FD == INVALID_SOCKET)
|
||||
return;
|
||||
|
||||
closesocket(m_FD);
|
||||
m_FD = INVALID_SOCKET;
|
||||
|
||||
Stream::Close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the socket.
|
||||
*/
|
||||
void Socket::Close(void)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_SocketMutex);
|
||||
CloseUnlocked();
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_FD == INVALID_SOCKET)
|
||||
return;
|
||||
|
||||
closesocket(m_FD);
|
||||
m_FD = INVALID_SOCKET;
|
||||
|
||||
Stream::Close();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -146,6 +148,8 @@ int Socket::GetLastSocketError(void)
|
||||
*/
|
||||
void Socket::HandleException(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
BOOST_THROW_EXCEPTION(SocketException("select() returned fd in except fdset", GetError()));
|
||||
}
|
||||
|
||||
@ -271,7 +275,7 @@ void Socket::ReadThreadProc(void)
|
||||
} catch (...) {
|
||||
SetException(boost::current_exception());
|
||||
|
||||
CloseUnlocked();
|
||||
Close();
|
||||
|
||||
break;
|
||||
}
|
||||
@ -326,7 +330,7 @@ void Socket::WriteThreadProc(void)
|
||||
} catch (...) {
|
||||
SetException(boost::current_exception());
|
||||
|
||||
CloseUnlocked();
|
||||
Close();
|
||||
|
||||
break;
|
||||
}
|
||||
@ -340,6 +344,8 @@ void Socket::WriteThreadProc(void)
|
||||
*/
|
||||
void Socket::SetConnected(bool connected)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_Connected = connected;
|
||||
}
|
||||
|
||||
@ -350,6 +356,8 @@ void Socket::SetConnected(bool connected)
|
||||
*/
|
||||
bool Socket::IsConnected(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Connected;
|
||||
}
|
||||
|
||||
@ -360,14 +368,12 @@ bool Socket::IsConnected(void) const
|
||||
*/
|
||||
size_t Socket::GetAvailableBytes(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_Listening)
|
||||
throw new logic_error("Socket does not support GetAvailableBytes().");
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||
|
||||
return m_RecvQueue->GetAvailableBytes();
|
||||
}
|
||||
return m_RecvQueue->GetAvailableBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -379,11 +385,13 @@ size_t Socket::GetAvailableBytes(void) const
|
||||
*/
|
||||
size_t Socket::Read(void *buffer, size_t size)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_Listening)
|
||||
throw new logic_error("Socket does not support Read().");
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||
ObjectLock olock(m_RecvQueue);
|
||||
|
||||
if (m_RecvQueue->GetAvailableBytes() == 0)
|
||||
CheckException();
|
||||
@ -401,11 +409,15 @@ size_t Socket::Read(void *buffer, size_t size)
|
||||
*/
|
||||
size_t Socket::Peek(void *buffer, size_t size)
|
||||
{
|
||||
if (m_Listening)
|
||||
throw new logic_error("Socket does not support Peek().");
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_Listening)
|
||||
throw new logic_error("Socket does not support Peek().");
|
||||
}
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||
ObjectLock olock(m_RecvQueue);
|
||||
|
||||
if (m_RecvQueue->GetAvailableBytes() == 0)
|
||||
CheckException();
|
||||
@ -422,14 +434,14 @@ size_t Socket::Peek(void *buffer, size_t size)
|
||||
*/
|
||||
void Socket::Write(const void *buffer, size_t size)
|
||||
{
|
||||
if (m_Listening)
|
||||
throw new logic_error("Socket does not support Write().");
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_SendQueue->Write(buffer, size);
|
||||
if (m_Listening)
|
||||
throw new logic_error("Socket does not support Write().");
|
||||
}
|
||||
|
||||
m_SendQueue->Write(buffer, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -437,6 +449,8 @@ void Socket::Write(const void *buffer, size_t size)
|
||||
*/
|
||||
void Socket::Listen(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (listen(GetFD(), SOMAXCONN) < 0)
|
||||
BOOST_THROW_EXCEPTION(SocketException("listen() failed", GetError()));
|
||||
|
||||
@ -472,29 +486,17 @@ void Socket::HandleWritableClient(void)
|
||||
SetConnected(true);
|
||||
|
||||
for (;;) {
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||
count = m_SendQueue->Peek(data, sizeof(data));
|
||||
|
||||
count = m_SendQueue->GetAvailableBytes();
|
||||
|
||||
if (count == 0)
|
||||
break;
|
||||
|
||||
if (count > sizeof(data))
|
||||
count = sizeof(data);
|
||||
|
||||
m_SendQueue->Peek(data, count);
|
||||
}
|
||||
if (count == 0)
|
||||
break;
|
||||
|
||||
rc = send(GetFD(), data, count, 0);
|
||||
|
||||
if (rc <= 0)
|
||||
BOOST_THROW_EXCEPTION(SocketException("send() failed", GetError()));
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||
m_SendQueue->Read(NULL, rc);
|
||||
}
|
||||
m_SendQueue->Read(NULL, rc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -522,11 +524,7 @@ void Socket::HandleReadableClient(void)
|
||||
if (rc <= 0)
|
||||
BOOST_THROW_EXCEPTION(SocketException("recv() failed", GetError()));
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||
|
||||
m_RecvQueue->Write(data, rc);
|
||||
}
|
||||
m_RecvQueue->Write(data, rc);
|
||||
|
||||
new_data = true;
|
||||
}
|
||||
@ -603,12 +601,8 @@ bool Socket::WantsToReadClient(void) const
|
||||
*/
|
||||
bool Socket::WantsToWriteClient(void) const
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_QueueMutex);
|
||||
|
||||
if (m_SendQueue->GetAvailableBytes() > 0)
|
||||
return true;
|
||||
}
|
||||
if (m_SendQueue->GetAvailableBytes() > 0)
|
||||
return true;
|
||||
|
||||
return (!IsConnected());
|
||||
}
|
||||
|
@ -83,7 +83,6 @@ private:
|
||||
|
||||
static String GetAddressFromSockaddr(sockaddr *address, socklen_t len);
|
||||
|
||||
mutable boost::mutex m_QueueMutex;
|
||||
FIFO::Ptr m_SendQueue;
|
||||
FIFO::Ptr m_RecvQueue;
|
||||
|
||||
@ -105,8 +104,6 @@ private:
|
||||
|
||||
bool WantsToWrite(void) const;
|
||||
bool WantsToRead(void) const;
|
||||
|
||||
void CloseUnlocked(void);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -43,13 +43,21 @@ StdioStream::~StdioStream(void)
|
||||
m_ReadAheadBuffer->Close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void StdioStream::Start(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
SetConnected(true);
|
||||
|
||||
Stream::Start();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
size_t StdioStream::GetAvailableBytes(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
@ -60,6 +68,9 @@ size_t StdioStream::GetAvailableBytes(void) const
|
||||
return 1024; /* doesn't have to be accurate */
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
size_t StdioStream::Read(void *buffer, size_t size)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
@ -75,6 +86,9 @@ size_t StdioStream::Read(void *buffer, size_t size)
|
||||
return peek_len + read_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
size_t StdioStream::Peek(void *buffer, size_t size)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
@ -91,6 +105,9 @@ size_t StdioStream::Peek(void *buffer, size_t size)
|
||||
return peek_len + read_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void StdioStream::Write(const void *buffer, size_t size)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
@ -98,6 +115,9 @@ void StdioStream::Write(const void *buffer, size_t size)
|
||||
m_InnerStream->write(static_cast<const char *>(buffer), size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void StdioStream::Close(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
@ -30,48 +30,81 @@ Stream::~Stream(void)
|
||||
assert(!m_Running);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
bool Stream::IsConnected(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Connected;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Stream::SetConnected(bool connected)
|
||||
{
|
||||
m_Connected = connected;
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
m_Connected = connected;
|
||||
}
|
||||
|
||||
if (m_Connected)
|
||||
if (connected)
|
||||
OnConnected(GetSelf());
|
||||
else
|
||||
OnClosed(GetSelf());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether an exception is available for this socket and re-throws
|
||||
* Checks whether an exception is available for this stream and re-throws
|
||||
* the exception if there is one.
|
||||
*
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Stream::CheckException(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_Exception)
|
||||
rethrow_exception(m_Exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Stream::SetException(boost::exception_ptr exception)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_Exception = exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
boost::exception_ptr Stream::GetException(void)
|
||||
{
|
||||
return m_Exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Stream::Start(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_Running = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Stream::Close(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
assert(m_Running);
|
||||
m_Running = false;
|
||||
|
||||
|
@ -49,11 +49,17 @@ typedef struct I2Stream_bio_s
|
||||
boost::exception_ptr Exception;
|
||||
} I2Stream_bio_t;
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
BIO_METHOD *BIO_s_I2Stream(void)
|
||||
{
|
||||
return &I2Stream_method;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
BIO *icinga::BIO_new_I2Stream(const Stream::Ptr& stream)
|
||||
{
|
||||
BIO *bi = BIO_new(BIO_s_I2Stream());
|
||||
@ -68,6 +74,9 @@ BIO *icinga::BIO_new_I2Stream(const Stream::Ptr& stream)
|
||||
return bi;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void icinga::I2Stream_check_exception(BIO *bi) {
|
||||
I2Stream_bio_t *bp = (I2Stream_bio_t *)bi->ptr;
|
||||
|
||||
@ -78,6 +87,9 @@ void icinga::I2Stream_check_exception(BIO *bi) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
static int I2Stream_new(BIO *bi)
|
||||
{
|
||||
bi->shutdown = 0;
|
||||
@ -88,6 +100,9 @@ static int I2Stream_new(BIO *bi)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
static int I2Stream_free(BIO *bi)
|
||||
{
|
||||
I2Stream_bio_t *bp = (I2Stream_bio_t *)bi->ptr;
|
||||
@ -96,6 +111,9 @@ static int I2Stream_free(BIO *bi)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
static int I2Stream_read(BIO *bi, char *out, int outl)
|
||||
{
|
||||
I2Stream_bio_t *bp = (I2Stream_bio_t *)bi->ptr;
|
||||
@ -119,6 +137,9 @@ static int I2Stream_read(BIO *bi, char *out, int outl)
|
||||
return data_read;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
static int I2Stream_write(BIO *bi, const char *in, int inl)
|
||||
{
|
||||
I2Stream_bio_t *bp = (I2Stream_bio_t *)bi->ptr;
|
||||
@ -127,6 +148,9 @@ static int I2Stream_write(BIO *bi, const char *in, int inl)
|
||||
return inl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
static long I2Stream_ctrl(BIO *, int cmd, long, void *)
|
||||
{
|
||||
switch (cmd) {
|
||||
|
@ -48,6 +48,9 @@ StreamLogger::~StreamLogger(void)
|
||||
delete m_Stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void StreamLogger::OpenFile(const String& filename)
|
||||
{
|
||||
ofstream *stream = new ofstream();
|
||||
@ -62,6 +65,8 @@ void StreamLogger::OpenFile(const String& filename)
|
||||
throw;
|
||||
}
|
||||
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_Stream = stream;
|
||||
m_OwnsStream = true;
|
||||
m_Tty = false;
|
||||
@ -73,6 +78,7 @@ void StreamLogger::OpenFile(const String& filename)
|
||||
* @param stream The output stream.
|
||||
* @param tty Whether the output stream is a TTY.
|
||||
* @param entry The log entry.
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void StreamLogger::ProcessLogEntry(ostream& stream, bool tty, const LogEntry& entry)
|
||||
{
|
||||
@ -107,12 +113,18 @@ void StreamLogger::ProcessLogEntry(ostream& stream, bool tty, const LogEntry& en
|
||||
* Processes a log entry and outputs it to a stream.
|
||||
*
|
||||
* @param entry The log entry.
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void StreamLogger::ProcessLogEntry(const LogEntry& entry)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
ProcessLogEntry(*m_Stream, m_Tty, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
bool StreamLogger::IsTty(ostream& stream)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
|
@ -26,6 +26,7 @@ using namespace icinga;
|
||||
* Processes a log entry and outputs it to syslog.
|
||||
*
|
||||
* @param entry The log entry.
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void SyslogLogger::ProcessLogEntry(const LogEntry& entry)
|
||||
{
|
||||
|
@ -38,6 +38,7 @@ void TcpSocket::Bind(String service, int family)
|
||||
* @param node The node.
|
||||
* @param service The service.
|
||||
* @param family The address family for the socket.
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void TcpSocket::Bind(String node, String service, int family)
|
||||
{
|
||||
@ -99,6 +100,7 @@ void TcpSocket::Bind(String node, String service, int family)
|
||||
*
|
||||
* @param node The node.
|
||||
* @param service The service.
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void TcpSocket::Connect(const String& node, const String& service)
|
||||
{
|
||||
|
@ -42,6 +42,8 @@ TlsStream::TlsStream(const Stream::Ptr& innerStream, TlsRole role, shared_ptr<SS
|
||||
|
||||
void TlsStream::Start(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_SSL = shared_ptr<SSL>(SSL_new(m_SSLContext.get()), SSL_free);
|
||||
|
||||
m_SSLContext.reset();
|
||||
@ -88,6 +90,8 @@ void TlsStream::Start(void)
|
||||
*/
|
||||
shared_ptr<X509> TlsStream::GetClientCertificate(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return shared_ptr<X509>(SSL_get_certificate(m_SSL.get()), &Utility::NullDeleter);
|
||||
}
|
||||
|
||||
@ -98,6 +102,8 @@ shared_ptr<X509> TlsStream::GetClientCertificate(void) const
|
||||
*/
|
||||
shared_ptr<X509> TlsStream::GetPeerCertificate(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return shared_ptr<X509>(SSL_get_peer_certificate(m_SSL.get()), X509_free);
|
||||
}
|
||||
|
||||
@ -114,6 +120,8 @@ void TlsStream::DataAvailableHandler(void)
|
||||
|
||||
void TlsStream::ClosedHandler(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
SetException(m_InnerStream->GetException());
|
||||
Close();
|
||||
}
|
||||
@ -123,6 +131,9 @@ void TlsStream::ClosedHandler(void)
|
||||
*/
|
||||
void TlsStream::HandleIO(void)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
ObjectLock olock(this);
|
||||
|
||||
char data[16 * 1024];
|
||||
int rc;
|
||||
|
||||
@ -172,8 +183,11 @@ void TlsStream::HandleIO(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (new_data)
|
||||
if (new_data) {
|
||||
olock.Unlock();
|
||||
OnDataAvailable(GetSelf());
|
||||
olock.Lock();
|
||||
}
|
||||
|
||||
while (m_SendQueue->GetAvailableBytes() > 0) {
|
||||
size_t count = m_SendQueue->GetAvailableBytes();
|
||||
@ -212,6 +226,8 @@ void TlsStream::HandleIO(void)
|
||||
*/
|
||||
void TlsStream::Close(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_SSL)
|
||||
SSL_shutdown(m_SSL.get());
|
||||
|
||||
@ -223,22 +239,32 @@ void TlsStream::Close(void)
|
||||
|
||||
size_t TlsStream::GetAvailableBytes(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_RecvQueue->GetAvailableBytes();
|
||||
}
|
||||
|
||||
size_t TlsStream::Peek(void *buffer, size_t count)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_RecvQueue->Peek(buffer, count);
|
||||
}
|
||||
|
||||
size_t TlsStream::Read(void *buffer, size_t count)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_RecvQueue->Read(buffer, count);
|
||||
}
|
||||
|
||||
void TlsStream::Write(const void *buffer, size_t count)
|
||||
{
|
||||
m_SendQueue->Write(buffer, count);
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_SendQueue->Write(buffer, count);
|
||||
}
|
||||
|
||||
HandleIO();
|
||||
}
|
||||
|
@ -137,6 +137,6 @@ void ConfigCompilerContext::ActivateItems(void)
|
||||
|
||||
Logger::Write(LogInformation, "config", "Activating config items in compilation unit '" + m_Unit + "'");
|
||||
BOOST_FOREACH(const ConfigItem::Ptr& item, m_Items) {
|
||||
ConfigItem::Commit(item);
|
||||
item->Commit();
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,8 @@ ConfigItem::ConfigItem(const String& type, const String& name,
|
||||
*/
|
||||
String ConfigItem::GetType(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Type;
|
||||
}
|
||||
|
||||
@ -60,6 +62,8 @@ String ConfigItem::GetType(void) const
|
||||
*/
|
||||
String ConfigItem::GetName(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Name;
|
||||
}
|
||||
|
||||
@ -70,6 +74,8 @@ String ConfigItem::GetName(void) const
|
||||
*/
|
||||
String ConfigItem::GetUnit(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Unit;
|
||||
}
|
||||
|
||||
@ -80,6 +86,8 @@ String ConfigItem::GetUnit(void) const
|
||||
*/
|
||||
DebugInfo ConfigItem::GetDebugInfo(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_DebugInfo;
|
||||
}
|
||||
|
||||
@ -90,6 +98,8 @@ DebugInfo ConfigItem::GetDebugInfo(void) const
|
||||
*/
|
||||
ExpressionList::Ptr ConfigItem::GetExpressionList(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_ExpressionList;
|
||||
}
|
||||
|
||||
@ -100,11 +110,15 @@ ExpressionList::Ptr ConfigItem::GetExpressionList(void) const
|
||||
*/
|
||||
vector<String> ConfigItem::GetParents(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Parents;
|
||||
}
|
||||
|
||||
set<ConfigItem::WeakPtr> ConfigItem::GetChildren(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_ChildObjects;
|
||||
}
|
||||
|
||||
@ -124,6 +138,8 @@ Dictionary::Ptr ConfigItem::Link(void) const
|
||||
*/
|
||||
void ConfigItem::InternalLink(const Dictionary::Ptr& dictionary) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
BOOST_FOREACH(const String& name, m_Parents) {
|
||||
ConfigItem::Ptr parent;
|
||||
|
||||
@ -157,66 +173,67 @@ void ConfigItem::InternalLink(const Dictionary::Ptr& dictionary) const
|
||||
*
|
||||
* @returns The DynamicObject that was created/updated.
|
||||
*/
|
||||
DynamicObject::Ptr ConfigItem::Commit(const ConfigItem::Ptr& self)
|
||||
DynamicObject::Ptr ConfigItem::Commit(void)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
String type, name;
|
||||
DynamicObject::Ptr dobj;
|
||||
vector<String> parents;
|
||||
Dictionary::Ptr properties;
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
type = self->GetType();
|
||||
name = self->GetName();
|
||||
dobj = self->GetDynamicObject();
|
||||
parents = self->GetParents();
|
||||
properties = self->Link();
|
||||
}
|
||||
|
||||
Logger::Write(LogDebug, "base", "Commit called for ConfigItem Type=" + type + ", Name=" + name);
|
||||
Logger::Write(LogDebug, "base", "Commit called for ConfigItem Type=" + GetType() + ", Name=" + GetName());
|
||||
|
||||
/* Make sure the type is valid. */
|
||||
DynamicType::Ptr dtype = DynamicType::GetByName(type);
|
||||
DynamicType::Ptr dtype = DynamicType::GetByName(GetType());
|
||||
|
||||
if (!dtype)
|
||||
BOOST_THROW_EXCEPTION(runtime_error("Type '" + type + "' does not exist."));
|
||||
BOOST_THROW_EXCEPTION(runtime_error("Type '" + GetType() + "' does not exist."));
|
||||
|
||||
/* Try to find an existing item with the same type and name. */
|
||||
pair<String, String> ikey = make_pair(GetType(), GetName());
|
||||
ConfigItem::Ptr oldItem;
|
||||
|
||||
{
|
||||
recursive_mutex::scoped_lock lock(m_Mutex);
|
||||
|
||||
/* Try to find an existing item with the same type and name. */
|
||||
pair<String, String> ikey = make_pair(type, name);
|
||||
ItemMap::iterator it = m_Items.find(ikey);
|
||||
|
||||
set<ConfigItem::WeakPtr> children;
|
||||
|
||||
if (it != m_Items.end()) {
|
||||
/* Unregister the old item from its parents. */
|
||||
ConfigItem::Ptr oldItem = it->second;
|
||||
ObjectLock olock(oldItem);
|
||||
oldItem->UnregisterFromParents();
|
||||
|
||||
/* Steal the old item's children. */
|
||||
children = oldItem->GetChildren();
|
||||
}
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
self->m_ChildObjects = children;
|
||||
}
|
||||
|
||||
/* Register this item. */
|
||||
m_Items[ikey] = self;
|
||||
if (it != m_Items.end())
|
||||
oldItem = it->second;
|
||||
}
|
||||
|
||||
set<ConfigItem::WeakPtr> children;
|
||||
|
||||
if (oldItem) {
|
||||
ObjectLock olock(oldItem);
|
||||
|
||||
/* Unregister the old item from its parents. */
|
||||
oldItem->UnregisterFromParents();
|
||||
|
||||
/* Steal the old item's children. */
|
||||
children = oldItem->GetChildren();
|
||||
}
|
||||
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
m_ChildObjects = children;
|
||||
}
|
||||
|
||||
{
|
||||
recursive_mutex::scoped_lock lock(m_Mutex);
|
||||
|
||||
/* Register this item. */
|
||||
m_Items[ikey] = GetSelf();
|
||||
}
|
||||
|
||||
DynamicObject::Ptr dobj = GetDynamicObject();
|
||||
|
||||
if (!dobj)
|
||||
dobj = dtype->GetObject(name);
|
||||
dobj = dtype->GetObject(GetName());
|
||||
|
||||
/* Register this item with its parents. */
|
||||
BOOST_FOREACH(const String& parentName, parents) {
|
||||
ConfigItem::Ptr parent = GetObject(type, parentName);
|
||||
BOOST_FOREACH(const String& parentName, GetParents()) {
|
||||
ConfigItem::Ptr parent = GetObject(GetType(), parentName);
|
||||
ObjectLock olock(parent);
|
||||
parent->RegisterChild(self);
|
||||
parent->RegisterChild(GetSelf());
|
||||
}
|
||||
|
||||
/* Create a fake update in the format that
|
||||
@ -225,6 +242,8 @@ DynamicObject::Ptr ConfigItem::Commit(const ConfigItem::Ptr& self)
|
||||
|
||||
double tx = DynamicObject::GetCurrentTx();
|
||||
|
||||
Dictionary::Ptr properties = Link();
|
||||
|
||||
{
|
||||
ObjectLock olock(properties);
|
||||
|
||||
@ -256,29 +275,20 @@ DynamicObject::Ptr ConfigItem::Commit(const ConfigItem::Ptr& self)
|
||||
was_null = true;
|
||||
}
|
||||
|
||||
{
|
||||
ObjectLock olock(dobj);
|
||||
|
||||
if (!was_null)
|
||||
dobj->ApplyUpdate(update, Attribute_Config);
|
||||
|
||||
self->m_DynamicObject = dobj;
|
||||
|
||||
if (dobj->IsAbstract())
|
||||
dobj->Unregister();
|
||||
else
|
||||
dobj->Register();
|
||||
}
|
||||
|
||||
/* We need to make a copy of the child objects because the
|
||||
* OnParentCommitted() handler is going to update the list. */
|
||||
set<ConfigItem::WeakPtr> children;
|
||||
if (!was_null)
|
||||
dobj->ApplyUpdate(update, Attribute_Config);
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
children = self->m_ChildObjects;
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_DynamicObject = dobj;
|
||||
}
|
||||
|
||||
if (dobj->IsAbstract())
|
||||
dobj->Unregister();
|
||||
else
|
||||
dobj->Register();
|
||||
|
||||
/* notify our children of the update */
|
||||
BOOST_FOREACH(const ConfigItem::WeakPtr wchild, children) {
|
||||
const ConfigItem::Ptr& child = wchild.lock();
|
||||
@ -289,7 +299,7 @@ DynamicObject::Ptr ConfigItem::Commit(const ConfigItem::Ptr& self)
|
||||
child->OnParentCommitted();
|
||||
}
|
||||
|
||||
OnCommitted(self);
|
||||
OnCommitted(GetSelf());
|
||||
|
||||
return dobj;
|
||||
}
|
||||
@ -299,19 +309,23 @@ DynamicObject::Ptr ConfigItem::Commit(const ConfigItem::Ptr& self)
|
||||
*/
|
||||
void ConfigItem::Unregister(void)
|
||||
{
|
||||
DynamicObject::Ptr dobj = m_DynamicObject.lock();
|
||||
assert(!OwnsLock());
|
||||
|
||||
if (dobj) {
|
||||
ObjectLock olock(dobj);
|
||||
DynamicObject::Ptr dobj = GetDynamicObject();
|
||||
|
||||
if (dobj)
|
||||
dobj->Unregister();
|
||||
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
ConfigItem::ItemMap::iterator it;
|
||||
it = m_Items.find(make_pair(GetType(), GetName()));
|
||||
|
||||
if (it != m_Items.end())
|
||||
m_Items.erase(it);
|
||||
}
|
||||
|
||||
ConfigItem::ItemMap::iterator it;
|
||||
it = m_Items.find(make_pair(GetType(), GetName()));
|
||||
|
||||
if (it != m_Items.end())
|
||||
m_Items.erase(it);
|
||||
|
||||
UnregisterFromParents();
|
||||
|
||||
OnRemoved(GetSelf());
|
||||
@ -319,23 +333,27 @@ void ConfigItem::Unregister(void)
|
||||
|
||||
void ConfigItem::RegisterChild(const ConfigItem::Ptr& child)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_ChildObjects.insert(child);
|
||||
}
|
||||
|
||||
void ConfigItem::UnregisterChild(const ConfigItem::Ptr& child)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_ChildObjects.erase(child);
|
||||
}
|
||||
|
||||
void ConfigItem::UnregisterFromParents(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
BOOST_FOREACH(const String& parentName, m_Parents) {
|
||||
ConfigItem::Ptr parent = GetObject(GetType(), parentName);
|
||||
|
||||
if (parent) {
|
||||
ObjectLock olock(parent);
|
||||
if (parent)
|
||||
parent->UnregisterChild(GetSelf());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -344,6 +362,8 @@ void ConfigItem::UnregisterFromParents(void)
|
||||
*/
|
||||
void ConfigItem::OnParentCommitted(void)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
ConfigItem::Ptr self;
|
||||
|
||||
{
|
||||
@ -354,7 +374,7 @@ void ConfigItem::OnParentCommitted(void)
|
||||
return;
|
||||
}
|
||||
|
||||
Commit(self);
|
||||
Commit();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -364,6 +384,8 @@ void ConfigItem::OnParentCommitted(void)
|
||||
*/
|
||||
DynamicObject::Ptr ConfigItem::GetDynamicObject(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_DynamicObject.lock();
|
||||
}
|
||||
|
||||
@ -397,6 +419,8 @@ ConfigItem::Ptr ConfigItem::GetObject(const String& type, const String& name)
|
||||
*/
|
||||
void ConfigItem::Dump(ostream& fp) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
fp << "object \"" << m_Type << "\" \"" << m_Name << "\"";
|
||||
|
||||
if (m_Parents.size() > 0) {
|
||||
@ -440,7 +464,6 @@ void ConfigItem::UnloadUnit(const String& unit)
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const ConfigItem::Ptr& item, obsoleteItems) {
|
||||
ObjectLock olock(item);
|
||||
item->Unregister();
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
|
||||
ExpressionList::Ptr GetExpressionList(void) const;
|
||||
|
||||
static DynamicObject::Ptr Commit(const ConfigItem::Ptr& self);
|
||||
DynamicObject::Ptr Commit(void);
|
||||
void Unregister(void);
|
||||
|
||||
void Dump(ostream& fp) const;
|
||||
|
@ -35,8 +35,5 @@ void API::GetAnswerToEverything(const ScriptTask::Ptr& task, const vector<Value>
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Hello from the Icinga 2 API: " + text);
|
||||
|
||||
{
|
||||
ObjectLock olock(task);
|
||||
task->FinishResult(42);
|
||||
}
|
||||
task->FinishResult(42);
|
||||
}
|
||||
|
@ -44,4 +44,3 @@ void CheckResultMessage::SetCheckResult(const Dictionary::Ptr& result)
|
||||
{
|
||||
Set("check_result", result);
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,7 @@ void ExternalCommandProcessor::ProcessHostCheckResult(double time, const vector<
|
||||
|
||||
Host::Ptr host = Host::GetByName(arguments[0]);
|
||||
|
||||
Service::Ptr hc = Host::GetHostCheckService(host);
|
||||
Service::Ptr hc = host->GetHostCheckService();
|
||||
|
||||
if (!hc->GetEnablePassiveChecks())
|
||||
BOOST_THROW_EXCEPTION(invalid_argument("Got passive check result for host '" + arguments[0] + "' which has passive checks disabled."));
|
||||
@ -222,7 +222,7 @@ void ExternalCommandProcessor::ScheduleHostCheck(double, const vector<String>& a
|
||||
|
||||
Host::Ptr host = Host::GetByName(arguments[0]);
|
||||
|
||||
Service::Ptr hc = Host::GetHostCheckService(host);
|
||||
Service::Ptr hc = host->GetHostCheckService();
|
||||
|
||||
double planned_check = Convert::ToDouble(arguments[1]);
|
||||
|
||||
@ -243,7 +243,7 @@ void ExternalCommandProcessor::ScheduleForcedHostCheck(double, const vector<Stri
|
||||
|
||||
Host::Ptr host = Host::GetByName(arguments[0]);
|
||||
|
||||
Service::Ptr hc = Host::GetHostCheckService(host);
|
||||
Service::Ptr hc = host->GetHostCheckService();
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Rescheduling next check for host '" + arguments[0] + "'");
|
||||
hc->SetForceNextCheck(true);
|
||||
@ -289,7 +289,7 @@ void ExternalCommandProcessor::EnableHostCheck(double, const vector<String>& arg
|
||||
Host::Ptr host = Host::GetByName(arguments[0]);
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Enabling active checks for host '" + arguments[0] + "'");
|
||||
Service::Ptr hc = Host::GetHostCheckService(host);
|
||||
Service::Ptr hc = host->GetHostCheckService();
|
||||
|
||||
if (hc)
|
||||
hc->SetEnableActiveChecks(true);
|
||||
@ -303,7 +303,7 @@ void ExternalCommandProcessor::DisableHostCheck(double, const vector<String>& ar
|
||||
Host::Ptr host = Host::GetByName(arguments[0]);
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Disabling active checks for host '" + arguments[0] + "'");
|
||||
Service::Ptr hc = Host::GetHostCheckService(host);
|
||||
Service::Ptr hc = host->GetHostCheckService();
|
||||
|
||||
if (hc)
|
||||
hc->SetEnableActiveChecks(false);
|
||||
@ -454,7 +454,7 @@ void ExternalCommandProcessor::AcknowledgeHostProblem(double, const vector<Strin
|
||||
Host::Ptr host = Host::GetByName(arguments[0]);
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Setting acknowledgement for host '" + host->GetName() + "'");
|
||||
Service::Ptr service = Host::GetHostCheckService(host);
|
||||
Service::Ptr service = host->GetHostCheckService();
|
||||
if (service) {
|
||||
if (service->GetState() == StateOK)
|
||||
BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' is OK."));
|
||||
@ -474,7 +474,7 @@ void ExternalCommandProcessor::AcknowledgeHostProblemExpire(double, const vector
|
||||
Host::Ptr host = Host::GetByName(arguments[0]);
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Setting timed acknowledgement for host '" + host->GetName() + "'");
|
||||
Service::Ptr service = Host::GetHostCheckService(host);
|
||||
Service::Ptr service = host->GetHostCheckService();
|
||||
if (service) {
|
||||
if (service->GetState() == StateOK)
|
||||
BOOST_THROW_EXCEPTION(invalid_argument("The host '" + arguments[0] + "' is OK."));
|
||||
@ -491,7 +491,7 @@ void ExternalCommandProcessor::RemoveHostAcknowledgement(double, const vector<St
|
||||
Host::Ptr host = Host::GetByName(arguments[0]);
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Removing acknowledgement for host '" + host->GetName() + "'");
|
||||
Service::Ptr service = Host::GetHostCheckService(host);
|
||||
Service::Ptr service = host->GetHostCheckService();
|
||||
if (service) {
|
||||
service->ClearAcknowledgement();
|
||||
}
|
||||
@ -504,7 +504,7 @@ void ExternalCommandProcessor::EnableHostgroupSvcChecks(double, const vector<Str
|
||||
|
||||
HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
|
||||
|
||||
BOOST_FOREACH(const Host::Ptr& host, HostGroup::GetMembers(hg)) {
|
||||
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);
|
||||
@ -519,7 +519,7 @@ void ExternalCommandProcessor::DisableHostgroupSvcChecks(double, const vector<St
|
||||
|
||||
HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
|
||||
|
||||
BOOST_FOREACH(const Host::Ptr& host, HostGroup::GetMembers(hg)) {
|
||||
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);
|
||||
@ -534,7 +534,7 @@ void ExternalCommandProcessor::EnableServicegroupSvcChecks(double, const vector<
|
||||
|
||||
ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
|
||||
|
||||
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
|
||||
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
|
||||
Logger::Write(LogInformation, "icinga", "Enabling active checks for service '" + service->GetName() + "'");
|
||||
service->SetEnableActiveChecks(true);
|
||||
}
|
||||
@ -547,7 +547,7 @@ void ExternalCommandProcessor::DisableServicegroupSvcChecks(double, const vector
|
||||
|
||||
ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
|
||||
|
||||
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
|
||||
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
|
||||
Logger::Write(LogInformation, "icinga", "Disabling active checks for service '" + service->GetName() + "'");
|
||||
service->SetEnableActiveChecks(false);
|
||||
}
|
||||
@ -561,7 +561,7 @@ void ExternalCommandProcessor::EnablePassiveHostChecks(double, const vector<Stri
|
||||
Host::Ptr host = Host::GetByName(arguments[0]);
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Enabling passive checks for host '" + arguments[0] + "'");
|
||||
Service::Ptr hc = Host::GetHostCheckService(host);
|
||||
Service::Ptr hc = host->GetHostCheckService();
|
||||
|
||||
if (hc)
|
||||
hc->SetEnablePassiveChecks(true);
|
||||
@ -575,7 +575,7 @@ void ExternalCommandProcessor::DisablePassiveHostChecks(double, const vector<Str
|
||||
Host::Ptr host = Host::GetByName(arguments[0]);
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Disabling passive checks for host '" + arguments[0] + "'");
|
||||
Service::Ptr hc = Host::GetHostCheckService(host);
|
||||
Service::Ptr hc = host->GetHostCheckService();
|
||||
|
||||
if (hc)
|
||||
hc->SetEnablePassiveChecks(false);
|
||||
@ -610,7 +610,7 @@ void ExternalCommandProcessor::EnableServicegroupPassiveSvcChecks(double, const
|
||||
|
||||
ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
|
||||
|
||||
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
|
||||
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
|
||||
Logger::Write(LogInformation, "icinga", "Enabling passive checks for service '" + service->GetName() + "'");
|
||||
service->SetEnablePassiveChecks(true);
|
||||
}
|
||||
@ -623,7 +623,7 @@ void ExternalCommandProcessor::DisableServicegroupPassiveSvcChecks(double, const
|
||||
|
||||
ServiceGroup::Ptr sg = ServiceGroup::GetByName(arguments[0]);
|
||||
|
||||
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
|
||||
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
|
||||
Logger::Write(LogInformation, "icinga", "Disabling passive checks for service '" + service->GetName() + "'");
|
||||
service->SetEnablePassiveChecks(true);
|
||||
}
|
||||
@ -636,7 +636,7 @@ void ExternalCommandProcessor::EnableHostgroupPassiveSvcChecks(double, const vec
|
||||
|
||||
HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
|
||||
|
||||
BOOST_FOREACH(const Host::Ptr& host, HostGroup::GetMembers(hg)) {
|
||||
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);
|
||||
@ -651,7 +651,7 @@ void ExternalCommandProcessor::DisableHostgroupPassiveSvcChecks(double, const ve
|
||||
|
||||
HostGroup::Ptr hg = HostGroup::GetByName(arguments[0]);
|
||||
|
||||
BOOST_FOREACH(const Host::Ptr& host, HostGroup::GetMembers(hg)) {
|
||||
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);
|
||||
@ -735,7 +735,7 @@ void ExternalCommandProcessor::ScheduleHostDowntime(double, const vector<String>
|
||||
triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Creating downtime for host " + host->GetName());
|
||||
Service::Ptr service = Host::GetHostCheckService(host);
|
||||
Service::Ptr service = host->GetHostCheckService();
|
||||
if (service) {
|
||||
(void) service->AddDowntime(arguments[6], arguments[7],
|
||||
Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
|
||||
@ -786,9 +786,9 @@ void ExternalCommandProcessor::ScheduleHostgroupHostDowntime(double, const vecto
|
||||
if (triggeredByLegacy != 0)
|
||||
triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
|
||||
|
||||
BOOST_FOREACH(const Host::Ptr& host, HostGroup::GetMembers(hg)) {
|
||||
BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
|
||||
Logger::Write(LogInformation, "icinga", "Creating downtime for host " + host->GetName());
|
||||
Service::Ptr service = Host::GetHostCheckService(host);
|
||||
Service::Ptr service = host->GetHostCheckService();
|
||||
if (service) {
|
||||
(void) service->AddDowntime(arguments[6], arguments[7],
|
||||
Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
|
||||
@ -815,7 +815,7 @@ void ExternalCommandProcessor::ScheduleHostgroupSvcDowntime(double, const vector
|
||||
|
||||
set<Service::Ptr> services;
|
||||
|
||||
BOOST_FOREACH(const Host::Ptr& host, HostGroup::GetMembers(hg)) {
|
||||
BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
|
||||
BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
|
||||
services.insert(service);
|
||||
}
|
||||
@ -847,9 +847,9 @@ void ExternalCommandProcessor::ScheduleServicegroupHostDowntime(double, const ve
|
||||
|
||||
set<Service::Ptr> services;
|
||||
|
||||
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
|
||||
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
|
||||
Host::Ptr host = service->GetHost();
|
||||
Service::Ptr hcService = Host::GetHostCheckService(host);
|
||||
Service::Ptr hcService = host->GetHostCheckService();
|
||||
if (hcService)
|
||||
services.insert(hcService);
|
||||
}
|
||||
@ -874,7 +874,7 @@ void ExternalCommandProcessor::ScheduleServicegroupSvcDowntime(double, const vec
|
||||
if (triggeredByLegacy != 0)
|
||||
triggeredBy = Service::GetDowntimeIDFromLegacyID(triggeredByLegacy);
|
||||
|
||||
BOOST_FOREACH(const Service::Ptr& service, ServiceGroup::GetMembers(sg)) {
|
||||
BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
|
||||
Logger::Write(LogInformation, "icinga", "Creating downtime for service " + service->GetName());
|
||||
(void) service->AddDowntime(arguments[6], arguments[7],
|
||||
Convert::ToDouble(arguments[1]), Convert::ToDouble(arguments[2]),
|
||||
@ -890,7 +890,7 @@ void ExternalCommandProcessor::AddHostComment(double, const vector<String>& argu
|
||||
Host::Ptr host = Host::GetByName(arguments[0]);
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Creating comment for host " + host->GetName());
|
||||
Service::Ptr service = Host::GetHostCheckService(host);
|
||||
Service::Ptr service = host->GetHostCheckService();
|
||||
if (service)
|
||||
(void) service->AddComment(CommentUser, arguments[2], arguments[3], 0);
|
||||
}
|
||||
@ -937,7 +937,7 @@ void ExternalCommandProcessor::DelAllHostComments(double, const vector<String>&
|
||||
Host::Ptr host = Host::GetByName(arguments[0]);
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Removing all comments for host " + host->GetName());
|
||||
Service::Ptr service = Host::GetHostCheckService(host);
|
||||
Service::Ptr service = host->GetHostCheckService();
|
||||
if (service)
|
||||
service->RemoveAllComments();
|
||||
}
|
||||
@ -961,7 +961,7 @@ void ExternalCommandProcessor::SendCustomHostNotification(double time, const vec
|
||||
Host::Ptr host = Host::GetByName(arguments[0]);
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Sending custom notification for host " + host->GetName());
|
||||
Service::Ptr service = Host::GetHostCheckService(host);
|
||||
Service::Ptr service = host->GetHostCheckService();
|
||||
if (service) {
|
||||
service->RequestNotifications(NotificationCustom);
|
||||
}
|
||||
@ -986,7 +986,7 @@ 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(host);
|
||||
Service::Ptr service = host->GetHostCheckService();
|
||||
if (service) {
|
||||
service->SetLastNotification(Convert::ToDouble(arguments[1]));
|
||||
}
|
||||
@ -1011,7 +1011,7 @@ void ExternalCommandProcessor::EnableHostNotifications(double, const vector<Stri
|
||||
Host::Ptr host = Host::GetByName(arguments[0]);
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Enabling notifications for host '" + arguments[0] + "'");
|
||||
Service::Ptr hc = Host::GetHostCheckService(host);
|
||||
Service::Ptr hc = host->GetHostCheckService();
|
||||
|
||||
if (hc)
|
||||
hc->SetEnableNotifications(true);
|
||||
@ -1025,7 +1025,7 @@ void ExternalCommandProcessor::DisableHostNotifications(double, const vector<Str
|
||||
Host::Ptr host = Host::GetByName(arguments[0]);
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Disabling notifications for host '" + arguments[0] + "'");
|
||||
Service::Ptr hc = Host::GetHostCheckService(host);
|
||||
Service::Ptr hc = host->GetHostCheckService();
|
||||
|
||||
if (hc)
|
||||
hc->SetEnableNotifications(false);
|
||||
|
@ -55,14 +55,18 @@ Host::~Host(void)
|
||||
|
||||
void Host::OnRegistrationCompleted(void)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
DynamicObject::OnRegistrationCompleted();
|
||||
|
||||
Host::InvalidateServicesCache();
|
||||
Host::UpdateSlaveServices(GetSelf());
|
||||
UpdateSlaveServices();
|
||||
}
|
||||
|
||||
String Host::GetDisplayName(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (!m_DisplayName.IsEmpty())
|
||||
return m_DisplayName;
|
||||
else
|
||||
@ -81,32 +85,44 @@ Host::Ptr Host::GetByName(const String& name)
|
||||
|
||||
Dictionary::Ptr Host::GetGroups(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_HostGroups;;
|
||||
}
|
||||
|
||||
Dictionary::Ptr Host::GetMacros(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Macros;
|
||||
}
|
||||
|
||||
Dictionary::Ptr Host::GetHostDependencies(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_HostDependencies;;
|
||||
}
|
||||
|
||||
Dictionary::Ptr Host::GetServiceDependencies(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_ServiceDependencies;
|
||||
}
|
||||
|
||||
String Host::GetHostCheck(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_HostCheck;
|
||||
}
|
||||
|
||||
bool Host::IsReachable(const Host::Ptr& self)
|
||||
bool Host::IsReachable(void) const
|
||||
{
|
||||
set<Service::Ptr> parentServices = Host::GetParentServices(self);
|
||||
assert(!OwnsLock());
|
||||
|
||||
set<Service::Ptr> parentServices = GetParentServices();
|
||||
|
||||
BOOST_FOREACH(const Service::Ptr& service, parentServices) {
|
||||
ObjectLock olock(service);
|
||||
@ -127,14 +143,19 @@ bool Host::IsReachable(const Host::Ptr& self)
|
||||
return false;
|
||||
}
|
||||
|
||||
set<Host::Ptr> parentHosts = Host::GetParentHosts(self);
|
||||
set<Host::Ptr> parentHosts = GetParentHosts();
|
||||
|
||||
BOOST_FOREACH(const Host::Ptr& host, parentHosts) {
|
||||
Service::Ptr hc = Host::GetHostCheckService(host);
|
||||
Service::Ptr hc = GetHostCheckService();
|
||||
|
||||
/* ignore hosts that don't have a hostcheck */
|
||||
if (!hc)
|
||||
continue;
|
||||
|
||||
ObjectLock olock(hc);
|
||||
|
||||
/* ignore hosts that are up */
|
||||
if (hc && hc->GetState() == StateOK)
|
||||
if (hc->GetState() == StateOK)
|
||||
continue;
|
||||
|
||||
return false;
|
||||
@ -190,37 +211,21 @@ static void CopyServiceAttributes(TDict serviceDesc, const ConfigItemBuilder::Pt
|
||||
}
|
||||
}
|
||||
|
||||
void Host::UpdateSlaveServices(const Host::Ptr& self)
|
||||
void Host::UpdateSlaveServices(void)
|
||||
{
|
||||
ConfigItem::Ptr item;
|
||||
Dictionary::Ptr oldServices, newServices, serviceDescs;
|
||||
String host_name;
|
||||
assert(!OwnsLock());
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
ConfigItem::Ptr item = ConfigItem::GetObject("Host", GetName());
|
||||
|
||||
host_name = self->GetName();
|
||||
/* Don't create slave services unless we own this object
|
||||
* and it's not a template. */
|
||||
if (!item || IsAbstract())
|
||||
return;
|
||||
|
||||
item = ConfigItem::GetObject("Host", host_name);
|
||||
Dictionary::Ptr oldServices = m_SlaveServices;
|
||||
Dictionary::Ptr serviceDescs = Get("services");
|
||||
|
||||
/* Don't create slave services unless we own this object
|
||||
* and it's not a template. */
|
||||
if (!item || self->IsAbstract())
|
||||
return;
|
||||
|
||||
oldServices = self->m_SlaveServices;
|
||||
serviceDescs = self->Get("services");
|
||||
}
|
||||
|
||||
newServices = boost::make_shared<Dictionary>();
|
||||
ObjectLock nlock(newServices);
|
||||
|
||||
DebugInfo debug_info;
|
||||
|
||||
{
|
||||
ObjectLock olock(item);
|
||||
debug_info = item->GetDebugInfo();
|
||||
}
|
||||
Dictionary::Ptr newServices = boost::make_shared<Dictionary>();
|
||||
|
||||
if (serviceDescs) {
|
||||
ObjectLock olock(serviceDescs);
|
||||
@ -231,17 +236,17 @@ void Host::UpdateSlaveServices(const Host::Ptr& self)
|
||||
svcname = svcdesc;
|
||||
|
||||
stringstream namebuf;
|
||||
namebuf << host_name << "-" << svcname;
|
||||
namebuf << GetName() << "-" << svcname;
|
||||
String name = namebuf.str();
|
||||
|
||||
ConfigItemBuilder::Ptr builder = boost::make_shared<ConfigItemBuilder>(debug_info);
|
||||
ConfigItemBuilder::Ptr builder = boost::make_shared<ConfigItemBuilder>(item->GetDebugInfo());
|
||||
builder->SetType("Service");
|
||||
builder->SetName(name);
|
||||
builder->AddExpression("host_name", OperatorSet, host_name);
|
||||
builder->AddExpression("host_name", OperatorSet, GetName());
|
||||
builder->AddExpression("display_name", OperatorSet, svcname);
|
||||
builder->AddExpression("short_name", OperatorSet, svcname);
|
||||
|
||||
CopyServiceAttributes<false>(self, builder);
|
||||
CopyServiceAttributes<false>(this, builder);
|
||||
|
||||
if (svcdesc.IsScalar()) {
|
||||
builder->AddParent(svcdesc);
|
||||
@ -272,7 +277,7 @@ void Host::UpdateSlaveServices(const Host::Ptr& self)
|
||||
}
|
||||
|
||||
ConfigItem::Ptr serviceItem = builder->Compile();
|
||||
DynamicObject::Ptr dobj = ConfigItem::Commit(serviceItem);
|
||||
DynamicObject::Ptr dobj = serviceItem->Commit();
|
||||
|
||||
newServices->Set(name, serviceItem);
|
||||
}
|
||||
@ -293,23 +298,18 @@ void Host::UpdateSlaveServices(const Host::Ptr& self)
|
||||
|
||||
newServices->Seal();
|
||||
|
||||
ObjectLock olock(self);
|
||||
self->Set("slave_services", newServices);
|
||||
ObjectLock olock(this);
|
||||
Set("slave_services", newServices);
|
||||
}
|
||||
|
||||
void Host::OnAttributeChanged(const String& name, const Value&)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
if (name == "hostgroups")
|
||||
HostGroup::InvalidateMembersCache();
|
||||
else if (name == "services") {
|
||||
Host::Ptr self;
|
||||
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
self = GetSelf();
|
||||
}
|
||||
|
||||
UpdateSlaveServices(self);
|
||||
UpdateSlaveServices();
|
||||
} else if (name == "notifications") {
|
||||
set<Service::Ptr> services;
|
||||
|
||||
@ -450,20 +450,13 @@ void Host::ValidateServiceDictionary(const ScriptTask::Ptr& task, const vector<V
|
||||
task->FinishResult(Empty);
|
||||
}
|
||||
|
||||
Service::Ptr Host::GetServiceByShortName(const Host::Ptr& self, const Value& name)
|
||||
Service::Ptr Host::GetServiceByShortName(const Value& name) const
|
||||
{
|
||||
String host_name;
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
host_name = self->GetName();
|
||||
}
|
||||
|
||||
if (name.IsScalar()) {
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_ServiceMutex);
|
||||
|
||||
map<String, Service::WeakPtr>& services = m_ServicesCache[host_name];
|
||||
map<String, Service::WeakPtr>& services = m_ServicesCache[GetName()];
|
||||
map<String, Service::WeakPtr>::iterator it = services.find(name);
|
||||
|
||||
if (it != services.end()) {
|
||||
@ -478,35 +471,26 @@ Service::Ptr Host::GetServiceByShortName(const Host::Ptr& self, const Value& nam
|
||||
Dictionary::Ptr dict = name;
|
||||
String short_name;
|
||||
|
||||
{
|
||||
ObjectLock olock(dict);
|
||||
host_name = dict->Get("host");
|
||||
short_name = dict->Get("service");
|
||||
}
|
||||
assert(dict->IsSealed());
|
||||
|
||||
return Service::GetByNamePair(host_name, short_name);
|
||||
return Service::GetByNamePair(dict->Get("host"), dict->Get("service"));
|
||||
} else {
|
||||
BOOST_THROW_EXCEPTION(invalid_argument("Host/Service name pair is invalid."));
|
||||
}
|
||||
}
|
||||
|
||||
set<Host::Ptr> Host::GetParentHosts(const Host::Ptr& self)
|
||||
set<Host::Ptr> Host::GetParentHosts(void) const
|
||||
{
|
||||
set<Host::Ptr> parents;
|
||||
|
||||
Dictionary::Ptr dependencies;
|
||||
String host_name;
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
dependencies = self->GetHostDependencies();
|
||||
host_name = self->GetName();
|
||||
}
|
||||
Dictionary::Ptr dependencies = GetHostDependencies();
|
||||
|
||||
if (dependencies) {
|
||||
ObjectLock olock(dependencies);
|
||||
|
||||
Value value;
|
||||
BOOST_FOREACH(tie(tuples::ignore, value), dependencies) {
|
||||
if (value == host_name)
|
||||
if (value == GetName())
|
||||
continue;
|
||||
|
||||
Host::Ptr host = GetByName(value);
|
||||
@ -521,60 +505,52 @@ set<Host::Ptr> Host::GetParentHosts(const Host::Ptr& self)
|
||||
return parents;
|
||||
}
|
||||
|
||||
Service::Ptr Host::GetHostCheckService(const Host::Ptr& self)
|
||||
Service::Ptr Host::GetHostCheckService(void) const
|
||||
{
|
||||
String host_check;
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
host_check = self->GetHostCheck();
|
||||
}
|
||||
String host_check = GetHostCheck();
|
||||
|
||||
if (host_check.IsEmpty())
|
||||
return Service::Ptr();
|
||||
|
||||
return GetServiceByShortName(self, host_check);
|
||||
return GetServiceByShortName(host_check);
|
||||
}
|
||||
|
||||
set<Service::Ptr> Host::GetParentServices(const Host::Ptr& self)
|
||||
set<Service::Ptr> Host::GetParentServices(void) const
|
||||
{
|
||||
set<Service::Ptr> parents;
|
||||
|
||||
Dictionary::Ptr dependencies;
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
dependencies = self->GetServiceDependencies();
|
||||
}
|
||||
Dictionary::Ptr dependencies = GetServiceDependencies();
|
||||
|
||||
if (dependencies) {
|
||||
ObjectLock olock(dependencies);
|
||||
|
||||
Value value;
|
||||
BOOST_FOREACH(tie(tuples::ignore, value), dependencies) {
|
||||
parents.insert(GetServiceByShortName(self, value));
|
||||
parents.insert(GetServiceByShortName(value));
|
||||
}
|
||||
}
|
||||
|
||||
return parents;
|
||||
}
|
||||
|
||||
Dictionary::Ptr Host::CalculateDynamicMacros(const Host::Ptr& self)
|
||||
Dictionary::Ptr Host::CalculateDynamicMacros(void) const
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
Dictionary::Ptr macros = boost::make_shared<Dictionary>();
|
||||
ObjectLock mlock(macros);
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
ObjectLock olock(this);
|
||||
|
||||
macros->Set("HOSTNAME", self->GetName());
|
||||
macros->Set("HOSTDISPLAYNAME", self->GetDisplayName());
|
||||
macros->Set("HOSTALIAS", self->GetName());
|
||||
macros->Set("HOSTNAME", GetName());
|
||||
macros->Set("HOSTDISPLAYNAME", GetDisplayName());
|
||||
macros->Set("HOSTALIAS", GetName());
|
||||
}
|
||||
|
||||
bool reachable = Host::IsReachable(self);
|
||||
|
||||
Dictionary::Ptr cr;
|
||||
|
||||
Service::Ptr hc = Host::GetHostCheckService(self);
|
||||
Service::Ptr hc = GetHostCheckService();
|
||||
|
||||
if (hc) {
|
||||
ObjectLock olock(hc);
|
||||
@ -594,7 +570,7 @@ Dictionary::Ptr Host::CalculateDynamicMacros(const Host::Ptr& self)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!reachable) {
|
||||
if (!IsReachable()) {
|
||||
state = "UNREACHABLE";
|
||||
stateid = 2;
|
||||
}
|
||||
|
@ -49,15 +49,15 @@ public:
|
||||
Dictionary::Ptr GetServiceDependencies(void) const;
|
||||
String GetHostCheck(void) const;
|
||||
|
||||
static Dictionary::Ptr CalculateDynamicMacros(const Host::Ptr& self);
|
||||
Dictionary::Ptr CalculateDynamicMacros(void) const;
|
||||
|
||||
static shared_ptr<Service> GetHostCheckService(const Host::Ptr& self);
|
||||
static set<Host::Ptr> GetParentHosts(const Host::Ptr& self);
|
||||
static set<shared_ptr<Service> > GetParentServices(const Host::Ptr& self);
|
||||
shared_ptr<Service> GetHostCheckService(void) const;
|
||||
set<Host::Ptr> GetParentHosts(void) const;
|
||||
set<shared_ptr<Service> > GetParentServices(void) const;
|
||||
|
||||
static bool IsReachable(const Host::Ptr& self);
|
||||
bool IsReachable() const;
|
||||
|
||||
static shared_ptr<Service> GetServiceByShortName(const Host::Ptr& self, const Value& name);
|
||||
shared_ptr<Service> GetServiceByShortName(const Value& name) const;
|
||||
|
||||
set<shared_ptr<Service> > GetServices(void) const;
|
||||
static void InvalidateServicesCache(void);
|
||||
@ -82,7 +82,7 @@ private:
|
||||
static map<String, map<String, weak_ptr<Service> > > m_ServicesCache;
|
||||
static bool m_ServicesCacheValid;
|
||||
|
||||
static void UpdateSlaveServices(const Host::Ptr& self);
|
||||
void UpdateSlaveServices(void);
|
||||
|
||||
static void RefreshServicesCache(void);
|
||||
};
|
||||
|
@ -40,26 +40,46 @@ HostGroup::~HostGroup(void)
|
||||
InvalidateMembersCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void HostGroup::OnRegistrationCompleted(void)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
InvalidateMembersCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String HostGroup::GetDisplayName(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (!m_DisplayName.IsEmpty())
|
||||
return m_DisplayName;
|
||||
else
|
||||
return GetName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String HostGroup::GetNotesUrl(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_NotesUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String HostGroup::GetActionUrl(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_ActionUrl;
|
||||
}
|
||||
|
||||
@ -76,21 +96,17 @@ HostGroup::Ptr HostGroup::GetByName(const String& name)
|
||||
return dynamic_pointer_cast<HostGroup>(configObject);
|
||||
}
|
||||
|
||||
set<Host::Ptr> HostGroup::GetMembers(const HostGroup::Ptr& self)
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
set<Host::Ptr> HostGroup::GetMembers(void) const
|
||||
{
|
||||
String name;
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
name = self->GetName();
|
||||
}
|
||||
|
||||
set<Host::Ptr> hosts;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
|
||||
BOOST_FOREACH(const Host::WeakPtr& whost, m_MembersCache[name]) {
|
||||
BOOST_FOREACH(const Host::WeakPtr& whost, m_MembersCache[GetName()]) {
|
||||
Host::Ptr host = whost.lock();
|
||||
|
||||
if (!host)
|
||||
@ -103,18 +119,22 @@ set<Host::Ptr> HostGroup::GetMembers(const HostGroup::Ptr& self)
|
||||
return hosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void HostGroup::InvalidateMembersCache(void)
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
|
||||
if (m_MembersCacheValid)
|
||||
Utility::QueueAsyncCallback(boost::bind(&HostGroup::RefreshMembersCache));
|
||||
if (m_MembersCacheValid)
|
||||
Utility::QueueAsyncCallback(boost::bind(&HostGroup::RefreshMembersCache));
|
||||
|
||||
m_MembersCacheValid = false;
|
||||
}
|
||||
m_MembersCacheValid = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void HostGroup::RefreshMembersCache(void)
|
||||
{
|
||||
{
|
||||
|
@ -43,7 +43,7 @@ public:
|
||||
String GetNotesUrl(void) const;
|
||||
String GetActionUrl(void) const;
|
||||
|
||||
static set<Host::Ptr> GetMembers(const HostGroup::Ptr& self);
|
||||
set<Host::Ptr> GetMembers(void) const;
|
||||
|
||||
static void InvalidateMembersCache(void);
|
||||
|
||||
|
@ -85,13 +85,24 @@ int IcingaApplication::Main(void)
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void IcingaApplication::OnShutdown(void)
|
||||
{
|
||||
m_RetentionTimer->Stop();
|
||||
assert(!OwnsLock());
|
||||
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
m_RetentionTimer->Stop();
|
||||
}
|
||||
|
||||
DumpProgramState();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void IcingaApplication::DumpProgramState(void)
|
||||
{
|
||||
DynamicObject::DumpObjects(GetStatePath());
|
||||
@ -102,58 +113,106 @@ IcingaApplication::Ptr IcingaApplication::GetInstance(void)
|
||||
return static_pointer_cast<IcingaApplication>(Application::GetInstance());
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String IcingaApplication::GetCertificateFile(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_CertPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String IcingaApplication::GetCAFile(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_CAPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String IcingaApplication::GetNode(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String IcingaApplication::GetService(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Service;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String IcingaApplication::GetPidPath(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_PidPath.IsEmpty())
|
||||
return Application::GetLocalStateDir() + "/run/icinga2.pid";
|
||||
else
|
||||
return m_PidPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String IcingaApplication::GetStatePath(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_PidPath.IsEmpty())
|
||||
return Application::GetLocalStateDir() + "/lib/icinga2/icinga2.state";
|
||||
else
|
||||
return m_PidPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr IcingaApplication::GetMacros(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Macros;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
double IcingaApplication::GetStartTime(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_StartTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
shared_ptr<SSL_CTX> IcingaApplication::GetSSLContext(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_SSLContext;
|
||||
}
|
||||
|
||||
Dictionary::Ptr IcingaApplication::CalculateDynamicMacros(const IcingaApplication::Ptr& self)
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr IcingaApplication::CalculateDynamicMacros(void)
|
||||
{
|
||||
Dictionary::Ptr macros = boost::make_shared<Dictionary>();
|
||||
ObjectLock mlock(macros);
|
||||
|
@ -51,7 +51,7 @@ public:
|
||||
|
||||
double GetStartTime(void) const;
|
||||
|
||||
static Dictionary::Ptr CalculateDynamicMacros(const IcingaApplication::Ptr& self);
|
||||
static Dictionary::Ptr CalculateDynamicMacros(void);
|
||||
|
||||
private:
|
||||
Attribute<String> m_CertPath;
|
||||
|
@ -21,10 +21,15 @@
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Value MacroProcessor::ResolveMacros(const Value& cmd, const Dictionary::Ptr& macros)
|
||||
{
|
||||
Value result;
|
||||
|
||||
assert(macros->IsSealed());
|
||||
|
||||
if (cmd.IsScalar()) {
|
||||
result = InternalResolveMacros(cmd, macros);
|
||||
} else if (cmd.IsObjectType<Dictionary>()) {
|
||||
@ -46,6 +51,9 @@ Value MacroProcessor::ResolveMacros(const Value& cmd, const Dictionary::Ptr& mac
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String MacroProcessor::InternalResolveMacros(const String& str, const Dictionary::Ptr& macros)
|
||||
{
|
||||
ObjectLock olock(macros);
|
||||
@ -73,6 +81,9 @@ String MacroProcessor::InternalResolveMacros(const String& str, const Dictionary
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr MacroProcessor::MergeMacroDicts(const vector<Dictionary::Ptr>& dicts)
|
||||
{
|
||||
Dictionary::Ptr result = boost::make_shared<Dictionary>();
|
||||
|
@ -39,6 +39,9 @@ Notification::~Notification(void)
|
||||
Service::InvalidateNotificationsCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Notification::Ptr Notification::GetByName(const String& name)
|
||||
{
|
||||
DynamicObject::Ptr configObject = DynamicObject::GetObject("Notification", name);
|
||||
@ -46,34 +49,57 @@ Notification::Ptr Notification::GetByName(const String& name)
|
||||
return dynamic_pointer_cast<Notification>(configObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Service::Ptr Notification::GetService(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
Host::Ptr host = Host::GetByName(m_HostName);
|
||||
|
||||
if (!host)
|
||||
return Service::Ptr();
|
||||
|
||||
if (m_Service.IsEmpty())
|
||||
return Host::GetHostCheckService(host);
|
||||
return host->GetHostCheckService();
|
||||
else
|
||||
return Host::GetServiceByShortName(host, m_Service);
|
||||
return host->GetServiceByShortName(m_Service);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Value Notification::GetNotificationCommand(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_NotificationCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr Notification::GetMacros(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Macros;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
set<User::Ptr> Notification::GetUsers(void) const
|
||||
{
|
||||
set<User::Ptr> result;
|
||||
|
||||
Dictionary::Ptr users = m_Users;
|
||||
Dictionary::Ptr users;
|
||||
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
users = m_Users;
|
||||
}
|
||||
|
||||
if (users) {
|
||||
ObjectLock olock(users);
|
||||
@ -92,11 +118,19 @@ set<User::Ptr> Notification::GetUsers(void) const
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
set<UserGroup::Ptr> Notification::GetGroups(void) const
|
||||
{
|
||||
set<UserGroup::Ptr> result;
|
||||
|
||||
Dictionary::Ptr groups = m_Groups;
|
||||
Dictionary::Ptr groups;
|
||||
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
groups = m_Groups;
|
||||
}
|
||||
|
||||
if (groups) {
|
||||
ObjectLock olock(groups);
|
||||
@ -115,6 +149,9 @@ set<UserGroup::Ptr> Notification::GetGroups(void) const
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String Notification::NotificationTypeToString(NotificationType type)
|
||||
{
|
||||
switch (type) {
|
||||
@ -137,8 +174,12 @@ String Notification::NotificationTypeToString(NotificationType type)
|
||||
}
|
||||
}
|
||||
|
||||
void Notification::BeginExecuteNotification(const Notification::Ptr& self, NotificationType type)
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Notification::BeginExecuteNotification(NotificationType type)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
vector<Dictionary::Ptr> macroDicts;
|
||||
|
||||
@ -146,53 +187,36 @@ void Notification::BeginExecuteNotification(const Notification::Ptr& self, Notif
|
||||
notificationMacros->Set("NOTIFICATIONTYPE", NotificationTypeToString(type));
|
||||
macroDicts.push_back(notificationMacros);
|
||||
|
||||
Service::Ptr service;
|
||||
set<User::Ptr> users;
|
||||
set<UserGroup::Ptr> groups;
|
||||
macroDicts.push_back(GetMacros());
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
macroDicts.push_back(self->GetMacros());
|
||||
service = self->GetService();
|
||||
users = self->GetUsers();
|
||||
groups = self->GetGroups();
|
||||
}
|
||||
Service::Ptr service = GetService();
|
||||
|
||||
Host::Ptr host;
|
||||
String service_name;
|
||||
|
||||
{
|
||||
ObjectLock olock(service);
|
||||
if (service) {
|
||||
macroDicts.push_back(service->GetMacros());
|
||||
service_name = service->GetName();
|
||||
host = service->GetHost();
|
||||
}
|
||||
macroDicts.push_back(service->CalculateDynamicMacros());
|
||||
|
||||
macroDicts.push_back(Service::CalculateDynamicMacros(service));
|
||||
Host::Ptr host = service->GetHost();
|
||||
|
||||
{
|
||||
ObjectLock olock(host);
|
||||
macroDicts.push_back(host->GetMacros());
|
||||
macroDicts.push_back(Host::CalculateDynamicMacros(host));
|
||||
if (host) {
|
||||
macroDicts.push_back(host->GetMacros());
|
||||
macroDicts.push_back(host->CalculateDynamicMacros());
|
||||
}
|
||||
}
|
||||
|
||||
IcingaApplication::Ptr app = IcingaApplication::GetInstance();
|
||||
macroDicts.push_back(app->GetMacros());
|
||||
|
||||
{
|
||||
ObjectLock olock(app);
|
||||
macroDicts.push_back(app->GetMacros());
|
||||
}
|
||||
|
||||
macroDicts.push_back(IcingaApplication::CalculateDynamicMacros(app));
|
||||
macroDicts.push_back(IcingaApplication::CalculateDynamicMacros());
|
||||
|
||||
Dictionary::Ptr macros = MacroProcessor::MergeMacroDicts(macroDicts);
|
||||
|
||||
set<User::Ptr> allUsers;
|
||||
|
||||
set<User::Ptr> users = GetUsers();
|
||||
std::copy(users.begin(), users.end(), std::inserter(allUsers, allUsers.begin()));
|
||||
|
||||
BOOST_FOREACH(const UserGroup::Ptr& ug, groups) {
|
||||
set<User::Ptr> members = UserGroup::GetMembers(ug);
|
||||
BOOST_FOREACH(const UserGroup::Ptr& ug, GetGroups()) {
|
||||
set<User::Ptr> members = ug->GetMembers();
|
||||
std::copy(members.begin(), members.end(), std::inserter(allUsers, allUsers.begin()));
|
||||
}
|
||||
|
||||
@ -205,58 +229,66 @@ void Notification::BeginExecuteNotification(const Notification::Ptr& self, Notif
|
||||
}
|
||||
|
||||
Logger::Write(LogDebug, "icinga", "Sending notification for user " + user_name);
|
||||
BeginExecuteNotificationHelper(self, macros, type, user);
|
||||
BeginExecuteNotificationHelper(macros, type, user);
|
||||
}
|
||||
|
||||
if (allUsers.size() == 0) {
|
||||
/* Send a notification even if there are no users specified. */
|
||||
BeginExecuteNotificationHelper(self, macros, type, User::Ptr());
|
||||
BeginExecuteNotificationHelper(macros, type, User::Ptr());
|
||||
}
|
||||
}
|
||||
|
||||
void Notification::BeginExecuteNotificationHelper(const Notification::Ptr& self, const Dictionary::Ptr& notificationMacros, NotificationType type, const User::Ptr& user)
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Notification::BeginExecuteNotificationHelper(const Dictionary::Ptr& notificationMacros, NotificationType type, const User::Ptr& user)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
vector<Dictionary::Ptr> macroDicts;
|
||||
|
||||
if (user) {
|
||||
{
|
||||
ObjectLock olock(user);
|
||||
macroDicts.push_back(user->GetMacros());
|
||||
}
|
||||
|
||||
macroDicts.push_back(User::CalculateDynamicMacros(user));
|
||||
macroDicts.push_back(user->GetMacros());
|
||||
macroDicts.push_back(user->CalculateDynamicMacros());
|
||||
}
|
||||
|
||||
macroDicts.push_back(notificationMacros);
|
||||
|
||||
Dictionary::Ptr macros = MacroProcessor::MergeMacroDicts(macroDicts);
|
||||
|
||||
Notification::Ptr self = GetSelf();
|
||||
|
||||
vector<Value> arguments;
|
||||
arguments.push_back(self);
|
||||
arguments.push_back(macros);
|
||||
arguments.push_back(type);
|
||||
|
||||
ScriptTask::Ptr task;
|
||||
task = MakeMethodTask("notify", arguments);
|
||||
|
||||
if (!task) {
|
||||
Logger::Write(LogWarning, "icinga", "Notification object '" + GetName() + "' doesn't have a 'notify' method.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
|
||||
vector<Value> arguments;
|
||||
arguments.push_back(self);
|
||||
arguments.push_back(macros);
|
||||
arguments.push_back(type);
|
||||
task = self->MakeMethodTask("notify", arguments);
|
||||
|
||||
if (!task) {
|
||||
Logger::Write(LogWarning, "icinga", "Notification object '" + self->GetName() + "' doesn't have a 'notify' method.");
|
||||
|
||||
return;
|
||||
}
|
||||
ObjectLock olock(this);
|
||||
|
||||
/* We need to keep the task object alive until the completion handler is called. */
|
||||
self->m_Tasks.insert(task);
|
||||
m_Tasks.insert(task);
|
||||
}
|
||||
|
||||
task->Start(boost::bind(&Notification::NotificationCompletedHandler, self, _1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Notification::NotificationCompletedHandler(const ScriptTask::Ptr& task)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
m_Tasks.erase(task);
|
||||
|
||||
try {
|
||||
@ -273,8 +305,13 @@ void Notification::NotificationCompletedHandler(const ScriptTask::Ptr& task)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Notification::OnAttributeChanged(const String& name, const Value& oldValue)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
if (name == "host_name" || name == "service")
|
||||
Service::InvalidateNotificationsCache();
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ public:
|
||||
set<User::Ptr> GetUsers(void) const;
|
||||
set<UserGroup::Ptr> GetGroups(void) const;
|
||||
|
||||
static void BeginExecuteNotification(const Notification::Ptr& self, NotificationType type);
|
||||
void BeginExecuteNotification(NotificationType type);
|
||||
|
||||
static String NotificationTypeToString(NotificationType type);
|
||||
|
||||
@ -82,8 +82,8 @@ private:
|
||||
|
||||
void NotificationCompletedHandler(const ScriptTask::Ptr& task);
|
||||
|
||||
static void BeginExecuteNotificationHelper(const Notification::Ptr& self,
|
||||
const Dictionary::Ptr& notificationMacros, NotificationType type, const User::Ptr& user);
|
||||
void BeginExecuteNotificationHelper(const Dictionary::Ptr& notificationMacros,
|
||||
NotificationType type, const User::Ptr& user);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -23,6 +23,9 @@ using namespace icinga;
|
||||
|
||||
REGISTER_SCRIPTFUNCTION("NullCheck", &NullCheckTask::ScriptFunc);
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void NullCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Value>& arguments)
|
||||
{
|
||||
if (arguments.size() < 1)
|
||||
@ -31,8 +34,5 @@ void NullCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Value>&
|
||||
Dictionary::Ptr cr = boost::make_shared<Dictionary>();
|
||||
cr->Set("state", StateUnknown);
|
||||
|
||||
{
|
||||
ObjectLock olock(task);
|
||||
task->FinishResult(cr);
|
||||
}
|
||||
task->FinishResult(cr);
|
||||
}
|
||||
|
@ -35,16 +35,26 @@ PerfdataWriter::~PerfdataWriter(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void PerfdataWriter::OnAttributeChanged(const String& name, const Value& oldValue)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
if (name == "rotation_interval") {
|
||||
ObjectLock olock(this);
|
||||
m_RotationTimer->SetInterval(GetRotationInterval());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void PerfdataWriter::Start(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_Endpoint = Endpoint::MakeEndpoint("perfdata_" + GetName(), false);
|
||||
|
||||
{
|
||||
@ -62,6 +72,9 @@ void PerfdataWriter::Start(void)
|
||||
RotateFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
PerfdataWriter::Ptr PerfdataWriter::GetByName(const String& name)
|
||||
{
|
||||
DynamicObject::Ptr configObject = DynamicObject::GetObject("PerfdataWriter", name);
|
||||
@ -69,16 +82,26 @@ PerfdataWriter::Ptr PerfdataWriter::GetByName(const String& name)
|
||||
return dynamic_pointer_cast<PerfdataWriter>(configObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String PerfdataWriter::GetPathPrefix(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (!m_PathPrefix.IsEmpty())
|
||||
return m_PathPrefix;
|
||||
else
|
||||
return Application::GetLocalStateDir() + "/cache/icinga2/perfdata/perfdata";
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String PerfdataWriter::GetFormatTemplate(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (!m_FormatTemplate.IsEmpty()) {
|
||||
return m_FormatTemplate;
|
||||
} else {
|
||||
@ -95,14 +118,22 @@ String PerfdataWriter::GetFormatTemplate(void) const
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
double PerfdataWriter::GetRotationInterval(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (!m_RotationInterval.IsEmpty())
|
||||
return m_RotationInterval;
|
||||
else
|
||||
return 30;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void PerfdataWriter::CheckResultRequestHandler(const RequestMessage& request)
|
||||
{
|
||||
CheckResultMessage params;
|
||||
@ -119,15 +150,20 @@ void PerfdataWriter::CheckResultRequestHandler(const RequestMessage& request)
|
||||
Dictionary::Ptr macros = cr->Get("macros");
|
||||
String line = MacroProcessor::ResolveMacros(GetFormatTemplate(), macros);
|
||||
|
||||
ObjectLock olock(this);
|
||||
if (!m_OutputFile.good())
|
||||
return;
|
||||
|
||||
ObjectLock olock(this);
|
||||
m_OutputFile << line << "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void PerfdataWriter::RotateFile(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
String tempFile = GetPathPrefix();
|
||||
|
||||
if (m_OutputFile.good()) {
|
||||
@ -143,8 +179,10 @@ void PerfdataWriter::RotateFile(void)
|
||||
Logger::Write(LogWarning, "icinga", "Could not open perfdata file '" + tempFile + "' for writing. Perfdata will be lost.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void PerfdataWriter::RotationTimerHandler(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
RotateFile();
|
||||
}
|
||||
|
@ -27,6 +27,9 @@ PluginCheckTask::PluginCheckTask(const ScriptTask::Ptr& task, const Process::Ptr
|
||||
: m_Task(task), m_Process(process), m_Command(command)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void PluginCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Value>& arguments)
|
||||
{
|
||||
if (arguments.size() < 1)
|
||||
@ -38,13 +41,7 @@ void PluginCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Value
|
||||
Service::Ptr service = arguments[0];
|
||||
Dictionary::Ptr macros = arguments[1];
|
||||
|
||||
Value raw_command;
|
||||
|
||||
{
|
||||
ObjectLock olock(service);
|
||||
raw_command = service->GetCheckCommand();
|
||||
}
|
||||
|
||||
Value raw_command = service->GetCheckCommand();
|
||||
Value command = MacroProcessor::ResolveMacros(raw_command, macros);
|
||||
|
||||
Process::Ptr process = boost::make_shared<Process>(Process::SplitCommand(command), macros);
|
||||
@ -54,6 +51,9 @@ void PluginCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector<Value
|
||||
process->Start(boost::bind(&PluginCheckTask::ProcessFinishedHandler, ct));
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void PluginCheckTask::ProcessFinishedHandler(PluginCheckTask ct)
|
||||
{
|
||||
ProcessResult pr;
|
||||
@ -77,6 +77,9 @@ void PluginCheckTask::ProcessFinishedHandler(PluginCheckTask ct)
|
||||
ct.m_Task->FinishResult(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
ServiceState PluginCheckTask::ExitStatusToState(int exitStatus)
|
||||
{
|
||||
switch (exitStatus) {
|
||||
@ -91,6 +94,9 @@ ServiceState PluginCheckTask::ExitStatusToState(int exitStatus)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr PluginCheckTask::ParseCheckOutput(const String& output)
|
||||
{
|
||||
Dictionary::Ptr result = boost::make_shared<Dictionary>();
|
||||
|
@ -46,20 +46,13 @@ void PluginNotificationTask::ScriptFunc(const ScriptTask::Ptr& task, const vecto
|
||||
Dictionary::Ptr macros = arguments[1];
|
||||
NotificationType type = static_cast<NotificationType>(static_cast<int>(arguments[2]));
|
||||
|
||||
Value raw_command;
|
||||
Value raw_command = notification->GetNotificationCommand();
|
||||
|
||||
String service_name;
|
||||
Service::Ptr service;
|
||||
|
||||
{
|
||||
ObjectLock olock(notification);
|
||||
raw_command = notification->GetNotificationCommand();
|
||||
service = notification->GetService();
|
||||
}
|
||||
|
||||
{
|
||||
ObjectLock olock(service);
|
||||
Service::Ptr service = notification->GetService();
|
||||
if (service)
|
||||
service_name = service->GetName();
|
||||
}
|
||||
|
||||
Value command = MacroProcessor::ResolveMacros(raw_command, macros);
|
||||
|
||||
@ -78,9 +71,7 @@ void PluginNotificationTask::ProcessFinishedHandler(PluginNotificationTask ct)
|
||||
ProcessResult pr;
|
||||
|
||||
try {
|
||||
{
|
||||
pr = ct.m_Process->GetResult();
|
||||
}
|
||||
pr = ct.m_Process->GetResult();
|
||||
|
||||
if (pr.ExitStatus != 0) {
|
||||
stringstream msgbuf;
|
||||
|
@ -28,58 +28,103 @@ const int Service::CheckIntervalDivisor = 5;
|
||||
signals2::signal<void (const Service::Ptr&, const String&)> Service::OnCheckerChanged;
|
||||
signals2::signal<void (const Service::Ptr&, const Value&)> Service::OnNextCheckChanged;
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Value Service::GetCheckCommand(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_CheckCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
long Service::GetMaxCheckAttempts(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_MaxCheckAttempts.IsEmpty())
|
||||
return DefaultMaxCheckAttempts;
|
||||
|
||||
return m_MaxCheckAttempts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
double Service::GetCheckInterval(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_CheckInterval.IsEmpty())
|
||||
return DefaultCheckInterval;
|
||||
|
||||
return m_CheckInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
double Service::GetRetryInterval(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_RetryInterval.IsEmpty())
|
||||
return GetCheckInterval() / CheckIntervalDivisor;
|
||||
|
||||
return m_RetryInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr Service::GetCheckers(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Checkers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetSchedulingOffset(long offset)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_SchedulingOffset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
long Service::GetSchedulingOffset(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_SchedulingOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetNextCheck(double nextCheck)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_NextCheck = nextCheck;
|
||||
Touch("next_check");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
double Service::GetNextCheck(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_NextCheck.IsEmpty()) {
|
||||
UpdateNextCheck();
|
||||
|
||||
@ -90,8 +135,13 @@ double Service::GetNextCheck(void)
|
||||
return m_NextCheck;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::UpdateNextCheck(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
double interval;
|
||||
|
||||
if (GetStateType() == StateTypeSoft)
|
||||
@ -108,39 +158,69 @@ void Service::UpdateNextCheck(void)
|
||||
SetNextCheck(now - adj + interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetCurrentChecker(const String& checker)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_CurrentChecker = checker;
|
||||
Touch("current_checker");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String Service::GetCurrentChecker(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_CurrentChecker;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetCurrentCheckAttempt(long attempt)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_CheckAttempt = attempt;
|
||||
Touch("check_attempt");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
long Service::GetCurrentCheckAttempt(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_CheckAttempt.IsEmpty())
|
||||
return 1;
|
||||
|
||||
return m_CheckAttempt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetState(ServiceState state)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_State = static_cast<long>(state);
|
||||
Touch("state");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
ServiceState Service::GetState(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_State.IsEmpty())
|
||||
return StateUnknown;
|
||||
|
||||
@ -148,14 +228,24 @@ ServiceState Service::GetState(void) const
|
||||
return static_cast<ServiceState>(ivalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetStateType(ServiceStateType type)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_StateType = static_cast<long>(type);
|
||||
Touch("state_type");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
ServiceStateType Service::GetStateType(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_StateType.IsEmpty())
|
||||
return StateTypeSoft;
|
||||
|
||||
@ -163,89 +253,155 @@ ServiceStateType Service::GetStateType(void) const
|
||||
return static_cast<ServiceStateType>(ivalue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetLastCheckResult(const Dictionary::Ptr& result)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_LastResult = result;
|
||||
Touch("last_result");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr Service::GetLastCheckResult(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_LastResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetLastStateChange(double ts)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_LastStateChange = ts;
|
||||
Touch("last_state_change");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
double Service::GetLastStateChange(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_LastStateChange.IsEmpty())
|
||||
return IcingaApplication::GetInstance()->GetStartTime();
|
||||
|
||||
return m_LastStateChange;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetLastHardStateChange(double ts)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_LastHardStateChange = ts;
|
||||
Touch("last_hard_state_change");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
double Service::GetLastHardStateChange(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_LastHardStateChange.IsEmpty())
|
||||
return IcingaApplication::GetInstance()->GetStartTime();
|
||||
|
||||
return m_LastHardStateChange;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
bool Service::GetEnableActiveChecks(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_EnableActiveChecks.IsEmpty())
|
||||
return true;
|
||||
else
|
||||
return m_EnableActiveChecks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetEnableActiveChecks(bool enabled)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_EnableActiveChecks = enabled ? 1 : 0;
|
||||
Touch("enable_active_checks");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
bool Service::GetEnablePassiveChecks(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_EnablePassiveChecks.IsEmpty())
|
||||
return true;
|
||||
else
|
||||
return m_EnablePassiveChecks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetEnablePassiveChecks(bool enabled)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_EnablePassiveChecks = enabled ? 1 : 0;
|
||||
Touch("enable_passive_checks");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
bool Service::GetForceNextCheck(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_ForceNextCheck.IsEmpty())
|
||||
return false;
|
||||
|
||||
return static_cast<bool>(m_ForceNextCheck);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetForceNextCheck(bool forced)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_ForceNextCheck = forced ? 1 : 0;
|
||||
Touch("force_next_check");
|
||||
}
|
||||
|
||||
void Service::ApplyCheckResult(const Dictionary::Ptr& cr)
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
ObjectLock olock(this);
|
||||
|
||||
ServiceState old_state = GetState();
|
||||
ServiceStateType old_stateType = GetStateType();
|
||||
bool hardChange = false;
|
||||
@ -298,13 +454,13 @@ void Service::ApplyCheckResult(const Dictionary::Ptr& cr)
|
||||
}
|
||||
|
||||
/* reschedule service dependencies */
|
||||
BOOST_FOREACH(const Service::Ptr& parent, Service::GetParentServices(GetSelf())) {
|
||||
BOOST_FOREACH(const Service::Ptr& parent, GetParentServices()) {
|
||||
parent->SetNextCheck(Utility::GetTime());
|
||||
}
|
||||
|
||||
/* reschedule host dependencies */
|
||||
BOOST_FOREACH(const Host::Ptr& parent, Service::GetParentHosts(GetSelf())) {
|
||||
Service::Ptr service = Host::GetHostCheckService(parent);
|
||||
BOOST_FOREACH(const Host::Ptr& parent, GetParentHosts()) {
|
||||
Service::Ptr service = parent->GetHostCheckService();
|
||||
|
||||
if (service) {
|
||||
ObjectLock olock(service);
|
||||
@ -313,21 +469,39 @@ void Service::ApplyCheckResult(const Dictionary::Ptr& cr)
|
||||
}
|
||||
}
|
||||
|
||||
if (hardChange)
|
||||
SetLastHardStateChange(now);
|
||||
|
||||
if (GetState() != StateOK)
|
||||
TriggerDowntimes();
|
||||
|
||||
if (hardChange) {
|
||||
SetLastHardStateChange(now);
|
||||
Service::UpdateStatistics(cr);
|
||||
|
||||
/* Make sure the notification component sees the updated
|
||||
* state/state_type attributes. */
|
||||
Flush();
|
||||
olock.Unlock();
|
||||
|
||||
if (IsReachable(GetSelf()) && !IsInDowntime() && !IsAcknowledged())
|
||||
RequestNotifications(recovery ? NotificationRecovery : NotificationProblem);
|
||||
}
|
||||
/* Flush the object so other instances see the service's
|
||||
* new state when they receive the CheckResult message */
|
||||
Flush();
|
||||
|
||||
RequestMessage rm;
|
||||
rm.SetMethod("checker::CheckResult");
|
||||
|
||||
/* TODO: add _old_ state to message */
|
||||
CheckResultMessage params;
|
||||
params.SetService(GetName());
|
||||
params.SetCheckResult(cr);
|
||||
|
||||
rm.SetParams(params);
|
||||
|
||||
EndpointManager::GetInstance()->SendMulticastMessage(rm);
|
||||
|
||||
if (hardChange && IsReachable() && !IsInDowntime() && !IsAcknowledged())
|
||||
RequestNotifications(recovery ? NotificationRecovery : NotificationProblem);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
ServiceState Service::StateFromString(const String& state)
|
||||
{
|
||||
if (state == "OK")
|
||||
@ -342,6 +516,9 @@ ServiceState Service::StateFromString(const String& state)
|
||||
return StateUnknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String Service::StateToString(ServiceState state)
|
||||
{
|
||||
switch (state) {
|
||||
@ -359,6 +536,9 @@ String Service::StateToString(ServiceState state)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
ServiceStateType Service::StateTypeFromString(const String& type)
|
||||
{
|
||||
if (type == "SOFT")
|
||||
@ -367,6 +547,9 @@ ServiceStateType Service::StateTypeFromString(const String& type)
|
||||
return StateTypeHard;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String Service::StateTypeToString(ServiceStateType type)
|
||||
{
|
||||
if (type == StateTypeSoft)
|
||||
@ -375,6 +558,9 @@ String Service::StateTypeToString(ServiceStateType type)
|
||||
return "HARD";
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
bool Service::IsAllowedChecker(const String& checker) const
|
||||
{
|
||||
Dictionary::Ptr checkers = GetCheckers();
|
||||
@ -382,6 +568,8 @@ bool Service::IsAllowedChecker(const String& checker) const
|
||||
if (!checkers)
|
||||
return true;
|
||||
|
||||
ObjectLock olock(checkers);
|
||||
|
||||
Value pattern;
|
||||
BOOST_FOREACH(tie(tuples::ignore, pattern), checkers) {
|
||||
if (Utility::Match(pattern, checker))
|
||||
@ -391,6 +579,9 @@ bool Service::IsAllowedChecker(const String& checker) const
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::BeginExecuteCheck(const Service::Ptr& self, const function<void (void)>& callback)
|
||||
{
|
||||
ObjectLock slock(self);
|
||||
@ -407,16 +598,12 @@ void Service::BeginExecuteCheck(const Service::Ptr& self, const function<void (v
|
||||
|
||||
/* keep track of scheduling info in case the check type doesn't provide its own information */
|
||||
Dictionary::Ptr checkInfo = boost::make_shared<Dictionary>();
|
||||
|
||||
{
|
||||
ObjectLock olock(checkInfo);
|
||||
checkInfo->Set("schedule_start", self->GetNextCheck());
|
||||
checkInfo->Set("execution_start", Utility::GetTime());
|
||||
}
|
||||
checkInfo->Set("schedule_start", self->GetNextCheck());
|
||||
checkInfo->Set("execution_start", Utility::GetTime());
|
||||
|
||||
vector<Dictionary::Ptr> macroDicts;
|
||||
macroDicts.push_back(self->GetMacros());
|
||||
macroDicts.push_back(Service::CalculateDynamicMacros(self));
|
||||
macroDicts.push_back(self->CalculateDynamicMacros());
|
||||
|
||||
Value raw_command = self->GetCheckCommand();
|
||||
|
||||
@ -424,21 +611,13 @@ void Service::BeginExecuteCheck(const Service::Ptr& self, const function<void (v
|
||||
|
||||
slock.Unlock();
|
||||
|
||||
{
|
||||
ObjectLock olock(host);
|
||||
macroDicts.push_back(host->GetMacros());
|
||||
}
|
||||
|
||||
macroDicts.push_back(Host::CalculateDynamicMacros(host));
|
||||
macroDicts.push_back(host->GetMacros());
|
||||
macroDicts.push_back(host->CalculateDynamicMacros());
|
||||
|
||||
IcingaApplication::Ptr app = IcingaApplication::GetInstance();
|
||||
macroDicts.push_back(app->GetMacros());
|
||||
|
||||
{
|
||||
ObjectLock olock(app);
|
||||
macroDicts.push_back(app->GetMacros());
|
||||
}
|
||||
|
||||
macroDicts.push_back(IcingaApplication::CalculateDynamicMacros(app));
|
||||
macroDicts.push_back(IcingaApplication::CalculateDynamicMacros());
|
||||
|
||||
Dictionary::Ptr macros = MacroProcessor::MergeMacroDicts(macroDicts);
|
||||
|
||||
@ -459,9 +638,14 @@ void Service::BeginExecuteCheck(const Service::Ptr& self, const function<void (v
|
||||
task->Start(boost::bind(&Service::CheckCompletedHandler, self, checkInfo, _1, callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::CheckCompletedHandler(const Dictionary::Ptr& checkInfo,
|
||||
const ScriptTask::Ptr& task, const function<void (void)>& callback)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
checkInfo->Set("execution_end", Utility::GetTime());
|
||||
checkInfo->Set("schedule_end", Utility::GetTime());
|
||||
checkInfo->Seal();
|
||||
@ -515,47 +699,25 @@ void Service::CheckCompletedHandler(const Dictionary::Ptr& checkInfo,
|
||||
result->Seal();
|
||||
}
|
||||
|
||||
if (result)
|
||||
ProcessCheckResult(result);
|
||||
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
if (result)
|
||||
ProcessCheckResult(result);
|
||||
|
||||
m_CurrentTask.reset();
|
||||
|
||||
/* 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();
|
||||
}
|
||||
|
||||
/* figure out when the next check is for this service; the call to
|
||||
* ApplyCheckResult() should've already done this but lets do it again
|
||||
* just in case there was no check result. */
|
||||
UpdateNextCheck();
|
||||
|
||||
callback();
|
||||
}
|
||||
|
||||
void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
|
||||
{
|
||||
ApplyCheckResult(cr);
|
||||
|
||||
Service::UpdateStatistics(cr);
|
||||
|
||||
/* Flush the object so other instances see the service's
|
||||
* new state when they receive the CheckResult message */
|
||||
Flush();
|
||||
|
||||
RequestMessage rm;
|
||||
rm.SetMethod("checker::CheckResult");
|
||||
|
||||
/* TODO: add _old_ state to message */
|
||||
CheckResultMessage params;
|
||||
params.SetService(GetName());
|
||||
params.SetCheckResult(cr);
|
||||
|
||||
rm.SetParams(params);
|
||||
|
||||
EndpointManager::Ptr em = EndpointManager::GetInstance();
|
||||
ObjectLock olock(em);
|
||||
em->SendMulticastMessage(rm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::UpdateStatistics(const Dictionary::Ptr& cr)
|
||||
{
|
||||
time_t ts;
|
||||
@ -572,15 +734,14 @@ void Service::UpdateStatistics(const Dictionary::Ptr& cr)
|
||||
CIB::UpdatePassiveChecksStatistics(ts, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
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;
|
||||
|
||||
@ -591,13 +752,14 @@ double Service::CalculateExecutionTime(const Dictionary::Ptr& cr)
|
||||
return (execution_end - execution_start);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
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;
|
||||
|
||||
|
@ -28,16 +28,29 @@ map<String, Service::WeakPtr> Service::m_CommentsCache;
|
||||
bool Service::m_CommentsCacheValid = true;
|
||||
Timer::Ptr Service::m_CommentsExpireTimer;
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
int Service::GetNextCommentID(void)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_CommentMutex);
|
||||
|
||||
return m_NextCommentID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr Service::GetComments(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String Service::AddComment(CommentType entryType, const String& author,
|
||||
const String& text, double expireTime)
|
||||
{
|
||||
@ -57,7 +70,9 @@ String Service::AddComment(CommentType entryType, const String& author,
|
||||
|
||||
comment->Set("legacy_id", legacy_id);
|
||||
|
||||
Dictionary::Ptr comments = m_Comments;
|
||||
ObjectLock olock(this);
|
||||
|
||||
Dictionary::Ptr comments = GetComments();
|
||||
|
||||
if (!comments)
|
||||
comments = boost::make_shared<Dictionary>();
|
||||
@ -71,12 +86,20 @@ String Service::AddComment(CommentType entryType, const String& author,
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::RemoveAllComments(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_Comments = Empty;
|
||||
Touch("comments");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::RemoveComment(const String& id)
|
||||
{
|
||||
Service::Ptr owner = GetOwnerByCommentID(id);
|
||||
@ -84,7 +107,9 @@ void Service::RemoveComment(const String& id)
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
Dictionary::Ptr comments = owner->m_Comments;
|
||||
ObjectLock olock(owner);
|
||||
|
||||
Dictionary::Ptr comments = owner->GetComments();
|
||||
|
||||
if (comments) {
|
||||
comments->Remove(id);
|
||||
@ -92,6 +117,9 @@ void Service::RemoveComment(const String& id)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String Service::GetCommentIDFromLegacyID(int id)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_CommentMutex);
|
||||
@ -104,6 +132,9 @@ String Service::GetCommentIDFromLegacyID(int id)
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Service::Ptr Service::GetOwnerByCommentID(const String& id)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_CommentMutex);
|
||||
@ -111,6 +142,9 @@ Service::Ptr Service::GetOwnerByCommentID(const String& id)
|
||||
return m_CommentsCache[id].lock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr Service::GetCommentByID(const String& id)
|
||||
{
|
||||
Service::Ptr owner = GetOwnerByCommentID(id);
|
||||
@ -118,36 +152,40 @@ Dictionary::Ptr Service::GetCommentByID(const String& id)
|
||||
if (!owner)
|
||||
return Dictionary::Ptr();
|
||||
|
||||
Dictionary::Ptr comments = owner->m_Comments;
|
||||
Dictionary::Ptr comments = owner->GetComments();
|
||||
|
||||
if (comments) {
|
||||
Dictionary::Ptr comment = comments->Get(id);
|
||||
return comment;
|
||||
}
|
||||
if (comments)
|
||||
return comments->Get(id);
|
||||
|
||||
return Dictionary::Ptr();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
bool Service::IsCommentExpired(const Dictionary::Ptr& comment)
|
||||
{
|
||||
ObjectLock olock(comment);
|
||||
double expire_time = comment->Get("expire_time");
|
||||
|
||||
return (expire_time != 0 && expire_time < Utility::GetTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::InvalidateCommentsCache(void)
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_CommentMutex);
|
||||
boost::mutex::scoped_lock lock(m_CommentMutex);
|
||||
|
||||
if (m_CommentsCacheValid)
|
||||
Utility::QueueAsyncCallback(boost::bind(&Service::RefreshCommentsCache));
|
||||
if (m_CommentsCacheValid)
|
||||
Utility::QueueAsyncCallback(boost::bind(&Service::RefreshCommentsCache));
|
||||
|
||||
m_CommentsCacheValid = false;
|
||||
}
|
||||
m_CommentsCacheValid = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::RefreshCommentsCache(void)
|
||||
{
|
||||
{
|
||||
@ -214,16 +252,21 @@ void Service::RefreshCommentsCache(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::RemoveExpiredComments(void)
|
||||
{
|
||||
Dictionary::Ptr comments = m_Comments;
|
||||
ObjectLock olock(this);
|
||||
|
||||
Dictionary::Ptr comments = GetComments();
|
||||
|
||||
if (!comments)
|
||||
return;
|
||||
|
||||
vector<String> expiredComments;
|
||||
|
||||
ObjectLock olock(comments);
|
||||
ObjectLock dlock(comments);
|
||||
|
||||
String id;
|
||||
Dictionary::Ptr comment;
|
||||
@ -241,11 +284,13 @@ void Service::RemoveExpiredComments(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::CommentsExpireTimerHandler(void)
|
||||
{
|
||||
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
|
||||
Service::Ptr service = dynamic_pointer_cast<Service>(object);
|
||||
ObjectLock olock(service);
|
||||
service->RemoveExpiredComments();
|
||||
}
|
||||
}
|
||||
|
@ -28,16 +28,27 @@ map<String, Service::WeakPtr> Service::m_DowntimesCache;
|
||||
bool Service::m_DowntimesCacheValid = true;
|
||||
Timer::Ptr Service::m_DowntimesExpireTimer;
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
int Service::GetNextDowntimeID(void)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_DowntimeMutex);
|
||||
|
||||
return m_NextDowntimeID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr Service::GetDowntimes(void) const
|
||||
{
|
||||
return m_Downtimes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String Service::AddDowntime(const String& author, const String& comment,
|
||||
double startTime, double endTime, bool fixed,
|
||||
const String& triggeredBy, double duration)
|
||||
@ -86,6 +97,9 @@ String Service::AddDowntime(const String& author, const String& comment,
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::RemoveDowntime(const String& id)
|
||||
{
|
||||
Service::Ptr owner = GetOwnerByDowntimeID(id);
|
||||
@ -93,22 +107,23 @@ void Service::RemoveDowntime(const String& id)
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
Dictionary::Ptr downtimes = owner->m_Downtimes;
|
||||
ObjectLock olock(owner);
|
||||
|
||||
Dictionary::Ptr downtimes = owner->GetDowntimes();
|
||||
|
||||
if (!downtimes)
|
||||
return;
|
||||
|
||||
{
|
||||
ObjectLock olock(downtimes);
|
||||
downtimes->Remove(id);
|
||||
}
|
||||
|
||||
downtimes->Remove(id);
|
||||
owner->Touch("downtimes");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::TriggerDowntimes(void)
|
||||
{
|
||||
Dictionary::Ptr downtimes = m_Downtimes;
|
||||
Dictionary::Ptr downtimes = GetDowntimes();
|
||||
|
||||
if (!downtimes)
|
||||
return;
|
||||
@ -121,6 +136,9 @@ void Service::TriggerDowntimes(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::TriggerDowntime(const String& id)
|
||||
{
|
||||
Service::Ptr owner = GetOwnerByDowntimeID(id);
|
||||
@ -150,6 +168,9 @@ void Service::TriggerDowntime(const String& id)
|
||||
owner->Touch("downtimes");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String Service::GetDowntimeIDFromLegacyID(int id)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_DowntimeMutex);
|
||||
@ -162,12 +183,18 @@ String Service::GetDowntimeIDFromLegacyID(int id)
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Service::Ptr Service::GetOwnerByDowntimeID(const String& id)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_DowntimeMutex);
|
||||
return m_DowntimesCache[id].lock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr Service::GetDowntimeByID(const String& id)
|
||||
{
|
||||
Service::Ptr owner = GetOwnerByDowntimeID(id);
|
||||
@ -175,17 +202,17 @@ Dictionary::Ptr Service::GetDowntimeByID(const String& id)
|
||||
if (!owner)
|
||||
return Dictionary::Ptr();
|
||||
|
||||
Dictionary::Ptr downtimes = owner->m_Downtimes;
|
||||
Dictionary::Ptr downtimes = owner->GetDowntimes();
|
||||
|
||||
if (downtimes) {
|
||||
ObjectLock olock(downtimes);
|
||||
Dictionary::Ptr downtime = downtimes->Get(id);
|
||||
return downtime;
|
||||
}
|
||||
if (downtimes)
|
||||
return downtimes->Get(id);
|
||||
|
||||
return Dictionary::Ptr();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
bool Service::IsDowntimeActive(const Dictionary::Ptr& downtime)
|
||||
{
|
||||
double now = Utility::GetTime();
|
||||
@ -207,24 +234,30 @@ bool Service::IsDowntimeActive(const Dictionary::Ptr& downtime)
|
||||
return (triggerTime + downtime->Get("duration") < now);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
bool Service::IsDowntimeExpired(const Dictionary::Ptr& downtime)
|
||||
{
|
||||
ObjectLock olock(downtime);
|
||||
return (downtime->Get("end_time") < Utility::GetTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::InvalidateDowntimesCache(void)
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_DowntimeMutex);
|
||||
boost::mutex::scoped_lock lock(m_DowntimeMutex);
|
||||
|
||||
if (m_DowntimesCacheValid)
|
||||
Utility::QueueAsyncCallback(boost::bind(&Service::RefreshDowntimesCache));
|
||||
if (m_DowntimesCacheValid)
|
||||
Utility::QueueAsyncCallback(boost::bind(&Service::RefreshDowntimesCache));
|
||||
|
||||
m_DowntimesCacheValid = false;
|
||||
}
|
||||
m_DowntimesCacheValid = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::RefreshDowntimesCache(void)
|
||||
{
|
||||
{
|
||||
@ -289,16 +322,21 @@ void Service::RefreshDowntimesCache(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::RemoveExpiredDowntimes(void)
|
||||
{
|
||||
Dictionary::Ptr downtimes = m_Downtimes;
|
||||
ObjectLock olock(this);
|
||||
|
||||
Dictionary::Ptr downtimes = GetDowntimes();
|
||||
|
||||
if (!downtimes)
|
||||
return;
|
||||
|
||||
vector<String> expiredDowntimes;
|
||||
|
||||
ObjectLock olock(downtimes);
|
||||
ObjectLock dlock(downtimes);
|
||||
|
||||
String id;
|
||||
Dictionary::Ptr downtime;
|
||||
@ -316,15 +354,20 @@ void Service::RemoveExpiredDowntimes(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::DowntimesExpireTimerHandler(void)
|
||||
{
|
||||
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
|
||||
Service::Ptr service = dynamic_pointer_cast<Service>(object);
|
||||
ObjectLock slock(service);
|
||||
service->RemoveExpiredDowntimes();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
bool Service::IsInDowntime(void) const
|
||||
{
|
||||
Dictionary::Ptr downtimes = GetDowntimes();
|
||||
|
@ -25,8 +25,13 @@ boost::mutex Service::m_NotificationMutex;
|
||||
map<String, set<Notification::WeakPtr> > Service::m_NotificationsCache;
|
||||
bool Service::m_NotificationsCacheValid = true;
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::RequestNotifications(NotificationType type)
|
||||
{
|
||||
SetLastNotification(Utility::GetTime());
|
||||
|
||||
RequestMessage msg;
|
||||
msg.SetMethod("icinga::SendNotifications");
|
||||
|
||||
@ -38,40 +43,32 @@ void Service::RequestNotifications(NotificationType type)
|
||||
|
||||
Logger::Write(LogDebug, "icinga", "Sending notification anycast request for service '" + GetName() + "'");
|
||||
EndpointManager::GetInstance()->SendAnycastMessage(Endpoint::Ptr(), msg);
|
||||
|
||||
SetLastNotification(Utility::GetTime());
|
||||
}
|
||||
|
||||
void Service::SendNotifications(const Service::Ptr& self, NotificationType type)
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SendNotifications(NotificationType type)
|
||||
{
|
||||
String service_name;
|
||||
bool enable_notifications;
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
service_name = self->GetName();
|
||||
enable_notifications = self->GetEnableNotifications();
|
||||
}
|
||||
|
||||
if (!enable_notifications) {
|
||||
Logger::Write(LogInformation, "icinga", "Notifications are disabled for service '" + service_name + "'.");
|
||||
if (!GetEnableNotifications()) {
|
||||
Logger::Write(LogInformation, "icinga", "Notifications are disabled for service '" + GetName() + "'.");
|
||||
return;
|
||||
}
|
||||
|
||||
Logger::Write(LogInformation, "icinga", "Sending notifications for service '" + service_name + "'");
|
||||
Logger::Write(LogInformation, "icinga", "Sending notifications for service '" + GetName() + "'");
|
||||
|
||||
set<Notification::Ptr> notifications = GetNotifications(self);
|
||||
set<Notification::Ptr> notifications = GetNotifications();
|
||||
|
||||
if (notifications.size() == 0)
|
||||
Logger::Write(LogInformation, "icinga", "Service '" + service_name + "' does not have any notifications.");
|
||||
Logger::Write(LogInformation, "icinga", "Service '" + GetName() + "' does not have any notifications.");
|
||||
|
||||
BOOST_FOREACH(const Notification::Ptr& notification, notifications) {
|
||||
try {
|
||||
Notification::BeginExecuteNotification(notification, type);
|
||||
notification->BeginExecuteNotification(type);
|
||||
} catch (const exception& ex) {
|
||||
stringstream msgbuf;
|
||||
msgbuf << "Exception occured during notification for service '"
|
||||
<< service_name << "': " << diagnostic_information(ex);
|
||||
<< GetName() << "': " << diagnostic_information(ex);
|
||||
String message = msgbuf.str();
|
||||
|
||||
Logger::Write(LogWarning, "icinga", message);
|
||||
@ -79,18 +76,22 @@ void Service::SendNotifications(const Service::Ptr& self, NotificationType type)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::InvalidateNotificationsCache(void)
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_NotificationMutex);
|
||||
boost::mutex::scoped_lock lock(m_NotificationMutex);
|
||||
|
||||
if (m_NotificationsCacheValid)
|
||||
Utility::QueueAsyncCallback(boost::bind(&Service::RefreshNotificationsCache));
|
||||
if (m_NotificationsCacheValid)
|
||||
Utility::QueueAsyncCallback(boost::bind(&Service::RefreshNotificationsCache));
|
||||
|
||||
m_NotificationsCacheValid = false;
|
||||
}
|
||||
m_NotificationsCacheValid = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::RefreshNotificationsCache(void)
|
||||
{
|
||||
{
|
||||
@ -107,42 +108,29 @@ void Service::RefreshNotificationsCache(void)
|
||||
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Notification")) {
|
||||
const Notification::Ptr& notification = static_pointer_cast<Notification>(object);
|
||||
|
||||
Service::Ptr service;
|
||||
Service::Ptr service = notification->GetService();
|
||||
|
||||
{
|
||||
ObjectLock olock(notification);
|
||||
service = notification->GetService();
|
||||
}
|
||||
if (!service)
|
||||
continue;
|
||||
|
||||
String service_name;
|
||||
|
||||
{
|
||||
ObjectLock olock(service);
|
||||
service_name = service->GetName();
|
||||
}
|
||||
|
||||
newNotificationsCache[service_name].insert(notification);
|
||||
newNotificationsCache[service->GetName()].insert(notification);
|
||||
}
|
||||
|
||||
boost::mutex::scoped_lock lock(m_NotificationMutex);
|
||||
m_NotificationsCache.swap(newNotificationsCache);
|
||||
}
|
||||
|
||||
set<Notification::Ptr> Service::GetNotifications(const Service::Ptr& self)
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
set<Notification::Ptr> Service::GetNotifications(void) const
|
||||
{
|
||||
String name;
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
name = self->GetName();
|
||||
}
|
||||
|
||||
set<Notification::Ptr> notifications;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_NotificationMutex);
|
||||
|
||||
BOOST_FOREACH(const Notification::WeakPtr& wservice, m_NotificationsCache[name]) {
|
||||
BOOST_FOREACH(const Notification::WeakPtr& wservice, m_NotificationsCache[GetName()]) {
|
||||
Notification::Ptr notification = wservice.lock();
|
||||
|
||||
if (!notification)
|
||||
@ -155,6 +143,9 @@ set<Notification::Ptr> Service::GetNotifications(const Service::Ptr& self)
|
||||
return notifications;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
template<typename TDict>
|
||||
static void CopyNotificationAttributes(TDict notificationDesc, const ConfigItemBuilder::Ptr& builder)
|
||||
{
|
||||
@ -276,7 +267,7 @@ void Service::UpdateSlaveNotifications(const Service::Ptr& self)
|
||||
}
|
||||
|
||||
ConfigItem::Ptr notificationItem = builder->Compile();
|
||||
ConfigItem::Commit(notificationItem);
|
||||
notificationItem->Commit();
|
||||
|
||||
newNotifications->Set(name, notificationItem);
|
||||
}
|
||||
@ -301,36 +292,61 @@ void Service::UpdateSlaveNotifications(const Service::Ptr& self)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
double Service::GetLastNotification(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_LastNotification.IsEmpty())
|
||||
return 0;
|
||||
else
|
||||
return m_LastNotification;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetLastNotification(double time)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_LastNotification = time;
|
||||
Touch("last_notification");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
bool Service::GetEnableNotifications(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_EnableNotifications.IsEmpty())
|
||||
return true;
|
||||
else
|
||||
return m_EnableNotifications;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetEnableNotifications(bool enabled)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_EnableNotifications = enabled;
|
||||
Touch("enable_notifications");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
double Service::GetNotificationInterval(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_NotificationInterval.IsEmpty())
|
||||
return 300;
|
||||
else
|
||||
|
@ -76,13 +76,25 @@ Service::~Service(void)
|
||||
Service::InvalidateCommentsCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::OnRegistrationCompleted(void)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
DynamicObject::OnRegistrationCompleted();
|
||||
|
||||
InvalidateNotificationsCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String Service::GetDisplayName(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_DisplayName.IsEmpty())
|
||||
return GetShortName();
|
||||
else
|
||||
@ -113,66 +125,99 @@ Service::Ptr Service::GetByNamePair(const String& hostName, const String& servic
|
||||
if (!host)
|
||||
return Service::Ptr();
|
||||
|
||||
return Host::GetServiceByShortName(host, serviceName);
|
||||
return host->GetServiceByShortName(serviceName);
|
||||
} else {
|
||||
return Service::GetByName(serviceName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Host::Ptr Service::GetHost(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return Host::GetByName(m_HostName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr Service::GetMacros(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Macros;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr Service::GetHostDependencies(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_HostDependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr Service::GetServiceDependencies(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_ServiceDependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr Service::GetGroups(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_ServiceGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String Service::GetHostName(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_HostName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String Service::GetShortName(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_ShortName.IsEmpty())
|
||||
return GetName();
|
||||
else
|
||||
return m_ShortName;
|
||||
}
|
||||
|
||||
bool Service::IsReachable(const Service::Ptr& self)
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
bool Service::IsReachable(void) const
|
||||
{
|
||||
String service_name;
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
service_name = self->GetName();
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const Service::Ptr& service, Service::GetParentServices(self)) {
|
||||
ObjectLock olock(service);
|
||||
assert(!OwnsLock());
|
||||
|
||||
BOOST_FOREACH(const Service::Ptr& service, GetParentServices()) {
|
||||
/* ignore ourselves */
|
||||
if (service->GetName() == service_name)
|
||||
if (service->GetName() == GetName())
|
||||
continue;
|
||||
|
||||
ObjectLock olock(service);
|
||||
|
||||
/* ignore pending services */
|
||||
if (!service->GetLastCheckResult())
|
||||
continue;
|
||||
@ -189,21 +234,25 @@ bool Service::IsReachable(const Service::Ptr& self)
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const Host::Ptr& host, Service::GetParentHosts(self)) {
|
||||
Service::Ptr hc = Host::GetHostCheckService(host);
|
||||
BOOST_FOREACH(const Host::Ptr& host, GetParentHosts()) {
|
||||
Service::Ptr hc = host->GetHostCheckService();
|
||||
|
||||
/* ignore hosts that don't have a hostcheck */
|
||||
if (!hc)
|
||||
continue;
|
||||
|
||||
/* ignore ourselves */
|
||||
if (hc->GetName() == GetName())
|
||||
continue;
|
||||
|
||||
ObjectLock olock(hc);
|
||||
|
||||
/* ignore ourselves */
|
||||
if (hc->GetName() == service_name)
|
||||
/* ignore soft states */
|
||||
if (hc->GetStateType() == StateTypeSoft)
|
||||
continue;
|
||||
|
||||
/* ignore hosts that are up */
|
||||
if (hc && hc->GetState() == StateOK)
|
||||
if (hc->GetState() == StateOK)
|
||||
continue;
|
||||
|
||||
return false;
|
||||
@ -212,8 +261,13 @@ bool Service::IsReachable(const Service::Ptr& self)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
AcknowledgementType Service::GetAcknowledgement(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_Acknowledgement.IsEmpty())
|
||||
return AcknowledgementNone;
|
||||
|
||||
@ -233,47 +287,78 @@ AcknowledgementType Service::GetAcknowledgement(void)
|
||||
return avalue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetAcknowledgement(AcknowledgementType acknowledgement)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_Acknowledgement = acknowledgement;
|
||||
Touch("acknowledgement");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
bool Service::IsAcknowledged(void)
|
||||
{
|
||||
return GetAcknowledgement() != AcknowledgementNone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
double Service::GetAcknowledgementExpiry(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_AcknowledgementExpiry.IsEmpty())
|
||||
return 0;
|
||||
|
||||
return static_cast<double>(m_AcknowledgementExpiry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::SetAcknowledgementExpiry(double timestamp)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_AcknowledgementExpiry = timestamp;
|
||||
Touch("acknowledgement_expiry");
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::AcknowledgeProblem(AcknowledgementType type, double expiry)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
SetAcknowledgement(type);
|
||||
SetAcknowledgementExpiry(expiry);
|
||||
|
||||
RequestNotifications(NotificationAcknowledgement);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::ClearAcknowledgement(void)
|
||||
{
|
||||
SetAcknowledgement(AcknowledgementNone);
|
||||
SetAcknowledgementExpiry(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void Service::OnAttributeChanged(const String& name, const Value& oldValue)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
Service::Ptr self;
|
||||
String service_name;
|
||||
bool abstract;
|
||||
@ -311,23 +396,24 @@ void Service::OnAttributeChanged(const String& name, const Value& oldValue)
|
||||
}
|
||||
}
|
||||
|
||||
set<Host::Ptr> Service::GetParentHosts(const Service::Ptr& self)
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
set<Host::Ptr> Service::GetParentHosts(void) const
|
||||
{
|
||||
set<Host::Ptr> parents;
|
||||
|
||||
Dictionary::Ptr dependencies;
|
||||
Host::Ptr host = GetHost();
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
|
||||
/* The service's host is implicitly a parent. */
|
||||
parents.insert(self->GetHost());
|
||||
|
||||
dependencies = self->GetHostDependencies();
|
||||
}
|
||||
/* The service's host is implicitly a parent. */
|
||||
if (host)
|
||||
parents.insert(host);
|
||||
|
||||
Dictionary::Ptr dependencies = GetHostDependencies();
|
||||
|
||||
if (dependencies) {
|
||||
ObjectLock olock(dependencies);
|
||||
|
||||
String key;
|
||||
BOOST_FOREACH(tie(key, tuples::ignore), dependencies) {
|
||||
Host::Ptr host = Host::GetByName(key);
|
||||
@ -342,29 +428,26 @@ set<Host::Ptr> Service::GetParentHosts(const Service::Ptr& self)
|
||||
return parents;
|
||||
}
|
||||
|
||||
set<Service::Ptr> Service::GetParentServices(const Service::Ptr& self)
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
set<Service::Ptr> Service::GetParentServices(void) const
|
||||
{
|
||||
set<Service::Ptr> parents;
|
||||
|
||||
Dictionary::Ptr dependencies;
|
||||
Host::Ptr host;
|
||||
String service_name;
|
||||
Host::Ptr host = GetHost();
|
||||
Dictionary::Ptr dependencies = GetServiceDependencies();
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
dependencies = self->GetServiceDependencies();
|
||||
host = self->GetHost();
|
||||
service_name = self->GetName();
|
||||
}
|
||||
|
||||
if (dependencies) {
|
||||
if (host && dependencies) {
|
||||
String key;
|
||||
Value value;
|
||||
BOOST_FOREACH(tie(key, value), dependencies) {
|
||||
Service::Ptr service = Host::GetServiceByShortName(host, value);
|
||||
ObjectLock olock(service);
|
||||
Service::Ptr service = host->GetServiceByShortName(value);
|
||||
|
||||
if (service->GetName() == service_name)
|
||||
if (!service)
|
||||
continue;
|
||||
|
||||
if (service->GetName() == GetName())
|
||||
continue;
|
||||
|
||||
parents.insert(service);
|
||||
@ -374,25 +457,27 @@ set<Service::Ptr> Service::GetParentServices(const Service::Ptr& self)
|
||||
return parents;
|
||||
}
|
||||
|
||||
Dictionary::Ptr Service::CalculateDynamicMacros(const Service::Ptr& self)
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr Service::CalculateDynamicMacros(void) const
|
||||
{
|
||||
Dictionary::Ptr macros = boost::make_shared<Dictionary>();
|
||||
ObjectLock mlock(macros);
|
||||
|
||||
Dictionary::Ptr cr;
|
||||
|
||||
{
|
||||
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());
|
||||
ObjectLock olock(this);
|
||||
macros->Set("SERVICEDESC", GetShortName());
|
||||
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());
|
||||
macros->Set("SERVICECHECKCOMMAND", "check_i2");
|
||||
|
||||
cr = self->GetLastCheckResult();
|
||||
cr = GetLastCheckResult();
|
||||
}
|
||||
|
||||
if (cr) {
|
||||
|
@ -106,12 +106,12 @@ public:
|
||||
String GetHostName(void) const;
|
||||
String GetShortName(void) const;
|
||||
|
||||
static Dictionary::Ptr CalculateDynamicMacros(const Service::Ptr& self);
|
||||
Dictionary::Ptr CalculateDynamicMacros(void) const;
|
||||
|
||||
static set<Host::Ptr> GetParentHosts(const Service::Ptr& self);
|
||||
static set<Service::Ptr> GetParentServices(const Service::Ptr& self);
|
||||
set<Host::Ptr> GetParentHosts(void) const;
|
||||
set<Service::Ptr> GetParentServices(void) const;
|
||||
|
||||
static bool IsReachable(const Service::Ptr& self);
|
||||
bool IsReachable(void) const;
|
||||
|
||||
AcknowledgementType GetAcknowledgement(void);
|
||||
void SetAcknowledgement(AcknowledgementType acknowledgement);
|
||||
@ -165,7 +165,6 @@ public:
|
||||
double GetAcknowledgementExpiry(void) const;
|
||||
void SetAcknowledgementExpiry(double timestamp);
|
||||
|
||||
void ApplyCheckResult(const Dictionary::Ptr& cr);
|
||||
static void UpdateStatistics(const Dictionary::Ptr& cr);
|
||||
|
||||
void AcknowledgeProblem(AcknowledgementType type, double expiry = 0);
|
||||
@ -238,9 +237,9 @@ public:
|
||||
double GetNotificationInterval(void) const;
|
||||
|
||||
void RequestNotifications(NotificationType type);
|
||||
static void SendNotifications(const Service::Ptr& self, NotificationType type);
|
||||
void SendNotifications(NotificationType type);
|
||||
|
||||
static set<Notification::Ptr> GetNotifications(const Service::Ptr& self);
|
||||
set<Notification::Ptr> GetNotifications(void) const;
|
||||
|
||||
static void InvalidateNotificationsCache(void);
|
||||
|
||||
|
@ -37,29 +37,49 @@ ServiceGroup::ServiceGroup(const Dictionary::Ptr& properties)
|
||||
|
||||
ServiceGroup::~ServiceGroup(void)
|
||||
{
|
||||
RefreshMembersCache();
|
||||
InvalidateMembersCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void ServiceGroup::OnRegistrationCompleted(void)
|
||||
{
|
||||
RefreshMembersCache();
|
||||
assert(!OwnsLock());
|
||||
|
||||
InvalidateMembersCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String ServiceGroup::GetDisplayName(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (!m_DisplayName.Get().IsEmpty())
|
||||
return m_DisplayName;
|
||||
else
|
||||
return GetName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String ServiceGroup::GetNotesUrl(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_NotesUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String ServiceGroup::GetActionUrl(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_ActionUrl;
|
||||
}
|
||||
|
||||
@ -76,21 +96,17 @@ ServiceGroup::Ptr ServiceGroup::GetByName(const String& name)
|
||||
return dynamic_pointer_cast<ServiceGroup>(configObject);
|
||||
}
|
||||
|
||||
set<Service::Ptr> ServiceGroup::GetMembers(const ServiceGroup::Ptr& self)
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
set<Service::Ptr> ServiceGroup::GetMembers(void) const
|
||||
{
|
||||
String name;
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
name = self->GetName();
|
||||
}
|
||||
|
||||
set<Service::Ptr> services;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
|
||||
BOOST_FOREACH(const Service::WeakPtr& wservice, m_MembersCache[name]) {
|
||||
BOOST_FOREACH(const Service::WeakPtr& wservice, m_MembersCache[GetName()]) {
|
||||
Service::Ptr service = wservice.lock();
|
||||
|
||||
if (!service)
|
||||
@ -103,18 +119,22 @@ set<Service::Ptr> ServiceGroup::GetMembers(const ServiceGroup::Ptr& self)
|
||||
return services;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void ServiceGroup::InvalidateMembersCache(void)
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
|
||||
if (m_MembersCacheValid)
|
||||
Utility::QueueAsyncCallback(boost::bind(&ServiceGroup::RefreshMembersCache));
|
||||
if (m_MembersCacheValid)
|
||||
Utility::QueueAsyncCallback(boost::bind(&ServiceGroup::RefreshMembersCache));
|
||||
|
||||
m_MembersCacheValid = false;
|
||||
}
|
||||
m_MembersCacheValid = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void ServiceGroup::RefreshMembersCache(void)
|
||||
{
|
||||
{
|
||||
|
@ -43,7 +43,7 @@ public:
|
||||
String GetNotesUrl(void) const;
|
||||
String GetActionUrl(void) const;
|
||||
|
||||
static set<Service::Ptr> GetMembers(const ServiceGroup::Ptr& self);
|
||||
set<Service::Ptr> GetMembers(void) const;
|
||||
|
||||
static void InvalidateMembersCache(void);
|
||||
|
||||
|
@ -36,12 +36,20 @@ User::~User(void)
|
||||
UserGroup::InvalidateMembersCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void User::OnAttributeChanged(const String& name, const Value& oldValue)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
if (name == "groups")
|
||||
UserGroup::InvalidateMembersCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
User::Ptr User::GetByName(const String& name)
|
||||
{
|
||||
DynamicObject::Ptr configObject = DynamicObject::GetObject("User", name);
|
||||
@ -49,33 +57,48 @@ User::Ptr User::GetByName(const String& name)
|
||||
return dynamic_pointer_cast<User>(configObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String User::GetDisplayName(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (!m_DisplayName.IsEmpty())
|
||||
return m_DisplayName;
|
||||
else
|
||||
return GetName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr User::GetGroups(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr User::GetMacros(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Macros;
|
||||
}
|
||||
|
||||
Dictionary::Ptr User::CalculateDynamicMacros(const User::Ptr& self)
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
Dictionary::Ptr User::CalculateDynamicMacros(void) const
|
||||
{
|
||||
Dictionary::Ptr macros = boost::make_shared<Dictionary>();
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
macros->Set("CONTACTNAME", self->GetName());
|
||||
macros->Set("CONTACTALIAS", self->GetName());
|
||||
}
|
||||
macros->Set("CONTACTNAME", GetName());
|
||||
macros->Set("CONTACTALIAS", GetName());
|
||||
|
||||
macros->Seal();
|
||||
|
||||
|
@ -43,7 +43,7 @@ public:
|
||||
Dictionary::Ptr GetGroups(void) const;
|
||||
|
||||
Dictionary::Ptr GetMacros(void) const;
|
||||
static Dictionary::Ptr CalculateDynamicMacros(const User::Ptr& self);
|
||||
Dictionary::Ptr CalculateDynamicMacros(void) const;
|
||||
|
||||
protected:
|
||||
void OnAttributeChanged(const String& name, const Value& oldValue);
|
||||
|
@ -38,13 +38,23 @@ UserGroup::~UserGroup(void)
|
||||
InvalidateMembersCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void UserGroup::OnRegistrationCompleted(void)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
InvalidateMembersCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
String UserGroup::GetDisplayName(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (!m_DisplayName.IsEmpty())
|
||||
return m_DisplayName;
|
||||
else
|
||||
@ -64,21 +74,17 @@ UserGroup::Ptr UserGroup::GetByName(const String& name)
|
||||
return dynamic_pointer_cast<UserGroup>(configObject);
|
||||
}
|
||||
|
||||
set<User::Ptr> UserGroup::GetMembers(const UserGroup::Ptr& self)
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
set<User::Ptr> UserGroup::GetMembers(void) const
|
||||
{
|
||||
String name;
|
||||
|
||||
{
|
||||
ObjectLock olock(self);
|
||||
name = self->GetName();
|
||||
}
|
||||
|
||||
set<User::Ptr> users;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
|
||||
BOOST_FOREACH(const User::WeakPtr& wuser, m_MembersCache[name]) {
|
||||
BOOST_FOREACH(const User::WeakPtr& wuser, m_MembersCache[GetName()]) {
|
||||
User::Ptr user = wuser.lock();
|
||||
|
||||
if (!user)
|
||||
@ -91,18 +97,22 @@ set<User::Ptr> UserGroup::GetMembers(const UserGroup::Ptr& self)
|
||||
return users;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void UserGroup::InvalidateMembersCache(void)
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
boost::mutex::scoped_lock lock(m_Mutex);
|
||||
|
||||
if (m_MembersCacheValid)
|
||||
Utility::QueueAsyncCallback(boost::bind(&UserGroup::RefreshMembersCache));
|
||||
if (m_MembersCacheValid)
|
||||
Utility::QueueAsyncCallback(boost::bind(&UserGroup::RefreshMembersCache));
|
||||
|
||||
m_MembersCacheValid = false;
|
||||
}
|
||||
m_MembersCacheValid = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @threadsafety Always.
|
||||
*/
|
||||
void UserGroup::RefreshMembersCache(void)
|
||||
{
|
||||
{
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
|
||||
String GetDisplayName(void) const;
|
||||
|
||||
static set<User::Ptr> GetMembers(const UserGroup::Ptr& self);
|
||||
set<User::Ptr> GetMembers(void) const;
|
||||
|
||||
static void InvalidateMembersCache(void);
|
||||
|
||||
|
@ -54,6 +54,8 @@ PythonInterpreter::~PythonInterpreter(void)
|
||||
|
||||
void PythonInterpreter::RegisterPythonFunction(const String& name, PyObject *function)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
SubscribeFunction(name);
|
||||
|
||||
Py_INCREF(function);
|
||||
@ -62,6 +64,8 @@ void PythonInterpreter::RegisterPythonFunction(const String& name, PyObject *fun
|
||||
|
||||
void PythonInterpreter::UnregisterPythonFunction(const String& name)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
UnsubscribeFunction(name);
|
||||
|
||||
m_Functions.erase(name);
|
||||
@ -70,6 +74,8 @@ void PythonInterpreter::UnregisterPythonFunction(const String& name)
|
||||
void PythonInterpreter::ProcessCall(const ScriptTask::Ptr& task, const String& function,
|
||||
const vector<Value>& arguments)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
PyEval_AcquireThread(m_ThreadState);
|
||||
PythonInterpreter *interp = m_Language->GetCurrentInterpreter();
|
||||
m_Language->SetCurrentInterpreter(this);
|
||||
|
@ -36,6 +36,8 @@ PythonLanguage::PythonLanguage(void)
|
||||
|
||||
void PythonLanguage::InitializeOnce(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
if (m_Initialized)
|
||||
return;
|
||||
|
||||
@ -85,6 +87,8 @@ ScriptInterpreter::Ptr PythonLanguage::CreateInterpreter(const Script::Ptr& scri
|
||||
|
||||
PyThreadState *PythonLanguage::GetMainThreadState(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_MainThreadState;
|
||||
}
|
||||
|
||||
@ -139,6 +143,8 @@ PyObject *PythonLanguage::MarshalToPython(const Value& value)
|
||||
return result;
|
||||
} else if (value.IsObjectType<Dictionary>()) {
|
||||
Dictionary::Ptr dict = value;
|
||||
ObjectLock olock(dict);
|
||||
|
||||
PyObject *pdict = PyDict_New();
|
||||
|
||||
String key;
|
||||
@ -214,6 +220,8 @@ Value PythonLanguage::MarshalFromPython(PyObject *value)
|
||||
|
||||
String PythonLanguage::ExceptionInfoToString(PyObject *type, PyObject *exc, PyObject *tb) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
PyObject *tb_dict = PyModule_GetDict(m_TracebackModule);
|
||||
PyObject *format_exception = PyDict_GetItemString(tb_dict, "format_exception");
|
||||
|
||||
@ -304,6 +312,8 @@ PyObject *PythonLanguage::PyCallNativeFunction(PyObject *self, PyObject *args)
|
||||
*/
|
||||
void PythonLanguage::RegisterNativeFunction(const String& name, const ScriptFunction::Ptr& function)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
PyThreadState *tstate = PyThreadState_Swap(m_MainThreadState);
|
||||
|
||||
PyObject *pname = PyString_FromString(name.CStr());
|
||||
@ -327,6 +337,8 @@ void PythonLanguage::RegisterNativeFunction(const String& name, const ScriptFunc
|
||||
*/
|
||||
void PythonLanguage::UnregisterNativeFunction(const String& name)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
PyThreadState *tstate = PyThreadState_Swap(m_MainThreadState);
|
||||
|
||||
PyObject *pdict = PyModule_GetDict(m_NativeModule);
|
||||
@ -378,6 +390,8 @@ PyObject *PythonLanguage::PyRegisterFunction(PyObject *self, PyObject *args)
|
||||
*/
|
||||
PythonInterpreter *PythonLanguage::GetCurrentInterpreter(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_CurrentInterpreter;
|
||||
}
|
||||
|
||||
@ -388,5 +402,7 @@ PythonInterpreter *PythonLanguage::GetCurrentInterpreter(void)
|
||||
*/
|
||||
void PythonLanguage::SetCurrentInterpreter(PythonInterpreter *interpreter)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_CurrentInterpreter = interpreter;
|
||||
}
|
||||
|
@ -72,7 +72,8 @@ Endpoint::Ptr Endpoint::MakeEndpoint(const String& name, bool replicated, bool l
|
||||
endpointConfig->SetLocal(!replicated);
|
||||
endpointConfig->AddExpression("local", OperatorSet, local);
|
||||
|
||||
DynamicObject::Ptr object = ConfigItem::Commit(endpointConfig->Compile());
|
||||
ConfigItem::Ptr item = endpointConfig->Compile();
|
||||
DynamicObject::Ptr object = item->Commit();
|
||||
return dynamic_pointer_cast<Endpoint>(object);
|
||||
}
|
||||
|
||||
@ -83,6 +84,8 @@ Endpoint::Ptr Endpoint::MakeEndpoint(const String& name, bool replicated, bool l
|
||||
*/
|
||||
bool Endpoint::IsLocalEndpoint(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Local;
|
||||
}
|
||||
|
||||
@ -104,15 +107,22 @@ bool Endpoint::IsConnected(void) const
|
||||
|
||||
JsonRpcConnection::Ptr Endpoint::GetClient(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Client;
|
||||
}
|
||||
|
||||
void Endpoint::SetClient(const JsonRpcConnection::Ptr& client)
|
||||
{
|
||||
m_Client = client;
|
||||
client->OnNewMessage.connect(boost::bind(&Endpoint::NewMessageHandler, this, _2));
|
||||
client->OnClosed.connect(boost::bind(&Endpoint::ClientClosedHandler, this));
|
||||
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_Client = client;
|
||||
}
|
||||
|
||||
OnConnected(GetSelf());
|
||||
}
|
||||
|
||||
@ -128,11 +138,8 @@ void Endpoint::RegisterSubscription(const String& topic)
|
||||
if (!subscriptions)
|
||||
subscriptions = boost::make_shared<Dictionary>();
|
||||
|
||||
ObjectLock olock(subscriptions);
|
||||
|
||||
if (!subscriptions->Contains(topic)) {
|
||||
Dictionary::Ptr newSubscriptions = subscriptions->ShallowClone();
|
||||
ObjectLock nlock(newSubscriptions);
|
||||
newSubscriptions->Set(topic, topic);
|
||||
SetSubscriptions(newSubscriptions);
|
||||
}
|
||||
@ -150,11 +157,8 @@ void Endpoint::UnregisterSubscription(const String& topic)
|
||||
if (!subscriptions)
|
||||
return;
|
||||
|
||||
ObjectLock olock(subscriptions);
|
||||
|
||||
if (subscriptions->Contains(topic)) {
|
||||
Dictionary::Ptr newSubscriptions = subscriptions->ShallowClone();
|
||||
ObjectLock nlock(newSubscriptions);
|
||||
newSubscriptions->Remove(topic);
|
||||
SetSubscriptions(newSubscriptions);
|
||||
}
|
||||
@ -178,6 +182,8 @@ bool Endpoint::HasSubscription(const String& topic) const
|
||||
*/
|
||||
void Endpoint::ClearSubscriptions(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_Subscriptions = Empty;
|
||||
Touch("subscriptions");
|
||||
}
|
||||
@ -189,12 +195,17 @@ Dictionary::Ptr Endpoint::GetSubscriptions(void) const
|
||||
|
||||
void Endpoint::SetSubscriptions(const Dictionary::Ptr& subscriptions)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
subscriptions->Seal();
|
||||
m_Subscriptions = subscriptions;
|
||||
Touch("subscriptions");
|
||||
}
|
||||
|
||||
void Endpoint::RegisterTopicHandler(const String& topic, const function<Endpoint::Callback>& callback)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
map<String, shared_ptr<signals2::signal<Endpoint::Callback> > >::iterator it;
|
||||
it = m_TopicHandlers.find(topic);
|
||||
|
||||
@ -223,6 +234,8 @@ void Endpoint::UnregisterTopicHandler(const String& topic, const function<Endpoi
|
||||
|
||||
void Endpoint::OnAttributeChanged(const String& name, const Value& oldValue)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
if (name == "subscriptions") {
|
||||
Dictionary::Ptr oldSubscriptions, newSubscriptions;
|
||||
|
||||
@ -231,10 +244,9 @@ void Endpoint::OnAttributeChanged(const String& name, const Value& oldValue)
|
||||
|
||||
newSubscriptions = GetSubscriptions();
|
||||
|
||||
ObjectLock olock(oldSubscriptions);
|
||||
ObjectLock nlock(newSubscriptions);
|
||||
|
||||
if (oldSubscriptions) {
|
||||
ObjectLock olock(oldSubscriptions);
|
||||
|
||||
String subscription;
|
||||
BOOST_FOREACH(tie(tuples::ignore, subscription), oldSubscriptions) {
|
||||
if (!newSubscriptions || !newSubscriptions->Contains(subscription)) {
|
||||
@ -245,6 +257,8 @@ void Endpoint::OnAttributeChanged(const String& name, const Value& oldValue)
|
||||
}
|
||||
|
||||
if (newSubscriptions) {
|
||||
ObjectLock olock(newSubscriptions);
|
||||
|
||||
String subscription;
|
||||
BOOST_FOREACH(tie(tuples::ignore, subscription), newSubscriptions) {
|
||||
if (!oldSubscriptions || !oldSubscriptions->Contains(subscription)) {
|
||||
@ -264,6 +278,8 @@ void Endpoint::ProcessRequest(const Endpoint::Ptr& sender, const RequestMessage&
|
||||
}
|
||||
|
||||
if (IsLocalEndpoint()) {
|
||||
ObjectLock olock(this);
|
||||
|
||||
String method;
|
||||
if (!request.GetMethod(&method))
|
||||
return;
|
||||
@ -317,6 +333,8 @@ void Endpoint::NewMessageHandler(const MessagePart& message)
|
||||
|
||||
void Endpoint::ClientClosedHandler(void)
|
||||
{
|
||||
assert(!OwnsLock());
|
||||
|
||||
/*try {
|
||||
GetClient()->CheckException();
|
||||
} catch (const exception& ex) {
|
||||
@ -328,12 +346,16 @@ void Endpoint::ClientClosedHandler(void)
|
||||
|
||||
Logger::Write(LogWarning, "jsonrpc", "Lost connection to endpoint: identity=" + GetName());
|
||||
|
||||
// TODO: _only_ clear non-persistent subscriptions
|
||||
// unregister ourselves if no persistent subscriptions are left (use a
|
||||
// timer for that, once we have a TTL property for the topics)
|
||||
ClearSubscriptions();
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_Client.reset();
|
||||
// TODO: _only_ clear non-persistent subscriptions
|
||||
// unregister ourselves if no persistent subscriptions are left (use a
|
||||
// timer for that, once we have a TTL property for the topics)
|
||||
ClearSubscriptions();
|
||||
|
||||
m_Client.reset();
|
||||
}
|
||||
|
||||
OnDisconnected(GetSelf());
|
||||
}
|
||||
@ -345,6 +367,8 @@ void Endpoint::ClientClosedHandler(void)
|
||||
*/
|
||||
String Endpoint::GetNode(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Node;
|
||||
}
|
||||
|
||||
@ -355,5 +379,7 @@ String Endpoint::GetNode(void) const
|
||||
*/
|
||||
String Endpoint::GetService(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Service;
|
||||
}
|
||||
|
@ -50,6 +50,8 @@ EndpointManager::EndpointManager(void)
|
||||
*/
|
||||
void EndpointManager::SetSSLContext(const shared_ptr<SSL_CTX>& sslContext)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_SSLContext = sslContext;
|
||||
}
|
||||
|
||||
@ -60,6 +62,8 @@ void EndpointManager::SetSSLContext(const shared_ptr<SSL_CTX>& sslContext)
|
||||
*/
|
||||
shared_ptr<SSL_CTX> EndpointManager::GetSSLContext(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_SSLContext;
|
||||
}
|
||||
|
||||
@ -71,6 +75,8 @@ shared_ptr<SSL_CTX> EndpointManager::GetSSLContext(void) const
|
||||
*/
|
||||
void EndpointManager::SetIdentity(const String& identity)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_Identity = identity;
|
||||
|
||||
if (m_Endpoint)
|
||||
@ -91,6 +97,8 @@ void EndpointManager::SetIdentity(const String& identity)
|
||||
*/
|
||||
String EndpointManager::GetIdentity(void) const
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
return m_Identity;
|
||||
}
|
||||
|
||||
@ -101,6 +109,8 @@ String EndpointManager::GetIdentity(void) const
|
||||
*/
|
||||
void EndpointManager::AddListener(const String& service)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
shared_ptr<SSL_CTX> sslContext = GetSSLContext();
|
||||
|
||||
if (!sslContext)
|
||||
@ -128,6 +138,8 @@ void EndpointManager::AddListener(const String& service)
|
||||
* @param service The remote port.
|
||||
*/
|
||||
void EndpointManager::AddConnection(const String& node, const String& service) {
|
||||
ObjectLock olock(this);
|
||||
|
||||
shared_ptr<SSL_CTX> sslContext = GetSSLContext();
|
||||
|
||||
if (!sslContext)
|
||||
@ -145,6 +157,8 @@ void EndpointManager::AddConnection(const String& node, const String& service) {
|
||||
*/
|
||||
void EndpointManager::NewClientHandler(const Socket::Ptr& client, TlsRole role)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
String peerAddress = client->GetPeerAddress();
|
||||
TlsStream::Ptr tlsStream = boost::make_shared<TlsStream>(client, role, GetSSLContext());
|
||||
tlsStream->Start();
|
||||
@ -158,6 +172,8 @@ void EndpointManager::NewClientHandler(const Socket::Ptr& client, TlsRole role)
|
||||
|
||||
void EndpointManager::ClientConnectedHandler(const Stream::Ptr& client, const String& peerAddress)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
TlsStream::Ptr tlsStream = static_pointer_cast<TlsStream>(client);
|
||||
JsonRpcConnection::Ptr jclient = boost::make_shared<JsonRpcConnection>(tlsStream);
|
||||
|
||||
@ -178,6 +194,8 @@ void EndpointManager::ClientConnectedHandler(const Stream::Ptr& client, const St
|
||||
|
||||
void EndpointManager::ClientClosedHandler(const Stream::Ptr& client)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
TlsStream::Ptr tlsStream = static_pointer_cast<TlsStream>(client);
|
||||
m_PendingClients.erase(tlsStream);
|
||||
}
|
||||
@ -293,6 +311,8 @@ void EndpointManager::SendAPIMessage(const Endpoint::Ptr& sender, const Endpoint
|
||||
RequestMessage& message,
|
||||
const EndpointManager::APICallback& callback, double timeout)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
m_NextMessageID++;
|
||||
|
||||
stringstream idstream;
|
||||
@ -337,7 +357,7 @@ void EndpointManager::SubscriptionTimerHandler(void)
|
||||
ObjectLock olock(endpointSubscriptions);
|
||||
|
||||
String topic;
|
||||
BOOST_FOREACH(tie(tuples::ignore, topic), endpoint->GetSubscriptions()) {
|
||||
BOOST_FOREACH(tie(tuples::ignore, topic), endpointSubscriptions) {
|
||||
subscriptions->Set(topic, topic);
|
||||
}
|
||||
}
|
||||
@ -374,6 +394,8 @@ void EndpointManager::ReconnectTimerHandler(void)
|
||||
|
||||
void EndpointManager::RequestTimerHandler(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
map<String, PendingRequest>::iterator it;
|
||||
for (it = m_Requests.begin(); it != m_Requests.end(); it++) {
|
||||
if (it->second.HasTimedOut()) {
|
||||
@ -390,6 +412,8 @@ void EndpointManager::RequestTimerHandler(void)
|
||||
void EndpointManager::ProcessResponseMessage(const Endpoint::Ptr& sender,
|
||||
const ResponseMessage& message)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
String id;
|
||||
if (!message.GetID(&id))
|
||||
BOOST_THROW_EXCEPTION(invalid_argument("Response message must have a message ID."));
|
||||
|
@ -37,6 +37,8 @@ JsonRpcConnection::JsonRpcConnection(const Stream::Ptr& stream)
|
||||
*/
|
||||
void JsonRpcConnection::SendMessage(const MessagePart& message)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
Value value = message.GetDictionary();
|
||||
String json = value.Serialize();
|
||||
//std::cerr << ">> " << json << std::endl;
|
||||
@ -48,6 +50,8 @@ void JsonRpcConnection::SendMessage(const MessagePart& message)
|
||||
*/
|
||||
void JsonRpcConnection::ProcessData(void)
|
||||
{
|
||||
ObjectLock olock(this);
|
||||
|
||||
String jsonString;
|
||||
|
||||
while (NetString::ReadStringFromStream(GetStream(), &jsonString)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user