This is an automated email from the ASF dual-hosted git repository.

panjuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new e64dd3e527b Fix connection leak when alter resource (#18812)
e64dd3e527b is described below

commit e64dd3e527ba93d627dde9f2898e22c52602d2cd
Author: Haoran Meng <menghaora...@gmail.com>
AuthorDate: Sun Jul 3 22:35:44 2022 +0800

    Fix connection leak when alter resource (#18812)
---
 .../mode/manager/ContextManager.java               | 34 ++++++++++++++++++++--
 .../mode/manager/ContextManagerTest.java           |  8 +++--
 2 files changed, 37 insertions(+), 5 deletions(-)

diff --git 
a/shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/ContextManager.java
 
b/shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/ContextManager.java
index 09d32f63d58..0bdc6a2cace 100644
--- 
a/shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/ContextManager.java
+++ 
b/shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/ContextManager.java
@@ -205,7 +205,7 @@ public final class ContextManager implements AutoCloseable {
      * @throws SQLException SQL exception
      */
     public void addResource(final String databaseName, final Map<String, 
DataSourceProperties> toBeAddedDataSourcePropsMap) throws SQLException {
-        refreshMetaDataContext(databaseName, toBeAddedDataSourcePropsMap);
+        refreshMetaDataContextForAddResource(databaseName, 
toBeAddedDataSourcePropsMap);
         metaDataContexts.getPersistService().ifPresent(optional -> 
optional.getDataSourceService().append(databaseName, 
toBeAddedDataSourcePropsMap));
     }
     
@@ -217,7 +217,7 @@ public final class ContextManager implements AutoCloseable {
      * @throws SQLException SQL exception
      */
     public void alterResource(final String databaseName, final Map<String, 
DataSourceProperties> toBeAlteredDataSourcePropsMap) throws SQLException {
-        refreshMetaDataContext(databaseName, toBeAlteredDataSourcePropsMap);
+        refreshMetaDataContextForAlterResource(databaseName, 
toBeAlteredDataSourcePropsMap);
         metaDataContexts.getPersistService().ifPresent(optional -> 
optional.getDataSourceService().append(databaseName, 
toBeAlteredDataSourcePropsMap));
     }
     
@@ -493,8 +493,17 @@ public final class ContextManager implements AutoCloseable 
{
         return new 
MetaDataContexts(metaDataContexts.getPersistService().orElse(null), 
changedMetaData, metaDataContexts.getOptimizerContext());
     }
     
-    private void refreshMetaDataContext(final String databaseName, final 
Map<String, DataSourceProperties> dataSourcePropsMap) throws SQLException {
+    private void refreshMetaDataContextForAddResource(final String 
databaseName, final Map<String, DataSourceProperties> dataSourcePropsMap) 
throws SQLException {
         MetaDataContexts changedMetaDataContexts = 
buildChangedMetaDataContextWithAddedDataSource(databaseName, 
dataSourcePropsMap);
+        refreshMetaDataContext(databaseName, changedMetaDataContexts);
+    }
+    
+    private void refreshMetaDataContextForAlterResource(final String 
databaseName, final Map<String, DataSourceProperties> dataSourcePropsMap) 
throws SQLException {
+        MetaDataContexts changedMetaDataContexts = 
buildChangedMetaDataContextWithAlteredDataSource(databaseName, 
dataSourcePropsMap);
+        refreshMetaDataContext(databaseName, changedMetaDataContexts);
+    }
+    
+    private void refreshMetaDataContext(final String databaseName, final 
MetaDataContexts changedMetaDataContexts) {
         
metaDataContexts.getMetaData().getDatabases().putAll(changedMetaDataContexts.getMetaData().getDatabases());
         
metaDataContexts.getOptimizerContext().getFederationMetaData().getDatabases().putAll(changedMetaDataContexts.getOptimizerContext().getFederationMetaData().getDatabases());
         
metaDataContexts.getOptimizerContext().getParserContexts().putAll(changedMetaDataContexts.getOptimizerContext().getParserContexts());
@@ -530,6 +539,25 @@ public final class ContextManager implements AutoCloseable 
{
         return result;
     }
     
+    private MetaDataContexts 
buildChangedMetaDataContextWithAlteredDataSource(final String databaseName, 
final Map<String, DataSourceProperties> alteredDataSourceProps) throws 
SQLException {
+        ShardingSphereDatabase database = 
metaDataContexts.getMetaData().getDatabases().get(databaseName);
+        Map<String, DataSource> pendingClosedDataSources = 
getChangedDataSources(database, alteredDataSourceProps);
+        Map<String, DataSourceProperties> pendingAlteredDataSourceProps = 
alteredDataSourceProps.entrySet().stream().filter(entry -> 
pendingClosedDataSources.keySet().contains(entry.getKey()))
+                .collect(Collectors.toMap(Map.Entry::getKey, 
Map.Entry::getValue));
+        
pendingClosedDataSources.values().forEach(database.getResource()::close);
+        Map<String, DataSource> dataSourceMap = new 
HashMap<>(database.getResource().getDataSources());
+        
dataSourceMap.putAll(DataSourcePoolCreator.create(pendingAlteredDataSourceProps));
+        ConfigurationProperties props = 
metaDataContexts.getMetaData().getProps();
+        DatabaseConfiguration databaseConfig = new 
DataSourceProvidedDatabaseConfiguration(dataSourceMap, 
database.getRuleMetaData().getConfigurations());
+        Map<String, ShardingSphereDatabase> databases = 
ShardingSphereDatabasesFactory.create(Collections.singletonMap(database.getName(),
 databaseConfig), props, instanceContext);
+        ShardingSphereRuleMetaData globalMetaData = new 
ShardingSphereRuleMetaData(
+                
GlobalRulesBuilder.buildRules(metaDataContexts.getMetaData().getGlobalRuleMetaData().getConfigurations(),
 databases, instanceContext));
+        ShardingSphereMetaData metaData = new 
ShardingSphereMetaData(databases, globalMetaData, props);
+        MetaDataContexts result = new 
MetaDataContexts(metaDataContexts.getPersistService().orElse(null), metaData, 
OptimizerContextFactory.create(databases, globalMetaData));
+        persistMetaData(result);
+        return result;
+    }
+    
     private MetaDataContexts 
buildChangedMetaDataContextWithChangedDataSource(final ShardingSphereDatabase 
originalDatabase,
                                                                               
final Map<String, DataSourceProperties> newDataSourceProps) throws SQLException 
{
         Collection<String> deletedDataSources = 
getDeletedDataSources(originalDatabase, newDataSourceProps).keySet();
diff --git 
a/shardingsphere-mode/shardingsphere-mode-core/src/test/java/org/apache/shardingsphere/mode/manager/ContextManagerTest.java
 
b/shardingsphere-mode/shardingsphere-mode-core/src/test/java/org/apache/shardingsphere/mode/manager/ContextManagerTest.java
index 9766ea86314..b08cd395894 100644
--- 
a/shardingsphere-mode/shardingsphere-mode-core/src/test/java/org/apache/shardingsphere/mode/manager/ContextManagerTest.java
+++ 
b/shardingsphere-mode/shardingsphere-mode-core/src/test/java/org/apache/shardingsphere/mode/manager/ContextManagerTest.java
@@ -171,14 +171,18 @@ public final class ContextManagerTest {
     @Test
     public void assertAlterResource() throws SQLException {
         Map<String, ShardingSphereDatabase> originalDatabases = new 
HashMap<>(Collections.singletonMap("foo_db", createOriginalDatabaseMetaData()));
+        ShardingSphereResource originalResource = 
originalDatabases.get("foo_db").getResource();
+        DataSource originalDataSource = 
originalResource.getDataSources().get("bar_ds");
         
when(metaDataContexts.getMetaData().getDatabases()).thenReturn(originalDatabases);
-        contextManager.alterResource("foo_db", 
Collections.singletonMap("bar_ds", new 
DataSourceProperties(MockedDataSource.class.getName(), createProperties("test", 
"test"))));
+        contextManager.alterResource("foo_db", 
Collections.singletonMap("bar_ds", new 
DataSourceProperties(MockedDataSource.class.getName(),
+                createProperties("test", "test"))));
+        verify(originalResource, times(1)).close(originalDataSource);
         assertAlteredDataSource((MockedDataSource) 
contextManager.getMetaDataContexts().getMetaData().getDatabases().get("foo_db").getResource().getDataSources().get("bar_ds"));
     }
     
     private ShardingSphereDatabase createOriginalDatabaseMetaData() {
         ShardingSphereResource resource = mock(ShardingSphereResource.class);
-        
when(resource.getDataSources()).thenReturn(Collections.singletonMap("foo_db", 
new MockedDataSource()));
+        
when(resource.getDataSources()).thenReturn(Collections.singletonMap("bar_ds", 
new MockedDataSource()));
         ShardingSphereRuleMetaData ruleMetaData = 
mock(ShardingSphereRuleMetaData.class);
         when(ruleMetaData.getConfigurations()).thenReturn(new LinkedList<>());
         return new ShardingSphereDatabase("foo_db", new MySQLDatabaseType(), 
resource, ruleMetaData, Collections.emptyMap());

Reply via email to