felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rickh...@apache.org
Subject svn commit: r1589839 - in /felix/trunk/resolver/src/main/java/org/apache/felix/resolver: Candidates.java ResolverImpl.java
Date Thu, 24 Apr 2014 19:23:48 GMT
Author: rickhall
Date: Thu Apr 24 19:23:48 2014
New Revision: 1589839

URL: http://svn.apache.org/r1589839
Log:
Apply patch FELIX-4493 to add support for "on demand" resource
resolving.

Modified:
    felix/trunk/resolver/src/main/java/org/apache/felix/resolver/Candidates.java
    felix/trunk/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java

Modified: felix/trunk/resolver/src/main/java/org/apache/felix/resolver/Candidates.java
URL: http://svn.apache.org/viewvc/felix/trunk/resolver/src/main/java/org/apache/felix/resolver/Candidates.java?rev=1589839&r1=1589838&r2=1589839&view=diff
==============================================================================
--- felix/trunk/resolver/src/main/java/org/apache/felix/resolver/Candidates.java (original)
+++ felix/trunk/resolver/src/main/java/org/apache/felix/resolver/Candidates.java Thu Apr 24
19:23:48 2014
@@ -19,6 +19,7 @@
 package org.apache.felix.resolver;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -44,7 +45,6 @@ class Candidates
 {
     public static final int MANDATORY = 0;
     public static final int OPTIONAL = 1;
-    public static final int ON_DEMAND = 2;
 
     private final Set<Resource> m_mandatoryResources;
     // Maps a capability to requirements that match it.
@@ -60,6 +60,8 @@ class Candidates
     // Flag to signal if fragments are present in the candidate map.
     private boolean m_fragmentsPresent = false;
 
+    private final Map<Resource, Boolean> m_validOnDemandResources;
+
     /**
      * Private copy constructor used by the copy() method.
      * @param dependentMap the capability dependency map.
@@ -72,7 +74,8 @@ class Candidates
         Map<Capability, Set<Requirement>> dependentMap,
         Map<Requirement, List<Capability>> candidateMap,
         Map<Resource, WrappedResource> wrappedHosts, Map<Resource, Object> populateResultCache,
-        boolean fragmentsPresent)
+        boolean fragmentsPresent,
+        Map<Resource, Boolean> onDemandResources)
     {
         m_mandatoryResources = mandatoryResources;
         m_dependentMap = dependentMap;
@@ -80,18 +83,20 @@ class Candidates
         m_allWrappedHosts = wrappedHosts;
         m_populateResultCache = populateResultCache;
         m_fragmentsPresent = fragmentsPresent;
+        m_validOnDemandResources = onDemandResources;
     }
 
     /**
      * Constructs an empty Candidates object.
     **/
-    public Candidates()
+    public Candidates(Map<Resource, Boolean> validOnDemandResources)
     {
         m_mandatoryResources = new HashSet<Resource>();
         m_dependentMap = new HashMap<Capability, Set<Requirement>>();
         m_candidateMap = new HashMap<Requirement, List<Capability>>();
         m_allWrappedHosts = new HashMap<Resource, WrappedResource>();
         m_populateResultCache = new HashMap<Resource, Object>();
+        m_validOnDemandResources = validOnDemandResources;
     }
 
     /**
@@ -137,28 +142,22 @@ class Candidates
             return;
         }
 
-        // Always attempt to populate mandatory or optional revisions.
-        // However, for on-demand fragments only populate if their host
-        // is already populated.
-        if ((resolution != ON_DEMAND)
-            || (isFragment && populateFragmentOndemand(rc, resource)))
+
+        if (resolution == MANDATORY)
+        {
+            m_mandatoryResources.add(resource);
+        }
+        try
         {
+            // Try to populate candidates for the optional revision.
+            populateResource(rc, resource);
+        }
+        catch (ResolutionException ex)
+        {
+            // Only throw an exception if resolution is mandatory.
             if (resolution == MANDATORY)
             {
-                m_mandatoryResources.add(resource);
-            }
-            try
-            {
-                // Try to populate candidates for the optional revision.
-                populateResource(rc, resource);
-            }
-            catch (ResolutionException ex)
-            {
-                // Only throw an exception if resolution is mandatory.
-                if (resolution == MANDATORY)
-                {
-                    throw ex;
-                }
+                throw ex;
             }
         }
     }
@@ -304,68 +303,28 @@ class Candidates
         {
             // Record that the revision was successfully populated.
             m_populateResultCache.put(resource, Boolean.TRUE);
-
             // Merge local candidate map into global candidate map.
             if (localCandidateMap.size() > 0)
             {
                 add(localCandidateMap);
             }
-        }
-    }
-
-    private boolean populateFragmentOndemand(ResolveContext rc, Resource resource)
-        throws ResolutionException
-    {
-        // Create a modifiable list of the revision's requirements.
-        List<Requirement> remainingReqs =
-            new ArrayList(resource.getRequirements(null));
-        // Find the host requirement.
-        Requirement hostReq = null;
-        for (Iterator<Requirement> it = remainingReqs.iterator();
-            it.hasNext(); )
-        {
-            Requirement r = it.next();
-            if (r.getNamespace().equals(HostNamespace.HOST_NAMESPACE))
-            {
-                hostReq = r;
-                it.remove();
-                break;
+            if ((rc instanceof FelixResolveContext) && !Util.isFragment(resource))
{
+            	Collection<Resource> ondemandFragments = ((FelixResolveContext) rc).getOndemandResources(resource);
+            	for (Resource fragment : ondemandFragments) {
+            		Boolean valid = m_validOnDemandResources.get(fragment);
+            		if (valid == null) {
+            			// Mark this resource as a valid on demand resource
+            			m_validOnDemandResources.put(fragment, Boolean.TRUE);
+            			valid = Boolean.TRUE;
+            		}
+            		if (valid) {
+            			// This resource is a valid on demand resource;
+            			// populate it now, consider it optional
+            			populate(rc, fragment, OPTIONAL);
+            		}
+				}
             }
         }
-        // Get candidates hosts and keep any that have been populated.
-        List<Capability> hosts = rc.findProviders(hostReq);
-        for (Iterator<Capability> it = hosts.iterator(); it.hasNext(); )
-        {
-            Capability host = it.next();
-            if (!isPopulated(host.getResource()))
-            {
-                it.remove();
-            }
-        }
-        // If there aren't any populated hosts, then we can just
-        // return since this fragment isn't needed.
-        if (hosts.isEmpty())
-        {
-            return false;
-        }
-
-        // If there are populated host candidates, then prepopulate
-        // the result cache with the work we've done so far.
-        // Record cycle count, but start at -1 since it will
-        // be incremented again in populate().
-        Integer cycleCount = new Integer(-1);
-        // Create a local map for populating candidates first, just in case
-        // the revision is not resolvable.
-        Map<Requirement, List<Capability>> localCandidateMap =
-            new HashMap<Requirement, List<Capability>>();
-        // Add the discovered host candidates to the local candidate map.
-        localCandidateMap.put(hostReq, hosts);
-        // Add these value to the result cache so we know we are
-        // in the middle of populating candidates for the current
-        // revision.
-        m_populateResultCache.put(resource,
-            new Object[] { cycleCount, localCandidateMap, remainingReqs });
-        return true;
     }
 
     public void populateDynamic(
@@ -1004,7 +963,7 @@ class Candidates
 
         return new Candidates(
             m_mandatoryResources, dependentMap, candidateMap,
-            m_allWrappedHosts, m_populateResultCache, m_fragmentsPresent);
+            m_allWrappedHosts, m_populateResultCache, m_fragmentsPresent, m_validOnDemandResources);
     }
 
     public void dump(ResolveContext rc)

Modified: felix/trunk/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java?rev=1589839&r1=1589838&r2=1589839&view=diff
==============================================================================
--- felix/trunk/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java (original)
+++ felix/trunk/resolver/src/main/java/org/apache/felix/resolver/ResolverImpl.java Thu Apr
24 19:23:48 2014
@@ -122,10 +122,9 @@ public class ResolverImpl implements Res
         // Make copies of arguments in case we want to modify them.
         Collection<Resource> mandatoryResources = new ArrayList(rc.getMandatoryResources());
         Collection<Resource> optionalResources = new ArrayList(rc.getOptionalResources());
-// TODO: RFC-112 - Need impl-specific type.
-//        Collection<Resource> ondemandFragments = (rc instanceof ResolveContextImpl)
-//            ? ((ResolveContextImpl) rc).getOndemandResources() : Collections.EMPTY_LIST;
-        Collection<Resource> ondemandFragments = Collections.EMPTY_LIST;
+        // keeps track of valid on demand fragments that we have seen.
+        // a null value or TRUE indicate it is valid
+        Map<Resource, Boolean> validOnDemandResources = new HashMap<Resource, Boolean>(0);
 
         boolean retry;
         do
@@ -134,7 +133,7 @@ public class ResolverImpl implements Res
             try
             {
                 // Create object to hold all candidates.
-                Candidates allCandidates = new Candidates();
+                Candidates allCandidates = new Candidates(validOnDemandResources);
 
                 // Populate mandatory resources; since these are mandatory
                 // resources, failure throws a resolve exception.
@@ -163,17 +162,6 @@ public class ResolverImpl implements Res
                     }
                 }
 
-                // Populate ondemand fragments; since these are optional
-                // resources, failure does not throw a resolve exception.
-                for (Resource resource : ondemandFragments)
-                {
-                    boolean isFragment = Util.isFragment(resource);
-                    if (isFragment)
-                    {
-                        allCandidates.populate(rc, resource, Candidates.ON_DEMAND);
-                    }
-                }
-
                 // Merge any fragments into hosts.
                 allCandidates.prepare(rc);
 
@@ -302,7 +290,16 @@ public class ResolverImpl implements Res
                 {
                     if (faultyResources != null) {
                     	Set<Resource> resourceKeys = faultyResources.keySet();
-                        retry = (optionalResources.removeAll(resourceKeys) || ondemandFragments.removeAll(resourceKeys));
+                        retry = (optionalResources.removeAll(resourceKeys));
+                        for (Resource faultyResource : resourceKeys) {
+							Boolean valid = validOnDemandResources.get(faultyResource);
+							if (valid != null && valid.booleanValue()) {
+								// This was an ondemand resource.
+								// Invalidate it and try again.
+								validOnDemandResources.put(faultyResource, Boolean.FALSE);
+								retry = true;
+							}
+						}
                         // log all the resolution exceptions for the uses constraint violations
                         for (Map.Entry<Resource, ResolutionException> usesError : faultyResources.entrySet())
{
     						m_logger.logUsesConstraintViolation(usesError.getKey(), usesError.getValue());
@@ -379,8 +376,6 @@ public class ResolverImpl implements Res
      * @param host the hosting resource
      * @param dynamicReq the dynamic requirement
      * @param matches a list of matching capabilities
-     * @param ondemandFragments collection of on demand fragments that will
-     * attach to any host that is a candidate
      * @return The new resources and wires required to satisfy the specified
      * dynamic requirement. The returned map is the property of the caller and
      * can be modified by the caller.
@@ -388,7 +383,7 @@ public class ResolverImpl implements Res
      */
     public Map<Resource, List<Wire>> resolve(
         ResolveContext rc, Resource host, Requirement dynamicReq,
-        List<Capability> matches, Collection<Resource> ondemandFragments)
+        List<Capability> matches)
         throws ResolutionException
     {
         ResolveSession session = new ResolveSession(rc);
@@ -413,15 +408,11 @@ public class ResolverImpl implements Res
                 }
             }
 
-            // Make copy of args in case we want to modify them.
-            ondemandFragments = new ArrayList<Resource>(ondemandFragments);
 
-            // Create all candidates pre-populated with the single candidate set
-            // for the resolving dynamic import of the host.
-            Candidates allCandidates = new Candidates();
-            allCandidates.populateDynamic(rc, host, dynamicReq, matches);
+
 
             Map<Resource, Packages> resourcePkgMap = new HashMap<Resource, Packages>();
+            Map<Resource, Boolean> onDemandResources = new HashMap<Resource, Boolean>();
 
             boolean retry;
             do
@@ -430,15 +421,10 @@ public class ResolverImpl implements Res
 
                 try
                 {
-                    // Try to populate optional fragments.
-                    for (Resource r : ondemandFragments)
-                    {
-                        if (Util.isFragment(r))
-                        {
-                            allCandidates.populate(rc, r, Candidates.ON_DEMAND);
-                        }
-                    }
-
+                    // Create all candidates pre-populated with the single candidate set
+                    // for the resolving dynamic import of the host.
+                    Candidates allCandidates = new Candidates(onDemandResources);
+                    allCandidates.populateDynamic(rc, host, dynamicReq, matches);
                     // Merge any fragments into hosts.
                     allCandidates.prepare(rc);
 
@@ -508,15 +494,13 @@ public class ResolverImpl implements Res
                                 ((WrappedRequirement) faultyReq)
                                 .getDeclaredRequirement().getResource();
                         }
-                        // Try to ignore the faulty resource if it is not mandatory.
-                        if (ondemandFragments.remove(faultyResource))
-                        {
-                            retry = true;
-                        }
-                        else
-                        {
+						Boolean valid = onDemandResources.get(faultyResource);
+						if (valid != null && valid.booleanValue()) {
+							onDemandResources.put(faultyResource, Boolean.FALSE);
+							retry = true;
+						} else {
                             throw rethrow;
-                        }
+						}
                     }
                     // If there is no exception to rethrow, then this was a clean
                     // resolve, so populate the wire map.



Mime
View raw message