java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui
--- java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java 2014-06-16 21:19:17 UTC (rev 714)
+++ java/trunk/monitoring-app/src/main/java/org/hps/monitoring/gui/MonitoringApplication.java 2014-06-17 15:14:10 UTC (rev 715)
@@ -28,6 +28,8 @@
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Dimension;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
@@ -47,18 +49,11 @@
import java.io.InputStream;
import java.io.PrintStream;
import java.net.InetAddress;
-import java.net.JarURLConnection;
-import java.net.URL;
import java.text.SimpleDateFormat;
-import java.util.ArrayList;
import java.util.Date;
-import java.util.Enumeration;
-import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
@@ -102,7 +97,7 @@
// TODO: Log the messages from all Exceptions.
// TODO: Capture std err and out and redirect to a text panel within the application.
// TODO: Report state of event processing at the end of the job in a new GUI component.
-// TODO: Check if the complex logic used to disconnect/cleanup the ET system is necessary anymore.
+// TODO: Move ET cleanup code to the record.etevent package.
public class MonitoringApplication {
// Top-level Swing components.
@@ -173,17 +168,14 @@
// Format for screenshots. Hard-coded to PNG.
private static final String screenshotFormat = "png";
- // Maximum time in millis to wait for the ET system to disconnect.
- // TODO: Make this an option in the JobPanel.
- private int maxCleanupTime = 5000;
-
// Format of date field for log.
private final SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM-dd-yyyy HH:mm:ss.SSS");
private static final String LCSIM_FAIL_MESSAGE = "Failed to setup LCSim.";
- private static final int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
- private static final int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
-
+ static GraphicsDevice graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
+ private static final int screenWidth = graphicsDevice.getDisplayMode().getWidth();
+ private static final int screenHeight = graphicsDevice.getDisplayMode().getHeight();
+
private static final int leftPanelWidth = (int) (screenWidth * 0.33);
private static final int rightPanelWidth = (int) (screenWidth * 0.40);
@@ -363,8 +355,6 @@
eventMenu.setMnemonic(KeyEvent.VK_E);
menuBar.add(eventMenu);
- //addMenuItem("Reset Event Monitor", KeyEvent.VK_E, RESET_EVENTS, true, "Reset timer and counters in the event monitor tab.", eventMenu);
-
/**
* FIXME: Rest of these should be converted to use the addMenuItem() helper method...
*/
@@ -376,15 +366,6 @@
eventRefreshItem.setToolTipText("Set the number of events between GUI updates.");
eventMenu.add(eventRefreshItem);
- /*
- JMenuItem maxEventsItem = new JMenuItem("Set Max Events...");
- maxEventsItem.setMnemonic(KeyEvent.VK_M);
- maxEventsItem.setActionCommand(SET_MAX_EVENTS);
- maxEventsItem.addActionListener(actionListener);
- maxEventsItem.setToolTipText("Set the maximum number of events to process in one session.");
- eventMenu.add(maxEventsItem);
- */
-
JMenu jobMenu = new JMenu("Job");
jobMenu.setMnemonic(KeyEvent.VK_J);
menuBar.add(jobMenu);
@@ -598,10 +579,8 @@
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (CONNECT.equals(cmd)) {
- //startSessionThread();
startSession();
} else if (DISCONNECT.equals(cmd)) {
- //startDisconnectThread();
stopSession();
} else if (EDIT_EVENT_REFRESH.equals(cmd)) {
setEventRefresh();
@@ -839,27 +818,6 @@
}
/**
- * Call the reset() method on Drivers which implement {@link Resettable}. They must implement
- * the {@link Resettable} interface for this to work.
- */
- /*
- private synchronized void resetDrivers() {
- if (jobManager != null) {
- for (Driver driver : jobManager.getDriverExecList()) {
- if (driver instanceof Resettable) {
- try {
- ((Resettable) driver).reset();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- }
- log(Level.INFO, "LCSim drivers were reset.");
- }
- */
-
- /**
* Redirect System.out and System.err to a file. This is primarily used to capture lengthy
* debug output from event processing. Messages sent to the Logger are unaffected.
*/
@@ -951,34 +909,6 @@
}
/**
- * Using a modal dialog, set the maximum number of events to process before an automatic
- * disconnect.
- */
- /*
- private void setMaxEvents() {
- String inputValue = JOptionPane.showInputDialog("Max Events:", eventPanel.getMaxEvents());
- try {
- int newMaxEvents = Integer.parseInt(inputValue);
- if (newMaxEvents < 0) {
- showDialog("Max Events is set to unlimited.");
- newMaxEvents = -1;
- }
- // Set max events in panel.
- eventPanel.setMaxEvents(newMaxEvents);
- // Set max events in event processor.
- //if (eventProcessor != null) {
- // eventProcessor.setMaxEvents(newMaxEvents);
- //}
- log("Max events set to <" + newMaxEvents + ">.");
- } catch (Exception e) {
- e.printStackTrace();
- log(Level.WARNING, "Ignored invalid max events setting <" + inputValue + ">.");
- showDialog("The value " + inputValue + " is not valid for Max Events.");
- }
- }
- */
-
- /**
* Set the GUI state to disconnected, which will enable/disable applicable GUI components and
* menu items.
*/
@@ -990,7 +920,6 @@
resetConnectionItem.setEnabled(true);
connectionLoadItem.setEnabled(true);
savePlotsItem.setEnabled(false);
- //resetDriversItem.setEnabled(false);
logItem.setEnabled(true);
terminalItem.setEnabled(true);
steeringItem.setEnabled(true);
@@ -1107,20 +1036,10 @@
}
/**
- * Get the current max events setting.
- * @return The maximum number of events to process before disconnect.
- */
- /*
- private int getMaxEvents() {
- return eventPanel.getMaxEvents();
- }
- */
-
- /**
* Execute a monitoring session. This should be executed in a separate thread so as not to block the
* GUI or other threads during a monitoring session.
*/
- private void startSession() {
+ synchronized private void startSession() {
log(Level.INFO, "Starting a new monitoring session.");
@@ -1149,7 +1068,7 @@
startSessionTimer();
log(Level.INFO, "Successfully started the monitoring session.");
-
+
} catch (Exception e) {
e.printStackTrace();
log(Level.SEVERE, e.getMessage());
@@ -1227,7 +1146,7 @@
* Disconnect from the current ET session with a particular status.
* @param status The connection status.
*/
- synchronized private void disconnect(int status) {
+ private void disconnect(int status) {
log("Disconnecting from the ET system.");
@@ -1252,6 +1171,7 @@
* It is executed under a separate thread, because it could potentially block forever.
* So we need to be able to kill it after waiting for X amount of time.
*/
+ /*
private class EtCleanupThread extends Thread {
boolean succeeded;
@@ -1274,6 +1194,7 @@
Thread.yield();
}
}
+ */
/**
* Cleanup the ET connection.
@@ -1281,6 +1202,12 @@
private void cleanupEtConnection() {
if (connection != null) {
+ connection.cleanup();
+ connection = null;
+ }
+
+ /*
+ if (connection != null) {
// Execute the connection cleanup thread.
EtCleanupThread cleanupThread = new EtCleanupThread();
@@ -1297,7 +1224,7 @@
if (cleanupThread.succeeded()) {
log(Level.FINE, "EtCleanupThread succeeded in disconnecting from ET system.");
} else {
- log(Level.SEVERE, "EtCleanupThread failed to disconnect. Your station <" + this.connection.getEtStation().getName() + "> is zombified!");
+ //log(Level.SEVERE, "EtCleanupThread failed to disconnect. Your station <" + this.connection.getEtStation().getName() + "> is zombified!");
// Make the cleanup thread yield.
cleanupThread.stopCleanup();
// Stop the cleanup thread.
@@ -1309,6 +1236,7 @@
this.connection = null;
}
}
+ */
}
/**
@@ -1490,6 +1418,7 @@
private void nextEvent() {
if (connected()) {
log(Level.FINER, "Notifying event processor to get next events.");
+
eventProcessing.next();
} else {
log(Level.WARNING, "Ignored next events command because app is disconnected.");
@@ -1614,75 +1543,82 @@
* Stop the session by stopping the event processing thread, ending the job,
* and disconnecting from the ET system.
*/
- // FIXME: Needs to be synchronized?
private synchronized void stopSession() {
- //Runnable runnable = new Runnable() {
- //public void run() {
+ logger.log(Level.FINE, "Stopping the session.");
- logger.log(Level.INFO, "Stopping session.");
+ // This will kill the event processing thread and, if necessary,
+ // the session thread.
+ killEventProcessing();
- // Request event processing to stop.
- // TODO: I think this check should be replaced with ...
- // eventProcessingThread.isAlive()
- if (!eventProcessing.isDone()) {
-
- //System.out.println("interrupting session thread");
-
- // Interrupt the session thread because if processing is still happening,
- // then we didn't get here through that thread.
- sessionThread.interrupt();
-
- //System.out.println("finishing event processing");
+ // Perform various end of job cleanup.
+ endJob();
- // Request processing to stop.
+ // Disconnect from the ET server.
+ disconnect();
+
+ // Stop the session timer.
+ stopSessionTimer();
+
+ logger.log(Level.INFO, "Session was stopped.");
+ }
+
+ /**
+ * Stop the event processing thread and, if necessary, the session thread.
+ */
+ private void killEventProcessing() {
+
+ // If event processing is still alive, we got here via a disconnect request
+ // from the GUI button and not an automatic disconnect.
+ if (eventProcessingThread.isAlive()) {
+
+ // Kill the session thread if it is active, because it is waiting for the
+ // event processing to finish.
+ killSessionThread();
+
+ // Request the event processing to stop.
eventProcessing.finish();
}
// Wait for the event processing thread to finish.
try {
- //logger.log(Level.FINER, "Waiting for event processing to finish before disconnecting.");
- //System.out.println("Waiting for event processing to finish before disconnecting.");
eventProcessingThread.join();
- //System.out.println("Event processing finished.");
- //logger.log(Level.FINER, "Event processing finished.");
} catch (InterruptedException e) {
- e.printStackTrace();
+ throw new RuntimeException("Unexpected interrupt while joining the EventProcessingThread.");
}
// Reset event processing objects.
eventProcessing = null;
eventProcessingThread = null;
+ }
- // Perform various end of job cleanup.
- endJob();
-
- // Disconnect from the ET server.
- //System.out.println("disconnecting from ET ...");
- disconnect();
- //System.out.println("done disconnecting");
-
- // Stop the session timer.
- stopSessionTimer();
-
+ /**
+ * Kill the current session watchdog thread.
+ */
+ private void killSessionThread() {
+ if (sessionThread.isAlive()) {
+ sessionThread.interrupt();
+ try {
+ sessionThread.join();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Unexpected interrupt while joining SessionThread.");
+ }
+ }
sessionThread = null;
-
- logger.log(Level.INFO, "Session done.");
- //}
- //};
-
- //Thread thread = new Thread(runnable);
- //thread.start();
-
}
/**
- * Thread to automatically trigger a disconnect when the event processing chain finishes.
+ * Thread to automatically trigger a disconnect when the event processing chain finishes
+ * or throws a fatal error.
*/
- class SessionThread extends Thread {
+ private class SessionThread extends Thread {
public void run() {
try {
+ // When the event processing thread finishes, the session should be stopped and disconnect
+ // should occur.
eventProcessingThread.join();
+
+ // Activate a disconnect using the ActionEvent which is used by the disconnect button.
actionListener.actionPerformed(new ActionEvent(Thread.currentThread(), 0, MonitoringCommands.DISCONNECT));
} catch (InterruptedException e) {
e.printStackTrace();