mirror of
https://github.com/Icinga/icinga2.git
synced 2026-04-21 14:19:32 -04:00
Refresh the states & types bitsets whenever states & types attrs change
Since the types and states attributes are user configurable and allowed to change at runtime, we need to update the actual filter bitsets whenever these attributes change. Otherwise, the filter bitsets would be stale and not reflect their current state.
This commit is contained in:
parent
fd1927115a
commit
186571ec99
6 changed files with 124 additions and 16 deletions
|
|
@ -100,12 +100,13 @@ void Notification::StaticInitialize()
|
|||
m_TypeFilterMap["FlappingEnd"] = NotificationFlappingEnd;
|
||||
}
|
||||
|
||||
void Notification::OnConfigLoaded()
|
||||
Notification::Notification()
|
||||
{
|
||||
ObjectImpl<Notification>::OnConfigLoaded();
|
||||
|
||||
SetTypeFilter(FilterArrayToInt(GetTypes(), GetTypeFilterMap(), ~0));
|
||||
SetStateFilter(FilterArrayToInt(GetStates(), GetStateFilterMap(), ~0));
|
||||
// If a notification is created without specifying the "types/states" attribute, the Set* methods won't be called,
|
||||
// consequently the filter bitset will also be 0. Thus, we need to ensure that the type/state filter are
|
||||
// initialized to the default values, which are all types and states enabled.
|
||||
SetTypes(nullptr, false, Empty);
|
||||
SetStates(nullptr, false, Empty);
|
||||
}
|
||||
|
||||
void Notification::OnAllConfigLoaded()
|
||||
|
|
@ -751,6 +752,36 @@ String Notification::NotificationHostStateToString(HostState state)
|
|||
}
|
||||
}
|
||||
|
||||
Array::Ptr Notification::GetTypes() const
|
||||
{
|
||||
return m_Types.load();
|
||||
}
|
||||
|
||||
void Notification::SetTypes(const Array::Ptr& value, bool suppress_events, const Value& cookie)
|
||||
{
|
||||
m_Types.store(value);
|
||||
// Ensure that the type filter is updated when the types attribute changes.
|
||||
SetTypeFilter(FilterArrayToInt(value, GetTypeFilterMap(), ~0));
|
||||
if (!suppress_events) {
|
||||
NotifyTypes(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
Array::Ptr Notification::GetStates() const
|
||||
{
|
||||
return m_States.load();
|
||||
}
|
||||
|
||||
void Notification::SetStates(const Array::Ptr& value, bool suppress_events, const Value& cookie)
|
||||
{
|
||||
m_States.store(value);
|
||||
// Ensure that the state filter is updated when the states attribute changes.
|
||||
SetStateFilter(FilterArrayToInt(value, GetStateFilterMap(), ~0));
|
||||
if (!suppress_events) {
|
||||
NotifyStates(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
void Notification::Validate(int types, const ValidationUtils& utils)
|
||||
{
|
||||
ObjectImpl<Notification>::Validate(types, utils);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ public:
|
|||
DECLARE_OBJECT(Notification);
|
||||
DECLARE_OBJECTNAME(Notification);
|
||||
|
||||
Notification();
|
||||
|
||||
static void StaticInitialize();
|
||||
|
||||
intrusive_ptr<Checkable> GetCheckable() const;
|
||||
|
|
@ -115,13 +117,28 @@ public:
|
|||
static const std::map<String, int>& GetStateFilterMap();
|
||||
static const std::map<String, int>& GetTypeFilterMap();
|
||||
|
||||
void OnConfigLoaded() override;
|
||||
void OnAllConfigLoaded() override;
|
||||
void Start(bool runtimeCreated) override;
|
||||
void Stop(bool runtimeRemoved) override;
|
||||
|
||||
Array::Ptr GetTypes() const override;
|
||||
void SetTypes(const Array::Ptr& value, bool suppress_events, const Value& cookie) override;
|
||||
|
||||
Array::Ptr GetStates() const override;
|
||||
void SetStates(const Array::Ptr& value, bool suppress_events, const Value& cookie) override;
|
||||
|
||||
private:
|
||||
ObjectImpl<Checkable>::Ptr m_Checkable;
|
||||
// These attributes represent the actual notification "types" and "states" attributes from the "notification.ti".
|
||||
// However, since we want to ensure that the type and state bitsets are always in sync with those attributes,
|
||||
// we need to override their setters, and this on the hand introduces another problem: The virtual setters are
|
||||
// called from within the ObjectImpl<Notification> constructor, which obviously violates the C++ standard [^1].
|
||||
// So, in order to avoid all this kind of mess, these two attributes have the "no_storage" flag set, and
|
||||
// their getters/setters are pure virtual, which means this class has to provide the implementation of them.
|
||||
//
|
||||
// [^1]: https://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctors
|
||||
AtomicOrLocked<Array::Ptr> m_Types;
|
||||
AtomicOrLocked<Array::Ptr> m_States;
|
||||
|
||||
bool CheckNotificationUserFilters(NotificationType type, const User::Ptr& user, bool force, bool reminder);
|
||||
|
||||
|
|
|
|||
|
|
@ -41,9 +41,15 @@ class Notification : CustomVarObject < NotificationNameComposer
|
|||
[config, signal_with_old_value] array(name(User)) users (UsersRaw);
|
||||
[config, signal_with_old_value] array(name(UserGroup)) user_groups (UserGroupsRaw);
|
||||
[config] Dictionary::Ptr times;
|
||||
[config] array(Value) types;
|
||||
[config, no_storage] array(Value) types {
|
||||
get;
|
||||
set;
|
||||
};
|
||||
[no_user_view, no_user_modify] int type_filter_real (TypeFilter);
|
||||
[config] array(Value) states;
|
||||
[config, no_storage] array(Value) states {
|
||||
get;
|
||||
set;
|
||||
};
|
||||
[no_user_view, no_user_modify] int state_filter_real (StateFilter);
|
||||
[config, no_user_modify, protected, required, navigation(host)] name(Host) host_name {
|
||||
navigate {{{
|
||||
|
|
|
|||
|
|
@ -12,12 +12,13 @@ using namespace icinga;
|
|||
|
||||
REGISTER_TYPE(User);
|
||||
|
||||
void User::OnConfigLoaded()
|
||||
User::User()
|
||||
{
|
||||
ObjectImpl<User>::OnConfigLoaded();
|
||||
|
||||
SetTypeFilter(FilterArrayToInt(GetTypes(), Notification::GetTypeFilterMap(), ~0));
|
||||
SetStateFilter(FilterArrayToInt(GetStates(), Notification::GetStateFilterMap(), ~0));
|
||||
// If a User is created without specifying the "types/states" attribute, the Set* methods won't be called,
|
||||
// consequently the filter bitset will also be 0. Thus, we need to ensure that the type/state filter are
|
||||
// initialized to the default values, which are all types and states enabled.
|
||||
SetTypes(nullptr, false, Empty);
|
||||
SetStates(nullptr, false, Empty);
|
||||
}
|
||||
|
||||
void User::OnAllConfigLoaded()
|
||||
|
|
@ -80,6 +81,36 @@ TimePeriod::Ptr User::GetPeriod() const
|
|||
return TimePeriod::GetByName(GetPeriodRaw());
|
||||
}
|
||||
|
||||
Array::Ptr User::GetTypes() const
|
||||
{
|
||||
return m_Types.load();
|
||||
}
|
||||
|
||||
void User::SetTypes(const Array::Ptr& value, bool suppress_events, const Value& cookie)
|
||||
{
|
||||
m_Types.store(value);
|
||||
// Ensure that the type filter is updated when the types attribute changes.
|
||||
SetTypeFilter(FilterArrayToInt(value, Notification::GetTypeFilterMap(), ~0));
|
||||
if (!suppress_events) {
|
||||
NotifyTypes(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
Array::Ptr User::GetStates() const
|
||||
{
|
||||
return m_States.load();
|
||||
}
|
||||
|
||||
void User::SetStates(const Array::Ptr& value, bool suppress_events, const Value& cookie)
|
||||
{
|
||||
m_States.store(value);
|
||||
// Ensure that the state filter is updated when the states attribute changes.
|
||||
SetStateFilter(FilterArrayToInt(value, Notification::GetStateFilterMap(), ~0));
|
||||
if (!suppress_events) {
|
||||
NotifyStates(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
void User::ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
|
||||
{
|
||||
ObjectImpl<User>::ValidateStates(lvalue, utils);
|
||||
|
|
|
|||
|
|
@ -22,21 +22,38 @@ public:
|
|||
DECLARE_OBJECT(User);
|
||||
DECLARE_OBJECTNAME(User);
|
||||
|
||||
User();
|
||||
|
||||
void AddGroup(const String& name);
|
||||
|
||||
/* Notifications */
|
||||
TimePeriod::Ptr GetPeriod() const;
|
||||
|
||||
Array::Ptr GetTypes() const override;
|
||||
void SetTypes(const Array::Ptr& value, bool suppress_events, const Value& cookie) override;
|
||||
|
||||
Array::Ptr GetStates() const override;
|
||||
void SetStates(const Array::Ptr& value, bool suppress_events, const Value& cookie) override;
|
||||
|
||||
void ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override;
|
||||
void ValidateTypes(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override;
|
||||
|
||||
protected:
|
||||
void Stop(bool runtimeRemoved) override;
|
||||
|
||||
void OnConfigLoaded() override;
|
||||
void OnAllConfigLoaded() override;
|
||||
private:
|
||||
mutable std::mutex m_UserMutex;
|
||||
// These attributes represent the actual User "types" and "states" attributes from the "user.ti".
|
||||
// However, since we want to ensure that the type and state bitsets are always in sync with those attributes,
|
||||
// we need to override their setters, and this on the hand introduces another problem: The virtual setters are
|
||||
// called from within the ObjectImpl<User> constructor, which obviously violates the C++ standard [^1].
|
||||
// So, in order to avoid al this kind of mess, these two attributes have the "no_storage" flag set, and
|
||||
// their getters/setters are pure virtual, which means this class has to provide the implementation of them.
|
||||
//
|
||||
// [^1]: https://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctors
|
||||
AtomicOrLocked<Array::Ptr> m_Types;
|
||||
AtomicOrLocked<Array::Ptr> m_States;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,9 +29,15 @@ class User : CustomVarObject
|
|||
}}}
|
||||
};
|
||||
|
||||
[config] array(Value) types;
|
||||
[config, no_storage] array(Value) types {
|
||||
get;
|
||||
set;
|
||||
};
|
||||
[no_user_view, no_user_modify] int type_filter_real (TypeFilter);
|
||||
[config] array(Value) states;
|
||||
[config, no_storage] array(Value) states {
|
||||
get;
|
||||
set;
|
||||
};
|
||||
[no_user_view, no_user_modify] int state_filter_real (StateFilter);
|
||||
|
||||
[config] String email;
|
||||
|
|
|
|||
Loading…
Reference in a new issue