Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2019-04-09 14:13:14 -0400
committerThomas Watson2019-04-12 09:58:21 -0400
commit2e8fc7a7f648e3ad325e55863aca098c8e108db6 (patch)
tree572bb72a7f16728e84a0f3411c22700e0135d8fc
parente98581771affe7d6ae47902670bacc572b0a9e75 (diff)
downloadrt.equinox.framework-2e8fc7a7f648e3ad325e55863aca098c8e108db6.tar.gz
rt.equinox.framework-2e8fc7a7f648e3ad325e55863aca098c8e108db6.tar.xz
rt.equinox.framework-2e8fc7a7f648e3ad325e55863aca098c8e108db6.zip
Bug 540507 - parallel activation of bundles from framework start-level
By default the framework start-level implementation activates all bundles that have the same start-level in sequential order using the bundle ID (install order) to determine the order the bundles are started from a single thread. A new configuration option is added equinox.start.level.thread.count that is set to 1 by default. This will cause the framework to continue with the behavior of activating all bundles with a single thread. If equinox.start.level.thread.count is set to -1 then the framework will use an executor with the number of threads == to java.lang.Runtime.availableProcessors() to activate the bundles in parallel. This means that the order the bundles with the same start-level are activated becomes random. The equinox.start.level.thread.count config setting can also be set to a value > 1 to give an explicit value for the number of threads to use (instead of using java.lang.Runtime.availableProcessors() to determine the number) Change-Id: Ifcf6f18b762bcb114f8f8c75630fdca0cb79a24c Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
-rwxr-xr-xbundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java136
-rw-r--r--bundles/org.eclipse.osgi/META-INF/MANIFEST.MF4
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java81
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainerAdaptor.java27
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java3
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainerAdaptor.java76
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java2
-rw-r--r--bundles/org.eclipse.osgi/pom.xml2
8 files changed, 284 insertions, 47 deletions
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java
index 8a4232659..795895916 100755
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java
@@ -37,9 +37,11 @@ import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
@@ -3517,6 +3519,140 @@ public class SystemBundleTests extends AbstractBundleTests {
}
}
+ public void testStartLevelSingleThread() throws IOException, InterruptedException {
+ File config = OSGiTestsActivator.getContext().getDataFile(getName()); //$NON-NLS-1$
+ Map configuration = new HashMap();
+ configuration.put(Constants.FRAMEWORK_STORAGE, config.getAbsolutePath());
+ Equinox equinox = null;
+ final int numBundles = 20;
+ final File[] testBundleFiles = createBundles(new File(config, "testBundles"), numBundles);
+ try {
+ equinox = new Equinox(configuration);
+ equinox.start();
+ for (int i = 0; i < numBundles; i++) {
+ Bundle b = equinox.getBundleContext().installBundle("reference:file:///" + testBundleFiles[i].getAbsolutePath());
+ b.adapt(BundleStartLevel.class).setStartLevel(5);
+ b.start();
+ }
+
+ final Set<Thread> startingThreads = Collections.synchronizedSet(new HashSet<Thread>());
+ equinox.getBundleContext().addBundleListener(new SynchronousBundleListener() {
+ @Override
+ public void bundleChanged(BundleEvent event) {
+ if (event.getType() == BundleEvent.STARTING) {
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException e) {
+ // nothing
+ }
+ startingThreads.add(Thread.currentThread());
+ }
+ }
+ });
+
+ final CountDownLatch waitForStartLevel = new CountDownLatch(1);
+ equinox.adapt(FrameworkStartLevel.class).setStartLevel(5, new FrameworkListener() {
+ @Override
+ public void frameworkEvent(FrameworkEvent event) {
+ waitForStartLevel.countDown();
+ }
+ });
+ waitForStartLevel.await(10, TimeUnit.SECONDS);
+
+ assertEquals("Did not finish start level setting.", 0, waitForStartLevel.getCount());
+ assertEquals("Wrong number of start threads.", 1, startingThreads.size());
+
+ } catch (BundleException e) {
+ fail("Failed init", e);
+ } finally {
+ try {
+ if (equinox != null) {
+ equinox.stop();
+ equinox.waitForStop(1000);
+ }
+ } catch (BundleException e) {
+ fail("Failed to stop framework.", e);
+ } catch (InterruptedException e) {
+ fail("Failed to stop framework.", e);
+ }
+ }
+ }
+
+ public void testStartLevelMultiThread() throws IOException, InterruptedException {
+ File config = OSGiTestsActivator.getContext().getDataFile(getName()); //$NON-NLS-1$
+ Map<String, String> configuration = new HashMap();
+ configuration.put(Constants.FRAMEWORK_STORAGE, config.getAbsolutePath());
+ configuration.put(EquinoxConfiguration.PROP_EQUINOX_START_LEVEL_THREAD_COUNT, "5");
+ Equinox equinox = null;
+ final int numBundles = 40;
+ final File[] testBundleFiles = createBundles(new File(config, "testBundles"), numBundles);
+ try {
+ equinox = new Equinox(configuration);
+ equinox.start();
+ for (int i = 0; i < numBundles; i++) {
+ Bundle b = equinox.getBundleContext().installBundle("reference:file:///" + testBundleFiles[i].getAbsolutePath());
+ if (i < 20) {
+ b.adapt(BundleStartLevel.class).setStartLevel(5);
+ } else {
+ b.adapt(BundleStartLevel.class).setStartLevel(10);
+ }
+ b.start();
+ }
+
+ final Set<Thread> startingThreads = Collections.synchronizedSet(new HashSet<Thread>());
+ final List<Bundle> startingBundles = Collections.synchronizedList(new ArrayList<Bundle>());
+ equinox.getBundleContext().addBundleListener(new SynchronousBundleListener() {
+ @Override
+ public void bundleChanged(BundleEvent event) {
+ if (event.getType() == BundleEvent.STARTING) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // nothing
+ }
+ startingBundles.add(event.getBundle());
+ startingThreads.add(Thread.currentThread());
+ }
+ }
+ });
+
+ final CountDownLatch waitForStartLevel = new CountDownLatch(1);
+ equinox.adapt(FrameworkStartLevel.class).setStartLevel(5, new FrameworkListener() {
+ @Override
+ public void frameworkEvent(FrameworkEvent event) {
+ waitForStartLevel.countDown();
+ }
+ });
+ waitForStartLevel.await(10, TimeUnit.SECONDS);
+
+ assertEquals("Did not finish start level setting.", 0, waitForStartLevel.getCount());
+ assertEquals("Wrong number of start threads.", 6, startingThreads.size());
+
+ ListIterator<Bundle> itr = startingBundles.listIterator();
+ while (itr.hasNext()) {
+ Bundle b2 = itr.next();
+ if (itr.hasPrevious()) {
+ Bundle b1 = itr.previous();
+ itr.next();
+ assertTrue("Wrong order to starting bundle.", b1.adapt(BundleStartLevel.class).getStartLevel() <= b2.adapt(BundleStartLevel.class).getStartLevel());
+ }
+ }
+ } catch (BundleException e) {
+ fail("Failed init", e);
+ } finally {
+ try {
+ if (equinox != null) {
+ equinox.stop();
+ equinox.waitForStop(1000);
+ }
+ } catch (BundleException e) {
+ fail("Failed to stop framework.", e);
+ } catch (InterruptedException e) {
+ fail("Failed to stop framework.", e);
+ }
+ }
+ }
+
public void testBundleIDLock() {
File config = OSGiTestsActivator.getContext().getDataFile(getName()); //$NON-NLS-1$
Map<String, Object> configuration = new HashMap<String, Object>();
diff --git a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
index dc7a293e5..1f3e297a4 100644
--- a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Export-Package: org.eclipse.core.runtime.adaptor;x-friends:="org.eclipse.core.runtime",
org.eclipse.core.runtime.internal.adaptor;x-internal:=true,
org.eclipse.equinox.log;version="1.1";uses:="org.osgi.framework,org.osgi.service.log",
- org.eclipse.osgi.container;version="1.3";
+ org.eclipse.osgi.container;version="1.4";
uses:="org.eclipse.osgi.report.resolution,
org.osgi.framework.wiring,
org.osgi.framework.startlevel,
@@ -101,7 +101,7 @@ Bundle-Activator: org.eclipse.osgi.internal.framework.SystemBundleActivator
Bundle-Description: %systemBundle
Bundle-Copyright: %copyright
Bundle-Vendor: %eclipse.org
-Bundle-Version: 3.13.400.qualifier
+Bundle-Version: 3.14.0.qualifier
Bundle-Localization: systembundle
Bundle-DocUrl: http://www.eclipse.org
Eclipse-ExtensibleAPI: true
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java
index e7870771f..e51ef84e8 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java
@@ -26,6 +26,8 @@ import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -1563,7 +1565,7 @@ public final class ModuleContainer implements DebugOptionsListener {
private final Object eventManagerLock = new Object();
private EventManager startLevelThread = null;
private final Object frameworkStartLevelLock = new Object();
- private boolean debugStartLevel = false;
+ boolean debugStartLevel = false;
{
setDebugOptions();
}
@@ -1708,6 +1710,8 @@ public final class ModuleContainer implements DebugOptionsListener {
List<Module> sorted = null;
long currentTimestamp = Long.MIN_VALUE;
if (newStartLevel > currentSL) {
+ List<Module> lazyStart = null;
+ List<Module> eagerStart = null;
for (int i = currentSL; i < newStartLevel; i++) {
int toStartLevel = i + 1;
activeStartLevel.set(toStartLevel);
@@ -1718,12 +1722,15 @@ public final class ModuleContainer implements DebugOptionsListener {
moduleDatabase.readLock();
try {
sorted = moduleDatabase.getSortedModules(Sort.BY_START_LEVEL);
+ lazyStart = new ArrayList<>(sorted.size());
+ eagerStart = new ArrayList<>(sorted.size());
+ separateModulesByActivationPolicy(sorted, lazyStart, eagerStart);
currentTimestamp = moduleDatabase.getTimestamp();
} finally {
moduleDatabase.readUnlock();
}
}
- incStartLevel(toStartLevel, sorted);
+ incStartLevel(toStartLevel, lazyStart, eagerStart);
}
} else {
for (int i = currentSL; i > newStartLevel; i--) {
@@ -1759,13 +1766,27 @@ public final class ModuleContainer implements DebugOptionsListener {
}
}
- private void incStartLevel(int toStartLevel, List<Module> sortedModules) {
- incStartLevel(toStartLevel, sortedModules, true);
- incStartLevel(toStartLevel, sortedModules, false);
+ private void incStartLevel(int toStartLevel, List<Module> lazyStart, List<Module> eagerStart) {
+ incStartLevel(toStartLevel, lazyStart);
+ incStartLevel(toStartLevel, eagerStart);
}
- private void incStartLevel(int toStartLevel, List<Module> sortedModules, boolean lazyOnly) {
+ private void separateModulesByActivationPolicy(List<Module> sortedModules, List<Module> lazyStart, List<Module> eagerStart) {
for (Module module : sortedModules) {
+ if (module.isLazyActivate()) {
+ lazyStart.add(module);
+ } else {
+ eagerStart.add(module);
+ }
+ }
+ }
+
+ private void incStartLevel(final int toStartLevel, List<Module> candidatesToStart) {
+ if (candidatesToStart.isEmpty()) {
+ return;
+ }
+ List<Module> toStart = new ArrayList<>();
+ for (final Module module : candidatesToStart) {
if (isRefreshingSystemModule()) {
return;
}
@@ -1775,22 +1796,8 @@ public final class ModuleContainer implements DebugOptionsListener {
// skip modules who should have already been started
continue;
} else if (moduleStartLevel == toStartLevel) {
- boolean isLazyStart = module.isLazyActivate();
- if (lazyOnly ? isLazyStart : !isLazyStart) {
- if (debugStartLevel) {
- Debug.println("StartLevel: resuming bundle; " + toString(module) + "; with startLevel=" + moduleStartLevel); //$NON-NLS-1$ //$NON-NLS-2$
- }
- try {
- module.start(StartOptions.TRANSIENT_IF_AUTO_START, StartOptions.TRANSIENT_RESUME);
- } catch (BundleException e) {
- adaptor.publishContainerEvent(ContainerEvent.ERROR, module, e);
- } catch (IllegalStateException e) {
- // been uninstalled
- continue;
- }
- }
+ toStart.add(module);
} else {
- // can stop resuming since any remaining modules have a greater startlevel than the active startlevel
break;
}
} catch (IllegalStateException e) {
@@ -1798,6 +1805,36 @@ public final class ModuleContainer implements DebugOptionsListener {
continue;
}
}
+ if (toStart.isEmpty()) {
+ return;
+ }
+ final Executor executor = adaptor.getStartLevelExecutor();
+ final CountDownLatch done = new CountDownLatch(toStart.size());
+ for (final Module module : toStart) {
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (debugStartLevel) {
+ Debug.println("StartLevel: resuming bundle; " + ContainerStartLevel.this.toString(module) + "; with startLevel=" + toStartLevel); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ module.start(StartOptions.TRANSIENT_IF_AUTO_START, StartOptions.TRANSIENT_RESUME);
+ } catch (BundleException e) {
+ adaptor.publishContainerEvent(ContainerEvent.ERROR, module, e);
+ } catch (IllegalStateException e) {
+ // been uninstalled
+ } finally {
+ done.countDown();
+ }
+ }
+ });
+
+ }
+ try {
+ done.await();
+ } catch (InterruptedException e) {
+ adaptor.publishContainerEvent(ContainerEvent.ERROR, moduleDatabase.getModule(0), e);
+ }
}
private void decStartLevel(int toStartLevel, List<Module> sortedModules) {
@@ -1865,7 +1902,7 @@ public final class ModuleContainer implements DebugOptionsListener {
}
}
- private String toString(Module m) {
+ String toString(Module m) {
Bundle b = m.getBundle();
return b != null ? b.toString() : m.toString();
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainerAdaptor.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainerAdaptor.java
index bfa760e79..df8838e76 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainerAdaptor.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainerAdaptor.java
@@ -22,12 +22,20 @@ import org.eclipse.osgi.service.debug.DebugOptions;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.hooks.resolver.ResolverHookFactory;
+import org.osgi.framework.startlevel.FrameworkStartLevel;
/**
* Adapts the behavior of a container.
* @since 3.10
*/
public abstract class ModuleContainerAdaptor {
+ private static Executor defaultExecutor = new Executor() {
+ @Override
+ public void execute(Runnable command) {
+ command.run();
+ }
+ };
+
/**
* Event types that may be {@link #publishContainerEvent(ContainerEvent, Module, Throwable, FrameworkListener...) published}
* for a container.
@@ -291,12 +299,19 @@ public abstract class ModuleContainerAdaptor {
* @since 3.11
*/
public Executor getResolverExecutor() {
- return new Executor() {
- @Override
- public void execute(Runnable command) {
- command.run();
- }
- };
+ return defaultExecutor;
+ }
+
+ /**
+ * Returns the executor used to by the
+ * {@link ModuleContainer#getFrameworkStartLevel() FrameworkStartLevel} implementation to
+ * start bundles that have the same start level. This allows bundles to be
+ * started in parallel.
+ * @return the executor used by the {@link FrameworkStartLevel} implementation.
+ * @since 3.14
+ */
+ public Executor getStartLevelExecutor() {
+ return defaultExecutor;
}
/**
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java
index dd8b559d6..f1f5b43e7 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java
@@ -223,7 +223,10 @@ public class EquinoxConfiguration implements EnvironmentInfo {
public static final String PROP_ALLOW_RESTRICTED_PROVIDES = "osgi.equinox.allow.restricted.provides"; //$NON-NLS-1$
public static final String PROP_LOG_HISTORY_MAX = "equinox.log.history.max"; //$NON-NLS-1$
+ @Deprecated
public static final String PROP_RESOLVER_THREAD_COUNT = "equinox.resolver.thead.count"; //$NON-NLS-1$
+ public static final String PROP_EQUINOX_RESOLVER_THREAD_COUNT = "equinox.resolver.thread.count"; //$NON-NLS-1$
+ public static final String PROP_EQUINOX_START_LEVEL_THREAD_COUNT = "equinox.start.level.thread.count"; //$NON-NLS-1$
public static final String PROP_RESOLVER_REVISION_BATCH_SIZE = "equinox.resolver.revision.batch.size"; //$NON-NLS-1$
public static final String PROP_RESOLVER_BATCH_TIMEOUT = "equinox.resolver.batch.timeout"; //$NON-NLS-1$
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainerAdaptor.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainerAdaptor.java
index 48b60316f..d8b7b2584 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainerAdaptor.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainerAdaptor.java
@@ -64,7 +64,8 @@ public class EquinoxContainerAdaptor extends ModuleContainerAdaptor {
platformClassLoader = (ClassLoader) getPlatformClassLoader.invoke(null);
} catch (Throwable t) {
// try everything possible to not fail <clinit>
- platformClassLoader = new ClassLoader(Object.class.getClassLoader()) { /* boot class loader */};
+ platformClassLoader = new ClassLoader(Object.class.getClassLoader()) {
+ /* boot class loader */};
}
BOOT_CLASSLOADER = platformClassLoader;
}
@@ -76,8 +77,10 @@ public class EquinoxContainerAdaptor extends ModuleContainerAdaptor {
private final ClassLoader moduleClassLoaderParent;
private final AtomicLong lastSecurityAdminFlush;
- final AtomicLazyInitializer<Executor> executor = new AtomicLazyInitializer<>();
- final Callable<Executor> lazyExecutorCreator;
+ final AtomicLazyInitializer<Executor> resolverExecutor;
+ final Callable<Executor> lazyResolverExecutorCreator;
+ final AtomicLazyInitializer<Executor> startLevelExecutor;
+ final Callable<Executor> lazyStartLevelExecutorCreator;
public EquinoxContainerAdaptor(EquinoxContainer container, Storage storage, Map<Long, Generation> initial) {
this.container = container;
@@ -86,19 +89,53 @@ public class EquinoxContainerAdaptor extends ModuleContainerAdaptor {
this.initial = initial;
this.moduleClassLoaderParent = getModuleClassLoaderParent(container.getConfiguration());
this.lastSecurityAdminFlush = new AtomicLong();
- this.lazyExecutorCreator = createLazyExecutorCreator(container.getConfiguration());
- }
- private Callable<Executor> createLazyExecutorCreator(EquinoxConfiguration config) {
- String threadCntProp = config.getConfiguration(EquinoxConfiguration.PROP_RESOLVER_THREAD_COUNT);
- int threadCntTmp;
+ EquinoxConfiguration config = container.getConfiguration();
+ @SuppressWarnings("deprecation")
+ String resolverThreadCntProp = config.getConfiguration(EquinoxConfiguration.PROP_EQUINOX_RESOLVER_THREAD_COUNT, //
+ config.getConfiguration(EquinoxConfiguration.PROP_RESOLVER_THREAD_COUNT));
+
+ int resolverThreadCnt;
+ try {
+ // note that resolver thread count defaults to -1 (compute based on processor number)
+ resolverThreadCnt = resolverThreadCntProp == null ? -1 : Integer.parseInt(resolverThreadCntProp);
+ } catch (NumberFormatException e) {
+ resolverThreadCnt = -1;
+ }
+ String startLevelThreadCntProp = config.getConfiguration(EquinoxConfiguration.PROP_EQUINOX_START_LEVEL_THREAD_COUNT);
+ int startLevelThreadCnt;
try {
- threadCntTmp = threadCntProp == null ? -1 : Integer.parseInt(threadCntProp);
+ // Note that start-level thread count defaults to 1 (synchronous start)
+ startLevelThreadCnt = startLevelThreadCntProp == null ? 1 : Integer.parseInt(startLevelThreadCntProp);
} catch (NumberFormatException e) {
- threadCntTmp = -1;
+ startLevelThreadCnt = 1;
+ }
+
+ if (resolverThreadCnt == startLevelThreadCnt) {
+ // use a single executor
+ this.resolverExecutor = new AtomicLazyInitializer<>();
+ this.lazyResolverExecutorCreator = createLazyExecutorCreator(container.getConfiguration(), //
+ "Equinox executor thread - " + EquinoxContainerAdaptor.this.toString(), //$NON-NLS-1$
+ resolverThreadCnt);
+ this.startLevelExecutor = resolverExecutor;
+ this.lazyStartLevelExecutorCreator = lazyResolverExecutorCreator;
+ } else {
+ // use two different executors
+ this.resolverExecutor = new AtomicLazyInitializer<>();
+ this.lazyResolverExecutorCreator = createLazyExecutorCreator(container.getConfiguration(), //
+ "Equinox resolver thread - " + EquinoxContainerAdaptor.this.toString(), //$NON-NLS-1$
+ resolverThreadCnt);
+ this.startLevelExecutor = new AtomicLazyInitializer<>();
+ this.lazyStartLevelExecutorCreator = createLazyExecutorCreator(container.getConfiguration(), //
+ "Equinox start level thread - " + EquinoxContainerAdaptor.this.toString(), //$NON-NLS-1$
+ startLevelThreadCnt);
}
+
+ }
+
+ private Callable<Executor> createLazyExecutorCreator(EquinoxConfiguration config, final String threadName, int threadCnt) {
// use the number of processors - 1 because we use the current thread when rejected
- final int maxThreads = threadCntTmp <= 0 ? Math.max(Runtime.getRuntime().availableProcessors() - 1, 1) : threadCntTmp;
+ final int maxThreads = threadCnt <= 0 ? Math.max(Runtime.getRuntime().availableProcessors() - 1, 1) : threadCnt;
return new Callable<Executor>() {
@Override
public Executor call() throws Exception {
@@ -120,7 +157,7 @@ public class EquinoxContainerAdaptor extends ModuleContainerAdaptor {
ThreadFactory threadFactory = new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
- Thread t = new Thread(r, "Resolver thread - " + EquinoxContainerAdaptor.this.toString()); //$NON-NLS-1$
+ Thread t = new Thread(r, threadName);
t.setDaemon(true);
return t;
}
@@ -362,7 +399,12 @@ public class EquinoxContainerAdaptor extends ModuleContainerAdaptor {
@Override
public Executor getResolverExecutor() {
- return executor.getInitialized(lazyExecutorCreator);
+ return resolverExecutor.getInitialized(lazyResolverExecutorCreator);
+ }
+
+ @Override
+ public Executor getStartLevelExecutor() {
+ return startLevelExecutor.getInitialized(lazyStartLevelExecutorCreator);
}
@Override
@@ -370,8 +412,12 @@ public class EquinoxContainerAdaptor extends ModuleContainerAdaptor {
return container.getScheduledExecutor();
}
- public void shutdownResolverExecutor() {
- Executor current = executor.getAndClear();
+ public void shutdownExecutors() {
+ Executor current = resolverExecutor.getAndClear();
+ if (current instanceof ExecutorService) {
+ ((ExecutorService) current).shutdown();
+ }
+ current = startLevelExecutor.getAndClear();
if (current instanceof ExecutorService) {
((ExecutorService) current).shutdown();
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java
index 25c70ac8f..ddea8b6f5 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java
@@ -474,7 +474,7 @@ public class Storage {
}
}
mruList.shutdown();
- adaptor.shutdownResolverExecutor();
+ adaptor.shutdownExecutors();
}
private boolean needUpdate(ModuleRevision currentRevision, ModuleRevisionBuilder newBuilder) {
diff --git a/bundles/org.eclipse.osgi/pom.xml b/bundles/org.eclipse.osgi/pom.xml
index 92a400413..48467d543 100644
--- a/bundles/org.eclipse.osgi/pom.xml
+++ b/bundles/org.eclipse.osgi/pom.xml
@@ -19,7 +19,7 @@
</parent>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
- <version>3.13.400-SNAPSHOT</version>
+ <version>3.14.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
<build>

Back to the top