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.manager.switcher;
19  
20  import org.apache.shardingsphere.infra.datasource.pool.creator.DataSourcePoolCreator;
21  import org.apache.shardingsphere.infra.datasource.pool.props.domain.DataSourcePoolProperties;
22  import org.apache.shardingsphere.infra.metadata.database.resource.ResourceMetaData;
23  import org.apache.shardingsphere.infra.metadata.database.resource.node.StorageNode;
24  import org.apache.shardingsphere.infra.metadata.database.resource.node.StorageNodeAggregator;
25  import org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnitNodeMapCreator;
26  
27  import javax.sql.DataSource;
28  import java.util.Collection;
29  import java.util.Collections;
30  import java.util.LinkedHashMap;
31  import java.util.LinkedHashSet;
32  import java.util.Map;
33  import java.util.Map.Entry;
34  import java.util.stream.Collectors;
35  
36  /**
37   * Resource switch manager.
38   */
39  public final class ResourceSwitchManager {
40      
41      /**
42       * Register storage unit.
43       *
44       * @param resourceMetaData resource meta data
45       * @param storageUnitDataSourcePoolPropsMap storage unit grouped data source pool properties map
46       * @return created switching resource
47       */
48      public SwitchingResource registerStorageUnit(final ResourceMetaData resourceMetaData, final Map<String, DataSourcePoolProperties> storageUnitDataSourcePoolPropsMap) {
49          Map<String, DataSourcePoolProperties> mergedPropsMap = new LinkedHashMap<>(resourceMetaData.getStorageUnits().entrySet().stream()
50                  .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().getDataSourcePoolProperties(), (oldValue, currentValue) -> oldValue, LinkedHashMap::new)));
51          mergedPropsMap.putAll(storageUnitDataSourcePoolPropsMap);
52          Map<String, StorageNode> toBeCreatedStorageUintNodeMap = StorageUnitNodeMapCreator.create(storageUnitDataSourcePoolPropsMap);
53          Map<StorageNode, DataSourcePoolProperties> dataSourcePoolPropsMap = StorageNodeAggregator.aggregateDataSourcePoolProperties(storageUnitDataSourcePoolPropsMap);
54          return new SwitchingResource(getNewDataSources(resourceMetaData, toBeCreatedStorageUintNodeMap, dataSourcePoolPropsMap), Collections.emptyMap(), Collections.emptyList(), mergedPropsMap);
55      }
56      
57      private Map<StorageNode, DataSource> getNewDataSources(final ResourceMetaData resourceMetaData,
58                                                             final Map<String, StorageNode> storageUintNodeMap, final Map<StorageNode, DataSourcePoolProperties> dataSourcePoolPropsMap) {
59          Map<StorageNode, DataSource> result = new LinkedHashMap<>(storageUintNodeMap.size(), 1F);
60          for (StorageNode each : storageUintNodeMap.values()) {
61              if (!resourceMetaData.getDataSources().containsKey(each)) {
62                  result.put(each, DataSourcePoolCreator.create(dataSourcePoolPropsMap.get(each)));
63              }
64          }
65          return result;
66      }
67      
68      /**
69       * Alter storage unit.
70       *
71       * @param resourceMetaData resource meta data
72       * @param propsMap data source pool properties map
73       * @return created switching resource
74       */
75      public SwitchingResource alterStorageUnit(final ResourceMetaData resourceMetaData, final Map<String, DataSourcePoolProperties> propsMap) {
76          Map<String, DataSourcePoolProperties> mergedDataSourcePoolPropsMap = new LinkedHashMap<>(resourceMetaData.getStorageUnits().entrySet().stream()
77                  .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().getDataSourcePoolProperties(), (oldValue, currentValue) -> oldValue, LinkedHashMap::new)));
78          mergedDataSourcePoolPropsMap.putAll(propsMap);
79          Map<String, StorageNode> toBeAlteredStorageUintNodeMap = StorageUnitNodeMapCreator.create(mergedDataSourcePoolPropsMap);
80          Map<StorageNode, DataSourcePoolProperties> dataSourcePoolPropsMap = StorageNodeAggregator.aggregateDataSourcePoolProperties(mergedDataSourcePoolPropsMap);
81          return new SwitchingResource(getAlterNewDataSources(toBeAlteredStorageUintNodeMap, dataSourcePoolPropsMap),
82                  getStaleDataSources(resourceMetaData, toBeAlteredStorageUintNodeMap.values()), new LinkedHashSet<>(toBeAlteredStorageUintNodeMap.keySet()), mergedDataSourcePoolPropsMap);
83      }
84      
85      private Map<StorageNode, DataSource> getAlterNewDataSources(final Map<String, StorageNode> storageUintNodeMap, final Map<StorageNode, DataSourcePoolProperties> dataSourcePoolPropsMap) {
86          Map<StorageNode, DataSource> result = new LinkedHashMap<>(storageUintNodeMap.size(), 1F);
87          for (StorageNode each : storageUintNodeMap.values()) {
88              result.put(each, DataSourcePoolCreator.create(dataSourcePoolPropsMap.get(each)));
89          }
90          return result;
91      }
92      
93      private Map<StorageNode, DataSource> getStaleDataSources(final ResourceMetaData resourceMetaData, final Collection<StorageNode> storageNodes) {
94          Map<StorageNode, DataSource> result = new LinkedHashMap<>(storageNodes.size(), 1F);
95          for (Entry<StorageNode, DataSource> entry : resourceMetaData.getDataSources().entrySet()) {
96              if (storageNodes.contains(entry.getKey())) {
97                  result.put(entry.getKey(), entry.getValue());
98              }
99          }
100         return result;
101     }
102     
103     /**
104      * Unregister storage unit.
105      *
106      * @param resourceMetaData resource meta data
107      * @param storageUnitNames storage unit names
108      * @return created switching resource
109      */
110     public SwitchingResource unregisterStorageUnit(final ResourceMetaData resourceMetaData, final Collection<String> storageUnitNames) {
111         Map<String, DataSourcePoolProperties> mergedDataSourcePoolPropertiesMap = new LinkedHashMap<>(resourceMetaData.getStorageUnits().entrySet().stream()
112                 .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().getDataSourcePoolProperties(), (oldValue, currentValue) -> oldValue, LinkedHashMap::new)));
113         SwitchingResource result = new SwitchingResource(Collections.emptyMap(),
114                 getToBeRemovedStaleDataSource(resourceMetaData, storageUnitNames), storageUnitNames, mergedDataSourcePoolPropertiesMap);
115         removeToBeRemovedStorageUnitNames(resourceMetaData, mergedDataSourcePoolPropertiesMap, storageUnitNames);
116         return result;
117     }
118     
119     private Map<StorageNode, DataSource> getToBeRemovedStaleDataSource(final ResourceMetaData resourceMetaData, final Collection<String> storageUnitNames) {
120         Map<StorageNode, DataSource> result = new LinkedHashMap<>(storageUnitNames.size(), 1F);
121         for (String each : storageUnitNames) {
122             if (!resourceMetaData.getStorageUnits().containsKey(each)) {
123                 return Collections.emptyMap();
124             }
125             StorageNode storageNode = resourceMetaData.getStorageUnits().get(each).getStorageNode();
126             result.put(storageNode, resourceMetaData.getDataSources().get(storageNode));
127         }
128         return result;
129     }
130     
131     private void removeToBeRemovedStorageUnitNames(final ResourceMetaData resourceMetaData, final Map<String, DataSourcePoolProperties> dataSourcePoolPropsMap,
132                                                    final Collection<String> storageUnitNames) {
133         for (String each : storageUnitNames) {
134             dataSourcePoolPropsMap.remove(each);
135             resourceMetaData.getStorageUnits().remove(each);
136         }
137     }
138 }