Issue #3423 Move alarm/alert product requests off UI thread

Change-Id: I44149b5af54fbeac75231d6caeb3929fbf6ecf5e

Former-commit-id: 17b681f355 [formerly c3401cee78edae8dea6d21736fac25bfed996fb3]
Former-commit-id: 174d8b59e0
This commit is contained in:
Ron Anderson 2014-07-24 14:02:10 -05:00
parent 05e49db6b5
commit 64ba8b1c1a
4 changed files with 181 additions and 108 deletions

View file

@ -62,6 +62,8 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* Sep 6, 2012 13365 rferrel Accumulate and Display fix.
* Sep 25, 2012 1196 lvenable Dialog refactor for AlarmDisplayWindow.Added DO_NOT_BLOCK.
* Nov 20, 2013 2488 randerso Changed to use DejaVu font
* Jul 24, 2014 3423 randerso Added setLoading() to indicate waiting on product
* retrieval. Removed prods from constructor.
*
* </pre>
*
@ -100,19 +102,13 @@ public class AlarmDisplayWindow extends CaveSWTDialog {
/**
* @param parentShell
* @param prodList
* @param accum_state
*/
protected AlarmDisplayWindow(Shell parentShell,
java.util.List<StdTextProduct> prodList,
ACCUMULATE_STATE accum_state) {
protected AlarmDisplayWindow(Shell parentShell, ACCUMULATE_STATE accum_state) {
super(parentShell, SWT.RESIZE, CAVE.PERSPECTIVE_INDEPENDENT
| CAVE.INDEPENDENT_SHELL | CAVE.DO_NOT_BLOCK);
setText("Alarm Display Window");
prods = prodList;
if (prods == null) {
prods = new ArrayList<StdTextProduct>();
}
prods = new ArrayList<StdTextProduct>(0);
this.accum_state = accum_state;
}
@ -265,6 +261,11 @@ public class AlarmDisplayWindow extends CaveSWTDialog {
populateText();
}
public void setLoading() {
actualText = text.getText();
text.setText("Loading...");
}
public void addText(String msg) {
if (accumulate) {
if (text.getText().isEmpty()) {

View file

@ -24,7 +24,13 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
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;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
@ -52,7 +58,9 @@ import com.raytheon.uf.common.dataplugin.text.db.StdTextProduct;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.util.Pair;
import com.raytheon.uf.edex.services.textdbsrv.IQueryTransport;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.viz.core.mode.CAVEMode;
import com.raytheon.viz.texteditor.alarmalert.dialogs.AlarmDisplayWindow.ACCUMULATE_STATE;
import com.raytheon.viz.texteditor.alarmalert.util.AlarmAlertFunctions;
@ -97,8 +105,10 @@ import com.raytheon.viz.ui.dialogs.ModeListener;
* Alarm Queue" GUI
* Sep 6, 2012 13365 rferrel Accumulate and Display fix.
* Sep 25, 2012 1196 lvenable Dialog refactor for AlarmDisplayWindow.
* Mar 05,2013 15173 mgamazaychikov The dimensions and location of closed window
* are saved and set on the next open.
* Mar 05, 2013 15173 mgamazaychikov The dimensions and location of closed window
* are saved and set on the next open.
* Jul 24, 2014 3423 randerso Created eclipse job to get afos command
* execution off the UI thread
*
* </pre>
*
@ -142,7 +152,7 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
* Location and dimensions of the dialog on the close.
*/
private static Point closeLocation = null;
private static Point closeDimensions = null;
/**
@ -151,14 +161,65 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
private boolean canRedraw = true;
/**
* Maximum width,initial height and offset of the window
* Maximum width,initial height and offset of the window
*/
private static final int SHELL_WIDTH = 350;
private static final int INIT_HEIGHT = 200;
private static final int INIT_OFFSET = 15;
/**
* Job to retrieve text products off the UI thread
*/
private class ProduceTextProductsJob extends Job {
private Queue<Pair<Long, String[]>> queue = new ConcurrentLinkedQueue<Pair<Long, String[]>>();
/**
* Constructor
*/
public ProduceTextProductsJob() {
super("ProduceTextProductsJob");
setSystem(true);
}
/**
* Queue a text product retrieval job
*
* @param refTime
* @param commands
*/
public void queue(Long refTime, String... commands) {
queue.add(new Pair<Long, String[]>(refTime, commands));
this.schedule();
}
@Override
protected IStatus run(IProgressMonitor monitor) {
while (queue.size() > 0) {
Pair<Long, String[]> pair = queue.poll();
if (pair != null) {
final java.util.List<StdTextProduct> prods = produceTextProducts(
pair.getFirst(), pair.getSecond());
VizApp.runSync(new Runnable() {
@Override
public void run() {
if (alarmDisplayDlg != null
&& !alarmDisplayDlg.isDisposed()) {
alarmDisplayDlg.setProds(prods);
}
}
});
}
}
return Status.OK_STATUS;
}
}
private ProduceTextProductsJob produceTextProductsJob = new ProduceTextProductsJob();
/**
* @param parentShell
* @param style
@ -261,12 +322,13 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
shellComp = new Composite(shell, SWT.NONE);
shellComp.setLayout(constructShellLayout());
shellComp.setLayoutData(gd);
/*
* DR15173 - Create a listener to save the location
* and dimensions of closed window.
* DR15173 - Create a listener to save the location and dimensions of
* closed window.
*/
shell.addShellListener(new ShellAdapter() {
@Override
public void shellClosed(ShellEvent event) {
closeLocation = getShell().getLocation();
closeDimensions = getShell().getSize();
@ -289,11 +351,13 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
/*
* DR15173 - Enforce that the window width does not exceed the SHELL_WIDTH.
*/
shell.setBounds(location.x, location.y, SHELL_WIDTH, point.y);
shell.setMinimumSize(SHELL_WIDTH, 0);
/*
* DR15173 - Enforce that the window width does not
* exceed the SHELL_WIDTH.
*/
shell.setBounds(location.x, location.y, SHELL_WIDTH,
point.y);
shell.setMinimumSize(SHELL_WIDTH, 0);
canRedraw = true;
}
});
@ -302,7 +366,7 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
// Initialize all of the controls and layouts
initializeComponents();
// Set the shell location and dimensions.
setShellGeometry();
}
@ -310,26 +374,25 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
/**
* Sets the geometry for the Current Alarm Queue shell
*/
private void setShellGeometry() {
Rectangle displayArea = shell.getDisplay().getClientArea();
int locationX = displayArea.x + INIT_OFFSET;
int locationY = displayArea.y + INIT_OFFSET;
int width = SHELL_WIDTH;
int height = INIT_HEIGHT;
if (CurrentAlarmQueue.closeLocation != null) {
locationX = CurrentAlarmQueue.closeLocation.x;
locationY = CurrentAlarmQueue.closeLocation.y;
}
if (CurrentAlarmQueue.closeDimensions != null) {
height = CurrentAlarmQueue.closeDimensions.y;
}
shell.setMinimumSize(width, height);
shell.setLocation(locationX, locationY);
return;
}
private void setShellGeometry() {
Rectangle displayArea = shell.getDisplay().getClientArea();
int locationX = displayArea.x + INIT_OFFSET;
int locationY = displayArea.y + INIT_OFFSET;
int width = SHELL_WIDTH;
int height = INIT_HEIGHT;
if (CurrentAlarmQueue.closeLocation != null) {
locationX = CurrentAlarmQueue.closeLocation.x;
locationY = CurrentAlarmQueue.closeLocation.y;
}
if (CurrentAlarmQueue.closeDimensions != null) {
height = CurrentAlarmQueue.closeDimensions.y;
}
shell.setMinimumSize(width, height);
shell.setLocation(locationX, locationY);
return;
}
/**
/**
* Initializes each component of the shell
*/
private void initializeComponents() {
@ -421,7 +484,7 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
* Display the selected product the current alarm queue list.
*/
private void displayList() {
String command = "";
String command = null;
Date refDate = null;
if (list != null && list.getItemCount() > 0
&& list.getSelectionCount() > 0 && list.getSelection() != null) {
@ -436,14 +499,9 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
}
}
java.util.List<StdTextProduct> prods = null;
if (command != "" && refDate != null) {
prods = produceTextProduct(command, refDate.getTime());
}
// Display the Alarm Display Window
if (alarmDisplayDlg == null || alarmDisplayDlg.getShell().isDisposed()) {
alarmDisplayDlg = new AlarmDisplayWindow(shell, prods,
alarmDisplayDlg = new AlarmDisplayWindow(shell,
ACCUMULATE_STATE.UNCHANGE);
alarmDisplayDlg.setCloseCallback(new ICloseCallback() {
@ -458,58 +516,52 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
alarmDisplayDlg.open();
} else {
alarmDisplayDlg.setProds(prods);
alarmDisplayDlg.setDialogFocus();
}
if (command != null && refDate != null) {
alarmDisplayDlg.setLoading();
produceTextProductsJob.queue(refDate.getTime(), command);
}
}
/**
* Display all the products in the alarm queue list and clear the list.
*/
private void displayAll() {
String[] command = null;
if (list != null) {
command = new String[list.getItemCount()];
for (int i = 0; i < list.getItemCount(); i++) {
command[i] = list.getItems()[i].split(" ")[0];
}
// Do a count of how many instances of each command are in
// the queue.
Map<String, Integer> counter = new HashMap<String, Integer>();
for (int i = 0; i < command.length; ++i) {
if (counter.get(command[i]) == null) {
counter.put(command[i], 0);
} else {
counter.put(command[i], (counter.get(command[i]) + 1));
}
}
// For each command, see how far back it needs to go to
// account for multiple instances, and construct the
// appropriate AFOS command.
for (int j = 0; j < command.length; ++j) {
Integer count = counter.get(command[j]);
if (count > 0) {
String newCom = "-" + count.toString() + ":" + command[j];
counter.put(command[j], (count - 1));
command[j] = newCom;
}
}
AlarmAlertLists.getInstance().getCurrentAlarms().clear();
listDates.clear();
list.removeAll();
AlarmAlertFunctions.getAlarmalertbell().close();
String[] command = new String[list.getItemCount()];
for (int i = 0; i < list.getItemCount(); i++) {
command[i] = list.getItems()[i].split(" ")[0];
}
java.util.List<StdTextProduct> prods = new ArrayList<StdTextProduct>();
if (command.length > 0) {
for (int i = 0; i < command.length; i++) {
prods.addAll(produceTextProduct(command[i]));
// Do a count of how many instances of each command are in
// the queue.
Map<String, Integer> counter = new HashMap<String, Integer>();
for (int i = 0; i < command.length; ++i) {
if (counter.get(command[i]) == null) {
counter.put(command[i], 0);
} else {
counter.put(command[i], (counter.get(command[i]) + 1));
}
}
// For each command, see how far back it needs to go to
// account for multiple instances, and construct the
// appropriate AFOS command.
for (int j = 0; j < command.length; ++j) {
Integer count = counter.get(command[j]);
if (count > 0) {
String newCom = "-" + count.toString() + ":" + command[j];
counter.put(command[j], (count - 1));
command[j] = newCom;
}
}
AlarmAlertLists.getInstance().getCurrentAlarms().clear();
listDates.clear();
list.removeAll();
AlarmAlertFunctions.getAlarmalertbell().close();
// Display the Alarm Display Window
if (alarmDisplayDlg == null || alarmDisplayDlg.getShell().isDisposed()) {
alarmDisplayDlg = new AlarmDisplayWindow(shell, prods,
alarmDisplayDlg = new AlarmDisplayWindow(shell,
ACCUMULATE_STATE.TRUE);
alarmDisplayDlg.setCloseCallback(new ICloseCallback() {
@Override
@ -523,10 +575,12 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
});
alarmDisplayDlg.open();
} else {
alarmDisplayDlg.setProds(prods);
alarmDisplayDlg.setAccumulate(true);
alarmDisplayDlg.setDialogFocus();
}
alarmDisplayDlg.setLoading();
produceTextProductsJob.queue(null, command);
}
/**
@ -578,12 +632,6 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
}
}
public java.util.List<StdTextProduct> produceTextProduct(String command) {
ICommand cmd = CommandFactory.getAfosCommand(command);
executeCommand(cmd);
return prodList;
}
/**
* Get the product for the given AFOS command and reference time.
*
@ -591,11 +639,16 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
* @param refTime
* @return prodList
*/
private java.util.List<StdTextProduct> produceTextProduct(String command,
Long refTime) {
ICommand cmd = CommandFactory.getAfosCommand(command, refTime);
executeCommand(cmd);
return prodList;
private java.util.List<StdTextProduct> produceTextProducts(Long refTime,
String... commands) {
java.util.List<StdTextProduct> prods = new ArrayList<StdTextProduct>();
for (String command : commands) {
ICommand cmd = CommandFactory.getAfosCommand(command, refTime);
executeCommand(cmd);
prods.addAll(prodList);
}
return prods;
}
/*
@ -652,12 +705,19 @@ public class CurrentAlarmQueue extends CaveSWTDialog implements
*/
@Override
public void currentAlarmChanged(CurrentAlarmEvent event) {
AlarmAlertProduct aap = (AlarmAlertProduct) event.getSource();
final AlarmAlertProduct aap = (AlarmAlertProduct) event.getSource();
if (!shell.isDisposed() && shell != null) {
CAVEMode mode = CAVEMode.getMode();
if ((CAVEMode.OPERATIONAL.equals(mode) || CAVEMode.TEST
.equals(mode)) && aap.getOperationalMode()) {
addToQueue(aap.getProductId(), aap.getDateReceived());
VizApp.runAsync(new Runnable() {
@Override
public void run() {
addToQueue(aap.getProductId(), aap.getDateReceived());
}
});
}
}
}

View file

@ -56,6 +56,7 @@ import com.raytheon.uf.common.localization.exception.LocalizationOpFailedExcepti
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.localization.LocalizationManager;
import com.raytheon.viz.texteditor.alarmalert.dialogs.AlarmAlertBell;
import com.raytheon.viz.texteditor.command.CommandFactory;
@ -79,6 +80,7 @@ import com.vividsolutions.jts.geom.GeometryFactory;
* 03/19/2012 D. Friedman Fix determination of "Alarm" entries.
* 12/07/2012 15555 m.gamazaychikov Added methods and constants for
* the implementation of proximity alarm
* 07/24/2014 3423 randerso Ensure ringBell is called on UI thread
*
* </pre>
*
@ -211,14 +213,16 @@ public class AlarmAlertFunctions {
match = true;
}
if (match) {
if (productFound == null)
if (productFound == null) {
productFound = p;
}
if ("Alarm".equals(p.getAlarmType()) && p.isAlarm()) {
alarm = true;
productFound = p;
}
if (alarm)
if (alarm) {
break;
}
}
}
}
@ -229,7 +233,14 @@ public class AlarmAlertFunctions {
instance.getCurrentAlarms().add(prod);
instance.fireNewCurrentAlarmEvent(prod);
ringBell(alarm);
final boolean sound = alarm;
VizApp.runAsync(new Runnable() {
@Override
public void run() {
ringBell(sound);
}
});
}
}
}

View file

@ -23,22 +23,22 @@ import com.raytheon.uf.common.dataplugin.text.alarms.AlarmAlertProduct;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.notification.INotificationObserver;
import com.raytheon.uf.viz.core.notification.NotificationMessage;
import com.raytheon.uf.viz.core.notification.jobs.NotificationManagerJob;
import com.raytheon.viz.core.mode.CAVEMode;
/**
* TODO Add Description
* Alarm Alert Notification Observer
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 13, 2009 mnash Initial creation
* Oct 13, 2009 mnash Initial creation
* Jun 07, 2010 5851 cjeanbap Properly stop alarm/alert observer listener.
* Jul 24, 2014 3423 randerso Get afos command execution off the UI thread
*
* </pre>
*
@ -108,7 +108,8 @@ public class AlarmAlertNotificationObserver implements INotificationObserver {
}
if (run != null) {
VizApp.runAsync(run);
Thread thread = new Thread(run);
thread.start();
}
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM,