Committed by
Yuta HIGUCHI
ConsistentDeviceMastership on top of LeadershipService, and leaders CLI command
modified to filter on topic. This does not support changing candidate ordering (yet). Refernce: ONOS-76 Change-Id: I028a6df0acbe3c4e4ff7c228f687f640e48e13be
Showing
3 changed files
with
28 additions
and
23 deletions
| ... | @@ -18,7 +18,9 @@ package org.onosproject.cli.net; | ... | @@ -18,7 +18,9 @@ package org.onosproject.cli.net; |
| 18 | import java.util.Comparator; | 18 | import java.util.Comparator; |
| 19 | import java.util.Map; | 19 | import java.util.Map; |
| 20 | import java.util.List; | 20 | import java.util.List; |
| 21 | +import java.util.regex.Pattern; | ||
| 21 | 22 | ||
| 23 | +import org.apache.karaf.shell.commands.Argument; | ||
| 22 | import org.apache.karaf.shell.commands.Command; | 24 | import org.apache.karaf.shell.commands.Command; |
| 23 | import org.apache.karaf.shell.commands.Option; | 25 | import org.apache.karaf.shell.commands.Option; |
| 24 | import org.onlab.util.Tools; | 26 | import org.onlab.util.Tools; |
| ... | @@ -40,6 +42,12 @@ public class LeaderCommand extends AbstractShellCommand { | ... | @@ -40,6 +42,12 @@ public class LeaderCommand extends AbstractShellCommand { |
| 40 | 42 | ||
| 41 | private static final String FMT = "%-20s | %-15s | %-6s | %-10s |"; | 43 | private static final String FMT = "%-20s | %-15s | %-6s | %-10s |"; |
| 42 | private static final String FMT_C = "%-20s | %-15s | %-19s |"; | 44 | private static final String FMT_C = "%-20s | %-15s | %-19s |"; |
| 45 | + private boolean allTopics; | ||
| 46 | + private Pattern pattern; | ||
| 47 | + | ||
| 48 | + @Argument(index = 0, name = "topic", description = "A leadership topic. Can be a regex", | ||
| 49 | + required = false, multiValued = false) | ||
| 50 | + String topicPattern = null; | ||
| 43 | 51 | ||
| 44 | @Option(name = "-c", aliases = "--candidates", | 52 | @Option(name = "-c", aliases = "--candidates", |
| 45 | description = "List candidate Nodes for each topic's leadership race", | 53 | description = "List candidate Nodes for each topic's leadership race", |
| ... | @@ -75,6 +83,7 @@ public class LeaderCommand extends AbstractShellCommand { | ... | @@ -75,6 +83,7 @@ public class LeaderCommand extends AbstractShellCommand { |
| 75 | 83 | ||
| 76 | leaderBoard.values() | 84 | leaderBoard.values() |
| 77 | .stream() | 85 | .stream() |
| 86 | + .filter(l -> allTopics || pattern.matcher(l.topic()).matches()) | ||
| 78 | .sorted(leadershipComparator) | 87 | .sorted(leadershipComparator) |
| 79 | .forEach(l -> print(FMT, | 88 | .forEach(l -> print(FMT, |
| 80 | l.topic(), | 89 | l.topic(), |
| ... | @@ -92,6 +101,7 @@ public class LeaderCommand extends AbstractShellCommand { | ... | @@ -92,6 +101,7 @@ public class LeaderCommand extends AbstractShellCommand { |
| 92 | leaderBoard | 101 | leaderBoard |
| 93 | .values() | 102 | .values() |
| 94 | .stream() | 103 | .stream() |
| 104 | + .filter(l -> allTopics || pattern.matcher(l.topic()).matches()) | ||
| 95 | .sorted(leadershipComparator) | 105 | .sorted(leadershipComparator) |
| 96 | .forEach(l -> { | 106 | .forEach(l -> { |
| 97 | List<NodeId> list = candidates.get(l.topic()).candidates(); | 107 | List<NodeId> list = candidates.get(l.topic()).candidates(); |
| ... | @@ -135,6 +145,13 @@ public class LeaderCommand extends AbstractShellCommand { | ... | @@ -135,6 +145,13 @@ public class LeaderCommand extends AbstractShellCommand { |
| 135 | LeadershipService leaderService = get(LeadershipService.class); | 145 | LeadershipService leaderService = get(LeadershipService.class); |
| 136 | Map<String, Leadership> leaderBoard = leaderService.getLeaderBoard(); | 146 | Map<String, Leadership> leaderBoard = leaderService.getLeaderBoard(); |
| 137 | 147 | ||
| 148 | + if (topicPattern == null) { | ||
| 149 | + allTopics = true; | ||
| 150 | + } else { | ||
| 151 | + allTopics = false; | ||
| 152 | + pattern = Pattern.compile(topicPattern); | ||
| 153 | + } | ||
| 154 | + | ||
| 138 | if (outputJson()) { | 155 | if (outputJson()) { |
| 139 | print("%s", json(leaderBoard)); | 156 | print("%s", json(leaderBoard)); |
| 140 | } else { | 157 | } else { | ... | ... |
| ... | @@ -362,8 +362,8 @@ public class DistributedLeadershipManager implements LeadershipService { | ... | @@ -362,8 +362,8 @@ public class DistributedLeadershipManager implements LeadershipService { |
| 362 | Leadership newInfo = new Leadership(path, candidates, epoch, electedTime); | 362 | Leadership newInfo = new Leadership(path, candidates, epoch, electedTime); |
| 363 | final MutableBoolean updated = new MutableBoolean(false); | 363 | final MutableBoolean updated = new MutableBoolean(false); |
| 364 | candidateBoard.compute(path, (k, current) -> { | 364 | candidateBoard.compute(path, (k, current) -> { |
| 365 | - if (current != null && current.epoch() == newInfo.epoch()) { | 365 | + if (current != null && current.epoch() <= newInfo.epoch()) { |
| 366 | - log.info("updating candidateboard with {}", newInfo); | 366 | + log.info("updating candidateboard with removal of {}", newInfo); |
| 367 | updated.setTrue(); | 367 | updated.setTrue(); |
| 368 | if (candidates.isEmpty()) { | 368 | if (candidates.isEmpty()) { |
| 369 | return null; | 369 | return null; |
| ... | @@ -452,7 +452,7 @@ public class DistributedLeadershipManager implements LeadershipService { | ... | @@ -452,7 +452,7 @@ public class DistributedLeadershipManager implements LeadershipService { |
| 452 | }); | 452 | }); |
| 453 | } else if (eventType.equals(LeadershipEvent.Type.LEADER_BOOTED)) { | 453 | } else if (eventType.equals(LeadershipEvent.Type.LEADER_BOOTED)) { |
| 454 | leaderBoard.compute(topic, (k, currentLeadership) -> { | 454 | leaderBoard.compute(topic, (k, currentLeadership) -> { |
| 455 | - if (currentLeadership == null || currentLeadership.epoch() < leadershipUpdate.epoch()) { | 455 | + if (currentLeadership == null || currentLeadership.epoch() == leadershipUpdate.epoch()) { |
| 456 | updateAccepted.setTrue(); | 456 | updateAccepted.setTrue(); |
| 457 | return null; | 457 | return null; |
| 458 | } | 458 | } |
| ... | @@ -462,6 +462,9 @@ public class DistributedLeadershipManager implements LeadershipService { | ... | @@ -462,6 +462,9 @@ public class DistributedLeadershipManager implements LeadershipService { |
| 462 | candidateBoard.compute(topic, (k, currentInfo) -> { | 462 | candidateBoard.compute(topic, (k, currentInfo) -> { |
| 463 | if (currentInfo == null || currentInfo.epoch() <= leadershipUpdate.epoch()) { | 463 | if (currentInfo == null || currentInfo.epoch() <= leadershipUpdate.epoch()) { |
| 464 | updateAccepted.setTrue(); | 464 | updateAccepted.setTrue(); |
| 465 | + if (leadershipUpdate.candidates().isEmpty()) { | ||
| 466 | + return null; | ||
| 467 | + } | ||
| 465 | return leadershipUpdate; | 468 | return leadershipUpdate; |
| 466 | } | 469 | } |
| 467 | return currentInfo; | 470 | return currentInfo; | ... | ... |
| ... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
| 16 | package org.onosproject.store.mastership.impl; | 16 | package org.onosproject.store.mastership.impl; |
| 17 | 17 | ||
| 18 | import static org.onlab.util.Tools.groupedThreads; | 18 | import static org.onlab.util.Tools.groupedThreads; |
| 19 | +import static org.onlab.util.Tools.futureGetOrElse; | ||
| 19 | import static org.onosproject.mastership.MastershipEvent.Type.BACKUPS_CHANGED; | 20 | import static org.onosproject.mastership.MastershipEvent.Type.BACKUPS_CHANGED; |
| 20 | import static org.onosproject.mastership.MastershipEvent.Type.MASTER_CHANGED; | 21 | import static org.onosproject.mastership.MastershipEvent.Type.MASTER_CHANGED; |
| 21 | import static org.slf4j.LoggerFactory.getLogger; | 22 | import static org.slf4j.LoggerFactory.getLogger; |
| ... | @@ -25,12 +26,8 @@ import java.io.IOException; | ... | @@ -25,12 +26,8 @@ import java.io.IOException; |
| 25 | import java.util.List; | 26 | import java.util.List; |
| 26 | import java.util.Map; | 27 | import java.util.Map; |
| 27 | import java.util.Set; | 28 | import java.util.Set; |
| 28 | -import java.util.concurrent.ExecutionException; | ||
| 29 | import java.util.concurrent.ExecutorService; | 29 | import java.util.concurrent.ExecutorService; |
| 30 | import java.util.concurrent.Executors; | 30 | import java.util.concurrent.Executors; |
| 31 | -import java.util.concurrent.Future; | ||
| 32 | -import java.util.concurrent.TimeUnit; | ||
| 33 | -import java.util.concurrent.TimeoutException; | ||
| 34 | import java.util.regex.Matcher; | 31 | import java.util.regex.Matcher; |
| 35 | import java.util.regex.Pattern; | 32 | import java.util.regex.Pattern; |
| 36 | import java.util.stream.Collectors; | 33 | import java.util.stream.Collectors; |
| ... | @@ -182,12 +179,12 @@ public class ConsistentDeviceMastershipStore | ... | @@ -182,12 +179,12 @@ public class ConsistentDeviceMastershipStore |
| 182 | return MastershipRole.NONE; | 179 | return MastershipRole.NONE; |
| 183 | } | 180 | } |
| 184 | } | 181 | } |
| 185 | - MastershipRole role = complete(clusterCommunicator.sendAndReceive( | 182 | + MastershipRole role = futureGetOrElse(clusterCommunicator.sendAndReceive( |
| 186 | deviceId, | 183 | deviceId, |
| 187 | ROLE_QUERY_SUBJECT, | 184 | ROLE_QUERY_SUBJECT, |
| 188 | SERIALIZER::encode, | 185 | SERIALIZER::encode, |
| 189 | SERIALIZER::decode, | 186 | SERIALIZER::decode, |
| 190 | - nodeId)); | 187 | + nodeId), null); |
| 191 | return role == null ? MastershipRole.NONE : role; | 188 | return role == null ? MastershipRole.NONE : role; |
| 192 | } | 189 | } |
| 193 | 190 | ||
| ... | @@ -270,12 +267,12 @@ public class ConsistentDeviceMastershipStore | ... | @@ -270,12 +267,12 @@ public class ConsistentDeviceMastershipStore |
| 270 | if (!nodeId.equals(localNodeId)) { | 267 | if (!nodeId.equals(localNodeId)) { |
| 271 | log.debug("Forwarding request to relinquish " | 268 | log.debug("Forwarding request to relinquish " |
| 272 | + "role for device {} to {}", deviceId, nodeId); | 269 | + "role for device {} to {}", deviceId, nodeId); |
| 273 | - return complete(clusterCommunicator.sendAndReceive( | 270 | + return futureGetOrElse(clusterCommunicator.sendAndReceive( |
| 274 | deviceId, | 271 | deviceId, |
| 275 | ROLE_RELINQUISH_SUBJECT, | 272 | ROLE_RELINQUISH_SUBJECT, |
| 276 | SERIALIZER::encode, | 273 | SERIALIZER::encode, |
| 277 | SERIALIZER::decode, | 274 | SERIALIZER::decode, |
| 278 | - nodeId)); | 275 | + nodeId), null); |
| 279 | } | 276 | } |
| 280 | 277 | ||
| 281 | // Check if this node is can be managed by this node. | 278 | // Check if this node is can be managed by this node. |
| ... | @@ -374,16 +371,4 @@ public class ConsistentDeviceMastershipStore | ... | @@ -374,16 +371,4 @@ public class ConsistentDeviceMastershipStore |
| 374 | return m.matches(); | 371 | return m.matches(); |
| 375 | } | 372 | } |
| 376 | 373 | ||
| 377 | - private <T> T complete(Future<byte[]> future) { | ||
| 378 | - try { | ||
| 379 | - return SERIALIZER.decode(future.get(PEER_REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS)); | ||
| 380 | - } catch (InterruptedException e) { | ||
| 381 | - Thread.currentThread().interrupt(); | ||
| 382 | - log.error("Interrupted while waiting for operation to complete.", e); | ||
| 383 | - return null; | ||
| 384 | - } catch (TimeoutException | ExecutionException e) { | ||
| 385 | - log.error("Failed remote operation", e); | ||
| 386 | - return null; | ||
| 387 | - } | ||
| 388 | - } | ||
| 389 | } | 374 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment