You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by me...@apache.org on 2022/06/16 12:30:15 UTC

[shardingsphere] branch master updated: Refactor lock judge engine by SPI (#18394)

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

menghaoran 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 93ec14e509d Refactor lock judge engine by SPI (#18394)
93ec14e509d is described below

commit 93ec14e509d6548df177d69869da9a32c36cde55
Author: gin <ja...@163.com>
AuthorDate: Thu Jun 16 20:30:02 2022 +0800

    Refactor lock judge engine by SPI (#18394)
    
    * Refactor lock judge engine by SPI
    
    * Fix IT
---
 ...reLockJudgeEngine.java => LockJudgeEngine.java} | 36 +++++++---------
 .../mode/manager/lock/LockJudgeEngineBuilder.java  | 47 +++++++++++++++++++++
 .../lock/ShardingSphereLockJudgeEngine.java        | 48 ++++++++++++++++++----
 ...hardingsphere.mode.manager.lock.LockJudgeEngine | 18 ++++++++
 .../lock/ShardingSphereLockJudgeEngineTest.java    | 47 +++++++++++++++++----
 .../communication/DatabaseCommunicationEngine.java |  9 ++--
 6 files changed, 162 insertions(+), 43 deletions(-)

diff --git a/shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/lock/ShardingSphereLockJudgeEngine.java b/shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/lock/LockJudgeEngine.java
similarity index 50%
copy from shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/lock/ShardingSphereLockJudgeEngine.java
copy to shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/lock/LockJudgeEngine.java
index bb80d07daf2..36860d77089 100644
--- a/shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/lock/ShardingSphereLockJudgeEngine.java
+++ b/shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/lock/LockJudgeEngine.java
@@ -17,38 +17,30 @@
 
 package org.apache.shardingsphere.mode.manager.lock;
 
-import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.infra.lock.LockContext;
-import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
-import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DDLStatement;
-import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DMLStatement;
-import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.spi.annotation.SingletonSPI;
+import org.apache.shardingsphere.spi.type.required.RequiredSPI;
 
 /**
- * Lock judge engine for ShardingSphere.
+ * Lock judge engine.
  */
-@RequiredArgsConstructor
-public final class ShardingSphereLockJudgeEngine {
+@SingletonSPI
+public interface LockJudgeEngine extends RequiredSPI {
     
-    private final LockContext lockContext;
+    /**
+     * Init.
+     *
+     * @param lockContext lock context
+     */
+    void init(LockContext lockContext);
     
     /**
      * Is locked.
      *
      * @param databaseName database name
-     * @param sqlStatement sql statement
+     * @param sqlStatementContext sql statement context
      * @return is locked or not
      */
-    public boolean isLocked(final String databaseName, final SQLStatement sqlStatement) {
-        if (sqlStatement instanceof DMLStatement) {
-            if (sqlStatement instanceof SelectStatement) {
-                return false;
-            }
-            return lockContext.isLocked(databaseName);
-        }
-        if (sqlStatement instanceof DDLStatement) {
-            return lockContext.isLocked(databaseName);
-        }
-        return false;
-    }
+    boolean isLocked(String databaseName, SQLStatementContext<?> sqlStatementContext);
 }
diff --git a/shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/lock/LockJudgeEngineBuilder.java b/shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/lock/LockJudgeEngineBuilder.java
new file mode 100644
index 00000000000..59e170712c6
--- /dev/null
+++ b/shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/lock/LockJudgeEngineBuilder.java
@@ -0,0 +1,47 @@
+/*
+ * 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.mode.manager.lock;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.infra.lock.LockContext;
+import org.apache.shardingsphere.spi.ShardingSphereServiceLoader;
+import org.apache.shardingsphere.spi.type.required.RequiredSPIRegistry;
+
+/**
+ * Lock judge engine builder.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class LockJudgeEngineBuilder {
+    
+    static {
+        ShardingSphereServiceLoader.register(LockJudgeEngine.class);
+    }
+    
+    /**
+     * Build.
+     *
+     * @param lockContext lock context
+     * @return lock judge engine
+     */
+    public static LockJudgeEngine build(final LockContext lockContext) {
+        LockJudgeEngine result = RequiredSPIRegistry.getRegisteredService(LockJudgeEngine.class);
+        result.init(lockContext);
+        return result;
+    }
+}
diff --git a/shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/lock/ShardingSphereLockJudgeEngine.java b/shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/lock/ShardingSphereLockJudgeEngine.java
index bb80d07daf2..598f8e4a15c 100644
--- a/shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/lock/ShardingSphereLockJudgeEngine.java
+++ b/shardingsphere-mode/shardingsphere-mode-core/src/main/java/org/apache/shardingsphere/mode/manager/lock/ShardingSphereLockJudgeEngine.java
@@ -18,37 +18,67 @@
 package org.apache.shardingsphere.mode.manager.lock;
 
 import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.infra.lock.LockContext;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DDLStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DMLStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
 
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
 /**
  * Lock judge engine for ShardingSphere.
  */
 @RequiredArgsConstructor
-public final class ShardingSphereLockJudgeEngine {
+public final class ShardingSphereLockJudgeEngine implements LockJudgeEngine {
+    
+    private static final Set<Class<? extends SQLStatement>> IGNORABLE_SQL_STATEMENT_CLASSES_STOP_WRITING = Collections.newSetFromMap(new ConcurrentHashMap<>());
     
-    private final LockContext lockContext;
+    private LockContext lockContext;
+    
+    @Override
+    public void init(final LockContext lockContext) {
+        this.lockContext = lockContext;
+    }
     
     /**
      * Is locked.
      *
      * @param databaseName database name
-     * @param sqlStatement sql statement
+     * @param sqlStatementContext sql statement context
      * @return is locked or not
      */
-    public boolean isLocked(final String databaseName, final SQLStatement sqlStatement) {
-        if (sqlStatement instanceof DMLStatement) {
-            if (sqlStatement instanceof SelectStatement) {
-                return false;
-            }
+    @Override
+    public boolean isLocked(final String databaseName, final SQLStatementContext<?> sqlStatementContext) {
+        if (isWriteStatement(sqlStatementContext.getSqlStatement())) {
             return lockContext.isLocked(databaseName);
         }
+        return false;
+    }
+    
+    private boolean isWriteStatement(final SQLStatement sqlStatement) {
+        Class<? extends SQLStatement> sqlStatementClass = sqlStatement.getClass();
+        if (IGNORABLE_SQL_STATEMENT_CLASSES_STOP_WRITING.contains(sqlStatementClass)) {
+            return false;
+        }
+        if (sqlStatement instanceof SelectStatement) {
+            catchIgnorable(sqlStatementClass);
+            return false;
+        }
+        if (sqlStatement instanceof DMLStatement) {
+            return true;
+        }
         if (sqlStatement instanceof DDLStatement) {
-            return lockContext.isLocked(databaseName);
+            return true;
         }
+        catchIgnorable(sqlStatementClass);
         return false;
     }
+    
+    private void catchIgnorable(final Class<? extends SQLStatement> sqlStatementClass) {
+        IGNORABLE_SQL_STATEMENT_CLASSES_STOP_WRITING.add(sqlStatementClass);
+    }
 }
diff --git a/shardingsphere-mode/shardingsphere-mode-core/src/main/resources/META-INF/services/org.apache.shardingsphere.mode.manager.lock.LockJudgeEngine b/shardingsphere-mode/shardingsphere-mode-core/src/main/resources/META-INF/services/org.apache.shardingsphere.mode.manager.lock.LockJudgeEngine
new file mode 100644
index 00000000000..0b5e3c4c1ba
--- /dev/null
+++ b/shardingsphere-mode/shardingsphere-mode-core/src/main/resources/META-INF/services/org.apache.shardingsphere.mode.manager.lock.LockJudgeEngine
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.apache.shardingsphere.mode.manager.lock.ShardingSphereLockJudgeEngine
diff --git a/shardingsphere-mode/shardingsphere-mode-core/src/test/java/org/apache/shardingsphere/mode/manager/lock/ShardingSphereLockJudgeEngineTest.java b/shardingsphere-mode/shardingsphere-mode-core/src/test/java/org/apache/shardingsphere/mode/manager/lock/ShardingSphereLockJudgeEngineTest.java
index 5df07a41820..f8a3ab3e31e 100644
--- a/shardingsphere-mode/shardingsphere-mode-core/src/test/java/org/apache/shardingsphere/mode/manager/lock/ShardingSphereLockJudgeEngineTest.java
+++ b/shardingsphere-mode/shardingsphere-mode-core/src/test/java/org/apache/shardingsphere/mode/manager/lock/ShardingSphereLockJudgeEngineTest.java
@@ -17,6 +17,11 @@
 
 package org.apache.shardingsphere.mode.manager.lock;
 
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.binder.statement.dml.DeleteStatementContext;
+import org.apache.shardingsphere.infra.binder.statement.dml.InsertStatementContext;
+import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
+import org.apache.shardingsphere.infra.binder.statement.dml.UpdateStatementContext;
 import org.apache.shardingsphere.infra.lock.LockContext;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DDLStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
@@ -33,21 +38,47 @@ import static org.mockito.Mockito.when;
 
 public final class ShardingSphereLockJudgeEngineTest {
     
-    private ShardingSphereLockJudgeEngine engine;
+    private LockJudgeEngine engine;
     
     @Before
     public void setUp() {
         LockContext lockContext = mock(LockContext.class);
         when(lockContext.isLocked("databaseName")).thenReturn(true);
-        engine = new ShardingSphereLockJudgeEngine(lockContext);
+        engine = LockJudgeEngineBuilder.build(lockContext);
     }
     
     @Test
-    public void assertIsLocked() {
-        assertTrue(engine.isLocked("databaseName", mock(InsertStatement.class)));
-        assertTrue(engine.isLocked("databaseName", mock(UpdateStatement.class)));
-        assertTrue(engine.isLocked("databaseName", mock(DeleteStatement.class)));
-        assertTrue(engine.isLocked("databaseName", mock(DDLStatement.class)));
-        assertFalse(engine.isLocked("databaseName", mock(SelectStatement.class)));
+    public void assertDDLIsLocked() {
+        SQLStatementContext<DDLStatement> sqlStatementContext = mock(SQLStatementContext.class);
+        when(sqlStatementContext.getSqlStatement()).thenReturn(mock(DDLStatement.class));
+        assertTrue(engine.isLocked("databaseName", sqlStatementContext));
+    }
+    
+    @Test
+    public void assertInsertIsLocked() {
+        InsertStatementContext insertStatementContext = mock(InsertStatementContext.class);
+        when(insertStatementContext.getSqlStatement()).thenReturn(mock(InsertStatement.class));
+        assertTrue(engine.isLocked("databaseName", insertStatementContext));
+    }
+    
+    @Test
+    public void assertUpdateIsLocked() {
+        UpdateStatementContext updateStatementContext = mock(UpdateStatementContext.class);
+        when(updateStatementContext.getSqlStatement()).thenReturn(mock(UpdateStatement.class));
+        assertTrue(engine.isLocked("databaseName", updateStatementContext));
+    }
+    
+    @Test
+    public void assertDeleteIsLocked() {
+        DeleteStatementContext deleteStatementContext = mock(DeleteStatementContext.class);
+        when(deleteStatementContext.getSqlStatement()).thenReturn(mock(DeleteStatement.class));
+        assertTrue(engine.isLocked("databaseName", deleteStatementContext));
+    }
+    
+    @Test
+    public void assertSelectIsLocked() {
+        SelectStatementContext selectStatementContext = mock(SelectStatementContext.class);
+        when(selectStatementContext.getSqlStatement()).thenReturn(mock(SelectStatement.class));
+        assertFalse(engine.isLocked("databaseName", selectStatementContext));
     }
 }
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/DatabaseCommunicationEngine.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/DatabaseCommunicationEngine.java
index eff0d08e2a9..34ca5592d90 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/DatabaseCommunicationEngine.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/DatabaseCommunicationEngine.java
@@ -38,7 +38,8 @@ import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.metadata.database.schema.event.MetaDataRefreshedEvent;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
 import org.apache.shardingsphere.infra.rule.identifier.type.DataNodeContainedRule;
-import org.apache.shardingsphere.mode.manager.lock.ShardingSphereLockJudgeEngine;
+import org.apache.shardingsphere.mode.manager.lock.LockJudgeEngine;
+import org.apache.shardingsphere.mode.manager.lock.LockJudgeEngineBuilder;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import org.apache.shardingsphere.proxy.backend.exception.DatabaseLockedException;
 import org.apache.shardingsphere.proxy.backend.response.data.QueryResponseCell;
@@ -82,7 +83,7 @@ public abstract class DatabaseCommunicationEngine<T> {
     
     private final BackendConnection<?> backendConnection;
     
-    private final ShardingSphereLockJudgeEngine lockJudgeEngine;
+    private final LockJudgeEngine lockJudgeEngine;
     
     public DatabaseCommunicationEngine(final String driverType, final ShardingSphereDatabase database, final LogicSQL logicSQL, final BackendConnection<?> backendConnection) {
         this.driverType = driverType;
@@ -94,7 +95,7 @@ public abstract class DatabaseCommunicationEngine<T> {
                 ProxyContext.getInstance().getContextManager().getMetaDataContexts().getOptimizerContext().getFederationMetaData().getDatabases().get(databaseName),
                 ProxyContext.getInstance().getContextManager().getMetaDataContexts().getOptimizerContext().getPlannerContexts(),
                 ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getProps());
-        lockJudgeEngine = new ShardingSphereLockJudgeEngine(ProxyContext.getInstance().getContextManager().getInstanceContext().getLockContext());
+        lockJudgeEngine = LockJudgeEngineBuilder.build(ProxyContext.getInstance().getContextManager().getInstanceContext().getLockContext());
     }
     
     /**
@@ -222,7 +223,7 @@ public abstract class DatabaseCommunicationEngine<T> {
     }
     
     protected void checkLockedDatabase(final ExecutionContext executionContext) {
-        if (lockJudgeEngine.isLocked(backendConnection.getConnectionSession().getDatabaseName(), executionContext.getSqlStatementContext().getSqlStatement())) {
+        if (lockJudgeEngine.isLocked(backendConnection.getConnectionSession().getDatabaseName(), executionContext.getSqlStatementContext())) {
             throw new DatabaseLockedException(backendConnection.getConnectionSession().getDatabaseName());
         }
     }