/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2006-2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
package org.openoss.opennms.spring.qosd;
import org.opennms.core.utils.ThreadCategory;
import org.openoss.opennms.spring.dao.OssDao;
/**
* This class provides a thread to decouple the OpenNMS event handling from updates to
* the Node list and the Alarm List in the ossDao. If OpenNMS issues multiple events to the QoSD
* event handler which cause it to want to update the alarm list or update the node list, this Thread latches
* the event and will request the ossDao to update it's cache and send any new alarms.
* If further events occur while the ossDao is updating, these will be latched until the
* process completes. This prevents every new opennms alarm causing a call to the ossDao while it is running
* which would otherwise back up a queue of requests against it's synchronized methods.
*
* @author ranger
* @version $Id: $
*/
public class OpenNMSEventHandlerThread extends Thread {
// ---------------SPRING DAO DECLARATIONS----------------
private static OssDao ossDao;
/**
* provides an interface to OpenNMS which provides a unified api
*
* @param _ossDao the ossDao to set
*/
public void setOssDao(OssDao _ossDao) {
ossDao = _ossDao;
}
// Business Methods
private static boolean sendList=false; // true if alarm list is to be updated and sent when the thread wakes up
private static boolean updateNCache=false; // true if node list is to be updated when the thread wakes up
private static boolean runThread=false; // true if this thread is to keep running. If false, the thread will exit
private static boolean init=false; // true if this thread has been initialised
//private static OpenNMSEventHandlerThread instance =null; // used to hold instance of this thread
/**
* Run method loops until kill() called.
* It wakes up if sendAlarmList() is called and updates the alarmlist
* It wakes up if updateNodeCache() is called and updates the node list
* init() must be called before the run() method.
*
* @throws java.lang.IllegalStateException if any.
*/
public void run() throws IllegalStateException {
ThreadCategory log = getLog();
//instance=this;
boolean localupdateNCache=false;
boolean localsendList=false;
// if the init variable is false then the thread has not been initialised
if(!init)
throw new IllegalStateException("OpenNMSEventHandlerThread.run() - You must call init() before calling run()");
while (runThread){
synchronized(this) {
try{
// test to see if there have been more requests to update the list while updating the list
if ((sendList==false)&&(updateNCache==false)){
if (log.isDebugEnabled()) log.debug("OpenNMSEventHandlerThread.run() thread waiting for interrupt");
wait();
}
} catch ( InterruptedException e){
if (log.isDebugEnabled()) log.debug("OpenNMSEventHandlerThread.run() thread woken up");
}
localupdateNCache=updateNCache;
localsendList=sendList;
updateNCache=false;
sendList=false;
}
if (localupdateNCache) try {
if (log.isDebugEnabled()) log.debug("OpenNMSEventHandlerThread.run() updating node list");
ossDao.updateNodeCaches();
} catch (Throwable ex) {
log.error("OpenNMSEventHandlerThread.run() Exception caught in ossDao.updateNodeCaches():", ex);
}
if (localsendList) try{
if (log.isDebugEnabled()) log.debug("OpenNMSEventHandlerThread.run() updating and sending alarm list");
ossDao.updateAlarmCacheAndSendAlarms();
}
catch (Throwable ex) {
log.error("OpenNMSEventHandlerThread.run() Exception caught in ossDao.updateAlarmCacheAndSendAlarms():", ex);
}
}
if (log.isDebugEnabled()) log.debug("OpenNMSEventHandlerThread.run() STOPPED");
}
/**
* Initialise the Thread. Must be called before a call to run.
*/
synchronized public void init() {
ThreadCategory log = getLog();
if (log.isDebugEnabled()) log.debug("OpenNMSEventHandlerThread.init() initialised");
init = true; //inform the thread that it has been initialised
//and can execute the run() method.
runThread=true;
}
/**
* Stop execution of the thread. Will complete any current update before exiting
*/
synchronized public void kill() {
// Thread.stop() is unsafe so ending run method by changing
// a status variable that tells the run method to return
// and end execution.
ThreadCategory log = getLog();
if (log.isDebugEnabled()) log.debug("OpenNMSEventHandlerThread.kill() request received to kill thread");
runThread=false;
//instance.notify();
notify();
}
/**
* If called, this method will request that the ossDao Alarm Cache is updated from the OpenNMS database
* and sent to the QoSD for processing.
* Note that multiple calls while the update process is running will be latched ( i.e. not queued) and result
* another update when the previous one completes
*/
synchronized public void sendAlarmList(){
ThreadCategory log = getLog();
if (log.isDebugEnabled()) log.debug("OpenNMSEventHandlerThread.sendAlarmList() request received to update alarm list");
sendList=true;
//instance.notify();
notify();
}
/**
* If called, this method will request that the ossDao Node Cache is updated from the OpenNMS database
* and sent to the QoSD for processing.
* Note that multiple calls while the update process is running will be latched ( i.e. not queued) and result
* in only one update when the previous one completes
*/
synchronized public void updateNodeCache(){
ThreadCategory log = getLog();
if (log.isDebugEnabled()) log.debug("OpenNMSEventHandlerThread.updateNodeCache() request received to update node list");
updateNCache=true;
//instance.notify();
notify();
}
private static ThreadCategory getLog() {
return ThreadCategory.getInstance(OpenNMSEventHandlerThread.class);
}
}