<commit_before>/*
 * Copyright (c) 2013 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,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.controller.config.manager.impl;

import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.String.format;

import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.management.DynamicMBean;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.config.manager.impl.dependencyresolver.DependencyResolverManager;
import org.opendaylight.controller.config.manager.impl.dependencyresolver.ModuleInternalTransactionalInfo;
import org.opendaylight.controller.config.manager.impl.dynamicmbean.DynamicWritableWrapper;
import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtomicBoolean;
import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtomicBoolean.ReadOnlyAtomicBooleanImpl;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HierarchicalConfigMBeanFactoriesHolder;
import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator;
import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration;
import org.opendaylight.controller.config.manager.impl.osgi.mapping.BindingContextProvider;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.yangtools.concepts.Identifiable;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * This is a JMX bean representing current transaction. It contains
 * transaction identifier, unique version and parent version for
 * optimistic locking.
 */
class ConfigTransactionControllerImpl implements
        ConfigTransactionControllerInternal,
        ConfigTransactionControllerImplMXBean,
        Identifiable<TransactionIdentifier> {
    private static final Logger LOG = LoggerFactory.getLogger(ConfigTransactionControllerImpl.class);

    private final ConfigTransactionLookupRegistry txLookupRegistry;
    private final ObjectName controllerON;

    private final long parentVersion, currentVersion;
    private final HierarchicalConfigMBeanFactoriesHolder factoriesHolder;
    private final DependencyResolverManager dependencyResolverManager;
    private final TransactionStatus transactionStatus;
    private final MBeanServer transactionsMBeanServer;
    private final Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories;

    /**
     * Disables ability of {@link DynamicWritableWrapper} to change attributes
     * during validation.
     */
    @GuardedBy("this")
    private final AtomicBoolean configBeanModificationDisabled = new AtomicBoolean(
            false);
    private final ReadOnlyAtomicBoolean readOnlyAtomicBoolean = new ReadOnlyAtomicBooleanImpl(
            configBeanModificationDisabled);
    private final MBeanServer configMBeanServer;

    private final boolean blankTransaction;

    @GuardedBy("this")
    private final SearchableServiceReferenceWritableRegistry writableSRRegistry;

    public ConfigTransactionControllerImpl(ConfigTransactionLookupRegistry txLookupRegistry,
                                           long parentVersion, BindingContextProvider bindingContextProvider, long currentVersion,
                                           Map<String, Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories,
                                           MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer,
                                           boolean blankTransaction, SearchableServiceReferenceWritableRegistry  writableSRRegistry) {
        this.txLookupRegistry = txLookupRegistry;
        String transactionName = txLookupRegistry.getTransactionIdentifier().getName();
        this.controllerON = ObjectNameUtil.createTransactionControllerON(transactionName);
        this.parentVersion = parentVersion;
        this.currentVersion = currentVersion;
        this.currentlyRegisteredFactories = currentlyRegisteredFactories;
        this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(currentlyRegisteredFactories);
        this.transactionStatus = new TransactionStatus();
        this.dependencyResolverManager = new DependencyResolverManager(txLookupRegistry.getTransactionIdentifier(),
                transactionStatus, writableSRRegistry, bindingContextProvider, transactionsMBeanServer);
        this.transactionsMBeanServer = transactionsMBeanServer;
        this.configMBeanServer = configMBeanServer;
        this.blankTransaction = blankTransaction;
        this.writableSRRegistry = writableSRRegistry;
    }

    @Override
    public void copyExistingModulesAndProcessFactoryDiff(Collection<ModuleInternalInfo> existingModules, List<ModuleFactory> lastListOfFactories) {
        // copy old configuration to this server
        for (ModuleInternalInfo oldConfigInfo : existingModules) {
            try {
                copyExistingModule(oldConfigInfo);
            } catch (InstanceAlreadyExistsException e) {
                throw new IllegalStateException("Error while copying " + oldConfigInfo, e);
            }
        }
        processDefaultBeans(lastListOfFactories);
    }

    private synchronized void processDefaultBeans(List<ModuleFactory> lastListOfFactories) {
        transactionStatus.checkNotCommitStarted();
        transactionStatus.checkNotAborted();

        Set<ModuleFactory> oldSet = new HashSet<>(lastListOfFactories);
        Set<ModuleFactory> newSet = new HashSet<>(factoriesHolder.getModuleFactories());

        List<ModuleFactory> toBeAdded = new ArrayList<>();
        List<ModuleFactory> toBeRemoved = new ArrayList<>();
        for (ModuleFactory moduleFactory : factoriesHolder.getModuleFactories()) {
            if (oldSet.contains(moduleFactory) == false) {
                toBeAdded.add(moduleFactory);
            }
        }
        for (ModuleFactory moduleFactory : lastListOfFactories) {
            if (newSet.contains(moduleFactory) == false) {
                toBeRemoved.add(moduleFactory);
            }
        }
        // add default modules
        for (ModuleFactory moduleFactory : toBeAdded) {
            BundleContext bundleContext = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
            Set<? extends Module> defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager,
                    bundleContext);
            for (Module module : defaultModules) {
                // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
                DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(module.getIdentifier());
                try {
                    boolean defaultBean = true;
                    putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null,
                            dependencyResolver, defaultBean, bundleContext);
                } catch (InstanceAlreadyExistsException e) {
                    throw new IllegalStateException(e);
                }
            }
        }

        // remove modules belonging to removed factories
        for (ModuleFactory removedFactory : toBeRemoved) {
            List<ModuleIdentifier> modulesOfRemovedFactory = dependencyResolverManager.findAllByFactory(removedFactory);
            for (ModuleIdentifier name : modulesOfRemovedFactory) {
                destroyModule(name);
            }
        }
    }


    private synchronized void copyExistingModule(ModuleInternalInfo oldConfigBeanInfo) throws InstanceAlreadyExistsException {

        transactionStatus.checkNotCommitStarted();
        transactionStatus.checkNotAborted();
        ModuleIdentifier moduleIdentifier = oldConfigBeanInfo.getIdentifier();
        dependencyResolverManager.assertNotExists(moduleIdentifier);

        ModuleFactory moduleFactory;
        BundleContext bc;
        try {
            moduleFactory = factoriesHolder.findByModuleName(moduleIdentifier.getFactoryName());<commit_msg>Expose default module instances into OSGi<commit_after>/*
 * Copyright (c) 2013 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,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.controller.config.manager.impl;

import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.String.format;

import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.management.DynamicMBean;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.api.ValidationException;
import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.config.manager.impl.dependencyresolver.DependencyResolverManager;
import org.opendaylight.controller.config.manager.impl.dependencyresolver.ModuleInternalTransactionalInfo;
import org.opendaylight.controller.config.manager.impl.dynamicmbean.DynamicWritableWrapper;
import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtomicBoolean;
import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtomicBoolean.ReadOnlyAtomicBooleanImpl;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HierarchicalConfigMBeanFactoriesHolder;
import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator;
import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration;
import org.opendaylight.controller.config.manager.impl.osgi.mapping.BindingContextProvider;
import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.yangtools.concepts.Identifiable;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * This is a JMX bean representing current transaction. It contains
 * transaction identifier, unique version and parent version for
 * optimistic locking.
 */
class ConfigTransactionControllerImpl implements
        ConfigTransactionControllerInternal,
        ConfigTransactionControllerImplMXBean,
        Identifiable<TransactionIdentifier> {
    private static final Logger LOG = LoggerFactory.getLogger(ConfigTransactionControllerImpl.class);

    private final ConfigTransactionLookupRegistry txLookupRegistry;
    private final ObjectName controllerON;

    private final long parentVersion, currentVersion;
    private final HierarchicalConfigMBeanFactoriesHolder factoriesHolder;
    private final DependencyResolverManager dependencyResolverManager;
    private final TransactionStatus transactionStatus;
    private final MBeanServer transactionsMBeanServer;
    private final Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories;

    /**
     * Disables ability of {@link DynamicWritableWrapper} to change attributes
     * during validation.
     */
    @GuardedBy("this")
    private final AtomicBoolean configBeanModificationDisabled = new AtomicBoolean(
            false);
    private final ReadOnlyAtomicBoolean readOnlyAtomicBoolean = new ReadOnlyAtomicBooleanImpl(
            configBeanModificationDisabled);
    private final MBeanServer configMBeanServer;

    private final boolean blankTransaction;

    @GuardedBy("this")
    private final SearchableServiceReferenceWritableRegistry writableSRRegistry;

    public ConfigTransactionControllerImpl(ConfigTransactionLookupRegistry txLookupRegistry,
                                           long parentVersion, BindingContextProvider bindingContextProvider, long currentVersion,
                                           Map<String, Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories,
                                           MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer,
                                           boolean blankTransaction, SearchableServiceReferenceWritableRegistry  writableSRRegistry) {
        this.txLookupRegistry = txLookupRegistry;
        String transactionName = txLookupRegistry.getTransactionIdentifier().getName();
        this.controllerON = ObjectNameUtil.createTransactionControllerON(transactionName);
        this.parentVersion = parentVersion;
        this.currentVersion = currentVersion;
        this.currentlyRegisteredFactories = currentlyRegisteredFactories;
        this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(currentlyRegisteredFactories);
        this.transactionStatus = new TransactionStatus();
        this.dependencyResolverManager = new DependencyResolverManager(txLookupRegistry.getTransactionIdentifier(),
                transactionStatus, writableSRRegistry, bindingContextProvider, transactionsMBeanServer);
        this.transactionsMBeanServer = transactionsMBeanServer;
        this.configMBeanServer = configMBeanServer;
        this.blankTransaction = blankTransaction;
        this.writableSRRegistry = writableSRRegistry;
    }

    @Override
    public void copyExistingModulesAndProcessFactoryDiff(Collection<ModuleInternalInfo> existingModules, List<ModuleFactory> lastListOfFactories) {
        // copy old configuration to this server
        for (ModuleInternalInfo oldConfigInfo : existingModules) {
            try {
                copyExistingModule(oldConfigInfo);
            } catch (InstanceAlreadyExistsException e) {
                throw new IllegalStateException("Error while copying " + oldConfigInfo, e);
            }
        }
        processDefaultBeans(lastListOfFactories);
    }

    private synchronized void processDefaultBeans(List<ModuleFactory> lastListOfFactories) {
        transactionStatus.checkNotCommitStarted();
        transactionStatus.checkNotAborted();

        Set<ModuleFactory> oldSet = new HashSet<>(lastListOfFactories);
        Set<ModuleFactory> newSet = new HashSet<>(factoriesHolder.getModuleFactories());

        List<ModuleFactory> toBeAdded = new ArrayList<>();
        List<ModuleFactory> toBeRemoved = new ArrayList<>();
        for (ModuleFactory moduleFactory : factoriesHolder.getModuleFactories()) {
            if (oldSet.contains(moduleFactory) == false) {
                toBeAdded.add(moduleFactory);
            }
        }
        for (ModuleFactory moduleFactory : lastListOfFactories) {
            if (newSet.contains(moduleFactory) == false) {
                toBeRemoved.add(moduleFactory);
            }
        }
        // add default modules
        for (ModuleFactory moduleFactory : toBeAdded) {
            BundleContext bundleContext = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
            Set<? extends Module> defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager,
                    bundleContext);
            for (Module module : defaultModules) {
                // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
                DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(module.getIdentifier());
                final ObjectName objectName;
                try {
                    boolean defaultBean = true;
                    objectName = putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null,
                            dependencyResolver, defaultBean, bundleContext);
                } catch (InstanceAlreadyExistsException e) {
                    throw new IllegalStateException(e);
                }

                // register default module as every possible service
                final Set<ServiceInterfaceAnnotation> serviceInterfaceAnnotations = InterfacesHelper.getServiceInterfaceAnnotations(moduleFactory);
                for (String qname : InterfacesHelper.getQNames(serviceInterfaceAnnotations)) {
                    try {
                        saveServiceReference(qname, module.getIdentifier().getInstanceName(), objectName);
                    } catch (InstanceNotFoundException e) {
                        throw new IllegalStateException("Unable to register default module instance " + module + " as a service of " + qname, e);
                    }
                }
            }
        }

        // remove modules belonging to removed factories
        for (ModuleFactory removedFactory : toBeRemoved) {
            List<ModuleIdentifier> modulesOfRemovedFactory = dependencyResolverManager.findAllByFactory(removedFactory);
            for (ModuleIdentifier name : modulesOfRemovedFactory) {
                // remove service refs
                final ModuleFactory moduleFactory = dependencyResolverManager.findModuleInternalTransactionalInfo(name).getModuleFactory();
                final Set<ServiceInterfaceAnnotation> serviceInterfaceAnnotations = InterfacesHelper.getServiceInterfaceAnnotations(moduleFactory);
                for (String qname : InterfacesHelper.getQNames(serviceInterfaceAnnotations)) {
                    try {
                        removeServiceReference(qname, name.getInstanceName());
                    } catch (InstanceNotFoundException e) {
                        throw new IllegalStateException("Unable to UNregister default module instance " + name + " as a service of " + qname, e);
                    }
                }

                // close module
                destroyModule(name);
            }
        }
    }


    private synchronized void copyExistingModule(ModuleInternalInfo oldConfigBeanInfo) throws InstanceAlreadyExistsException {

        transactionStatus.checkNotCommitStarted();
        transactionStatus.checkNotAborted();
        ModuleIdentifier moduleIdentifier = oldConfigBeanInfo.getIdentifier();
        dependencyResolverManager.assertNotExists(moduleIdentifier);

        ModuleFactory moduleFactory;
        BundleContext bc;
        try {
            moduleFactory = factoriesHolder.findByModuleName(moduleIdentifier.getFactoryName());
{'fraction_non_alphanumeric': 0.06685, 'fraction_numerical': 0.001, 'mean_word_length': 3.589490592014686, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2899562', 'n_tokens_mistral': 4657, 'n_tokens_neox': 4520, 'n_words': 969}