io.mycat.manager.response.ReloadConfig.java Source code

Java tutorial

Introduction

Here is the source code for io.mycat.manager.response.ReloadConfig.java

Source

/*
 * Copyright (c) 2013, OpenCloudDB/MyCAT and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software;Designed and Developed mainly by many Chinese 
 * opensource volunteers. you can redistribute it and/or modify it under the 
 * terms of the GNU General Public License version 2 only, as published by the
 * Free Software Foundation.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 * 
 * Any questions about this component can be directed to it's project Web address 
 * https://code.google.com/p/opencloudb/.
 *
 */
package io.mycat.manager.response;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.locks.ReentrantLock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;

import io.mycat.MycatServer;
import io.mycat.backend.BackendConnection;
import io.mycat.backend.datasource.PhysicalDBNode;
import io.mycat.backend.datasource.PhysicalDBPool;
import io.mycat.backend.datasource.PhysicalDatasource;
import io.mycat.backend.jdbc.JDBCConnection;
import io.mycat.backend.mysql.nio.MySQLConnection;
import io.mycat.config.ConfigInitializer;
import io.mycat.config.ErrorCode;
import io.mycat.config.MycatCluster;
import io.mycat.config.MycatConfig;
import io.mycat.config.model.FirewallConfig;
import io.mycat.config.model.SchemaConfig;
import io.mycat.config.model.UserConfig;
import io.mycat.config.util.DnPropertyUtil;
import io.mycat.manager.ManagerConnection;
import io.mycat.net.NIOProcessor;
import io.mycat.net.mysql.OkPacket;

/**
 * @author mycat
 * @author zhuam
 */
public final class ReloadConfig {

    private static final Logger LOGGER = LoggerFactory.getLogger(ReloadConfig.class);

    public static void execute(ManagerConnection c, final boolean loadAll) {

        // reload @@config_all ??
        if (loadAll && !NIOProcessor.backends_old.isEmpty()) {
            c.writeErrMessage(ErrorCode.ER_YES,
                    "The are several unfinished db transactions before executing \"reload @@config_all\", therefore the execution is terminated for logical integrity and please try again later.");
            return;
        }

        final ReentrantLock lock = MycatServer.getInstance().getConfig().getLock();
        lock.lock();
        try {
            ListenableFuture<Boolean> listenableFuture = MycatServer.getInstance().getListeningExecutorService()
                    .submit(new Callable<Boolean>() {
                        @Override
                        public Boolean call() throws Exception {
                            return loadAll ? reload_all() : reload();
                        }
                    });
            Futures.addCallback(listenableFuture, new ReloadCallBack(c),
                    MycatServer.getInstance().getListeningExecutorService());
        } finally {
            lock.unlock();
        }
    }

    public static boolean reload_all() {

        /**
         *  1??
         *  1.1?ConfigInitializer ?
         *  1.2?DataNode/DataHost 
         */
        ConfigInitializer loader = new ConfigInitializer(true);
        Map<String, UserConfig> newUsers = loader.getUsers();
        Map<String, SchemaConfig> newSchemas = loader.getSchemas();
        Map<String, PhysicalDBNode> newDataNodes = loader.getDataNodes();
        Map<String, PhysicalDBPool> newDataHosts = loader.getDataHosts();
        MycatCluster newCluster = loader.getCluster();
        FirewallConfig newFirewall = loader.getFirewall();

        /**
         * 1.2?
         */
        loader.testConnection();

        /**
         *  2?
         *  2.1?? dataSource 
         *  2.2? dataSource ? ? 2.3
         *  2.3? dataSource 
         *  2.4?? dataSource  
         *  2.5?? dataSource 
         */

        MycatConfig config = MycatServer.getInstance().getConfig();

        /**
         * 2.1 ?? dataSource  ???
         */

        boolean isReloadStatusOK = true;

        /**
         * 2.2? dataHosts ?
         */
        for (PhysicalDBPool dbPool : newDataHosts.values()) {
            String hostName = dbPool.getHostName();

            //  schemas
            ArrayList<String> dnSchemas = new ArrayList<String>(30);
            for (PhysicalDBNode dn : newDataNodes.values()) {
                if (dn.getDbPool().getHostName().equals(hostName)) {
                    dnSchemas.add(dn.getDatabase());
                }
            }
            dbPool.setSchemas(dnSchemas.toArray(new String[dnSchemas.size()]));

            // ? data host
            String dnIndex = DnPropertyUtil.loadDnIndexProps().getProperty(dbPool.getHostName(), "0");
            if (!"0".equals(dnIndex)) {
                LOGGER.info("init datahost: " + dbPool.getHostName() + "  to use datasource index:" + dnIndex);
            }

            dbPool.init(Integer.valueOf(dnIndex));
            if (!dbPool.isInitSuccess()) {
                isReloadStatusOK = false;
                break;
            }
        }

        /**
         *  TODO ?
         *    
         *   dataHosts ???
         */
        if (isReloadStatusOK) {

            /**
             * 2.3? ???
             */
            config.reload(newUsers, newSchemas, newDataNodes, newDataHosts, newCluster, newFirewall, true);

            /**
             * 2.4? ??
             */
            LOGGER.warn("1?clear old backend connection(size): " + NIOProcessor.backends_old.size());

            // ? reload  old Cons
            Iterator<BackendConnection> iter = NIOProcessor.backends_old.iterator();
            while (iter.hasNext()) {
                BackendConnection con = iter.next();
                con.close("clear old datasources");
                iter.remove();
            }

            Map<String, PhysicalDBPool> oldDataHosts = config.getBackupDataHosts();
            for (PhysicalDBPool dbPool : oldDataHosts.values()) {
                dbPool.stopHeartbeat();

                // ?????
                for (PhysicalDatasource ds : dbPool.getAllDataSources()) {
                    //
                    for (NIOProcessor processor : MycatServer.getInstance().getProcessors()) {
                        for (BackendConnection con : processor.getBackends().values()) {
                            if (con instanceof MySQLConnection) {
                                MySQLConnection mysqlCon = (MySQLConnection) con;
                                if (mysqlCon.getPool() == ds) {
                                    NIOProcessor.backends_old.add(con);
                                }

                            } else if (con instanceof JDBCConnection) {
                                JDBCConnection jdbcCon = (JDBCConnection) con;
                                if (jdbcCon.getPool() == ds) {
                                    NIOProcessor.backends_old.add(con);
                                }
                            }
                        }
                    }
                }
            }
            LOGGER.warn("2?to be recycled old backend connection(size): " + NIOProcessor.backends_old.size());

            //?
            MycatServer.getInstance().getCacheService().clearCache();
            MycatServer.getInstance().initRuleData();
            return true;

        } else {
            // ??????
            LOGGER.warn("reload failed, clear previously created datasources ");
            for (PhysicalDBPool dbPool : newDataHosts.values()) {
                dbPool.clearDataSources("reload config");
                dbPool.stopHeartbeat();
            }
            return false;
        }
    }

    public static boolean reload() {

        /**
        *  1?? ConfigInitializer ?, ????,? dataHost  dataNode
        */
        ConfigInitializer loader = new ConfigInitializer(false);
        Map<String, UserConfig> users = loader.getUsers();
        Map<String, SchemaConfig> schemas = loader.getSchemas();
        Map<String, PhysicalDBNode> dataNodes = loader.getDataNodes();
        Map<String, PhysicalDBPool> dataHosts = loader.getDataHosts();
        MycatCluster cluster = loader.getCluster();
        FirewallConfig firewall = loader.getFirewall();

        /**
         * 2????
         */
        MycatServer.getInstance().getConfig().reload(users, schemas, dataNodes, dataHosts, cluster, firewall,
                false);

        /**
         * 3??
         */
        MycatServer.getInstance().getCacheService().clearCache();
        MycatServer.getInstance().initRuleData();
        return true;
    }

    /**
     * ?
     */
    private static class ReloadCallBack implements FutureCallback<Boolean> {

        private ManagerConnection mc;

        private ReloadCallBack(ManagerConnection c) {
            this.mc = c;
        }

        @Override
        public void onSuccess(Boolean result) {
            if (result) {
                LOGGER.warn("send ok package to client " + String.valueOf(mc));
                OkPacket ok = new OkPacket();
                ok.packetId = 1;
                ok.affectedRows = 1;
                ok.serverStatus = 2;
                ok.message = "Reload config success".getBytes();
                ok.write(mc);
            } else {
                mc.writeErrMessage(ErrorCode.ER_YES, "Reload config failure");
            }
        }

        @Override
        public void onFailure(Throwable t) {
            mc.writeErrMessage(ErrorCode.ER_YES, "Reload config failure");
        }
    }
}