Improve notification delivery defensiveness
[mdsal.git] / dom / mdsal-dom-broker / src / main / java / org / opendaylight / mdsal / dom / broker / DOMNotificationRouterEvent.java
index e75adebfd29384971da0a9b696d427096268ba45..9dd4f6a3ec999aab0a58261c6e3ae21a31a31a8b 100644 (file)
@@ -7,29 +7,27 @@
  */
 package org.opendaylight.mdsal.dom.broker;
 
-import com.google.common.base.Preconditions;
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.SettableFuture;
 import com.lmax.disruptor.EventFactory;
 import java.util.Collection;
 import org.opendaylight.mdsal.dom.api.DOMNotification;
 import org.opendaylight.mdsal.dom.api.DOMNotificationListener;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
- * A single notification event in the disruptor ringbuffer. These objects are reused,
- * so they do have mutable state.
+ * A single notification event in the disruptor ringbuffer. These objects are reused, so they do have mutable state.
  */
 final class DOMNotificationRouterEvent {
-    public static final EventFactory<DOMNotificationRouterEvent> FACTORY =
-            new EventFactory<DOMNotificationRouterEvent>() {
-        @Override
-        public DOMNotificationRouterEvent newInstance() {
-            return new DOMNotificationRouterEvent();
-        }
-    };
+    private static final Logger LOG = LoggerFactory.getLogger(DOMNotificationRouterEvent.class);
 
-    private Collection<ListenerRegistration<? extends DOMNotificationListener>> subscribers;
+    static final EventFactory<DOMNotificationRouterEvent> FACTORY = DOMNotificationRouterEvent::new;
+
+    private Collection<AbstractListenerRegistration<? extends DOMNotificationListener>> subscribers;
     private DOMNotification notification;
     private SettableFuture<Void> future;
 
@@ -37,19 +35,25 @@ final class DOMNotificationRouterEvent {
         // Hidden on purpose, initialized in initialize()
     }
 
+    @SuppressWarnings("checkstyle:hiddenField")
     ListenableFuture<Void> initialize(final DOMNotification notification,
-            final Collection<ListenerRegistration<? extends DOMNotificationListener>> subscribers) {
-        this.notification = Preconditions.checkNotNull(notification);
-        this.subscribers = Preconditions.checkNotNull(subscribers);
+            final Collection<AbstractListenerRegistration<? extends DOMNotificationListener>> subscribers) {
+        this.notification = requireNonNull(notification);
+        this.subscribers = requireNonNull(subscribers);
         this.future = SettableFuture.create();
         return this.future;
     }
 
+    @SuppressWarnings("checkstyle:illegalCatch")
     void deliverNotification() {
-        for (ListenerRegistration<? extends DOMNotificationListener> r : subscribers) {
-            final DOMNotificationListener l = r.getInstance();
-            if (l != null) {
-                l.onNotification(notification);
+        for (AbstractListenerRegistration<? extends DOMNotificationListener> reg : subscribers) {
+            if (reg.notClosed()) {
+                final DOMNotificationListener listener = reg.getInstance();
+                try {
+                    listener.onNotification(notification);
+                } catch (Exception e) {
+                    LOG.warn("Listener {} failed during notification delivery", listener, e);
+                }
             }
         }
     }
@@ -57,5 +61,4 @@ final class DOMNotificationRouterEvent {
     void setFuture() {
         future.set(null);
     }
-
-}
\ No newline at end of file
+}