Merge "Bug 1262 - Document Transaction Chaining of MD-SAL"
[controller.git] / opendaylight / configuration / implementation / src / main / java / org / opendaylight / controller / configuration / internal / ContainerConfigurationService.java
index 5f1db6b597d707c649b5d094ae15a1a19e62b5d7..dcab1f63fbc1104e4225b0351455fb3de0db1d70 100644 (file)
@@ -9,21 +9,31 @@
 
 package org.opendaylight.controller.configuration.internal;
 
+import java.io.File;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Dictionary;
 import java.util.EnumSet;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.ConcurrentMap;
 
+import org.apache.felix.dm.Component;
 import org.opendaylight.controller.clustering.services.CacheConfigException;
 import org.opendaylight.controller.clustering.services.CacheExistException;
 import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
 import org.opendaylight.controller.clustering.services.IClusterServices;
 import org.opendaylight.controller.configuration.ConfigurationEvent;
+import org.opendaylight.controller.configuration.ConfigurationObject;
 import org.opendaylight.controller.configuration.IConfigurationAware;
 import org.opendaylight.controller.configuration.IConfigurationContainerAware;
 import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.ObjectReader;
+import org.opendaylight.controller.sal.utils.ObjectWriter;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
 import org.slf4j.Logger;
@@ -34,22 +44,22 @@ import org.slf4j.LoggerFactory;
  *
  * @brief  Backend functionality for all ConfigurationService related tasks.
  *
- *
  */
 
-public class ContainerConfigurationService implements IConfigurationContainerService, IConfigurationAware,
-        ICacheUpdateAware<ConfigurationEvent, String> {
+public class ContainerConfigurationService implements IConfigurationContainerService,
+        IConfigurationAware,
+        ICacheUpdateAware<String, String> {
     public static final String CONTAINER_SAVE_EVENT_CACHE = "config.container.event.save";
     private static final Logger logger = LoggerFactory.getLogger(ContainerConfigurationService.class);
     private IClusterContainerServices clusterServices;
-    private ConcurrentMap <ConfigurationEvent, String> containerConfigEvent;
-    /*
-     * Collection containing the configuration objects.
-     * This is configuration world: container names (also the map key)
-     * are maintained as they were configured by user, same case
-     */
+    private ConcurrentMap<String, String> containerConfigEvent;
+    // Directory which contains the startup files for this container
+    private String root;
     private Set<IConfigurationContainerAware> configurationAwareList = Collections
             .synchronizedSet(new HashSet<IConfigurationContainerAware>());
+    private ObjectReader objReader;
+    private ObjectWriter objWriter;
+    private String containerName;
 
     public void addConfigurationContainerAware(
             IConfigurationContainerAware configurationAware) {
@@ -79,12 +89,18 @@ public class ContainerConfigurationService implements IConfigurationContainerSer
         }
     }
 
-    public void init() {
+    void init(Component c) {
+        Dictionary<?, ?> props = c.getServiceProperties();
+        containerName = (props != null) ? (String) props.get("containerName") :
+            GlobalConstants.DEFAULT.toString();
+        root =  String.format("%s%s/", GlobalConstants.STARTUPHOME.toString(), containerName);
     }
 
     public void start() {
         allocateCache();
         retrieveCache();
+        objReader = new ObjectReader();
+        objWriter = new ObjectWriter();
     }
 
     public void destroy() {
@@ -92,33 +108,47 @@ public class ContainerConfigurationService implements IConfigurationContainerSer
         this.configurationAwareList.clear();
     }
 
+    /**
+     * Function called by the dependency manager before Container is Stopped and Destroyed.
+     */
+    public void containerStop() {
+        // Do nothing
+    }
+
+    @Override
+    public String getConfigurationRoot() {
+        return root;
+    }
+
     @Override
     public Status saveConfiguration() {
         boolean success = true;
+
         for (IConfigurationContainerAware configurationAware : configurationAwareList) {
             logger.trace("Save Config triggered for {}", configurationAware.getClass().getSimpleName());
 
             Status status = configurationAware.saveConfiguration();
             if (!status.isSuccess()) {
                 success = false;
-                logger.warn("Failed to save config for {}", configurationAware.getClass().getSimpleName());
+                logger.warn("Failed to save config for {} ({})", configurationAware.getClass().getSimpleName(),
+                        status.getDescription());
             }
         }
         if (success) {
             return new Status(StatusCode.SUCCESS);
         } else {
-            return new Status(StatusCode.INTERNALERROR, "Failed to Save All Configurations");
+            return new Status(StatusCode.INTERNALERROR, "Failed to save one or more configurations");
         }
     }
 
     @Override
     public Status saveConfigurations() {
-        containerConfigEvent.put(ConfigurationEvent.SAVE, "");
+        containerConfigEvent.put(ConfigurationEvent.SAVE.toString(), "");
         return saveConfiguration();
     }
 
     @Override
-    public void entryCreated(ConfigurationEvent key, String cacheName,
+    public void entryCreated(String key, String cacheName,
             boolean originLocal) {
         if (originLocal) {
             return;
@@ -126,19 +156,19 @@ public class ContainerConfigurationService implements IConfigurationContainerSer
     }
 
     @Override
-    public void entryUpdated(ConfigurationEvent key, String new_value,
+    public void entryUpdated(String key, String new_value,
             String cacheName, boolean originLocal) {
         if (originLocal) {
             return;
         }
         logger.debug("Processing {} event", key);
-        if (key == ConfigurationEvent.SAVE) {
+        if (key.equals(ConfigurationEvent.SAVE.toString())) {
             saveConfiguration();
         }
     }
 
     @Override
-    public void entryDeleted(ConfigurationEvent key, String cacheName,
+    public void entryDeleted(String key, String cacheName,
             boolean originLocal) {
         if (originLocal) {
             return;
@@ -166,9 +196,47 @@ public class ContainerConfigurationService implements IConfigurationContainerSer
             logger.error("uninitialized clusterServices, can't retrieve cache");
             return;
         }
-        containerConfigEvent = (ConcurrentMap<ConfigurationEvent, String>) this.clusterServices.getCache(CONTAINER_SAVE_EVENT_CACHE);
+        containerConfigEvent =
+                (ConcurrentMap<String, String>) this.clusterServices.getCache(CONTAINER_SAVE_EVENT_CACHE);
         if (containerConfigEvent == null) {
             logger.error("Failed to retrieve configuration Cache");
         }
     }
+
+    @Override
+    public Status persistConfiguration(List<ConfigurationObject> config, String fileName) {
+        if (!hasBeenSaved()) {
+            return new Status(StatusCode.NOTALLOWED,
+                    String.format("Container %s has not been saved yet", containerName));
+        }
+        String destination = String.format("%s%s", root, fileName);
+        return objWriter.write(config, destination);
+    }
+
+    @Override
+    public List<ConfigurationObject> retrieveConfiguration(IObjectReader reader, String fileName) {
+        if (!clusterServices.amICoordinator()) {
+            return Collections.emptyList();
+        }
+        String source = String.format("%s%s", root, fileName);
+        Object obj = objReader.read(reader, source);
+        if (obj == null) {
+            return Collections.<ConfigurationObject> emptyList();
+        }
+        if (obj instanceof ConcurrentMap) {
+            return new ArrayList<ConfigurationObject>(((ConcurrentMap)obj).values());
+        }
+        return (List<ConfigurationObject>) obj;
+    }
+
+    @Override
+    public boolean hasBeenSaved() {
+        try {
+            File configRoot = new File(this.getConfigurationRoot());
+            return configRoot.exists();
+        } catch (Exception e) {
+            return false;
+        }
+
+    }
 }