Merge "bug 433 NPE in onGlobalContextUpdated of ControllerContext class"
[controller.git] / opendaylight / configuration / implementation / src / main / java / org / opendaylight / controller / configuration / internal / ContainerConfigurationService.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9
10 package org.opendaylight.controller.configuration.internal;
11
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.Dictionary;
15 import java.util.EnumSet;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Set;
19 import java.util.concurrent.ConcurrentMap;
20
21 import org.apache.felix.dm.Component;
22 import org.opendaylight.controller.clustering.services.CacheConfigException;
23 import org.opendaylight.controller.clustering.services.CacheExistException;
24 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
25 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
26 import org.opendaylight.controller.clustering.services.IClusterServices;
27 import org.opendaylight.controller.configuration.ConfigurationEvent;
28 import org.opendaylight.controller.configuration.ConfigurationObject;
29 import org.opendaylight.controller.configuration.IConfigurationAware;
30 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
31 import org.opendaylight.controller.configuration.IConfigurationContainerService;
32 import org.opendaylight.controller.sal.utils.GlobalConstants;
33 import org.opendaylight.controller.sal.utils.IObjectReader;
34 import org.opendaylight.controller.sal.utils.ObjectReader;
35 import org.opendaylight.controller.sal.utils.ObjectWriter;
36 import org.opendaylight.controller.sal.utils.Status;
37 import org.opendaylight.controller.sal.utils.StatusCode;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 /**
42  * @file   ConfigurationImpl.java
43  *
44  * @brief  Backend functionality for all ConfigurationService related tasks.
45  *
46  */
47
48 public class ContainerConfigurationService implements IConfigurationContainerService,
49         IConfigurationAware, ICacheUpdateAware<ConfigurationEvent, String> {
50     public static final String CONTAINER_SAVE_EVENT_CACHE = "config.container.event.save";
51     private static final Logger logger = LoggerFactory.getLogger(ContainerConfigurationService.class);
52     private IClusterContainerServices clusterServices;
53     private ConcurrentMap <ConfigurationEvent, String> containerConfigEvent;
54     // Directory which contains the startup files for this container
55     private String root;
56     private Set<IConfigurationContainerAware> configurationAwareList = Collections
57             .synchronizedSet(new HashSet<IConfigurationContainerAware>());
58     private ObjectReader objReader;
59     private ObjectWriter objWriter;
60
61     public void addConfigurationContainerAware(
62             IConfigurationContainerAware configurationAware) {
63         if (!this.configurationAwareList.contains(configurationAware)) {
64             this.configurationAwareList.add(configurationAware);
65         }
66     }
67
68     public int getConfigurationAwareListSize() {
69         return this.configurationAwareList.size();
70     }
71
72     public void removeConfigurationContainerAware(
73             IConfigurationContainerAware configurationAware) {
74         this.configurationAwareList.remove(configurationAware);
75     }
76
77     public void setClusterServices(IClusterContainerServices i) {
78         this.clusterServices = i;
79         logger.debug("IClusterServices set");
80     }
81
82     public void unsetClusterServices(IClusterContainerServices i) {
83         if (this.clusterServices == i) {
84             this.clusterServices = null;
85             logger.debug("IClusterServices Unset");
86         }
87     }
88
89     void init(Component c) {
90         Dictionary<?, ?> props = c.getServiceProperties();
91         String containerName = (props != null) ? (String) props.get("containerName") :
92             GlobalConstants.DEFAULT.toString();
93         root =  String.format("%s%s/", GlobalConstants.STARTUPHOME.toString(), containerName);
94     }
95
96     public void start() {
97         allocateCache();
98         retrieveCache();
99         objReader = new ObjectReader();
100         objWriter = new ObjectWriter();
101     }
102
103     public void destroy() {
104         // Clear local states
105         this.configurationAwareList.clear();
106     }
107
108     /**
109      * Function called by the dependency manager before Container is Stopped and Destroyed.
110      */
111     public void containerStop() {
112         // Do nothing
113     }
114
115     @Override
116     public String getConfigurationRoot() {
117         return root;
118     }
119
120     @Override
121     public Status saveConfiguration() {
122         boolean success = true;
123
124         for (IConfigurationContainerAware configurationAware : configurationAwareList) {
125             logger.trace("Save Config triggered for {}", configurationAware.getClass().getSimpleName());
126
127             Status status = configurationAware.saveConfiguration();
128             if (!status.isSuccess()) {
129                 success = false;
130                 logger.warn("Failed to save config for {}", configurationAware.getClass().getSimpleName());
131             }
132         }
133         if (success) {
134             return new Status(StatusCode.SUCCESS);
135         } else {
136             return new Status(StatusCode.INTERNALERROR, "Failed to Save All Configurations");
137         }
138     }
139
140     @Override
141     public Status saveConfigurations() {
142         containerConfigEvent.put(ConfigurationEvent.SAVE, "");
143         return saveConfiguration();
144     }
145
146     @Override
147     public void entryCreated(ConfigurationEvent key, String cacheName,
148             boolean originLocal) {
149         if (originLocal) {
150             return;
151         }
152     }
153
154     @Override
155     public void entryUpdated(ConfigurationEvent key, String new_value,
156             String cacheName, boolean originLocal) {
157         if (originLocal) {
158             return;
159         }
160         logger.debug("Processing {} event", key);
161         if (key == ConfigurationEvent.SAVE) {
162             saveConfiguration();
163         }
164     }
165
166     @Override
167     public void entryDeleted(ConfigurationEvent key, String cacheName,
168             boolean originLocal) {
169         if (originLocal) {
170             return;
171         }
172     }
173
174     private void allocateCache() {
175         if (this.clusterServices == null) {
176             logger.error("uninitialized clusterServices, can't create cache");
177             return;
178         }
179         try {
180             this.clusterServices.createCache(CONTAINER_SAVE_EVENT_CACHE,
181                     EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
182         } catch (CacheConfigException cce) {
183             logger.debug("Error creating ContainerConfigurationService cache ", cce);
184         } catch (CacheExistException cce) {
185             logger.debug("ConfigurationService Cache already exists, destroy and recreate ", cce);
186         }
187     }
188
189     @SuppressWarnings({ "unchecked" })
190     private void retrieveCache() {
191         if (this.clusterServices == null) {
192             logger.error("uninitialized clusterServices, can't retrieve cache");
193             return;
194         }
195         containerConfigEvent = (ConcurrentMap<ConfigurationEvent, String>) this.clusterServices.getCache(CONTAINER_SAVE_EVENT_CACHE);
196         if (containerConfigEvent == null) {
197             logger.error("Failed to retrieve configuration Cache");
198         }
199     }
200
201     @Override
202     public Status persistConfiguration(List<ConfigurationObject> config, String fileName) {
203         String destination = String.format("%s%s", root, fileName);
204         return objWriter.write(config, destination);
205     }
206
207     @Override
208     public List<ConfigurationObject> retrieveConfiguration(IObjectReader reader, String fileName) {
209         if (!clusterServices.amICoordinator()) {
210             return Collections.emptyList();
211         }
212         String source = String.format("%s%s", root, fileName);
213         Object obj = objReader.read(reader, source);
214         if (obj == null) {
215             return Collections.<ConfigurationObject> emptyList();
216         }
217         if (obj instanceof ConcurrentMap) {
218             return new ArrayList<ConfigurationObject>(((ConcurrentMap)obj).values());
219         }
220         return (List<ConfigurationObject>) obj;
221     }
222 }