You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@felix.apache.org by Felix Meschberger <Fe...@day.com> on 2007/05/16 08:59:09 UTC

Felix bundle resolution

Hi all,

I ran across an issue with package resolution in the have a problem with
R4SearchPolicyCore class, namely the getInUseCandidates and
getUnusedCandidates method.

My use case is updating a bundle, which has somewhere around 30 exports and
imports with rather big uses lists. Additionally, the bundle has for
historical reasons a "*" DynamicImportPackage, but I think, this is not
important when resolving. Now when the bundle has been updated it is started
again and requires resolution. This calls the
R4SearchPolicyCore.resolve(IModule)
with the new module of the bundle.

This method first populates a map of candidate packages for import using the
populateCandidatesMap methd and then uses the findConsistentClassSpace
method to cleanup the candidates such as to only use valid packages.
Unfortunately now, the populateCandidatesMap, actually the
getInUseCandidates and getUnusedCandidates methods consider exports of the
old version of the bundle as candidates for the resolution. This of course
bloats the candidate list with candidates, which may not be used anyway.

My idea is to not consider modules pending removal in the getInUseCandidates
getUnusedCandidates methods.

A consequence of this change is that the Felix._updateBundle and
Felix._uninstallBundle methods must be adapted to call the
getExportedPackages method BEFORE current module is set pending removal.

What do you think ? Is my assumption correct ?

Regards and Thanks
Felix

PS: Here is a proposed patch:

Index:
/usr/src/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java
===================================================================
---
/usr/src/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java
(revision 538445)
+++
/usr/src/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java
(working copy)
@@ -1545,6 +1545,24 @@
                     info.setState(Bundle.INSTALLED);
                 }

+                // Determine if the bundle is in use by anyone.
+//              TODO: FRAMEWORK - This is really inefficient since it will
end up looping
+//                    through all bundles and their imports, maybe we
should keep track of
+//                    wiring.
+// fmeschbe: This must be done BEFORE setting the module removal
+// pending, otherwise getExportedPackages will not find the
+// uses (as it is implemented currently)
+                 List usedPackages = new ArrayList();
+                 getExportedPackages(bundle, usedPackages);
+                 boolean used = false;
+                 for (int i = 0; !used && (i < usedPackages.size()); i++)
+                 {
+                     if (((ExportedPackageImpl)
usedPackages.get(i)).getImportingBundles()
!= null)
+                     {
+                         used = true;
+                     }
+                 }
+
                 fireBundleEvent(BundleEvent.UNRESOLVED, bundle);

                 // Mark previous the bundle's old module for removal since
@@ -1554,21 +1572,6 @@

                 fireBundleEvent(BundleEvent.UPDATED, bundle);

-                // Determine if the bundle is in use by anyone.
-// TODO: FRAMEWORK - This is really inefficient since it will end up
looping
-//       through all bundles and their imports, maybe we should keep track
of
-//       wiring.
-                List usedPackages = new ArrayList();
-                getExportedPackages(bundle, usedPackages);
-                boolean used = false;
-                for (int i = 0; !used && (i < usedPackages.size()); i++)
-                {
-                    if (((ExportedPackageImpl)
usedPackages.get(i)).getImportingBundles()
!= null)
-                    {
-                        used = true;
-                    }
-                }
-
                 // If the bundle is not used by anyone, then garbage
                 // collect it now.
                 if (!used)
@@ -1788,6 +1791,24 @@
             target = (BundleImpl) m_installedBundleMap.remove(
info.getLocation());
         }

+        // Determine if the bundle is in use by anyone.
+//      TODO: FRAMEWORK - This is really inefficient since it will end up
looping
+//            through all bundles and their imports, maybe we should keep
track of
+//            wiring.
+//      fmeschbe: This must be done BEFORE setting the module removal
+//      pending, otherwise getExportedPackages will not find the
+//      uses (as it is implemented currently)
+        List usedPackages = new ArrayList();
+        getExportedPackages( bundle, usedPackages );
+        boolean used = false;
+        for ( int i = 0; !used && ( i < usedPackages.size() ); i++ )
+        {
+            if ( ( ( ExportedPackageImpl ) usedPackages.get( i )
).getImportingBundles() != null )
+            {
+                used = true;
+            }
+        }
+
         // Finally, put the uninstalled bundle into the
         // uninstalled list for subsequent refreshing.
         if (target != null)
@@ -1815,21 +1836,6 @@
         // Fire bundle event.
         fireBundleEvent(BundleEvent.UNINSTALLED, bundle);

-        // Determine if the bundle is in use by anyone.
-// TODO: FRAMEWORK - This is really inefficient since it will end up
looping
-//       through all bundles and their imports, maybe we should keep track
of
-//       wiring.
-         List usedPackages = new ArrayList();
-         getExportedPackages(bundle, usedPackages);
-         boolean used = false;
-         for (int i = 0; !used && (i < usedPackages.size()); i++)
-         {
-             if (((ExportedPackageImpl)
usedPackages.get(i)).getImportingBundles()
!= null)
-             {
-                 used = true;
-             }
-         }
-
          // If the bundle is not used by anyone, then garbage
          // collect it now.
          if (!used)
Index:
/usr/src/felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
===================================================================
---
/usr/src/felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
(revision 538445)
+++
/usr/src/felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java
(working copy)
@@ -639,6 +639,12 @@
             {
                 Map.Entry entry = (Map.Entry) i.next();
                 IModule module = (IModule) entry.getKey();
+
+                // don't consider modules pending removal
+                if (module.isRemovalPending()) {
+                    continue;
+                }
+
                 ICapability[] inUseCaps = (ICapability[]) entry.getValue();
                 for (int capIdx = 0; capIdx < inUseCaps.length; capIdx++)
                 {
@@ -698,6 +704,12 @@
             PackageSource[] candidates = m_emptySources;
             for (int modIdx = 0; (modules != null) && (modIdx <
modules.length); modIdx++)
             {
+
+                // don't consider modules pending removal
+                if (modules[modIdx].isRemovalPending()) {
+                    continue;
+                }
+
                 // Get the module's export package for the target package.
                 ICapability cap =
Util.getSatisfyingCapability(modules[modIdx],
req);
                 // If compatible and it is not currently used, then add