View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shardingsphere.infra.metadata.database;
19  
20  import lombok.Getter;
21  import org.apache.shardingsphere.infra.config.database.DatabaseConfiguration;
22  import org.apache.shardingsphere.infra.config.database.impl.DataSourceProvidedDatabaseConfiguration;
23  import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
24  import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
25  import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
26  import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
27  import org.apache.shardingsphere.infra.instance.InstanceContext;
28  import org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData;
29  import org.apache.shardingsphere.infra.metadata.database.resource.node.StorageNode;
30  import org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit;
31  import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
32  import org.apache.shardingsphere.infra.metadata.database.schema.builder.GenericSchemaBuilder;
33  import org.apache.shardingsphere.infra.metadata.database.schema.builder.GenericSchemaBuilderMaterial;
34  import org.apache.shardingsphere.infra.metadata.database.schema.builder.SystemSchemaBuilder;
35  import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
36  import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
37  import org.apache.shardingsphere.infra.rule.builder.database.DatabaseRulesBuilder;
38  import org.apache.shardingsphere.infra.rule.attribute.datanode.MutableDataNodeRuleAttribute;
39  import org.apache.shardingsphere.infra.state.datasource.DataSourceStateManager;
40  
41  import javax.sql.DataSource;
42  import java.sql.SQLException;
43  import java.util.Collection;
44  import java.util.LinkedHashMap;
45  import java.util.LinkedList;
46  import java.util.Map;
47  import java.util.Map.Entry;
48  import java.util.concurrent.ConcurrentHashMap;
49  import java.util.stream.Collectors;
50  
51  /**
52   * ShardingSphere database.
53   */
54  @Getter
55  public final class ShardingSphereDatabase {
56      
57      private final String name;
58      
59      private final DatabaseType protocolType;
60      
61      private final ResourceMetaData resourceMetaData;
62      
63      private final RuleMetaData ruleMetaData;
64      
65      private final Map<String, ShardingSphereSchema> schemas;
66      
67      public ShardingSphereDatabase(final String name, final DatabaseType protocolType, final ResourceMetaData resourceMetaData,
68                                    final RuleMetaData ruleMetaData, final Map<String, ShardingSphereSchema> schemas) {
69          this.name = name;
70          this.protocolType = protocolType;
71          this.resourceMetaData = resourceMetaData;
72          this.ruleMetaData = ruleMetaData;
73          this.schemas = new ConcurrentHashMap<>(schemas.size(), 1F);
74          schemas.forEach((key, value) -> this.schemas.put(key.toLowerCase(), value));
75      }
76      
77      /**
78       * Create database meta data.
79       * 
80       * @param name database name
81       * @param protocolType database protocol type
82       * @param storageTypes storage types
83       * @param databaseConfig database configuration
84       * @param props configuration properties
85       * @param instanceContext instance context
86       * @return database meta data
87       * @throws SQLException SQL exception
88       */
89      public static ShardingSphereDatabase create(final String name, final DatabaseType protocolType, final Map<String, DatabaseType> storageTypes,
90                                                  final DatabaseConfiguration databaseConfig, final ConfigurationProperties props, final InstanceContext instanceContext) throws SQLException {
91          Collection<ShardingSphereRule> databaseRules = DatabaseRulesBuilder.build(name, protocolType, databaseConfig, instanceContext);
92          Map<String, ShardingSphereSchema> schemas = new ConcurrentHashMap<>(GenericSchemaBuilder
93                  .build(new GenericSchemaBuilderMaterial(protocolType, storageTypes, DataSourceStateManager.getInstance().getEnabledDataSources(name, databaseConfig), databaseRules,
94                          props, new DatabaseTypeRegistry(protocolType).getDefaultSchemaName(name))));
95          SystemSchemaBuilder.build(name, protocolType, props).forEach(schemas::putIfAbsent);
96          return create(name, protocolType, databaseConfig, databaseRules, schemas);
97      }
98      
99      /**
100      * Create system database meta data.
101      * 
102      * @param name system database name
103      * @param protocolType protocol database type
104      * @param props configuration properties
105      * @return system database meta data
106      */
107     public static ShardingSphereDatabase create(final String name, final DatabaseType protocolType, final ConfigurationProperties props) {
108         DatabaseConfiguration databaseConfig = new DataSourceProvidedDatabaseConfiguration(new LinkedHashMap<>(), new LinkedList<>());
109         return create(name, protocolType, databaseConfig, new LinkedList<>(), SystemSchemaBuilder.build(name, protocolType, props));
110     }
111     
112     /**
113      * Create database meta data.
114      *
115      * @param name database name
116      * @param protocolType database protocol type
117      * @param databaseConfig database configuration
118      * @param rules rules
119      * @param schemas schemas
120      * @return database meta data
121      */
122     public static ShardingSphereDatabase create(final String name, final DatabaseType protocolType, final DatabaseConfiguration databaseConfig,
123                                                 final Collection<ShardingSphereRule> rules, final Map<String, ShardingSphereSchema> schemas) {
124         ResourceMetaData resourceMetaData = createResourceMetaData(databaseConfig.getDataSources(), databaseConfig.getStorageUnits());
125         RuleMetaData ruleMetaData = new RuleMetaData(rules);
126         return new ShardingSphereDatabase(name, protocolType, resourceMetaData, ruleMetaData, schemas);
127     }
128     
129     private static ResourceMetaData createResourceMetaData(final Map<StorageNode, DataSource> dataSources, final Map<String, StorageUnit> storageUnits) {
130         return new ResourceMetaData(dataSources, storageUnits);
131     }
132     
133     /**
134      * Judge contains schema from database or not.
135      *
136      * @param schemaName schema name
137      * @return contains schema from database or not
138      */
139     public boolean containsSchema(final String schemaName) {
140         return schemas.containsKey(schemaName.toLowerCase());
141     }
142     
143     /**
144      * Get schema.
145      *
146      * @param schemaName schema name
147      * @return schema
148      */
149     public ShardingSphereSchema getSchema(final String schemaName) {
150         return schemas.get(schemaName.toLowerCase());
151     }
152     
153     /**
154      * Add schema.
155      *
156      * @param schemaName schema name
157      * @param schema schema
158      */
159     public void addSchema(final String schemaName, final ShardingSphereSchema schema) {
160         schemas.put(schemaName.toLowerCase(), schema);
161     }
162     
163     /**
164      * Drop schema.
165      *
166      * @param schemaName schema name
167      */
168     public void dropSchema(final String schemaName) {
169         schemas.remove(schemaName.toLowerCase());
170     }
171     
172     /**
173      * Judge whether is completed.
174      *
175      * @return is completed or not
176      */
177     public boolean isComplete() {
178         return !ruleMetaData.getRules().isEmpty() && !resourceMetaData.getStorageUnits().isEmpty();
179     }
180     
181     /**
182      * Judge whether contains data source.
183      *
184      * @return contains data source or not
185      */
186     public boolean containsDataSource() {
187         return !resourceMetaData.getStorageUnits().isEmpty();
188     }
189     
190     /**
191      * Reload rules.
192      */
193     public synchronized void reloadRules() {
194         Collection<ShardingSphereRule> toBeReloadedRules = ruleMetaData.getRules().stream()
195                 .filter(each -> each.getAttributes().findAttribute(MutableDataNodeRuleAttribute.class).isPresent()).collect(Collectors.toList());
196         RuleConfiguration ruleConfig = toBeReloadedRules.stream().map(ShardingSphereRule::getConfiguration).findFirst().orElse(null);
197         Collection<ShardingSphereRule> rules = new LinkedList<>(ruleMetaData.getRules());
198         toBeReloadedRules.stream().findFirst().ifPresent(optional -> {
199             rules.removeAll(toBeReloadedRules);
200             Map<String, DataSource> dataSources = resourceMetaData.getStorageUnits().entrySet().stream()
201                     .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().getDataSource(), (oldValue, currentValue) -> oldValue, LinkedHashMap::new));
202             rules.add(optional.getAttributes().getAttribute(MutableDataNodeRuleAttribute.class).reloadRule(ruleConfig, name, dataSources, rules));
203         });
204         ruleMetaData.getRules().clear();
205         ruleMetaData.getRules().addAll(rules);
206     }
207 }