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 247a48b468..8c3cca4af0 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,9 +43,10 @@ public class RangerRoleCache { private final int waitTimeInSeconds; private final ReentrantLock lock = new ReentrantLock(); - RangerRoleCacheWrapper roleCacheWrapper; + private final RangerRoleCacheWrapper roleCacheWrapper; private RangerRoleCache() { + roleCacheWrapper = new RangerRoleCacheWrapper(); RangerAdminConfig config = RangerAdminConfig.getInstance(); waitTimeInSeconds = config.getInt("ranger.admin.policy.download.cache.max.waittime.for.update", MAX_WAIT_TIME_FOR_UPDATE); @@ -69,21 +70,42 @@ 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 { + LOG.error("Could not get lock in [{}] seconds, returning cached RangerRoles and wait Queue Length:[{}], roles version:[{}]", waitTimeInSeconds, lock.getQueueLength(), roleCacheWrapper.getRolesVersion()); + } + + } 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 +122,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); - - 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 rolesInDB = new HashSet<>(roleDBStore.getRoles(searchFilter)); - final long dbLoadTimeMs = System.currentTimeMillis() - startTimeMs; - Date updateTime = new Date(); + // 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 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);