/*
* Copyright 2015 Liu Huanting.
*
* 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 fm.liu.timo.config.loader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import fm.liu.timo.config.model.Database;
import fm.liu.timo.config.model.Datanode;
import fm.liu.timo.config.model.Datasource;
import fm.liu.timo.config.model.Function;
import fm.liu.timo.config.model.Rule;
import fm.liu.timo.config.model.Table;
import fm.liu.timo.config.model.User;
import fm.liu.timo.route.function.AutoFunction;
import fm.liu.timo.route.function.HashFunction;
import fm.liu.timo.route.function.MatchFunction;
import fm.liu.timo.route.function.Range;
import fm.liu.timo.route.function.RangeFunction;
/**
* @author Liu Huanting 2015年5月9日
* 配置库配置加载器
*/
public class ServerConfigLoader {
private final String url;
private final String username;
private final String password;
private final Map<Integer, Datasource> datasources;
private final Map<Integer, Datanode> datanodes;
private final Map<Integer, ArrayList<Integer>> handovers;
private final Map<String, Database> databases;
private final Map<Integer, Rule> rules;
private final Map<Integer, Function> functions;
private final Map<String, User> users;
public ServerConfigLoader(String url, String username, String password) {
this.url = url;
this.username = username;
this.password = password;
this.datasources = new HashMap<Integer, Datasource>();
this.datanodes = new HashMap<Integer, Datanode>();
this.handovers = new HashMap<Integer, ArrayList<Integer>>();
this.databases = new HashMap<String, Database>();
this.rules = new HashMap<Integer, Rule>();
this.functions = new HashMap<Integer, Function>();
this.users = new HashMap<String, User>();
try {
load();
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
private void load() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(url, username, password);
loadFunctions(con);
loadRules(con);
loadDatasources(con);
loadDatanodes(con);
loadHandovers(con);
loadDatabase(con);
loadUsers(con);
con.close();
}
/**
* 加载拆分函数
*/
private void loadFunctions(Connection con) throws SQLException {
String sql = "SELECT `id`,`type` FROM `functions`";
ResultSet result = con.createStatement().executeQuery(sql);
int defaultNode = 1;
while (result.next()) {
int id = result.getInt("id");
String type = result.getString("type").toUpperCase();
Function function = null;
sql = "SELECT `args`,`datanode_id` FROM `function_args` WHERE `function_id`=" + id;
ResultSet r = con.createStatement().executeQuery(sql);
switch (type) {
case "AUTO":
while (r.next()) {
int count = Integer.parseInt(r.getString("args"));
function = new AutoFunction(count);
}
break;
case "HASH":
Set<Range> hash = new HashSet<Range>();
while (r.next()) {
int node = r.getInt("datanode_id");
String[] value = r.getString("args").split(":");
Range range = new Range(node, Long.decode(value[0]), Long.decode(value[1]));
hash.add(range);
}
function = new HashFunction(hash);
break;
case "MATCH":
Map<Object, Integer> match = new HashMap<Object, Integer>();
while (r.next()) {
int node = r.getInt("datanode_id");
if (node != 0) {
Object val = r.getObject("args");
match.put(val, node);
} else {
defaultNode = r.getInt("args");
}
}
function = new MatchFunction(match, defaultNode);
break;
case "RANGE":
Set<Range> ranges = new HashSet<Range>();
while (r.next()) {
int node = r.getInt("datanode_id");
if (node != 0) {
String[] value = r.getString("args").split(":");
Range range =
new Range(node, Long.decode(value[0]), Long.decode(value[1]));
ranges.add(range);
} else {
defaultNode = r.getInt("args");
}
}
function = new RangeFunction(ranges, defaultNode);
break;
}
functions.put(id, function);
}
}
/**
* 加载拆分规则
*/
private void loadRules(Connection con) throws SQLException {
String sql = "SELECT `id`,`column_name`,`function_id` FROM `rules`";
ResultSet result = con.createStatement().executeQuery(sql);
while (result.next()) {
int id = result.getInt("id");
String column = result.getString("column_name").toUpperCase();
int functionId = result.getInt("function_id");
Function function = functions.get(functionId);
if (function == null) {
}
Rule rule = new Rule(column, function);
rules.put(id, rule);
}
}
/**
* 加载数据源
*/
private void loadDatasources(Connection con) throws SQLException {
String sql =
"SELECT `id`,`datanode_id`,`host`,`port`,`username`,`password`,`db`,`datasource_type`,`datasource_status`,`character_type`,`init_con`,`max_con`,`min_idle`,`max_idle`,`idle_check_period` FROM `datasources`";
ResultSet result = con.createStatement().executeQuery(sql);
while (result.next()) {
int id = result.getInt("id");
int datanodeID = result.getInt("datanode_id");
String host = result.getString("host");
int port = result.getInt("port");
String username = result.getString("username");
String password = result.getString("password");
String db = result.getString("db");
int type = result.getInt("datasource_type");
int status = result.getInt("datasource_status");
String charset = result.getString("character_type");
int initCon = result.getInt("init_con");
int maxCon = result.getInt("max_con");
int minIdle = result.getInt("min_idle");
int maxIdle = result.getInt("max_idle");
int idleCheckPeriod = result.getInt("idle_check_period");
Datasource datasource = new Datasource(id, datanodeID, host, port, username, password,
db, type, status, charset, initCon, maxCon, minIdle, maxIdle, idleCheckPeriod);
datasources.put(id, datasource);
}
}
/**
* 加载数据节点
*/
private void loadDatanodes(Connection con) throws SQLException {
String sql = "SELECT `id`,`strategy` FROM `datanodes`";
ResultSet result = con.createStatement().executeQuery(sql);
while (result.next()) {
int id = result.getInt("id");
int strategy = result.getInt("strategy");
List<Integer> ds = new ArrayList<Integer>();
sql = "SELECT `id` FROM `datasources` WHERE `datanode_id`=" + id
+ " ORDER BY `priority` ASC";
ResultSet rs = con.createStatement().executeQuery(sql);
while (rs.next()) {
ds.add(rs.getInt("id"));
}
Datanode datanode = new Datanode(id, strategy, ds);
datanodes.put(id, datanode);
}
}
/**
* 加载节点切换信息
*/
private void loadHandovers(Connection con) throws SQLException {
String sql = "SELECT DISTINCT `datasource_id` FROM `handovers`";
ResultSet result = con.createStatement().executeQuery(sql);
while (result.next()) {
int id = result.getInt("datasource_id");
sql = "SELECT `handover_id` FROM `handovers` WHERE `datasource_id`=" + id
+ " ORDER BY `priority`";
ResultSet rs = con.createStatement().executeQuery(sql);
ArrayList<Integer> sources = new ArrayList<>();
while (rs.next()) {
sources.add(rs.getInt("handover_id"));
}
handovers.put(id, sources);
}
}
/**
* 加载逻辑数据库
*/
private void loadDatabase(Connection con) throws SQLException {
String sql = "SELECT `id`,`name` FROM `dbs`";
ResultSet result = con.createStatement().executeQuery(sql);
while (result.next()) {
int id = result.getInt("id");
String name = result.getString("name").toUpperCase();
Database database = new Database(id, name, loadTables(id, con));
databases.put(name, database);
}
}
/**
* 加载逻辑表
*/
private Map<String, Table> loadTables(int id, Connection con) throws SQLException {
String sql = "SELECT `name`,`type`,`datanodes`,`rule_id` FROM `tables` WHERE db_id=" + id;
Map<String, Table> tables = new HashMap<String, Table>();
ResultSet result = con.createStatement().executeQuery(sql);
while (result.next()) {
String name = result.getString("name").toUpperCase();
int type = result.getInt("type");
String datanodes = result.getString("datanodes");
String[] datanode = datanodes.split(",");
List<Integer> nodes = new ArrayList<Integer>();
for (String node : datanode) {
nodes.add(Integer.parseInt(node));
}
int ruleID = result.getInt("rule_id");
Rule rule = rules.get(ruleID);
Table table = new Table(id, name, type, rule, nodes);
tables.put(name, table);
}
return tables;
}
/**
* 加载用户信息
*/
private void loadUsers(Connection con) throws SQLException {
String sql = "SELECT `username`,`password`,`dbs`,`hosts` FROM `users`";
ResultSet result = con.createStatement().executeQuery(sql);
while (result.next()) {
String username = result.getString("username");
String password = result.getString("password");
String dbs = result.getString("dbs");
String[] db = dbs.split(",");
Set<String> databases = new HashSet<String>();
for (String d : db) {
databases.add(d);
}
String host = result.getString("hosts");
String[] hos = host.split(",");
Set<String> hosts = new HashSet<String>();
for (String h : hos) {
if (!h.equals("")) {
hosts.add(h);
}
}
User user = new User(username, password, databases, hosts);
users.put(username, user);
}
}
public Map<String, User> getUsers() {
return users;
}
public Map<String, Database> getDatabases() {
return databases;
}
public Map<Integer, Datanode> getDatanodes() {
return datanodes;
}
public Map<Integer, Datasource> getDatasources() {
return datasources;
}
public Map<Integer, ArrayList<Integer>> getHandovers() {
return handovers;
}
}