You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@celix.apache.org by Pepijn Noltes <pe...@gmail.com> on 2015/10/28 12:23:50 UTC

[DISCUSS] Service versions & semantic versioning

 Hi All,

I like to discuss how to handle service versions in Apache Celix.

To start of, I like to shortly review how service versions are handled in
the Java OSGi frameworks:
In Java, services are versioned by their java interface package version.
The OSGi framework will automatically select services you can resolve as
result of an package import statement. This is done using semantic
versioning.
The reasons this is possible is because Java has runtime type information
(RTTI) available.

Apache Celix is based on the OSGi specification (written for Java) and
Celix has been been following the Java OSGi API as much as possible.
But because C has no RTTI, there is currently has no way to determining the
version of a service. This can result in very problematic bugs in
applications when (note not if) services will change/update.

To make this problem more clear, consider the following, version 1, service
:

struct example {
   void (*bar)(double a, double b);
};

Also consider a version 2 of this service:

struct example {
   void (*foo)(double a, double b);
   void (*bar)(double a, double b);
};

If the provider was compiled with version 1 and the consumer with version
2, when the consumer tries to invoke bar it will invoke foo instead. And
currently there is no runtime information present to detect and prevent
this.
Also note that with the current solution of services, adding a method
before an existing method or reordering existing methods must result in a
major version update.

IMO The primary feature Apache Celix delivers is (dynamic) modularity for C
applications. One of the key aspect of modularity is the ability to handle
different versions of services/interfaces. I think Apache Celix should
deliver a solution for this.


In this thread I would like to discuss how we can tackle this problem. I
already gave this some thoughts ,so I will start with listing some options

Option 1.
Add a version / version range argument when registering services and
looking up services. This will break API with OSGi spec and does not
improve the situations where major update of the service version is needed.

Option 2.
Add a version / version range argument to the dependency manager API. This
does not break the OSGi API (OSGi assembly). But also does not improves
when major updates are needed.

Option 2.
Change how we use services. Instead of directly using struct, use a more
elaborate/opaque date type to support some run-time information (e.g.
version, provided method names, consumer method names) combined with some
marco magic to keep performance optimal.
This could work but I do think this breaks the simplicity approach we have
with Apace Celix. It does offer a solution to handle versions and also
improves support for service evolution.

Option 3.
Add runtime information by parsing the services headers.
With remote services we already starting using descriptor files which
describes services. This makes it possible to runtime reason about services
and the differences between provided and consumer service. As result in
remote services there is already more flexibility to changes in the
services. This could also be done with local services, but then we must
parse the C header files.
This will support version info and improved support for service evolution.
I think is a very interesting solution, but a complex one and with
considerable effort to achieve. I would push Apache Celix to the next
level, meaning interface/service RTTI support for C. But is this something
we want / aspire?

If anybody has some remarks, additional ideas/options or preferences for
the already mentioned options I would like to hear them.

Greetings,
Pepijn