Commit 09089e09 by Jeff Hagelberg

ATLAS-1388: Cache entities that are created/updated

parent 62a05c97
...@@ -9,6 +9,7 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al ...@@ -9,6 +9,7 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al
ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai) ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai)
ALL CHANGES: ALL CHANGES:
ATLAS-1388 Cache entities that are created/updated (jnhagelb)
ATLAS-1369 Optimize Gremlin queries generated by DSL translator (jnhagelb) ATLAS-1369 Optimize Gremlin queries generated by DSL translator (jnhagelb)
ATLAS-1517: updated hive_model to include schema related attributes (sarath.kum4r@gmail.com via mneethiraj) ATLAS-1517: updated hive_model to include schema related attributes (sarath.kum4r@gmail.com via mneethiraj)
ATLAS-1514 Remove duplicates from class array attribute when target is deleted (dkantor) ATLAS-1514 Remove duplicates from class array attribute when target is deleted (dkantor)
......
...@@ -18,9 +18,12 @@ ...@@ -18,9 +18,12 @@
package org.apache.atlas.discovery.graph; package org.apache.atlas.discovery.graph;
import com.google.common.collect.ImmutableCollection; import java.util.List;
import com.google.common.collect.ImmutableList;
import javax.inject.Inject;
import org.apache.atlas.AtlasException; import org.apache.atlas.AtlasException;
import org.apache.atlas.RequestContext;
import org.apache.atlas.groovy.GroovyExpression; import org.apache.atlas.groovy.GroovyExpression;
import org.apache.atlas.query.GraphPersistenceStrategies; import org.apache.atlas.query.GraphPersistenceStrategies;
import org.apache.atlas.query.GraphPersistenceStrategies$class; import org.apache.atlas.query.GraphPersistenceStrategies$class;
...@@ -48,8 +51,8 @@ import org.apache.atlas.typesystem.types.TypeSystem; ...@@ -48,8 +51,8 @@ import org.apache.atlas.typesystem.types.TypeSystem;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.inject.Inject; import com.google.common.collect.ImmutableCollection;
import java.util.List; import com.google.common.collect.ImmutableList;
/** /**
* Default implementation of GraphPersistenceStrategy. * Default implementation of GraphPersistenceStrategy.
...@@ -178,9 +181,12 @@ public class DefaultGraphPersistenceStrategy implements GraphPersistenceStrategi ...@@ -178,9 +181,12 @@ public class DefaultGraphPersistenceStrategy implements GraphPersistenceStrategi
case CLASS: case CLASS:
AtlasVertex classVertex = (AtlasVertex) value; AtlasVertex classVertex = (AtlasVertex) value;
ITypedReferenceableInstance classInstance = metadataRepository.getGraphToInstanceMapper() String guid = classVertex.getProperty(Constants.GUID_PROPERTY_KEY, String.class);
.mapGraphToTypedInstance(GraphHelper.getSingleValuedProperty(classVertex, Constants.GUID_PROPERTY_KEY, String.class), // Check if the instance we need was previously loaded.
classVertex); ITypedReferenceableInstance classInstance = RequestContext.get().getInstance(guid);
if (classInstance == null) {
classInstance = metadataRepository.getGraphToInstanceMapper().mapGraphToTypedInstance(guid, classVertex);
}
return dataType.convert(classInstance, Multiplicity.OPTIONAL); return dataType.convert(classInstance, Multiplicity.OPTIONAL);
default: default:
......
...@@ -17,11 +17,11 @@ ...@@ -17,11 +17,11 @@
*/ */
package org.apache.atlas.repository.graph; package org.apache.atlas.repository.graph;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.atlas.AtlasException; import org.apache.atlas.AtlasException;
import org.apache.atlas.RequestContext;
import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.typesystem.ITypedInstance; import org.apache.atlas.typesystem.ITypedInstance;
import org.apache.atlas.typesystem.ITypedReferenceableInstance; import org.apache.atlas.typesystem.ITypedReferenceableInstance;
...@@ -44,20 +44,19 @@ public class FullTextMapper { ...@@ -44,20 +44,19 @@ public class FullTextMapper {
private static final GraphHelper graphHelper = GraphHelper.getInstance(); private static final GraphHelper graphHelper = GraphHelper.getInstance();
private static final String FULL_TEXT_DELIMITER = " "; private static final String FULL_TEXT_DELIMITER = " ";
private final Map<String, ITypedReferenceableInstance> instanceCache;
FullTextMapper(TypedInstanceToGraphMapper typedInstanceToGraphMapper, FullTextMapper(TypedInstanceToGraphMapper typedInstanceToGraphMapper,
GraphToTypedInstanceMapper graphToTypedInstanceMapper) { GraphToTypedInstanceMapper graphToTypedInstanceMapper) {
this.graphToTypedInstanceMapper = graphToTypedInstanceMapper; this.graphToTypedInstanceMapper = graphToTypedInstanceMapper;
this.typedInstanceToGraphMapper = typedInstanceToGraphMapper; this.typedInstanceToGraphMapper = typedInstanceToGraphMapper;
instanceCache = new HashMap<>();
} }
public String mapRecursive(AtlasVertex instanceVertex, boolean followReferences) throws AtlasException { public String mapRecursive(AtlasVertex instanceVertex, boolean followReferences) throws AtlasException {
String guid = GraphHelper.getGuid(instanceVertex); String guid = GraphHelper.getGuid(instanceVertex);
ITypedReferenceableInstance typedReference; ITypedReferenceableInstance typedReference;
if (instanceCache.containsKey(guid)) { RequestContext context = RequestContext.get();
typedReference = instanceCache.get(guid); typedReference = context.getInstance(guid);
if (typedReference != null) {
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("Cache hit: guid = {}, entityId = {}", guid, typedReference.getId()._getId()); LOG.debug("Cache hit: guid = {}, entityId = {}", guid, typedReference.getId()._getId());
...@@ -65,7 +64,7 @@ public class FullTextMapper { ...@@ -65,7 +64,7 @@ public class FullTextMapper {
} else { } else {
typedReference = typedReference =
graphToTypedInstanceMapper.mapGraphToTypedInstance(guid, instanceVertex); graphToTypedInstanceMapper.mapGraphToTypedInstance(guid, instanceVertex);
instanceCache.put(guid, typedReference); context.cache(typedReference);
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("Cache miss: guid = {}, entityId = {}", guid, typedReference.getId().getId()); LOG.debug("Cache miss: guid = {}, entityId = {}", guid, typedReference.getId().getId());
......
...@@ -191,6 +191,10 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -191,6 +191,10 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
Constants.STATE_PROPERTY_KEY, Id.EntityState.ACTIVE.name()); Constants.STATE_PROPERTY_KEY, Id.EntityState.ACTIVE.name());
String guid = GraphHelper.getGuid(instanceVertex); String guid = GraphHelper.getGuid(instanceVertex);
ITypedReferenceableInstance cached = RequestContext.get().getInstance(guid);
if(cached != null) {
return cached;
}
return graphToInstanceMapper.mapGraphToTypedInstance(guid, instanceVertex); return graphToInstanceMapper.mapGraphToTypedInstance(guid, instanceVertex);
} }
......
...@@ -17,8 +17,18 @@ ...@@ -17,8 +17,18 @@
*/ */
package org.apache.atlas.repository.graph; package org.apache.atlas.repository.graph;
import com.google.inject.Singleton; import static org.apache.atlas.repository.graph.GraphHelper.string;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.atlas.AtlasException; import org.apache.atlas.AtlasException;
import org.apache.atlas.RequestContext;
import org.apache.atlas.repository.RepositoryException; import org.apache.atlas.repository.RepositoryException;
import org.apache.atlas.repository.Constants; import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.graphdb.AtlasEdge; import org.apache.atlas.repository.graphdb.AtlasEdge;
...@@ -28,10 +38,8 @@ import org.apache.atlas.repository.graphdb.AtlasVertex; ...@@ -28,10 +38,8 @@ import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.typesystem.ITypedInstance; import org.apache.atlas.typesystem.ITypedInstance;
import org.apache.atlas.typesystem.ITypedReferenceableInstance; import org.apache.atlas.typesystem.ITypedReferenceableInstance;
import org.apache.atlas.typesystem.ITypedStruct; import org.apache.atlas.typesystem.ITypedStruct;
import org.apache.atlas.typesystem.Referenceable;
import org.apache.atlas.typesystem.persistence.AtlasSystemAttributes; import org.apache.atlas.typesystem.persistence.AtlasSystemAttributes;
import org.apache.atlas.typesystem.persistence.Id; import org.apache.atlas.typesystem.persistence.Id;
import org.apache.atlas.typesystem.persistence.ReferenceableInstance;
import org.apache.atlas.typesystem.types.AttributeInfo; import org.apache.atlas.typesystem.types.AttributeInfo;
import org.apache.atlas.typesystem.types.ClassType; import org.apache.atlas.typesystem.types.ClassType;
import org.apache.atlas.typesystem.types.DataTypes; import org.apache.atlas.typesystem.types.DataTypes;
...@@ -43,15 +51,7 @@ import org.apache.atlas.typesystem.types.TypeSystem; ...@@ -43,15 +51,7 @@ import org.apache.atlas.typesystem.types.TypeSystem;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.math.BigDecimal; import com.google.inject.Singleton;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.apache.atlas.repository.graph.GraphHelper.string;
@Singleton @Singleton
public final class GraphToTypedInstanceMapper { public final class GraphToTypedInstanceMapper {
...@@ -69,7 +69,14 @@ public final class GraphToTypedInstanceMapper { ...@@ -69,7 +69,14 @@ public final class GraphToTypedInstanceMapper {
public ITypedReferenceableInstance mapGraphToTypedInstance(String guid, AtlasVertex instanceVertex) public ITypedReferenceableInstance mapGraphToTypedInstance(String guid, AtlasVertex instanceVertex)
throws AtlasException { throws AtlasException {
if (LOG.isDebugEnabled()) { if(LOG.isDebugEnabled()) {
//We don't do a cache check here since we want that to be at a higher level
//where the vertex lookup can also be avoided. However, this is a convenient
//place to add a check to see if there are any places that were missed.
if(RequestContext.get().getInstance(guid) != null) {
LOG.warn("Looking up previously cached guid at: ", new Exception());
}
LOG.debug("Mapping graph root vertex {} to typed instance for guid {}", instanceVertex, guid); LOG.debug("Mapping graph root vertex {} to typed instance for guid {}", instanceVertex, guid);
} }
...@@ -99,7 +106,7 @@ public final class GraphToTypedInstanceMapper { ...@@ -99,7 +106,7 @@ public final class GraphToTypedInstanceMapper {
mapVertexToInstance(instanceVertex, typedInstance, classType.fieldMapping().fields); mapVertexToInstance(instanceVertex, typedInstance, classType.fieldMapping().fields);
mapVertexToInstanceTraits(instanceVertex, typedInstance, traits); mapVertexToInstanceTraits(instanceVertex, typedInstance, traits);
RequestContext.get().cache(typedInstance);
return typedInstance; return typedInstance;
} }
...@@ -209,6 +216,10 @@ public final class GraphToTypedInstanceMapper { ...@@ -209,6 +216,10 @@ public final class GraphToTypedInstanceMapper {
if (attributeInfo.isComposite) { if (attributeInfo.isComposite) {
//Also, when you retrieve a type's instance, you get the complete object graph of the composites //Also, when you retrieve a type's instance, you get the complete object graph of the composites
LOG.debug("Found composite, mapping vertex to instance"); LOG.debug("Found composite, mapping vertex to instance");
ITypedReferenceableInstance cached = RequestContext.get().getInstance(guid);
if(cached != null) {
return cached;
}
return mapGraphToTypedInstance(guid, referenceVertex); return mapGraphToTypedInstance(guid, referenceVertex);
} else { } else {
String state = GraphHelper.getStateAsString(referenceVertex); String state = GraphHelper.getStateAsString(referenceVertex);
......
...@@ -125,6 +125,9 @@ public final class TypedInstanceToGraphMapper { ...@@ -125,6 +125,9 @@ public final class TypedInstanceToGraphMapper {
throw new UnsupportedOperationException("Not handled - " + operation); throw new UnsupportedOperationException("Not handled - " + operation);
} }
for(ITypedReferenceableInstance instance : typedInstances) {
addToEntityCache(requestContext, instance);
}
} }
private Collection<IReferenceableInstance> walkClassInstances(ITypedReferenceableInstance typedInstance) private Collection<IReferenceableInstance> walkClassInstances(ITypedReferenceableInstance typedInstance)
...@@ -825,4 +828,23 @@ public final class TypedInstanceToGraphMapper { ...@@ -825,4 +828,23 @@ public final class TypedInstanceToGraphMapper {
public AtlasVertex lookupVertex(Id refId) { public AtlasVertex lookupVertex(Id refId) {
return idToVertexMap.get(refId); return idToVertexMap.get(refId);
} }
private void addToEntityCache(RequestContext context, ITypedReferenceableInstance instance)
throws EntityNotFoundException {
Id instanceId = instance.getId();
if(instanceId.isUnassigned()) {
if(instance instanceof ReferenceableInstance) {
//When the id is unassigned, we can only cache the instance of it is
//an instance of ReferenceableInstance, since replaceWithNewId is not
//currently in the ITypedReferenceableInstance interface.
Id id = getId(instance);
((ReferenceableInstance)instance).replaceWithNewId(id);
context.cache(instance);
}
}
else {
context.cache(instance);
}
}
} }
...@@ -18,14 +18,33 @@ ...@@ -18,14 +18,33 @@
package org.apache.atlas; package org.apache.atlas;
import com.google.common.collect.ImmutableList; import static org.apache.atlas.typesystem.types.utils.TypesUtil.createClassTypeDef;
import com.google.common.collect.ImmutableSet; import static org.apache.atlas.typesystem.types.utils.TypesUtil.createOptionalAttrDef;
import com.google.inject.Provider; import static org.apache.atlas.typesystem.types.utils.TypesUtil.createRequiredAttrDef;
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createStructTypeDef;
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createTraitTypeDef;
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createUniqueRequiredAttrDef;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import org.apache.atlas.listener.EntityChangeListener; import org.apache.atlas.listener.EntityChangeListener;
import org.apache.atlas.listener.TypesChangeListener; import org.apache.atlas.listener.TypesChangeListener;
import org.apache.atlas.repository.MetadataRepository; import org.apache.atlas.repository.MetadataRepository;
import org.apache.atlas.repository.graph.AtlasGraphProvider; import org.apache.atlas.repository.graph.AtlasGraphProvider;
import org.apache.atlas.repository.graph.GraphBackedMetadataRepository;
import org.apache.atlas.repository.graph.GraphBackedSearchIndexer; import org.apache.atlas.repository.graph.GraphBackedSearchIndexer;
import org.apache.atlas.repository.graph.GraphHelper; import org.apache.atlas.repository.graph.GraphHelper;
import org.apache.atlas.repository.graphdb.AtlasGraph; import org.apache.atlas.repository.graphdb.AtlasGraph;
...@@ -59,23 +78,9 @@ import org.apache.commons.lang.RandomStringUtils; ...@@ -59,23 +78,9 @@ import org.apache.commons.lang.RandomStringUtils;
import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONArray;
import org.testng.Assert; import org.testng.Assert;
import java.io.File; import com.google.common.collect.ImmutableList;
import java.io.FileOutputStream; import com.google.common.collect.ImmutableSet;
import java.io.IOException; import com.google.inject.Provider;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createClassTypeDef;
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createOptionalAttrDef;
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createRequiredAttrDef;
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createStructTypeDef;
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createTraitTypeDef;
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createUniqueRequiredAttrDef;
/** /**
* Test utility class. * Test utility class.
...@@ -505,11 +510,14 @@ public final class TestUtils { ...@@ -505,11 +510,14 @@ public final class TestUtils {
} }
return null; return null;
} }
public static void resetRequestContext() { public static void resetRequestContext() {
//reset the context while preserving the user
String user = RequestContext.get().getUser();
RequestContext.createContext(); RequestContext.createContext();
RequestContext.get().setUser(user);
} }
public static void setupGraphProvider(MetadataRepository repo) throws AtlasException { public static void setupGraphProvider(MetadataRepository repo) throws AtlasException {
TypeCache typeCache = null; TypeCache typeCache = null;
try { try {
...@@ -538,10 +546,92 @@ public final class TestUtils { ...@@ -538,10 +546,92 @@ public final class TestUtils {
getGraph().commit(); getGraph().commit();
} }
public static AtlasGraph getGraph() { public static AtlasGraph getGraph() {
return AtlasGraphProvider.getGraphInstance(); return AtlasGraphProvider.getGraphInstance();
}
/**
* Adds a proxy wrapper around the specified MetadataService that automatically
* resets the request context before every call.
*
* @param delegate
* @return
*/
public static MetadataService addSessionCleanupWrapper(final MetadataService delegate) {
return (MetadataService)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class[]{MetadataService.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
resetRequestContext();
Object result = method.invoke(delegate, args);
return result;
}
catch(InvocationTargetException e) {
e.getCause().printStackTrace();
throw e.getCause();
}
catch(Throwable t) {
t.printStackTrace();
throw t;
}
}
});
}
/**
* Adds a proxy wrapper around the specified MetadataRepository that automatically
* resets the request context before every call and either commits or rolls
* back the graph transaction after every call.
*
* @param delegate
* @return
*/
public static MetadataRepository addTransactionWrapper(final MetadataRepository delegate) {
return (MetadataRepository)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class[]{MetadataRepository.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
boolean useTransaction = GraphBackedMetadataRepository.class.getMethod(
method.getName(), method.getParameterTypes())
.isAnnotationPresent(GraphTransaction.class);
try {
resetRequestContext();
Object result = method.invoke(delegate, args);
if(useTransaction) {
System.out.println("Committing changes");
getGraph().commit();
System.out.println("Commit succeeded.");
}
return result;
}
catch(InvocationTargetException e) {
e.getCause().printStackTrace();
if(useTransaction) {
System.out.println("Rolling back changes due to exception.");
getGraph().rollback();
}
throw e.getCause();
}
catch(Throwable t) {
t.printStackTrace();
if(useTransaction) {
System.out.println("Rolling back changes due to exception.");
getGraph().rollback();
}
throw t;
}
}
});
} }
} }
...@@ -87,6 +87,7 @@ public class GraphBackedDiscoveryServiceTest extends BaseRepositoryTest { ...@@ -87,6 +87,7 @@ public class GraphBackedDiscoveryServiceTest extends BaseRepositoryTest {
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp(); super.setUp();
repositoryService = TestUtils.addTransactionWrapper(repositoryService);
final TypeSystem typeSystem = TypeSystem.getInstance(); final TypeSystem typeSystem = TypeSystem.getInstance();
Collection<String> oldTypeNames = new HashSet<>(); Collection<String> oldTypeNames = new HashSet<>();
oldTypeNames.addAll(typeSystem.getTypeNames()); oldTypeNames.addAll(typeSystem.getTypeNames());
......
...@@ -114,43 +114,7 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase { ...@@ -114,43 +114,7 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
new GraphBackedSearchIndexer(new AtlasTypeRegistry()); new GraphBackedSearchIndexer(new AtlasTypeRegistry());
final GraphBackedMetadataRepository delegate = new GraphBackedMetadataRepository(getDeleteHandler(typeSystem)); final GraphBackedMetadataRepository delegate = new GraphBackedMetadataRepository(getDeleteHandler(typeSystem));
repositoryService = (MetadataRepository)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), repositoryService = TestUtils.addTransactionWrapper(delegate);
new Class[]{MetadataRepository.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
boolean useTransaction = GraphBackedMetadataRepository.class.getMethod(
method.getName(), method.getParameterTypes())
.isAnnotationPresent(GraphTransaction.class);
try {
Object result = method.invoke(delegate, args);
if(useTransaction) {
System.out.println("Committing changes");
TestUtils.getGraph().commit();
System.out.println("Commit succeeded.");
}
return result;
}
catch(InvocationTargetException e) {
e.getCause().printStackTrace();
if(useTransaction) {
System.out.println("Rolling back changes due to exception.");
TestUtils.getGraph().rollback();
}
throw e.getCause();
}
catch(Throwable t) {
t.printStackTrace();
if(useTransaction) {
System.out.println("Rolling back changes due to exception.");
TestUtils.getGraph().rollback();
}
throw t;
}
}
});
TestUtils.defineDeptEmployeeTypes(typeSystem); TestUtils.defineDeptEmployeeTypes(typeSystem);
TestUtils.createHiveTypes(typeSystem); TestUtils.createHiveTypes(typeSystem);
...@@ -531,7 +495,7 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase { ...@@ -531,7 +495,7 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
/** /**
* Verify deleting an entity which is contained by another * Verify deleting an entity which is contained by another
* entity through a bi-directional composite reference. * entity through a bi-directional composite reference.
* *
* @throws Exception * @throws Exception
*/ */
@Test @Test
...@@ -633,21 +597,21 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase { ...@@ -633,21 +597,21 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
@Test @Test
public void testDisconnectUnidirectionalArrayReferenceFromStructAndTraitTypes() throws Exception { public void testDisconnectUnidirectionalArrayReferenceFromStructAndTraitTypes() throws Exception {
// Define class types. // Define class types.
HierarchicalTypeDefinition<ClassType> structTargetDef = TypesUtil.createClassTypeDef("StructTarget", HierarchicalTypeDefinition<ClassType> structTargetDef = TypesUtil.createClassTypeDef("StructTarget",
ImmutableSet.<String>of(), TypesUtil.createOptionalAttrDef("attr1", DataTypes.STRING_TYPE)); ImmutableSet.<String>of(), TypesUtil.createOptionalAttrDef("attr1", DataTypes.STRING_TYPE));
HierarchicalTypeDefinition<ClassType> traitTargetDef = TypesUtil.createClassTypeDef("TraitTarget", HierarchicalTypeDefinition<ClassType> traitTargetDef = TypesUtil.createClassTypeDef("TraitTarget",
ImmutableSet.<String>of(), TypesUtil.createOptionalAttrDef("attr1", DataTypes.STRING_TYPE)); ImmutableSet.<String>of(), TypesUtil.createOptionalAttrDef("attr1", DataTypes.STRING_TYPE));
HierarchicalTypeDefinition<ClassType> structContainerDef = TypesUtil.createClassTypeDef("StructContainer", HierarchicalTypeDefinition<ClassType> structContainerDef = TypesUtil.createClassTypeDef("StructContainer",
ImmutableSet.<String>of(), TypesUtil.createOptionalAttrDef("struct", "TestStruct")); ImmutableSet.<String>of(), TypesUtil.createOptionalAttrDef("struct", "TestStruct"));
// Define struct and trait types which have a unidirectional array reference // Define struct and trait types which have a unidirectional array reference
// to a class type. // to a class type.
StructTypeDefinition structDef = TypesUtil.createStructTypeDef("TestStruct", StructTypeDefinition structDef = TypesUtil.createStructTypeDef("TestStruct",
new AttributeDefinition("target", DataTypes.arrayTypeName("StructTarget"), Multiplicity.OPTIONAL, false, null), new AttributeDefinition("target", DataTypes.arrayTypeName("StructTarget"), Multiplicity.OPTIONAL, false, null),
new AttributeDefinition("nestedStructs", DataTypes.arrayTypeName("NestedStruct"), Multiplicity.OPTIONAL, false, null)); new AttributeDefinition("nestedStructs", DataTypes.arrayTypeName("NestedStruct"), Multiplicity.OPTIONAL, false, null));
StructTypeDefinition nestedStructDef = TypesUtil.createStructTypeDef("NestedStruct", StructTypeDefinition nestedStructDef = TypesUtil.createStructTypeDef("NestedStruct",
TypesUtil.createOptionalAttrDef("attr1", DataTypes.STRING_TYPE)); TypesUtil.createOptionalAttrDef("attr1", DataTypes.STRING_TYPE));
HierarchicalTypeDefinition<TraitType> traitDef = TypesUtil.createTraitTypeDef("TestTrait", ImmutableSet.<String>of(), HierarchicalTypeDefinition<TraitType> traitDef = TypesUtil.createTraitTypeDef("TestTrait", ImmutableSet.<String>of(),
new AttributeDefinition("target", DataTypes.arrayTypeName("TraitTarget"), Multiplicity.OPTIONAL, false, null)); new AttributeDefinition("target", DataTypes.arrayTypeName("TraitTarget"), Multiplicity.OPTIONAL, false, null));
TypesDef typesDef = TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(), ImmutableList.of(structDef, nestedStructDef), TypesDef typesDef = TypesUtil.getTypesDef(ImmutableList.<EnumTypeDefinition>of(), ImmutableList.of(structDef, nestedStructDef),
...@@ -669,9 +633,9 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase { ...@@ -669,9 +633,9 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
ClassType traitTargetType = typeSystem.getDataType(ClassType.class, "TraitTarget"); ClassType traitTargetType = typeSystem.getDataType(ClassType.class, "TraitTarget");
ClassType structContainerType = typeSystem.getDataType(ClassType.class, "StructContainer"); ClassType structContainerType = typeSystem.getDataType(ClassType.class, "StructContainer");
ITypedReferenceableInstance structTargetConvertedEntity = ITypedReferenceableInstance structTargetConvertedEntity =
structTargetType.convert(structTargetEntity, Multiplicity.REQUIRED); structTargetType.convert(structTargetEntity, Multiplicity.REQUIRED);
ITypedReferenceableInstance traitTargetConvertedEntity = ITypedReferenceableInstance traitTargetConvertedEntity =
traitTargetType.convert(traitTargetEntity, Multiplicity.REQUIRED); traitTargetType.convert(traitTargetEntity, Multiplicity.REQUIRED);
ITypedReferenceableInstance structContainerConvertedEntity = ITypedReferenceableInstance structContainerConvertedEntity =
structContainerType.convert(structContainerEntity, Multiplicity.REQUIRED); structContainerType.convert(structContainerEntity, Multiplicity.REQUIRED);
...@@ -755,13 +719,13 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase { ...@@ -755,13 +719,13 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
@Test @Test
public void testDisconnectMapReferenceFromClassType() throws Exception { public void testDisconnectMapReferenceFromClassType() throws Exception {
// Define type for map value. // Define type for map value.
HierarchicalTypeDefinition<ClassType> mapValueDef = TypesUtil.createClassTypeDef("MapValue", HierarchicalTypeDefinition<ClassType> mapValueDef = TypesUtil.createClassTypeDef("MapValue",
ImmutableSet.<String>of(), ImmutableSet.<String>of(),
new AttributeDefinition("biMapOwner", "MapOwner", Multiplicity.OPTIONAL, false, "biMap")); new AttributeDefinition("biMapOwner", "MapOwner", Multiplicity.OPTIONAL, false, "biMap"));
// Define type with unidirectional and bidirectional map references, // Define type with unidirectional and bidirectional map references,
// where the map value is a class reference to MapValue. // where the map value is a class reference to MapValue.
HierarchicalTypeDefinition<ClassType> mapOwnerDef = TypesUtil.createClassTypeDef("MapOwner", HierarchicalTypeDefinition<ClassType> mapOwnerDef = TypesUtil.createClassTypeDef("MapOwner",
ImmutableSet.<String>of(), ImmutableSet.<String>of(),
new AttributeDefinition("map", DataTypes.mapTypeName(DataTypes.STRING_TYPE.getName(), new AttributeDefinition("map", DataTypes.mapTypeName(DataTypes.STRING_TYPE.getName(),
"MapValue"), Multiplicity.OPTIONAL, false, null), "MapValue"), Multiplicity.OPTIONAL, false, null),
...@@ -811,7 +775,7 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase { ...@@ -811,7 +775,7 @@ public abstract class GraphBackedMetadataRepositoryDeleteTestBase {
} }
// Delete the map value instance. // Delete the map value instance.
// This should disconnect the references from the map owner instance. // This should disconnect the references from the map owner instance.
deleteEntities(mapValueGuid); deleteEntities(mapValueGuid);
assertEntityDeleted(mapValueGuid); assertEntityDeleted(mapValueGuid);
assertTestDisconnectMapReferenceFromClassType(mapOwnerGuid); assertTestDisconnectMapReferenceFromClassType(mapOwnerGuid);
......
...@@ -28,6 +28,7 @@ import org.apache.atlas.TestUtils; ...@@ -28,6 +28,7 @@ import org.apache.atlas.TestUtils;
import org.apache.atlas.discovery.graph.GraphBackedDiscoveryService; import org.apache.atlas.discovery.graph.GraphBackedDiscoveryService;
import org.apache.atlas.query.QueryParams; import org.apache.atlas.query.QueryParams;
import org.apache.atlas.repository.Constants; import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.MetadataRepository;
import org.apache.atlas.repository.RepositoryException; import org.apache.atlas.repository.RepositoryException;
import org.apache.atlas.repository.graphdb.AtlasEdge; import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasEdgeDirection; import org.apache.atlas.repository.graphdb.AtlasEdgeDirection;
...@@ -76,7 +77,7 @@ import java.util.concurrent.Future; ...@@ -76,7 +77,7 @@ import java.util.concurrent.Future;
import javax.inject.Inject; import javax.inject.Inject;
import scala.actors.threadpool.Arrays; import java.util.Arrays;
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createClassTypeDef; import static org.apache.atlas.typesystem.types.utils.TypesUtil.createClassTypeDef;
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createUniqueRequiredAttrDef; import static org.apache.atlas.typesystem.types.utils.TypesUtil.createUniqueRequiredAttrDef;
...@@ -95,7 +96,7 @@ import static org.testng.Assert.assertTrue; ...@@ -95,7 +96,7 @@ import static org.testng.Assert.assertTrue;
public class GraphBackedMetadataRepositoryTest { public class GraphBackedMetadataRepositoryTest {
@Inject @Inject
private GraphBackedMetadataRepository repositoryService; private MetadataRepository repositoryService;
@Inject @Inject
private GraphBackedDiscoveryService discoveryService; private GraphBackedDiscoveryService discoveryService;
...@@ -109,6 +110,8 @@ public class GraphBackedMetadataRepositoryTest { ...@@ -109,6 +110,8 @@ public class GraphBackedMetadataRepositoryTest {
typeSystem = TypeSystem.getInstance(); typeSystem = TypeSystem.getInstance();
typeSystem.reset(); typeSystem.reset();
assertTrue(repositoryService instanceof GraphBackedMetadataRepository);
repositoryService = TestUtils.addTransactionWrapper(repositoryService);
new GraphBackedSearchIndexer(new AtlasTypeRegistry()); new GraphBackedSearchIndexer(new AtlasTypeRegistry());
TestUtils.defineDeptEmployeeTypes(typeSystem); TestUtils.defineDeptEmployeeTypes(typeSystem);
......
...@@ -97,6 +97,7 @@ public class AtlasEntityStoreV1Test { ...@@ -97,6 +97,7 @@ public class AtlasEntityStoreV1Test {
@BeforeClass @BeforeClass
public void setUp() throws Exception { public void setUp() throws Exception {
metadataService = TestUtils.addSessionCleanupWrapper(metadataService);
new GraphBackedSearchIndexer(typeRegistry); new GraphBackedSearchIndexer(typeRegistry);
final AtlasTypesDef deptTypesDef = TestUtilsV2.defineDeptEmployeeTypes(); final AtlasTypesDef deptTypesDef = TestUtilsV2.defineDeptEmployeeTypes();
typeDefStore.createTypesDef(deptTypesDef); typeDefStore.createTypesDef(deptTypesDef);
...@@ -112,6 +113,7 @@ public class AtlasEntityStoreV1Test { ...@@ -112,6 +113,7 @@ public class AtlasEntityStoreV1Test {
@AfterClass @AfterClass
public void clear() { public void clear() {
AtlasGraphProvider.cleanup(); AtlasGraphProvider.cleanup();
TestUtils.resetRequestContext();
} }
@BeforeTest @BeforeTest
......
...@@ -18,9 +18,30 @@ ...@@ -18,9 +18,30 @@
package org.apache.atlas.service; package org.apache.atlas.service;
import com.google.common.collect.ImmutableList; import static org.apache.atlas.TestUtils.COLUMNS_ATTR_NAME;
import com.google.common.collect.ImmutableSet; import static org.apache.atlas.TestUtils.COLUMN_TYPE;
import com.google.inject.Inject; import static org.apache.atlas.TestUtils.PII;
import static org.apache.atlas.TestUtils.TABLE_TYPE;
import static org.apache.atlas.TestUtils.createColumnEntity;
import static org.apache.atlas.TestUtils.createDBEntity;
import static org.apache.atlas.TestUtils.createInstance;
import static org.apache.atlas.TestUtils.createTableEntity;
import static org.apache.atlas.TestUtils.randomString;
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createClassTypeDef;
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createOptionalAttrDef;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.atlas.AtlasClient; import org.apache.atlas.AtlasClient;
import org.apache.atlas.AtlasException; import org.apache.atlas.AtlasException;
...@@ -32,6 +53,7 @@ import org.apache.atlas.discovery.graph.GraphBackedDiscoveryService; ...@@ -32,6 +53,7 @@ import org.apache.atlas.discovery.graph.GraphBackedDiscoveryService;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.listener.ChangedTypeDefs; import org.apache.atlas.listener.ChangedTypeDefs;
import org.apache.atlas.listener.EntityChangeListener; import org.apache.atlas.listener.EntityChangeListener;
import org.apache.atlas.listener.TypeDefChangeListener;
import org.apache.atlas.query.QueryParams; import org.apache.atlas.query.QueryParams;
import org.apache.atlas.repository.audit.EntityAuditRepository; import org.apache.atlas.repository.audit.EntityAuditRepository;
import org.apache.atlas.repository.audit.HBaseBasedAuditRepository; import org.apache.atlas.repository.audit.HBaseBasedAuditRepository;
...@@ -72,37 +94,17 @@ import org.testng.annotations.BeforeTest; ...@@ -72,37 +94,17 @@ import org.testng.annotations.BeforeTest;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.util.ArrayList; import com.google.common.collect.ImmutableList;
import java.util.Arrays; import com.google.common.collect.ImmutableSet;
import java.util.Collection; import com.google.inject.Inject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Collections;
import static org.apache.atlas.TestUtils.COLUMNS_ATTR_NAME;
import static org.apache.atlas.TestUtils.COLUMN_TYPE;
import static org.apache.atlas.TestUtils.DATABASE_TYPE;
import static org.apache.atlas.TestUtils.PII;
import static org.apache.atlas.TestUtils.TABLE_TYPE;
import static org.apache.atlas.TestUtils.createColumnEntity;
import static org.apache.atlas.TestUtils.createDBEntity;
import static org.apache.atlas.TestUtils.createInstance;
import static org.apache.atlas.TestUtils.createTableEntity;
import static org.apache.atlas.TestUtils.randomString;
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createClassTypeDef;
import static org.apache.atlas.typesystem.types.utils.TypesUtil.createOptionalAttrDef;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
@Guice(modules = RepositoryMetadataModule.class) @Guice(modules = RepositoryMetadataModule.class)
public class DefaultMetadataServiceTest { public class DefaultMetadataServiceTest {
@Inject @Inject
private MetadataService metadataService; private MetadataService metadataService;
private TypeDefChangeListener typeDefChangeListener;
@Inject @Inject
private EntityAuditRepository auditRepository; private EntityAuditRepository auditRepository;
...@@ -114,12 +116,16 @@ public class DefaultMetadataServiceTest { ...@@ -114,12 +116,16 @@ public class DefaultMetadataServiceTest {
private Referenceable table; private Referenceable table;
private Id tableId; private Id tableId;
private final String NAME = "name"; private final String NAME = "name";
@BeforeTest @BeforeTest
public void setUp() throws Exception { public void setUp() throws Exception {
typeDefChangeListener = (DefaultMetadataService)metadataService;
metadataService = TestUtils.addSessionCleanupWrapper(metadataService);
if (auditRepository instanceof HBaseBasedAuditRepository) { if (auditRepository instanceof HBaseBasedAuditRepository) {
HBaseTestUtils.startCluster(); HBaseTestUtils.startCluster();
((HBaseBasedAuditRepository) auditRepository).start(); ((HBaseBasedAuditRepository) auditRepository).start();
...@@ -1218,7 +1224,7 @@ public class DefaultMetadataServiceTest { ...@@ -1218,7 +1224,7 @@ public class DefaultMetadataServiceTest {
List<String> beforeChangeTypeNames = new ArrayList<>(); List<String> beforeChangeTypeNames = new ArrayList<>();
beforeChangeTypeNames.addAll(metadataService.getTypeNames(new HashMap<TypeCache.TYPE_FILTER, String>())); beforeChangeTypeNames.addAll(metadataService.getTypeNames(new HashMap<TypeCache.TYPE_FILTER, String>()));
((DefaultMetadataService)metadataService).onChange(new ChangedTypeDefs()); typeDefChangeListener.onChange(new ChangedTypeDefs());
List<String> afterChangeTypeNames = new ArrayList<>(); List<String> afterChangeTypeNames = new ArrayList<>();
afterChangeTypeNames.addAll(metadataService.getTypeNames(new HashMap<TypeCache.TYPE_FILTER, String>())); afterChangeTypeNames.addAll(metadataService.getTypeNames(new HashMap<TypeCache.TYPE_FILTER, String>()));
...@@ -1269,7 +1275,7 @@ public class DefaultMetadataServiceTest { ...@@ -1269,7 +1275,7 @@ public class DefaultMetadataServiceTest {
deletedEntities.add(entity.getId()._getId()); deletedEntities.add(entity.getId()._getId());
} }
} }
public List<String> getDeletedEntities() { public List<String> getDeletedEntities() {
return deletedEntities; return deletedEntities;
} }
......
...@@ -18,6 +18,14 @@ ...@@ -18,6 +18,14 @@
package org.apache.atlas; package org.apache.atlas;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.atlas.metrics.Metrics; import org.apache.atlas.metrics.Metrics;
import org.apache.atlas.typesystem.ITypedReferenceableInstance; import org.apache.atlas.typesystem.ITypedReferenceableInstance;
import org.apache.atlas.typesystem.persistence.Id; import org.apache.atlas.typesystem.persistence.Id;
...@@ -26,12 +34,6 @@ import org.apache.atlas.typesystem.types.TypeSystem; ...@@ -26,12 +34,6 @@ import org.apache.atlas.typesystem.types.TypeSystem;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class RequestContext { public class RequestContext {
private static final Logger LOG = LoggerFactory.getLogger(RequestContext.class); private static final Logger LOG = LoggerFactory.getLogger(RequestContext.class);
...@@ -41,6 +43,7 @@ public class RequestContext { ...@@ -41,6 +43,7 @@ public class RequestContext {
private Set<String> updatedEntityIds = new LinkedHashSet<>(); private Set<String> updatedEntityIds = new LinkedHashSet<>();
private Set<String> deletedEntityIds = new LinkedHashSet<>(); private Set<String> deletedEntityIds = new LinkedHashSet<>();
private List<ITypedReferenceableInstance> deletedEntities = new ArrayList<>(); private List<ITypedReferenceableInstance> deletedEntities = new ArrayList<>();
private Map<String,ITypedReferenceableInstance> entityCache = new HashMap<>();
private String user; private String user;
private long requestTime; private long requestTime;
...@@ -71,7 +74,27 @@ public class RequestContext { ...@@ -71,7 +74,27 @@ public class RequestContext {
return context; return context;
} }
/**
* Adds the specified instance to the cache
*
*/
public void cache(ITypedReferenceableInstance instance) {
entityCache.put(instance.getId()._getId(), instance);
}
/**
* Checks if an instance with the given guid is in the cache for this request. Either returns the instance
* or null if it is not in the cache.
*
* @param guid the guid to find
* @return Either the instance or null if it is not in the cache.
*/
public ITypedReferenceableInstance getInstance(String guid) {
return entityCache.get(guid);
}
public static void clear() { public static void clear() {
CURRENT_CONTEXT.get().entityCache.clear();
CURRENT_CONTEXT.remove(); CURRENT_CONTEXT.remove();
} }
...@@ -122,7 +145,7 @@ public class RequestContext { ...@@ -122,7 +145,7 @@ public class RequestContext {
public long getRequestTime() { public long getRequestTime() {
return requestTime; return requestTime;
} }
public boolean isDeletedEntity(String entityGuid) { public boolean isDeletedEntity(String entityGuid) {
return deletedEntityIds.contains(entityGuid); return deletedEntityIds.contains(entityGuid);
} }
......
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