BUG-2976: Resolve clash between current and feature cfg pusher
[controller.git] / opendaylight / config / config-persister-file-xml-adapter / src / main / java / org / opendaylight / controller / config / persist / storage / file / xml / XmlFileStorageAdapter.java
index e75c62b81db8dce90184d7142042a00fbce3a88f..a714fdc9d27dd4c1901fa1f0ef25045b82cb138b 100644 (file)
@@ -12,6 +12,12 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
 import org.opendaylight.controller.config.persist.api.Persister;
 import org.opendaylight.controller.config.persist.api.PropertiesProvider;
@@ -21,17 +27,11 @@ import org.opendaylight.controller.config.persist.storage.file.xml.model.ConfigS
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.SortedSet;
-
 /**
  * StorageAdapter that stores configuration in an xml file.
  */
 public class XmlFileStorageAdapter implements StorageAdapter, Persister {
-    private static final Logger logger = LoggerFactory.getLogger(XmlFileStorageAdapter.class);
+    private static final Logger LOG = LoggerFactory.getLogger(XmlFileStorageAdapter.class);
 
     public static final String FILE_STORAGE_PROP = "fileStorage";
     public static final String NUMBER_OF_BACKUPS = "numberOfBackups";
@@ -39,22 +39,38 @@ public class XmlFileStorageAdapter implements StorageAdapter, Persister {
     private static Integer numberOfStoredBackups;
     private File storage;
 
+    private static volatile XmlFileStorageAdapter instance;
+    private volatile ConfigSnapshot lastCfgSnapshotCache;
+    private volatile Optional<FeatureListProvider> featuresService = Optional.absent();
+
+    @VisibleForTesting
+    public void reset() {
+        instance = null;
+        lastCfgSnapshotCache = null;
+        featuresService = null;
+    }
+
     @Override
     public Persister instantiate(PropertiesProvider propertiesProvider) {
+        if(instance != null) {
+            return instance;
+        }
+
         File storage = extractStorageFileFromProperties(propertiesProvider);
-        logger.debug("Using file {}", storage.getAbsolutePath());
+        LOG.debug("Using file {}", storage.getAbsolutePath());
         // Create file if it does not exist
         File parentFile = storage.getAbsoluteFile().getParentFile();
         if (parentFile.exists() == false) {
-            logger.debug("Creating parent folders {}", parentFile);
+            LOG.debug("Creating parent folders {}", parentFile);
             parentFile.mkdirs();
         }
         if (storage.exists() == false) {
-            logger.debug("Storage file does not exist, creating empty file");
+            LOG.debug("Storage file does not exist, creating empty file");
             try {
                 boolean result = storage.createNewFile();
-                if (result == false)
+                if (result == false) {
                     throw new RuntimeException("Unable to create storage file " + storage);
+                }
             } catch (IOException e) {
                 throw new RuntimeException("Unable to create storage file " + storage, e);
             }
@@ -64,9 +80,23 @@ public class XmlFileStorageAdapter implements StorageAdapter, Persister {
                     + " property should be either set to positive value, or ommited. Can not be set to 0.");
         }
         setFileStorage(storage);
+
+        instance = this;
         return this;
     }
 
+    public static Optional<XmlFileStorageAdapter> getInstance() {
+        return Optional.fromNullable(instance);
+    }
+
+    public Set<String> getPersistedFeatures() {
+        return lastCfgSnapshotCache == null ? Collections.<String>emptySet() : lastCfgSnapshotCache.getFeatures();
+    }
+
+    public void setFeaturesService(final FeatureListProvider featuresService) {
+        this.featuresService = Optional.of(featuresService);
+    }
+
     @VisibleForTesting
     public void setFileStorage(File storage) {
         this.storage = storage;
@@ -87,7 +117,7 @@ public class XmlFileStorageAdapter implements StorageAdapter, Persister {
         } else {
             numberOfStoredBackups = Integer.MAX_VALUE;
         }
-        logger.trace("Property {} set to {}", NUMBER_OF_BACKUPS, numberOfStoredBackups);
+        LOG.trace("Property {} set to {}", NUMBER_OF_BACKUPS, numberOfStoredBackups);
         return result;
     }
 
@@ -95,8 +125,13 @@ public class XmlFileStorageAdapter implements StorageAdapter, Persister {
     public void persistConfig(ConfigSnapshotHolder holder) throws IOException {
         Preconditions.checkNotNull(storage, "Storage file is null");
 
+        Set<String> installedFeatureIds = Collections.emptySet();
+        if(featuresService.isPresent()) {
+            installedFeatureIds = featuresService.get().listFeatures();
+        }
+
         Config cfg = Config.fromXml(storage);
-        cfg.addConfigSnapshot(ConfigSnapshot.fromConfigSnapshot(holder), numberOfStoredBackups);
+        cfg.addConfigSnapshot(ConfigSnapshot.fromConfigSnapshot(holder, installedFeatureIds), numberOfStoredBackups);
         cfg.toXml(storage);
     }
 
@@ -110,10 +145,12 @@ public class XmlFileStorageAdapter implements StorageAdapter, Persister {
 
         Optional<ConfigSnapshot> lastSnapshot = Config.fromXml(storage).getLastSnapshot();
 
-        if (lastSnapshot.isPresent())
-            return Lists.newArrayList(toConfigSnapshot(lastSnapshot.get()));
-        else
+        if (lastSnapshot.isPresent()) {
+            lastCfgSnapshotCache = lastSnapshot.get();
+            return Lists.newArrayList(toConfigSnapshot(lastCfgSnapshotCache));
+        } else {
             return Collections.emptyList();
+        }
     }