1. Interpretation of the DataNode source code for loading Schema in Mycat1.6
//<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(); //Load all DataHost first loadDataHosts(root); //Reload all DataNodes loadDataNodes(root); //Finally load all schemas loadSchemas(root); } //<dataNode name="dn1" dataHost="localhost1_gaojingsong1" database="scott" /> private void loadDataNodes(Element root) { //Read the DataNode branch 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"); // string is not empty 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) can be configured with multiple , separated by ',', '$', '-', //But you need to ensure the number of databases * the number of dataHosts = the number of names //If multiple dataHost and multiple databases are written in one tag, each dataHost owns all databases //E.g: //Then: localhost1 has dn1$0-75, localhost2 also has dn1$0-75 (corresponding to 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, ',', '$', '-'); //Please see the complex configuration relationship here Step 2 Experimental results to understand 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); } } } /** * Match DataHost and Database, each DataHost has each Database name * @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; }
2. Validation of experimental results
in conclusion:
<dataNode name="dn1$0-75" dataHost="localhost$1-10" database="db$0-759" />
name.length must be=databases.length*dataHost.length"
//There is no direct path from A to C, and it needs to transit through B. It is known that there are three databases from A to B, and two dataHost roads from B to C.
//, how about there are several options from A to C