diff --git a/edexOsgi/com.raytheon.uf.common.python.concurrent/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.common.python.concurrent/META-INF/MANIFEST.MF index 3a77aae644..cc3bff8db9 100644 --- a/edexOsgi/com.raytheon.uf.common.python.concurrent/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.common.python.concurrent/META-INF/MANIFEST.MF @@ -5,5 +5,6 @@ Bundle-SymbolicName: com.raytheon.uf.common.python.concurrent Bundle-Version: 1.0.0.qualifier Bundle-Vendor: RAYTHEON Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Require-Bundle: com.raytheon.uf.common.python;bundle-version="1.12.1174" +Require-Bundle: com.raytheon.uf.common.python;bundle-version="1.12.1174", + org.jep;bundle-version="1.0.0" Export-Package: com.raytheon.uf.common.python.concurrent diff --git a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/AbstractPythonScriptFactory.java b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/AbstractPythonScriptFactory.java index 1b4cebfb3b..fa41a9dbd3 100644 --- a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/AbstractPythonScriptFactory.java +++ b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/AbstractPythonScriptFactory.java @@ -19,6 +19,8 @@ **/ package com.raytheon.uf.common.python.concurrent; +import jep.JepException; + import com.raytheon.uf.common.python.PythonInterpreter; /** @@ -32,7 +34,9 @@ import com.raytheon.uf.common.python.PythonInterpreter; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Feb 5, 2013 mnash Initial creation + * Feb 05, 2013 mnash Initial creation + * Jun 04, 2013 2041 bsteffen Improve exception handling for concurrent + * python. * * * @@ -52,7 +56,7 @@ public abstract class AbstractPythonScriptFactory

{ * * @return */ - public abstract P createPythonScript(); + public abstract P createPythonScript() throws JepException; public AbstractPythonScriptFactory(String name, int maxThreads) { this.name = name; diff --git a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/IPythonExecutor.java b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/IPythonExecutor.java index 91941f5575..befcaeda62 100644 --- a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/IPythonExecutor.java +++ b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/IPythonExecutor.java @@ -19,6 +19,8 @@ **/ package com.raytheon.uf.common.python.concurrent; +import jep.JepException; + import com.raytheon.uf.common.python.PythonInterpreter; /** @@ -31,7 +33,9 @@ import com.raytheon.uf.common.python.PythonInterpreter; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Feb 5, 2013 mnash Initial creation + * Feb 05, 2013 mnash Initial creation + * Jun 04, 2013 2041 bsteffen Improve exception handling for concurrent + * python. * * * @@ -47,5 +51,5 @@ public interface IPythonExecutor

* @param script * @return */ - public abstract R execute(P script); + public abstract R execute(P script) throws JepException; } diff --git a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonJob.java b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonJob.java index b99d7099a6..7719ee6361 100644 --- a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonJob.java +++ b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonJob.java @@ -21,6 +21,8 @@ package com.raytheon.uf.common.python.concurrent; import java.util.concurrent.Callable; +import jep.JepException; + import com.raytheon.uf.common.python.PythonInterpreter; /** @@ -32,7 +34,9 @@ import com.raytheon.uf.common.python.PythonInterpreter; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 31, 2013 mnash Initial creation + * Jan 31, 2013 mnash Initial creation + * Jun 04, 2013 2041 bsteffen Improve exception handling for concurrent + * python. * * * @@ -69,17 +73,21 @@ public class PythonJob

public R call() { P script = threadPython.get(); R result = null; - try { - result = executor.execute(script); - } catch (Throwable t) { - if (listener != null) { - listener.jobFailed(t); + if (listener == null) { + try { + result = executor.execute(script); + } catch (JepException e) { + throw new PythonJobFailedException(e); + } + } else { + try { + result = executor.execute(script); + } catch (Throwable t) { + listener.jobFailed(t); + return null; } - return null; - } - // fire listener to alert the original caller that we are done - if (listener != null) { + // fire listener to alert the original caller that we are done listener.jobFinished(result); } return result; diff --git a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonJobCoordinator.java b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonJobCoordinator.java index b421252f09..c8da58cfd3 100644 --- a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonJobCoordinator.java +++ b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonJobCoordinator.java @@ -26,6 +26,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import jep.JepException; + import com.raytheon.uf.common.python.PythonInterpreter; /** @@ -43,7 +45,7 @@ import com.raytheon.uf.common.python.PythonInterpreter; * IPythonExecutor executor = new CAVEExecutor( * args); * try { - * coordinator.submitJob(executor, listener); + * coordinator.submitAsyncJob(executor, listener); * } catch (Exception e) { * e.printStackTrace(); * } @@ -54,7 +56,9 @@ import com.raytheon.uf.common.python.PythonInterpreter; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 31, 2013 mnash Initial creation + * Jan 31, 2013 mnash Initial creation + * Jun 04, 2013 2041 bsteffen Improve exception handling for concurrent + * python. * * * @@ -70,13 +74,17 @@ public class PythonJobCoordinator

{ private static Map> pools = new ConcurrentHashMap>(); private PythonJobCoordinator(final AbstractPythonScriptFactory

factory) { - execService = Executors.newFixedThreadPool(factory.getMaxThreads(), - new PythonThreadFactory(factory.getName())); threadLocal = new ThreadLocal

() { protected P initialValue() { - return factory.createPythonScript(); + try { + return factory.createPythonScript(); + } catch (JepException e) { + throw new ScriptCreationException(e); + } }; }; + execService = Executors.newFixedThreadPool(factory.getMaxThreads(), + new PythonThreadFactory(threadLocal, factory.getName())); } /** @@ -85,11 +93,11 @@ public class PythonJobCoordinator

{ * @param name * @return */ - public static PythonJobCoordinator getInstance( + public static PythonJobCoordinator getInstance( String name) { synchronized (pools) { if (pools.containsKey(name)) { - return pools.get(name); + return (PythonJobCoordinator) pools.get(name); } else { throw new RuntimeException( "Unable to find instance of PythonJobCoordinator named " @@ -167,10 +175,11 @@ public class PythonJobCoordinator

{ * * @param name */ - public void shutdownCoordinator(String name) { - /* - * TODO need to add for future functionality - */ + public void shutdown() { + synchronized (pools) { + pools.remove(this); + } + execService.shutdown(); } /** diff --git a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonJobFailedException.java b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonJobFailedException.java new file mode 100644 index 0000000000..e66f3935e0 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonJobFailedException.java @@ -0,0 +1,50 @@ +/** + * 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.common.python.concurrent; + +import jep.JepException; + +/** + * This exception is thrown by the PythonJobCoordinator when the + * AbstractPythonScriptFactory fails to execute a Job. + * + *

+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jun 04, 2013 2041       bsteffen    Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ + +public class PythonJobFailedException extends RuntimeException { + + private static final long serialVersionUID = -6716989387583873621L; + + public PythonJobFailedException(JepException cause) { + super(cause.getMessage(), cause); + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonThreadFactory.java b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonThreadFactory.java index 943c7aa577..9fde052ac5 100644 --- a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonThreadFactory.java +++ b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/PythonThreadFactory.java @@ -22,6 +22,8 @@ package com.raytheon.uf.common.python.concurrent; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; +import com.raytheon.uf.common.python.PythonInterpreter; + /** * Creates new threads named according to what python task they were created * for. Based nearly identically off of {@link ThreadFactory} @@ -32,7 +34,9 @@ import java.util.concurrent.atomic.AtomicInteger; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 31, 2013 mnash Initial creation + * Jan 31, 2013 mnash Initial creation + * Jun 04, 2013 2041 bsteffen Improve exception handling for concurrent + * python. * * * @@ -49,7 +53,11 @@ public class PythonThreadFactory implements ThreadFactory { private final String namePrefix; - public PythonThreadFactory(String name) { + private final ThreadLocal threadLocal; + + public PythonThreadFactory( + ThreadLocal threadLocal, String name) { + this.threadLocal = threadLocal; SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread() .getThreadGroup(); @@ -58,7 +66,7 @@ public class PythonThreadFactory implements ThreadFactory { } public Thread newThread(Runnable r) { - Thread t = new Thread(group, r, namePrefix + Thread t = new PythonThread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); if (t.isDaemon()) { t.setDaemon(false); @@ -68,4 +76,22 @@ public class PythonThreadFactory implements ThreadFactory { } return t; } + + private class PythonThread extends Thread { + + public PythonThread(ThreadGroup group, Runnable target, String name, + long stackSize) { + super(group, target, name, stackSize); + } + + @Override + public void run() { + try { + super.run(); + } finally { + threadLocal.get().dispose(); + } + } + + }; } diff --git a/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/ScriptCreationException.java b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/ScriptCreationException.java new file mode 100644 index 0000000000..a5515d5a4a --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.python.concurrent/src/com/raytheon/uf/common/python/concurrent/ScriptCreationException.java @@ -0,0 +1,50 @@ +/** + * 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.common.python.concurrent; + +import jep.JepException; + +/** + * This exception is thrown by the PythonJobCoordinator when a + * AbstractPythonScriptFactory has Jep problems. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jun 04, 2013 2041       bsteffen    Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ + +public class ScriptCreationException extends RuntimeException { + + private static final long serialVersionUID = 6443312895295667778L; + + public ScriptCreationException(JepException cause) { + super(cause.getMessage(), cause); + } + +}