66c43c2650e53a6e5bcf771946ec708d1c031588
[controller.git] / opendaylight / config / config-persister-impl / src / main / java / org / opendaylight / controller / config / persist / impl / osgi / ConfigPersisterActivator.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.config.persist.impl.osgi;
10
11 import com.google.common.collect.Lists;
12 import java.lang.management.ManagementFactory;
13 import java.util.List;
14 import java.util.concurrent.TimeUnit;
15 import javax.management.MBeanServer;
16 import org.opendaylight.controller.config.facade.xml.ConfigSubsystemFacadeFactory;
17 import org.opendaylight.controller.config.persist.api.ConfigPusher;
18 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
19 import org.opendaylight.controller.config.persist.api.Persister;
20 import org.opendaylight.controller.config.persist.impl.ConfigPusherImpl;
21 import org.opendaylight.controller.config.persist.impl.PersisterAggregator;
22 import org.opendaylight.controller.config.util.CloseableUtil;
23 import org.osgi.framework.BundleActivator;
24 import org.osgi.framework.BundleContext;
25 import org.osgi.framework.ServiceReference;
26 import org.osgi.framework.ServiceRegistration;
27 import org.osgi.util.tracker.ServiceTracker;
28 import org.osgi.util.tracker.ServiceTrackerCustomizer;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 public class ConfigPersisterActivator implements BundleActivator {
33
34     private static final Logger LOG = LoggerFactory.getLogger(ConfigPersisterActivator.class);
35     private static final MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
36
37     public static final String MAX_WAIT_FOR_CAPABILITIES_MILLIS_PROPERTY = "maxWaitForCapabilitiesMillis";
38     private static final long MAX_WAIT_FOR_CAPABILITIES_MILLIS_DEFAULT = TimeUnit.MINUTES.toMillis(2);
39     public static final String CONFLICTING_VERSION_TIMEOUT_MILLIS_PROPERTY = "conflictingVersionTimeoutMillis";
40     private static final long CONFLICTING_VERSION_TIMEOUT_MILLIS_DEFAULT = TimeUnit.MINUTES.toMillis(1);
41
42     public static final String NETCONF_CONFIG_PERSISTER = "netconf.config.persister";
43
44     public static final String STORAGE_ADAPTER_CLASS_PROP_SUFFIX = "storageAdapterClass";
45
46     private final List<AutoCloseable> autoCloseables = Lists.newArrayList();
47     private volatile BundleContext context;
48
49     ServiceRegistration<?> registration;
50
51     @Override
52     public void start(final BundleContext context) throws Exception {
53         LOG.debug("ConfigPersister starting");
54         this.context = context;
55
56         PropertiesProviderBaseImpl propertiesProvider = new PropertiesProviderBaseImpl(context);
57
58         final PersisterAggregator persisterAggregator = PersisterAggregator.createFromProperties(propertiesProvider);
59         autoCloseables.add(persisterAggregator);
60         final long maxWaitForCapabilitiesMillis = getMaxWaitForCapabilitiesMillis(propertiesProvider);
61         final List<ConfigSnapshotHolder> configs = persisterAggregator.loadLastConfigs();
62         final long conflictingVersionTimeoutMillis = getConflictingVersionTimeoutMillis(propertiesProvider);
63         LOG.debug("Following configs will be pushed: {}", configs);
64
65         ServiceTrackerCustomizer<ConfigSubsystemFacadeFactory, ConfigSubsystemFacadeFactory> schemaServiceTrackerCustomizer = new ServiceTrackerCustomizer<ConfigSubsystemFacadeFactory, ConfigSubsystemFacadeFactory>() {
66
67             @Override
68             public ConfigSubsystemFacadeFactory addingService(ServiceReference<ConfigSubsystemFacadeFactory> reference) {
69                 LOG.debug("Got addingService(SchemaContextProvider) event");
70                 // Yang store service should not be registered multiple times
71                 ConfigSubsystemFacadeFactory ConfigSubsystemFacadeFactory = reference.getBundle().getBundleContext().getService(reference);
72                 startPusherThread(configs, maxWaitForCapabilitiesMillis, ConfigSubsystemFacadeFactory, conflictingVersionTimeoutMillis, persisterAggregator);
73                 return ConfigSubsystemFacadeFactory;
74             }
75
76             @Override
77             public void modifiedService(ServiceReference<ConfigSubsystemFacadeFactory> reference, ConfigSubsystemFacadeFactory service) {
78                 LOG.warn("Config manager facade was modified unexpectedly");
79             }
80
81             @Override
82             public void removedService(ServiceReference<ConfigSubsystemFacadeFactory> reference, ConfigSubsystemFacadeFactory service) {
83                 LOG.warn("Config manager facade was removed unexpectedly");
84             }
85         };
86
87         ServiceTracker<ConfigSubsystemFacadeFactory, ConfigSubsystemFacadeFactory> schemaContextProviderServiceTracker =
88                 new ServiceTracker<>(context, ConfigSubsystemFacadeFactory.class, schemaServiceTrackerCustomizer);
89         schemaContextProviderServiceTracker.open();
90     }
91
92     private long getConflictingVersionTimeoutMillis(PropertiesProviderBaseImpl propertiesProvider) {
93         String timeoutProperty = propertiesProvider.getProperty(CONFLICTING_VERSION_TIMEOUT_MILLIS_PROPERTY);
94         return timeoutProperty == null ? CONFLICTING_VERSION_TIMEOUT_MILLIS_DEFAULT : Long.valueOf(timeoutProperty);
95     }
96
97     private long getMaxWaitForCapabilitiesMillis(PropertiesProviderBaseImpl propertiesProvider) {
98         String timeoutProperty = propertiesProvider.getProperty(MAX_WAIT_FOR_CAPABILITIES_MILLIS_PROPERTY);
99         return timeoutProperty == null ? MAX_WAIT_FOR_CAPABILITIES_MILLIS_DEFAULT : Long.valueOf(timeoutProperty);
100     }
101
102     @Override
103     public void stop(BundleContext context) throws Exception {
104         synchronized(autoCloseables) {
105             CloseableUtil.closeAll(autoCloseables);
106             autoCloseables.clear();
107             if (registration != null) {
108                 registration.unregister();
109             }
110             this.context = null;
111         }
112     }
113
114     private void startPusherThread(final List<? extends ConfigSnapshotHolder> configs, final long maxWaitForCapabilitiesMillis,
115                            final ConfigSubsystemFacadeFactory service, final long conflictingVersionTimeoutMillis, final Persister persisterAggregator){
116         LOG.debug("Creating new job queue");
117         final ConfigPusherImpl configPusher = new ConfigPusherImpl(service,
118                 maxWaitForCapabilitiesMillis, conflictingVersionTimeoutMillis);
119         LOG.debug("Configuration Persister got {}", service);
120         LOG.debug("Context was {}", context);
121         LOG.debug("Registration was {}", registration);
122         final Thread pushingThread = new Thread(new Runnable() {
123                 @Override
124                 public void run() {
125                     try {
126                         if(configs != null && !configs.isEmpty()) {
127                             configPusher.pushConfigs(configs);
128                         }
129                         if(context != null) {
130                             registration = context.registerService(ConfigPusher.class.getName(), configPusher, null);
131                             configPusher.process(autoCloseables, platformMBeanServer, persisterAggregator, false);
132                         } else {
133                             LOG.warn("Unable to process configs as BundleContext is null");
134                         }
135                     } catch (InterruptedException e) {
136                         LOG.info("ConfigPusher thread stopped");
137                     }
138                     LOG.info("Configuration Persister initialization completed.");
139                 }
140             }, "config-pusher");
141         synchronized (autoCloseables) {
142             autoCloseables.add(new AutoCloseable() {
143                 @Override
144                 public void close() {
145                     pushingThread.interrupt();
146                 }
147             });
148         }
149         pushingThread.setDaemon(true);
150         pushingThread.start();
151     }
152 }
153