Mechanical code cleanup (config)
[controller.git] / opendaylight / config / config-manager-facade-xml / src / main / java / org / opendaylight / controller / config / facade / xml / osgi / YangStoreActivator.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.facade.xml.osgi;
10
11 import com.google.common.base.Preconditions;
12 import java.lang.management.ManagementFactory;
13 import java.util.Hashtable;
14 import java.util.concurrent.atomic.AtomicBoolean;
15 import javax.management.MBeanServer;
16 import org.opendaylight.controller.config.facade.xml.ConfigSubsystemFacadeFactory;
17 import org.opendaylight.controller.config.util.ConfigRegistryJMXClient;
18 import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
19 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
20 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
21 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
22 import org.osgi.framework.BundleActivator;
23 import org.osgi.framework.BundleContext;
24 import org.osgi.framework.ServiceReference;
25 import org.osgi.framework.ServiceRegistration;
26 import org.osgi.util.tracker.ServiceTracker;
27 import org.osgi.util.tracker.ServiceTrackerCustomizer;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * Start yang store service and the XML config manager facade
33  */
34 public class YangStoreActivator implements BundleActivator {
35
36     private static final Logger LOG = LoggerFactory.getLogger(YangStoreActivator.class);
37
38     private final MBeanServer configMBeanServer = ManagementFactory.getPlatformMBeanServer();
39
40     private ServiceRegistration<YangStoreService> yangStoreServiceServiceRegistration;
41     private ConfigRegistryLookupThread configRegistryLookup = null;
42     private BundleContext context;
43     private ServiceRegistration<ConfigSubsystemFacadeFactory> osgiRegistrayion;
44
45     @Override
46     public void start(final BundleContext context) throws Exception {
47         LOG.debug("ConfigPersister starting");
48         this.context = context;
49
50         ServiceTrackerCustomizer<SchemaContextProvider, YangStoreService> schemaServiceTrackerCustomizer = new ServiceTrackerCustomizer<SchemaContextProvider, YangStoreService>() {
51
52             private final AtomicBoolean alreadyStarted = new AtomicBoolean(false);
53
54             @Override
55             public YangStoreService addingService(ServiceReference<SchemaContextProvider> reference) {
56                 LOG.debug("Got addingService(SchemaContextProvider) event");
57                 if(reference.getProperty(SchemaSourceProvider.class.getName()) == null &&
58                     reference.getProperty(BindingRuntimeContext.class.getName()) == null) {
59                     LOG.debug("SchemaContextProvider not from config-manager. Ignoring");
60                     return null;
61                 }
62
63                 // Yang store service should not be registered multiple times
64                 if(!alreadyStarted.compareAndSet(false, true)) {
65                     LOG.warn("Starting yang store service multiple times. Received new service {}", reference);
66                     throw new RuntimeException("Starting yang store service multiple times");
67                 }
68                 SchemaContextProvider schemaContextProvider = reference.getBundle().getBundleContext().getService(reference);
69                 final Object sourceProvider = Preconditions.checkNotNull(
70                     reference.getProperty(SchemaSourceProvider.class.getName()), "Source provider not found");
71                 Preconditions.checkArgument(sourceProvider instanceof SchemaSourceProvider);
72
73                 // TODO avoid cast
74                 final YangStoreService yangStoreService = new YangStoreService(schemaContextProvider,
75                     ((SchemaSourceProvider<YangTextSchemaSource>) sourceProvider));
76
77                 final BindingRuntimeContext runtimeContext = (BindingRuntimeContext) reference
78                         .getProperty(BindingRuntimeContext.class.getName());
79                 LOG.debug("BindingRuntimeContext retrieved as {}", runtimeContext);
80                 if(runtimeContext != null) {
81                     yangStoreService.refresh(runtimeContext);
82                 }
83
84                 yangStoreServiceServiceRegistration = context.registerService(YangStoreService.class, yangStoreService,
85                         new Hashtable<>());
86                 configRegistryLookup = new ConfigRegistryLookupThread(yangStoreService);
87                 configRegistryLookup.start();
88                 return yangStoreService;
89             }
90
91             @Override
92             public void modifiedService(ServiceReference<SchemaContextProvider> reference, YangStoreService service) {
93                 if (service == null) {
94                     return;
95                 }
96
97                 LOG.debug("Got modifiedService(SchemaContextProvider) event");
98                 final BindingRuntimeContext runtimeContext = (BindingRuntimeContext) reference
99                     .getProperty(BindingRuntimeContext.class.getName());
100                 LOG.debug("BindingRuntimeContext retrieved as {}", runtimeContext);
101                 service.refresh(runtimeContext);
102             }
103
104             @Override
105             public void removedService(ServiceReference<SchemaContextProvider> reference, YangStoreService service) {
106                 if(service == null) {
107                     return;
108                 }
109
110                 LOG.debug("Got removedService(SchemaContextProvider) event");
111                 alreadyStarted.set(false);
112                 configRegistryLookup.interrupt();
113                 yangStoreServiceServiceRegistration.unregister();
114                 yangStoreServiceServiceRegistration = null;
115             }
116         };
117
118         ServiceTracker<SchemaContextProvider, YangStoreService> schemaContextProviderServiceTracker =
119                 new ServiceTracker<>(context, SchemaContextProvider.class, schemaServiceTrackerCustomizer);
120         schemaContextProviderServiceTracker.open();
121     }
122
123     @Override
124     public void stop(BundleContext context) throws Exception {
125         if(configRegistryLookup != null) {
126             configRegistryLookup.interrupt();
127         }
128         if(osgiRegistrayion != null) {
129             osgiRegistrayion.unregister();
130         }
131         if (yangStoreServiceServiceRegistration != null) {
132             yangStoreServiceServiceRegistration.unregister();
133             yangStoreServiceServiceRegistration = null;
134         }
135     }
136
137     /**
138      * Find ConfigRegistry from config manager in JMX
139      */
140     private class ConfigRegistryLookupThread extends Thread {
141         public static final int ATTEMPT_TIMEOUT_MS = 1000;
142         private static final int SILENT_ATTEMPTS = 30;
143
144         private final YangStoreService yangStoreService;
145
146         private ConfigRegistryLookupThread(YangStoreService yangStoreService) {
147             super("config-registry-lookup");
148             this.yangStoreService = yangStoreService;
149         }
150
151         @Override
152         public void run() {
153
154             ConfigRegistryJMXClient configRegistryJMXClient;
155             ConfigRegistryJMXClient configRegistryJMXClientNoNotifications;
156             int i = 0;
157             // Config registry might not be present yet, but will be eventually
158             while(true) {
159
160                 try {
161                     configRegistryJMXClient = new ConfigRegistryJMXClient(configMBeanServer);
162                     configRegistryJMXClientNoNotifications = ConfigRegistryJMXClient.createWithoutNotifications(configMBeanServer);
163                     break;
164                 } catch (IllegalStateException e) {
165                     ++i;
166                     if (i > SILENT_ATTEMPTS) {
167                         LOG.info("JMX client not created after {} attempts, still trying", i, e);
168                     } else {
169                         LOG.debug("JMX client could not be created, reattempting, try {}", i, e);
170                     }
171                     try {
172                         Thread.sleep(ATTEMPT_TIMEOUT_MS);
173                     } catch (InterruptedException e1) {
174                         Thread.currentThread().interrupt();
175                         throw new IllegalStateException("Interrupted while reattempting connection", e1);
176                     }
177                 }
178             }
179
180             final ConfigRegistryJMXClient jmxClient = configRegistryJMXClient;
181             final ConfigRegistryJMXClient jmxClientNoNotifications = configRegistryJMXClientNoNotifications;
182             if (i > SILENT_ATTEMPTS) {
183                 LOG.info("Created JMX client after {} attempts", i);
184             } else {
185                 LOG.debug("Created JMX client after {} attempts", i);
186             }
187
188             final ConfigSubsystemFacadeFactory configSubsystemFacade =
189                     new ConfigSubsystemFacadeFactory(jmxClient, jmxClientNoNotifications, yangStoreService);
190             osgiRegistrayion = context.registerService(ConfigSubsystemFacadeFactory.class, configSubsystemFacade,
191                     new Hashtable<>());
192         }
193     }
194 }
195