Merge "BUG-2288: DOMNotification API"
authorTony Tkacik <ttkacik@cisco.com>
Thu, 18 Dec 2014 14:13:12 +0000 (14:13 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 18 Dec 2014 14:13:12 +0000 (14:13 +0000)
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);
+    }
+}