package org.mobicents.slee.container.profile; import java.util.concurrent.ConcurrentHashMap; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.slee.SLEEException; import javax.slee.profile.UnrecognizedProfileTableNameException; import org.apache.commons.pool.ObjectPool; import org.apache.commons.pool.impl.GenericObjectPool; import org.apache.commons.pool.impl.GenericObjectPoolFactory; import org.apache.log4j.Logger; import org.mobicents.slee.container.SleeContainer; import org.mobicents.slee.runtime.transaction.SleeTransactionManager; import org.mobicents.slee.runtime.transaction.TransactionalAction; /** * * Manages profile object pools in the SLEE container. * * @author martins * */ public class ProfileObjectPoolManagement implements ProfileObjectPoolManagementMBean { private final static Logger logger = Logger .getLogger(ProfileObjectPoolManagement.class); private final ConcurrentHashMap<String, ProfileObjectPool> pools; private final SleeContainer sleeContainer; private GenericObjectPool.Config config; public ProfileObjectPoolManagement(SleeContainer sleeContainer) { this.sleeContainer = sleeContainer; // create pool config mbean with default pool configuration config = new GenericObjectPool.Config(); config.maxActive = -1; config.maxIdle = 50; config.maxWait = -1; config.minEvictableIdleTimeMillis = 60000; config.minIdle = 0; config.numTestsPerEvictionRun = -1; config.testOnBorrow = true; config.testOnReturn = true; config.testWhileIdle = false; config.timeBetweenEvictionRunsMillis = 300000; config.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_FAIL; // create pools map pools = new ConcurrentHashMap<String, ProfileObjectPool>(); } /** * Retrieves the current pool configuration * * @return */ public GenericObjectPool.Config getPoolConfig() { return config; } /** * Defines the current pool configuration */ public void setPoolConfig(GenericObjectPool.Config config) { this.config = config; } /** * Retrieves the object pool for the specified profile table. * @param profileTable * @return */ public ProfileObjectPool getObjectPool(String profileTableName) { return pools.get(profileTableName); } /** * Creates an object pool for the specified profile table. If a * transaction manager is used then, and if the tx rollbacks, the pool will * be removed. * * @param * @param sleeTransactionManager */ public void createObjectPool(final ProfileTableImpl profileTable, final SleeTransactionManager sleeTransactionManager) { if (logger.isDebugEnabled()) { logger.debug("Creating Pool for " + profileTable); } createObjectPool(profileTable); if (sleeTransactionManager != null) { // add a rollback action to remove sbb object pool TransactionalAction action = new TransactionalAction() { public void execute() { if (logger.isDebugEnabled()) { logger .debug("Due to tx rollback, removing pool for " + profileTable); } try { removeObjectPool(profileTable); } catch (Throwable e) { logger.error("Failed to remove table's " + profileTable + " object pool", e); } } }; try { sleeTransactionManager.addAfterRollbackAction(action); } catch (Throwable e) { logger.error(e.getMessage(),e); } } } /** * * @param profileTable */ private void createObjectPool(final ProfileTableImpl profileTable) { // create the pool GenericObjectPoolFactory poolFactory = new GenericObjectPoolFactory( new ProfileObjectPoolFactory(profileTable), config); final ObjectPool objectPool = poolFactory.createPool(); final ProfileObjectPool oldObjectPool = pools.put(profileTable.getProfileTableName(), new ProfileObjectPool(objectPool)); if (oldObjectPool != null) { // there was an old pool, close it try { oldObjectPool.close(); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Failed to close old pool for " + profileTable); } } } if (logger.isDebugEnabled()) { logger.debug("Created Pool for " + profileTable); } } /** * Removes the object pool for the specified profile table. If a * transaction manager is used then the removal is only after the tx commit. * * @param sleeTransactionManager * @throws Exception */ public void removeObjectPool(final ProfileTableImpl profileTable, final SleeTransactionManager sleeTransactionManager) { TransactionalAction action = new TransactionalAction() { public void execute() { if (logger.isDebugEnabled()) { logger.debug("Removing Pool for " + profileTable); } removeObjectPool(profileTable); } }; if (sleeTransactionManager != null) { try { sleeTransactionManager.addAfterCommitAction(action); } catch (Throwable e) { logger.error(e.getMessage(),e); } } else { action.execute(); } } /** * Removes the pool for the specified ids * * @param serviceID * @param sbbID * @throws Exception */ private void removeObjectPool(final ProfileTableImpl profileTable) { final ProfileObjectPool objectPool = pools.remove(profileTable.getProfileTableName()); if (objectPool != null) { try { objectPool.close(); } catch (Exception e) { logger.error("failed to close pool",e); } } if (logger.isDebugEnabled()) { logger.debug("Removed Pool for " + profileTable); } } // ---- MBEAN METHODS public void register() { MBeanServer mBeanServer = sleeContainer.getMBeanServer(); try { mBeanServer.registerMBean(this, new ObjectName(MBEAN_NAME)); } catch (Exception e) { logger.error("Failed to register", e); } } public void unregister() { try { sleeContainer.getMBeanServer().unregisterMBean( new ObjectName(MBEAN_NAME)); } catch (Exception e) { logger.error("Failed to unregister", e); } } public int getMaxActive() { return config.maxActive; } public void setMaxActive(int maxActive) { config.maxActive = maxActive; } public int getMaxIdle() { return config.maxIdle; } public void setMaxIdle(int maxIdle) { config.maxIdle = maxIdle; } public int getMinIdle() { return config.minIdle; } public void setMinIdle(int minIdle) { config.minIdle = minIdle; } public long getMaxWait() { return config.maxWait; } public void setMaxWait(long maxWait) { config.maxWait = maxWait; } public long getMinEvictableIdleTimeMillis() { return config.minEvictableIdleTimeMillis; } public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { config.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; } public int getNumTestsPerEvictionRun() { return config.numTestsPerEvictionRun; } public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { config.numTestsPerEvictionRun = numTestsPerEvictionRun; } public boolean getTestOnBorrow() { return config.testOnBorrow; } public void setTestOnBorrow(boolean testOnBorrow) { config.testOnBorrow = testOnBorrow; } public boolean getTestOnReturn() { return config.testOnReturn; } public void setTestOnReturn(boolean testOnReturn) { config.testOnReturn = testOnReturn; } public boolean getTestWhileIdle() { return config.testWhileIdle; } public void setTestWhileIdle(boolean testWhileIdle) { config.testWhileIdle = testWhileIdle; } public long getTimeBetweenEvictionRunsMillis() { return config.timeBetweenEvictionRunsMillis; } public void setTimeBetweenEvictionRunsMillis( long timeBetweenEvictionRunsMillis) { config.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; } public byte getWhenExhaustedAction() { return config.whenExhaustedAction; } public void setWhenExhaustedAction(byte whenExhaustedAction) { config.whenExhaustedAction = whenExhaustedAction; } public void reconfig() { for (String key : pools.keySet()) { ProfileTableImpl profileTable; try { profileTable = (ProfileTableImpl) sleeContainer.getSleeProfileTableManager().getProfileTable(key); } catch (UnrecognizedProfileTableNameException e) { throw new SLEEException(e.getMessage(),e); } createObjectPool(profileTable); } } @Override public String toString() { return "Profile Object Pool Management: " + "\n+-- Pools: " + pools.keySet(); } }