You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by ma...@apache.org on 2018/02/13 01:27:34 UTC
atlas git commit: ATLAS-2169: delete request fails when hard-delete
is configured
Repository: atlas
Updated Branches:
refs/heads/master ad6b07a98 -> 154dda0e5
ATLAS-2169: delete request fails when hard-delete is configured
Project: http://git-wip-us.apache.org/repos/asf/atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/154dda0e
Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/154dda0e
Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/154dda0e
Branch: refs/heads/master
Commit: 154dda0e5b03020b405faed8fd37f15654f492f4
Parents: ad6b07a
Author: Madhan Neethiraj <ma...@apache.org>
Authored: Sun Feb 11 02:26:28 2018 -0800
Committer: Madhan Neethiraj <ma...@apache.org>
Committed: Sun Feb 11 22:31:36 2018 -0800
----------------------------------------------------------------------
.../model/instance/EntityMutationResponse.java | 35 +-
.../atlas/repository/graph/GraphHelper.java | 64 +--
.../graph/v1/AtlasEntityChangeNotifier.java | 15 +-
.../store/graph/v1/AtlasEntityStoreV1.java | 14 +-
.../store/graph/v1/DeleteHandlerV1.java | 522 ++++++++++---------
.../store/graph/v1/EntityGraphMapper.java | 50 +-
.../store/graph/v1/EntityGraphRetriever.java | 64 +++
.../java/org/apache/atlas/RequestContextV1.java | 63 +--
8 files changed, 452 insertions(+), 375 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/atlas/blob/154dda0e/intg/src/main/java/org/apache/atlas/model/instance/EntityMutationResponse.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/model/instance/EntityMutationResponse.java b/intg/src/main/java/org/apache/atlas/model/instance/EntityMutationResponse.java
index 05411d6..4589262 100644
--- a/intg/src/main/java/org/apache/atlas/model/instance/EntityMutationResponse.java
+++ b/intg/src/main/java/org/apache/atlas/model/instance/EntityMutationResponse.java
@@ -195,7 +195,7 @@ public class EntityMutationResponse {
public void addEntity(EntityOperation op, AtlasEntityHeader header) {
// if an entity is already included in CREATE, ignore subsequent UPDATE, PARTIAL_UPDATE
if (op == EntityOperation.UPDATE || op == EntityOperation.PARTIAL_UPDATE) {
- if (entityHeaderExists(getCreatedEntities(), header)) {
+ if (entityHeaderExists(getCreatedEntities(), header.getGuid())) {
return;
}
}
@@ -211,17 +211,42 @@ public class EntityMutationResponse {
mutatedEntities.put(op, opEntities);
}
- if (!entityHeaderExists(opEntities, header)) {
+ if (!entityHeaderExists(opEntities, header.getGuid())) {
opEntities.add(header);
}
}
- private boolean entityHeaderExists(List<AtlasEntityHeader> entityHeaders, AtlasEntityHeader newEntityHeader) {
+ @JsonIgnore
+ public void addEntity(EntityOperation op, AtlasObjectId entity) {
+ if (mutatedEntities == null) {
+ mutatedEntities = new HashMap<>();
+ } else {
+ // if an entity is already included in CREATE, ignore subsequent UPDATE, PARTIAL_UPDATE
+ if (op == EntityOperation.UPDATE || op == EntityOperation.PARTIAL_UPDATE) {
+ if (entityHeaderExists(getCreatedEntities(), entity.getGuid())) {
+ return;
+ }
+ }
+ }
+
+ List<AtlasEntityHeader> opEntities = mutatedEntities.get(op);
+
+ if (opEntities == null) {
+ opEntities = new ArrayList<>();
+ mutatedEntities.put(op, opEntities);
+ }
+
+ if (!entityHeaderExists(opEntities, entity.getGuid())) {
+ opEntities.add(new AtlasEntityHeader(entity.getTypeName(), entity.getGuid(), entity.getUniqueAttributes()));
+ }
+ }
+
+ private boolean entityHeaderExists(List<AtlasEntityHeader> entityHeaders, String guid) {
boolean ret = false;
- if (CollectionUtils.isNotEmpty(entityHeaders) && newEntityHeader != null) {
+ if (CollectionUtils.isNotEmpty(entityHeaders) && guid != null) {
for (AtlasEntityHeader entityHeader : entityHeaders) {
- if (StringUtils.equals(entityHeader.getGuid(), newEntityHeader.getGuid())) {
+ if (StringUtils.equals(entityHeader.getGuid(), guid)) {
ret = true;
break;
}
http://git-wip-us.apache.org/repos/asf/atlas/blob/154dda0e/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java b/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java
index 4d2b284..d61bff2 100755
--- a/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java
+++ b/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java
@@ -68,9 +68,6 @@ import java.util.Objects;
import java.util.Set;
import java.util.UUID;
-import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.BOTH;
-import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.IN;
-import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.OUT;
/**
* Utility class for graph operations.
@@ -888,24 +885,23 @@ public final class GraphHelper {
* Guid and AtlasVertex combo
*/
public static class VertexInfo {
- private String guid;
- private AtlasVertex vertex;
- private String typeName;
+ private final AtlasObjectId entity;
+ private final AtlasVertex vertex;
- public VertexInfo(String guid, AtlasVertex vertex, String typeName) {
- this.guid = guid;
+ public VertexInfo(AtlasObjectId entity, AtlasVertex vertex) {
+ this.entity = entity;
this.vertex = vertex;
- this.typeName = typeName;
}
- public String getGuid() {
- return guid;
- }
+ public AtlasObjectId getEntity() { return entity; }
public AtlasVertex getVertex() {
return vertex;
}
+ public String getGuid() {
+ return entity.getGuid();
+ }
public String getTypeName() {
- return typeName;
+ return entity.getTypeName();
}
@Override
@@ -913,14 +909,13 @@ public final class GraphHelper {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
VertexInfo that = (VertexInfo) o;
- return Objects.equals(guid, that.guid) &&
- Objects.equals(vertex, that.vertex) &&
- Objects.equals(typeName, that.typeName);
+ return Objects.equals(entity, that.entity) &&
+ Objects.equals(vertex, that.vertex);
}
@Override
public int hashCode() {
- return Objects.hash(guid, vertex, typeName);
+ return Objects.hash(entity, vertex);
}
}
@@ -1304,39 +1299,4 @@ public final class GraphHelper {
return StringUtils.isNotEmpty(edge.getLabel()) ? edgeLabel.startsWith("r:") : false;
}
-
- public static AtlasObjectId getReferenceObjectId(AtlasEdge edge, AtlasRelationshipEdgeDirection relationshipDirection,
- AtlasVertex parentVertex) {
- AtlasObjectId ret = null;
-
- if (relationshipDirection == OUT) {
- ret = getAtlasObjectIdForInVertex(edge);
-
- } else if (relationshipDirection == IN) {
- ret = getAtlasObjectIdForOutVertex(edge);
-
- } else if (relationshipDirection == BOTH){
- // since relationship direction is BOTH, edge direction can be inward or outward
- // compare with parent entity vertex and pick the right reference vertex
- if (verticesEquals(parentVertex, edge.getOutVertex())) {
- ret = getAtlasObjectIdForInVertex(edge);
- } else {
- ret = getAtlasObjectIdForOutVertex(edge);
- }
- }
-
- return ret;
- }
-
- public static AtlasObjectId getAtlasObjectIdForOutVertex(AtlasEdge edge) {
- return new AtlasObjectId(getGuid(edge.getOutVertex()), getTypeName(edge.getOutVertex()));
- }
-
- public static AtlasObjectId getAtlasObjectIdForInVertex(AtlasEdge edge) {
- return new AtlasObjectId(getGuid(edge.getInVertex()), getTypeName(edge.getInVertex()));
- }
-
- private static boolean verticesEquals(AtlasVertex vertexA, AtlasVertex vertexB) {
- return StringUtils.equals(getGuid(vertexB), getGuid(vertexA));
- }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/atlas/blob/154dda0e/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityChangeNotifier.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityChangeNotifier.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityChangeNotifier.java
index 1bda8ff..2b6bead 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityChangeNotifier.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityChangeNotifier.java
@@ -158,7 +158,7 @@ public class AtlasEntityChangeNotifier {
return;
}
- List<Referenceable> typedRefInsts = toReferenceables(entityHeaders);
+ List<Referenceable> typedRefInsts = toReferenceables(entityHeaders, operation);
for (EntityChangeListener listener : entityChangeListeners) {
try {
@@ -180,11 +180,18 @@ public class AtlasEntityChangeNotifier {
}
}
- private List<Referenceable> toReferenceables(List<AtlasEntityHeader> entityHeaders) throws AtlasBaseException {
+ private List<Referenceable> toReferenceables(List<AtlasEntityHeader> entityHeaders, EntityOperation operation) throws AtlasBaseException {
List<Referenceable> ret = new ArrayList<>(entityHeaders.size());
- for (AtlasEntityHeader entityHeader : entityHeaders) {
- ret.add(toReferenceable(entityHeader.getGuid()));
+ // delete notifications don't need all attributes. Hence the special handling for delete operation
+ if (operation == EntityOperation.DELETE) {
+ for (AtlasEntityHeader entityHeader : entityHeaders) {
+ ret.add(new Referenceable(entityHeader.getGuid(), entityHeader.getTypeName(), entityHeader.getAttributes()));
+ }
+ } else {
+ for (AtlasEntityHeader entityHeader : entityHeaders) {
+ ret.add(toReferenceable(entityHeader.getGuid()));
+ }
}
return ret;
http://git-wip-us.apache.org/repos/asf/atlas/blob/154dda0e/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1.java
index 3a6f733..ca0eeeb 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1.java
@@ -647,14 +647,16 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
private EntityMutationResponse deleteVertices(Collection<AtlasVertex> deletionCandidates) throws AtlasBaseException {
EntityMutationResponse response = new EntityMutationResponse();
- deleteHandler.deleteEntities(deletionCandidates);
- RequestContextV1 req = RequestContextV1.get();
- for (AtlasObjectId id : req.getDeletedEntityIds()) {
- response.addEntity(DELETE, EntityGraphMapper.constructHeader(id));
+ RequestContextV1 req = RequestContextV1.get();
+
+ deleteHandler.deleteEntities(deletionCandidates); // this will update req with list of deleted/updated entities
+
+ for (AtlasObjectId entity : req.getDeletedEntities()) {
+ response.addEntity(DELETE, entity);
}
- for (AtlasObjectId id : req.getUpdatedEntityIds()) {
- response.addEntity(UPDATE, EntityGraphMapper.constructHeader(id));
+ for (AtlasObjectId entity : req.getUpdatedEntities()) {
+ response.addEntity(UPDATE, entity);
}
return response;
http://git-wip-us.apache.org/repos/asf/atlas/blob/154dda0e/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/DeleteHandlerV1.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/DeleteHandlerV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/DeleteHandlerV1.java
index e011c78..2b62a68 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/DeleteHandlerV1.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/DeleteHandlerV1.java
@@ -43,38 +43,30 @@ import org.apache.atlas.type.AtlasTypeRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.Stack;
+import java.util.*;
import static org.apache.atlas.model.instance.AtlasEntity.Status.DELETED;
import static org.apache.atlas.repository.graph.GraphHelper.EDGE_LABEL_PREFIX;
-import static org.apache.atlas.repository.graph.GraphHelper.getReferenceObjectId;
import static org.apache.atlas.repository.graph.GraphHelper.isRelationshipEdge;
import static org.apache.atlas.repository.graph.GraphHelper.string;
import static org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1.getIdFromEdge;
import static org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1.getState;
public abstract class DeleteHandlerV1 {
-
public static final Logger LOG = LoggerFactory.getLogger(DeleteHandlerV1.class);
- private AtlasTypeRegistry typeRegistry;
- private boolean shouldUpdateInverseReferences;
- private boolean softDelete;
+ private final AtlasTypeRegistry typeRegistry;
+ private final EntityGraphRetriever entityRetriever;
+ private final boolean shouldUpdateInverseReferences;
+ private final boolean softDelete;
protected static final GraphHelper graphHelper = GraphHelper.getInstance();
public DeleteHandlerV1(AtlasTypeRegistry typeRegistry, boolean shouldUpdateInverseReference, boolean softDelete) {
- this.typeRegistry = typeRegistry;
+ this.typeRegistry = typeRegistry;
+ this.entityRetriever = new EntityGraphRetriever(typeRegistry);
this.shouldUpdateInverseReferences = shouldUpdateInverseReference;
- this.softDelete = softDelete;
+ this.softDelete = softDelete;
}
/**
@@ -86,34 +78,25 @@ public abstract class DeleteHandlerV1 {
* @throws AtlasException
*/
public void deleteEntities(Collection<AtlasVertex> instanceVertices) throws AtlasBaseException {
- RequestContextV1 requestContext = RequestContextV1.get();
-
+ RequestContextV1 requestContext = RequestContextV1.get();
Set<AtlasVertex> deletionCandidateVertices = new HashSet<>();
for (AtlasVertex instanceVertex : instanceVertices) {
String guid = AtlasGraphUtilsV1.getIdFromVertex(instanceVertex);
AtlasEntity.Status state = getState(instanceVertex);
- if (state == DELETED) {
- LOG.debug("Skipping deletion of {} as it is already deleted", guid);
- continue;
- }
-
- String typeName = AtlasGraphUtilsV1.getTypeName(instanceVertex);
- AtlasObjectId objId = new AtlasObjectId(guid, typeName);
+ if (state == DELETED || requestContext.isDeletedEntity(guid)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Skipping deletion of {} as it is already deleted", guid);
+ }
- if (requestContext.getDeletedEntityIds().contains(objId)) {
- LOG.debug("Skipping deletion of {} as it is already deleted", guid);
continue;
}
- // Get GUIDs and vertices for all deletion candidates.
- Set<GraphHelper.VertexInfo> compositeVertices = getOwnedVertices(instanceVertex);
-
- // Record all deletion candidate GUIDs in RequestContext
+ // Record all deletion candidate entities in RequestContext
// and gather deletion candidate vertices.
- for (GraphHelper.VertexInfo vertexInfo : compositeVertices) {
- requestContext.recordEntityDelete(new AtlasObjectId(vertexInfo.getGuid(), vertexInfo.getTypeName()));
+ for (GraphHelper.VertexInfo vertexInfo : getOwnedVertices(instanceVertex)) {
+ requestContext.recordEntityDelete(vertexInfo.getEntity());
deletionCandidateVertices.add(vertexInfo.getVertex());
}
}
@@ -134,7 +117,10 @@ public abstract class DeleteHandlerV1 {
public void deleteRelationships(Collection<AtlasEdge> edges) throws AtlasBaseException {
for (AtlasEdge edge : edges) {
if (getState(edge) == DELETED) {
- LOG.debug("Skipping deletion of {} as it is already deleted", getIdFromEdge(edge));
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Skipping deletion of {} as it is already deleted", getIdFromEdge(edge));
+ }
+
continue;
}
@@ -150,83 +136,104 @@ public abstract class DeleteHandlerV1 {
* @return set of VertexInfo for all composite entities
* @throws AtlasException
*/
- public Set<GraphHelper.VertexInfo> getOwnedVertices(AtlasVertex entityVertex) throws AtlasBaseException {
- Set<GraphHelper.VertexInfo> result = new LinkedHashSet<>();
- Stack<AtlasVertex> vertices = new Stack<>();
+ public Collection<GraphHelper.VertexInfo> getOwnedVertices(AtlasVertex entityVertex) throws AtlasBaseException {
+ Map<String, GraphHelper.VertexInfo> vertexInfoMap = new HashMap<>();
+ Stack<AtlasVertex> vertices = new Stack<>();
+
vertices.push(entityVertex);
+
while (vertices.size() > 0) {
- AtlasVertex vertex = vertices.pop();
+ AtlasVertex vertex = vertices.pop();
+ AtlasEntity.Status state = getState(vertex);
- AtlasEntity.Status state = getState(vertex);
if (state == DELETED) {
//If the reference vertex is marked for deletion, skip it
continue;
}
- String typeName = GraphHelper.getTypeName(vertex);
String guid = GraphHelper.getGuid(vertex);
- result.add(new GraphHelper.VertexInfo(guid, vertex, typeName));
+ if (vertexInfoMap.containsKey(guid)) {
+ continue;
+ }
+
+ AtlasObjectId entity = entityRetriever.toAtlasObjectId(vertex);
+ String typeName = entity.getTypeName();
AtlasEntityType entityType = typeRegistry.getEntityTypeByName(typeName);
if (entityType == null) {
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, TypeCategory.ENTITY.name(), typeName);
}
+ vertexInfoMap.put(guid, new GraphHelper.VertexInfo(entity, vertex));
+
for (AtlasStructType.AtlasAttribute attributeInfo : entityType.getAllAttributes().values()) {
if (! attributeInfo.isOwnedRef()) {
continue;
}
- String edgeLabel = AtlasGraphUtilsV1.getAttributeEdgeLabel(entityType, attributeInfo.getName());
- AtlasType attrType = attributeInfo.getAttributeType();
+
+ String edgeLabel = AtlasGraphUtilsV1.getAttributeEdgeLabel(entityType, attributeInfo.getName());
+ AtlasType attrType = attributeInfo.getAttributeType();
+
switch (attrType.getTypeCategory()) {
- case OBJECT_ID_TYPE:
- AtlasEdge edge = graphHelper.getEdgeForLabel(vertex, edgeLabel);
- if (edge != null && getState(edge) == AtlasEntity.Status.ACTIVE) {
- AtlasVertex compositeVertex = edge.getInVertex();
- vertices.push(compositeVertex);
+ case OBJECT_ID_TYPE: {
+ AtlasEdge edge = graphHelper.getEdgeForLabel(vertex, edgeLabel);
+
+ if (edge != null && getState(edge) == AtlasEntity.Status.ACTIVE) {
+ vertices.push(edge.getInVertex());
+ }
}
break;
- case ARRAY:
- AtlasArrayType arrType = (AtlasArrayType) attrType;
- if (arrType.getElementType().getTypeCategory() != TypeCategory.OBJECT_ID_TYPE) {
- continue;
- }
- Iterator<AtlasEdge> edges = graphHelper.getOutGoingEdgesByLabel(vertex, edgeLabel);
- if (edges != null) {
- while (edges.hasNext()) {
- edge = edges.next();
- if (edge != null && getState(edge) == AtlasEntity.Status.ACTIVE) {
- AtlasVertex compositeVertex = edge.getInVertex();
- vertices.push(compositeVertex);
+
+ case ARRAY: {
+ AtlasArrayType arrType = (AtlasArrayType) attrType;
+
+ if (arrType.getElementType().getTypeCategory() != TypeCategory.OBJECT_ID_TYPE) {
+ continue;
+ }
+
+ Iterator<AtlasEdge> edges = graphHelper.getOutGoingEdgesByLabel(vertex, edgeLabel);
+
+ if (edges != null) {
+ while (edges.hasNext()) {
+ AtlasEdge edge = edges.next();
+
+ if (edge != null && getState(edge) == AtlasEntity.Status.ACTIVE) {
+ vertices.push(edge.getInVertex());
+ }
}
}
}
break;
- case MAP:
- AtlasMapType mapType = (AtlasMapType) attrType;
- TypeCategory valueTypeCategory = mapType.getValueType().getTypeCategory();
- if (valueTypeCategory != TypeCategory.OBJECT_ID_TYPE) {
- continue;
- }
- String propertyName = AtlasGraphUtilsV1.getQualifiedAttributePropertyKey(entityType, attributeInfo.getName());
- List<String> keys = vertex.getProperty(propertyName, List.class);
- if (keys != null) {
- for (String key : keys) {
- String mapEdgeLabel = GraphHelper.getQualifiedNameForMapKey(edgeLabel, key);
- edge = graphHelper.getEdgeForLabel(vertex, mapEdgeLabel);
- if (edge != null && getState(edge) == AtlasEntity.Status.ACTIVE) {
- AtlasVertex compositeVertex = edge.getInVertex();
- vertices.push(compositeVertex);
+
+ case MAP: {
+ AtlasMapType mapType = (AtlasMapType) attrType;
+ TypeCategory valueTypeCategory = mapType.getValueType().getTypeCategory();
+
+ if (valueTypeCategory != TypeCategory.OBJECT_ID_TYPE) {
+ continue;
+ }
+
+ String propertyName = AtlasGraphUtilsV1.getQualifiedAttributePropertyKey(entityType, attributeInfo.getName());
+ List<String> keys = vertex.getProperty(propertyName, List.class);
+
+ if (keys != null) {
+ for (String key : keys) {
+ String mapEdgeLabel = GraphHelper.getQualifiedNameForMapKey(edgeLabel, key);
+ AtlasEdge edge = graphHelper.getEdgeForLabel(vertex, mapEdgeLabel);
+
+ if (edge != null && getState(edge) == AtlasEntity.Status.ACTIVE) {
+ vertices.push(edge.getInVertex());
+ }
}
}
}
break;
- default:
}
}
}
- return result;
+
+ return vertexInfoMap.values();
}
/**
@@ -240,19 +247,19 @@ public abstract class DeleteHandlerV1 {
*/
public boolean deleteEdgeReference(AtlasEdge edge, TypeCategory typeCategory, boolean isOwned,
boolean forceDeleteStructTrait, AtlasVertex vertex) throws AtlasBaseException {
-
// default edge direction is outward
return deleteEdgeReference(edge, typeCategory, isOwned, forceDeleteStructTrait, AtlasRelationshipEdgeDirection.OUT, vertex);
}
public boolean deleteEdgeReference(AtlasEdge edge, TypeCategory typeCategory, boolean isOwned, boolean forceDeleteStructTrait,
AtlasRelationshipEdgeDirection relationshipDirection, AtlasVertex entityVertex) throws AtlasBaseException {
- LOG.debug("Deleting {}", string(edge));
- boolean forceDelete =
- (typeCategory == TypeCategory.STRUCT || typeCategory == TypeCategory.CLASSIFICATION) && forceDeleteStructTrait;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Deleting {}", string(edge));
+ }
- if (typeCategory == TypeCategory.STRUCT || typeCategory == TypeCategory.CLASSIFICATION
- || (typeCategory == TypeCategory.OBJECT_ID_TYPE && isOwned)) {
+ boolean forceDelete = (typeCategory == TypeCategory.STRUCT || typeCategory == TypeCategory.CLASSIFICATION) && forceDeleteStructTrait;
+
+ if (typeCategory == TypeCategory.STRUCT || typeCategory == TypeCategory.CLASSIFICATION || (typeCategory == TypeCategory.OBJECT_ID_TYPE && isOwned)) {
//If the vertex is of type struct/trait, delete the edge and then the reference vertex as the vertex is not shared by any other entities.
//If the vertex is of type class, and its composite attribute, this reference vertex' lifecycle is controlled
//through this delete, hence delete the edge and the reference vertex.
@@ -270,8 +277,18 @@ public abstract class DeleteHandlerV1 {
if (isRelationshipEdge(edge)) {
deleteEdge(edge, false);
- AtlasObjectId deletedReferenceObjectId = getReferenceObjectId(edge, relationshipDirection, entityVertex);
- RequestContextV1.get().recordEntityUpdate(deletedReferenceObjectId);
+ AtlasVertex referencedVertex = entityRetriever.getReferencedEntityVertex(edge, relationshipDirection, entityVertex);
+
+ if (referencedVertex != null) {
+ RequestContextV1 requestContext = RequestContextV1.get();
+
+ if (!requestContext.isUpdatedEntity(GraphHelper.getGuid(referencedVertex))) {
+ GraphHelper.setProperty(referencedVertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, requestContext.getRequestTime());
+ GraphHelper.setProperty(referencedVertex, Constants.MODIFIED_BY_KEY, requestContext.getUser());
+
+ requestContext.recordEntityUpdate(entityRetriever.toAtlasObjectId(referencedVertex));
+ }
+ }
} else {
//legacy case - not a relationship edge
//If deleting just the edge, reverse attribute should be updated for any references
@@ -279,6 +296,7 @@ public abstract class DeleteHandlerV1 {
deleteEdge(edge, true, false);
}
}
+
return !softDelete || forceDelete;
}
@@ -286,13 +304,12 @@ public abstract class DeleteHandlerV1 {
//update inverse attribute
if (updateInverseAttribute) {
AtlasEdgeLabel atlasEdgeLabel = new AtlasEdgeLabel(edge.getLabel());
-
- AtlasType parentType = typeRegistry.getType(atlasEdgeLabel.getTypeName());
+ AtlasType parentType = typeRegistry.getType(atlasEdgeLabel.getTypeName());
if (parentType instanceof AtlasEntityType) {
- AtlasEntityType parentEntityType = (AtlasEntityType) parentType;
+ AtlasEntityType parentEntityType = (AtlasEntityType) parentType;
+ AtlasStructType.AtlasAttribute attribute = parentEntityType.getAttribute(atlasEdgeLabel.getAttributeName());
- AtlasStructType.AtlasAttribute attribute = parentEntityType.getAttribute(atlasEdgeLabel.getAttributeName());
if (attribute.getInverseRefAttribute() != null) {
deleteEdgeBetweenVertices(edge.getInVertex(), edge.getOutVertex(), attribute.getInverseRefAttribute());
}
@@ -305,18 +322,18 @@ public abstract class DeleteHandlerV1 {
protected void deleteTypeVertex(AtlasVertex instanceVertex, TypeCategory typeCategory, boolean force) throws AtlasBaseException {
switch (typeCategory) {
- case STRUCT:
- case CLASSIFICATION:
- deleteTypeVertex(instanceVertex, force);
+ case STRUCT:
+ case CLASSIFICATION:
+ deleteTypeVertex(instanceVertex, force);
break;
- case ENTITY:
- case OBJECT_ID_TYPE:
- deleteEntities(Collections.singletonList(instanceVertex));
+ case ENTITY:
+ case OBJECT_ID_TYPE:
+ deleteEntities(Collections.singletonList(instanceVertex));
break;
- default:
- throw new IllegalStateException("Type category " + typeCategory + " not handled");
+ default:
+ throw new IllegalStateException("Type category " + typeCategory + " not handled");
}
}
@@ -326,10 +343,11 @@ public abstract class DeleteHandlerV1 {
* @throws AtlasException
*/
protected void deleteTypeVertex(AtlasVertex instanceVertex, boolean force) throws AtlasBaseException {
- LOG.debug("Deleting {}", string(instanceVertex));
- String typeName = GraphHelper.getTypeName(instanceVertex);
-
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Deleting {}", string(instanceVertex));
+ }
+ String typeName = GraphHelper.getTypeName(instanceVertex);
AtlasType parentType = typeRegistry.getType(typeName);
if (parentType instanceof AtlasStructType) {
@@ -337,55 +355,62 @@ public abstract class DeleteHandlerV1 {
boolean isEntityType = (parentType instanceof AtlasEntityType);
for (AtlasStructType.AtlasAttribute attributeInfo : structType.getAllAttributes().values()) {
- LOG.debug("Deleting attribute {} for {}", attributeInfo.getName(), string(instanceVertex));
- boolean isOwned = isEntityType && attributeInfo.isOwnedRef();
-
- AtlasType attrType = attributeInfo.getAttributeType();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Deleting attribute {} for {}", attributeInfo.getName(), string(instanceVertex));
+ }
- String edgeLabel = AtlasGraphUtilsV1.getAttributeEdgeLabel(structType, attributeInfo.getName());
+ boolean isOwned = isEntityType && attributeInfo.isOwnedRef();
+ AtlasType attrType = attributeInfo.getAttributeType();
+ String edgeLabel = AtlasGraphUtilsV1.getAttributeEdgeLabel(structType, attributeInfo.getName());
switch (attrType.getTypeCategory()) {
- case OBJECT_ID_TYPE:
- //If its class attribute, delete the reference
- deleteEdgeReference(instanceVertex, edgeLabel, attrType.getTypeCategory(), isOwned);
+ case OBJECT_ID_TYPE:
+ //If its class attribute, delete the reference
+ deleteEdgeReference(instanceVertex, edgeLabel, attrType.getTypeCategory(), isOwned);
break;
- case STRUCT:
- //If its struct attribute, delete the reference
- deleteEdgeReference(instanceVertex, edgeLabel, attrType.getTypeCategory(), false);
+ case STRUCT:
+ //If its struct attribute, delete the reference
+ deleteEdgeReference(instanceVertex, edgeLabel, attrType.getTypeCategory(), false);
break;
- case ARRAY:
- //For array attribute, if the element is struct/class, delete all the references
- AtlasArrayType arrType = (AtlasArrayType) attrType;
- AtlasType elemType = arrType.getElementType();
- if (AtlasGraphUtilsV1.isReference(elemType.getTypeCategory())) {
- Iterator<AtlasEdge> edges = graphHelper.getOutGoingEdgesByLabel(instanceVertex, edgeLabel);
- if (edges != null) {
- while (edges.hasNext()) {
- AtlasEdge edge = edges.next();
- deleteEdgeReference(edge, elemType.getTypeCategory(), isOwned, false, instanceVertex);
+ case ARRAY:
+ //For array attribute, if the element is struct/class, delete all the references
+ AtlasArrayType arrType = (AtlasArrayType) attrType;
+ AtlasType elemType = arrType.getElementType();
+
+ if (AtlasGraphUtilsV1.isReference(elemType.getTypeCategory())) {
+ Iterator<AtlasEdge> edges = graphHelper.getOutGoingEdgesByLabel(instanceVertex, edgeLabel);
+
+ if (edges != null) {
+ while (edges.hasNext()) {
+ AtlasEdge edge = edges.next();
+
+ deleteEdgeReference(edge, elemType.getTypeCategory(), isOwned, false, instanceVertex);
+ }
}
}
- }
break;
- case MAP:
- //For map attribute, if the value type is struct/class, delete all the references
- AtlasMapType mapType = (AtlasMapType) attrType;
- AtlasType keyType = mapType.getKeyType();
- TypeCategory valueTypeCategory = mapType.getValueType().getTypeCategory();
- String propertyName = AtlasGraphUtilsV1.getQualifiedAttributePropertyKey(structType, attributeInfo.getName());
+ case MAP:
+ //For map attribute, if the value type is struct/class, delete all the references
+ AtlasMapType mapType = (AtlasMapType) attrType;
+ AtlasType keyType = mapType.getKeyType();
+ TypeCategory valueTypeCategory = mapType.getValueType().getTypeCategory();
+ String propertyName = AtlasGraphUtilsV1.getQualifiedAttributePropertyKey(structType, attributeInfo.getName());
- if (AtlasGraphUtilsV1.isReference(valueTypeCategory)) {
- List<Object> keys = EntityGraphMapper.getArrayElementsProperty(keyType, instanceVertex, propertyName);
- if (keys != null) {
- for (Object key : keys) {
- String mapEdgeLabel = GraphHelper.getQualifiedNameForMapKey(edgeLabel, (String) key);
- deleteEdgeReference(instanceVertex, mapEdgeLabel, valueTypeCategory, isOwned);
+ if (AtlasGraphUtilsV1.isReference(valueTypeCategory)) {
+ List<Object> keys = EntityGraphMapper.getArrayElementsProperty(keyType, instanceVertex, propertyName);
+
+ if (keys != null) {
+ for (Object key : keys) {
+ String mapEdgeLabel = GraphHelper.getQualifiedNameForMapKey(edgeLabel, (String) key);
+
+ deleteEdgeReference(instanceVertex, mapEdgeLabel, valueTypeCategory, isOwned);
+ }
}
}
- }
+ break;
}
}
}
@@ -393,9 +418,9 @@ public abstract class DeleteHandlerV1 {
deleteVertex(instanceVertex, force);
}
- public void deleteEdgeReference(AtlasVertex outVertex, String edgeLabel, TypeCategory typeCategory,
- boolean isOwned) throws AtlasBaseException {
+ public void deleteEdgeReference(AtlasVertex outVertex, String edgeLabel, TypeCategory typeCategory, boolean isOwned) throws AtlasBaseException {
AtlasEdge edge = graphHelper.getEdgeForLabel(outVertex, edgeLabel);
+
if (edge != null) {
deleteEdgeReference(edge, typeCategory, isOwned, false, outVertex);
}
@@ -407,20 +432,23 @@ public abstract class DeleteHandlerV1 {
* @throws AtlasException
*/
private void deleteAllTraits(AtlasVertex instanceVertex) throws AtlasBaseException {
+ String typeName = GraphHelper.getTypeName(instanceVertex);
List<String> traitNames = GraphHelper.getTraitNames(instanceVertex);
- LOG.debug("Deleting traits {} for {}", traitNames, string(instanceVertex));
- String typeName = GraphHelper.getTypeName(instanceVertex);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Deleting traits {} for {}", traitNames, string(instanceVertex));
+ }
for (String traitNameToBeDeleted : traitNames) {
String relationshipLabel = GraphHelper.getTraitLabel(typeName, traitNameToBeDeleted);
+
deleteEdgeReference(instanceVertex, relationshipLabel, TypeCategory.CLASSIFICATION, false);
}
}
protected AtlasAttribute getAttributeForEdge(String edgeLabel) throws AtlasBaseException {
- AtlasEdgeLabel atlasEdgeLabel = new AtlasEdgeLabel(edgeLabel);
-
- AtlasType parentType = typeRegistry.getType(atlasEdgeLabel.getTypeName());
+ AtlasEdgeLabel atlasEdgeLabel = new AtlasEdgeLabel(edgeLabel);
+ AtlasType parentType = typeRegistry.getType(atlasEdgeLabel.getTypeName());
AtlasStructType parentStructType = (AtlasStructType) parentType;
return parentStructType.getAttribute(atlasEdgeLabel.getAttributeName());
@@ -438,148 +466,161 @@ public abstract class DeleteHandlerV1 {
* @throws AtlasException
*/
protected void deleteEdgeBetweenVertices(AtlasVertex outVertex, AtlasVertex inVertex, AtlasAttribute attribute) throws AtlasBaseException {
- LOG.debug("Removing edge from {} to {} with attribute name {}", string(outVertex), string(inVertex),
- attribute.getName());
- String typeName = GraphHelper.getTypeName(outVertex);
- String outId = GraphHelper.getGuid(outVertex);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Removing edge from {} to {} with attribute name {}", string(outVertex), string(inVertex), attribute.getName());
+ }
- AtlasObjectId objId = new AtlasObjectId(outId, typeName);
- AtlasEntity.Status state = getState(outVertex);
+ final String typeName = GraphHelper.getTypeName(outVertex);
+ final String outId = GraphHelper.getGuid(outVertex);
+ final AtlasEntity.Status state = getState(outVertex);
- if (state == DELETED || (outId != null && RequestContextV1.get().isDeletedEntity(objId))) {
+ if (state == DELETED || (outId != null && RequestContextV1.get().isDeletedEntity(outId))) {
//If the reference vertex is marked for deletion, skip updating the reference
return;
}
- AtlasStructType parentType = (AtlasStructType) typeRegistry.getType(typeName);
- String propertyName = AtlasGraphUtilsV1.getQualifiedAttributePropertyKey(parentType, attribute.getName());
- String edgeLabel = EDGE_LABEL_PREFIX + propertyName;
- AtlasEdge edge = null;
-
- AtlasAttributeDef attrDef = attribute.getAttributeDef();
- AtlasType attrType = attribute.getAttributeType();
+ AtlasStructType parentType = (AtlasStructType) typeRegistry.getType(typeName);
+ String propertyName = AtlasGraphUtilsV1.getQualifiedAttributePropertyKey(parentType, attribute.getName());
+ String edgeLabel = EDGE_LABEL_PREFIX + propertyName;
+ AtlasEdge edge = null;
+ AtlasAttributeDef attrDef = attribute.getAttributeDef();
+ AtlasType attrType = attribute.getAttributeType();
switch (attrType.getTypeCategory()) {
- case OBJECT_ID_TYPE:
- //If its class attribute, its the only edge between two vertices
- if (attrDef.getIsOptional()) {
- edge = graphHelper.getEdgeForLabel(outVertex, edgeLabel);
- if (shouldUpdateInverseReferences) {
- GraphHelper.setProperty(outVertex, propertyName, null);
+ case OBJECT_ID_TYPE: {
+ //If its class attribute, its the only edge between two vertices
+ if (attrDef.getIsOptional()) {
+ edge = graphHelper.getEdgeForLabel(outVertex, edgeLabel);
+
+ if (shouldUpdateInverseReferences) {
+ GraphHelper.setProperty(outVertex, propertyName, null);
+ }
+ } else {
+ // Cannot unset a required attribute.
+ throw new AtlasBaseException("Cannot unset required attribute " + propertyName + " on " + GraphHelper.vertexString(outVertex) + " edge = " + edgeLabel);
}
- } else {
- // Cannot unset a required attribute.
- throw new AtlasBaseException("Cannot unset required attribute " + propertyName +
- " on " + GraphHelper.vertexString(outVertex) + " edge = " + edgeLabel);
}
break;
- case ARRAY:
- //If its array attribute, find the right edge between the two vertices and update array property
- List<String> elements = GraphHelper.getListProperty(outVertex, propertyName);
- if (elements != null) {
- elements = new ArrayList<>(elements); //Make a copy, else list.remove reflects on titan.getProperty()
- for (String elementEdgeId : elements) {
- AtlasEdge elementEdge = graphHelper.getEdgeByEdgeId(outVertex, edgeLabel, elementEdgeId);
- if (elementEdge == null) {
- continue;
- }
+ case ARRAY: {
+ //If its array attribute, find the right edge between the two vertices and update array property
+ List<String> elements = GraphHelper.getListProperty(outVertex, propertyName);
- AtlasVertex elementVertex = elementEdge.getInVertex();
- if (elementVertex.equals(inVertex)) {
- edge = elementEdge;
-
- //TODO element.size includes deleted items as well. should exclude
- if (!attrDef.getIsOptional()
- && elements.size() <= attrDef.getValuesMinCount()) {
- // Deleting this edge would violate the attribute's lower bound.
- throw new AtlasBaseException(
- "Cannot remove array element from required attribute " +
- propertyName + " on "
- + GraphHelper.getVertexDetails(outVertex) + " " + GraphHelper.getEdgeDetails(elementEdge));
+ if (elements != null) {
+ elements = new ArrayList<>(elements); //Make a copy, else list.remove reflects on titan.getProperty()
+
+ for (String elementEdgeId : elements) {
+ AtlasEdge elementEdge = graphHelper.getEdgeByEdgeId(outVertex, edgeLabel, elementEdgeId);
+
+ if (elementEdge == null) {
+ continue;
}
- if (shouldUpdateInverseReferences) {
- //if composite attribute, remove the reference as well. else, just remove the edge
- //for example, when table is deleted, process still references the table
- //but when column is deleted, table will not reference the deleted column
- LOG.debug("Removing edge {} from the array attribute {}", string(elementEdge),
- attribute.getName());
- // Remove all occurrences of the edge ID from the list.
- // This prevents dangling edge IDs (i.e. edge IDs for deleted edges)
- // from the remaining in the list if there are duplicates.
- elements.removeAll(Collections.singletonList(elementEdge.getId().toString()));
- GraphHelper.setProperty(outVertex, propertyName, elements);
- break;
+ AtlasVertex elementVertex = elementEdge.getInVertex();
+
+ if (elementVertex.equals(inVertex)) {
+ edge = elementEdge;
+ //TODO element.size includes deleted items as well. should exclude
+ if (!attrDef.getIsOptional() && elements.size() <= attrDef.getValuesMinCount()) {
+ // Deleting this edge would violate the attribute's lower bound.
+ throw new AtlasBaseException("Cannot remove array element from required attribute " + propertyName + " on " + GraphHelper.getVertexDetails(outVertex) + " " + GraphHelper.getEdgeDetails(elementEdge));
+ }
+
+ if (shouldUpdateInverseReferences) {
+ //if composite attribute, remove the reference as well. else, just remove the edge
+ //for example, when table is deleted, process still references the table
+ //but when column is deleted, table will not reference the deleted column
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Removing edge {} from the array attribute {}", string(elementEdge), attribute.getName());
+ }
+
+ // Remove all occurrences of the edge ID from the list.
+ // This prevents dangling edge IDs (i.e. edge IDs for deleted edges)
+ // from the remaining in the list if there are duplicates.
+ elements.removeAll(Collections.singletonList(elementEdge.getId().toString()));
+ GraphHelper.setProperty(outVertex, propertyName, elements);
+ break;
+ }
}
}
}
}
break;
- case MAP:
- //If its map attribute, find the right edge between two vertices and update map property
- List<String> keys = GraphHelper.getListProperty(outVertex, propertyName);
- if (keys != null) {
- keys = new ArrayList<>(keys); //Make a copy, else list.remove reflects on titan.getProperty()
- for (String key : keys) {
- String keyPropertyName = GraphHelper.getQualifiedNameForMapKey(propertyName, key);
- String mapEdgeId = GraphHelper.getSingleValuedProperty(outVertex, keyPropertyName, String.class);
- AtlasEdge mapEdge = graphHelper.getEdgeByEdgeId(outVertex, keyPropertyName, mapEdgeId);
- if(mapEdge != null) {
- AtlasVertex mapVertex = mapEdge.getInVertex();
- if (mapVertex.getId().toString().equals(inVertex.getId().toString())) {
- //TODO keys.size includes deleted items as well. should exclude
- if (attrDef.getIsOptional() || keys.size() > attrDef.getValuesMinCount()) {
- edge = mapEdge;
- } else {
- // Deleting this entry would violate the attribute's lower bound.
- throw new AtlasBaseException(
- "Cannot remove map entry " + keyPropertyName + " from required attribute " +
- propertyName + " on " + GraphHelper.getVertexDetails(outVertex) + " " + GraphHelper.getEdgeDetails(mapEdge));
- }
-
- if (shouldUpdateInverseReferences) {
- //remove this key
- LOG.debug("Removing edge {}, key {} from the map attribute {}", string(mapEdge), key,
- attribute.getName());
- keys.remove(key);
- GraphHelper.setProperty(outVertex, propertyName, keys);
- GraphHelper.setProperty(outVertex, keyPropertyName, null);
+ case MAP: {
+ //If its map attribute, find the right edge between two vertices and update map property
+ List<String> keys = GraphHelper.getListProperty(outVertex, propertyName);
+
+ if (keys != null) {
+ keys = new ArrayList<>(keys); //Make a copy, else list.remove reflects on titan.getProperty()
+
+ for (String key : keys) {
+ String keyPropertyName = GraphHelper.getQualifiedNameForMapKey(propertyName, key);
+ String mapEdgeId = GraphHelper.getSingleValuedProperty(outVertex, keyPropertyName, String.class);
+ AtlasEdge mapEdge = graphHelper.getEdgeByEdgeId(outVertex, keyPropertyName, mapEdgeId);
+
+ if (mapEdge != null) {
+ AtlasVertex mapVertex = mapEdge.getInVertex();
+
+ if (mapVertex.getId().toString().equals(inVertex.getId().toString())) {
+ //TODO keys.size includes deleted items as well. should exclude
+ if (attrDef.getIsOptional() || keys.size() > attrDef.getValuesMinCount()) {
+ edge = mapEdge;
+ } else {
+ // Deleting this entry would violate the attribute's lower bound.
+ throw new AtlasBaseException("Cannot remove map entry " + keyPropertyName + " from required attribute " + propertyName + " on " + GraphHelper.getVertexDetails(outVertex) + " " + GraphHelper.getEdgeDetails(mapEdge));
+ }
+
+ if (shouldUpdateInverseReferences) {
+ //remove this key
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Removing edge {}, key {} from the map attribute {}", string(mapEdge), key, attribute.getName());
+ }
+
+ keys.remove(key);
+ GraphHelper.setProperty(outVertex, propertyName, keys);
+ GraphHelper.setProperty(outVertex, keyPropertyName, null);
+ }
+ break;
}
- break;
}
}
}
}
break;
- case STRUCT:
- case CLASSIFICATION:
+ case STRUCT:
+ case CLASSIFICATION:
break;
- default:
- throw new IllegalStateException("There can't be an edge from " + GraphHelper.getVertexDetails(outVertex) + " to "
- + GraphHelper.getVertexDetails(inVertex) + " with attribute name " + attribute.getName() + " which is not class/array/map attribute. found " + attrType.getTypeCategory().name());
+ default:
+ throw new IllegalStateException("There can't be an edge from " + GraphHelper.getVertexDetails(outVertex) + " to " + GraphHelper.getVertexDetails(inVertex) + " with attribute name " + attribute.getName() + " which is not class/array/map attribute. found " + attrType.getTypeCategory().name());
}
if (edge != null) {
deleteEdge(edge, false);
+
RequestContextV1 requestContext = RequestContextV1.get();
- GraphHelper.setProperty(outVertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY,
- requestContext.getRequestTime());
- GraphHelper.setProperty(outVertex, Constants.MODIFIED_BY_KEY, requestContext.getUser());
- requestContext.recordEntityUpdate(new AtlasObjectId(outId, typeName));
+
+ if (! requestContext.isUpdatedEntity(outId)) {
+ GraphHelper.setProperty(outVertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, requestContext.getRequestTime());
+ GraphHelper.setProperty(outVertex, Constants.MODIFIED_BY_KEY, requestContext.getUser());
+
+ requestContext.recordEntityUpdate(entityRetriever.toAtlasObjectId(outVertex));
+ }
}
}
protected void deleteVertex(AtlasVertex instanceVertex, boolean force) throws AtlasBaseException {
//Update external references(incoming edges) to this vertex
- LOG.debug("Setting the external references to {} to null(removing edges)", string(instanceVertex));
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Setting the external references to {} to null(removing edges)", string(instanceVertex));
+ }
for (AtlasEdge edge : (Iterable<AtlasEdge>) instanceVertex.getEdges(AtlasEdgeDirection.IN)) {
AtlasEntity.Status edgeState = getState(edge);
+
if (edgeState == AtlasEntity.Status.ACTIVE) {
//Delete only the active edge references
AtlasAttribute attribute = getAttributeForEdge(edge.getLabel());
@@ -587,6 +628,7 @@ public abstract class DeleteHandlerV1 {
deleteEdgeBetweenVertices(edge.getOutVertex(), edge.getInVertex(), attribute);
}
}
+
_deleteVertex(instanceVertex, force);
}
}
http://git-wip-us.apache.org/repos/asf/atlas/blob/154dda0e/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
index 0fd4355..779bc38 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
@@ -85,6 +85,7 @@ public class EntityGraphMapper {
private final AtlasGraph graph;
private final DeleteHandlerV1 deleteHandler;
private final AtlasTypeRegistry typeRegistry;
+ private final EntityGraphRetriever entityRetriever;
private final AtlasRelationshipStore relationshipStore;
@Inject
@@ -92,6 +93,7 @@ public class EntityGraphMapper {
AtlasRelationshipStore relationshipStore) {
this.deleteHandler = deleteHandler;
this.typeRegistry = typeRegistry;
+ this.entityRetriever = new EntityGraphRetriever(typeRegistry);
this.graph = atlasGraph;
this.relationshipStore = relationshipStore;
}
@@ -192,16 +194,16 @@ public class EntityGraphMapper {
RequestContextV1 req = RequestContextV1.get();
- for (AtlasObjectId id : req.getDeletedEntityIds()) {
- resp.addEntity(DELETE, constructHeader(id));
+ for (AtlasObjectId entity : req.getDeletedEntities()) {
+ resp.addEntity(DELETE, entity);
}
- for (AtlasObjectId id : req.getUpdatedEntityIds()) {
+ for (AtlasObjectId entity : req.getUpdatedEntities()) {
if (isPartialUpdate) {
- resp.addEntity(PARTIAL_UPDATE, constructHeader(id));
+ resp.addEntity(PARTIAL_UPDATE, entity);
}
else {
- resp.addEntity(UPDATE, constructHeader(id));
+ resp.addEntity(UPDATE, entity);
}
}
@@ -423,7 +425,6 @@ public class EntityGraphMapper {
AtlasVertex attrVertex = context.getDiscoveryContext().getResolvedEntityVertex(getGuid(ctx.getValue()));
recordEntityUpdate(attrVertex);
- updateModificationMetadata(attrVertex);
}
//delete old reference
@@ -494,9 +495,13 @@ public class EntityGraphMapper {
}
if (inverseUpdated) {
- updateModificationMetadata(inverseVertex);
- AtlasObjectId inverseEntityId = new AtlasObjectId(getIdFromVertex(inverseVertex), inverseType.getTypeName());
- RequestContextV1.get().recordEntityUpdate(inverseEntityId);
+ RequestContextV1 requestContext = RequestContextV1.get();
+
+ if (!requestContext.isDeletedEntity(GraphHelper.getGuid(inverseVertex))) {
+ updateModificationMetadata(inverseVertex);
+
+ requestContext.recordEntityUpdate(entityRetriever.toAtlasObjectId(inverseVertex));
+ }
}
}
@@ -1441,31 +1446,14 @@ public class EntityGraphMapper {
return ret;
}
- private void recordEntityUpdate(AtlasVertex vertex) {
- AtlasObjectId objectId = new AtlasObjectId(GraphHelper.getGuid(vertex), GraphHelper.getTypeName(vertex));
- RequestContextV1 req = RequestContextV1.get();
-
- if (!objectIdsContain(req.getUpdatedEntityIds(), objectId) && !objectIdsContain(req.getCreatedEntityIds(), objectId)) {
- req.recordEntityUpdate(objectId);
- }
- }
-
- private boolean objectIdsContain(Collection<AtlasObjectId> objectIds, AtlasObjectId objectId) {
- boolean ret = false;
+ private void recordEntityUpdate(AtlasVertex vertex) throws AtlasBaseException {
+ RequestContextV1 req = RequestContextV1.get();
- if (CollectionUtils.isEmpty(objectIds)) {
- ret = false;
+ if (!req.isUpdatedEntity(GraphHelper.getGuid(vertex))) {
+ updateModificationMetadata(vertex);
- } else {
- for (AtlasObjectId id : objectIds) {
- if (StringUtils.equals(id.getGuid(), objectId.getGuid())) {
- ret = true;
- break;
- }
- }
+ req.recordEntityUpdate(entityRetriever.toAtlasObjectId(vertex));
}
-
- return ret;
}
private static void compactAttributes(AtlasEntity entity) {
http://git-wip-us.apache.org/repos/asf/atlas/blob/154dda0e/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
index e9051a6..b05a9a3 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
@@ -147,6 +147,70 @@ public final class EntityGraphRetriever {
return atlasVertex != null ? mapVertexToAtlasEntityHeader(atlasVertex, attributes) : null;
}
+ public AtlasEntityHeader toAtlasEntityHeader(AtlasEntity entity) {
+ AtlasEntityHeader ret = null;
+ String typeName = entity.getTypeName();
+ AtlasEntityType entityType = typeRegistry.getEntityTypeByName(typeName);
+
+ if (entityType != null) {
+ Map<String, Object> uniqueAttributes = new HashMap<>();
+
+ for (AtlasAttribute attribute : entityType.getUniqAttributes().values()) {
+ Object attrValue = entity.getAttribute(attribute.getName());
+
+ if (attrValue != null) {
+ uniqueAttributes.put(attribute.getName(), attrValue);
+ }
+ }
+
+ ret = new AtlasEntityHeader(entity.getTypeName(), entity.getGuid(), uniqueAttributes);
+ }
+
+ return ret;
+ }
+
+ public AtlasObjectId toAtlasObjectId(AtlasVertex entityVertex) throws AtlasBaseException {
+ AtlasObjectId ret = null;
+ String typeName = entityVertex.getProperty(Constants.TYPE_NAME_PROPERTY_KEY, String.class);
+ AtlasEntityType entityType = typeRegistry.getEntityTypeByName(typeName);
+
+ if (entityType != null) {
+ Map<String, Object> uniqueAttributes = new HashMap<>();
+
+ for (AtlasAttribute attribute : entityType.getUniqAttributes().values()) {
+ Object attrValue = getVertexAttribute(entityVertex, attribute);
+
+ if (attrValue != null) {
+ uniqueAttributes.put(attribute.getName(), attrValue);
+ }
+ }
+
+ ret = new AtlasObjectId(entityVertex.getProperty(Constants.GUID_PROPERTY_KEY, String.class), typeName, uniqueAttributes);
+ }
+
+ return ret;
+ }
+
+ public AtlasVertex getReferencedEntityVertex(AtlasEdge edge, AtlasRelationshipEdgeDirection relationshipDirection, AtlasVertex parentVertex) throws AtlasBaseException {
+ AtlasVertex entityVertex = null;
+
+ if (relationshipDirection == OUT) {
+ entityVertex = edge.getInVertex();
+ } else if (relationshipDirection == IN) {
+ entityVertex = edge.getOutVertex();
+ } else if (relationshipDirection == BOTH){
+ // since relationship direction is BOTH, edge direction can be inward or outward
+ // compare with parent entity vertex and pick the right reference vertex
+ if (StringUtils.equals(GraphHelper.getGuid(parentVertex), GraphHelper.getGuid(edge.getOutVertex()))) {
+ entityVertex = edge.getInVertex();
+ } else {
+ entityVertex = edge.getOutVertex();
+ }
+ }
+
+ return entityVertex;
+ }
+
public AtlasVertex getEntityVertex(String guid) throws AtlasBaseException {
AtlasVertex ret = AtlasGraphUtilsV1.findByGuid(guid);
http://git-wip-us.apache.org/repos/asf/atlas/blob/154dda0e/server-api/src/main/java/org/apache/atlas/RequestContextV1.java
----------------------------------------------------------------------
diff --git a/server-api/src/main/java/org/apache/atlas/RequestContextV1.java b/server-api/src/main/java/org/apache/atlas/RequestContextV1.java
index 27fe3d2..9177cb8 100644
--- a/server-api/src/main/java/org/apache/atlas/RequestContextV1.java
+++ b/server-api/src/main/java/org/apache/atlas/RequestContextV1.java
@@ -31,18 +31,15 @@ public class RequestContextV1 {
private static final ThreadLocal<RequestContextV1> CURRENT_CONTEXT = new ThreadLocal<>();
- private Set<AtlasObjectId> createdEntityIds = new LinkedHashSet<>();
- private Set<AtlasObjectId> updatedEntityIds = new LinkedHashSet<>();
- private Set<AtlasObjectId> deletedEntityIds = new LinkedHashSet<>();
- private Map<String, AtlasEntityWithExtInfo> entityCacheV2 = new HashMap<>();
+ private final Map<String, AtlasObjectId> updatedEntities = new HashMap<>();
+ private final Map<String, AtlasObjectId> deletedEntities = new HashMap<>();
+ private final Map<String, AtlasEntityWithExtInfo> entityCacheV2 = new HashMap<>();
+ private final Metrics metrics = new Metrics();
+ private final long requestTime = System.currentTimeMillis();
private String user;
- private final long requestTime;
-
- private Metrics metrics = new Metrics();
private RequestContextV1() {
- requestTime = System.currentTimeMillis();
}
//To handle gets from background threads where createContext() is not called
@@ -62,9 +59,9 @@ public class RequestContextV1 {
RequestContextV1 instance = CURRENT_CONTEXT.get();
if (instance != null) {
- if (instance.entityCacheV2 != null) {
- instance.entityCacheV2.clear();
- }
+ instance.updatedEntities.clear();
+ instance.deletedEntities.clear();
+ instance.entityCacheV2.clear();
}
CURRENT_CONTEXT.remove();
@@ -78,24 +75,16 @@ public class RequestContextV1 {
this.user = user;
}
- public void recordEntityCreate(Collection<AtlasObjectId> createdEntityIds) {
- this.createdEntityIds.addAll(createdEntityIds);
- }
-
- public void recordEntityCreate(AtlasObjectId createdEntityId) {
- this.createdEntityIds.add(createdEntityId);
- }
-
- public void recordEntityUpdate(Collection<AtlasObjectId> updatedEntityIds) {
- this.updatedEntityIds.addAll(updatedEntityIds);
- }
-
- public void recordEntityUpdate(AtlasObjectId entityId) {
- this.updatedEntityIds.add(entityId);
+ public void recordEntityUpdate(AtlasObjectId entity) {
+ if (entity != null && entity.getGuid() != null) {
+ updatedEntities.put(entity.getGuid(), entity);
+ }
}
- public void recordEntityDelete(AtlasObjectId entityId) {
- deletedEntityIds.add(entityId);
+ public void recordEntityDelete(AtlasObjectId entity) {
+ if (entity != null && entity.getGuid() != null) {
+ deletedEntities.put(entity.getGuid(), entity);
+ }
}
/**
@@ -108,16 +97,12 @@ public class RequestContextV1 {
}
}
- public Collection<AtlasObjectId> getCreatedEntityIds() {
- return createdEntityIds;
- }
-
- public Collection<AtlasObjectId> getUpdatedEntityIds() {
- return updatedEntityIds;
+ public Collection<AtlasObjectId> getUpdatedEntities() {
+ return updatedEntities.values();
}
- public Collection<AtlasObjectId> getDeletedEntityIds() {
- return deletedEntityIds;
+ public Collection<AtlasObjectId> getDeletedEntities() {
+ return deletedEntities.values();
}
/**
@@ -135,8 +120,12 @@ public class RequestContextV1 {
return requestTime;
}
- public boolean isDeletedEntity(AtlasObjectId entityId) {
- return deletedEntityIds.contains(entityId);
+ public boolean isUpdatedEntity(String guid) {
+ return updatedEntities.containsKey(guid);
+ }
+
+ public boolean isDeletedEntity(String guid) {
+ return deletedEntities.containsKey(guid);
}
public static Metrics getMetrics() {