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

chengzhang 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 043963d1415 Add PartialRuleUpdateSupported feature and try in encrypt 
rule first (#31162)
043963d1415 is described below

commit 043963d1415bcb98a12ab4309f4d71cb199a18a0
Author: Liang Zhang <[email protected]>
AuthorDate: Wed May 8 00:51:06 2024 +0800

    Add PartialRuleUpdateSupported feature and try in encrypt rule first 
(#31162)
    
    * Add PartialRuleUpdateSupported feature and try in encrypt rule first
    
    * Add PartialRuleUpdateSupported feature and try in encrypt rule first
---
 .../shardingsphere/encrypt/rule/EncryptRule.java   | 73 ++++++++++++++++++++--
 .../infra/rule/PartialRuleUpdateSupported.java     | 44 +++++++++++++
 .../context/ConfigurationContextManager.java       | 35 ++++++-----
 3 files changed, 132 insertions(+), 20 deletions(-)

diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rule/EncryptRule.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rule/EncryptRule.java
index e2e5f4f6f97..ea67c80bc60 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rule/EncryptRule.java
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rule/EncryptRule.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.encrypt.rule;
 
+import com.google.common.base.Preconditions;
 import lombok.Getter;
 import org.apache.shardingsphere.encrypt.api.config.EncryptRuleConfiguration;
 import 
org.apache.shardingsphere.encrypt.api.config.rule.EncryptColumnRuleConfiguration;
@@ -25,27 +26,31 @@ import 
org.apache.shardingsphere.encrypt.exception.metadata.EncryptTableNotFound
 import 
org.apache.shardingsphere.encrypt.exception.metadata.MismatchedEncryptAlgorithmTypeException;
 import 
org.apache.shardingsphere.encrypt.rule.attribute.EncryptTableMapperRuleAttribute;
 import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithm;
+import 
org.apache.shardingsphere.infra.algorithm.core.config.AlgorithmConfiguration;
 import 
org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
+import org.apache.shardingsphere.infra.rule.PartialRuleUpdateSupported;
 import org.apache.shardingsphere.infra.rule.attribute.RuleAttributes;
 import org.apache.shardingsphere.infra.rule.scope.DatabaseRule;
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 
 import java.util.Collection;
-import java.util.LinkedHashMap;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
 /**
  * Encrypt rule.
  */
-public final class EncryptRule implements DatabaseRule {
+public final class EncryptRule implements DatabaseRule, 
PartialRuleUpdateSupported<EncryptRuleConfiguration> {
     
     private final String databaseName;
     
-    @Getter
-    private final EncryptRuleConfiguration configuration;
+    private final AtomicReference<EncryptRuleConfiguration> ruleConfig = new 
AtomicReference<>();
     
     private final Map<String, EncryptTable> tables;
     
@@ -54,8 +59,8 @@ public final class EncryptRule implements DatabaseRule {
     
     public EncryptRule(final String databaseName, final 
EncryptRuleConfiguration ruleConfig) {
         this.databaseName = databaseName;
-        configuration = ruleConfig;
-        tables = new LinkedHashMap<>();
+        this.ruleConfig.set(ruleConfig);
+        tables = new ConcurrentHashMap<>();
         Map<String, EncryptAlgorithm> encryptors = 
ruleConfig.getEncryptors().entrySet().stream()
                 .collect(Collectors.toMap(Entry::getKey, entry -> 
TypedSPILoader.getService(EncryptAlgorithm.class, entry.getValue().getType(), 
entry.getValue().getProps())));
         for (EncryptTableRuleConfiguration each : ruleConfig.getTables()) {
@@ -107,4 +112,60 @@ public final class EncryptRule implements DatabaseRule {
         ShardingSpherePreconditions.checkState(encryptTable.isPresent(), () -> 
new EncryptTableNotFoundException(tableName));
         return encryptTable.get();
     }
+    
+    @Override
+    public EncryptRuleConfiguration getConfiguration() {
+        return ruleConfig.get();
+    }
+    
+    @Override
+    public void updateConfiguration(final EncryptRuleConfiguration 
toBeUpdatedRuleConfig) {
+        ruleConfig.set(toBeUpdatedRuleConfig);
+    }
+    
+    @Override
+    public boolean partialUpdateRule(final EncryptRuleConfiguration 
toBeUpdatedRuleConfig) {
+        Collection<String> toBeAddedTableNames = 
toBeUpdatedRuleConfig.getTables().stream().map(EncryptTableRuleConfiguration::getName).collect(Collectors.toList());
+        toBeAddedTableNames.removeAll(tables.keySet());
+        if (!toBeAddedTableNames.isEmpty()) {
+            for (String each : toBeAddedTableNames) {
+                EncryptTableRuleConfiguration tableRuleConfig = 
getEncryptTableRuleConfiguration(each, toBeUpdatedRuleConfig);
+                Map<String, AlgorithmConfiguration> encryptorConfigs = 
getEncryptorConfigurations(tableRuleConfig, 
toBeUpdatedRuleConfig.getEncryptors());
+                Map<String, EncryptAlgorithm> encryptors = 
encryptorConfigs.entrySet().stream()
+                        .collect(Collectors.toMap(Entry::getKey, entry -> 
TypedSPILoader.getService(EncryptAlgorithm.class, entry.getValue().getType(), 
entry.getValue().getProps())));
+                tableRuleConfig.getColumns().forEach(columnRuleConfig -> 
checkEncryptorType(columnRuleConfig, encryptors));
+                tables.put(each.toLowerCase(), new 
EncryptTable(tableRuleConfig, encryptors));
+            }
+            return true;
+        }
+        Collection<String> toBeRemovedTableNames = new 
HashSet<>(tables.keySet());
+        
toBeRemovedTableNames.removeAll(toBeUpdatedRuleConfig.getTables().stream().map(EncryptTableRuleConfiguration::getName).collect(Collectors.toList()));
+        if (!toBeRemovedTableNames.isEmpty()) {
+            
toBeRemovedTableNames.stream().map(String::toLowerCase).forEach(tables::remove);
+            return true;
+        }
+        // TODO Process update table
+        // TODO Process update encryptors
+        return false;
+    }
+    
+    private EncryptTableRuleConfiguration 
getEncryptTableRuleConfiguration(final String tableName, final 
EncryptRuleConfiguration toBeUpdatedRuleConfig) {
+        Optional<EncryptTableRuleConfiguration> result = 
toBeUpdatedRuleConfig.getTables().stream().filter(table -> 
table.getName().equals(tableName)).findFirst();
+        Preconditions.checkState(result.isPresent());
+        return result.get();
+    }
+    
+    private Map<String, AlgorithmConfiguration> 
getEncryptorConfigurations(final EncryptTableRuleConfiguration tableRuleConfig, 
final Map<String, AlgorithmConfiguration> encryptors) {
+        Map<String, AlgorithmConfiguration> result = new 
HashMap<>(encryptors.size(), 1F);
+        for (EncryptColumnRuleConfiguration each : 
tableRuleConfig.getColumns()) {
+            result.put(each.getCipher().getEncryptorName(), 
encryptors.get(each.getCipher().getEncryptorName()));
+            if (each.getAssistedQuery().isPresent()) {
+                result.put(each.getAssistedQuery().get().getEncryptorName(), 
encryptors.get(each.getAssistedQuery().get().getEncryptorName()));
+            }
+            if (each.getLikeQuery().isPresent()) {
+                result.put(each.getLikeQuery().get().getEncryptorName(), 
encryptors.get(each.getLikeQuery().get().getEncryptorName()));
+            }
+        }
+        return result;
+    }
 }
diff --git 
a/infra/common/src/main/java/org/apache/shardingsphere/infra/rule/PartialRuleUpdateSupported.java
 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/rule/PartialRuleUpdateSupported.java
new file mode 100644
index 00000000000..48b9773f997
--- /dev/null
+++ 
b/infra/common/src/main/java/org/apache/shardingsphere/infra/rule/PartialRuleUpdateSupported.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.infra.rule;
+
+import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
+
+/**
+ * Partial rule update supported.
+ * 
+ * @param <T> rule configuration type
+ */
+public interface PartialRuleUpdateSupported<T extends RuleConfiguration> {
+    
+    /**
+     * Update rule configuration.
+     *
+     * @param toBeUpdatedRuleConfig to be updated configuration
+     */
+    void updateConfiguration(T toBeUpdatedRuleConfig);
+    
+    /**
+     * Partial update.
+     *
+     * @param toBeUpdatedRuleConfig to be updated configuration
+     * @return update success or not
+     */
+    // TODO remove return value when support alter
+    boolean partialUpdateRule(T toBeUpdatedRuleConfig);
+}
diff --git 
a/mode/core/src/main/java/org/apache/shardingsphere/mode/manager/context/ConfigurationContextManager.java
 
b/mode/core/src/main/java/org/apache/shardingsphere/mode/manager/context/ConfigurationContextManager.java
index 32adc980d52..f79844c4013 100644
--- 
a/mode/core/src/main/java/org/apache/shardingsphere/mode/manager/context/ConfigurationContextManager.java
+++ 
b/mode/core/src/main/java/org/apache/shardingsphere/mode/manager/context/ConfigurationContextManager.java
@@ -35,6 +35,7 @@ import 
org.apache.shardingsphere.infra.metadata.database.resource.unit.StorageUn
 import org.apache.shardingsphere.infra.metadata.database.rule.RuleMetaData;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.manager.GenericSchemaManager;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
+import org.apache.shardingsphere.infra.rule.PartialRuleUpdateSupported;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
 import 
org.apache.shardingsphere.infra.rule.builder.database.DatabaseRulesBuilder;
 import org.apache.shardingsphere.infra.rule.builder.global.GlobalRulesBuilder;
@@ -154,15 +155,18 @@ public final class ConfigurationContextManager {
      * @param databaseName database name
      * @param ruleConfig rule configurations
      */
+    @SuppressWarnings({"unchecked", "rawtypes"})
     public synchronized void alterRuleConfiguration(final String databaseName, 
final RuleConfiguration ruleConfig) {
-        // TODO add feature for partly refresh
-        // 1. Judge if impl partly interface
-        // 2. compare diff with current and ruleConfig
-        // 3. Do partly refresh
-        // 4. return
+        ShardingSphereDatabase database = 
metaDataContexts.get().getMetaData().getDatabase(databaseName);
+        Collection<ShardingSphereRule> rules = new 
LinkedList<>(database.getRuleMetaData().getRules());
+        Optional<ShardingSphereRule> toBeChangedRule = 
rules.stream().filter(each -> 
each.getConfiguration().getClass().equals(ruleConfig.getClass())).findFirst();
+        if (toBeChangedRule.isPresent() && toBeChangedRule.get() instanceof 
PartialRuleUpdateSupported) {
+            if (((PartialRuleUpdateSupported) 
toBeChangedRule.get()).partialUpdateRule(ruleConfig)) {
+                ((PartialRuleUpdateSupported) 
toBeChangedRule.get()).updateConfiguration(ruleConfig);
+                return;
+            }
+        }
         try {
-            ShardingSphereDatabase database = 
metaDataContexts.get().getMetaData().getDatabase(databaseName);
-            Collection<ShardingSphereRule> rules = new 
LinkedList<>(database.getRuleMetaData().getRules());
             rules.removeIf(each -> 
each.getConfiguration().getClass().isAssignableFrom(ruleConfig.getClass()));
             rules.addAll(DatabaseRulesBuilder.build(databaseName, 
database.getProtocolType(),
                     
database.getResourceMetaData().getStorageUnits().entrySet().stream()
@@ -180,15 +184,18 @@ public final class ConfigurationContextManager {
      * @param databaseName database name
      * @param ruleConfig rule configurations
      */
+    @SuppressWarnings({"unchecked", "rawtypes"})
     public synchronized void dropRuleConfiguration(final String databaseName, 
final RuleConfiguration ruleConfig) {
-        // TODO add feature for partly refresh
-        // 1. Judge if impl partly interface
-        // 2. compare diff with current and ruleConfig
-        // 3. Remove to be removed partial config
-        // 4. return
+        ShardingSphereDatabase database = 
metaDataContexts.get().getMetaData().getDatabase(databaseName);
+        Collection<ShardingSphereRule> rules = new 
LinkedList<>(database.getRuleMetaData().getRules());
+        Optional<ShardingSphereRule> toBeChangedRule = 
rules.stream().filter(each -> 
each.getConfiguration().getClass().equals(ruleConfig.getClass())).findFirst();
+        if (toBeChangedRule.isPresent() && toBeChangedRule.get() instanceof 
PartialRuleUpdateSupported) {
+            if (((PartialRuleUpdateSupported) 
toBeChangedRule.get()).partialUpdateRule(ruleConfig)) {
+                ((PartialRuleUpdateSupported) 
toBeChangedRule.get()).updateConfiguration(ruleConfig);
+                return;
+            }
+        }
         try {
-            ShardingSphereDatabase database = 
metaDataContexts.get().getMetaData().getDatabase(databaseName);
-            Collection<ShardingSphereRule> rules = new 
LinkedList<>(database.getRuleMetaData().getRules());
             rules.removeIf(each -> 
each.getConfiguration().getClass().isAssignableFrom(ruleConfig.getClass()));
             if (!((DatabaseRuleConfiguration) ruleConfig).isEmpty()) {
                 rules.addAll(DatabaseRulesBuilder.build(databaseName, 
database.getProtocolType(),

Reply via email to