This is an automated email from the ASF dual-hosted git repository.
abhay pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push:
new 9648f8f8c RANGER-4852: De-duplicated tags do not work correctly when
tag-deltas are enabled
9648f8f8c is described below
commit 9648f8f8c9e6f178837942ee76a992636e83f772
Author: Abhay Kulkarni <[email protected]>
AuthorDate: Fri Jul 12 16:13:39 2024 -0700
RANGER-4852: De-duplicated tags do not work correctly when tag-deltas are
enabled
---
.../contextenricher/RangerAdminTagRetriever.java | 13 ---
.../RangerFileBasedTagRetriever.java | 8 +-
.../plugin/contextenricher/RangerTagEnricher.java | 7 +-
.../plugin/contextenricher/RangerTagRetriever.java | 1 +
.../ranger/plugin/model/RangerServiceTags.java | 2 +-
.../ranger/plugin/util/RangerCommonConstants.java | 4 +-
.../plugin/util/RangerServiceTagsDeltaUtil.java | 124 ++++++++++++---------
.../org/apache/ranger/plugin/util/ServiceTags.java | 57 ++++++++--
.../java/org/apache/ranger/biz/TagDBStore.java | 18 ++-
.../ranger/common/RangerServiceTagsCache.java | 4 +-
10 files changed, 148 insertions(+), 90 deletions(-)
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerAdminTagRetriever.java
b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerAdminTagRetriever.java
index b2b7d5f71..bae31e6cc 100644
---
a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerAdminTagRetriever.java
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerAdminTagRetriever.java
@@ -33,12 +33,7 @@ import java.util.Map;
public class RangerAdminTagRetriever extends RangerTagRetriever {
private static final Logger LOG =
LoggerFactory.getLogger(RangerAdminTagRetriever.class);
- private static final String OPTION_DEDUP_TAGS = "deDupTags";
- private static final Boolean OPTION_DEDUP_TAGS_DEFAULT = true;
-
-
private RangerAdminClient adminClient;
- private boolean deDupTags;
@Override
public void init(Map<String, String> options) {
@@ -50,11 +45,9 @@ public class RangerAdminTagRetriever extends
RangerTagRetriever {
pluginConfig = new
RangerPluginConfig(serviceDef.getName(), serviceName, appId, null, null, null);
}
- String deDupTagsVal = options != null?
options.get(OPTION_DEDUP_TAGS) : null;
RangerPluginContext pluginContext = getPluginContext();
RangerAdminClient rangerAdmin =
pluginContext.getAdminClient();
- this.deDupTags = StringUtils.isNotBlank(deDupTagsVal)
? Boolean.parseBoolean(deDupTagsVal) : OPTION_DEDUP_TAGS_DEFAULT;
this.adminClient = (rangerAdmin != null) ? rangerAdmin
: pluginContext.createAdminClient(pluginConfig);
} else {
LOG.error("FATAL: Cannot find service/serviceDef to use
for retrieving tags. Will NOT be able to retrieve tags.");
@@ -78,12 +71,6 @@ public class RangerAdminTagRetriever extends
RangerTagRetriever {
}
}
- if (serviceTags != null && !serviceTags.getIsDelta() &&
deDupTags) {
- final int countOfDuplicateTags =
serviceTags.dedupTags();
-
- LOG.info("Number of duplicate tags removed from the
received serviceTags:[" + countOfDuplicateTags + "]. Number of tags in the
de-duplicated serviceTags :[" + serviceTags.getTags().size() + "].");
- }
-
return serviceTags;
}
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerFileBasedTagRetriever.java
b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerFileBasedTagRetriever.java
index 2a3643399..1e39d93fa 100644
---
a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerFileBasedTagRetriever.java
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerFileBasedTagRetriever.java
@@ -37,7 +37,6 @@ public class RangerFileBasedTagRetriever extends
RangerTagRetriever {
private URL serviceTagsFileURL;
private String serviceTagsFileName;
- private boolean deDupTags;
int tagFilesCount = 0;
int currentTagFileIndex = 0;
boolean isInitial = true;
@@ -50,15 +49,12 @@ public class RangerFileBasedTagRetriever extends
RangerTagRetriever {
String serviceTagsFileNameProperty = "serviceTagsFileName";
String serviceTagsDefaultFileName =
"/testdata/test_servicetags_hive.json";
- String deDupTagsProperty = "deDupTags";
String tagFilesCountProperty = "tagFileCount";
if (StringUtils.isNotBlank(serviceName) && serviceDef != null
&& StringUtils.isNotBlank(appId)) {
// Open specified file from options- it should contain
service-tags
serviceTagsFileName = options != null?
options.get(serviceTagsFileNameProperty) : null;
- String deDupTagsVal = options != null?
options.get(deDupTagsProperty) : "false";
- deDupTags =
Boolean.parseBoolean(deDupTagsVal);
serviceTagsFileName = serviceTagsFileName == null ?
serviceTagsDefaultFileName : serviceTagsFileName;
if (options != null) {
@@ -179,7 +175,7 @@ public class RangerFileBasedTagRetriever extends
RangerTagRetriever {
) {
ret = JsonUtils.jsonToObject(reader,
ServiceTags.class);
- if (deDupTags) {
+ if (ret.getIsTagsDeduped()) {
final int countOfDuplicateTags
= ret.dedupTags();
LOG.info("Number of duplicate
tags removed from the received serviceTags:[" + countOfDuplicateTags + "].
Number of tags in the de-duplicated serviceTags :[" + ret.getTags().size() +
"].");
}
@@ -204,7 +200,7 @@ public class RangerFileBasedTagRetriever extends
RangerTagRetriever {
ret = JsonUtils.jsonToObject(reader,
ServiceTags.class);
currentTagFileIndex++;
- if (deDupTags) {
+ if (ret.getIsTagsDeduped()) {
final int countOfDuplicateTags
= ret.dedupTags();
LOG.info("Number of duplicate
tags removed from the received serviceTags:[" + countOfDuplicateTags + "].
Number of tags in the de-duplicated serviceTags :[" + ret.getTags().size() +
"].");
}
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 0208e6892..2fa24eba6 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
@@ -309,13 +309,18 @@ public class RangerTagEnricher extends
RangerAbstractContextEnricher {
}
if (!serviceTags.getIsDelta()) {
+ if (serviceTags.getIsTagsDeduped()) {
+ final int countOfDuplicateTags
= serviceTags.dedupTags();
+
+ LOG.info("Number of duplicate
tags removed from the received serviceTags:[" + countOfDuplicateTags + "].
Number of tags in the de-duplicated serviceTags :[" +
serviceTags.getTags().size() + "].");
+ }
processServiceTags(serviceTags);
} 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);
+ ServiceTags allServiceTags =
rebuildOnlyIndex ? oldServiceTags :
RangerServiceTagsDeltaUtil.applyDelta(oldServiceTags, serviceTags,
serviceTags.getIsTagsDeduped());
if (serviceTags.getTagsChangeExtent()
== ServiceTags.TagsChangeExtent.NONE) {
if (LOG.isDebugEnabled()) {
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagRetriever.java
b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagRetriever.java
index d7c737525..584959e02 100644
---
a/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagRetriever.java
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/contextenricher/RangerTagRetriever.java
@@ -71,4 +71,5 @@ public abstract class RangerTagRetriever {
public void setPluginContext(RangerPluginContext pluginContext) {
this.pluginContext = pluginContext;
}
+
}
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceTags.java
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceTags.java
index 59288f7d5..3a2633974 100644
---
a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceTags.java
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerServiceTags.java
@@ -170,7 +170,7 @@ public class RangerServiceTags implements
java.io.Serializable {
ret = new ServiceTags(toServiceTagsOp(tags.getOp()),
tags.getServiceName(),
tags.tagVersion, tags.getTagUpdateTime(),
tags.getTagDefinitions(), tags.getTags(),
tags.getServiceResources(),
tags.getResourceToTagIds(), false,
- ServiceTags.TagsChangeExtent.ALL);
+ ServiceTags.TagsChangeExtent.ALL, false);
}
return ret;
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 23689790d..9d6e1f0b5 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
@@ -40,7 +40,7 @@ public class RangerCommonConstants {
public static final String RANGER_ADMIN_SUFFIX_IN_PLACE_TAG_UPDATES
= ".supports.in.place.tag.updates";
public static final String PLUGIN_CONFIG_SUFFIX_IN_PLACE_TAG_UPDATES
= ".supports.in.place.tag.updates";
- public static final String RANGER_ADMIN_SUPPORTS_TAGS_DEDUP
= ".supports.tags.dedup";
+ public static final String RANGER_SUPPORTS_TAGS_DEDUP
= ".supports.tags.dedup";
public static final boolean RANGER_ADMIN_SUFFIX_POLICY_DELTA_DEFAULT
= false;
public static final boolean PLUGIN_CONFIG_SUFFIX_POLICY_DELTA_DEFAULT
= false;
@@ -54,7 +54,7 @@ public class RangerCommonConstants {
public static final boolean
RANGER_ADMIN_SUFFIX_IN_PLACE_TAG_UPDATES_DEFAULT = false;
public static final boolean
PLUGIN_CONFIG_SUFFIX_IN_PLACE_TAG_UPDATES_DEFAULT = false;
- public static final boolean RANGER_ADMIN_SUPPORTS_TAGS_DEDUP_DEFAULT
= true;
+ public static final boolean RANGER_SUPPORTS_TAGS_DEDUP_DEFAULT
= true;
public static final boolean POLICY_REST_CLIENT_SESSION_COOKIE_ENABLED
= true;
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerServiceTagsDeltaUtil.java
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerServiceTagsDeltaUtil.java
index f2e68aed9..d5a0915e0 100644
---
a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerServiceTagsDeltaUtil.java
+++
b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerServiceTagsDeltaUtil.java
@@ -19,8 +19,10 @@
package org.apache.ranger.plugin.util;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
-import org.apache.ranger.authorization.hadoop.config.RangerAdminConfig;
+import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.ranger.plugin.model.RangerServiceResource;
import org.apache.ranger.plugin.model.RangerTag;
import org.apache.ranger.plugin.model.RangerTagDef;
@@ -42,16 +44,13 @@ public class RangerServiceTagsDeltaUtil {
private static final Logger PERF_TAGS_DELTA_LOG =
RangerPerfTracer.getPerfLogger("tags.delta");
- private static boolean SUPPORTS_TAGS_DEDUP_INITIALIZED = false;
- private static boolean SUPPORTS_TAGS_DEDUP = false;
-
/*
It should be possible to call applyDelta() multiple times with serviceTags
and delta resulting from previous call to applyDelta()
The end result should be same if called once or multiple times.
*/
- static public ServiceTags applyDelta(ServiceTags serviceTags, ServiceTags
delta) {
+ static public ServiceTags applyDelta(ServiceTags serviceTags, ServiceTags
delta, boolean supportsTagsDedup) {
if (LOG.isDebugEnabled()) {
- LOG.debug("==> RangerServiceTagsDeltaUtil.applyDelta()");
+ LOG.debug("==> RangerServiceTagsDeltaUtil.applyDelta():
serviceTags:[" + serviceTags + "], delta:[" + delta + "], supportsTagsDedup:["
+ supportsTagsDedup + "]");
}
ServiceTags ret = serviceTags;
@@ -66,6 +65,7 @@ public class RangerServiceTagsDeltaUtil {
ret.setServiceName(delta.getServiceName());
ret.setTagVersion(delta.getTagVersion());
+ ret.setIsTagsDeduped(delta.getIsTagsDeduped());
int tagDefsAdded = 0, tagDefsUpdated = 0, tagDefsRemoved = 0;
int tagsAdded = 0, tagsUpdated = 0, tagsRemoved = 0;
@@ -103,25 +103,47 @@ public class RangerServiceTagsDeltaUtil {
RangerTag deltaTag = entry.getValue();
if (StringUtils.isEmpty(deltaTag.getType())) { // tag has been
removed
- RangerTag removedTag = tags.remove(deltaTagId);
-
- if (removedTag != null) {
- tagsRemoved++;
+ if (supportsTagsDedup) {
+ boolean found = false;
+
+ for (Iterator<Map.Entry<RangerTag, MutablePair<Long,
Long>>> iterator = ret.cachedTags.entrySet().iterator(); iterator.hasNext(); ) {
+ MutablePair<Long, Long> value =
iterator.next().getValue();
+ if (value.left.equals(deltaTagId)) {
+ if (--value.right == 0) {
+ // This may never be true when this tag is
duplicated
+ // as the mapping between de-duplicated
tags is not maintained - only the reference count is stored
+ // So, the tag with the smallest tag-id
(among duplicate tags) will never be removed
+ if (tags.remove(deltaTagId) != null) {
+ tagsRemoved++;
+ }
+ iterator.remove();
+ }
+ found = true;
+ break;
+ }
+ }
- if (isSupportsTagsDedup()) {
- ret.cachedTags.remove(removedTag);
+ if (!found) {
+ if (tags.remove(deltaTagId) != null) {
+ tagsRemoved++;
+ }
+ }
+ } else {
+ if (tags.remove(deltaTagId) != null) {
+ tagsRemoved++;
}
}
} else {
- if (isSupportsTagsDedup()) {
- Long cachedTagId = ret.cachedTags.get(deltaTag);
+ if (supportsTagsDedup) {
+ MutablePair<Long, Long> cachedTag =
ret.cachedTags.get(deltaTag);
- if (cachedTagId == null) {
- ret.cachedTags.put(deltaTag, deltaTagId);
+ if (cachedTag == null) {
+ ret.cachedTags.put(deltaTag, new
MutablePair<>(deltaTagId, 1L));
tags.put(deltaTagId, deltaTag);
+ tagsAdded++;
} else {
- replacedTagIds.put(deltaTagId, cachedTagId);
- deltaTagIter.remove();
+ cachedTag.right++;
+ replacedTagIds.put(deltaTagId, cachedTag.left);
}
} else {
RangerTag existing = tags.put(deltaTagId, deltaTag);
@@ -147,43 +169,29 @@ public class RangerServiceTagsDeltaUtil {
if (existingResource != null) {
if
(StringUtils.isNotEmpty(resource.getResourceSignature())) {
if
(!StringUtils.equals(resource.getResourceSignature(),
existingResource.getResourceSignature())) { // ServiceResource changed;
replace existing instance
- existingResource.setResourceSignature(null);
-
- boolean isAddedResource =
resourcesToAdd.remove(existingResource.getId()) == existingResource;
-
- // if a resource with this ID was already removed,
don't replace the entry in resourcesToRemove
- if (!isAddedResource &&
!resourcesToRemove.containsKey(existingResource.getId())) {
-
resourcesToRemove.put(existingResource.getId(), existingResource);
- }
-
+ /* If the signature changed, we need to remove
existing resource and add new resource */
+ resourcesToRemove.put(resource.getId(),
existingResource);
resourcesToAdd.put(resource.getId(), resource);
- idResourceMap.put(resource.getId(), resource);
}
} else { // resource deleted
- boolean isAddedResource =
resourcesToAdd.remove(existingResource.getId()) == existingResource;
-
- if (!isAddedResource) {
- resourcesToRemove.put(existingResource.getId(),
existingResource);
- }
+ resourcesToRemove.put(resource.getId(),
existingResource);
- idResourceMap.remove(existingResource.getId());
resourceToTagIds.remove(existingResource.getId());
}
} else { // resource added
if
(StringUtils.isNotEmpty(resource.getResourceSignature())) {
resourcesToAdd.put(resource.getId(), resource);
-
- idResourceMap.put(resource.getId(), resource);
}
}
}
if (!resourcesToRemove.isEmpty()) {
for (ListIterator<RangerServiceResource> iter =
serviceResources.listIterator(); iter.hasNext(); ) {
- RangerServiceResource resource = iter.next();
- RangerServiceResource replacedResource =
resourcesToRemove.get(resource.getId());
+ RangerServiceResource resource = iter.next();
+ RangerServiceResource deletedResource =
resourcesToRemove.get(resource.getId());
+ RangerServiceResource addedResource =
resourcesToAdd.get(resource.getId());
- if (replacedResource == resource) {
+ if (addedResource == null && deletedResource == resource) {
iter.remove();
}
}
@@ -208,16 +216,33 @@ public class RangerServiceTagsDeltaUtil {
resourceToTagIds.putAll(delta.getResourceToTagIds());
+ if (MapUtils.isEmpty(resourceToTagIds)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("There are no resource->tag mappings!!");
+ }
+ if (MapUtils.isNotEmpty(ret.getTags())) {
+ LOG.warn("There are no resource->tag mappings, but there
are tags in the ServiceTags!! Cleaning up");
+ ret.getTags().clear();
+ }
+ if (supportsTagsDedup) {
+ ret.cachedTags.clear();
+ }
+ }
+
// Ensure that any modified service-resources are at head of list
of service-resources in delta
// So that in setServiceTags(), they get cleaned out first, and
service-resource with new spec gets added
- if (!resourcesToAdd.isEmpty()) {
- List<RangerServiceResource> deltaServiceResources = new
ArrayList<>(resourcesToAdd.values());
- deltaServiceResources.addAll(delta.getServiceResources());
-
- delta.setServiceResources(deltaServiceResources);
+ List<RangerServiceResource> deltaServiceResources = new
ArrayList<>();
+ for (RangerServiceResource resourceToRemove :
resourcesToRemove.values()) {
+ resourceToRemove.setResourceSignature(null);
+ deltaServiceResources.add(resourceToRemove);
+ }
+ if (!resourcesToAdd.isEmpty()) {
+ deltaServiceResources.addAll(resourcesToAdd.values());
}
+ delta.setServiceResources(deltaServiceResources);
+
if (LOG.isDebugEnabled()) {
LOG.debug("RangerServiceTagsDeltaUtil.applyDelta():
delta(tagDefs={}, tags={}, resources={}), " +
"resources(total={}, added={}, removed={}), " +
@@ -235,7 +260,7 @@ public class RangerServiceTagsDeltaUtil {
}
if (LOG.isDebugEnabled()) {
- LOG.debug("<== RangerServiceTagsDeltaUtil.applyDelta()");
+ LOG.debug("<== RangerServiceTagsDeltaUtil.applyDelta():
serviceTags:[" + ret + "], delta:[" + delta + "], supportsTagsDedup:[" +
supportsTagsDedup + "]");
}
RangerPerfTracer.log(perf);
@@ -312,13 +337,4 @@ public class RangerServiceTagsDeltaUtil {
}
}
- public static boolean isSupportsTagsDedup() {
- if (!SUPPORTS_TAGS_DEDUP_INITIALIZED) {
- RangerAdminConfig config = RangerAdminConfig.getInstance();
-
- SUPPORTS_TAGS_DEDUP = config.getBoolean("ranger.admin" +
RangerCommonConstants.RANGER_ADMIN_SUPPORTS_TAGS_DEDUP,
RangerCommonConstants.RANGER_ADMIN_SUPPORTS_TAGS_DEDUP_DEFAULT);
- SUPPORTS_TAGS_DEDUP_INITIALIZED = true;
- }
- return SUPPORTS_TAGS_DEDUP;
- }
}
diff --git
a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java
b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java
index 39110357d..cc2ebe53a 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java
@@ -28,6 +28,7 @@ import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
+import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.ranger.authorization.utils.StringUtil;
import org.apache.ranger.plugin.model.RangerServiceResource;
import org.apache.ranger.plugin.model.RangerTag;
@@ -61,9 +62,11 @@ public class ServiceTags implements java.io.Serializable {
private Map<Long, List<Long>> resourceToTagIds;
private Boolean isDelta;
private TagsChangeExtent tagsChangeExtent;
+ private Boolean isTagsDeduped;
+ // MutablePair.left is the tag-id, MutablePair.right is the
reference-count
@JsonIgnore
- Map<RangerTag, Long> cachedTags = new HashMap<>();
+ Map<RangerTag, MutablePair<Long, Long>> cachedTags = new HashMap<>();
public ServiceTags() {
this(OP_ADD_OR_UPDATE, null, 0L, null, null, null, null, null);
@@ -71,10 +74,10 @@ public class ServiceTags implements java.io.Serializable {
public ServiceTags(String op, String serviceName, Long tagVersion, Date
tagUpdateTime, Map<Long, RangerTagDef> tagDefinitions,
Map<Long, RangerTag> tags,
List<RangerServiceResource> serviceResources, Map<Long, List<Long>>
resourceToTagIds) {
- this(op, serviceName, tagVersion, tagUpdateTime,
tagDefinitions, tags, serviceResources, resourceToTagIds, false,
TagsChangeExtent.ALL);
+ this(op, serviceName, tagVersion, tagUpdateTime,
tagDefinitions, tags, serviceResources, resourceToTagIds, false,
TagsChangeExtent.ALL, false);
}
public ServiceTags(String op, String serviceName, Long tagVersion, Date
tagUpdateTime, Map<Long, RangerTagDef> tagDefinitions,
- Map<Long, RangerTag> tags,
List<RangerServiceResource> serviceResources, Map<Long, List<Long>>
resourceToTagIds, Boolean isDelta, TagsChangeExtent tagsChangeExtent) {
+ Map<Long, RangerTag> tags,
List<RangerServiceResource> serviceResources, Map<Long, List<Long>>
resourceToTagIds, Boolean isDelta, TagsChangeExtent tagsChangeExtent, Boolean
isTagsDeduped) {
setOp(op);
setServiceName(serviceName);
setTagVersion(tagVersion);
@@ -85,6 +88,7 @@ public class ServiceTags implements java.io.Serializable {
setResourceToTagIds(resourceToTagIds);
setIsDelta(isDelta);
setTagsChangeExtent(tagsChangeExtent);
+ setIsTagsDeduped(isTagsDeduped);
}
public ServiceTags(ServiceTags other) {
@@ -97,6 +101,7 @@ public class ServiceTags implements java.io.Serializable {
setServiceResources(other.getServiceResources() != null ? new
ArrayList<>(other.getServiceResources()) : null);
setResourceToTagIds(other.getResourceToTagIds() != null ? new
HashMap<>(other.getResourceToTagIds()) : null);
setIsDelta(other.getIsDelta());
+ setIsTagsDeduped(other.getIsTagsDeduped());
setTagsChangeExtent(other.getTagsChangeExtent());
this.cachedTags = new HashMap<>(other.cachedTags);
@@ -198,6 +203,14 @@ public class ServiceTags implements java.io.Serializable {
this.isDelta = isDelta;
}
+ public Boolean getIsTagsDeduped() {
+ return isTagsDeduped == null ? Boolean.FALSE : isTagsDeduped;
+ }
+
+ public void setIsTagsDeduped(Boolean isTagsDeduped) {
+ this.isTagsDeduped = isTagsDeduped;
+ }
+
public TagsChangeExtent getTagsChangeExtent() {
return tagsChangeExtent;
}
@@ -225,6 +238,8 @@ public class ServiceTags implements java.io.Serializable {
.append(",
serviceResources={").append(serviceResources).append("}")
.append(", tags={").append(tags).append("}")
.append(",
resourceToTagIds={").append(resourceToTagIds).append("}")
+ .append(",
isTagsDeduped={").append(isTagsDeduped).append("}")
+ .append(",
cachedTags={").append(cachedTags).append("}")
.append("}");
return sb;
@@ -234,31 +249,51 @@ public class ServiceTags implements java.io.Serializable {
final int ret;
final Map<Long, Long> replacedIds = new HashMap<>();
final int initialTagsCount = tags.size();
+ final List<Long> tagIdsToRemove = new ArrayList<>();
for (Iterator<Map.Entry<Long, RangerTag>> iter =
tags.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry<Long, RangerTag> entry = iter.next();
Long tagId = entry.getKey();
RangerTag tag =
entry.getValue();
- Long cachedTagId =
cachedTags.get(tag);
+ MutablePair<Long, Long> cachedTag =
cachedTags.get(tag);
- if (cachedTagId == null) {
- cachedTags.put(tag, tagId);
+ if (cachedTag == null) {
+ cachedTags.put(tag, new MutablePair<>(tagId,
0L)); // reference count will be incremented later
} else {
- replacedIds.put(tagId, cachedTagId);
- iter.remove();
+ if (tagId < cachedTag.left) {
+ replacedIds.put(cachedTag.left, tagId);
+ tagIdsToRemove.add(cachedTag.left);
+ cachedTag.left = tagId;
+ } else {
+ replacedIds.put(tagId, cachedTag.left);
+ iter.remove();
+ }
}
}
+ for (Long tagIdToRemove : tagIdsToRemove) {
+ tags.remove(tagIdToRemove);
+ }
final int finalTagsCount = tags.size();
for (Map.Entry<Long, List<Long>> resourceEntry :
resourceToTagIds.entrySet()) {
for (ListIterator<Long> listIter =
resourceEntry.getValue().listIterator(); listIter.hasNext(); ) {
Long tagId = listIter.next();
- Long replacerTagId = replacedIds.get(tagId);
- if (replacerTagId != null) {
- listIter.set(replacerTagId);
+ for (Long replacerTagId =
replacedIds.get(tagId); replacerTagId != null; replacerTagId =
replacedIds.get(tagId)) {
+ tagId = replacerTagId;
}
+
+ listIter.set(tagId);
+
+ RangerTag tag = tags.get(tagId);
+ if (tag != null) { // This should always
be true
+ MutablePair<Long, Long> cachedTag =
cachedTags.get(tag);
+ if (cachedTag != null) { // This should
always be true
+ cachedTag.right++;
+ }
+ }
+
}
}
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 9ecbb14ac..9134e3988 100755
--- a/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/TagDBStore.java
@@ -1033,7 +1033,9 @@ public class TagDBStore extends AbstractTagStore {
ret.setServiceResources(resources);
ret.setResourceToTagIds(resourceToTagIds);
- if (RangerServiceTagsDeltaUtil.isSupportsTagsDedup()) {
+ ret.setIsTagsDeduped(isSupportsTagsDedup());
+
+ if (isSupportsTagsDedup()) {
final int countOfDuplicateTags =
ret.dedupTags();
if (LOG.isDebugEnabled()) {
LOG.debug("Number of duplicate tags
removed from the received serviceTags:[" + countOfDuplicateTags + "]. Number of
tags in the de-duplicated serviceTags :[" + ret.getTags().size() + "].");
@@ -1243,6 +1245,7 @@ public class TagDBStore extends AbstractTagStore {
if (CollectionUtils.isNotEmpty(serviceResourceIds) ||
CollectionUtils.isNotEmpty(tagIds)) {
ret = new ServiceTags();
ret.setIsDelta(true);
+ ret.setIsTagsDeduped(isSupportsTagsDedup());
ServiceTags.TagsChangeExtent tagsChangeExtent =
ServiceTags.TagsChangeExtent.TAGS;
@@ -1457,4 +1460,17 @@ public class TagDBStore extends AbstractTagStore {
return ret;
}
+
+ private static boolean SUPPORTS_TAGS_DEDUP_INITIALIZED = false;
+ private static boolean SUPPORTS_TAGS_DEDUP = false;
+
+ public static boolean isSupportsTagsDedup() {
+ if (!SUPPORTS_TAGS_DEDUP_INITIALIZED) {
+ RangerAdminConfig config =
RangerAdminConfig.getInstance();
+
+ SUPPORTS_TAGS_DEDUP = config.getBoolean("ranger.admin"
+ RangerCommonConstants.RANGER_SUPPORTS_TAGS_DEDUP,
RangerCommonConstants.RANGER_SUPPORTS_TAGS_DEDUP_DEFAULT);
+ SUPPORTS_TAGS_DEDUP_INITIALIZED = true;
+ }
+ return SUPPORTS_TAGS_DEDUP;
+ }
}
diff --git
a/security-admin/src/main/java/org/apache/ranger/common/RangerServiceTagsCache.java
b/security-admin/src/main/java/org/apache/ranger/common/RangerServiceTagsCache.java
index 2aecc4388..ec0ff7083 100644
---
a/security-admin/src/main/java/org/apache/ranger/common/RangerServiceTagsCache.java
+++
b/security-admin/src/main/java/org/apache/ranger/common/RangerServiceTagsCache.java
@@ -22,6 +22,7 @@ package org.apache.ranger.common;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ranger.authorization.hadoop.config.RangerAdminConfig;
+import org.apache.ranger.biz.TagDBStore;
import org.apache.ranger.plugin.store.TagStore;
import org.apache.ranger.plugin.util.RangerServiceTagsDeltaUtil;
@@ -376,7 +377,8 @@ public class RangerServiceTagsCache {
LOG.debug("Retrieved
tag-deltas from database. These will be applied on top of ServiceTags
version:[" + cachedServiceTagsVersion + "], tag-deltas:[" +
serviceTagsFromDb.getTagVersion() + "]");
}
- this.serviceTags =
RangerServiceTagsDeltaUtil.applyDelta(serviceTags, serviceTagsFromDb);
+ boolean supportsTagsDedeup =
TagDBStore.isSupportsTagsDedup();
+ this.serviceTags =
RangerServiceTagsDeltaUtil.applyDelta(serviceTags, serviceTagsFromDb,
supportsTagsDedeup);
this.deltaCache = new
ServiceTagsDeltasCache(cachedServiceTagsVersion, serviceTagsFromDb);
}
} else {