You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ab...@apache.org on 2023/06/16 16:41:19 UTC

[ranger] branch master updated: RANGER-4284: Additional logging messages to help with debugging when policy deltas are enabled

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

abhay 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 04f5f639a RANGER-4284: Additional logging messages to help with debugging when policy deltas are enabled
04f5f639a is described below

commit 04f5f639aab36135c18652ab183350080c37ecd4
Author: Abhay Kulkarni <ab...@apache.org>
AuthorDate: Fri Jun 16 09:41:10 2023 -0700

    RANGER-4284: Additional logging messages to help with debugging when policy deltas are enabled
---
 .../ranger/plugin/policyengine/PolicyEngine.java   |   4 +-
 .../plugin/policyengine/RangerResourceTrie.java    |   4 +-
 .../ranger/plugin/service/RangerBasePlugin.java    |  12 +-
 .../apache/ranger/plugin/store/ServiceStore.java   |   2 +-
 .../apache/ranger/plugin/util/PolicyRefresher.java |  36 +++++-
 .../java/org/apache/ranger/biz/ServiceDBStore.java |  23 ++--
 .../ranger/common/RangerServicePoliciesCache.java  | 131 ++++++++++++++++-----
 .../org/apache/ranger/db/XXPolicyChangeLogDao.java |   6 +-
 .../main/resources/META-INF/jpa_named_queries.xml  |  11 +-
 9 files changed, 174 insertions(+), 55 deletions(-)

diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java
index f1dc03944..1e99b5824 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/PolicyEngine.java
@@ -680,8 +680,10 @@ public class PolicyEngine {
                 LOG.debug("Built matchers for all Zones");
             }
 
+            RangerPolicyEngineOptions options = pluginContext.getConfig().getPolicyEngineOptions();
+
             for (RangerServiceDef.RangerResourceDef resourceDef : serviceDef.getResources()) {
-                resourceZoneTrie.put(resourceDef.getName(), new RangerResourceTrie<>(resourceDef, matchers));
+                resourceZoneTrie.put(resourceDef.getName(), new RangerResourceTrie<>(resourceDef, matchers, options.optimizeTrieForSpace, options.optimizeTrieForRetrieval, pluginContext));
             }
         }
 
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceTrie.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceTrie.java
index 07eb5815c..647059203 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceTrie.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerResourceTrie.java
@@ -87,11 +87,13 @@ public class RangerResourceTrie<T extends RangerResourceEvaluator> {
         this.optWildcard             = other.optWildcard;
         this.wildcardChars           = other.wildcardChars;
         this.isOptimizedForSpace     = other.isOptimizedForSpace;
-        this.isOptimizedForRetrieval = false;
+        this.isOptimizedForRetrieval = other.isOptimizedForRetrieval;
         this.separatorChar           = other.separatorChar;
         this.inheritedEvaluators     = other.inheritedEvaluators != null ? new HashSet<>(other.inheritedEvaluators) : null;
         this.root                    = copyTrieSubtree(other.root, null);
 
+        wrapUpUpdate();
+
         RangerPerfTracer.logAlways(perf);
 
         if (PERF_TRIE_INIT_LOG.isDebugEnabled()) {
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
index b1e2ecbcc..9249b3295 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/service/RangerBasePlugin.java
@@ -421,7 +421,17 @@ public class RangerBasePlugin {
 					}
 
 					if (this.refresher != null) {
-						this.refresher.saveToCache(usePolicyDeltas ? servicePolicies : policies);
+						boolean doPreserveDeltas = pluginConfig.getBoolean (pluginConfig.getPropertyPrefix() + ".preserve.deltas", false);
+						if (!doPreserveDeltas) {
+							this.refresher.saveToCache(usePolicyDeltas ? servicePolicies : policies);
+						} else {
+							// Save both deltas and all policies to cache for verification
+							this.refresher.saveToCache(policies);
+
+							if (usePolicyDeltas) {
+								this.refresher.saveToCache(servicePolicies);
+							}
+						}
 					}
 				}
 
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/ServiceStore.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/ServiceStore.java
index aecde05fb..8ad3e12c8 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/store/ServiceStore.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/ServiceStore.java
@@ -105,7 +105,7 @@ public interface ServiceStore {
 
 	ServicePolicies getServicePolicyDeltasOrPolicies(String serviceName, Long lastKnownVersion) throws Exception;
 
-	ServicePolicies getServicePolicyDeltas(String serviceName, Long lastKnownVersion) throws Exception;
+	ServicePolicies getServicePolicyDeltas(String serviceName, Long lastKnownVersion, Long cachedPolicyVersion) throws Exception;
 
 	ServicePolicies getServicePolicies(String serviceName, Long lastKnownVersion) throws Exception;
 
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/PolicyRefresher.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/PolicyRefresher.java
index b2e5429ab..c130309ea 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/PolicyRefresher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/PolicyRefresher.java
@@ -28,6 +28,7 @@ import java.util.Timer;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.ranger.admin.client.RangerAdminClient;
 import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig;
@@ -404,22 +405,31 @@ public class PolicyRefresher extends Thread {
 		if(LOG.isDebugEnabled()) {
 			LOG.debug("==> PolicyRefresher(serviceName=" + serviceName + ").saveToCache()");
 		}
+		boolean doPreserveDeltas = plugIn.getConfig().getBoolean(plugIn.getConfig().getPropertyPrefix() + ".preserve.deltas", false);
 
 		if(policies != null) {
 			File cacheFile = null;
+			File backupCacheFile = null;
 			if (cacheDir != null) {
+				String realCacheDirName = CollectionUtils.isNotEmpty(policies.getPolicyDeltas()) ? cacheDir + File.separator + "deltas" : cacheDir;
+				String backupCacheFileName = cacheFileName + "_" + policies.getPolicyVersion();
+				String realCacheFileName = CollectionUtils.isNotEmpty(policies.getPolicyDeltas()) ? backupCacheFileName : cacheFileName;
+
 				// Create the cacheDir if it doesn't already exist
-				File cacheDirTmp = new File(cacheDir);
+				File cacheDirTmp = new File(realCacheDirName);
 				if (cacheDirTmp.exists()) {
-					cacheFile =  new File(cacheDir + File.separator + cacheFileName);
+					cacheFile =  new File(realCacheDirName + File.separator + realCacheFileName);
 				} else {
 					try {
 						cacheDirTmp.mkdirs();
-						cacheFile =  new File(cacheDir + File.separator + cacheFileName);
+						cacheFile =  new File(realCacheDirName + File.separator + realCacheFileName);
 					} catch (SecurityException ex) {
 						LOG.error("Cannot create cache directory", ex);
 					}
 				}
+				if (CollectionUtils.isEmpty(policies.getPolicyDeltas())) {
+					backupCacheFile = new File(realCacheDirName + File.separator + backupCacheFileName);
+				}
 			}
 			
 	    	if(cacheFile != null) {
@@ -451,6 +461,26 @@ public class PolicyRefresher extends Thread {
 				RangerPerfTracer.log(perf);
 
 	    	}
+
+			if (doPreserveDeltas) {
+				if (backupCacheFile != null) {
+
+					RangerPerfTracer perf = null;
+
+					if (RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) {
+						perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "PolicyRefresher.saveToCache(serviceName=" + serviceName + ")");
+					}
+
+					try (Writer writer = new FileWriter(backupCacheFile)) {
+						gson.toJson(policies, writer);
+					} catch (Exception excp) {
+						LOG.error("failed to save policies to cache file '" + backupCacheFile.getAbsolutePath() + "'", excp);
+					}
+
+					RangerPerfTracer.log(perf);
+
+				}
+			}
 		} else {
 			LOG.info("policies is null. Nothing to save in cache");
 		}
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
index 356b01f3c..7030542d9 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/ServiceDBStore.java
@@ -2936,18 +2936,18 @@ public class ServiceDBStore extends AbstractServiceStore {
 		if (LOG.isDebugEnabled()) {
 			LOG.debug("Support for incremental policy updates enabled using \"ranger.admin" + RangerCommonConstants.RANGER_ADMIN_SUFFIX_POLICY_DELTA + "\" configuation parameter :[" + SUPPORTS_POLICY_DELTAS +"]");
 		}
-		return getServicePolicies(serviceName, lastKnownVersion, getOnlyDeltas, SUPPORTS_POLICY_DELTAS);
+		return getServicePolicies(serviceName, lastKnownVersion, getOnlyDeltas, SUPPORTS_POLICY_DELTAS, Long.MAX_VALUE);
 	}
 
 	@Override
-	public ServicePolicies getServicePolicyDeltas(String serviceName, Long lastKnownVersion) throws Exception {
+	public ServicePolicies getServicePolicyDeltas(String serviceName, Long lastKnownVersion, Long cachedPolicyVersion) throws Exception {
 		ServicePolicies ret = null;
 
 		if (SUPPORTS_POLICY_DELTAS) {
 			if (LOG.isDebugEnabled()) {
 				LOG.debug("Support for incremental policy updates enabled using \"ranger.admin" + RangerCommonConstants.RANGER_ADMIN_SUFFIX_POLICY_DELTA + "\" configuation parameter :[" + SUPPORTS_POLICY_DELTAS + "]");
 			}
-			ret = getServicePolicies(serviceName, lastKnownVersion, true, SUPPORTS_POLICY_DELTAS);
+			ret = getServicePolicies(serviceName, lastKnownVersion, true, SUPPORTS_POLICY_DELTAS, cachedPolicyVersion);
 		}
 
 		return ret;
@@ -2956,10 +2956,10 @@ public class ServiceDBStore extends AbstractServiceStore {
 	@Override
 	public ServicePolicies getServicePolicies(String serviceName, Long lastKnownVersion) throws Exception {
 		boolean getOnlyDeltas = false;
-		return getServicePolicies(serviceName, lastKnownVersion, getOnlyDeltas, false);
+		return getServicePolicies(serviceName, lastKnownVersion, getOnlyDeltas, false, Long.MAX_VALUE);
 	}
 
-	private ServicePolicies getServicePolicies(String serviceName, Long lastKnownVersion, boolean getOnlyDeltas, boolean isDeltaEnabled) throws Exception {
+	private ServicePolicies getServicePolicies(String serviceName, Long lastKnownVersion, boolean getOnlyDeltas, boolean isDeltaEnabled, Long maxNeededVersion) throws Exception {
 		if (LOG.isDebugEnabled()) {
 			LOG.debug("==> ServiceDBStore.getServicePolicies(" + serviceName  + ", " + lastKnownVersion + ")");
 		}
@@ -3010,7 +3010,7 @@ public class ServiceDBStore extends AbstractServiceStore {
 		}
 
 		if (isDeltaEnabled) {
-			ret = getServicePoliciesWithDeltas(serviceDef, serviceDbObj, tagServiceDef, tagServiceDbObj, lastKnownVersion);
+			ret = getServicePoliciesWithDeltas(serviceDef, serviceDbObj, tagServiceDef, tagServiceDbObj, lastKnownVersion, maxNeededVersion);
 		}
 
 		if (ret != null) {
@@ -3200,10 +3200,7 @@ public class ServiceDBStore extends AbstractServiceStore {
 				}
 				if (policyDeltasForPolicy != null) {
 					if (LOG.isDebugEnabled()) {
-						LOG.debug("Processed multiple deltas for policy:[" + entry.getKey() + "], compressed-deltas:[" + policyDeltasForPolicy + "]");
-					}
-					if (policyDeltasForPolicy.size() > 1) {
-						LOG.error("More than one Compressed-deltas for policy:[" + entry.getKey() + "], compressed-deltas:[" + policyDeltasForPolicy + "].. Should not have come here!!");
+						LOG.debug("Processed deltas for policy:[" + entry.getKey() + "], compressed-deltas:[" + policyDeltasForPolicy + "]");
 					}
 					ret.addAll(policyDeltasForPolicy);
 				} else {
@@ -3222,7 +3219,7 @@ public class ServiceDBStore extends AbstractServiceStore {
 
 	}
 
-	ServicePolicies getServicePoliciesWithDeltas(RangerServiceDef serviceDef, XXService service, RangerServiceDef tagServiceDef, XXService tagService, Long lastKnownVersion) {
+	ServicePolicies getServicePoliciesWithDeltas(RangerServiceDef serviceDef, XXService service, RangerServiceDef tagServiceDef, XXService tagService, Long lastKnownVersion, Long maxNeededVersion) {
 		ServicePolicies ret = null;
 
 		// if lastKnownVersion != -1L : try and get deltas. Get delta for serviceName first. Find id of the delta
@@ -3242,7 +3239,7 @@ public class ServiceDBStore extends AbstractServiceStore {
 
 			boolean isValid;
 
-			resourcePolicyDeltas = daoMgr.getXXPolicyChangeLog().findLaterThan(lastKnownVersion, service.getId());
+			resourcePolicyDeltas = daoMgr.getXXPolicyChangeLog().findLaterThan(lastKnownVersion, maxNeededVersion, service.getId());
 			if (CollectionUtils.isNotEmpty(resourcePolicyDeltas)) {
 				isValid = RangerPolicyDeltaUtil.isValidDeltas(resourcePolicyDeltas, componentServiceType);
 
@@ -3254,7 +3251,7 @@ public class ServiceDBStore extends AbstractServiceStore {
 
 				if (isValid && tagService != null) {
 					Long id = resourcePolicyDeltas.get(0).getId();
-					tagPolicyDeltas = daoMgr.getXXPolicyChangeLog().findGreaterThan(id, tagService.getId());
+					tagPolicyDeltas = daoMgr.getXXPolicyChangeLog().findGreaterThan(id, maxNeededVersion, tagService.getId());
 
 
 					if (CollectionUtils.isNotEmpty(tagPolicyDeltas)) {
diff --git a/security-admin/src/main/java/org/apache/ranger/common/RangerServicePoliciesCache.java b/security-admin/src/main/java/org/apache/ranger/common/RangerServicePoliciesCache.java
index 70d01e57e..9fda659ac 100644
--- a/security-admin/src/main/java/org/apache/ranger/common/RangerServicePoliciesCache.java
+++ b/security-admin/src/main/java/org/apache/ranger/common/RangerServicePoliciesCache.java
@@ -19,6 +19,8 @@
 
 package org.apache.ranger.common;
 
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.ranger.authorization.hadoop.config.RangerAdminConfig;
@@ -30,6 +32,9 @@ import org.apache.ranger.plugin.util.ServicePolicies;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.File;
+import java.io.FileWriter;
+import java.io.Writer;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
@@ -49,6 +54,7 @@ public class RangerServicePoliciesCache {
 
 	private final int     waitTimeInSeconds;
 	private final boolean dedupStrings;
+	private Gson gson;
 
 	private final Map<String, ServicePoliciesWrapper> servicePoliciesMap = new HashMap<>();
 
@@ -68,6 +74,11 @@ public class RangerServicePoliciesCache {
 
 		waitTimeInSeconds = config.getInt("ranger.admin.policy.download.cache.max.waittime.for.update", MAX_WAIT_TIME_FOR_UPDATE);
 		dedupStrings      = config.getBoolean("ranger.admin.policy.dedup.strings", Boolean.TRUE);
+		try {
+			gson = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z").create();
+		} catch(Throwable excp) {
+			LOG.error("PolicyRefresher(): failed to create GsonBuilder object", excp);
+		}
 	}
 
 	public void dump() {
@@ -130,7 +141,6 @@ public class RangerServicePoliciesCache {
 				LOG.error("getServicePolicies(" + serviceName + "): failed to get latest policies as service-store is null! Returning cached servicePolicies!");
 				ret = servicePoliciesWrapper.getServicePolicies();
 			}
-
 		} else {
 			LOG.error("getServicePolicies() failed to get policies as serviceName is null or blank and/or serviceId is null!");
 		}
@@ -186,6 +196,58 @@ public class RangerServicePoliciesCache {
         return ret;
     }
 
+	public void saveToCache(ServicePolicies policies) {
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("==> RangerServicePoliciesCache(serviceName=" + policies.getServiceName() + ").saveToCache()");
+		}
+		if (policies != null) {
+			RangerAdminConfig config = RangerAdminConfig.getInstance();
+			boolean doSaveToDisk = config.getBoolean("ranger.admin.policy.save.to.disk", false);
+
+			if (doSaveToDisk) {
+				File cacheFile = null;
+
+				String cacheDir = config.get("ranger.admin.policy.cache.dir");
+				if (cacheDir != null) {
+					String appId = policies.getServiceDef().getName();
+					String serviceName = policies.getServiceName();
+					String cacheFileName = String.format("%s_%s.json", appId, serviceName);
+
+					cacheFileName = cacheFileName.replace(File.separatorChar, '_');
+					cacheFileName = cacheFileName.replace(File.pathSeparatorChar, '_');
+					cacheFileName = cacheFileName + "_" + policies.getPolicyVersion();
+
+					// Create the cacheDir if it doesn't already exist
+					File cacheDirTmp = new File(cacheDir);
+					if (cacheDirTmp.exists()) {
+						cacheFile = new File(cacheDir + File.separator + cacheFileName);
+					} else {
+						try {
+							cacheDirTmp.mkdirs();
+							cacheFile = new File(cacheDir + File.separator + cacheFileName);
+						} catch (SecurityException ex) {
+							LOG.error("Cannot create cache directory", ex);
+						}
+					}
+				}
+
+				if (cacheFile != null) {
+					try (Writer writer = new FileWriter(cacheFile)) {
+						gson.toJson(policies, writer);
+					} catch (Exception excp) {
+						LOG.error("failed to save policies to cache file '" + cacheFile.getAbsolutePath() + "'", excp);
+					}
+				}
+			}
+		} else {
+			LOG.error("ServicePolicies is null object!!");
+		}
+
+		if(LOG.isDebugEnabled()) {
+			LOG.debug("<== RangerServicePoliciesCache(serviceName=" + policies.getServiceName() + ").saveToCache()");
+		}
+	}
+
 	private class ServicePoliciesWrapper {
 		final Long          serviceId;
 		ServicePolicies     servicePolicies;
@@ -229,6 +291,7 @@ public class RangerServicePoliciesCache {
 			}
 			ServicePolicies ret        = null;
 			boolean         lockResult = false;
+			boolean         doSaveToCache = false;
 
 			try {
 				final boolean isCacheReloadedByDQEvent;
@@ -238,49 +301,61 @@ public class RangerServicePoliciesCache {
 				if (lockResult) {
 					isCacheReloadedByDQEvent = getLatest(serviceName, serviceStore, lastKnownVersion);
 
-					if (isCacheReloadedByDQEvent) {
-						if (LOG.isDebugEnabled()) {
-							LOG.debug("ServicePolicies cache was completely loaded from database because of a disqualifying event - such as service-definition change!");
+					if (this.servicePolicies != null) {
+						if (isCacheReloadedByDQEvent) {
+							if (LOG.isDebugEnabled()) {
+								LOG.debug("ServicePolicies cache was completely loaded from database because of a disqualifying event - such as service-definition change!");
+							}
 						}
-					}
-
-					if (needsBackwardCompatibility || isCacheReloadedByDQEvent
-						|| lastKnownVersion == -1L || lastKnownVersion.equals(servicePolicies.getPolicyVersion())) {
-						// Looking for all policies, or Some disqualifying change encountered
-						if (LOG.isDebugEnabled()) {
-							LOG.debug("All policies were requested, returning cached ServicePolicies");
+						if (!lastKnownVersion.equals(servicePolicies.getPolicyVersion()) || isCacheReloadedByDQEvent) {
+							doSaveToCache = true;
 						}
-						ret = this.servicePolicies;
-					} else {
-						boolean         isDeltaCacheReinitialized = false;
-						ServicePolicies servicePoliciesForDeltas  = this.deltaCache != null ? this.deltaCache.getServicePolicyDeltasFromVersion(lastKnownVersion) : null;
 
-						if (servicePoliciesForDeltas == null) {
-							servicePoliciesForDeltas  = serviceStore.getServicePolicyDeltas(serviceName, lastKnownVersion);
-							isDeltaCacheReinitialized = true;
-						}
-						if (servicePoliciesForDeltas != null && servicePoliciesForDeltas.getPolicyDeltas() != null) {
+						if (needsBackwardCompatibility || isCacheReloadedByDQEvent
+								|| lastKnownVersion == -1L || lastKnownVersion.equals(servicePolicies.getPolicyVersion())) {
+							// Looking for all policies, or Some disqualifying change encountered
 							if (LOG.isDebugEnabled()) {
-								LOG.debug("Deltas were requested. Returning deltas from lastKnownVersion:[" + lastKnownVersion + "]");
-							}
-							if (isDeltaCacheReinitialized) {
-								this.deltaCache = new ServicePolicyDeltasCache(lastKnownVersion, servicePoliciesForDeltas);
+								LOG.debug("All policies were requested, returning cached ServicePolicies");
 							}
-							ret = servicePoliciesForDeltas;
+							ret = this.servicePolicies;
 						} else {
-							LOG.warn("Deltas were requested for service:[" + serviceName + "], but could not get them!! lastKnownVersion:[" + lastKnownVersion + "]; Returning cached ServicePolicies:[" + (servicePolicies != null ? servicePolicies.getPolicyVersion() : -1L) + "]");
+							boolean isDeltaCacheReinitialized = false;
+							ServicePolicies servicePoliciesForDeltas = this.deltaCache != null ? this.deltaCache.getServicePolicyDeltasFromVersion(lastKnownVersion) : null;
 
-							this.deltaCache = null;
-							ret = this.servicePolicies;
+							if (servicePoliciesForDeltas == null) {
+								servicePoliciesForDeltas = serviceStore.getServicePolicyDeltas(serviceName, lastKnownVersion, servicePolicies.getPolicyVersion());
+								isDeltaCacheReinitialized = true;
+							}
+							if (servicePoliciesForDeltas != null && servicePoliciesForDeltas.getPolicyDeltas() != null) {
+								if (LOG.isDebugEnabled()) {
+									LOG.debug("Deltas were requested. Returning deltas from lastKnownVersion:[" + lastKnownVersion + "]");
+								}
+								if (isDeltaCacheReinitialized) {
+									this.deltaCache = new ServicePolicyDeltasCache(lastKnownVersion, servicePoliciesForDeltas);
+								}
+								ret = servicePoliciesForDeltas;
+							} else {
+								LOG.warn("Deltas were requested for service:[" + serviceName + "], but could not get them!! lastKnownVersion:[" + lastKnownVersion + "]; Returning cached ServicePolicies:[" + (servicePolicies != null ? servicePolicies.getPolicyVersion() : -1L) + "]");
+
+								this.deltaCache = null;
+								ret = this.servicePolicies;
+							}
 						}
+					} else {
+						LOG.error("ServicePolicies object is null!");
 					}
 				} else {
 					LOG.error("Could not get lock in [" + waitTimeInSeconds + "] seconds, returning cached ServicePolicies and wait Queue Length:[" +lock.getQueueLength() + "], servicePolicies version:[" + (servicePolicies != null ? servicePolicies.getPolicyVersion() : -1L) + "]");
 					ret = this.servicePolicies;
+					doSaveToCache = true;
 				}
 			} catch (InterruptedException exception) {
 				LOG.error("getLatestOrCached:lock got interrupted..", exception);
 			} finally {
+				// Dump cached policies to disk
+				if (doSaveToCache) {
+					saveToCache(this.servicePolicies);
+				}
 				if (lockResult) {
 					lock.unlock();
 				}
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyChangeLogDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyChangeLogDao.java
index 483a7a04e..bdf05cdb7 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXPolicyChangeLogDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXPolicyChangeLogDao.java
@@ -56,12 +56,13 @@ public class XXPolicyChangeLogDao extends BaseDao<XXPolicyChangeLog> {
         super(daoManager);
     }
 
-    public List<RangerPolicyDelta> findLaterThan(Long version, Long serviceId) {
+    public List<RangerPolicyDelta> findLaterThan(Long version, Long maxVersion, Long serviceId) {
         final List<RangerPolicyDelta> ret;
         if (version != null) {
             List<Object[]> logs = getEntityManager()
                     .createNamedQuery("XXPolicyChangeLog.findSinceVersion", Object[].class)
                     .setParameter("version", version)
+                    .setParameter("maxVersion", maxVersion)
                     .setParameter("serviceId", serviceId)
                     .getResultList();
 
@@ -94,12 +95,13 @@ public class XXPolicyChangeLogDao extends BaseDao<XXPolicyChangeLog> {
         return ret;
     }
 
-    public List<RangerPolicyDelta> findGreaterThan(Long id, Long serviceId) {
+    public List<RangerPolicyDelta> findGreaterThan(Long id, Long maxVersion, Long serviceId) {
         final List<RangerPolicyDelta> ret;
         if (id != null) {
             List<Object[]> logs = getEntityManager()
                     .createNamedQuery("XXPolicyChangeLog.findGreaterThan", Object[].class)
                     .setParameter("id", id)
+                    .setParameter("maxVersion", maxVersion)
                     .setParameter("serviceId", serviceId)
                     .getResultList();
             ret = convert(logs);
diff --git a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
index 14eca878f..1e8e4e2c5 100755
--- a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
+++ b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
@@ -1781,16 +1781,17 @@
     </named-query>
     <named-query name="XXPolicyChangeLog.findSinceVersion">
         <query>
-            select obj.id, obj.changeType, obj.policyVersion, obj.serviceType, obj.policyType, obj.policyId, obj.zoneName from
-            XXPolicyChangeLog obj where obj.serviceId = :serviceId and obj.policyVersion >= :version order by
-            obj.policyVersion
+			<![CDATA[select obj.id, obj.changeType, obj.policyVersion, obj.serviceType, obj.policyType, obj.policyId, obj.zoneName from
+            XXPolicyChangeLog obj where obj.serviceId = :serviceId and obj.policyVersion >= :version and obj.policyVersion <= :maxVersion order by
+            obj.policyVersion]]>
         </query>
     </named-query>
 
     <named-query name="XXPolicyChangeLog.findGreaterThan">
         <query>
-            select obj.id, obj.changeType, obj.policyVersion, obj.serviceType, obj.policyType, obj.policyId, obj.zoneName from
-            XXPolicyChangeLog obj where obj.serviceId = :serviceId and obj.serviceType = 'tag' and obj.id > :id order by obj.id
+            <![CDATA[select obj.id, obj.changeType, obj.policyVersion, obj.serviceType, obj.policyType, obj.policyId, obj.zoneName from
+            XXPolicyChangeLog obj where obj.serviceId = :serviceId and obj.serviceType = 'tag' and obj.id > :id and obj.policyVersion <= :maxVersion
+            order by obj.id]]>
         </query>
     </named-query>