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

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


The following commit(s) were added to refs/heads/master by this push:
     new 7f302a19a1d [fix](fe) Reuse Ranger Doris access controller (#65570)
7f302a19a1d is described below

commit 7f302a19a1deb6d262d07a3356fa758632c44ca1
Author: Mingyu Chen (Rayner) <[email protected]>
AuthorDate: Wed Jul 15 09:43:46 2026 +0800

    [fix](fe) Reuse Ranger Doris access controller (#65570)
    
    ### What problem does this PR solve?
    
    Issue Number: close #65524
    
    Related PR: #45645
    
    Problem Summary:
    
    When Ranger Doris authorization is enabled, constructing a
    `RangerDorisAccessController` initializes a Ranger plugin and starts a
    `PolicyRefresher` background thread. Metadata checkpoints create
    temporary `Env` instances, and each `Env` previously received a newly
    constructed Ranger Doris access controller. Destroying the checkpoint
    `Env` only released the `Env` reference, so the refresher threads
    remained alive. A successful checkpoint could therefore leak two
    `PolicyRefresher` threads.
    
    This change uses an initialization-on-demand holder in
    `RangerDorisAccessControllerFactory` so all `Env` instances in the FE
    process share one lazily initialized controller and one refresher
    thread. The unit test verifies that multiple factory instances construct
    and return only one controller.
---
 .../RangerDorisAccessControllerFactory.java        |  7 +++++-
 .../RangerDorisAccessControllerFactoryTest.java}   | 27 ++++++++++++++--------
 2 files changed, 24 insertions(+), 10 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RangerDorisAccessControllerFactory.java
 
b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RangerDorisAccessControllerFactory.java
index 28093ad7886..7e237699115 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RangerDorisAccessControllerFactory.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RangerDorisAccessControllerFactory.java
@@ -22,6 +22,11 @@ import 
org.apache.doris.catalog.authorizer.ranger.doris.RangerDorisAccessControl
 import java.util.Map;
 
 public class RangerDorisAccessControllerFactory implements 
AccessControllerFactory {
+    private static class SingletonHolder {
+        // Every controller starts a Ranger policy refresher, so all Env 
instances must share one controller.
+        private static final RangerDorisAccessController INSTANCE = new 
RangerDorisAccessController("doris");
+    }
+
     @Override
     public String factoryIdentifier() {
         return "ranger-doris";
@@ -29,6 +34,6 @@ public class RangerDorisAccessControllerFactory implements 
AccessControllerFacto
 
     @Override
     public RangerDorisAccessController createAccessController(Map<String, 
String> prop) {
-        return new RangerDorisAccessController("doris");
+        return SingletonHolder.INSTANCE;
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RangerDorisAccessControllerFactory.java
 
b/fe/fe-core/src/test/java/org/apache/doris/mysql/privilege/RangerDorisAccessControllerFactoryTest.java
similarity index 51%
copy from 
fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RangerDorisAccessControllerFactory.java
copy to 
fe/fe-core/src/test/java/org/apache/doris/mysql/privilege/RangerDorisAccessControllerFactoryTest.java
index 28093ad7886..7029f8e4389 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/RangerDorisAccessControllerFactory.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/mysql/privilege/RangerDorisAccessControllerFactoryTest.java
@@ -19,16 +19,25 @@ package org.apache.doris.mysql.privilege;
 
 import 
org.apache.doris.catalog.authorizer.ranger.doris.RangerDorisAccessController;
 
-import java.util.Map;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.MockedConstruction;
+import org.mockito.Mockito;
 
-public class RangerDorisAccessControllerFactory implements 
AccessControllerFactory {
-    @Override
-    public String factoryIdentifier() {
-        return "ranger-doris";
-    }
+import java.util.Collections;
+
+public class RangerDorisAccessControllerFactoryTest {
+    @Test
+    public void testCreateAccessControllerReturnsSingleton() {
+        try (MockedConstruction<RangerDorisAccessController> 
mockedConstruction =
+                Mockito.mockConstruction(RangerDorisAccessController.class)) {
+            RangerDorisAccessController first = new 
RangerDorisAccessControllerFactory()
+                    .createAccessController(Collections.emptyMap());
+            RangerDorisAccessController second = new 
RangerDorisAccessControllerFactory()
+                    .createAccessController(Collections.emptyMap());
 
-    @Override
-    public RangerDorisAccessController createAccessController(Map<String, 
String> prop) {
-        return new RangerDorisAccessController("doris");
+            Assert.assertEquals(1, mockedConstruction.constructed().size());
+            Assert.assertSame(first, second);
+        }
     }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to