[FELIX-4656] Avoid trying to solve the same set multiple times
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1667214 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/resolver/src/main/java/org/apache/felix/resolver/Candidates.java b/resolver/src/main/java/org/apache/felix/resolver/Candidates.java
index 1cb929e..f46844b 100644
--- a/resolver/src/main/java/org/apache/felix/resolver/Candidates.java
+++ b/resolver/src/main/java/org/apache/felix/resolver/Candidates.java
@@ -72,6 +72,8 @@
private final Map<Capability, Requirement> m_subtitutableMap;
+ private final OpenHashMapSet<Requirement, Capability> m_path;
+
/**
* Private copy constructor used by the copy() method.
*/
@@ -82,7 +84,8 @@
Map<Resource, WrappedResource> wrappedHosts, Map<Resource, Object> populateResultCache,
boolean fragmentsPresent,
Map<Resource, Boolean> onDemandResources,
- Map<Capability, Requirement> substitutableMap)
+ Map<Capability, Requirement> substitutableMap,
+ OpenHashMapSet<Requirement, Capability> path)
{
m_mandatoryResources = mandatoryResources;
m_dependentMap = dependentMap;
@@ -92,6 +95,7 @@
m_fragmentsPresent = fragmentsPresent;
m_validOnDemandResources = onDemandResources;
m_subtitutableMap = substitutableMap;
+ m_path = path;
}
/**
@@ -106,6 +110,11 @@
m_populateResultCache = new HashMap<Resource, Object>();
m_validOnDemandResources = validOnDemandResources;
m_subtitutableMap = new HashMap<Capability, Requirement>();
+ m_path = new OpenHashMapSet<Requirement, Capability>(3);
+ }
+
+ public Object getPath() {
+ return m_path;
}
/**
@@ -803,17 +812,31 @@
{
List<Capability> candidates = m_candidateMap.get(req);
// Remove the conflicting candidate.
- candidates.remove(0);
+ Capability cap = candidates.remove(0);
if (candidates.isEmpty())
{
m_candidateMap.remove(req);
}
+ // Update resolution path
+ CopyOnWriteSet<Capability> capPath = m_path.get(req);
+ if (capPath == null) {
+ capPath = new CopyOnWriteSet<Capability>();
+ m_path.put(req, capPath);
+ }
+ capPath.add(cap);
}
public List<Capability> clearCandidates(Requirement req, Collection<Capability> caps)
{
List<Capability> l = m_candidateMap.get(req);
l.removeAll(caps);
+ // Update resolution path
+ CopyOnWriteSet<Capability> capPath = m_path.get(req);
+ if (capPath == null) {
+ capPath = new CopyOnWriteSet<Capability>();
+ m_path.put(req, capPath);
+ }
+ capPath.addAll(caps);
return l;
}
@@ -1231,7 +1254,8 @@
m_populateResultCache,
m_fragmentsPresent,
m_validOnDemandResources,
- m_subtitutableMap);
+ m_subtitutableMap,
+ m_path.deepClone());
}
public void dump(ResolveContext rc)
diff --git a/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java b/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java
index 1a032dc..1ea56ec 100644
--- a/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java
+++ b/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java
@@ -202,9 +202,24 @@
}
}
+ Set<Object> donePaths = new HashSet<Object>();
Map<Resource, ResolutionException> faultyResources = null;
do
{
+ allCandidates = (usesPermutations.size() > 0)
+ ? usesPermutations.remove(0)
+ : (importPermutations.size() > 0
+ ? importPermutations.remove(0)
+ : null);
+ if (allCandidates == null)
+ {
+ break;
+ }
+ if (!donePaths.add(allCandidates.getPath()))
+ {
+ continue;
+ }
+
rethrow = null;
resourcePkgMap.clear();
@@ -214,9 +229,6 @@
// delta of the current permutation.
session.setMultipleCardCandidates(null);
- allCandidates = (usesPermutations.size() > 0)
- ? usesPermutations.remove(0)
- : importPermutations.remove(0);
//allCandidates.dump();
Map<Resource, ResolutionException> currentFaultyResources = null;
@@ -295,8 +307,7 @@
}
}
}
- while ((rethrow != null)
- && ((usesPermutations.size() > 0) || (importPermutations.size() > 0)));
+ while (rethrow != null);
// If there is a resolve exception, then determine if an
// optionally resolved resource is to blame (typically a fragment).