1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.mode.metadata;
19
20 import com.google.common.base.Preconditions;
21 import com.google.common.base.Splitter;
22 import lombok.AccessLevel;
23 import lombok.NoArgsConstructor;
24 import org.apache.shardingsphere.infra.config.database.DatabaseConfiguration;
25 import org.apache.shardingsphere.infra.config.database.impl.DataSourceGeneratedDatabaseConfiguration;
26 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
27 import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
28 import org.apache.shardingsphere.infra.datasource.pool.config.DataSourceConfiguration;
29 import org.apache.shardingsphere.infra.datasource.pool.destroyer.DataSourcePoolDestroyer;
30 import org.apache.shardingsphere.infra.instance.InstanceContext;
31 import org.apache.shardingsphere.infra.instance.metadata.jdbc.JDBCInstanceMetaData;
32 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
33 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
34 import org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData;
35 import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
36 import org.apache.shardingsphere.infra.rule.builder.global.GlobalRulesBuilder;
37 import org.apache.shardingsphere.infra.state.datasource.DataSourceState;
38 import org.apache.shardingsphere.infra.state.datasource.DataSourceStateManager;
39 import org.apache.shardingsphere.metadata.factory.ExternalMetaDataFactory;
40 import org.apache.shardingsphere.metadata.factory.InternalMetaDataFactory;
41 import org.apache.shardingsphere.metadata.persist.MetaDataPersistService;
42 import org.apache.shardingsphere.mode.event.storage.StorageNodeDataSource;
43 import org.apache.shardingsphere.mode.manager.ContextManagerBuilderParameter;
44
45 import javax.sql.DataSource;
46 import java.sql.SQLException;
47 import java.util.Collection;
48 import java.util.Collections;
49 import java.util.HashMap;
50 import java.util.LinkedHashMap;
51 import java.util.List;
52 import java.util.Map;
53 import java.util.Map.Entry;
54 import java.util.stream.Collectors;
55
56
57
58
59 @NoArgsConstructor(access = AccessLevel.PRIVATE)
60 public final class MetaDataContextsFactory {
61
62
63
64
65
66
67
68
69
70
71 public static MetaDataContexts create(final MetaDataPersistService persistService, final ContextManagerBuilderParameter param, final InstanceContext instanceContext) throws SQLException {
72 return create(persistService, param, instanceContext, Collections.emptyMap());
73 }
74
75
76
77
78
79
80
81
82
83
84
85 public static MetaDataContexts create(final MetaDataPersistService persistService, final ContextManagerBuilderParameter param,
86 final InstanceContext instanceContext, final Map<String, StorageNodeDataSource> storageNodes) throws SQLException {
87 boolean isDatabaseMetaDataExisted = !persistService.getDatabaseMetaDataService().loadAllDatabaseNames().isEmpty();
88 Map<String, DatabaseConfiguration> effectiveDatabaseConfigs = isDatabaseMetaDataExisted
89 ? createEffectiveDatabaseConfigurations(getDatabaseNames(instanceContext, param.getDatabaseConfigs(), persistService), param.getDatabaseConfigs(), persistService)
90 : param.getDatabaseConfigs();
91 checkDataSourceStates(effectiveDatabaseConfigs, storageNodes, param.isForce());
92
93 Map<String, DataSource> globalDataSources = param.getGlobalDataSources();
94 Collection<RuleConfiguration> globalRuleConfigs = isDatabaseMetaDataExisted ? persistService.getGlobalRuleService().load() : param.getGlobalRuleConfigs();
95 ConfigurationProperties props = isDatabaseMetaDataExisted ? new ConfigurationProperties(persistService.getPropsService().load()) : new ConfigurationProperties(param.getProps());
96 Map<String, ShardingSphereDatabase> databases = isDatabaseMetaDataExisted
97 ? InternalMetaDataFactory.create(persistService, effectiveDatabaseConfigs, props, instanceContext)
98 : ExternalMetaDataFactory.create(effectiveDatabaseConfigs, props, instanceContext);
99 ResourceMetaData globalResourceMetaData = new ResourceMetaData(globalDataSources);
100 RuleMetaData globalRuleMetaData = new RuleMetaData(GlobalRulesBuilder.buildRules(globalRuleConfigs, databases, props));
101 MetaDataContexts result = new MetaDataContexts(persistService, new ShardingSphereMetaData(databases, globalResourceMetaData, globalRuleMetaData, props));
102 if (!isDatabaseMetaDataExisted) {
103 persistDatabaseConfigurations(result, param);
104 persistMetaData(result);
105 }
106 return result;
107 }
108
109 private static Collection<String> getDatabaseNames(final InstanceContext instanceContext,
110 final Map<String, DatabaseConfiguration> databaseConfigs, final MetaDataPersistService persistService) {
111 return instanceContext.getInstance().getMetaData() instanceof JDBCInstanceMetaData ? databaseConfigs.keySet() : persistService.getDatabaseMetaDataService().loadAllDatabaseNames();
112 }
113
114 private static Map<String, DatabaseConfiguration> createEffectiveDatabaseConfigurations(final Collection<String> databaseNames,
115 final Map<String, DatabaseConfiguration> databaseConfigs, final MetaDataPersistService persistService) {
116 return databaseNames.stream().collect(Collectors.toMap(each -> each, each -> createEffectiveDatabaseConfiguration(each, databaseConfigs, persistService)));
117 }
118
119 private static DatabaseConfiguration createEffectiveDatabaseConfiguration(final String databaseName,
120 final Map<String, DatabaseConfiguration> databaseConfigs, final MetaDataPersistService persistService) {
121 closeGeneratedDataSources(databaseName, databaseConfigs);
122 Map<String, DataSourceConfiguration> dataSources = persistService.loadDataSourceConfigurations(databaseName);
123 Collection<RuleConfiguration> databaseRuleConfigs = persistService.getDatabaseRulePersistService().load(databaseName);
124 return new DataSourceGeneratedDatabaseConfiguration(dataSources, databaseRuleConfigs);
125 }
126
127 private static void closeGeneratedDataSources(final String databaseName, final Map<String, ? extends DatabaseConfiguration> databaseConfigs) {
128 if (databaseConfigs.containsKey(databaseName) && !databaseConfigs.get(databaseName).getStorageUnits().isEmpty()) {
129 databaseConfigs.get(databaseName).getDataSources().values().forEach(each -> new DataSourcePoolDestroyer(each).asyncDestroy());
130 }
131 }
132
133 private static void checkDataSourceStates(final Map<String, DatabaseConfiguration> databaseConfigs, final Map<String, StorageNodeDataSource> storageNodes, final boolean force) {
134 Map<String, DataSourceState> storageDataSourceStates = getStorageDataSourceStates(storageNodes);
135 databaseConfigs.forEach((key, value) -> {
136 if (!value.getStorageUnits().isEmpty()) {
137 DataSourceStateManager.getInstance().initStates(key, value.getStorageUnits(), storageDataSourceStates, force);
138 }
139 });
140 }
141
142 private static Map<String, DataSourceState> getStorageDataSourceStates(final Map<String, StorageNodeDataSource> storageDataSourceStates) {
143 Map<String, DataSourceState> result = new HashMap<>(storageDataSourceStates.size(), 1F);
144 storageDataSourceStates.forEach((key, value) -> {
145 List<String> values = Splitter.on(".").splitToList(key);
146 Preconditions.checkArgument(3 == values.size(), "Illegal data source of storage node.");
147 String databaseName = values.get(0);
148 String dataSourceName = values.get(2);
149 result.put(databaseName + "." + dataSourceName, DataSourceState.valueOf(value.getStatus().name()));
150 });
151 return result;
152 }
153
154 private static void persistDatabaseConfigurations(final MetaDataContexts metadataContexts, final ContextManagerBuilderParameter param) {
155 metadataContexts.getPersistService().persistGlobalRuleConfiguration(param.getGlobalRuleConfigs(), param.getProps());
156 for (Entry<String, ? extends DatabaseConfiguration> entry : param.getDatabaseConfigs().entrySet()) {
157 String databaseName = entry.getKey();
158 metadataContexts.getPersistService().persistConfigurations(entry.getKey(), entry.getValue(),
159 metadataContexts.getMetaData().getDatabase(databaseName).getResourceMetaData().getStorageUnits().entrySet().stream()
160 .collect(Collectors.toMap(Entry::getKey, each -> each.getValue().getDataSource(), (oldValue, currentValue) -> oldValue, LinkedHashMap::new)),
161 metadataContexts.getMetaData().getDatabase(databaseName).getRuleMetaData().getRules());
162 }
163 }
164
165 private static void persistMetaData(final MetaDataContexts metaDataContexts) {
166 metaDataContexts.getMetaData().getDatabases().values().forEach(each -> each.getSchemas()
167 .forEach((schemaName, schema) -> metaDataContexts.getPersistService().getDatabaseMetaDataService().persistByAlterConfiguration(each.getName(), schemaName, schema)));
168 metaDataContexts.getStatistics().getDatabaseData().forEach((databaseName, databaseData) -> databaseData.getSchemaData().forEach((schemaName, schemaData) -> metaDataContexts
169 .getPersistService().getShardingSphereDataPersistService().persist(databaseName, schemaName, schemaData, metaDataContexts.getMetaData().getDatabases())));
170 }
171 }