/* * Licensed Materials - Property of Perforce Software, Inc. * © Copyright Perforce Software, Inc. 2014, 2021 * © Copyright IBM Corp. 2009, 2014 * © Copyright ILOG 1996, 2009 * All Rights Reserved. * * Note to U.S. Government Users Restricted Rights: * The Software and Documentation were developed at private expense and * are "Commercial Items" as that term is defined at 48 CFR 2.101, * consisting of "Commercial Computer Software" and * "Commercial Computer Software Documentation", as such terms are * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4, * as applicable. */ package monitoring.generator; import ilog.cpl.datasource.DataSourceEvent; import ilog.cpl.datasource.DataSourceListener; import ilog.cpl.datasource.DataSourceObjectEvent; import ilog.cpl.datasource.IlpDataSource; import ilog.cpl.datasource.IlpMutableDataSource; import ilog.cpl.model.IlpObject; import ilog.tgo.model.IltAlarm; import ilog.tgo.model.IltNetworkElement; import ilog.views.util.IlvResourceUtil; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Random; import java.util.logging.Level; import java.util.logging.Logger; /** * Abstact alarm generator that is to be used as a base for all alarm generator * as it provides some common code. */ abstract public class AbstractAlarmGenerator { /** * Contains the number of live threads that are actively generating alarms. */ private static int alarmGenerationLiveThreadCount = 0; /** Support for logging. */ protected static Logger log = Logger.getLogger("generator"); /** * Random number generator used to randomly select property values from * arrays. */ protected Random randomGenerator; /** The thread used to automatically generate new alarms. */ protected AlarmGeneratorThread alarmGenerationThread; /** Data source to retrieve the managed objects that have alarms. */ protected IlpMutableDataSource moDataSource; /** * Cache with all business objects in the datasource to randomly choose * an object when generating alarms. */ protected Object[] moiCache; /** * List of alarms that have been generated and that can be changed. This list * is used as a basis for randomly selecting existing alarms to change. */ protected List<Object> generatedAlarms; /** * The maximum number of alarms to be generated. After this number is reached * no more alarms will be generated. */ protected int maxNumberOfAlarms; /** Period (in ms) to wait between each alarm. */ protected int waitPeriod; /** * List of possible alarm types. This array contains all the defined alarm * types and is used as a basis for randomly selecting an alarm type when * creating a new alarm event. */ protected static Object[] ALARM_TYPES; /** * List of possible alarm severities. This is an array containing all the * defined severities (except <code>CLEARED</code>). The array is used as a * source for selecting a random severity. */ protected static Object[] ALARM_SEVERITIES; /** * List of probable causes. This is an array of selected causes that is used * as a source for selecting a random cause. This is not an exhaustive list. */ protected static Object[] PROBABLE_CAUSES; /** * List of possible alarm trends. This array contains a set of defined * alarm trends and is used as a basis for randomly selecting an alarm trend. * <code>TrendIndicationType.NO_CHANGE</code> is repeated several times to * weigh the probablility for it being picked. */ protected static Object[] ALARM_TRENDS; /** * The system identifier used by the generator. */ protected String systemId; /** * The user identifier used by the generator. */ protected String userId; /** * Creates an alarm generator. * * @param period Interval between the generation of two alarm * events. * @param maxNumberOfAlarms The maximum number of alarms to be generated. * * @param moDataSource The data source containing the managed objects * used as Managed Object Instances for the generated * alarms. */ public AbstractAlarmGenerator(int period, int maxNumberOfAlarms, IlpMutableDataSource moDataSource) { this.waitPeriod = period; this.moDataSource = moDataSource; this.maxNumberOfAlarms = maxNumberOfAlarms; // Cache to the objects in the datasource this.moiCache = null; // Listen to datasource changes so that when they occur the cache // is cleared this.moDataSource.addDataSourceListener(new DataSourceListener() { Override public void batchEnded(DataSourceEvent e) { } Override public void batchStarted(DataSourceEvent e) { } Override public void objectsAdded(DataSourceEvent e) { clearMOICache(); } Override public void objectsRemoved(DataSourceEvent e) { clearMOICache(); } Override public void objectAttributeChanged(DataSourceObjectEvent e) { } Override public void objectStructureChanged(DataSourceObjectEvent e) { } }); this.randomGenerator = new Random(new Date().getTime()); this.generatedAlarms = new ArrayList<Object>(maxNumberOfAlarms); } /** * Should initialize the internal structures. This particular implementation * does nothing. All subclasses must override this * method to initialize the arrays of types for alarm trends, probable causes, * alarm severities, and alarm types. * <p> * This method must be called just once, at initialization time. */ public static void initialize() { } /** * Should generate a single new alarm. */ abstract protected void generateOneAlarm(); /** * Should clears the given alarm. */ abstract public void clearOneAlarm(Object alarm); /** * Should remove all alarms. */ abstract public void removeAllAlarms(); /** * Return the system identifier used by the generator */ public String getSystemId() { return systemId; } /** * Sets the system identifier used by the generator. */ public void setSystemId(String systemId) { this.systemId = systemId; } /** * Returns the user identifier used by the generator. */ public String getUserId() { return userId; } /** * Sets the user identifier used by the generator. */ public void setUserId(String userId) { this.userId = userId; } /** * Sets the pause period between generated alarms. This is the amount of time * the generator will pause before sending the new alarm event. * * @param period Number of milliseconds to pause before sending a new alarm * event. */ public void setPeriod(int period) { this.waitPeriod = period; } /** * Returns the pause period between generated alarms. * * @return The current waiting period before sending a new alarm, given as * the number of milliseconds. */ public int getPeriod() { return this.waitPeriod; } /** * Returns the maximum number of alarms to be generated. * * @return The maximum number of alarms to be generated. */ public int getMaxNumberOfAlarms() { return maxNumberOfAlarms; } /** * Sets the maximum number of alarms to be generated. * * @param maxNumberOfAlarms the maximum number of alarms to be generated. */ public void setMaxNumberOfAlarms(int maxNumberOfAlarms) { this.maxNumberOfAlarms = maxNumberOfAlarms; } /** * Returns the <code>IlpDataSource</code> used by the generator to select * managed object instances. * * @return The data source containing the managed object instances. */ public IlpDataSource getMODataSource() { return this.moDataSource; } /** * Returns the number of generated alarms. * * @return the number of generated alarms. */ public int getNumberOfGeneratedAlarms() { return generatedAlarms.size(); } /** * Create a new thread that constantly generates new alarm events waiting for * the specified wait period between publishing each new alarm. */ public void startAlarmGeneration() { if (getPeriod() <= 0) { String msg=IlvResourceUtil.getServerLocaleString(AbstractAlarmGenerator.class,"NotStartAlarmGeneration"); log.log(Level.WARNING, msg, Integer.valueOf(getPeriod())); return; } alarmGenerationThread = new AlarmGeneratorThread(); String msg=IlvResourceUtil.getServerLocaleString(AbstractAlarmGenerator.class,"StartingAlarmGeneration"); log.log(Level.INFO, msg,Integer.valueOf(getPeriod())); alarmGenerationThread.start(); } /** * Stops the alarm generation thread. */ public void stopAlarmGeneration() { if (alarmGenerationThread != null) { log.info("Requesting alarm generation to stop"); alarmGenerationThread.requestStop(); } } /** * Adds an alarm event to the list of generated alarms. * * @param event The alarm event to add. */ public void addAlarm(IltAlarm event) { synchronized (generatedAlarms) { generatedAlarms.add(event); } } /** * Removes an alarm from the list of generated alarms. * * @param event The alarm to remove. */ public void removeAlarm(IltAlarm alarm) { synchronized (generatedAlarms) { generatedAlarms.remove(alarm); } } /** * Returns the Managed Object Class of a given MOI. * * @param moi A Managed Object Instance. * @return The Managed Object Class of the Managed Object Instance. */ protected String getMOC(IlpObject moi) { if (moi instanceof IltNetworkElement) { IltNetworkElement ne = (IltNetworkElement) moi; String moc = "ManagedElement/" + ne.getType().getName(); return moc; } else { return moi.getIlpClass().getName(); } } /** * Returns a randomly generated Managed Object Instance. * * @return A randomly selected Managed Object Instance. */ protected synchronized IlpObject generateRandomMOI() { if (this.moiCache == null) this.moiCache = moDataSource.getObjects().toArray(); //No IltAlarm instances should be returned IlpObject moi = null; do { moi = (IlpObject) moiCache[randomGenerator.nextInt(moiCache.length)]; } while (moi instanceof IltAlarm); return moi; } /** * Generates a random severity value. * * @return A randomly generated severity value. */ protected Object generateRandomSeverity() { return ALARM_SEVERITIES[randomGenerator .nextInt(ALARM_SEVERITIES.length)]; } /** * Generates a random probable cause value. * * @return A randomly generated probable cause value. */ protected Object generateRandomProbableCause() { return PROBABLE_CAUSES[randomGenerator.nextInt(PROBABLE_CAUSES.length)]; } /** * Generates a random alarm type value. * * @return randomly generated alarm type. */ protected Object generateRandomAlarmType() { return ALARM_TYPES[randomGenerator.nextInt(ALARM_TYPES.length)]; } /** * Generates a random alarm type value. * * @return A randomly generated trend value. */ protected Object generateRandomTrend() { return ALARM_TRENDS[randomGenerator.nextInt(ALARM_TRENDS.length)]; } /** * Clear the cache with all the managed object instances. * <p>This method is used when objects are added or removed from the * datasource. */ protected synchronized void clearMOICache() { this.moiCache = null; } /** * Thread class used to run the alarm generator. The thread continually * generates new alarm events using the current alarm generator settings until * the thread is stopped. The thread can (and should) be stopped gently by * calling <code>requestStop</code>. * * <p>Alarms are generated using the given interval as the number of * milliseconds to pause between each new alarm being generated. */ protected class AlarmGeneratorThread extends Thread { // Track request to stop the thread (gently) private boolean stopRequested = false; //Check if the maximum number of alarm has been reached private boolean maximumNumberReached=false; /** * Constructor. */ AlarmGeneratorThread() { super("Alarm Generation " + alarmGenerationLiveThreadCount++); } /** * Run the thread. */ Override public void run() { while (!isStopRequested()) { try { //Enforce the max number of alarms if(generatedAlarms.size() < maxNumberOfAlarms) { generateOneAlarm(); maximumNumberReached = false; } else { if(maximumNumberReached==false){ maximumNumberReached=true; log.info("Maximum number of alarms has been reached '" + maxNumberOfAlarms + "' no more alarms being generated"); } } clearOneAlarm(null); Thread.sleep(waitPeriod); } catch (Exception e) { e.printStackTrace(); requestStop(); } } log.info("Alarm generation stopped..."); alarmGenerationLiveThreadCount--; if(alarmGenerationThread == this) alarmGenerationThread = null; } /** * Request a stop of the alarm generation. */ public synchronized void requestStop() { stopRequested = true; } /** * Synchronized access to the stopRequested variable. * @return A boolean indicating if a request has been issued to stop the * thread. */ synchronized boolean isStopRequested() { return stopRequested; } } }