Bug 1029: Remove dead code: samples/clustersession
[controller.git] / opendaylight / adsal / 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<String, 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<String, 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         // Create the default startup directory, so that container unaware apps can initiate save
90         createContainerDirectory(ROOT + GlobalConstants.DEFAULT.toString());
91     }
92
93     public void start() {
94         allocateCache();
95         retrieveCache();
96         objReader = new ObjectReader();
97         objWriter = new ObjectWriter();
98     }
99
100     public void destroy() {
101         // Clear local states
102         this.configurationAwareList.clear();
103     }
104
105     @Override
106     public Status saveConfigurations() {
107         if (configEvent != null) {
108             configEvent.put(ConfigurationEvent.SAVE.toString(), "");
109         }
110         return saveConfigurationsInternal();
111     }
112
113
114     private List<String> getContainerDirectoryList() {
115         List<String> containerList = new ArrayList<String>();
116         for (IConfigurationAware configurationAware : this.configurationAwareList) {
117             if (configurationAware instanceof IConfigurationContainerService) {
118                 String containerFilePath = ((IConfigurationContainerService)configurationAware).getConfigurationRoot();
119                 containerList.add(containerFilePath);
120             }
121         }
122         return containerList;
123     }
124
125     private void createContainerDirectory(IConfigurationAware configurationAware) {
126         String containerFilePath = ((IConfigurationContainerService) configurationAware).getConfigurationRoot();
127         createContainerDirectory(containerFilePath);
128     }
129
130     private void createContainerDirectory(String containerFilePath) {
131
132         try {
133             if (!new File(containerFilePath).exists()) {
134                 boolean created = new File(containerFilePath).mkdir();
135                 if (!created) {
136                     logger.error("Failed to create config directory: {}", containerFilePath);
137                 }
138             }
139         } catch (Exception e) {
140             logger.error("Failed to create config directory: {} ({})", containerFilePath, e.getMessage());
141         }
142     }
143
144     private void clearStaleContainerDirectories() {
145         List<String> activeContainers = getContainerDirectoryList();
146         for (File file : new File(ROOT).listFiles()) {
147             if (file.isDirectory() && !activeContainers.contains(file.toPath() + File.separator)) {
148                 logger.trace("Removing directory for container {}", file.getName());
149                 for (File innerFile : file.listFiles()) {
150                       innerFile.delete();
151                 }
152                 boolean removed = file.delete();
153                 if (!removed) {
154                    logger.warn("Failed to remove stale directory: {}", file.getName());
155                 }
156             }
157         }
158     }
159
160
161     private Status saveConfigurationsInternal() {
162         boolean success = true;
163         for (IConfigurationAware configurationAware : configurationAwareList) {
164             if (configurationAware instanceof IConfigurationContainerService) {
165                 // Create directory for new containers
166                 createContainerDirectory(configurationAware);
167             }
168             Status status = configurationAware.saveConfiguration();
169             if (!status.isSuccess()) {
170                 success = false;
171                 logger.warn("Failed to save config for {}", configurationAware.getClass().getName());
172             }
173         }
174         // Remove startup directories of containers that were removed from
175         // the configuration but not saved
176         clearStaleContainerDirectories();
177
178         if (success) {
179             return new Status(StatusCode.SUCCESS);
180         } else {
181             return new Status(StatusCode.INTERNALERROR, "Failed to Save All Configurations");
182         }
183     }
184
185     @Override
186     public void entryCreated(String key, String cacheName,
187             boolean originLocal) {
188         if (originLocal) {
189             return;
190         }
191     }
192
193     @Override
194     public void entryUpdated(String key, String new_value,
195             String cacheName, boolean originLocal) {
196         if (originLocal) {
197             return;
198         }
199         if (key.equals(ConfigurationEvent.SAVE.toString())) {
200             saveConfigurationsInternal();
201         }
202     }
203
204     @Override
205     public void entryDeleted(String key, String cacheName,
206             boolean originLocal) {
207         if (originLocal) {
208             return;
209         }
210     }
211
212     private void allocateCache() {
213         if (this.clusterServices == null) {
214             logger.error("uninitialized clusterServices, can't create cache");
215             return;
216         }
217         try {
218             this.clusterServices.createCache(SAVE_EVENT_CACHE,
219                     EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
220         } catch (CacheConfigException cce) {
221             logger.debug("Error creating ConfigurationService cache ", cce);
222         } catch (CacheExistException cce) {
223             logger.debug("ConfigurationService Cache already exists, destroy and recreate ", cce);
224         }
225     }
226
227     @SuppressWarnings({ "unchecked" })
228     private void retrieveCache() {
229         if (this.clusterServices == null) {
230             logger.error("uninitialized clusterServices, can't retrieve cache");
231             return;
232         }
233         configEvent = (ConcurrentMap<String, String>) this.clusterServices.getCache(SAVE_EVENT_CACHE);
234         if (configEvent == null) {
235             logger.error("Failed to retrieve configuration Cache");
236         }
237     }
238
239     @Override
240     public Status persistConfiguration(List<ConfigurationObject> config, String fileName) {
241         String destination = String.format("%s%s", ROOT, fileName);
242         return objWriter.write(config, destination);
243     }
244
245     @Override
246     public List<ConfigurationObject> retrieveConfiguration(IObjectReader reader, String fileName) {
247         if (!clusterServices.amICoordinator()) {
248             return Collections.emptyList();
249         }
250         String source = String.format("%s%s", ROOT, fileName);
251         Object obj = objReader.read(reader, source);
252         if (obj == null) {
253             return Collections.<ConfigurationObject> emptyList();
254         }
255         if (obj instanceof ConcurrentMap) {
256             return new ArrayList<ConfigurationObject>(((ConcurrentMap)obj).values());
257         }
258         return (List<ConfigurationObject>) obj;
259     }
260 }