Refactor InMemoryJournal and InMemorySnapshot to sal-akka-raft
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / test / java / org / opendaylight / controller / cluster / raft / utils / InMemorySnapshotStore.java
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2015 Brocade Communications Systems, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.controller.cluster.datastore.utils;
+package org.opendaylight.controller.cluster.raft.utils;
 
 import akka.dispatch.Futures;
 import akka.japi.Option;
@@ -15,18 +15,29 @@ import akka.persistence.SnapshotMetadata;
 import akka.persistence.SnapshotSelectionCriteria;
 import akka.persistence.snapshot.japi.SnapshotStore;
 import com.google.common.collect.Iterables;
-import scala.concurrent.Future;
+import com.google.common.collect.Lists;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
-import org.opendaylight.controller.cluster.raft.Snapshot;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import scala.concurrent.Future;
 
+/**
+ * An akka SnapshotStore implementation that stores data in memory. This is intended for testing.
+ *
+ * @author Thomas Pantelis
+ */
 public class InMemorySnapshotStore extends SnapshotStore {
 
+    static final Logger LOG = LoggerFactory.getLogger(InMemorySnapshotStore.class);
+
     private static Map<String, List<StoredSnapshot>> snapshots = new ConcurrentHashMap<>();
 
-    public static void addSnapshot(String persistentId, Snapshot snapshot) {
+    public static void addSnapshot(String persistentId, Object snapshot) {
         List<StoredSnapshot> snapshotList = snapshots.get(persistentId);
 
         if(snapshotList == null) {
@@ -34,8 +45,30 @@ public class InMemorySnapshotStore extends SnapshotStore {
             snapshots.put(persistentId, snapshotList);
         }
 
-        snapshotList.add(new StoredSnapshot(new SnapshotMetadata(persistentId, snapshotList.size(),
-                System.currentTimeMillis()), snapshot));
+        synchronized (snapshotList) {
+            snapshotList.add(new StoredSnapshot(new SnapshotMetadata(persistentId, snapshotList.size(),
+                    System.currentTimeMillis()), snapshot));
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> List<T> getSnapshots(String persistentId, Class<T> type) {
+        List<StoredSnapshot> stored = snapshots.get(persistentId);
+        if(stored == null) {
+            return Collections.emptyList();
+        }
+
+        List<T> retList;
+        synchronized (stored) {
+            retList = Lists.newArrayListWithCapacity(stored.size());
+            for(StoredSnapshot s: stored) {
+                if(type.isInstance(s.getData())) {
+                    retList.add((T) s.getData());
+                }
+            }
+        }
+
+        return retList;
     }
 
     public static void clear() {
@@ -64,7 +97,9 @@ public class InMemorySnapshotStore extends SnapshotStore {
             snapshotList = new ArrayList<>();
             snapshots.put(snapshotMetadata.persistenceId(), snapshotList);
         }
-        snapshotList.add(new StoredSnapshot(snapshotMetadata, o));
+        synchronized (snapshotList) {
+            snapshotList.add(new StoredSnapshot(snapshotMetadata, o));
+        }
 
         return Futures.successful(null);
     }
@@ -83,32 +118,42 @@ public class InMemorySnapshotStore extends SnapshotStore {
 
         int deleteIndex = -1;
 
-        for(int i=0;i<snapshotList.size(); i++){
-            StoredSnapshot snapshot = snapshotList.get(i);
-            if(snapshotMetadata.equals(snapshot.getMetadata())){
-                deleteIndex = i;
-                break;
+        synchronized (snapshotList) {
+            for(int i=0;i<snapshotList.size(); i++){
+                StoredSnapshot snapshot = snapshotList.get(i);
+                if(snapshotMetadata.equals(snapshot.getMetadata())){
+                    deleteIndex = i;
+                    break;
+                }
             }
-        }
 
-        if(deleteIndex != -1){
-            snapshotList.remove(deleteIndex);
+            if(deleteIndex != -1){
+                snapshotList.remove(deleteIndex);
+            }
         }
-
     }
 
     @Override
-    public void doDelete(String s, SnapshotSelectionCriteria snapshotSelectionCriteria)
+    public void doDelete(String persistentId, SnapshotSelectionCriteria snapshotSelectionCriteria)
         throws Exception {
-        List<StoredSnapshot> snapshotList = snapshots.get(s);
+        List<StoredSnapshot> snapshotList = snapshots.get(persistentId);
 
         if(snapshotList == null){
             return;
         }
 
-        // TODO : This is a quick and dirty implementation. Do actual match later.
-        snapshotList.clear();
-        snapshots.remove(s);
+        synchronized (snapshotList) {
+            Iterator<StoredSnapshot> iter = snapshotList.iterator();
+            while(iter.hasNext()) {
+                StoredSnapshot s = iter.next();
+                LOG.trace("doDelete: sequenceNr: {}, maxSequenceNr: {}", s.getMetadata().sequenceNr(),
+                        snapshotSelectionCriteria.maxSequenceNr());
+
+                if(s.getMetadata().sequenceNr() <= snapshotSelectionCriteria.maxSequenceNr()) {
+                    iter.remove();
+                }
+            }
+        }
     }
 
     private static class StoredSnapshot {