Clean up BindingRuntimeContext instantiation
Description
blocks
is duplicated by
Activity
Robert Varga February 28, 2020 at 9:51 AM
https://git.opendaylight.org/gerrit/c/mdsal/+/88028 deals with the all but the codec/adapter parts. It leaves off with a properly-published BindingRuntimeContext, which needs to be injected into codec/adapter. We already have the CodecTree part of codec ready, but adapter's use of CodecRegistry needs to be audited. We may need a separate interface for a fused CodecContextFactory, BindingCodecTree, DataObjectSerializerRegistry – which is what BindingCodecContext provides.
Robert Varga February 22, 2020 at 10:49 PMEdited
The code has been refactored to the point where we have mdsal-binding-runtime-{api,spi}. API is where BindingRuntimeContext landed. SPI is where ModuleInfoBackedContext ended up being (which cleaned the dependency tree a lot). It is used by static utilities (for tests and statically-wired environments), which do not offer any fallback classloader nor support dynamic updates. Its dynamic capabilities are used only by mdsal-binding-dom-codec-osgi.
mdsal-binding-dom-codec-osgi also does the wrong thing, really, as it is using ClassLoaderFactory to effectively enlarge the space of allowed classloaders (in the hope they'll provide the augmentation being saught), hence its BindingRuntimeContext is not really immutable, as the backing factory is playing tricks – which directly contradicts Immutable contract. The dynamic part of ModuleInfoBackedContext needs to be factored out into a Builder pattern, where the dynamic parts of ModuleInfoBackedContext are handled by the OSGi part (i.e. retain a cache/registry/etc.). Once it attempts to create a BindingRuntimeContext, it really wants to capture a snapshot of current state of affairs, including the right set of ClassLoaders and present that as the BindingRuntimeContext. This will disconnect the BindingRuntimeContext from any further actions of the OSGi part.
mdsal-binding-dom-codec-osgi tries to solve this by propagating BindingRuntimeContext updates, but unfortunately no one is acting on them – as evidenced by https://git.opendaylight.org/gerrit/c/mdsal/+/79999 .
The root cause is the use of Blueprint by mdsal-binding-dom-adapter. Blueprint's take on lifecycle is that you cannot retain (i.e. cache) anything the service has given you – simply because if the service goes away, there is no way to find out, because BP will very helpfully actually block the call until the disappeared services comes back (backed by completely different state!) and then resume operation. If the service does not come back by some arbitrary time, it will throw an exception. There is nothing we can use to invalidate anything we cache, hence we cannot cache anything.
This means that while mdsal-binding-dom-codec can be tightly bound to a BindingRuntimeContext (and internally is via BindingCodecContext), this is not exposed to the adapter, but rather covered by the BindingNormalizedNodeCodecRegistry indirection – which actually is the only implementation class the adapter uses!.
OSGi Declarative Services (DS), a.k.a Service Component Runtime, provides a properly-propagated binding lifecycle where we are in control of the services we are actually talking to. Most notably the default static binding completely embraces immutability and guarantees that the binding does not change between invocation of @Activate and @Deactivate methods. This in turn allows us to instantiated immutable services – and those do not need to deal with externalities changing. At the very most there may end up being some inter-component hand-off, but the need for that is not quite clear ATM.
We want to remove BindingRuntimeContextListener, but we also want to leverage DS to perform all the service tracking – hence we can whiteboard easily and not worry about how things are coming and going.
Therefore Blueprint has to be terminated with prejudice and replaced by properly-defined components. The primary component is mdsal-binding-runtime-osgi, a new component, which will do the codec-osgi work and publish BindingRuntimeContext as a component (hence it needs to become a service).
All of these will be naturally immutable, allowing safe derivation of state. This also means that for OSGi binding-runtime-osgi will also provide the DOMSchemaService component – as that is readily derived. Once DOM is ready (i.e. when we have ), this role will revert to the DOM layer and Binding will just tack BindingRuntimeTypes on top of a ClassLoading strategy.
At the end of all of this, binding-dom-codec needs to provide a factory, which takes a BindingRuntimeContext and produces the public equivalent of BindingCodecContext. That factory is then used by binding-dom-adapter to instantiate its context – and publish services across them.
Robert Varga February 22, 2020 at 8:45 PM
Okay, so after moving things around and cleaning them up, the picture is quite clear – we are battling lifecycle issues coming from multiple fronts and their common denominator is that the entities involved are not effectively-immutable and are attempting to make in-place updates work.
This will involve multiple steps, each of which will provide incremental improvement to the situation at hand.
Robert Varga July 24, 2019 at 11:45 AM
Acquiring a ClassLoader in OSGi requires knowledge of at least one class name, so that the class can be looked up.
In order to do this, mdsal-binding-dom-codec-osgi is examining /META-INF/services/org.opendaylight.yangtools.yang.binding.YangModelBindingProvider, which is a springboard to YangModuleInfo.
There is no DOM-level service available, which would provide the equivalent facility, not at least until we have implemented. Until that is done, mdsal-dom-schema-service-osgi should be bound to the binding packaging in its reliance on YangModelBindingProvider. Note it should not instantiate the provider, just load the class. Most definitely it must not access YangModuleInfo and the dependency information it holds, as that static resolution (and implied inter-revision dependencies) are part of Binding Spec proper.
Michael Vorburger January 29, 2019 at 6:11 PM
> BindingRuntimeContextListener and BindingRuntimeContextService need to be disregarded, as they are not used anywhere
DOM OSGi SchemaContext services and the interaction between binding codec, adapter are quite a bit perplexing. The wiring should really be simplified, so that we can arrive at a place where the codec tree is completely predictable and does not rely on TCCL.
One key ingredient we seem to be missing is that the set of ClassLoaders from which a particular SchemaContext should be carried with it.