Requirement-Capability Model Library
Add a Requirement-Capability-Model (RCM) library that can replace the current requirement-capability model in the framework lib.
The current (2.3.0) requirement-capability model works on globals and is not reentrant. A new requirement-capability model can be made as a separate (Apache Celix specific) library, which can be used in the framework lib.
The goal of the RCM library should be to provide functionality for:
- [x] Basic Resource dependency model (chapter 3.3, OSGi 8 spec)
- [ ] (Bundle) Wiring of the capability requirement model (Chapter 6 & 7, OSGi 8 spec)
- [ ] Req-Cap resolving, to resolve per resource the requirement based on capabilities from other resources
Note that the functionality can be implemented with multiple pull request (base, wiring, resolving)
The RCM library will then be used in helping to resolve bundle modules and this includes handling Export-Library / Import-Library statements in the bundle manifests. The RCM resolving does not replace "dlopen" / linking, but will provide the framework library with information (wiring) which Export-Library satisfies which Import-Library (if any).
The RCM library can also be used to resolve "generic" requirement / capability manifest statements, for example:
Provide-Capability: osgi.extender;
osgi.extender="celix.http";
uses:="celix.http_admin_service";
version:Version="1.0.0"
Require-Capability: osgi.extender;
filter:="(&(osgi.extender=celix.http)(version>=1.0)(!(version>=2.0)))"
I think we'd better give a precise specification of the Celix component model before doing this work. We shall take the fundamental differences between C/C++ and JAVA into account when specifying Celix component model. At least, a reinterpretation of OSGi within C/C++ context is necessary.
Java Class Loader
By letting each bundle have its own class loader, the OSGi modularization layer supports a model where multiple versions of the same class are loaded in the same VM (but in different class spaces).
Specifically, the framework can have precise control of where a specific class is loaded from (Wiring/Export-Package/Import-Package).
As made clear in #441, we don't have such super power in C/C++, and the closest we have is rtld-audit.
Let's admit that C/C++ runtime linker is not designed to work that way.
If we step back a bit by giving up Export-Library / Import-Library and focusing on services instead, we can easily make Wiring/Export-Service/Import-Service work. That is, if the requirement of a specific service Foo in bundle A is wired to the provider in bundle B, then any service tracker for Foo created in bundle A will only receive Foo service instances from bundle B. In Celix, we don't have class spaces, but we can have service spaces.
What if a bundle wants to use OpenSSL of a different version from the installed ?
We can embed the OpenSSL static library in a separate bundle, wrap the interface (such as Encryption) we want to use in a service and export the service.
This way, multiple versions of OpenSSL coexist but live in different service spaces.
Or we can embed the OpenSSL static library in the user bundle as a private copy.
Note for the latter approach to work, we should use -Wl,-Bsymbolic linker option to make the bundle self-contained.
Garbage Collection
Even if a bundle is stopped, its resource may still be used by other bundles. I think that's why the bundle update procedure is so complicated with multiple coexisting bundle revisions. If we can guarantee that when a bundle is stopped, its resource will NOT be available to the outside world, we can have a much simpler overall design. If a bundle's resource must be accessed through its service, then we are done.
I agree that services is a more safe way to approach this and if we document this approach / pattern that would be helpful.
I also think we still can look into a export/import library feature based on manipulating SONAME/NEEDED (akka nOSGi) or maybe look into rtld-audit concept, but this is a long term goal.
Still I think it is good to improve the current Requirement-Capability Model implementation and ensure that this is not the bottleneck to implement a future export/import libraries feature.
I also think we still can look into a export/import library feature based on manipulating SONAME/NEEDED (akka nOSGi) or maybe look into rtld-audit concept, but this is a long term goal.
I agree that export/import library could be left for future consideration. I suggest we remove it from 3.0 and add it back if we could work out a solution in the future.
What do you think about bundle update, bundle revision, and gc? Shall we make it clear that when a bundle is stopped, its resource will not be available?
I also think we still can look into a export/import library feature based on manipulating SONAME/NEEDED (akka nOSGi) or maybe look into rtld-audit concept, but this is a long term goal.
I agree that export/import library could be left for future consideration. I suggest we remove it from 3.0 and add it back if we could work out a solution in the future.
:+1:
What do you think about bundle update, bundle revision, and gc? Shall we make it clear that when a bundle is stopped, its resource will not be available?
Yes and I agree this is easier (and already in place) for services. I think the only place where a bit more clarification is needed is the bundle trackers. So to make it clear bundle resource cannot be access after the onStopped event is handled.
If we move requirement-capability model more back to the future, I think the only think left is to remove the current resolver from celix framework. The handling of private bundle libraries (through dlopen) already functions as a resolver for the bundle and is IMO good enough until we have a more clear vision/goal for export/import libraries.
If we move requirement-capability model more back to the future, I think the only think left is to remove the current resolver from celix framework. The handling of private bundle libraries (through dlopen) already functions as a resolver for the bundle and is IMO good enough until we have a more clear vision/goal for export/import libraries.
I plan to send a PR:
- Remove the resolver
- Remove the broken part of manifestParser(#531)
- Improve
manifest.c(#527)