Issue #2041 Improve exception handling for concurrent python.

Change-Id: I36bf449af216feb45ea3a2464da5096f94d02d47

Former-commit-id: 8ce74c44df [formerly c605b0ce9b7437bfaa803b31c6f4b2f7dc17a6ea]
Former-commit-id: ef10b56e2b
This commit is contained in:
Ben Steffensmeier 2013-06-04 15:57:49 -05:00
parent 9af992ed12
commit 0f70964bc9
8 changed files with 181 additions and 29 deletions

View file

@ -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

View file

@ -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.
*
* </pre>
*
@ -52,7 +56,7 @@ public abstract class AbstractPythonScriptFactory<P extends PythonInterpreter> {
*
* @return
*/
public abstract P createPythonScript();
public abstract P createPythonScript() throws JepException;
public AbstractPythonScriptFactory(String name, int maxThreads) {
this.name = name;

View file

@ -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.
*
* </pre>
*
@ -47,5 +51,5 @@ public interface IPythonExecutor<P extends PythonInterpreter, R extends Object>
* @param script
* @return
*/
public abstract R execute(P script);
public abstract R execute(P script) throws JepException;
}

View file

@ -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.
*
* </pre>
*
@ -69,17 +73,21 @@ public class PythonJob<P extends PythonInterpreter, R extends Object>
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;

View file

@ -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<PythonInterpreter, Object> 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.
*
* </pre>
*
@ -70,13 +74,17 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
private static Map<String, PythonJobCoordinator<? extends PythonInterpreter>> pools = new ConcurrentHashMap<String, PythonJobCoordinator<? extends PythonInterpreter>>();
private PythonJobCoordinator(final AbstractPythonScriptFactory<P> factory) {
execService = Executors.newFixedThreadPool(factory.getMaxThreads(),
new PythonThreadFactory(factory.getName()));
threadLocal = new ThreadLocal<P>() {
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<P extends PythonInterpreter> {
* @param name
* @return
*/
public static PythonJobCoordinator<? extends PythonInterpreter> getInstance(
public static <S extends PythonInterpreter> PythonJobCoordinator<S> getInstance(
String name) {
synchronized (pools) {
if (pools.containsKey(name)) {
return pools.get(name);
return (PythonJobCoordinator<S>) pools.get(name);
} else {
throw new RuntimeException(
"Unable to find instance of PythonJobCoordinator named "
@ -167,10 +175,11 @@ public class PythonJobCoordinator<P extends PythonInterpreter> {
*
* @param name
*/
public void shutdownCoordinator(String name) {
/*
* TODO need to add for future functionality
*/
public void shutdown() {
synchronized (pools) {
pools.remove(this);
}
execService.shutdown();
}
/**

View file

@ -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.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 04, 2013 2041 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class PythonJobFailedException extends RuntimeException {
private static final long serialVersionUID = -6716989387583873621L;
public PythonJobFailedException(JepException cause) {
super(cause.getMessage(), cause);
}
}

View file

@ -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.
*
* </pre>
*
@ -49,7 +53,11 @@ public class PythonThreadFactory implements ThreadFactory {
private final String namePrefix;
public PythonThreadFactory(String name) {
private final ThreadLocal<? extends PythonInterpreter> threadLocal;
public PythonThreadFactory(
ThreadLocal<? extends PythonInterpreter> 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();
}
}
};
}

View file

@ -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.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 04, 2013 2041 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class ScriptCreationException extends RuntimeException {
private static final long serialVersionUID = 6443312895295667778L;
public ScriptCreationException(JepException cause) {
super(cause.getMessage(), cause);
}
}