From: Jakub Morvay Date: Wed, 30 Jan 2019 19:19:54 +0000 (+0100) Subject: Initialize EXISchema grammars lazily X-Git-Tag: release/neon~6 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=netconf.git;a=commitdiff_plain;h=0e143235aefb80016c223f3fd8f921db21114cba Initialize EXISchema grammars lazily Creating schema-backed netconf grammar is costly operation. Do not create it until we actually need it. This way we do not introduce any performance regression for netconf sessions that do not want to use schema-informed grammars for EXI encoding. Also do not force grammar instantiation when a mismatching option is specified by the peer. JIRA: NETCONF-584 Change-Id: I83f5e18f423cd21c1dc993980f42e030f36a12ed Signed-off-by: Jakub Morvay Signed-off-by: Robert Varga --- diff --git a/netconf/netconf-netty-util/src/main/java/org/opendaylight/netconf/nettyutil/handler/exi/EXIParameters.java b/netconf/netconf-netty-util/src/main/java/org/opendaylight/netconf/nettyutil/handler/exi/EXIParameters.java index 837beeeab2..d15f441c69 100644 --- a/netconf/netconf-netty-util/src/main/java/org/opendaylight/netconf/nettyutil/handler/exi/EXIParameters.java +++ b/netconf/netconf-netty-util/src/main/java/org/opendaylight/netconf/nettyutil/handler/exi/EXIParameters.java @@ -20,7 +20,6 @@ import org.opendaylight.netconf.shaded.exificient.core.FidelityOptions; import org.opendaylight.netconf.shaded.exificient.core.SchemaIdResolver; import org.opendaylight.netconf.shaded.exificient.core.exceptions.EXIException; import org.opendaylight.netconf.shaded.exificient.core.exceptions.UnsupportedOption; -import org.opendaylight.netconf.shaded.exificient.core.grammars.Grammars; import org.opendaylight.netconf.shaded.exificient.core.helpers.DefaultEXIFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,10 +51,8 @@ public final class EXIParameters { if (schemaId.isEmpty()) { return EXISchema.BUILTIN.getGrammar(); } - - final Grammars g = EXISchema.BASE_1_1.getGrammar(); - if (g.getSchemaId().equals(schemaId)) { - return g; + if (schemaId.equals(EXISchema.BASE_1_1.getOption())) { + return EXISchema.BASE_1_1.getGrammar(); } throw new EXIException("Cannot resolve schema " + schemaId); diff --git a/netconf/netconf-netty-util/src/main/java/org/opendaylight/netconf/nettyutil/handler/exi/EXISchema.java b/netconf/netconf-netty-util/src/main/java/org/opendaylight/netconf/nettyutil/handler/exi/EXISchema.java index 52f9375173..72c9f1779f 100644 --- a/netconf/netconf-netty-util/src/main/java/org/opendaylight/netconf/nettyutil/handler/exi/EXISchema.java +++ b/netconf/netconf-netty-util/src/main/java/org/opendaylight/netconf/nettyutil/handler/exi/EXISchema.java @@ -9,10 +9,13 @@ package org.opendaylight.netconf.nettyutil.handler.exi; import static java.util.Objects.requireNonNull; +import com.google.common.base.Suppliers; import com.google.common.io.ByteSource; import com.google.common.io.Resources; import java.io.IOException; import java.io.InputStream; +import java.util.function.Supplier; +import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.netconf.shaded.exificient.core.exceptions.EXIException; import org.opendaylight.netconf.shaded.exificient.core.grammars.Grammars; import org.opendaylight.netconf.shaded.exificient.grammars.GrammarFactory; @@ -21,52 +24,72 @@ import org.opendaylight.netconf.shaded.exificient.grammars.GrammarFactory; * Enumeration of schema modes defined by the NETCONF EXI capability. */ public enum EXISchema { - NONE("none", GrammarFactory.newInstance().createSchemaLessGrammars()), - BUILTIN("builtin", createBuiltinGrammar()), - BASE_1_1("base:1.1", createNetconfGrammar()); + NONE("none") { + @Override + Grammars createGrammar() { + return GrammarFactory.newInstance().createSchemaLessGrammars(); + } + }, + BUILTIN("builtin") { + @Override + Grammars createGrammar() { + try { + return GrammarFactory.newInstance().createXSDTypesOnlyGrammars(); + } catch (EXIException e) { + throw new IllegalStateException("Failed to create builtin grammar", e); + } + } + }, + BASE_1_1("base:1.1") { + @Override + Grammars createGrammar() { + final ByteSource source = Resources.asByteSource(EXISchema.class.getResource("/rfc6241.xsd")); + try (InputStream is = source.openStream()) { + final Grammars g = GrammarFactory.newInstance().createGrammars(is); + g.setSchemaId(getOption()); + return g; + } catch (EXIException | IOException e) { + throw new IllegalStateException("Failed to create RFC6241 grammar", e); + } + } + }; private String option; - private Grammars grammar; + private Supplier grammarsSupplier; - EXISchema(final String option, final Grammars grammar) { + EXISchema(final String option) { this.option = requireNonNull(option); - this.grammar = requireNonNull(grammar); + // Grammar instantiation can be CPU-intensive, hence we instantiate it lazily through a memoizing supplier + this.grammarsSupplier = Suppliers.memoize(this::createGrammar); } final String getOption() { return option; } + /** + * Return the grammar associated with this EXISchema. + * + * @return An EXI grammar. + */ final Grammars getGrammar() { - return grammar; + return grammarsSupplier.get(); } - static EXISchema forOption(final String id) { + /** + * Create grammars associated with this EXISchema. This is a potentially expensive operation for internal use only, + * use {@link #getGrammar()} instead. + * + * @return An EXI grammar. + */ + abstract Grammars createGrammar(); + + static @Nullable EXISchema forOption(final String id) { for (EXISchema s : EXISchema.values()) { if (id.equals(s.getOption())) { return s; } } - return null; } - - private static Grammars createNetconfGrammar() { - final ByteSource source = Resources.asByteSource(EXISchema.class.getResource("/rfc6241.xsd")); - try (InputStream is = source.openStream()) { - final Grammars g = GrammarFactory.newInstance().createGrammars(is); - g.setSchemaId("base:1.1"); - return g; - } catch (EXIException | IOException e) { - throw new IllegalStateException("Failed to create RFC6241 grammar", e); - } - } - - private static Grammars createBuiltinGrammar() { - try { - return GrammarFactory.newInstance().createXSDTypesOnlyGrammars(); - } catch (EXIException e) { - throw new IllegalStateException("Failed to create builtin grammar", e); - } - } }