2 * SPDX-License-Identifier: LGPL-2.1-only
4 * Copyright (C) 2015 EfficiOS Inc.
5 * Copyright (C) 2015 Alexandre Montplaisir <alexmonthy@efficios.com>
8 package org
.lttng
.ust
.agent
.filter
;
10 import java
.util
.Collection
;
11 import java
.util
.HashMap
;
12 import java
.util
.LinkedList
;
13 import java
.util
.List
;
16 import org
.lttng
.ust
.agent
.session
.EventRule
;
19 * Singleton class managing the filter notifications.
21 * Applications can register a {@link IFilterChangeListener} to be notified when
22 * event filtering rules change in the tracing sessions.
24 * @author Alexandre Montplaisir
26 public final class FilterChangeNotifier
{
28 /** Lazy-loaded singleton instance object */
29 private static FilterChangeNotifier instance
= null;
31 private final Map
<EventRule
, Integer
> enabledEventRules
= new HashMap
<EventRule
, Integer
>();
32 private final Collection
<IFilterChangeListener
> registeredListeners
= new LinkedList
<IFilterChangeListener
>();
36 * Private constructor, singleton class should not be instantiated directly.
38 private FilterChangeNotifier() {
42 * Get the singleton instance, initializing it if needed.
44 * @return The singleton instance
46 public static synchronized FilterChangeNotifier
getInstance() {
47 if (instance
== null) {
48 instance
= new FilterChangeNotifier();
54 * Notify the filter manager that a new rule was enabled in a tracing
55 * session ("lttng enable-event ...")
57 * This is meant to be called by the LTTng Agent only. External Java
58 * applications should not call this.
61 * The rule that was added
63 public synchronized void addEventRule(EventRule rule
) {
64 Integer count
= enabledEventRules
.get(rule
);
67 * This is the first instance of this rule being enabled. Add it to
68 * the map and send notifications to the registered notifiers.
70 enabledEventRules
.put(rule
, Integer
.valueOf(1));
71 notifyForAddedRule(rule
);
74 if (count
.intValue() <= 0) {
75 /* It should not have been in the map! */
76 throw new IllegalStateException();
79 * This exact event rule was already enabled, just increment its
80 * refcount without sending notifications
82 enabledEventRules
.put(rule
, Integer
.valueOf(count
.intValue() + 1));
86 * Notify the filter manager that an event name was disabled in the tracing
87 * sessions ("lttng disable-event ...").
89 * The "disable-event" only specifies an event name. This means all the
90 * rules containing this event name are to be disabled.
92 * This is meant to be called by the LTTng Agent only. External Java
93 * applications should not call this.
96 * The event name to disable
98 public synchronized void removeEventRules(String eventName
) {
99 List
<EventRule
> rulesToRemove
= new LinkedList
<EventRule
>();
101 for (EventRule eventRule
: enabledEventRules
.keySet()) {
102 if (eventRule
.getEventName().equals(eventName
)) {
103 rulesToRemove
.add(eventRule
);
107 * We cannot modify the map while iterating on it. We have to do the
108 * removal separately from the iteration above.
110 for (EventRule rule
: rulesToRemove
) {
111 removeEventRule(rule
);
115 private synchronized void removeEventRule(EventRule eventRule
) {
116 Integer count
= enabledEventRules
.get(eventRule
);
117 if (count
== null || count
.intValue() <= 0) {
119 * We were asked us to disable an event rule that was not enabled
120 * previously. Command error?
122 throw new IllegalStateException();
124 if (count
.intValue() == 1) {
126 * This is the last instance of this event rule being disabled,
127 * remove it from the map and send notifications of this rule being
130 enabledEventRules
.remove(eventRule
);
131 notifyForRemovedRule(eventRule
);
135 * Other sessions/daemons are still looking for this event rule, simply
136 * decrement its refcount, and do not send notifications.
138 enabledEventRules
.put(eventRule
, Integer
.valueOf(count
.intValue() - 1));
143 * Register a new listener to the manager.
146 * The listener to add
148 public synchronized void registerListener(IFilterChangeListener listener
) {
149 registeredListeners
.add(listener
);
151 /* Send the current rules to the new listener ("statedump") */
152 for (EventRule rule
: enabledEventRules
.keySet()) {
153 listener
.eventRuleAdded(rule
);
158 * Unregister a listener from the manager.
161 * The listener to remove
163 public synchronized void unregisterListener(IFilterChangeListener listener
) {
164 registeredListeners
.remove(listener
);
167 private void notifyForAddedRule(final EventRule rule
) {
168 for (IFilterChangeListener notifier
: registeredListeners
) {
169 notifier
.eventRuleAdded(rule
);
173 private void notifyForRemovedRule(final EventRule rule
) {
174 for (IFilterChangeListener notifier
: registeredListeners
) {
175 notifier
.eventRuleRemoved(rule
);