Issue #1939 Fix deadlock at CAVE start up.
Change-Id: Ic3a0f527cdae7ee1abc32662c90d9594686d4bab Former-commit-id:2c2e2b4baa
[formerly6f2a6ce80c
] [formerlyfcc157a91b
[formerly b38ba1c92e4e176364dc3967d11b98fbd66478cd]] Former-commit-id:fcc157a91b
Former-commit-id:3ea6817796
This commit is contained in:
parent
2fbb05b3f7
commit
1d00b3d37a
6 changed files with 142 additions and 66 deletions
|
@ -69,6 +69,8 @@ import com.raytheon.uf.viz.core.notification.NotificationMessage;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* 05/08/08 1127 randerso Initial Creation
|
||||
* 09/03/08 1448 chammack Refactored notification observer interface
|
||||
* 04/23/13 1939 randerso Add separate connect method to allow application
|
||||
* to complete initialization before connecting to JMS
|
||||
* </pre>
|
||||
*
|
||||
* @author randerso
|
||||
|
@ -184,7 +186,6 @@ public class NotificationManagerJob implements ExceptionListener, IDisposable {
|
|||
*/
|
||||
protected NotificationManagerJob() {
|
||||
this.listeners = new HashMap<ListenerKey, NotificationListener>();
|
||||
connect(true);
|
||||
Activator.getDefault().registerDisposable(this);
|
||||
}
|
||||
|
||||
|
@ -411,6 +412,20 @@ public class NotificationManagerJob implements ExceptionListener, IDisposable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to JMS
|
||||
*/
|
||||
public static void connect() {
|
||||
getInstance().connect(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from JMS
|
||||
*/
|
||||
public static void disconnect() {
|
||||
getInstance().disconnect(true);
|
||||
}
|
||||
|
||||
private static class NotificationListener implements MessageListener {
|
||||
|
||||
private Type type;
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.List;
|
|||
|
||||
import javax.xml.bind.JAXBException;
|
||||
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.jface.preference.IPreferenceStore;
|
||||
import org.eclipse.ui.application.WorkbenchAdvisor;
|
||||
import org.osgi.framework.Bundle;
|
||||
|
@ -68,6 +69,7 @@ import com.raytheon.viz.ui.personalities.awips.CAVE;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 4, 2011 njensen Initial creation
|
||||
* Apr 23, 2013 1939 randerso Return null from initializeSerialization
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -192,6 +194,7 @@ public class ThinClientComponent extends CAVE implements IThinClientComponent {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopComponent() {
|
||||
// Persist caches
|
||||
cacheManager.storeCaches();
|
||||
|
@ -201,13 +204,15 @@ public class ThinClientComponent extends CAVE implements IThinClientComponent {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void initializeSerialization() {
|
||||
protected Job initializeSerialization() {
|
||||
try {
|
||||
SerializationUtil.getJaxbContext();
|
||||
} catch (JAXBException e) {
|
||||
statusHandler.handle(Priority.CRITICAL,
|
||||
"An error occured initializing Serialization", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ import com.raytheon.uf.common.status.IUFStatusHandler;
|
|||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
import com.raytheon.uf.common.time.SimulatedTime;
|
||||
import com.raytheon.uf.common.time.util.ITimer;
|
||||
import com.raytheon.uf.common.time.util.TimeUtil;
|
||||
import com.raytheon.uf.viz.alertviz.SystemStatusHandler;
|
||||
import com.raytheon.uf.viz.alertviz.ui.dialogs.AlertVisualization;
|
||||
import com.raytheon.uf.viz.application.ProgramArguments;
|
||||
|
@ -60,6 +62,7 @@ import com.raytheon.uf.viz.core.localization.CAVELocalizationNotificationObserve
|
|||
import com.raytheon.uf.viz.core.localization.LocalizationConstants;
|
||||
import com.raytheon.uf.viz.core.localization.LocalizationInitializer;
|
||||
import com.raytheon.uf.viz.core.localization.LocalizationManager;
|
||||
import com.raytheon.uf.viz.core.notification.jobs.NotificationManagerJob;
|
||||
import com.raytheon.uf.viz.core.status.VizStatusHandlerFactory;
|
||||
import com.raytheon.viz.alerts.jobs.AutoUpdater;
|
||||
import com.raytheon.viz.alerts.jobs.MenuUpdater;
|
||||
|
@ -90,6 +93,8 @@ import com.raytheon.viz.core.units.UnitRegistrar;
|
|||
* mode is off.
|
||||
* Jan 09, 2013 #1442 rferrel Changes to notify SimultedTime listeners.
|
||||
* Apr 17, 2013 1786 mpduff startComponent now sets StatusHandlerFactory
|
||||
* Apr 23, 2013 #1939 randerso Allow serialization to complete initialization
|
||||
* before connecting to JMS to avoid deadlock
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -139,7 +144,8 @@ public abstract class AbstractCAVEComponent implements IStandaloneComponent {
|
|||
UnitRegistrar.registerUnits();
|
||||
CAVEMode.performStartupDuties();
|
||||
|
||||
long t0 = System.currentTimeMillis();
|
||||
ITimer timer = TimeUtil.getTimer();
|
||||
timer.start();
|
||||
|
||||
Display display = null;
|
||||
int modes = getRuntimeModes();
|
||||
|
@ -166,7 +172,7 @@ public abstract class AbstractCAVEComponent implements IStandaloneComponent {
|
|||
}
|
||||
UFStatus.setHandlerFactory(new VizStatusHandlerFactory());
|
||||
|
||||
initializeSerialization();
|
||||
Job serializationJob = initializeSerialization();
|
||||
initializeDataStoreFactory();
|
||||
initializeObservers();
|
||||
|
||||
|
@ -204,12 +210,22 @@ public abstract class AbstractCAVEComponent implements IStandaloneComponent {
|
|||
WorkbenchAdvisor workbenchAdvisor = null;
|
||||
// A component was passed as command line arg
|
||||
// launch cave normally, should cave be registered as component?
|
||||
long t1 = System.currentTimeMillis();
|
||||
System.out.println("Localization time: " + (t1 - t0) + "ms");
|
||||
|
||||
try {
|
||||
initializeSimulatedTime();
|
||||
|
||||
// wait for serialization initialization to complete before
|
||||
// opening JMS connection to avoid deadlock in class loaders
|
||||
if (serializationJob != null) {
|
||||
serializationJob.join();
|
||||
}
|
||||
|
||||
// open JMS connection to allow alerts to be received
|
||||
NotificationManagerJob.connect();
|
||||
|
||||
timer.stop();
|
||||
System.out.println("Initialization time: " + timer.getElapsedTime()
|
||||
+ "ms");
|
||||
|
||||
if (cave) {
|
||||
workbenchAdvisor = getWorkbenchAdvisor();
|
||||
} else if (!nonui) {
|
||||
|
@ -220,6 +236,7 @@ public abstract class AbstractCAVEComponent implements IStandaloneComponent {
|
|||
if (workbenchAdvisor instanceof HiddenWorkbenchAdvisor == false) {
|
||||
startInternal(componentName);
|
||||
}
|
||||
|
||||
if (workbenchAdvisor != null) {
|
||||
returnCode = PlatformUI.createAndRunWorkbench(display,
|
||||
workbenchAdvisor);
|
||||
|
@ -239,6 +256,15 @@ public abstract class AbstractCAVEComponent implements IStandaloneComponent {
|
|||
// catch any exceptions to ensure rest of finally block
|
||||
// executes
|
||||
}
|
||||
|
||||
try {
|
||||
// disconnect from JMS
|
||||
NotificationManagerJob.disconnect();
|
||||
} catch (RuntimeException e) {
|
||||
// catch any exceptions to ensure rest of finally block
|
||||
// executes
|
||||
}
|
||||
|
||||
if (av != null) {
|
||||
av.dispose();
|
||||
}
|
||||
|
@ -368,8 +394,8 @@ public abstract class AbstractCAVEComponent implements IStandaloneComponent {
|
|||
!LocalizationManager.internalAlertServer).run();
|
||||
}
|
||||
|
||||
protected void initializeSerialization() {
|
||||
new Job("Loading Serialization") {
|
||||
protected Job initializeSerialization() {
|
||||
Job job = new Job("Loading Serialization") {
|
||||
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
|
@ -382,7 +408,9 @@ public abstract class AbstractCAVEComponent implements IStandaloneComponent {
|
|||
return Status.OK_STATUS;
|
||||
}
|
||||
|
||||
}.schedule();
|
||||
};
|
||||
job.schedule();
|
||||
return job;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -147,6 +147,7 @@ wrapper.java.additional.48=-Dhttp.port=${HTTP_PORT}
|
|||
wrapper.java.additional.49=-Dedex.arch=${EDEX_BITS}-bit
|
||||
wrapper.java.additional.50=-Dedex.tmp=${TEMP_DIR}
|
||||
wrapper.java.additional.51=-Dncf.bandwidth.manager.service=${NCF_BANDWIDTH_MANAGER_SERVICE}
|
||||
wrapper.java.additional.52=-DinitializeHibernatables=true
|
||||
|
||||
# Initial Java Heap Size (in MB)
|
||||
wrapper.java.initmemory=${INIT_MEM}
|
||||
|
|
|
@ -3,7 +3,6 @@ com.raytheon.uf.common.dataplugin.gfe.db.objects.DatabaseID
|
|||
com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord
|
||||
com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation
|
||||
com.raytheon.uf.common.dataplugin.gfe.db.objects.ParmID
|
||||
com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation
|
||||
com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceData
|
||||
com.raytheon.uf.common.dataplugin.gfe.sample.SampleData
|
||||
com.raytheon.uf.common.dataplugin.gfe.server.lock.Lock
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.p df") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.serialization;
|
||||
|
@ -31,6 +31,7 @@ import java.util.HashSet;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.ServiceConfigurationError;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -56,6 +57,9 @@ import com.raytheon.uf.common.serialization.jaxb.JaxbDummyObject;
|
|||
* Aug 11, 2008 njensen Initial creation
|
||||
* Aug 31, 2009 2924 rjpeter Added Embeddable.
|
||||
* Feb 07, 2013 1543 djohnson Implement IJaxbableClassesLocator.
|
||||
* Apr 24, 2013 1939 randerso Clean up code and attempt to improve speed.
|
||||
* Added initializeHibernatables flag to disable
|
||||
* processing hibernatables on CAVE
|
||||
* </pre>
|
||||
*
|
||||
* @author njensen
|
||||
|
@ -82,8 +86,6 @@ public class SerializableManager implements IJaxbableClassesLocator {
|
|||
*/
|
||||
@SuppressWarnings(value = { "unchecked" })
|
||||
private synchronized void initialize() {
|
||||
ClassLoader cl = getClass().getClassLoader();
|
||||
long t0 = System.currentTimeMillis(), total = 0;
|
||||
// this is here in case in the future we want to re-initialize the lists
|
||||
// during runtime, i.e. hot deploy of a new plugin
|
||||
hibernatables.clear();
|
||||
|
@ -96,23 +98,37 @@ public class SerializableManager implements IJaxbableClassesLocator {
|
|||
.getResources(
|
||||
"META-INF/services/"
|
||||
+ ISerializableObject.class.getName());
|
||||
|
||||
// doHibernate will be false in CAVE since they are not needed
|
||||
boolean doHibernate = Boolean.getBoolean("initializeHibernatables");
|
||||
|
||||
// In testing 1 thread is slowest, 2 threads cuts the time down
|
||||
// about 50% and 3 threads cuts down another 5% or so, 4 threads
|
||||
// shows no benefit over 2. These results are system specific.
|
||||
int numThreads = 3;
|
||||
Thread[] threads = new Thread[numThreads];
|
||||
for (int i = 1; i < numThreads; i++) {
|
||||
threads[i] = new LoadSerializableClassesThread(urls, clazzSet,
|
||||
hibernatables);
|
||||
LoadSerializableClassesThread[] threads = new LoadSerializableClassesThread[numThreads];
|
||||
for (int i = 0; i < numThreads; i++) {
|
||||
threads[i] = new LoadSerializableClassesThread(urls,
|
||||
doHibernate);
|
||||
threads[i].start();
|
||||
}
|
||||
threads[0] = new LoadSerializableClassesThread(urls, clazzSet,
|
||||
hibernatables);
|
||||
// Run this one on the current thread since its not doing anything
|
||||
// but waiting and this avoids overhead of starting a new thread
|
||||
threads[0].run();
|
||||
for (int i = 1; i < numThreads; i++) {
|
||||
threads[i].join();
|
||||
|
||||
for (LoadSerializableClassesThread thread : threads) {
|
||||
thread.join();
|
||||
clazzSet.addAll(thread.getClazzList());
|
||||
|
||||
if (doHibernate) {
|
||||
for (Entry<String, List<Class<ISerializableObject>>> entry : thread
|
||||
.getHibernatables().entrySet()) {
|
||||
List<Class<ISerializableObject>> list = hibernatables
|
||||
.get(entry.getKey());
|
||||
if (list == null) {
|
||||
list = new ArrayList<Class<ISerializableObject>>();
|
||||
hibernatables.put(entry.getKey(), list);
|
||||
}
|
||||
list.addAll(entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
|
@ -127,6 +143,7 @@ public class SerializableManager implements IJaxbableClassesLocator {
|
|||
|
||||
System.out.println("Total time spent loading classes: "
|
||||
+ (System.currentTimeMillis() - realStartTime) + "ms");
|
||||
|
||||
}
|
||||
|
||||
private static void fail(Class service, String msg, Throwable cause)
|
||||
|
@ -153,24 +170,27 @@ public class SerializableManager implements IJaxbableClassesLocator {
|
|||
return -1;
|
||||
}
|
||||
int ci = ln.indexOf('#');
|
||||
if (ci >= 0)
|
||||
if (ci >= 0) {
|
||||
ln = ln.substring(0, ci);
|
||||
}
|
||||
ln = ln.trim();
|
||||
int n = ln.length();
|
||||
if (n != 0) {
|
||||
if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0))
|
||||
if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0)) {
|
||||
fail(service, u, lc, "Illegal configuration-file syntax");
|
||||
}
|
||||
int cp = ln.codePointAt(0);
|
||||
if (!Character.isJavaIdentifierStart(cp))
|
||||
if (!Character.isJavaIdentifierStart(cp)) {
|
||||
fail(service, u, lc, "Illegal provider-class name: " + ln);
|
||||
}
|
||||
for (int i = Character.charCount(cp); i < n; i += Character
|
||||
.charCount(cp)) {
|
||||
cp = ln.codePointAt(i);
|
||||
if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
|
||||
if (!Character.isJavaIdentifierPart(cp) && (cp != '.')) {
|
||||
fail(service, u, lc, "Illegal provider-class name: " + ln);
|
||||
}
|
||||
}
|
||||
|
||||
if (!names.contains(ln))
|
||||
names.add(ln);
|
||||
}
|
||||
return lc + 1;
|
||||
|
@ -233,30 +253,42 @@ public class SerializableManager implements IJaxbableClassesLocator {
|
|||
|
||||
private final Enumeration<URL> urls;
|
||||
|
||||
private final Set<Class<ISerializableObject>> clazzSet;
|
||||
private final boolean doHibernate;
|
||||
|
||||
private final List<Class<ISerializableObject>> clazzList;
|
||||
|
||||
private final Map<String, List<Class<ISerializableObject>>> hibernatables;
|
||||
|
||||
public LoadSerializableClassesThread(Enumeration<URL> urls,
|
||||
Set<Class<ISerializableObject>> clazzSet,
|
||||
Map<String, List<Class<ISerializableObject>>> hibernatables) {
|
||||
boolean doHibernate) {
|
||||
this.urls = urls;
|
||||
this.clazzSet = clazzSet;
|
||||
this.hibernatables = hibernatables;
|
||||
this.doHibernate = doHibernate;
|
||||
this.clazzList = new ArrayList<Class<ISerializableObject>>(500);
|
||||
this.hibernatables = new HashMap<String, List<Class<ISerializableObject>>>();
|
||||
}
|
||||
|
||||
public List<Class<ISerializableObject>> getClazzList() {
|
||||
return clazzList;
|
||||
}
|
||||
|
||||
public Map<String, List<Class<ISerializableObject>>> getHibernatables() {
|
||||
return hibernatables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ClassLoader cl = getClass().getClassLoader();
|
||||
Set<Class<ISerializableObject>> pluginHibernateSet = new HashSet<Class<ISerializableObject>>();
|
||||
Set<Class<ISerializableObject>> pluginHibernateSet = null;
|
||||
if (doHibernate) {
|
||||
pluginHibernateSet = new HashSet<Class<ISerializableObject>>();
|
||||
}
|
||||
List<String> names = new ArrayList<String>();
|
||||
URL u = getNextUrl();
|
||||
while (u != null) {
|
||||
InputStream in = null;
|
||||
BufferedReader r = null;
|
||||
names.clear();
|
||||
pluginHibernateSet.clear();
|
||||
String path = u.getPath();
|
||||
int endIndex = path.indexOf(".jar");
|
||||
if (endIndex < 0) {
|
||||
|
@ -276,24 +308,31 @@ public class SerializableManager implements IJaxbableClassesLocator {
|
|||
"utf-8"));
|
||||
int lc = 1;
|
||||
while ((lc = parseLine(ISerializableObject.class, u, r,
|
||||
lc, names)) >= 0)
|
||||
lc, names)) >= 0) {
|
||||
;
|
||||
}
|
||||
} catch (IOException x) {
|
||||
fail(ISerializableObject.class,
|
||||
"Error reading configuration file", x);
|
||||
} finally {
|
||||
try {
|
||||
if (r != null)
|
||||
if (r != null) {
|
||||
r.close();
|
||||
if (in != null)
|
||||
}
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
} catch (IOException y) {
|
||||
fail(ISerializableObject.class,
|
||||
"Error closing configuration file", y);
|
||||
}
|
||||
}
|
||||
Iterator<String> iter = names.iterator();
|
||||
|
||||
if (doHibernate) {
|
||||
pluginHibernateSet.clear();
|
||||
}
|
||||
|
||||
Iterator<String> iter = names.iterator();
|
||||
while (iter.hasNext()) {
|
||||
String clazz = iter.next();
|
||||
try {
|
||||
|
@ -303,18 +342,20 @@ public class SerializableManager implements IJaxbableClassesLocator {
|
|||
boolean added = false;
|
||||
if (c.getAnnotation(XmlAccessorType.class) != null
|
||||
|| c.getAnnotation(XmlRegistry.class) != null) {
|
||||
addToClazzSet(c);
|
||||
clazzList.add(c);
|
||||
added = true;
|
||||
}
|
||||
|
||||
if (doHibernate) {
|
||||
if (c.getAnnotation(Entity.class) != null
|
||||
|| c.getAnnotation(Embeddable.class) != null) {
|
||||
pluginHibernateSet.add(c);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
|
||||
long time = (System.currentTimeMillis() - t0);
|
||||
if (!added) {
|
||||
if (doHibernate && !added) {
|
||||
System.out
|
||||
.println("Class: "
|
||||
+ clazz
|
||||
|
@ -329,8 +370,10 @@ public class SerializableManager implements IJaxbableClassesLocator {
|
|||
}
|
||||
}
|
||||
|
||||
if (pluginHibernateSet.size() > 0) {
|
||||
addToHibernatables(pluginFQN, pluginHibernateSet);
|
||||
if (doHibernate && pluginHibernateSet.size() > 0) {
|
||||
hibernatables.put(pluginFQN,
|
||||
new ArrayList<Class<ISerializableObject>>(
|
||||
pluginHibernateSet));
|
||||
}
|
||||
u = getNextUrl();
|
||||
}
|
||||
|
@ -347,20 +390,5 @@ public class SerializableManager implements IJaxbableClassesLocator {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void addToClazzSet(Class<ISerializableObject> clazz) {
|
||||
synchronized (clazzSet) {
|
||||
clazzSet.add(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
private void addToHibernatables(String pluginFQN,
|
||||
Set<Class<ISerializableObject>> pluginHibernateSet) {
|
||||
synchronized (hibernatables) {
|
||||
hibernatables.put(pluginFQN,
|
||||
new ArrayList<Class<ISerializableObject>>(
|
||||
pluginHibernateSet));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue