1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shardingsphere.mode.manager;
19
20 import lombok.Getter;
21 import lombok.extern.slf4j.Slf4j;
22 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
23 import org.apache.shardingsphere.database.exception.core.exception.syntax.database.NoDatabaseSelectedException;
24 import org.apache.shardingsphere.database.exception.core.exception.syntax.database.UnknownDatabaseException;
25 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
26 import org.apache.shardingsphere.infra.config.props.ConfigurationPropertyKey;
27 import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
28 import org.apache.shardingsphere.infra.database.DatabaseTypeEngine;
29 import org.apache.shardingsphere.infra.datasource.pool.props.domain.DataSourcePoolProperties;
30 import org.apache.shardingsphere.infra.exception.ShardingSpherePreconditions;
31 import org.apache.shardingsphere.infra.executor.kernel.ExecutorEngine;
32 import org.apache.shardingsphere.infra.instance.ComputeNodeInstanceContext;
33 import org.apache.shardingsphere.infra.instance.metadata.InstanceType;
34 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
35 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
36 import org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit;
37 import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
38 import org.apache.shardingsphere.infra.metadata.database.schema.builder.GenericSchemaBuilder;
39 import org.apache.shardingsphere.infra.metadata.database.schema.builder.GenericSchemaBuilderMaterial;
40 import org.apache.shardingsphere.infra.metadata.database.schema.manager.GenericSchemaManager;
41 import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
42 import org.apache.shardingsphere.infra.metadata.statistics.builder.ShardingSphereStatisticsFactory;
43 import org.apache.shardingsphere.infra.rule.builder.global.GlobalRulesBuilder;
44 import org.apache.shardingsphere.mode.exclusive.ExclusiveOperatorEngine;
45 import org.apache.shardingsphere.mode.manager.listener.ContextManagerLifecycleListenerFactory;
46 import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
47 import org.apache.shardingsphere.mode.metadata.factory.MetaDataContextsFactory;
48 import org.apache.shardingsphere.mode.metadata.manager.MetaDataContextManager;
49 import org.apache.shardingsphere.mode.metadata.manager.resource.SwitchingResource;
50 import org.apache.shardingsphere.mode.persist.PersistServiceFacade;
51 import org.apache.shardingsphere.mode.spi.repository.PersistRepository;
52 import org.apache.shardingsphere.mode.state.StateContext;
53
54 import java.sql.SQLException;
55 import java.util.Collection;
56 import java.util.Collections;
57 import java.util.Map;
58 import java.util.stream.Collectors;
59
60
61
62
63 @Getter
64 @Slf4j
65 public final class ContextManager implements AutoCloseable {
66
67 private final MetaDataContexts metaDataContexts;
68
69 private final ComputeNodeInstanceContext computeNodeInstanceContext;
70
71 private final ExclusiveOperatorEngine exclusiveOperatorEngine;
72
73 private final ExecutorEngine executorEngine;
74
75 private final MetaDataContextManager metaDataContextManager;
76
77 private final PersistServiceFacade persistServiceFacade;
78
79 private final StateContext stateContext;
80
81 public ContextManager(final MetaDataContexts metaDataContexts, final ComputeNodeInstanceContext computeNodeInstanceContext, final ExclusiveOperatorEngine exclusiveOperatorEngine,
82 final PersistRepository repository) {
83 this.metaDataContexts = metaDataContexts;
84 this.computeNodeInstanceContext = computeNodeInstanceContext;
85 this.exclusiveOperatorEngine = exclusiveOperatorEngine;
86 executorEngine = ExecutorEngine.createExecutorEngineWithSize(metaDataContexts.getMetaData().getProps().<Integer>getValue(ConfigurationPropertyKey.KERNEL_EXECUTOR_SIZE));
87 metaDataContextManager = new MetaDataContextManager(metaDataContexts, computeNodeInstanceContext, repository);
88 persistServiceFacade = new PersistServiceFacade(repository, computeNodeInstanceContext.getModeConfiguration(), metaDataContextManager);
89 stateContext = new StateContext(persistServiceFacade.getStateService().load());
90 ContextManagerLifecycleListenerFactory.getListeners(this).forEach(each -> each.onInitialized(this));
91 }
92
93
94
95
96
97
98 public DatabaseType getDatabaseType() {
99 Collection<ShardingSphereDatabase> databases = metaDataContexts.getMetaData().getAllDatabases();
100 return databases.stream().flatMap(each -> each.getResourceMetaData().getStorageUnits().values().stream()).findFirst().map(StorageUnit::getStorageType)
101 .orElseGet(DatabaseTypeEngine::getDefaultStorageType);
102 }
103
104
105
106
107
108
109 public Collection<String> getAllDatabaseNames() {
110 return metaDataContexts.getMetaData().getAllDatabases().stream().map(ShardingSphereDatabase::getName).collect(Collectors.toList());
111 }
112
113
114
115
116
117
118
119 public ShardingSphereDatabase getDatabase(final String name) {
120 ShardingSpherePreconditions.checkNotEmpty(name, NoDatabaseSelectedException::new);
121 ShardingSphereMetaData metaData = metaDataContexts.getMetaData();
122 ShardingSpherePreconditions.checkState(metaData.containsDatabase(name), () -> new UnknownDatabaseException(name));
123 return metaData.getDatabase(name);
124 }
125
126
127
128
129
130
131
132 public Map<String, StorageUnit> getStorageUnits(final String databaseName) {
133 return getDatabase(databaseName).getResourceMetaData().getStorageUnits();
134 }
135
136
137
138
139
140
141 public void reloadDatabase(final ShardingSphereDatabase database) {
142 try {
143 MetaDataContexts reloadedMetaDataContexts = createMetaDataContexts(database);
144 dropSchemas(database.getName(), reloadedMetaDataContexts.getMetaData().getDatabase(database.getName()), database);
145 metaDataContexts.update(reloadedMetaDataContexts);
146 metaDataContexts.getMetaData().getDatabase(database.getName()).getAllSchemas()
147 .forEach(each -> persistServiceFacade.getMetaDataFacade().getDatabaseMetaDataFacade().getSchema().alterByRefresh(database.getName(), each));
148 } catch (final SQLException ex) {
149 log.error("Refresh database meta data: {} failed", database.getName(), ex);
150 }
151 }
152
153 private MetaDataContexts createMetaDataContexts(final ShardingSphereDatabase database) throws SQLException {
154 Map<String, DataSourcePoolProperties> dataSourcePoolProps = persistServiceFacade.getMetaDataFacade().getDataSourceUnitService().load(database.getName());
155 SwitchingResource switchingResource = metaDataContextManager.getResourceSwitchManager().switchByAlterStorageUnit(database.getResourceMetaData(), dataSourcePoolProps);
156 Collection<RuleConfiguration> ruleConfigs = persistServiceFacade.getMetaDataFacade().getDatabaseRuleService().load(database.getName());
157 ShardingSphereDatabase changedDatabase = new MetaDataContextsFactory(persistServiceFacade.getMetaDataFacade(), computeNodeInstanceContext)
158 .createChangedDatabase(database.getName(), false, switchingResource, ruleConfigs, metaDataContexts);
159 metaDataContexts.getMetaData().putDatabase(changedDatabase);
160 ConfigurationProperties props = new ConfigurationProperties(persistServiceFacade.getMetaDataFacade().getPropsService().load());
161 Collection<RuleConfiguration> globalRuleConfigs = persistServiceFacade.getMetaDataFacade().getGlobalRuleService().load();
162 RuleMetaData changedGlobalMetaData = new RuleMetaData(GlobalRulesBuilder.buildRules(globalRuleConfigs, metaDataContexts.getMetaData().getAllDatabases(), props));
163 ShardingSphereMetaData metaData = new ShardingSphereMetaData(
164 metaDataContexts.getMetaData().getAllDatabases(), metaDataContexts.getMetaData().getGlobalResourceMetaData(), changedGlobalMetaData, props);
165 MetaDataContexts result =
166 new MetaDataContexts(metaData, ShardingSphereStatisticsFactory.create(metaData, persistServiceFacade.getMetaDataFacade().getStatisticsService().load(metaData)));
167 switchingResource.closeStaleDataSources();
168 return result;
169 }
170
171 private void dropSchemas(final String databaseName, final ShardingSphereDatabase reloadDatabase, final ShardingSphereDatabase currentDatabase) {
172 GenericSchemaManager.getToBeDroppedSchemaNames(reloadDatabase, currentDatabase)
173 .forEach(each -> persistServiceFacade.getMetaDataFacade().getDatabaseMetaDataFacade().getSchema().drop(databaseName, each));
174 }
175
176
177
178
179
180
181
182
183 public void reloadSchema(final ShardingSphereDatabase database, final String schemaName, final String dataSourceName) {
184 try {
185 ShardingSphereSchema reloadedSchema = loadSchema(database, schemaName, dataSourceName);
186 if (reloadedSchema.getAllTables().isEmpty()) {
187 database.dropSchema(schemaName);
188 persistServiceFacade.getMetaDataFacade().getDatabaseMetaDataFacade().getSchema().drop(database.getName(), schemaName);
189 } else {
190 database.addSchema(reloadedSchema);
191 persistServiceFacade.getMetaDataFacade().getDatabaseMetaDataFacade().getSchema().alterByRefresh(database.getName(), reloadedSchema);
192 }
193 } catch (final SQLException ex) {
194 log.error("Reload meta data of database: {} schema: {} with data source: {} failed", database.getName(), schemaName, dataSourceName, ex);
195 }
196 }
197
198 private ShardingSphereSchema loadSchema(final ShardingSphereDatabase database, final String schemaName, final String dataSourceName) throws SQLException {
199 database.reloadRules();
200 GenericSchemaBuilderMaterial material = new GenericSchemaBuilderMaterial(Collections.singletonMap(dataSourceName, database.getResourceMetaData().getStorageUnits().get(dataSourceName)),
201 database.getRuleMetaData().getRules(), metaDataContexts.getMetaData().getProps(), schemaName);
202 ShardingSphereSchema result = GenericSchemaBuilder.build(database.getProtocolType(), material).get(schemaName);
203 persistServiceFacade.getMetaDataFacade().getDatabaseMetaDataFacade().getView().load(database.getName(), schemaName).forEach(result::putView);
204 return result;
205 }
206
207
208
209
210
211
212
213
214 public void reloadTable(final ShardingSphereDatabase database, final String schemaName, final String tableName) {
215 GenericSchemaBuilderMaterial material = new GenericSchemaBuilderMaterial(
216 database.getResourceMetaData().getStorageUnits(), database.getRuleMetaData().getRules(), metaDataContexts.getMetaData().getProps(), schemaName);
217 try {
218 persistTable(database, schemaName, tableName, material);
219 } catch (final SQLException ex) {
220 log.error("Reload table: {} meta data of database: {} schema: {} failed", tableName, database.getName(), schemaName, ex);
221 }
222 }
223
224
225
226
227
228
229
230
231
232 public void reloadTable(final ShardingSphereDatabase database, final String schemaName, final String dataSourceName, final String tableName) {
233 StorageUnit storageUnit = database.getResourceMetaData().getStorageUnits().get(dataSourceName);
234 GenericSchemaBuilderMaterial material = new GenericSchemaBuilderMaterial(
235 Collections.singletonMap(dataSourceName, storageUnit), database.getRuleMetaData().getRules(), metaDataContexts.getMetaData().getProps(), schemaName);
236 try {
237 persistTable(database, schemaName, tableName, material);
238 } catch (final SQLException ex) {
239 log.error("Reload table: {} meta data of database: {} schema: {} with data source: {} failed", tableName, database.getName(), schemaName, dataSourceName, ex);
240 }
241 }
242
243 private void persistTable(final ShardingSphereDatabase database, final String schemaName, final String tableName, final GenericSchemaBuilderMaterial material) throws SQLException {
244 ShardingSphereSchema schema = GenericSchemaBuilder.build(Collections.singleton(tableName), database.getProtocolType(), material).getOrDefault(schemaName, new ShardingSphereSchema(schemaName));
245 if (schema.containsTable(tableName)) {
246 persistServiceFacade.getMetaDataFacade().getDatabaseMetaDataFacade().getTable().persist(database.getName(), schemaName, Collections.singleton(schema.getTable(tableName)));
247 } else {
248 persistServiceFacade.getModeFacade().getMetaDataManagerService().dropTables(database, schemaName, Collections.singleton(tableName));
249 }
250 }
251
252
253
254
255
256
257 public String getPreSelectedDatabaseName() {
258 return InstanceType.JDBC == computeNodeInstanceContext.getInstance().getMetaData().getType() ? metaDataContexts.getMetaData().getAllDatabases().iterator().next().getName() : null;
259 }
260
261 @Override
262 public void close() {
263 ContextManagerLifecycleListenerFactory.getListeners(this).forEach(each -> each.onDestroyed(this));
264 executorEngine.close();
265 metaDataContexts.getMetaData().close();
266 persistServiceFacade.close();
267 }
268 }