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.proxy.backend.handler.distsql.ral.queryable;
19  
20  import org.apache.shardingsphere.distsql.handler.engine.query.DistSQLQueryExecutor;
21  import org.apache.shardingsphere.distsql.statement.ral.queryable.export.ExportStorageNodesStatement;
22  import org.apache.shardingsphere.infra.database.core.connector.ConnectionProperties;
23  import org.apache.shardingsphere.infra.datasource.pool.props.creator.DataSourcePoolPropertiesCreator;
24  import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
25  import org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
26  import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
27  import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
28  import org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUnit;
29  import org.apache.shardingsphere.infra.util.json.JsonUtils;
30  import org.apache.shardingsphere.mode.manager.ContextManager;
31  import org.apache.shardingsphere.proxy.backend.distsql.export.ExportedStorageNode;
32  import org.apache.shardingsphere.proxy.backend.distsql.export.ExportedStorageNodes;
33  import org.apache.shardingsphere.proxy.backend.util.ExportUtils;
34  
35  import java.time.LocalDateTime;
36  import java.util.Arrays;
37  import java.util.Collection;
38  import java.util.Collections;
39  import java.util.LinkedHashMap;
40  import java.util.Map;
41  import java.util.Map.Entry;
42  
43  /**
44   * Export storage nodes executor.
45   */
46  public final class ExportStorageNodesExecutor implements DistSQLQueryExecutor<ExportStorageNodesStatement> {
47      
48      @Override
49      public Collection<String> getColumnNames(final ExportStorageNodesStatement sqlStatement) {
50          return Arrays.asList("id", "create_time", "storage_nodes");
51      }
52      
53      @Override
54      public Collection<LocalDataQueryResultRow> getRows(final ExportStorageNodesStatement sqlStatement, final ContextManager contextManager) {
55          checkSQLStatement(contextManager.getMetaDataContexts().getMetaData(), sqlStatement);
56          String exportedData = generateExportData(contextManager.getMetaDataContexts().getMetaData(), sqlStatement);
57          if (sqlStatement.getFilePath().isPresent()) {
58              String filePath = sqlStatement.getFilePath().get();
59              ExportUtils.exportToFile(filePath, exportedData);
60              return Collections.singleton(new LocalDataQueryResultRow(contextManager.getInstanceContext().getInstance().getCurrentInstanceId(), LocalDateTime.now(),
61                      String.format("Successfully exported to:'%s'", filePath)));
62          }
63          return Collections.singleton(
64                  new LocalDataQueryResultRow(contextManager.getInstanceContext().getInstance().getCurrentInstanceId(), LocalDateTime.now(), exportedData));
65      }
66      
67      private void checkSQLStatement(final ShardingSphereMetaData metaData, final ExportStorageNodesStatement sqlStatement) {
68          ShardingSpherePreconditions.checkState(null == sqlStatement.getDatabaseName() || null != metaData.getDatabase(sqlStatement.getDatabaseName()),
69                  () -> new IllegalArgumentException(String.format("database %s is not existed", sqlStatement.getDatabaseName())));
70      }
71      
72      private String generateExportData(final ShardingSphereMetaData metaData, final ExportStorageNodesStatement sqlStatement) {
73          ExportedStorageNodes storageNodes = new ExportedStorageNodes();
74          storageNodes.setStorageNodes(null == sqlStatement.getDatabaseName()
75                  ? getAllStorageNodes(metaData)
76                  : generateDatabaseExportStorageNodesData(metaData.getDatabase(sqlStatement.getDatabaseName())));
77          return JsonUtils.toJsonString(storageNodes);
78      }
79      
80      private Map<String, Collection<ExportedStorageNode>> getAllStorageNodes(final ShardingSphereMetaData metaData) {
81          Map<String, Collection<ExportedStorageNode>> storageNodes = new LinkedHashMap<>();
82          metaData.getDatabases().values().forEach(each -> {
83              if (each.getResourceMetaData().getAllInstanceDataSourceNames().isEmpty()) {
84                  return;
85              }
86              storageNodes.putAll(generateDatabaseExportStorageNodesData(each));
87          });
88          return storageNodes;
89      }
90      
91      private Map<String, Collection<ExportedStorageNode>> generateDatabaseExportStorageNodesData(final ShardingSphereDatabase database) {
92          Map<String, ExportedStorageNode> storageNodes = new LinkedHashMap<>();
93          for (Entry<String, StorageUnit> entry : database.getResourceMetaData().getStorageUnits().entrySet()) {
94              ConnectionProperties connectionProps = database.getResourceMetaData().getStorageUnits().get(entry.getKey()).getConnectionProperties();
95              String databaseInstanceIp = getDatabaseInstanceIp(connectionProps);
96              if (storageNodes.containsKey(databaseInstanceIp)) {
97                  continue;
98              }
99              Map<String, Object> standardProps = DataSourcePoolPropertiesCreator.create(entry.getValue().getDataSource()).getConnectionPropertySynonyms().getStandardProperties();
100             ExportedStorageNode exportedStorageNode = new ExportedStorageNode(connectionProps.getHostname(), String.valueOf(connectionProps.getPort()),
101                     String.valueOf(standardProps.get("username")), String.valueOf(standardProps.get("password")), connectionProps.getCatalog());
102             storageNodes.put(databaseInstanceIp, exportedStorageNode);
103         }
104         return Collections.singletonMap(database.getName(), storageNodes.values());
105     }
106     
107     private String getDatabaseInstanceIp(final ConnectionProperties connectionProps) {
108         return String.format("%s:%s", connectionProps.getHostname(), connectionProps.getPort());
109     }
110     
111     @Override
112     public Class<ExportStorageNodesStatement> getType() {
113         return ExportStorageNodesStatement.class;
114     }
115 }