Ayaka Koshibe
Committed by Madan Jampani

Create local storage for topic candidates mapping. This also includes:

 - using Optional in Leadership, and some commenting.
 - using MutableBooleans + compute()

    part of: Device Mastership store on top of LeadershipService
    Reference: ONOS-76

Conflicts:
	core/api/src/main/java/org/onosproject/cluster/LeadershipService.java
	core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DistributedLeadershipManager.java

Change-Id: I7f090abb123cf23bb5126a935a6e72be00f3e3ce
......@@ -85,7 +85,7 @@ public class LeaderCommand extends AbstractShellCommand {
}
private void displayCandidates(Map<String, Leadership> leaderBoard,
Map<String, List<NodeId>> candidates) {
Map<String, Leadership> candidates) {
print("--------------------------------------------------------------");
print(FMT_C, "Topic", "Leader", "Candidates");
print("--------------------------------------------------------------");
......@@ -94,13 +94,13 @@ public class LeaderCommand extends AbstractShellCommand {
.stream()
.sorted(leadershipComparator)
.forEach(l -> {
List<NodeId> list = candidates.get(l.topic());
List<NodeId> list = candidates.get(l.topic()).candidates();
print(FMT_C,
l.topic(),
l.leader(),
list.remove(0).toString());
list.get(0).toString());
// formatting hacks to get it into a table
list.forEach(n -> print(FMT_C, " ", " ", n));
list.subList(1, list.size()).forEach(n -> print(FMT_C, " ", " ", n));
print(FMT_C, " ", " ", " ");
});
print("--------------------------------------------------------------");
......@@ -139,7 +139,7 @@ public class LeaderCommand extends AbstractShellCommand {
print("%s", json(leaderBoard));
} else {
if (showCandidates) {
Map<String, List<NodeId>> candidates = leaderService.getCandidates();
Map<String, Leadership> candidates = leaderService.getCandidates();
displayCandidates(leaderBoard, candidates);
} else {
displayLeaders(leaderBoard);
......
......@@ -17,6 +17,7 @@ package org.onosproject.cluster;
import java.util.Objects;
import java.util.List;
import java.util.Optional;
import org.joda.time.DateTime;
......@@ -33,19 +34,21 @@ import com.google.common.collect.ImmutableList;
* rest in decreasing preference order.</li>
* <li>The epoch is the logical age of a Leadership construct, and should be
* used for comparing two Leaderships, but only of the same topic.</li>
* <li>The leader may be null if its accuracy can't be guaranteed. This applies
* to CANDIDATES_CHANGED events and candidate board contents.</li>
* </ul>
*/
public class Leadership {
private final String topic;
private final NodeId leader;
private final Optional<NodeId> leader;
private final List<NodeId> candidates;
private final long epoch;
private final long electedTime;
public Leadership(String topic, NodeId leader, long epoch, long electedTime) {
this.topic = topic;
this.leader = leader;
this.leader = Optional.of(leader);
this.candidates = ImmutableList.of(leader);
this.epoch = epoch;
this.electedTime = electedTime;
......@@ -54,7 +57,16 @@ public class Leadership {
public Leadership(String topic, NodeId leader, List<NodeId> candidates,
long epoch, long electedTime) {
this.topic = topic;
this.leader = leader;
this.leader = Optional.of(leader);
this.candidates = ImmutableList.copyOf(candidates);
this.epoch = epoch;
this.electedTime = electedTime;
}
public Leadership(String topic, List<NodeId> candidates,
long epoch, long electedTime) {
this.topic = topic;
this.leader = Optional.empty();
this.candidates = ImmutableList.copyOf(candidates);
this.epoch = epoch;
this.electedTime = electedTime;
......@@ -74,8 +86,9 @@ public class Leadership {
*
* @return leader node.
*/
// This will return Optional<NodeId> in the future.
public NodeId leader() {
return leader;
return leader.orElse(null);
}
/**
......
......@@ -43,14 +43,14 @@ public class LeadershipEvent extends AbstractEvent<LeadershipEvent.Type, Leaders
LEADER_REELECTED,
/**
* Signifies that the leader has been booted and lost leadership. The event subject is the
* former leader.
* Signifies that the leader has been booted and lost leadership. The
* event subject is the former leader.
*/
LEADER_BOOTED,
/**
* Signifies that the list of candidates for leadership for a topic has
* changed.
* changed. This event does not guarantee accurate leader information.
*/
CANDIDATES_CHANGED
}
......
......@@ -76,9 +76,9 @@ public interface LeadershipService {
/**
* Returns the candidates for all known topics.
*
* @return A map of topics to lists of NodeIds.
* @return A mapping from topics to up-to-date candidate info.
*/
Map<String, List<NodeId>> getCandidates();
Map<String, Leadership> getCandidates();
/**
* Returns the candidates for a given topic.
......
......@@ -65,7 +65,7 @@ public class LeadershipServiceAdapter implements LeadershipService {
}
@Override
public Map<String, List<NodeId>> getCandidates() {
public Map<String, Leadership> getCandidates() {
return null;
}
......
......@@ -576,7 +576,7 @@ public class HazelcastLeadershipService implements LeadershipService {
}
@Override
public Map<String, List<NodeId>> getCandidates() {
public Map<String, Leadership> getCandidates() {
return null;
}
......
......@@ -111,7 +111,7 @@ public class SimpleLeadershipManager implements LeadershipService {
}
@Override
public Map<String, List<NodeId>> getCandidates() {
public Map<String, Leadership> getCandidates() {
return null;
}
......