blob: 4536ddae1d4e1224c1030e9521b50ec15bafdb90 [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
Ray Milkeyd84f89b2018-08-17 14:54:17 -070018import com.google.common.collect.ImmutableList;
Jordan Halterman0a2bd452018-06-13 17:24:58 -070019import com.google.common.collect.ImmutableMap;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070020import com.google.common.collect.ImmutableSet;
Madan Jampani7d2fab22015-03-18 17:21:57 -070021import org.onlab.packet.IpAddress;
Brian O'Connorabafb502014-12-02 22:26:20 -080022import org.onosproject.cluster.ClusterEventListener;
23import org.onosproject.cluster.ClusterService;
24import org.onosproject.cluster.ControllerNode;
25import org.onosproject.cluster.ControllerNode.State;
26import org.onosproject.cluster.DefaultControllerNode;
Jordan Halterman00e92da2018-05-22 23:05:52 -070027import org.onosproject.cluster.Node;
Brian O'Connorabafb502014-12-02 22:26:20 -080028import org.onosproject.cluster.NodeId;
29import org.onosproject.cluster.RoleInfo;
Jordan Haltermanf70bf462017-07-29 13:12:00 -070030import org.onosproject.core.Version;
31import org.onosproject.core.VersionService;
Brian O'Connorabafb502014-12-02 22:26:20 -080032import org.onosproject.mastership.MastershipEvent;
Jordan Halterman0a2bd452018-06-13 17:24:58 -070033import org.onosproject.mastership.MastershipInfo;
Brian O'Connorabafb502014-12-02 22:26:20 -080034import org.onosproject.mastership.MastershipStore;
35import org.onosproject.mastership.MastershipStoreDelegate;
36import org.onosproject.mastership.MastershipTerm;
37import org.onosproject.net.DeviceId;
38import org.onosproject.net.MastershipRole;
39import org.onosproject.store.AbstractStore;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070040import org.osgi.service.component.annotations.Activate;
41import org.osgi.service.component.annotations.Component;
42import org.osgi.service.component.annotations.Deactivate;
43import org.osgi.service.component.annotations.Reference;
44import org.osgi.service.component.annotations.ReferenceCardinality;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070045import org.slf4j.Logger;
46
Ray Milkeyd84f89b2018-08-17 14:54:17 -070047import java.time.Instant;
48import java.util.ArrayList;
49import java.util.Collections;
50import java.util.HashMap;
51import java.util.HashSet;
52import java.util.List;
53import java.util.Map;
54import java.util.Objects;
55import java.util.Optional;
56import java.util.Set;
57import java.util.concurrent.CompletableFuture;
58import java.util.concurrent.atomic.AtomicInteger;
59
60import static org.onosproject.mastership.MastershipEvent.Type.BACKUPS_CHANGED;
61import static org.onosproject.mastership.MastershipEvent.Type.MASTER_CHANGED;
62import static org.slf4j.LoggerFactory.getLogger;
Ayaka Koshibefc981cf2014-10-21 12:44:17 -070063
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070064/**
65 * Manages inventory of controller mastership over devices using
Ayaka Koshibe406d0102014-09-24 16:08:12 -070066 * trivial, non-distributed in-memory structures implementation.
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070067 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070068@Component(immediate = true, service = MastershipStore.class)
tomf80c9722014-09-24 14:49:18 -070069public class SimpleMastershipStore
70 extends AbstractStore<MastershipEvent, MastershipStoreDelegate>
71 implements MastershipStore {
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070072
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070073 private final Logger log = getLogger(getClass());
74
Yuta HIGUCHIdfe6e3b2014-10-30 11:31:51 -070075 private static final int NOTHING = 0;
76 private static final int INIT = 1;
77
Ray Milkeyd84f89b2018-08-17 14:54:17 -070078 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -080079 protected ClusterService clusterService;
Ayaka Koshibe406d0102014-09-24 16:08:12 -070080
Ray Milkeyd84f89b2018-08-17 14:54:17 -070081 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jordan Haltermanf70bf462017-07-29 13:12:00 -070082 protected VersionService versionService;
83
Ayaka Koshibe406d0102014-09-24 16:08:12 -070084 //devices mapped to their masters, to emulate multiple nodes
Ayaka Koshibe3de43ca2014-09-26 16:40:23 -070085 protected final Map<DeviceId, NodeId> masterMap = new HashMap<>();
Ayaka Koshibe971a38a2014-09-30 11:56:23 -070086 //emulate backups with pile of nodes
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -080087 protected final Map<DeviceId, List<NodeId>> backups = new HashMap<>();
Ayaka Koshibed9f693e2014-09-29 18:04:54 -070088 //terms
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -070089 protected final Map<DeviceId, AtomicInteger> termMap = new HashMap<>();
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070090
91 @Activate
92 public void activate() {
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -080093 if (clusterService == null) {
94 // just for ease of unit test
95 final ControllerNode instance =
96 new DefaultControllerNode(new NodeId("local"),
97 IpAddress.valueOf("127.0.0.1"));
98
99 clusterService = new ClusterService() {
100
Yuta HIGUCHI0c47d532017-08-18 23:16:35 -0700101 private final Instant creationTime = Instant.now();
Madan Jampani7d2fab22015-03-18 17:21:57 -0700102
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800103 @Override
104 public ControllerNode getLocalNode() {
105 return instance;
106 }
107
108 @Override
109 public Set<ControllerNode> getNodes() {
110 return ImmutableSet.of(instance);
111 }
112
113 @Override
Jordan Halterman00e92da2018-05-22 23:05:52 -0700114 public Set<Node> getConsensusNodes() {
115 return ImmutableSet.of();
116 }
117
118 @Override
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800119 public ControllerNode getNode(NodeId nodeId) {
120 if (instance.id().equals(nodeId)) {
121 return instance;
122 }
123 return null;
124 }
125
126 @Override
127 public State getState(NodeId nodeId) {
128 if (instance.id().equals(nodeId)) {
129 return State.ACTIVE;
130 } else {
131 return State.INACTIVE;
132 }
133 }
134
135 @Override
Jordan Haltermanf70bf462017-07-29 13:12:00 -0700136 public Version getVersion(NodeId nodeId) {
137 if (instance.id().equals(nodeId)) {
138 return versionService.version();
139 }
140 return null;
141 }
142
143 @Override
Yuta HIGUCHI0c47d532017-08-18 23:16:35 -0700144 public Instant getLastUpdatedInstant(NodeId nodeId) {
Madan Jampani7d2fab22015-03-18 17:21:57 -0700145 return creationTime;
146 }
147
148 @Override
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800149 public void addListener(ClusterEventListener listener) {
150 }
151
152 @Override
153 public void removeListener(ClusterEventListener listener) {
154 }
155 };
156 }
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700157 log.info("Started");
158 }
159
160 @Deactivate
161 public void deactivate() {
162 log.info("Stopped");
163 }
164
165 @Override
Madan Jampanif7536ab2015-05-07 23:23:23 -0700166 public synchronized CompletableFuture<MastershipEvent> setMaster(NodeId nodeId, DeviceId deviceId) {
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700167
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800168 MastershipRole role = getRole(nodeId, deviceId);
169 switch (role) {
170 case MASTER:
171 // no-op
Madan Jampanif7536ab2015-05-07 23:23:23 -0700172 return CompletableFuture.completedFuture(null);
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800173 case STANDBY:
174 case NONE:
175 NodeId prevMaster = masterMap.put(deviceId, nodeId);
176 incrementTerm(deviceId);
177 removeFromBackups(deviceId, nodeId);
178 addToBackup(deviceId, prevMaster);
179 break;
180 default:
181 log.warn("unknown Mastership Role {}", role);
182 return null;
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700183 }
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700184
Madan Jampanif7536ab2015-05-07 23:23:23 -0700185 return CompletableFuture.completedFuture(
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700186 new MastershipEvent(MASTER_CHANGED, deviceId, getMastership(deviceId)));
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700187 }
188
189 @Override
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700190 public NodeId getMaster(DeviceId deviceId) {
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700191 return masterMap.get(deviceId);
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700192 }
193
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800194 // synchronized for atomic read
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700195 @Override
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800196 public synchronized RoleInfo getNodes(DeviceId deviceId) {
197 return new RoleInfo(masterMap.get(deviceId),
198 backups.getOrDefault(deviceId, ImmutableList.of()));
Ayaka Koshibe45503ce2014-10-14 11:26:45 -0700199 }
200
201 @Override
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700202 public Set<DeviceId> getDevices(NodeId nodeId) {
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700203 Set<DeviceId> ids = new HashSet<>();
204 for (Map.Entry<DeviceId, NodeId> d : masterMap.entrySet()) {
Thomas Vachuskaa68be812014-11-27 11:49:54 -0800205 if (Objects.equals(d.getValue(), nodeId)) {
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700206 ids.add(d.getKey());
207 }
208 }
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800209 return ids;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700210 }
211
212 @Override
Madan Jampanide003d92015-05-11 17:14:20 -0700213 public synchronized CompletableFuture<MastershipRole> requestRole(DeviceId deviceId) {
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700214 //query+possible reelection
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800215 NodeId node = clusterService.getLocalNode().id();
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700216 MastershipRole role = getRole(node, deviceId);
217
218 switch (role) {
219 case MASTER:
Madan Jampanide003d92015-05-11 17:14:20 -0700220 return CompletableFuture.completedFuture(MastershipRole.MASTER);
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700221 case STANDBY:
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800222 if (getMaster(deviceId) == null) {
223 // no master => become master
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700224 masterMap.put(deviceId, node);
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800225 incrementTerm(deviceId);
226 // remove from backup list
227 removeFromBackups(deviceId, node);
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700228 notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, getMastership(deviceId)));
Madan Jampanide003d92015-05-11 17:14:20 -0700229 return CompletableFuture.completedFuture(MastershipRole.MASTER);
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700230 }
Madan Jampanide003d92015-05-11 17:14:20 -0700231 return CompletableFuture.completedFuture(MastershipRole.STANDBY);
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800232 case NONE:
233 if (getMaster(deviceId) == null) {
234 // no master => become master
235 masterMap.put(deviceId, node);
236 incrementTerm(deviceId);
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700237 notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, getMastership(deviceId)));
Madan Jampanide003d92015-05-11 17:14:20 -0700238 return CompletableFuture.completedFuture(MastershipRole.MASTER);
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800239 }
240 // add to backup list
241 if (addToBackup(deviceId, node)) {
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700242 notifyDelegate(new MastershipEvent(BACKUPS_CHANGED, deviceId, getMastership(deviceId)));
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800243 }
Madan Jampanide003d92015-05-11 17:14:20 -0700244 return CompletableFuture.completedFuture(MastershipRole.STANDBY);
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700245 default:
246 log.warn("unknown Mastership Role {}", role);
247 }
Madan Jampanide003d92015-05-11 17:14:20 -0700248 return CompletableFuture.completedFuture(role);
tomb41d1ac2014-09-24 01:51:24 -0700249 }
250
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800251 // add to backup if not there already, silently ignores null node
252 private synchronized boolean addToBackup(DeviceId deviceId, NodeId nodeId) {
253 boolean modified = false;
254 List<NodeId> stbys = backups.getOrDefault(deviceId, new ArrayList<>());
255 if (nodeId != null && !stbys.contains(nodeId)) {
256 stbys.add(nodeId);
257 modified = true;
258 }
259 backups.put(deviceId, stbys);
260 return modified;
261 }
262
263 private synchronized boolean removeFromBackups(DeviceId deviceId, NodeId node) {
264 List<NodeId> stbys = backups.getOrDefault(deviceId, new ArrayList<>());
265 boolean modified = stbys.remove(node);
266 backups.put(deviceId, stbys);
267 return modified;
268 }
269
270 private synchronized void incrementTerm(DeviceId deviceId) {
271 AtomicInteger term = termMap.getOrDefault(deviceId, new AtomicInteger(NOTHING));
272 term.incrementAndGet();
273 termMap.put(deviceId, term);
274 }
275
tomb41d1ac2014-09-24 01:51:24 -0700276 @Override
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700277 public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) {
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700278 //just query
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700279 NodeId current = masterMap.get(deviceId);
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700280 MastershipRole role;
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700281
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800282 if (current != null && current.equals(nodeId)) {
283 return MastershipRole.MASTER;
284 }
285
286 if (backups.getOrDefault(deviceId, Collections.emptyList()).contains(nodeId)) {
287 role = MastershipRole.STANDBY;
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700288 } else {
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800289 role = MastershipRole.NONE;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700290 }
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700291 return role;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700292 }
293
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800294 // synchronized for atomic read
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -0700295 @Override
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800296 public synchronized MastershipTerm getTermFor(DeviceId deviceId) {
Yuta HIGUCHIdfe6e3b2014-10-30 11:31:51 -0700297 if ((termMap.get(deviceId) == null)) {
298 return MastershipTerm.of(masterMap.get(deviceId), NOTHING);
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -0700299 }
300 return MastershipTerm.of(
301 masterMap.get(deviceId), termMap.get(deviceId).get());
302 }
303
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700304 @Override
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700305 public MastershipInfo getMastership(DeviceId deviceId) {
306 ImmutableMap.Builder<NodeId, MastershipRole> roleBuilder = ImmutableMap.builder();
307 NodeId master = masterMap.get(deviceId);
308 if (master != null) {
309 roleBuilder.put(master, MastershipRole.MASTER);
310 }
311 backups.getOrDefault(deviceId, Collections.emptyList())
312 .forEach(nodeId -> roleBuilder.put(nodeId, MastershipRole.STANDBY));
313 return new MastershipInfo(
314 termMap.getOrDefault(deviceId, new AtomicInteger(NOTHING)).get(),
315 Optional.ofNullable(master),
316 roleBuilder.build());
317 }
318
319 @Override
Madan Jampanif7536ab2015-05-07 23:23:23 -0700320 public synchronized CompletableFuture<MastershipEvent> setStandby(NodeId nodeId, DeviceId deviceId) {
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700321 MastershipRole role = getRole(nodeId, deviceId);
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800322 switch (role) {
323 case MASTER:
324 NodeId backup = reelect(deviceId, nodeId);
325 if (backup == null) {
326 // no master alternative
327 masterMap.remove(deviceId);
328 // TODO: Should there be new event type for no MASTER?
Madan Jampanif7536ab2015-05-07 23:23:23 -0700329 return CompletableFuture.completedFuture(
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700330 new MastershipEvent(MASTER_CHANGED, deviceId, getMastership(deviceId)));
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800331 } else {
332 NodeId prevMaster = masterMap.put(deviceId, backup);
333 incrementTerm(deviceId);
334 addToBackup(deviceId, prevMaster);
Madan Jampanif7536ab2015-05-07 23:23:23 -0700335 return CompletableFuture.completedFuture(
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700336 new MastershipEvent(MASTER_CHANGED, deviceId, getMastership(deviceId)));
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700337 }
Yuta HIGUCHI1b3f4db2014-11-18 11:04:31 -0800338
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800339 case STANDBY:
340 case NONE:
341 boolean modified = addToBackup(deviceId, nodeId);
342 if (modified) {
Madan Jampanif7536ab2015-05-07 23:23:23 -0700343 return CompletableFuture.completedFuture(
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700344 new MastershipEvent(BACKUPS_CHANGED, deviceId, getMastership(deviceId)));
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800345 }
Yuta HIGUCHI1b3f4db2014-11-18 11:04:31 -0800346 break;
347
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800348 default:
349 log.warn("unknown Mastership Role {}", role);
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700350 }
351 return null;
352 }
353
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700354 //dumbly selects next-available node that's not the current one
355 //emulate leader election
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800356 private synchronized NodeId reelect(DeviceId did, NodeId nodeId) {
357 List<NodeId> stbys = backups.getOrDefault(did, Collections.emptyList());
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700358 NodeId backup = null;
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800359 for (NodeId n : stbys) {
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700360 if (!n.equals(nodeId)) {
361 backup = n;
362 break;
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700363 }
364 }
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800365 stbys.remove(backup);
Ayaka Koshibe971a38a2014-09-30 11:56:23 -0700366 return backup;
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700367 }
368
Ayaka Koshibec4047702014-10-07 14:43:52 -0700369 @Override
Madan Jampanif7536ab2015-05-07 23:23:23 -0700370 public synchronized CompletableFuture<MastershipEvent> relinquishRole(NodeId nodeId, DeviceId deviceId) {
Ayaka Koshibeb62aab52014-10-24 13:15:25 -0700371 MastershipRole role = getRole(nodeId, deviceId);
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800372 switch (role) {
373 case MASTER:
374 NodeId backup = reelect(deviceId, nodeId);
375 masterMap.put(deviceId, backup);
376 incrementTerm(deviceId);
Madan Jampanif7536ab2015-05-07 23:23:23 -0700377 return CompletableFuture.completedFuture(
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700378 new MastershipEvent(MASTER_CHANGED, deviceId, getMastership(deviceId)));
Yuta HIGUCHI1b3f4db2014-11-18 11:04:31 -0800379
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800380 case STANDBY:
381 if (removeFromBackups(deviceId, nodeId)) {
Madan Jampanif7536ab2015-05-07 23:23:23 -0700382 return CompletableFuture.completedFuture(
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700383 new MastershipEvent(BACKUPS_CHANGED, deviceId, getMastership(deviceId)));
Ayaka Koshibeb62aab52014-10-24 13:15:25 -0700384 }
Yuta HIGUCHI1b3f4db2014-11-18 11:04:31 -0800385 break;
386
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800387 case NONE:
Yuta HIGUCHI1b3f4db2014-11-18 11:04:31 -0800388 break;
389
Yuta HIGUCHI0c6e1842014-11-05 22:34:23 -0800390 default:
391 log.warn("unknown Mastership Role {}", role);
Ayaka Koshibeb62aab52014-10-24 13:15:25 -0700392 }
Madan Jampanif7536ab2015-05-07 23:23:23 -0700393 return CompletableFuture.completedFuture(null);
Ayaka Koshibec4047702014-10-07 14:43:52 -0700394 }
HIGUCHI Yuta59f02292015-02-25 19:51:48 -0800395
396 @Override
397 public synchronized void relinquishAllRole(NodeId nodeId) {
Madan Jampanif7536ab2015-05-07 23:23:23 -0700398 List<CompletableFuture<MastershipEvent>> eventFutures = new ArrayList<>();
HIGUCHI Yuta59f02292015-02-25 19:51:48 -0800399 Set<DeviceId> toRelinquish = new HashSet<>();
400
401 masterMap.entrySet().stream()
402 .filter(entry -> nodeId.equals(entry.getValue()))
403 .forEach(entry -> toRelinquish.add(entry.getKey()));
404
405 backups.entrySet().stream()
406 .filter(entry -> entry.getValue().contains(nodeId))
407 .forEach(entry -> toRelinquish.add(entry.getKey()));
408
Sho SHIMIZUfeafdca2015-09-11 15:02:21 -0700409 toRelinquish.forEach(deviceId -> eventFutures.add(relinquishRole(nodeId, deviceId)));
HIGUCHI Yuta59f02292015-02-25 19:51:48 -0800410
Madan Jampanif7536ab2015-05-07 23:23:23 -0700411 eventFutures.forEach(future -> {
Sho SHIMIZUfeafdca2015-09-11 15:02:21 -0700412 future.whenComplete((event, error) -> notifyDelegate(event));
Madan Jampanif7536ab2015-05-07 23:23:23 -0700413 });
HIGUCHI Yuta59f02292015-02-25 19:51:48 -0800414 }
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700415}