From: Robert Varga Date: Mon, 15 Nov 2021 08:03:27 +0000 (+0100) Subject: Add DOMInstanceNotificationService X-Git-Tag: v9.0.2~29 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=mdsal.git;a=commitdiff_plain;h=4e4fb5facd45805b6661a53aea71cbcf83db6e96 Add DOMInstanceNotificationService DOMNotificationService provides a means to subscribe to top-level notifications, as defined by YANG 1.0. RFC7950 (YANG 1.1) extended this construct with the notion that notifications can be bound to a datastore instance. Define a set of DOMInstanceNotification* interfaces which cover provide a conterpart to DOMNotification* interfaces and cover the extensions introduced in YANG 1.1. JIRA: MDSAL-494 Change-Id: I610f761bfcb9fb292709dd12618ec5bcb9b843c2 Signed-off-by: Robert Varga --- diff --git a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMInstanceNotificationListener.java b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMInstanceNotificationListener.java new file mode 100644 index 0000000000..f4db1b7583 --- /dev/null +++ b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMInstanceNotificationListener.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.mdsal.dom.api; + +import com.google.common.annotations.Beta; +import java.util.EventListener; +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * An {@link EventListener} registered to receive instance (YANG 1.1) {@link DOMNotification}s from a + * {@link DOMInstanceNotificationService}. + */ +@Beta +@FunctionalInterface +@NonNullByDefault +public interface DOMInstanceNotificationListener extends EventListener { + /** + * Invoked whenever a {@link DOMNotification} matching the subscription criteria is received. + * + * @param path Notification's parent path + * @param notification Received notification + */ + void onNotification(DOMDataTreeIdentifier path, DOMNotification notification); +} diff --git a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMInstanceNotificationPublishService.java b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMInstanceNotificationPublishService.java new file mode 100644 index 0000000000..c655c3dc75 --- /dev/null +++ b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMInstanceNotificationPublishService.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.mdsal.dom.api; + +import com.google.common.annotations.Beta; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.TimeUnit; +import org.checkerframework.checker.index.qual.NonNegative; +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.yangtools.util.concurrent.FluentFutures; + +/** + * A {@link DOMService} which allows its user to publish instance (YANG 1.1) {@link DOMNotification}s. It provides two + * styles of initiating the notification delivery, similar to {@link java.util.concurrent.BlockingQueue}: + * + */ +@Beta +public interface DOMInstanceNotificationPublishService extends DOMService { + /** + * Well-known value indicating that the implementation is currently not + * able to accept a notification. + */ + ListenableFuture REJECTED = FluentFutures.immediateFailedFluentFuture( + new DOMNotificationRejectedException("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 path parent reference path + * @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 putNotification(@NonNull DOMDataTreeIdentifier path, + @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(DOMDataTreeIdentifier, DOMNotification)}, this method is guaranteed not to block if the + * underlying implementation encounters contention. + * + * @param path parent reference path + * @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 {@link #REJECTED} if + * resource constraints prevent the implementation from accepting the notification for + * delivery. + * @throws NullPointerException if notification is null. + */ + @NonNull ListenableFuture offerNotification(@NonNull DOMDataTreeIdentifier path, + @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(DOMDataTreeIdentifier, DOMNotification)}, this method is guaranteed to block more than + * the specified timeout. + * + * @param path parent reference path + * @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 {@link #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 offerNotification(@NonNull DOMDataTreeIdentifier path, + @NonNull DOMNotification notification, @NonNegative long timeout, @NonNull TimeUnit unit) + throws InterruptedException; +} diff --git a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMInstanceNotificationService.java b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMInstanceNotificationService.java new file mode 100644 index 0000000000..29e1280697 --- /dev/null +++ b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMInstanceNotificationService.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.mdsal.dom.api; + +import com.google.common.annotations.Beta; +import com.google.common.util.concurrent.MoreExecutors; +import java.util.concurrent.Executor; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.opendaylight.yangtools.concepts.Registration; +import org.opendaylight.yangtools.yang.common.QName; + +/** + * A {@link DOMService} providing access to subscription to YANG 1.1 instance notifications. + */ +@Beta +@NonNullByDefault +public interface DOMInstanceNotificationService extends DOMService { + /** + * Register a {@link DOMInstanceNotificationListener} for a particular {@code path} and notification {@code type}. + * + * @param path Instance notification's parent path, must not be empty, but may be a wildcard identifier. + * @param type Notification type, i.e. its schema node QName + * @param listener Listener to deliver notifications to + * @param executor Executor to use for invoking + * @return Listener's registration object + * @throws NullPointerException if any of the arguments is null + * @throws IllegalArgumentException if the {@code path} is empty or if the combination of {@code path} and + * {@code type} does not identify an instance notification + */ + Registration registerNotificationListener(DOMDataTreeIdentifier path, QName type, + DOMInstanceNotificationListener listener, Executor executor); + + /** + * Register a {@link DOMInstanceNotificationListener} for a particular {@code path} and notification {@code type}. + * This method is a convenience equivalent to + * {@code registerNotificationListener(path, type, listener, MoreExecutors.directExecutor())}. + * + * @param path Instance notification's parent path, must not be empty, but may be a wildcard identifier. + * @param type Notification type, i.e. its schema node QName + * @param listener Listener to deliver notifications to + * @return Listener's registration object + * @throws NullPointerException if any of the arguments is null + * @throws IllegalArgumentException if the {@code path} is empty or if the combination of {@code path} and + * {@code type} does not identify an instance notification + */ + default Registration registerNotificationListener(final DOMDataTreeIdentifier path, final QName type, + final DOMInstanceNotificationListener listener) { + return registerNotificationListener(path, type, listener, MoreExecutors.directExecutor()); + } +} diff --git a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMNotificationPublishService.java b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMNotificationPublishService.java index 99bf87141f..f6dcf47890 100644 --- a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMNotificationPublishService.java +++ b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMNotificationPublishService.java @@ -14,14 +14,13 @@ import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.yangtools.util.concurrent.FluentFutures; /** - * 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. + * A {@link DOMService} which allows its user to publish top-level (YANG 1.0) {@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 { /** diff --git a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMNotificationService.java b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMNotificationService.java index 666f125b0e..fd6891671c 100644 --- a/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMNotificationService.java +++ b/dom/mdsal-dom-api/src/main/java/org/opendaylight/mdsal/dom/api/DOMNotificationService.java @@ -14,8 +14,7 @@ import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute; /** - * A {@link DOMService} which allows its users to subscribe to receive - * {@link DOMNotification}s. + * A {@link DOMService} which allows its users to subscribe to receive top-level (YANG 1.0) {@link DOMNotification}s. */ public interface DOMNotificationService extends DOMService { /**