Author: rickhall
Date: Tue Dec 8 16:28:14 2009
New Revision: 888470
URL: http://svn.apache.org/viewvc?rev=888470&view=rev
Log:
Try to simplify main resolver loop.
Modified:
felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/prototype/ProtoResolver.java
Modified:
felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/prototype/ProtoResolver.java
URL:
http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/prototype/ProtoResolver.java?rev=888470&r1=888469&r2=888470&view=diff
==============================================================================
---
felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/prototype/ProtoResolver.java
(original)
+++
felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/prototype/ProtoResolver.java
Tue Dec 8 16:28:14 2009
@@ -93,7 +93,7 @@
m_resolvingConstraintCache.clear();
m_resolvedConstraintCache.clear();
m_verifyCache.clear();
- Map<Requirement, Set<Capability>> candidateMap = resolve(
+ Map<Requirement, Set<Capability>> candidateMap = resolveRoot(
module,
null,
module,
@@ -108,7 +108,7 @@
return populateWireMap(module, candidateMap, new HashMap<Module,
List<Wire>>());
}
- private Map<Requirement, Set<Capability>> resolve(
+ private Map<Requirement, Set<Capability>> resolveRoot(
Module module, Capability capGoal, Module blameModule,
Map<Requirement, Set<Capability>> candidateMap,
Map<String, Blame> existingConstrains,
@@ -132,190 +132,151 @@
Map<String, Blame> existingConstraintsCopy =
new HashMap<String, Blame>(existingConstrains);
- try
+ // Add the module to the cycle map; use Boolean.FALSE to
+ // mark it as in the process of being resolved.
+ cycleMap.put(module, Boolean.FALSE);
+
+ m_rootModule = module;
+ m_candidatePermutations.clear();
+
+ // Find candidates for all imports for the target module.
+ List<Requirement> reqs = module.getRequirements();
+ for (Requirement req : reqs)
{
- // If the module is in the process of being resolved, then
- // we are going to want to just return the candidate map
- // to break the cycle.
- Boolean found = cycleMap.get(module);
- if (found != null)
- {
- // If the modules is in the process of being resolved,
but
- // we have already selected all candidates for it,
then we
- // need to verify consistency before returning the
- // candidate map.
- if (found.booleanValue())
- {
-
- Map<String, Blame> currentConstraints =
- calculateResolvingConstraints(module,
blameModule);
- checkConsistency(module, capGoal, candidateMap,
- existingConstraintsCopy, currentConstraints);
- existingConstrains.putAll(existingConstraintsCopy);
- }
- return candidateMap;
+ Set<Capability> exporters = findExporters(req);
+ if ((exporters.size() == 0) && !req.isOptional())
+ {
+ throw new RuntimeException("Unable to resolve " +
module
+ + ": missing requirement " + req);
}
-
- // Add the module to the cycle map; use Boolean.FALSE to
- // mark it as in the process of being resolved.
- cycleMap.put(module, Boolean.FALSE);
-
- // If this is the starting module, then remember it.
- if (m_rootModule == null)
+ else if (exporters.size() > 0)
{
- m_rootModule = module;
- m_candidatePermutations.clear();
+ candidateMap.put(req, exporters);
}
+ }
- // Find candidates for all imports for the target module.
- List<Requirement> reqs = module.getRequirements();
+ // Calculate current package constraints for the target module.
+ Map<String, Blame> currentConstraints =
+ calculateConstraints(module, blameModule);
+
+ // Make copy of current package constraints, since we need to
+ // be able to freely modify, but we may need to revert if a
+ // candidate resolve fails.
+ Map <String, Blame> currentConstraintsCopy = new
HashMap<String, Blame>();
+
+ m_candidatePermutations.add(candidateMap);
+
+ // Verify current candidates are resolvable and consistent.
+ ResolveException rethrow;
+ do
+ {
+ rethrow = null;
+
+ m_resolvingConstraintCache.clear();
+ m_verifyCache.clear();
+
+ currentConstraintsCopy.clear();
+ currentConstraintsCopy.putAll(currentConstraints);
+
+ candidateMap = m_candidatePermutations.remove(0);
+//System.out.println("+++ TRYING CANDIDATE MAP: " + candidateMap);
+
+ // Loop through all of the target module's imports and see
+ // if there is a consistent candidate provider.
for (Requirement req : reqs)
{
- // If we are using a permutated candidate map, then
the target
- // module's candidates may have already been
calculated, so use
- // those instead, otherwise find the matching
providers.
- if (candidateMap.get(req) == null)
+ // Get the current candidate capability for the
current import.
+ Set<Capability> exporters = candidateMap.get(req);
+ // Optional imports may not have any exporters.
+ if (exporters == null)
{
- Set<Capability> exporters = findExporters(req);
- if ((exporters.size() == 0) && !req.isOptional())
- {
- throw new RuntimeException("Unable to resolve
" + module
- + ": missing requirement " + req);
- }
- else if (exporters.size() > 0)
- {
- candidateMap.put(req, exporters);
- }
+ continue;
}
- }
- // Calculate current package constraints for the target
module.
- Map<String, Blame> currentConstraints =
- calculateConstraints(module, blameModule);
-
- // Make copy of current package constraints, since we need
to
- // be able to freely modify, but we may need to revert if a
- // candidate resolve fails.
- Map <String, Blame> currentConstraintsCopy =
- new HashMap<String, Blame>(currentConstraints);
-
- // Verify current candidates are resolvable and consistent.
- boolean repeat;
- do
- {
- repeat = false;
-
- // Loop through all of the target module's imports and
see
- // if there is a consistent candidate provider.
- for (Requirement req : reqs)
+ // Find a consistent candidate.
+ Capability selectedCandidate = null;
+ Iterator<Capability> itExporters =
exporters.iterator();
+ while ((selectedCandidate == null) &&
itExporters.hasNext())
{
- // Get the current candidate capability for the
current import.
- Set<Capability> exporters = candidateMap.get(req);
- // Optional imports may not have any exporters.
- if (exporters == null)
- {
- continue;
- }
-
- // Find a consistent candidate.
- Capability selectedCandidate = null;
- Iterator<Capability> itExporters =
exporters.iterator();
- while ((selectedCandidate == null) &&
itExporters.hasNext())
- {
- Capability cap = itExporters.next();
+ Capability cap = itExporters.next();
//System.out.println("+++ RESOLVING " + cap + " FOR " + module);
- try
+ try
+ {
+ // If current candidate is resolved, then try
to merge
+ // in its constraints with the existing
constraints.
+ if (cap.getModule().isResolved())
{
- // If current candidate is resolved, then
try to merge
- // in its constraints with the existing
constraints.
- if (cap.getModule().isResolved())
- {
- mergeResolvedConstraints(
- module, candidateMap,
currentConstraintsCopy,
- cap);
- }
- // If current candidate is the same as the
module being
- // resolved, then just directly add it as
a constraint.
- else if (cap.getModule().equals(module))
- {
- currentConstraintsCopy.put(
- (String)
cap.getAttribute(Capability.PACKAGE_ATTR).getValue(),
- new Blame(cap, blameModule));
- }
- // If the current candidate is not
resolved, then try to resolve
- // it, which will also merge packages
while verify constraints.
- else
- {
- resolve(
- cap.getModule(),
- cap,
- module,
- candidateMap,
- currentConstraintsCopy,
- cycleMap);
- }
-
- // This candidate was consistent, so
select it.
- selectedCandidate = cap;
+ mergeResolvedConstraints(
+ module, candidateMap,
currentConstraintsCopy,
+ cap);
+ }
+ // If current candidate is the same as the
module being
+ // resolved, then just directly add it as a
constraint.
+ else if (cap.getModule().equals(module))
+ {
+ currentConstraintsCopy.put(
+ (String)
cap.getAttribute(Capability.PACKAGE_ATTR).getValue(),
+ new Blame(cap, blameModule));
}
- // If we have a resolve exception, then the
current candidate
- // should be removed. If we are at the root,
we should try the
- // next permutated candidate map if there are
no more candidates.
- catch (ResolveException ex)
+ // If the current candidate is not resolved,
then try to resolve
+ // it, which will also merge packages while
verify constraints.
+ else
{
+ resolveCandidate(
+ cap.getModule(),
+ cap,
+ module,
+ candidateMap,
+ currentConstraintsCopy,
+ cycleMap);
+ }
+
+ // This candidate was consistent, so select it.
+ selectedCandidate = cap;
+ }
+ // If we have a resolve exception, then the
current candidate
+ // should be removed. If we are at the root, we
should try the
+ // next permutated candidate map if there are no
more candidates.
+ catch (ResolveException ex)
+ {
+// TODO: PROTO RESOLVER: This should be logged.
+ System.out.println("DEBUG: " + ex);
System.out.println("RE " + ex);
ex.printStackTrace();
//System.out.println("Current candidate map : " + candidateMap);
- // Remove offending candidate.
- itExporters.remove();
+ // Remove offending candidate.
+ itExporters.remove();
//System.out.println("Updated candidate map : " + candidateMap);
- if (!itExporters.hasNext() &&
!req.isOptional())
- {
- // TODO: PROTO RESOLVER - Maybe this
should be moved.
- if ((module == m_rootModule) &&
(m_candidatePermutations.size() > 0))
- {
- currentConstraintsCopy.clear();
-
currentConstraintsCopy.putAll(currentConstraints);
- candidateMap =
m_candidatePermutations.remove(0);
-//System.out.println("+++ TRYING ALTERNATIVE: " + candidateMap);
- // Flush various caches for new
candidates.
- m_resolvingConstraintCache.clear();
- m_verifyCache.clear();
- repeat = true;
- }
- else
- {
- candidateMap.remove(req);
- throw new
ResolveException("Unresolved constraint "
- + req + " in " + module);
- }
- }
+ if (!itExporters.hasNext() &&
!req.isOptional())
+ {
+ candidateMap.remove(req);
+ rethrow = new ResolveException("Unresolved
constraint "
+ + req + " in " + module);
}
}
}
}
- while (repeat);
+ }
+ while ((rethrow != null) && (m_candidatePermutations.size() >
0));
- // At this point, we have selected a candidate capability
for
- // every import, so we need to merge the calculated
constraints
- // with the existing constraints, checking the consistency
- // while we do it.
+ if (rethrow != null)
+ {
+ throw rethrow;
+ }
+
+ // At this point, we have selected a candidate capability for
+ // every import, so we need to merge the calculated constraints
+ // with the existing constraints, checking the consistency
+ // while we do it.
//System.out.println("+++ existingConstraints: " + existingConstraintsCopy);
//System.out.println("+++ currentConstraints : " + currentConstraints);
- checkConsistency(
- module, capGoal, candidateMap,
existingConstraintsCopy, currentConstraintsCopy);
- // If we are here, then the candidates were consistent with
- // existing constraints, so cache the result.
- m_resolvingConstraintCache.put(module,
existingConstraintsCopy);
- // Finally, modify the original existing constraints.
- existingConstrains.putAll(existingConstraintsCopy);
- }
- catch (RuntimeException ex)
- {
- // Any exception should remove the target module from the
cycle map.
- cycleMap.remove(module);
- throw ex;
- }
+ checkConsistency(
+ module, capGoal, candidateMap, existingConstraintsCopy,
currentConstraintsCopy);
+ // If we are here, then the candidates were consistent with
+ // existing constraints, so cache the result.
+ m_resolvingConstraintCache.put(module,
existingConstraintsCopy);
+ // Finally, modify the original existing constraints.
+ existingConstrains.putAll(existingConstraintsCopy);
}
// Update the cycle map to mark the module as finished.
@@ -326,12 +287,196 @@
}
finally
{
- // If we are done with the root target module, then forget about
it.
- if (module == m_rootModule)
+ m_rootModule = null;
+ }
+ }
+
+ private Map<Requirement, Set<Capability>> resolveCandidate(
+ Module module, Capability capGoal, Module blameModule,
+ Map<Requirement, Set<Capability>> candidateMap,
+ Map<String, Blame> existingConstrains,
+ Map<Module, Boolean> cycleMap)
+ {
+ if (m_isInvokeCount)
+ {
+ String methodName = new
Exception().fillInStackTrace().getStackTrace()[0].getMethodName();
+ Long count = m_invokeCounts.get(methodName);
+ count = (count == null) ? new Long(1) : new Long(count.longValue()
+ 1);
+ m_invokeCounts.put(methodName, count);
+ }
+
+ // If the module is already resolved, then do nothing.
+ if (!module.isResolved())
+ {
+ // Copy the existing constraints, since we need to be able
+ // to freely modify them.
+ Map<String, Blame> existingConstraintsCopy =
+ new HashMap<String, Blame>(existingConstrains);
+
+ try
+ {
+ // If the module is in the process of being resolved, then
+ // we are going to want to just return the candidate map
+ // to break the cycle.
+ Boolean found = cycleMap.get(module);
+ if (found != null)
+ {
+ // If the modules is in the process of being resolved, but
+ // we have already selected all candidates for it, then we
+ // need to verify consistency before returning the
+ // candidate map.
+ if (found.booleanValue())
+ {
+
+ Map<String, Blame> currentConstraints =
+ calculateResolvingConstraints(module, blameModule);
+ checkConsistency(module, capGoal, candidateMap,
+ existingConstraintsCopy, currentConstraints);
+ existingConstrains.putAll(existingConstraintsCopy);
+ }
+ return candidateMap;
+ }
+
+ // Add the module to the cycle map; use Boolean.FALSE to
+ // mark it as in the process of being resolved.
+ cycleMap.put(module, Boolean.FALSE);
+
+ // Find candidates for all imports for the target module.
+ List<Requirement> reqs = module.getRequirements();
+ for (Requirement req : reqs)
+ {
+ // If we are using a permutated candidate map, then the
target
+ // module's candidates may have already been calculated,
so use
+ // those instead, otherwise find the matching providers.
+ if (candidateMap.get(req) == null)
+ {
+ Set<Capability> exporters = findExporters(req);
+ if ((exporters.size() == 0) && !req.isOptional())
+ {
+ throw new RuntimeException("Unable to resolve " +
module
+ + ": missing requirement " + req);
+ }
+ else if (exporters.size() > 0)
+ {
+ candidateMap.put(req, exporters);
+ }
+ }
+ }
+
+ // Calculate current package constraints for the target module.
+ Map<String, Blame> currentConstraints =
+ calculateConstraints(module, blameModule);
+
+ // Make copy of current package constraints, since we need to
+ // be able to freely modify, but we may need to revert if a
+ // candidate resolve fails.
+ Map <String, Blame> currentConstraintsCopy =
+ new HashMap<String, Blame>(currentConstraints);
+
+ // Verify current candidates are resolvable and consistent.
+ // Loop through all of the target module's imports and see
+ // if there is a consistent candidate provider.
+ for (Requirement req : reqs)
+ {
+ // Get the current candidate capability for the current
import.
+ Set<Capability> exporters = candidateMap.get(req);
+ // Optional imports may not have any exporters.
+ if (exporters == null)
+ {
+ continue;
+ }
+
+ // Find a consistent candidate.
+ Capability selectedCandidate = null;
+ Iterator<Capability> itExporters = exporters.iterator();
+ while ((selectedCandidate == null) &&
itExporters.hasNext())
+ {
+ Capability cap = itExporters.next();
+//System.out.println("+++ RESOLVING " + cap + " FOR " + module);
+ try
+ {
+ // If current candidate is resolved, then try to
merge
+ // in its constraints with the existing
constraints.
+ if (cap.getModule().isResolved())
+ {
+ mergeResolvedConstraints(
+ module, candidateMap,
currentConstraintsCopy,
+ cap);
+ }
+ // If current candidate is the same as the module
being
+ // resolved, then just directly add it as a
constraint.
+ else if (cap.getModule().equals(module))
+ {
+ currentConstraintsCopy.put(
+ (String)
cap.getAttribute(Capability.PACKAGE_ATTR).getValue(),
+ new Blame(cap, blameModule));
+ }
+ // If the current candidate is not resolved, then
try to resolve
+ // it, which will also merge packages while verify
constraints.
+ else
+ {
+ resolveCandidate(
+ cap.getModule(),
+ cap,
+ module,
+ candidateMap,
+ currentConstraintsCopy,
+ cycleMap);
+ }
+
+ // This candidate was consistent, so select it.
+ selectedCandidate = cap;
+ }
+ // If we have a resolve exception, then the current
candidate
+ // should be removed. If we are at the root, we should
try the
+ // next permutated candidate map if there are no more
candidates.
+ catch (ResolveException ex)
+ {
+// TODO: PROTO RESOLVER: This should be logged.
+ System.out.println("DEBUG: " + ex);
+System.out.println("RE " + ex);
+ex.printStackTrace();
+//System.out.println("Current candidate map : " + candidateMap);
+ // Remove offending candidate.
+ itExporters.remove();
+//System.out.println("Updated candidate map : " + candidateMap);
+ if (!itExporters.hasNext() && !req.isOptional())
+ {
+ candidateMap.remove(req);
+ throw new ResolveException("Unresolved
constraint "
+ + req + " in " + module);
+ }
+ }
+ }
+ }
+
+ // At this point, we have selected a candidate capability for
+ // every import, so we need to merge the calculated constraints
+ // with the existing constraints, checking the consistency
+ // while we do it.
+//System.out.println("+++ existingConstraints: " + existingConstraintsCopy);
+//System.out.println("+++ currentConstraints : " + currentConstraints);
+ checkConsistency(
+ module, capGoal, candidateMap, existingConstraintsCopy,
currentConstraintsCopy);
+ // If we are here, then the candidates were consistent with
+ // existing constraints, so cache the result.
+ m_resolvingConstraintCache.put(module,
existingConstraintsCopy);
+ // Finally, modify the original existing constraints.
+ existingConstrains.putAll(existingConstraintsCopy);
+ }
+ catch (RuntimeException ex)
{
- m_rootModule = null;
+ // Any exception should remove the target module from the
cycle map.
+ cycleMap.remove(module);
+ throw ex;
}
}
+
+ // Update the cycle map to mark the module as finished.
+ cycleMap.put(module, Boolean.TRUE);
+
+ // Return the updated candidate map.
+ return candidateMap;
}
private Map<String, Blame> calculateResolvingConstraints(Module module,
Module blameModule)