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 <[email protected]>
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());