5525d75b7dcf3b6ec2d2ddcaca32f3b59d518d70
[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     private short payloadVersion = -1;
30
31     public FollowerLogInformationImpl(String id, long matchIndex, RaftActorContext context) {
32         this.id = id;
33         this.nextIndex = context.getCommitIndex();
34         this.matchIndex = matchIndex;
35         this.context = context;
36     }
37
38     @Override
39     public long incrNextIndex() {
40         return nextIndex++;
41     }
42
43     @Override
44     public long decrNextIndex() {
45         return nextIndex--;
46     }
47
48     @Override
49     public boolean setNextIndex(long nextIndex) {
50         if(this.nextIndex != nextIndex) {
51             this.nextIndex = nextIndex;
52             return true;
53         }
54
55         return false;
56     }
57
58     @Override
59     public long incrMatchIndex(){
60         return matchIndex++;
61     }
62
63     @Override
64     public boolean setMatchIndex(long matchIndex) {
65         if(this.matchIndex != matchIndex) {
66             this.matchIndex = matchIndex;
67             return true;
68         }
69
70         return false;
71     }
72
73     @Override
74     public String getId() {
75         return id;
76     }
77
78     @Override
79     public long getNextIndex() {
80         return nextIndex;
81     }
82
83     @Override
84     public long getMatchIndex() {
85         return matchIndex;
86     }
87
88     @Override
89     public boolean isFollowerActive() {
90         long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS);
91         return (stopwatch.isRunning()) &&
92                 (elapsed <= context.getConfigParams().getElectionTimeOutInterval().toMillis());
93     }
94
95     @Override
96     public void markFollowerActive() {
97         if (stopwatch.isRunning()) {
98             stopwatch.reset();
99         }
100         stopwatch.start();
101     }
102
103     @Override
104     public void markFollowerInActive() {
105         if (stopwatch.isRunning()) {
106             stopwatch.stop();
107         }
108     }
109
110     @Override
111     public long timeSinceLastActivity() {
112         return stopwatch.elapsed(TimeUnit.MILLISECONDS);
113     }
114
115     @Override
116     public boolean okToReplicate() {
117         // Return false if we are trying to send duplicate data before the heartbeat interval
118         if(getNextIndex() == lastReplicatedIndex){
119             if(lastReplicatedStopwatch.elapsed(TimeUnit.MILLISECONDS) < context.getConfigParams()
120                     .getHeartBeatInterval().toMillis()){
121                 return false;
122             }
123         }
124
125         resetLastReplicated();
126         return true;
127     }
128
129     private void resetLastReplicated(){
130         lastReplicatedIndex = getNextIndex();
131         if(lastReplicatedStopwatch.isRunning()){
132             lastReplicatedStopwatch.reset();
133         }
134         lastReplicatedStopwatch.start();
135     }
136
137     @Override
138     public String toString() {
139         StringBuilder builder = new StringBuilder();
140         builder.append("FollowerLogInformationImpl [id=").append(id).append(", nextIndex=").append(nextIndex)
141                 .append(", matchIndex=").append(matchIndex).append(", stopwatch=")
142                 .append(stopwatch.elapsed(TimeUnit.MILLISECONDS))
143                 .append(", followerTimeoutMillis=")
144                 .append(context.getConfigParams().getElectionTimeOutInterval().toMillis()).append("]");
145         return builder.toString();
146     }
147
148     @Override
149     public short getPayloadVersion() {
150         return payloadVersion;
151     }
152
153     @Override
154     public void setPayloadVersion(short payloadVersion) {
155         this.payloadVersion = payloadVersion;
156     }
157 }