[MDSAL-86] Split up BindingDOMRpcImplementationAdapter Created: 28/May/15 Updated: 28/Nov/22 Resolved: 25/Nov/22 |
|
| Status: | Resolved |
| Project: | mdsal |
| Component/s: | Binding runtime |
| Affects Version/s: | None |
| Fix Version/s: | 11.0.0 |
| Type: | Improvement | Priority: | Medium |
| Reporter: | Robert Varga | Assignee: | Robert Varga |
| Resolution: | Done | Votes: | 0 |
| Labels: | pt | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
Operating System: All |
||
| Issue Links: |
|
||||||||
| Description |
|
We create an instance of this class for each RPC registration, which means we need to dynamically create a SchemaPath on each invocation. That schema path is used for lookup in the codec tree cache, which is lazily instantiated. Since we are using a different SchemaPath object on each lookup, equals() part of the cache lookup strays away from the identity comparison, leading to lost performance. Break up the Adapter such that we maintain a per-method registration, which retains the registration SchemaPath. This will result in the lookup not allocating any objects and keeping on the identity path. |
| Comments |
| Comment by Robert Varga [ 05/Nov/19 ] |
|
We will need to implement BindingCodecTree.getSubtreeCodec(SchemaNodeIdentifier), so that we can efficiently lookup RPC input/output as well as notifications. Once we have that, we can properly bind methods to their SchemaContext counterparts without having to go through the codec. This should result in a BindingDOMRpcProviderServiceAdapter having a Cache<Class<? extends RpcService>, RpcServiceClassContext> rpcServiceClasses; populated lazily as services are registered. Furthermore RpcServiceClassContext should have the basic shape of: final class RpcServiceClassContext implements Immutable { final ImmutableMap<SchemaNodeIdentifier, RpcServiceMethodContext> methods; } Note the methods map should not be used during invocation, only during decomposition of the RPC implementation – the keys are input to DOMRpcIdentifier and values form the invocation context, which in turn looks like this: final class RpcServiceMethodContext implements Immutable { final QName inputQName; // Note: shared between all MethodContexts in a ClassContext final BindingNormalizedNodeCodec inputCodec; final BindingNormalizedNodeCodec outputCodec; final RpcMethodInvoker methodInvoker; } now when an implementation is registered, we look up the RpcServiceClassContext and for each RpcServiceMethodContext we create a DOMRpcImplementation, which has a pointer to the MethodContext and the RpcService object being registered. During invocation we use the inputCodec/inputQName combo to create the DataObject representation of input and pass that to the methodInvoker. We then return a variation on LazyDOMRpcResultFuture, which actually holds a reference to outputCodec directly, not going through the codec/codecRegistry. Note that since the DOMRpcImplementations created are not multiplexing but rather each points to a single YANG RPC, we do not consult DOMRpcImplementation.invokeRpc()'s first argument. |
| Comment by Robert Varga [ 05/Nov/19 ] |
|
The problem with this decomposition, though, is that the resulting object would not be registered atomically – for that we will need an atomic DOMRpcProviderService.registerRpcImplementations(Map<DOMRpcIdentifier, DOMRpcImplementation>); method and have that implemented. |
| Comment by Robert Varga [ 04/Oct/22 ] |
|
I think we can address this cleanly by removing the Adapter, as we won't be needing it. |
| Comment by Robert Varga [ 24/Nov/22 ] |
|
Actually, we can implement an efficient split by reusing the DOM and Binding infra existing for single-RPC invocations. |