ModuleInfoBackedContext uses YangTextSchemaResolver. 75/27975/2
authorTony Tkacik <ttkacik@cisco.com>
Tue, 6 Oct 2015 16:19:21 +0000 (18:19 +0200)
committerTony Tkacik <ttkacik@cisco.com>
Tue, 6 Oct 2015 16:46:42 +0000 (18:46 +0200)
This removes locking from ModuleInfoBackedContext
and improves perforamance characteristic during
access from multiple threads.

Change-Id: I8c6c3d228fcdb384761185f5347cde284490fbde
Signed-off-by: Tony Tkacik <ttkacik@cisco.com>
binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/ExceptionReportingTest.java
binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/ModuleInfoBackedContext.java

index 12effb52d589df11fdd15e8d91f0c802d270b5d6..2452ca2f910f36cba18ecf65955c82235c646db2 100644 (file)
@@ -14,6 +14,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.te
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121.LowestLevel1;
 import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
 import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
 import org.opendaylight.yangtools.binding.data.codec.impl.IncorrectNestingException;
@@ -33,7 +34,7 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 public class ExceptionReportingTest {
 
 
-    private static final BindingNormalizedNodeCodecRegistry EMPTY_SCHEMA_CODEC = codec();
+    private static final BindingNormalizedNodeCodecRegistry CODEC_WITHOUT_TOP = codec(LowestLevel1.class);
     private static final BindingNormalizedNodeCodecRegistry ONLY_TOP_CODEC = codec(Top.class);
     private static final BindingNormalizedNodeCodecRegistry FULL_CODEC = codec(TreeComplexUsesAugment.class);
 
@@ -50,17 +51,17 @@ public class ExceptionReportingTest {
 
     @Test(expected=MissingSchemaException.class)
     public void testDOMTop() {
-        EMPTY_SCHEMA_CODEC.fromYangInstanceIdentifier(BI_TOP_PATH);
+        CODEC_WITHOUT_TOP.fromYangInstanceIdentifier(BI_TOP_PATH);
     }
 
     @Test(expected=MissingSchemaException.class)
     public void testDOMAugment() {
-        EMPTY_SCHEMA_CODEC.fromYangInstanceIdentifier(BI_TREE_LEAF_ONLY);
+        CODEC_WITHOUT_TOP.fromYangInstanceIdentifier(BI_TREE_LEAF_ONLY);
     }
 
     @Test(expected=MissingSchemaForClassException.class)
     public void testBindingTop() {
-        EMPTY_SCHEMA_CODEC.toYangInstanceIdentifier(BA_TOP_LEVEL_LIST);
+        CODEC_WITHOUT_TOP.toYangInstanceIdentifier(BA_TOP_LEVEL_LIST);
     }
 
     @Test(expected=MissingSchemaForClassException.class)
index 289ff4fa8e85c08f0bf403e9f1ea30f86c7ca438..5894e329d894cbdd69dc9b4ac81bdc7b494d29a9 100644 (file)
@@ -7,16 +7,14 @@
  */
 package org.opendaylight.yangtools.sal.binding.generator.impl;
 
+import com.google.common.base.MoreObjects.ToStringHelper;
 import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
 import com.google.common.io.ByteSource;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.ref.WeakReference;
-import java.util.Collection;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
@@ -32,16 +30,15 @@ import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
-import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
-import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
-import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
+import org.opendaylight.yangtools.yang.parser.repo.YangTextSchemaContextResolver;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy
         implements ModuleInfoRegistry, SchemaContextProvider, SchemaSourceProvider<YangTextSchemaSource> {
 
+    private final YangTextSchemaContextResolver ctxResolver = YangTextSchemaContextResolver.create("binding-context");
+
     private ModuleInfoBackedContext(final ClassLoadingStrategy loadingStrategy) {
         this.backingLoadingStrategy = loadingStrategy;
     }
@@ -75,52 +72,18 @@ public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy
         }
         Class<?> cls = backingLoadingStrategy.loadClass(fullyQualifiedName);
         if (BindingReflections.isBindingClass(cls)) {
-            boolean newModule = resolveModuleInfo(cls);
-            if (newModule) {
-                recreateSchemaContext();
-            }
+            resolveModuleInfo(cls);
         }
 
         return cls;
     }
 
-
-    private synchronized Optional<SchemaContext> recreateSchemaContext() {
-        try {
-            Collection<ByteSource> streams = getAvailableStreams();
-            CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR
-                    .newBuild();
-            SchemaContext schemaContext = reactor.buildEffective(streams);
-            return Optional.of(schemaContext);
-        } catch (IOException | SourceException | ReactorException e) {
-            LOG.error("Schema was not recreated.", e);
-        }
-        return Optional.absent();
-    }
-
     // TODO finish schema parsing and expose as SchemaService
     // Unite with current SchemaService
     // Implement remove ModuleInfo to update SchemaContext
 
-    public synchronized Optional<SchemaContext> tryToCreateSchemaContext() {
-        return recreateSchemaContext();
-    }
-
-    private Collection<ByteSource> getAvailableStreams() throws IOException {
-        ImmutableSet<YangModuleInfo> moduleInfos = ImmutableSet.copyOf(sourceIdentifierToModuleInfo.values());
-
-        ImmutableList.Builder<ByteSource> sourceStreams = ImmutableList.<ByteSource> builder();
-        for (final YangModuleInfo moduleInfo : moduleInfos) {
-            sourceStreams.add(new ByteSource() {
-
-                @Override
-                public InputStream openStream() throws IOException {
-                    return moduleInfo.getModuleSourceStream();
-                }
-            });
-            ;
-        }
-        return sourceStreams.build();
+    public Optional<SchemaContext> tryToCreateSchemaContext() {
+        return ctxResolver.getSchemaContext();
     }
 
     private boolean resolveModuleInfo(final Class<?> cls) {
@@ -136,19 +99,39 @@ public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy
         SourceIdentifier identifier = sourceIdentifierFrom(moduleInfo);
         YangModuleInfo previous = sourceIdentifierToModuleInfo.putIfAbsent(identifier, moduleInfo);
         ClassLoader moduleClassLoader = moduleInfo.getClass().getClassLoader();
-        if (previous == null) {
-            String modulePackageName = moduleInfo.getClass().getPackage().getName();
-            packageNameToClassLoader.putIfAbsent(modulePackageName, new WeakReference<ClassLoader>(moduleClassLoader));
-
-            for (YangModuleInfo importedInfo : moduleInfo.getImportedModules()) {
-                resolveModuleInfo(importedInfo);
+        try {
+            if (previous == null) {
+                String modulePackageName = moduleInfo.getClass().getPackage().getName();
+                packageNameToClassLoader.putIfAbsent(modulePackageName,
+                        new WeakReference<ClassLoader>(moduleClassLoader));
+                ctxResolver.registerSource(toYangTextSource(identifier, moduleInfo));
+                for (YangModuleInfo importedInfo : moduleInfo.getImportedModules()) {
+                    resolveModuleInfo(importedInfo);
+                }
+            } else {
+                return false;
             }
-        } else {
-            return false;
+        } catch (Exception e) {
+            LOG.error("Not including {} in YANG sources because of error.", moduleInfo, e);
         }
         return true;
     }
 
+    private YangTextSchemaSource toYangTextSource(SourceIdentifier identifier, final YangModuleInfo moduleInfo) {
+        return new YangTextSchemaSource(identifier) {
+
+            @Override
+            public InputStream openStream() throws IOException {
+                return moduleInfo.getModuleSourceStream();
+            }
+
+            @Override
+            protected ToStringHelper addToStringAttributes(ToStringHelper toStringHelper) {
+                return toStringHelper;
+            }
+        };
+    }
+
     private static SourceIdentifier sourceIdentifierFrom(final YangModuleInfo moduleInfo) {
         return SourceIdentifier.create(moduleInfo.getName(), Optional.of(moduleInfo.getRevision()));
     }
@@ -162,9 +145,7 @@ public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy
     @Override
     public ObjectRegistration<YangModuleInfo> registerModuleInfo(final YangModuleInfo yangModuleInfo) {
         YangModuleInfoRegistration registration = new YangModuleInfoRegistration(yangModuleInfo, this);
-
         resolveModuleInfo(yangModuleInfo);
-
         return registration;
     }