1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.mode.manager.standalone;
19
20 import com.google.common.base.Strings;
21 import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
22 import org.apache.shardingsphere.infra.connection.refresher.util.TableRefreshUtils;
23 import org.apache.shardingsphere.infra.datasource.pool.props.domain.DataSourcePoolProperties;
24 import org.apache.shardingsphere.infra.instance.mode.ModeContextManager;
25 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
26 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
27 import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
28 import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereTable;
29 import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereView;
30 import org.apache.shardingsphere.infra.metadata.database.schema.pojo.AlterSchemaMetaDataPOJO;
31 import org.apache.shardingsphere.infra.metadata.database.schema.pojo.AlterSchemaPOJO;
32 import org.apache.shardingsphere.infra.metadata.version.MetaDataVersion;
33 import org.apache.shardingsphere.infra.rule.attribute.datanode.MutableDataNodeRuleAttribute;
34 import org.apache.shardingsphere.infra.rule.scope.GlobalRule;
35 import org.apache.shardingsphere.infra.rule.scope.GlobalRule.GlobalRuleChangedType;
36 import org.apache.shardingsphere.infra.spi.type.ordered.cache.OrderedServicesCache;
37 import org.apache.shardingsphere.metadata.persist.service.config.database.DatabaseBasedPersistService;
38 import org.apache.shardingsphere.metadata.persist.service.database.DatabaseMetaDataBasedPersistService;
39 import org.apache.shardingsphere.mode.event.DataChangedEvent;
40 import org.apache.shardingsphere.mode.event.DataChangedEvent.Type;
41 import org.apache.shardingsphere.mode.manager.ContextManager;
42 import org.apache.shardingsphere.mode.manager.ContextManagerAware;
43 import org.apache.shardingsphere.mode.manager.switcher.ResourceSwitchManager;
44 import org.apache.shardingsphere.mode.manager.switcher.SwitchingResource;
45 import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
46 import org.apache.shardingsphere.mode.metadata.builder.RuleConfigurationEventBuilder;
47 import org.apache.shardingsphere.single.api.config.SingleRuleConfiguration;
48
49 import java.sql.SQLException;
50 import java.util.Collection;
51 import java.util.Collections;
52 import java.util.LinkedHashSet;
53 import java.util.Map;
54 import java.util.Map.Entry;
55 import java.util.Optional;
56 import java.util.Properties;
57 import java.util.stream.Collectors;
58
59
60
61
62 public final class StandaloneModeContextManager implements ModeContextManager, ContextManagerAware {
63
64 private final RuleConfigurationEventBuilder ruleConfigurationEventBuilder = new RuleConfigurationEventBuilder();
65
66 private ContextManager contextManager;
67
68 @Override
69 public void createDatabase(final String databaseName) {
70 contextManager.getResourceMetaDataContextManager().addDatabase(databaseName);
71 contextManager.getMetaDataContexts().getPersistService().getDatabaseMetaDataService().addDatabase(databaseName);
72 clearServiceCache();
73 }
74
75 @Override
76 public void dropDatabase(final String databaseName) {
77 contextManager.getResourceMetaDataContextManager().dropDatabase(databaseName);
78 contextManager.getMetaDataContexts().getPersistService().getDatabaseMetaDataService().dropDatabase(databaseName);
79 clearServiceCache();
80 }
81
82 @Override
83 public void createSchema(final String databaseName, final String schemaName) {
84 ShardingSphereSchema schema = new ShardingSphereSchema();
85 ShardingSphereMetaData metaData = contextManager.getMetaDataContexts().getMetaData();
86 ShardingSphereDatabase database = metaData.getDatabase(databaseName);
87 database.addSchema(schemaName, schema);
88 metaData.getGlobalRuleMetaData().getRules().forEach(each -> ((GlobalRule) each).refresh(metaData.getDatabases(), GlobalRuleChangedType.SCHEMA_CHANGED));
89 contextManager.getMetaDataContexts().getPersistService().getDatabaseMetaDataService().persistByAlterConfiguration(databaseName, schemaName, schema);
90 }
91
92 @Override
93 public void alterSchema(final AlterSchemaPOJO alterSchemaPOJO) {
94 ShardingSphereMetaData metaData = contextManager.getMetaDataContexts().getMetaData();
95 ShardingSphereDatabase database = metaData.getDatabase(alterSchemaPOJO.getDatabaseName());
96 putSchemaMetaData(database, alterSchemaPOJO.getSchemaName(), alterSchemaPOJO.getRenameSchemaName(), alterSchemaPOJO.getLogicDataSourceName());
97 removeSchemaMetaData(database, alterSchemaPOJO.getSchemaName());
98 metaData.getGlobalRuleMetaData().getRules().forEach(each -> ((GlobalRule) each).refresh(metaData.getDatabases(), GlobalRuleChangedType.SCHEMA_CHANGED));
99 DatabaseMetaDataBasedPersistService databaseMetaDataService = contextManager.getMetaDataContexts().getPersistService().getDatabaseMetaDataService();
100 databaseMetaDataService.persistByAlterConfiguration(alterSchemaPOJO.getDatabaseName(), alterSchemaPOJO.getRenameSchemaName(), database.getSchema(alterSchemaPOJO.getRenameSchemaName()));
101 databaseMetaDataService.getViewMetaDataPersistService().persist(alterSchemaPOJO.getDatabaseName(), alterSchemaPOJO.getRenameSchemaName(),
102 database.getSchema(alterSchemaPOJO.getRenameSchemaName()).getViews());
103 databaseMetaDataService.dropSchema(alterSchemaPOJO.getDatabaseName(), alterSchemaPOJO.getSchemaName());
104 }
105
106 private void putSchemaMetaData(final ShardingSphereDatabase database, final String schemaName, final String renameSchemaName, final String logicDataSourceName) {
107 ShardingSphereSchema schema = database.getSchema(schemaName);
108 database.addSchema(renameSchemaName, schema);
109 addDataNode(database, logicDataSourceName, schemaName, schema.getAllTableNames());
110 }
111
112 private void addDataNode(final ShardingSphereDatabase database, final String logicDataSourceName, final String schemaName, final Collection<String> tobeAddedTableNames) {
113 tobeAddedTableNames.forEach(each -> {
114 if (!Strings.isNullOrEmpty(logicDataSourceName) && TableRefreshUtils.isSingleTable(each, database)) {
115 database.getRuleMetaData().getAttributes(MutableDataNodeRuleAttribute.class).forEach(rule -> rule.put(logicDataSourceName, schemaName, each));
116 }
117 });
118 }
119
120 private void addDataNode(final ShardingSphereDatabase database, final String logicDataSourceName, final String schemaName, final Map<String, ShardingSphereTable> toBeAddedTables,
121 final Map<String, ShardingSphereView> toBeAddedViews) {
122 addTablesToDataNode(database, schemaName, logicDataSourceName, toBeAddedTables);
123 addViewsToDataNode(database, schemaName, logicDataSourceName, toBeAddedTables, toBeAddedViews);
124 }
125
126 private void addTablesToDataNode(final ShardingSphereDatabase database, final String schemaName, final String logicDataSourceName, final Map<String, ShardingSphereTable> toBeAddedTables) {
127 for (Entry<String, ShardingSphereTable> entry : toBeAddedTables.entrySet()) {
128 if (!Strings.isNullOrEmpty(logicDataSourceName) && TableRefreshUtils.isSingleTable(entry.getKey(), database)) {
129 database.getRuleMetaData().getAttributes(MutableDataNodeRuleAttribute.class).forEach(rule -> rule.put(logicDataSourceName, schemaName, entry.getKey()));
130 }
131 database.getSchema(schemaName).putTable(entry.getKey(), entry.getValue());
132 }
133 }
134
135 private void addViewsToDataNode(final ShardingSphereDatabase database, final String schemaName, final String logicDataSourceName,
136 final Map<String, ShardingSphereTable> toBeAddedTables, final Map<String, ShardingSphereView> toBeAddedViews) {
137 for (Entry<String, ShardingSphereView> entry : toBeAddedViews.entrySet()) {
138 if (!Strings.isNullOrEmpty(logicDataSourceName) && TableRefreshUtils.isSingleTable(entry.getKey(), database)) {
139 database.getRuleMetaData().getAttributes(MutableDataNodeRuleAttribute.class).forEach(each -> each.put(logicDataSourceName, schemaName, entry.getKey()));
140 }
141 database.getSchema(schemaName).putTable(entry.getKey(), toBeAddedTables.get(entry.getKey().toLowerCase()));
142 database.getSchema(schemaName).putView(entry.getKey(), entry.getValue());
143 }
144 }
145
146 private void removeSchemaMetaData(final ShardingSphereDatabase database, final String schemaName) {
147 ShardingSphereSchema schema = new ShardingSphereSchema(database.getSchema(schemaName).getTables(), database.getSchema(schemaName).getViews());
148 database.dropSchema(schemaName);
149 removeDataNode(database.getRuleMetaData().getAttributes(MutableDataNodeRuleAttribute.class), Collections.singletonList(schemaName), schema.getAllTableNames());
150 }
151
152 private void removeDataNode(final Collection<MutableDataNodeRuleAttribute> ruleAttributes, final Collection<String> schemaNames, final Collection<String> tobeRemovedTables) {
153 tobeRemovedTables.forEach(each -> ruleAttributes.forEach(rule -> rule.remove(schemaNames, each)));
154 }
155
156 private void removeDataNode(final ShardingSphereDatabase database, final String schemaName, final Collection<String> tobeRemovedTables, final Collection<String> tobeRemovedViews) {
157 removeTablesToDataNode(database, schemaName, tobeRemovedTables);
158 removeViewsToDataNode(database, schemaName, tobeRemovedTables, tobeRemovedViews);
159 }
160
161 private void removeDataNode(final Collection<MutableDataNodeRuleAttribute> ruleAttributes, final String schemaName, final Collection<String> tobeRemovedTables) {
162 tobeRemovedTables.forEach(each -> ruleAttributes.forEach(rule -> rule.remove(schemaName, each)));
163 }
164
165 private void removeTablesToDataNode(final ShardingSphereDatabase database, final String schemaName, final Collection<String> toBeDroppedTables) {
166 removeDataNode(database.getRuleMetaData().getAttributes(MutableDataNodeRuleAttribute.class), schemaName, toBeDroppedTables);
167 toBeDroppedTables.forEach(each -> database.getSchema(schemaName).removeTable(each));
168 }
169
170 private void removeViewsToDataNode(final ShardingSphereDatabase database, final String schemaName, final Collection<String> toBeDroppedTables, final Collection<String> toBeDroppedViews) {
171 removeDataNode(database.getRuleMetaData().getAttributes(MutableDataNodeRuleAttribute.class), schemaName, toBeDroppedViews);
172 ShardingSphereSchema schema = database.getSchema(schemaName);
173 toBeDroppedTables.forEach(schema::removeTable);
174 toBeDroppedViews.forEach(schema::removeView);
175 }
176
177 @Override
178 public void dropSchema(final String databaseName, final Collection<String> schemaNames) {
179 Collection<String> tobeRemovedTables = new LinkedHashSet<>();
180 Collection<String> tobeRemovedSchemas = new LinkedHashSet<>();
181 ShardingSphereMetaData metaData = contextManager.getMetaDataContexts().getMetaData();
182 ShardingSphereDatabase database = metaData.getDatabase(databaseName);
183 for (String each : schemaNames) {
184 ShardingSphereSchema schema = new ShardingSphereSchema(database.getSchema(each).getTables(), database.getSchema(each).getViews());
185 database.dropSchema(each);
186 Optional.of(schema).ifPresent(optional -> tobeRemovedTables.addAll(optional.getAllTableNames()));
187 tobeRemovedSchemas.add(each.toLowerCase());
188 }
189 removeDataNode(database.getRuleMetaData().getAttributes(MutableDataNodeRuleAttribute.class), tobeRemovedSchemas, tobeRemovedTables);
190 metaData.getGlobalRuleMetaData().getRules().forEach(each -> ((GlobalRule) each).refresh(metaData.getDatabases(), GlobalRuleChangedType.SCHEMA_CHANGED));
191 }
192
193 @Override
194 public void alterSchemaMetaData(final AlterSchemaMetaDataPOJO alterSchemaMetaDataPOJO) {
195 String databaseName = alterSchemaMetaDataPOJO.getDatabaseName();
196 String schemaName = alterSchemaMetaDataPOJO.getSchemaName();
197 ShardingSphereMetaData metaData = contextManager.getMetaDataContexts().getMetaData();
198 ShardingSphereDatabase database = metaData.getDatabase(databaseName);
199 Map<String, ShardingSphereTable> tables = alterSchemaMetaDataPOJO.getAlteredTables().stream().collect(Collectors.toMap(ShardingSphereTable::getName, table -> table));
200 Map<String, ShardingSphereView> views = alterSchemaMetaDataPOJO.getAlteredViews().stream().collect(Collectors.toMap(ShardingSphereView::getName, view -> view));
201 addDataNode(database, alterSchemaMetaDataPOJO.getLogicDataSourceName(), schemaName, tables, views);
202 removeDataNode(database, schemaName, alterSchemaMetaDataPOJO.getDroppedTables(), alterSchemaMetaDataPOJO.getDroppedViews());
203 metaData.getGlobalRuleMetaData().getRules().forEach(each -> ((GlobalRule) each).refresh(metaData.getDatabases(), GlobalRuleChangedType.SCHEMA_CHANGED));
204 DatabaseMetaDataBasedPersistService databaseMetaDataService = contextManager.getMetaDataContexts().getPersistService().getDatabaseMetaDataService();
205 databaseMetaDataService.getTableMetaDataPersistService().persist(databaseName, schemaName, tables);
206 databaseMetaDataService.getViewMetaDataPersistService().persist(databaseName, schemaName, views);
207 alterSchemaMetaDataPOJO.getDroppedTables().forEach(each -> databaseMetaDataService.getTableMetaDataPersistService().delete(databaseName, schemaName, each));
208 alterSchemaMetaDataPOJO.getDroppedViews().forEach(each -> databaseMetaDataService.getViewMetaDataPersistService().delete(databaseName, schemaName, each));
209 }
210
211 @Override
212 public void registerStorageUnits(final String databaseName, final Map<String, DataSourcePoolProperties> toBeRegisteredProps) throws SQLException {
213 SwitchingResource switchingResource =
214 new ResourceSwitchManager().registerStorageUnit(contextManager.getMetaDataContexts().getMetaData().getDatabase(databaseName).getResourceMetaData(), toBeRegisteredProps);
215 contextManager.getMetaDataContexts().getMetaData().getDatabases().putAll(contextManager.getConfigurationContextManager().createChangedDatabases(databaseName, false, switchingResource, null));
216 contextManager.getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getRules()
217 .forEach(each -> ((GlobalRule) each).refresh(contextManager.getMetaDataContexts().getMetaData().getDatabases(), GlobalRuleChangedType.DATABASE_CHANGED));
218 contextManager.getMetaDataContexts().getMetaData().getDatabase(databaseName).getSchemas()
219 .forEach((schemaName, schema) -> contextManager.getMetaDataContexts().getPersistService().getDatabaseMetaDataService()
220 .persistByAlterConfiguration(contextManager.getMetaDataContexts().getMetaData().getDatabase(databaseName).getName(), schemaName, schema));
221 DatabaseBasedPersistService<Map<String, DataSourcePoolProperties>> dataSourceService = contextManager.getMetaDataContexts().getPersistService().getDataSourceUnitService();
222 contextManager.getMetaDataContexts().getPersistService().getMetaDataVersionPersistService().switchActiveVersion(dataSourceService.persistConfigurations(databaseName, toBeRegisteredProps));
223 clearServiceCache();
224 }
225
226 @Override
227 public void alterStorageUnits(final String databaseName, final Map<String, DataSourcePoolProperties> toBeUpdatedProps) throws SQLException {
228 SwitchingResource switchingResource =
229 new ResourceSwitchManager().alterStorageUnit(contextManager.getMetaDataContexts().getMetaData().getDatabase(databaseName).getResourceMetaData(), toBeUpdatedProps);
230 contextManager.getMetaDataContexts().getMetaData().getDatabases().putAll(contextManager.getConfigurationContextManager().createChangedDatabases(databaseName, true, switchingResource, null));
231 contextManager.getMetaDataContexts().getMetaData().getGlobalRuleMetaData().getRules()
232 .forEach(each -> ((GlobalRule) each).refresh(contextManager.getMetaDataContexts().getMetaData().getDatabases(), GlobalRuleChangedType.DATABASE_CHANGED));
233 DatabaseBasedPersistService<Map<String, DataSourcePoolProperties>> dataSourceService = contextManager.getMetaDataContexts().getPersistService().getDataSourceUnitService();
234 contextManager.getMetaDataContexts().getPersistService().getMetaDataVersionPersistService().switchActiveVersion(dataSourceService.persistConfigurations(databaseName, toBeUpdatedProps));
235 switchingResource.closeStaleDataSources();
236 clearServiceCache();
237 }
238
239 @Override
240 public void unregisterStorageUnits(final String databaseName, final Collection<String> toBeDroppedStorageUnitNames) throws SQLException {
241 SwitchingResource switchingResource =
242 new ResourceSwitchManager().unregisterStorageUnit(contextManager.getMetaDataContexts().getMetaData().getDatabase(databaseName).getResourceMetaData(), toBeDroppedStorageUnitNames);
243 contextManager.getMetaDataContexts().getMetaData().getDatabases()
244 .putAll(contextManager.getConfigurationContextManager().renewDatabase(contextManager.getMetaDataContexts().getMetaData().getDatabase(databaseName), switchingResource));
245 MetaDataContexts reloadMetaDataContexts = contextManager.getConfigurationContextManager().createMetaDataContexts(databaseName, false, switchingResource, null);
246 contextManager.getConfigurationContextManager().alterSchemaMetaData(databaseName, reloadMetaDataContexts.getMetaData().getDatabase(databaseName),
247 contextManager.getMetaDataContexts().getMetaData().getDatabase(databaseName), true);
248 contextManager.deletedSchemaNames(databaseName, reloadMetaDataContexts.getMetaData().getDatabase(databaseName), contextManager.getMetaDataContexts().getMetaData().getDatabase(databaseName));
249 contextManager.renewMetaDataContexts(reloadMetaDataContexts);
250 switchingResource.closeStaleDataSources();
251 clearServiceCache();
252 }
253
254 @Override
255 public void alterSingleRuleConfiguration(final String databaseName, final Collection<RuleConfiguration> ruleConfigs) {
256 ruleConfigs.removeIf(each -> !each.getClass().isAssignableFrom(SingleRuleConfiguration.class));
257 Collection<MetaDataVersion> metaDataVersions = contextManager.getMetaDataContexts().getPersistService().getDatabaseRulePersistService()
258 .persistConfigurations(contextManager.getMetaDataContexts().getMetaData().getDatabase(databaseName).getName(), ruleConfigs);
259 contextManager.getMetaDataContexts().getPersistService().getMetaDataVersionPersistService().switchActiveVersion(metaDataVersions);
260 contextManager.getConfigurationContextManager().alterRuleConfiguration(databaseName, ruleConfigs.iterator().next());
261 clearServiceCache();
262 }
263
264 @Override
265 public Collection<MetaDataVersion> alterRuleConfiguration(final String databaseName, final RuleConfiguration toBeAlteredRuleConfig) {
266 if (null != toBeAlteredRuleConfig) {
267 Collection<MetaDataVersion> metaDataVersions = contextManager.getMetaDataContexts().getPersistService().getDatabaseRulePersistService()
268 .persistConfigurations(contextManager.getMetaDataContexts().getMetaData().getDatabase(databaseName).getName(), Collections.singletonList(toBeAlteredRuleConfig));
269 contextManager.getMetaDataContexts().getPersistService().getMetaDataVersionPersistService().switchActiveVersion(metaDataVersions);
270 sendDatabaseRuleChangedEvent(databaseName, metaDataVersions);
271 clearServiceCache();
272 }
273 return Collections.emptyList();
274 }
275
276 private void sendDatabaseRuleChangedEvent(final String databaseName, final Collection<MetaDataVersion> metaDataVersions) {
277 for (MetaDataVersion each : metaDataVersions) {
278 sendDatabaseRuleChangedEvent(databaseName, each);
279 }
280 }
281
282 private void sendDatabaseRuleChangedEvent(final String databaseName, final MetaDataVersion metaDataVersion) {
283 for (String each : metaDataVersion.getActiveVersionKeys()) {
284 ruleConfigurationEventBuilder.build(databaseName, new DataChangedEvent(each, metaDataVersion.getNextActiveVersion(), Type.UPDATED))
285 .ifPresent(optional -> contextManager.getInstanceContext().getEventBusContext().post(optional));
286 }
287 }
288
289 @Override
290 public void removeRuleConfigurationItem(final String databaseName, final RuleConfiguration toBeRemovedRuleConfig) {
291 if (null != toBeRemovedRuleConfig) {
292 sendDatabaseRuleChangedEvent(databaseName,
293 contextManager.getMetaDataContexts().getPersistService().getDatabaseRulePersistService().deleteConfigurations(databaseName, Collections.singleton(toBeRemovedRuleConfig)));
294 clearServiceCache();
295 }
296 }
297
298 @Override
299 public void removeRuleConfiguration(final String databaseName, final String ruleName) {
300 contextManager.getMetaDataContexts().getPersistService().getDatabaseRulePersistService().delete(databaseName, ruleName);
301 clearServiceCache();
302 }
303
304 @Override
305 public void alterGlobalRuleConfiguration(final RuleConfiguration toBeAlteredRuleConfig) {
306 contextManager.getConfigurationContextManager().alterGlobalRuleConfiguration(toBeAlteredRuleConfig);
307 contextManager.getMetaDataContexts().getPersistService().getGlobalRuleService().persist(Collections.singleton(toBeAlteredRuleConfig));
308 clearServiceCache();
309 }
310
311 @Override
312 public void alterProperties(final Properties props) {
313 contextManager.getConfigurationContextManager().alterProperties(props);
314 contextManager.getMetaDataContexts().getPersistService().getPropsService().persist(props);
315 clearServiceCache();
316 }
317
318 private void clearServiceCache() {
319 OrderedServicesCache.clearCache();
320 }
321
322 @Override
323 public void setContextManagerAware(final ContextManager contextManager) {
324 this.contextManager = contextManager;
325 }
326 }