3 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
10 package org.opendaylight.controller.configuration.internal;
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;
19 import java.util.concurrent.ConcurrentMap;
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;
42 * @file ConfigurationImpl.java
44 * @brief Backend functionality for all ConfigurationService related tasks.
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;
55 * Collection containing the configuration objects.
56 * This is configuration world: container names (also the map key)
57 * are maintained as they were configured by user, same case
59 private Set<IConfigurationContainerAware> configurationAwareList = Collections
60 .synchronizedSet(new HashSet<IConfigurationContainerAware>());
62 private ObjectReader objReader;
63 private ObjectWriter objWriter;
65 public void addConfigurationContainerAware(
66 IConfigurationContainerAware configurationAware) {
67 if (!this.configurationAwareList.contains(configurationAware)) {
68 this.configurationAwareList.add(configurationAware);
72 public int getConfigurationAwareListSize() {
73 return this.configurationAwareList.size();
76 public void removeConfigurationContainerAware(
77 IConfigurationContainerAware configurationAware) {
78 this.configurationAwareList.remove(configurationAware);
81 public void setClusterServices(IClusterContainerServices i) {
82 this.clusterServices = i;
83 logger.debug("IClusterServices set");
86 public void unsetClusterServices(IClusterContainerServices i) {
87 if (this.clusterServices == i) {
88 this.clusterServices = null;
89 logger.debug("IClusterServices Unset");
93 void init(Component c) {
94 Dictionary<?, ?> props = c.getServiceProperties();
95 String containerName = (props != null) ? (String) props.get("containerName") : GlobalConstants.DEFAULT.toString();
96 root = String.format("%s%s/", GlobalConstants.STARTUPHOME.toString(), containerName);
97 if (!new File(root).exists()) {
98 boolean created = new File(root).mkdir();
100 logger.error("Failed to create startup config directory for container {}", containerName);
105 public void start() {
108 objReader = new ObjectReader();
109 objWriter = new ObjectWriter();
112 public void destroy() {
113 // Clear local states
114 this.configurationAwareList.clear();
118 * Function called by the dependency manager before Container is Stopped and Destroyed.
120 public void containerStop() {
121 // Remove container directory along with its startup files
122 File[] files = new File(root).listFiles();
123 for (File file : files) {
126 new File(root).delete();
130 public Status saveConfiguration() {
131 boolean success = true;
132 for (IConfigurationContainerAware configurationAware : configurationAwareList) {
133 logger.trace("Save Config triggered for {}", configurationAware.getClass().getSimpleName());
135 Status status = configurationAware.saveConfiguration();
136 if (!status.isSuccess()) {
138 logger.warn("Failed to save config for {}", configurationAware.getClass().getSimpleName());
142 return new Status(StatusCode.SUCCESS);
144 return new Status(StatusCode.INTERNALERROR, "Failed to Save All Configurations");
149 public Status saveConfigurations() {
150 containerConfigEvent.put(ConfigurationEvent.SAVE, "");
151 return saveConfiguration();
155 public void entryCreated(ConfigurationEvent key, String cacheName,
156 boolean originLocal) {
163 public void entryUpdated(ConfigurationEvent key, String new_value,
164 String cacheName, boolean originLocal) {
168 logger.debug("Processing {} event", key);
169 if (key == ConfigurationEvent.SAVE) {
175 public void entryDeleted(ConfigurationEvent key, String cacheName,
176 boolean originLocal) {
182 private void allocateCache() {
183 if (this.clusterServices == null) {
184 logger.error("uninitialized clusterServices, can't create cache");
188 this.clusterServices.createCache(CONTAINER_SAVE_EVENT_CACHE,
189 EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
190 } catch (CacheConfigException cce) {
191 logger.debug("Error creating ContainerConfigurationService cache ", cce);
192 } catch (CacheExistException cce) {
193 logger.debug("ConfigurationService Cache already exists, destroy and recreate ", cce);
197 @SuppressWarnings({ "unchecked" })
198 private void retrieveCache() {
199 if (this.clusterServices == null) {
200 logger.error("uninitialized clusterServices, can't retrieve cache");
203 containerConfigEvent = (ConcurrentMap<ConfigurationEvent, String>) this.clusterServices.getCache(CONTAINER_SAVE_EVENT_CACHE);
204 if (containerConfigEvent == null) {
205 logger.error("Failed to retrieve configuration Cache");
210 public Status persistConfiguration(List<ConfigurationObject> config, String fileName) {
211 String destination = String.format("%s%s", root, fileName);
212 return objWriter.write(config, destination);
216 public List<ConfigurationObject> retrieveConfiguration(IObjectReader reader, String fileName) {
217 if (!clusterServices.amICoordinator()) {
218 return Collections.emptyList();
220 String source = String.format("%s%s", root, fileName);
221 Object obj = objReader.read(reader, source);
222 return (obj == null || !(obj instanceof List)) ? Collections.<ConfigurationObject> emptyList()
223 : (List<ConfigurationObject>) obj;