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.mode.metadata;
19  
20  import lombok.Getter;
21  import lombok.SneakyThrows;
22  import org.apache.shardingsphere.infra.database.core.metadata.database.DialectDatabaseMetaData;
23  import org.apache.shardingsphere.infra.database.core.spi.DatabaseTypedSPILoader;
24  import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
25  import org.apache.shardingsphere.infra.database.core.type.DatabaseTypeRegistry;
26  import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
27  import org.apache.shardingsphere.infra.metadata.statistics.ShardingSphereDatabaseData;
28  import org.apache.shardingsphere.infra.metadata.statistics.ShardingSphereSchemaData;
29  import org.apache.shardingsphere.infra.metadata.statistics.ShardingSphereStatistics;
30  import org.apache.shardingsphere.infra.metadata.statistics.ShardingSphereTableData;
31  import org.apache.shardingsphere.infra.metadata.statistics.builder.ShardingSphereStatisticsBuilder;
32  import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
33  import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
34  import org.apache.shardingsphere.metadata.persist.MetaDataBasedPersistService;
35  
36  import java.util.Collection;
37  import java.util.LinkedList;
38  import java.util.Map.Entry;
39  import java.util.Optional;
40  
41  /**
42   * Meta data contexts.
43   */
44  @Getter
45  public final class MetaDataContexts implements AutoCloseable {
46      
47      private final MetaDataBasedPersistService persistService;
48      
49      private final ShardingSphereMetaData metaData;
50      
51      private final ShardingSphereStatistics statistics;
52      
53      public MetaDataContexts(final MetaDataBasedPersistService persistService, final ShardingSphereMetaData metaData) {
54          this.persistService = persistService;
55          this.metaData = metaData;
56          this.statistics = initStatistics(metaData);
57      }
58      
59      private ShardingSphereStatistics initStatistics(final ShardingSphereMetaData metaData) {
60          if (metaData.getDatabases().isEmpty()) {
61              return new ShardingSphereStatistics();
62          }
63          DatabaseType protocolType = metaData.getDatabases().values().iterator().next().getProtocolType();
64          DialectDatabaseMetaData dialectDatabaseMetaData = new DatabaseTypeRegistry(protocolType).getDialectDatabaseMetaData();
65          // TODO can `protocolType instanceof SchemaSupportedDatabaseType ? "PostgreSQL" : protocolType.getType()` replace to trunk database type?
66          DatabaseType databaseType = dialectDatabaseMetaData.getDefaultSchema().isPresent() ? TypedSPILoader.getService(DatabaseType.class, "PostgreSQL") : protocolType;
67          Optional<ShardingSphereStatisticsBuilder> statisticsBuilder = DatabaseTypedSPILoader.findService(ShardingSphereStatisticsBuilder.class, databaseType);
68          if (!statisticsBuilder.isPresent()) {
69              return new ShardingSphereStatistics();
70          }
71          ShardingSphereStatistics result = statisticsBuilder.get().build(metaData);
72          Optional<ShardingSphereStatistics> loadedStatistics = persistService.getShardingSphereDataPersistService().load(metaData);
73          loadedStatistics.ifPresent(optional -> useLoadedToReplaceInit(result, optional));
74          return result;
75      }
76      
77      private void useLoadedToReplaceInit(final ShardingSphereStatistics initStatistics, final ShardingSphereStatistics loadedStatistics) {
78          for (Entry<String, ShardingSphereDatabaseData> entry : initStatistics.getDatabaseData().entrySet()) {
79              if (loadedStatistics.getDatabaseData().containsKey(entry.getKey())) {
80                  useLoadedToReplaceInitByDatabaseData(entry.getValue(), loadedStatistics.getDatabaseData().get(entry.getKey()));
81              }
82          }
83      }
84      
85      private void useLoadedToReplaceInitByDatabaseData(final ShardingSphereDatabaseData initDatabaseData, final ShardingSphereDatabaseData loadedDatabaseData) {
86          for (Entry<String, ShardingSphereSchemaData> entry : initDatabaseData.getSchemaData().entrySet()) {
87              if (loadedDatabaseData.getSchemaData().containsKey(entry.getKey())) {
88                  useLoadedToReplaceInitBySchemaData(entry.getValue(), loadedDatabaseData.getSchemaData().get(entry.getKey()));
89              }
90          }
91      }
92      
93      private void useLoadedToReplaceInitBySchemaData(final ShardingSphereSchemaData initSchemaData, final ShardingSphereSchemaData loadedSchemaData) {
94          for (Entry<String, ShardingSphereTableData> entry : initSchemaData.getTableData().entrySet()) {
95              if (loadedSchemaData.getTableData().containsKey(entry.getKey())) {
96                  entry.setValue(loadedSchemaData.getTableData().get(entry.getKey()));
97              }
98          }
99      }
100     
101     @SneakyThrows(Exception.class)
102     @Override
103     public void close() {
104         persistService.getRepository().close();
105         for (ShardingSphereRule each : getAllRules()) {
106             if (each instanceof AutoCloseable) {
107                 ((AutoCloseable) each).close();
108             }
109         }
110     }
111     
112     private Collection<ShardingSphereRule> getAllRules() {
113         Collection<ShardingSphereRule> result = new LinkedList<>(metaData.getGlobalRuleMetaData().getRules());
114         metaData.getDatabases().values().stream().map(each -> each.getRuleMetaData().getRules()).forEach(result::addAll);
115         return result;
116     }
117 }