Repository: karaf Updated Branches: refs/heads/master 788eee91d -> d7de15972
[KARAF-2842] Smarter way to not start 'new' bundles, using the resolution output Project: http://git-wip-us.apache.org/repos/asf/karaf/repo Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/d7de1597 Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/d7de1597 Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/d7de1597 Branch: refs/heads/master Commit: d7de159727cbb1fb8486a7693e288f69c57bc198 Parents: 788eee9 Author: Guillaume Nodet <[email protected]> Authored: Tue Apr 8 20:46:22 2014 +0200 Committer: Guillaume Nodet <[email protected]> Committed: Tue Apr 8 20:46:55 2014 +0200 ---------------------------------------------------------------------- .../internal/deployment/DeploymentBuilder.java | 5 +- .../internal/service/FeaturesServiceImpl.java | 56 ++++++++++++++++---- 2 files changed, 48 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/karaf/blob/d7de1597/features/core/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java ---------------------------------------------------------------------- diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java b/features/core/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java index 7226471..022e56f 100644 --- a/features/core/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java +++ b/features/core/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java @@ -153,7 +153,7 @@ public class DeploymentBuilder { return resources; } - public Collection<Resource> resolve(List<Resource> systemBundles, + public Map<Resource, List<Wire>> resolve(List<Resource> systemBundles, boolean resolveOptionalImports) throws ResolutionException { // Resolve for (int i = 0; i < systemBundles.size(); i++) { @@ -171,8 +171,7 @@ public class DeploymentBuilder { new AggregateRepository(repos), resolveOptionalImports); - Map<Resource, List<Wire>> resolution = resolver.resolve(context); - return resolution.keySet(); + return resolver.resolve(context); } public void requireFeature(String feature, ResourceImpl resource) throws IOException { http://git-wip-us.apache.org/repos/asf/karaf/blob/d7de1597/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java ---------------------------------------------------------------------- diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java index e5f5992..a42e133 100644 --- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java +++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java @@ -73,6 +73,7 @@ import org.osgi.framework.wiring.BundleRequirement; import org.osgi.framework.wiring.BundleRevision; import org.osgi.framework.wiring.FrameworkWiring; import org.osgi.resource.Resource; +import org.osgi.resource.Wire; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -541,9 +542,11 @@ public class FeaturesServiceImpl implements FeaturesService { public void doAddFeatures(Set<String> features, EnumSet<Option> options) throws Exception { Set<String> required; + Set<String> installed; Set<Long> managed; synchronized (lock) { required = new HashSet<String>(state.features); + installed = new HashSet<String>(state.installedFeatures); managed = new HashSet<Long>(state.managedBundles); } List<String> featuresToAdd = new ArrayList<String>(); @@ -569,14 +572,16 @@ public class FeaturesServiceImpl implements FeaturesService { } print(sb.toString(), options.contains(Option.Verbose)); required.addAll(featuresToAdd); - doInstallFeaturesInThread(required, managed, options); + doInstallFeaturesInThread(required, installed, managed, options); } public void doRemoveFeatures(Set<String> features, EnumSet<Option> options) throws Exception { Set<String> required; + Set<String> installed; Set<Long> managed; synchronized (lock) { required = new HashSet<String>(state.features); + installed = new HashSet<String>(state.installedFeatures); managed = new HashSet<Long>(state.managedBundles); } List<String> featuresToRemove = new ArrayList<String>(); @@ -622,7 +627,7 @@ public class FeaturesServiceImpl implements FeaturesService { } print(sb.toString(), options.contains(Option.Verbose)); required.removeAll(featuresToRemove); - doInstallFeaturesInThread(required, managed, options); + doInstallFeaturesInThread(required, installed, managed, options); } protected String normalize(String feature) { @@ -642,6 +647,7 @@ public class FeaturesServiceImpl implements FeaturesService { * to bundles not being started after the refresh. */ public void doInstallFeaturesInThread(final Set<String> features, + final Set<String> installed, final Set<Long> managed, final EnumSet<Option> options) throws Exception { ExecutorService executor = Executors.newCachedThreadPool(); @@ -649,7 +655,7 @@ public class FeaturesServiceImpl implements FeaturesService { executor.submit(new Callable<Object>() { @Override public Object call() throws Exception { - doInstallFeatures(features, managed, options); + doInstallFeatures(features, installed, managed, options); return null; } }).get(); @@ -669,7 +675,11 @@ public class FeaturesServiceImpl implements FeaturesService { } } - public void doInstallFeatures(Set<String> features, Set<Long> managed, EnumSet<Option> options) throws Exception { + public void doInstallFeatures(Set<String> features, // all request features + Set<String> installed, // installed features + Set<Long> managed, // currently managed bundles + EnumSet<Option> options // installation options + ) throws Exception { // TODO: make this configurable through ConfigAdmin // TODO: this needs to be tested a bit // TODO: note that this only applies to managed and updateable bundles @@ -719,7 +729,8 @@ public class FeaturesServiceImpl implements FeaturesService { Collections.<String>emptySet(), overrides, Collections.<String>emptySet()); - Collection<Resource> allResources = builder.resolve(systemBundles, false); + Map<Resource, List<Wire>> resolution = builder.resolve(systemBundles, false); + Collection<Resource> allResources = resolution.keySet(); Map<String, StreamProvider> providers = builder.getProviders(); // Install conditionals @@ -762,7 +773,8 @@ public class FeaturesServiceImpl implements FeaturesService { Collections.<String>emptySet(), overrides, Collections.<String>emptySet()); - allResources = builder.resolve(systemBundles, false); + resolution = builder.resolve(systemBundles, false); + allResources = resolution.keySet(); providers = builder.getProviders(); } @@ -784,6 +796,22 @@ public class FeaturesServiceImpl implements FeaturesService { } } + // TODO: handle bundleInfo.isStart() + + // Get all resources that will be used to satisfy the old features set + Set<Resource> resourceLinkedToOldFeatures = new HashSet<Resource>(); + if (noStart) { + for (Resource resource : resolution.keySet()) { + String name = FeatureNamespace.getName(resource); + if (name != null) { + Version version = FeatureNamespace.getVersion(resource); + String id = version != null ? name + "/" + version : name; + if (installed.contains(id)) { + addTransitive(resource, resourceLinkedToOldFeatures, resolution); + } + } + } + } // // Compute deployment @@ -878,7 +906,9 @@ public class FeaturesServiceImpl implements FeaturesService { InputStream is = getBundleInputStream(resource, providers); Bundle bundle = systemBundleContext.installBundle(uri, is); managed.add(bundle.getBundleId()); - toStart.add(bundle); + if (!noStart || resourceLinkedToOldFeatures.contains(resource)) { + toStart.add(bundle); + } deployment.resToBnd.put(resource, bundle); // save a checksum of installed snapshot bundle if (isUpdateable(resource) && !deployment.newCheckums.containsKey(bundle.getLocation())) { @@ -989,9 +1019,7 @@ public class FeaturesServiceImpl implements FeaturesService { for (Bundle bundle : bs) { LOGGER.info(" " + bundle.getSymbolicName() + " / " + bundle.getVersion()); try { - if (!noStart) { - bundle.start(); - } + bundle.start(); } catch (BundleException e) { exceptions.add(e); } @@ -1006,6 +1034,14 @@ public class FeaturesServiceImpl implements FeaturesService { print("Done.", verbose); } + private void addTransitive(Resource resource, Set<Resource> resources, Map<Resource, List<Wire>> resolution) { + if (resources.add(resource)) { + for (Wire wire : resolution.get(resource)) { + addTransitive(wire.getProvider(), resources, resolution); + } + } + } + protected BundleInfo mergeBundleInfo(BundleInfo bi, BundleInfo oldBi) { // TODO: we need a proper merge strategy when a bundle // TODO: comes from different features
