in agents-common/src/main/java/org/apache/ranger/plugin/util/RangerServiceTagsDeltaUtil.java [52:265]
public static ServiceTags applyDelta(ServiceTags serviceTags, ServiceTags delta, boolean supportsTagsDedup) {
LOG.debug("==> RangerServiceTagsDeltaUtil.applyDelta(): serviceTags:[{}], delta:[{}], supportsTagsDedup:[{}]", serviceTags, delta, supportsTagsDedup);
ServiceTags ret = serviceTags;
RangerPerfTracer perf = null;
if (RangerPerfTracer.isPerfTraceEnabled(PERF_TAGS_DELTA_LOG)) {
perf = RangerPerfTracer.getPerfTracer(PERF_TAGS_DELTA_LOG, "RangerServiceTagsDeltaUtil.applyDelta()");
}
if (serviceTags != null && !serviceTags.getIsDelta() && delta != null && delta.getIsDelta()) {
ret = new ServiceTags(serviceTags);
ret.setServiceName(delta.getServiceName());
ret.setTagVersion(delta.getTagVersion());
ret.setIsTagsDeduped(delta.getIsTagsDeduped());
int tagDefsAdded = 0;
int tagDefsUpdated = 0;
int tagDefsRemoved = 0;
int tagsAdded = 0;
int tagsUpdated = 0;
int tagsRemoved = 0;
Map<Long, RangerTagDef> tagDefs = ret.getTagDefinitions();
for (Map.Entry<Long, RangerTagDef> entry : delta.getTagDefinitions().entrySet()) {
Long deltaTagDefId = entry.getKey();
RangerTagDef deltaTagDef = entry.getValue();
if (StringUtils.isEmpty(deltaTagDef.getName())) { // tagdef has been removed
RangerTagDef removedTagDef = tagDefs.remove(deltaTagDefId);
if (removedTagDef != null) {
tagDefsRemoved++;
}
}
RangerTagDef existing = tagDefs.put(deltaTagDefId, deltaTagDef);
if (existing == null) {
tagDefsAdded++;
} else if (!existing.equals(deltaTagDef)) {
tagDefsUpdated++;
}
}
Map<Long, RangerTag> tags = ret.getTags();
Map<Long, Long> replacedTagIds = new HashMap<>();
for (Map.Entry<Long, RangerTag> entry : delta.getTags().entrySet()) {
Long deltaTagId = entry.getKey();
RangerTag deltaTag = entry.getValue();
if (StringUtils.isEmpty(deltaTag.getType())) { // tag has been removed
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 (!found) {
if (tags.remove(deltaTagId) != null) {
tagsRemoved++;
}
}
} else {
if (tags.remove(deltaTagId) != null) {
tagsRemoved++;
}
}
} else {
if (supportsTagsDedup) {
MutablePair<Long, Long> cachedTag = ret.cachedTags.get(deltaTag);
if (cachedTag == null) {
ret.cachedTags.put(deltaTag, new MutablePair<>(deltaTagId, 1L));
tags.put(deltaTagId, deltaTag);
tagsAdded++;
} else {
cachedTag.right++;
replacedTagIds.put(deltaTagId, cachedTag.left);
}
} else {
RangerTag existing = tags.put(deltaTagId, deltaTag);
if (existing == null) {
tagsAdded++;
} else if (!existing.equals(deltaTag)) {
tagsUpdated++;
}
}
}
}
List<RangerServiceResource> serviceResources = ret.getServiceResources();
Map<Long, List<Long>> resourceToTagIds = ret.getResourceToTagIds();
Map<Long, RangerServiceResource> idResourceMap = serviceResources.stream().collect(Collectors.toMap(RangerServiceResource::getId, Function.identity()));
Map<Long, RangerServiceResource> resourcesToRemove = new HashMap<>();
Map<Long, RangerServiceResource> resourcesToAdd = new HashMap<>();
for (RangerServiceResource resource : delta.getServiceResources()) {
RangerServiceResource existingResource = idResourceMap.get(resource.getId());
if (existingResource != null) {
if (StringUtils.isNotEmpty(resource.getResourceSignature())) {
if (!StringUtils.equals(resource.getResourceSignature(), existingResource.getResourceSignature())) { // ServiceResource changed; replace existing instance
/* If the signature changed, we need to remove existing resource and add new resource */
resourcesToRemove.put(resource.getId(), existingResource);
resourcesToAdd.put(resource.getId(), resource);
}
} else { // resource deleted
resourcesToRemove.put(resource.getId(), existingResource);
resourceToTagIds.remove(existingResource.getId());
}
} else { // resource added
if (StringUtils.isNotEmpty(resource.getResourceSignature())) {
resourcesToAdd.put(resource.getId(), resource);
}
}
}
if (!resourcesToRemove.isEmpty()) {
for (ListIterator<RangerServiceResource> iter = serviceResources.listIterator(); iter.hasNext(); ) {
RangerServiceResource resource = iter.next();
RangerServiceResource deletedResource = resourcesToRemove.get(resource.getId());
RangerServiceResource addedResource = resourcesToAdd.get(resource.getId());
if (addedResource == null && deletedResource == resource) {
iter.remove();
}
}
}
serviceResources.addAll(resourcesToAdd.values());
if (!replacedTagIds.isEmpty()) {
for (Map.Entry<Long, List<Long>> resourceEntry : delta.getResourceToTagIds().entrySet()) {
ListIterator<Long> listIter = resourceEntry.getValue().listIterator();
while (listIter.hasNext()) {
Long tagId = listIter.next();
Long replacerTagId = replacedTagIds.get(tagId);
if (replacerTagId != null) {
listIter.set(replacerTagId);
}
}
}
}
resourceToTagIds.putAll(delta.getResourceToTagIds());
if (MapUtils.isEmpty(resourceToTagIds)) {
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
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={}), tags(total={}, added={}, updated={}, removed={}), tagDefs(total={}, added={}, updated={}, removed={})",
delta.getTagDefinitions().size(), delta.getTags().size(), delta.getServiceResources().size(),
serviceResources.size(), resourcesToAdd.size(), resourcesToRemove.size(),
tags.size(), tagsAdded, tagsUpdated, tagsRemoved,
tagDefs.size(), tagDefsAdded, tagDefsUpdated, tagDefsRemoved);
}
} else {
LOG.debug("Cannot apply deltas to service-tags as one of preconditions is violated. Returning received serviceTags without applying delta!!");
}
LOG.debug("<== RangerServiceTagsDeltaUtil.applyDelta(): serviceTags:[{}], delta:[{}], supportsTagsDedup:[{}]", ret, delta, supportsTagsDedup);
RangerPerfTracer.log(perf);
return ret;
}