Refactor the cache code... again.

This commit is contained in:
Gunnar Beutner 2013-02-27 15:23:25 +01:00
parent e9648f35bc
commit d666960fa0
20 changed files with 202 additions and 114 deletions

View File

@ -106,11 +106,11 @@ void DelegationComponent::DelegationTimerHandler(void)
if (checker.IsEmpty())
continue;
if (!Endpoint::Exists(checker))
continue;
Endpoint::Ptr endpoint = Endpoint::GetByName(checker);
if (!endpoint)
continue;
histogram[endpoint]++;
}
@ -124,9 +124,7 @@ void DelegationComponent::DelegationTimerHandler(void)
String checker = service->GetCurrentChecker();
Endpoint::Ptr oldEndpoint;
if (Endpoint::Exists(checker))
oldEndpoint = Endpoint::GetByName(checker);
Endpoint::Ptr oldEndpoint = Endpoint::GetByName(checker);
set<Endpoint::Ptr> candidates = GetCheckerCandidates(service);

View File

@ -70,7 +70,8 @@ void NotificationComponent::NotificationTimerHandler(void)
if (service->GetLastNotification() > now - service->GetNotificationInterval())
continue;
service->RequestNotifications(NotificationProblem);
if (Service::IsReachable(service) && !service->IsInDowntime() && !service->IsAcknowledged())
service->RequestNotifications(NotificationProblem);
}
}

View File

@ -23,6 +23,7 @@ using namespace icinga;
boost::mutex Host::m_ServiceMutex;
map<String, map<String, weak_ptr<Service> > > Host::m_ServicesCache;
bool Host::m_ServicesCacheValid = false;
REGISTER_SCRIPTFUNCTION("ValidateServiceDictionary", &Host::ValidateServiceDictionary);
@ -42,7 +43,7 @@ Host::Host(const Dictionary::Ptr& properties)
Host::~Host(void)
{
HostGroup::RefreshMembersCache();
HostGroup::InvalidateMembersCache();
if (m_SlaveServices) {
ConfigItem::Ptr service;
@ -56,7 +57,6 @@ void Host::OnRegistrationCompleted(void)
{
DynamicObject::OnRegistrationCompleted();
HostGroup::RefreshMembersCache();
Host::UpdateSlaveServices(GetSelf());
}
@ -68,14 +68,6 @@ String Host::GetDisplayName(void) const
return GetName();
}
/**
* @threadsafety Always.
*/
bool Host::Exists(const String& name)
{
return (DynamicObject::GetObject("Host", name));
}
/**
* @threadsafety Always.
*/
@ -292,7 +284,7 @@ void Host::UpdateSlaveServices(const Host::Ptr& self)
void Host::OnAttributeChanged(const String& name, const Value&)
{
if (name == "hostgroups")
HostGroup::RefreshMembersCache();
HostGroup::InvalidateMembersCache();
else if (name == "services") {
UpdateSlaveServices(GetSelf());
} else if (name == "notifications") {
@ -328,8 +320,27 @@ set<Service::Ptr> Host::GetServices(void) const
return services;
}
void Host::InvalidateServicesCache(void)
{
{
boost::mutex::scoped_lock lock(m_ServiceMutex);
m_ServicesCacheValid = false;
}
Utility::QueueAsyncCallback(boost::bind(&Host::RefreshServicesCache));
}
void Host::RefreshServicesCache(void)
{
{
boost::mutex::scoped_lock lock(m_ServiceMutex);
if (m_ServicesCacheValid)
return;
m_ServicesCacheValid = true;
}
map<String, map<String, weak_ptr<Service> > > newServicesCache;
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
@ -433,10 +444,18 @@ Service::Ptr Host::GetServiceByShortName(const Host::Ptr& self, const Value& nam
}
}
return Service::GetByName(name);
return Service::Ptr();
} else if (name.IsObjectType<Dictionary>()) {
Dictionary::Ptr dict = name;
return GetServiceByShortName(GetByName(dict->Get("host")), dict->Get("service"));
String short_name;
{
ObjectLock olock(dict);
host_name = dict->Get("host");
short_name = dict->Get("service");
}
return Service::GetByNamePair(host_name, short_name);
} else {
BOOST_THROW_EXCEPTION(invalid_argument("Host/Service name pair is invalid."));
}
@ -461,7 +480,12 @@ set<Host::Ptr> Host::GetParentHosts(const Host::Ptr& self)
if (value == host_name)
continue;
parents.insert(Host::GetByName(value));
Host::Ptr host = GetByName(value);
if (!host)
continue;
parents.insert(host);
}
}
@ -477,6 +501,9 @@ Service::Ptr Host::GetHostCheckService(const Host::Ptr& self)
host_check = self->GetHostCheck();
}
if (host_check.IsEmpty())
return Service::Ptr();
return GetServiceByShortName(self, host_check);
}

View File

@ -39,7 +39,6 @@ public:
Host(const Dictionary::Ptr& properties);
~Host(void);
static bool Exists(const String& name);
static Host::Ptr GetByName(const String& name);
String GetDisplayName(void) const;
@ -61,7 +60,7 @@ public:
static shared_ptr<Service> GetServiceByShortName(const Host::Ptr& self, const Value& name);
set<shared_ptr<Service> > GetServices(void) const;
static void RefreshServicesCache(void);
static void InvalidateServicesCache(void);
static void ValidateServiceDictionary(const ScriptTask::Ptr& task,
const std::vector<icinga::Value>& arguments);
@ -81,10 +80,11 @@ private:
static boost::mutex m_ServiceMutex;
static map<String, map<String, weak_ptr<Service> > > m_ServicesCache;
static bool m_ServicesCacheValid;
static void UpdateSlaveServices(const Host::Ptr& self);
static void ValidateServicesCache(void);
static void RefreshServicesCache(void);
};
}

View File

@ -23,6 +23,7 @@ using namespace icinga;
boost::mutex HostGroup::m_Mutex;
map<String, vector<Host::WeakPtr> > HostGroup::m_MembersCache;
bool HostGroup::m_MembersCacheValid = true;
REGISTER_TYPE(HostGroup, NULL);
@ -36,12 +37,12 @@ HostGroup::HostGroup(const Dictionary::Ptr& properties)
HostGroup::~HostGroup(void)
{
RefreshMembersCache();
InvalidateMembersCache();
}
void HostGroup::OnRegistrationCompleted(void)
{
RefreshMembersCache();
InvalidateMembersCache();
}
String HostGroup::GetDisplayName(void) const
@ -62,14 +63,6 @@ String HostGroup::GetActionUrl(void) const
return m_ActionUrl;
}
/**
* @threadsafety Always.
*/
bool HostGroup::Exists(const String& name)
{
return (DynamicObject::GetObject("HostGroup", name));
}
/**
* @threadsafety Always.
*/
@ -110,8 +103,27 @@ set<Host::Ptr> HostGroup::GetMembers(const HostGroup::Ptr& self)
return hosts;
}
void HostGroup::InvalidateMembersCache(void)
{
{
boost::mutex::scoped_lock lock(m_Mutex);
m_MembersCacheValid = false;
}
Utility::QueueAsyncCallback(boost::bind(&HostGroup::RefreshMembersCache));
}
void HostGroup::RefreshMembersCache(void)
{
{
boost::mutex::scoped_lock lock(m_Mutex);
if (m_MembersCacheValid)
return;
m_MembersCacheValid = true;
}
map<String, vector<weak_ptr<Host> > > newMembersCache;
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Host")) {
@ -125,9 +137,6 @@ void HostGroup::RefreshMembersCache(void)
ObjectLock mlock(dict);
Value hostgroup;
BOOST_FOREACH(tie(tuples::ignore, hostgroup), dict) {
if (!HostGroup::Exists(hostgroup))
continue;
newMembersCache[hostgroup].push_back(host);
}
}

View File

@ -37,7 +37,6 @@ public:
HostGroup(const Dictionary::Ptr& properties);
~HostGroup(void);
static bool Exists(const String& name);
static HostGroup::Ptr GetByName(const String& name);
String GetDisplayName(void) const;
@ -46,7 +45,7 @@ public:
static set<Host::Ptr> GetMembers(const HostGroup::Ptr& self);
static void RefreshMembersCache(void);
static void InvalidateMembersCache(void);
protected:
virtual void OnRegistrationCompleted(void);
@ -58,6 +57,9 @@ private:
static boost::mutex m_Mutex;
static map<String, vector<weak_ptr<Host> > > m_MembersCache;
static bool m_MembersCacheValid;
static void RefreshMembersCache(void);
};
}

View File

@ -31,18 +31,11 @@ Notification::Notification(const Dictionary::Ptr& properties)
RegisterAttribute("users", Attribute_Config, &m_Users);
RegisterAttribute("host_name", Attribute_Config, &m_HostName);
RegisterAttribute("service", Attribute_Config, &m_Service);
Service::RefreshNotificationsCache();
}
Notification::~Notification(void)
{
Service::RefreshNotificationsCache();
}
bool Notification::Exists(const String& name)
{
return (DynamicObject::GetObject("Notification", name));
Service::InvalidateNotificationsCache();
}
Notification::Ptr Notification::GetByName(const String& name)
@ -59,6 +52,9 @@ Service::Ptr Notification::GetService(void) const
{
Host::Ptr host = Host::GetByName(m_HostName);
if (!host)
return Service::Ptr();
if (m_Service.IsEmpty())
return Host::GetHostCheckService(host);
else
@ -239,5 +235,5 @@ void Notification::NotificationCompletedHandler(const ScriptTask::Ptr& task)
void Notification::OnAttributeChanged(const String& name, const Value& oldValue)
{
if (name == "host_name" || name == "service")
Service::RefreshNotificationsCache();
Service::InvalidateNotificationsCache();
}

View File

@ -55,7 +55,6 @@ public:
Notification(const Dictionary::Ptr& properties);
~Notification(void);
static bool Exists(const String& name);
static Notification::Ptr GetByName(const String& name);
shared_ptr<Service> GetService(void) const;

View File

@ -25,6 +25,7 @@ int Service::m_NextCommentID = 1;
boost::mutex Service::m_CommentMutex;
map<int, String> Service::m_LegacyCommentsCache;
map<String, Service::WeakPtr> Service::m_CommentsCache;
bool Service::m_CommentsCacheValid = true;
Timer::Ptr Service::m_CommentsExpireTimer;
int Service::GetNextCommentID(void)
@ -135,8 +136,27 @@ bool Service::IsCommentExpired(const Dictionary::Ptr& comment)
return (expire_time != 0 && expire_time < Utility::GetTime());
}
void Service::InvalidateCommentsCache(void)
{
{
boost::mutex::scoped_lock lock(m_CommentMutex);
m_CommentsCacheValid = false;
}
Utility::QueueAsyncCallback(boost::bind(&Service::RefreshCommentsCache));
}
void Service::RefreshCommentsCache(void)
{
{
boost::mutex::scoped_lock lock(m_CommentMutex);
if (m_CommentsCacheValid)
return;
m_CommentsCacheValid = true;
}
map<int, String> newLegacyCommentsCache;
map<String, Service::WeakPtr> newCommentsCache;

View File

@ -25,6 +25,7 @@ int Service::m_NextDowntimeID = 1;
boost::mutex Service::m_DowntimeMutex;
map<int, String> Service::m_LegacyDowntimesCache;
map<String, Service::WeakPtr> Service::m_DowntimesCache;
bool Service::m_DowntimesCacheValid = true;
Timer::Ptr Service::m_DowntimesExpireTimer;
int Service::GetNextDowntimeID(void)
@ -212,8 +213,27 @@ bool Service::IsDowntimeExpired(const Dictionary::Ptr& downtime)
return (downtime->Get("end_time") < Utility::GetTime());
}
void Service::InvalidateDowntimesCache(void)
{
{
boost::mutex::scoped_lock lock(m_DowntimeMutex);
m_DowntimesCacheValid = false;
}
Utility::QueueAsyncCallback(boost::bind(&Service::RefreshDowntimesCache));
}
void Service::RefreshDowntimesCache(void)
{
{
boost::mutex::scoped_lock lock(m_DowntimeMutex);
if (m_DowntimesCacheValid)
return;
m_DowntimesCacheValid = true;
}
map<int, String> newLegacyDowntimesCache;
map<String, Service::WeakPtr> newDowntimesCache;

View File

@ -23,6 +23,7 @@ using namespace icinga;
boost::mutex Service::m_NotificationMutex;
map<String, set<Notification::WeakPtr> > Service::m_NotificationsCache;
bool Service::m_NotificationsCacheValid = true;
void Service::RequestNotifications(NotificationType type)
{
@ -78,8 +79,27 @@ void Service::SendNotifications(const Service::Ptr& self, NotificationType type)
}
}
void Service::InvalidateNotificationsCache(void)
{
{
boost::mutex::scoped_lock lock(m_NotificationMutex);
m_NotificationsCacheValid = false;
}
Utility::QueueAsyncCallback(boost::bind(&Service::RefreshNotificationsCache));
}
void Service::RefreshNotificationsCache(void)
{
{
boost::mutex::scoped_lock lock(m_NotificationMutex);
if (m_NotificationsCacheValid)
return;
m_NotificationsCacheValid = true;
}
map<String, set<Notification::WeakPtr> > newNotificationsCache;
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Notification")) {
@ -157,7 +177,7 @@ void Service::UpdateSlaveNotifications(const Service::Ptr& self)
Dictionary::Ptr oldNotifications;
Host::Ptr host;
vector<Dictionary::Ptr> notificationDescsList;
String service_name;
String service_name, short_name;
ConfigItem::Ptr item;
{
@ -171,6 +191,7 @@ void Service::UpdateSlaveNotifications(const Service::Ptr& self)
return;
service_name = self->GetName();
short_name = self->GetShortName();
oldNotifications = self->m_SlaveNotifications;
host = self->GetHost();
@ -216,7 +237,7 @@ void Service::UpdateSlaveNotifications(const Service::Ptr& self)
builder->SetType("Notification");
builder->SetName(name);
builder->AddExpression("host_name", OperatorSet, host_name);
builder->AddExpression("service", OperatorSet, service_name);
builder->AddExpression("service", OperatorSet, short_name);
CopyNotificationAttributes(self, builder);

View File

@ -70,18 +70,17 @@ Service::Service(const Dictionary::Ptr& serializedObject)
Service::~Service(void)
{
ServiceGroup::RefreshMembersCache();
Host::RefreshServicesCache();
Service::RefreshDowntimesCache();
Service::RefreshCommentsCache();
ServiceGroup::InvalidateMembersCache();
Host::InvalidateServicesCache();
Service::InvalidateDowntimesCache();
Service::InvalidateCommentsCache();
}
void Service::OnRegistrationCompleted(void)
{
DynamicObject::OnRegistrationCompleted();
ServiceGroup::RefreshMembersCache();
Host::RefreshServicesCache();
Host::InvalidateServicesCache();
}
String Service::GetDisplayName(void) const
@ -92,14 +91,6 @@ String Service::GetDisplayName(void) const
return m_DisplayName;
}
/**
* @threadsafety Always.
*/
bool Service::Exists(const String& name)
{
return (DynamicObject::GetObject("Service", name));
}
/**
* @threadsafety Always.
*/
@ -120,6 +111,10 @@ Service::Ptr Service::GetByNamePair(const String& hostName, const String& servic
{
if (!hostName.IsEmpty()) {
Host::Ptr host = Host::GetByName(hostName);
if (!host)
return Service::Ptr();
return Host::GetServiceByShortName(host, serviceName);
} else {
return Service::GetByName(serviceName);
@ -266,15 +261,15 @@ void Service::OnAttributeChanged(const String& name, const Value& oldValue)
else if (name == "next_check")
OnNextCheckChanged(GetSelf(), oldValue);
else if (name == "servicegroups")
ServiceGroup::RefreshMembersCache();
ServiceGroup::InvalidateMembersCache();
else if (name == "host_name" || name == "short_name") {
Host::RefreshServicesCache();
Host::InvalidateServicesCache();
UpdateSlaveNotifications(GetSelf());
} else if (name == "downtimes")
Service::RefreshDowntimesCache();
Service::InvalidateDowntimesCache();
else if (name == "comments")
Service::RefreshCommentsCache();
Service::InvalidateCommentsCache();
else if (name == "notifications")
UpdateSlaveNotifications(GetSelf());
else if (name == "check_interval") {
@ -306,7 +301,12 @@ set<Host::Ptr> Service::GetParentHosts(const Service::Ptr& self)
if (dependencies) {
String key;
BOOST_FOREACH(tie(key, tuples::ignore), dependencies) {
parents.insert(Host::GetByName(key));
Host::Ptr host = Host::GetByName(key);
if (!host)
continue;
parents.insert(host);
}
}

View File

@ -89,7 +89,6 @@ public:
Service(const Dictionary::Ptr& properties);
~Service(void);
static bool Exists(const String& name);
static Service::Ptr GetByName(const String& name);
static Service::Ptr GetByNamePair(const String& hostName, const String& serviceName);
@ -112,7 +111,7 @@ public:
static set<Host::Ptr> GetParentHosts(const Service::Ptr& self);
static set<Service::Ptr> GetParentServices(const Service::Ptr& self);
bool IsReachable(const Service::Ptr& self);
static bool IsReachable(const Service::Ptr& self);
AcknowledgementType GetAcknowledgement(void);
void SetAcknowledgement(AcknowledgementType acknowledgement);
@ -208,7 +207,7 @@ public:
static bool IsDowntimeActive(const Dictionary::Ptr& downtime);
static bool IsDowntimeExpired(const Dictionary::Ptr& downtime);
static void RefreshDowntimesCache(void);
static void InvalidateDowntimesCache(void);
bool IsInDowntime(void) const;
bool IsAcknowledged(void);
@ -230,7 +229,7 @@ public:
static bool IsCommentExpired(const Dictionary::Ptr& comment);
static void RefreshCommentsCache(void);
static void InvalidateCommentsCache(void);
/* Notifications */
bool GetEnableNotifications(void) const;
@ -243,7 +242,7 @@ public:
static set<Notification::Ptr> GetNotifications(const Service::Ptr& self);
static void RefreshNotificationsCache(void);
static void InvalidateNotificationsCache(void);
static void UpdateSlaveNotifications(const Service::Ptr& self);
@ -299,12 +298,15 @@ private:
static boost::mutex m_DowntimeMutex;
static map<int, String> m_LegacyDowntimesCache;
static map<String, Service::WeakPtr> m_DowntimesCache;
static bool m_DowntimesCacheValid;
static Timer::Ptr m_DowntimesExpireTimer;
static void DowntimesExpireTimerHandler(void);
void RemoveExpiredDowntimes(void);
static void RefreshDowntimesCache(void);
/* Comments */
Attribute<Dictionary::Ptr> m_Comments;
@ -313,6 +315,7 @@ private:
static boost::mutex m_CommentMutex;
static map<int, String> m_LegacyCommentsCache;
static map<String, Service::WeakPtr> m_CommentsCache;
static bool m_CommentsCacheValid;
static Timer::Ptr m_CommentsExpireTimer;
static void CommentsExpireTimerHandler(void);
@ -320,6 +323,8 @@ private:
void AddCommentsToCache(void);
void RemoveExpiredComments(void);
static void RefreshCommentsCache(void);
/* Notifications */
Attribute<bool> m_EnableNotifications;
Attribute<double> m_LastNotification;
@ -327,6 +332,9 @@ private:
static boost::mutex m_NotificationMutex;
static map<String, set<Notification::WeakPtr> > m_NotificationsCache;
static bool m_NotificationsCacheValid;
static void RefreshNotificationsCache(void);
};
}

View File

@ -23,6 +23,7 @@ using namespace icinga;
boost::mutex ServiceGroup::m_Mutex;
map<String, vector<Service::WeakPtr> > ServiceGroup::m_MembersCache;
bool ServiceGroup::m_MembersCacheValid = true;
REGISTER_TYPE(ServiceGroup, NULL);
@ -62,14 +63,6 @@ String ServiceGroup::GetActionUrl(void) const
return m_ActionUrl;
}
/**
* @threadsafety Always.
*/
bool ServiceGroup::Exists(const String& name)
{
return (DynamicObject::GetObject("ServiceGroup", name));
}
/**
* @threadsafety Always.
*/
@ -110,8 +103,27 @@ set<Service::Ptr> ServiceGroup::GetMembers(const ServiceGroup::Ptr& self)
return services;
}
void ServiceGroup::InvalidateMembersCache(void)
{
{
boost::mutex::scoped_lock lock(m_Mutex);
m_MembersCacheValid = false;
}
Utility::QueueAsyncCallback(boost::bind(&ServiceGroup::RefreshMembersCache));
}
void ServiceGroup::RefreshMembersCache(void)
{
{
boost::mutex::scoped_lock lock(m_Mutex);
if (m_MembersCacheValid)
return;
m_MembersCacheValid = true;
}
map<String, vector<weak_ptr<Service> > > newMembersCache;
BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
@ -125,9 +137,6 @@ void ServiceGroup::RefreshMembersCache(void)
ObjectLock mlock(dict);
Value servicegroup;
BOOST_FOREACH(tie(tuples::ignore, servicegroup), dict) {
if (!ServiceGroup::Exists(servicegroup))
continue;
newMembersCache[servicegroup].push_back(service);
}
}
@ -135,5 +144,4 @@ void ServiceGroup::RefreshMembersCache(void)
boost::mutex::scoped_lock lock(m_Mutex);
m_MembersCache.swap(newMembersCache);
}

View File

@ -37,7 +37,6 @@ public:
ServiceGroup(const Dictionary::Ptr& properties);
~ServiceGroup(void);
static bool Exists(const String& name);
static ServiceGroup::Ptr GetByName(const String& name);
String GetDisplayName(void) const;
@ -46,7 +45,7 @@ public:
static set<Service::Ptr> GetMembers(const ServiceGroup::Ptr& self);
static void RefreshMembersCache(void);
static void InvalidateMembersCache(void);
protected:
virtual void OnRegistrationCompleted(void);
@ -58,6 +57,9 @@ private:
static boost::mutex m_Mutex;
static map<String, vector<weak_ptr<Service> > > m_MembersCache;
static bool m_MembersCacheValid;
static void RefreshMembersCache(void);
};
}

View File

@ -29,11 +29,6 @@ User::User(const Dictionary::Ptr& properties)
RegisterAttribute("macros", Attribute_Config, &m_Macros);
}
bool User::Exists(const String& name)
{
return (DynamicObject::GetObject("User", name));
}
User::Ptr User::GetByName(const String& name)
{
DynamicObject::Ptr configObject = DynamicObject::GetObject("User", name);

View File

@ -36,7 +36,6 @@ public:
User(const Dictionary::Ptr& properties);
static bool Exists(const String& name);
static User::Ptr GetByName(const String& name);
Dictionary::Ptr GetMacros(void) const;

View File

@ -43,17 +43,6 @@ Endpoint::Endpoint(const Dictionary::Ptr& serializedUpdate)
RegisterAttribute("subscriptions", Attribute_Replicated, &m_Subscriptions);
}
/**
* Checks whether an endpoint with the specified name exists.
*
* @param name The name of the endpoint.
* @returns true if the endpoint exists, false otherwise.
*/
bool Endpoint::Exists(const String& name)
{
return (DynamicObject::GetObject("Endpoint", name));
}
/**
* Retrieves an endpoint by name.
*
@ -64,9 +53,6 @@ Endpoint::Ptr Endpoint::GetByName(const String& name)
{
DynamicObject::Ptr configObject = DynamicObject::GetObject("Endpoint", name);
if (!configObject)
BOOST_THROW_EXCEPTION(invalid_argument("Endpoint '" + name + "' does not exist."));
return dynamic_pointer_cast<Endpoint>(configObject);
}

View File

@ -40,7 +40,6 @@ public:
Endpoint(const Dictionary::Ptr& serializedUpdate);
static bool Exists(const String& name);
static Endpoint::Ptr GetByName(const String& name);
JsonRpcConnection::Ptr GetClient(void) const;

View File

@ -168,11 +168,9 @@ void EndpointManager::ClientConnectedHandler(const Stream::Ptr& client, const St
Logger::Write(LogInformation, "icinga", "New client connection at " + peerAddress + " for identity '" + identity + "'");
Endpoint::Ptr endpoint;
Endpoint::Ptr endpoint = Endpoint::GetByName(identity);
if (Endpoint::Exists(identity))
endpoint = Endpoint::GetByName(identity);
else
if (!endpoint)
endpoint = Endpoint::MakeEndpoint(identity, true);
endpoint->SetClient(jclient);