/*
* 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;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
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.SystemConfig;
import com.alibaba.cobar.config.model.UserConfig;
import com.alibaba.cobar.mysql.MySQLDataNode;
import com.alibaba.cobar.util.TimeUtil;
/**
* @author xianmao.hexm
*/
public class CobarConfig {
private static final int RELOAD = 1;
private static final int ROLLBACK = 2;
private volatile SystemConfig system;
private volatile CobarCluster cluster;
private volatile CobarCluster _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, MySQLDataNode> dataNodes;
private volatile Map<String, MySQLDataNode> _dataNodes;
private volatile Map<String, DataSourceConfig> dataSources;
private volatile Map<String, DataSourceConfig> _dataSources;
private long reloadTime;
private long rollbackTime;
private int status;
private final ReentrantLock lock;
public CobarConfig() {
ConfigInitializer confInit = new ConfigInitializer();
this.system = confInit.getSystem();
this.users = confInit.getUsers();
this.schemas = confInit.getSchemas();
this.dataSources = confInit.getDataSources();
this.dataNodes = confInit.getDataNodes();
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, MySQLDataNode> getDataNodes() {
return dataNodes;
}
public Map<String, MySQLDataNode> getBackupDataNodes() {
return _dataNodes;
}
public Map<String, DataSourceConfig> getDataSources() {
return dataSources;
}
public Map<String, DataSourceConfig> getBackupDataSources() {
return _dataSources;
}
public CobarCluster getCluster() {
return cluster;
}
public CobarCluster 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 void reload(Map<String, UserConfig> users, Map<String, SchemaConfig> schemas,
Map<String, MySQLDataNode> dataNodes, Map<String, DataSourceConfig> dataSources,
CobarCluster cluster, QuarantineConfig quarantine) {
apply(users, schemas, dataNodes, dataSources, cluster, quarantine);
this.reloadTime = TimeUtil.currentTimeMillis();
this.status = RELOAD;
}
public boolean canRollback() {
if (_users == null || _schemas == null || _dataNodes == null || _dataSources == null || _cluster == null
|| _quarantine == null || status == ROLLBACK) {
return false;
} else {
return true;
}
}
public void rollback(Map<String, UserConfig> users, Map<String, SchemaConfig> schemas,
Map<String, MySQLDataNode> dataNodes, Map<String, DataSourceConfig> dataSources,
CobarCluster cluster, QuarantineConfig quarantine) {
apply(users, schemas, dataNodes, dataSources, cluster, quarantine);
this.rollbackTime = TimeUtil.currentTimeMillis();
this.status = ROLLBACK;
}
private void apply(Map<String, UserConfig> users, Map<String, SchemaConfig> schemas,
Map<String, MySQLDataNode> dataNodes, Map<String, DataSourceConfig> dataSources,
CobarCluster cluster, QuarantineConfig quarantine) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
// stop mysql heartbeat
Map<String, MySQLDataNode> oldDataNodes = this.dataNodes;
if (oldDataNodes != null) {
for (MySQLDataNode n : oldDataNodes.values()) {
if (n != null) {
n.stopHeartbeat();
}
}
}
// stop cobar heartbeat
CobarCluster oldCluster = this.cluster;
if (oldCluster != null) {
Map<String, CobarNode> nodes = oldCluster.getNodes();
for (CobarNode n : nodes.values()) {
if (n != null) {
n.stopHeartbeat();
}
}
}
this._users = this.users;
this._schemas = this.schemas;
this._dataNodes = this.dataNodes;
this._dataSources = this.dataSources;
this._cluster = this.cluster;
this._quarantine = this.quarantine;
// start mysql heartbeat
if (dataNodes != null) {
for (MySQLDataNode n : dataNodes.values()) {
if (n != null) {
n.startHeartbeat();
}
}
}
// start cobar heartbeat
if (cluster != null) {
Map<String, CobarNode> nodes = cluster.getNodes();
for (CobarNode n : nodes.values()) {
if (n != null) {
n.startHeartbeat();
}
}
}
this.users = users;
this.schemas = schemas;
this.dataNodes = dataNodes;
this.dataSources = dataSources;
this.cluster = cluster;
this.quarantine = quarantine;
} finally {
lock.unlock();
}
}
}