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 2021/02/27 16:58:01 UTC

[ranger] branch ranger-2.2 updated: RANGER-3192: Use read-write locks for managing access to policy-engine and tag-repository

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

abhay pushed a commit to branch ranger-2.2
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/ranger-2.2 by this push:
     new c20d0e0  RANGER-3192: Use read-write locks for managing access to policy-engine and tag-repository
c20d0e0 is described below

commit c20d0e0a65aed8f7fbd8020acfe1612c9b7887f8
Author: Abhay Kulkarni <ab...@apache.org>
AuthorDate: Sat Feb 27 07:08:47 2021 -0800

    RANGER-3192: Use read-write locks for managing access to policy-engine and tag-repository
---
 .../ranger/admin/client/RangerAdminRESTClient.java |  18 +-
 .../plugin/contextenricher/RangerTagEnricher.java  | 151 +++++---
 .../ranger/plugin/policyengine/PolicyEngine.java   | 259 +++++++++-----
 .../policyengine/RangerPolicyEngineImpl.java       | 397 ++++++++++++++-------
 .../policyengine/RangerPolicyRepository.java       | 263 ++++++++------
 .../org/apache/ranger/plugin/store/TagStore.java   |   2 +
 .../ranger/plugin/util/RangerCommonConstants.java  |  24 +-
 .../ranger/plugin/util/RangerReadWriteLock.java    |  98 +++++
 .../admin/client/RangerAdminJersey2RESTClient.java |  18 +-
 .../apache/ranger/biz/RangerPolicyAdminCache.java  |   4 +-
 .../apache/ranger/biz/RangerPolicyAdminImpl.java   | 250 +++++++++----
 .../java/org/apache/ranger/biz/ServiceDBStore.java |   9 +-
 .../java/org/apache/ranger/biz/TagDBStore.java     |  24 +-
 .../ranger/common/RangerAdminTagEnricher.java      |  12 +
 .../java/org/apache/ranger/biz/TestXUserMgr.java   |   4 -
 15 files changed, 1044 insertions(+), 489 deletions(-)

diff --git a/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminRESTClient.java b/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminRESTClient.java
index 9d527bf..e0d7a9b 100644
--- a/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminRESTClient.java
+++ b/agents-common/src/main/java/org/apache/ranger/admin/client/RangerAdminRESTClient.java
@@ -53,8 +53,8 @@ public class RangerAdminRESTClient extends AbstractRangerAdminClient {
 	private String           clusterName;
 	private RangerRESTClient restClient;
 	private RangerRESTUtils  restUtils   = new RangerRESTUtils();
-	private String 		     supportsPolicyDeltas;
-	private String 		     supportsTagDeltas;
+	private boolean 		 supportsPolicyDeltas;
+	private boolean 		 supportsTagDeltas;
 	private final String     pluginCapabilities = Long.toHexString(new RangerPluginCapability().getPluginCapabilities());
 
 	public static <T> GenericType<List<T>> getGenericType(final T clazz) {
@@ -97,8 +97,8 @@ public class RangerAdminRESTClient extends AbstractRangerAdminClient {
 		}
 		int	 restClientConnTimeOutMs	= config.getInt(propertyPrefix + ".policy.rest.client.connection.timeoutMs", 120 * 1000);
 		int	 restClientReadTimeOutMs	= config.getInt(propertyPrefix + ".policy.rest.client.read.timeoutMs", 30 * 1000);
-		supportsPolicyDeltas            = config.get(propertyPrefix + ".policy.rest.supports.policy.deltas", "false");
-		supportsTagDeltas               = config.get(propertyPrefix + ".tag.rest.supports.tag.deltas", "false");
+		supportsPolicyDeltas            = config.getBoolean(propertyPrefix + RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_POLICY_DELTA, RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_POLICY_DELTA_DEFAULT);
+		supportsTagDeltas               = config.getBoolean(propertyPrefix + RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_TAG_DELTA, RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_TAG_DELTA_DEFAULT);
 
         if (!StringUtil.isEmpty(tmpUrl)) {
             url = tmpUrl.trim();
@@ -106,12 +106,6 @@ public class RangerAdminRESTClient extends AbstractRangerAdminClient {
         if (url.endsWith("/")) {
             url = url.substring(0, url.length() - 1);
         }
-		if (!"true".equalsIgnoreCase(supportsPolicyDeltas)) {
-			supportsPolicyDeltas = "false";
-		}
-		if (!"true".equalsIgnoreCase(supportsTagDeltas)) {
-			supportsTagDeltas = "false";
-		}
 
 		init(url, sslConfigFileName, restClientConnTimeOutMs , restClientReadTimeOutMs, config);
 
@@ -140,7 +134,7 @@ public class RangerAdminRESTClient extends AbstractRangerAdminClient {
 		queryParams.put(RangerRESTUtils.REST_PARAM_LAST_ACTIVATION_TIME, Long.toString(lastActivationTimeInMillis));
 		queryParams.put(RangerRESTUtils.REST_PARAM_PLUGIN_ID, pluginId);
 		queryParams.put(RangerRESTUtils.REST_PARAM_CLUSTER_NAME, clusterName);
-		queryParams.put(RangerRESTUtils.REST_PARAM_SUPPORTS_POLICY_DELTAS, supportsPolicyDeltas);
+		queryParams.put(RangerRESTUtils.REST_PARAM_SUPPORTS_POLICY_DELTAS, Boolean.toString(supportsPolicyDeltas));
 		queryParams.put(RangerRESTUtils.REST_PARAM_CAPABILITIES, pluginCapabilities);
 
 		if (isSecureMode) {
@@ -799,7 +793,7 @@ public class RangerAdminRESTClient extends AbstractRangerAdminClient {
 		queryParams.put(RangerRESTUtils.LAST_KNOWN_TAG_VERSION_PARAM, Long.toString(lastKnownVersion));
 		queryParams.put(RangerRESTUtils.REST_PARAM_LAST_ACTIVATION_TIME, Long.toString(lastActivationTimeInMillis));
 		queryParams.put(RangerRESTUtils.REST_PARAM_PLUGIN_ID, pluginId);
-		queryParams.put(RangerRESTUtils.REST_PARAM_SUPPORTS_TAG_DELTAS, supportsTagDeltas);
+		queryParams.put(RangerRESTUtils.REST_PARAM_SUPPORTS_TAG_DELTAS, Boolean.toString(supportsTagDeltas));
 		queryParams.put(RangerRESTUtils.REST_PARAM_CAPABILITIES, pluginCapabilities);
 
 		if (isSecureMode) {
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
index 97b9e2c..f457460 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagEnricher.java
@@ -26,6 +26,7 @@ import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig;
 import org.apache.ranger.plugin.model.RangerPolicy;
 import org.apache.ranger.plugin.model.RangerServiceDef;
 import org.apache.ranger.plugin.model.RangerServiceResource;
@@ -42,7 +43,9 @@ import org.apache.ranger.plugin.util.DownloadTrigger;
 import org.apache.ranger.plugin.util.DownloaderTask;
 import org.apache.ranger.plugin.service.RangerAuthContext;
 import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
+import org.apache.ranger.plugin.util.RangerCommonConstants;
 import org.apache.ranger.plugin.util.RangerPerfTracer;
+import org.apache.ranger.plugin.util.RangerReadWriteLock;
 import org.apache.ranger.plugin.util.RangerServiceNotFoundException;
 import org.apache.ranger.plugin.util.RangerServiceTagsDeltaUtil;
 import org.apache.ranger.plugin.util.ServiceTags;
@@ -87,6 +90,7 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
 	private Timer                              tagDownloadTimer;
 
 	private RangerServiceDefHelper             serviceDefHelper;
+	private RangerReadWriteLock                lock = new RangerReadWriteLock(false);
 
 	@Override
 	public void init() {
@@ -132,6 +136,9 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
 				cacheFilename = cacheFilename.replace(File.pathSeparatorChar,  '_');
 
 				String cacheFile = cacheDir == null ? null : (cacheDir + File.separator + cacheFilename);
+
+				createLock();
+
 				tagRetriever.setServiceName(serviceName);
 				tagRetriever.setServiceDef(serviceDef);
 				tagRetriever.setAppId(appId);
@@ -189,21 +196,33 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
 		if (LOG.isDebugEnabled()) {
 			LOG.debug("==> RangerTagEnricher.enrich(" + request + ") with dataStore:[" + dataStore + "]");
 		}
-		final EnrichedServiceTags enrichedServiceTags;
 
-		if (dataStore instanceof EnrichedServiceTags) {
-			enrichedServiceTags = (EnrichedServiceTags) dataStore;
-		} else {
-			enrichedServiceTags = this.enrichedServiceTags;
+		final Set<RangerTagForEval> matchedTags;
+
+		try (RangerReadWriteLock.RangerLock readLock = this.lock.getReadLock()) {
 
-			if (dataStore != null) {
-				LOG.warn("Incorrect type of dataStore :[" + dataStore.getClass().getName() + "], falling back to original enrich");
+			if (LOG.isDebugEnabled()) {
+				if (readLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + readLock);
+				}
 			}
-		}
 
-		final Set<RangerTagForEval> matchedTags = enrichedServiceTags == null ? null : findMatchingTags(request, enrichedServiceTags);
+			final EnrichedServiceTags enrichedServiceTags;
 
-		RangerAccessRequestUtil.setRequestTagsInContext(request.getContext(), matchedTags);
+			if (dataStore instanceof EnrichedServiceTags) {
+				enrichedServiceTags = (EnrichedServiceTags) dataStore;
+			} else {
+				enrichedServiceTags = this.enrichedServiceTags;
+
+				if (dataStore != null) {
+					LOG.warn("Incorrect type of dataStore :[" + dataStore.getClass().getName() + "], falling back to original enrich");
+				}
+			}
+
+			matchedTags = enrichedServiceTags == null ? null : findMatchingTags(request, enrichedServiceTags);
+
+			RangerAccessRequestUtil.setRequestTagsInContext(request.getContext(), matchedTags);
+		}
 
 		if (LOG.isDebugEnabled()) {
 			LOG.debug("<== RangerTagEnricher.enrich(" + request + ") with dataStore:[" + dataStore + "]): tags count=" + (matchedTags == null ? 0 : matchedTags.size()));
@@ -266,48 +285,64 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
 			LOG.debug("==> RangerTagEnricher.setServiceTags(serviceTags=" + serviceTags + ", rebuildOnlyIndex=" + rebuildOnlyIndex + ")");
 		}
 
-		if (serviceTags == null) {
-			LOG.info("ServiceTags is null for service " + serviceName);
-			enrichedServiceTags = null;
-		} else  {
+		try (RangerReadWriteLock.RangerLock writeLock = this.lock.getWriteLock()) {
+
+			if (LOG.isDebugEnabled()) {
+				if (writeLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + writeLock);
+				}
+			}
 			RangerPerfTracer perf = null;
 
 			if(RangerPerfTracer.isPerfTraceEnabled(PERF_SET_SERVICETAGS_LOG)) {
 				perf = RangerPerfTracer.getPerfTracer(PERF_SET_SERVICETAGS_LOG, "RangerTagEnricher.setServiceTags(newTagVersion=" + serviceTags.getTagVersion() + ",isDelta=" + serviceTags.getIsDelta() + ")");
 			}
 
-			if (!serviceTags.getIsDelta()) {
-				processServiceTags(serviceTags);
+			if (serviceTags == null) {
+				LOG.info("ServiceTags is null for service " + serviceName);
+				enrichedServiceTags = null;
 			} else {
-				if (LOG.isDebugEnabled()) {
-					LOG.debug("Received service-tag deltas:" + serviceTags);
-				}
-
-				ServiceTags oldServiceTags = enrichedServiceTags != null ? enrichedServiceTags.getServiceTags() : new ServiceTags();
-				ServiceTags allServiceTags = rebuildOnlyIndex ? oldServiceTags : RangerServiceTagsDeltaUtil.applyDelta(oldServiceTags, serviceTags);
-
-				if (serviceTags.getTagsChangeExtent() == ServiceTags.TagsChangeExtent.NONE) {
+				if (!serviceTags.getIsDelta()) {
+					processServiceTags(serviceTags);
+				} else {
 					if (LOG.isDebugEnabled()) {
-						LOG.debug("No change to service-tags other than version change");
+						LOG.debug("Received service-tag deltas:" + serviceTags);
 					}
-				} else {
-					if (serviceTags.getTagsChangeExtent() != ServiceTags.TagsChangeExtent.TAGS) {
-						processServiceTagDeltas(serviceTags, allServiceTags);
-					} else {
+					ServiceTags oldServiceTags = enrichedServiceTags != null ? enrichedServiceTags.getServiceTags() : new ServiceTags();
+					ServiceTags allServiceTags = rebuildOnlyIndex ? oldServiceTags : RangerServiceTagsDeltaUtil.applyDelta(oldServiceTags, serviceTags);
+
+					if (serviceTags.getTagsChangeExtent() == ServiceTags.TagsChangeExtent.NONE) {
 						if (LOG.isDebugEnabled()) {
-							LOG.debug("Delta contains only tag attribute changes");
+							LOG.debug("No change to service-tags other than version change");
+						}
+					} else {
+						if (serviceTags.getTagsChangeExtent() != ServiceTags.TagsChangeExtent.TAGS) {
+							Map<String, RangerResourceTrie<RangerServiceResourceMatcher>> trieMap;
+
+							if (enrichedServiceTags == null) {
+								trieMap = new HashMap<>();
+							} else {
+								trieMap = writeLock.isLockingEnabled() ? enrichedServiceTags.getServiceResourceTrie() : copyServiceResourceTrie();
+							}
+
+							processServiceTagDeltas(serviceTags, allServiceTags, trieMap);
+						} else {
+							if (LOG.isDebugEnabled()) {
+								LOG.debug("Delta contains only tag attribute changes");
+							}
+							List<RangerServiceResourceMatcher> resourceMatchers = enrichedServiceTags != null ? enrichedServiceTags.getServiceResourceMatchers() : new ArrayList<>();
+							Map<String, RangerResourceTrie<RangerServiceResourceMatcher>> serviceResourceTrie = enrichedServiceTags != null ? enrichedServiceTags.getServiceResourceTrie() : new HashMap<>();
+							enrichedServiceTags = new EnrichedServiceTags(allServiceTags, resourceMatchers, serviceResourceTrie);
 						}
-						List<RangerServiceResourceMatcher>                            resourceMatchers    = enrichedServiceTags != null ? enrichedServiceTags.getServiceResourceMatchers() : new ArrayList<>();
-						Map<String, RangerResourceTrie<RangerServiceResourceMatcher>> serviceResourceTrie = enrichedServiceTags != null ? enrichedServiceTags.getServiceResourceTrie() : new HashMap<>();
-						enrichedServiceTags = new EnrichedServiceTags(allServiceTags, resourceMatchers, serviceResourceTrie);
 					}
 				}
+
 			}
+			setEnrichedServiceTagsInPlugin();
+
 			RangerPerfTracer.logAlways(perf);
 		}
 
-		setEnrichedServiceTagsInPlugin();
-
 		if (LOG.isDebugEnabled()) {
 			LOG.debug("<== RangerTagEnricher.setServiceTags(serviceTags=" + serviceTags + ", rebuildOnlyIndex=" + rebuildOnlyIndex + ")");
 		}
@@ -315,11 +350,13 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
 	}
 
 	protected Long getServiceTagsVersion() {
-		return enrichedServiceTags != null ? enrichedServiceTags.getServiceTags().getTagVersion() : -1L;
+		EnrichedServiceTags localEnrichedServiceTags = enrichedServiceTags;
+		return localEnrichedServiceTags != null ? localEnrichedServiceTags.getServiceTags().getTagVersion() : -1L;
 	}
 
 	protected Long getResourceTrieVersion() {
-		return enrichedServiceTags != null ? enrichedServiceTags.getResourceTrieVersion() : -1L;
+		EnrichedServiceTags localEnrichedServiceTags = enrichedServiceTags;
+		return localEnrichedServiceTags != null ? localEnrichedServiceTags.getResourceTrieVersion() : -1L;
 	}
 
 	@Override
@@ -359,6 +396,18 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
 		return enrichedServiceTags;
 	}
 
+	protected RangerReadWriteLock createLock() {
+		String             propertyPrefix        = "ranger.plugin." + serviceDef.getName();
+		RangerPluginConfig config                = getPluginConfig();
+		boolean            deltasEnabled         = config != null && config.getBoolean(propertyPrefix + RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_TAG_DELTA, RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_TAG_DELTA_DEFAULT);
+		boolean            inPlaceUpdatesEnabled = config != null && config.getBoolean(propertyPrefix + RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_IN_PLACE_TAG_UPDATES, RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_IN_PLACE_TAG_UPDATES_DEFAULT);
+		boolean            useReadWriteLock      = deltasEnabled && inPlaceUpdatesEnabled;
+
+		LOG.info("Policy-Engine will" + (useReadWriteLock ? " " : " not ") + "use read-write locking to update tags in place when tag-deltas are provided");
+
+		return new RangerReadWriteLock(useReadWriteLock);
+
+	}
 	private void processServiceTags(ServiceTags serviceTags) {
 		if (LOG.isDebugEnabled()) {
 			LOG.debug("Processing all service-tags");
@@ -405,24 +454,18 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
 		}
 	}
 
-	private void processServiceTagDeltas(ServiceTags deltas, ServiceTags allServiceTags) {
+	private void processServiceTagDeltas(ServiceTags deltas, ServiceTags allServiceTags, Map<String, RangerResourceTrie<RangerServiceResourceMatcher>> serviceResourceTrie) {
 		if (LOG.isDebugEnabled()) {
 			LOG.debug("Delta contains changes other than tag attribute changes, [" + deltas.getTagsChangeExtent() + "]");
 		}
 
-		boolean isInError = false;
-
-		ResourceHierarchies    hierarchies      = new ResourceHierarchies();
+		boolean                            isInError        = false;
 
-		List<RangerServiceResourceMatcher>                            resourceMatchers    = new ArrayList<>();
-		Map<String, RangerResourceTrie<RangerServiceResourceMatcher>> serviceResourceTrie = new HashMap<>();
+		ResourceHierarchies                hierarchies      = new ResourceHierarchies();
+		List<RangerServiceResourceMatcher> resourceMatchers = new ArrayList<>();
 
 		if (enrichedServiceTags != null) {
 			resourceMatchers.addAll(enrichedServiceTags.getServiceResourceMatchers());
-			for (Map.Entry<String, RangerResourceTrie<RangerServiceResourceMatcher>> entry : enrichedServiceTags.getServiceResourceTrie().entrySet()) {
-				RangerResourceTrie<RangerServiceResourceMatcher> resourceTrie = new RangerResourceTrie<>(entry.getValue());
-				serviceResourceTrie.put(entry.getKey(), resourceTrie);
-			}
 		}
 
 		List<RangerServiceResource> changedServiceResources = deltas.getServiceResources();
@@ -810,6 +853,18 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
 		return ret;
 	}
 
+	private Map<String, RangerResourceTrie<RangerServiceResourceMatcher>> copyServiceResourceTrie() {
+		Map<String, RangerResourceTrie<RangerServiceResourceMatcher>> ret = new HashMap<>();
+
+		if (enrichedServiceTags != null) {
+			for (Map.Entry<String, RangerResourceTrie<RangerServiceResourceMatcher>> entry : enrichedServiceTags.getServiceResourceTrie().entrySet()) {
+				RangerResourceTrie<RangerServiceResourceMatcher> resourceTrie = new RangerResourceTrie<>(entry.getValue());
+				ret.put(entry.getKey(), resourceTrie);
+			}
+		}
+		return ret;
+	}
+
 	static public final class EnrichedServiceTags {
 		final private ServiceTags                                                      serviceTags;
 		final private List<RangerServiceResourceMatcher>                               serviceResourceMatchers;
@@ -896,7 +951,7 @@ public class RangerTagEnricher extends RangerAbstractContextEnricher {
 					RangerPerfTracer.log(perf);
 
 				} catch (InterruptedException excp) {
-					LOG.debug("RangerTagRefresher(" + getName() + ").run(): Interrupted! Exiting thread", excp);
+					LOG.info("RangerTagRefresher(" + getName() + ").run(): Interrupted! Exiting thread", excp);
 					break;
 				} finally {
 					if (trigger != null) {
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 1909ad4..9d79520 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
@@ -46,6 +46,7 @@ import org.apache.ranger.plugin.service.RangerAuthContext;
 import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil;
 import org.apache.ranger.plugin.util.RangerPerfTracer;
 import org.apache.ranger.plugin.util.RangerPolicyDeltaUtil;
+import org.apache.ranger.plugin.util.RangerReadWriteLock;
 import org.apache.ranger.plugin.util.RangerRoles;
 import org.apache.ranger.plugin.util.ServicePolicies;
 import org.apache.ranger.plugin.util.StringTokenReplacer;
@@ -67,6 +68,16 @@ public class PolicyEngine {
     private       String[]                            trustedProxyAddresses;
     private final Map<String, StringTokenReplacer>    tokenReplacers = new HashMap<>();
 
+    private final RangerReadWriteLock                 lock;
+
+    public RangerReadWriteLock.RangerLock getReadLock() {
+        return lock.getReadLock();
+    }
+
+    public RangerReadWriteLock.RangerLock getWriteLock() {
+        return lock.getWriteLock();
+    }
+
     public boolean getUseForwardedIPAddress() {
         return useForwardedIPAddress;
     }
@@ -152,6 +163,8 @@ public class PolicyEngine {
         }
         sb.append("} ");
 
+        sb.append(lock.toString());
+
         sb.append("}");
 
         return sb;
@@ -167,7 +180,7 @@ public class PolicyEngine {
         return resourceZoneTrie;
     }
 
-        public PolicyEngine(ServicePolicies servicePolicies, RangerPluginContext pluginContext, RangerRoles roles) {
+    public PolicyEngine(ServicePolicies servicePolicies, RangerPluginContext pluginContext, RangerRoles roles, boolean isUseReadWriteLock) {
         if (LOG.isDebugEnabled()) {
             LOG.debug("==> PolicyEngine(" + ", " + servicePolicies + ", " + pluginContext + ")");
         }
@@ -184,6 +197,9 @@ public class PolicyEngine {
         }
 
         this.pluginContext = pluginContext;
+        this.lock          = new RangerReadWriteLock(isUseReadWriteLock);
+
+        LOG.info("Policy engine will" + (isUseReadWriteLock ? " " : " not ") + "perform in place update while processing policy-deltas.");
 
         this.pluginContext.setAuthContext(new RangerAuthContext(null, roles));
 
@@ -200,8 +216,7 @@ public class PolicyEngine {
         if (!options.disableTagPolicyEvaluation
                 && tagPolicies != null
                 && !StringUtils.isEmpty(tagPolicies.getServiceName())
-                && tagPolicies.getServiceDef() != null
-                && !CollectionUtils.isEmpty(tagPolicies.getPolicies())) {
+                && tagPolicies.getServiceDef() != null) {
             if (LOG.isDebugEnabled()) {
                 LOG.debug("PolicyEngine : Building tag-policy-repository for tag-service " + tagPolicies.getServiceName());
             }
@@ -281,33 +296,46 @@ public class PolicyEngine {
             perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerPolicyEngine.cloneWithDelta()");
         }
 
-        RangerServiceDef serviceDef    = this.getServiceDef();
-        String           serviceType   = (serviceDef != null) ? serviceDef.getName() : "";
-        boolean          isValidDeltas = false;
+        try (RangerReadWriteLock.RangerLock writeLock = getWriteLock()) {
+            if (LOG.isDebugEnabled()) {
+                if (writeLock.isLockingEnabled()) {
+                    LOG.debug("Acquired lock - " + writeLock);
+                }
+            }
 
-        if (CollectionUtils.isNotEmpty(servicePolicies.getPolicyDeltas()) || MapUtils.isNotEmpty(servicePolicies.getSecurityZones())) {
-            isValidDeltas = CollectionUtils.isEmpty(servicePolicies.getPolicyDeltas()) || RangerPolicyDeltaUtil.isValidDeltas(servicePolicies.getPolicyDeltas(), serviceType);
+            RangerServiceDef serviceDef = this.getServiceDef();
+            String serviceType = (serviceDef != null) ? serviceDef.getName() : "";
+            boolean isValidDeltas = false;
 
-            if (isValidDeltas) {
-                if (MapUtils.isNotEmpty(servicePolicies.getSecurityZones())) {
-                    for (Map.Entry<String, ServicePolicies.SecurityZoneInfo> entry : servicePolicies.getSecurityZones().entrySet()) {
-                        if (!RangerPolicyDeltaUtil.isValidDeltas(entry.getValue().getPolicyDeltas(), serviceType)) {
-                            if (LOG.isDebugEnabled()) {
-                                LOG.debug("Invalid policy-deltas for security zone:[" + entry.getKey() + "]");
-                            }
+            if (CollectionUtils.isNotEmpty(servicePolicies.getPolicyDeltas()) || MapUtils.isNotEmpty(servicePolicies.getSecurityZones())) {
+                isValidDeltas = CollectionUtils.isEmpty(servicePolicies.getPolicyDeltas()) || RangerPolicyDeltaUtil.isValidDeltas(servicePolicies.getPolicyDeltas(), serviceType);
+
+                if (isValidDeltas) {
+                    if (MapUtils.isNotEmpty(servicePolicies.getSecurityZones())) {
+                        for (Map.Entry<String, ServicePolicies.SecurityZoneInfo> entry : servicePolicies.getSecurityZones().entrySet()) {
+                            if (!RangerPolicyDeltaUtil.isValidDeltas(entry.getValue().getPolicyDeltas(), serviceType)) {
+                                if (LOG.isDebugEnabled()) {
+                                    LOG.debug("Invalid policy-deltas for security zone:[" + entry.getKey() + "]");
+                                }
 
-                            isValidDeltas = false;
-                            break;
+                                isValidDeltas = false;
+                                break;
+                            }
                         }
                     }
                 }
             }
-        }
 
-        if (isValidDeltas) {
-            ret = new PolicyEngine(this, servicePolicies);
-        } else {
-            ret = null;
+            if (isValidDeltas) {
+                if (writeLock.isLockingEnabled()) {
+                    updatePolicyEngine(servicePolicies);
+                    ret = this;
+                } else {
+                    ret = new PolicyEngine(this, servicePolicies);
+                }
+            } else {
+                ret = null;
+            }
         }
 
         RangerPerfTracer.log(perf);
@@ -556,83 +584,17 @@ public class PolicyEngine {
         return ret;
     }
 
-
     private PolicyEngine(final PolicyEngine other, ServicePolicies servicePolicies) {
         this.useForwardedIPAddress = other.useForwardedIPAddress;
         this.trustedProxyAddresses = other.trustedProxyAddresses;
         this.pluginContext         = other.pluginContext;
+        this.lock                  = other.lock;
 
         long                    policyVersion                   = servicePolicies.getPolicyVersion() != null ? servicePolicies.getPolicyVersion() : -1L;
         List<RangerPolicyDelta> defaultZoneDeltas               = new ArrayList<>();
         List<RangerPolicyDelta> defaultZoneDeltasForTagPolicies = new ArrayList<>();
 
-        if (MapUtils.isNotEmpty(servicePolicies.getSecurityZones())) {
-            buildZoneTrie(servicePolicies);
-
-            Map<String, List<RangerPolicyDelta>> zoneDeltasMap = new HashMap<>();
-
-            for (Map.Entry<String, ServicePolicies.SecurityZoneInfo> zone : servicePolicies.getSecurityZones().entrySet()) {
-                List<RangerPolicyDelta> deltas = zone.getValue().getPolicyDeltas();
-
-                for (RangerPolicyDelta delta : deltas) {
-                    String zoneName = delta.getZoneName();
-
-                    if (StringUtils.isNotEmpty(zoneName)) {
-                        List<RangerPolicyDelta> zoneDeltas = zoneDeltasMap.get(zoneName);
-
-                        if (zoneDeltas == null) {
-                            zoneDeltas = new ArrayList<>();
-                            zoneDeltasMap.put(zoneName, zoneDeltas);
-                        }
-
-                        zoneDeltas.add(delta);
-                    } else {
-                        LOG.warn("policyDelta : [" + delta + "] does not belong to any zone. Should not have come here.");
-                    }
-                }
-            }
-
-            for (Map.Entry<String, List<RangerPolicyDelta>> entry : zoneDeltasMap.entrySet()) {
-                final String                  zoneName        = entry.getKey();
-                final List<RangerPolicyDelta> zoneDeltas      = entry.getValue();
-                final RangerPolicyRepository  otherRepository = other.zonePolicyRepositories.get(zoneName);
-                final RangerPolicyRepository  policyRepository;
-
-                if (CollectionUtils.isNotEmpty(zoneDeltas)) {
-                    if (otherRepository == null) {
-                        List<RangerPolicy> policies = new ArrayList<>();
-
-                        for (RangerPolicyDelta delta : zoneDeltas) {
-                            if (delta.getChangeType() == RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE) {
-                                policies.add(delta.getPolicy());
-                            } else {
-                                LOG.warn("Expected changeType:[" + RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE + "], found policy-change-delta:[" + delta +"]");
-                            }
-                        }
-
-                        servicePolicies.getSecurityZones().get(zoneName).setPolicies(policies);
-
-                        policyRepository = new RangerPolicyRepository(servicePolicies, this.pluginContext, zoneName);
-                    } else {
-                        policyRepository = new RangerPolicyRepository(otherRepository, zoneDeltas, policyVersion);
-                    }
-                } else {
-                    policyRepository = shareWith(otherRepository);
-                }
-
-                zonePolicyRepositories.put(zoneName, policyRepository);
-            }
-        }
-
-        List<RangerPolicyDelta> unzonedDeltas = servicePolicies.getPolicyDeltas();
-
-        for (RangerPolicyDelta delta : unzonedDeltas) {
-            if (servicePolicies.getServiceDef().getName().equals(delta.getServiceType())) {
-                defaultZoneDeltas.add(delta);
-            } else {
-                defaultZoneDeltasForTagPolicies.add(delta);
-            }
-        }
+        getDeltasSortedByZones(servicePolicies, defaultZoneDeltas, defaultZoneDeltasForTagPolicies);
 
         if (other.policyRepository != null && CollectionUtils.isNotEmpty(defaultZoneDeltas)) {
             this.policyRepository = new RangerPolicyRepository(other.policyRepository, defaultZoneDeltas, policyVersion);
@@ -813,5 +775,122 @@ public class PolicyEngine {
             LOG.debug("<== PolicyEngine.cleanup()");
         }
     }
+
+    void updatePolicyEngine(ServicePolicies servicePolicies) {
+
+        long                    policyVersion                   = servicePolicies.getPolicyVersion() != null ? servicePolicies.getPolicyVersion() : -1L;
+        List<RangerPolicyDelta> defaultZoneDeltas               = new ArrayList<>();
+        List<RangerPolicyDelta> defaultZoneDeltasForTagPolicies = new ArrayList<>();
+
+        getDeltasSortedByZones(servicePolicies, defaultZoneDeltas, defaultZoneDeltasForTagPolicies);
+
+        if (this.policyRepository != null && CollectionUtils.isNotEmpty(defaultZoneDeltas)) {
+            this.policyRepository.reinit(defaultZoneDeltas, policyVersion);
+        }
+
+        if (servicePolicies.getTagPolicies() != null && CollectionUtils.isNotEmpty(defaultZoneDeltasForTagPolicies)) {
+            if (this.tagPolicyRepository != null) {
+                this.tagPolicyRepository.reinit(defaultZoneDeltasForTagPolicies, policyVersion);
+            } else {
+                LOG.error("No previous tagPolicyRepository to update! Should not have come here!!");
+            }
+        }
+
+        // Set all repositories to shared
+        if (policyRepository != null) {
+            policyRepository.setShared();
+        }
+        for (RangerPolicyRepository zoneRepository : zonePolicyRepositories.values()) {
+            if (zoneRepository != null) {
+                zoneRepository.setShared();
+            }
+        }
+        if (tagPolicyRepository != null) {
+            tagPolicyRepository.setShared();
+        }
+
+        reorderPolicyEvaluators();
+    }
+
+    private void getDeltasSortedByZones(ServicePolicies servicePolicies, List<RangerPolicyDelta> defaultZoneDeltas, List<RangerPolicyDelta> defaultZoneDeltasForTagPolicies) {
+        long                    policyVersion                   = servicePolicies.getPolicyVersion() != null ? servicePolicies.getPolicyVersion() : -1L;
+
+        if (CollectionUtils.isNotEmpty(defaultZoneDeltas)) {
+            LOG.warn("Emptying out defaultZoneDeltas!");
+            defaultZoneDeltas.clear();
+        }
+        if (CollectionUtils.isNotEmpty(defaultZoneDeltasForTagPolicies)) {
+            LOG.warn("Emptying out defaultZoneDeltasForTagPolicies!");
+            defaultZoneDeltasForTagPolicies.clear();
+        }
+
+        if (MapUtils.isNotEmpty(servicePolicies.getSecurityZones())) {
+            buildZoneTrie(servicePolicies);
+
+            Map<String, List<RangerPolicyDelta>> zoneDeltasMap = new HashMap<>();
+
+            for (Map.Entry<String, ServicePolicies.SecurityZoneInfo> zone : servicePolicies.getSecurityZones().entrySet()) {
+                List<RangerPolicyDelta> deltas = zone.getValue().getPolicyDeltas();
+
+                for (RangerPolicyDelta delta : deltas) {
+                    String zoneName = delta.getZoneName();
+
+                    if (StringUtils.isNotEmpty(zoneName)) {
+                        List<RangerPolicyDelta> zoneDeltas = zoneDeltasMap.get(zoneName);
+
+                        if (zoneDeltas == null) {
+                            zoneDeltas = new ArrayList<>();
+                            zoneDeltasMap.put(zoneName, zoneDeltas);
+                        }
+
+                        zoneDeltas.add(delta);
+                    } else {
+                        LOG.warn("policyDelta : [" + delta + "] does not belong to any zone. Should not have come here.");
+                    }
+                }
+            }
+
+            for (Map.Entry<String, List<RangerPolicyDelta>> entry : zoneDeltasMap.entrySet()) {
+                final String                  zoneName        = entry.getKey();
+                final List<RangerPolicyDelta> zoneDeltas      = entry.getValue();
+                final RangerPolicyRepository  otherRepository = this.zonePolicyRepositories.get(zoneName);
+                final RangerPolicyRepository  policyRepository;
+
+                if (CollectionUtils.isNotEmpty(zoneDeltas)) {
+                    if (otherRepository == null) {
+                        List<RangerPolicy> policies = new ArrayList<>();
+
+                        for (RangerPolicyDelta delta : zoneDeltas) {
+                            if (delta.getChangeType() == RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE) {
+                                policies.add(delta.getPolicy());
+                            } else {
+                                LOG.warn("Expected changeType:[" + RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE + "], found policy-change-delta:[" + delta +"]");
+                            }
+                        }
+
+                        servicePolicies.getSecurityZones().get(zoneName).setPolicies(policies);
+
+                        policyRepository = new RangerPolicyRepository(servicePolicies, this.pluginContext, zoneName);
+                    } else {
+                        policyRepository = new RangerPolicyRepository(otherRepository, zoneDeltas, policyVersion);
+                    }
+                } else {
+                    policyRepository = shareWith(otherRepository);
+                }
+
+                zonePolicyRepositories.put(zoneName, policyRepository);
+            }
+        }
+
+        List<RangerPolicyDelta> unzonedDeltas = servicePolicies.getPolicyDeltas();
+
+        for (RangerPolicyDelta delta : unzonedDeltas) {
+            if (servicePolicies.getServiceDef().getName().equals(delta.getServiceType())) {
+                defaultZoneDeltas.add(delta);
+            } else {
+                defaultZoneDeltasForTagPolicies.add(delta);
+            }
+        }
+    }
 }
 
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
index 4e0c98e..75811b8 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyEngineImpl.java
@@ -25,6 +25,7 @@ import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
 import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig;
 import org.apache.ranger.authorization.utils.StringUtil;
 import org.apache.ranger.plugin.contextenricher.RangerTagForEval;
@@ -36,7 +37,9 @@ import org.apache.ranger.plugin.policyresourcematcher.RangerPolicyResourceMatche
 import org.apache.ranger.plugin.service.RangerDefaultRequestProcessor;
 import org.apache.ranger.plugin.util.GrantRevokeRequest;
 import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
+import org.apache.ranger.plugin.util.RangerCommonConstants;
 import org.apache.ranger.plugin.util.RangerPerfTracer;
+import org.apache.ranger.plugin.util.RangerReadWriteLock;
 import org.apache.ranger.plugin.util.RangerRoles;
 import org.apache.ranger.plugin.util.ServicePolicies;
 
@@ -71,7 +74,11 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
 			PolicyEngine policyEngine = other.policyEngine.cloneWithDelta(servicePolicies);
 
 			if (policyEngine != null) {
-				ret = new RangerPolicyEngineImpl(policyEngine, other);
+				if (policyEngine == other.policyEngine) {
+					ret = other;
+				} else {
+					ret = new RangerPolicyEngineImpl(policyEngine, other);
+				}
 			}
 		}
 
@@ -79,7 +86,18 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
 	}
 
 	public RangerPolicyEngineImpl(ServicePolicies servicePolicies, RangerPluginContext pluginContext, RangerRoles roles) {
-		policyEngine     = new PolicyEngine(servicePolicies, pluginContext, roles);
+		final boolean isUseReadWriteLock;
+
+		Configuration config = pluginContext != null ? pluginContext.getConfig() : null;
+
+		if (config != null) {
+			boolean isDeltasSupported = config.getBoolean(pluginContext.getConfig().getPropertyPrefix() + RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_POLICY_DELTA, RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_POLICY_DELTA_DEFAULT);
+			isUseReadWriteLock = isDeltasSupported && config.getBoolean(pluginContext.getConfig().getPropertyPrefix() + RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_IN_PLACE_POLICY_UPDATES, RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_IN_PLACE_POLICY_UPDATES_DEFAULT);
+		} else {
+			isUseReadWriteLock = false;
+		}
+
+		policyEngine     = new PolicyEngine(servicePolicies, pluginContext, roles, isUseReadWriteLock);
 		serviceConfig    = new ServiceConfig(servicePolicies.getServiceConfig());
 		requestProcessor = new RangerDefaultRequestProcessor(policyEngine);
 	}
@@ -105,22 +123,32 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
 			LOG.info("RangerPolicyEngineImpl.evaluatePolicies(" + requestHashCode + ", " + request + ")");
 		}
 
-		requestProcessor.preProcess(request);
+		RangerAccessResult ret;
 
-		RangerAccessResult ret = zoneAwareAccessEvaluationWithNoAudit(request, policyType);
+		try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+			if (LOG.isDebugEnabled()) {
+				if (readLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + readLock);
+				}
+			}
 
-		if (resultProcessor != null) {
-			RangerPerfTracer perfAuditTracer = null;
+			requestProcessor.preProcess(request);
 
-			if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_AUDIT_LOG)) {
-				String requestHashCode = Integer.toHexString(System.identityHashCode(request)) + "_" + policyType;
+			ret = zoneAwareAccessEvaluationWithNoAudit(request, policyType);
 
-				perfAuditTracer = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_AUDIT_LOG, "RangerPolicyEngine.processAudit(requestHashCode=" + requestHashCode + ")");
-			}
+			if (resultProcessor != null) {
+				RangerPerfTracer perfAuditTracer = null;
 
-			resultProcessor.processResult(ret);
+				if (RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_AUDIT_LOG)) {
+					String requestHashCode = Integer.toHexString(System.identityHashCode(request)) + "_" + policyType;
 
-			RangerPerfTracer.log(perfAuditTracer);
+					perfAuditTracer = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_AUDIT_LOG, "RangerPolicyEngine.processAudit(requestHashCode=" + requestHashCode + ")");
+				}
+
+				resultProcessor.processResult(ret);
+
+				RangerPerfTracer.log(perfAuditTracer);
+			}
 		}
 
 		RangerPerfTracer.log(perf);
@@ -140,18 +168,25 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
 
 		Collection<RangerAccessResult> ret = new ArrayList<>();
 
-		if (requests != null) {
-			for (RangerAccessRequest request : requests) {
-				requestProcessor.preProcess(request);
+		try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+			if (LOG.isDebugEnabled()) {
+				if (readLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + readLock);
+				}
+			}
+			if (requests != null) {
+				for (RangerAccessRequest request : requests) {
+					requestProcessor.preProcess(request);
 
-				RangerAccessResult result = zoneAwareAccessEvaluationWithNoAudit(request, policyType);
+					RangerAccessResult result = zoneAwareAccessEvaluationWithNoAudit(request, policyType);
 
-				ret.add(result);
+					ret.add(result);
+				}
 			}
-		}
 
-		if (resultProcessor != null) {
-			resultProcessor.processResults(ret);
+			if (resultProcessor != null) {
+				resultProcessor.processResults(ret);
+			}
 		}
 
 		if (LOG.isDebugEnabled()) {
@@ -167,27 +202,35 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
 			LOG.debug("==> RangerPolicyEngineImpl.evaluateAuditPolicies(result=" + result + ")");
 		}
 
-		RangerPolicyRepository tagPolicyRepository      = policyEngine.getTagPolicyRepository();
-		RangerPolicyRepository policyRepository         = policyEngine.getPolicyRepository();
-		RangerAccessRequest    request                  = result.getAccessRequest();
-		boolean                savedIsAuditedDetermined = result.getIsAuditedDetermined();
-		boolean                savedIsAudited           = result.getIsAudited();
+		try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+			if (LOG.isDebugEnabled()) {
+				if (readLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + readLock);
+				}
+			}
 
-		result.setIsAudited(false);
-		result.setIsAuditedDetermined(false);
+			RangerPolicyRepository tagPolicyRepository = policyEngine.getTagPolicyRepository();
+			RangerPolicyRepository policyRepository = policyEngine.getPolicyRepository();
+			RangerAccessRequest request = result.getAccessRequest();
+			boolean savedIsAuditedDetermined = result.getIsAuditedDetermined();
+			boolean savedIsAudited = result.getIsAudited();
 
-		try {
-			if (tagPolicyRepository != null) {
-				evaluateTagAuditPolicies(request, result, tagPolicyRepository);
-			}
+			result.setIsAudited(false);
+			result.setIsAuditedDetermined(false);
 
-			if (!result.getIsAuditedDetermined() && policyRepository != null) {
-				evaluateResourceAuditPolicies(request, result, policyRepository);
-			}
-		} finally {
-			if (!result.getIsAuditedDetermined()) {
-				result.setIsAudited(savedIsAudited);
-				result.setIsAuditedDetermined(savedIsAuditedDetermined);
+			try {
+				if (tagPolicyRepository != null) {
+					evaluateTagAuditPolicies(request, result, tagPolicyRepository);
+				}
+
+				if (!result.getIsAuditedDetermined() && policyRepository != null) {
+					evaluateResourceAuditPolicies(request, result, policyRepository);
+				}
+			} finally {
+				if (!result.getIsAuditedDetermined()) {
+					result.setIsAudited(savedIsAudited);
+					result.setIsAuditedDetermined(savedIsAuditedDetermined);
+				}
 			}
 		}
 
@@ -209,122 +252,130 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
 			perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_GET_ACLS_LOG, "RangerPolicyEngine.getResourceACLs(requestHashCode=" + request.getResource().getAsString() + ")");
 		}
 
-		requestProcessor.preProcess(request);
+		try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+			if (LOG.isDebugEnabled()) {
+				if (readLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + readLock);
+				}
+			}
 
-		String zoneName = policyEngine.getUniquelyMatchedZoneName(request.getResource().getAsMap());
+			requestProcessor.preProcess(request);
 
-		if (LOG.isDebugEnabled()) {
-			LOG.debug("zoneName:[" + zoneName + "]");
-		}
-		List<RangerPolicyEvaluator>                      allEvaluators           = new ArrayList<>();
-		Map<Long, RangerPolicyResourceMatcher.MatchType> tagMatchTypeMap         = new HashMap<>();
-		Set<Long>                                        policyIdForTemporalTags = new HashSet<>();
+			String zoneName = policyEngine.getUniquelyMatchedZoneName(request.getResource().getAsMap());
 
-		getResourceACLEvaluatorsForZone(request, zoneName, allEvaluators, tagMatchTypeMap, policyIdForTemporalTags);
+			if (LOG.isDebugEnabled()) {
+				LOG.debug("zoneName:[" + zoneName + "]");
+			}
+			List<RangerPolicyEvaluator> allEvaluators = new ArrayList<>();
+			Map<Long, RangerPolicyResourceMatcher.MatchType> tagMatchTypeMap = new HashMap<>();
+			Set<Long> policyIdForTemporalTags = new HashSet<>();
 
-		allEvaluators.sort(RangerPolicyEvaluator.EVAL_ORDER_COMPARATOR);
+			getResourceACLEvaluatorsForZone(request, zoneName, allEvaluators, tagMatchTypeMap, policyIdForTemporalTags);
 
-		if (CollectionUtils.isNotEmpty(allEvaluators)) {
-			Integer policyPriority = null;
+			allEvaluators.sort(RangerPolicyEvaluator.EVAL_ORDER_COMPARATOR);
 
-			for (RangerPolicyEvaluator evaluator : allEvaluators) {
-				if (policyPriority == null) {
-					policyPriority = evaluator.getPolicyPriority();
-				}
+			if (CollectionUtils.isNotEmpty(allEvaluators)) {
+				Integer policyPriority = null;
 
-				if (policyPriority != evaluator.getPolicyPriority()) {
-					ret.finalizeAcls();
+				for (RangerPolicyEvaluator evaluator : allEvaluators) {
+					if (policyPriority == null) {
+						policyPriority = evaluator.getPolicyPriority();
+					}
 
-					policyPriority = evaluator.getPolicyPriority();
-				}
+					if (policyPriority != evaluator.getPolicyPriority()) {
+						ret.finalizeAcls();
 
-				RangerPolicyResourceMatcher.MatchType matchType =  tagMatchTypeMap.get(evaluator.getId());
+						policyPriority = evaluator.getPolicyPriority();
+					}
 
-				if (matchType == null) {
-					matchType = evaluator.getPolicyResourceMatcher().getMatchType(request.getResource(), request.getContext());
-				}
+					RangerPolicyResourceMatcher.MatchType matchType = tagMatchTypeMap.get(evaluator.getId());
 
-				final boolean isMatched;
+					if (matchType == null) {
+						matchType = evaluator.getPolicyResourceMatcher().getMatchType(request.getResource(), request.getContext());
+					}
 
-				if (request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS) {
-					isMatched = matchType != RangerPolicyResourceMatcher.MatchType.NONE;
-				} else {
-					isMatched = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.SELF_AND_ALL_DESCENDANTS;
-				}
+					final boolean isMatched;
 
-				if (!isMatched) {
-					continue;
-				}
+					if (request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS) {
+						isMatched = matchType != RangerPolicyResourceMatcher.MatchType.NONE;
+					} else {
+						isMatched = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.SELF_AND_ALL_DESCENDANTS;
+					}
 
-				PolicyACLSummary aclSummary = evaluator.getPolicyACLSummary();
+					if (!isMatched) {
+						continue;
+					}
 
-				if (aclSummary != null) {
-					boolean isConditional = policyIdForTemporalTags.contains(evaluator.getId()) || evaluator.getValidityScheduleEvaluatorsCount() != 0;
-					Integer accessResult;
+					PolicyACLSummary aclSummary = evaluator.getPolicyACLSummary();
 
-					for (Map.Entry<String, Map<String, PolicyACLSummary.AccessResult>> userAccessInfo : aclSummary.getUsersAccessInfo().entrySet()) {
-						final String userName = userAccessInfo.getKey();
+					if (aclSummary != null) {
+						boolean isConditional = policyIdForTemporalTags.contains(evaluator.getId()) || evaluator.getValidityScheduleEvaluatorsCount() != 0;
+						Integer accessResult;
 
-						for (Map.Entry<String, PolicyACLSummary.AccessResult> accessInfo : userAccessInfo.getValue().entrySet()) {
-							if (isConditional) {
-								accessResult = ACCESS_CONDITIONAL;
-							} else {
-								accessResult = accessInfo.getValue().getResult();
+						for (Map.Entry<String, Map<String, PolicyACLSummary.AccessResult>> userAccessInfo : aclSummary.getUsersAccessInfo().entrySet()) {
+							final String userName = userAccessInfo.getKey();
+
+							for (Map.Entry<String, PolicyACLSummary.AccessResult> accessInfo : userAccessInfo.getValue().entrySet()) {
+								if (isConditional) {
+									accessResult = ACCESS_CONDITIONAL;
+								} else {
+									accessResult = accessInfo.getValue().getResult();
 
-								if (accessResult.equals(RangerPolicyEvaluator.ACCESS_UNDETERMINED)) {
-									accessResult = RangerPolicyEvaluator.ACCESS_DENIED;
+									if (accessResult.equals(RangerPolicyEvaluator.ACCESS_UNDETERMINED)) {
+										accessResult = RangerPolicyEvaluator.ACCESS_DENIED;
+									}
 								}
-							}
 
-							RangerPolicy policy = evaluator.getPolicy();
+								RangerPolicy policy = evaluator.getPolicy();
 
-							ret.setUserAccessInfo(userName, accessInfo.getKey(), accessResult, policy);
+								ret.setUserAccessInfo(userName, accessInfo.getKey(), accessResult, policy);
+							}
 						}
-					}
 
-					for (Map.Entry<String, Map<String, PolicyACLSummary.AccessResult>> groupAccessInfo : aclSummary.getGroupsAccessInfo().entrySet()) {
-						final String groupName = groupAccessInfo.getKey();
+						for (Map.Entry<String, Map<String, PolicyACLSummary.AccessResult>> groupAccessInfo : aclSummary.getGroupsAccessInfo().entrySet()) {
+							final String groupName = groupAccessInfo.getKey();
 
-						for (Map.Entry<String, PolicyACLSummary.AccessResult> accessInfo : groupAccessInfo.getValue().entrySet()) {
-							if (isConditional) {
-								accessResult = ACCESS_CONDITIONAL;
-							} else {
-								accessResult = accessInfo.getValue().getResult();
+							for (Map.Entry<String, PolicyACLSummary.AccessResult> accessInfo : groupAccessInfo.getValue().entrySet()) {
+								if (isConditional) {
+									accessResult = ACCESS_CONDITIONAL;
+								} else {
+									accessResult = accessInfo.getValue().getResult();
 
-								if (accessResult.equals(RangerPolicyEvaluator.ACCESS_UNDETERMINED)) {
-									accessResult = RangerPolicyEvaluator.ACCESS_DENIED;
+									if (accessResult.equals(RangerPolicyEvaluator.ACCESS_UNDETERMINED)) {
+										accessResult = RangerPolicyEvaluator.ACCESS_DENIED;
+									}
 								}
-							}
 
-							RangerPolicy policy = evaluator.getPolicy();
+								RangerPolicy policy = evaluator.getPolicy();
 
-							ret.setGroupAccessInfo(groupName, accessInfo.getKey(), accessResult, policy);
+								ret.setGroupAccessInfo(groupName, accessInfo.getKey(), accessResult, policy);
+							}
 						}
-					}
 
-					for (Map.Entry<String, Map<String, PolicyACLSummary.AccessResult>> roleAccessInfo : aclSummary.getRolesAccessInfo().entrySet()) {
-						final String roleName = roleAccessInfo.getKey();
+						for (Map.Entry<String, Map<String, PolicyACLSummary.AccessResult>> roleAccessInfo : aclSummary.getRolesAccessInfo().entrySet()) {
+							final String roleName = roleAccessInfo.getKey();
 
-						for (Map.Entry<String, PolicyACLSummary.AccessResult> accessInfo : roleAccessInfo.getValue().entrySet()) {
-							if (isConditional) {
-								accessResult = ACCESS_CONDITIONAL;
-							} else {
-								accessResult = accessInfo.getValue().getResult();
+							for (Map.Entry<String, PolicyACLSummary.AccessResult> accessInfo : roleAccessInfo.getValue().entrySet()) {
+								if (isConditional) {
+									accessResult = ACCESS_CONDITIONAL;
+								} else {
+									accessResult = accessInfo.getValue().getResult();
 
-								if (accessResult.equals(RangerPolicyEvaluator.ACCESS_UNDETERMINED)) {
-									accessResult = RangerPolicyEvaluator.ACCESS_DENIED;
+									if (accessResult.equals(RangerPolicyEvaluator.ACCESS_UNDETERMINED)) {
+										accessResult = RangerPolicyEvaluator.ACCESS_DENIED;
+									}
 								}
-							}
 
-							RangerPolicy policy = evaluator.getPolicy();
+								RangerPolicy policy = evaluator.getPolicy();
 
-							ret.setRoleAccessInfo(roleName, accessInfo.getKey(), accessResult, policy);
+								ret.setRoleAccessInfo(roleName, accessInfo.getKey(), accessResult, policy);
+							}
 						}
 					}
 				}
-			}
 
-			ret.finalizeAcls();
+				ret.finalizeAcls();
+			}
 		}
 
 		RangerPerfTracer.logAlways(perf);
@@ -338,22 +389,56 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
 
 	@Override
 	public void setUseForwardedIPAddress(boolean useForwardedIPAddress) {
-		policyEngine.setUseForwardedIPAddress(useForwardedIPAddress);
+		try (RangerReadWriteLock.RangerLock writeLock = policyEngine.getWriteLock()) {
+			if (LOG.isDebugEnabled()) {
+				if (writeLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + writeLock);
+				}
+			}
+			policyEngine.setUseForwardedIPAddress(useForwardedIPAddress);
+		}
 	}
 
 	@Override
 	public void setTrustedProxyAddresses(String[] trustedProxyAddresses) {
-		policyEngine.setTrustedProxyAddresses(trustedProxyAddresses);
+		try (RangerReadWriteLock.RangerLock writeLock = policyEngine.getWriteLock()) {
+			if (LOG.isDebugEnabled()) {
+				if (writeLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + writeLock);
+				}
+			}
+			policyEngine.setTrustedProxyAddresses(trustedProxyAddresses);
+		}
 	}
 
 	@Override
 	public RangerServiceDef getServiceDef() {
-		return policyEngine.getServiceDef();
+		final RangerServiceDef ret;
+
+		try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+			if (LOG.isDebugEnabled()) {
+				if (readLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + readLock);
+				}
+			}
+			ret = policyEngine.getServiceDef();
+		}
+		return ret;
 	}
 
 	@Override
 	public long getPolicyVersion() {
-		return policyEngine.getPolicyVersion();
+		long ret;
+
+		try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+			if (LOG.isDebugEnabled()) {
+				if (readLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + readLock);
+				}
+			}
+			ret = policyEngine.getPolicyVersion();
+		}
+		return ret;
 	}
 
 	@Override
@@ -361,12 +446,29 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
 
 	@Override
 	public void setRoles(RangerRoles roles) {
-		policyEngine.setRoles(roles);
+		try (RangerReadWriteLock.RangerLock writeLock = policyEngine.getWriteLock()) {
+			if (LOG.isDebugEnabled()) {
+				if (writeLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + writeLock);
+				}
+			}
+			policyEngine.setRoles(roles);
+		}
+
 	}
 
 	@Override
 	public Set<String> getRolesFromUserAndGroups(String user, Set<String> groups) {
-		return policyEngine.getPluginContext().getAuthContext().getRolesForUserAndGroups(user, groups);
+		Set<String> ret;
+		try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+			if (LOG.isDebugEnabled()) {
+				if (readLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + readLock);
+				}
+			}
+			ret = policyEngine.getPluginContext().getAuthContext().getRolesForUserAndGroups(user, groups);
+		}
+		return ret;
 	}
 
 	@Override
@@ -375,7 +477,16 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
 			LOG.debug("==> RangerPolicyEngineImpl.getUniquelyMatchedZoneName(" + grantRevokeRequest + ")");
 		}
 
-		String ret = policyEngine.getUniquelyMatchedZoneName(grantRevokeRequest.getResource());
+		String ret;
+
+		try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+			if (LOG.isDebugEnabled()) {
+				if (readLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + readLock);
+				}
+			}
+			ret = policyEngine.getUniquelyMatchedZoneName(grantRevokeRequest.getResource());
+		}
 
 		if (LOG.isDebugEnabled()) {
 			LOG.debug("<== RangerPolicyEngineImpl.getUniquelyMatchedZoneName(" + grantRevokeRequest + ") : " + ret);
@@ -386,21 +497,53 @@ public class RangerPolicyEngineImpl implements RangerPolicyEngine {
 
 	@Override
 	public List<RangerPolicy> getResourcePolicies(String zoneName) {
-		return policyEngine.getResourcePolicies(zoneName);
+		List<RangerPolicy> ret;
+
+		try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+			if (LOG.isDebugEnabled()) {
+				if (readLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + readLock);
+				}
+			}
+			List<RangerPolicy> oldPolicies = policyEngine.getResourcePolicies(zoneName);
+			ret = CollectionUtils.isNotEmpty(oldPolicies) ? new ArrayList<>(oldPolicies) : oldPolicies;
+		}
+
+		return ret;
 	}
 
 	@Override
 	public List<RangerPolicy> getResourcePolicies() {
-		RangerPolicyRepository policyRepository = policyEngine.getPolicyRepository();
+		List<RangerPolicy> ret;
 
-		return policyRepository == null ? ListUtils.EMPTY_LIST : policyRepository.getPolicies();
+		try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+			if (LOG.isDebugEnabled()) {
+				if (readLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + readLock);
+				}
+			}
+			RangerPolicyRepository policyRepository = policyEngine.getPolicyRepository();
+			List<RangerPolicy> oldPolicies = policyRepository == null ? ListUtils.EMPTY_LIST : policyRepository.getPolicies();
+			ret = CollectionUtils.isNotEmpty(oldPolicies) ? new ArrayList<>(oldPolicies) : oldPolicies;
+		}
+		return ret;
 	}
 
 	@Override
 	public List<RangerPolicy> getTagPolicies() {
-		RangerPolicyRepository tagPolicyRepository = policyEngine.getTagPolicyRepository();
+		List<RangerPolicy> ret;
 
-		return tagPolicyRepository == null ? ListUtils.EMPTY_LIST : tagPolicyRepository.getPolicies();
+		try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+			if (LOG.isDebugEnabled()) {
+				if (readLock.isLockingEnabled()) {
+					LOG.debug("Acquired lock - " + readLock);
+				}
+			}
+			RangerPolicyRepository tagPolicyRepository = policyEngine.getTagPolicyRepository();
+			List<RangerPolicy> oldPolicies = tagPolicyRepository == null ? ListUtils.EMPTY_LIST : tagPolicyRepository.getPolicies();
+			ret = CollectionUtils.isNotEmpty(oldPolicies) ? new ArrayList<>(oldPolicies) : oldPolicies;
+		}
+		return ret;
 	}
 
 	// This API is used only used by test code
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
index b2f3438..4fb0b08 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerPolicyRepository.java
@@ -73,9 +73,9 @@ public class RangerPolicyRepository {
     private final RangerPolicyEngineOptions         options;
     private final RangerPluginContext               pluginContext;
     private final RangerServiceDef                  serviceDef;
-    private final List<RangerPolicy>                policies;
+    private /*final*/ List<RangerPolicy>                policies;
     private final long                              policyVersion;
-    private final List<RangerContextEnricher>       contextEnrichers;
+    private /*final*/ List<RangerContextEnricher>       contextEnrichers;
     private final AuditModeEnum                     auditModeEnum;
     private final Map<String, AuditInfo>            accessAuditCache;
     private final String                            componentServiceName;
@@ -157,111 +157,12 @@ public class RangerPolicyRepository {
             this.accessAuditCache = null;
         }
 
-        boolean[] flags = new boolean[RangerPolicy.POLICY_TYPES.length];
-
-        for (RangerPolicyDelta delta : deltas) {
-            final Integer changeType  = delta.getChangeType();
-            final String  serviceType = delta.getServiceType();
-            final Long    policyId    = delta.getPolicyId();
-            final Integer policyType  = delta.getPolicyType();
-
-            if (!serviceType.equals(this.serviceDef.getName())) {
-                continue;
-            }
-
-            RangerPolicyEvaluator evaluator = null;
-
-            switch (changeType) {
-                case RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE:
-                    if (delta.getPolicy() == null) {
-                        if (LOG.isDebugEnabled()) {
-                            LOG.debug("Could not find policy for policy-id:[" + policyId + "]");
-                        }
-
-                        continue;
-                    }
-                    break;
-
-                case RangerPolicyDelta.CHANGE_TYPE_POLICY_UPDATE:
-                    evaluator = getPolicyEvaluator(policyId);
-
-                    if (evaluator == null) {
-                        if (LOG.isDebugEnabled()) {
-                            LOG.debug("Could not find evaluator for policy-id:[" + policyId + "]");
-                        }
-                    }
-                    break;
-
-                case RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE:
-                    evaluator = getPolicyEvaluator(policyId);
-                    if (evaluator == null) {
-                        if (LOG.isDebugEnabled()) {
-                            LOG.debug("Could not find evaluator for policy-id:[" + policyId + "]");
-                        }
-                    }
-                    break;
-
-                default:
-                    LOG.error("Unknown changeType:[" + changeType + "], Ignoring");
-                    break;
-            }
-
-            evaluator = update(delta, evaluator);
-
-            if (evaluator != null) {
-                switch (changeType) {
-                    case RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE:
-                        policyEvaluatorsMap.put(policyId, evaluator);
-                        break;
-
-                    case RangerPolicyDelta.CHANGE_TYPE_POLICY_UPDATE:
-                        policyEvaluatorsMap.put(policyId, evaluator);
-                        break;
-
-                    case RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE:
-                        policyEvaluatorsMap.remove(policyId);
-                        break;
-
-                    default:
-                        break;
-                }
-
-                flags[policyType] = true;
-            }
-        }
-
-        for (int policyType = 0; policyType < flags.length; policyType++) {
-            if (flags[policyType]) {
-                Map<String, RangerResourceTrie> trie = getTrie(policyType);
-
-                if (trie != null) {
-                    for (Map.Entry<String, RangerResourceTrie> entry : trie.entrySet()) {
-                        entry.getValue().wrapUpUpdate();
-                    }
-                }
-            }
-        }
+        final boolean isExistingPolicies = CollectionUtils.isNotEmpty(this.policies);
 
-        if (auditFilterResourceTrie != null) {
-            for (Map.Entry<String, RangerResourceTrie> entry : auditFilterResourceTrie.entrySet()) {
-                entry.getValue().wrapUpUpdate();
-            }
-        }
+        List<RangerContextEnricher> newContextEnrichers = updateResourceTrie(deltas, policyVersion);
 
-        if (StringUtils.isEmpty(zoneName)) {
-            if (CollectionUtils.isNotEmpty(other.getPolicies())) {
-                if (CollectionUtils.isNotEmpty(this.getPolicies())) {
-                    this.contextEnrichers = shareWith(other);
-                } else {
-                    this.contextEnrichers = null;
-                }
-            } else {
-                if (CollectionUtils.isNotEmpty(this.policies)) {
-                    this.contextEnrichers = Collections.unmodifiableList(buildContextEnrichers(options));
-                } else {
-                    this.contextEnrichers = null;
-                }
-            }
+        if (newContextEnrichers != null && CollectionUtils.isNotEmpty(this.policies)) {
+            this.contextEnrichers = isExistingPolicies ? shareWith(other) : buildContextEnrichers(options);
         } else {
             this.contextEnrichers = null;
         }
@@ -288,9 +189,9 @@ public class RangerPolicyRepository {
         this.pluginContext        = pluginContext;
 
         if (StringUtils.isEmpty(zoneName)) {
-            this.policies = Collections.unmodifiableList(servicePolicies.getPolicies());
+            this.policies = servicePolicies.getPolicies();
         } else {
-            this.policies = Collections.unmodifiableList(servicePolicies.getSecurityZones().get(zoneName).getPolicies());
+            this.policies = servicePolicies.getSecurityZones().get(zoneName).getPolicies();
         }
         this.policyVersion = servicePolicies.getPolicyVersion() != null ? servicePolicies.getPolicyVersion() : -1;
 
@@ -326,7 +227,7 @@ public class RangerPolicyRepository {
         init(options);
 
         if (StringUtils.isEmpty(zoneName)) {
-            this.contextEnrichers = Collections.unmodifiableList(buildContextEnrichers(options));
+            this.contextEnrichers = buildContextEnrichers(options);
             this.auditPolicyEvaluators = buildAuditPolicyEvaluators(servicePolicies.getServiceConfig());
         } else {
             this.contextEnrichers = null;
@@ -358,7 +259,7 @@ public class RangerPolicyRepository {
         this.appId                = pluginContext.getConfig().getAppId();
         this.options              = new RangerPolicyEngineOptions(pluginContext.getConfig().getPolicyEngineOptions());
         this.pluginContext        = pluginContext;
-        this.policies             = Collections.unmodifiableList(normalizeAndPrunePolicies(tagPolicies.getPolicies(), componentServiceDef.getName()));
+        this.policies             = normalizeAndPrunePolicies(tagPolicies.getPolicies(), componentServiceDef.getName());
         this.policyVersion        = tagPolicies.getPolicyVersion() != null ? tagPolicies.getPolicyVersion() : -1;
 
         String auditMode = tagPolicies.getAuditMode();
@@ -380,7 +281,7 @@ public class RangerPolicyRepository {
         init(options);
 
         if (StringUtils.isEmpty(zoneName)) {
-            this.contextEnrichers = Collections.unmodifiableList(buildContextEnrichers(options));
+            this.contextEnrichers = buildContextEnrichers(options);
             this.auditPolicyEvaluators = buildAuditPolicyEvaluators(tagPolicies.getServiceConfig());
         } else {
             this.contextEnrichers = null;
@@ -892,7 +793,7 @@ public class RangerPolicyRepository {
             }
         }
 
-        return rangerPolicies;
+        return rangerPolicies == null ? new ArrayList<>() : rangerPolicies;
     }
 
     private boolean isPolicyNeedsPruning(RangerPolicy policy, final String componentType) {
@@ -1049,13 +950,13 @@ public class RangerPolicyRepository {
         }
         RangerPolicyEvaluator.PolicyEvalOrderComparator comparator = new RangerPolicyEvaluator.PolicyEvalOrderComparator();
         Collections.sort(policyEvaluators, comparator);
-        this.policyEvaluators = Collections.unmodifiableList(policyEvaluators);
+        this.policyEvaluators = policyEvaluators;
 
         Collections.sort(dataMaskPolicyEvaluators, comparator);
-        this.dataMaskPolicyEvaluators = Collections.unmodifiableList(dataMaskPolicyEvaluators);
+        this.dataMaskPolicyEvaluators = dataMaskPolicyEvaluators;
 
         Collections.sort(rowFilterPolicyEvaluators, comparator);
-        this.rowFilterPolicyEvaluators = Collections.unmodifiableList(rowFilterPolicyEvaluators);
+        this.rowFilterPolicyEvaluators = rowFilterPolicyEvaluators;
 
         this.policyEvaluatorsMap = createPolicyEvaluatorsMap();
 
@@ -1267,8 +1168,6 @@ public class RangerPolicyRepository {
         if (CollectionUtils.isNotEmpty(evaluators)) {
             ret = new ArrayList<>(evaluators);
             Collections.sort(ret, new RangerPolicyEvaluator.PolicyEvalOrderComparator());
-
-            ret = Collections.unmodifiableList(ret);
         }
 
         return ret;
@@ -1350,7 +1249,7 @@ public class RangerPolicyRepository {
             tmpPolicyEvaluatorMap.put(evaluator.getPolicy().getId(), evaluator);
         }
 
-        return  Collections.unmodifiableMap(tmpPolicyEvaluatorMap);
+        return  tmpPolicyEvaluatorMap;
     }
 
 
@@ -1530,4 +1429,134 @@ public class RangerPolicyRepository {
             return isAudited;
         }
     }
+
+    void reinit(List<RangerPolicyDelta> deltas, long policyVersion) {
+        final boolean isExistingPolicies = CollectionUtils.isNotEmpty(this.policies);
+
+        List<RangerContextEnricher> newContextEnrichers = updateResourceTrie(deltas, policyVersion);
+
+        if (newContextEnrichers != null && CollectionUtils.isNotEmpty(this.policies)) {
+            this.contextEnrichers = isExistingPolicies ? newContextEnrichers : buildContextEnrichers(options);
+        } else {
+            this.contextEnrichers = null;
+        }
+    }
+
+    private List<RangerContextEnricher> updateResourceTrie(List<RangerPolicyDelta> deltas, long policyVersion) {
+
+        final List<RangerContextEnricher> ret;
+
+        final boolean isExistingPolicies = CollectionUtils.isNotEmpty(this.policies);
+
+        boolean[] flags = new boolean[RangerPolicy.POLICY_TYPES.length];
+
+        for (RangerPolicyDelta delta : deltas) {
+            final Integer changeType  = delta.getChangeType();
+            final String  serviceType = delta.getServiceType();
+            final Long    policyId    = delta.getPolicyId();
+            final Integer policyType  = delta.getPolicyType();
+
+            if (!serviceType.equals(this.serviceDef.getName())) {
+                continue;
+            }
+
+            RangerPolicyEvaluator evaluator = null;
+
+            switch (changeType) {
+                case RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE:
+                    if (delta.getPolicy() == null) {
+                        if (LOG.isDebugEnabled()) {
+                            LOG.debug("Could not find policy for policy-id:[" + policyId + "]");
+                        }
+
+                        continue;
+                    }
+                    break;
+
+                case RangerPolicyDelta.CHANGE_TYPE_POLICY_UPDATE:
+                    evaluator = getPolicyEvaluator(policyId);
+
+                    if (evaluator == null) {
+                        if (LOG.isDebugEnabled()) {
+                            LOG.debug("Could not find evaluator for policy-id:[" + policyId + "]");
+                        }
+                    }
+                    break;
+
+                case RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE:
+                    evaluator = getPolicyEvaluator(policyId);
+                    if (evaluator == null) {
+                        if (LOG.isDebugEnabled()) {
+                            LOG.debug("Could not find evaluator for policy-id:[" + policyId + "]");
+                        }
+                    }
+                    break;
+
+                default:
+                    LOG.error("Unknown changeType:[" + changeType + "], Ignoring");
+                    break;
+            }
+
+            evaluator = update(delta, evaluator);
+
+            if (evaluator != null) {
+                switch (changeType) {
+                    case RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE:
+                        policyEvaluatorsMap.put(policyId, evaluator);
+                        break;
+
+                    case RangerPolicyDelta.CHANGE_TYPE_POLICY_UPDATE:
+                        policyEvaluatorsMap.put(policyId, evaluator);
+                        break;
+
+                    case RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE:
+                        policyEvaluatorsMap.remove(policyId);
+                        break;
+
+                    default:
+                        break;
+                }
+
+                flags[policyType] = true;
+            }
+        }
+
+        for (int policyType = 0; policyType < flags.length; policyType++) {
+            if (flags[policyType]) {
+                Map<String, RangerResourceTrie> trie = getTrie(policyType);
+
+                if (trie != null) {
+                    for (Map.Entry<String, RangerResourceTrie> entry : trie.entrySet()) {
+                        entry.getValue().wrapUpUpdate();
+                    }
+                }
+            }
+        }
+
+        if (auditFilterResourceTrie != null) {
+            for (Map.Entry<String, RangerResourceTrie> entry : auditFilterResourceTrie.entrySet()) {
+                entry.getValue().wrapUpUpdate();
+            }
+        }
+
+        if (StringUtils.isEmpty(zoneName)) {
+            if (isExistingPolicies) {
+                if (CollectionUtils.isNotEmpty(this.policies)) {
+                    ret = this.contextEnrichers; // Handled by caller
+                } else {
+                    ret = null;
+                }
+            } else {
+                if (CollectionUtils.isNotEmpty(this.policies)) {
+                    ret = new ArrayList<>(); // Handled by caller
+                } else {
+                    ret = null;
+                }
+            }
+        } else {
+            ret = null;
+        }
+
+        return ret;
+    }
 }
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/store/TagStore.java b/agents-common/src/main/java/org/apache/ranger/plugin/store/TagStore.java
index 795289b..f9f80c9 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/store/TagStore.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/store/TagStore.java
@@ -139,4 +139,6 @@ public interface TagStore {
 
     void deleteAllTagObjectsForService(String serviceName) throws Exception;
 
+    boolean isInPlaceTagUpdateSupported();
+
 }
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerCommonConstants.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerCommonConstants.java
index 5ecb280..e0c3f79 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerCommonConstants.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerCommonConstants.java
@@ -21,7 +21,25 @@ package org.apache.ranger.plugin.util;
 
 public class RangerCommonConstants {
 
-	public static final String PROP_COOKIE_NAME = "ranger.admin.cookie.name";
-	public static final String DEFAULT_COOKIE_NAME = "RANGERADMINSESSIONID";
+	public static final String PROP_COOKIE_NAME                             = "ranger.admin.cookie.name";
+	public static final String DEFAULT_COOKIE_NAME                          = "RANGERADMINSESSIONID";
+	public static final String PLUGIN_CONFIG_SUFFIX_POLICY_DELTA            = ".policy.rest.supports.policy.deltas";
+	public static final String PLUGIN_CONFIG_SUFFIX_TAG_DELTA               = ".tag.rest.supports.policy.deltas";
+	public static final String PLUGIN_CONFIG_SUFFIX_IN_PLACE_POLICY_UPDATES = ".supports.in.place.policy.updates";
+	public static final String PLUGIN_CONFIG_SUFFIX_IN_PLACE_TAG_UPDATES    = ".supports.in.place.tag.updates";
+	public static final String RANGER_ADMIN_SUFFIX_POLICY_DELTA             = ".supports.policy.deltas";
+	public static final String RANGER_ADMIN_SUFFIX_TAG_DELTA                = ".supports.tag.deltas";
+	public static final String RANGER_ADMIN_SUFFIX_IN_PLACE_POLICY_UPDATES  = ".supports.in.place.policy.updates";
+	public static final String RANGER_ADMIN_SUFFIX_IN_PLACE_TAG_UPDATES     = ".supports.in.place.tag.updates";
 
-}
\ No newline at end of file
+	public static final boolean PLUGIN_CONFIG_SUFFIX_POLICY_DELTA_DEFAULT            = false;
+	public static final boolean PLUGIN_CONFIG_SUFFIX_TAG_DELTA_DEFAULT               = false;
+	public static final boolean PLUGIN_CONFIG_SUFFIX_IN_PLACE_POLICY_UPDATES_DEFAULT = false;
+	public static final boolean PLUGIN_CONFIG_SUFFIX_IN_PLACE_TAG_UPDATES_DEFAULT    = false;
+	public static final boolean RANGER_ADMIN_SUFFIX_POLICY_DELTA_DEFAULT             = false;
+	public static final boolean RANGER_ADMIN_SUFFIX_TAG_DELTA_DEFAULT                = false;
+	public static final boolean RANGER_ADMIN_SUFFIX_IN_PLACE_POLICY_UPDATES_DEFAULT  = false;
+	public static final boolean RANGER_ADMIN_SUFFIX_IN_PLACE_TAG_UPDATES_DEFAULT     = false;
+
+
+}
diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerReadWriteLock.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerReadWriteLock.java
new file mode 100644
index 0000000..7f17a52
--- /dev/null
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerReadWriteLock.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.plugin.util;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+public class RangerReadWriteLock {
+
+    private static final RangerLock NO_OP_LOCK = new RangerLock(null);
+
+    private final ReentrantReadWriteLock lock;
+
+    public RangerReadWriteLock(boolean isUseLock) {
+        lock = isUseLock ? new ReentrantReadWriteLock(true) : null;
+    }
+
+    public RangerLock getReadLock() {
+        final RangerLock ret;
+        if (lock != null) {
+            ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
+            readLock.lock();
+            ret = new RangerLock(readLock);
+        } else {
+            ret = NO_OP_LOCK;
+        }
+        return ret;
+    }
+
+    public RangerLock getWriteLock() {
+        final RangerLock ret;
+        if (lock != null) {
+            boolean isLocked = false;
+            ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
+            while (!isLocked) {
+                isLocked = writeLock.tryLock();
+                // Another thread has acquired write lock. Hint to scheduler to schedule some other thread if needed
+                if (!isLocked && lock.getReadLockCount() == 0) {
+                    Thread.yield();
+                }
+            }
+            ret = new RangerLock(writeLock);
+        } else {
+            ret = NO_OP_LOCK;
+        }
+        return ret;
+    }
+
+    @Override
+    public String toString() {
+        if (lock != null) {
+            return "ReadWriteLock:[" + lock.toString() + "], ReadLock:[" + lock.readLock().toString() + "], WriteLock:[" + lock.writeLock().toString() + "]";
+        } else {
+            return "ReadWriteLock:[null]";
+        }
+    }
+
+    static final public class RangerLock implements AutoCloseable {
+        private final Lock lock;
+
+        private RangerLock(Lock lock) {
+            this.lock = lock;
+        }
+
+        @Override
+        public void close() {
+            if (lock != null) {
+                lock.unlock();
+            }
+        }
+
+        public boolean isLockingEnabled() {
+            return lock != null;
+        }
+
+        @Override
+        public String toString() {
+            return lock == null ? "null" : lock.toString();
+        }
+    }
+}
diff --git a/knox-agent/src/main/java/org/apache/ranger/admin/client/RangerAdminJersey2RESTClient.java b/knox-agent/src/main/java/org/apache/ranger/admin/client/RangerAdminJersey2RESTClient.java
index 1beef86..fa17f5d 100644
--- a/knox-agent/src/main/java/org/apache/ranger/admin/client/RangerAdminJersey2RESTClient.java
+++ b/knox-agent/src/main/java/org/apache/ranger/admin/client/RangerAdminJersey2RESTClient.java
@@ -71,8 +71,8 @@ public class RangerAdminJersey2RESTClient extends AbstractRangerAdminClient {
 	String _sslConfigFileName = null;
 	String _serviceName = null;
 	String _clusterName = null;
-	String _supportsPolicyDeltas = null;
-	String _supportsTagDeltas = null;
+	boolean _supportsPolicyDeltas = false;
+	boolean _supportsTagDeltas = false;
 	String _pluginId = null;
 	int	   _restClientConnTimeOutMs;
 	int	   _restClientReadTimeOutMs;
@@ -99,14 +99,8 @@ public class RangerAdminJersey2RESTClient extends AbstractRangerAdminClient {
 		if(StringUtil.isEmpty(_clusterName)){
 			_clusterName =config.get(configPropertyPrefix + ".ambari.cluster.name", "");
 		}
-		_supportsPolicyDeltas = config.get(configPropertyPrefix + ".policy.rest.supports.policy.deltas", "false");
-		if (!"true".equalsIgnoreCase(_supportsPolicyDeltas)) {
-			_supportsPolicyDeltas = "false";
-		}
-		_supportsTagDeltas = config.get(configPropertyPrefix + ".tag.rest.supports.tag.deltas", "false");
-		if (!"true".equalsIgnoreCase(_supportsTagDeltas)) {
-			_supportsTagDeltas = "false";
-		}
+		_supportsPolicyDeltas = config.getBoolean(configPropertyPrefix + RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_POLICY_DELTA, RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_POLICY_DELTA_DEFAULT);
+		_supportsTagDeltas = config.getBoolean(configPropertyPrefix + RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_TAG_DELTA, RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_TAG_DELTA_DEFAULT);
 
 		configURLs = StringUtil.getURLs(tmpUrl);
 		this.lastKnownActiveUrlIndex = new Random().nextInt(configURLs.size());
@@ -141,7 +135,7 @@ public class RangerAdminJersey2RESTClient extends AbstractRangerAdminClient {
 		queryParams.put(RangerRESTUtils.REST_PARAM_LAST_ACTIVATION_TIME, Long.toString(lastActivationTimeInMillis));
 		queryParams.put(RangerRESTUtils.REST_PARAM_PLUGIN_ID, _pluginId);
 		queryParams.put(RangerRESTUtils.REST_PARAM_CLUSTER_NAME, _clusterName);
-		queryParams.put(RangerRESTUtils.REST_PARAM_SUPPORTS_POLICY_DELTAS, _supportsPolicyDeltas);
+		queryParams.put(RangerRESTUtils.REST_PARAM_SUPPORTS_POLICY_DELTAS, Boolean.toString(_supportsPolicyDeltas));
 		queryParams.put(RangerRESTUtils.REST_PARAM_CAPABILITIES, pluginCapabilities);
 
 		if (isSecureMode) {
@@ -383,7 +377,7 @@ public class RangerAdminJersey2RESTClient extends AbstractRangerAdminClient {
 		queryParams.put(RangerRESTUtils.REST_PARAM_LAST_KNOWN_POLICY_VERSION, Long.toString(lastKnownVersion));
 		queryParams.put(RangerRESTUtils.REST_PARAM_LAST_ACTIVATION_TIME, Long.toString(lastActivationTimeInMillis));
 		queryParams.put(RangerRESTUtils.REST_PARAM_PLUGIN_ID, _pluginId);
-		queryParams.put(RangerRESTUtils.REST_PARAM_SUPPORTS_TAG_DELTAS, _supportsTagDeltas);
+		queryParams.put(RangerRESTUtils.REST_PARAM_SUPPORTS_TAG_DELTAS, Boolean.toString(_supportsTagDeltas));
 		queryParams.put(RangerRESTUtils.REST_PARAM_CAPABILITIES, pluginCapabilities);
 
 		String relativeURL = null;
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminCache.java b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminCache.java
index 089bf43..fd5b147 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminCache.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminCache.java
@@ -158,11 +158,11 @@ public class RangerPolicyAdminCache {
 					oldPolicyAdmin.releaseResources(!isPolicyEngineShared);
 				}
 			} else {
-				LOG.warn("Could not build new policy-engine. Continuing with the old policy-engine, if any");
+				LOG.warn("Could not build new policy-engine.");
 			}
 		}
 
-		return ret != null ? ret : oldPolicyAdmin;
+		return ret;
 	}
 
 	private RangerPolicyAdmin addPolicyAdmin(ServicePolicies policies, RangerRoles roles, RangerPolicyEngineOptions options) {
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminImpl.java b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminImpl.java
index 66835bd..2eef20b 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminImpl.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/RangerPolicyAdminImpl.java
@@ -45,6 +45,7 @@ import org.apache.ranger.plugin.service.RangerDefaultRequestProcessor;
 import org.apache.ranger.plugin.util.GrantRevokeRequest;
 import org.apache.ranger.plugin.util.RangerAccessRequestUtil;
 import org.apache.ranger.plugin.util.RangerPerfTracer;
+import org.apache.ranger.plugin.util.RangerReadWriteLock;
 import org.apache.ranger.plugin.util.RangerRoles;
 import org.apache.ranger.plugin.util.ServiceDefUtil;
 import org.apache.ranger.plugin.util.ServicePolicies;
@@ -81,7 +82,11 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin {
             PolicyEngine policyEngine = other.policyEngine.cloneWithDelta(servicePolicies);
 
             if (policyEngine != null) {
-                ret = new RangerPolicyAdminImpl(policyEngine);
+                if (policyEngine == other.policyEngine) {
+                    ret = other;
+                } else {
+                    ret = new RangerPolicyAdminImpl(policyEngine);
+                }
             }
         }
 
@@ -89,7 +94,7 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin {
     }
 
     RangerPolicyAdminImpl(ServicePolicies servicePolicies, RangerPluginContext pluginContext, RangerRoles roles) {
-        this.policyEngine     = new PolicyEngine(servicePolicies, pluginContext, roles);
+        this.policyEngine     = new PolicyEngine(servicePolicies, pluginContext, roles, ServiceDBStore.SUPPORTS_IN_PLACE_POLICY_UPDATES);
         this.requestProcessor = new RangerDefaultRequestProcessor(policyEngine);
     }
 
@@ -111,32 +116,41 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin {
             perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_REQUEST_LOG, "RangerPolicyAdminImpl.isDelegatedAdminAccessAllowed(user=" + user + ",accessTypes=" + accessTypes + "resource=" + resource.getAsString() + ")");
         }
 
-        final RangerPolicyRepository matchedRepository = policyEngine.getRepositoryForZone(zoneName);
+        try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
 
-        if (matchedRepository != null) {
-            Set<String> roles = getRolesFromUserAndGroups(user, userGroups);
-            Set<String> requestedAccesses = new HashSet<>(accessTypes);
+            if (LOG.isDebugEnabled()) {
+                if (readLock.isLockingEnabled()) {
+                    LOG.debug("Acquired lock - " + readLock);
+                }
+            }
+
+            final RangerPolicyRepository matchedRepository = policyEngine.getRepositoryForZone(zoneName);
+
+            if (matchedRepository != null) {
+                Set<String> roles = getRolesFromUserAndGroups(user, userGroups);
+                Set<String> requestedAccesses = new HashSet<>(accessTypes);
 
-            RangerAccessRequestImpl request = new RangerAccessRequestImpl();
-            request.setResource(resource);
+                RangerAccessRequestImpl request = new RangerAccessRequestImpl();
+                request.setResource(resource);
 
-            for (RangerPolicyEvaluator evaluator : matchedRepository.getLikelyMatchPolicyEvaluators(request, RangerPolicy.POLICY_TYPE_ACCESS)) {
+                for (RangerPolicyEvaluator evaluator : matchedRepository.getLikelyMatchPolicyEvaluators(request, RangerPolicy.POLICY_TYPE_ACCESS)) {
 
-                Set<String> allowedAccesses = evaluator.getAllowedAccesses(resource, user, userGroups, roles, requestedAccesses);
-                if (CollectionUtils.isNotEmpty(allowedAccesses)) {
-                    requestedAccesses.removeAll(allowedAccesses);
-                    if (CollectionUtils.isEmpty(requestedAccesses)) {
-                        if (LOG.isDebugEnabled()) {
-                            LOG.debug("Access granted by policy:[" + evaluator.getPolicy() + "]");
+                    Set<String> allowedAccesses = evaluator.getAllowedAccesses(resource, user, userGroups, roles, requestedAccesses);
+                    if (CollectionUtils.isNotEmpty(allowedAccesses)) {
+                        requestedAccesses.removeAll(allowedAccesses);
+                        if (CollectionUtils.isEmpty(requestedAccesses)) {
+                            if (LOG.isDebugEnabled()) {
+                                LOG.debug("Access granted by policy:[" + evaluator.getPolicy() + "]");
+                            }
+                            ret = true;
+                            break;
                         }
-                        ret = true;
-                        break;
                     }
                 }
+
             }
 
         }
-
         RangerPerfTracer.log(perf);
 
         if (LOG.isDebugEnabled()) {
@@ -159,36 +173,46 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin {
             perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_REQUEST_LOG, "RangerPolicyEngine.isDelegatedAdminAccessAllowed(user=" + user + "," + userGroups + ", roles=" + roles + ")");
         }
 
-        final RangerPolicyRepository matchedRepository = policyEngine.getRepositoryForMatchedZone(policy);
-
-        if (matchedRepository != null) {
-            // RANGER-3082
-            // Convert policy resources to by substituting macros with ASTERISK
-            Map<String, RangerPolicyResource> modifiedPolicyResources = getPolicyResourcesWithMacrosReplaced(policy.getResources(), wildcardEvalContext);
-            Set<String> accessTypes = getAllAccessTypes(policy, getServiceDef());
+        try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
 
             if (LOG.isDebugEnabled()) {
-                LOG.debug("Checking admin-access for the access-types:[" + accessTypes + "]");
+                if (readLock.isLockingEnabled()) {
+                    LOG.debug("Acquired lock - " + readLock);
+                }
             }
 
-            if (CollectionUtils.isEmpty(accessTypes)) {
-                LOG.info("access-types to check for admin-access are empty!! Allowing admin access!!");
-                ret = true;
-            } else {
-                for (RangerPolicyEvaluator evaluator : matchedRepository.getPolicyEvaluators()) {
-                    Set<String> allowedAccesses = evaluator.getAllowedAccesses(modifiedPolicyResources, user, userGroups, roles, accessTypes, evalContext);
-                    if (CollectionUtils.isNotEmpty(allowedAccesses)) {
-                        accessTypes.removeAll(allowedAccesses);
-                        if (CollectionUtils.isEmpty(accessTypes)) {
-                            ret = true;
-                            break;
+            final RangerPolicyRepository matchedRepository = policyEngine.getRepositoryForMatchedZone(policy);
+
+            if (matchedRepository != null) {
+                // RANGER-3082
+                // Convert policy resources to by substituting macros with ASTERISK
+                Map<String, RangerPolicyResource> modifiedPolicyResources = getPolicyResourcesWithMacrosReplaced(policy.getResources(), wildcardEvalContext);
+                Set<String> accessTypes = getAllAccessTypes(policy, getServiceDef());
+
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Checking admin-access for the access-types:[" + accessTypes + "]");
+                }
+
+                if (CollectionUtils.isEmpty(accessTypes)) {
+                    LOG.info("access-types to check for admin-access are empty!! Allowing admin access!!");
+                    ret = true;
+                } else {
+                    for (RangerPolicyEvaluator evaluator : matchedRepository.getPolicyEvaluators()) {
+                        Set<String> allowedAccesses = evaluator.getAllowedAccesses(modifiedPolicyResources, user, userGroups, roles, accessTypes, evalContext);
+                        if (CollectionUtils.isNotEmpty(allowedAccesses)) {
+                            accessTypes.removeAll(allowedAccesses);
+                            if (CollectionUtils.isEmpty(accessTypes)) {
+                                ret = true;
+                                break;
+                            }
                         }
                     }
-                }
-                if (CollectionUtils.isNotEmpty(accessTypes)) {
-                    LOG.info("Accesses : " + accessTypes + " are not authorized for the policy:[" + policy.getId() + "] by any of delegated-admin policies");
+                    if (CollectionUtils.isNotEmpty(accessTypes)) {
+                        LOG.info("Accesses : " + accessTypes + " are not authorized for the policy:[" + policy.getId() + "] by any of delegated-admin policies");
+                    }
                 }
             }
+
         }
 
         RangerPerfTracer.log(perf);
@@ -208,18 +232,27 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin {
 
         List<RangerPolicy>     ret              = null;
 
-        RangerPolicyRepository policyRepository = policyEngine.getRepositoryForZone(zoneName);
+        try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+            if (LOG.isDebugEnabled()) {
+                if (readLock.isLockingEnabled()) {
+                    LOG.debug("Acquired lock - " + readLock);
+                }
+            }
 
-        if (policyRepository != null) {
-            for (RangerPolicyEvaluator evaluator : policyRepository.getPolicyEvaluators()) {
-                if (evaluator.isCompleteMatch(resource, evalContext)) {
-                    if (ret == null) {
-                        ret = new ArrayList<>();
-                    }
+            RangerPolicyRepository policyRepository = policyEngine.getRepositoryForZone(zoneName);
 
-                    ret.add(evaluator.getPolicy());
+            if (policyRepository != null) {
+                for (RangerPolicyEvaluator evaluator : policyRepository.getPolicyEvaluators()) {
+                    if (evaluator.isCompleteMatch(resource, evalContext)) {
+                        if (ret == null) {
+                            ret = new ArrayList<>();
+                        }
+
+                        ret.add(evaluator.getPolicy());
+                    }
                 }
             }
+
         }
 
         if (LOG.isDebugEnabled()) {
@@ -236,20 +269,31 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin {
         }
 
         List<RangerPolicy>     ret              = null;
-        RangerPolicyRepository policyRepository = policyEngine.getRepositoryForMatchedZone(policy);
 
-        if (policyRepository != null) {
-            Map<String, RangerPolicyResource> resources = policy.getResources();
+        try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
 
-            for (RangerPolicyEvaluator evaluator : policyRepository.getPolicyEvaluators()) {
-                if (evaluator.isCompleteMatch(resources, evalContext)) {
-                    if (ret == null) {
-                        ret = new ArrayList<>();
-                    }
+            if (LOG.isDebugEnabled()) {
+                if (readLock.isLockingEnabled()) {
+                    LOG.debug("Acquired lock - " + readLock);
+                }
+            }
+
+            RangerPolicyRepository policyRepository = policyEngine.getRepositoryForMatchedZone(policy);
+
+            if (policyRepository != null) {
+                Map<String, RangerPolicyResource> resources = policy.getResources();
 
-                    ret.add(evaluator.getPolicy());
+                for (RangerPolicyEvaluator evaluator : policyRepository.getPolicyEvaluators()) {
+                    if (evaluator.isCompleteMatch(resources, evalContext)) {
+                        if (ret == null) {
+                            ret = new ArrayList<>();
+                        }
+
+                        ret.add(evaluator.getPolicy());
+                    }
                 }
             }
+
         }
 
         if (LOG.isDebugEnabled()) {
@@ -264,8 +308,16 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin {
         if (LOG.isDebugEnabled()) {
             LOG.debug("==> RangerPolicyAdminImpl.getMatchingPolicies(" + resource + ")");
         }
+        List<RangerPolicy> ret;
 
-        List<RangerPolicy> ret = getMatchingPolicies(resource, RangerPolicyEngine.ANY_ACCESS);
+        try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+            if (LOG.isDebugEnabled()) {
+                if (readLock.isLockingEnabled()) {
+                    LOG.debug("Acquired lock - " + readLock);
+                }
+            }
+            ret = getMatchingPolicies(resource, RangerPolicyEngine.ANY_ACCESS);
+        }
 
         if (LOG.isDebugEnabled()) {
             LOG.debug("<== RangerPolicyAdminImpl.getMatchingPolicies(" + resource + ") : " + ret.size());
@@ -275,27 +327,87 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin {
     }
 
     @Override
-    public long getPolicyVersion() { return policyEngine.getPolicyVersion(); }
+    public long getPolicyVersion() {
+        long ret;
+
+        try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+            if (LOG.isDebugEnabled()) {
+                if (readLock.isLockingEnabled()) {
+                    LOG.debug("Acquired lock - " + readLock);
+                }
+            }
+            ret = policyEngine.getPolicyVersion();
+        }
+        return ret;
+    }
 
     @Override
-    public long getRoleVersion() { return policyEngine.getRoleVersion(); }
+    public long getRoleVersion() {
+        long ret;
+        try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+            if (LOG.isDebugEnabled()) {
+                if (readLock.isLockingEnabled()) {
+                    LOG.debug("Acquired lock - " + readLock);
+                }
+            }
+            ret = policyEngine.getRoleVersion();
+        }
+        return ret;
+    }
 
     @Override
-    public String getServiceName() { return policyEngine.getServiceName(); }
+    public String getServiceName() {
+        String ret;
+
+        try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+            if (LOG.isDebugEnabled()) {
+                if (readLock.isLockingEnabled()) {
+                    LOG.debug("Acquired lock - " + readLock);
+                }
+            }
+            ret = policyEngine.getServiceName();
+        }
+        return ret;
+    }
 
 
     @Override
     public RangerServiceDef getServiceDef() {
-        return policyEngine.getServiceDef();
+        RangerServiceDef ret;
+        try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+            if (LOG.isDebugEnabled()) {
+                if (readLock.isLockingEnabled()) {
+                    LOG.debug("Acquired lock - " + readLock);
+                }
+            }
+            ret = policyEngine.getServiceDef();
+        }
+        return ret;
     }
     @Override
     public void setRoles(RangerRoles roles) {
-        policyEngine.setRoles(roles);
+        try (RangerReadWriteLock.RangerLock writeLock = policyEngine.getWriteLock()) {
+            if (LOG.isDebugEnabled()) {
+                if (writeLock.isLockingEnabled()) {
+                    LOG.debug("Acquired lock - " + writeLock);
+                }
+            }
+            policyEngine.setRoles(roles);
+        }
     }
 
     @Override
     public Set<String> getRolesFromUserAndGroups(String user, Set<String> groups) {
-        return policyEngine.getPluginContext().getAuthContext().getRolesForUserAndGroups(user, groups);
+        Set<String> ret;
+        try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+            if (LOG.isDebugEnabled()) {
+                if (readLock.isLockingEnabled()) {
+                    LOG.debug("Acquired lock - " + readLock);
+                }
+            }
+            ret = policyEngine.getPluginContext().getAuthContext().getRolesForUserAndGroups(user, groups);
+        }
+        return ret;
     }
 
     @Override
@@ -303,8 +415,16 @@ public class RangerPolicyAdminImpl implements RangerPolicyAdmin {
         if (LOG.isDebugEnabled()) {
             LOG.debug("==> RangerPolicyAdminImpl.getUniquelyMatchedZoneName(" + grantRevokeRequest + ")");
         }
+        String ret;
 
-        String ret = policyEngine.getUniquelyMatchedZoneName(grantRevokeRequest.getResource());
+        try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) {
+            if (LOG.isDebugEnabled()) {
+                if (readLock.isLockingEnabled()) {
+                    LOG.debug("Acquired lock - " + readLock);
+                }
+            }
+            ret = policyEngine.getUniquelyMatchedZoneName(grantRevokeRequest.getResource());
+        }
 
         if (LOG.isDebugEnabled()) {
             LOG.debug("<== RangerPolicyAdminImpl.getUniquelyMatchedZoneName(" + grantRevokeRequest + ") : " + ret);
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 41980d2..ec788af 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
@@ -70,6 +70,7 @@ import org.apache.ranger.db.XXGlobalStateDao;
 import org.apache.ranger.db.XXPolicyDao;
 import org.apache.ranger.entity.XXTagChangeLog;
 import org.apache.ranger.plugin.model.RangerSecurityZone;
+import org.apache.ranger.plugin.util.RangerCommonConstants;
 import org.apache.ranger.plugin.util.ServiceTags;
 import org.apache.ranger.plugin.model.validation.RangerServiceDefValidator;
 import org.apache.ranger.plugin.model.validation.RangerValidator;
@@ -240,6 +241,7 @@ public class ServiceDBStore extends AbstractServiceStore {
 	public static final String  SALT            = PropertiesUtil.getProperty("ranger.password.salt", PasswordUtils.DEFAULT_SALT);
 	public static final Integer ITERATION_COUNT = PropertiesUtil.getIntProperty("ranger.password.iteration.count", PasswordUtils.DEFAULT_ITERATION_COUNT);
 	public static boolean SUPPORTS_POLICY_DELTAS = false;
+	public static boolean SUPPORTS_IN_PLACE_POLICY_UPDATES = false;
 	public static Integer RETENTION_PERIOD_IN_DAYS = 7;
 	public static Integer TAG_RETENTION_PERIOD_IN_DAYS = 3;
 
@@ -377,10 +379,11 @@ public class ServiceDBStore extends AbstractServiceStore {
 			synchronized(ServiceDBStore.class) {
 				if(!legacyServiceDefsInitDone) {
 
-					SUPPORTS_POLICY_DELTAS       = config.getBoolean("ranger.admin.supports.policy.deltas", false);
+					SUPPORTS_POLICY_DELTAS       = config.getBoolean("ranger.admin" + RangerCommonConstants.RANGER_ADMIN_SUFFIX_POLICY_DELTA, RangerCommonConstants.RANGER_ADMIN_SUFFIX_POLICY_DELTA_DEFAULT);
 					RETENTION_PERIOD_IN_DAYS     = config.getInt("ranger.admin.delta.retention.time.in.days", 7);
 					TAG_RETENTION_PERIOD_IN_DAYS = config.getInt("ranger.admin.tag.delta.retention.time.in.days", 3);
 					isRolesDownloadedByService   = config.getBoolean("ranger.support.for.service.specific.role.download", false);
+					SUPPORTS_IN_PLACE_POLICY_UPDATES    = SUPPORTS_POLICY_DELTAS && config.getBoolean("ranger.admin" + RangerCommonConstants.RANGER_ADMIN_SUFFIX_IN_PLACE_POLICY_UPDATES, RangerCommonConstants.RANGER_ADMIN_SUFFIX_IN_PLACE_POLICY_UPDATES_DEFAULT);
 
 					TransactionTemplate txTemplate = new TransactionTemplate(txManager);
 
@@ -2818,7 +2821,7 @@ public class ServiceDBStore extends AbstractServiceStore {
 	public ServicePolicies getServicePolicyDeltasOrPolicies(String serviceName, Long lastKnownVersion) throws Exception {
 		boolean getOnlyDeltas = false;
 		if (LOG.isDebugEnabled()) {
-			LOG.debug("Support for incremental policy updates enabled using \"ranger.admin.supports.policy.deltas\" configuation parameter :[" + SUPPORTS_POLICY_DELTAS +"]");
+			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);
 	}
@@ -2827,7 +2830,7 @@ public class ServiceDBStore extends AbstractServiceStore {
 	public ServicePolicies getServicePolicyDeltas(String serviceName, Long lastKnownVersion) throws Exception {
 		boolean getOnlyDeltas = true;
 		if (LOG.isDebugEnabled()) {
-			LOG.debug("Support for incremental policy updates enabled using \"ranger.admin.supports.policy.deltas\" configuation parameter :[" + SUPPORTS_POLICY_DELTAS +"]");
+			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);
 	}
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java
index 581f11a..1bdfce0 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java
@@ -49,6 +49,7 @@ import org.apache.ranger.plugin.model.validation.ValidationFailureDetails;
 import org.apache.ranger.plugin.store.AbstractTagStore;
 import org.apache.ranger.plugin.store.PList;
 import org.apache.ranger.plugin.store.RangerServiceResourceSignature;
+import org.apache.ranger.plugin.util.RangerCommonConstants;
 import org.apache.ranger.plugin.util.RangerPerfTracer;
 import org.apache.ranger.plugin.util.RangerServiceNotFoundException;
 import org.apache.ranger.plugin.util.RangerServiceTagsDeltaUtil;
@@ -74,6 +75,7 @@ public class TagDBStore extends AbstractTagStore {
 
 	private static boolean SUPPORTS_TAG_DELTAS = false;
 	private static boolean IS_SUPPORTS_TAG_DELTAS_INITIALIZED = false;
+	public static boolean SUPPORTS_IN_PLACE_TAG_UPDATES = false;
 
 	@Autowired
 	RangerTagDefService rangerTagDefService;
@@ -1270,13 +1272,23 @@ public class TagDBStore extends AbstractTagStore {
 		return ret;
 	}
 
-	public static boolean isSupportsTagDeltas() {
-        if (!IS_SUPPORTS_TAG_DELTAS_INITIALIZED) {
-            RangerAdminConfig config = RangerAdminConfig.getInstance();
+	private static void initStatics() {
+		if (!IS_SUPPORTS_TAG_DELTAS_INITIALIZED) {
+			RangerAdminConfig config = RangerAdminConfig.getInstance();
+
+			SUPPORTS_TAG_DELTAS = config.getBoolean("ranger.admin" + RangerCommonConstants.RANGER_ADMIN_SUFFIX_TAG_DELTA, RangerCommonConstants.RANGER_ADMIN_SUFFIX_TAG_DELTA_DEFAULT);
+			SUPPORTS_IN_PLACE_TAG_UPDATES    = SUPPORTS_TAG_DELTAS && config.getBoolean("ranger.admin" + RangerCommonConstants.RANGER_ADMIN_SUFFIX_IN_PLACE_TAG_UPDATES, RangerCommonConstants.RANGER_ADMIN_SUFFIX_IN_PLACE_TAG_UPDATES_DEFAULT);
+			IS_SUPPORTS_TAG_DELTAS_INITIALIZED = true;
+		}
+	}
 
-            SUPPORTS_TAG_DELTAS = config.getBoolean("ranger.admin.supports.tag.deltas", false);
-            IS_SUPPORTS_TAG_DELTAS_INITIALIZED = true;
-        }
+	public static boolean isSupportsTagDeltas() {
+		initStatics();
         return SUPPORTS_TAG_DELTAS;
     }
+
+	public boolean isInPlaceTagUpdateSupported() {
+		initStatics();
+		return SUPPORTS_IN_PLACE_TAG_UPDATES;
+	}
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/common/RangerAdminTagEnricher.java b/security-admin/src/main/java/org/apache/ranger/common/RangerAdminTagEnricher.java
index 09e5c50..c3b70dc 100644
--- a/security-admin/src/main/java/org/apache/ranger/common/RangerAdminTagEnricher.java
+++ b/security-admin/src/main/java/org/apache/ranger/common/RangerAdminTagEnricher.java
@@ -30,6 +30,7 @@ import org.apache.ranger.plugin.model.RangerService;
 import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
 import org.apache.ranger.plugin.store.ServiceStore;
 import org.apache.ranger.plugin.store.TagStore;
+import org.apache.ranger.plugin.util.RangerReadWriteLock;
 import org.apache.ranger.plugin.util.ServiceTags;
 
 public class RangerAdminTagEnricher extends RangerTagEnricher {
@@ -71,9 +72,11 @@ public class RangerAdminTagEnricher extends RangerTagEnricher {
         if (tagStore == null || svcStore == null) {
             LOG.error("ServiceDBStore/TagDBStore is not initialized!! Internal Error!");
         } else {
+            super.init();
             try {
                 RangerService service = svcStore.getServiceByName(serviceName);
                 serviceId = service.getId();
+                createLock();
             } catch (Exception e) {
                 LOG.error("Cannot find service with name:[" + serviceName + "]", e);
                 LOG.error("This will cause tag-enricher in Ranger-Admin to fail!!");
@@ -85,6 +88,15 @@ public class RangerAdminTagEnricher extends RangerTagEnricher {
     }
 
     @Override
+    protected RangerReadWriteLock createLock() {
+        boolean useReadWriteLock = tagStore != null && tagStore.isInPlaceTagUpdateSupported();
+
+        LOG.info("Policy-Engine will" + (useReadWriteLock ? " " : " not ") + "use read-write locking to update tags in place when tag-deltas are provided");
+
+        return new RangerReadWriteLock(useReadWriteLock);
+    }
+
+    @Override
     public void enrich(RangerAccessRequest request) {
         if (LOG.isDebugEnabled()) {
             LOG.debug("==> RangerAdminTagEnricher.enrich(" + request + ")");
diff --git a/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java b/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java
index cfd66b1..284b9dc 100644
--- a/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java
+++ b/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java
@@ -2029,17 +2029,14 @@ public class TestXUserMgr {
 	public void test49createServiceConfigUser() {
 		XXUserDao xxUserDao = Mockito.mock(XXUserDao.class);
 		XXPortalUserDao userDao = Mockito.mock(XXPortalUserDao.class);
-		XXModuleDefDao xXModuleDefDao = Mockito.mock(XXModuleDefDao.class);
 		VXUser vxUser = vxUser();
 		XXUser xXUser = xxUser(vxUser);
 		VXPortalUser userProfile = userProfile();
 		XXPortalUser xXPortalUser = xxPortalUser(userProfile);
-		Collection<String> userRoleList =getRoleList();
 		VXUserPermission vXUserPermission=vxUserPermission();
 		XXUserPermission xUserPermissionObj = xxUserPermission();
 		xUserPermissionObj.setModuleId(vXUserPermission.getModuleId());
 		xUserPermissionObj.setUserId(vXUserPermission.getUserId());
-		List<XXModuleDef> xXModuleDefs = xxModuleDefs();
 		Mockito.when(daoManager.getXXUser()).thenReturn(xxUserDao);
 		Mockito.when(xxUserDao.findByUserName(vxUser.getName())).thenReturn(xXUser);
 		Mockito.when(daoManager.getXXPortalUser()).thenReturn(userDao);
@@ -3194,7 +3191,6 @@ public class TestXUserMgr {
 		XXUser xXUser = xxUser(vxUser);
 		VXPortalUser userProfile = userProfile();
 		XXPortalUser xXPortalUser = xxPortalUser(userProfile);
-		Collection<String> userRoleList =getRoleList();
 		VXUserPermission vXUserPermission=vxUserPermission();
 		XXUserPermission xUserPermissionObj = xxUserPermission();
 		xUserPermissionObj.setModuleId(vXUserPermission.getModuleId());