Try to backtrack on selected candidates when the candidate itself is not
consistent and it unable to generate any permutations. (FELIX-2529)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@983091 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java b/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java
index 3db5df4..da666c7 100644
--- a/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/resolver/ResolverImpl.java
@@ -872,8 +872,6 @@
Map<Requirement, Set<Capability>> permutation = null;
Set<Requirement> mutated = null;
- Set<Module> checkModules = new HashSet();
-
// Check for conflicting imports from fragments.
for (Entry<String, List<Blame>> entry : pkgs.m_importedPkgs.entrySet())
{
@@ -981,11 +979,6 @@
{
for (Blame importBlame : entry.getValue())
{
- if (!module.equals(importBlame.m_cap.getModule()))
- {
- checkModules.add(importBlame.m_cap.getModule());
- }
-
String pkgName = entry.getKey();
if (!pkgs.m_usedPkgs.containsKey(pkgName))
{
@@ -1042,7 +1035,7 @@
}
}
- // If there was a uses confliect, then we should add a uses
+ // If there was a uses conflict, then we should add a uses
// permutation if we were able to permutate any candidates.
// Additionally, we should try to push an import permutation
// for the original import to force a backtracking on the
@@ -1062,32 +1055,11 @@
Requirement req = importBlame.m_reqs.get(0);
if (!mutated.contains(req))
{
- Set<Capability> candidates = candidateMap.get(req);
- if (candidates.size() > 1)
- {
- // Check existing import permutations to make sure
- // we haven't already permutated this requirement.
- // This check for duplicate permutations is simplistic.
- // It assumes if there is any permutation that contains
- // a different candidate for the requirement in question,
- // then it has already been permutated.
- boolean permutated = false;
- for (Map<Requirement, Set<Capability>> existingPerm
- : m_importPermutations)
- {
- Set<Capability> existingPermCands = existingPerm.get(req);
- if (!existingPermCands.iterator().next().equals(candidates.iterator().next()))
- {
- permutated = true;
- }
- }
- // If we haven't already permutated the existing
- // import, do so now.
- if (!permutated)
- {
- permutate(candidateMap, req, m_importPermutations);
- }
- }
+ // Since there may be lots of uses constraint violations
+ // with existing import decisions, we may end up trying
+ // to permutate the same import a lot of times, so we should
+ // try to check if that the case and only permutate it once.
+ permutateIfNeeded(candidateMap, req, m_importPermutations);
}
m_logger.log(Logger.LOG_DEBUG, "Conflict between imports", rethrow);
@@ -1099,10 +1071,37 @@
resultCache.put(module, Boolean.TRUE);
// Now check the consistency of all modules on which the
- // current module depends.
- for (Module m : checkModules)
+ // current module depends. Keep track of the current number
+ // of permutations so we know if the lower level check was
+ // able to create a permutation or not in the case of failure.
+ int permCount = m_usesPermutations.size() + m_importPermutations.size();
+ for (Entry<String, List<Blame>> entry : pkgs.m_importedPkgs.entrySet())
{
- checkPackageSpaceConsistency(m, candidateMap, modulePkgMap, capDepSet, resultCache);
+ for (Blame importBlame : entry.getValue())
+ {
+ if (!module.equals(importBlame.m_cap.getModule()))
+ {
+ try
+ {
+ checkPackageSpaceConsistency(
+ importBlame.m_cap.getModule(), candidateMap, modulePkgMap,
+ capDepSet, resultCache);
+ }
+ catch (ResolveException ex)
+ {
+ // If the lower level check didn't create any permutations,
+ // then we should create an import permutation for the
+ // requirement with the dependency on the failing module
+ // to backtrack on our current candidate selection.
+ if (permCount == (m_usesPermutations.size() + m_importPermutations.size()))
+ {
+ Requirement req = importBlame.m_reqs.get(0);
+ permutate(candidateMap, req, m_importPermutations);
+ }
+ throw ex;
+ }
+ }
+ }
}
}
@@ -1122,6 +1121,37 @@
}
}
+ private static void permutateIfNeeded(
+ Map<Requirement, Set<Capability>> candidateMap, Requirement req,
+ List<Map<Requirement, Set<Capability>>> permutations)
+ {
+ Set<Capability> candidates = candidateMap.get(req);
+ if (candidates.size() > 1)
+ {
+ // Check existing permutations to make sure we haven't
+ // already permutated this requirement. This check for
+ // duplicate permutations is simplistic. It assumes if
+ // there is any permutation that contains a different
+ // initial candidate for the requirement in question,
+ // then it has already been permutated.
+ boolean permutated = false;
+ for (Map<Requirement, Set<Capability>> existingPerm : permutations)
+ {
+ Set<Capability> existingPermCands = existingPerm.get(req);
+ if (!existingPermCands.iterator().next().equals(candidates.iterator().next()))
+ {
+ permutated = true;
+ }
+ }
+ // If we haven't already permutated the existing
+ // import, do so now.
+ if (!permutated)
+ {
+ permutate(candidateMap, req, permutations);
+ }
+ }
+ }
+
private static void calculateExportedPackages(
Module module, Map<Module, Packages> modulePkgMap)
{