/* * 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.server.config.node; import io.mycat.MycatServer; import io.mycat.backend.PhysicalDBNode; import io.mycat.backend.PhysicalDBPool; import io.mycat.server.config.cluster.MycatClusterConfig; import io.mycat.server.config.loader.ConfigInitializer; import io.mycat.server.config.loader.ConfigReLoader; import io.mycat.util.TimeUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Map; import java.util.concurrent.locks.ReentrantLock; /** * @author mycat */ public class MycatConfig implements ConfigReLoader{ private static final Logger LOGGER = LoggerFactory.getLogger("MycatConfig"); private static final int RELOAD = 1; private static final int ROLLBACK = 2; private static final int RELOAD_ALL = 3; private volatile SystemConfig system; private volatile MycatClusterConfig cluster; private volatile MycatClusterConfig _cluster; private volatile QuarantineConfig quarantine; private volatile QuarantineConfig _quarantine; private volatile Map<String, UserConfig> users; private volatile Map<String, UserConfig> _users; private volatile Map<String, SchemaConfig> schemas; private volatile Map<String, SchemaConfig> _schemas; private volatile Map<String, PhysicalDBNode> dataNodes; private volatile Map<String, PhysicalDBNode> _dataNodes; private volatile Map<String, PhysicalDBPool> dataHosts; private volatile Map<String, PhysicalDBPool> _dataHosts; private volatile HostIndexConfig hostIndexConfig; private volatile HostIndexConfig _hostIndexConfig; private volatile CharsetConfig charsetConfig; private volatile CharsetConfig _charsetConfig; private volatile SequenceConfig sequenceConfig; private volatile SequenceConfig _sequenceConfig; private long reloadTime; private long rollbackTime; private int status; private final ReentrantLock lock; public MycatConfig() { ConfigInitializer confInit = new ConfigInitializer(true); this.system = confInit.getSystem(); this.users = confInit.getUsers(); this.schemas = confInit.getSchemas(); this.dataHosts = confInit.getDataHosts(); this.charsetConfig = confInit.getCharsetConfig(); this.sequenceConfig = confInit.getSequenceConfig(); this.hostIndexConfig = confInit.getHostIndexs(); this.dataNodes = confInit.getDataNodes(); for (PhysicalDBPool dbPool : dataHosts.values()) { dbPool.setSchemas(getDataNodeSchemasOfDataHost(dbPool.getHostName())); } this.quarantine = confInit.getQuarantine(); this.cluster = confInit.getCluster(); this.reloadTime = TimeUtil.currentTimeMillis(); this.rollbackTime = -1L; this.status = RELOAD; this.lock = new ReentrantLock(); } public SystemConfig getSystem() { return system; } public Map<String, UserConfig> getUsers() { return users; } public Map<String, UserConfig> getBackupUsers() { return _users; } public Map<String, SchemaConfig> getSchemas() { return schemas; } public Map<String, SchemaConfig> getBackupSchemas() { return _schemas; } public Map<String, PhysicalDBNode> getDataNodes() { return dataNodes; } public String getHostIndex(String hostName, String index) { if(this.hostIndexConfig.getProps().isEmpty() || !this.hostIndexConfig.getProps().containsKey(hostName)){ return index; } return String.valueOf(hostIndexConfig.getProps().get(hostName)); } public void setHostIndex(String hostName, int index) { this.hostIndexConfig.getProps().put(hostName, index); } public String[] getDataNodeSchemasOfDataHost(String dataHost) { ArrayList<String> schemas = new ArrayList<String>(30); for (PhysicalDBNode dn : dataNodes.values()) { if (dn.getDbPool().getHostName().equals(dataHost)) { schemas.add(dn.getDatabase()); } } return schemas.toArray(new String[schemas.size()]); } public Map<String, PhysicalDBNode> getBackupDataNodes() { return _dataNodes; } public Map<String, PhysicalDBPool> getDataHosts() { return dataHosts; } public Map<String, PhysicalDBPool> getBackupDataHosts() { return _dataHosts; } public MycatClusterConfig getCluster() { return cluster; } public MycatClusterConfig getBackupCluster() { return _cluster; } public QuarantineConfig getQuarantine() { return quarantine; } public QuarantineConfig getBackupQuarantine() { return _quarantine; } public ReentrantLock getLock() { return lock; } public long getReloadTime() { return reloadTime; } public long getRollbackTime() { return rollbackTime; } public CharsetConfig getBackupCharsetConfig() { return _charsetConfig; } public SequenceConfig getBackupSequenceConfig() { return _sequenceConfig; } public HostIndexConfig getBackupHostIndexs() { return _hostIndexConfig; } public CharsetConfig getCharsetConfig() { return charsetConfig; } public void setCharsetConfig(CharsetConfig charsetConfig) { this.charsetConfig = charsetConfig; } public SequenceConfig getSequenceConfig() { return sequenceConfig; } public void setSequenceConfig(SequenceConfig sequenceConfig) { this.sequenceConfig = sequenceConfig; } public boolean canRollback() { if (_users == null || _schemas == null || _dataNodes == null || _dataHosts == null || _cluster == null || _quarantine == null || status == ROLLBACK) { return false; } else { return true; } } public void reload(Map<String, UserConfig> users, Map<String, SchemaConfig> schemas, Map<String, PhysicalDBNode> dataNodes, Map<String, PhysicalDBPool> dataHosts, MycatClusterConfig cluster, QuarantineConfig quarantine, CharsetConfig charsetConfig, SequenceConfig sequenceConfig, HostIndexConfig hostIndexConfig,boolean reloadAll) { apply(users, schemas, dataNodes, dataHosts, cluster, quarantine,charsetConfig,sequenceConfig,hostIndexConfig,reloadAll); this.reloadTime = TimeUtil.currentTimeMillis(); this.status = reloadAll?RELOAD_ALL:RELOAD; } public void rollback(Map<String, UserConfig> users, Map<String, SchemaConfig> schemas, Map<String, PhysicalDBNode> dataNodes, Map<String, PhysicalDBPool> dataHosts, MycatClusterConfig cluster, QuarantineConfig quarantine, CharsetConfig charsetConfig, SequenceConfig sequenceConfig, HostIndexConfig hostIndexConfig) { apply(users, schemas, dataNodes, dataHosts, cluster, quarantine,charsetConfig,sequenceConfig,hostIndexConfig,status==RELOAD_ALL); this.rollbackTime = TimeUtil.currentTimeMillis(); this.status = ROLLBACK; } private void apply(Map<String, UserConfig> users, Map<String, SchemaConfig> schemas, Map<String, PhysicalDBNode> dataNodes, Map<String, PhysicalDBPool> dataHosts, MycatClusterConfig cluster, QuarantineConfig quarantine, CharsetConfig charsetConfig, SequenceConfig sequenceConfig, HostIndexConfig hostIndexConfig, boolean isLoadAll) { final ReentrantLock lock = this.lock; lock.lock(); try { if(isLoadAll) { // stop datasource heartbeat Map<String, PhysicalDBPool> oldDataHosts = this.dataHosts; if (oldDataHosts != null) { for (PhysicalDBPool n : oldDataHosts.values()) { if (n != null) { n.stopHeartbeat(); } } } this._dataNodes = this.dataNodes; this._dataHosts = this.dataHosts; } this._users = this.users; this._schemas = this.schemas; this._cluster = this.cluster; this._quarantine = this.quarantine; this._charsetConfig = this.charsetConfig; this._sequenceConfig = this.sequenceConfig; this._hostIndexConfig = this.hostIndexConfig; if(isLoadAll) { // start datasoruce heartbeat if (dataNodes != null) { for (PhysicalDBPool n : dataHosts.values()) { if (n != null) { n.startHeartbeat(); } } } this.dataNodes = dataNodes; this.dataHosts = dataHosts; } this.users = users; this.schemas = schemas; this.cluster = cluster; this.quarantine = quarantine; this.charsetConfig = charsetConfig; this.sequenceConfig = sequenceConfig; this.hostIndexConfig = hostIndexConfig; } finally { lock.unlock(); } } public boolean initDatasource(){ LOGGER.info("Initialize dataHost ..."); for (PhysicalDBPool node : dataHosts.values()) { String index = this.getHostIndex(node.getHostName(),"0"); if (!"0".equals(index)) { LOGGER.info("init datahost: " + node.getHostName() + " to use datasource index:" + index); } node.init(Integer.valueOf(index)); node.startHeartbeat(); } return true; } public boolean reloadDatasource(){ Map<String, PhysicalDBPool> cNodes = this.getDataHosts(); boolean reloadStatus = true; for (PhysicalDBPool dn : dataHosts.values()) { dn.setSchemas(MycatServer.getInstance().getConfig().getDataNodeSchemasOfDataHost(dn.getHostName())); //init datahost String index = this.getHostIndex(dn.getHostName(), "0"); if (!"0".equals(index)) { LOGGER.info("init datahost: " + dn.getHostName() + " to use datasource index:" + index); } dn.init(Integer.valueOf(index)); //dn.init(0); if (!dn.isInitSuccess()) { reloadStatus = false; // 如果重载不成功,则清理已初始化的资源。 LOGGER.warn("reload failed ,clear previously created datasources "); dn.clearDataSources("reload config"); dn.stopHeartbeat(); break; } } // 处理旧的资源 for (PhysicalDBPool dn : cNodes.values()) { dn.clearDataSources("reload config clear old datasources"); dn.stopHeartbeat(); } return reloadStatus; } public boolean rebackDatasource(){ // 如果回滚已经存在的pool boolean rollbackStatus = true; Map<String, PhysicalDBPool> cNodes = this.getDataHosts(); for (PhysicalDBPool dn : dataHosts.values()) { dn.init(dn.getActivedIndex()); if (!dn.isInitSuccess()) { rollbackStatus = false; break; } } // 如果回滚不成功,则清理已初始化的资源。 if (!rollbackStatus) { for (PhysicalDBPool dn : dataHosts.values()) { dn.clearDataSources("rollbackup config"); dn.stopHeartbeat(); } return false; } // 处理旧的资源 for (PhysicalDBPool dn : cNodes.values()) { dn.clearDataSources("clear old config "); dn.stopHeartbeat(); } return rollbackStatus; } @Override public void reloadSchemaConfig(String schema) { // TODO Auto-generated method stub } @Override public void reloadSchemaConfigs() { // TODO Auto-generated method stub } @Override public void reloadDataNodeConfigs() { // TODO Auto-generated method stub } @Override public void reloadDataHostConfigs() { // TODO Auto-generated method stub } @Override public void reloadTableRuleConfigs() { // TODO Auto-generated method stub } @Override public void reloadSystemConfig() { // TODO Auto-generated method stub } @Override public void reloadUserConfig(String user) { // TODO Auto-generated method stub } @Override public void reloadUserConfigs() { // TODO Auto-generated method stub } @Override public void reloadQuarantineConfigs() { // TODO Auto-generated method stub } @Override public void reloadClusterConfigs() { // TODO Auto-generated method stub } @Override public void reloadCharsetConfigs() { // TODO Auto-generated method stub } @Override public void reloadHostIndexConfig() { // TODO Auto-generated method stub } }