X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fconfig%2Fconfig-manager-facade-xml%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fconfig%2Ffacade%2Fxml%2Fosgi%2FYangStoreSnapshot.java;h=ce34496810a2356b04b593bfd43dfc5c4bf1f6a8;hp=8babb867b24016f0349856501a63599d5232a760;hb=2d60632f7cf63712e8357a3cf3fc40d83366e5e6;hpb=f77ea78c351d1c3604287e8444aae6943f70042f diff --git a/opendaylight/config/config-manager-facade-xml/src/main/java/org/opendaylight/controller/config/facade/xml/osgi/YangStoreSnapshot.java b/opendaylight/config/config-manager-facade-xml/src/main/java/org/opendaylight/controller/config/facade/xml/osgi/YangStoreSnapshot.java index 8babb867b2..ce34496810 100644 --- a/opendaylight/config/config-manager-facade-xml/src/main/java/org/opendaylight/controller/config/facade/xml/osgi/YangStoreSnapshot.java +++ b/opendaylight/config/config-manager-facade-xml/src/main/java/org/opendaylight/controller/config/facade/xml/osgi/YangStoreSnapshot.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2015, 2017 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -8,7 +8,7 @@ package org.opendaylight.controller.config.facade.xml.osgi; -import com.google.common.base.Charsets; +import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.BiMap; import com.google.common.collect.Maps; @@ -16,17 +16,21 @@ import com.google.common.collect.Sets; import com.google.common.io.ByteStreams; import com.google.common.util.concurrent.CheckedFuture; import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.SoftReference; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Set; import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; import org.opendaylight.controller.config.yangjmxgenerator.PackageTranslator; import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntry; import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper; -import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext; -import org.opendaylight.yangtools.sal.binding.yang.types.TypeProviderImpl; +import org.opendaylight.mdsal.binding.generator.util.BindingRuntimeContext; +import org.opendaylight.mdsal.binding.yang.types.TypeProviderImpl; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode; import org.opendaylight.yangtools.yang.model.api.Module; @@ -38,87 +42,109 @@ import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -final class YangStoreSnapshot implements YangStoreContext, EnumResolver { - private static final Logger LOG = LoggerFactory.getLogger(YangStoreSnapshot.class); +public final class YangStoreSnapshot implements YangStoreContext, EnumResolver { + private static final class MXBeans { + private final Map> moduleMXBeanEntryMap; + private final Map> namesToIdentitiesToModuleMXBeanEntries; + + MXBeans(final SchemaContext schemaContext) { + LOG.trace("Resolved modules:{}", schemaContext.getModules()); + + // JMX generator + final Map namespaceToPackageMapping = Maps.newHashMap(); + final PackageTranslator packageTranslator = new PackageTranslator(namespaceToPackageMapping); + final Map qNamesToSIEs = new HashMap<>(); + final Map knownSEITracker = new HashMap<>(); + // create SIE structure qNamesToSIEs + for (final Module module : schemaContext.getModules()) { + final String packageName = packageTranslator.getPackageName(module); + final Map namesToSIEntries = ServiceInterfaceEntry + .create(module, packageName, knownSEITracker); + for (final Entry sieEntry : namesToSIEntries.entrySet()) { + // merge value into qNamesToSIEs + if (!qNamesToSIEs.containsKey(sieEntry.getKey())) { + qNamesToSIEs.put(sieEntry.getKey(), sieEntry.getValue()); + } else { + throw new IllegalStateException("Cannot add two SIE with same qname " + + sieEntry.getValue()); + } + } + } + final Map> moduleMXBeanEntries = Maps.newHashMap(); - private final Map> moduleMXBeanEntryMap; + final Map> qNamesToIdentitiesToModuleMXBeanEntries = new HashMap<>(); - private final Map> qNamesToIdentitiesToModuleMXBeanEntries; + for (final Module module : schemaContext.getModules()) { + final String packageName = packageTranslator.getPackageName(module); + final TypeProviderWrapper typeProviderWrapper = new TypeProviderWrapper( + new TypeProviderImpl(schemaContext)); - private final SchemaContext schemaContext; - private final BindingRuntimeContext bindingContextProvider; - private final SchemaSourceProvider sourceProvider; + final QName qName = QName.create(module.getNamespace(), module.getRevision(), module.getName()); - public YangStoreSnapshot(final SchemaContext resolveSchemaContext, - final BindingRuntimeContext bindingContextProvider, - final SchemaSourceProvider sourceProvider) { - this.bindingContextProvider = bindingContextProvider; - this.sourceProvider = sourceProvider; - LOG.trace("Resolved modules:{}", resolveSchemaContext.getModules()); - this.schemaContext = resolveSchemaContext; - // JMX generator - - Map namespaceToPackageMapping = Maps.newHashMap(); - PackageTranslator packageTranslator = new PackageTranslator(namespaceToPackageMapping); - Map qNamesToSIEs = new HashMap<>(); - Map knownSEITracker = new HashMap<>(); - // create SIE structure qNamesToSIEs - for (Module module : resolveSchemaContext.getModules()) { - String packageName = packageTranslator.getPackageName(module); - Map namesToSIEntries = ServiceInterfaceEntry - .create(module, packageName, knownSEITracker); - for (Entry sieEntry : namesToSIEntries.entrySet()) { - // merge value into qNamesToSIEs - if (qNamesToSIEs.containsKey(sieEntry.getKey()) == false) { - qNamesToSIEs.put(sieEntry.getKey(), sieEntry.getValue()); - } else { - throw new IllegalStateException("Cannot add two SIE with same qname " - + sieEntry.getValue()); - } + final Map namesToMBEs = + Collections.unmodifiableMap(ModuleMXBeanEntry.create(module, qNamesToSIEs, schemaContext, + typeProviderWrapper, packageName)); + moduleMXBeanEntries.put(module.getNamespace().toString(), namesToMBEs); + + qNamesToIdentitiesToModuleMXBeanEntries.put(qName, namesToMBEs); } + this.moduleMXBeanEntryMap = Collections.unmodifiableMap(moduleMXBeanEntries); + this.namesToIdentitiesToModuleMXBeanEntries = + Collections.unmodifiableMap(qNamesToIdentitiesToModuleMXBeanEntries); } + } - Map> moduleMXBeanEntryMap = Maps.newHashMap(); - - Map> qNamesToIdentitiesToModuleMXBeanEntries = new HashMap<>(); - + private static final Logger LOG = LoggerFactory.getLogger(YangStoreSnapshot.class); + private final SchemaSourceProvider sourceProvider; + private final BindingRuntimeContext bindingContextProvider; - for (Module module : schemaContext.getModules()) { - String packageName = packageTranslator.getPackageName(module); - TypeProviderWrapper typeProviderWrapper = new TypeProviderWrapper( - new TypeProviderImpl(resolveSchemaContext)); + /** + * We want to lazily compute the context of the MXBean class and have it only softly-attached to this instance, + * so it can be garbage collected when the memory gets tight. If the schema context changes as we are computing + * things, YangStoreService will detect that and retry, so we do not have to worry about that. + */ + private volatile SoftReference ref = new SoftReference<>(null); - QName qName = QName.create(module.getNamespace(), module.getRevision(), module.getName()); + public YangStoreSnapshot(final BindingRuntimeContext bindingContextProvider, + final SchemaSourceProvider sourceProvider) { + this.bindingContextProvider = Preconditions.checkNotNull(bindingContextProvider); + this.sourceProvider = Preconditions.checkNotNull(sourceProvider); + } - Map namesToMBEs = - Collections.unmodifiableMap(ModuleMXBeanEntry.create(module, qNamesToSIEs, resolveSchemaContext, - typeProviderWrapper, packageName)); - moduleMXBeanEntryMap.put(module.getNamespace().toString(), namesToMBEs); + private MXBeans getMXBeans() { + MXBeans mxBean = this.ref.get(); - qNamesToIdentitiesToModuleMXBeanEntries.put(qName, namesToMBEs); + if (mxBean == null) { + synchronized (this) { + mxBean = this.ref.get(); + if (mxBean == null) { + mxBean = new MXBeans(this.bindingContextProvider.getSchemaContext()); + this.ref = new SoftReference<>(mxBean); + } + } } - this.moduleMXBeanEntryMap = Collections.unmodifiableMap(moduleMXBeanEntryMap); - this.qNamesToIdentitiesToModuleMXBeanEntries = Collections.unmodifiableMap(qNamesToIdentitiesToModuleMXBeanEntries); + return mxBean; } @Override public Map> getModuleMXBeanEntryMap() { - return moduleMXBeanEntryMap; + return getMXBeans().moduleMXBeanEntryMap; } @Override public Map> getQNamesToIdentitiesToModuleMXBeanEntries() { - return qNamesToIdentitiesToModuleMXBeanEntries; + return getMXBeans().namesToIdentitiesToModuleMXBeanEntries; } @Override public Set getModules() { - final Set modules = Sets.newHashSet(schemaContext.getModules()); - for (final Module module : schemaContext.getModules()) { + final Set modules = Sets.newHashSet(this.bindingContextProvider.getSchemaContext().getModules()); + for (final Module module : this.bindingContextProvider.getSchemaContext().getModules()) { modules.addAll(module.getSubmodules()); } return modules; @@ -126,15 +152,15 @@ final class YangStoreSnapshot implements YangStoreContext, EnumResolver { @Override public String getModuleSource(final org.opendaylight.yangtools.yang.model.api.ModuleIdentifier moduleIdentifier) { - final CheckedFuture source = sourceProvider.getSource( - moduleIdentifier.getRevision() == null ? - new SourceIdentifier(moduleIdentifier.getName()) : - new SourceIdentifier(moduleIdentifier.getName(), - QName.formattedRevision(moduleIdentifier.getRevision()))); + final CheckedFuture source = this.sourceProvider + .getSource(SourceIdentifier.create(moduleIdentifier.getName(), + Optional.fromNullable(QName.formattedRevision(moduleIdentifier.getRevision())))); try { final YangTextSchemaSource yangTextSchemaSource = source.checkedGet(); - return new String(ByteStreams.toByteArray(yangTextSchemaSource.openStream()), Charsets.UTF_8); + try (InputStream inStream = yangTextSchemaSource.openStream()) { + return new String(ByteStreams.toByteArray(inStream), StandardCharsets.UTF_8); + } } catch (SchemaSourceException | IOException e) { LOG.warn("Unable to provide source for {}", moduleIdentifier, e); throw new IllegalArgumentException("Unable to provide source for " + moduleIdentifier, e); @@ -147,37 +173,40 @@ final class YangStoreSnapshot implements YangStoreContext, EnumResolver { } @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - final YangStoreSnapshot that = (YangStoreSnapshot) o; - - if (schemaContext != null ? !schemaContext.equals(that.schemaContext) : that.schemaContext != null) + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof YangStoreSnapshot)) { return false; + } - return true; + final YangStoreSnapshot other = (YangStoreSnapshot) obj; + return Objects.equals(this.bindingContextProvider, other.bindingContextProvider); } @Override public int hashCode() { - return schemaContext != null ? schemaContext.hashCode() : 0; + return Objects.hashCode(this.bindingContextProvider); } @Override public String fromYang(final String enumClass, final String enumYangValue) { - Preconditions.checkState(bindingContextProvider != null, "Binding context provider was not set yet"); - final BiMap enumMapping = bindingContextProvider.getEnumMapping(enumClass); + Preconditions.checkState(this.bindingContextProvider != null, "Binding context provider was not set yet"); + final BiMap enumMapping = this.bindingContextProvider.getEnumMapping(enumClass); final String javaName = enumMapping.get(enumYangValue); - return Preconditions.checkNotNull(javaName, "Unable to resolve enum value %s for enum class %s with assumed enum mapping: %s", enumYangValue, enumClass, enumMapping); + return Preconditions.checkNotNull(javaName, + "Unable to resolve enum value %s for enum class %s with assumed enum mapping: %s", enumYangValue, + enumClass, enumMapping); } @Override public String toYang(final String enumClass, final String enumJavaValue) { - Preconditions.checkState(bindingContextProvider != null, "Binding context provider was not set yet"); - final BiMap enumMapping = bindingContextProvider.getEnumMapping(enumClass); + Preconditions.checkState(this.bindingContextProvider != null, "Binding context provider was not set yet"); + final BiMap enumMapping = this.bindingContextProvider.getEnumMapping(enumClass); final String javaName = enumMapping.inverse().get(enumJavaValue); - return Preconditions.checkNotNull(javaName, "Unable to map enumcd .." + - "cd value %s for enum class %s with assumed enum mapping: %s", enumJavaValue, enumClass, enumMapping.inverse()); + return Preconditions.checkNotNull(javaName, + "Unable to map enum value %s for enum class %s with assumed enum mapping: %s", enumJavaValue, enumClass, + enumMapping.inverse()); } }