Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 123707 - consider resolver support for matching arbitrary properties
Summary: consider resolver support for matching arbitrary properties
Status: RESOLVED FIXED
Alias: None
Product: Equinox
Classification: Eclipse Project
Component: Framework (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.2 M6   Edit
Assignee: equinox.framework-inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 110013 (view as bug list)
Depends on:
Blocks:
 
Reported: 2006-01-12 21:35 EST by Jeff McAffer CLA
Modified: 2006-04-10 14:45 EDT (History)
2 users (show)

See Also:


Attachments
Patch to add generic capability resolving support (52.99 KB, patch)
2006-01-26 14:55 EST, Thomas Watson CLA
no flags Details | Diff
Fix some bugs (54.46 KB, patch)
2006-01-29 19:41 EST, Thomas Watson CLA
no flags Details | Diff
Updated patch (92.01 KB, patch)
2006-02-21 15:58 EST, Thomas Watson CLA
no flags Details | Diff
patch (122.59 KB, patch)
2006-03-03 17:26 EST, Thomas Watson CLA
no flags Details | Diff
patch (122.57 KB, patch)
2006-03-16 17:12 EST, Thomas Watson CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jeff McAffer CLA 2006-01-12 21:35:14 EST
There are a number of cases were it would be interesting to add arbitrary property matching to the resolution process.  For example, if you wanted to do service dependency resolution you could say that a bundle that Export-Service: foo "provides" the foo "capability" and some bundle that does Import-Service: foo "requires" the foo capability.  (These terms are taken from the recent OBR2 work)

This should be relatively easy to add though may be a somewhat pervasive change in the resolver.
Comment 1 Thomas Watson CLA 2006-01-26 14:55:59 EST
Created attachment 33665 [details]
Patch to add generic capability resolving support

This patch adds generic capability resolving support to the resolver.  It works by specifying headers in the manifest dictionaries used to construct BundleDescritions for the state.  There are two new headers supported, one to specify a generic capability (Eclipse-GenericCapability) and one to specify a generic capability requirement (Eclipse-GenericRequire).  The two headers use the following syntax

Eclipse-GenericCapability := capability ( ',' capability ) *
capability                := name ( ';' parameter ) *
parameter                 := key '=' quouted-string

Eclipse-GenericRequire    := generic-require ( ',' generic-require ) *
generic-require           := generic-require 
                               ( selection-filter '=' quoated-ldapFilter )

For example:
Eclipse-GenericCapability: myCoolCapability; version="1.2.1"; coolness="high";

This specifies a myCoolCapability at version 1.2.1 a matching attribute of coolness equal to "high".

Eclipse-GenericRequire: myCoolCapability;
 selection-filter=(&(&(version>=1.2)(!(version>=1.3)))(coolness=high))

This specifies a generic requirement on myCoolCapability at a version >= 1.2 and < 1.3 and has a matching attribute of coolness=high

There is a new platform property which can be set on the state to provide header aliasing.  For example, the OSGi defined headers Export-Service/Import-Service could be aliased onto Eclipse-Generic headers.  The platform property is osgi.genericAliases and uses the following syntax

osgi.genericAliases := generic-alias ( ',' generic-alias ) *
generic-alias       := generic-capability-alias ':' generic-require-alias

For the Export-Service/Import-Service example the platform property would be:

osgi.genericAliases=Export-Service:Import-Service

Under the covers this aliases are translated into Generics
Export-Service: org.osgi.service.log.LogService
Import-Service: org.osgi.service.log.LogService

becomes this
Eclipse-GenericCapability: org.osgi.service.log.LogService;
 genericAlias=Export-Package
Eclipse-GenericRequire: org.osgi.service.log.LogService;
 selection-filter="(genericAlias=Export-Package)"

Jeff, is this useful in the context you were thinking.  I know it will help in scenarios that want us to resolver Import-Service/Export-Service headers.  Another interesting aspect of generic constraint resolving is for scenarios where a bundle only wants to be resolved if a particular fragment is installed and resolved.  Currently there is no good way to require a fragment.  With generics you could have a fragment declare a generic capability and another bundle could require it.
Comment 2 Thomas Watson CLA 2006-01-29 19:41:00 EST
Created attachment 33770 [details]
Fix some bugs

Flushed some around fragments.
Comment 3 Jeff McAffer CLA 2006-01-29 20:21:56 EST
This is great.  I think it will go a long way to helping with various usecases.  One thing that came up was whether or not we need the notion of "types" for the values.  I noticed in the new OBR2 metadata that they have types.  for example, the following represents an Export-Package

<capability name="package">
  <p v="org.eclipse.search.internal.core.text" n="package" /> 
  <p v="0.0.0" t="version" n="version" /> 
  <p v="true" n="x-internal:" /> 
</capability>

Notice the second <p> has a 't' attribute whose value is "version".  That identifies the <p>'s type as version.  I'm not sure what this means in practice...  Adding Peter to see if he can comment.
Comment 4 Thomas Watson CLA 2006-01-30 09:31:58 EST
I noticed the 't' and 'n' attributes also.  Peter, in the example above I had a question about the 'n' and 't' attrs.  Shouldn't the primary name of the capability be captured in the capability tag like this:

<capability v="org.eclipse.search.internal.core.text" n="Export-Package">
  <p v="0.0.0" t="version" n="version" /> 
  <p v="true" n="x-internal:" /> 
</capability>

It seems strange that you have name="package" and then later n="package".  Why not just combine the value of the package name into the capability tag?

It also seems to make sense to use the header "Export-Package" as the 'n' value.  I'm guessing you use "package" as a name because others can require a capability (Import-Package) and you want them to use the value of n=package.  I guess that is fine.  It just makes sense to me to use the headers as the name of the capability.

I assume 't' is for type which defaults the String?  Is there any other 't' value besides version and string?  I realize there may be an unlimited number of types, but I would like to know what types OBR is supporting.

In the resolver all attributes are assumed to be string unless the attr name is 'version'.  Then the value is parsed as a Version object.  The Version object is then used to match section-filters with.

Something that is missing from the resolver is support for generic requirements with any cardinality other than 'UNARY'.  Also what about optional directives.  Does the OBR syntax allow for all the directives of OSGi?  Is there something like cardinality="OPTIONAL"?
Comment 5 Peter Kriens CLA 2006-01-30 15:06:38 EST
The RFC describes the different design issues 
http://bundles.osgi.org/rfc-0112_BundleRepository.pdf

>I noticed the 't' and 'n' attributes also.  Peter, in the example above I had a
>question about the 'n' and 't' attrs.  Shouldn't the primary name of the
>capability be captured in the capability tag like this:
><capability v="org.eclipse.search.internal.core.text" n="Export-Package">
>  <p v="0.0.0" t="version" n="version" /> 
>  <p v="true" n="x-internal:" /> 
></capability>
>It seems strange that you have name="package" and then later n="package".  Why
>not just combine the value of the package name into the capability tag?

Nope! A capability is a set of properties. They are named so you do not match cows with apples ... Trying to create a "special" value is usually making the code more complex.


>It also seems to make sense to use the header "Export-Package" as the 'n'
>value.  I'm guessing you use "package" as a name because others can require a
>capability (Import-Package) and you want them to use the value of n=package.  I
>guess that is fine.  It just makes sense to me to use the headers as the name
>of the capability.
Well, it is a design choice ... The reason I did not choose bundle headers is that it implies semantics that do not exist ... the resolver must work purely on filters and capabilities, not on any implied semantics by the Export-Package OSGi header.

>I assume 't' is for type which defaults the String?  Is there any other 't'
>value besides version and string?  I realize there may be an unlimited number
>of types, but I would like to know what types OBR is supporting.
Nope, read the rfc. There is a limited set of float,string,version,integer (I think).

The RFC should address some of the other questions
Comment 6 Thomas Watson CLA 2006-01-31 10:01:42 EST
Thanks Peter.  This clears things up a bit.  It looks like it will be necessary to add types for each attr key.  The RFC has a list of types which are supported.

The name attr on capability also seems to translate into a kind of 'type' of capability.  For example:

<capability name='package'>
  <p v='org.osgi.test.cases.tracker' n='package'/>
  <p v='0.0.0' t='version' n='version'/>
</capability>

This capability has a name of 'package'.  To me this equates into a capability of type package.  If we step back out of the resolver implementation, it may make sense to rebase to implementation on generics, we still need to handle special cases for directives but it may clean up the resolver implemenation if all constraints and capabilities are expressed as generic capablities and generic requirements.

I think as a first step we should try to implement generic constraint resolving for all the types specified in RFC 112.  After that we can look at the constructs and see if we can extend that generic model to include some of the more complicated directives (like uses and singleton).

I'm going to suggest for some syntactic surgar to express the different types of attributes.  Maybe something like attrname:attrtype=value.  The default attrtype would be string.  For example, to express an export/import package foo

Eclipse-GenericCapability: foo:package; version:version="1.0.0"; coolpkg="true"
Eclipse-GenericRequire: foo:package;
     selection-filter="(&(version>=1.0.0)(coolpkg=true))"

The double version:version is strange, maybe we can default the attr type of of an attr name version to version.

Also note that the RFC 112 calls for the Filter support to be expanded to include '<' and '>' operations.  I like that but it does force us to either enhance the FilterImpl provided by the framework (which may cause us to not be OSGi compliant) or to extend the FilterImpl with a class only used by the resolver.
Comment 7 Peter Kriens CLA 2006-02-01 02:40:58 EST
> The name attr on capability also seems to translate into a kind of 'type' of
> capability.
It is the "type" of the capability. Capability and requirements must match the names or you would compare apples to oranges.

> ..we still need to handle
> special cases for directives but it may clean up the resolver implemenation if
> all constraints and capabilities are expressed as generic capablities and
> generic requirements.
I think some directives can also be handled by the filter. If we have to extend the filter to support some of the directives then I have no qualms about that as long as it does not become too dedicated to a single purpose.

Comment 8 Thomas Watson CLA 2006-02-14 12:10:57 EST
marking for M6.
Comment 9 Thomas Watson CLA 2006-02-21 15:58:18 EST
Created attachment 35101 [details]
Updated patch

I had a discussion with Richard Hall about the fact that the capability and require 'name' attributes actually describe the 'type' of capability and require.  I would suggest that the attr be changed from 'name' to 'type' to make more sense.  Richard also indicated that the cardinality attribute on the require tag got split into two attributes optional="true|false" and multiple="true|false" where false is the default value for both attrs.

One of the overall issues I see is that the capability and require tags in the RFC do not allow you to specify a real 'name' of the capability or require.  It would be nice if this was an optional attr that had a default value of "generic" or something.  This way you could key all the capabilities by type and name.  I think this would help scale any resolver algorithms.  Richard and I had different opinions on the matter, but I allowed our resolver of generic types to consider named capabilities.  With this in mind I allowed for a capability and require to specify both a name and type

This is an updated patch that includes allowing for types to be specified on the generic capiblity name and on the generic attributes.  The patch also includes some simple tests for the org.eclipse.osgi.tests project.  Here is the proposed syntax:

Eclipse-GenericCapabilty ::= capability ( ',' capability ) *
capability               ::= typed-name ( ';' typed-name ) * 
                               ( ';' typed-param ) *
typed-name               ::= name ( ':' capability-type )
typed-param              ::= typed-key '=' quouted-string
typed-key                ::= name ( ':' 
                              [string | version | uri | long | double | set] )

Eclipse-GenericRequire   ::= generic-require ( ',' generic-require ) *
generic-require          ::= typed-name ( ';' typed-name ) *
                              ( ';' selection-filter '=' quoated-ldapFilter )
                              ( ';' optional '=' [true|false] )
                              ( ';' multiple '=' [true|false] )

Examples from rfc 112:
<capability name='bundle'>
  <p v='1' n='manifestversion'/>
  <p v='aQute.eclipse.osgi' n='symbolicname'/>
  <p v='1.0.1' t='version' n='version'/>
</capability>

translates to:

Eclipse-GenericCapability: 
 aQute.eclipse.osgi:bundle;
  manifestversion:long="1";
  version:version="1.0.1";
  symbolicname="aQute.eclipse.osgi"

<capability name="package">
  <p v="org.osgi.util.tracker" n="package" />
  <p v="0.0.0" t="version" n="version" />
</capability>

translates to:

Eclipse-GenericCapability: 
 org.osgi.util.tracker:package;
  version:version="1.0.1";
  package="org.osgi.util.tracker"

<require name="package" optional="true"
  filter="(&(package=org.osgi.test.cases.util)(version=1.1.0))"/>

translates to:

Eclipse-GenericRequire:
 org.osgi.test.cases.util:package;
  optional=true; 
  selection-filter="(&(package=org.osgi.test.cases.util)(version=1.1.0))"

Note that directives are not supported by the generic resolver

Also note that to translate the typed-name correctly you have to have detailed information about the different types.  For example, the capabilty type 'package' gets its name from the property with the name 'package'.  More general types that you don't know the details of would need to be handled by using a "default" name.  Consider the following capability and require tags:

<capability name="ram">
  <p v="1000000" n="memory" t="long" />
</capability>

<require name="ram" 
 filter="(memory>=1000)"/>

translate to:

Eclipse-GenericCapability: generic:ram; memory:long=1000000

Eclipse-GenericRequire: generic:ram; selection-filter="(memory>=1000)"

Since there is no good name mapping for the type ram the default value of
'generic' can be used as the name of the capability.
Comment 10 Thomas Watson CLA 2006-03-03 17:26:32 EST
Created attachment 35707 [details]
patch

updated patch to do some cleanup.  No functional changes.
Comment 11 Thomas Watson CLA 2006-03-16 17:12:27 EST
Created attachment 36450 [details]
patch

updated patch against HEAD.  This includes some additional methods on StateObjectFactory so that Generics can be created like other state objects.
Comment 12 Jeff McAffer CLA 2006-03-16 23:07:24 EST
I did a quick scan and it looks like my concerns were addressed.  +1 for M6
Comment 13 Thomas Watson CLA 2006-03-17 09:47:01 EST
Released for M6
Comment 14 Thomas Watson CLA 2006-04-10 14:45:23 EDT
*** Bug 110013 has been marked as a duplicate of this bug. ***