Merge "CHange log level from warn to debug in ProtocolSessionPromise when connection...
[controller.git] / opendaylight / configuration / implementation / src / main / java / org / opendaylight / controller / configuration / internal / ConfigurationService.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.io.File;
13 import java.util.ArrayList;
14 import java.util.Collections;
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.opendaylight.controller.clustering.services.CacheConfigException;
22 import org.opendaylight.controller.clustering.services.CacheExistException;
23 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
24 import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
25 import org.opendaylight.controller.clustering.services.IClusterServices;
26 import org.opendaylight.controller.configuration.ConfigurationEvent;
27 import org.opendaylight.controller.configuration.ConfigurationObject;
28 import org.opendaylight.controller.configuration.IConfigurationAware;
29 import org.opendaylight.controller.configuration.IConfigurationContainerService;
30 import org.opendaylight.controller.configuration.IConfigurationService;
31 import org.opendaylight.controller.sal.utils.GlobalConstants;
32 import org.opendaylight.controller.sal.utils.IObjectReader;
33 import org.opendaylight.controller.sal.utils.ObjectReader;
34 import org.opendaylight.controller.sal.utils.ObjectWriter;
35 import org.opendaylight.controller.sal.utils.Status;
36 import org.opendaylight.controller.sal.utils.StatusCode;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 /**
41  * @file   ConfigurationImpl.java
42  *
43  * @brief  Backend functionality for all ConfigurationService related tasks.
44  *
45  */
46
47 public class ConfigurationService implements IConfigurationService, ICacheUpdateAware<ConfigurationEvent, String> {
48     private static final Logger logger = LoggerFactory
49             .getLogger(ConfigurationService.class);
50     public static final String SAVE_EVENT_CACHE = "config.event.save";
51     private static final String ROOT = GlobalConstants.STARTUPHOME.toString();
52     private IClusterGlobalServices clusterServices;
53     private ConcurrentMap <ConfigurationEvent, String> configEvent;
54     private Set<IConfigurationAware> configurationAwareList = Collections
55             .synchronizedSet(new HashSet<IConfigurationAware>());
56     private ObjectReader objReader;
57     private ObjectWriter objWriter;
58
59
60     public int getConfigurationAwareListSize() {
61         return this.configurationAwareList.size();
62     }
63
64     public void addConfigurationAware(IConfigurationAware configurationAware) {
65         if (!this.configurationAwareList.contains(configurationAware)) {
66             this.configurationAwareList.add(configurationAware);
67         }
68     }
69
70     public void removeConfigurationAware(IConfigurationAware configurationAware) {
71         this.configurationAwareList.remove(configurationAware);
72     }
73
74     public void setClusterServices(IClusterGlobalServices i) {
75         this.clusterServices = i;
76         logger.debug("IClusterServices set");
77     }
78
79     public void unsetClusterServices(IClusterGlobalServices i) {
80         if (this.clusterServices == i) {
81             this.clusterServices = null;
82             logger.debug("IClusterServices Unset");
83         }
84     }
85
86     public void init() {
87         logger.info("ConfigurationService Manager init");
88     }
89
90     public void start() {
91         allocateCache();
92         retrieveCache();
93         objReader = new ObjectReader();
94         objWriter = new ObjectWriter();
95     }
96
97     public void destroy() {
98         // Clear local states
99         this.configurationAwareList.clear();
100     }
101
102     @Override
103     public Status saveConfigurations() {
104         if (configEvent != null) {
105             configEvent.put(ConfigurationEvent.SAVE, "");
106         }
107         return saveConfigurationsInternal();
108     }
109
110
111     private List<String> getContainerDirectoryList() {
112         List<String> containerList = new ArrayList<String>();
113         for (IConfigurationAware configurationAware : this.configurationAwareList) {
114             if (configurationAware instanceof IConfigurationContainerService) {
115                 String containerFilePath = ((ContainerConfigurationService)configurationAware).getConfigurationRoot();
116                 containerList.add(containerFilePath);
117             }
118         }
119         return containerList;
120     }
121
122     private void createContainerDirectory(IConfigurationAware configurationAware) {
123         String containerFilePath = ((ContainerConfigurationService) configurationAware).getConfigurationRoot();
124         if (!new File(containerFilePath).exists()) {
125             boolean created = new File(containerFilePath).mkdir();
126             if (!created) {
127                logger.error("Failed to create startup config directory: {}", containerFilePath);
128             }
129         }
130     }
131
132     private void clearStaleContainerDirectories() {
133         List<String> activeContainers = getContainerDirectoryList();
134         for (File file : new File(ROOT).listFiles()) {
135             if (file.isDirectory() && !activeContainers.contains(file.toPath() + File.separator)) {
136                 logger.trace("Removing directory for container {}", file.getName());
137                 for (File innerFile : file.listFiles()) {
138                       innerFile.delete();
139                 }
140                 boolean removed = file.delete();
141                 if (!removed) {
142                    logger.warn("Failed to remove stale directory: {}", file.getName());
143                 }
144             }
145         }
146     }
147
148
149     private Status saveConfigurationsInternal() {
150         boolean success = true;
151         for (IConfigurationAware configurationAware : configurationAwareList) {
152             if (configurationAware instanceof IConfigurationContainerService) {
153                 // Create directory for new containers
154                 createContainerDirectory(configurationAware);
155             }
156             Status status = configurationAware.saveConfiguration();
157             if (!status.isSuccess()) {
158                 success = false;
159                 logger.warn("Failed to save config for {}", configurationAware.getClass().getName());
160             }
161         }
162         // Remove startup directories of containers that were removed from
163         // the configuration but not saved
164         clearStaleContainerDirectories();
165
166         if (success) {
167             return new Status(StatusCode.SUCCESS);
168         } else {
169             return new Status(StatusCode.INTERNALERROR, "Failed to Save All Configurations");
170         }
171     }
172
173     @Override
174     public void entryCreated(ConfigurationEvent key, String cacheName,
175             boolean originLocal) {
176         if (originLocal) {
177             return;
178         }
179     }
180
181     @Override
182     public void entryUpdated(ConfigurationEvent key, String new_value,
183             String cacheName, boolean originLocal) {
184         if (originLocal) {
185             return;
186         }
187         if (key == ConfigurationEvent.SAVE) {
188             saveConfigurationsInternal();
189         }
190     }
191
192     @Override
193     public void entryDeleted(ConfigurationEvent key, String cacheName,
194             boolean originLocal) {
195         if (originLocal) {
196             return;
197         }
198     }
199
200     private void allocateCache() {
201         if (this.clusterServices == null) {
202             logger.error("uninitialized clusterServices, can't create cache");
203             return;
204         }
205         try {
206             this.clusterServices.createCache(SAVE_EVENT_CACHE,
207                     EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
208         } catch (CacheConfigException cce) {
209             logger.debug("Error creating ConfigurationService cache ", cce);
210         } catch (CacheExistException cce) {
211             logger.debug("ConfigurationService Cache already exists, destroy and recreate ", cce);
212         }
213     }
214
215     @SuppressWarnings({ "unchecked" })
216     private void retrieveCache() {
217         if (this.clusterServices == null) {
218             logger.error("uninitialized clusterServices, can't retrieve cache");
219             return;
220         }
221         configEvent = (ConcurrentMap<ConfigurationEvent, String>) this.clusterServices.getCache(SAVE_EVENT_CACHE);
222         if (configEvent == null) {
223             logger.error("Failed to retrieve configuration Cache");
224         }
225     }
226
227     @Override
228     public Status persistConfiguration(List<ConfigurationObject> config, String fileName) {
229         String destination = String.format("%s%s", ROOT, fileName);
230         return objWriter.write(config, destination);
231     }
232
233     @Override
234     public List<ConfigurationObject> retrieveConfiguration(IObjectReader reader, String fileName) {
235         if (!clusterServices.amICoordinator()) {
236             return Collections.emptyList();
237         }
238         String source = String.format("%s%s", ROOT, fileName);
239         Object obj = objReader.read(reader, source);
240         if (obj == null) {
241             return Collections.<ConfigurationObject> emptyList();
242         }
243         if (obj instanceof ConcurrentMap) {
244             return new ArrayList<ConfigurationObject>(((ConcurrentMap)obj).values());
245         }
246         return (List<ConfigurationObject>) obj;
247     }
248 }