/* * Copyright 1999-2012 Alibaba Group. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.cobar.manager.response; import java.util.Map; import java.util.concurrent.locks.ReentrantLock; import org.apache.log4j.Logger; import com.alibaba.cobar.CobarCluster; import com.alibaba.cobar.CobarConfig; import com.alibaba.cobar.CobarServer; import com.alibaba.cobar.config.ErrorCode; import com.alibaba.cobar.config.model.DataSourceConfig; import com.alibaba.cobar.config.model.QuarantineConfig; import com.alibaba.cobar.config.model.SchemaConfig; import com.alibaba.cobar.config.model.UserConfig; import com.alibaba.cobar.manager.ManagerConnection; import com.alibaba.cobar.mysql.MySQLDataNode; import com.alibaba.cobar.mysql.MySQLDataSource; import com.alibaba.cobar.net.mysql.OkPacket; /** * @author xianmao.hexm */ public final class RollbackConfig { private static final Logger LOGGER = Logger.getLogger(RollbackConfig.class); public static void execute(ManagerConnection c) { final ReentrantLock lock = CobarServer.getInstance().getConfig().getLock(); lock.lock(); try { if (rollback()) { StringBuilder s = new StringBuilder(); s.append(c).append("Rollback config success by manager"); LOGGER.warn(s.toString()); OkPacket ok = new OkPacket(); ok.packetId = 1; ok.affectedRows = 1; ok.serverStatus = 2; ok.message = "Rollback config success".getBytes(); ok.write(c); } else { c.writeErrMessage(ErrorCode.ER_YES, "Rollback config failure"); } } finally { lock.unlock(); } } private static boolean rollback() { CobarConfig conf = CobarServer.getInstance().getConfig(); Map<String, UserConfig> users = conf.getBackupUsers(); Map<String, SchemaConfig> schemas = conf.getBackupSchemas(); Map<String, MySQLDataNode> dataNodes = conf.getBackupDataNodes(); Map<String, DataSourceConfig> dataSources = conf.getBackupDataSources(); CobarCluster cluster = conf.getBackupCluster(); QuarantineConfig quarantine = conf.getBackupQuarantine(); // 检查可回滚状态 if (!conf.canRollback()) { return false; } // 如果回滚已经存在的pool,初始化连接数参考空闲连接数,否则为1。 boolean rollbackStatus = true; Map<String, MySQLDataNode> cNodes = conf.getDataNodes(); for (MySQLDataNode dn : dataNodes.values()) { MySQLDataNode cdn = cNodes.get(dn.getName()); if (cdn != null && cdn.getSource() != null) { int size = Math.min(cdn.getSource().getIdleCount(), dn.getConfig().getPoolSize()); dn.init(size > 0 ? size : 1, dn.getActivedIndex()); } else { dn.init(1, dn.getActivedIndex()); } if (!dn.isInitSuccess()) { rollbackStatus = false; break; } } // 如果回滚不成功,则清理已初始化的资源。 if (!rollbackStatus) { for (MySQLDataNode dn : dataNodes.values()) { MySQLDataSource ds = dn.getSource(); if (ds != null) { ds.clear(); } } return false; } // 应用回滚 conf.rollback(users, schemas, dataNodes, dataSources, cluster, quarantine); // 处理旧的资源 for (MySQLDataNode dn : cNodes.values()) { MySQLDataSource ds = dn.getSource(); if (ds != null) { ds.clear(); } } return true; } }