]> granicus.if.org Git - icinga2/commitdiff
More lock refactoring. Yay.
authorGunnar Beutner <gunnar.beutner@netways.de>
Sat, 2 Mar 2013 08:07:47 +0000 (09:07 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Sat, 2 Mar 2013 08:07:47 +0000 (09:07 +0100)
67 files changed:
components/checker/checkercomponent.cpp
components/checker/checkercomponent.h
components/compat/compatcomponent.cpp
components/compat/compatcomponent.h
components/delegation/delegationcomponent.cpp
components/demo/democomponent.cpp
components/notification/notificationcomponent.cpp
lib/base/application.cpp
lib/base/application.h
lib/base/component.cpp
lib/base/component.h
lib/base/dynamicobject.cpp
lib/base/dynamicobject.h
lib/base/dynamictype.cpp
lib/base/object.cpp
lib/base/object.h
lib/base/objectlock.cpp
lib/base/objectlock.h
lib/base/script.cpp
lib/base/scriptfunction.cpp
lib/base/scriptfunction.h
lib/base/scripttask.cpp
lib/base/socket.cpp
lib/base/socket.h
lib/base/stdiostream.cpp
lib/base/stream.cpp
lib/base/stream_bio.cpp
lib/base/streamlogger.cpp
lib/base/sysloglogger.cpp
lib/base/tcpsocket.cpp
lib/base/tlsstream.cpp
lib/config/configcompilercontext.cpp
lib/config/configitem.cpp
lib/config/configitem.h
lib/icinga/api.cpp
lib/icinga/checkresultmessage.cpp
lib/icinga/externalcommandprocessor.cpp
lib/icinga/host.cpp
lib/icinga/host.h
lib/icinga/hostgroup.cpp
lib/icinga/hostgroup.h
lib/icinga/icingaapplication.cpp
lib/icinga/icingaapplication.h
lib/icinga/macroprocessor.cpp
lib/icinga/notification.cpp
lib/icinga/notification.h
lib/icinga/nullchecktask.cpp
lib/icinga/perfdatawriter.cpp
lib/icinga/pluginchecktask.cpp
lib/icinga/pluginnotificationtask.cpp
lib/icinga/service-check.cpp
lib/icinga/service-comment.cpp
lib/icinga/service-downtime.cpp
lib/icinga/service-notification.cpp
lib/icinga/service.cpp
lib/icinga/service.h
lib/icinga/servicegroup.cpp
lib/icinga/servicegroup.h
lib/icinga/user.cpp
lib/icinga/user.h
lib/icinga/usergroup.cpp
lib/icinga/usergroup.h
lib/python/pythoninterpreter.cpp
lib/python/pythonlanguage.cpp
lib/remoting/endpoint.cpp
lib/remoting/endpointmanager.cpp
lib/remoting/jsonrpcconnection.cpp

index 75157c2b10399715bcf974b455e78657126acd4a..2ae2677dbb05f77c2316e3fbb566b6ae19482bd3 100644 (file)
@@ -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);
index 9170d0498803f92c2f7475730ccf6be7362951de..fc34b1c6425cae78f2500686082d18fc192faf12 100644 (file)
@@ -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)
        {
index 13520301dd7c1d8d426d8dd56533b76d9013bf1c..cb3dc3c6963870fae69c112eec45472f792221e2 100644 (file)
@@ -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);
-
-               downtimes = owner->GetDowntimes();
-               short_name = owner->GetShortName();
-               host = owner->GetHost();
-       }
+       if (!host)
+               return;
 
-       {
-               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();
 
-       {
-               ObjectLock olock(service);
+               if (!host)
+                       return;
 
-               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";
+               if (!host->IsReachable())
+                       state = 2; /* UNREACHABLE */
        }
+
+       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;
-
-                       {
-                               ObjectLock olock(service);
-                               host = service->GetHost();
-                               short_name = service->GetShortName();
-                       }
+               BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
+                       Host::Ptr host = service->GetHost();
 
-                       {
-                               ObjectLock olock(host);
-                               host_name = host->GetName();
-                       }
+                       if (!host)
+                               continue;
 
-                       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";
 
index eda87c0434f51d2f2ddb35dab120d837451b89e0..3c9e1a9e0c5ecfa645eec25436dc9436fa164650 100644 (file)
@@ -43,7 +43,6 @@ private:
        thread m_CommandThread;
 
        void CommandPipeThread(const String& commandPath);
-       void ProcessCommand(const String& command);
 #endif /* _WIN32 */
 
        Timer::Ptr m_StatusTimer;
index 98a3fb0f86783e734087320a6dd1272b721400f7..9f4e059fb47b02494c8861d4303e37552233e24e 100644 (file)
@@ -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());
index 355f5014ce2420209b664abefd25c3dd0e15bc7a..a974f832f1f469aaec3c5b2bf189b2c4aaf79b4c 100644 (file)
@@ -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);
 }
 
 /**
index f8f6018d5adc0e6b272f5e45f940ec23d4c90fd5..02ba944e20ba860b7b8c5467309df9f869d1f570 100644 (file)
@@ -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));
 }
index 3ccf0e32be2804b857f5d4c6fa103756654664f9..c16b158f3379e6c1289d10bfa55fd5bd355d23c0 100644 (file)
@@ -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);
 
index ddfc2c322e9aafa3fe160bb2d4610e9ac1b6f6de..08352dac517ce5741229acae7154d869d6e662d0 100644 (file)
@@ -37,7 +37,7 @@ public:
        Application(const Dictionary::Ptr& serializedUpdate);
        ~Application(void);
 
-       static Application *GetInstance(void);
+       static Application::Ptr GetInstance(void);
 
        int Run(void);
 
index f72a35cc4523290ea8d70eab7afe660e2f9821f9..5d8b81edc92c7ee6dbae8dc44829850ac26cd626 100644 (file)
@@ -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)
-               BOOST_THROW_EXCEPTION(runtime_error("Component factory returned NULL."));
+               if (it == m_Factories.end())
+                       BOOST_THROW_EXCEPTION(invalid_argument("Unknown component: " + GetName()));
+
+               factory = it->second;
+       }
 
-       m_Impl = impl;
+       m_Impl = factory();
+
+       if (!m_Impl)
+               BOOST_THROW_EXCEPTION(runtime_error("Component factory returned NULL."));
 }
 
 /**
@@ -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;
 }
index 003729da9c46fceb08252849c27f44edc7e85614..d6a9a8213bf8bd90ed5524343add9d8e1e17e31d 100644 (file)
@@ -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;
 };
 
index 374423b1fe55d3c0752f240dc4ca299dde03b99e..9650fd979100e8012af7350e4ab6ee08e258397b 100644 (file)
@@ -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;
-}
index ddfce211a301700a6866b3ff2f75f24a60d1027f..3e40604633224c0f6fdcaa185208678422ae23f3 100644 (file)
@@ -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;
 
index 1cf5f21f1bc958dd7346a2fb305f35600c3741d1..10390ff60f45341f3320b7cf597dffeac3a2bc30 100644 (file)
@@ -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();
 }
 
 /**
index 8acfba85bda1fdeda5312f592c830619cebb0463..d629f3f7e966918f662ea0fae5e288b5a883d82f 100644 (file)
@@ -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 */
index c200ad9d4a3fadcdede745c860b2ab1ed2c4c223..faa9c76d9bbbc232bd4f721e6f0747ed069c1baa 100644 (file)
@@ -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;
 };
index eb9b96483f02e3724bae0406e80efc3bacd341ac..1451810a591370fc9738cfe52585e75602d1112e 100644 (file)
 
 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();
 }
index 34aa38fa781edabc41b92ca3b5986b08709f04e7..0d5bdd731025e13088d15c62b744ad31a9afe54e 100644 (file)
@@ -39,6 +39,9 @@ public:
 private:
        const Object *m_Object;
        recursive_mutex::scoped_lock m_Lock;
+#ifdef _DEBUG
+       double m_TS;
+#endif /* _DEBUG */
 };
 
 }
index 4db0837c35cc2a95b1005d4767eb6bd8b6c267c2..9ea097b7c2900aacb17229f453a4ddd72d2ecb02 100644 (file)
@@ -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() + "'");
index f401e1027062d2cbe6c4cf346afc2ee21492d87d..e2f8fc32a06c209cf6b9f10d54f32c540f26591e 100644 (file)
@@ -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;
index 74c450b9d1286ad40362fd941802e12642b162a7..3a7b4167becdb0820251360137d457043e7aab9c 100644 (file)
@@ -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;
 };
 
 /**
index 4f0420d7cf384954765a35c3d158c250184409d0..5ef9030b5542e3c6cdcfea87f3ed50b1bbf6875f 100644 (file)
@@ -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);
 }
index d860bf8cffaec11ce2d8a5b4e9af66697c267fe5..6e6c9295077657d2df2df36598dd3989f49f0370 100644 (file)
@@ -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,11 +90,18 @@ void Socket::SetFD(SOCKET fd)
  */
 SOCKET Socket::GetFD(void) const
 {
+       ObjectLock olock(this);
+
        return m_FD;
 }
 
-void Socket::CloseUnlocked(void)
+/**
+ * Closes the socket.
+ */
+void Socket::Close(void)
 {
+       ObjectLock olock(this);
+
        if (m_FD == INVALID_SOCKET)
                return;
 
@@ -100,15 +111,6 @@ void Socket::CloseUnlocked(void)
        Stream::Close();
 }
 
-/**
- * Closes the socket.
- */
-void Socket::Close(void)
-{
-       boost::mutex::scoped_lock lock(m_SocketMutex);
-       CloseUnlocked();
-}
-
 /**
  * Retrieves the last error that occured for the socket.
  *
@@ -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->GetAvailableBytes();
+               count = m_SendQueue->Peek(data, sizeof(data));
 
-                       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());
 }
index 4d586024399bec301e3c59493a99f5eb29249ad9..a5d86a49ca06bcc40e69fb6041189b61c32644cb 100644 (file)
@@ -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);
 };
 
 /**
index efa0cc15d5ca680d3311a6f4984e66cb07289f32..3299da0bb4215f0080d0ff6b10a89d0af8c41135 100644 (file)
@@ -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);
index b6e7a03a0245da9875bd69e84a446c066e536f69..0e34891eb1d9554c127c4a2b641fff4dcad3be16 100644 (file)
@@ -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;
 
index 885bdaa04a370f1c8eacdb7672d51b038903df86..7f7051e3e52ca55d8b57718f659fb0d551927c18 100644 (file)
@@ -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) {
index 27cf7744fd9d3f9df2c09ef1bcb2173a0e7232e6..3b149cca739e7a45a5ba9d4d5d6f6a336379b62f 100644 (file)
@@ -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
index 838d461f1c8c8e4a572e51e4d2a12d2ef0448e67..57d674fb3ec60579d9761ac2fa76a5d2e469e03e 100644 (file)
@@ -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)
 {
index a235ce6c6d97c897516a79f543364b08ee6c6981..bbd35505bc7dcd246f26faba6e7fbd73c48178cd 100644 (file)
@@ -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)
 {
index c3e16b5a6b038f956a913734832056c5df6e9e28..29e81586cfa377ae9870f19f9468da90fd10aa55 100644 (file)
@@ -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();
 }
index fc2c1e365c83dfb2e2d6ddfdecc2080bebd56eca..f0ea29ce0b52b04a7916fea9f35938a8453bf739 100644 (file)
@@ -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();
        }
 }
index 7eafa0afe39221683e1cda4448f47983eda59c39..1d0893f38b457965afa9ebe9f65880b19670f395 100644 (file)
@@ -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)
 {
-       String type, name;
-       DynamicObject::Ptr dobj;
-       vector<String> parents;
-       Dictionary::Ptr properties;
+       assert(!OwnsLock());
 
-       {
-               ObjectLock olock(self);
-               type = self->GetType();
-               name = self->GetName();
-               dobj = self->GetDynamicObject();
-               parents = self->GetParents();
-               properties = self->Link();
-       }
+       String type, name;
 
-       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())
+                       oldItem = it->second;
+       }
 
-               if (it != m_Items.end()) {
-                       /* Unregister the old item from its parents. */
-                       ConfigItem::Ptr oldItem = it->second;
-                       ObjectLock olock(oldItem);
-                       oldItem->UnregisterFromParents();
+       set<ConfigItem::WeakPtr> children;
 
-                       /* Steal the old item's children. */
-                       children = oldItem->GetChildren();
-               }
+       if (oldItem) {
+               ObjectLock olock(oldItem);
 
-               {
-                       ObjectLock olock(self);
-                       self->m_ChildObjects = children;
-               }
+               /* 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] = self;
+               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,28 +275,19 @@ DynamicObject::Ptr ConfigItem::Commit(const ConfigItem::Ptr& self)
                was_null = true;
        }
 
-       {
-               ObjectLock olock(dobj);
-
-               if (!was_null)
-                       dobj->ApplyUpdate(update, Attribute_Config);
+       if (!was_null)
+               dobj->ApplyUpdate(update, Attribute_Config);
 
-               self->m_DynamicObject = dobj;
+       {
+               ObjectLock olock(this);
 
-               if (dobj->IsAbstract())
-                       dobj->Unregister();
-               else
-                       dobj->Register();
+               m_DynamicObject = dobj;
        }
 
-       /* We need to make a copy of the child objects because the
-        * OnParentCommitted() handler is going to update the list. */
-       set<ConfigItem::WeakPtr> children;
-
-       {
-               ObjectLock olock(self);
-               children = self->m_ChildObjects;
-       }
+       if (dobj->IsAbstract())
+               dobj->Unregister();
+       else
+               dobj->Register();
 
        /* notify our children of the update */
        BOOST_FOREACH(const ConfigItem::WeakPtr wchild, children) {
@@ -289,7 +299,7 @@ DynamicObject::Ptr ConfigItem::Commit(const ConfigItem::Ptr& self)
                child->OnParentCommitted();
        }
 
-       OnCommitted(self);
+       OnCommitted(GetSelf());
 
        return dobj;
 }
@@ -299,18 +309,22 @@ 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();
-       }
 
-       ConfigItem::ItemMap::iterator it;
-       it = m_Items.find(make_pair(GetType(), GetName()));
+       {
+               ObjectLock olock(this);
 
-       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();
 
@@ -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();
        }
 }
index 56c1c470767f651ce7bca6fd1514317f9cc59d90..cef45691a72458367625a8046ff5623effc867cd 100644 (file)
@@ -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;
index f4541745d18c233d8c3d07ad7cfe8a6b25082a99..4317969064f8830cd654c8763902ea8a565730bc 100644 (file)
@@ -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);
 }
index fff9d96982494aa9808593c3971d168ab2b790ea..2ecaf9c3579c02700a95ce3322b39d663a76bc7a 100644 (file)
@@ -44,4 +44,3 @@ void CheckResultMessage::SetCheckResult(const Dictionary::Ptr& result)
 {
        Set("check_result", result);
 }
-
index d303a7a150e67f6102a93b8ca88e952fb64fb2f3..f8e502dce71673882f7921854e798ee2cac4c20e 100644 (file)
@@ -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);
index 70dde422f7ebdc2813e0b18a6003174a6e1252eb..24bc40882ab4b38fa815e5836abc23b02d16cad4 100644 (file)
@@ -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;
                }
index d45f0b0e33f6ac8da2c22b954bebaa6863d063cf..76165527a11e721b94d9e44884faa0428ed361cf 100644 (file)
@@ -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);
 };
index 094b2f52b88409bc60d5e8a655816466e9d26619..bb30f94cc551b2ceebd6660b6aadc8bab8543a55 100644 (file)
@@ -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)
 {
        {
index 1e865bf8481143890c04e9217cce6c5c26559d50..3528d1b8db7c847dc73b15374fad75166ee1e699 100644 (file)
@@ -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);
 
index 287c77ee379d26c113d17b121c67523899f8298d..5c012b88d7f4c4dee79dbd61511778a3bde99314 100644 (file)
@@ -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);
index 5d39a3ea8570898eb4ee43f1e1f2ef5b788f2512..e6032e647e7413b098cd5222df18188043939de1 100644 (file)
@@ -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;
index 5bc9a2a1a6cb200d032a456ed3611ab84b861188..20507a485fa5203f5cc440119a2d680174544d04 100644 (file)
 
 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>();
index a59688976483bcda703dbd19efaaec13e673bf35..107dbfd30cc105284094b4a539d90a06151da9b6 100644 (file)
@@ -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);
 
-       ScriptTask::Ptr task;
+       Notification::Ptr self = GetSelf();
 
-       {
-               ObjectLock olock(self);
+       vector<Value> arguments;
+       arguments.push_back(self);
+       arguments.push_back(macros);
+       arguments.push_back(type);
 
-               vector<Value> arguments;
-               arguments.push_back(self);
-               arguments.push_back(macros);
-               arguments.push_back(type);
-               task = self->MakeMethodTask("notify", arguments);
+       ScriptTask::Ptr task;
+       task = MakeMethodTask("notify", arguments);
 
-               if (!task) {
-                       Logger::Write(LogWarning, "icinga", "Notification object '" + self->GetName() + "' doesn't have a 'notify' method.");
+       if (!task) {
+               Logger::Write(LogWarning, "icinga", "Notification object '" + GetName() + "' doesn't have a 'notify' method.");
 
-                       return;
-               }
+               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();
 }
index 4bbba987ee138eb915e3858aab123f30078acca9..02f52090f42a75c2d45e552948ecb58a805465ac 100644 (file)
@@ -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);
 };
 
 }
index 01d26ca7cdf2d9efc6168b8814017d2af9317a07..fef26eeaea624c1ddf21c458ff3c676ed2edcf5b 100644 (file)
@@ -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);
 }
index 845d753d228d8d22d9b453ddd465cb7181f25780..495be030e639d1518f997d02c2488d2e0c25575d 100644 (file)
@@ -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();
 }
index 6fd969ab6abd321876d481c032884c76b9b0d44d..814a1ce82c3a3ed9e7c502462843df2de8eb2da8 100644 (file)
@@ -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>();
index 0b5fba893b90c65f19376e96e610d55264d26903..d83b27e0ef988bdeab1fe91179ea8bc325913399 100644 (file)
@@ -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;
-       String service_name;
-       Service::Ptr service;
+       Value raw_command = notification->GetNotificationCommand();
 
-       {
-               ObjectLock olock(notification);
-               raw_command = notification->GetNotificationCommand();
-               service = notification->GetService();
-       }
+       String service_name;
 
-       {
-               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;
index 57b6f1a87c4dd7c42e38ea22defca8af155c03c6..2a3ff40c66de5b550a446aafe4ebc0f810d4530d 100644 (file)
@@ -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();
        }
 
-       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");
+       /* 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();
 
-       /* 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);
+       callback();
 }
 
+/**
+ * @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;
 
index c3277b2f21b456011f3add683ccca05eae0804c3..5791c7bf17bbdefa41761d43f2829b93406ff8ac 100644 (file)
@@ -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();
        }
 }
index 95ecfc3a74ea87bf0b091ce8c90846c19701d5cd..236d811482e70695342a5f85c1b5466f01deed8a 100644 (file)
@@ -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();
index 63ee72335219c33baf1eed38d37aa4ba41607290..85dfe44f4351e4397f4f7850d05bc28bdc8c0a53 100644 (file)
@@ -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();
-               }
-
-               String service_name;
-
-               {
-                       ObjectLock olock(service);
-                       service_name = service->GetName();
-               }
+               if (!service)
+                       continue;
 
-               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
index cc40a1d93b9cc3b6aa3b7cb3d86f32070bb0d6f9..a9facf1dfa383e53baab84c5b9b6a98fbe94e79c 100644 (file)
@@ -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) {
index 9bac7289cd9751200f387a1c919b13bd59237b2b..070c45cf717d670015dfd720d56e45a064650722 100644 (file)
@@ -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);
 
index e01b4e89ad576a5a895cd853c094848dae8ce41c..b60e4e4210e2ab768274ee979d47c44545a55b42 100644 (file)
@@ -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)
 {
        {
index 073f515bf8355b083d4241171175f4b24d66557b..6451eacad852949e67f0551bcb74fc61d4fa9c28 100644 (file)
@@ -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);
 
index 517cc81886ce8e2eb8e2fa8b191385bf6f3fd227..e707f36fffa588f2d42cad09a7ac25a537f6a2f8 100644 (file)
@@ -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();
 
index 9245cb0f455beb3dfba709b3de1a027b8a771804..5b09c227c1468d6e1df0d59f51f20788782c99fa 100644 (file)
@@ -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);
index 350ec30effaad8f0f598aefc1a5642b45007098c..bd788267612c7865b81500b0a2b2570b3ab5b2cd 100644 (file)
@@ -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)
 {
        {
index 8ad92b33728479bee0a7a75e769e969e48b49dda..986e530a61b09830db03405829f5bcc332592929 100644 (file)
@@ -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);
 
index 8cd1b3937dbfec02aae1b3bd22398f2effd2eaa8..0410a924e318b28c0ce07258a2786ed7ad6e6ce5 100644 (file)
@@ -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);
index 5fb894c76b4d35ac0eb4a5676bf729b28f8a4891..e9491472122ba92951d0a8a5821123e0ff23cee3 100644 (file)
@@ -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;
 }
index 82d03ee3595a97995d970c32f1529c39f191e193..59d5efbf102cf62e988594c0812b7d12e1b08e08 100644 (file)
@@ -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);
+
+               // 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();
+               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;
 }
index eaa8d9cb26a1c928eaa7c0383ee2431d0905abb6..41899ea606795999618fca76977c646e9caf95f4 100644 (file)
@@ -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."));
index 15fc68461a6442bec0bc80a35e8858a45e44d683..b66ad9f7a1c023e41a9f86fe48b71a3a8e91b2c1 100644 (file)
@@ -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)) {