]> granicus.if.org Git - icinga2/blob - components/checker/checkercomponent.cpp
Use BOOST_THROW_EXCEPTION instead of boost::throw_exception()
[icinga2] / components / checker / checkercomponent.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
4  *                                                                            *
5  * This program is free software; you can redistribute it and/or              *
6  * modify it under the terms of the GNU General Public License                *
7  * as published by the Free Software Foundation; either version 2             *
8  * of the License, or (at your option) any later version.                     *
9  *                                                                            *
10  * This program is distributed in the hope that it will be useful,            *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
13  * GNU General Public License for more details.                               *
14  *                                                                            *
15  * You should have received a copy of the GNU General Public License          *
16  * along with this program; if not, write to the Free Software Foundation     *
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
18  ******************************************************************************/
19
20 #include "i2-checker.h"
21
22 using namespace icinga;
23
24 void CheckerComponent::Start(void)
25 {
26         m_Endpoint = Endpoint::MakeEndpoint("checker", false);
27
28         /* dummy registration so the delegation module knows this is a checker
29            TODO: figure out a better way for this */
30         m_Endpoint->RegisterSubscription("checker");
31
32         Service::OnCheckerChanged.connect(bind(&CheckerComponent::CheckerChangedHandler, this, _1));
33         Service::OnNextCheckChanged.connect(bind(&CheckerComponent::NextCheckChangedHandler, this, _1));
34         DynamicObject::OnUnregistered.connect(bind(&CheckerComponent::ObjectRemovedHandler, this, _1));
35
36         m_CheckTimer = boost::make_shared<Timer>();
37         m_CheckTimer->SetInterval(1);
38         m_CheckTimer->OnTimerExpired.connect(boost::bind(&CheckerComponent::CheckTimerHandler, this));
39         m_CheckTimer->Start();
40
41         m_ResultTimer = boost::make_shared<Timer>();
42         m_ResultTimer->SetInterval(5);
43         m_ResultTimer->OnTimerExpired.connect(boost::bind(&CheckerComponent::ResultTimerHandler, this));
44         m_ResultTimer->Start();
45 }
46
47 void CheckerComponent::Stop(void)
48 {
49         m_Endpoint->Unregister();
50 }
51
52 void CheckerComponent::CheckTimerHandler(void)
53 {
54         Logger::Write(LogDebug, "checker", "CheckTimerHandler entered.");
55
56         double now = Utility::GetTime();
57         long tasks = 0;
58
59         int missedServices = 0, missedChecks = 0;
60
61         while (!m_IdleServices.empty()) {
62                 typedef nth_index<ServiceSet, 1>::type CheckTimeView;
63                 CheckTimeView& idx = boost::get<1>(m_IdleServices);
64
65                 CheckTimeView::iterator it = idx.begin();
66                 Service::Ptr service = *it;
67
68                 if (service->GetNextCheck() > now)
69                         break;
70
71                 idx.erase(it);
72
73                 /* reschedule the service if checks are currently disabled
74                  * for it and this is not a forced check */
75                 if (!service->GetEnableActiveChecks()) {
76                         if (!service->GetForceNextCheck()) {
77                                 Logger::Write(LogDebug, "checker", "Ignoring service check for disabled service: " + service->GetName());
78
79                                 service->UpdateNextCheck();
80
81                                 idx.insert(service);
82
83                                 continue;
84                         }
85                 }
86
87                 service->SetForceNextCheck(false);
88
89                 Dictionary::Ptr cr = service->GetLastCheckResult();
90
91                 if (cr) {
92                         double lastCheck = cr->Get("execution_end");
93                         int missed = (Utility::GetTime() - lastCheck) / service->GetCheckInterval() - 1;
94
95                         if (missed > 0 && !service->GetFirstCheck()) {
96                                 missedChecks += missed;
97                                 missedServices++;
98                         }
99                 }
100
101                 service->SetFirstCheck(false);
102
103                 Logger::Write(LogDebug, "checker", "Executing service check for '" + service->GetName() + "'");
104
105                 m_IdleServices.erase(service);
106                 m_PendingServices.insert(service);
107
108                 try {
109                         service->BeginExecuteCheck(boost::bind(&CheckerComponent::CheckCompletedHandler, this, service));
110                 } catch (const exception& ex) {
111                         Logger::Write(LogCritical, "checker", "Exception occured while checking service '" + service->GetName() + "': " + diagnostic_information(ex));
112                 }
113
114                 tasks++;
115         }
116
117         Logger::Write(LogDebug, "checker", "CheckTimerHandler: past loop.");
118
119         if (missedServices > 0) {
120                 stringstream msgbuf;
121                 msgbuf << "Missed " << missedChecks << " checks for " << missedServices << " services";;
122                 Logger::Write(LogWarning, "checker", msgbuf.str());
123         }
124
125         if (tasks > 0) {
126                 stringstream msgbuf;
127                 msgbuf << "CheckTimerHandler: created " << tasks << " task(s)";
128                 Logger::Write(LogInformation, "checker", msgbuf.str());
129         }
130 }
131
132 void CheckerComponent::CheckCompletedHandler(const Service::Ptr& service)
133 {
134         /* remove the service from the list of pending services; if it's not in the
135          * list this was a manual (i.e. forced) check and we must not re-add the
136          * service to the services list because it's already there. */
137         CheckerComponent::ServiceSet::iterator it;
138         it = m_PendingServices.find(service);
139         if (it != m_PendingServices.end()) {
140                 m_PendingServices.erase(it);
141                 m_IdleServices.insert(service);
142         }
143
144         Logger::Write(LogDebug, "checker", "Check finished for service '" + service->GetName() + "'");
145 }
146
147 void CheckerComponent::ResultTimerHandler(void)
148 {
149         Logger::Write(LogDebug, "checker", "ResultTimerHandler entered.");
150
151         stringstream msgbuf;
152         msgbuf << "Pending services: " << m_PendingServices.size() << "; Idle services: " << m_IdleServices.size();
153         Logger::Write(LogInformation, "checker", msgbuf.str());
154 }
155
156 void CheckerComponent::CheckerChangedHandler(const Service::Ptr& service)
157 {
158         String checker = service->GetChecker();
159
160         if (checker == EndpointManager::GetInstance()->GetIdentity() || checker == m_Endpoint->GetName()) {
161                 if (m_PendingServices.find(service) != m_PendingServices.end())
162                         return;
163
164                 m_IdleServices.insert(service);
165         } else {
166                 m_IdleServices.erase(service);
167                 m_PendingServices.erase(service);
168         }
169 }
170
171 void CheckerComponent::NextCheckChangedHandler(const Service::Ptr& service)
172 {
173         /* remove and re-insert the service from the set in order to force an index update */
174         typedef nth_index<ServiceSet, 0>::type ServiceView;
175         ServiceView& idx = boost::get<0>(m_IdleServices);
176
177         ServiceView::iterator it = idx.find(service);
178         if (it == idx.end())
179                 return;
180
181         idx.erase(it);
182         idx.insert(service);
183 }
184
185 void CheckerComponent::ObjectRemovedHandler(const DynamicObject::Ptr& object)
186 {
187         Service::Ptr service = dynamic_pointer_cast<Service>(object);
188
189         /* ignore it if the removed object is not a service */
190         if (!service)
191                 return;
192
193         m_IdleServices.erase(service);
194         m_PendingServices.erase(service);
195 }
196
197 EXPORT_COMPONENT(checker, CheckerComponent);
198