Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Candidates.java49
-rwxr-xr-xbundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java12
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())
{

Back to the top