2 * Copyright (C) 2015 - EfficiOS Inc., Alexandre Montplaisir <alexmonthy@efficios.com>
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 package org
.lttng
.ust
.agent
.filter
;
20 import java
.util
.Collection
;
21 import java
.util
.HashMap
;
22 import java
.util
.LinkedList
;
23 import java
.util
.List
;
26 import org
.lttng
.ust
.agent
.session
.EventRule
;
29 * Singleton class managing the filter notifications.
31 * Applications can register a {@link IFilterChangeListener} to be notified when
32 * event filtering rules change in the tracing sessions.
34 * @author Alexandre Montplaisir
36 public final class FilterChangeNotifier
{
38 /** Lazy-loaded singleton instance object */
39 private static FilterChangeNotifier instance
= null;
41 private final Map
<EventRule
, Integer
> enabledEventRules
= new HashMap
<EventRule
, Integer
>();
42 private final Collection
<IFilterChangeListener
> registeredListeners
= new LinkedList
<IFilterChangeListener
>();
46 * Private constructor, singleton class should not be instantiated directly.
48 private FilterChangeNotifier() {
52 * Get the singleton instance, initializing it if needed.
54 * @return The singleton instance
56 public static synchronized FilterChangeNotifier
getInstance() {
57 if (instance
== null) {
58 instance
= new FilterChangeNotifier();
64 * Notify the filter manager that a new rule was enabled in a tracing
65 * session ("lttng enable-event ...")
67 * This is meant to be called by the LTTng Agent only. External Java
68 * applications should not call this.
71 * The rule that was added
73 public synchronized void addEventRule(EventRule rule
) {
74 Integer count
= enabledEventRules
.get(rule
);
77 * This is the first instance of this rule being enabled. Add it to
78 * the map and send notifications to the registered notifiers.
80 enabledEventRules
.put(rule
, Integer
.valueOf(1));
81 notifyForAddedRule(rule
);
84 if (count
.intValue() <= 0) {
85 /* It should not have been in the map! */
86 throw new IllegalStateException();
89 * This exact event rule was already enabled, just increment its
90 * refcount without sending notifications
92 enabledEventRules
.put(rule
, Integer
.valueOf(count
.intValue() + 1));
96 * Notify the filter manager that an event name was disabled in the tracing
97 * sessions ("lttng disable-event ...").
99 * The "disable-event" only specifies an event name. This means all the
100 * rules containing this event name are to be disabled.
102 * This is meant to be called by the LTTng Agent only. External Java
103 * applications should not call this.
106 * The event name to disable
108 public synchronized void removeEventRules(String eventName
) {
109 List
<EventRule
> rulesToRemove
= new LinkedList
<EventRule
>();
111 for (EventRule eventRule
: enabledEventRules
.keySet()) {
112 if (eventRule
.getEventName().equals(eventName
)) {
113 rulesToRemove
.add(eventRule
);
117 * We cannot modify the map while iterating on it. We have to do the
118 * removal separately from the iteration above.
120 for (EventRule rule
: rulesToRemove
) {
121 removeEventRule(rule
);
125 private synchronized void removeEventRule(EventRule eventRule
) {
126 Integer count
= enabledEventRules
.get(eventRule
);
127 if (count
== null || count
.intValue() <= 0) {
129 * We were asked us to disable an event rule that was not enabled
130 * previously. Command error?
132 throw new IllegalStateException();
134 if (count
.intValue() == 1) {
136 * This is the last instance of this event rule being disabled,
137 * remove it from the map and send notifications of this rule being
140 enabledEventRules
.remove(eventRule
);
141 notifyForRemovedRule(eventRule
);
145 * Other sessions/daemons are still looking for this event rule, simply
146 * decrement its refcount, and do not send notifications.
148 enabledEventRules
.put(eventRule
, Integer
.valueOf(count
.intValue() - 1));
153 * Register a new listener to the manager.
156 * The listener to add
158 public synchronized void registerListener(IFilterChangeListener listener
) {
159 registeredListeners
.add(listener
);
161 /* Send the current rules to the new listener ("statedump") */
162 for (EventRule rule
: enabledEventRules
.keySet()) {
163 listener
.eventRuleAdded(rule
);
168 * Unregister a listener from the manager.
171 * The listener to remove
173 public synchronized void unregisterListener(IFilterChangeListener listener
) {
174 registeredListeners
.remove(listener
);
177 private void notifyForAddedRule(final EventRule rule
) {
178 for (IFilterChangeListener notifier
: registeredListeners
) {
179 notifier
.eventRuleAdded(rule
);
183 private void notifyForRemovedRule(final EventRule rule
) {
184 for (IFilterChangeListener notifier
: registeredListeners
) {
185 notifier
.eventRuleRemoved(rule
);