Introduce inbound and outbound signal blacklisting
authorJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Wed, 26 Oct 2016 22:49:24 +0000 (18:49 -0400)
committerJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Fri, 11 Nov 2016 15:36:07 +0000 (10:36 -0500)
Allow blacklisting based on class type hierarchy.

Change-Id: Ia8526799be822679bdc474284c9df8bf0e8c913d
Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
doc/org.eclipse.tracecompass.doc.dev/doc/Developer-Guide.mediawiki
tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/signal/TmfSignalManager.java

index b99decb16465ec5945abe05c2d0c673e82ee9334..1054562653b56abde45eebd1555348dc9e015d98 100644 (file)
@@ -789,6 +789,33 @@ When the throttler is no longer needed, it should be disposed:
 throttler.dispose();
 </pre>
 
+== Ignoring inbound/outbound signals ==
+
+It is possible to stop certain signals from being sent or received.
+
+To block all incoming signals to an object:
+
+<pre>
+    TmfSignalManager.addIgnoredInboundSignal(objectInstance, TmfSignal.class);
+</pre>
+
+To block all outgoing signals originating from an object:
+
+<pre>
+    TmfSignalManager.addIgnoredOutboundSignal(objectInstance, TmfSignal.class);
+</pre>
+
+The blocked signal filtering is based on type hierarchy. Blocking <code>TmfSignal.class</code> will result in blocking all signals derived from TmfSignal. Blocking <code>TmfTraceSelectedSignal</code> will block all signals of this type and derived signals from <code>TmfTraceSelectedSignal</code>
+
+To remove an ignore rule or clear them all:
+<pre>
+    TmfSignalManager.removeIgnoredOutboundSignal(Object source, Class<? extends TmfSignal> signal)
+    TmfSignalManager.removeIgnoredInboundSignal(Object listener, Class<? extends TmfSignal> signal)
+    TmfSignalManager.clearIgnoredOutboundSignalList(Object source)
+    TmfSignalManager.clearIgnoredInboundSignalList(Object listener)
+</pre>
+
+
 == Signal Reference ==
 
 The following is a list of built-in signals defined in the framework.
index 48215a28d6fcc54019fb091b0d02820a4ca61c83..f6a36d98f44075edba8ac83e9f37089c5a9f8120 100644 (file)
@@ -13,6 +13,8 @@
 
 package org.eclipse.tracecompass.tmf.core.signal;
 
+import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
+
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
@@ -22,9 +24,14 @@ import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.tracecompass.internal.tmf.core.Activator;
 import org.eclipse.tracecompass.internal.tmf.core.TmfCoreTracer;
 
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+
 /**
  * This class manages the set of signal listeners and the signals they are
  * interested in. When a signal is broadcasted, the appropriate listeners
@@ -42,6 +49,11 @@ public class TmfSignalManager {
     private static Map<Object, Method[]> fListeners = new HashMap<>();
     private static Map<Object, Method[]> fVIPListeners = new HashMap<>();
 
+    /** The outbound blacklist of pair <source, signal> */
+    private static Multimap<@NonNull Object, @NonNull Class<? extends TmfSignal>> fOutboundSignalBlacklist = HashMultimap.create();
+    /** The inbound blacklist of pair <listener, signal> */
+    private static Multimap<@NonNull Object, @NonNull Class<? extends TmfSignal>> fInboundSignalBlacklist = HashMultimap.create();
+
     // The signal executor for asynchronous signals
     private static final ExecutorService fExecutor = Executors.newSingleThreadExecutor();
 
@@ -73,6 +85,87 @@ public class TmfSignalManager {
         }
     }
 
+    /**
+     * Ignore the outbound signal type from the specified source.
+     * One can ignore all signals by passing TmfSignal.class as the signal class.
+     *
+     * @param source
+     *            The source object
+     * @param signal
+     *            The signal class to ignore
+     * @since 2.2
+     */
+    @NonNullByDefault
+    public static synchronized void addIgnoredOutboundSignal(Object source, Class<? extends TmfSignal> signal) {
+        fOutboundSignalBlacklist.put(source, signal);
+    }
+
+    /**
+     * Ignore the inbound signal type for the specified listener.
+     * All signals can be ignored by passing TmfSignal.class.
+     *
+     * @param listener
+     *            The listener object for which the signal must be ignored
+     * @param signal
+     *            The signal class to ignore
+     * @since 2.2
+     */
+    @NonNullByDefault
+    public static synchronized void addIgnoredInboundSignal(Object listener, Class<? extends TmfSignal> signal) {
+        fInboundSignalBlacklist.put(listener, signal);
+    }
+
+    /**
+     * Remove the signal from the list of ignored outbound signal for the
+     * specified source if present.
+     *
+     * @param source
+     *            The source object
+     * @param signal
+     *            The signal class to remove from the ignore list
+     * @since 2.2
+     */
+    public static synchronized void removeIgnoredOutboundSignal(Object source, Class<? extends TmfSignal> signal) {
+        fOutboundSignalBlacklist.remove(source, signal);
+    }
+
+    /**
+     * Remove the signal from the list of inbound ignored signals for the
+     * specified listener if present.
+     *
+     * @param listener
+     *            The listener object
+     * @param signal
+     *            The signal class to remove from the ignore list
+     * @since 2.2
+     */
+    public static synchronized void removeIgnoredInboundSignal(Object listener, Class<? extends TmfSignal> signal) {
+        fInboundSignalBlacklist.remove(listener, signal);
+    }
+
+
+    /**
+     * Clear the list of ignored outbound signals for the source.
+     *
+     * @param source
+     *            The source object
+     * @since 2.2
+     */
+    public static synchronized void clearIgnoredOutboundSignalList(Object source) {
+        fOutboundSignalBlacklist.removeAll(source);
+    }
+
+    /**
+     * Clear the list of ignored inbound signals for the listener.
+     *
+     * @param listener
+     *            The listener object
+     * @since 2.2
+     */
+    public static synchronized void clearIgnoredInboundSignalList(Object listener) {
+        fInboundSignalBlacklist.removeAll(listener);
+    }
+
     /**
      * Register an object to the signal manager as a "VIP" listener. All VIP
      * listeners will all receive the signal before the manager moves on to the
@@ -99,6 +192,8 @@ public class TmfSignalManager {
     public static synchronized void deregister(Object listener) {
         fVIPListeners.remove(listener);
         fListeners.remove(listener);
+        fInboundSignalBlacklist.removeAll(listener);
+        fOutboundSignalBlacklist.removeAll(listener);
     }
 
     /**
@@ -137,6 +232,17 @@ public class TmfSignalManager {
      *            the signal to dispatch
      */
     public static synchronized void dispatchSignal(TmfSignal signal) {
+
+        /* Check if the source,signal tuple is blacklisted */
+        Object source = signal.getSource();
+        if (source != null) {
+            boolean isBlackListed = fOutboundSignalBlacklist.get(source).stream()
+                    .anyMatch(x -> x.isAssignableFrom(signal.getClass()));
+            if (isBlackListed) {
+                return;
+            }
+        }
+
         int signalId = fSignalId++;
         sendSignal(new TmfStartSynchSignal(signalId));
         signal.setReference(signalId);
@@ -186,12 +292,23 @@ public class TmfSignalManager {
 
         // Build the list of listener methods that are registered for this signal
         Class<?> signalClass = signal.getClass();
+
         Map<Object, List<Method>> targets = new HashMap<>();
         targets.clear();
         for (Map.Entry<Object, Method[]> entry : listeners.entrySet()) {
             List<Method> matchingMethods = new ArrayList<>();
             for (Method method : entry.getValue()) {
-                if (method.getParameterTypes()[0].isAssignableFrom(signalClass)) {
+                Class<?> classParam = method.getParameterTypes()[0];
+                if (classParam.isAssignableFrom(signalClass)) {
+                    if (fInboundSignalBlacklist.containsKey(entry.getKey())) {
+                        /* Check if any of the ignore rule apply to the signal */
+                        boolean isBlackListed = fInboundSignalBlacklist.get(checkNotNull(entry.getKey())).stream()
+                                .anyMatch( x ->  x.isAssignableFrom(classParam));
+                        if (isBlackListed) {
+                            continue;
+                        }
+                    }
+                    /* No rules apply add it */
                     matchingMethods.add(method);
                 }
             }
This page took 0.030856 seconds and 5 git commands to generate.