Merge "Do not use protobuf serialization for FindPrimary and it's responses"
[controller.git] / opendaylight / netconf / config-persister-impl / src / main / java / org / opendaylight / controller / netconf / persist / impl / osgi / ConfigPersisterActivator.java
1 /*
2  * Copyright (c) 2013 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.netconf.persist.impl.osgi;
10
11 import java.lang.management.ManagementFactory;
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.concurrent.TimeUnit;
15
16 import javax.management.MBeanServer;
17
18 import org.opendaylight.controller.config.persist.api.ConfigPusher;
19 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
20 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
21 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
22 import org.opendaylight.controller.netconf.persist.impl.ConfigPusherImpl;
23 import org.opendaylight.controller.netconf.persist.impl.PersisterAggregator;
24 import org.opendaylight.controller.netconf.util.CloseableUtil;
25 import org.osgi.framework.BundleActivator;
26 import org.osgi.framework.BundleContext;
27 import org.osgi.framework.Constants;
28 import org.osgi.framework.Filter;
29 import org.osgi.framework.InvalidSyntaxException;
30 import org.osgi.framework.ServiceReference;
31 import org.osgi.framework.ServiceRegistration;
32 import org.osgi.util.tracker.ServiceTracker;
33 import org.osgi.util.tracker.ServiceTrackerCustomizer;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 import com.google.common.annotations.VisibleForTesting;
38
39 public class ConfigPersisterActivator implements BundleActivator {
40
41     private static final Logger logger = LoggerFactory.getLogger(ConfigPersisterActivator.class);
42     private static final MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
43
44     public static final String MAX_WAIT_FOR_CAPABILITIES_MILLIS_PROPERTY = "maxWaitForCapabilitiesMillis";
45     private static final long MAX_WAIT_FOR_CAPABILITIES_MILLIS_DEFAULT = TimeUnit.MINUTES.toMillis(2);
46     public static final String CONFLICTING_VERSION_TIMEOUT_MILLIS_PROPERTY = "conflictingVersionTimeoutMillis";
47     private static final long CONFLICTING_VERSION_TIMEOUT_MILLIS_DEFAULT = TimeUnit.SECONDS.toMillis(30);
48
49     public static final String NETCONF_CONFIG_PERSISTER = "netconf.config.persister";
50
51     public static final String STORAGE_ADAPTER_CLASS_PROP_SUFFIX = "storageAdapterClass";
52
53     private List<AutoCloseable> autoCloseables;
54     private volatile BundleContext context;
55
56     ServiceRegistration<?> registration;
57
58     @Override
59     public void start(final BundleContext context) throws Exception {
60         logger.debug("ConfigPersister starting");
61         this.context = context;
62
63         autoCloseables = new ArrayList<>();
64         PropertiesProviderBaseImpl propertiesProvider = new PropertiesProviderBaseImpl(context);
65
66         final PersisterAggregator persisterAggregator = PersisterAggregator.createFromProperties(propertiesProvider);
67         autoCloseables.add(persisterAggregator);
68         long maxWaitForCapabilitiesMillis = getMaxWaitForCapabilitiesMillis(propertiesProvider);
69         List<ConfigSnapshotHolder> configs = persisterAggregator.loadLastConfigs();
70         long conflictingVersionTimeoutMillis = getConflictingVersionTimeoutMillis(propertiesProvider);
71         logger.debug("Following configs will be pushed: {}", configs);
72
73         InnerCustomizer innerCustomizer = new InnerCustomizer(configs, maxWaitForCapabilitiesMillis,
74                 conflictingVersionTimeoutMillis, persisterAggregator);
75         OuterCustomizer outerCustomizer = new OuterCustomizer(context, innerCustomizer);
76         new ServiceTracker<>(context, NetconfOperationProvider.class, outerCustomizer).open();
77     }
78
79     private long getConflictingVersionTimeoutMillis(PropertiesProviderBaseImpl propertiesProvider) {
80         String timeoutProperty = propertiesProvider.getProperty(CONFLICTING_VERSION_TIMEOUT_MILLIS_PROPERTY);
81         return timeoutProperty == null ? CONFLICTING_VERSION_TIMEOUT_MILLIS_DEFAULT : Long.valueOf(timeoutProperty);
82     }
83
84     private long getMaxWaitForCapabilitiesMillis(PropertiesProviderBaseImpl propertiesProvider) {
85         String timeoutProperty = propertiesProvider.getProperty(MAX_WAIT_FOR_CAPABILITIES_MILLIS_PROPERTY);
86         return timeoutProperty == null ? MAX_WAIT_FOR_CAPABILITIES_MILLIS_DEFAULT : Long.valueOf(timeoutProperty);
87     }
88
89     @Override
90     public void stop(BundleContext context) throws Exception {
91         synchronized(autoCloseables) {
92             CloseableUtil.closeAll(autoCloseables);
93             if (registration != null) {
94                 registration.unregister();
95             }
96             this.context = null;
97         }
98     }
99
100
101     @VisibleForTesting
102     public static String getFilterString() {
103         return "(&" +
104                 "(" + Constants.OBJECTCLASS + "=" + NetconfOperationServiceFactory.class.getName() + ")" +
105                 "(name" + "=" + "config-netconf-connector" + ")" +
106                 ")";
107     }
108
109     class OuterCustomizer implements ServiceTrackerCustomizer<NetconfOperationProvider, NetconfOperationProvider> {
110         private final BundleContext context;
111         private final InnerCustomizer innerCustomizer;
112
113         OuterCustomizer(BundleContext context, InnerCustomizer innerCustomizer) {
114             this.context = context;
115             this.innerCustomizer = innerCustomizer;
116         }
117
118         @Override
119         public NetconfOperationProvider addingService(ServiceReference<NetconfOperationProvider> reference) {
120             logger.trace("Got OuterCustomizer.addingService {}", reference);
121             // JMX was registered, track config-netconf-connector
122             Filter filter;
123             try {
124                 filter = context.createFilter(getFilterString());
125             } catch (InvalidSyntaxException e) {
126                 throw new IllegalStateException(e);
127             }
128             new ServiceTracker<>(context, filter, innerCustomizer).open();
129             return null;
130         }
131
132         @Override
133         public void modifiedService(ServiceReference<NetconfOperationProvider> reference, NetconfOperationProvider service) {
134
135         }
136
137         @Override
138         public void removedService(ServiceReference<NetconfOperationProvider> reference, NetconfOperationProvider service) {
139
140         }
141     }
142
143     class InnerCustomizer implements ServiceTrackerCustomizer<NetconfOperationServiceFactory, NetconfOperationServiceFactory> {
144         private final List<ConfigSnapshotHolder> configs;
145         private final PersisterAggregator persisterAggregator;
146         private final long maxWaitForCapabilitiesMillis, conflictingVersionTimeoutMillis;
147
148
149         InnerCustomizer(List<ConfigSnapshotHolder> configs, long maxWaitForCapabilitiesMillis, long conflictingVersionTimeoutMillis,
150                         PersisterAggregator persisterAggregator) {
151             this.configs = configs;
152             this.maxWaitForCapabilitiesMillis = maxWaitForCapabilitiesMillis;
153             this.conflictingVersionTimeoutMillis = conflictingVersionTimeoutMillis;
154             this.persisterAggregator = persisterAggregator;
155         }
156
157         @Override
158         public NetconfOperationServiceFactory addingService(ServiceReference<NetconfOperationServiceFactory> reference) {
159             logger.trace("Got InnerCustomizer.addingService {}", reference);
160             NetconfOperationServiceFactory service = reference.getBundle().getBundleContext().getService(reference);
161
162             logger.debug("Creating new job queue");
163
164             final ConfigPusherImpl configPusher = new ConfigPusherImpl(service, maxWaitForCapabilitiesMillis, conflictingVersionTimeoutMillis);
165             logger.debug("Configuration Persister got {}", service);
166             logger.debug("Context was {}", context);
167             logger.debug("Registration was {}", registration);
168
169             final Thread pushingThread = new Thread(new Runnable() {
170                 @Override
171                 public void run() {
172                     try {
173                         if(configs != null && !configs.isEmpty()) {
174                             configPusher.pushConfigs(configs);
175                         }
176                         if(context != null) {
177                             registration = context.registerService(ConfigPusher.class.getName(), configPusher, null);
178                             configPusher.process(autoCloseables, platformMBeanServer, persisterAggregator);
179                         } else {
180                             logger.warn("Unable to process configs as BundleContext is null");
181                         }
182                     } catch (InterruptedException e) {
183                         logger.info("ConfigPusher thread stopped",e);
184                     }
185                     logger.info("Configuration Persister initialization completed.");
186                 }
187             }, "config-pusher");
188             synchronized (autoCloseables) {
189                 autoCloseables.add(new AutoCloseable() {
190                     @Override
191                     public void close() {
192                         pushingThread.interrupt();
193                     }
194                 });
195             }
196             pushingThread.start();
197             return service;
198         }
199
200         @Override
201         public void modifiedService(ServiceReference<NetconfOperationServiceFactory> reference, NetconfOperationServiceFactory service) {
202         }
203
204         @Override
205         public void removedService(ServiceReference<NetconfOperationServiceFactory> reference, NetconfOperationServiceFactory service) {
206         }
207
208     }
209 }
210