Add RaftActorServerConfigurationSupport.raftActor
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / main / java / org / opendaylight / controller / cluster / raft / FollowerLogInformationImpl.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.controller.cluster.raft;
10
11 import com.google.common.base.Preconditions;
12 import com.google.common.base.Stopwatch;
13 import java.util.concurrent.TimeUnit;
14
15 public class FollowerLogInformationImpl implements FollowerLogInformation {
16     private final Stopwatch stopwatch = Stopwatch.createUnstarted();
17
18     private final RaftActorContext context;
19
20     private long nextIndex;
21
22     private long matchIndex;
23
24     private long lastReplicatedIndex = -1L;
25
26     private final Stopwatch lastReplicatedStopwatch = Stopwatch.createUnstarted();
27
28     private short payloadVersion = -1;
29
30     private final PeerInfo peerInfo;
31
32     public FollowerLogInformationImpl(PeerInfo peerInfo, long matchIndex, RaftActorContext context) {
33         this.nextIndex = context.getCommitIndex();
34         this.matchIndex = matchIndex;
35         this.context = context;
36         this.peerInfo = Preconditions.checkNotNull(peerInfo);
37     }
38
39     @Override
40     public long incrNextIndex() {
41         return nextIndex++;
42     }
43
44     @Override
45     public long decrNextIndex() {
46         return nextIndex--;
47     }
48
49     @Override
50     public boolean setNextIndex(long nextIndex) {
51         if(this.nextIndex != nextIndex) {
52             this.nextIndex = nextIndex;
53             return true;
54         }
55
56         return false;
57     }
58
59     @Override
60     public long incrMatchIndex(){
61         return matchIndex++;
62     }
63
64     @Override
65     public boolean setMatchIndex(long matchIndex) {
66         if(this.matchIndex != matchIndex) {
67             this.matchIndex = matchIndex;
68             return true;
69         }
70
71         return false;
72     }
73
74     @Override
75     public String getId() {
76         return peerInfo.getId();
77     }
78
79     @Override
80     public long getNextIndex() {
81         return nextIndex;
82     }
83
84     @Override
85     public long getMatchIndex() {
86         return matchIndex;
87     }
88
89     @Override
90     public boolean isFollowerActive() {
91         if(peerInfo.getVotingState() == VotingState.VOTING_NOT_INITIALIZED) {
92             return false;
93         }
94
95         long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS);
96         return (stopwatch.isRunning()) &&
97                 (elapsed <= context.getConfigParams().getElectionTimeOutInterval().toMillis());
98     }
99
100     @Override
101     public void markFollowerActive() {
102         if (stopwatch.isRunning()) {
103             stopwatch.reset();
104         }
105         stopwatch.start();
106     }
107
108     @Override
109     public void markFollowerInActive() {
110         if (stopwatch.isRunning()) {
111             stopwatch.stop();
112         }
113     }
114
115     @Override
116     public long timeSinceLastActivity() {
117         return stopwatch.elapsed(TimeUnit.MILLISECONDS);
118     }
119
120     @Override
121     public boolean okToReplicate() {
122         if(peerInfo.getVotingState() == VotingState.VOTING_NOT_INITIALIZED) {
123             return false;
124         }
125
126         // Return false if we are trying to send duplicate data before the heartbeat interval
127         if(getNextIndex() == lastReplicatedIndex){
128             if(lastReplicatedStopwatch.elapsed(TimeUnit.MILLISECONDS) < context.getConfigParams()
129                     .getHeartBeatInterval().toMillis()){
130                 return false;
131             }
132         }
133
134         resetLastReplicated();
135         return true;
136     }
137
138     private void resetLastReplicated(){
139         lastReplicatedIndex = getNextIndex();
140         if(lastReplicatedStopwatch.isRunning()){
141             lastReplicatedStopwatch.reset();
142         }
143         lastReplicatedStopwatch.start();
144     }
145
146     @Override
147     public short getPayloadVersion() {
148         return payloadVersion;
149     }
150
151     @Override
152     public void setPayloadVersion(short payloadVersion) {
153         this.payloadVersion = payloadVersion;
154     }
155
156     @Override
157     public String toString() {
158         return "FollowerLogInformationImpl [id=" + getId() + ", nextIndex=" + nextIndex + ", matchIndex=" + matchIndex
159                 + ", lastReplicatedIndex=" + lastReplicatedIndex + ", votingState=" + peerInfo.getVotingState()
160                 + ", stopwatch=" + stopwatch.elapsed(TimeUnit.MILLISECONDS) + ", followerTimeoutMillis="
161                 + context.getConfigParams().getElectionTimeOutInterval().toMillis() + "]";
162     }
163 }