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]