/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat, Inc., and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.jboss.narayana.blacktie.administration;
import java.io.IOException;
import java.util.Properties;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;
import javax.ejb.TimerConfig;
import javax.ejb.NoSuchObjectLocalException;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.jboss.narayana.blacktie.jatmibroker.core.conf.ConfigurationException;
import org.jboss.narayana.blacktie.jatmibroker.core.conf.XMLParser;
@Singleton
@Startup
public class QueueReaperBean {
/** logger */
private static final Logger log = LogManager.getLogger(QueueReaperBean.class);
/** Interval at which to run */
private long interval = -1;
private Properties prop;
private MBeanServer beanServerConnection;
@Resource
private TimerService timerService;
public QueueReaperBean() {
beanServerConnection = java.lang.management.ManagementFactory.getPlatformMBeanServer();
}
@PostConstruct
public void start() {
log.info("QueueReaper Started");
try {
prop = new Properties();
XMLParser.loadProperties("btconfig.xsd", "btconfig.xml", prop);
this.interval = Integer.parseInt(prop.getProperty("QueueReaperInterval", "30")) * 1000;
timerService.createIntervalTimer(interval, interval, new TimerConfig("queue reaper", false));
log.info("QueueReaper create timer with " + interval + "ms");
} catch (ConfigurationException e) {
log.error("btconfig.xml is not valid: " + e);
}
}
@PreDestroy
public void stop() {
log.info("QueueReaper stopped");
}
@Timeout
public void run(Timer timer) {
try {
log.trace("QueueReaper Running: timer is " + timer.getInfo());
ObjectName objName = new ObjectName("jboss.as:subsystem=messaging,hornetq-server=default,jms-queue=*");
ObjectInstance[] dests = beanServerConnection.queryMBeans(objName, null).toArray(new ObjectInstance[] {});
for (int i = 0; i < dests.length; i++) {
String serviceComponentOfObjectName = dests[i].getObjectName().getCanonicalName();
serviceComponentOfObjectName = serviceComponentOfObjectName.substring(
serviceComponentOfObjectName.indexOf('_') + 1,
serviceComponentOfObjectName.indexOf(",", serviceComponentOfObjectName.indexOf('_')));
log.trace("Service name component of ObjectName is: " + serviceComponentOfObjectName);
String server = (String) prop.get("blacktie." + serviceComponentOfObjectName + ".server");
log.trace("Checking for: " + serviceComponentOfObjectName + " " + server + " "
+ prop.get("blacktie." + serviceComponentOfObjectName + ".externally-managed-destination"));
if ((serviceComponentOfObjectName.startsWith(".") || ((server != null && !(Boolean) prop.get("blacktie."
+ serviceComponentOfObjectName + ".externally-managed-destination"))))
&& consumerCount(serviceComponentOfObjectName) == 0) {
log.warn("undeploy service pending for " + serviceComponentOfObjectName
+ " as consumer count is 0, will check again in " + interval + "ms");
long queueReapCheck = System.currentTimeMillis();
Thread.sleep(this.interval);
// double check consumer is 0
if (BlacktieStompAdministrationService.isOlderThanReapCheck(serviceComponentOfObjectName, queueReapCheck)
&& consumerCount(serviceComponentOfObjectName) == 0) {
BlacktieStompAdministrationService.undeployQueue(serviceComponentOfObjectName);
log.warn("undeploy service " + serviceComponentOfObjectName + " for consumer is 0");
} else {
log.debug("Undeploy not required for: " + serviceComponentOfObjectName + " at: " + server
+ " as client connected");
}
} else {
log.debug("Undeploy not required for: " + serviceComponentOfObjectName + " at: " + server);
}
}
} catch (NoSuchObjectLocalException e) {
log.debug("The timer has expired or has been cancelled");
} catch (InterruptedException e) {
log.debug("Sleeping interrupted");
} catch (Exception e) {
log.error("run ping thread failed with (will wait for: " + interval + " ms): " + e, e);
}
}
int consumerCount(String serviceName) throws MalformedObjectNameException, NullPointerException,
AttributeNotFoundException, InstanceNotFoundException, ReflectionException, IOException, MBeanException {
log.trace(serviceName);
boolean conversational = false;
String type = "queue";
if (!serviceName.startsWith(".")) {
conversational = (Boolean) prop.get("blacktie." + serviceName + ".conversational");
type = (String) prop.get("blacktie." + serviceName + ".type");
}
String prefix = null;
if (conversational) {
prefix = "BTC_";
} else {
prefix = "BTR_";
}
ObjectName objName = new ObjectName("jboss.as:subsystem=messaging,hornetq-server=default,jms-" + type + "=" + prefix
+ serviceName);
try {
Integer count = null;
if (type.equals("queue")) {
count = (Integer) beanServerConnection.getAttribute(objName, "consumerCount");
} else {
count = (Integer) beanServerConnection.getAttribute(objName, "subscriptionCount");
}
return count.intValue();
} catch (javax.management.InstanceNotFoundException e) {
log.debug("Instance not found: " + objName);
return -1;
}
}
}