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