diff options
author | Thomas Watson | 2017-03-23 19:37:18 +0000 |
---|---|---|
committer | Thomas Watson | 2017-03-27 15:32:41 +0000 |
commit | b477ccb34d9ff989784ed570ea210ca678400230 (patch) | |
tree | 2e3455bf7aadf45fb1491c033f1dc1458988f109 | |
parent | d25f9dfca57a43b751195640181bdb604dee3e7c (diff) | |
download | rt.equinox.framework-b477ccb34d9ff989784ed570ea210ca678400230.tar.gz rt.equinox.framework-b477ccb34d9ff989784ed570ea210ca678400230.tar.xz rt.equinox.framework-b477ccb34d9ff989784ed570ea210ca678400230.zip |
Bug 514149 - [resolver] issues resolving with substitutable exports
Fix by checking if removing a candidate will substitute the only
provider which satisfies a dependency.
Change-Id: Iae05477ce7ddef9ee036ac8e7cc5000c816d042f
Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
-rwxr-xr-x | bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Candidates.java | 49 | ||||
-rwxr-xr-x | bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java | 12 |
2 files changed, 58 insertions, 3 deletions
diff --git a/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Candidates.java b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Candidates.java index 29b2b7b10..44c96a310 100755 --- a/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Candidates.java +++ b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Candidates.java @@ -1203,7 +1203,54 @@ class Candidates public boolean canRemoveCandidate(Requirement req) { CandidateSelector candidates = m_candidateMap.get(req); - return ((candidates != null) && (candidates.getRemainingCandidateCount() > 1 || Util.isOptional(req))); + if (candidates != null) + { + Capability current = candidates.getCurrentCandidate(); + if (current != null) + { + // IMPLEMENTATION NOTE: + // Here we check for a req that is used for a substitutable export. + // If we find a substitutable req then an extra check is done to see + // if the substitutable capability is currently depended on as the + // only provider of some other requirement. If it is then we do not + // allow the candidate to be removed. + // This is done because of the way we attempt to reduce permutations + // checked by permuting all used requirements that conflict with a + // directly imported/required capability in one go. + // If we allowed these types of substitutable requirements to move + // to the next capability then the permutation would be thrown out + // because it would cause some other resource to not resolve. + // That in turn would throw out the complete permutation along with + // any follow on permutations that could have resulted. + // See ResolverImpl::checkPackageSpaceConsistency + + // Check if the current candidate is substitutable by the req; + // This check is necessary here because + if (req.equals(m_subtitutableMap.get(current))) + { + // this is a substitute req, + // make sure there is not an existing dependency that would fail if we substitute + Set<Requirement> dependents = m_dependentMap.get(current); + if (dependents != null) + { + for (Requirement dependent : dependents) + { + CandidateSelector dependentSelector = m_candidateMap.get(dependent); + // If the dependent selector only has one capability left then we know it is + // using the current candidate and has no options left + if (dependentSelector != null && dependentSelector.getRemainingCandidateCount() <= 1) + { + // return false since we do not want to allow this requirement + // to substitute the capability + return false; + } + } + } + } + } + return candidates.getRemainingCandidateCount() > 1 || Util.isOptional(req); + } + return false; } static class DynamicImportFailed extends ResolutionError { diff --git a/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java index 60beca879..dd7b7c51c 100755 --- a/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java +++ b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java @@ -1288,8 +1288,6 @@ public class ResolverImpl implements Resolver Packages pkgs = resourcePkgMap.get(resource); ResolutionError rethrow = null; - Candidates permutation = null; - Set<Requirement> mutated = null; // Check for conflicting imports from fragments. // TODO: Is this only needed for imports or are generic and bundle requirements also needed? @@ -1332,6 +1330,16 @@ public class ResolverImpl implements Resolver } } + // IMPLEMENTATION NOTE: + // Below we track the mutated reqs that have been permuted + // in a single candidates permutation. This permutation may contain a + // delta of several reqs which conflict with a directly imported/required candidates. + // When several reqs are permuted at the same time this reduces the number of solutions tried. + // See the method Candidates::canRemoveCandidate for a case where substitutions must be checked + // because of this code that may permute multiple reqs in on candidates permutation. + Set<Requirement> mutated = null; + Candidates permutation = null; + // Check if there are any uses conflicts with exported packages. for (Entry<String, Blame> entry : pkgs.m_exportedPkgs.fast()) { |