BUG-2288: DOMNotification API 84/11484/18
authorRobert Varga <rovarga@cisco.com>
Wed, 17 Sep 2014 19:17:43 +0000 (21:17 +0200)
committerRobert Varga <rovarga@cisco.com>
Tue, 9 Dec 2014 15:05:52 +0000 (16:05 +0100)
This API definition tries to fix the missing pieces in the
CompositeNode-centered APIs, such as inability to drop a notification
rather than waiting for resources needed to publish it to become
available.

Also adds missing documentation to the DOMService concept, which is used
by the two services being defined.

Change-Id: I93d22cf6121a7cf231b2da424e94d14b59fb883f
Signed-off-by: Robert Varga <rovarga@cisco.com>
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMNotification.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMNotificationListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMNotificationListenerRegistration.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMNotificationPublishService.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMNotificationService.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMService.java
opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/AbstractDOMNotificationListenerRegistration.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMNotificationPublishService.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMNotificationService.java [new file with mode: 0644]

diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMNotification.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMNotification.java
new file mode 100644 (file)
index 0000000..d99001e
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.api;
+
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+/**
+ * A single YANG notification.
+ */
+public interface DOMNotification {
+    /**
+     * Return the type of this notification.
+     *
+     * @return Notification type.
+     */
+    @Nonnull SchemaPath getType();
+
+    /**
+     * Return the body of this notification.
+     *
+     * @return Notification body.
+     */
+    @Nonnull ContainerNode getBody();
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMNotificationListener.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMNotificationListener.java
new file mode 100644 (file)
index 0000000..7085588
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.api;
+
+import java.util.EventListener;
+import javax.annotation.Nonnull;
+
+/**
+ * Interface implemented by listeners interested in {@link DOMNotification}s.
+ */
+public interface DOMNotificationListener extends EventListener {
+    /**
+     * Invoked whenever a {@link DOMNotification} matching the subscription
+     * criteria is received.
+     *
+     * @param notification Received notification
+     */
+    void onNotification(@Nonnull DOMNotification notification);
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMNotificationListenerRegistration.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMNotificationListenerRegistration.java
new file mode 100644 (file)
index 0000000..4dccad2
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.api;
+
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+
+/**
+ * A registration of a {@link DOMNotificationListener}. Invoking {@link #close()} will prevent further
+ * delivery of events to the listener.
+ */
+public interface DOMNotificationListenerRegistration extends ListenerRegistration<DOMNotificationListener> {
+
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMNotificationPublishService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMNotificationPublishService.java
new file mode 100644 (file)
index 0000000..8a845e8
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.api;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.Nonnegative;
+import javax.annotation.Nonnull;
+
+/**
+ * A {@link DOMService} which allows its user to send {@link DOMNotification}s. It
+ * provides two styles of initiating the notification delivery, similar to
+ * {@link java.util.concurrent.BlockingQueue}:
+ * - a put-style method which waits until the implementation can accept the notification
+ *   for delivery, and
+ * - an offer-style method, which attempts to enqueue the notification, but allows
+ *   the caller to specify that it should never wait, or put an upper bound on how
+ *   long it is going to wait.
+ */
+public interface DOMNotificationPublishService extends DOMService {
+    /**
+     * Well-known value indicating that the implementation is currently not
+     * able to accept a notification.
+     */
+    ListenableFuture<Object> REJECTED = Futures.immediateFailedFuture(new Throwable("Unacceptable blocking conditions encountered"));
+
+    /**
+     * Publish a notification. The result of this method is a {@link ListenableFuture}
+     * which will complete once the notification has been delivered to all immediate
+     * registrants. The type of the object resulting from the future is not defined
+     * and implementations may use it to convey additional information related to the
+     * publishing process.
+     *
+     * Abstract subclasses can refine the return type as returning a promise of a
+     * more specific type, e.g.:
+     *
+     *     public interface DeliveryStatus { int getListenerCount(); }
+     *     ListenableFuture<? extends DeliveryStatus> putNotification(DOMNotification notification);
+     *
+     * Once the Future succeeds, the resulting object can be queried for traits using
+     * instanceof, e.g:
+     *
+     *     // Can block when (for example) the implemention's ThreadPool queue is full
+     *     Object o = service.putNotification(notif).get();
+     *     if (o instanceof DeliveryStatus) {
+     *         DeliveryStatus ds = (DeliveryStatus)o;
+     *         LOG.debug("Notification was received by {} listeners", ds.getListenerCount(););
+     *     }
+     * }
+     *
+     * In case an implementation is running out of resources, it can block the calling
+     * thread until enough resources become available to accept the notification for
+     * processing, or it is interrupted.
+     *
+     * Caution: completion here means that the implementation has completed processing
+     *          of the notification. This does not mean that all existing registrants
+     *          have seen the notification. Most importantly, the delivery process at
+     *          other cluster nodes may have not begun yet.
+     *
+     * @param notification Notification to be published.
+     * @return A listenable future which will report completion when the service
+     *         has finished propagating the notification to its immediate registrants.
+     * @throws InterruptedException if interrupted while waiting
+     * @throws NullPointerException if notification is null.
+     */
+    @Nonnull ListenableFuture<? extends Object> putNotification(@Nonnull DOMNotification notification) throws InterruptedException;
+
+    /**
+     * Attempt to publish a notification. The result of this method is a {@link ListenableFuture}
+     * which will complete once the notification has been delivered to all immediate
+     * registrants. The type of the object resulting from the future is not defined
+     * and implementations may use it to convey additional information related to the
+     * publishing process. Unlike {@link #putNotification(DOMNotification)}, this method
+     * is guaranteed not to block if the underlying implementation encounters contention.
+     *
+     * @param notification Notification to be published.
+     * @return A listenable future which will report completion when the service
+     *         has finished propagating the notification to its immediate registrants,
+     *         or {@value #REJECTED} if resource constraints prevent
+     *         the implementation from accepting the notification for delivery.
+     * @throws NullPointerException if notification is null.
+     */
+    @Nonnull ListenableFuture<? extends Object> offerNotification(@Nonnull DOMNotification notification);
+
+    /**
+     * Attempt to publish a notification. The result of this method is a {@link ListenableFuture}
+     * which will complete once the notification has been delivered to all immediate
+     * registrants. The type of the object resulting from the future is not defined
+     * and implementations may use it to convey additional information related to the
+     * publishing process. Unlike {@link #putNotification(DOMNotification)}, this method
+     * is guaranteed to block more than the specified timeout.
+     *
+     * @param notification Notification to be published.
+     * @param timeout how long to wait before giving up, in units of unit
+     * @param unit a TimeUnit determining how to interpret the timeout parameter
+     * @return A listenable future which will report completion when the service
+     *         has finished propagating the notification to its immediate registrants,
+     *         or {@value #REJECTED} if resource constraints prevent
+     *         the implementation from accepting the notification for delivery.
+     * @throws InterruptedException if interrupted while waiting
+     * @throws NullPointerException if notification or unit is null.
+     * @throws IllegalArgumentException if timeout is negative.
+     */
+    @Nonnull ListenableFuture<? extends Object> offerNotification(@Nonnull DOMNotification notification,
+        @Nonnegative long timeout, @Nonnull TimeUnit unit) throws InterruptedException;
+}
diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMNotificationService.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMNotificationService.java
new file mode 100644 (file)
index 0000000..6bce9c4
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.api;
+
+import java.util.Collection;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+/**
+ * A {@link DOMService} which allows its users to subscribe to receive
+ * {@link DOMNotification}s.
+ */
+public interface DOMNotificationService {
+    /**
+     * Register a {@link DOMNotificationListener} to receive a set of notifications. As with
+     * other ListenerRegistration-based interfaces, registering an instance multiple times
+     * results in notifications being delivered for each registration.
+     *
+     * @param listener Notification instance to register
+     * @param types Notification types which should be delivered to the listener. Duplicate
+     *              entries are processed only once, null entries are ignored.
+     * @return Registration handle. Invoking {@link DOMNotificationListenerRegistration#close()}
+     *         will stop the delivery of notifications to the listener
+     * @throws IllegalArgumentException if types is empty or contains an invalid element, such as
+     *         null or a SchemaPath which does not represent a valid {@link DOMNotification} type.
+     * @throws NullPointerException if either of the arguments is null
+     */
+    DOMNotificationListenerRegistration registerNotificationListener(@Nonnull DOMNotificationListener listener, @Nonnull Collection<SchemaPath> types);
+
+    /**
+     * Register a {@link DOMNotificationListener} to receive a set of notifications. As with
+     * other ListenerRegistration-based interfaces, registering an instance multiple times
+     * results in notifications being delivered for each registration.
+     *
+     * @param listener Notification instance to register
+     * @param types Notification types which should be delivered to the listener. Duplicate
+     *              entries are processed only once, null entries are ignored.
+     * @return Registration handle. Invoking {@link DOMNotificationListenerRegistration#close()}
+     *         will stop the delivery of notifications to the listener
+     * @throws IllegalArgumentException if types is empty or contains an invalid element, such as
+     *         null or a SchemaPath which does not represent a valid {@link DOMNotification} type.
+     * @throws NullPointerException if listener is null
+     */
+    // FIXME: Java 8: provide a default implementation of this method.
+    DOMNotificationListenerRegistration registerNotificationListener(@Nonnull DOMNotificationListener listener, SchemaPath... types);
+}
index 357cb8bfe610fbfd226a3d3b2f5cbb2c5cdc4d67..dc18394ffd4225131c3369baefe42bbf19cca2e6 100644 (file)
@@ -5,9 +5,12 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html.
  */
-
 package org.opendaylight.controller.md.sal.dom.api;
 
+/**
+ * Marker interface for services which can be obtained from a {@link DOMMountPoint}
+ * instance. No further semantics are implied.
+ */
 public interface DOMService {
 
 }
diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/AbstractDOMNotificationListenerRegistration.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/AbstractDOMNotificationListenerRegistration.java
new file mode 100644 (file)
index 0000000..2934b0d
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.spi;
+
+import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationListenerRegistration;
+import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
+
+/**
+ * Utility base class for {@link DOMNotificationListenerRegistration}
+ * implementations.
+ */
+public abstract class AbstractDOMNotificationListenerRegistration extends AbstractListenerRegistration<DOMNotificationListener> implements DOMNotificationListenerRegistration {
+    /**
+     * Default constructor. Subclasses need to invoke it from their
+     * constructor(s).
+     *
+     * @param listener {@link DOMNotificationListener} instance which is
+     *                 being held by this registration. May not be null.
+     */
+    protected AbstractDOMNotificationListenerRegistration(final @Nonnull DOMNotificationListener listener) {
+        super(listener);
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMNotificationPublishService.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMNotificationPublishService.java
new file mode 100644 (file)
index 0000000..6bc1107
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.spi;
+
+import com.google.common.collect.ForwardingObject;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.concurrent.TimeUnit;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotification;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationPublishService;
+
+/**
+ * Utility implementations of {@link DOMNotificationPublishService} which forwards
+ * all requests to a delegate instance.
+ */
+public abstract class ForwardingDOMNotificationPublishService extends ForwardingObject implements DOMNotificationPublishService {
+    @Override
+    protected abstract DOMNotificationPublishService delegate();
+
+    @Override
+    public ListenableFuture<? extends Object> putNotification(final DOMNotification notification) throws InterruptedException {
+        return delegate().putNotification(notification);
+    }
+
+    @Override
+    public ListenableFuture<? extends Object> offerNotification(final DOMNotification notification) {
+        return delegate().offerNotification(notification);
+    }
+
+    @Override
+    public ListenableFuture<? extends Object> offerNotification(final DOMNotification notification, final long timeout,
+            final TimeUnit unit) throws InterruptedException {
+        return delegate().offerNotification(notification, timeout, unit);
+    }
+}
diff --git a/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMNotificationService.java b/opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/md/sal/dom/spi/ForwardingDOMNotificationService.java
new file mode 100644 (file)
index 0000000..5199a38
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.md.sal.dom.spi;
+
+import com.google.common.collect.ForwardingObject;
+import java.util.Collection;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationListenerRegistration;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+/**
+ * Utility implementation of a {@link DOMNotificationService} which forwards all requests
+ * to a delegate instance.
+ */
+public abstract class ForwardingDOMNotificationService extends ForwardingObject implements DOMNotificationService {
+    @Override
+    protected abstract DOMNotificationService delegate();
+
+    @Override
+    public DOMNotificationListenerRegistration registerNotificationListener(final DOMNotificationListener listener,
+            final Collection<SchemaPath> types) {
+        return delegate().registerNotificationListener(listener, types);
+    }
+
+    @Override
+    public DOMNotificationListenerRegistration registerNotificationListener(final DOMNotificationListener listener,
+            final SchemaPath... types) {
+        return delegate().registerNotificationListener(listener, types);
+    }
+}