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=677867091afc4f5c180675c39422acda7f4487b1;hp=4be2fa3876347f7a6f624d0b48ea8466f40e2afc;hb=990c36b8a92ffb36b0b386855f6a7ea79e5ea226;hpb=a7517a9b9c40dee08cff8be2febaa2d369012e48 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 4be2fa3876..677867091a 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 @@ -16,6 +16,8 @@ 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.util.Collections; import java.util.HashMap; import java.util.Map; @@ -40,79 +42,100 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; final class YangStoreSnapshot implements YangStoreContext, EnumResolver { - private static final Logger LOG = LoggerFactory.getLogger(YangStoreSnapshot.class); + private static final class MXBeans { + private final Map> moduleMXBeanEntryMap; + private final Map> qNamesToIdentitiesToModuleMXBeanEntries; + + MXBeans(final SchemaContext schemaContext) { + LOG.trace("Resolved modules:{}", schemaContext.getModules()); + + // 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 : schemaContext.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()); + } + } + } + Map> moduleMXBeanEntryMap = Maps.newHashMap(); - private final Map> moduleMXBeanEntryMap; + Map> qNamesToIdentitiesToModuleMXBeanEntries = new HashMap<>(); - private final Map> qNamesToIdentitiesToModuleMXBeanEntries; + for (Module module : schemaContext.getModules()) { + String packageName = packageTranslator.getPackageName(module); + TypeProviderWrapper typeProviderWrapper = new TypeProviderWrapper( + new TypeProviderImpl(schemaContext)); - private final BindingRuntimeContext bindingContextProvider; - private final SchemaSourceProvider sourceProvider; + QName qName = QName.create(module.getNamespace(), module.getRevision(), module.getName()); - public YangStoreSnapshot(final BindingRuntimeContext bindingContextProvider, - final SchemaSourceProvider sourceProvider) { - this.bindingContextProvider = bindingContextProvider; - this.sourceProvider = sourceProvider; - - final SchemaContext schemaContext = bindingContextProvider.getSchemaContext(); - LOG.trace("Resolved modules:{}", schemaContext.getModules()); - - // 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 : schemaContext.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()); - } + Map namesToMBEs = + Collections.unmodifiableMap(ModuleMXBeanEntry.create(module, qNamesToSIEs, schemaContext, + typeProviderWrapper, packageName)); + moduleMXBeanEntryMap.put(module.getNamespace().toString(), namesToMBEs); + + qNamesToIdentitiesToModuleMXBeanEntries.put(qName, namesToMBEs); } + this.moduleMXBeanEntryMap = Collections.unmodifiableMap(moduleMXBeanEntryMap); + this.qNamesToIdentitiesToModuleMXBeanEntries = 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(schemaContext)); + /** + * 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, schemaContext, - typeProviderWrapper, packageName)); - moduleMXBeanEntryMap.put(module.getNamespace().toString(), namesToMBEs); + private MXBeans getMXBeans() { + MXBeans mxBean = ref.get(); - qNamesToIdentitiesToModuleMXBeanEntries.put(qName, namesToMBEs); + if (mxBean == null) { + synchronized (this) { + mxBean = ref.get(); + if (mxBean == null) { + mxBean = new MXBeans(bindingContextProvider.getSchemaContext()); + 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().qNamesToIdentitiesToModuleMXBeanEntries; } @Override @@ -134,7 +157,9 @@ final class YangStoreSnapshot implements YangStoreContext, EnumResolver { 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), Charsets.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);