package cern.laser.business.pojo; import java.sql.Timestamp; import java.text.ParseException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Logger; import javax.jms.Message; import javax.jms.TextMessage; import alma.alarmsystem.core.alarms.LaserCoreFaultState.LaserCoreFaultCodes; import alma.alarmsystem.statistics.StatsCalculator; import cern.laser.business.cache.AlarmCacheException; import cern.laser.business.dao.SourceDAO; import cern.laser.business.data.Alarm; import cern.laser.business.data.Source; import cern.laser.business.data.Status; import cern.laser.business.data.Triplet; import cern.laser.source.alarmsysteminterface.AlarmSystemInterfaceFactory; import cern.laser.source.alarmsysteminterface.FaultState; import cern.laser.source.alarmsysteminterface.impl.ASIMessageHelper; import cern.laser.source.alarmsysteminterface.impl.XMLMessageHelper; import cern.laser.source.alarmsysteminterface.impl.message.ASIMessage; import cern.laser.util.LogTimeStamp; import com.cosylab.acs.laser.LaserComponent; import com.cosylab.acs.laser.dao.ACSAlarmCacheImpl; import alma.acs.logging.AcsLogLevel; import alma.acs.util.IsoDateFormat; /** * CERN documentation is missing unfortunately... Below you can find ACS documentation of the changes * done on top of the CERN class. * <P> * The <code>AlarmMessageProcessorImpl</code> checks the timestamp of the alarms it receives from the NC * and publishes a core alarm ({@link LaserCoreFaultCodes#ALARMS_TOO_OLD}) * if the delay between the actual time and the timestamp exceeds the threshold ({@link #delayThreashold}). * The check is done in this class because this is the place where alarms from sources are checked. * <BR> * To ensure that the alarm is set/cleared even if the alarms server does not process alarms, * the check is done by the thread in {@link #createTimerTask()}. * <BR> * This feature is tested in the <code>alarmTest</code> module. * * @author acaproni * */ public class AlarmMessageProcessorImpl { private SourceDAO sourceDAO; private ACSAlarmCacheImpl alarmCache; /** * Helper class to record, for each time interval, the biggest delay between * the actual time and the timestamp of alarms. * * @author acaproni * @since ACS 11.1 * */ private final class AlarmsDelayHelper { /** * Set to the bigger delay between the actual time and the message timestamp in * the current time interval */ private long largestDelay = 0; /** * Check the passed timestamp against the actual time and * update the delay ({@link #largestDelay}) accordingly * * @param timestamp The timestamp of a alarm * @throws RuntimeException If the timestamp is ahead of the actual time */ public synchronized void updateDelay(long timestamp) throws RuntimeException { long delay=System.currentTimeMillis()-timestamp; if (delay<0) { // This should never happen if the timestamp has been correctly set by // the API. throw new RuntimeException("The timestamp is ahead of actual time"); } if (delay> largestDelay) { largestDelay=delay; } } /** * Check if the alarms are processed too late i.e. if their oldest timestamp in the last * time interval has been greater then the threshold. * <BR>This method reset the delay to be ready to check the delay during a new time interval. * * @return <code>true</code> if the delay has been greater then the threshold */ public synchronized boolean chekDelayAndReset() { boolean ret=largestDelay>AlarmMessageProcessorImpl.delayThreashold; largestDelay=0; return ret; } } /** * The helper to check the timestamp of alarms against the actual time */ private final AlarmsDelayHelper alarmsDelayHelper = new AlarmsDelayHelper(); /** * If the timestamp of alarms and the actual time differ of more then * <code>delayThreashold</code> then a core alarm is issued. */ public static final long delayThreashold=TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES); // 5 min /** * Do not publish twice the alarm unless its state changed. * <P> * Actually the alarm server itself does this check but we do not want * to process this alarm every interval unless its state changed * (to reduce the load on the server). * <P> * Note that there is no need to synchronize on this variable * Because it used only by the timer thread to issue or not * a new alarm. */ private boolean alarmTooOldActive=false; /** * The logger */ private final Logger logger; /** * The number of alarms processed in the past {@link #alarmTimestampsCheckInterval}; */ private final AtomicInteger alarmsProcessed = new AtomicInteger(0); /** * The timestamp of alarms is checked every <code>alarmTimestamsCheckInterval</code> * to reduce the risk to fill the alarm system publishing this alarm too often. */ public static final long alarmTimestampsCheckInterval=TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES); // 5 min /** * The LaserComponent to publish core alarms */ private final LaserComponent laserComponent; /** * The timer to check the delay and do periodic tasks. */ private final Timer timer = new Timer("AlarmMessageProcessorTimer",true); /** * The engine to calculate statistics */ private final StatsCalculator statisticsEngine; /** * Constructor * * @param component The {@link LaserComponent} */ public AlarmMessageProcessorImpl(LaserComponent component,Logger logger, StatsCalculator statsCalculator) { if (component==null) { throw new IllegalArgumentException("The LaserComponent can't be null"); } if (logger==null) { throw new IllegalArgumentException("The logger can't be null"); } if (statsCalculator==null) { throw new IllegalArgumentException("The StatsCalculator can't be null"); } laserComponent=component; this.logger=logger; this.statisticsEngine=statsCalculator; } // // -- PUBLIC METHODS ---------------------------------------------- // public void setSourceDAO(SourceDAO sourceDAO) { this.sourceDAO = sourceDAO; } public void setAlarmCache(ACSAlarmCacheImpl alarmCache) { this.alarmCache = alarmCache; } public void notifyReductionRelatives(Alarm alarm) { try { logger.log(AcsLogLevel.DEBUG,"notifying reduction relatives for " + alarm.getTriplet() + "..."); notifyNodeChildren(alarm); notifyMultiplicityChildren(alarm); notifyMultiplicityParents(alarm); logger.log(AcsLogLevel.DEBUG,"notified"); } catch (Exception e) { logger.log(AcsLogLevel.ERROR,"unable to notify reduction relatives for " + alarm.getTriplet(), e); } } public void process(Message alarmMessage) throws Exception { if (alarmMessage instanceof TextMessage) { TextMessage text_message = (TextMessage) alarmMessage; } logger.log(AcsLogLevel.DEBUG,"processing message...", true); if (alarmMessage instanceof TextMessage) { TextMessage text_message = (TextMessage) alarmMessage; String xml_message = text_message.getText(); process(xml_message); } else { throw new Exception("TextMessage expected"); } logger.log(AcsLogLevel.DEBUG,"message processed"); } /** * Process a message * * @param xml the XML message to unmarshall into a <code>ASIMessage</code> */ public void process(String xml) throws Exception { ASIMessage asi_message = XMLMessageHelper.unmarshal(xml); logger.log(AcsLogLevel.DEBUG,"message from " + asi_message.getSourceName() + "@" + asi_message.getSourceHostname()); if (asi_message.getBackup()) { logger.log(AcsLogLevel.DEBUG,"processing backup..."); processBackup(asi_message); logger.log(AcsLogLevel.DEBUG,"backup processed"); } else { logger.log(AcsLogLevel.DEBUG,"processing change..."); processChanges(asi_message); logger.log(AcsLogLevel.DEBUG,"change processed"); } // One alarm more has been processed! alarmsProcessed.incrementAndGet(); // Check for the delay comparing the actual time with the timestamp // of the processed message try { long timestamp = IsoDateFormat.parseIsoTimestamp(asi_message.getSourceTimestamp()).getTime(); alarmsDelayHelper.updateDelay(timestamp); } catch (ParseException pe) { logger.log(AcsLogLevel.ERROR,"Error parsing a ISO timestamp: "+asi_message.getSourceTimestamp(), pe); } } public void processChange(FaultState faultState, String sourceName, String sourceHostname, Timestamp sourceTimestamp) throws Exception { alarmCache.acquire(); try { logger.log(AcsLogLevel.DEBUG,"processing fault state: " + faultState.getFamily()+":"+faultState.getMember()+":"+faultState.getCode()+", Descriptor="+faultState.getDescriptor()+"\n"); Timestamp system_timestamp = new Timestamp(System.currentTimeMillis()); Alarm alarm = alarmCache.getCopy( Triplet.toIdentifier(faultState.getFamily(), faultState.getMember(), Integer.valueOf(faultState.getCode()))); // process the change String defined_source_name = alarm.getSource().getName(); if (!defined_source_name.equals(sourceName)) { logger.log(AcsLogLevel.ERROR,"source name mismatch : received " + sourceName + ", should be " + defined_source_name + ".\nFault State was discarded :\n" + faultState); } else { Status current_status = alarm.getStatus(); boolean ordered = true; // check if fault state changes were received in the right order if ((current_status.getUserTimestamp() != null) && (faultState.getUserTimestamp() != null)) { if (faultState.getUserTimestamp().before(current_status.getUserTimestamp())) { logger.log(AcsLogLevel.ERROR,"user timestamp not ordered : received " + faultState.getUserTimestamp() + ", was " + current_status.getUserTimestamp() + ".\nFault State was discarded :\n" + faultState); ordered = false; } } else { if (sourceTimestamp.before(current_status.getSourceTimestamp())) { logger.log(AcsLogLevel.ERROR,"source timestamp not ordered : received " + sourceTimestamp + ", was " + current_status.getSourceTimestamp() + ".\nFault State was discarded :\n" + faultState); ordered = false; } } if (ordered) { // StatusImpl new_status = null; // StatusImpl alarm_status = alarm.getStatus(); boolean notify_reduction_relatives = false; boolean alarm_updated = false; if (alarm.getInstant().booleanValue()) { if (faultState.getDescriptor().equalsIgnoreCase(FaultState.INSTANT)) { // process INSTANT fault state updateStatus(faultState, current_status, Boolean.TRUE, sourceHostname, sourceTimestamp, system_timestamp); alarm_updated = true; // new_status = new StatusImpl(Boolean.TRUE, current_status.getMasked(), current_status.getReduced(), new // Boolean( // faultState.getActivatedByBackup()), new Boolean(faultState.getTerminatedByBackup()), sourceHostname, // sourceTimestamp, faultState.getUserTimestamp(), system_timestamp, faultState.getUserProperties()); } else { logger.log(AcsLogLevel.ERROR,"invalid fault descriptor : received " + faultState.getDescriptor() + " while expecting " + FaultState.INSTANT + ".\nFault State was discarded :\n" + faultState); } } else { if (faultState.getDescriptor().equalsIgnoreCase(FaultState.ACTIVE)) { // process ACTIVE fault state if (alarm.getStatus().getActive().equals(Boolean.FALSE)) { updateStatus(faultState, current_status, Boolean.TRUE, sourceHostname, sourceTimestamp, system_timestamp); // new_status = new StatusImpl(Boolean.TRUE, current_status.getMasked(), current_status.getReduced(), // new Boolean(faultState.getActivatedByBackup()), new Boolean(faultState.getTerminatedByBackup()), // sourceHostname, sourceTimestamp, faultState.getUserTimestamp(), system_timestamp, faultState // .getUserProperties()); notify_reduction_relatives = true; alarm_updated = true; } else { logger.log(AcsLogLevel.WARNING,"Alarm already active: Fault State "+alarm.getAlarmId()+" discarded"); } } else if (faultState.getDescriptor().equalsIgnoreCase(FaultState.TERMINATE)) { // process TERMINATE fault state if (alarm.getStatus().getActive().equals(Boolean.TRUE)) { updateStatus(faultState, current_status, Boolean.FALSE, sourceHostname, sourceTimestamp, system_timestamp); // new_status = new StatusImpl(Boolean.FALSE, current_status.getMasked(), current_status.getReduced(), // new Boolean(faultState.getActivatedByBackup()), new Boolean(faultState.getTerminatedByBackup()), // sourceHostname, sourceTimestamp, faultState.getUserTimestamp(), system_timestamp, faultState // .getUserProperties()); notify_reduction_relatives = true; alarm_updated = true; } else { logger.log(AcsLogLevel.WARNING,"Alarm already terminated: Fault State "+alarm.getAlarmId()+" discarded"); } } else if (faultState.getDescriptor().equalsIgnoreCase(FaultState.CHANGE)) { // process CHANGE fault state if (alarm.getStatus().getActive().equals(Boolean.FALSE)) { logger.log(AcsLogLevel.ERROR,"changed alarm was terminated : " + alarm.getAlarmId()); notify_reduction_relatives = true; } else { updateStatus(faultState, current_status, Boolean.TRUE, sourceHostname, sourceTimestamp, system_timestamp); // new_status = new StatusImpl(Boolean.TRUE, current_status.getMasked(), current_status.getReduced(), new // Boolean( // faultState.getActivatedByBackup()), new Boolean(faultState.getTerminatedByBackup()), sourceHostname, // sourceTimestamp, faultState.getUserTimestamp(), system_timestamp, faultState.getUserProperties()); alarm_updated = true; } } else { logger.log(AcsLogLevel.ERROR,"invalid fault descriptor : received " + faultState.getDescriptor() + " while expecting " + FaultState.ACTIVE + "|" + FaultState.TERMINATE + "|" + FaultState.CHANGE + ".\nFault State was discarded :\n" + faultState); } } // if (new_status != null) { if (alarm_updated) { // alarm.setStatus(new_status); logger.log(AcsLogLevel.DEBUG,"applying change..."); if (alarm.getSource()!=null && sourceHostname!=null) { alarm.getSource().setHostName(sourceHostname.toLowerCase()); } alarmCache.put(alarm); if (notify_reduction_relatives) { notifyReductionRelatives(alarm); } } } } } finally { alarmCache.release(); logger.log(AcsLogLevel.DEBUG,"processed fault state:" + faultState.getFamily()+":"+faultState.getMember()+":"+faultState.getCode()+", Descriptor="+faultState.getDescriptor()+"\n"); } } private void updateStatus(FaultState faultState, Status currentStatus, Boolean active, String sourceHostname, Timestamp sourceTimestamp, Timestamp system_timestamp) { currentStatus.setActive(active); currentStatus.setActivatedByBackup(new Boolean(faultState.getActivatedByBackup())); currentStatus.setTerminatedByBackup(new Boolean(faultState.getTerminatedByBackup())); currentStatus.setSourceHostname(sourceHostname); currentStatus.setSourceTimestamp(sourceTimestamp); currentStatus.setUserTimestamp(faultState.getUserTimestamp()); currentStatus.setSystemTimestamp(system_timestamp); String alarmServerProp = currentStatus.getProperties().getProperty(ACSAlarmCacheImpl.alarmServerPropkey); currentStatus.setProperties(faultState.getUserProperties()); if (alarmServerProp!=null) { currentStatus.getProperties().put(ACSAlarmCacheImpl.alarmServerPropkey, alarmServerProp); } } public void updateMultiplicityNode(Alarm alarm) { try { if (hasTooManyActiveMultiplicityChildren(alarm)) { if (alarm.getStatus().getActive().equals(Boolean.FALSE)) { // activate multiplicity parent logger.log(AcsLogLevel.DEBUG,"Activating multiplicity parent " + alarm.getTriplet()); alarm.getStatus().setActive(Boolean.TRUE); Timestamp current_time = new Timestamp(System.currentTimeMillis()); alarm.getStatus().setSourceTimestamp(current_time); alarm.getStatus().setUserTimestamp(current_time); alarm.getStatus().setSystemTimestamp(current_time); alarmCache.put(alarm); notifyReductionRelatives(alarm); } } else { if (alarm.getStatus().getActive().equals(Boolean.TRUE)) { // terminate multiplicity parent logger.log(AcsLogLevel.DEBUG,"Terminating multiplicity parent " + alarm.getTriplet()); alarm.getStatus().setActive(Boolean.FALSE); Timestamp current_time = new Timestamp(System.currentTimeMillis()); alarm.getStatus().setSourceTimestamp(current_time); alarm.getStatus().setUserTimestamp(current_time); alarm.getStatus().setSystemTimestamp(current_time); alarmCache.put(alarm); notifyReductionRelatives(alarm); } } } catch (Exception e) { logger.log(AcsLogLevel.ERROR,"Unable to update multiplicity node for " + alarm.getTriplet(), e); } } public void updateReductionStatus(Alarm alarm) { try { logger.log(AcsLogLevel.DEBUG,"Updating reduction status for alarm : " + alarm); if (alarm.getStatus().getReduced().equals(Boolean.TRUE)) { if ((!hasActiveNodeParents(alarm)) && (!hasActiveMultiplicityParents(alarm))) { alarm.getStatus().setReduced(Boolean.FALSE); alarmCache.put(alarm); } } else { if (hasActiveNodeParents(alarm) || hasActiveMultiplicityParents(alarm)) { alarm.getStatus().setReduced(Boolean.TRUE); alarmCache.put(alarm); } } logger.log(AcsLogLevel.DEBUG,"updated"); } catch (Exception e) { logger.log(AcsLogLevel.ERROR,"Unable to update reduction status for " + alarm.getTriplet(), e); } } // // -- PRIVATE METHODS --------------------------------------------- // private boolean isMultiplicityParent(Alarm alarm) { return alarm.hasMultiplicityChildren(); } private boolean isNodeParent(Alarm alarm) { return alarm.hasNodeChildren(); } private boolean hasActiveMultiplicityParents(Alarm alarm) throws Exception { String[] parents = alarm.getMultiplicityParents(); for (int i = 0; i < parents.length; i++) { Alarm parent = alarmCache.getReference(parents[i]); if (parent.getStatus().getActive().booleanValue()) { return true; } } return false; } private boolean hasActiveNodeParents(Alarm alarm) throws Exception { String[] parents = alarm.getNodeParents(); for (int i = 0; i < parents.length; i++) { Alarm parent = alarmCache.getReference(parents[i]); if (parent.getStatus().getActive().booleanValue()) { return true; } } return false; } private boolean hasTooManyActiveMultiplicityChildren(Alarm alarm) throws Exception { int active_children = 0; String[] children = alarm.getMultiplicityChildren(); for (int i = 0; i < children.length; i++) { Alarm child = alarmCache.getReference(children[i]); if (child.getStatus().getActive().booleanValue()) { active_children++; } } return (active_children > alarm.getMultiplicityThreshold().intValue()); } private void processBackup(ASIMessage asiMessage) throws Exception { String source_name = asiMessage.getSourceName(); String source_hostname = asiMessage.getSourceHostname(); String source_timestamp = asiMessage.getSourceTimestamp(); logger.log(AcsLogLevel.DEBUG,"processing backup from " + source_name + "@" + source_hostname + " [" + source_timestamp + "]"); Source source = sourceDAO.findSource(source_name); logger.log(AcsLogLevel.DEBUG,"getting active alarms..."); String[] source_alarm_ids = sourceDAO.getAlarms(source.getSourceId()); Collection active_alarms = new ArrayList(source_alarm_ids.length); for (int i = 0; i < source_alarm_ids.length; i++) { Alarm alarm = alarmCache.getReference(source_alarm_ids[i]); if (alarm.getStatus().getActive().booleanValue() && (!alarm.getInstant().booleanValue())) { active_alarms.add(alarm); } } logger.log(AcsLogLevel.DEBUG,"checking backup..."); // check if backup alarms match active alarms for the same source Set active_identifiers = new HashSet(); Iterator active_alarms_iterator = active_alarms.iterator(); while (active_alarms_iterator.hasNext()) { active_identifiers.add(((Alarm) active_alarms_iterator.next()).getAlarmId()); } Collection<FaultState> backup_fault_states = ASIMessageHelper.unmarshal(asiMessage); logger.log(AcsLogLevel.DEBUG,"processing " + backup_fault_states.size() + " backup alarms"); Set<String> backup_identifiers = new HashSet<String>(); for (FaultState fault_state: backup_fault_states) { // Before notify the statistics that a alarm is going to be processed String alarmID=Triplet.toIdentifier( fault_state.getFamily(), fault_state.getMember(), Integer.valueOf(fault_state.getCode())); statisticsEngine.processedFS(alarmID, fault_state.getDescriptor().equals(FaultState.ACTIVE)); backup_identifiers.add(alarmID); } logger.log(AcsLogLevel.DEBUG,asiMessage.getSourceName() + " : " + active_identifiers.size() + " active alarms found, received " + backup_identifiers.size()); if ((backup_identifiers.containsAll(active_identifiers)) && (active_identifiers.containsAll(backup_identifiers))) { logger.log(AcsLogLevel.DEBUG,"backup matches active alarms"); } else { logger.log(AcsLogLevel.WARNING,"backup mismatch"); logger.log(AcsLogLevel.DEBUG,"alarms found :\n" + active_identifiers); logger.log(AcsLogLevel.DEBUG,"alarms received :\n" + backup_identifiers); Iterator backup_identifiers_iterator = backup_identifiers.iterator(); while (backup_identifiers_iterator.hasNext()) { if (active_identifiers.remove(backup_identifiers_iterator.next())) { backup_identifiers_iterator.remove(); } } if (!backup_identifiers.isEmpty()) { logger.log(AcsLogLevel.WARNING,backup_identifiers.size() + " backup alarms are not active"); logger.log(AcsLogLevel.DEBUG,"active by backup :\n" + backup_identifiers); for (FaultState fault_state: backup_fault_states) { if (backup_identifiers.contains(Triplet.toIdentifier(fault_state.getFamily(), fault_state.getMember(), new Integer(fault_state.getCode())))) { fault_state.setDescriptor(FaultState.ACTIVE); fault_state.setActivatedByBackup(true); try { Timestamp timestamp = new Timestamp(IsoDateFormat.parseIsoTimestamp(source_timestamp).getTime()); processChange(fault_state, source_name, source_hostname, timestamp); } catch (Exception e) { logger.log(AcsLogLevel.ERROR,"unable to activate alarm by backup", e); } } } } if (!active_identifiers.isEmpty()) { logger.log(AcsLogLevel.WARNING,active_identifiers.size() + " active alarms are not in backup"); logger.log(AcsLogLevel.DEBUG,"terminate by backup :\n" + active_identifiers); active_alarms_iterator = active_alarms.iterator(); while (active_alarms_iterator.hasNext()) { Alarm alarm = (Alarm) active_alarms_iterator.next(); if (active_identifiers.contains(alarm.getAlarmId())) { FaultState fault_state = AlarmSystemInterfaceFactory.createFaultState(alarm.getTriplet().getFaultFamily(), alarm.getTriplet().getFaultMember(), alarm.getTriplet().getFaultCode().intValue()); fault_state.setUserTimestamp(new Timestamp(System.currentTimeMillis())); fault_state.setUserProperties(alarm.getStatus().getProperties()); fault_state.setDescriptor(FaultState.TERMINATE); fault_state.setTerminatedByBackup(true); try { Timestamp timestamp = new Timestamp(IsoDateFormat.parseIsoTimestamp(source_timestamp).getTime()); processChange(fault_state, source_name, source_hostname, timestamp); } catch (Exception e) { logger.log(AcsLogLevel.ERROR,"unable to terminate alarm by backup", e); } } } } } source.getStatus().setLastContact(new Timestamp(System.currentTimeMillis())); sourceDAO.updateSource(source); logger.log(AcsLogLevel.DEBUG,"backup processed"); } private void processChanges(ASIMessage asiMessage) { String source_name = asiMessage.getSourceName(); String source_hostname = asiMessage.getSourceHostname(); String source_timestamp = asiMessage.getSourceTimestamp(); logger.log(AcsLogLevel.DEBUG,"processing changes from " + source_name + "@" + source_hostname + " [" + source_timestamp + "]"); Collection<FaultState> change_fault_states = ASIMessageHelper.unmarshal(asiMessage); logger.log(AcsLogLevel.DEBUG,"processing " + change_fault_states.size() + " changes"); for (FaultState fault_state: change_fault_states) { try { // Notify the statistics that a alarm is going to be processed String alarmID=Triplet.toIdentifier( fault_state.getFamily(), fault_state.getMember(), Integer.valueOf(fault_state.getCode())); statisticsEngine.processedFS(alarmID, fault_state.getDescriptor().equals(FaultState.ACTIVE)); Timestamp timestamp = new Timestamp(IsoDateFormat.parseIsoTimestamp(source_timestamp).getTime()); processChange(fault_state, source_name, source_hostname, timestamp); } catch (Throwable t) { logger.log(AcsLogLevel.ERROR,"exception caught processing fault state : \n" + fault_state, t); } } logger.log(AcsLogLevel.DEBUG,"changes processed"); } private void notifyNodeChildren(Alarm alarm) throws Exception { String[] children = alarm.getNodeChildren(); for (int i = 0; i < children.length; i++) { Alarm child = alarmCache.getCopy(children[i]); logger.log(AcsLogLevel.DEBUG,"notifying node child " + child.getTriplet()); if (hasActiveNodeParents(child)) { if (child.getStatus().getReduced().equals(Boolean.FALSE)) { logger.log(AcsLogLevel.DEBUG,"reducing node child " + child.getTriplet()); child.getStatus().setReduced(Boolean.TRUE); alarmCache.put(child); } } else { if (child.getStatus().getReduced().equals(Boolean.TRUE)) { logger.log(AcsLogLevel.DEBUG,"unreducing node child " + child.getTriplet()); child.getStatus().setReduced(Boolean.FALSE); alarmCache.put(child); } } } } private void notifyMultiplicityChildren(Alarm alarm) throws Exception { String[] children = alarm.getMultiplicityChildren(); for (int i = 0; i < children.length; i++) { Alarm child = alarmCache.getCopy(children[i]); logger.log(AcsLogLevel.DEBUG,"notifying multiplicity child " + child.getTriplet()); if (hasActiveMultiplicityParents(child)) { if (child.getStatus().getReduced().equals(Boolean.FALSE)) { logger.log(AcsLogLevel.DEBUG,"reducing multiplicity child " + child.getTriplet()); child.getStatus().setReduced(Boolean.TRUE); alarmCache.put(child); } } else { if (child.getStatus().getReduced().equals(Boolean.TRUE)) { logger.log(AcsLogLevel.DEBUG,"unreducing multiplicity child " + child.getTriplet()); child.getStatus().setReduced(Boolean.FALSE); alarmCache.put(child); } } } } private void notifyMultiplicityParents(Alarm alarm) throws Exception { String[] parents = alarm.getMultiplicityParents(); for (int i = 0; i < parents.length; i++) { Alarm parent = alarmCache.getCopy(parents[i]); logger.log(AcsLogLevel.DEBUG,"notifying multiplicity parent " + parent.getTriplet()); updateMultiplicityNode(parent); } } private void dumpAlarm(Alarm alarm) { System.out.print ("\t"+alarm.getAlarmId()+", active="+alarm.getStatus().getActive()); System.out.print (", reduced="+alarm.getStatus().getReduced()); System.out.println(", masked="+alarm.getStatus().getMasked()); } /** * Print on the stdout the state of the reduction of the passed alarm. * * @param alarm */ private void dumpAlarmReductionStatus(Alarm alarm) throws AlarmCacheException { System.out.print("Reduction state of "+alarm.getAlarmId()+", active="+alarm.getStatus().getActive()); System.out.print(", isReduced="+alarm.getStatus().getReduced()); System.out.println(", isMasked="+alarm.getStatus().getMasked()); System.out.println("NODE Parents:"); String[] nodeP=alarm.getNodeParents(); for (String id: nodeP) { Alarm parent=alarmCache.getReference(id); dumpAlarm(parent); } System.out.println("NODE Childs:"); String[] nodeC=alarm.getNodeChildren(); for (String id: nodeC) { Alarm child=alarmCache.getReference(id); dumpAlarm(child); } System.out.println("MULTIPLICITY Parents:"); String[] multiP=alarm.getMultiplicityParents(); for (String id: multiP) { Alarm parent=alarmCache.getReference(id); dumpAlarm(parent); } System.out.println("MULTIPLICITY Childs:"); String[] multiC=alarm.getMultiplicityChildren(); for (String id: multiC) { Alarm child=alarmCache.getReference(id); dumpAlarm(child); } } private TimerTask createTimerTask() { TimerTask task = new TimerTask() { @Override public void run() { // Logs the number of alarms processed in the past interval (and reset the counter) logger.log(AcsLogLevel.DEBUG,""+alarmsProcessed.getAndSet(0)+" alarms processed in the past 5 mins"); // Check if the delay alarm must be published boolean alarmsAreTooLate=alarmsDelayHelper.chekDelayAndReset(); if (alarmsAreTooLate!=alarmTooOldActive) { // Process the core alarm only if its state changed laserComponent.sendCoreAlarmAsync(LaserCoreFaultCodes.ALARMS_TOO_OLD,alarmsAreTooLate); alarmTooOldActive=alarmsAreTooLate; } } }; return task; } /** * Start the periodic task */ public void start() { timer.schedule(createTimerTask(), alarmTimestampsCheckInterval, alarmTimestampsCheckInterval); } /** * Stop the periodic task */ public void stop() { timer.cancel(); } }