X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-binding-api%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Fbinding%2Fapi%2FRpcProviderRegistry.java;h=22db985ba96b82cc4245a42f28ccd3e1f9959774;hb=919145b1bf7d68e436efa9b22c174965005a174a;hp=cc764888cca932b89dacfe8210c6671147bc5f9d;hpb=3b0f2c65bfb0f0b07e27529734561a7ae9ee5ad9;p=controller.git diff --git a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/RpcProviderRegistry.java b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/RpcProviderRegistry.java index cc764888cc..22db985ba9 100644 --- a/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/RpcProviderRegistry.java +++ b/opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/sal/binding/api/RpcProviderRegistry.java @@ -1,3 +1,10 @@ +/* + * 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.sal.binding.api; import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher; @@ -8,40 +15,256 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.RpcService; /** - * Interface defining provider's access to the Rpc Registry which could be used - * to register their implementations of service to the MD-SAL. - * - * @author ttkacik - * + * Provides a registry for Remote Procedure Call (RPC) service implementations. The RPCs are + * defined in YANG models. + *
+ * There are 2 types of RPCs: + *
+ * An RPC is global if there is intended to be only 1 registered implementation. A global RPC is not + * explicitly declared as such, essentially any RPC that is not defined to be routed is considered global. + *
+ * Global RPCs are registered using the + * {@link #addRpcImplementation(Class, RpcService)} method. + * + *
+ * MD-SAL supports routing of RPC between multiple implementations where the appropriate + * implementation is selected at run time based on the content of the RPC message as described in + * YANG model. + *
+ * RPC routing is based on: + *
+ * A context type is modeled in YANG using a combination of a YANG identity
+ * and Opendaylight specific extensions from yang-ext
module. These extensions are:
+ *
identity
.
+ * Instance identifiers that reference these nodes are valid route identifiers for RPCs that
+ * reference this context type.instance-identifier
as a reference to the particular context type defined by the
+ * specified context identity
. The value of this
+ * leaf is used by the RPC broker at run time to route the RPC request to the correct implementation.
+ * Note that context-reference
may only be used on leaf elements of type
+ * instance-identifier
or a type derived from instance-identifier
.+ *
+ * The following snippet declares a simple YANG identity
named example-context
:
+ *
+ *
+ * module example { + * ... + * identity example-context { + * description "Identity used to define an example-context type"; + * } + * ... + * } + *+ *
+ * We then use the declared identity to define a context type by using it in combination
+ * with the context-instance
YANG extension. We'll associate the context type
+ * with a list element in the data tree. This defines the set of nodes whose instance
+ * identifiers are valid for the example-context
context type.
+ *
+ * The following YANG snippet imports the yang-ext
module and defines the list
+ * element named item
inside a container named foo
:
+ *
+ *
+ * module foo { + * ... + * import yang-ext {prefix ext;} + * ... + * container foo { + * list item { + * key "id"; + * leaf id {type string;} + * ext:context-instance "example-context"; + * } + * } + * ... + * } + *+ *
+ * The statement ext:context-instance "example-context";
inside the list element
+ * declares that any instance identifier referencing item
in the data
+ * tree is valid for example-context
. For example, the following instance
+ * identifier:
+ *
+ * InstanceIdentifier.create(Foo.class).child(Item.class,new ItemKey("Foo")) + *+ * is valid for
example-context
. However the following:
+ * + * InstanceIdentifier.create(Example.class) + *+ * is not valid. + *
+ * So using an identity
in combination with context-instance
we
+ * have effectively defined a context type that can be referenced in a YANG RPC input.
+ *
+ *
+ * To define an RPC to be routed based on the context type we need to add an input leaf element + * that references the context type which will hold an instance identifier value to be + * used to route the RPC. + *
+ * The following snippet defines an RPC named show-item
with 2 leaf elements
+ * as input: item
of type instance-identifier
and description
:
+ *
+ *
+ * module foo { + * ... + * import yang-ext {prefix ext;} + * ... + * rpc show-item { + * input { + * leaf item { + * type instance-identifier; + * ext:context-reference example-context; + * } + * leaf description { + * type "string"; + * } + * } + * } + * } + *+ *
+ * We mark the item
leaf with a context-reference
statement that
+ * references the example-context
context type. RPC calls will then be routed
+ * based on the instance identifier value contained in item
. Only instance
+ * identifiers that point to a foo/item
node are valid as input.
+ *
+ * The generated RPC Service interface for the module is: + * + *
+ * interface FooService implements RpcService { + * Future<RpcResult<Void>> showItem(ShowItemInput input); + * } + *+ *
+ * For constructing the RPC input, there are generated classes ShowItemInput and ShowItemInputBuilder. + * + *
+ * To register a routed implementation for the show-item
RPC, we must use the
+ * {@link #addRoutedRpcImplementation(Class, RpcService)} method. This
+ * will return a {@link RoutedRpcRegistration} instance which can then be used to register /
+ * unregister routed paths associated with the registered implementation.
+ *
+ * The following snippet registers myImpl
as the RPC implementation for an
+ * item
with key "foo"
:
+ *
+ * // Create the instance identifier path for item "foo" + * InstanceIdentifier path = InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey("foo")); + * + * // Register myImpl as the implementation for the FooService RPC interface + * RoutedRpcRegistration reg = rpcRegistry.addRoutedRpcImplementation(FooService.class, myImpl); + * + * // Now register for the context type and specific path ID. The context type is specified by the + * // YANG-generated class for the example-context identity. + * reg.registerPath(ExampleContext.class, path); + *+ *
+ * It is also possible to register the same implementation for multiple paths: + * + *
+ * InstanceIdentifier one = InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey("One")); + * InstanceIdentifier two = InstanceIdentifier.create(Foo.class).child(Item.class, new ItemKey("Two")); + * + * RoutedRpcRegistration reg = rpcRegistry.addRoutedRpcImplementation(FooService.class, myImpl); + * reg.registerPath(ExampleContext.class, one); + * reg.registerPath(ExampleContext.class, two); + *+ * + *
+ * When another client invokes the showItem(ShowItemInput)
method on the proxy instance
+ * retrieved via {@link RpcConsumerRegistry#getRpcService(Class)}, the proxy will inspect the
+ * arguments in ShowItemInput, extract the InstanceIdentifier value of the item
leaf and select
+ * the implementation whose registered path matches the InstanceIdentifier value of the item
leaf.
+ *
+ *
+ * The generated interfaces require implementors to return + * {@link java.util.concurrent.Future Future}<{@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult}<{RpcName}Output>> instances. + * + * Implementations should do processing of RPC calls asynchronously and update the + * returned {@link java.util.concurrent.Future Future} instance when processing is complete. + * However using {@link com.google.common.util.concurrent.Futures#immediateFuture(Object) Futures.immediateFuture} + * is valid only if the result is immediately available and asynchronous processing is unnecessary and + * would only introduce additional complexity. + * + *
+ * The {@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult} is a generic + * wrapper for the RPC output payload, if any, and also allows for attaching error or + * warning information (possibly along with the payload) should the RPC processing partially + * or completely fail. This is intended to provide additional human readable information + * for users of the API and to transfer warning / error information across the system + * so it may be visible via other external APIs such as Restconf. + *
+ * It is recommended to use the {@link org.opendaylight.yangtools.yang.common.RpcResult RpcResult}
+ * for conveying appropriate error information
+ * on failure rather than purposely throwing unchecked exceptions if at all possible.
+ * While unchecked exceptions will fail the returned {@link java.util.concurrent.Future Future},
+ * using the intended RpcResult to convey the error information is more user-friendly.
*/
public interface RpcProviderRegistry extends //
RpcConsumerRegistry, //
RouteChangePublisher
+ * See the {@link RpcProviderRegistry class} documentation for information and example on
+ * how to use routed RPCs.
+ *
+ * @param serviceInterface the YANG-generated interface of the RPC Service for which to register.
+ * @param implementation the implementation instance to register.
+ * @return a RoutedRpcRegistration instance which can be used to register paths for the RPC
+ * implementation via invoking {@link RoutedRpcRegistration#registerPath(....).
+ * {@link RoutedRpcRegistration#close()} should be called to unregister the implementation
+ * and all previously registered paths when no longer needed.
+ *
* @throws IllegalStateException
+ * if the supplied RPC interface is not a routed RPC type.
*/
-