Resolved a concurrency issue that could result in the same bundle being
resolved more than once; also tried to simplify locking in the core search
policy implementation. (FELIX-381)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@580747 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index ece37b5..2fa49af 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -623,8 +623,17 @@
acquireBundleLock(bundle);
if (bundle.getInfo().getCurrentModule() == event.getModule())
{
- bundle.getInfo().setState(Bundle.RESOLVED);
- fireBundleEvent(BundleEvent.RESOLVED, bundle);
+ if (bundle.getInfo().getState() != Bundle.INSTALLED)
+ {
+ m_logger.log(
+ Logger.LOG_WARNING,
+ "Received a resolve event for a bundle that has already been resolved.");
+ }
+ else
+ {
+ bundle.getInfo().setState(Bundle.RESOLVED);
+ fireBundleEvent(BundleEvent.RESOLVED, bundle);
+ }
}
}
finally
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
index 581edce..fbaa569 100755
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
@@ -125,13 +125,23 @@
}
}
- protected synchronized boolean isResolved(IModule module)
+ /**
+ * Private utility method to check module resolved state.
+ * CONCURRENCY NOTE: This method must be called while holding
+ * a lock on m_factory.
+ **/
+ private boolean isResolved(IModule module)
{
ModuleData data = (ModuleData) m_moduleDataMap.get(module);
return (data == null) ? false : data.m_resolved;
}
- protected synchronized void setResolved(IModule module, boolean resolved)
+ /**
+ * Private utility method to set module resolved state.
+ * CONCURRENCY NOTE: This method must be called while holding
+ * a lock on m_factory.
+ **/
+ private void setResolved(IModule module, boolean resolved)
{
ModuleData data = (ModuleData) m_moduleDataMap.get(module);
if (data == null)
@@ -904,19 +914,6 @@
public void resolve(IModule rootModule)
throws ResolveException
{
- // If the module is already resolved, then we can just return.
- if (isResolved(rootModule))
- {
- return;
- }
-
- // This variable maps an unresolved module to a list of candidate
- // sets, where there is one candidate set for each requirement that
- // must be resolved. A candidate set contains the potential canidates
- // available to resolve the requirement and the currently selected
- // candidate index.
- Map candidatesMap = new HashMap();
-
// This map will be used to hold the final wires for all
// resolved modules, which can then be used to fire resolved
// events outside of the synchronized block.
@@ -927,6 +924,19 @@
// middle of this operation.
synchronized (m_factory)
{
+ // If the module is already resolved, then we can just return.
+ if (isResolved(rootModule))
+ {
+ return;
+ }
+
+ // This variable maps an unresolved module to a list of candidate
+ // sets, where there is one candidate set for each requirement that
+ // must be resolved. A candidate set contains the potential canidates
+ // available to resolve the requirement and the currently selected
+ // candidate index.
+ Map candidatesMap = new HashMap();
+
// The first step is to populate the candidates map. This
// will use the target module to populate the candidates map
// with all potential modules that need to be resolved as a