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;
19  
20  import lombok.AccessLevel;
21  import lombok.Getter;
22  import lombok.SneakyThrows;
23  import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
24  import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
25  import org.apache.shardingsphere.infra.config.props.temporary.TemporaryConfigurationProperties;
26  import org.apache.shardingsphere.infra.datasource.pool.destroyer.DataSourcePoolDestroyer;
27  import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
28  import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabaseFactory;
29  import org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData;
30  import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
31  import org.apache.shardingsphere.infra.metadata.identifier.ShardingSphereIdentifier;
32  import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
33  import org.apache.shardingsphere.infra.rule.attribute.datasource.StaticDataSourceRuleAttribute;
34  import org.apache.shardingsphere.infra.rule.scope.GlobalRule;
35  import org.apache.shardingsphere.infra.rule.scope.GlobalRule.GlobalRuleChangedType;
36  
37  import java.util.Collection;
38  import java.util.Collections;
39  import java.util.LinkedList;
40  import java.util.Map;
41  import java.util.Optional;
42  import java.util.Properties;
43  import java.util.concurrent.ConcurrentHashMap;
44  import java.util.stream.Collectors;
45  
46  /**
47   * ShardingSphere meta data.
48   */
49  @Getter
50  public final class ShardingSphereMetaData implements AutoCloseable {
51      
52      @Getter(AccessLevel.NONE)
53      private final Map<ShardingSphereIdentifier, ShardingSphereDatabase> databases;
54      
55      private final ResourceMetaData globalResourceMetaData;
56      
57      private final RuleMetaData globalRuleMetaData;
58      
59      private final ConfigurationProperties props;
60      
61      private final TemporaryConfigurationProperties temporaryProps;
62      
63      public ShardingSphereMetaData() {
64          this(Collections.emptyList(), new ResourceMetaData(Collections.emptyMap()), new RuleMetaData(Collections.emptyList()), new ConfigurationProperties(new Properties()));
65      }
66      
67      public ShardingSphereMetaData(final Collection<ShardingSphereDatabase> databases, final ResourceMetaData globalResourceMetaData,
68                                    final RuleMetaData globalRuleMetaData, final ConfigurationProperties props) {
69          this.databases = new ConcurrentHashMap<>(databases.stream().collect(Collectors.toMap(each -> new ShardingSphereIdentifier(each.getName()), each -> each)));
70          this.globalResourceMetaData = globalResourceMetaData;
71          this.globalRuleMetaData = globalRuleMetaData;
72          this.props = props;
73          temporaryProps = new TemporaryConfigurationProperties(props.getProps());
74      }
75      
76      /**
77       * Get all databases.
78       *
79       * @return all databases
80       */
81      public Collection<ShardingSphereDatabase> getAllDatabases() {
82          return databases.values();
83      }
84      
85      /**
86       * Judge contains database from meta data or not.
87       *
88       * @param databaseName database name
89       * @return contains database from meta data or not
90       */
91      public boolean containsDatabase(final String databaseName) {
92          return databases.containsKey(new ShardingSphereIdentifier(databaseName));
93      }
94      
95      /**
96       * Get database.
97       *
98       * @param databaseName database name
99       * @return meta data database
100      */
101     public ShardingSphereDatabase getDatabase(final String databaseName) {
102         return databases.get(new ShardingSphereIdentifier(databaseName));
103     }
104     
105     /**
106      * Add database.
107      *
108      * @param databaseName database name
109      * @param protocolType protocol database type
110      * @param props configuration properties
111      */
112     public void addDatabase(final String databaseName, final DatabaseType protocolType, final ConfigurationProperties props) {
113         ShardingSphereDatabase database = ShardingSphereDatabaseFactory.create(databaseName, protocolType, props);
114         databases.put(new ShardingSphereIdentifier(database.getName()), database);
115         globalRuleMetaData.getRules().forEach(each -> ((GlobalRule) each).refresh(databases.values(), GlobalRuleChangedType.DATABASE_CHANGED));
116     }
117     
118     /**
119      * Put database.
120      *
121      * @param database database
122      */
123     public void putDatabase(final ShardingSphereDatabase database) {
124         databases.put(new ShardingSphereIdentifier(database.getName()), database);
125     }
126     
127     /**
128      * Drop database.
129      *
130      * @param databaseName database name
131      */
132     public void dropDatabase(final String databaseName) {
133         cleanResources(databases.remove(new ShardingSphereIdentifier(databaseName)));
134     }
135     
136     @SneakyThrows(Exception.class)
137     private void cleanResources(final ShardingSphereDatabase database) {
138         globalRuleMetaData.getRules().forEach(each -> ((GlobalRule) each).refresh(databases.values(), GlobalRuleChangedType.DATABASE_CHANGED));
139         for (ShardingSphereRule each : database.getRuleMetaData().getRules()) {
140             if (each instanceof AutoCloseable) {
141                 ((AutoCloseable) each).close();
142             }
143         }
144         database.getRuleMetaData().getAttributes(StaticDataSourceRuleAttribute.class).forEach(StaticDataSourceRuleAttribute::cleanStorageNodeDataSources);
145         Optional.ofNullable(database.getResourceMetaData())
146                 .ifPresent(optional -> optional.getStorageUnits().values().forEach(each -> new DataSourcePoolDestroyer(each.getDataSource()).asyncDestroy()));
147     }
148     
149     @SneakyThrows(Exception.class)
150     @Override
151     public void close() {
152         for (ShardingSphereRule each : getAllRules()) {
153             if (each instanceof AutoCloseable) {
154                 ((AutoCloseable) each).close();
155             }
156         }
157     }
158     
159     private Collection<ShardingSphereRule> getAllRules() {
160         Collection<ShardingSphereRule> result = new LinkedList<>(globalRuleMetaData.getRules());
161         getAllDatabases().stream().map(each -> each.getRuleMetaData().getRules()).forEach(result::addAll);
162         return result;
163     }
164 }