blob: d52db145f17ea405666bc956f4cf7fb7a2cc69a5 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Thomas Vachuskac97aa612015-06-23 16:00:18 -070016package org.onosproject.store.trivial;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070017
Madan Jampani7d2fab22015-03-18 17:21:57 -070018import static org.onosproject.mastership.MastershipEvent.Type.BACKUPS_CHANGED;
19import static org.onosproject.mastership.MastershipEvent.Type.MASTER_CHANGED;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070020import static org.slf4j.LoggerFactory.getLogger;
21
Yuta HIGUCHI0c47d532017-08-18 23:16:35 -070022import java.time.Instant;
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070023import java.util.ArrayList;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070024import java.util.Collections;
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -070025import java.util.HashMap;
Ayaka Koshibe406d0102014-09-24 16:08:12 -070026import java.util.HashSet;
Ayaka Koshibe45503ce2014-10-14 11:26:45 -070027import java.util.List;
Ayaka Koshibe406d0102014-09-24 16:08:12 -070028import java.util.Map;
Thomas Vachuskaa68be812014-11-27 11:49:54 -080029import java.util.Objects;
Jordan Halterman0a2bd452018-06-13 17:24:58 -070030import java.util.Optional;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070031import java.util.Set;
Madan Jampanif7536ab2015-05-07 23:23:23 -070032import java.util.concurrent.CompletableFuture;
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -070033import java.util.concurrent.atomic.AtomicInteger;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070034
Jordan Halterman0a2bd452018-06-13 17:24:58 -070035import com.google.common.collect.ImmutableMap;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070036import org.apache.felix.scr.annotations.Activate;
37import org.apache.felix.scr.annotations.Component;
38import org.apache.felix.scr.annotations.Deactivate;
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -080039import org.apache.felix.scr.annotations.Reference;
40import org.apache.felix.scr.annotations.ReferenceCardinality;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070041import org.apache.felix.scr.annotations.Service;
Madan Jampani7d2fab22015-03-18 17:21:57 -070042import org.onlab.packet.IpAddress;
Brian O'Connorabafb502014-12-02 22:26:20 -080043import org.onosproject.cluster.ClusterEventListener;
44import org.onosproject.cluster.ClusterService;
45import org.onosproject.cluster.ControllerNode;
46import org.onosproject.cluster.ControllerNode.State;
47import org.onosproject.cluster.DefaultControllerNode;
Jordan Halterman00e92da2018-05-22 23:05:52 -070048import org.onosproject.cluster.Node;
Brian O'Connorabafb502014-12-02 22:26:20 -080049import org.onosproject.cluster.NodeId;
50import org.onosproject.cluster.RoleInfo;
Jordan Haltermanf70bf462017-07-29 13:12:00 -070051import org.onosproject.core.Version;
52import org.onosproject.core.VersionService;
Brian O'Connorabafb502014-12-02 22:26:20 -080053import org.onosproject.mastership.MastershipEvent;
Jordan Halterman0a2bd452018-06-13 17:24:58 -070054import org.onosproject.mastership.MastershipInfo;
Brian O'Connorabafb502014-12-02 22:26:20 -080055import org.onosproject.mastership.MastershipStore;
56import org.onosproject.mastership.MastershipStoreDelegate;
57import org.onosproject.mastership.MastershipTerm;
58import org.onosproject.net.DeviceId;
59import org.onosproject.net.MastershipRole;
60import org.onosproject.store.AbstractStore;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070061import org.slf4j.Logger;
62
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -080063import com.google.common.collect.ImmutableList;
64import com.google.common.collect.ImmutableSet;
Ayaka Koshibefc981cf2014-10-21 12:44:17 -070065
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070066/**
67 * Manages inventory of controller mastership over devices using
Ayaka Koshibe406d0102014-09-24 16:08:12 -070068 * trivial, non-distributed in-memory structures implementation.
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070069 */
70@Component(immediate = true)
71@Service
tomf80c9722014-09-24 14:49:18 -070072public class SimpleMastershipStore
73 extends AbstractStore<MastershipEvent, MastershipStoreDelegate>
74 implements MastershipStore {
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070075
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070076 private final Logger log = getLogger(getClass());
77
Yuta HIGUCHIdfe6e3b2014-10-30 11:31:51 -070078 private static final int NOTHING = 0;
79 private static final int INIT = 1;
80
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -080081 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected ClusterService clusterService;
Ayaka Koshibe406d0102014-09-24 16:08:12 -070083
Jordan Haltermanf70bf462017-07-29 13:12:00 -070084 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 protected VersionService versionService;
86
Ayaka Koshibe406d0102014-09-24 16:08:12 -070087 //devices mapped to their masters, to emulate multiple nodes
Ayaka Koshibe3de43ca2014-09-26 16:40:23 -070088 protected final Map<DeviceId, NodeId> masterMap = new HashMap<>();
Ayaka Koshibe971a38a2014-09-30 11:56:23 -070089 //emulate backups with pile of nodes
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -080090 protected final Map<DeviceId, List<NodeId>> backups = new HashMap<>();
Ayaka Koshibed9f693e2014-09-29 18:04:54 -070091 //terms
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -070092 protected final Map<DeviceId, AtomicInteger> termMap = new HashMap<>();
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070093
94 @Activate
95 public void activate() {
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -080096 if (clusterService == null) {
97 // just for ease of unit test
98 final ControllerNode instance =
99 new DefaultControllerNode(new NodeId("local"),
100 IpAddress.valueOf("127.0.0.1"));
101
102 clusterService = new ClusterService() {
103
Yuta HIGUCHI0c47d532017-08-18 23:16:35 -0700104 private final Instant creationTime = Instant.now();
Madan Jampani7d2fab22015-03-18 17:21:57 -0700105
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800106 @Override
107 public ControllerNode getLocalNode() {
108 return instance;
109 }
110
111 @Override
112 public Set<ControllerNode> getNodes() {
113 return ImmutableSet.of(instance);
114 }
115
116 @Override
Jordan Halterman00e92da2018-05-22 23:05:52 -0700117 public Set<Node> getConsensusNodes() {
118 return ImmutableSet.of();
119 }
120
121 @Override
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800122 public ControllerNode getNode(NodeId nodeId) {
123 if (instance.id().equals(nodeId)) {
124 return instance;
125 }
126 return null;
127 }
128
129 @Override
130 public State getState(NodeId nodeId) {
131 if (instance.id().equals(nodeId)) {
132 return State.ACTIVE;
133 } else {
134 return State.INACTIVE;
135 }
136 }
137
138 @Override
Jordan Haltermanf70bf462017-07-29 13:12:00 -0700139 public Version getVersion(NodeId nodeId) {
140 if (instance.id().equals(nodeId)) {
141 return versionService.version();
142 }
143 return null;
144 }
145
146 @Override
Yuta HIGUCHI0c47d532017-08-18 23:16:35 -0700147 public Instant getLastUpdatedInstant(NodeId nodeId) {
Madan Jampani7d2fab22015-03-18 17:21:57 -0700148 return creationTime;
149 }
150
151 @Override
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800152 public void addListener(ClusterEventListener listener) {
153 }
154
155 @Override
156 public void removeListener(ClusterEventListener listener) {
157 }
158 };
159 }
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700160 log.info("Started");
161 }
162
163 @Deactivate
164 public void deactivate() {
165 log.info("Stopped");
166 }
167
168 @Override
Madan Jampanif7536ab2015-05-07 23:23:23 -0700169 public synchronized CompletableFuture<MastershipEvent> setMaster(NodeId nodeId, DeviceId deviceId) {
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700170
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800171 MastershipRole role = getRole(nodeId, deviceId);
172 switch (role) {
173 case MASTER:
174 // no-op
Madan Jampanif7536ab2015-05-07 23:23:23 -0700175 return CompletableFuture.completedFuture(null);
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800176 case STANDBY:
177 case NONE:
178 NodeId prevMaster = masterMap.put(deviceId, nodeId);
179 incrementTerm(deviceId);
180 removeFromBackups(deviceId, nodeId);
181 addToBackup(deviceId, prevMaster);
182 break;
183 default:
184 log.warn("unknown Mastership Role {}", role);
185 return null;
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700186 }
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700187
Madan Jampanif7536ab2015-05-07 23:23:23 -0700188 return CompletableFuture.completedFuture(
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700189 new MastershipEvent(MASTER_CHANGED, deviceId, getMastership(deviceId)));
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700190 }
191
192 @Override
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700193 public NodeId getMaster(DeviceId deviceId) {
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700194 return masterMap.get(deviceId);
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700195 }
196
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800197 // synchronized for atomic read
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700198 @Override
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800199 public synchronized RoleInfo getNodes(DeviceId deviceId) {
200 return new RoleInfo(masterMap.get(deviceId),
201 backups.getOrDefault(deviceId, ImmutableList.of()));
Ayaka Koshibe45503ce2014-10-14 11:26:45 -0700202 }
203
204 @Override
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700205 public Set<DeviceId> getDevices(NodeId nodeId) {
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700206 Set<DeviceId> ids = new HashSet<>();
207 for (Map.Entry<DeviceId, NodeId> d : masterMap.entrySet()) {
Thomas Vachuskaa68be812014-11-27 11:49:54 -0800208 if (Objects.equals(d.getValue(), nodeId)) {
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700209 ids.add(d.getKey());
210 }
211 }
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800212 return ids;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700213 }
214
215 @Override
Madan Jampanide003d92015-05-11 17:14:20 -0700216 public synchronized CompletableFuture<MastershipRole> requestRole(DeviceId deviceId) {
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700217 //query+possible reelection
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800218 NodeId node = clusterService.getLocalNode().id();
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700219 MastershipRole role = getRole(node, deviceId);
220
221 switch (role) {
222 case MASTER:
Madan Jampanide003d92015-05-11 17:14:20 -0700223 return CompletableFuture.completedFuture(MastershipRole.MASTER);
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700224 case STANDBY:
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800225 if (getMaster(deviceId) == null) {
226 // no master => become master
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700227 masterMap.put(deviceId, node);
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800228 incrementTerm(deviceId);
229 // remove from backup list
230 removeFromBackups(deviceId, node);
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700231 notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, getMastership(deviceId)));
Madan Jampanide003d92015-05-11 17:14:20 -0700232 return CompletableFuture.completedFuture(MastershipRole.MASTER);
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700233 }
Madan Jampanide003d92015-05-11 17:14:20 -0700234 return CompletableFuture.completedFuture(MastershipRole.STANDBY);
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800235 case NONE:
236 if (getMaster(deviceId) == null) {
237 // no master => become master
238 masterMap.put(deviceId, node);
239 incrementTerm(deviceId);
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700240 notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, getMastership(deviceId)));
Madan Jampanide003d92015-05-11 17:14:20 -0700241 return CompletableFuture.completedFuture(MastershipRole.MASTER);
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800242 }
243 // add to backup list
244 if (addToBackup(deviceId, node)) {
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700245 notifyDelegate(new MastershipEvent(BACKUPS_CHANGED, deviceId, getMastership(deviceId)));
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800246 }
Madan Jampanide003d92015-05-11 17:14:20 -0700247 return CompletableFuture.completedFuture(MastershipRole.STANDBY);
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700248 default:
249 log.warn("unknown Mastership Role {}", role);
250 }
Madan Jampanide003d92015-05-11 17:14:20 -0700251 return CompletableFuture.completedFuture(role);
tomb41d1ac2014-09-24 01:51:24 -0700252 }
253
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800254 // add to backup if not there already, silently ignores null node
255 private synchronized boolean addToBackup(DeviceId deviceId, NodeId nodeId) {
256 boolean modified = false;
257 List<NodeId> stbys = backups.getOrDefault(deviceId, new ArrayList<>());
258 if (nodeId != null && !stbys.contains(nodeId)) {
259 stbys.add(nodeId);
260 modified = true;
261 }
262 backups.put(deviceId, stbys);
263 return modified;
264 }
265
266 private synchronized boolean removeFromBackups(DeviceId deviceId, NodeId node) {
267 List<NodeId> stbys = backups.getOrDefault(deviceId, new ArrayList<>());
268 boolean modified = stbys.remove(node);
269 backups.put(deviceId, stbys);
270 return modified;
271 }
272
273 private synchronized void incrementTerm(DeviceId deviceId) {
274 AtomicInteger term = termMap.getOrDefault(deviceId, new AtomicInteger(NOTHING));
275 term.incrementAndGet();
276 termMap.put(deviceId, term);
277 }
278
tomb41d1ac2014-09-24 01:51:24 -0700279 @Override
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700280 public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) {
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700281 //just query
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700282 NodeId current = masterMap.get(deviceId);
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700283 MastershipRole role;
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700284
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800285 if (current != null && current.equals(nodeId)) {
286 return MastershipRole.MASTER;
287 }
288
289 if (backups.getOrDefault(deviceId, Collections.emptyList()).contains(nodeId)) {
290 role = MastershipRole.STANDBY;
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700291 } else {
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800292 role = MastershipRole.NONE;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700293 }
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700294 return role;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700295 }
296
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800297 // synchronized for atomic read
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -0700298 @Override
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800299 public synchronized MastershipTerm getTermFor(DeviceId deviceId) {
Yuta HIGUCHIdfe6e3b2014-10-30 11:31:51 -0700300 if ((termMap.get(deviceId) == null)) {
301 return MastershipTerm.of(masterMap.get(deviceId), NOTHING);
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -0700302 }
303 return MastershipTerm.of(
304 masterMap.get(deviceId), termMap.get(deviceId).get());
305 }
306
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700307 @Override
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700308 public MastershipInfo getMastership(DeviceId deviceId) {
309 ImmutableMap.Builder<NodeId, MastershipRole> roleBuilder = ImmutableMap.builder();
310 NodeId master = masterMap.get(deviceId);
311 if (master != null) {
312 roleBuilder.put(master, MastershipRole.MASTER);
313 }
314 backups.getOrDefault(deviceId, Collections.emptyList())
315 .forEach(nodeId -> roleBuilder.put(nodeId, MastershipRole.STANDBY));
316 return new MastershipInfo(
317 termMap.getOrDefault(deviceId, new AtomicInteger(NOTHING)).get(),
318 Optional.ofNullable(master),
319 roleBuilder.build());
320 }
321
322 @Override
Madan Jampanif7536ab2015-05-07 23:23:23 -0700323 public synchronized CompletableFuture<MastershipEvent> setStandby(NodeId nodeId, DeviceId deviceId) {
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700324 MastershipRole role = getRole(nodeId, deviceId);
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800325 switch (role) {
326 case MASTER:
327 NodeId backup = reelect(deviceId, nodeId);
328 if (backup == null) {
329 // no master alternative
330 masterMap.remove(deviceId);
331 // TODO: Should there be new event type for no MASTER?
Madan Jampanif7536ab2015-05-07 23:23:23 -0700332 return CompletableFuture.completedFuture(
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700333 new MastershipEvent(MASTER_CHANGED, deviceId, getMastership(deviceId)));
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800334 } else {
335 NodeId prevMaster = masterMap.put(deviceId, backup);
336 incrementTerm(deviceId);
337 addToBackup(deviceId, prevMaster);
Madan Jampanif7536ab2015-05-07 23:23:23 -0700338 return CompletableFuture.completedFuture(
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700339 new MastershipEvent(MASTER_CHANGED, deviceId, getMastership(deviceId)));
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700340 }
Yuta HIGUCHI1b3f4db2014-11-18 11:04:31 -0800341
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800342 case STANDBY:
343 case NONE:
344 boolean modified = addToBackup(deviceId, nodeId);
345 if (modified) {
Madan Jampanif7536ab2015-05-07 23:23:23 -0700346 return CompletableFuture.completedFuture(
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700347 new MastershipEvent(BACKUPS_CHANGED, deviceId, getMastership(deviceId)));
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800348 }
Yuta HIGUCHI1b3f4db2014-11-18 11:04:31 -0800349 break;
350
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800351 default:
352 log.warn("unknown Mastership Role {}", role);
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700353 }
354 return null;
355 }
356
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700357 //dumbly selects next-available node that's not the current one
358 //emulate leader election
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800359 private synchronized NodeId reelect(DeviceId did, NodeId nodeId) {
360 List<NodeId> stbys = backups.getOrDefault(did, Collections.emptyList());
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700361 NodeId backup = null;
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800362 for (NodeId n : stbys) {
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700363 if (!n.equals(nodeId)) {
364 backup = n;
365 break;
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700366 }
367 }
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800368 stbys.remove(backup);
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700369 return backup;
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700370 }
371
Ayaka Koshibec4047702014-10-07 14:43:52 -0700372 @Override
Madan Jampanif7536ab2015-05-07 23:23:23 -0700373 public synchronized CompletableFuture<MastershipEvent> relinquishRole(NodeId nodeId, DeviceId deviceId) {
Ayaka Koshibeb62aab52014-10-24 13:15:25 -0700374 MastershipRole role = getRole(nodeId, deviceId);
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800375 switch (role) {
376 case MASTER:
377 NodeId backup = reelect(deviceId, nodeId);
378 masterMap.put(deviceId, backup);
379 incrementTerm(deviceId);
Madan Jampanif7536ab2015-05-07 23:23:23 -0700380 return CompletableFuture.completedFuture(
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700381 new MastershipEvent(MASTER_CHANGED, deviceId, getMastership(deviceId)));
Yuta HIGUCHI1b3f4db2014-11-18 11:04:31 -0800382
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800383 case STANDBY:
384 if (removeFromBackups(deviceId, nodeId)) {
Madan Jampanif7536ab2015-05-07 23:23:23 -0700385 return CompletableFuture.completedFuture(
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700386 new MastershipEvent(BACKUPS_CHANGED, deviceId, getMastership(deviceId)));
Ayaka Koshibeb62aab52014-10-24 13:15:25 -0700387 }
Yuta HIGUCHI1b3f4db2014-11-18 11:04:31 -0800388 break;
389
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800390 case NONE:
Yuta HIGUCHI1b3f4db2014-11-18 11:04:31 -0800391 break;
392
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800393 default:
394 log.warn("unknown Mastership Role {}", role);
Ayaka Koshibeb62aab52014-10-24 13:15:25 -0700395 }
Madan Jampanif7536ab2015-05-07 23:23:23 -0700396 return CompletableFuture.completedFuture(null);
Ayaka Koshibec4047702014-10-07 14:43:52 -0700397 }
HIGUCHI Yuta59f02292015-02-25 19:51:48 -0800398
399 @Override
400 public synchronized void relinquishAllRole(NodeId nodeId) {
Madan Jampanif7536ab2015-05-07 23:23:23 -0700401 List<CompletableFuture<MastershipEvent>> eventFutures = new ArrayList<>();
HIGUCHI Yuta59f02292015-02-25 19:51:48 -0800402 Set<DeviceId> toRelinquish = new HashSet<>();
403
404 masterMap.entrySet().stream()
405 .filter(entry -> nodeId.equals(entry.getValue()))
406 .forEach(entry -> toRelinquish.add(entry.getKey()));
407
408 backups.entrySet().stream()
409 .filter(entry -> entry.getValue().contains(nodeId))
410 .forEach(entry -> toRelinquish.add(entry.getKey()));
411
Sho SHIMIZUfeafdca2015-09-11 15:02:21 -0700412 toRelinquish.forEach(deviceId -> eventFutures.add(relinquishRole(nodeId, deviceId)));
HIGUCHI Yuta59f02292015-02-25 19:51:48 -0800413
Madan Jampanif7536ab2015-05-07 23:23:23 -0700414 eventFutures.forEach(future -> {
Sho SHIMIZUfeafdca2015-09-11 15:02:21 -0700415 future.whenComplete((event, error) -> notifyDelegate(event));
Madan Jampanif7536ab2015-05-07 23:23:23 -0700416 });
HIGUCHI Yuta59f02292015-02-25 19:51:48 -0800417 }
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700418}