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.shadow.route;
19  
20  import org.apache.shardingsphere.infra.annotation.HighFrequencyInvocation;
21  import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
22  import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
23  import org.apache.shardingsphere.infra.route.context.RouteContext;
24  import org.apache.shardingsphere.infra.route.context.RouteMapper;
25  import org.apache.shardingsphere.infra.route.context.RouteUnit;
26  import org.apache.shardingsphere.infra.route.lifecycle.DecorateSQLRouter;
27  import org.apache.shardingsphere.infra.session.query.QueryContext;
28  import org.apache.shardingsphere.shadow.constant.ShadowOrder;
29  import org.apache.shardingsphere.shadow.route.retriever.ShadowDataSourceMappingsRetrieverFactory;
30  import org.apache.shardingsphere.shadow.rule.ShadowRule;
31  
32  import java.util.Collection;
33  import java.util.LinkedList;
34  import java.util.Map;
35  import java.util.Optional;
36  
37  /**
38   * Shadow SQL router.
39   */
40  @HighFrequencyInvocation
41  public final class ShadowSQLRouter implements DecorateSQLRouter<ShadowRule> {
42      
43      @Override
44      public void decorateRouteContext(final RouteContext routeContext, final QueryContext queryContext, final ShardingSphereDatabase database,
45                                       final ShadowRule rule, final Collection<String> tableNames, final ConfigurationProperties props) {
46          Collection<RouteUnit> toBeRemovedRouteUnit = new LinkedList<>();
47          Collection<RouteUnit> toBeAddedRouteUnit = new LinkedList<>();
48          Map<String, String> shadowDataSourceMappings = ShadowDataSourceMappingsRetrieverFactory.newInstance(queryContext).retrieve(rule);
49          for (RouteUnit each : routeContext.getRouteUnits()) {
50              String logicName = each.getDataSourceMapper().getLogicName();
51              String actualName = each.getDataSourceMapper().getActualName();
52              Optional<String> productionDataSourceName = rule.findProductionDataSourceName(actualName);
53              if (productionDataSourceName.isPresent()) {
54                  String shadowDataSourceName = shadowDataSourceMappings.get(productionDataSourceName.get());
55                  toBeRemovedRouteUnit.add(each);
56                  String dataSourceName = null == shadowDataSourceName ? productionDataSourceName.get() : shadowDataSourceName;
57                  toBeAddedRouteUnit.add(new RouteUnit(new RouteMapper(logicName, dataSourceName), each.getTableMappers()));
58              }
59          }
60          routeContext.getRouteUnits().removeAll(toBeRemovedRouteUnit);
61          routeContext.getRouteUnits().addAll(toBeAddedRouteUnit);
62      }
63      
64      @Override
65      public Type getType() {
66          return Type.DATA_SOURCE;
67      }
68      
69      @Override
70      public int getOrder() {
71          return ShadowOrder.ORDER;
72      }
73      
74      @Override
75      public Class<ShadowRule> getTypeClass() {
76          return ShadowRule.class;
77      }
78  }