From: Moiz Raja Date: Mon, 7 Jul 2014 00:38:52 +0000 (-0700) Subject: Initial code/design for an Akka Raft implementation X-Git-Tag: release/helium~443^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=789431e2c0c76d9d00bdc7599a08036e3720f170 Initial code/design for an Akka Raft implementation Also implements the LeaderBehavior for elections Change-Id: I629f2cd71717e5d76eae9c1a9a4dc960246070c9 Signed-off-by: Moiz Raja --- diff --git a/opendaylight/md-sal/sal-akka-raft/pom.xml b/opendaylight/md-sal/sal-akka-raft/pom.xml new file mode 100644 index 0000000000..50442bda5c --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/pom.xml @@ -0,0 +1,135 @@ + + + 4.0.0 + + org.opendaylight.controller + sal-parent + 1.1-SNAPSHOT + + sal-akka-raft + bundle + + + + com.google.guava + guava + + + + com.typesafe.akka + akka-actor_${scala.version} + + + + com.typesafe.akka + akka-cluster_${scala.version} + + + + com.typesafe.akka + akka-persistence-experimental_${scala.version} + + + + com.typesafe.akka + akka-remote_${scala.version} + + + + com.typesafe.akka + akka-testkit_${scala.version} + + + + org.osgi + org.osgi.core + + + + org.scala-lang + scala-library + + + + + junit + junit + test + + + org.mockito + mockito-all + test + + + + org.slf4j + slf4j-simple + ${slf4j.version} + test + + + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.groupId}.${project.artifactId} + + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + + + org.jacoco + jacoco-maven-plugin + + + org.opendaylight.controller.* + + false + + + + pre-test + + prepare-agent + + + + post-test + + report + + test + + + + + + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + HEAD + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Architecture:Clustering + + diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java new file mode 100644 index 0000000000..3c8e12b8b1 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/example/ExampleActor.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014 Cisco 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.example; + +import org.opendaylight.controller.cluster.raft.RaftActor; + +/** + * A sample actor showing how the RaftActor is to be extended + */ +public class ExampleActor extends RaftActor { + public ExampleActor(String id) { + super(id); + } + + @Override public void onReceiveCommand(Object message){ + /* + Here the extended class does whatever it needs to do. + If it cannot handle a message then it passes it on to the super + class for handling + */ + super.onReceiveCommand(message); + } + + @Override public void onReceiveRecover(Object message) { + super.onReceiveRecover(message); + } + +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ElectionTerm.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ElectionTerm.java new file mode 100644 index 0000000000..2cf39b59f1 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ElectionTerm.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014 Cisco 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.raft; + +import java.util.concurrent.atomic.AtomicLong; + +/** + * ElectionTerm contains information about a RaftActors election term. + *

+ * This information includes the last known current term of the RaftActor + * and which peer was voted for by the RaftActor in that term + *

+ * This class ensures that election term information is persisted + */ +public interface ElectionTerm { + /** + * latest term server has seen (initialized to 0 + * on first boot, increases monotonically) + */ + AtomicLong getCurrentTerm(); + + /** + * candidateId that received vote in current + * term (or null if none) + */ + String getVotedFor(); + + /** + * Called when we need to update the current term either because we received + * a message from someone with a more uptodate term or because we just voted + * for someone + * + * @param currentTerm + * @param votedFor + */ + void update(AtomicLong currentTerm, String votedFor); +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ElectionTermImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ElectionTermImpl.java new file mode 100644 index 0000000000..e918f75273 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ElectionTermImpl.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 Cisco 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.raft; + +import java.util.concurrent.atomic.AtomicLong; + +public class ElectionTermImpl implements ElectionTerm{ + /** + * Identifier of the actor whose election term information this is + */ + private final String id; + + private AtomicLong currentTerm; + + private String votedFor; + + public ElectionTermImpl(String id) { + this.id = id; + + // TODO: Read currentTerm from some persistent state + currentTerm = new AtomicLong(0); + + // TODO: Read votedFor from some file + votedFor = ""; + } + + public AtomicLong getCurrentTerm() { + return currentTerm; + } + + public String getVotedFor() { + return votedFor; + } + + public void update(AtomicLong currentTerm, String votedFor){ + this.currentTerm = currentTerm; + this.votedFor = votedFor; + + // TODO : Write to some persistent state + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformation.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformation.java new file mode 100644 index 0000000000..5f185cbb9c --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformation.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014 Cisco 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.raft; + +import java.util.concurrent.atomic.AtomicLong; + +/** + * The state of the followers log as known by the Leader + */ +public interface FollowerLogInformation { + + /** + * Increment the value of the nextIndex + * @return + */ + public long incrNextIndex(); + + /** + * Increment the value of the matchIndex + * @return + */ + public long incrMatchIndex(); + + /** + * The identifier of the follower + * This could simply be the url of the remote actor + */ + public String getId(); + + /** + * for each server, index of the next log entry + * to send to that server (initialized to leader + * last log index + 1) + */ + public AtomicLong getNextIndex(); + + /** + * for each server, index of highest log entry + * known to be replicated on server + * (initialized to 0, increases monotonically) + */ + public AtomicLong getMatchIndex(); + + +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java new file mode 100644 index 0000000000..6aa76508fc --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014 Cisco 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.raft; + +import java.util.concurrent.atomic.AtomicLong; + +public class FollowerLogInformationImpl implements FollowerLogInformation{ + + private final String id; + + private final AtomicLong nextIndex; + + private final AtomicLong matchIndex; + + public FollowerLogInformationImpl(String id, AtomicLong nextIndex, + AtomicLong matchIndex) { + this.id = id; + this.nextIndex = nextIndex; + this.matchIndex = matchIndex; + } + + public long incrNextIndex(){ + return nextIndex.incrementAndGet(); + } + + public long incrMatchIndex(){ + return matchIndex.incrementAndGet(); + } + + public String getId() { + return id; + } + + public AtomicLong getNextIndex() { + return nextIndex; + } + + public AtomicLong getMatchIndex() { + return matchIndex; + } + +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java new file mode 100644 index 0000000000..6e8e8208fb --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014 Cisco 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.raft; + +import akka.persistence.UntypedEventsourcedProcessor; +import org.opendaylight.controller.cluster.raft.behaviors.Candidate; +import org.opendaylight.controller.cluster.raft.behaviors.Follower; +import org.opendaylight.controller.cluster.raft.behaviors.Leader; +import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior; + +import java.util.Collections; +import java.util.concurrent.atomic.AtomicLong; + +/** + * RaftActor encapsulates a state machine that needs to be kept synchronized + * in a cluster. It implements the RAFT algorithm as described in the paper + * + * In Search of an Understandable Consensus Algorithm + *

+ * RaftActor has 3 states and each state has a certain behavior associated + * with it. A Raft actor can behave as, + *

+ * + *

+ * A RaftActor MUST be a Leader in order to accept requests from clients to + * change the state of it's encapsulated state machine. Once a RaftActor becomes + * a Leader it is also responsible for ensuring that all followers ultimately + * have the same log and therefore the same state machine as itself. + * + *

+ * The current behavior of a RaftActor determines how election for leadership + * is initiated and how peer RaftActors react to request for votes. + * + *

+ * Each RaftActor also needs to know the current election term. It uses this + * information for a couple of things. One is to simply figure out who it + * voted for in the last election. Another is to figure out if the message + * it received to update it's state is stale. + * + *

+ * The RaftActor uses akka-persistence to store it's replicated log. + * Furthermore through it's behaviors a Raft Actor determines + * + *

+ * + * UntypeEventSourceProcessor + */ +public abstract class RaftActor extends UntypedEventsourcedProcessor { + + /** + * The current state determines the current behavior of a RaftActor + * A Raft Actor always starts off in the Follower State + */ + private RaftActorBehavior currentBehavior; + + /** + * This context should NOT be passed directly to any other actor it is + * only to be consumed by the RaftActorBehaviors + */ + private RaftActorContext context; + + public RaftActor(String id){ + context = new RaftActorContextImpl(this.getSelf(), + this.getContext(), + id, new ElectionTermImpl(id), + new AtomicLong(0), new AtomicLong(0), new ReplicatedLogImpl()); + currentBehavior = switchBehavior(RaftState.Follower); + } + + @Override public void onReceiveRecover(Object message) { + throw new UnsupportedOperationException("onReceiveRecover"); + } + + @Override public void onReceiveCommand(Object message) { + RaftState state = currentBehavior.handleMessage(getSender(), message); + currentBehavior = switchBehavior(state); + } + + private RaftActorBehavior switchBehavior(RaftState state){ + RaftActorBehavior behavior = null; + if(state == RaftState.Candidate){ + behavior = new Candidate(context, Collections.EMPTY_LIST); + } else if(state == RaftState.Follower){ + behavior = new Follower(context); + } else { + behavior = new Leader(context, Collections.EMPTY_LIST); + } + return behavior; + } + + private class ReplicatedLogImpl implements ReplicatedLog { + + @Override public ReplicatedLogEntry getReplicatedLogEntry(long index) { + throw new UnsupportedOperationException("getReplicatedLogEntry"); + } + + @Override public ReplicatedLogEntry last() { + throw new UnsupportedOperationException("last"); + } + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContext.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContext.java new file mode 100644 index 0000000000..a78b890950 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContext.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014 Cisco 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.raft; + +import akka.actor.ActorRef; +import akka.actor.ActorSelection; +import akka.actor.Props; + +import java.util.concurrent.atomic.AtomicLong; + +/** + * The RaftActorContext contains that portion of the RaftActors state that + * needs to be shared with it's behaviors. A RaftActorContext should NEVER be + * used in any actor context outside the RaftActor that constructed it. + */ +public interface RaftActorContext { + /** + * Create a new local actor + * @param props + * @return + */ + ActorRef actorOf(Props props); + + /** + * Create a actor selection + * @param path + * @return + */ + ActorSelection actorSelection(String path); + + /** + * Get the identifier for the RaftActor. This identifier represents the + * name of the actor whose common state is being shared. For example the + * id could be 'inventory' + * @return the identifier + */ + String getId(); + + /** + * A reference to the RaftActor itself. This could be used to send messages + * to the RaftActor + * @return + */ + ActorRef getActor(); + + /** + * Get the ElectionTerm information + * @return + */ + ElectionTerm getTermInformation(); + + /** + * index of highest log entry known to be + * committed (initialized to 0, increases + * monotonically) + * @return + */ + AtomicLong getCommitIndex(); + + /** + * index of highest log entry applied to state + * machine (initialized to 0, increases + * monotonically) + * @return + */ + AtomicLong getLastApplied(); + + /** + * + */ + ReplicatedLog getReplicatedLog(); +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContextImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContextImpl.java new file mode 100644 index 0000000000..9ec8dddf6a --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActorContextImpl.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014 Cisco 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.raft; + +import akka.actor.ActorRef; +import akka.actor.ActorSelection; +import akka.actor.Props; +import akka.actor.UntypedActorContext; + +import java.util.concurrent.atomic.AtomicLong; + +public class RaftActorContextImpl implements RaftActorContext{ + + private final ActorRef actor; + + private final UntypedActorContext context; + + private final String id; + + private final ElectionTerm termInformation; + + private final AtomicLong commitIndex; + + private final AtomicLong lastApplied; + + private final ReplicatedLog replicatedLog; + + public RaftActorContextImpl(ActorRef actor, UntypedActorContext context, + String id, + ElectionTerm termInformation, AtomicLong commitIndex, + AtomicLong lastApplied, ReplicatedLog replicatedLog) { + this.actor = actor; + this.context = context; + this.id = id; + this.termInformation = termInformation; + this.commitIndex = commitIndex; + this.lastApplied = lastApplied; + this.replicatedLog = replicatedLog; + } + + public ActorRef actorOf(Props props){ + return context.actorOf(props); + } + + public ActorSelection actorSelection(String path){ + return context.actorSelection(path); + } + + public String getId() { + return id; + } + + public ActorRef getActor() { + return actor; + } + + public ElectionTerm getTermInformation() { + return termInformation; + } + + public AtomicLong getCommitIndex() { + return commitIndex; + } + + public AtomicLong getLastApplied() { + return lastApplied; + } + + @Override public ReplicatedLog getReplicatedLog() { + return replicatedLog; + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftReplicator.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftReplicator.java new file mode 100644 index 0000000000..73deceeb31 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftReplicator.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2014 Cisco 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.raft; + +import akka.actor.ActorRef; +import akka.actor.ActorSelection; +import akka.actor.Cancellable; +import akka.actor.Props; +import akka.actor.UntypedActor; +import akka.japi.Creator; +import org.opendaylight.controller.cluster.raft.internal.messages.SendHeartBeat; +import scala.concurrent.duration.FiniteDuration; + +import java.util.concurrent.TimeUnit; + +/** + * A RaftReplicator is responsible for replicating messages to any one follower. + * Once it gets a message for replication it should keep trying to replicate it + * to the remote follower indefinitely. + *

+ * Any new messages that are sent to this actor while it is replicating a + * message may need to be stashed till the current message has been successfully + * replicated. When a message is successfully replicated the RaftReplicator + * needs to inform the RaftActor of it. + */ +public class RaftReplicator extends UntypedActor { + + /** + * The interval at which a heart beat message will be sent to the remote + * RaftActor + * + * Since this is set to 100 milliseconds the Election timeout should be + * at least 200 milliseconds + * + */ + private static final FiniteDuration HEART_BEAT_INTERVAL = + new FiniteDuration(100, TimeUnit.MILLISECONDS); + + /** + * The state of the follower as known to this replicator + */ + private final FollowerLogInformation followerLogInformation; + + /** + * The local RaftActor that created this replicator so that it could + * replicate messages to the follower + */ + private final ActorRef leader; + + + /** + * The remote RaftActor to whom the messages need to be replicated + */ + private ActorSelection follower; + + private Cancellable heartbeatCancel = null; + + public RaftReplicator(FollowerLogInformation followerLogInformation, + ActorRef leader) { + + this.followerLogInformation = followerLogInformation; + this.leader = leader; + this.follower = getContext().actorSelection(followerLogInformation.getId()); + + // Immediately schedule a heartbeat + // Upon election: send initial empty AppendEntries RPCs + // (heartbeat) to each server; repeat during idle periods to + // prevent election timeouts (§5.2) + scheduleHeartBeat(new FiniteDuration(0, TimeUnit.SECONDS)); + } + + private void scheduleHeartBeat(FiniteDuration interval) { + if(heartbeatCancel != null && ! heartbeatCancel.isCancelled()){ + heartbeatCancel.cancel(); + } + + // Schedule a heartbeat. When the scheduler triggers the replicator + // will let the RaftActor (leader) know that a new heartbeat needs to be sent + // Scheduling the heartbeat only once here because heartbeats do not + // need to be sent if there are other messages being sent to the remote + // actor. + heartbeatCancel = + getContext().system().scheduler().scheduleOnce(interval, + leader, new SendHeartBeat(), getContext().dispatcher(), getSelf()); + } + + + + @Override public void onReceive(Object message) throws Exception { + scheduleHeartBeat(HEART_BEAT_INTERVAL); + follower.forward(message, getContext()); + } + + public static Props props(final FollowerLogInformation followerLogInformation, + final ActorRef leader) { + return Props.create(new Creator() { + + @Override public RaftReplicator create() throws Exception { + return new RaftReplicator(followerLogInformation, leader); + } + }); + } +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftState.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftState.java new file mode 100644 index 0000000000..65114eb659 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftState.java @@ -0,0 +1,7 @@ +package org.opendaylight.controller.cluster.raft; + +public enum RaftState { + Candidate, + Follower, + Leader +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java new file mode 100644 index 0000000000..e2f4bdbeb6 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014 Cisco 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.raft; + +/** + * Represents the ReplicatedLog that needs to be kept in sync by the RaftActor + */ +public interface ReplicatedLog { + /** + * Get a replicated log entry at the specified index + * + * @param index + * @return + */ + ReplicatedLogEntry getReplicatedLogEntry(long index); + + + /** + * Get the last replicated log entry + * + * @return + */ + ReplicatedLogEntry last(); +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogEntry.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogEntry.java new file mode 100644 index 0000000000..3bbaa22838 --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLogEntry.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014 Cisco 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.raft; + +/** + * Represents one entry in the replicated log + */ +public interface ReplicatedLogEntry { + /** + * The data stored in that entry + * + * @return + */ + Object getData(); + + /** + * The term stored in that entry + * + * @return + */ + long getTerm(); + + /** + * The index of the entry + * + * @return + */ + long getIndex(); +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java new file mode 100644 index 0000000000..fde104223b --- /dev/null +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014 Cisco 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.raft.behaviors; + +import org.opendaylight.controller.cluster.raft.RaftActorContext; + +/** + * Abstract class that represents the behavior of a RaftActor + *

+ * All Servers: + *