Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Powell2010-07-09 16:37:05 +0000
committerSteve Powell2010-07-09 16:37:05 +0000
commitf743671d013f1b4a5b7b62201ac30742f60a1981 (patch)
treeb08debc20a60be333d7b392bd0344620a95c7903
parent5e2cded58e9836c7c60ca265a4415153eec36160 (diff)
downloadorg.eclipse.virgo.kernel-f743671d013f1b4a5b7b62201ac30742f60a1981.tar.gz
org.eclipse.virgo.kernel-f743671d013f1b4a5b7b62201ac30742f60a1981.tar.xz
org.eclipse.virgo.kernel-f743671d013f1b4a5b7b62201ac30742f60a1981.zip
[BUG 319401] StartupTracker improved.
-rw-r--r--org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/KernelStatus.java4
-rw-r--r--org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/ServiceReferenceTracker.java80
-rw-r--r--org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/StartupTracker.java135
-rw-r--r--org.eclipse.virgo.kernel.core/src/test/java/org/eclipse/virgo/kernel/core/internal/StartupTrackerTests.java2
4 files changed, 158 insertions, 63 deletions
diff --git a/org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/KernelStatus.java b/org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/KernelStatus.java
index 409c86ba..40bdccb8 100644
--- a/org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/KernelStatus.java
+++ b/org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/KernelStatus.java
@@ -23,8 +23,8 @@ final class KernelStatus implements KernelStatusMBean {
return this.status;
}
- public void setStatus(String status) {
- this.status = status;
+ public void setStarted() {
+ this.status = STATUS_STARTED;
}
}
diff --git a/org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/ServiceReferenceTracker.java b/org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/ServiceReferenceTracker.java
new file mode 100644
index 00000000..4740d505
--- /dev/null
+++ b/org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/ServiceReferenceTracker.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * This file is part of the Virgo Web Server.
+ *
+ * Copyright (c) 2010 Eclipse Foundation.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SpringSource, a division of VMware - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.core.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+
+/**
+ * Utility class that tracks a set of {@link ServiceReference}s for a bundle and allows them to be safely
+ * ungotten.
+ * <p/>
+ * <code>ServiceReferences</code> are tracked in a thread-safe manner, and are ungotten without
+ * holding any locks.
+ *
+ * @see ServiceReference
+ */
+class ServiceReferenceTracker {
+
+ private final BundleContext context;
+
+ private final Object monitor = new Object();
+
+ private Set<ServiceReference> references; // protected by monitor.
+
+
+ ServiceReferenceTracker(BundleContext context) {
+ this.context = context;
+ }
+
+ /**
+ * Tracks the supplied {@link ServiceReference}. This <code>ServiceReference</code> will be
+ * {@link ServiceReference#unget ungotten} during {@link #ungetAll()}.
+ *
+ * @param reference the <code>ServiceReference</code> to track.
+ * @return the reference itself
+ */
+ public ServiceReference track(ServiceReference reference) {
+ synchronized (this.monitor) {
+ if (this.references == null) {
+ this.references = new HashSet<ServiceReference>();
+ }
+ this.references.add(reference);
+ }
+ return reference;
+ }
+
+ /**
+ * Safely unregisters all the tracked <code>ServiceRegistrations</code>.
+ */
+ public void ungetAll() {
+ Set<ServiceReference> toUnget = null;
+ synchronized (this.monitor) {
+ toUnget = this.references;
+ this.references = null;
+ }
+ if (toUnget != null) {
+ for (ServiceReference serviceReference : toUnget) {
+ try {
+ this.context.ungetService(serviceReference);
+ } catch (IllegalStateException e) {
+ }
+ }
+ }
+ }
+}
diff --git a/org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/StartupTracker.java b/org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/StartupTracker.java
index aa92a843..078d9861 100644
--- a/org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/StartupTracker.java
+++ b/org.eclipse.virgo.kernel.core/src/main/java/org/eclipse/virgo/kernel/core/internal/StartupTracker.java
@@ -69,23 +69,17 @@ final class StartupTracker {
private static final Logger LOGGER = LoggerFactory.getLogger(StartupTracker.class);
private final KernelStatus status = new KernelStatus();
-
+
private final KernelConfiguration configuration;
private final Thread startupTrackingThread;
- private final Shutdown shutdown;
-
- private final DumpGenerator dumpGenerator;
-
private volatile ObjectInstance statusInstance;
StartupTracker(BundleContext context, KernelConfiguration configuration, int startupWaitTime, BundleStartTracker asyncBundleStartTracker, Shutdown shutdown, DumpGenerator dumpGenerator) {
- Runnable startupTrackingRunnable = new StartupTrackingRunnable(context, startupWaitTime, asyncBundleStartTracker);
+ Runnable startupTrackingRunnable = new StartupTrackingRunnable(context, startupWaitTime, asyncBundleStartTracker, this.status, shutdown, dumpGenerator);
this.startupTrackingThread = new Thread(startupTrackingRunnable, THREAD_NAME_STARTUP_TRACKER);
this.configuration = configuration;
- this.shutdown = shutdown;
- this.dumpGenerator = dumpGenerator;
}
void start() {
@@ -119,11 +113,7 @@ final class StartupTracker {
}
}
- private void signalStarted() {
- this.status.setStatus(KernelStatus.STATUS_STARTED);
- }
-
- private final class StartupTrackingRunnable implements Runnable {
+ private final static class StartupTrackingRunnable implements Runnable {
private final BundleContext context;
@@ -131,43 +121,80 @@ final class StartupTracker {
private final BundleStartTracker asyncBundleStartTracker;
- private StartupTrackingRunnable(BundleContext context, int startupWaitTime, BundleStartTracker asyncBundleStartTracker) {
+ private final KernelStatus kernelStatus;
+ private final Shutdown shutdown;
+ private final DumpGenerator dumpGenerator;
+
+ private final ServiceReferenceTracker serviceReferenceTracker;
+
+ private EventLogger eventLogger = null;
+ private EventAdmin eventAdmin = null;
+
+ private StartupTrackingRunnable(BundleContext context, int startupWaitTime, BundleStartTracker asyncBundleStartTracker, KernelStatus kernelStatus, Shutdown shutdown, DumpGenerator dumpGenerator) {
this.context = context;
this.startupWaitTime = startupWaitTime;
this.asyncBundleStartTracker = asyncBundleStartTracker;
+ this.kernelStatus = kernelStatus;
+ this.shutdown = shutdown;
+ this.dumpGenerator = dumpGenerator;
+ this.serviceReferenceTracker = new ServiceReferenceTracker(context);
}
public void run() {
-
- kernelStarting();
-
- Bundle[] bundles = this.context.getBundles();
-
+ this.eventLogger = getEventLoggerService();
+ this.eventAdmin = getEventAdminService();
+
try {
- for (Bundle bundle : bundles) {
- if (!BundleUtils.isFragmentBundle(bundle) && isKernelBundle(bundle)) {
- BlockingSignal signal = new BlockingSignal();
-
- this.asyncBundleStartTracker.trackStart(bundle, signal);
-
- LOGGER.debug("Awaiting signal {} for up to {} seconds", signal, this.startupWaitTime);
-
- if (!signal.awaitCompletion(this.startupWaitTime, TimeUnit.SECONDS)) {
- LOGGER.error("Bundle {} did not start within {} seconds.", bundle, this.startupWaitTime);
- kernelStartTimedOut();
- return;
- }
- }
+ kernelStarting();
+
+ Bundle[] bundles = this.context.getBundles();
+
+ try {
+ for (Bundle bundle : bundles) {
+ if (!BundleUtils.isFragmentBundle(bundle) && isKernelBundle(bundle)) {
+ BlockingSignal signal = new BlockingSignal();
+
+ this.asyncBundleStartTracker.trackStart(bundle, signal);
+
+ LOGGER.debug("Awaiting signal {} for up to {} seconds", signal, this.startupWaitTime);
+
+ if (!signal.awaitCompletion(this.startupWaitTime, TimeUnit.SECONDS)) {
+ LOGGER.error("Bundle {} did not start within {} seconds.", bundle, this.startupWaitTime);
+ kernelStartTimedOut();
+ return;
+ }
+ }
+ }
+ } catch (FailureSignalledException fse) {
+ kernelStartFailed(fse.getCause());
+ return;
+ } catch (Exception e) {
+ kernelStartFailed(e);
+ return;
}
- } catch (FailureSignalledException fse) {
- kernelStartFailed(fse.getCause());
- return;
- } catch (Exception e) {
- kernelStartFailed(e);
- return;
+
+ kernelStarted();
+ } finally {
+ this.serviceReferenceTracker.ungetAll();
}
-
- kernelStarted();
+ }
+
+ private EventLogger getEventLoggerService() {
+ EventLogger eventLogger = null;
+ ServiceReference eventLoggerServiceReference = this.context.getServiceReference(EventLogger.class.getName());
+ if (eventLoggerServiceReference != null) {
+ eventLogger = (EventLogger) this.context.getService(this.serviceReferenceTracker.track(eventLoggerServiceReference));
+ }
+ return eventLogger;
+ }
+
+ private EventAdmin getEventAdminService() {
+ EventAdmin eventAdmin = null;
+ ServiceReference eventAdminServiceReference = this.context.getServiceReference(EventAdmin.class.getName());
+ if (eventAdminServiceReference != null) {
+ eventAdmin = (EventAdmin) this.context.getService(this.serviceReferenceTracker.track(eventAdminServiceReference));
+ }
+ return eventAdmin;
}
private boolean isKernelBundle(Bundle bundle) {
@@ -181,7 +208,7 @@ final class StartupTracker {
}
private void kernelStarted() {
- signalStarted();
+ this.kernelStatus.setStarted();
postEvent(KERNEL_EVENT_STARTED);
logEvent(KernelLogEvents.KERNEL_STARTED);
}
@@ -200,21 +227,16 @@ final class StartupTracker {
private void generateDumpAndShutdown(String cause, Throwable failure) {
if (failure != null) {
- StartupTracker.this.dumpGenerator.generateDump(cause, failure);
+ this.dumpGenerator.generateDump(cause, failure);
} else {
- StartupTracker.this.dumpGenerator.generateDump(cause);
+ this.dumpGenerator.generateDump(cause);
}
- StartupTracker.this.shutdown.immediateShutdown();
+ this.shutdown.immediateShutdown();
}
private void logEvent(KernelLogEvents event, Throwable throwable, Object...args) {
- ServiceReference serviceReference = this.context.getServiceReference(EventLogger.class.getName());
- if (serviceReference != null) {
- EventLogger eventLogger = (EventLogger) this.context.getService(serviceReference);
- if (eventLogger != null) {
- eventLogger.log(event, throwable, args);
- this.context.ungetService(serviceReference);
- }
+ if (this.eventLogger != null) {
+ this.eventLogger.log(event, throwable, args);
}
}
@@ -223,13 +245,8 @@ final class StartupTracker {
}
private void postEvent(String topic) {
- ServiceReference serviceReference = this.context.getServiceReference(EventAdmin.class.getName());
- if (serviceReference != null) {
- EventAdmin eventAdmin = (EventAdmin) this.context.getService(serviceReference);
- if (eventAdmin != null) {
- eventAdmin.postEvent(new Event(topic, null));
- this.context.ungetService(serviceReference);
- }
+ if (this.eventAdmin != null) {
+ this.eventAdmin.postEvent(new Event(topic, null));
}
}
}
diff --git a/org.eclipse.virgo.kernel.core/src/test/java/org/eclipse/virgo/kernel/core/internal/StartupTrackerTests.java b/org.eclipse.virgo.kernel.core/src/test/java/org/eclipse/virgo/kernel/core/internal/StartupTrackerTests.java
index efb3f608..879cdf8d 100644
--- a/org.eclipse.virgo.kernel.core/src/test/java/org/eclipse/virgo/kernel/core/internal/StartupTrackerTests.java
+++ b/org.eclipse.virgo.kernel.core/src/test/java/org/eclipse/virgo/kernel/core/internal/StartupTrackerTests.java
@@ -25,7 +25,6 @@ import javax.management.MBeanServer;
import javax.management.ObjectName;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.osgi.framework.Version;
import org.osgi.service.event.Event;
@@ -85,7 +84,6 @@ public class StartupTrackerTests {
}
@Test
- @Ignore("[DMS-2424] timeout is now hard-coded at one hour and so cannot be tested conveniently")
public void startupTimeout() {
BundleStartTracker bundleStartTracker = new BundleStartTracker(new SyncTaskExecutor());

Back to the top