Merge "Avoid IllegalArgument on missing source"
[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.Stopwatch;
12 import java.util.concurrent.TimeUnit;
13
14 public class FollowerLogInformationImpl implements FollowerLogInformation {
15     private final String id;
16
17     private final Stopwatch stopwatch = Stopwatch.createUnstarted();
18
19     private final RaftActorContext context;
20
21     private long nextIndex;
22
23     private long matchIndex;
24
25     private long lastReplicatedIndex = -1L;
26
27     private final Stopwatch lastReplicatedStopwatch = Stopwatch.createUnstarted();
28
29
30     public FollowerLogInformationImpl(String id, long matchIndex, RaftActorContext context) {
31         this.id = id;
32         this.nextIndex = context.getCommitIndex();
33         this.matchIndex = matchIndex;
34         this.context = context;
35     }
36
37     @Override
38     public long incrNextIndex() {
39         return nextIndex++;
40     }
41
42     @Override
43     public long decrNextIndex() {
44         return nextIndex--;
45     }
46
47     @Override
48     public boolean setNextIndex(long nextIndex) {
49         if(this.nextIndex != nextIndex) {
50             this.nextIndex = nextIndex;
51             return true;
52         }
53
54         return false;
55     }
56
57     @Override
58     public long incrMatchIndex(){
59         return matchIndex++;
60     }
61
62     @Override
63     public boolean setMatchIndex(long matchIndex) {
64         if(this.matchIndex != matchIndex) {
65             this.matchIndex = matchIndex;
66             return true;
67         }
68
69         return false;
70     }
71
72     @Override
73     public String getId() {
74         return id;
75     }
76
77     @Override
78     public long getNextIndex() {
79         return nextIndex;
80     }
81
82     @Override
83     public long getMatchIndex() {
84         return matchIndex;
85     }
86
87     @Override
88     public boolean isFollowerActive() {
89         long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS);
90         return (stopwatch.isRunning()) &&
91                 (elapsed <= context.getConfigParams().getElectionTimeOutInterval().toMillis());
92     }
93
94     @Override
95     public void markFollowerActive() {
96         if (stopwatch.isRunning()) {
97             stopwatch.reset();
98         }
99         stopwatch.start();
100     }
101
102     @Override
103     public void markFollowerInActive() {
104         if (stopwatch.isRunning()) {
105             stopwatch.stop();
106         }
107     }
108
109     @Override
110     public long timeSinceLastActivity() {
111         return stopwatch.elapsed(TimeUnit.MILLISECONDS);
112     }
113
114     @Override
115     public boolean okToReplicate() {
116         // Return false if we are trying to send duplicate data before the heartbeat interval
117         if(getNextIndex() == lastReplicatedIndex){
118             if(lastReplicatedStopwatch.elapsed(TimeUnit.MILLISECONDS) < context.getConfigParams()
119                     .getHeartBeatInterval().toMillis()){
120                 return false;
121             }
122         }
123
124         resetLastReplicated();
125         return true;
126     }
127
128     private void resetLastReplicated(){
129         lastReplicatedIndex = getNextIndex();
130         if(lastReplicatedStopwatch.isRunning()){
131             lastReplicatedStopwatch.reset();
132         }
133         lastReplicatedStopwatch.start();
134     }
135
136     @Override
137     public String toString() {
138         StringBuilder builder = new StringBuilder();
139         builder.append("FollowerLogInformationImpl [id=").append(id).append(", nextIndex=").append(nextIndex)
140                 .append(", matchIndex=").append(matchIndex).append(", stopwatch=")
141                 .append(stopwatch.elapsed(TimeUnit.MILLISECONDS))
142                 .append(", followerTimeoutMillis=")
143                 .append(context.getConfigParams().getElectionTimeOutInterval().toMillis()).append("]");
144         return builder.toString();
145     }
146 }