com.meidusa.amoeba.context.ProxyRuntimeContext.java Source code

Java tutorial

Introduction

Here is the source code for com.meidusa.amoeba.context.ProxyRuntimeContext.java

Source

/**
 * <pre>
 *    This program is free software; you can redistribute it and/or modify it under the terms of 
 * the GNU AFFERO GENERAL PUBLIC LICENSE as published by the Free Software Foundation; either version 3 of the License, 
 * or (at your option) any later version. 
 * 
 *    This program 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 AFFERO GENERAL PUBLIC LICENSE for more details. 
 *    You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE along with this program; 
 * if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * </pre>
 */
package com.meidusa.amoeba.context;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.LogLog;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import com.meidusa.amoeba.config.BeanObjectEntityConfig;
import com.meidusa.amoeba.config.ConfigurationException;
import com.meidusa.amoeba.config.DBServerConfig;
import com.meidusa.amoeba.config.DocumentUtil;
import com.meidusa.amoeba.config.ParameterMapping;
import com.meidusa.amoeba.config.ProxyServerConfig;
import com.meidusa.amoeba.heartbeat.HeartbeatDelayed;
import com.meidusa.amoeba.heartbeat.HeartbeatManager;
import com.meidusa.amoeba.heartbeat.Status;
import com.meidusa.amoeba.net.ConnectionManager;
import com.meidusa.amoeba.net.poolable.MultipleLoadBalanceObjectPool;
import com.meidusa.amoeba.net.poolable.ObjectPool;
import com.meidusa.amoeba.net.poolable.PoolableObject;
import com.meidusa.amoeba.route.QueryRouter;
import com.meidusa.amoeba.util.Initialisable;
import com.meidusa.amoeba.util.InitialisationException;
import com.meidusa.amoeba.util.Reporter;
import com.meidusa.amoeba.util.StringUtil;

/**
 * @author <a href=mailto:piratebase@sina.com>Struct chen</a>
 */
public class ProxyRuntimeContext implements Reporter {

    public static final String DEFAULT_SERVER_CONNECTION_MANAGER_CLASS = "com.meidusa.amoeba.net.AuthingableConnectionManager";
    public static final String DEFAULT_REAL_POOL_CLASS = "com.meidusa.amoeba.net.poolable.PoolableObjectPool";
    public static final String DEFAULT_VIRTUAL_POOL_CLASS = "com.meidusa.amoeba.server.MultipleServerPool";

    protected static Logger logger = Logger.getLogger(ProxyRuntimeContext.class);

    private static ProxyRuntimeContext context = null;

    private ProxyServerConfig config;

    private Map<String, ConnectionManager> conMgrMap = new HashMap<String, ConnectionManager>();
    private Map<String, ConnectionManager> readOnlyConMgrMap = Collections.unmodifiableMap(conMgrMap);

    private Map<String, ObjectPool> poolMap = new HashMap<String, ObjectPool>();
    private Map<String, ObjectPool> readOnlyPoolMap = Collections.unmodifiableMap(poolMap);

    private List<ContextChangedListener> listeners = new ArrayList<ContextChangedListener>();

    @SuppressWarnings("unchecked")
    private QueryRouter queryRouter;
    private RuntimeContext runtimeContext;

    private Map<String, Object> beanContext = new HashMap<String, Object>();

    public RuntimeContext getRuntimeContext() {
        return runtimeContext;
    }

    public static ProxyRuntimeContext getInstance() {
        return context;
    }

    public static void setInstance(ProxyRuntimeContext context) {
        ProxyRuntimeContext.context = context;
    }

    protected String getDefaultServerConnectionManagerClassName() {
        return DEFAULT_SERVER_CONNECTION_MANAGER_CLASS;
    }

    protected String getDefaultRealPoolClassName() {
        return DEFAULT_REAL_POOL_CLASS;
    }

    protected String getDefaultVirtualPoolClassName() {
        return DEFAULT_VIRTUAL_POOL_CLASS;
    }

    public ProxyServerConfig getConfig() {
        return config;
    }

    public QueryRouter getQueryRouter() {
        return queryRouter;
    }

    public ProxyRuntimeContext() {
    }

    public Map<String, ConnectionManager> getConnectionManagerList() {
        return readOnlyConMgrMap;
    }

    public Map<String, ObjectPool> getPoolMap() {
        return readOnlyPoolMap;
    }

    private List<Initialisable> initialisableList = new ArrayList<Initialisable>();

    /**
     * 
     * @param parent
     * @param dest
     * @return
     */
    protected void inheritDBServerConfig(DBServerConfig parent, DBServerConfig dest) {
        BeanObjectEntityConfig destBeanConfig = dest.getFactoryConfig();
        BeanObjectEntityConfig parentBeanConfig = parent.getFactoryConfig();

        if (destBeanConfig != null) {
            if (parentBeanConfig != null) {
                inheritBeanObjectEntityConfig(parentBeanConfig, destBeanConfig);
            }
        } else {
            dest.setFactoryConfig(parentBeanConfig);
        }

        destBeanConfig = dest.getPoolConfig();
        parentBeanConfig = parent.getPoolConfig();

        if (destBeanConfig != null) {
            if (parentBeanConfig != null) {
                inheritBeanObjectEntityConfig(parentBeanConfig, destBeanConfig);
            }
        } else {
            dest.setPoolConfig(parentBeanConfig);
        }

        if (dest.getVirtual() == null) {
            dest.setVirtual(parent.getVirtual());
        }

        if (dest.getAbstractive() == null) {
            dest.setAbstractive(parent.getAbstractive());
        }

    }

    public void addContextChangedListener(ContextChangedListener listener) {
        if (!listeners.contains(listener)) {
            this.listeners.add(listener);
        }
    }

    public void removeContextChangedListener(ContextChangedListener listener) {
        this.listeners.remove(listener);
    }

    public void notifyAllContextChangedListener() {
        for (ContextChangedListener listener : listeners) {
            listener.doChange();
        }
    }

    protected void inheritBeanObjectEntityConfig(BeanObjectEntityConfig parent, BeanObjectEntityConfig dest) {
        BeanObjectEntityConfig parentCloned = (BeanObjectEntityConfig) parent.clone();
        if (!StringUtil.isEmpty(dest.getClassName())) {
            parentCloned.setClassName(dest.getClassName());
        }

        /*if(!StringUtil.isEmpty(dest.getName())){
           parentCloned.setName(dest.getName());
        }*/

        if (dest.getParams() != null) {
            if (parentCloned.getParams() == null) {
                parentCloned.setParams(dest.getParams());
            } else {
                parentCloned.getParams().putAll(dest.getParams());
            }
        }

        dest.setClassName(parentCloned.getClassName());
        //dest.setName(parentCloned.getName());
        dest.setParams(parentCloned.getParams());
    }

    private Object createBeanObjectEntity(BeanObjectEntityConfig config, boolean initEarly) {
        Object object = config.createBeanObject(initEarly);
        if (!StringUtil.isEmpty(config.getName())) {
            beanContext.put(config.getName(), object);
        }
        return object;
    }

    public void init(String file) {
        config = loadConfig(file);
        this.runtimeContext = (RuntimeContext) createBeanObjectEntity(config.getRuntimeConfig(), true);
        /*for (Map.Entry<String, BeanObjectEntityConfig> entry : config.getManagers().entrySet()) {
        BeanObjectEntityConfig beanObjectEntityConfig = entry.getValue();
        try {
            ConnectionManager manager = (ConnectionManager) beanObjectEntityConfig.createBeanObject(false);
            manager.setName(entry.getKey());
            initialisableList.add(manager);
            conMgrMap.put(manager.getName(), manager);
        } catch (Exception e) {
            throw new ConfigurationException("manager instance error", e);
        }
        }*/

        for (Map.Entry<String, DBServerConfig> entry : config.getDbServers().entrySet()) {
            DBServerConfig dbServerConfig = (DBServerConfig) entry.getValue().clone();
            String parent = dbServerConfig.getParent();
            if (!StringUtil.isEmpty(parent)) {
                DBServerConfig parentConfig = config.getDbServers().get(parent);
                if (parentConfig == null || parentConfig.getParent() != null) {
                    throw new ConfigurationException(entry.getKey() + " cannot found parent with name=" + parent
                            + " or parent's parent must be null");
                }
                inheritDBServerConfig(parentConfig, dbServerConfig);
            }

            //ignore if dbServer is abstract
            if (dbServerConfig.getAbstractive() != null && dbServerConfig.getAbstractive().booleanValue()) {
                continue;
            }

            try {
                BeanObjectEntityConfig poolConfig = dbServerConfig.getPoolConfig();
                ObjectPool pool = (ObjectPool) poolConfig.createBeanObject(false, conMgrMap);
                pool.setName(
                        StringUtil.isEmpty(poolConfig.getName()) ? dbServerConfig.getName() : poolConfig.getName());
                if (pool instanceof Initialisable) {
                    initialisableList.add((Initialisable) pool);
                }
                if (dbServerConfig.getFactoryConfig() != null) {
                    PoolableObjectFactory factory = (PoolableObjectFactory) dbServerConfig.getFactoryConfig()
                            .createBeanObject(false, conMgrMap);
                    if (factory instanceof Initialisable) {
                        initialisableList.add((Initialisable) factory);
                    }
                    pool.setFactory(factory);
                }
                poolMap.put(entry.getKey(), pool);
            } catch (Exception e) {
                throw new ConfigurationException("createBean error dbServer=" + dbServerConfig.getName(), e);
            }
        }

        if (config.getQueryRouterConfig() != null) {
            BeanObjectEntityConfig queryRouterConfig = config.getQueryRouterConfig();
            try {
                queryRouter = (QueryRouter) queryRouterConfig.createBeanObject(false, conMgrMap);
                if (queryRouter instanceof Initialisable) {
                    initialisableList.add((Initialisable) queryRouter);
                }
                if (queryRouter instanceof ContextChangedListener) {
                    this.addContextChangedListener((ContextChangedListener) queryRouter);
                }
            } catch (Exception e) {
                throw new ConfigurationException("queryRouter instance error", e);
            }
        }

        initAllInitialisableBeans();
        initialisableList.clear();
        for (ConnectionManager cm : getConnectionManagerList().values()) {
            cm.start();
        }
        initPools();
    }

    protected void initPools() {
        for (Map.Entry<String, ObjectPool> entry : poolMap.entrySet()) {
            ObjectPool pool = entry.getValue();
            if (pool instanceof MultipleLoadBalanceObjectPool) {
                MultipleLoadBalanceObjectPool multiPool = (MultipleLoadBalanceObjectPool) pool;
                multiPool.initAllPools();
            } else {
                PoolableObject object = null;
                try {
                    object = (PoolableObject) pool.borrowObject();
                } catch (Exception e) {
                    logger.error("init pool error!", e);
                } finally {
                    if (object != null) {
                        try {
                            pool.returnObject(object);
                        } catch (Exception e) {
                            logger.error("return init pools error", e);
                        }
                    }
                }
            }

            if (pool instanceof ContextChangedListener) {
                this.addContextChangedListener((ContextChangedListener) pool);
            }
        }
    }

    private void initAllInitialisableBeans() {
        for (Initialisable bean : initialisableList) {
            try {
                bean.init();
                if (bean instanceof ContextChangedListener) {
                    this.addContextChangedListener((ContextChangedListener) bean);
                }
            } catch (InitialisationException e) {
                throw new ConfigurationException("Initialisation bean=" + bean + " error", e);
            }
        }
    }

    private ProxyServerConfig loadConfig(String configFileName) {
        DocumentBuilder db;

        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setValidating(true);
            dbf.setNamespaceAware(false);

            db = dbf.newDocumentBuilder();
            db.setEntityResolver(new EntityResolver() {

                public InputSource resolveEntity(String publicId, String systemId) {
                    if (systemId.endsWith("amoeba.dtd")) {
                        InputStream in = ProxyRuntimeContext.class
                                .getResourceAsStream("/com/meidusa/amoeba/xml/amoeba.dtd");
                        if (in == null) {
                            LogLog.error("Could not find [amoeba.dtd]. Used ["
                                    + ProxyRuntimeContext.class.getClassLoader() + "] class loader in the search.");
                            return null;
                        } else {
                            return new InputSource(in);
                        }
                    } else {
                        return null;
                    }
                }
            });

            db.setErrorHandler(new ErrorHandler() {

                public void warning(SAXParseException exception) {
                }

                public void error(SAXParseException exception) throws SAXException {
                    logger.error(exception.getMessage() + " at (" + exception.getLineNumber() + ":"
                            + exception.getColumnNumber() + ")");
                    throw exception;
                }

                public void fatalError(SAXParseException exception) throws SAXException {
                    logger.fatal(exception.getMessage() + " at (" + exception.getLineNumber() + ":"
                            + exception.getColumnNumber() + ")");
                    throw exception;
                }
            });
            return loadConfigurationFile(configFileName, db);
        } catch (Exception e) {
            logger.fatal("Could not load configuration file, failing", e);
            throw new ConfigurationException("Error loading configuration file " + configFileName, e);
        }
    }

    private ProxyServerConfig loadConfigurationFile(String fileName, DocumentBuilder db) {
        Document doc = null;
        InputStream is = null;
        ProxyServerConfig config = new ProxyServerConfig();
        try {
            is = new FileInputStream(new File(fileName));

            if (is == null) {
                throw new Exception("Could not open file " + fileName);
            }

            doc = db.parse(is);
        } catch (Exception e) {
            final String s = "Caught exception while loading file " + fileName;
            logger.error(s, e);
            throw new ConfigurationException(s, e);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    logger.error("Unable to close input stream", e);
                }
            }
        }
        Element rootElement = doc.getDocumentElement();
        NodeList children = rootElement.getChildNodes();
        int childSize = children.getLength();

        for (int i = 0; i < childSize; i++) {
            Node childNode = children.item(i);

            if (childNode instanceof Element) {
                Element child = (Element) childNode;

                final String nodeName = child.getNodeName();
                if (nodeName.equals("proxy")) {
                    loadProxyConfig(child, config);
                } else if (nodeName.equals("connectionManagerList")) {
                    loadConnectionManagers(child, config);
                } else if (nodeName.equals("dbServerLoader")) {
                    loadDbServerLoader(rootElement, config);
                } else if (nodeName.equals("queryRouter")) {
                    loadQueryRouter(rootElement, config);
                }
            }
        }

        if (logger.isInfoEnabled()) {
            logger.info("Loaded Amoeba Proxy configuration from: " + fileName);
        }
        return config;
    }

    private void loadQueryRouter(Element current, ProxyServerConfig config) {
        BeanObjectEntityConfig queryRouter = DocumentUtil
                .loadBeanConfig(DocumentUtil.getTheOnlyElement(current, "queryRouter"));
        config.setQueryRouterConfig(queryRouter);
    }

    private void loadDbServerLoader(Element current, ProxyServerConfig config) {
        BeanObjectEntityConfig dbserverLoader = DocumentUtil
                .loadBeanConfig(DocumentUtil.getTheOnlyElement(current, "dbServerLoader"));
        DBServerConfigLoader loader = (DBServerConfigLoader) dbserverLoader.createBeanObject(true,
                this.getConnectionManagerList());
        config.putAllServers(loader.loadConfig());
    }

    private void loadConnectionManagers(Element current, ProxyServerConfig config) {
        NodeList children = current.getChildNodes();
        int childSize = children.getLength();
        for (int i = 0; i < childSize; i++) {
            Node childNode = children.item(i);
            if (childNode instanceof Element) {
                Element child = (Element) childNode;
                BeanObjectEntityConfig managerConfig = DocumentUtil.loadBeanConfig(child);
                if (StringUtil.isEmpty(managerConfig.getClassName())) {
                    managerConfig.setClassName(getDefaultServerConnectionManagerClassName());
                }
                config.addManager(managerConfig.getName(), managerConfig);
            }
        }

        //create bean and init
        for (Map.Entry<String, BeanObjectEntityConfig> entry : config.getManagers().entrySet()) {
            BeanObjectEntityConfig beanObjectEntityConfig = entry.getValue();
            try {
                ConnectionManager manager = (ConnectionManager) createBeanObjectEntity(beanObjectEntityConfig,
                        true);
                manager.setName(entry.getKey());
                conMgrMap.put(manager.getName(), manager);
            } catch (Exception e) {
                throw new ConfigurationException("manager instance error", e);
            }
        }
    }

    private void loadProxyConfig(Element current, ProxyServerConfig config) {
        NodeList children = current.getChildNodes();
        int childSize = children.getLength();
        Map<String, Object> map = new HashMap<String, Object>();
        for (int i = 0; i < childSize; i++) {
            Node childNode = children.item(i);
            if (childNode instanceof Element) {
                Element child = (Element) childNode;
                final String nodeName = child.getNodeName();
                if (nodeName.equals("property")) {
                    String key = child.getAttribute("name");
                    String value = child.getTextContent();
                    map.put(key, value);
                } else if (nodeName.equals("service")) {
                    BeanObjectEntityConfig server = DocumentUtil.loadBeanConfig(child);
                    config.addServerConfig(server);
                } else if (nodeName.equals("runtime")) {
                    BeanObjectEntityConfig runtime = DocumentUtil.loadBeanConfig(child);
                    config.setRuntimeConfig(runtime);
                }
            }
        }
        ParameterMapping.mappingObject(config, map, null);
    }

    public void appendReport(StringBuilder buffer, long now, long sinceLast, boolean reset, Level level) {
        for (Map.Entry<String, ObjectPool> entry : getPoolMap().entrySet()) {
            ObjectPool pool = entry.getValue();
            String poolName = entry.getKey();
            buffer.append("* Server pool=").append(poolName == null ? "default pool" : poolName).append("\n")
                    .append(" - pool active Size=").append(pool.getNumActive());
            buffer.append(", pool Idle size=").append(pool.getNumIdle()).append("\n");
        }
    }

    static class CloseObjectPoolHeartbeatDelayed extends HeartbeatDelayed {
        private ObjectPool pool;

        public CloseObjectPoolHeartbeatDelayed(long nsTime, TimeUnit timeUnit, ObjectPool pool) {
            super(nsTime, timeUnit);
            this.pool = pool;
        }

        @Override
        public Status doCheck() {
            if (pool.getNumActive() == 0) {
                return Status.VALID;
            }
            return null;
        }

        public boolean isCycle() {
            return false;
        }

        public void cancel() {
            try {
                this.pool.close();
            } catch (Exception e) {
            }
        }

        public boolean equals(Object obj) {
            if (obj instanceof CloseObjectPoolHeartbeatDelayed) {
                CloseObjectPoolHeartbeatDelayed other = (CloseObjectPoolHeartbeatDelayed) obj;
                return other.pool == this.pool && this.getClass() == obj.getClass();
            } else {
                return false;
            }
        }

        public int hashCode() {
            return pool == null ? this.getClass().hashCode() : this.getClass().hashCode() + pool.hashCode();
        }

        @Override
        public String getName() {
            return "closing Pool=" + pool.getName();
        }

    }

    private ObjectPool createObjectPool(DBServerConfig config) throws ConfigurationException {
        ObjectPool pool = null;
        try {
            BeanObjectEntityConfig poolConfig = config.getPoolConfig();
            pool = (ObjectPool) createBeanObjectEntity(poolConfig, true);
            pool.setName(StringUtil.isEmpty(poolConfig.getName()) ? config.getName() : poolConfig.getName());

            if (config.getFactoryConfig() != null) {
                PoolableObjectFactory factory = (PoolableObjectFactory) createBeanObjectEntity(
                        config.getFactoryConfig(), true);
                pool.setFactory(factory);
            }
        } catch (Exception e) {
            throw new ConfigurationException("createBean error", e);
        }

        if (pool instanceof MultipleLoadBalanceObjectPool) {
            MultipleLoadBalanceObjectPool multiPool = (MultipleLoadBalanceObjectPool) pool;
            multiPool.initAllPools();
        } else {
            PoolableObject object = null;
            try {
                object = (PoolableObject) pool.borrowObject();
            } catch (Exception e) {
                logger.error("init pool error!", e);
                throw new ConfigurationException("init pool error!", e);
            } finally {
                if (object != null) {
                    try {
                        pool.returnObject(object);
                    } catch (Exception e) {
                        logger.error("return init pools error", e);
                        throw new ConfigurationException("return init pools error", e);
                    }
                }
            }
        }

        return pool;
    }

    /**
     * update dbServerConfig
     * @param sourceConfig
     * @param tryUpdate
     * @throws ConfigurationException
     */
    public void updateDBServer(DBServerConfig sourceConfig, boolean tryUpdate) throws ConfigurationException {
        boolean abstractive = sourceConfig.getAbstractive();

        if (sourceConfig == null || StringUtil.isEmpty(sourceConfig.getName())) {
            throw new ConfigurationException("config or config's name cannot be null");
        }

        if (tryUpdate) {

            //try to create ObjectPool with this sourceConfig
            if (!abstractive) {
                DBServerConfig config = (DBServerConfig) sourceConfig.clone();
                if (sourceConfig.getParent() != null) {
                    DBServerConfig parent = this.getConfig().getDbServers().get(config.getParent());
                    if (parent == null) {
                        throw new ConfigurationException(
                                "parent config withe name=" + config.getParent() + " not found");
                    }
                    this.inheritDBServerConfig(parent, config);
                }

                ObjectPool pool = createObjectPool(config);
                try {
                    pool.close();
                } catch (Exception e) {

                }
            } else {
                Map<String, DBServerConfig> dbServerConfigs = this.getConfig().getDbServers();
                for (Map.Entry<String, DBServerConfig> entry : dbServerConfigs.entrySet()) {
                    if (StringUtil.equals(entry.getValue().getParent(), sourceConfig.getName())) {
                        if (!entry.getValue().getAbstractive()) {
                            DBServerConfig child = (DBServerConfig) entry.getValue().clone();
                            this.inheritDBServerConfig(sourceConfig, child);
                            ObjectPool pool = createObjectPool(child);
                            try {
                                pool.close();
                            } catch (Exception e) {

                            }
                            break;
                        }
                    }
                }
            }

        } else {

            /**
             * close old objectPool
             * if this configuration is abstractive then close all children's objectPools 
             * else the old ObjectPool will be closed
             * 
             */
            this.getConfig().addServer(sourceConfig.getName(), sourceConfig);

            if (!abstractive) {
                DBServerConfig config = (DBServerConfig) sourceConfig.clone();
                if (sourceConfig.getParent() != null) {
                    DBServerConfig parent = this.getConfig().getDbServers().get(sourceConfig.getParent());
                    if (parent == null) {
                        throw new ConfigurationException(
                                "parent config withe name=" + sourceConfig.getParent() + " not found");
                    }

                    this.inheritDBServerConfig(parent, config);
                }

                ObjectPool pool = createObjectPool(config);

                //close old ObjectPool
                ObjectPool oldObjectPool = this.getPoolMap().get(config.getName());

                this.getPoolMap().put(config.getName(), pool);
                this.notifyAllContextChangedListener();
                if (oldObjectPool != null) {

                    //MultipleLoadBalanceObjectPool not to be closed;
                    if (!(oldObjectPool instanceof MultipleLoadBalanceObjectPool)) {
                        CloseObjectPoolHeartbeatDelayed delay = new CloseObjectPoolHeartbeatDelayed(5,
                                TimeUnit.SECONDS, oldObjectPool);
                        HeartbeatManager.addHeartbeat(delay);
                    }
                }
            } else {
                //close all children's ObjectPools
                Map<String, DBServerConfig> dbServerConfigs = this.getConfig().getDbServers();
                for (Map.Entry<String, DBServerConfig> entry : dbServerConfigs.entrySet()) {
                    if (StringUtil.equals(entry.getValue().getParent(), sourceConfig.getName())) {
                        if (!entry.getValue().getAbstractive()) {
                            DBServerConfig child = (DBServerConfig) entry.getValue().clone();
                            this.inheritDBServerConfig(sourceConfig, child);

                            ObjectPool pool = createObjectPool(child);

                            //close old ObjectPool
                            ObjectPool oldObjectPool = this.getPoolMap().get(child.getName());

                            this.getPoolMap().put(child.getName(), pool);
                            this.notifyAllContextChangedListener();
                            if (oldObjectPool != null) {

                                //MultipleLoadBalanceObjectPool not to be closed;
                                if (!(oldObjectPool instanceof MultipleLoadBalanceObjectPool)) {
                                    CloseObjectPoolHeartbeatDelayed delay = new CloseObjectPoolHeartbeatDelayed(5,
                                            TimeUnit.SECONDS, oldObjectPool);
                                    HeartbeatManager.addHeartbeat(delay);
                                }
                            }
                        }
                    }
                }

                this.getConfig().addServer(sourceConfig.getName(), sourceConfig);
            }
        }
    }
}