一、Mycat1.6之加载Schema的DataNode源码解读
//<dataNode name="dn1" dataHost="localhost1_gaojingsong1" database="scott" /> private void load(String dtdFile, String xmlFile) { InputStream dtd = null; InputStream xml = null; dtd = XMLSchemaLoader.class.getResourceAsStream(dtdFile); xml = XMLSchemaLoader.class.getResourceAsStream(xmlFile); Element root = ConfigUtil.getDocument(dtd, xml).getDocumentElement(); //先加载所有的DataHost loadDataHosts(root); //再加载所有的DataNode loadDataNodes(root); //最后加载所有的Schema loadSchemas(root); } //<dataNode name="dn1" dataHost="localhost1_gaojingsong1" database="scott" /> private void loadDataNodes(Element root) { //读取DataNode分支 NodeList list = root.getElementsByTagName("dataNode"); for (int i = 0, n = list.getLength(); i < n; i++) { Element element = (Element) list.item(i); String dnNamePre = element.getAttribute("name"); String databaseStr = element.getAttribute("database"); String host = element.getAttribute("dataHost"); //字符串不为空 if (empty(dnNamePre) || empty(databaseStr) || empty(host)) { throw new ConfigException("dataNode " + dnNamePre + " define error ,attribute can't be empty"); } //dnNames(name),databases(database),hostStrings(dataHost)都可以配置多 个,以',', '$', '-'区分, //但是需要保证database的个数*dataHost的个数=name的个数 //多个dataHost与多个database如果写在一个标签,则每个dataHost拥有所有database //例如: //则为:localhost1拥有dn1$0-75,localhost2也拥有dn1$0-75(对应db$76-151) String[] dnNames = io.mycat.util.SplitUtil.split(dnNamePre, ',', '$', '-'); String[] databases = io.mycat.util.SplitUtil.split(databaseStr, ',', '$', '-'); String[] hostStrings = io.mycat.util.SplitUtil.split(host, ',', '$', '-'); //此处复杂的配置关系请看步骤二实验结果,进行理解 if (dnNames.length > 1 && dnNames.length != databases.length * hostStrings.length) { throw new ConfigException("dataNode " + dnNamePre + " define error ,dnNames.length must be=databases.length*hostStrings.length"); } if (dnNames.length > 1) { List<String[]> mhdList = mergerHostDatabase(hostStrings, databases); for (int k = 0; k < dnNames.length; k++) { String[] hd = mhdList.get(k); String dnName = dnNames[k]; String databaseName = hd[1]; String hostName = hd[0]; createDataNode(dnName, databaseName, hostName); } } else { createDataNode(dnNamePre, databaseStr, host); } } } /** * 匹配DataHost和Database,每个DataHost拥有每个Database名字 * @param hostStrings * @param databases * @return */ private List<String[]> mergerHostDatabase(String[] hostStrings, String[] databases) { List<String[]> mhdList = new ArrayList<>(); for (int i = 0; i < hostStrings.length; i++) { String hostString = hostStrings[i]; for (int i1 = 0; i1 < databases.length; i1++) { String database = databases[i1]; String[] hd = new String[2]; hd[0] = hostString; hd[1] = database; mhdList.add(hd); } } return mhdList; } private void createDataNode(String dnName, String database, String host) { DataNodeConfig conf = new DataNodeConfig(dnName, database, host); if (dataNodes.containsKey(conf.getName())) { throw new ConfigException("dataNode " + conf.getName() + " duplicated!"); } if (!dataHosts.containsKey(host)) { throw new ConfigException("dataNode " + dnName + " reference dataHost:" + host + " not exists!"); } dataHosts.get(host).addDataNode(conf.getName()); dataNodes.put(conf.getName(), conf); } public final class DataNodeConfig { private final String name; private final String database; private final String dataHost; }
二、实验结果验证
结论:
<dataNode name="dn1$0-75" dataHost="localhost$1-10" database="db$0-759" />
name.length must be=databases.length*dataHost.length"
//从A到C地没有直达路径,需要经过B中转,已知从A到B有三条databases路,从B到C有2条dataHost路
//,试问从A到C有几种方案