]> granicus.if.org Git - icinga2/blob - lib/icinga/servicegroup.cpp
Refactor #includes (Part 2).
[icinga2] / lib / icinga / servicegroup.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-icinga.h"
21 #include "icinga/servicegroup.h"
22 #include "base/dynamictype.h"
23 #include "base/objectlock.h"
24 #include "base/logger_fwd.h"
25 #include <boost/smart_ptr/make_shared.hpp>
26 #include <boost/foreach.hpp>
27
28 using namespace icinga;
29
30 boost::mutex ServiceGroup::m_Mutex;
31 std::map<String, std::vector<Service::WeakPtr> > ServiceGroup::m_MembersCache;
32 bool ServiceGroup::m_MembersCacheNeedsUpdate = false;
33 Timer::Ptr ServiceGroup::m_MembersCacheTimer;
34
35 REGISTER_TYPE(ServiceGroup);
36
37 ServiceGroup::ServiceGroup(const Dictionary::Ptr& serializedUpdate)
38         : DynamicObject(serializedUpdate)
39 {
40         RegisterAttribute("display_name", Attribute_Config, &m_DisplayName);
41         RegisterAttribute("notes_url", Attribute_Config, &m_NotesUrl);
42         RegisterAttribute("action_url", Attribute_Config, &m_ActionUrl);
43 }
44
45 ServiceGroup::~ServiceGroup(void)
46 {
47         InvalidateMembersCache();
48 }
49
50 /**
51  * @threadsafety Always.
52  */
53 void ServiceGroup::OnRegistrationCompleted(void)
54 {
55         ASSERT(!OwnsLock());
56
57         InvalidateMembersCache();
58 }
59
60 /**
61  * @threadsafety Always.
62  */
63 String ServiceGroup::GetDisplayName(void) const
64 {
65         if (!m_DisplayName.Get().IsEmpty())
66                 return m_DisplayName;
67         else
68                 return GetName();
69 }
70
71 /**
72  * @threadsafety Always.
73  */
74 String ServiceGroup::GetNotesUrl(void) const
75 {
76         return m_NotesUrl;
77 }
78
79 /**
80  * @threadsafety Always.
81  */
82 String ServiceGroup::GetActionUrl(void) const
83 {
84         return m_ActionUrl;
85 }
86
87 /**
88  * @threadsafety Always.
89  */
90 ServiceGroup::Ptr ServiceGroup::GetByName(const String& name)
91 {
92         DynamicObject::Ptr configObject = DynamicObject::GetObject("ServiceGroup", name);
93
94         if (!configObject)
95                 BOOST_THROW_EXCEPTION(std::invalid_argument("ServiceGroup '" + name + "' does not exist."));
96
97         return dynamic_pointer_cast<ServiceGroup>(configObject);
98 }
99
100 /**
101  * @threadsafety Always.
102  */
103 std::set<Service::Ptr> ServiceGroup::GetMembers(void) const
104 {
105         std::set<Service::Ptr> services;
106
107         {
108                 boost::mutex::scoped_lock lock(m_Mutex);
109
110                 BOOST_FOREACH(const Service::WeakPtr& wservice, m_MembersCache[GetName()]) {
111                         Service::Ptr service = wservice.lock();
112
113                         if (!service)
114                                 continue;
115
116                         services.insert(service);
117                 }
118         }
119
120         return services;
121 }
122
123 /**
124  * @threadsafety Always.
125  */
126 void ServiceGroup::InvalidateMembersCache(void)
127 {
128         boost::mutex::scoped_lock lock(m_Mutex);
129
130         if (m_MembersCacheNeedsUpdate)
131                 return; /* Someone else has already requested a refresh. */
132
133         if (!m_MembersCacheTimer) {
134                 m_MembersCacheTimer = boost::make_shared<Timer>();
135                 m_MembersCacheTimer->SetInterval(0.5);
136                 m_MembersCacheTimer->OnTimerExpired.connect(boost::bind(&ServiceGroup::RefreshMembersCache));
137                 m_MembersCacheTimer->Start();
138         }
139
140         m_MembersCacheNeedsUpdate = true;
141 }
142
143 /**
144  * @threadsafety Always.
145  */
146 void ServiceGroup::RefreshMembersCache(void)
147 {
148         {
149                 boost::mutex::scoped_lock lock(m_Mutex);
150
151                 if (!m_MembersCacheNeedsUpdate)
152                         return;
153
154                 m_MembersCacheNeedsUpdate = false;
155         }
156
157         Log(LogDebug, "icinga", "Updating ServiceGroup members cache.");
158
159         std::map<String, std::vector<Service::WeakPtr> > newMembersCache;
160
161         BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
162                 const Service::Ptr& service = static_pointer_cast<Service>(object);
163
164                 Array::Ptr groups = service->GetGroups();
165
166                 if (groups) {
167                         ObjectLock mlock(groups);
168                         BOOST_FOREACH(const Value& group, groups) {
169                                 newMembersCache[group].push_back(service);
170                         }
171                 }
172         }
173
174         boost::mutex::scoped_lock lock(m_Mutex);
175         m_MembersCache.swap(newMembersCache);
176 }