This is an automated email from the ASF dual-hosted git repository.
madhan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push:
new 6d6bce47f RANGER-5148: fix redundant role cache update in concurrent
scenarios (#538)
6d6bce47f is described below
commit 6d6bce47ff30a602256a8b97ebeafcfc5cce0a33
Author: Gooch <[email protected]>
AuthorDate: Mon Jan 12 14:24:23 2026 +0800
RANGER-5148: fix redundant role cache update in concurrent scenarios (#538)
Co-authored-by: Madhan Neethiraj <[email protected]>
---
.../org/apache/ranger/common/RangerRoleCache.java | 87 ++++++++++++----------
1 file changed, 47 insertions(+), 40 deletions(-)
diff --git
a/security-admin/src/main/java/org/apache/ranger/common/RangerRoleCache.java
b/security-admin/src/main/java/org/apache/ranger/common/RangerRoleCache.java
index 247a48b46..cbad34b54 100644
--- a/security-admin/src/main/java/org/apache/ranger/common/RangerRoleCache.java
+++ b/security-admin/src/main/java/org/apache/ranger/common/RangerRoleCache.java
@@ -43,7 +43,7 @@ public class RangerRoleCache {
private final int waitTimeInSeconds;
private final ReentrantLock lock = new ReentrantLock();
- RangerRoleCacheWrapper roleCacheWrapper;
+ private final RangerRoleCacheWrapper roleCacheWrapper = new
RangerRoleCacheWrapper();
private RangerRoleCache() {
RangerAdminConfig config = RangerAdminConfig.getInstance();
@@ -69,21 +69,45 @@ public static RangerRoleCache getInstance() {
}
public RangerRoles getLatestRangerRoleOrCached(String serviceName,
RoleDBStore roleDBStore, Long lastKnownRoleVersion, Long rangerRoleVersionInDB)
throws Exception {
- final RangerRoles ret;
+ RangerRoles ret = null;
if (lastKnownRoleVersion == null ||
!lastKnownRoleVersion.equals(rangerRoleVersionInDB)) {
- roleCacheWrapper = new RangerRoleCacheWrapper();
- ret =
roleCacheWrapper.getLatestRangerRoles(serviceName, roleDBStore,
lastKnownRoleVersion, rangerRoleVersionInDB);
- } else {
- ret = null;
+ ret = roleCacheWrapper.getRoles();
+
+ if (roleCacheWrapper.getRolesVersion() < rangerRoleVersionInDB) {
+ boolean lockResult = false;
+
+ try {
+ lockResult = lock.tryLock(waitTimeInSeconds,
TimeUnit.SECONDS);
+
+ if (lockResult) {
+ if (roleCacheWrapper.getRolesVersion() <
rangerRoleVersionInDB) {
+ ret =
roleCacheWrapper.getLatestRangerRoles(serviceName, roleDBStore,
lastKnownRoleVersion, rangerRoleVersionInDB);
+ } else {
+ ret = roleCacheWrapper.getRoles();
+ }
+ } else {
+ ret = roleCacheWrapper.getRoles();
+
+ LOG.error("Could not get lock in [{}] seconds,
returning cached RangerRoles and wait Queue Length:[{}], roles version:[{}]",
waitTimeInSeconds, lock.getQueueLength(), (ret != null ? ret.getRoleVersion() :
-1L));
+ }
+ } catch (InterruptedException exception) {
+ Thread.currentThread().interrupt();
+ LOG.error("RangerRoleCache.getLatestRangerRoles:lock got
interrupted..", exception);
+ } finally {
+ if (lockResult) {
+ lock.unlock();
+ }
+ }
+ }
}
return ret;
}
private class RangerRoleCacheWrapper {
- RangerRoles roles;
- Long rolesVersion;
+ volatile RangerRoles roles;
+ volatile Long rolesVersion;
RangerRoleCacheWrapper() {
this.roles = null;
@@ -100,45 +124,28 @@ public Long getRolesVersion() {
public RangerRoles getLatestRangerRoles(String serviceName,
RoleDBStore roleDBStore, Long lastKnownRoleVersion, Long rolesVersionInDB)
throws Exception {
RangerRoles ret = null;
- boolean lockResult = false;
LOG.debug("==> RangerRoleCache.getLatestRangerRoles(ServiceName=
{} lastKnownRoleVersion= {} rolesVersionInDB= {})", serviceName,
lastKnownRoleVersion, rolesVersionInDB);
- try {
- lockResult = lock.tryLock(waitTimeInSeconds, TimeUnit.SECONDS);
+ // We are getting all the Roles to be downloaded for now. Should
do downloades for each service based on what roles are there in the policies.
+ final long startTimeMs = System.currentTimeMillis();
+ SearchFilter searchFilter = null;
+ final Set<RangerRole> rolesInDB = new
HashSet<>(roleDBStore.getRoles(searchFilter));
+ final long dbLoadTimeMs = System.currentTimeMillis() -
startTimeMs;
+ Date updateTime = new Date();
- if (lockResult) {
- // We are getting all the Roles to be downloaded for now.
Should do downloades for each service based on what roles are there in the
policies.
- final long startTimeMs =
System.currentTimeMillis();
- SearchFilter searchFilter = null;
- final Set<RangerRole> rolesInDB = new
HashSet<>(roleDBStore.getRoles(searchFilter));
- final long dbLoadTimeMs =
System.currentTimeMillis() - startTimeMs;
- Date updateTime = new Date();
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("loading Roles from database and it took:{}
seconds", TimeUnit.MILLISECONDS.toSeconds(dbLoadTimeMs));
- }
-
- ret = new RangerRoles();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("loading Roles from database and it took:{}
seconds", TimeUnit.MILLISECONDS.toSeconds(dbLoadTimeMs));
+ }
- ret.setRangerRoles(rolesInDB);
- ret.setRoleUpdateTime(updateTime);
- ret.setRoleVersion(rolesVersionInDB);
+ ret = new RangerRoles();
- rolesVersion = rolesVersionInDB;
- roles = ret;
- } else {
- LOG.debug("Could not get lock in [{}] seconds, returning
cached RangerRoles", waitTimeInSeconds);
+ ret.setRangerRoles(rolesInDB);
+ ret.setRoleUpdateTime(updateTime);
+ ret.setRoleVersion(rolesVersionInDB);
- ret = getRoles();
- }
- } catch (InterruptedException exception) {
- LOG.error("RangerRoleCache.getLatestRangerRoles:lock got
interrupted..", exception);
- } finally {
- if (lockResult) {
- lock.unlock();
- }
- }
+ roles = ret;
+ rolesVersion = rolesVersionInDB;
LOG.debug("<== RangerRoleCache.getLatestRangerRoles(ServiceName=
{} lastKnownRoleVersion= {} rolesVersionInDB= {} RangerRoles= {})",
serviceName, lastKnownRoleVersion, rolesVersionInDB, ret);