Commit b10b34e0 by Shwetha G S

Merge pull request #139 from sumashivaprasad/api_merged

Fixed indexing issues across data types not supported in backing index and API response codes
parents 189ba064 92afb649
...@@ -85,7 +85,7 @@ public abstract class ABridge implements IBridge { ...@@ -85,7 +85,7 @@ public abstract class ABridge implements IBridge {
ITypedReferenceableInstance refBean = null; ITypedReferenceableInstance refBean = null;
try { try {
refBean = type.convert(this.convertToReferencable(bean), Multiplicity.REQUIRED); refBean = type.convert(this.convertToReferencable(bean), Multiplicity.REQUIRED);
String id = repo.createEntity(refBean, type.getName()); String id = repo.createEntity(refBean);
return id; return id;
} catch (IllegalArgumentException | IllegalAccessException e) { } catch (IllegalArgumentException | IllegalAccessException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
......
...@@ -44,7 +44,7 @@ public class GraphTransactionInterceptor implements MethodInterceptor { ...@@ -44,7 +44,7 @@ public class GraphTransactionInterceptor implements MethodInterceptor {
return response; return response;
} catch (Throwable t){ } catch (Throwable t){
titanGraph.rollback(); titanGraph.rollback();
LOG.debug("graph rollback"); LOG.error("graph rollback due to exception ", t);
throw t; throw t;
} }
} }
......
...@@ -41,6 +41,7 @@ import org.apache.atlas.services.MetadataService; ...@@ -41,6 +41,7 @@ import org.apache.atlas.services.MetadataService;
* Guice module for Repository module. * Guice module for Repository module.
*/ */
public class RepositoryMetadataModule extends com.google.inject.AbstractModule { public class RepositoryMetadataModule extends com.google.inject.AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
// special wiring for Titan Graph // special wiring for Titan Graph
...@@ -66,7 +67,7 @@ public class RepositoryMetadataModule extends com.google.inject.AbstractModule { ...@@ -66,7 +67,7 @@ public class RepositoryMetadataModule extends com.google.inject.AbstractModule {
// bind the DiscoveryService interface to an implementation // bind the DiscoveryService interface to an implementation
bind(DiscoveryService.class).to(GraphBackedDiscoveryService.class).asEagerSingleton(); bind(DiscoveryService.class).to(GraphBackedDiscoveryService.class).asEagerSingleton();
bind(SearchIndexer.class).to(GraphBackedSearchIndexer.class).asEagerSingleton(); bind(SearchIndexer.class).to(GraphBackedSearchIndexer.class);
bind(LineageService.class).to(HiveLineageService.class).asEagerSingleton(); bind(LineageService.class).to(HiveLineageService.class).asEagerSingleton();
...@@ -74,4 +75,5 @@ public class RepositoryMetadataModule extends com.google.inject.AbstractModule { ...@@ -74,4 +75,5 @@ public class RepositoryMetadataModule extends com.google.inject.AbstractModule {
requestInjection(interceptor); requestInjection(interceptor);
bindInterceptor(Matchers.any(), Matchers.annotatedWith(GraphTransaction.class), interceptor); bindInterceptor(Matchers.any(), Matchers.annotatedWith(GraphTransaction.class), interceptor);
} }
} }
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
package org.apache.atlas.discovery; package org.apache.atlas.discovery;
import org.apache.atlas.listener.TypesChangeListener; import org.apache.atlas.listener.TypesChangeListener;
import org.apache.atlas.repository.IndexException;
/** /**
...@@ -26,4 +27,11 @@ import org.apache.atlas.listener.TypesChangeListener; ...@@ -26,4 +27,11 @@ import org.apache.atlas.listener.TypesChangeListener;
*/ */
public interface SearchIndexer extends TypesChangeListener { public interface SearchIndexer extends TypesChangeListener {
/* Commit the indexes */
void commit() throws IndexException;
/* RollBack the index */
void rollback() throws IndexException;
} }
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
package org.apache.atlas.discovery.graph; package org.apache.atlas.discovery.graph;
import com.thinkaurelius.titan.core.TitanVertex; import com.thinkaurelius.titan.core.TitanVertex;
import org.apache.atlas.GraphTransaction;
import org.apache.atlas.MetadataException; import org.apache.atlas.MetadataException;
import org.apache.atlas.query.Expressions; import org.apache.atlas.query.Expressions;
import org.apache.atlas.query.GraphPersistenceStrategies; import org.apache.atlas.query.GraphPersistenceStrategies;
......
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.atlas.repository;
public class IndexCreationException extends IndexException {
public IndexCreationException() {
}
public IndexCreationException(String message) {
super(message);
}
public IndexCreationException(String message, Throwable cause) {
super(message, cause);
}
public IndexCreationException(Throwable cause) {
super(cause);
}
public IndexCreationException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.atlas.repository;
import org.apache.atlas.MetadataException;
public class IndexException extends MetadataException {
public IndexException() {
}
public IndexException(String message) {
super(message);
}
public IndexException(String message, Throwable cause) {
super(message, cause);
}
public IndexException(Throwable cause) {
super(cause);
}
public IndexException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
...@@ -257,6 +257,8 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -257,6 +257,8 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
((TitanVertex) instanceVertex) ((TitanVertex) instanceVertex)
.addProperty(Constants.TRAIT_NAMES_PROPERTY_KEY, traitName); .addProperty(Constants.TRAIT_NAMES_PROPERTY_KEY, traitName);
} catch (RepositoryException e) {
throw e;
} catch (Exception e) { } catch (Exception e) {
throw new RepositoryException(e); throw new RepositoryException(e);
} }
...@@ -279,7 +281,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -279,7 +281,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
List<String> traitNames = getTraitNames(instanceVertex); List<String> traitNames = getTraitNames(instanceVertex);
if (!traitNames.contains(traitNameToBeDeleted)) { if (!traitNames.contains(traitNameToBeDeleted)) {
throw new RepositoryException("Could not find trait=" + traitNameToBeDeleted throw new EntityNotFoundException("Could not find trait=" + traitNameToBeDeleted
+ " in the repository for entity: " + guid); + " in the repository for entity: " + guid);
} }
...@@ -302,6 +304,8 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -302,6 +304,8 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
updateTraits(instanceVertex, traitNames); updateTraits(instanceVertex, traitNames);
} }
} }
} catch (RepositoryException e) {
throw e;
} catch (Exception e) { } catch (Exception e) {
throw new RepositoryException(e); throw new RepositoryException(e);
} }
...@@ -350,6 +354,8 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -350,6 +354,8 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
instanceToGraphMapper.mapAttributesToVertex(getIdFromVertex(typeName, instanceVertex), instanceToGraphMapper.mapAttributesToVertex(getIdFromVertex(typeName, instanceVertex),
instance, instanceVertex, new HashMap<Id, Vertex>(), instance, instanceVertex, new HashMap<Id, Vertex>(),
attributeInfo, attributeInfo.dataType()); attributeInfo, attributeInfo.dataType());
} catch (RepositoryException e) {
throw e;
} catch (Exception e) { } catch (Exception e) {
throw new RepositoryException(e); throw new RepositoryException(e);
} }
...@@ -426,7 +432,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -426,7 +432,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
} }
} }
public void createVerticesForClassTypes( private void createVerticesForClassTypes(
List<ITypedReferenceableInstance> newInstances) throws MetadataException { List<ITypedReferenceableInstance> newInstances) throws MetadataException {
for (ITypedReferenceableInstance typedInstance : newInstances) { for (ITypedReferenceableInstance typedInstance : newInstances) {
final Id id = typedInstance.getId(); final Id id = typedInstance.getId();
...@@ -955,7 +961,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -955,7 +961,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
return typedInstance; return typedInstance;
} }
public void mapVertexToInstanceTraits(Vertex instanceVertex, private void mapVertexToInstanceTraits(Vertex instanceVertex,
ITypedReferenceableInstance typedInstance, ITypedReferenceableInstance typedInstance,
List<String> traits) throws MetadataException { List<String> traits) throws MetadataException {
for (String traitName : traits) { for (String traitName : traits) {
...@@ -977,7 +983,8 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -977,7 +983,8 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
} }
} }
public void mapVertexToAttribute(Vertex instanceVertex, ITypedInstance typedInstance,
private void mapVertexToAttribute(Vertex instanceVertex, ITypedInstance typedInstance,
AttributeInfo attributeInfo) throws MetadataException { AttributeInfo attributeInfo) throws MetadataException {
LOG.debug("Mapping attributeInfo {}", attributeInfo.name); LOG.debug("Mapping attributeInfo {}", attributeInfo.name);
final IDataType dataType = attributeInfo.dataType(); final IDataType dataType = attributeInfo.dataType();
...@@ -1027,7 +1034,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -1027,7 +1034,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
} }
} }
public Object mapClassReferenceToVertex(Vertex instanceVertex, private Object mapClassReferenceToVertex(Vertex instanceVertex,
AttributeInfo attributeInfo, AttributeInfo attributeInfo,
String relationshipLabel, String relationshipLabel,
IDataType dataType) throws MetadataException { IDataType dataType) throws MetadataException {
...@@ -1057,7 +1064,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -1057,7 +1064,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void mapVertexToArrayInstance(Vertex instanceVertex, ITypedInstance typedInstance, private void mapVertexToArrayInstance(Vertex instanceVertex, ITypedInstance typedInstance,
AttributeInfo attributeInfo, AttributeInfo attributeInfo,
String propertyName) throws MetadataException { String propertyName) throws MetadataException {
LOG.debug("mapping vertex {} to array {}", instanceVertex, attributeInfo.name); LOG.debug("mapping vertex {} to array {}", instanceVertex, attributeInfo.name);
...@@ -1077,7 +1084,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -1077,7 +1084,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
typedInstance.set(attributeInfo.name, values); typedInstance.set(attributeInfo.name, values);
} }
public Object mapVertexToCollectionEntry(Vertex instanceVertex, private Object mapVertexToCollectionEntry(Vertex instanceVertex,
AttributeInfo attributeInfo, AttributeInfo attributeInfo,
IDataType elementType, Object value, String propertyName) IDataType elementType, Object value, String propertyName)
throws MetadataException { throws MetadataException {
...@@ -1161,7 +1168,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -1161,7 +1168,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
return null; return null;
} }
public Object mapClassReferenceToVertex(Vertex instanceVertex, private Object mapClassReferenceToVertex(Vertex instanceVertex,
AttributeInfo attributeInfo, AttributeInfo attributeInfo,
String relationshipLabel, String relationshipLabel,
IDataType dataType, IDataType dataType,
...@@ -1228,7 +1235,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository { ...@@ -1228,7 +1235,7 @@ public class GraphBackedMetadataRepository implements MetadataRepository {
traitName, traitType, traitInstance); traitName, traitType, traitInstance);
} }
public void mapVertexToTraitInstance(Vertex instanceVertex, String typedInstanceTypeName, private void mapVertexToTraitInstance(Vertex instanceVertex, String typedInstanceTypeName,
String traitName, TraitType traitType, String traitName, TraitType traitType,
ITypedStruct traitInstance) throws MetadataException { ITypedStruct traitInstance) throws MetadataException {
String relationshipLabel = getEdgeLabel(typedInstanceTypeName, traitName); String relationshipLabel = getEdgeLabel(typedInstanceTypeName, traitName);
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
package org.apache.atlas.repository.graph; package org.apache.atlas.repository.graph;
import com.google.inject.Singleton;
import com.thinkaurelius.titan.core.Cardinality; import com.thinkaurelius.titan.core.Cardinality;
import com.thinkaurelius.titan.core.PropertyKey; import com.thinkaurelius.titan.core.PropertyKey;
import com.thinkaurelius.titan.core.TitanGraph; import com.thinkaurelius.titan.core.TitanGraph;
...@@ -30,6 +29,8 @@ import com.tinkerpop.blueprints.Vertex; ...@@ -30,6 +29,8 @@ import com.tinkerpop.blueprints.Vertex;
import org.apache.atlas.MetadataException; import org.apache.atlas.MetadataException;
import org.apache.atlas.discovery.SearchIndexer; import org.apache.atlas.discovery.SearchIndexer;
import org.apache.atlas.repository.Constants; import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.IndexCreationException;
import org.apache.atlas.repository.IndexException;
import org.apache.atlas.repository.RepositoryException; import org.apache.atlas.repository.RepositoryException;
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;
...@@ -49,19 +50,24 @@ import java.util.Map; ...@@ -49,19 +50,24 @@ import java.util.Map;
/** /**
* Adds index for properties of a given type when its added before any instances are added. * Adds index for properties of a given type when its added before any instances are added.
*/ */
@Singleton
public class GraphBackedSearchIndexer implements SearchIndexer { public class GraphBackedSearchIndexer implements SearchIndexer {
private static final Logger LOG = LoggerFactory.getLogger(GraphBackedSearchIndexer.class); private static final Logger LOG = LoggerFactory.getLogger(GraphBackedSearchIndexer.class);
private final TitanGraph titanGraph; private final TitanGraph titanGraph;
private TitanManagement management;
@Inject @Inject
public GraphBackedSearchIndexer(GraphProvider<TitanGraph> graphProvider) public GraphBackedSearchIndexer(GraphProvider<TitanGraph> graphProvider)
throws RepositoryException { throws RepositoryException {
this.titanGraph = graphProvider.get(); this.titanGraph = graphProvider.get();
/* Create the transaction for indexing.
* Commit/rollback is expected to be called from the caller.
*/
management = titanGraph.getManagementSystem();
initialize(); initialize();
} }
...@@ -69,18 +75,17 @@ public class GraphBackedSearchIndexer implements SearchIndexer { ...@@ -69,18 +75,17 @@ public class GraphBackedSearchIndexer implements SearchIndexer {
* Initializes the indices for the graph - create indices for Global Vertex Keys * Initializes the indices for the graph - create indices for Global Vertex Keys
*/ */
private void initialize() { private void initialize() {
TitanManagement management = titanGraph.getManagementSystem();
if (management.containsPropertyKey(Constants.GUID_PROPERTY_KEY)) { if (management.containsPropertyKey(Constants.GUID_PROPERTY_KEY)) {
LOG.info("Global indexes already exist for graph"); LOG.info("Global indexes already exist for graph");
return; return;
} }
/* This is called only once, which is the first time Atlas types are made indexable .*/
LOG.info("Indexes do not exist, Creating indexes for titanGraph."); LOG.info("Indexes do not exist, Creating indexes for titanGraph.");
management.buildIndex(Constants.VERTEX_INDEX, Vertex.class) management.buildIndex(Constants.VERTEX_INDEX, Vertex.class)
.buildMixedIndex(Constants.BACKING_INDEX); .buildMixedIndex(Constants.BACKING_INDEX);
management.buildIndex(Constants.EDGE_INDEX, Edge.class) management.buildIndex(Constants.EDGE_INDEX, Edge.class)
.buildMixedIndex(Constants.BACKING_INDEX); .buildMixedIndex(Constants.BACKING_INDEX);
management.commit();
// create a composite index for guid as its unique // create a composite index for guid as its unique
createCompositeIndex(Constants.GUID_INDEX, createCompositeIndex(Constants.GUID_INDEX,
...@@ -105,18 +110,20 @@ public class GraphBackedSearchIndexer implements SearchIndexer { ...@@ -105,18 +110,20 @@ public class GraphBackedSearchIndexer implements SearchIndexer {
//Indexes for graph backed type system store //Indexes for graph backed type system store
createTypeStoreIndexes(); createTypeStoreIndexes();
management.commit();
//Make sure we acquire another transaction after commit for subsequent indexing
management = titanGraph.getManagementSystem();
LOG.info("Index creation for global keys complete."); LOG.info("Index creation for global keys complete.");
} }
private void createFullTextIndex() { private void createFullTextIndex() {
TitanManagement management = titanGraph.getManagementSystem();
PropertyKey fullText = PropertyKey fullText =
management.makePropertyKey(Constants.ENTITY_TEXT_PROPERTY_KEY).dataType(String.class).make(); management.makePropertyKey(Constants.ENTITY_TEXT_PROPERTY_KEY).dataType(String.class).make();
management.buildIndex(Constants.FULLTEXT_INDEX, Vertex.class) management.buildIndex(Constants.FULLTEXT_INDEX, Vertex.class)
.addKey(fullText, com.thinkaurelius.titan.core.schema.Parameter.of("mapping", Mapping.TEXT)) .addKey(fullText, com.thinkaurelius.titan.core.schema.Parameter.of("mapping", Mapping.TEXT))
.buildMixedIndex(Constants.BACKING_INDEX); .buildMixedIndex(Constants.BACKING_INDEX);
management.commit();
LOG.info("Created mixed index for {}", Constants.ENTITY_TEXT_PROPERTY_KEY); LOG.info("Created mixed index for {}", Constants.ENTITY_TEXT_PROPERTY_KEY);
} }
...@@ -147,9 +154,8 @@ public class GraphBackedSearchIndexer implements SearchIndexer { ...@@ -147,9 +154,8 @@ public class GraphBackedSearchIndexer implements SearchIndexer {
LOG.info("Index creation for type {} complete", typeName); LOG.info("Index creation for type {} complete", typeName);
} catch (Throwable throwable) { } catch (Throwable throwable) {
// gets handle to currently open transaction
titanGraph.getManagementSystem().rollback();
LOG.error("Error creating index for type {}", dataType, throwable); LOG.error("Error creating index for type {}", dataType, throwable);
throw new IndexCreationException("Error while creating index for type " + dataType, throwable);
} }
} }
...@@ -282,7 +288,6 @@ public class GraphBackedSearchIndexer implements SearchIndexer { ...@@ -282,7 +288,6 @@ public class GraphBackedSearchIndexer implements SearchIndexer {
private PropertyKey createCompositeIndex(String indexName, private PropertyKey createCompositeIndex(String indexName,
String propertyName, Class propertyClass, String propertyName, Class propertyClass,
boolean isUnique, Cardinality cardinality) { boolean isUnique, Cardinality cardinality) {
TitanManagement management = titanGraph.getManagementSystem();
PropertyKey propertyKey = management.getPropertyKey(propertyName); PropertyKey propertyKey = management.getPropertyKey(propertyName);
if (propertyKey == null) { if (propertyKey == null) {
propertyKey = management propertyKey = management
...@@ -300,8 +305,6 @@ public class GraphBackedSearchIndexer implements SearchIndexer { ...@@ -300,8 +305,6 @@ public class GraphBackedSearchIndexer implements SearchIndexer {
} }
indexBuilder.buildCompositeIndex(); indexBuilder.buildCompositeIndex();
management.commit();
LOG.info("Created index for property {} in composite index {}", propertyName, indexName); LOG.info("Created index for property {} in composite index {}", propertyName, indexName);
} }
...@@ -309,7 +312,7 @@ public class GraphBackedSearchIndexer implements SearchIndexer { ...@@ -309,7 +312,7 @@ public class GraphBackedSearchIndexer implements SearchIndexer {
} }
private PropertyKey createVertexMixedIndex(String propertyName, Class propertyClass) { private PropertyKey createVertexMixedIndex(String propertyName, Class propertyClass) {
TitanManagement management = titanGraph.getManagementSystem();
PropertyKey propertyKey = management.getPropertyKey(propertyName); PropertyKey propertyKey = management.getPropertyKey(propertyName);
if (propertyKey == null) { if (propertyKey == null) {
// ignored cardinality as Can only index single-valued property keys on vertices // ignored cardinality as Can only index single-valued property keys on vertices
...@@ -318,15 +321,17 @@ public class GraphBackedSearchIndexer implements SearchIndexer { ...@@ -318,15 +321,17 @@ public class GraphBackedSearchIndexer implements SearchIndexer {
.dataType(propertyClass) .dataType(propertyClass)
.make(); .make();
if (propertyClass == Boolean.class) { if (!checkIfMixedIndexApplicable(propertyClass)) {
LOG.debug("Creating composite index for property {} of type {} ", propertyName, propertyClass.getName());
//Use standard index as backing index only supports string, int and geo types //Use standard index as backing index only supports string, int and geo types
management.buildIndex(propertyName, Vertex.class).addKey(propertyKey).buildCompositeIndex(); management.buildIndex(propertyName, Vertex.class).addKey(propertyKey).buildCompositeIndex();
management.commit(); LOG.debug("Created composite index for property {} of type {} ", propertyName, propertyClass.getName());
} else { } else {
//Use backing index //Use backing index
LOG.debug("Creating backing index for property {} of type {} ", propertyName, propertyClass.getName());
TitanGraphIndex vertexIndex = management.getGraphIndex(Constants.VERTEX_INDEX); TitanGraphIndex vertexIndex = management.getGraphIndex(Constants.VERTEX_INDEX);
management.addIndexKey(vertexIndex, propertyKey); management.addIndexKey(vertexIndex, propertyKey);
management.commit(); LOG.debug("Created backing index for property {} of type {} ", propertyName, propertyClass.getName());
} }
LOG.info("Created mixed vertex index for property {}", propertyName); LOG.info("Created mixed vertex index for property {}", propertyName);
} }
...@@ -334,15 +339,41 @@ public class GraphBackedSearchIndexer implements SearchIndexer { ...@@ -334,15 +339,41 @@ public class GraphBackedSearchIndexer implements SearchIndexer {
return propertyKey; return propertyKey;
} }
private boolean checkIfMixedIndexApplicable(Class propertyClass) {
//TODO - Check why date types are failing in ES/Solr
if (propertyClass == Boolean.class || propertyClass == BigDecimal.class || propertyClass == BigInteger.class || propertyClass == Date.class) {
return false;
}
return true;
}
@Override
public void commit() throws IndexException {
try {
management.commit();
} catch (Exception e) {
LOG.error("Index commit failed" , e);
throw new IndexException("Index commit failed " , e);
}
}
@Override
public void rollback() throws IndexException {
try {
management.rollback();
} catch (Exception e) {
LOG.error("Index rollback failed " , e);
throw new IndexException("Index rollback failed " , e);
}
}
/* Commenting this out since we do not need an index for edge label here /* Commenting this out since we do not need an index for edge label here
private void createEdgeMixedIndex(String propertyName) { private void createEdgeMixedIndex(String propertyName) {
TitanManagement management = titanGraph.getManagementSystem();
EdgeLabel edgeLabel = management.getEdgeLabel(propertyName); EdgeLabel edgeLabel = management.getEdgeLabel(propertyName);
if (edgeLabel == null) { if (edgeLabel == null) {
edgeLabel = management.makeEdgeLabel(propertyName).make(); edgeLabel = management.makeEdgeLabel(propertyName).make();
management.buildEdgeIndex(edgeLabel, propertyName, Direction.BOTH, Order.DEFAULT); management.buildEdgeIndex(edgeLabel, propertyName, Direction.BOTH, Order.DEFAULT);
management.commit();
LOG.info("Created index for edge label {}", propertyName); LOG.info("Created index for edge label {}", propertyName);
} }
} */ }*/
} }
...@@ -74,6 +74,7 @@ public class GraphBackedTypeStore implements ITypeStore { ...@@ -74,6 +74,7 @@ public class GraphBackedTypeStore implements ITypeStore {
} }
@Override @Override
@GraphTransaction
public void store(TypeSystem typeSystem, ImmutableList<String> typeNames) throws MetadataException { public void store(TypeSystem typeSystem, ImmutableList<String> typeNames) throws MetadataException {
ImmutableList<String> coreTypes = typeSystem.getCoreTypes(); ImmutableList<String> coreTypes = typeSystem.getCoreTypes();
for (String typeName : typeNames) { for (String typeName : typeNames) {
......
...@@ -20,14 +20,17 @@ package org.apache.atlas.services; ...@@ -20,14 +20,17 @@ package org.apache.atlas.services;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.inject.Provider;
import org.apache.atlas.GraphTransaction; import org.apache.atlas.GraphTransaction;
import org.apache.atlas.MetadataException; import org.apache.atlas.MetadataException;
import org.apache.atlas.MetadataServiceClient; import org.apache.atlas.MetadataServiceClient;
import org.apache.atlas.ParamChecker; import org.apache.atlas.ParamChecker;
import org.apache.atlas.TypeNotFoundException;
import org.apache.atlas.classification.InterfaceAudience; import org.apache.atlas.classification.InterfaceAudience;
import org.apache.atlas.discovery.SearchIndexer; import org.apache.atlas.discovery.SearchIndexer;
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.IndexCreationException;
import org.apache.atlas.repository.MetadataRepository; import org.apache.atlas.repository.MetadataRepository;
import org.apache.atlas.repository.typestore.ITypeStore; import org.apache.atlas.repository.typestore.ITypeStore;
import org.apache.atlas.typesystem.ITypedReferenceableInstance; import org.apache.atlas.typesystem.ITypedReferenceableInstance;
...@@ -56,6 +59,9 @@ import org.slf4j.LoggerFactory; ...@@ -56,6 +59,9 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -71,22 +77,22 @@ public class DefaultMetadataService implements MetadataService { ...@@ -71,22 +77,22 @@ public class DefaultMetadataService implements MetadataService {
private static final Logger LOG = private static final Logger LOG =
LoggerFactory.getLogger(DefaultMetadataService.class); LoggerFactory.getLogger(DefaultMetadataService.class);
private final Set<TypesChangeListener> typesChangeListeners = new LinkedHashSet<>();
private final Set<EntityChangeListener> entityChangeListeners private final Set<EntityChangeListener> entityChangeListeners
= new LinkedHashSet<>(); = new LinkedHashSet<>();
private final TypeSystem typeSystem; private final TypeSystem typeSystem;
private final MetadataRepository repository; private final MetadataRepository repository;
private final ITypeStore typeStore; private final ITypeStore typeStore;
private final Set<Provider<SearchIndexer>> typeChangeListeners;
@Inject @Inject
DefaultMetadataService(MetadataRepository repository, DefaultMetadataService(final MetadataRepository repository,
SearchIndexer searchIndexer, ITypeStore typeStore) throws MetadataException { final Provider<SearchIndexer> searchIndexProvider, final ITypeStore typeStore) throws MetadataException {
this.typeStore = typeStore; this.typeStore = typeStore;
this.typeSystem = TypeSystem.getInstance(); this.typeSystem = TypeSystem.getInstance();
this.repository = repository; this.repository = repository;
registerListener(searchIndexer); this.typeChangeListeners = new LinkedHashSet<Provider<SearchIndexer>>() {{ add(searchIndexProvider); }};
restoreTypeSystem(); restoreTypeSystem();
} }
...@@ -149,30 +155,32 @@ public class DefaultMetadataService implements MetadataService { ...@@ -149,30 +155,32 @@ public class DefaultMetadataService implements MetadataService {
* @return a unique id for this type * @return a unique id for this type
*/ */
@Override @Override
@GraphTransaction
public JSONObject createType(String typeDefinition) throws MetadataException { public JSONObject createType(String typeDefinition) throws MetadataException {
ParamChecker.notEmpty(typeDefinition, "type definition cannot be empty"); ParamChecker.notEmpty(typeDefinition, "type definition cannot be empty");
TypesDef typesDef; TypesDef typesDef;
try { try {
typesDef = TypesSerialization.fromJson(typeDefinition); typesDef = TypesSerialization.fromJson(typeDefinition);
if(typesDef.isEmpty()) { if (typesDef.isEmpty()) {
throw new MetadataException("Invalid type definition"); throw new MetadataException("Invalid type definition");
} }
} catch (Exception e) { } catch (Exception e) {
LOG.error("Unable to deserialize json={}", typeDefinition, e); LOG.error("Unable to deserialize json={}", typeDefinition, e);
throw new IllegalArgumentException("Unable to deserialize json"); throw new IllegalArgumentException("Unable to deserialize json ", e);
} }
try { try {
final Map<String, IDataType> typesAdded = typeSystem.defineTypes(typesDef); final Map<String, IDataType> typesAdded = typeSystem.defineTypes(typesDef);
try { try {
typeStore.store(typeSystem, ImmutableList.copyOf(typesAdded.keySet())); /* Create indexes first so that if index creation fails then we rollback
the typesystem and also do not persist the graph
*/
onTypesAddedToRepo(typesAdded); onTypesAddedToRepo(typesAdded);
} catch(Throwable t) { typeStore.store(typeSystem, ImmutableList.copyOf(typesAdded.keySet()));
typeSystem.removeTypes(ImmutableList.copyOf(typesAdded.keySet())); } catch (Throwable t) {
throw new MetadataException(t); typeSystem.removeTypes(typesAdded.keySet());
throw new MetadataException("Unable to persist types ", t);
} }
return new JSONObject() {{ return new JSONObject() {{
...@@ -180,7 +188,7 @@ public class DefaultMetadataService implements MetadataService { ...@@ -180,7 +188,7 @@ public class DefaultMetadataService implements MetadataService {
}}; }};
} catch (JSONException e) { } catch (JSONException e) {
LOG.error("Unable to create response for types={}", typeDefinition, e); LOG.error("Unable to create response for types={}", typeDefinition, e);
throw new MetadataException("Unable to create response"); throw new MetadataException("Unable to create response ", e);
} }
} }
...@@ -294,7 +302,7 @@ public class DefaultMetadataService implements MetadataService { ...@@ -294,7 +302,7 @@ public class DefaultMetadataService implements MetadataService {
// verify if the type exists // verify if the type exists
if (!typeSystem.isRegistered(entityType)) { if (!typeSystem.isRegistered(entityType)) {
throw new MetadataException("type is not defined for : " + entityType); throw new TypeNotFoundException("type is not defined for : " + entityType);
} }
} }
...@@ -328,8 +336,12 @@ public class DefaultMetadataService implements MetadataService { ...@@ -328,8 +336,12 @@ public class DefaultMetadataService implements MetadataService {
final String traitName = traitInstance.getTypeName(); final String traitName = traitInstance.getTypeName();
// ensure trait type is already registered with the TS // ensure trait type is already registered with the TS
Preconditions.checkArgument(typeSystem.isRegistered(traitName), if ( !typeSystem.isRegistered(traitName) ) {
"trait=%s should be defined in type system before it can be added", traitName); String msg = String.format("trait=%s should be defined in type system before it can be added", traitName);
LOG.error(msg);
throw new TypeNotFoundException(msg);
}
// ensure trait is not already defined // ensure trait is not already defined
Preconditions.checkArgument(!getTraitNames(guid).contains(traitName), Preconditions.checkArgument(!getTraitNames(guid).contains(traitName),
"trait=%s is already defined for entity=%s", traitName, guid); "trait=%s is already defined for entity=%s", traitName, guid);
...@@ -340,7 +352,7 @@ public class DefaultMetadataService implements MetadataService { ...@@ -340,7 +352,7 @@ public class DefaultMetadataService implements MetadataService {
} }
private ITypedStruct deserializeTraitInstance(String traitInstanceDefinition) private ITypedStruct deserializeTraitInstance(String traitInstanceDefinition)
throws MetadataException { throws MetadataException {
try { try {
Struct traitInstance = InstanceSerialization.fromJsonStruct( Struct traitInstance = InstanceSerialization.fromJsonStruct(
...@@ -351,6 +363,8 @@ public class DefaultMetadataService implements MetadataService { ...@@ -351,6 +363,8 @@ public class DefaultMetadataService implements MetadataService {
TraitType traitType = typeSystem.getDataType(TraitType.class, entityTypeName); TraitType traitType = typeSystem.getDataType(TraitType.class, entityTypeName);
return traitType.convert( return traitType.convert(
traitInstance, Multiplicity.REQUIRED); traitInstance, Multiplicity.REQUIRED);
} catch ( TypeNotFoundException e ) {
throw e;
} catch (Exception e) { } catch (Exception e) {
throw new MetadataException("Error deserializing trait instance", e); throw new MetadataException("Error deserializing trait instance", e);
} }
...@@ -370,9 +384,12 @@ public class DefaultMetadataService implements MetadataService { ...@@ -370,9 +384,12 @@ public class DefaultMetadataService implements MetadataService {
ParamChecker.notEmpty(traitNameToBeDeleted, "Trait name cannot be null"); ParamChecker.notEmpty(traitNameToBeDeleted, "Trait name cannot be null");
// ensure trait type is already registered with the TS // ensure trait type is already registered with the TS
Preconditions.checkArgument(typeSystem.isRegistered(traitNameToBeDeleted), if ( !typeSystem.isRegistered(traitNameToBeDeleted)) {
"trait=%s should be defined in type system before it can be deleted", final String msg = String.format("trait=%s should be defined in type system before it can be deleted",
traitNameToBeDeleted); traitNameToBeDeleted);
LOG.error(msg);
throw new TypeNotFoundException(msg);
}
repository.deleteTrait(guid, traitNameToBeDeleted); repository.deleteTrait(guid, traitNameToBeDeleted);
...@@ -380,23 +397,28 @@ public class DefaultMetadataService implements MetadataService { ...@@ -380,23 +397,28 @@ public class DefaultMetadataService implements MetadataService {
} }
private void onTypesAddedToRepo(Map<String, IDataType> typesAdded) throws MetadataException { private void onTypesAddedToRepo(Map<String, IDataType> typesAdded) throws MetadataException {
for (TypesChangeListener listener : typesChangeListeners) { Map<SearchIndexer, Throwable> caughtExceptions = new HashMap<>();
for (Map.Entry<String, IDataType> entry : typesAdded.entrySet()) { for(Provider<SearchIndexer> indexerProvider : typeChangeListeners) {
listener.onAdd(entry.getKey(), entry.getValue()); final SearchIndexer indexer = indexerProvider.get();
try {
for (Map.Entry<String, IDataType> entry : typesAdded.entrySet()) {
indexer.onAdd(entry.getKey(), entry.getValue());
}
indexer.commit();
} catch (IndexCreationException ice) {
LOG.error("Index creation for listener {} failed ", indexerProvider, ice);
indexer.rollback();
caughtExceptions.put(indexer, ice);
} }
} }
}
public void registerListener(TypesChangeListener listener) {
typesChangeListeners.add(listener);
}
public void unregisterListener(TypesChangeListener listener) { if (caughtExceptions.size() > 0) {
typesChangeListeners.remove(listener); throw new IndexCreationException("Index creation failed for types " + typesAdded.keySet() + ". Aborting");
}
} }
private void onEntityAddedToRepo(ITypedReferenceableInstance typedInstance) private void onEntityAddedToRepo(ITypedReferenceableInstance typedInstance)
throws MetadataException { throws MetadataException {
for (EntityChangeListener listener : entityChangeListeners) { for (EntityChangeListener listener : entityChangeListeners) {
listener.onEntityAdded(typedInstance); listener.onEntityAdded(typedInstance);
...@@ -424,4 +446,5 @@ public class DefaultMetadataService implements MetadataService { ...@@ -424,4 +446,5 @@ public class DefaultMetadataService implements MetadataService {
public void unregisterListener(EntityChangeListener listener) { public void unregisterListener(EntityChangeListener listener) {
entityChangeListeners.remove(listener); entityChangeListeners.remove(listener);
} }
}
}
\ No newline at end of file
...@@ -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.
...@@ -19,11 +19,20 @@ ...@@ -19,11 +19,20 @@
package org.apache.atlas.repository.graph; package org.apache.atlas.repository.graph;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.thinkaurelius.titan.core.TitanFactory;
import com.thinkaurelius.titan.core.TitanGraph; import com.thinkaurelius.titan.core.TitanGraph;
import com.thinkaurelius.titan.core.TitanIndexQuery; import com.thinkaurelius.titan.core.TitanIndexQuery;
import com.thinkaurelius.titan.core.schema.TitanGraphIndex;
import com.thinkaurelius.titan.diskstorage.BackendException;
import com.thinkaurelius.titan.diskstorage.configuration.Configuration;
import com.thinkaurelius.titan.diskstorage.configuration.ModifiableConfiguration;
import com.thinkaurelius.titan.diskstorage.configuration.ReadConfiguration;
import com.thinkaurelius.titan.diskstorage.configuration.backend.CommonsConfiguration;
import com.thinkaurelius.titan.graphdb.configuration.GraphDatabaseConfiguration;
import com.tinkerpop.blueprints.Compare; import com.tinkerpop.blueprints.Compare;
import com.tinkerpop.blueprints.GraphQuery; import com.tinkerpop.blueprints.GraphQuery;
import com.tinkerpop.blueprints.Vertex; import com.tinkerpop.blueprints.Vertex;
import org.apache.atlas.GraphTransaction;
import org.apache.atlas.RepositoryMetadataModule; import org.apache.atlas.RepositoryMetadataModule;
import org.apache.atlas.repository.Constants; import org.apache.atlas.repository.Constants;
import org.apache.atlas.typesystem.ITypedReferenceableInstance; import org.apache.atlas.typesystem.ITypedReferenceableInstance;
...@@ -42,16 +51,21 @@ import org.apache.atlas.typesystem.types.StructTypeDefinition; ...@@ -42,16 +51,21 @@ import org.apache.atlas.typesystem.types.StructTypeDefinition;
import org.apache.atlas.typesystem.types.TraitType; import org.apache.atlas.typesystem.types.TraitType;
import org.apache.atlas.typesystem.types.TypeSystem; import org.apache.atlas.typesystem.types.TypeSystem;
import org.apache.atlas.typesystem.types.utils.TypesUtil; import org.apache.atlas.typesystem.types.utils.TypesUtil;
import org.apache.commons.io.FileUtils;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import javax.inject.Inject; import javax.inject.Inject;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Random;
@Test @Test
@Guice(modules = RepositoryMetadataModule.class)
public class GraphRepoMapperScaleTest { public class GraphRepoMapperScaleTest {
private static final String DATABASE_TYPE = "hive_database_type"; private static final String DATABASE_TYPE = "hive_database_type";
...@@ -59,9 +73,39 @@ public class GraphRepoMapperScaleTest { ...@@ -59,9 +73,39 @@ public class GraphRepoMapperScaleTest {
private static final String TABLE_TYPE = "hive_table_type"; private static final String TABLE_TYPE = "hive_table_type";
private static final String TABLE_NAME = "bar"; private static final String TABLE_NAME = "bar";
@Inject private static final String INDEX_DIR = System.getProperty("java.io.tmpdir", "/tmp") + "/atlas-test" + new Random().nextLong();
private GraphProvider<TitanGraph> graphProvider;
@Inject private GraphProvider<TitanGraph> graphProvider = new GraphProvider<TitanGraph>() {
private TitanGraph graph = null;
//Ensure separate directory for graph provider to avoid issues with index merging
@Override
public TitanGraph get() {
try {
if (graph == null) {
synchronized (GraphRepoMapperScaleTest.class) {
if (graph == null) {
ReadConfiguration config = new CommonsConfiguration() {{
set("storage.backend", "inmemory");
set("index.search.directory", INDEX_DIR);
set("index.search.backend", "elasticsearch");
set("index.search.elasticsearch.local-mode", "true");
set("index.search.elasticsearch.client-only", "false");
}};
GraphDatabaseConfiguration graphconfig = new GraphDatabaseConfiguration(config);
graphconfig.getBackend().clearStorage();
graph = TitanFactory.open(config);
}
}
}
} catch (BackendException e) {
e.printStackTrace();
}
return graph;
}
};
private GraphBackedMetadataRepository repositoryService; private GraphBackedMetadataRepository repositoryService;
private GraphBackedSearchIndexer searchIndexer; private GraphBackedSearchIndexer searchIndexer;
...@@ -69,7 +113,11 @@ public class GraphRepoMapperScaleTest { ...@@ -69,7 +113,11 @@ public class GraphRepoMapperScaleTest {
private String dbGUID; private String dbGUID;
@BeforeClass @BeforeClass
@GraphTransaction
public void setUp() throws Exception { public void setUp() throws Exception {
//Make sure we can cleanup the index directory
repositoryService = new GraphBackedMetadataRepository(graphProvider);
searchIndexer = new GraphBackedSearchIndexer(graphProvider); searchIndexer = new GraphBackedSearchIndexer(graphProvider);
typeSystem = TypeSystem.getInstance(); typeSystem = TypeSystem.getInstance();
...@@ -77,6 +125,16 @@ public class GraphRepoMapperScaleTest { ...@@ -77,6 +125,16 @@ public class GraphRepoMapperScaleTest {
createHiveTypes(); createHiveTypes();
} }
@AfterClass
public void tearDown() throws Exception {
graphProvider.get().shutdown();
try {
FileUtils.deleteDirectory(new File(INDEX_DIR));
} catch(IOException ioe) {
System.err.println("Failed to cleanup index directory");
}
}
@Test @Test
public void testSubmitEntity() throws Exception { public void testSubmitEntity() throws Exception {
Referenceable databaseInstance = new Referenceable(DATABASE_TYPE); Referenceable databaseInstance = new Referenceable(DATABASE_TYPE);
...@@ -220,6 +278,7 @@ public class GraphRepoMapperScaleTest { ...@@ -220,6 +278,7 @@ public class GraphRepoMapperScaleTest {
for (Map.Entry<String, IDataType> entry : types.entrySet()) { for (Map.Entry<String, IDataType> entry : types.entrySet()) {
searchIndexer.onAdd(entry.getKey(), entry.getValue()); searchIndexer.onAdd(entry.getKey(), entry.getValue());
} }
searchIndexer.commit();
} }
private ITypedReferenceableInstance createHiveTableInstance( private ITypedReferenceableInstance createHiveTableInstance(
...@@ -270,3 +329,4 @@ public class GraphRepoMapperScaleTest { ...@@ -270,3 +329,4 @@ public class GraphRepoMapperScaleTest {
return tableType.convert(tableInstance, Multiplicity.REQUIRED); return tableType.convert(tableInstance, Multiplicity.REQUIRED);
} }
} }
...@@ -81,7 +81,6 @@ public class GraphBackedTypeStoreTest { ...@@ -81,7 +81,6 @@ public class GraphBackedTypeStoreTest {
} }
@Test (dependsOnMethods = "testStore") @Test (dependsOnMethods = "testStore")
@GraphTransaction
public void testRestore() throws Exception { public void testRestore() throws Exception {
TypesDef types = typeStore.restore(); TypesDef types = typeStore.restore();
......
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.atlas;
/**
* A simple wrapper for 404.
*/
public class TypeNotFoundException extends MetadataException {
public TypeNotFoundException() {
}
public TypeNotFoundException(String message) {
super(message);
}
public TypeNotFoundException(String message, Throwable cause) {
super(message, cause);
}
public TypeNotFoundException(Throwable cause) {
super(cause);
}
public TypeNotFoundException(String message, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
...@@ -22,21 +22,14 @@ import com.google.common.collect.ArrayListMultimap; ...@@ -22,21 +22,14 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import org.apache.atlas.MetadataException; import org.apache.atlas.MetadataException;
import org.apache.atlas.TypeNotFoundException;
import org.apache.atlas.classification.InterfaceAudience; import org.apache.atlas.classification.InterfaceAudience;
import org.apache.atlas.typesystem.TypesDef; import org.apache.atlas.typesystem.TypesDef;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@Singleton @Singleton
...@@ -159,7 +152,7 @@ public class TypeSystem { ...@@ -159,7 +152,7 @@ public class TypeSystem {
return cls.cast(dT); return cls.cast(dT);
} }
throw new MetadataException(String.format("Unknown datatype: %s", name)); throw new TypeNotFoundException(String.format("Unknown datatype: %s", name));
} }
public StructType defineStructType(String name, public StructType defineStructType(String name,
...@@ -306,8 +299,13 @@ public class TypeSystem { ...@@ -306,8 +299,13 @@ public class TypeSystem {
return false; return false;
} }
public void removeTypes(ImmutableList<String> typeNames) { public void removeTypes(Collection<String> typeNames) {
for(String typeName : typeNames) {
IDataType dataType = types.get(typeName);
final DataTypes.TypeCategory typeCategory = dataType.getTypeCategory();
typeCategoriesToTypeNamesMap.get(typeCategory).remove(typeName);
types.remove(typeName);
}
} }
class TransientTypeSystem extends TypeSystem { class TransientTypeSystem extends TypeSystem {
...@@ -567,9 +565,10 @@ public class TypeSystem { ...@@ -567,9 +565,10 @@ public class TypeSystem {
} }
Map<String, IDataType> defineTypes() throws MetadataException { Map<String, IDataType> defineTypes() throws MetadataException {
step1();
step2();
try { try {
step1();
step2();
step3(); step3();
step4(); step4();
} catch (MetadataException me) { } catch (MetadataException me) {
......
...@@ -81,11 +81,12 @@ public class AuditFilter implements Filter { ...@@ -81,11 +81,12 @@ public class AuditFilter implements Filter {
final String who = getUserFromRequest(httpRequest); final String who = getUserFromRequest(httpRequest);
final String fromHost = httpRequest.getRemoteHost(); final String fromHost = httpRequest.getRemoteHost();
final String fromAddress = httpRequest.getRemoteAddr(); final String fromAddress = httpRequest.getRemoteAddr();
final String whatRequest = httpRequest.getMethod();
final String whatURL = Servlets.getRequestURL(httpRequest); final String whatURL = Servlets.getRequestURL(httpRequest);
final String whatAddrs = httpRequest.getLocalAddr(); final String whatAddrs = httpRequest.getLocalAddr();
LOG.debug("Audit: {}/{} performed request {} ({}) at time {}", LOG.debug("Audit: {}/{} performed request {} {} ({}) at time {}",
who, fromAddress, whatURL, whatAddrs, whenISO9601); who, fromAddress, whatRequest, whatURL, whatAddrs, whenISO9601);
audit(who, fromAddress, fromHost, whatURL, whatAddrs, whenISO9601); audit(who, fromAddress, fromHost, whatURL, whatAddrs, whenISO9601);
} }
......
...@@ -22,6 +22,7 @@ import com.google.common.base.Preconditions; ...@@ -22,6 +22,7 @@ import com.google.common.base.Preconditions;
import org.apache.atlas.MetadataException; import org.apache.atlas.MetadataException;
import org.apache.atlas.MetadataServiceClient; import org.apache.atlas.MetadataServiceClient;
import org.apache.atlas.ParamChecker; import org.apache.atlas.ParamChecker;
import org.apache.atlas.TypeNotFoundException;
import org.apache.atlas.repository.EntityNotFoundException; import org.apache.atlas.repository.EntityNotFoundException;
import org.apache.atlas.services.MetadataService; import org.apache.atlas.services.MetadataService;
import org.apache.atlas.typesystem.types.ValueConversionException; import org.apache.atlas.typesystem.types.ValueConversionException;
...@@ -48,7 +49,6 @@ import javax.ws.rs.core.Context; ...@@ -48,7 +49,6 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
...@@ -300,11 +300,11 @@ public class EntityResource { ...@@ -300,11 +300,11 @@ public class EntityResource {
response.put(MetadataServiceClient.GUID, guid); response.put(MetadataServiceClient.GUID, guid);
return Response.created(locationURI).entity(response).build(); return Response.created(locationURI).entity(response).build();
} catch (EntityNotFoundException e) { } catch (EntityNotFoundException | TypeNotFoundException e) {
LOG.error("An entity with GUID={} does not exist", guid, e); LOG.error("An entity with GUID={} does not exist", guid, e);
throw new WebApplicationException( throw new WebApplicationException(
Servlets.getErrorResponse(e, Response.Status.NOT_FOUND)); Servlets.getErrorResponse(e, Response.Status.NOT_FOUND));
} catch (MetadataException | IOException | IllegalArgumentException e) { } catch (MetadataException | IllegalArgumentException e) {
LOG.error("Unable to add trait for entity={}", guid, e); LOG.error("Unable to add trait for entity={}", guid, e);
throw new WebApplicationException( throw new WebApplicationException(
Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST)); Servlets.getErrorResponse(e, Response.Status.BAD_REQUEST));
...@@ -338,7 +338,7 @@ public class EntityResource { ...@@ -338,7 +338,7 @@ public class EntityResource {
response.put(TRAIT_NAME, traitName); response.put(TRAIT_NAME, traitName);
return Response.ok(response).build(); return Response.ok(response).build();
} catch (EntityNotFoundException e) { } catch (EntityNotFoundException | TypeNotFoundException e) {
LOG.error("An entity with GUID={} does not exist", guid, e); LOG.error("An entity with GUID={} does not exist", guid, e);
throw new WebApplicationException( throw new WebApplicationException(
Servlets.getErrorResponse(e, Response.Status.NOT_FOUND)); Servlets.getErrorResponse(e, Response.Status.NOT_FOUND));
......
...@@ -424,7 +424,7 @@ public class EntityJerseyResourceIT extends BaseResourceIT { ...@@ -424,7 +424,7 @@ public class EntityJerseyResourceIT extends BaseResourceIT {
.accept(Servlets.JSON_MEDIA_TYPE) .accept(Servlets.JSON_MEDIA_TYPE)
.type(Servlets.JSON_MEDIA_TYPE) .type(Servlets.JSON_MEDIA_TYPE)
.method(HttpMethod.POST, ClientResponse.class, traitInstanceAsJSON); .method(HttpMethod.POST, ClientResponse.class, traitInstanceAsJSON);
Assert.assertEquals(clientResponse.getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); Assert.assertEquals(clientResponse.getStatus(), Response.Status.NOT_FOUND.getStatusCode());
} }
@Test(dependsOnMethods = "testGetTraitNames") @Test(dependsOnMethods = "testGetTraitNames")
...@@ -494,7 +494,7 @@ public class EntityJerseyResourceIT extends BaseResourceIT { ...@@ -494,7 +494,7 @@ public class EntityJerseyResourceIT extends BaseResourceIT {
.accept(Servlets.JSON_MEDIA_TYPE) .accept(Servlets.JSON_MEDIA_TYPE)
.type(Servlets.JSON_MEDIA_TYPE) .type(Servlets.JSON_MEDIA_TYPE)
.method(HttpMethod.POST, ClientResponse.class, traitInstanceAsJSON); .method(HttpMethod.POST, ClientResponse.class, traitInstanceAsJSON);
Assert.assertEquals(clientResponse.getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); Assert.assertEquals(clientResponse.getStatus(), Response.Status.NOT_FOUND.getStatusCode());
} }
@Test(dependsOnMethods = "testAddTrait") @Test(dependsOnMethods = "testAddTrait")
...@@ -532,7 +532,7 @@ public class EntityJerseyResourceIT extends BaseResourceIT { ...@@ -532,7 +532,7 @@ public class EntityJerseyResourceIT extends BaseResourceIT {
.accept(Servlets.JSON_MEDIA_TYPE) .accept(Servlets.JSON_MEDIA_TYPE)
.type(Servlets.JSON_MEDIA_TYPE) .type(Servlets.JSON_MEDIA_TYPE)
.method(HttpMethod.DELETE, ClientResponse.class); .method(HttpMethod.DELETE, ClientResponse.class);
Assert.assertEquals(clientResponse.getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); Assert.assertEquals(clientResponse.getStatus(), Response.Status.NOT_FOUND.getStatusCode());
String responseAsString = clientResponse.getEntity(String.class); String responseAsString = clientResponse.getEntity(String.class);
Assert.assertNotNull(responseAsString); Assert.assertNotNull(responseAsString);
......
...@@ -219,6 +219,9 @@ public class TypesJerseyResourceIT extends BaseResourceIT { ...@@ -219,6 +219,9 @@ public class TypesJerseyResourceIT extends BaseResourceIT {
ImmutableList.<String>of(), ImmutableList.<String>of(),
TypesUtil.createUniqueRequiredAttrDef("name", DataTypes.STRING_TYPE), TypesUtil.createUniqueRequiredAttrDef("name", DataTypes.STRING_TYPE),
TypesUtil.createRequiredAttrDef("description", DataTypes.STRING_TYPE), TypesUtil.createRequiredAttrDef("description", DataTypes.STRING_TYPE),
TypesUtil.createOptionalAttrDef("columnNames", DataTypes.arrayTypeName(DataTypes.STRING_TYPE)),
TypesUtil.createOptionalAttrDef("created", DataTypes.DATE_TYPE),
TypesUtil.createOptionalAttrDef("parameters", DataTypes.mapTypeName(DataTypes.STRING_TYPE, DataTypes.STRING_TYPE)),
TypesUtil.createRequiredAttrDef("type", DataTypes.STRING_TYPE), TypesUtil.createRequiredAttrDef("type", DataTypes.STRING_TYPE),
new AttributeDefinition("database", new AttributeDefinition("database",
"database", Multiplicity.REQUIRED, false, "database")); "database", Multiplicity.REQUIRED, false, "database"));
......
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