package io.mycat.server.config.loader.zkloader; import com.google.common.collect.ObjectArrays; import com.alibaba.fastjson.JSON; import org.apache.curator.framework.CuratorFramework; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; import io.mycat.server.config.node.SchemaConfig; import io.mycat.server.config.node.TableConfig; /** * * Created by v1.lion on 2015/10/18. */ public class ZkSchemaConfigLoader extends AbstractZKLoaders { private static final Logger LOGGER = LoggerFactory.getLogger(ZkSchemaConfigLoader.class); //directory name of data node config in zookeeper private static final String SCHEMA_CONFIG_DIRECTORY = "schema-config"; ZkDataNodeConfigLoader dataNodeConfigLoader; ZkRuleConfigLoader ruleConfigLoadr; //hold a zookeeper connection,it is be closed after initiation CuratorFramework zkConnection; //hold schema name mapping to DataNodeConfig private Map<String, SchemaConfig> schemaConfigs; public ZkSchemaConfigLoader(final String clusterID, ZkDataNodeConfigLoader dataNodeConfigLoader, ZkRuleConfigLoader ruleConfigLoader) { super(clusterID, SCHEMA_CONFIG_DIRECTORY); this.ruleConfigLoadr = ruleConfigLoader; this.dataNodeConfigLoader = dataNodeConfigLoader; } @Override public void fetchConfig(CuratorFramework zkConnection) { this.ruleConfigLoadr.fetchConfig(zkConnection); this.dataNodeConfigLoader.fetchConfig(zkConnection); this.zkConnection = zkConnection; //data node config path in zookeeper //example: /mycat-cluster-1/schema-config / ${schemaName} this.schemaConfigs = super.fetchChildren(zkConnection) .stream() .map(this::createSchema) .collect(Collectors.toMap(SchemaConfig::getName, Function.identity())); } private SchemaConfig createSchema(final String schemaName) { //parse schema //mycat-cluster-1/ schema-config/ ${schema name} SchemaConfig schemaConfig = JSON.parseObject( super.fetchData(this.zkConnection, schemaName), SchemaConfig.class); //parse TableConfig //mycat-cluster-1/ schema-config/ ${schema name} /${table name} Map<String, TableConfig> tables = super.fetchChildren(this.zkConnection, schemaName) .stream() .flatMap(tableName -> generateTable(schemaName, tableName)) .collect(Collectors.toMap(TableConfig::getName, Function.identity())); schemaConfig.setTables(tables); return schemaConfig; } /** * create parent tableConfig. */ private Stream<TableConfig> generateTable(final String schemaName, final String tableName) { TableConfig parentTableConfig = createTableConfig(schemaName, tableName); return Stream.concat( super.fetchChildren(zkConnection, schemaName, tableName) .stream() .flatMap(childTableName -> generateChildTable(parentTableConfig, schemaName, tableName, childTableName)), Stream.of(parentTableConfig)); } /** * create child tableConfig. */ private Stream<TableConfig> generateChildTable(TableConfig parentTableConfig, final String schemaName, final String... childTableName) { //recursion parse child TableConfig //mycat-cluster-1/ schema-config/ ${schema name} /${table name} /${child table name} //deep first. TableConfig childTableConfig = createTableConfig(schemaName, childTableName); childTableConfig.setParentTC(parentTableConfig); return Stream.concat( super.fetchChildren(zkConnection, ObjectArrays.concat(new String[]{schemaName}, childTableName, String.class)) .stream() .flatMap( grandChildTableName -> generateChildTable(childTableConfig, schemaName, ObjectArrays.concat(childTableName, new String[]{grandChildTableName}, String.class)) ) , Stream.of(childTableConfig)); } private TableConfig createTableConfig(String schemaName, String... tableName) { TableConfig tableConfig = JSON.parseObject( super.fetchData(this.zkConnection, schemaName, tableName), TableConfig.class); tableConfig.setRule(this.ruleConfigLoadr.getRuleConfigs().get(tableConfig.getRuleName())); tableConfig.checkConfig(); return tableConfig; } public Map<String, SchemaConfig> getSchemaConfigs() { return schemaConfigs; } }