Issue #1496 Changes to allow multiple query jobs. (Reduced long queries from 30 to 5 seconds.)
Changes to use fewer synchronized blocks. Change-Id: I854a5ff9d34be63e46d26f3d78953bc3b8cc796a Former-commit-id:fbcc5fb9a0
[formerly97b6a1a810
[formerly7a7f86bfe6
] [formerlyfbcc5fb9a0
[formerly 7adb742310b662763315fc721d6d6f326b8ba160]]] Former-commit-id:97b6a1a810
[formerly7a7f86bfe6
] Former-commit-id:97b6a1a810
Former-commit-id:2db9c6d959
This commit is contained in:
parent
f40885a2af
commit
658ac1f354
2 changed files with 233 additions and 61 deletions
|
@ -23,8 +23,10 @@ package com.raytheon.viz.texteditor.dialogs;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
@ -97,8 +99,9 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
|
||||||
* functionality.
|
* functionality.
|
||||||
* 06/28/2010 3283 cjeanbap Implement window resize.
|
* 06/28/2010 3283 cjeanbap Implement window resize.
|
||||||
* 25Sep2012 1196 lvenable Dialog refactor to prevent blocking.
|
* 25Sep2012 1196 lvenable Dialog refactor to prevent blocking.
|
||||||
* 22Jan2013 1496 rferrel Changes to designator hours query
|
* 29Jan2013 1496 rferrel Changes to designator hours query
|
||||||
* off the UI thread.
|
* off the UI thread.
|
||||||
|
* Changes to have multiple query jobs.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author lvenable
|
* @author lvenable
|
||||||
|
@ -147,11 +150,6 @@ public class AfosBrowserDlg extends CaveSWTDialog implements
|
||||||
*/
|
*/
|
||||||
private long newestTime = -1L;
|
private long newestTime = -1L;
|
||||||
|
|
||||||
/**
|
|
||||||
* Index of designator who time is being updated.
|
|
||||||
*/
|
|
||||||
private int dtlIndex;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* custom mouse handling so we can do the required vertical bar
|
* custom mouse handling so we can do the required vertical bar
|
||||||
* non-scrolling.
|
* non-scrolling.
|
||||||
|
@ -705,7 +703,6 @@ public class AfosBrowserDlg extends CaveSWTDialog implements
|
||||||
// Keep this list the same size as disignatorList.
|
// Keep this list the same size as disignatorList.
|
||||||
designatorTimeList.add("");
|
designatorTimeList.add("");
|
||||||
updateSelectionList(designatorTimeList);
|
updateSelectionList(designatorTimeList);
|
||||||
dtlIndex = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -723,6 +720,8 @@ public class AfosBrowserDlg extends CaveSWTDialog implements
|
||||||
}
|
}
|
||||||
designatorTimeList.setItem(0, value);
|
designatorTimeList.setItem(0, value);
|
||||||
|
|
||||||
|
checkLoadBtn();
|
||||||
|
|
||||||
loadingTimes = false;
|
loadingTimes = false;
|
||||||
if (!loadingProduct) {
|
if (!loadingProduct) {
|
||||||
getShell().setCursor(null);
|
getShell().setCursor(null);
|
||||||
|
@ -730,16 +729,17 @@ public class AfosBrowserDlg extends CaveSWTDialog implements
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the the next chuck of times retrieved. Assume these values should
|
* Update the the chuck of times retrieved. The values should be inserted
|
||||||
* be inserted staring at dtlIndex+1.
|
* starting at startIndex.
|
||||||
*
|
*
|
||||||
* @param queryResponse
|
* @param queryResponse
|
||||||
|
* @param startIndex
|
||||||
*/
|
*/
|
||||||
private void updateAfterQuery(Message queryResponse) {
|
private void updateAfterQuery(Message queryResponse, int startIndex) {
|
||||||
|
|
||||||
Property[] properties = queryResponse.getHeader().getProperties();
|
Property[] properties = queryResponse.getHeader().getProperties();
|
||||||
|
|
||||||
ArrayList<Long> times = new ArrayList<Long>();
|
ArrayList<Long> times = new ArrayList<Long>();
|
||||||
|
|
||||||
// We use this time to populate the "000" designator entry.
|
// We use this time to populate the "000" designator entry.
|
||||||
if (properties != null) {
|
if (properties != null) {
|
||||||
for (Property p : properties) {
|
for (Property p : properties) {
|
||||||
|
@ -755,10 +755,9 @@ public class AfosBrowserDlg extends CaveSWTDialog implements
|
||||||
|
|
||||||
String value = null;
|
String value = null;
|
||||||
try {
|
try {
|
||||||
int startIndex = dtlIndex;
|
int index = startIndex;
|
||||||
int selectIndex = designatorList.getSelectionIndex();
|
int selectIndex = designatorList.getSelectionIndex();
|
||||||
for (Long time : times) {
|
for (Long time : times) {
|
||||||
++dtlIndex;
|
|
||||||
if (time > 0) {
|
if (time > 0) {
|
||||||
Calendar c = TimeTools.newCalendar(time);
|
Calendar c = TimeTools.newCalendar(time);
|
||||||
value = String.format(TIME_FORMAT, c);
|
value = String.format(TIME_FORMAT, c);
|
||||||
|
@ -767,11 +766,12 @@ public class AfosBrowserDlg extends CaveSWTDialog implements
|
||||||
} else {
|
} else {
|
||||||
value = DATA_NONE;
|
value = DATA_NONE;
|
||||||
}
|
}
|
||||||
designatorTimeList.setItem(dtlIndex, value);
|
designatorTimeList.setItem(index, value);
|
||||||
|
++index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Selected designator time updated check status of load buttons.
|
// Selected designator time updated check status of load buttons.
|
||||||
if (selectIndex > startIndex && selectIndex <= dtlIndex) {
|
if (selectIndex > startIndex && selectIndex <= index) {
|
||||||
checkLoadBtn();
|
checkLoadBtn();
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
|
@ -1445,18 +1445,132 @@ public class AfosBrowserDlg extends CaveSWTDialog implements
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Job to query for designator times.
|
* Job to query for designator times.
|
||||||
*/
|
*/
|
||||||
private class QueryRequests extends Job {
|
private class QueryRequests extends Job {
|
||||||
|
/*
|
||||||
|
* This contains the query command for getting a some of the Designator
|
||||||
|
* times for the query and where in the designator time list the times
|
||||||
|
* belong.
|
||||||
|
*/
|
||||||
|
private class TimesRequest {
|
||||||
|
/**
|
||||||
|
* Clone copy of the query passed to the constructor.
|
||||||
|
*/
|
||||||
|
protected TextDBQuery query;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index in the Designator Time list where to start placing the
|
||||||
|
* results.
|
||||||
|
*/
|
||||||
|
protected int startIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query results.
|
||||||
|
*/
|
||||||
|
protected Message queryResults;
|
||||||
|
|
||||||
|
public TimesRequest(TextDBQuery query, int startIndex) {
|
||||||
|
this.query = query.clone();
|
||||||
|
this.startIndex = startIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of pending Times Requests needed to populate the designator
|
||||||
|
* times.
|
||||||
|
*/
|
||||||
|
final LinkedBlockingQueue<TimesRequest> timesRequestQueue = new LinkedBlockingQueue<AfosBrowserDlg.QueryRequests.TimesRequest>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of completed Times Requests that need to be processed to update
|
||||||
|
* the designator's hours.
|
||||||
|
*/
|
||||||
|
final LinkedBlockingQueue<TimesRequest> timesResultQueue = new LinkedBlockingQueue<AfosBrowserDlg.QueryRequests.TimesRequest>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A job for taking a pending TimesRequest, perform the query and then
|
||||||
|
* place it on the result list.
|
||||||
|
*/
|
||||||
|
private class QueryJob extends Job {
|
||||||
|
/**
|
||||||
|
* Flag to indicate active request has been canceled.
|
||||||
|
*/
|
||||||
|
private boolean canceled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
public QueryJob(String name) {
|
||||||
|
super("QueryJob");
|
||||||
|
setSystem(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime
|
||||||
|
* .IProgressMonitor)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
|
while (true) {
|
||||||
|
TimesRequest timesRequest = timesRequestQueue.poll();
|
||||||
|
if (timesRequest == null || canceled) {
|
||||||
|
queryJobList.remove(this);
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
timesRequest.queryResults = timesRequest.query
|
||||||
|
.executeQuery();
|
||||||
|
timesRequest.query = null;
|
||||||
|
|
||||||
|
if (!canceled) {
|
||||||
|
timesResultQueue.add(timesRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of product ids to place in a Times Request.
|
||||||
|
*/
|
||||||
private final int MAX_PRODUCTS_PER_QUERY = 25;
|
private final int MAX_PRODUCTS_PER_QUERY = 25;
|
||||||
|
|
||||||
private TextDBQuery request = null;
|
/**
|
||||||
|
* Maximum number of jobs to service the Times Request.
|
||||||
|
*/
|
||||||
|
private final int MAX_QUERIES = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Active Query Jobs. The list must be synchronized since it is modified
|
||||||
|
* in multiple threads outside of any synchronized block.
|
||||||
|
*/
|
||||||
|
private final java.util.List<QueryJob> queryJobList = Collections
|
||||||
|
.synchronizedList(new ArrayList<AfosBrowserDlg.QueryRequests.QueryJob>(
|
||||||
|
MAX_QUERIES));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The pending request for getting designator hours.
|
||||||
|
*/
|
||||||
|
private TextDBQuery pendingRequest = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag to indicate the current request is canceled.
|
||||||
|
*/
|
||||||
private boolean canceled = false;
|
private boolean canceled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The complete list of productIds to run in the request query.
|
||||||
|
*/
|
||||||
private java.util.List<String> productIds;
|
private java.util.List<String> productIds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
public QueryRequests() {
|
public QueryRequests() {
|
||||||
super("QueryRequests");
|
super("QueryRequests");
|
||||||
setSystem(true);
|
setSystem(true);
|
||||||
|
@ -1471,6 +1585,7 @@ public class AfosBrowserDlg extends CaveSWTDialog implements
|
||||||
@Override
|
@Override
|
||||||
protected IStatus run(IProgressMonitor monitor) {
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
java.util.List<String> prodIds = null;
|
java.util.List<String> prodIds = null;
|
||||||
|
TextDBQuery request = null;
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (monitor.isCanceled()) {
|
if (monitor.isCanceled()) {
|
||||||
|
@ -1478,6 +1593,8 @@ public class AfosBrowserDlg extends CaveSWTDialog implements
|
||||||
} else {
|
} else {
|
||||||
prodIds = productIds;
|
prodIds = productIds;
|
||||||
productIds = null;
|
productIds = null;
|
||||||
|
request = pendingRequest;
|
||||||
|
pendingRequest = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1490,52 +1607,88 @@ public class AfosBrowserDlg extends CaveSWTDialog implements
|
||||||
});
|
});
|
||||||
|
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
int startIndex = 1;
|
||||||
|
|
||||||
|
// Queue up requests for getting Designator hours and start jobs
|
||||||
|
// to process them.
|
||||||
Iterator<String> iterator = prodIds.iterator();
|
Iterator<String> iterator = prodIds.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
String productId = iterator.next();
|
String productId = iterator.next();
|
||||||
|
|
||||||
if (canceled) {
|
if (canceled) {
|
||||||
synchronized (this) {
|
break;
|
||||||
canceled = false;
|
|
||||||
this.notify();
|
|
||||||
return Status.OK_STATUS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
request.addProductId(productId);
|
request.addProductId(productId);
|
||||||
++cnt;
|
++cnt;
|
||||||
|
|
||||||
if (cnt >= MAX_PRODUCTS_PER_QUERY || !iterator.hasNext()) {
|
if (cnt >= MAX_PRODUCTS_PER_QUERY || !iterator.hasNext()) {
|
||||||
final Message queryResponse = request.executeQuery();
|
TimesRequest timesRequest = new TimesRequest(request,
|
||||||
if (!canceled) {
|
startIndex);
|
||||||
VizApp.runAsync(new Runnable() {
|
timesRequestQueue.add(timesRequest);
|
||||||
|
if (queryJobList.size() < MAX_QUERIES) {
|
||||||
@Override
|
QueryJob queryJob = new QueryJob("");
|
||||||
public void run() {
|
queryJobList.add(queryJob);
|
||||||
if (!canceled) {
|
queryJob.schedule();
|
||||||
updateAfterQuery(queryResponse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
request.clearProductIds();
|
request.clearProductIds();
|
||||||
|
startIndex += cnt;
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (this) {
|
// Wait for all query jobs to finish and update results.
|
||||||
request = null;
|
boolean finished = false;
|
||||||
|
while (!(finished || canceled)) {
|
||||||
|
if (!timesResultQueue.isEmpty()) {
|
||||||
|
final java.util.List<TimesRequest> resultList = new ArrayList<AfosBrowserDlg.QueryRequests.TimesRequest>();
|
||||||
|
timesResultQueue.drainTo(resultList);
|
||||||
|
|
||||||
|
VizApp.runAsync(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (TimesRequest result : resultList) {
|
||||||
|
if (canceled) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
updateAfterQuery(result.queryResults,
|
||||||
|
result.startIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryJobList.size() > 0) {
|
||||||
|
synchronized (this) {
|
||||||
|
try {
|
||||||
|
wait(200L);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
statusHandler.handle(Priority.PROBLEM,
|
||||||
|
e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
finished = timesResultQueue.isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VizApp.runAsync(new Runnable() {
|
if (!canceled) {
|
||||||
|
VizApp.runAsync(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
finishDesignatorTimeList();
|
finishDesignatorTimeList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure everything is in proper state for the next time job is
|
||||||
|
// schedule.
|
||||||
|
timesRequestQueue.clear();
|
||||||
|
timesResultQueue.clear();
|
||||||
|
queryJobList.clear();
|
||||||
|
canceled = false;
|
||||||
return Status.OK_STATUS;
|
return Status.OK_STATUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1548,27 +1701,15 @@ public class AfosBrowserDlg extends CaveSWTDialog implements
|
||||||
* @param productIds
|
* @param productIds
|
||||||
* - List of products for the query.
|
* - List of products for the query.
|
||||||
*/
|
*/
|
||||||
public void addRequest(TextDBQuery request,
|
public synchronized void addRequest(TextDBQuery request,
|
||||||
java.util.List<String> productIds) {
|
java.util.List<String> productIds) {
|
||||||
synchronized (this) {
|
if (getState() != Job.NONE) {
|
||||||
if (this.request != null) {
|
cancel();
|
||||||
if (getState() != Job.NONE) {
|
|
||||||
cancel();
|
|
||||||
while (request != null && getState() != Job.NONE) {
|
|
||||||
try {
|
|
||||||
wait(100L);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
AfosBrowserDlg.statusHandler.handle(
|
|
||||||
Priority.PROBLEM,
|
|
||||||
e.getLocalizedMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.request = request;
|
|
||||||
this.productIds = productIds;
|
|
||||||
schedule();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.pendingRequest = request;
|
||||||
|
this.productIds = productIds;
|
||||||
|
schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1579,6 +1720,9 @@ public class AfosBrowserDlg extends CaveSWTDialog implements
|
||||||
@Override
|
@Override
|
||||||
protected void canceling() {
|
protected void canceling() {
|
||||||
canceled = true;
|
canceled = true;
|
||||||
|
for (QueryJob query : queryJobList) {
|
||||||
|
query.canceled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -39,7 +39,7 @@ import com.raytheon.uf.common.message.Property;
|
||||||
* Nov 3, 2008 jkorman Initial creation
|
* Nov 3, 2008 jkorman Initial creation
|
||||||
* 28May2010 cjeanbap Added operational functionality.
|
* 28May2010 cjeanbap Added operational functionality.
|
||||||
* 02Aug2010 2187 cjeanbap Update variable/method signature to be consistent.
|
* 02Aug2010 2187 cjeanbap Update variable/method signature to be consistent.
|
||||||
* 22Jan2013 1496 rferrel Added method clearProductIds
|
* 29Jan2013 1496 rferrel Added methods clearProductIds and clone.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -91,6 +91,34 @@ public class TextDBQuery {
|
||||||
queryTransport = transport;
|
queryTransport = transport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see java.lang.Object#clone()
|
||||||
|
*/
|
||||||
|
public TextDBQuery clone() {
|
||||||
|
TextDBQuery tdq = new TextDBQuery(queryTransport);
|
||||||
|
tdq.queryViewName = this.queryViewName;
|
||||||
|
tdq.queryOpName = this.queryOpName;
|
||||||
|
tdq.querySubObName = this.querySubObName;
|
||||||
|
tdq.queryTimeFormatName = this.queryTimeFormatName;
|
||||||
|
tdq.queryTimeFormat = this.queryTimeFormat;
|
||||||
|
tdq.queryAfosCmd = this.queryAfosCmd;
|
||||||
|
tdq.queryWmoId = this.queryWmoId;
|
||||||
|
tdq.querySite = this.querySite;
|
||||||
|
tdq.queryHour = this.queryHour;
|
||||||
|
tdq.queryHdrTime = this.queryHdrTime;
|
||||||
|
tdq.queryBBB = this.queryBBB;
|
||||||
|
tdq.queryNnnXxx = this.queryNnnXxx;
|
||||||
|
tdq.queryFullDataRead = this.queryFullDataRead;
|
||||||
|
tdq.queryOperationalMode = this.queryOperationalMode;
|
||||||
|
tdq.queryProduct = this.queryProduct;
|
||||||
|
if (productIds != null) {
|
||||||
|
tdq.productIds = new ArrayList<String>(productIds);
|
||||||
|
}
|
||||||
|
return tdq;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the queryViewName
|
* @return the queryViewName
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Reference in a new issue