Merge "Omaha #3668 Give grid a custom job pool." into omaha_14.4.1
Former-commit-id:5e22943a26
[formerly b98016900319d31c23be96640aa97f7b2efcee5b] Former-commit-id:e83c1f20bb
This commit is contained in:
commit
c004468689
2 changed files with 165 additions and 48 deletions
|
@ -0,0 +1,128 @@
|
||||||
|
/**
|
||||||
|
* 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.viz.grid.rsc.general;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pool of {@link Job} that executes {@link GridDataRequestRunner}s with a
|
||||||
|
* scheduling pattern that is ideal for smooth user interaction. This object
|
||||||
|
* expects {@link #schedule(GridDataRequestRunner)} to be called each time data
|
||||||
|
* is needed that is not yet available(primarily when the frame is displayed).
|
||||||
|
* Calling {@link #schedule(GridDataRequestRunner)} causes the runner to be
|
||||||
|
* bumped to the front of the queue so that data will be ready as soon as
|
||||||
|
* possible. This causes runners that are not being displayed to frequently get
|
||||||
|
* bumped to the back of the queue, which is desired since the user does not
|
||||||
|
* need that data yet.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------- -------- ----------- --------------------------
|
||||||
|
* Oct 29, 2014 3668 bsteffen Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author bsteffen
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public class GridDataRequestJobPool {
|
||||||
|
|
||||||
|
private static final int POOL_SIZE = Integer.getInteger(
|
||||||
|
"grid.request.pool.size", 10);
|
||||||
|
|
||||||
|
private static final GridDataRequestJobPool instance = new GridDataRequestJobPool();
|
||||||
|
|
||||||
|
public static void schedule(GridDataRequestRunner runner) {
|
||||||
|
instance.scheduleRunner(runner);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected LinkedBlockingQueue<Job> jobQueue = new LinkedBlockingQueue<Job>();
|
||||||
|
|
||||||
|
protected List<GridDataRequestRunner> runners = new LinkedList<>();
|
||||||
|
|
||||||
|
private GridDataRequestJobPool(){
|
||||||
|
for (int i = 0; i <POOL_SIZE; i++) {
|
||||||
|
jobQueue.add(new GridDataRequestJob());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void scheduleRunner(GridDataRequestRunner runner) {
|
||||||
|
synchronized (runners) {
|
||||||
|
if (runners.isEmpty() || !(runners.get(0) == runner)) {
|
||||||
|
runners.remove(runner);
|
||||||
|
runners.add(0, runner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Job job = jobQueue.poll();
|
||||||
|
if (job != null) {
|
||||||
|
job.schedule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void reschedule(GridDataRequestRunner runner){
|
||||||
|
synchronized (runners) {
|
||||||
|
if(!runners.contains(runner)){
|
||||||
|
runners.add(runner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected GridDataRequestRunner getNextRunner(){
|
||||||
|
synchronized (runners) {
|
||||||
|
if(runners.isEmpty()){
|
||||||
|
return null;
|
||||||
|
}else{
|
||||||
|
return runners.remove(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class GridDataRequestJob extends Job{
|
||||||
|
|
||||||
|
public GridDataRequestJob() {
|
||||||
|
super("Requesting Grid Data");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
|
jobQueue.offer(this);
|
||||||
|
GridDataRequestRunner runner = getNextRunner();
|
||||||
|
while(runner != null){
|
||||||
|
if(runner.processOneRequest()){
|
||||||
|
reschedule(runner);
|
||||||
|
}
|
||||||
|
runner = getNextRunner();
|
||||||
|
}
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -29,11 +29,10 @@ import com.raytheon.uf.common.status.UFStatus;
|
||||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||||
import com.raytheon.uf.common.time.DataTime;
|
import com.raytheon.uf.common.time.DataTime;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
import com.raytheon.uf.viz.core.jobs.JobPool;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Manages asynchronously requesting data for GridResources.
|
* Manages asynchronously requesting data for {@link AbstractGridResource}s.
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
*
|
*
|
||||||
|
@ -47,21 +46,15 @@ import com.raytheon.uf.viz.core.jobs.JobPool;
|
||||||
* Jun 24, 2013 2140 randerso Moved safe name code into AbstractVizResource
|
* Jun 24, 2013 2140 randerso Moved safe name code into AbstractVizResource
|
||||||
* Oct 07, 2014 3668 bclement uses executor instead of eclipse job
|
* Oct 07, 2014 3668 bclement uses executor instead of eclipse job
|
||||||
* renamed to GridDataRequestRunner
|
* renamed to GridDataRequestRunner
|
||||||
* Oct 23, 2014 3668 bsteffen replace executor with job pool so user
|
* Oct 29, 2014 3668 bsteffen replace executor with custom job pool.
|
||||||
* sees progress.
|
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author bsteffen
|
* @author bsteffen
|
||||||
* @version 1.0
|
* @version 1.0
|
||||||
|
* @see GridDataRequestJobPool
|
||||||
*/
|
*/
|
||||||
class GridDataRequestRunner implements Runnable {
|
class GridDataRequestRunner {
|
||||||
|
|
||||||
private static final int POOL_SIZE = Integer.getInteger(
|
|
||||||
"grid.request.pool.size", 10);
|
|
||||||
|
|
||||||
private static final JobPool jobPool = new JobPool("Requesting Grid Data",
|
|
||||||
POOL_SIZE);
|
|
||||||
|
|
||||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||||
.getHandler(GridDataRequestRunner.class);
|
.getHandler(GridDataRequestRunner.class);
|
||||||
|
@ -80,6 +73,8 @@ class GridDataRequestRunner implements Runnable {
|
||||||
// been notified.)
|
// been notified.)
|
||||||
public boolean exceptionHandled = false;
|
public boolean exceptionHandled = false;
|
||||||
|
|
||||||
|
public boolean isRunning = false;
|
||||||
|
|
||||||
public GridDataRequest(DataTime time, List<PluginDataObject> pdos) {
|
public GridDataRequest(DataTime time, List<PluginDataObject> pdos) {
|
||||||
this.time = time;
|
this.time = time;
|
||||||
if (pdos == null) {
|
if (pdos == null) {
|
||||||
|
@ -91,21 +86,12 @@ class GridDataRequestRunner implements Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldRequest() {
|
public boolean shouldRequest() {
|
||||||
return (gridData == null) && (exception == null);
|
return (gridData == null) && (exception == null)
|
||||||
|
&& (isRunning == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is not designed to handle multiple requests concurrently. To
|
|
||||||
* ensure this doesn't happen we track when it is scheduled and do not
|
|
||||||
* schedule again. It would have been simpler to synchronize the run method
|
|
||||||
* but that ties up threads from the pool that other resources should use.
|
|
||||||
* So we don't leave dangling requests this should only be modified while
|
|
||||||
* synchronized on requests.
|
|
||||||
*/
|
|
||||||
private volatile boolean scheduled = false;
|
|
||||||
|
|
||||||
private AbstractGridResource<?> resource;
|
private AbstractGridResource<?> resource;
|
||||||
|
|
||||||
private List<GridDataRequest> requests = new ArrayList<GridDataRequest>();
|
private List<GridDataRequest> requests = new ArrayList<GridDataRequest>();
|
||||||
|
@ -114,42 +100,49 @@ class GridDataRequestRunner implements Runnable {
|
||||||
this.resource = resource;
|
this.resource = resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void run() {
|
* Attempt to process a request if there are any that need to be processed
|
||||||
for (GridDataRequest request = getNext(); request != null; request = getNext()) {
|
*
|
||||||
try {
|
* @return true if a request was processed or false if no requests need to
|
||||||
request.gridData = resource.getData(request.time, request.pdos);
|
* be processed.
|
||||||
if (request.gridData == null) {
|
*/
|
||||||
/*
|
public boolean processOneRequest() {
|
||||||
* need to remove unfulfillable requests to avoid infinite
|
GridDataRequest request = getNext();
|
||||||
* loop.
|
if (request == null) {
|
||||||
*/
|
return false;
|
||||||
synchronized (requests) {
|
}
|
||||||
requests.remove(request);
|
try {
|
||||||
}
|
request.gridData = resource.getData(request.time, request.pdos);
|
||||||
} else {
|
if (request.gridData == null) {
|
||||||
resource.issueRefresh();
|
/* need to remove unfulfillable requests to avoid infinite loop. */
|
||||||
|
synchronized (requests) {
|
||||||
|
requests.remove(request);
|
||||||
}
|
}
|
||||||
} catch (VizException e) {
|
} else {
|
||||||
request.exception = e;
|
|
||||||
resource.issueRefresh();
|
resource.issueRefresh();
|
||||||
}
|
}
|
||||||
|
} catch (VizException e) {
|
||||||
|
request.exception = e;
|
||||||
|
resource.issueRefresh();
|
||||||
|
} finally {
|
||||||
|
request.isRunning = false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the next request that should be sent
|
* Get the next request that should be processed
|
||||||
*
|
*
|
||||||
* @return null if no request should be sent
|
* @return null if no request should be processed
|
||||||
*/
|
*/
|
||||||
protected GridDataRequest getNext() {
|
protected GridDataRequest getNext() {
|
||||||
synchronized (requests) {
|
synchronized (requests) {
|
||||||
for (GridDataRequest request : requests) {
|
for (GridDataRequest request : requests) {
|
||||||
if (request.shouldRequest()) {
|
if (request.shouldRequest()) {
|
||||||
|
request.isRunning = true;
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scheduled = false;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -181,9 +174,8 @@ class GridDataRequestRunner implements Runnable {
|
||||||
if ((request.exception != null) && !request.exceptionHandled) {
|
if ((request.exception != null) && !request.exceptionHandled) {
|
||||||
handleExceptions();
|
handleExceptions();
|
||||||
}
|
}
|
||||||
if (!scheduled && request.shouldRequest()) {
|
if (request.shouldRequest()) {
|
||||||
scheduled = true;
|
GridDataRequestJobPool.schedule(this);
|
||||||
jobPool.schedule(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -268,9 +260,6 @@ class GridDataRequestRunner implements Runnable {
|
||||||
public void stopAndClear() {
|
public void stopAndClear() {
|
||||||
synchronized (requests) {
|
synchronized (requests) {
|
||||||
requests.clear();
|
requests.clear();
|
||||||
if (jobPool.cancel(this)) {
|
|
||||||
scheduled = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue