Repository: incubator-atlas Updated Branches: refs/heads/master 765d556cc -> 08944c54d
ATLAS-1593: fix type-update handling to ensure that active type registry state is not updated while processing the changes Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/08944c54 Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/08944c54 Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/08944c54 Branch: refs/heads/master Commit: 08944c54de13054b4b7a76dbcba79218779f02d3 Parents: 765d556 Author: Madhan Neethiraj <[email protected]> Authored: Thu Feb 23 17:51:22 2017 -0800 Committer: Madhan Neethiraj <[email protected]> Committed: Fri Feb 24 16:22:15 2017 -0800 ---------------------------------------------------------------------- .../apache/atlas/type/AtlasTypeRegistry.java | 22 +++--- .../atlas/type/TestAtlasTypeRegistry.java | 77 ++++++++++++++++++++ 2 files changed, 88 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/08944c54/intg/src/main/java/org/apache/atlas/type/AtlasTypeRegistry.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasTypeRegistry.java b/intg/src/main/java/org/apache/atlas/type/AtlasTypeRegistry.java index 3f3ea59..ddb6c71 100644 --- a/intg/src/main/java/org/apache/atlas/type/AtlasTypeRegistry.java +++ b/intg/src/main/java/org/apache/atlas/type/AtlasTypeRegistry.java @@ -65,7 +65,7 @@ public class AtlasTypeRegistry { // used only by AtlasTransientTypeRegistry protected AtlasTypeRegistry(AtlasTypeRegistry other) { - registryData = new RegistryData(other.registryData); + registryData = new RegistryData(); updateSynchronizer = other.updateSynchronizer; } @@ -245,15 +245,6 @@ public class AtlasTypeRegistry { allTypes.addType(new AtlasBuiltInTypes.AtlasObjectIdType()); } - RegistryData(RegistryData other) { - allTypes = new TypeCache(other.allTypes); - enumDefs = new TypeDefCache<>(other.enumDefs, allTypes); - structDefs = new TypeDefCache<>(other.structDefs, allTypes); - classificationDefs = new TypeDefCache<>(other.classificationDefs, allTypes); - entityDefs = new TypeDefCache<>(other.entityDefs, allTypes); - allDefCaches = new TypeDefCache[] { enumDefs, structDefs, classificationDefs, entityDefs }; - } - AtlasBaseTypeDef getTypeDefByName(String name) { AtlasBaseTypeDef ret = null; @@ -320,8 +311,17 @@ public class AtlasTypeRegistry { private List<AtlasBaseTypeDef> deletedTypes = new ArrayList<>(); - private AtlasTransientTypeRegistry(AtlasTypeRegistry parent) { + private AtlasTransientTypeRegistry(AtlasTypeRegistry parent) throws AtlasBaseException { super(parent); + + addTypesWithNoRefResolve(parent.getAllEnumDefs()); + addTypesWithNoRefResolve(parent.getAllStructDefs()); + addTypesWithNoRefResolve(parent.getAllClassificationDefs()); + addTypesWithNoRefResolve(parent.getAllEntityDefs()); + + addedTypes.clear(); + updatedTypes.clear(); + deletedTypes.clear(); } private void resolveReferences() throws AtlasBaseException { http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/08944c54/intg/src/test/java/org/apache/atlas/type/TestAtlasTypeRegistry.java ---------------------------------------------------------------------- diff --git a/intg/src/test/java/org/apache/atlas/type/TestAtlasTypeRegistry.java b/intg/src/test/java/org/apache/atlas/type/TestAtlasTypeRegistry.java index f93a2e8..accba77 100644 --- a/intg/src/test/java/org/apache/atlas/type/TestAtlasTypeRegistry.java +++ b/intg/src/test/java/org/apache/atlas/type/TestAtlasTypeRegistry.java @@ -482,6 +482,83 @@ public class TestAtlasTypeRegistry { } } + /* create 2 entity types: L0 and L1, with L0 as superType of L1 + * add entity type L2, with L0, L1 and L2 as super-types - this should fail due to L2 self-referencing itself in super-types + * verify that after the update failure, the registry still has correct super-type/sub-type information for L0 and L1 + */ + @Test + public void testRegistryValidityOnInvalidUpdate() { + AtlasEntityDef entL0 = new AtlasEntityDef("L0"); + AtlasEntityDef entL1 = new AtlasEntityDef("L1"); + + entL1.addSuperType(entL0.getName()); + + entL0.addAttribute(new AtlasAttributeDef("L0_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); + entL1.addAttribute(new AtlasAttributeDef("L1_a1", AtlasBaseTypeDef.ATLAS_TYPE_INT)); + + AtlasTypesDef typesDef = new AtlasTypesDef(); + + typesDef.getEntityDefs().add(entL0); + typesDef.getEntityDefs().add(entL1); + + AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry(); + AtlasTransientTypeRegistry ttr = null; + boolean commit = false; + String failureMsg = null; + + try { + ttr = typeRegistry.lockTypeRegistryForUpdate(); + + ttr.addTypes(typesDef); + + commit = true; + } catch (AtlasBaseException excp) { + failureMsg = excp.getMessage(); + } finally { + typeRegistry.releaseTypeRegistryForUpdate(ttr, commit); + } + assertNull(failureMsg); + + validateSuperTypes(typeRegistry, "L0", new HashSet<String>()); + validateSubTypes(typeRegistry, "L0", new HashSet<>(Arrays.asList("L1"))); + + validateSuperTypes(typeRegistry, "L1", new HashSet<>(Arrays.asList("L0"))); + validateSubTypes(typeRegistry, "L1", new HashSet<String>()); + + + // create a circular reference + AtlasEntityDef entL2 = new AtlasEntityDef("L2"); + entL2.addSuperType(entL0.getName()); + entL2.addSuperType(entL1.getName()); + entL2.addSuperType(entL2.getName()); + + typesDef.clear(); + typesDef.getEntityDefs().add(entL2); + + try { + commit = false; + + ttr = typeRegistry.lockTypeRegistryForUpdate(); + + ttr.updateTypes(typesDef); + + commit = true; + } catch (AtlasBaseException excp) { + failureMsg = excp.getMessage(); + } finally { + typeRegistry.releaseTypeRegistryForUpdate(ttr, commit); + } + assertNotNull(failureMsg); + + assertNull(typeRegistry.getEntityTypeByName("L2")); + + validateSuperTypes(typeRegistry, "L0", new HashSet<String>()); + validateSubTypes(typeRegistry, "L0", new HashSet<>(Arrays.asList("L1"))); + + validateSuperTypes(typeRegistry, "L1", new HashSet<>(Arrays.asList("L0"))); + validateSubTypes(typeRegistry, "L1", new HashSet<String>()); + } + private boolean addType(AtlasTypeRegistry typeRegistry, AtlasBaseTypeDef typeDef) { boolean ret = false; AtlasTransientTypeRegistry ttr = null;
