Commit f4574531 by Ashutosh Mestry

ATLAS-3212: Importing with import transforms applied to exising entities.

parent b0063fa5
...@@ -25,4 +25,5 @@ import java.lang.annotation.Target; ...@@ -25,4 +25,5 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
public @interface GraphTransaction { public @interface GraphTransaction {
boolean logRollback() default true;
} }
...@@ -20,6 +20,7 @@ package org.apache.atlas; ...@@ -20,6 +20,7 @@ package org.apache.atlas;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
import org.apache.atlas.annotation.GraphTransaction;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.exception.NotFoundException; import org.apache.atlas.exception.NotFoundException;
import org.apache.atlas.repository.graphdb.AtlasGraph; import org.apache.atlas.repository.graphdb.AtlasGraph;
...@@ -63,6 +64,7 @@ public class GraphTransactionInterceptor implements MethodInterceptor { ...@@ -63,6 +64,7 @@ public class GraphTransactionInterceptor implements MethodInterceptor {
Method method = invocation.getMethod(); Method method = invocation.getMethod();
String invokingClass = method.getDeclaringClass().getSimpleName(); String invokingClass = method.getDeclaringClass().getSimpleName();
String invokedMethodName = method.getName(); String invokedMethodName = method.getName();
boolean logRollback = method.getAnnotation(GraphTransaction.class).logRollback();
boolean isInnerTxn = isTxnOpen.get(); boolean isInnerTxn = isTxnOpen.get();
// Outermost txn marks any subsequent transaction as inner // Outermost txn marks any subsequent transaction as inner
...@@ -99,7 +101,7 @@ public class GraphTransactionInterceptor implements MethodInterceptor { ...@@ -99,7 +101,7 @@ public class GraphTransactionInterceptor implements MethodInterceptor {
} }
innerFailure.set(true); innerFailure.set(true);
} else { } else {
doRollback(t); doRollback(logRollback, t);
} }
throw t; throw t;
} }
...@@ -159,12 +161,15 @@ public class GraphTransactionInterceptor implements MethodInterceptor { ...@@ -159,12 +161,15 @@ public class GraphTransactionInterceptor implements MethodInterceptor {
} }
} }
private void doRollback(final Throwable t) { private void doRollback(boolean logRollback, final Throwable t) {
if (logRollback) {
if (logException(t)) { if (logException(t)) {
LOG.error("graph rollback due to exception ", t); LOG.error("graph rollback due to exception ", t);
} else { } else {
LOG.error("graph rollback due to exception {}:{}", t.getClass().getSimpleName(), t.getMessage()); LOG.error("graph rollback due to exception {}:{}", t.getClass().getSimpleName(), t.getMessage());
} }
}
graph.rollback(); graph.rollback();
} }
......
...@@ -276,7 +276,7 @@ public class AtlasEntityStoreV2 implements AtlasEntityStore { ...@@ -276,7 +276,7 @@ public class AtlasEntityStoreV2 implements AtlasEntityStore {
} }
@Override @Override
@GraphTransaction @GraphTransaction(logRollback = false)
public EntityMutationResponse createOrUpdateForImport(EntityStream entityStream) throws AtlasBaseException { public EntityMutationResponse createOrUpdateForImport(EntityStream entityStream) throws AtlasBaseException {
return createOrUpdate(entityStream, false, true); return createOrUpdate(entityStream, false, true);
} }
......
...@@ -6,9 +6,9 @@ ...@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the * to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance * "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at * with the License. You may obtain a copy of the License at
* * <p>
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* * <p>
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
...@@ -22,7 +22,6 @@ import org.apache.atlas.AtlasErrorCode; ...@@ -22,7 +22,6 @@ import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.RequestContext; import org.apache.atlas.RequestContext;
import org.apache.atlas.annotation.GraphTransaction; import org.apache.atlas.annotation.GraphTransaction;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.impexp.AtlasExportRequest;
import org.apache.atlas.model.impexp.AtlasImportResult; import org.apache.atlas.model.impexp.AtlasImportResult;
import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
...@@ -30,14 +29,12 @@ import org.apache.atlas.model.instance.AtlasEntityHeader; ...@@ -30,14 +29,12 @@ import org.apache.atlas.model.instance.AtlasEntityHeader;
import org.apache.atlas.model.instance.AtlasObjectId; import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.instance.EntityMutationResponse; import org.apache.atlas.model.instance.EntityMutationResponse;
import org.apache.atlas.repository.Constants; import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.graphdb.AtlasGraph;
import org.apache.atlas.repository.graphdb.AtlasSchemaViolationException; import org.apache.atlas.repository.graphdb.AtlasSchemaViolationException;
import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.impexp.StartEntityFetchByExportRequest;
import org.apache.atlas.repository.store.graph.AtlasEntityStore; import org.apache.atlas.repository.store.graph.AtlasEntityStore;
import org.apache.atlas.repository.store.graph.BulkImporter; import org.apache.atlas.repository.store.graph.BulkImporter;
import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.util.AtlasGremlinQueryProvider;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -48,7 +45,6 @@ import java.util.ArrayList; ...@@ -48,7 +45,6 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import static org.apache.atlas.repository.Constants.HISTORICAL_GUID_PROPERTY_KEY; import static org.apache.atlas.repository.Constants.HISTORICAL_GUID_PROPERTY_KEY;
...@@ -59,15 +55,14 @@ public class BulkImporterImpl implements BulkImporter { ...@@ -59,15 +55,14 @@ public class BulkImporterImpl implements BulkImporter {
private final AtlasEntityStore entityStore; private final AtlasEntityStore entityStore;
private final EntityGraphRetriever entityGraphRetriever; private final EntityGraphRetriever entityGraphRetriever;
private final Map<AtlasObjectId, String> objectIdExistingGuidMap; private AtlasTypeRegistry typeRegistry;
private final StartEntityFetchByExportRequest startEntityFetchByExportRequest; private final int MAX_ATTEMPTS = 2;
@Inject @Inject
public BulkImporterImpl(AtlasGraph atlasGraph, AtlasEntityStore entityStore, AtlasTypeRegistry typeRegistry) { public BulkImporterImpl(AtlasEntityStore entityStore, AtlasTypeRegistry typeRegistry) {
this.entityStore = entityStore; this.entityStore = entityStore;
this.entityGraphRetriever = new EntityGraphRetriever(typeRegistry); this.entityGraphRetriever = new EntityGraphRetriever(typeRegistry);
this.objectIdExistingGuidMap = new HashMap<>(); this.typeRegistry = typeRegistry;
this.startEntityFetchByExportRequest = new StartEntityFetchByExportRequest(atlasGraph, typeRegistry, AtlasGremlinQueryProvider.INSTANCE);
} }
@Override @Override
...@@ -80,7 +75,6 @@ public class BulkImporterImpl implements BulkImporter { ...@@ -80,7 +75,6 @@ public class BulkImporterImpl implements BulkImporter {
throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, "no entities to create/update."); throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, "no entities to create/update.");
} }
fetchExistingEntitiesNotCreatedByImport(importResult.getExportResult().getRequest());
EntityMutationResponse ret = new EntityMutationResponse(); EntityMutationResponse ret = new EntityMutationResponse();
ret.setGuidAssignments(new HashMap<>()); ret.setGuidAssignments(new HashMap<>());
...@@ -98,40 +92,51 @@ public class BulkImporterImpl implements BulkImporter { ...@@ -98,40 +92,51 @@ public class BulkImporterImpl implements BulkImporter {
continue; continue;
} }
AtlasEntityStreamForImport oneEntityStream = new AtlasEntityStreamForImport(entityWithExtInfo, entityStream); for (int attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
try { try {
AtlasEntityStreamForImport oneEntityStream = new AtlasEntityStreamForImport(entityWithExtInfo, null);
EntityMutationResponse resp = entityStore.createOrUpdateForImport(oneEntityStream); EntityMutationResponse resp = entityStore.createOrUpdateForImport(oneEntityStream);
if (resp.getGuidAssignments() != null) { if (resp.getGuidAssignments() != null) {
ret.getGuidAssignments().putAll(resp.getGuidAssignments()); ret.getGuidAssignments().putAll(resp.getGuidAssignments());
} }
currentPercent = updateImportMetrics(entityWithExtInfo, resp, importResult, processedGuids, entityStream.getPosition(), entityImportStreamWithResidualList.getStreamSize(), currentPercent); currentPercent = updateImportMetrics(entityWithExtInfo, resp, importResult, processedGuids,
entityStream.getPosition(),
entityImportStreamWithResidualList.getStreamSize(),
currentPercent);
entityStream.onImportComplete(entity.getGuid()); entityStream.onImportComplete(entity.getGuid());
break;
} catch (AtlasBaseException e) { } catch (AtlasBaseException e) {
if (!updateResidualList(e, residualList, entityWithExtInfo.getEntity().getGuid())) { if (!updateResidualList(e, residualList, entityWithExtInfo.getEntity().getGuid())) {
throw e; throw e;
} }
break;
} catch (AtlasSchemaViolationException e) { } catch (AtlasSchemaViolationException e) {
AtlasObjectId objectId = entityGraphRetriever.toAtlasObjectIdWithoutGuid(entity); if (LOG.isDebugEnabled()) {
if (objectIdExistingGuidMap.containsKey(objectId)) { LOG.debug("Entity: {}", entity.getGuid(), e);
updateVertexGuidIfImportingToNonImportedEntity(entity, objectId);
} }
continue; if (attempt == 0) {
updateVertexGuid(entity);
} else {
LOG.error("Guid update failed: {}", entityWithExtInfo.getEntity().getGuid());
throw e;
} }
catch (Throwable e) { } catch (Throwable e) {
AtlasBaseException abe = new AtlasBaseException(e); AtlasBaseException abe = new AtlasBaseException(e);
if (!updateResidualList(abe, residualList, entityWithExtInfo.getEntity().getGuid())) { if (!updateResidualList(abe, residualList, entityWithExtInfo.getEntity().getGuid())) {
throw abe; throw abe;
} }
LOG.warn("Exception: {}", entity.getGuid(), e);
break;
} finally { } finally {
RequestContext.get().clearCache(); RequestContext.get().clearCache();
} }
} }
}
importResult.getProcessedEntities().addAll(processedGuids); importResult.getProcessedEntities().addAll(processedGuids);
LOG.info("bulkImport(): done. Total number of entities (including referred entities) imported: {}", processedGuids.size()); LOG.info("bulkImport(): done. Total number of entities (including referred entities) imported: {}", processedGuids.size());
...@@ -139,25 +144,21 @@ public class BulkImporterImpl implements BulkImporter { ...@@ -139,25 +144,21 @@ public class BulkImporterImpl implements BulkImporter {
return ret; return ret;
} }
private void fetchExistingEntitiesNotCreatedByImport(AtlasExportRequest request) { @GraphTransaction
List<AtlasObjectId> objectIds = startEntityFetchByExportRequest.get(request); public void updateVertexGuid(AtlasEntity entity) {
if (objectIds.isEmpty()) { String entityGuid = entity.getGuid();
return; AtlasObjectId objectId = entityGraphRetriever.toAtlasObjectIdWithoutGuid(entity);
}
for (AtlasObjectId objectId : objectIds) {
String existingGuid = objectId.getGuid();
objectId.setGuid(null);
objectIdExistingGuidMap.put(objectId, existingGuid); AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entity.getTypeName());
} String vertexGuid = null;
try {
vertexGuid = AtlasGraphUtilsV2.getGuidByUniqueAttributes(entityType, objectId.getUniqueAttributes());
} catch (AtlasBaseException e) {
LOG.warn("Entity: {}: Does not exist!", objectId);
return;
} }
@GraphTransaction if (StringUtils.isEmpty(vertexGuid) || vertexGuid.equals(entityGuid)) {
public void updateVertexGuidIfImportingToNonImportedEntity(AtlasEntity entity, AtlasObjectId objectId) {
String entityGuid = entity.getGuid();
String vertexGuid = objectIdExistingGuidMap.get(objectId);
if (vertexGuid.equals(entityGuid)) {
return; return;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment