blob: 1b5402477401f71676514197d5ac6f85dd61cc45 [file] [log] [blame]
Madan Jampani84b6b402015-02-25 17:49:54 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Madan Jampani84b6b402015-02-25 17:49:54 -08003 *
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 */
16package org.onosproject.store.mastership.impl;
17
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;
Madan Jampani84b6b402015-02-25 17:49:54 -080020import org.onlab.util.KryoNamespace;
21import org.onosproject.cluster.ClusterService;
22import org.onosproject.cluster.Leadership;
Madan Jampani620f70d2016-01-30 22:22:47 -080023import org.onosproject.cluster.LeadershipAdminService;
Madan Jampani84b6b402015-02-25 17:49:54 -080024import org.onosproject.cluster.LeadershipEvent;
25import org.onosproject.cluster.LeadershipEventListener;
26import org.onosproject.cluster.LeadershipService;
27import org.onosproject.cluster.NodeId;
28import org.onosproject.cluster.RoleInfo;
29import org.onosproject.mastership.MastershipEvent;
Jordan Halterman0a2bd452018-06-13 17:24:58 -070030import org.onosproject.mastership.MastershipInfo;
Madan Jampani84b6b402015-02-25 17:49:54 -080031import org.onosproject.mastership.MastershipStore;
32import org.onosproject.mastership.MastershipStoreDelegate;
33import org.onosproject.mastership.MastershipTerm;
34import org.onosproject.net.DeviceId;
35import org.onosproject.net.MastershipRole;
36import org.onosproject.store.AbstractStore;
37import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
Madan Jampani84b6b402015-02-25 17:49:54 -080038import org.onosproject.store.cluster.messaging.MessageSubject;
39import org.onosproject.store.serializers.KryoNamespaces;
Jordan Halterman2c83a102017-08-20 17:11:41 -070040import org.onosproject.store.service.Serializer;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070041import org.osgi.service.component.annotations.Activate;
42import org.osgi.service.component.annotations.Component;
43import org.osgi.service.component.annotations.Deactivate;
44import org.osgi.service.component.annotations.Reference;
45import org.osgi.service.component.annotations.ReferenceCardinality;
Madan Jampani84b6b402015-02-25 17:49:54 -080046import org.slf4j.Logger;
47
Ray Milkeyd84f89b2018-08-17 14:54:17 -070048import java.util.List;
49import java.util.Objects;
50import java.util.Optional;
51import java.util.Set;
52import java.util.concurrent.CompletableFuture;
53import java.util.concurrent.ExecutorService;
54import java.util.concurrent.Executors;
55import java.util.concurrent.ScheduledExecutorService;
56import java.util.concurrent.TimeUnit;
57import java.util.regex.Matcher;
58import java.util.regex.Pattern;
59import java.util.stream.Collectors;
60
61import static com.google.common.base.Preconditions.checkArgument;
62import static org.onlab.util.Tools.groupedThreads;
63import static org.onosproject.mastership.MastershipEvent.Type.BACKUPS_CHANGED;
64import static org.onosproject.mastership.MastershipEvent.Type.MASTER_CHANGED;
65import static org.onosproject.mastership.MastershipEvent.Type.RESTORED;
66import static org.onosproject.mastership.MastershipEvent.Type.SUSPENDED;
67import static org.slf4j.LoggerFactory.getLogger;
Madan Jampani84b6b402015-02-25 17:49:54 -080068
69/**
70 * Implementation of the MastershipStore on top of Leadership Service.
71 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070072@Component(immediate = true, service = MastershipStore.class)
Madan Jampani84b6b402015-02-25 17:49:54 -080073public class ConsistentDeviceMastershipStore
74 extends AbstractStore<MastershipEvent, MastershipStoreDelegate>
75 implements MastershipStore {
76
77 private final Logger log = getLogger(getClass());
78
Ray Milkeyd84f89b2018-08-17 14:54:17 -070079 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Madan Jampani84b6b402015-02-25 17:49:54 -080080 protected LeadershipService leadershipService;
81
Ray Milkeyd84f89b2018-08-17 14:54:17 -070082 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Madan Jampani620f70d2016-01-30 22:22:47 -080083 protected LeadershipAdminService leadershipAdminService;
84
Ray Milkeyd84f89b2018-08-17 14:54:17 -070085 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Madan Jampani84b6b402015-02-25 17:49:54 -080086 protected ClusterService clusterService;
87
Ray Milkeyd84f89b2018-08-17 14:54:17 -070088 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Madan Jampani84b6b402015-02-25 17:49:54 -080089 protected ClusterCommunicationService clusterCommunicator;
90
91 private NodeId localNodeId;
Madan Jampani84b6b402015-02-25 17:49:54 -080092
Madan Jampani84b6b402015-02-25 17:49:54 -080093 private static final MessageSubject ROLE_RELINQUISH_SUBJECT =
94 new MessageSubject("mastership-store-device-role-relinquish");
95
Carmelo Cascone0e3b6232019-03-08 11:11:29 -080096 private static final String DEVICE_MASTERSHIP_TOPIC_PREFIX = "device-mastership:";
97
Madan Jampani84b6b402015-02-25 17:49:54 -080098 private static final Pattern DEVICE_MASTERSHIP_TOPIC_PATTERN =
Carmelo Cascone0e3b6232019-03-08 11:11:29 -080099 Pattern.compile("^" + DEVICE_MASTERSHIP_TOPIC_PREFIX + "(.*)");
Madan Jampani84b6b402015-02-25 17:49:54 -0800100
Madan Jampani71c32ca2016-06-22 08:23:18 -0700101 private ExecutorService eventHandler;
Madan Jampani84b6b402015-02-25 17:49:54 -0800102 private ExecutorService messageHandlingExecutor;
Madan Jampanif7536ab2015-05-07 23:23:23 -0700103 private ScheduledExecutorService transferExecutor;
Madan Jampani84b6b402015-02-25 17:49:54 -0800104 private final LeadershipEventListener leadershipEventListener =
105 new InternalDeviceMastershipEventListener();
106
107 private static final String NODE_ID_NULL = "Node ID cannot be null";
Madan Jampanif7536ab2015-05-07 23:23:23 -0700108 private static final String DEVICE_ID_NULL = "Device ID cannot be null";
109 private static final int WAIT_BEFORE_MASTERSHIP_HANDOFF_MILLIS = 3000;
Madan Jampani84b6b402015-02-25 17:49:54 -0800110
Jordan Halterman2c83a102017-08-20 17:11:41 -0700111 public static final Serializer SERIALIZER = Serializer.using(
HIGUCHI Yutae7290652016-05-18 11:29:01 -0700112 KryoNamespace.newBuilder()
Madan Jampani84b6b402015-02-25 17:49:54 -0800113 .register(KryoNamespaces.API)
114 .register(MastershipRole.class)
115 .register(MastershipEvent.class)
Madan Jampani1af8e132015-04-30 16:41:18 -0700116 .register(MastershipEvent.Type.class)
HIGUCHI Yutae7290652016-05-18 11:29:01 -0700117 .build("MastershipStore"));
Madan Jampani84b6b402015-02-25 17:49:54 -0800118
119 @Activate
120 public void activate() {
Madan Jampani71c32ca2016-06-22 08:23:18 -0700121
122 eventHandler = Executors.newSingleThreadExecutor(
123 groupedThreads("onos/store/device/mastership", "event-handler", log));
124
Madan Jampani84b6b402015-02-25 17:49:54 -0800125 messageHandlingExecutor =
Madan Jampanif7536ab2015-05-07 23:23:23 -0700126 Executors.newSingleThreadExecutor(
HIGUCHI Yuta060da9a2016-03-11 19:16:35 -0800127 groupedThreads("onos/store/device/mastership", "message-handler", log));
Madan Jampanif7536ab2015-05-07 23:23:23 -0700128 transferExecutor =
129 Executors.newSingleThreadScheduledExecutor(
HIGUCHI Yuta060da9a2016-03-11 19:16:35 -0800130 groupedThreads("onos/store/device/mastership", "mastership-transfer-executor", log));
Madan Jampanibbed40422015-05-20 12:00:38 -0700131 clusterCommunicator.addSubscriber(ROLE_RELINQUISH_SUBJECT,
Madan Jampanid46e18f2015-05-04 23:19:33 -0700132 SERIALIZER::decode,
Madan Jampanif7536ab2015-05-07 23:23:23 -0700133 this::relinquishLocalRole,
Madan Jampanid46e18f2015-05-04 23:19:33 -0700134 SERIALIZER::encode,
135 messageHandlingExecutor);
Madan Jampani84b6b402015-02-25 17:49:54 -0800136 localNodeId = clusterService.getLocalNode().id();
137 leadershipService.addListener(leadershipEventListener);
138
Madan Jampaniafeebbd2015-05-19 15:26:01 -0700139 log.info("Started");
Madan Jampani84b6b402015-02-25 17:49:54 -0800140 }
141
142 @Deactivate
143 public void deactivate() {
Madan Jampani84b6b402015-02-25 17:49:54 -0800144 clusterCommunicator.removeSubscriber(ROLE_RELINQUISH_SUBJECT);
Madan Jampani71c32ca2016-06-22 08:23:18 -0700145 leadershipService.removeListener(leadershipEventListener);
Madan Jampani84b6b402015-02-25 17:49:54 -0800146 messageHandlingExecutor.shutdown();
Madan Jampanif7536ab2015-05-07 23:23:23 -0700147 transferExecutor.shutdown();
Madan Jampani71c32ca2016-06-22 08:23:18 -0700148 eventHandler.shutdown();
Madan Jampaniafeebbd2015-05-19 15:26:01 -0700149 log.info("Stopped");
Madan Jampani84b6b402015-02-25 17:49:54 -0800150 }
151
152 @Override
Madan Jampanide003d92015-05-11 17:14:20 -0700153 public CompletableFuture<MastershipRole> requestRole(DeviceId deviceId) {
Madan Jampani84b6b402015-02-25 17:49:54 -0800154 checkArgument(deviceId != null, DEVICE_ID_NULL);
155
156 String leadershipTopic = createDeviceMastershipTopic(deviceId);
Madan Jampani620f70d2016-01-30 22:22:47 -0800157 Leadership leadership = leadershipService.runForLeadership(leadershipTopic);
Jordan Halterman980a8c12017-09-22 18:01:19 -0700158 NodeId leader = leadership == null ? null : leadership.leaderNodeId();
159 List<NodeId> candidates = leadership == null ?
160 ImmutableList.of() : ImmutableList.copyOf(leadership.candidates());
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700161 MastershipRole role = Objects.equals(localNodeId, leader) ?
Jordan Halterman980a8c12017-09-22 18:01:19 -0700162 MastershipRole.MASTER : candidates.contains(localNodeId) ? MastershipRole.STANDBY : MastershipRole.NONE;
163 return CompletableFuture.completedFuture(role);
Madan Jampani84b6b402015-02-25 17:49:54 -0800164 }
165
166 @Override
167 public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) {
168 checkArgument(nodeId != null, NODE_ID_NULL);
169 checkArgument(deviceId != null, DEVICE_ID_NULL);
170
171 String leadershipTopic = createDeviceMastershipTopic(deviceId);
Madan Jampani620f70d2016-01-30 22:22:47 -0800172 Leadership leadership = leadershipService.getLeadership(leadershipTopic);
173 NodeId leader = leadership == null ? null : leadership.leaderNodeId();
174 List<NodeId> candidates = leadership == null ?
175 ImmutableList.of() : ImmutableList.copyOf(leadership.candidates());
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700176 return Objects.equals(nodeId, leader) ?
Madan Jampani620f70d2016-01-30 22:22:47 -0800177 MastershipRole.MASTER : candidates.contains(nodeId) ? MastershipRole.STANDBY : MastershipRole.NONE;
Madan Jampani84b6b402015-02-25 17:49:54 -0800178 }
179
180 @Override
181 public NodeId getMaster(DeviceId deviceId) {
182 checkArgument(deviceId != null, DEVICE_ID_NULL);
183
Madan Jampani620f70d2016-01-30 22:22:47 -0800184 return leadershipService.getLeader(createDeviceMastershipTopic(deviceId));
Madan Jampani84b6b402015-02-25 17:49:54 -0800185 }
186
187 @Override
188 public RoleInfo getNodes(DeviceId deviceId) {
189 checkArgument(deviceId != null, DEVICE_ID_NULL);
Jordan Halterman86741ec2018-12-10 11:02:31 -0800190 MastershipInfo mastership = getMastership(deviceId);
191 return new RoleInfo(mastership.master().orElse(null), mastership.backups());
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700192 }
Madan Jampani84b6b402015-02-25 17:49:54 -0800193
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700194 @Override
195 public MastershipInfo getMastership(DeviceId deviceId) {
196 checkArgument(deviceId != null, DEVICE_ID_NULL);
197 Leadership leadership = leadershipService.getLeadership(createDeviceMastershipTopic(deviceId));
198 return buildMastershipFromLeadership(leadership);
Madan Jampani84b6b402015-02-25 17:49:54 -0800199 }
200
201 @Override
202 public Set<DeviceId> getDevices(NodeId nodeId) {
203 checkArgument(nodeId != null, NODE_ID_NULL);
204
Yuta HIGUCHId9340032017-01-25 09:25:44 -0800205 // FIXME This result contains REMOVED device.
206 // MastershipService cannot listen to DeviceEvent to GC removed topic,
207 // since DeviceManager depend on it.
208 // Reference count, etc. at LeadershipService layer?
Madan Jampani84b6b402015-02-25 17:49:54 -0800209 return leadershipService
210 .ownedTopics(nodeId)
211 .stream()
212 .filter(this::isDeviceMastershipTopic)
213 .map(this::extractDeviceIdFromTopic)
214 .collect(Collectors.toSet());
215 }
216
217 @Override
Madan Jampanif7536ab2015-05-07 23:23:23 -0700218 public CompletableFuture<MastershipEvent> setMaster(NodeId nodeId, DeviceId deviceId) {
Madan Jampani84b6b402015-02-25 17:49:54 -0800219 checkArgument(nodeId != null, NODE_ID_NULL);
220 checkArgument(deviceId != null, DEVICE_ID_NULL);
221
Madan Jampani620f70d2016-01-30 22:22:47 -0800222 String leadershipTopic = createDeviceMastershipTopic(deviceId);
223 if (leadershipAdminService.promoteToTopOfCandidateList(leadershipTopic, nodeId)) {
224 transferExecutor.schedule(() -> leadershipAdminService.transferLeadership(leadershipTopic, nodeId),
225 WAIT_BEFORE_MASTERSHIP_HANDOFF_MILLIS, TimeUnit.MILLISECONDS);
Madan Jampani1af8e132015-04-30 16:41:18 -0700226 }
Madan Jampanif7536ab2015-05-07 23:23:23 -0700227 return CompletableFuture.completedFuture(null);
Madan Jampani84b6b402015-02-25 17:49:54 -0800228 }
229
230 @Override
231 public MastershipTerm getTermFor(DeviceId deviceId) {
232 checkArgument(deviceId != null, DEVICE_ID_NULL);
233
234 String leadershipTopic = createDeviceMastershipTopic(deviceId);
235 Leadership leadership = leadershipService.getLeadership(leadershipTopic);
Madan Jampanidbe8a812016-01-31 21:10:46 -0800236 return leadership != null && leadership.leaderNodeId() != null ?
237 MastershipTerm.of(leadership.leaderNodeId(), leadership.leader().term()) : null;
Madan Jampani84b6b402015-02-25 17:49:54 -0800238 }
239
240 @Override
Madan Jampanif7536ab2015-05-07 23:23:23 -0700241 public CompletableFuture<MastershipEvent> setStandby(NodeId nodeId, DeviceId deviceId) {
Madan Jampani84b6b402015-02-25 17:49:54 -0800242 checkArgument(nodeId != null, NODE_ID_NULL);
243 checkArgument(deviceId != null, DEVICE_ID_NULL);
244
Madan Jampani1af8e132015-04-30 16:41:18 -0700245 NodeId currentMaster = getMaster(deviceId);
246 if (!nodeId.equals(currentMaster)) {
Madan Jampanif7536ab2015-05-07 23:23:23 -0700247 return CompletableFuture.completedFuture(null);
Madan Jampani1af8e132015-04-30 16:41:18 -0700248 }
Madan Jampanid46e18f2015-05-04 23:19:33 -0700249
250 String leadershipTopic = createDeviceMastershipTopic(deviceId);
251 List<NodeId> candidates = leadershipService.getCandidates(leadershipTopic);
252
253 NodeId newMaster = candidates.stream()
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700254 .filter(candidate -> !Objects.equals(nodeId, candidate))
Madan Jampanid46e18f2015-05-04 23:19:33 -0700255 .findFirst()
256 .orElse(null);
257 log.info("Transitioning to role {} for {}. Next master: {}",
258 newMaster != null ? MastershipRole.STANDBY : MastershipRole.NONE, deviceId, newMaster);
259
260 if (newMaster != null) {
261 return setMaster(newMaster, deviceId);
262 }
263 return relinquishRole(nodeId, deviceId);
Madan Jampani84b6b402015-02-25 17:49:54 -0800264 }
265
266 @Override
Madan Jampanif7536ab2015-05-07 23:23:23 -0700267 public CompletableFuture<MastershipEvent> relinquishRole(NodeId nodeId, DeviceId deviceId) {
Madan Jampani84b6b402015-02-25 17:49:54 -0800268 checkArgument(nodeId != null, NODE_ID_NULL);
269 checkArgument(deviceId != null, DEVICE_ID_NULL);
270
Madan Jampanibbed40422015-05-20 12:00:38 -0700271 if (nodeId.equals(localNodeId)) {
272 return relinquishLocalRole(deviceId);
Madan Jampani84b6b402015-02-25 17:49:54 -0800273 }
Madan Jampanibbed40422015-05-20 12:00:38 -0700274
275 log.debug("Forwarding request to relinquish "
276 + "role for device {} to {}", deviceId, nodeId);
277 return clusterCommunicator.sendAndReceive(
278 deviceId,
279 ROLE_RELINQUISH_SUBJECT,
280 SERIALIZER::encode,
281 SERIALIZER::decode,
282 nodeId);
Madan Jampanif7536ab2015-05-07 23:23:23 -0700283 }
284
Madan Jampanibbed40422015-05-20 12:00:38 -0700285 private CompletableFuture<MastershipEvent> relinquishLocalRole(DeviceId deviceId) {
Madan Jampanif7536ab2015-05-07 23:23:23 -0700286 checkArgument(deviceId != null, DEVICE_ID_NULL);
Madan Jampani84b6b402015-02-25 17:49:54 -0800287
Madan Jampani620f70d2016-01-30 22:22:47 -0800288 String leadershipTopic = createDeviceMastershipTopic(deviceId);
289 if (!leadershipService.getCandidates(leadershipTopic).contains(localNodeId)) {
Madan Jampanibbed40422015-05-20 12:00:38 -0700290 return CompletableFuture.completedFuture(null);
Madan Jampani84b6b402015-02-25 17:49:54 -0800291 }
Madan Jampani620f70d2016-01-30 22:22:47 -0800292 MastershipEvent.Type eventType = localNodeId.equals(leadershipService.getLeader(leadershipTopic)) ?
293 MastershipEvent.Type.MASTER_CHANGED : MastershipEvent.Type.BACKUPS_CHANGED;
294 leadershipService.withdraw(leadershipTopic);
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700295 return CompletableFuture.completedFuture(new MastershipEvent(eventType, deviceId, getMastership(deviceId)));
Madan Jampani1af8e132015-04-30 16:41:18 -0700296 }
297
Madan Jampani84b6b402015-02-25 17:49:54 -0800298 @Override
299 public void relinquishAllRole(NodeId nodeId) {
Madan Jampani620f70d2016-01-30 22:22:47 -0800300 // Noop. LeadershipService already takes care of detecting and purging stale locks.
Madan Jampani84b6b402015-02-25 17:49:54 -0800301 }
302
pierventrecdcd91c2021-05-06 09:27:00 +0200303 @Override
304 public void demote(NodeId instance, DeviceId deviceId) {
305 String leadershipTopic = createDeviceMastershipTopic(deviceId);
306 leadershipAdminService.demote(leadershipTopic, instance);
307 }
308
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700309 private MastershipInfo buildMastershipFromLeadership(Leadership leadership) {
310 ImmutableMap.Builder<NodeId, MastershipRole> builder = ImmutableMap.builder();
311 if (leadership.leaderNodeId() != null) {
312 builder.put(leadership.leaderNodeId(), MastershipRole.MASTER);
313 }
314 leadership.candidates().stream()
315 .filter(nodeId -> !Objects.equals(leadership.leaderNodeId(), nodeId))
316 .forEach(nodeId -> builder.put(nodeId, MastershipRole.STANDBY));
317 clusterService.getNodes().stream()
318 .filter(node -> !Objects.equals(leadership.leaderNodeId(), node.id()))
319 .filter(node -> !leadership.candidates().contains(node.id()))
320 .forEach(node -> builder.put(node.id(), MastershipRole.NONE));
321
322 return new MastershipInfo(
323 leadership.leader() != null ? leadership.leader().term() : 0,
324 leadership.leader() != null
325 ? Optional.of(leadership.leader().nodeId())
326 : Optional.empty(),
327 builder.build());
328 }
329
Madan Jampani84b6b402015-02-25 17:49:54 -0800330 private class InternalDeviceMastershipEventListener implements LeadershipEventListener {
Madan Jampani620f70d2016-01-30 22:22:47 -0800331
332 @Override
333 public boolean isRelevant(LeadershipEvent event) {
334 Leadership leadership = event.subject();
335 return isDeviceMastershipTopic(leadership.topic());
336 }
337
Madan Jampani84b6b402015-02-25 17:49:54 -0800338 @Override
339 public void event(LeadershipEvent event) {
Madan Jampani71c32ca2016-06-22 08:23:18 -0700340 eventHandler.execute(() -> handleEvent(event));
341 }
342
343 private void handleEvent(LeadershipEvent event) {
Madan Jampani84b6b402015-02-25 17:49:54 -0800344 Leadership leadership = event.subject();
Madan Jampani84b6b402015-02-25 17:49:54 -0800345 DeviceId deviceId = extractDeviceIdFromTopic(leadership.topic());
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700346 MastershipInfo mastershipInfo = event.type() != LeadershipEvent.Type.SERVICE_DISRUPTED
347 ? buildMastershipFromLeadership(event.subject())
348 : new MastershipInfo();
349
Thomas Vachuska4b839c72015-05-18 15:43:03 -0700350 switch (event.type()) {
Jordan Haltermana1ccbc32017-12-15 17:07:52 -0800351 case LEADER_AND_CANDIDATES_CHANGED:
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700352 notifyDelegate(new MastershipEvent(BACKUPS_CHANGED, deviceId, mastershipInfo));
353 notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, mastershipInfo));
Jordan Haltermana1ccbc32017-12-15 17:07:52 -0800354 break;
355 case LEADER_CHANGED:
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700356 notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, mastershipInfo));
Jordan Haltermana1ccbc32017-12-15 17:07:52 -0800357 break;
358 case CANDIDATES_CHANGED:
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700359 notifyDelegate(new MastershipEvent(BACKUPS_CHANGED, deviceId, mastershipInfo));
Jordan Haltermana1ccbc32017-12-15 17:07:52 -0800360 break;
361 case SERVICE_DISRUPTED:
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700362 notifyDelegate(new MastershipEvent(SUSPENDED, deviceId, mastershipInfo));
Jordan Haltermana1ccbc32017-12-15 17:07:52 -0800363 break;
364 case SERVICE_RESTORED:
Andrea Campanella80b296d2018-09-18 10:48:15 +0200365 notifyDelegate(new MastershipEvent(RESTORED, deviceId, mastershipInfo));
Jordan Haltermana1ccbc32017-12-15 17:07:52 -0800366 break;
367 default:
368 return;
Madan Jampani84b6b402015-02-25 17:49:54 -0800369 }
370 }
371 }
372
373 private String createDeviceMastershipTopic(DeviceId deviceId) {
Carmelo Cascone0e3b6232019-03-08 11:11:29 -0800374 return String.format("%s%s", DEVICE_MASTERSHIP_TOPIC_PREFIX, deviceId.toString());
Madan Jampani84b6b402015-02-25 17:49:54 -0800375 }
376
377 private DeviceId extractDeviceIdFromTopic(String topic) {
378 Matcher m = DEVICE_MASTERSHIP_TOPIC_PATTERN.matcher(topic);
379 if (m.matches()) {
380 return DeviceId.deviceId(m.group(1));
381 } else {
382 throw new IllegalArgumentException("Invalid device mastership topic: " + topic);
383 }
384 }
385
386 private boolean isDeviceMastershipTopic(String topic) {
387 Matcher m = DEVICE_MASTERSHIP_TOPIC_PATTERN.matcher(topic);
388 return m.matches();
389 }
Madan Jampanidbe8a812016-01-31 21:10:46 -0800390}