/** * Update 'global' JMS clients and RDB * * @param pv Alarm PV * @param severity Alarm severity (highest, latched) * @param message Alarm message * @param value Value that triggered * @param timestamp Time of last alarm update */ public void sendGlobalUpdate( final AlarmPV pv, final SeverityLevel severity, final String message, final String value, final Timestamp timestamp) { // Send to JMS messenger.sendGlobalUpdate(pv, severity, message, value, timestamp); // Persist global alarm state change in separate queue & thread // so that it won't delay the alarm server from updating work_queue.execute( new Runnable() { @Override public void run() { try { rdb.writeGlobalUpdate(pv, severity.isActive()); recoverFromRDBErrors(); } catch (Exception ex) { // Remember that there was an error had_RDB_error = true; Activator.getLogger().log(Level.SEVERE, "Exception during global alarm update", ex); } } }); }
/** * Update JMS clients and RDB * * @param pv Alarm PV * @param current_severity Current channel severity * @param current_message Current message * @param severity Alarm severity (highest, latched) * @param message Alarm message * @param value Value that triggered * @param timestamp Time of last alarm update */ public void sendStateUpdate( final AlarmPV pv, final SeverityLevel current_severity, final String current_message, final SeverityLevel severity, final String message, final String value, final Timestamp timestamp) { messenger.sendStateUpdate( pv, current_severity, current_message, severity, message, value, timestamp); // Move the persistence of states into separate queue & thread // so that it won't delay the alarm server from updating. // ReplacableRunnable: // If there is already an update request for this PV on the queue, // replace it with the new one because it's out of date and no // longer needs to be writting to the RDB anyway. work_queue.executeReplacable( new ReplacableRunnable<AlarmPV>(pv) { @Override public void run() { try { rdb.writeStateUpdate( pv, current_severity, current_message, severity, message, value, timestamp); recoverFromRDBErrors(); } catch (Exception ex) { // Remember that there was an error had_RDB_error = true; Activator.getLogger().log(Level.SEVERE, "Exception during alarm state update", ex); } } }); }
/** Invoked for received messages */ private void handleMapMessage(final MapMessage message) { try { final String text = message.getString(JMSLogMessage.TEXT); Runnable action = null; // Create action, or handle the message right away // Alarm state change? if (JMSAlarmMessage.TEXT_STATE.equals(text)) { // Received a state update from server, reset timeout timeout_timer.reset(); action = new UpdateAction(AlarmUpdateInfo.fromMapMessage(message)); model.updateServerState(false); } else if (JMSAlarmMessage.TEXT_STATE_MAINTENANCE.equals(text)) { timeout_timer.reset(); action = new UpdateAction(AlarmUpdateInfo.fromMapMessage(message)); model.updateServerState(true); } // Idle messages in absence of 'real' traffic? else if (JMSAlarmMessage.TEXT_IDLE.equals(text)) { timeout_timer.reset(); model.updateServerState(false); } else if (JMSAlarmMessage.TEXT_IDLE_MAINTENANCE.equals(text)) { timeout_timer.reset(); model.updateServerState(true); } // Enable/disable? else if (JMSAlarmMessage.TEXT_ENABLE.equals(text)) { timeout_timer.reset(); final String name = message.getString(JMSLogMessage.NAME); action = new EnableAction(name, true); } else if (JMSAlarmMessage.TEXT_DISABLE.equals(text)) { timeout_timer.reset(); final String name = message.getString(JMSLogMessage.NAME); action = new EnableAction(name, false); } // Configuration change else if (JMSAlarmMessage.TEXT_CONFIG.equals(text)) { final String name = message.getString(JMSLogMessage.NAME); model.readConfig(name); } // Debug trigger else if (JMSAlarmMessage.TEXT_DEBUG.equals(text)) model.dump(); if (action == null) return; // Queue or dispatch? synchronized (queue) { if (use_queue) { queue.execute(action); return; } } // else: Not using queue, and queue no longer locked action.run(); } catch (Throwable ex) { Activator.getLogger().log(Level.SEVERE, "Message handler error", ex); } }
/** * If this is the first successful RDB update after errors, tell everybody to re-load the * configuration because otherwise they get out of sync. * * @throws Exception on error */ protected void recoverFromRDBErrors() throws Exception { if (!had_RDB_error) return; // We should be on the work queue thread work_queue.assertOnThread(); Activator.getLogger().info("RDB connection recovered, re-loading configuration"); updateConfig(null); // If that worked out, reset error and inform clients had_RDB_error = false; messenger.sendReloadMessage(); }
/** * Update JMS clients and RDB about 'enabled' state of PV * * @param pv Alarm PV * @param enabled Enabled or not? */ public void sendEnablementUpdate(final AlarmPV pv, final boolean enabled) { messenger.sendEnablementUpdate(pv, enabled); // Handle in separate queue & thread work_queue.execute( new Runnable() { @Override public void run() { try { rdb.writeEnablementUpdate(pv, enabled); recoverFromRDBErrors(); } catch (Exception ex) { // Remember that there was an error had_RDB_error = true; Activator.getLogger().log(Level.SEVERE, "Exception during enablement update", ex); } } }); }
/** Dump all PVs to stdout */ public void dump() { System.out.println("== Alarm Server PV Snapshot =="); synchronized (this) { alarm_tree.dump(System.out); } System.out.println("Work queue size: " + work_queue.size()); // Log memory usage in MB final double free = Runtime.getRuntime().freeMemory() / (1024.0 * 1024.0); final double total = Runtime.getRuntime().totalMemory() / (1024.0 * 1024.0); final double max = Runtime.getRuntime().maxMemory() / (1024.0 * 1024.0); final DateFormat format = new SimpleDateFormat(JMSLogMessage.DATE_FORMAT); System.out.format( "%s == Alarm Server Memory: Max %.2f MB, Free %.2f MB (%.1f %%), total %.2f MB (%.1f %%)\n", format.format(new Date()), max, free, 100.0 * free / max, total, 100.0 * total / max); }
/** * Dispatch queued events, or directly dispatch received events? * * <p>While reading model information, queue mode should be enabled. Then, after model information * from RDB has been obtained, disable queue mode which also dispatched all the queued up events. * * @param use_queue <code>true</code> to queue */ public void setQueueMode(final boolean use_queue) { this.use_queue = use_queue; if (use_queue) return; // Queuing turned off -> Dispatched what has accumulated until now queue.performQueuedCommands(); }