/**
  * 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);
           }
         }
       });
 }
  /** 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);
    }
  }
 /**
  * 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);
           }
         }
       });
 }