Take snapshot after recovery on migrated messages
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / main / java / org / opendaylight / controller / cluster / raft / RaftActorContextImpl.java
index fa851515d70d94d7a8b7411652519926d5d85a1e..926e9748d477d8c54fcbde9265197e97a1369063 100644 (file)
@@ -13,6 +13,7 @@ import akka.actor.ActorRef;
 import akka.actor.ActorSelection;
 import akka.actor.ActorSystem;
 import akka.actor.Props;
+import akka.cluster.Cluster;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import java.util.ArrayList;
@@ -21,15 +22,18 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
-import java.util.function.Supplier;
+import java.util.function.LongSupplier;
 import org.opendaylight.controller.cluster.DataPersistenceProvider;
-import org.opendaylight.controller.cluster.raft.ServerConfigurationPayload.ServerInfo;
 import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior;
+import org.opendaylight.controller.cluster.raft.persisted.ServerConfigurationPayload;
+import org.opendaylight.controller.cluster.raft.persisted.ServerInfo;
 import org.opendaylight.controller.cluster.raft.policy.RaftPolicy;
 import org.slf4j.Logger;
 
 public class RaftActorContextImpl implements RaftActorContext {
+    private static final LongSupplier JVM_MEMORY_RETRIEVER = () -> Runtime.getRuntime().maxMemory();
 
     private final ActorRef actor;
 
@@ -54,7 +58,7 @@ public class RaftActorContextImpl implements RaftActorContext {
     private boolean dynamicServerConfiguration = false;
 
     @VisibleForTesting
-    private Supplier<Long> totalMemoryRetriever;
+    private LongSupplier totalMemoryRetriever = JVM_MEMORY_RETRIEVER;
 
     // Snapshot manager will need to be created on demand as it needs raft actor context which cannot
     // be passed to it in the constructor
@@ -68,6 +72,10 @@ public class RaftActorContextImpl implements RaftActorContext {
 
     private RaftActorBehavior currentBehavior;
 
+    private int numVotingPeers = -1;
+
+    private Optional<Cluster> cluster;
+
     public RaftActorContextImpl(ActorRef actor, ActorContext context, String id,
             ElectionTerm termInformation, long commitIndex, long lastApplied, Map<String, String> peerAddresses,
             ConfigParams configParams, DataPersistenceProvider persistenceProvider, Logger logger) {
@@ -120,6 +128,21 @@ public class RaftActorContextImpl implements RaftActorContext {
         return actor;
     }
 
+    @Override
+    public Optional<Cluster> getCluster() {
+        if(cluster == null) {
+            try {
+                cluster = Optional.of(Cluster.get(getActorSystem()));
+            } catch(Exception e) {
+                // An exception means there's no cluster configured. This will only happen in unit tests.
+                LOG.debug("{}: Could not obtain Cluster: {}", getId(), e);
+                cluster = Optional.empty();
+            }
+        }
+
+        return cluster;
+    }
+
     @Override
     public ElectionTerm getTermInformation() {
         return termInformation;
@@ -224,6 +247,8 @@ public class RaftActorContextImpl implements RaftActorContext {
             votingMember = false;
         }
 
+        LOG.debug("{}: Updated server config: isVoting: {}, peers: {}", id, votingMember, peerInfoMap.values());
+
         setDynamicServerConfigurationInUse();
     }
 
@@ -234,6 +259,7 @@ public class RaftActorContextImpl implements RaftActorContext {
     @Override
     public void addToPeers(String id, String address, VotingState votingState) {
         peerInfoMap.put(id, new PeerInfo(id, address, votingState));
+        numVotingPeers = -1;
     }
 
     @Override
@@ -242,6 +268,7 @@ public class RaftActorContextImpl implements RaftActorContext {
             votingMember = false;
         } else {
             peerInfoMap.remove(name);
+            numVotingPeers = -1;
         }
     }
 
@@ -272,12 +299,12 @@ public class RaftActorContextImpl implements RaftActorContext {
 
     @Override
     public long getTotalMemory() {
-        return totalMemoryRetriever != null ? totalMemoryRetriever.get() : Runtime.getRuntime().totalMemory();
+        return totalMemoryRetriever.getAsLong();
     }
 
     @Override
-    public void setTotalMemoryRetriever(Supplier<Long> retriever) {
-        totalMemoryRetriever = retriever;
+    public void setTotalMemoryRetriever(LongSupplier retriever) {
+        totalMemoryRetriever = retriever == null ? JVM_MEMORY_RETRIEVER : retriever;
     }
 
     @Override
@@ -329,6 +356,20 @@ public class RaftActorContextImpl implements RaftActorContext {
         return votingMember;
     }
 
+    @Override
+    public boolean anyVotingPeers() {
+        if(numVotingPeers < 0) {
+            numVotingPeers = 0;
+            for(PeerInfo info: getPeers()) {
+                if(info.isVoting()) {
+                    numVotingPeers++;
+                }
+            }
+        }
+
+        return numVotingPeers > 0;
+    }
+
     @Override
     public RaftActorBehavior getCurrentBehavior() {
         return currentBehavior;