Author: [log in to unmask] Date: Thu Mar 12 16:53:02 2015 New Revision: 2425 Log: Add first working version of reading DAQ config events on separate ET station. HPSJAVA-464 Added: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/util/EvioDAQConfigStation.java java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/util/MonitoringApplicationEventBuilder.java Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/EventProcessing.java java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/MonitoringApplication.java Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/EventProcessing.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/EventProcessing.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/EventProcessing.java Thu Mar 12 16:53:02 2015 @@ -14,6 +14,7 @@ import org.hps.monitoring.application.model.ConnectionStatus; import org.hps.monitoring.application.model.SteeringType; import org.hps.monitoring.application.util.EtSystemUtil; +import org.hps.monitoring.application.util.EvioDAQConfigStation; import org.hps.monitoring.subsys.et.EtSystemMonitor; import org.hps.monitoring.subsys.et.EtSystemStripCharts; import org.hps.record.LCSimEventBuilder; @@ -32,20 +33,20 @@ import org.lcsim.util.Driver; /** - * This class encapsulates all of the logic involved with processing events - * and managing the related state and objects within the monitoring application. + * This class encapsulates all of the logic involved with processing events and managing the related + * state and objects within the monitoring application. * * @author Jeremy McCormick <[log in to unmask]> */ class EventProcessing { - + MonitoringApplication application; Logger logger; SessionState sessionState; List<CompositeRecordProcessor> processors; List<Driver> drivers; List<ConditionsListener> conditionsListeners; - + /** * This class is used to organize the objects for an event processing session. */ @@ -57,27 +58,22 @@ Thread sessionWatchdogThread; EtConnection connection; } - - /** - * Initialize with reference to the current monitoring application - * and a list of extra processors to add to the loop after - * configuration. + + /** + * Initialize with reference to the current monitoring application and a list of extra + * processors to add to the loop after configuration. * @param application The current monitoring application. * @param processors A list of processors to add after configuration is performed. */ - EventProcessing( - MonitoringApplication application, - List<CompositeRecordProcessor> processors, - List<Driver> drivers, - List<ConditionsListener> conditionsListeners) { + EventProcessing(MonitoringApplication application, List<CompositeRecordProcessor> processors, List<Driver> drivers, List<ConditionsListener> conditionsListeners) { this.application = application; - this.sessionState = new SessionState(); + this.sessionState = new SessionState(); this.logger = MonitoringApplication.logger; this.processors = processors; this.drivers = drivers; this.conditionsListeners = conditionsListeners; } - + /** * Setup this class from the global configuration. * @param configurationModel The global configuration. @@ -97,26 +93,28 @@ MonitoringApplication.logger.config("Set steering to " + steering + " with type " + (steeringType == SteeringType.RESOURCE ? "RESOURCE" : "FILE")); try { - // Create and the job manager. The conditions manager is instantiated from this call but not configured. + // Create and the job manager. The conditions manager is instantiated from this call but + // not configured. sessionState.jobManager = new JobManager(); - - // Add conditions listeners after new database conditions manager is initialized from job manager. + + // Add conditions listeners after new database conditions manager is initialized from + // job manager. DatabaseConditionsManager conditionsManager = DatabaseConditionsManager.getInstance(); for (ConditionsListener conditionsListener : conditionsListeners) { logger.config("adding conditions listener " + conditionsListener.getClass().getName()); conditionsManager.addConditionsListener(conditionsListener); } - + if (configurationModel.hasValidProperty(ConfigurationModel.DETECTOR_ALIAS_PROPERTY)) { - // Set a detector alias. + // Set a detector alias. ConditionsReader.addAlias(configurationModel.getDetectorName(), "file://" + configurationModel.getDetectorAlias()); logger.config("using detector alias " + configurationModel.getDetectorAlias()); } - + // Setup the event builder to translate from EVIO to LCIO. // This must happen before Driver setup so the builder's listeners are activated first! createEventBuilder(configurationModel); - + // Configure the job manager for the XML steering. sessionState.jobManager.setPerformDryRun(true); if (steeringType == SteeringType.RESOURCE) { @@ -124,14 +122,14 @@ } else if (steeringType.equals(SteeringType.FILE)) { setupSteeringFile(steering); } - + // Set conditions tag. if (configurationModel.hasValidProperty(ConfigurationModel.CONDITIONS_TAG_PROPERTY) && !configurationModel.getConditionsTag().equals("")) { - logger.config("conditions tag is set to " + configurationModel.getConditionsTag()); + logger.config("conditions tag is set to " + configurationModel.getConditionsTag()); } else { logger.config("conditions NOT using a tag"); } - + // Is there a user specified run number from the JobPanel? if (configurationModel.hasValidProperty(ConfigurationModel.USER_RUN_NUMBER_PROPERTY)) { int userRunNumber = configurationModel.getUserRunNumber(); @@ -139,7 +137,7 @@ logger.config("setting user run number " + userRunNumber + " with detector " + detectorName); conditionsManager.setDetector(configurationModel.getDetectorName(), userRunNumber); if (configurationModel.hasPropertyKey(ConfigurationModel.FREEZE_CONDITIONS_PROPERTY)) { - // Freeze the conditions system to ignore run numbers from the events. + // Freeze the conditions system to ignore run numbers from the events. logger.config("user configured to freeze conditions system from monitoring app"); conditionsManager.freeze(); } else { @@ -155,11 +153,11 @@ // Catch all errors and rethrow them as RuntimeExceptions. application.errorHandler.setError(t).setMessage("Error setting up LCSim.").printStackTrace().raiseException(); } - + // Now setup the CompositeLoop. setupLoop(configurationModel); } - + /** * Create the event builder for converting EVIO events to LCSim. */ @@ -178,32 +176,25 @@ // Add the builder as a listener so it is notified when conditions change. ConditionsManager.defaultInstance().addConditionsListener(sessionState.eventBuilder); } - + /** * Setup the loop from the global configuration. * @param configurationModel The global configuration. */ void setupLoop(ConfigurationModel configurationModel) { - CompositeLoopConfiguration loopConfig = new CompositeLoopConfiguration() - .setStopOnEndRun(configurationModel.getDisconnectOnEndRun()) - .setStopOnErrors(configurationModel.getDisconnectOnError()) - .setDataSourceType(configurationModel.getDataSourceType()) - .setProcessingStage(configurationModel.getProcessingStage()) - .setEtConnection(sessionState.connection) - .setFilePath(configurationModel.getDataSourcePath()) - .setLCSimEventBuilder(sessionState.eventBuilder); + CompositeLoopConfiguration loopConfig = new CompositeLoopConfiguration().setStopOnEndRun(configurationModel.getDisconnectOnEndRun()).setStopOnErrors(configurationModel.getDisconnectOnError()).setDataSourceType(configurationModel.getDataSourceType()).setProcessingStage(configurationModel.getProcessingStage()).setEtConnection(sessionState.connection).setFilePath(configurationModel.getDataSourcePath()).setLCSimEventBuilder(sessionState.eventBuilder); if (configurationModel.hasValidProperty(ConfigurationModel.MAX_EVENTS_PROPERTY)) { long maxEvents = configurationModel.getMaxEvents(); if (maxEvents > 0L) { - //logger.config("processing will stop after max events: " + maxEvents); + // logger.config("processing will stop after max events: " + maxEvents); loopConfig.setMaxRecords(maxEvents); } } - + // Add all Drivers from the JobManager. - for (Driver driver : sessionState.jobManager.getDriverExecList()) { + for (Driver driver : sessionState.jobManager.getDriverExecList()) { loopConfig.add(driver); logger.config("added Driver " + driver.getName() + " to job"); } @@ -221,25 +212,25 @@ } // Add extra CompositeRecordProcessors to the loop config. - for (CompositeRecordProcessor processor : processors) { - loopConfig.add(processor); + for (CompositeRecordProcessor processor : processors) { + loopConfig.add(processor); logger.config("added extra processor " + processor.getClass().getSimpleName() + " to job"); } - + // Add extra Drivers to the loop config. - for (Driver driver : drivers) { + for (Driver driver : drivers) { loopConfig.add(driver); logger.config("added extra Driver " + driver.getName() + " to job"); } - + // Enable conditions system activation from EVIO event information. logger.config("added EvioDetectorConditionsProcessor to job with detector " + configurationModel.getDetectorName()); loopConfig.add(new EvioDetectorConditionsProcessor(configurationModel.getDetectorName())); // Create the CompositeLoop with the configuration. - sessionState.loop = new CompositeLoop(loopConfig); - } - + sessionState.loop = new CompositeLoop(loopConfig); + } + /** * Setup a steering file on disk. * @param steering The steering file. @@ -260,14 +251,14 @@ sessionState.jobManager.setup(is); is.close(); } - + synchronized void stop() { - + // Kill session watchdog thread. logger.fine("killing watchdog thread ..."); killWatchdogThread(); logger.fine("watchdog thread killed"); - + // Wake up ET system in case it is blocked in a getEvents() call. if (sessionState.connection != null) { try { @@ -278,58 +269,57 @@ e.printStackTrace(); } } - + // Stop event processing. logger.fine("commanding event processing to stop ..."); sessionState.loop.execute(Command.STOP); logger.fine("event processing commanded to stop"); - + // Cleanup the event processing thread. try { logger.fine("joining on event processing thread ..."); sessionState.processingThread.join(); logger.fine("event processing thread joined"); - + // Invalidate event processing thread. sessionState.processingThread = null; } catch (InterruptedException e) { e.printStackTrace(); } - + // Notify of last error that occurred in event processing. if (sessionState.loop.getLastError() != null) { // Log the error. application.errorHandler.setError(sessionState.loop.getLastError()).log(); } - + // Invalidate loop. sessionState.loop = null; - + // Disconnect from the ET system. logger.fine("disconnecting from ET system ..."); disconnect(); logger.fine("ET system disconnected"); } - - /** - * Start event processing on the event processing thread - * and start the watchdog thread. + + /** + * Start event processing on the event processing thread and start the watchdog thread. */ synchronized void start() { - + logger.fine("event processing threads are starting"); - + // Start the event processing thread. sessionState.processingThread = new EventProcessingThread(sessionState.loop); sessionState.processingThread.start(); - + // Start the watchdog thread which will auto-disconnect when event processing is done. sessionState.sessionWatchdogThread = new SessionWatchdogThread(sessionState.processingThread); sessionState.sessionWatchdogThread.start(); - + logger.fine("started event processing threads"); } - + /** * Notify the event processor to pause processing. */ @@ -341,7 +331,7 @@ } logger.finest("paused"); } - + /** * Get next event if in pause mode. */ @@ -354,7 +344,7 @@ } logger.finest("got next event"); } - + /** * Resume processing events from pause mode. */ @@ -362,12 +352,12 @@ logger.finest("resuming"); if (application.connectionModel.getPaused()) { // Notify event processor to continue. - sessionState.loop.resume(); + sessionState.loop.resume(); application.connectionModel.setPaused(false); } logger.finest("resumed"); } - + /** * Interrupt and join to the processing watchdog thread. */ @@ -392,7 +382,7 @@ } logger.fine("watchdog thread killed"); } - + /** * Cleanup the ET connection. */ @@ -408,7 +398,7 @@ logger.fine("ET connection closed"); } } - + /** * True if the processing thread is active. * @return True if processing thread is active. @@ -416,7 +406,7 @@ boolean isActive() { return sessionState.processingThread != null && sessionState.processingThread.isAlive(); } - + /** * Connect to the ET system using the current connection settings. */ @@ -426,7 +416,11 @@ if (usingEtServer()) { // Create a connection to the ET server. try { + // Create the main ET system connection. createEtConnection(); + + // Add an attachment that listens for DAQ configuration changes. + createEvioDAQConfigStation(); } catch (Exception e) { throw new IOException(e); } @@ -436,15 +430,15 @@ } logger.fine("ET system is connected"); } - + /** * True if using an ET server. * @return True if using an ET server. */ boolean usingEtServer() { return application.configurationModel.getDataSourceType().equals(DataSourceType.ET_SERVER); - } - + } + /** * Create a connection to an ET system using current parameters from the GUI. If successful, the * application's ConnectionStatus is changed to CONNECTED. @@ -456,31 +450,43 @@ if (sessionState.connection != null) { // Set status to connected as there is now a live ET connection. application.connectionModel.setConnectionStatus(ConnectionStatus.CONNECTED); - //logger.info("successfully connected to ET system"); + // logger.info("successfully connected to ET system"); } else { application.errorHandler.setError(new RuntimeException("Failed to create ET connection.")).log().printStackTrace().raiseException(); } } - + + /** + * Create the ET that listens for DAQ configuration change via SYNC events. + */ + void createEvioDAQConfigStation() { + logger.fine("starting EVIO DAQ config station ..."); + EvioDAQConfigStation configStation = new EvioDAQConfigStation(this.sessionState.connection); + configStation.setup(); + Thread configThread = new Thread(configStation); + configThread.start(); + logger.fine("EVIO DAQ config station started"); + } + /** * Disconnect from the current ET session with a particular status. * @param status The connection status. */ synchronized void disconnect() { - + logger.fine("disconnecting"); - + // Cleanup the ET connection. closeEtConnection(); - + // Change application state to disconnected. application.connectionModel.setConnectionStatus(ConnectionStatus.DISCONNECTED); - + logger.fine("disconnected"); - } - - /** - * This class notifies the application to disconnect if the event processing thread completes. + } + + /** + * This class notifies the application to disconnect if the event processing thread completes. */ class SessionWatchdogThread extends Thread { @@ -489,21 +495,23 @@ SessionWatchdogThread(Thread processingThread) { this.processingThread = processingThread; } - + public void run() { try { // When the event processing thread finishes, the session should be stopped and a // disconnect should occur. processingThread.join(); - - // Activate a disconnect using the ActionEvent which is used by the disconnect button. + + // Activate a disconnect using the ActionEvent which is used by the disconnect + // button. logger.fine("processing thread ended so automatic disconnect is happening"); application.actionPerformed(new ActionEvent(Thread.currentThread(), 0, Commands.DISCONNECT)); - + } catch (InterruptedException e) { logger.fine("SessionWatchdogThread got interrupted"); - // This happens when the thread is interrupted by the user pressing the disconnect button. - } + // This happens when the thread is interrupted by the user pressing the disconnect + // button. + } } } } Modified: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/MonitoringApplication.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/MonitoringApplication.java (original) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/MonitoringApplication.java Thu Mar 12 16:53:02 2015 @@ -40,6 +40,7 @@ import org.hps.monitoring.application.LogTable.LogRecordModel; import org.hps.monitoring.application.model.Configuration; import org.hps.monitoring.application.model.ConfigurationModel; +import org.hps.monitoring.application.model.ConnectionStatus; import org.hps.monitoring.application.model.ConnectionStatusModel; import org.hps.monitoring.application.model.RunModel; import org.hps.monitoring.application.util.AIDAServer; @@ -245,7 +246,10 @@ startSession(); } else if (Commands.DISCONNECT.equals(command)) { // TODO: Start this on new thread. - processing.stop(); + //processing.stop(); + System.out.println("MonitoringApplication.actionPerformed - running disconnect thread ..."); + runDisconnectThread(); + System.out.println("MonitoringApplication.actionPerformed - disconnect thread is done!"); } else if (Commands.SAVE_PLOTS.equals(command)) { savePlots(); } else if (Commands.EXIT.equals(command)) { @@ -458,12 +462,12 @@ * Exit from the application. */ void exit() { - if (processing != null && processing.isActive()) { + if (connectionModel.isConnected()) { processing.stop(); } - frame.setVisible(false); logger.info("exiting the application"); logger.getHandlers()[0].flush(); + frame.setVisible(false); System.exit(0); } @@ -803,5 +807,19 @@ frame.menu.stopAIDAServer(); logger.info("AIDA server was stopped"); DialogUtil.showInfoDialog(frame, "AIDA Server Stopped", "The AIDA server was stopped."); - } + } + + /** + * + */ + void runDisconnectThread() { + new Thread() { + public void run() { + logger.fine("disconnect thread is running ..."); + connectionModel.setConnectionStatus(ConnectionStatus.DISCONNECTING); + MonitoringApplication.this.processing.stop(); + logger.fine("disconnect thread finished"); + } + }.run(); + } } Added: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/util/EvioDAQConfigStation.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/util/EvioDAQConfigStation.java (added) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/util/EvioDAQConfigStation.java Thu Mar 12 16:53:02 2015 @@ -0,0 +1,134 @@ +/** + * + */ +package org.hps.monitoring.application.util; + +import java.util.List; + +import org.hps.evio.TriggerConfigEvioReader; +import org.hps.readout.ecal.daqconfig.ConfigurationManager; +import org.hps.readout.ecal.daqconfig.EvioDAQParser; +import org.hps.record.et.EtConnection; +import org.jlab.coda.et.EtAttachment; +import org.jlab.coda.et.EtConstants; +import org.jlab.coda.et.EtEvent; +import org.jlab.coda.et.EtStation; +import org.jlab.coda.et.EtStationConfig; +import org.jlab.coda.et.enums.Mode; +import org.jlab.coda.et.enums.Modify; +import org.jlab.coda.jevio.BaseStructure; +import org.jlab.coda.jevio.EvioEvent; +import org.jlab.coda.jevio.EvioReader; +import org.lcsim.event.base.BaseLCSimEvent; + +/** + * This is an ET station that looks for DAQ configuration events + * from the ET server and updates the global DAQ configuration if + * it finds one. + * + * @author Jeremy McCormick <[log in to unmask]> + */ +public class EvioDAQConfigStation implements Runnable { + + private static final String TRIGGER_CONFIG = "TriggerConfig"; + EtConnection connection; + EtAttachment attachment; + TriggerConfigEvioReader configReader = new TriggerConfigEvioReader(); + EventTagFilter filter = new PhysicsTagFilter(); + + public EvioDAQConfigStation(EtConnection connection) { + this.connection = connection; + } + + public EvioDAQConfigStation(EtConnection connection, EventTagFilter filter) { + this.connection = connection; + this.filter = filter; + } + + public void setup() { + EtStationConfig stationConfig = new EtStationConfig(); + try { + stationConfig.setFlowMode(EtConstants.stationSerial); + stationConfig.setBlockMode(EtConstants.stationNonBlocking); + stationConfig.setPrescale(1); + + EtStation station = connection.getEtSystem().createStation( + stationConfig, + connection.getEtStation().getName() + "_EvioDAQConfigStation", + connection.getEtSystem().getStationPosition(connection.getEtStation()) + 1); + + attachment = connection.getEtSystem().attach(station); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void run() { + for(;;) { + try { + EtEvent[] events = + connection.getEtSystem().getEvents(attachment, Mode.SLEEP, Modify.NOTHING, 0, 100); + for (EtEvent event : events) { + int eventTag = event.getControl()[0]; + if (filter.accept(eventTag)) { + EvioEvent evioEvent = new EvioReader(event.getDataBuffer()).parseNextEvent(); + BaseLCSimEvent lcsimEvent = new BaseLCSimEvent(9999, 9999, "dummy", 0, false); + configReader.getDAQConfig(evioEvent, lcsimEvent); + if (lcsimEvent.hasCollection(EvioDAQParser.class, TRIGGER_CONFIG)) { + List<EvioDAQParser> configList = lcsimEvent.get(EvioDAQParser.class, TRIGGER_CONFIG); + if (!configList.isEmpty()) { + ConfigurationManager.updateConfiguration(configList.get(0)); + } + break; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + break; + } + } + if (connection.getEtSystem().alive()) { + disconnect(); + } + } + + static interface EventTagFilter { + boolean accept(int eventTag); + } + + static class SyncTagFilter implements EventTagFilter { + public boolean accept(int eventTag) { + return (((eventTag >> 6) & 1) == 1); + } + } + + static class PhysicsTagFilter implements EventTagFilter { + public boolean accept(int eventTag) { + return (((eventTag >> 7) & 1) == 1); + } + } + + static boolean hasConfigBank(EvioEvent evioEvent) { + for (BaseStructure bank : evioEvent.getChildrenList()) { + if (bank.getChildCount() <= 0) + continue; + for (BaseStructure subBank : bank.getChildrenList()) { + if (subBank.getHeader().getTag() == EvioDAQParser.BANK_TAG) { + return true; + } + } + } + return false; + } + + public void disconnect() { + try { + connection.getEtSystem().wakeUpAttachment(attachment); + connection.getEtSystem().detach(attachment); + } catch (Exception e) { + e.printStackTrace(); + } + } +} Added: java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/util/MonitoringApplicationEventBuilder.java ============================================================================= --- java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/util/MonitoringApplicationEventBuilder.java (added) +++ java/branches/monitoring-app-dev/src/main/java/org/hps/monitoring/application/util/MonitoringApplicationEventBuilder.java Thu Mar 12 16:53:02 2015 @@ -0,0 +1,44 @@ +package org.hps.monitoring.application.util; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.hps.evio.LCSimEngRunEventBuilder; +import org.hps.record.evio.EvioEventUtilities; +import org.jlab.coda.jevio.EvioEvent; +import org.lcsim.event.EventHeader; + + +/** + * Build LCSim events from EVIO data. + * + * @author Sho Uemura <[log in to unmask]> + * @author Jeremy McCormick <[log in to unmask]> + */ +public class MonitoringApplicationEventBuilder extends LCSimEngRunEventBuilder { + + public MonitoringApplicationEventBuilder() { + super(); + } + + @Override + public EventHeader makeLCSimEvent(EvioEvent evioEvent) { + + if (!EvioEventUtilities.isPhysicsEvent(evioEvent)) { + throw new RuntimeException("Not a physics event: event tag " + evioEvent.getHeader().getTag()); + } + + // Create a new LCSimEvent. + EventHeader lcsimEvent = getEventData(evioEvent); + + // Make RawCalorimeterHit collection, combining top and bottom section + // of ECal into one list. + try { + ecalReader.makeHits(evioEvent, lcsimEvent); + } catch (Exception e) { + Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "Error making ECal hits", e); + } + + return lcsimEvent; + } +}