BUG-6522: create a dedicated extensions map 68/47568/8
authorRobert Varga <rovarga@cisco.com>
Tue, 25 Oct 2016 23:24:15 +0000 (01:24 +0200)
committerRobert Varga <nite@hq.sk>
Wed, 26 Oct 2016 14:34:32 +0000 (14:34 +0000)
SourceSpecificContext already calls out to BuildGlobalContext
to lookup up support statements, hence the potential extension
lookup will be slower.

This lookup occurs before we check for type arguments, hence
we want to keep it fast. Therefore we take a snapshot of all
extensions defined in the global context.

Also make StatementDefinitionNamespace a source-local, so the
definitions do not leak outside of the module where they are
defined.

Change-Id: I0c50de89cee5d4297e8ccd0cb61203c3cfe9a2f3
Signed-off-by: Robert Varga <rovarga@cisco.com>
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YangInferencePipeline.java

index 1d8c2ac6ed8387cc5a6d66568487f2c72e9f7d49..ec0ae036345ba92d841e49b648a2893c0798d63b 100644 (file)
@@ -11,6 +11,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
 import com.google.common.collect.Multimap;
 import java.net.URI;
 import java.util.ArrayList;
@@ -82,12 +83,13 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
             .put(TypeUtils.INSTANCE_IDENTIFIER, new InstanceIdentifierSpecificationImpl.Definition())
             .build();
 
-    private final Multimap<ModelProcessingPhase, ModifierImpl> modifiers = HashMultimap.create();
     private final QNameToStatementDefinitionMap qNameToStmtDefMap = new QNameToStatementDefinitionMap();
+    private final Multimap<ModelProcessingPhase, ModifierImpl> modifiers = HashMultimap.create();
     private final PrefixToModuleMap prefixToModuleMap = new PrefixToModuleMap();
     private final BuildGlobalContext currentContext;
     private final StatementStreamSource source;
 
+    private Map<QName, StatementSupport<?, ?, ?>> definedExtensions = ImmutableMap.of();
     private Collection<NamespaceStorageNode> importedNamespaces = ImmutableList.of();
     private ModelProcessingPhase finishedPhase = ModelProcessingPhase.INIT;
     private ModelProcessingPhase inProgressPhase;
@@ -111,7 +113,7 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
         StatementDefinitionContext<?, ?, ?> def = currentContext.getStatementDefinition(name);
 
         if (def == null) {
-            final StatementSupport<?, ?, ?> extension = qNameToStmtDefMap.get(name);
+            final StatementSupport<?, ?, ?> extension = definedExtensions.get(name);
             if (extension != null) {
                 def = new StatementDefinitionContext<>(extension);
             } else {
@@ -362,20 +364,28 @@ public class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeh
         return prefixToModuleMap;
     }
 
+    private static <K, V> void addSupports(final Builder<K, V> builder, @Nullable final Map<K, V> supports) {
+        if (supports != null) {
+            builder.putAll(supports);
+        }
+    }
+
     private QNameToStatementDefinition stmtDef() {
         // regular YANG statements and extension supports added
         qNameToStmtDefMap.putAll(currentContext.getSupportsForPhase(inProgressPhase).getDefinitions());
 
-        // No further actions needed
-        if (inProgressPhase != ModelProcessingPhase.FULL_DECLARATION) {
-            return qNameToStmtDefMap;
-        }
-
         // We need to any and all extension statements which have been declared in the context
-        final Map<QName, StatementSupport<?, ?, ?>> extensions = currentContext.getAllFromNamespace(
-                StatementDefinitionNamespace.class);
-        if (extensions != null) {
-            extensions.forEach((qname, support) -> {
+        if (inProgressPhase == ModelProcessingPhase.FULL_DECLARATION) {
+            // We maintain this map for createDeclaredChild(), which calls out to global context first,
+            // hence there is no point in performing double lookups.
+            final Builder<QName, StatementSupport<?, ?, ?>> b = ImmutableMap.builder();
+            addSupports(b, getRoot().getAllFromLocalStorage(StatementDefinitionNamespace.class));
+            for (NamespaceStorageNode namespace : importedNamespaces) {
+                addSupports(b, namespace.getAllFromLocalStorage(StatementDefinitionNamespace.class));
+            }
+
+            definedExtensions = b.build();
+            definedExtensions.forEach((qname, support) -> {
                 final StatementSupport<?, ?, ?> existing = qNameToStmtDefMap.putIfAbsent(qname, support);
                 if (existing != null) {
                     LOG.debug("Source {} already defines statement {} as {}", source, qname, existing);
index d0802782e9420f361bafd4fc00e24814495ff319..4bb671e6514d93b82855421dcba9bd04b0f628ab 100644 (file)
@@ -144,7 +144,7 @@ public final class YangInferencePipeline {
             .addSupport(new FractionDigitsStatementImpl.Definition())
             .addSupport(new BaseStatementImpl.Definition())
             .addSupport(global(DerivedIdentitiesNamespace.class))
-            .addSupport(global(StatementDefinitionNamespace.class))
+            .addSupport(sourceLocal(StatementDefinitionNamespace.class))
             .build();
 
     public static final StatementSupportBundle FULL_DECL_BUNDLE = StatementSupportBundle