From 4195c36f08a92bc5f15204da38c211515a4a7fbf Mon Sep 17 00:00:00 2001 From: Ron Anderson Date: Thu, 24 Jul 2014 14:02:10 -0500 Subject: [PATCH] Issue #3423 Move alarm/alert product requests off UI thread Change-Id: I44149b5af54fbeac75231d6caeb3929fbf6ecf5e Former-commit-id: be5794d46482809de0f3302906416ab6e44632c3 [formerly ac0799ce35f67068bcf837610b5bbad1abbd67c8] [formerly 17b681f3559957c6e260bc0aaef9bcd8d0b01be8] [formerly 174d8b59e0c8e8c8fc94bf2f7743e7966d143228 [formerly 17b681f3559957c6e260bc0aaef9bcd8d0b01be8 [formerly c3401cee78edae8dea6d21736fac25bfed996fb3]]] Former-commit-id: 174d8b59e0c8e8c8fc94bf2f7743e7966d143228 Former-commit-id: f037b9fe395c757a1cf7c40690b05cf533498d43 [formerly 64ba8b1c1aeb5afe87acc377e899a0d5cc6f4e48] Former-commit-id: 3da914cf978c67d175e522caac9d049fc15cf409 --- .../dialogs/AlarmDisplayWindow.java | 17 +- .../alarmalert/dialogs/CurrentAlarmQueue.java | 246 +++++++++++------- .../alarmalert/util/AlarmAlertFunctions.java | 17 +- .../util/AlarmAlertNotificationObserver.java | 9 +- 4 files changed, 181 insertions(+), 108 deletions(-) diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmDisplayWindow.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmDisplayWindow.java index 1bd1acdfdd..c9f80f5071 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmDisplayWindow.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/AlarmDisplayWindow.java @@ -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. * * * @@ -100,19 +102,13 @@ public class AlarmDisplayWindow extends CaveSWTDialog { /** * @param parentShell - * @param prodList * @param accum_state */ - protected AlarmDisplayWindow(Shell parentShell, - java.util.List 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(); - } + prods = new ArrayList(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()) { diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/CurrentAlarmQueue.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/CurrentAlarmQueue.java index 31c0300df0..0d7dda8784 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/CurrentAlarmQueue.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/dialogs/CurrentAlarmQueue.java @@ -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 * * * @@ -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> queue = new ConcurrentLinkedQueue>(); + + /** + * 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(refTime, commands)); + this.schedule(); + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + while (queue.size() > 0) { + Pair pair = queue.poll(); + if (pair != null) { + final java.util.List 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 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 counter = new HashMap(); - 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 prods = new ArrayList(); - 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 counter = new HashMap(); + 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 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 produceTextProduct(String command, - Long refTime) { - ICommand cmd = CommandFactory.getAfosCommand(command, refTime); - executeCommand(cmd); - return prodList; + private java.util.List produceTextProducts(Long refTime, + String... commands) { + + java.util.List prods = new ArrayList(); + 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()); + } + }); } } } diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmAlertFunctions.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmAlertFunctions.java index 1579b620a1..fe2c6b2846 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmAlertFunctions.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmAlertFunctions.java @@ -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 * * * @@ -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); + } + }); } } } diff --git a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmAlertNotificationObserver.java b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmAlertNotificationObserver.java index 1a68290813..0a3b6e6c03 100644 --- a/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmAlertNotificationObserver.java +++ b/cave/com.raytheon.viz.texteditor/src/com/raytheon/viz/texteditor/alarmalert/util/AlarmAlertNotificationObserver.java @@ -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 * *
  * 
  * 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
  * 
  * 
* @@ -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,