BUG-7608: Clarify DOMRpc routing/invocation/listener interactions 34/51034/4
authorRobert Varga <rovarga@cisco.com>
Wed, 25 Jan 2017 21:47:02 +0000 (22:47 +0100)
committerTom Pantelis <tpanteli@brocade.com>
Mon, 30 Jan 2017 13:45:01 +0000 (13:45 +0000)
As it happens our DOMRpcProviderService is under-documented around
routing behavior and how it interacts with respect to both
DOMRpcService and DOMRpcAvailabilityListener.

Fix this by defining the interactions the same way they are implemented
in the only implementation, DOMRpcRouter.

The fallout of these clarifications is that blueprint's interpretation
of the API contract covers only the RFC6020 RPC part correctly and falls
short of the RFC7950 action case.

This shortcoming will be addressed in a follow-up patch.

Change-Id: I2572c21b7aa6f24b9e2ed37f446b76a032f1880b
Signed-off-by: Robert Varga <rovarga@cisco.com>
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcAvailabilityListener.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcProviderService.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcService.java

index 35c58fe..a62f79d 100644 (file)
@@ -12,8 +12,41 @@ import java.util.EventListener;
 import javax.annotation.Nonnull;
 
 /**
- * An {@link EventListener} used to track RPC implementations becoming (un)available
- * to a {@link DOMRpcService}.
+ * An {@link EventListener} used to track RPC implementations becoming (un)available a {@link DOMRpcService}. Note that
+ * the reported {@link DOMRpcIdentifier}s form an identifier space shared between RFC7950 actions and RFC6020 RPCs,
+ * the former being also known as 'Routed RPCs'.
+ *
+ * <p>
+ * Interpretation of DOMRpcIdentifiers has to be evaluated in the context of one of these types, which need to be
+ * determined by matching {@link DOMRpcIdentifier#getType()} against a
+ * {@link org.opendaylight.yangtools.yang.model.api.SchemaContext}, which determines actual semantics of
+ * {@link DOMRpcIdentifier#getContextReference()}. Corresponding SchemaNode is required to be a known sub-interface
+ * of {@link org.opendaylight.yangtools.yang.model.api.OperationDefinition}.
+ *
+ * <p>
+ * For RFC6020 RPCs, reported context reference is always non-null and empty. It indicates an RPC implementation has
+ * been registered and invocations can be reasonably (with obvious distributed system caveats coming from asynchronous
+ * events) expected to succeed.
+ *
+ * <p>
+ * For RFC7950 actions with a non-empty context-reference, the indication is the same as for RFC6020 RPCs.
+ *
+ * <p>
+ * For RFC7950 actions with an empty context-reference, the indication is that the corresponding actions are
+ * potentially available, but are subject to dynamic lifecycle of their context references. This includes two primary
+ * use cases:
+ * <ul>
+ *     <li>dynamic action instantiation (when a device connects)</li>
+ *     <li>dynamic action translation, such as transforming one action into another</li>
+ * </ul>
+ * First use case will provide further availability events with non-empty context references as they become available,
+ * which can be safely ignored if the listener is interested in pure invocation-type integration.
+ *
+ * <p>
+ * Second use case will not be providing further events, but rather will attempt to map any incoming invocation onto
+ * some other RPC or action, or similar, which can separately fail. If a sub-request fails, such implementations are
+ * required do report {@link DOMRpcImplementationNotAvailableException} as the invocation result, with the underlying
+ * failure being linked as a cause.
  */
 public interface DOMRpcAvailabilityListener extends EventListener {
     /**
index 4a4f965..82de4b0 100644 (file)
@@ -11,8 +11,23 @@ import java.util.Set;
 import javax.annotation.Nonnull;
 
 /**
- * A {@link DOMService} which allows registration of RPC implementations with a conceptual
- * router. The client counterpart of this service is {@link DOMRpcService}.
+ * A {@link DOMService} which allows registration of RPC implementations with a conceptual router. The client
+ * counterpart of this service is {@link DOMRpcService}.
+ *
+ * <p>
+ * This interface supports both RFC6020 RPCs and RFC7950 actions (formerly known as 'Routed RPCs'. Invocation for
+ * RFC6020 RPCs is always based on an empty context reference. Invocation of actions requires a non-empty context
+ * reference and is matched against registered implementations as follows:
+ * <ul>
+ *     <li>First, attempt to look up the implementation based on exact match. If a match is found the invocation is
+ *         on that implementation, returning its result.</li>
+ *     <li>Second, attempt to look up the implementation which registered for empty context reference. If a such an
+ *         implementation exists, invoke that implementation, returning its result</li>
+ *     <li>Throw {@link DOMRpcImplementationNotAvailableException}
+ * </ul>
+ *
+ * <p>
+ * All implementations are required to perform these steps as specified above.
  */
 public interface DOMRpcProviderService extends DOMService {
     /**
@@ -25,7 +40,8 @@ public interface DOMRpcProviderService extends DOMService {
      * @throws NullPointerException if implementation or types is null
      * @throws IllegalArgumentException if types is empty or contains a null element.
      */
-    @Nonnull <T extends DOMRpcImplementation> DOMRpcImplementationRegistration<T> registerRpcImplementation(@Nonnull T implementation, @Nonnull DOMRpcIdentifier... rpcs);
+    @Nonnull <T extends DOMRpcImplementation> DOMRpcImplementationRegistration<T> registerRpcImplementation(
+            @Nonnull T implementation, @Nonnull DOMRpcIdentifier... rpcs);
 
     /**
      * Register an {@link DOMRpcImplementation} object with this service.
@@ -36,5 +52,6 @@ public interface DOMRpcProviderService extends DOMService {
      * @throws NullPointerException if implementation or types is null
      * @throws IllegalArgumentException if types is empty or contains a null element.
      */
-    @Nonnull <T extends DOMRpcImplementation> DOMRpcImplementationRegistration<T> registerRpcImplementation(@Nonnull T implementation, @Nonnull Set<DOMRpcIdentifier> rpcs);
+    @Nonnull <T extends DOMRpcImplementation> DOMRpcImplementationRegistration<T> registerRpcImplementation(
+            @Nonnull T implementation, @Nonnull Set<DOMRpcIdentifier> rpcs);
 }
index e0c95a1..c84e2d3 100644 (file)
@@ -31,17 +31,22 @@ public interface DOMRpcService extends DOMService {
      *         or report a subclass of {@link DOMRpcException} reporting a transport
      *         error.
      */
-    @Nonnull CheckedFuture<DOMRpcResult, DOMRpcException> invokeRpc(@Nonnull SchemaPath type, @Nullable NormalizedNode<?, ?> input);
+    @Nonnull CheckedFuture<DOMRpcResult, DOMRpcException> invokeRpc(@Nonnull SchemaPath type,
+            @Nullable NormalizedNode<?, ?> input);
 
     /**
      * Register a {@link DOMRpcAvailabilityListener} with this service to receive notifications
      * about RPC implementations becoming (un)available. The listener will be invoked with the
      * current implementations reported and will be kept uptodate as implementations come and go.
      *
-     * Users should note that using a listener does not necessarily mean that {@link #invokeRpc(SchemaPath, NormalizedNode)}
-     * will not report a failure due to {@link DOMRpcImplementationNotAvailableException} and
-     * need to be ready to handle it. Implementations are encouraged to take reasonable precautions
-     * to prevent this scenario from occurring.
+     * <p>
+     * Users should note that using a listener does not necessarily mean that
+     * {@link #invokeRpc(SchemaPath, NormalizedNode)} will not report a failure due to
+     * {@link DOMRpcImplementationNotAvailableException} and need to be ready to handle it.
+     *
+     * <p>
+     * Implementations of this interface are encouraged to take reasonable precautions to prevent this scenario from
+     * occurring.
      *
      * @param listener {@link DOMRpcAvailabilityListener} instance to register
      * @return A {@link ListenerRegistration} representing this registration. Performing