org.mobicents.slee.runtime.sbb.SbbObjectPoolManagementImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.mobicents.slee.runtime.sbb.SbbObjectPoolManagementImpl.java

Source

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt 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.mobicents.slee.runtime.sbb;

import java.util.concurrent.ConcurrentHashMap;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.slee.SbbID;
import javax.slee.ServiceID;

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.container.component.sbb.SbbComponent;
import org.mobicents.slee.container.transaction.SleeTransactionManager;
import org.mobicents.slee.container.transaction.TransactionalAction;

/**
 * 
 * Manages sbb object pools in the SLEE container.
 * 
 * @author martins
 * 
 */
public class SbbObjectPoolManagementImpl implements SbbObjectPoolManagementImplMBean {

    private final static Logger logger = Logger.getLogger(SbbObjectPoolManagementImpl.class);

    private final ConcurrentHashMap<ObjectPoolMapKey, SbbObjectPoolImpl> pools;
    private final SleeContainer sleeContainer;

    private GenericObjectPool.Config config;

    public SbbObjectPoolManagementImpl(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<ObjectPoolMapKey, SbbObjectPoolImpl>();
    }

    /**
     * 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 sbb and service.
     * @param serviceID
     * @param sbbID
     * @return
     */
    public SbbObjectPoolImpl getObjectPool(ServiceID serviceID, SbbID sbbID) {
        return pools.get(new ObjectPoolMapKey(serviceID, sbbID));
    }

    /**
     * Creates an object pool for the specified service and sbb. If a
     * transaction manager is used then, and if the tx rollbacks, the pool will
     * be removed.
     * 
     * @param 
     * @param sleeTransactionManager
     */
    public void createObjectPool(final ServiceID serviceID, final SbbComponent sbbComponent,
            final SleeTransactionManager sleeTransactionManager) {

        if (logger.isTraceEnabled()) {
            logger.trace("Creating Pool for  " + serviceID + " and " + sbbComponent);
        }

        createObjectPool(serviceID, sbbComponent);

        if (sleeTransactionManager != null && sleeTransactionManager.getTransactionContext() != 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 " + serviceID + " and " + sbbComponent);
                    }
                    try {
                        removeObjectPool(serviceID, sbbComponent.getSbbID());
                    } catch (Throwable e) {
                        logger.error("Failed to remove " + serviceID + " and " + sbbComponent + " object pool", e);
                    }
                }
            };
            sleeTransactionManager.getTransactionContext().getAfterRollbackActions().add(action);
        }
    }

    /**
     * 
     * @param serviceID
     * @param sbbID
     */
    private void createObjectPool(final ServiceID serviceID, final SbbComponent sbbComponent) {
        // create the pool for the given SbbID
        GenericObjectPoolFactory poolFactory = new GenericObjectPoolFactory(
                new SbbObjectPoolFactory(serviceID, sbbComponent), config);
        final ObjectPool objectPool = poolFactory.createPool();
        final SbbObjectPoolImpl oldObjectPool = pools.put(new ObjectPoolMapKey(serviceID, sbbComponent.getSbbID()),
                new SbbObjectPoolImpl(sbbComponent, serviceID, 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 " + serviceID + "and " + sbbComponent);
                }
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Created Pool for " + serviceID + "and " + sbbComponent);
        }
    }

    /**
     * Removes the object pool for the sbb with the specified component and the specified service. If a
     * transaction manager is used then, and if the tx rollbacks, the pool will
     * be restored.
     * 
     * @param sbbDescriptor
     * @param sleeTransactionManager
     * @throws Exception
     */
    public void removeObjectPool(final ServiceID serviceID, final SbbComponent sbbComponent,
            final SleeTransactionManager sleeTransactionManager) {

        if (logger.isTraceEnabled()) {
            logger.trace("Removing Pool for " + serviceID + "and " + sbbComponent);
        }

        removeObjectPool(serviceID, sbbComponent.getSbbID());

        if (sleeTransactionManager != null) {
            // restore object pool if tx rollbacks
            TransactionalAction action = new TransactionalAction() {
                public void execute() {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Due to tx rollback, restoring pool for " + serviceID + "and " + sbbComponent);
                    }
                    createObjectPool(serviceID, sbbComponent);
                }
            };
            sleeTransactionManager.getTransactionContext().getAfterRollbackActions().add(action);
        }
    }

    /**
     * Removes the pool for the specified ids
     * 
     * @param serviceID
     * @param sbbID
     * @throws Exception
     */
    private void removeObjectPool(final ServiceID serviceID, final SbbID sbbID) {
        ObjectPoolMapKey key = new ObjectPoolMapKey(serviceID, sbbID);
        final SbbObjectPoolImpl objectPool = pools.remove(key);
        if (objectPool != null) {
            try {
                objectPool.close();
            } catch (Exception e) {
                logger.error("failed to close pool", e);
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Removed Pool for " + key);
        }
    }

    // ---- 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 (ObjectPoolMapKey key : pools.keySet()) {
            final SbbComponent sbbComponent = sleeContainer.getComponentRepository().getComponentByID(key.sbbID);
            createObjectPool(key.serviceID, sbbComponent);
        }
    }

    @Override
    public String toString() {
        return "SbbObject Pool Management: " + "\n+-- Pools: " + pools.keySet();
    }

    private static class ObjectPoolMapKey {

        private final ServiceID serviceID;
        private final SbbID sbbID;

        public ObjectPoolMapKey(ServiceID serviceID, SbbID sbbID) {
            this.serviceID = serviceID;
            this.sbbID = sbbID;
        }

        @Override
        public int hashCode() {
            return serviceID.hashCode() * 31 + sbbID.hashCode();
        }

        @Override
        public boolean equals(Object obj) {
            if (obj != null && obj.getClass() == this.getClass()) {
                ObjectPoolMapKey other = (ObjectPoolMapKey) obj;
                return this.serviceID.equals(other.serviceID) && this.sbbID.equals(other.sbbID);
            } else {
                return false;
            }
        }

        @Override
        public String toString() {
            return serviceID.toString() + " & " + sbbID.toString();
        }
    }
}