From fdf7efda11d2b70f74236d26a85893139be0c8f2 Mon Sep 17 00:00:00 2001 From: Tony Tkacik Date: Wed, 25 Jun 2014 10:26:15 +0200 Subject: [PATCH] Bug 1235: Documented Notification services of MD-SAL Change-Id: I56c7b41b56eef8c92854e986a5f9f7af21ae1d09 Signed-off-by: Tony Tkacik --- .../sal/binding/api/NotificationListener.java | 16 +-- .../api/NotificationProviderService.java | 51 +++++++-- .../sal/binding/api/NotificationService.java | 100 ++++++++++++++++-- .../notify/NotificationPublishService.java | 56 +++++++++- 4 files changed, 197 insertions(+), 26 deletions(-) diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationListener.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationListener.java index 9429d3f8fa..be8e0cefc1 100644 --- a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationListener.java +++ b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationListener.java @@ -12,20 +12,20 @@ import java.util.EventListener; import org.opendaylight.yangtools.yang.binding.Notification; /** - * Interface implemented by objects interested in some sort of Notification. This - * class acts as a base interface for specific listeners which usually are a type + * Interface for a generic listener that is interested in receiving YANG modeled notifications. + * This interface acts as a base interface for specific listeners which usually are a type * capture of this interface. * - * @param Notification type + * @param the interested notification type */ public interface NotificationListener extends EventListener { /** - * Invoked to deliver the notification. Note that this method may be invoked - * from a shared thread pool, so implementations SHOULD NOT perform CPU-intensive - * operations and they definitely MUST NOT invoke any potentially blocking - * operations. + * Invoked to deliver a notification. + *

+ * Note that this method may be invoked from a shared thread pool, so implementations SHOULD NOT + * perform CPU-intensive operations and MUST NOT invoke any potentially blocking operations. * - * @param notification Notification being delivered. + * @param notification the notification. */ void onNotification(T notification); } diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationProviderService.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationProviderService.java index b94695b83d..00db80c19f 100644 --- a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationProviderService.java +++ b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationProviderService.java @@ -14,29 +14,62 @@ import org.opendaylight.controller.md.sal.common.api.notify.NotificationPublishS import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.binding.Notification; +/** + * Interface for a notification service that provides publish/subscribe capabilities for YANG + * modeled notifications. This interface is a combination of the {@link NotificationService} and + * {@link NotificationPublishService} interfaces. + */ public interface NotificationProviderService extends NotificationService, NotificationPublishService { + /** - * Publishes a notification. - * - * @param Notification - * notification to publish. - * + * {@inheritDoc} */ @Override - void publish(Notification notification); + public void publish(Notification notification); /** - * Publishes a notification, listener calls are done in provided executor. - * + * {@inheritDoc} */ @Override - void publish(Notification notification, ExecutorService service); + void publish(Notification notification, ExecutorService executor); + /** + * Registers a listener to be notified about notification subscriptions. This + * enables a component to know when there is a notification listener subscribed + * for a particular notification type. + *

+ * On registration of this listener, the + * {@link NotificationInterestListener#onNotificationSubscribtion(Class)} method + * will be invoked for every notification type that currently has a notification listener + * subscribed. + * + * @param interestListener the listener that will be notified when subscriptions + * for new notification types occur. + * @return a {@link ListenerRegistration} instance that should be used to unregister the listener + * by invoking the {@link ListenerRegistration#close()} method when no longer needed. + */ ListenerRegistration registerInterestListener( NotificationInterestListener interestListener); + /** + * Interface for a listener interested in being notified about notification subscriptions. + */ public interface NotificationInterestListener extends EventListener { + /** + * Callback that is invoked when a notification listener subscribes for a + * particular notification type. + *

+ * This method is only called for the first subscription that occurs for a + * particular notification type. Subsequent subscriptions for the same + * notification type do not trigger invocation of this method. + *

+ * Note:This callback is delivered from thread not owned by this listener, + * all processing should be as fast as possible and implementations should + * not do any blocking calls or block this thread. + * + * @param notificationType the notification type for the subscription that occurred. + */ void onNotificationSubscribtion(Class notificationType); } } diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationService.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationService.java index 46e372aea6..335f55bcbb 100644 --- a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationService.java +++ b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/NotificationService.java @@ -10,24 +10,108 @@ package org.opendaylight.controller.sal.binding.api; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.binding.Notification; +/** + * Notification broker which allows clients to subscribe for and publish YANG-modeled notifications. + * + *

+ * Two styles of listeners are supported: + *

    + *
  • Generic listener
  • + *
  • Dispatch listener - listener, which implements {ModelName}Listener interface, + * which has dispatch methods for each defined notification. Methods are invoked based on notification type (class). + *
  • + * + *

    Generic Listener

    + *

    + * A generic listener implements the {@link NotificationListener} interface which has one callback method + * onNotification that is invoked for any notification type the listener is subscribed to. + *

    + * A generic listener is subscribed using the {@link #registerNotificationListener(Class, NotificationListener)} + * method by which you specify the type of notification to receive. A generic listener may be registered for + * multiple notification types via multiple subscriptions. + *

    + * Generic listeners allow for a more flexible approach, allowing you to subscribe for just + * one type of notification from a YANG model. You could also have a general subscription + * for all notification in the system via + *

    + *   service.registerNotificationListener(Notification.class, listener);
    + * 
    + * + *

    Dispatch Listener

    + *

    + * A dispatch listener implements a YANG-generated module interface {ModuleName}Listener + * which handles all the notifications defined in the YANG model. Each notification type translates to + * a specific method of the form on{NotificationType} on the generated interface. + * The generated interface also extends the + * {@link org.opendaylight.yangtools.yang.binding.NotificationListener} interface and implementations + * are registered using {@link #registerNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener)} + * method. + * + *

    Dispatch Listener Example
    + *

    + * Lets assume we have following YANG model: + * + *

    + * module example {
    + *      ...
    + *
    + *      notification start {
    + *          ...
    + *      }
    + *
    + *      notification stop {
    + *           ...
    + *      }
    + * }
    + * 
    + * + * The generated interface will be: + *
    + *  public interface ExampleListener extends NotificationListener {
    + *      void onStart(Start notification);
    + *      void onStop(Stop notification);
    + *  }
    + * 
    + * The following defines an implementation of the generated interface: + *
    + *  public class MyExampleListener implements ExampleListener {
    + *      public void onStart(Start notification) {
    + *          // do something
    + *      }
    + *
    + *      public void onStop(Stop notification) {
    + *          // do something
    + *      }
    + *  }
    + * 
    + * The implementation is registered as follows: + *
    + *  MyExampleListener listener = new MyExampleListener();
    + *  ListenerRegistration reg = service.registerNotificationListener( listener );
    + * 
    + * The onStart method will be invoked when someone publishes a Start notification and + * the onStop method will be invoked when someone publishes a Stop notification. + */ public interface NotificationService extends BindingAwareService { /** - * Register a generic listener for specified notification type only. + * Registers a generic listener implementation for a specified notification type. * - * @param notificationType - * @param listener - * @return Registration for listener. To unregister listener invoke {@link ListenerRegistration#close()} method. + * @param notificationType the YANG-generated interface of the notification type. + * @param listener the listener implementation that will receive notifications. + * @return a {@link ListenerRegistration} instance that should be used to unregister the listener + * by invoking the {@link ListenerRegistration#close()} method when no longer needed. */ ListenerRegistration> registerNotificationListener( Class notificationType, NotificationListener listener); /** - * Register a listener which implements generated notification interfaces derived from + * Registers a listener which implements a YANG-generated notification interface derived from * {@link org.opendaylight.yangtools.yang.binding.NotificationListener}. - * Listener is registered for all notifications present in implemented interfaces. + * The listener is registered for all notifications present in the implemented interface. * - * @param listener - * @return Registration for listener. To unregister listener invoke {@link ListenerRegistration#close()} method. + * @param listener the listener implementation that will receive notifications. + * @return a {@link ListenerRegistration} instance that should be used to unregister the listener + * by invoking the {@link ListenerRegistration#close()} method when no longer needed. */ ListenerRegistration registerNotificationListener( org.opendaylight.yangtools.yang.binding.NotificationListener listener); diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/notify/NotificationPublishService.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/notify/NotificationPublishService.java index f5f03a106b..bb866f276e 100644 --- a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/notify/NotificationPublishService.java +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/notify/NotificationPublishService.java @@ -9,9 +9,63 @@ package org.opendaylight.controller.md.sal.common.api.notify; import java.util.concurrent.ExecutorService; +/** + * Interface for publishing YANG-modeled notifications. + *

    + * Users of this interface can publish any YANG-modeled notification which will + * be delivered to all subscribed listeners. + *

    + * Prefered way of publishing of notifications is done by invoking {@link #publish(Object)}. + * + *

    You may consider using {@link #publish(Object, ExecutorService)} if and only if + * your use-case requires customized execution policy or run-to-completion + * inside process. + * + *

    + * The metadata required to deliver a notification to the correct listeners is + * extracted from the published notification. + * + * + * FIXME: Consider clarification of execution/delivery policy, how it will be + * affected by Actor model and cluster-wide notifications. + * + * @param + * the type of notifications + */ public interface NotificationPublishService { + /** + * Publishes a notification and notifies subscribed listeners. All listener + * notifications are done via a default executor. + *

    + * Note: This call will block when the default executor is saturated + * and the notification queue for this executor is full. + * + * @param notification + * the notification to publish. + */ void publish(N notification); - void publish(N notification,ExecutorService executor); + /** + * Publishes a notification and notifies subscribed listeners. All listener + * notifications are done via the provided executor. + *

    + * Note: Use only if ineccessary. Consider using + * {@link #publish(Object)} for most use-cases. + * + *

    + * By using this method you could customize execution policy of listeners present + * inside process (e.g. using single-threaded executor or even same-thread executor + * delivery. + * + *

    + * This executor is used only for inside-process notification deliveries. + * + * @param notification + * the notification to publish. + * @param executor + * the executor that will be used to deliver notifications to + * subscribed listeners. + */ + void publish(N notification, ExecutorService executor); } -- 2.36.6