e1c96e1609bf8f332627093a167d4a3233332a1a
[lttng-ust.git] /
1 /*
2 * SPDX-License-Identifier: LGPL-2.1-only
3 *
4 * Copyright (C) 2015 EfficiOS Inc.
5 * Copyright (C) 2015 Alexandre Montplaisir <alexmonthy@efficios.com>
6 */
7
8 package org.lttng.ust.agent.filter;
9
10 import java.util.Collection;
11 import java.util.HashMap;
12 import java.util.LinkedList;
13 import java.util.List;
14 import java.util.Map;
15
16 import org.lttng.ust.agent.session.EventRule;
17
18 /**
19 * Singleton class managing the filter notifications.
20 *
21 * Applications can register a {@link IFilterChangeListener} to be notified when
22 * event filtering rules change in the tracing sessions.
23 *
24 * @author Alexandre Montplaisir
25 */
26 public final class FilterChangeNotifier {
27
28 /** Lazy-loaded singleton instance object */
29 private static FilterChangeNotifier instance = null;
30
31 private final Map<EventRule, Integer> enabledEventRules = new HashMap<EventRule, Integer>();
32 private final Collection<IFilterChangeListener> registeredListeners = new LinkedList<IFilterChangeListener>();
33
34
35 /**
36 * Private constructor, singleton class should not be instantiated directly.
37 */
38 private FilterChangeNotifier() {
39 }
40
41 /**
42 * Get the singleton instance, initializing it if needed.
43 *
44 * @return The singleton instance
45 */
46 public static synchronized FilterChangeNotifier getInstance() {
47 if (instance == null) {
48 instance = new FilterChangeNotifier();
49 }
50 return instance;
51 }
52
53 /**
54 * Notify the filter manager that a new rule was enabled in a tracing
55 * session ("lttng enable-event ...")
56 *
57 * This is meant to be called by the LTTng Agent only. External Java
58 * applications should not call this.
59 *
60 * @param rule
61 * The rule that was added
62 */
63 public synchronized void addEventRule(EventRule rule) {
64 Integer count = enabledEventRules.get(rule);
65 if (count == null) {
66 /*
67 * This is the first instance of this rule being enabled. Add it to
68 * the map and send notifications to the registered notifiers.
69 */
70 enabledEventRules.put(rule, Integer.valueOf(1));
71 notifyForAddedRule(rule);
72 return;
73 }
74 if (count.intValue() <= 0) {
75 /* It should not have been in the map! */
76 throw new IllegalStateException();
77 }
78 /*
79 * This exact event rule was already enabled, just increment its
80 * refcount without sending notifications
81 */
82 enabledEventRules.put(rule, Integer.valueOf(count.intValue() + 1));
83 }
84
85 /**
86 * Notify the filter manager that an event name was disabled in the tracing
87 * sessions ("lttng disable-event ...").
88 *
89 * The "disable-event" only specifies an event name. This means all the
90 * rules containing this event name are to be disabled.
91 *
92 * This is meant to be called by the LTTng Agent only. External Java
93 * applications should not call this.
94 *
95 * @param eventName
96 * The event name to disable
97 */
98 public synchronized void removeEventRules(String eventName) {
99 List<EventRule> rulesToRemove = new LinkedList<EventRule>();
100
101 for (EventRule eventRule : enabledEventRules.keySet()) {
102 if (eventRule.getEventName().equals(eventName)) {
103 rulesToRemove.add(eventRule);
104 }
105 }
106 /*
107 * We cannot modify the map while iterating on it. We have to do the
108 * removal separately from the iteration above.
109 */
110 for (EventRule rule : rulesToRemove) {
111 removeEventRule(rule);
112 }
113 }
114
115 private synchronized void removeEventRule(EventRule eventRule) {
116 Integer count = enabledEventRules.get(eventRule);
117 if (count == null || count.intValue() <= 0) {
118 /*
119 * We were asked us to disable an event rule that was not enabled
120 * previously. Command error?
121 */
122 throw new IllegalStateException();
123 }
124 if (count.intValue() == 1) {
125 /*
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
128 * gone.
129 */
130 enabledEventRules.remove(eventRule);
131 notifyForRemovedRule(eventRule);
132 return;
133 }
134 /*
135 * Other sessions/daemons are still looking for this event rule, simply
136 * decrement its refcount, and do not send notifications.
137 */
138 enabledEventRules.put(eventRule, Integer.valueOf(count.intValue() - 1));
139
140 }
141
142 /**
143 * Register a new listener to the manager.
144 *
145 * @param listener
146 * The listener to add
147 */
148 public synchronized void registerListener(IFilterChangeListener listener) {
149 registeredListeners.add(listener);
150
151 /* Send the current rules to the new listener ("statedump") */
152 for (EventRule rule : enabledEventRules.keySet()) {
153 listener.eventRuleAdded(rule);
154 }
155 }
156
157 /**
158 * Unregister a listener from the manager.
159 *
160 * @param listener
161 * The listener to remove
162 */
163 public synchronized void unregisterListener(IFilterChangeListener listener) {
164 registeredListeners.remove(listener);
165 }
166
167 private void notifyForAddedRule(final EventRule rule) {
168 for (IFilterChangeListener notifier : registeredListeners) {
169 notifier.eventRuleAdded(rule);
170 }
171 }
172
173 private void notifyForRemovedRule(final EventRule rule) {
174 for (IFilterChangeListener notifier : registeredListeners) {
175 notifier.eventRuleRemoved(rule);
176 }
177 }
178 }
This page took 0.031907 seconds and 3 git commands to generate.