/**
* Helios, OpenSource Monitoring
* Brought to you by the Helios Development Group
*
* Copyright 2007, Helios Development Group and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*
*/
package org.helios.apmrouter.catalog.jdbc.h2;
import java.lang.management.ManagementFactory;
import java.sql.Connection;
import java.sql.SQLException;
import javax.management.MBeanNotificationInfo;
import javax.sql.DataSource;
import org.helios.apmrouter.jmx.JMXHelper;
import org.helios.apmrouter.spring.ctx.ApplicationContextService;
import org.helios.apmrouter.util.thread.ManagedThreadPool;
import org.helios.apmrouter.util.thread.ThreadPoolConfig;
import org.springframework.context.ApplicationContext;
/**
* <p>Title: AsynchAbstractTrigger</p>
* <p>Description: Trigger base class that fires triggers asynchronously</p>
* <p>Company: Helios Development Group LLC</p>
* @author Whitehead (nwhitehead AT heliosdev DOT org)
* <p><code>org.helios.apmrouter.catalog.jdbc.h2.AsynchAbstractTrigger</code></p>
*/
public abstract class AsynchAbstractTrigger extends AbstractTrigger implements AsynchAbstractTriggerMBean {
/** The thread pool used for asynch execution */
protected ManagedThreadPool threadPool = null;
/** A data source of connections back into the same used by asynch trigger excutions that need to get data from the DB */
protected DataSource dataSource = null;
/** A proxy reference to the root application context */
protected ApplicationContext rootAppCtx = null;
/**
* Creates a new AsynchAbstractTrigger
* @param infos The MBean notification metadata
*/
public AsynchAbstractTrigger(MBeanNotificationInfo... infos) {
super(infos);
}
/** The number of cores available */
public static final int CORES = ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors();
/**
* {@inheritDoc}
* @see org.helios.apmrouter.catalog.jdbc.h2.AbstractTrigger#init(java.sql.Connection, java.lang.String, java.lang.String, java.lang.String, boolean, int)
*/
@Override
public void init(Connection conn, String schemaName, String triggerName,
String tableName, boolean before, int type) throws SQLException {
super.init(conn, schemaName, triggerName, tableName, before, type);
rootAppCtx = ApplicationContextService.getRootInstance();
log.info("Acquired Root AppCtx [" + rootAppCtx.getDisplayName() + "]");
dataSource = rootAppCtx.getBean("DataSource", DataSource.class);
if(dataSource==null) throw new RuntimeException("Datasource was null", new Throwable());
ThreadPoolConfig tpc = new ThreadPoolConfig();
tpc.setCorePoolSize(2);
tpc.setMaximumPoolSize(CORES);
tpc.setDaemonThreads(true);
tpc.setFairQueue(false);
tpc.setQueueSize(100);
tpc.setCoreThreadsStarted(2);
tpc.setKeepAliveTime(60000);
threadPool = new ManagedThreadPool(tpc);
threadPool.setBeanName(schemaName + "-" + tableName + "-" + triggerName + (before ? "_before" : "_after"));
threadPool.setObjectName(
JMXHelper.objectName(
NewElementTriggers.class.getPackage().getName(),
"service", "AsynchTriggerThreadPool",
"class", getClass().getSimpleName(),
"schema", schemaName,
"table", tableName,
"trigger", triggerName,
"order", (before ? "before" : "after"),
"type", TriggerOp.getEnabledStatesName(type))
);
try {
threadPool.start();
} catch (Exception ex) {
throw new RuntimeException("Failed to start asynch trigger thread pool", ex);
}
// try {
// JMXHelper.getHeliosMBeanServer().registerMBean(threadPool, threadPool.getObjectName());
// } catch (Exception ex) {
// log.warn("Failed to register management interface for asynch trigger thread pool", ex);
// }
}
/**
* {@inheritDoc}
* @see org.h2.api.Trigger#fire(java.sql.Connection, java.lang.Object[], java.lang.Object[])
*/
@Override
public void fire(Connection conn, final Object[] oldRow, final Object[] newRow) throws SQLException {
final DataSource finalDs = dataSource;
threadPool.submit(new Runnable(){
@Override
public void run() {
doFire(finalDs, oldRow, newRow);
}
});
}
/**
* The asynch trigger execution defined by concrete implementations
* @param dataSource A data source of connections back into the same used by asynch trigger excutions that need to get data from the DB
* @param oldRow The row values before change
* @param newRow The row values after change
*/
protected abstract void doFire(DataSource dataSource, Object[] oldRow, Object[] newRow);
/**
* @return int
* @see org.helios.apmrouter.util.thread.ManagedThreadPool#getActiveCount()
*/
public int getActiveCount() {
return threadPool.getActiveCount();
}
public int getCorePoolSize() {
return threadPool.getCorePoolSize();
}
/**
* @return String
* @see org.helios.apmrouter.server.ServerComponentBean#getBeanName()
*/
public String getBeanName() {
return threadPool.getBeanName();
}
/**
* @return int
* @see org.helios.apmrouter.util.thread.ManagedThreadPool#getPoolSize()
*/
public int getPoolSize() {
return threadPool.getPoolSize();
}
public int getLargestPoolSize() {
return threadPool.getLargestPoolSize();
}
public int getMaximumPoolSize() {
return threadPool.getMaximumPoolSize();
}
/**
* @return int
* @see org.helios.apmrouter.util.thread.ManagedThreadPool#getQueueSize()
*/
public int getQueueSize() {
return threadPool.getQueueSize();
}
/**
*
* @see org.helios.apmrouter.server.ServerComponent#resetMetrics()
*/
public void resetMetrics() {
threadPool.resetMetrics();
}
/**
* @return long
* @see org.helios.apmrouter.util.thread.ManagedThreadPool#getTaskCount()
*/
public long getTaskCount() {
return threadPool.getTaskCount();
}
/**
* @return boolean
* @see org.helios.apmrouter.util.thread.ManagedThreadPool#isShutdown()
*/
public boolean isShutdown() {
return threadPool.isShutdown();
}
/**
* @return boolean
* @see org.helios.apmrouter.util.thread.ManagedThreadPool#isTerminated()
*/
public boolean isTerminated() {
return threadPool.isTerminated();
}
/**
* @return boolean
* @see org.helios.apmrouter.util.thread.ManagedThreadPool#isTerminating()
*/
public boolean isTerminating() {
return threadPool.isTerminating();
}
/**
*
* @see org.helios.apmrouter.util.thread.ManagedThreadPool#purge()
*/
public void purge() {
threadPool.purge();
}
/**
* @return String[]
* @see org.helios.apmrouter.util.thread.ManagedThreadPool#getThreadStats()
*/
public String[] getThreadStats() {
return threadPool.getThreadStats();
}
/**
* @return boolean
* @see org.helios.apmrouter.server.ServerComponentBean#isStarted()
*/
public boolean isStarted() {
return threadPool.isStarted();
}
}