2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.cluster.raft;
11 import com.google.common.base.Stopwatch;
12 import java.util.concurrent.TimeUnit;
14 public class FollowerLogInformationImpl implements FollowerLogInformation {
15 private final String id;
17 private final Stopwatch stopwatch = Stopwatch.createUnstarted();
19 private final RaftActorContext context;
21 private long nextIndex;
23 private long matchIndex;
25 private long lastReplicatedIndex = -1L;
27 private final Stopwatch lastReplicatedStopwatch = Stopwatch.createUnstarted();
29 private short payloadVersion = -1;
31 private FollowerState state = FollowerState.VOTING;
33 public FollowerLogInformationImpl(String id, long matchIndex, RaftActorContext context) {
35 this.nextIndex = context.getCommitIndex();
36 this.matchIndex = matchIndex;
37 this.context = context;
41 public long incrNextIndex() {
46 public long decrNextIndex() {
51 public boolean setNextIndex(long nextIndex) {
52 if(this.nextIndex != nextIndex) {
53 this.nextIndex = nextIndex;
61 public long incrMatchIndex(){
66 public boolean setMatchIndex(long matchIndex) {
67 if(this.matchIndex != matchIndex) {
68 this.matchIndex = matchIndex;
76 public String getId() {
81 public long getNextIndex() {
86 public long getMatchIndex() {
91 public boolean isFollowerActive() {
92 if(state == FollowerState.VOTING_NOT_INITIALIZED) {
96 long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS);
97 return (stopwatch.isRunning()) &&
98 (elapsed <= context.getConfigParams().getElectionTimeOutInterval().toMillis());
102 public void markFollowerActive() {
103 if (stopwatch.isRunning()) {
110 public void markFollowerInActive() {
111 if (stopwatch.isRunning()) {
117 public long timeSinceLastActivity() {
118 return stopwatch.elapsed(TimeUnit.MILLISECONDS);
122 public boolean okToReplicate() {
123 if(state == FollowerState.VOTING_NOT_INITIALIZED) {
127 // Return false if we are trying to send duplicate data before the heartbeat interval
128 if(getNextIndex() == lastReplicatedIndex){
129 if(lastReplicatedStopwatch.elapsed(TimeUnit.MILLISECONDS) < context.getConfigParams()
130 .getHeartBeatInterval().toMillis()){
135 resetLastReplicated();
139 private void resetLastReplicated(){
140 lastReplicatedIndex = getNextIndex();
141 if(lastReplicatedStopwatch.isRunning()){
142 lastReplicatedStopwatch.reset();
144 lastReplicatedStopwatch.start();
148 public short getPayloadVersion() {
149 return payloadVersion;
153 public void setPayloadVersion(short payloadVersion) {
154 this.payloadVersion = payloadVersion;
158 public boolean canParticipateInConsensus() {
159 return state == FollowerState.VOTING;
163 public void setFollowerState(FollowerState state) {
168 public FollowerState getFollowerState() {
173 public String toString() {
174 return "FollowerLogInformationImpl [id=" + id + ", nextIndex=" + nextIndex + ", matchIndex=" + matchIndex
175 + ", lastReplicatedIndex=" + lastReplicatedIndex + ", state=" + state + ", stopwatch="
176 + stopwatch.elapsed(TimeUnit.MILLISECONDS) + ", followerTimeoutMillis="
177 + context.getConfigParams().getElectionTimeOutInterval().toMillis() + "]";