Issue #3500 remove locking on osgi internals, rework gfe client startup

fixed error handling in loadConfig.py
added python to path in GfePyIncludeUtil
moved ProcedureXMLManager to overridable method in AbstractCaveComponent

Change-Id: Ie7dff55657ba216c47f7a56b3506cbed3a3f6ab2

Former-commit-id: b0ea9a2a04cf043fe1a9e4dbf4d4498b0d3f4684
This commit is contained in:
Brian Clements 2014-08-21 15:48:30 -05:00
parent 62236ee92a
commit d62db22874
9 changed files with 39 additions and 286 deletions

View file

@ -1,83 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.core.reflect;
import org.eclipse.osgi.framework.internal.core.AbstractBundle;
import org.eclipse.osgi.framework.internal.core.BundleHost;
import org.eclipse.osgi.internal.loader.BundleLoader;
import org.eclipse.osgi.internal.loader.BundleLoaderProxy;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
/**
* Utility class to get the BundleLoader object associated with a Bundle, to
* potentially synchronize against that object.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 13, 2014 3500 bclement Initial creation
*
* </pre>
*
* @author bclement
* @version 1.0
* @see BundleSynchronizer
*/
public class BundleLoaderGetter {
private BundleLoaderGetter() {
}
/**
* Attempts to retrieve the BundleLoader associated with the bundle. Returns
* the BundleLoader or null if it could not be retrieved.
*
* @param bundle
* the bundle to retrieve the associated BundleLoader for
* @return the BundleLoader or null
*/
@SuppressWarnings("restriction")
protected static BundleLoader getBundleLoader(Bundle bundle) {
BundleLoader rval = null;
if (bundle instanceof AbstractBundle) {
BundleDescription bundleDesc = ((AbstractBundle) bundle)
.getBundleDescription();
if (bundleDesc != null) {
Object o = bundleDesc.getUserObject();
if (!(o instanceof BundleLoaderProxy)) {
if (o instanceof BundleReference)
o = ((BundleReference) o).getBundle();
if (o instanceof BundleHost)
o = ((BundleHost) o).getLoaderProxy();
}
if (o instanceof BundleLoaderProxy) {
rval = ((BundleLoaderProxy) o).getBundleLoader();
}
}
}
return rval;
}
}

View file

@ -49,6 +49,7 @@ import org.reflections.util.ConfigurationBuilder;
* Jan 22, 2014 2062 bsteffen Handle bundles with no wiring.
* Apr 16, 2014 3018 njensen Synchronize against BundleRepository
* Aug 13, 2014 3500 bclement uses BundleSynchronizer
* Aug 22, 2014 3500 bclement removed sync on OSGi internals
*
* </pre>
*
@ -61,17 +62,11 @@ public class BundleReflections {
private final Reflections reflections;
public BundleReflections(Bundle bundle, Scanner scanner) throws IOException {
final ConfigurationBuilder cb = new ConfigurationBuilder();
final BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
ConfigurationBuilder cb = new ConfigurationBuilder();
BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
if (bundleWiring != null) {
BundleSynchronizer.runSynchedWithBundle(new Runnable() {
@Override
public void run() {
cb.addClassLoader(bundleWiring.getClassLoader());
}
}, bundle);
cb.addClassLoader(bundleWiring.getClassLoader());
cb.addUrls(FileLocator.getBundleFile(bundle).toURI().toURL());
cb.setScanners(scanner);

View file

@ -1,83 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.core.reflect;
import java.lang.reflect.Field;
import org.eclipse.osgi.framework.internal.core.AbstractBundle;
import org.eclipse.osgi.framework.internal.core.BundleRepository;
import org.eclipse.osgi.framework.internal.core.Framework;
import org.osgi.framework.Bundle;
/**
* Utility class to get the BundleRepository object associated with a Bundle, to
* potentially synchronize against that object.
*
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Apr 17, 2014 njensen Initial creation
* Aug 13, 2014 3500 bclement moved documentation over to BundleSynchronizer
*
* </pre>
*
* @author njensen
* @version 1.0
* @see BundleSynchronizer
*/
public class BundleRepositoryGetter {
private BundleRepositoryGetter() {
}
/**
* Attempts to retrieve the BundleRepository associated with the bundle's
* framework. Returns the BundleRepository or null if it could not be
* retrieved.
*
* @param bundle
* the bundle to retrieve the associated BundleRepository for
* @return the BundleRepository or null
*/
@SuppressWarnings("restriction")
protected static BundleRepository getFrameworkBundleRepository(Bundle bundle) {
BundleRepository bundleRepo = null;
if (bundle instanceof AbstractBundle) {
try {
AbstractBundle ab = (AbstractBundle) bundle;
Field bundleRepoField = Framework.getField(Framework.class,
BundleRepository.class, true);
bundleRepo = (BundleRepository) bundleRepoField.get(ab
.getFramework());
} catch (Throwable t) {
// intentionally log to console and proceed anyway
t.printStackTrace();
}
}
return bundleRepo;
}
}

View file

@ -1,96 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.core.reflect;
import org.eclipse.osgi.framework.internal.core.BundleRepository;
import org.eclipse.osgi.internal.loader.BundleLoader;
import org.osgi.framework.Bundle;
/**
* If a call to BundleWiring.getClassLoader() is invoked on a thread other than
* main/UI thread, then there is a possible deadlock if the application shuts
* down while the BundleWiring.getClassLoader() call is still going. The
* BundleLoader and BundleRepository of the Framework are the primary resources
* that are in contention in this deadlock scenario, due to the BundleRepository
* being used as a synchronization lock both deep in
* bundleWiring.getClassloader() and in Framework shutdown code. The other
* resource used as a synchronization lock and causing the deadlock is the
* BundleLoader associated with the bundle. When BundleLoader.findClass() is
* called, it results in a lock on the BundleLoader and then a lock on the
* BundleRepository. This happens when the DefaultClassLoader loads a class.
*
* Therefore to avoid this deadlock, if you are going to call
* BundleWiring.getClassLoader() you should attempt synchronize against the
* BundleLoader and the BundleRepository. This will ensure the call to
* getClassLoader() can finish and then release synchronization locks of both
* the BundleRepository and BundleLoader.
*
* If we fail to get the BundleLoader or BundleRepository, then you should
* proceed onwards anyway because the odds of the application shutting down at
* the same time as the call to BundleWiring.getClassLoader() is still running
* is low. Even if that occurs, the odds are further reduced that the two
* threads will synchronize against the BundleLoader and the BundleRepository at
* the same time and deadlock.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 13, 2014 3500 bclement Initial creation
*
* </pre>
*
* @author bclement
* @version 1.0
*/
public class BundleSynchronizer {
private BundleSynchronizer() {
}
/**
* Attempts to synchronize with the bundle's BundleLoader and
* BundleRepository objects before running the runner. If either the
* BundleLoader or the BundleRepository are unable to be retrieved from the
* bundle, the runner is ran anyway since the likelihood of a deadlock is
* relatively small.
*
* @param runner
* @param bundle
* @see BundleLoaderGetter#getBundleLoader(Bundle)
* @see BundleRepositoryGetter#getFrameworkBundleRepository(Bundle)
*/
protected static void runSynchedWithBundle(Runnable runner, Bundle bundle) {
BundleRepository repo = BundleRepositoryGetter
.getFrameworkBundleRepository(bundle);
BundleLoader loader = BundleLoaderGetter.getBundleLoader(bundle);
if (repo != null && loader != null) {
synchronized (loader) {
synchronized (repo) {
runner.run();
}
}
} else {
runner.run();
}
}
}

View file

@ -58,6 +58,7 @@ import com.raytheon.uf.viz.core.Activator;
* Feb 03, 2013 2764 bsteffen Use OSGi API to get dependencies.
* Apr 17, 2014 3018 njensen Synchronize against BundleRepository
* Aug 13, 2014 3500 bclement uses BundleSynchronizer
* Aug 22, 2014 3500 bclement removed sync on OSGi internals
*
* </pre>
*
@ -265,20 +266,12 @@ public class SubClassLocator implements ISubClassLocator {
*/
private Set<Class<?>> loadClassesFromCache(Bundle bundle,
Collection<String> classNames) {
final BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
if (bundleWiring == null) {
return Collections.emptySet();
}
final ClassLoader[] loaderHolder = new ClassLoader[1];
BundleSynchronizer.runSynchedWithBundle(new Runnable() {
@Override
public void run() {
loaderHolder[0] = bundleWiring.getClassLoader();
}
}, bundle);
ClassLoader loader = loaderHolder[0];
ClassLoader loader = bundleWiring.getClassLoader();
if (loader == null) {
return Collections.emptySet();
}

View file

@ -27,11 +27,13 @@
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# 12/11/09 njensen Initial Creation.
# 08/21/14 3500 bclement fixed loadPreferences except block
#
#
#
import types
import LogStream
from java.util import HashMap, ArrayList
from java.lang import String, Float, Integer, Boolean
@ -48,8 +50,7 @@ def loadPreferences(config):
Activator.getDefault().setPreferenceStore(prefs)
return prefs
except Exception, e:
LogStream.logProblem("Unknown or improper config file: ",
configFile, " for user: ", userName)
LogStream.logProblem("Unknown or improper config file: ", config)
raise Exception, e

View file

@ -62,6 +62,7 @@ import com.raytheon.viz.ui.personalities.awips.AbstractCAVEComponent;
* which was adding an empty string into the
* python path causing python to look in user's
* current default directory for modules.
* Aug 22, 2014 3500 bclement override postStartupActions()
*
* </pre>
*
@ -196,4 +197,17 @@ public class GfeClient extends AbstractCAVEComponent {
return new HashSet<String>(Arrays.asList("-site", "-server", "-mode",
"-time"));
}
/* (non-Javadoc)
* @see com.raytheon.viz.ui.personalities.awips.AbstractCAVEComponent#postStartupActions()
*/
@Override
protected void postStartupActions() {
/*
* GFE client does not require the default post startup actions (ie
* ProcedureXMLManager being initialized)
*/
}
}

View file

@ -99,6 +99,7 @@ import com.raytheon.viz.core.units.UnitRegistrar;
* startup
* Dec 10, 2013 2602 bsteffen Start loading ProcedureXmlManager in
* startComponent.
* Aug 22, 2014 3500 bclement moved ProcedureXMLManager initialization to postStartupActions()
*
* </pre>
*
@ -259,7 +260,7 @@ public abstract class AbstractCAVEComponent implements IStandaloneComponent {
startInternal(componentName);
}
ProcedureXmlManager.inititializeAsync();
postStartupActions();
if (workbenchAdvisor != null) {
returnCode = PlatformUI.createAndRunWorkbench(display,
@ -303,6 +304,14 @@ public abstract class AbstractCAVEComponent implements IStandaloneComponent {
return IApplication.EXIT_OK;
}
/**
* perform any additional initialization after the component has been
* started
*/
protected void postStartupActions() {
ProcedureXmlManager.inititializeAsync();
}
/**
* Get the workbench advisor for the application
*

View file

@ -39,6 +39,7 @@ import com.raytheon.uf.common.util.FileUtil;
* Feb 27, 2013 #1447 dgilling Re-factor based on PythonPathIncludeUtil.
* Mar 11, 2013 #1759 dgilling Add method getGfeConfigLF().
* Sep 16, 2013 #1759 dgilling Move tests and autotests to GfeCavePyIncludeUtil.
* Aug 22, 2014 3500 bclement added python path in getConfigIncludePath()
* </pre>
*
* @author njensen
@ -287,6 +288,7 @@ public class GfePyIncludeUtil extends PythonIncludePathUtil {
}
public static String getConfigIncludePath(boolean includeUser) {
String pythonPath = GfePyIncludeUtil.getCommonPythonIncludePath();
String baseDir = getPath(PATH_MANAGER.getContext(
LocalizationType.CAVE_STATIC, LocalizationLevel.BASE), CONFIG);
String siteDir = getPath(PATH_MANAGER.getContext(
@ -295,9 +297,10 @@ public class GfePyIncludeUtil extends PythonIncludePathUtil {
String userDir = getPath(PATH_MANAGER.getContext(
LocalizationType.CAVE_STATIC, LocalizationLevel.USER),
CONFIG);
return PyUtil.buildJepIncludePath(userDir, siteDir, baseDir);
return PyUtil.buildJepIncludePath(userDir, siteDir, baseDir,
pythonPath);
} else {
return PyUtil.buildJepIncludePath(siteDir, baseDir);
return PyUtil.buildJepIncludePath(siteDir, baseDir, pythonPath);
}
}