diff options
Diffstat (limited to 'container-core/src/main/java/com/yahoo/container/core/config/ApplicationBundleLoader.java')
-rw-r--r-- | container-core/src/main/java/com/yahoo/container/core/config/ApplicationBundleLoader.java | 88 |
1 files changed, 32 insertions, 56 deletions
diff --git a/container-core/src/main/java/com/yahoo/container/core/config/ApplicationBundleLoader.java b/container-core/src/main/java/com/yahoo/container/core/config/ApplicationBundleLoader.java index 972d6677e3b..f0ca5aee8a2 100644 --- a/container-core/src/main/java/com/yahoo/container/core/config/ApplicationBundleLoader.java +++ b/container-core/src/main/java/com/yahoo/container/core/config/ApplicationBundleLoader.java @@ -6,14 +6,13 @@ import com.yahoo.osgi.Osgi; import org.osgi.framework.Bundle; import java.util.ArrayList; -import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Logger; +import java.util.stream.Collectors; /** * Manages the set of installed and active/inactive bundles. @@ -25,15 +24,16 @@ public class ApplicationBundleLoader { private static final Logger log = Logger.getLogger(ApplicationBundleLoader.class.getName()); - // The active bundles for the current application generation. + /** + * Map of file refs of active bundles (not scheduled for uninstall) to the installed bundle. + * + * Used to: + * 1. Avoid installing already installed bundles. Just an optimization, installing the same bundle location is a NOP + * 2. Start bundles (all are started every time) + * 3. Calculate the set of bundles to uninstall + */ private final Map<FileReference, Bundle> reference2Bundle = new LinkedHashMap<>(); - // The bundles that are obsolete from the previous generation, but kept in case the generation is reverted. - private Map<FileReference, Bundle> obsoleteBundles = Map.of(); - - // The bundles that exclusively belong to the current application generation. - private Map<FileReference, Bundle> bundlesFromNewGeneration = Map.of(); - private final Osgi osgi; private final FileAcquirerBundleInstaller bundleInstaller; @@ -48,76 +48,54 @@ public class ApplicationBundleLoader { */ public synchronized Set<Bundle> useBundles(List<FileReference> newFileReferences) { - obsoleteBundles = removeObsoleteBundles(newFileReferences); - Set<Bundle> bundlesToUninstall = new LinkedHashSet<>(obsoleteBundles.values()); + Set<FileReference> obsoleteReferences = getObsoleteFileReferences(newFileReferences); + Set<Bundle> bundlesToUninstall = getObsoleteBundles(obsoleteReferences); log.info("Bundles to schedule for uninstall: " + bundlesToUninstall); osgi.allowDuplicateBundles(bundlesToUninstall); + removeInactiveFileReferences(obsoleteReferences); - bundlesFromNewGeneration = installBundles(newFileReferences); + installBundles(newFileReferences); BundleStarter.startBundles(reference2Bundle.values()); log.info(installedBundlesMessage()); return bundlesToUninstall; } - /** - * Restores state from the previous application generation and returns the set of bundles that - * exclusively belongs to the latest (failed) application generation. Uninstalling must - * be done by the Deconstructor as they may still be needed by components from the failed gen. - */ - public synchronized Collection<Bundle> revertToPreviousGeneration() { - reference2Bundle.putAll(obsoleteBundles); - bundlesFromNewGeneration.forEach(reference2Bundle::remove); - Collection<Bundle> ret = bundlesFromNewGeneration.values(); - - // No duplicate bundles should be allowed until the next call to useBundles. - osgi.allowDuplicateBundles(Set.of()); - - // Clear restore info in case this method is called multiple times, for some reason. - bundlesFromNewGeneration = Map.of(); - obsoleteBundles = Map.of(); - - return ret; + private Set<FileReference> getObsoleteFileReferences(List<FileReference> newReferences) { + Set<FileReference> obsoleteReferences = new HashSet<>(reference2Bundle.keySet()); + obsoleteReferences.removeAll(newReferences); + return obsoleteReferences; } /** - * Calculates the set of bundles that are not needed by the new application generation and - * removes them from the map of active bundles. - * - * Returns the map of bundles that are not needed by the new application generation. + * Returns the bundles that will not be retained by the new application generation. */ - private Map<FileReference, Bundle> removeObsoleteBundles(List<FileReference> newReferences) { - Map<FileReference, Bundle> obsoleteReferences = new LinkedHashMap<>(reference2Bundle); - newReferences.forEach(obsoleteReferences::remove); + private Set<Bundle> getObsoleteBundles(Set<FileReference> obsoleteReferences) { + return obsoleteReferences.stream().map(reference2Bundle::get).collect(Collectors.toSet()); + } - obsoleteReferences.forEach(reference2Bundle::remove); - return obsoleteReferences; + private void removeInactiveFileReferences(Set<FileReference> fileReferencesToRemove) { + fileReferencesToRemove.forEach(reference2Bundle::remove); } - /** - * Returns the set of new bundles that were installed. - */ - private Map<FileReference, Bundle> installBundles(List<FileReference> references) { + private void installBundles(List<FileReference> references) { Set<FileReference> bundlesToInstall = new HashSet<>(references); // This is just an optimization, as installing a bundle with the same location id returns the already installed bundle. bundlesToInstall.removeAll(reference2Bundle.keySet()); - if (bundlesToInstall.isEmpty()) return Map.of(); - - if (bundleInstaller.hasFileDistribution()) { - return installWithFileDistribution(bundlesToInstall, bundleInstaller); - } else { - log.warning("Can't retrieve bundles since file distribution is disabled."); - return Map.of(); + if (!bundlesToInstall.isEmpty()) { + if (bundleInstaller.hasFileDistribution()) { + installWithFileDistribution(bundlesToInstall, bundleInstaller); + } else { + log.warning("Can't retrieve bundles since file distribution is disabled."); + } } } - private Map<FileReference, Bundle> installWithFileDistribution(Set<FileReference> bundlesToInstall, - FileAcquirerBundleInstaller bundleInstaller) { - var newBundles = new LinkedHashMap<FileReference, Bundle>(); - + private void installWithFileDistribution(Set<FileReference> bundlesToInstall, + FileAcquirerBundleInstaller bundleInstaller) { for (FileReference reference : bundlesToInstall) { try { log.info("Installing bundle with reference '" + reference.value() + "'"); @@ -130,13 +108,11 @@ public class ApplicationBundleLoader { throw new RuntimeException("Bundle '" + bundles.get(0).getSymbolicName() + "' tried to pre-install bundles from disk."); } reference2Bundle.put(reference, bundles.get(0)); - newBundles.put(reference, bundles.get(0)); } catch(Exception e) { throw new RuntimeException("Could not install bundle with reference '" + reference + "'", e); } } - return newBundles; } private String installedBundlesMessage() { |