blob: 3990a8be8bd1779f2ed8ae995927f71bca9035ce [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
96 private static final Pattern DEVICE_MASTERSHIP_TOPIC_PATTERN =
Madan Jampani5756c352015-04-29 00:23:58 -070097 Pattern.compile("device:(.*)");
Madan Jampani84b6b402015-02-25 17:49:54 -080098
Madan Jampani71c32ca2016-06-22 08:23:18 -070099 private ExecutorService eventHandler;
Madan Jampani84b6b402015-02-25 17:49:54 -0800100 private ExecutorService messageHandlingExecutor;
Madan Jampanif7536ab2015-05-07 23:23:23 -0700101 private ScheduledExecutorService transferExecutor;
Madan Jampani84b6b402015-02-25 17:49:54 -0800102 private final LeadershipEventListener leadershipEventListener =
103 new InternalDeviceMastershipEventListener();
104
105 private static final String NODE_ID_NULL = "Node ID cannot be null";
Madan Jampanif7536ab2015-05-07 23:23:23 -0700106 private static final String DEVICE_ID_NULL = "Device ID cannot be null";
107 private static final int WAIT_BEFORE_MASTERSHIP_HANDOFF_MILLIS = 3000;
Madan Jampani84b6b402015-02-25 17:49:54 -0800108
Jordan Halterman2c83a102017-08-20 17:11:41 -0700109 public static final Serializer SERIALIZER = Serializer.using(
HIGUCHI Yutae7290652016-05-18 11:29:01 -0700110 KryoNamespace.newBuilder()
Madan Jampani84b6b402015-02-25 17:49:54 -0800111 .register(KryoNamespaces.API)
112 .register(MastershipRole.class)
113 .register(MastershipEvent.class)
Madan Jampani1af8e132015-04-30 16:41:18 -0700114 .register(MastershipEvent.Type.class)
HIGUCHI Yutae7290652016-05-18 11:29:01 -0700115 .build("MastershipStore"));
Madan Jampani84b6b402015-02-25 17:49:54 -0800116
117 @Activate
118 public void activate() {
Madan Jampani71c32ca2016-06-22 08:23:18 -0700119
120 eventHandler = Executors.newSingleThreadExecutor(
121 groupedThreads("onos/store/device/mastership", "event-handler", log));
122
Madan Jampani84b6b402015-02-25 17:49:54 -0800123 messageHandlingExecutor =
Madan Jampanif7536ab2015-05-07 23:23:23 -0700124 Executors.newSingleThreadExecutor(
HIGUCHI Yuta060da9a2016-03-11 19:16:35 -0800125 groupedThreads("onos/store/device/mastership", "message-handler", log));
Madan Jampanif7536ab2015-05-07 23:23:23 -0700126 transferExecutor =
127 Executors.newSingleThreadScheduledExecutor(
HIGUCHI Yuta060da9a2016-03-11 19:16:35 -0800128 groupedThreads("onos/store/device/mastership", "mastership-transfer-executor", log));
Madan Jampanibbed40422015-05-20 12:00:38 -0700129 clusterCommunicator.addSubscriber(ROLE_RELINQUISH_SUBJECT,
Madan Jampanid46e18f2015-05-04 23:19:33 -0700130 SERIALIZER::decode,
Madan Jampanif7536ab2015-05-07 23:23:23 -0700131 this::relinquishLocalRole,
Madan Jampanid46e18f2015-05-04 23:19:33 -0700132 SERIALIZER::encode,
133 messageHandlingExecutor);
Madan Jampani84b6b402015-02-25 17:49:54 -0800134 localNodeId = clusterService.getLocalNode().id();
135 leadershipService.addListener(leadershipEventListener);
136
Madan Jampaniafeebbd2015-05-19 15:26:01 -0700137 log.info("Started");
Madan Jampani84b6b402015-02-25 17:49:54 -0800138 }
139
140 @Deactivate
141 public void deactivate() {
Madan Jampani84b6b402015-02-25 17:49:54 -0800142 clusterCommunicator.removeSubscriber(ROLE_RELINQUISH_SUBJECT);
Madan Jampani71c32ca2016-06-22 08:23:18 -0700143 leadershipService.removeListener(leadershipEventListener);
Madan Jampani84b6b402015-02-25 17:49:54 -0800144 messageHandlingExecutor.shutdown();
Madan Jampanif7536ab2015-05-07 23:23:23 -0700145 transferExecutor.shutdown();
Madan Jampani71c32ca2016-06-22 08:23:18 -0700146 eventHandler.shutdown();
Madan Jampaniafeebbd2015-05-19 15:26:01 -0700147 log.info("Stopped");
Madan Jampani84b6b402015-02-25 17:49:54 -0800148 }
149
150 @Override
Madan Jampanide003d92015-05-11 17:14:20 -0700151 public CompletableFuture<MastershipRole> requestRole(DeviceId deviceId) {
Madan Jampani84b6b402015-02-25 17:49:54 -0800152 checkArgument(deviceId != null, DEVICE_ID_NULL);
153
154 String leadershipTopic = createDeviceMastershipTopic(deviceId);
Madan Jampani620f70d2016-01-30 22:22:47 -0800155 Leadership leadership = leadershipService.runForLeadership(leadershipTopic);
Jordan Halterman980a8c12017-09-22 18:01:19 -0700156 NodeId leader = leadership == null ? null : leadership.leaderNodeId();
157 List<NodeId> candidates = leadership == null ?
158 ImmutableList.of() : ImmutableList.copyOf(leadership.candidates());
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700159 MastershipRole role = Objects.equals(localNodeId, leader) ?
Jordan Halterman980a8c12017-09-22 18:01:19 -0700160 MastershipRole.MASTER : candidates.contains(localNodeId) ? MastershipRole.STANDBY : MastershipRole.NONE;
161 return CompletableFuture.completedFuture(role);
Madan Jampani84b6b402015-02-25 17:49:54 -0800162 }
163
164 @Override
165 public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) {
166 checkArgument(nodeId != null, NODE_ID_NULL);
167 checkArgument(deviceId != null, DEVICE_ID_NULL);
168
169 String leadershipTopic = createDeviceMastershipTopic(deviceId);
Madan Jampani620f70d2016-01-30 22:22:47 -0800170 Leadership leadership = leadershipService.getLeadership(leadershipTopic);
171 NodeId leader = leadership == null ? null : leadership.leaderNodeId();
172 List<NodeId> candidates = leadership == null ?
173 ImmutableList.of() : ImmutableList.copyOf(leadership.candidates());
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700174 return Objects.equals(nodeId, leader) ?
Madan Jampani620f70d2016-01-30 22:22:47 -0800175 MastershipRole.MASTER : candidates.contains(nodeId) ? MastershipRole.STANDBY : MastershipRole.NONE;
Madan Jampani84b6b402015-02-25 17:49:54 -0800176 }
177
178 @Override
179 public NodeId getMaster(DeviceId deviceId) {
180 checkArgument(deviceId != null, DEVICE_ID_NULL);
181
Madan Jampani620f70d2016-01-30 22:22:47 -0800182 return leadershipService.getLeader(createDeviceMastershipTopic(deviceId));
Madan Jampani84b6b402015-02-25 17:49:54 -0800183 }
184
185 @Override
186 public RoleInfo getNodes(DeviceId deviceId) {
187 checkArgument(deviceId != null, DEVICE_ID_NULL);
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700188 Leadership leadership = leadershipService.getLeadership(createDeviceMastershipTopic(deviceId));
189 return new RoleInfo(leadership.leaderNodeId(), leadership.candidates());
190 }
Madan Jampani84b6b402015-02-25 17:49:54 -0800191
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700192 @Override
193 public MastershipInfo getMastership(DeviceId deviceId) {
194 checkArgument(deviceId != null, DEVICE_ID_NULL);
195 Leadership leadership = leadershipService.getLeadership(createDeviceMastershipTopic(deviceId));
196 return buildMastershipFromLeadership(leadership);
Madan Jampani84b6b402015-02-25 17:49:54 -0800197 }
198
199 @Override
200 public Set<DeviceId> getDevices(NodeId nodeId) {
201 checkArgument(nodeId != null, NODE_ID_NULL);
202
Yuta HIGUCHId9340032017-01-25 09:25:44 -0800203 // FIXME This result contains REMOVED device.
204 // MastershipService cannot listen to DeviceEvent to GC removed topic,
205 // since DeviceManager depend on it.
206 // Reference count, etc. at LeadershipService layer?
Madan Jampani84b6b402015-02-25 17:49:54 -0800207 return leadershipService
208 .ownedTopics(nodeId)
209 .stream()
210 .filter(this::isDeviceMastershipTopic)
211 .map(this::extractDeviceIdFromTopic)
212 .collect(Collectors.toSet());
213 }
214
215 @Override
Madan Jampanif7536ab2015-05-07 23:23:23 -0700216 public CompletableFuture<MastershipEvent> setMaster(NodeId nodeId, DeviceId deviceId) {
Madan Jampani84b6b402015-02-25 17:49:54 -0800217 checkArgument(nodeId != null, NODE_ID_NULL);
218 checkArgument(deviceId != null, DEVICE_ID_NULL);
219
Madan Jampani620f70d2016-01-30 22:22:47 -0800220 String leadershipTopic = createDeviceMastershipTopic(deviceId);
221 if (leadershipAdminService.promoteToTopOfCandidateList(leadershipTopic, nodeId)) {
222 transferExecutor.schedule(() -> leadershipAdminService.transferLeadership(leadershipTopic, nodeId),
223 WAIT_BEFORE_MASTERSHIP_HANDOFF_MILLIS, TimeUnit.MILLISECONDS);
Madan Jampani1af8e132015-04-30 16:41:18 -0700224 }
Madan Jampanif7536ab2015-05-07 23:23:23 -0700225 return CompletableFuture.completedFuture(null);
Madan Jampani84b6b402015-02-25 17:49:54 -0800226 }
227
228 @Override
229 public MastershipTerm getTermFor(DeviceId deviceId) {
230 checkArgument(deviceId != null, DEVICE_ID_NULL);
231
232 String leadershipTopic = createDeviceMastershipTopic(deviceId);
233 Leadership leadership = leadershipService.getLeadership(leadershipTopic);
Madan Jampanidbe8a812016-01-31 21:10:46 -0800234 return leadership != null && leadership.leaderNodeId() != null ?
235 MastershipTerm.of(leadership.leaderNodeId(), leadership.leader().term()) : null;
Madan Jampani84b6b402015-02-25 17:49:54 -0800236 }
237
238 @Override
Madan Jampanif7536ab2015-05-07 23:23:23 -0700239 public CompletableFuture<MastershipEvent> setStandby(NodeId nodeId, DeviceId deviceId) {
Madan Jampani84b6b402015-02-25 17:49:54 -0800240 checkArgument(nodeId != null, NODE_ID_NULL);
241 checkArgument(deviceId != null, DEVICE_ID_NULL);
242
Madan Jampani1af8e132015-04-30 16:41:18 -0700243 NodeId currentMaster = getMaster(deviceId);
244 if (!nodeId.equals(currentMaster)) {
Madan Jampanif7536ab2015-05-07 23:23:23 -0700245 return CompletableFuture.completedFuture(null);
Madan Jampani1af8e132015-04-30 16:41:18 -0700246 }
Madan Jampanid46e18f2015-05-04 23:19:33 -0700247
248 String leadershipTopic = createDeviceMastershipTopic(deviceId);
249 List<NodeId> candidates = leadershipService.getCandidates(leadershipTopic);
250
251 NodeId newMaster = candidates.stream()
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700252 .filter(candidate -> !Objects.equals(nodeId, candidate))
Madan Jampanid46e18f2015-05-04 23:19:33 -0700253 .findFirst()
254 .orElse(null);
255 log.info("Transitioning to role {} for {}. Next master: {}",
256 newMaster != null ? MastershipRole.STANDBY : MastershipRole.NONE, deviceId, newMaster);
257
258 if (newMaster != null) {
259 return setMaster(newMaster, deviceId);
260 }
261 return relinquishRole(nodeId, deviceId);
Madan Jampani84b6b402015-02-25 17:49:54 -0800262 }
263
264 @Override
Madan Jampanif7536ab2015-05-07 23:23:23 -0700265 public CompletableFuture<MastershipEvent> relinquishRole(NodeId nodeId, DeviceId deviceId) {
Madan Jampani84b6b402015-02-25 17:49:54 -0800266 checkArgument(nodeId != null, NODE_ID_NULL);
267 checkArgument(deviceId != null, DEVICE_ID_NULL);
268
Madan Jampanibbed40422015-05-20 12:00:38 -0700269 if (nodeId.equals(localNodeId)) {
270 return relinquishLocalRole(deviceId);
Madan Jampani84b6b402015-02-25 17:49:54 -0800271 }
Madan Jampanibbed40422015-05-20 12:00:38 -0700272
273 log.debug("Forwarding request to relinquish "
274 + "role for device {} to {}", deviceId, nodeId);
275 return clusterCommunicator.sendAndReceive(
276 deviceId,
277 ROLE_RELINQUISH_SUBJECT,
278 SERIALIZER::encode,
279 SERIALIZER::decode,
280 nodeId);
Madan Jampanif7536ab2015-05-07 23:23:23 -0700281 }
282
Madan Jampanibbed40422015-05-20 12:00:38 -0700283 private CompletableFuture<MastershipEvent> relinquishLocalRole(DeviceId deviceId) {
Madan Jampanif7536ab2015-05-07 23:23:23 -0700284 checkArgument(deviceId != null, DEVICE_ID_NULL);
Madan Jampani84b6b402015-02-25 17:49:54 -0800285
Madan Jampani620f70d2016-01-30 22:22:47 -0800286 String leadershipTopic = createDeviceMastershipTopic(deviceId);
287 if (!leadershipService.getCandidates(leadershipTopic).contains(localNodeId)) {
Madan Jampanibbed40422015-05-20 12:00:38 -0700288 return CompletableFuture.completedFuture(null);
Madan Jampani84b6b402015-02-25 17:49:54 -0800289 }
Madan Jampani620f70d2016-01-30 22:22:47 -0800290 MastershipEvent.Type eventType = localNodeId.equals(leadershipService.getLeader(leadershipTopic)) ?
291 MastershipEvent.Type.MASTER_CHANGED : MastershipEvent.Type.BACKUPS_CHANGED;
292 leadershipService.withdraw(leadershipTopic);
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700293 return CompletableFuture.completedFuture(new MastershipEvent(eventType, deviceId, getMastership(deviceId)));
Madan Jampani1af8e132015-04-30 16:41:18 -0700294 }
295
Madan Jampani84b6b402015-02-25 17:49:54 -0800296 @Override
297 public void relinquishAllRole(NodeId nodeId) {
Madan Jampani620f70d2016-01-30 22:22:47 -0800298 // Noop. LeadershipService already takes care of detecting and purging stale locks.
Madan Jampani84b6b402015-02-25 17:49:54 -0800299 }
300
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700301 private MastershipInfo buildMastershipFromLeadership(Leadership leadership) {
302 ImmutableMap.Builder<NodeId, MastershipRole> builder = ImmutableMap.builder();
303 if (leadership.leaderNodeId() != null) {
304 builder.put(leadership.leaderNodeId(), MastershipRole.MASTER);
305 }
306 leadership.candidates().stream()
307 .filter(nodeId -> !Objects.equals(leadership.leaderNodeId(), nodeId))
308 .forEach(nodeId -> builder.put(nodeId, MastershipRole.STANDBY));
309 clusterService.getNodes().stream()
310 .filter(node -> !Objects.equals(leadership.leaderNodeId(), node.id()))
311 .filter(node -> !leadership.candidates().contains(node.id()))
312 .forEach(node -> builder.put(node.id(), MastershipRole.NONE));
313
314 return new MastershipInfo(
315 leadership.leader() != null ? leadership.leader().term() : 0,
316 leadership.leader() != null
317 ? Optional.of(leadership.leader().nodeId())
318 : Optional.empty(),
319 builder.build());
320 }
321
Madan Jampani84b6b402015-02-25 17:49:54 -0800322 private class InternalDeviceMastershipEventListener implements LeadershipEventListener {
Madan Jampani620f70d2016-01-30 22:22:47 -0800323
324 @Override
325 public boolean isRelevant(LeadershipEvent event) {
326 Leadership leadership = event.subject();
327 return isDeviceMastershipTopic(leadership.topic());
328 }
329
Madan Jampani84b6b402015-02-25 17:49:54 -0800330 @Override
331 public void event(LeadershipEvent event) {
Madan Jampani71c32ca2016-06-22 08:23:18 -0700332 eventHandler.execute(() -> handleEvent(event));
333 }
334
335 private void handleEvent(LeadershipEvent event) {
Madan Jampani84b6b402015-02-25 17:49:54 -0800336 Leadership leadership = event.subject();
Madan Jampani84b6b402015-02-25 17:49:54 -0800337 DeviceId deviceId = extractDeviceIdFromTopic(leadership.topic());
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700338 MastershipInfo mastershipInfo = event.type() != LeadershipEvent.Type.SERVICE_DISRUPTED
339 ? buildMastershipFromLeadership(event.subject())
340 : new MastershipInfo();
341
Thomas Vachuska4b839c72015-05-18 15:43:03 -0700342 switch (event.type()) {
Jordan Haltermana1ccbc32017-12-15 17:07:52 -0800343 case LEADER_AND_CANDIDATES_CHANGED:
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700344 notifyDelegate(new MastershipEvent(BACKUPS_CHANGED, deviceId, mastershipInfo));
345 notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, mastershipInfo));
Jordan Haltermana1ccbc32017-12-15 17:07:52 -0800346 break;
347 case LEADER_CHANGED:
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700348 notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, mastershipInfo));
Jordan Haltermana1ccbc32017-12-15 17:07:52 -0800349 break;
350 case CANDIDATES_CHANGED:
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700351 notifyDelegate(new MastershipEvent(BACKUPS_CHANGED, deviceId, mastershipInfo));
Jordan Haltermana1ccbc32017-12-15 17:07:52 -0800352 break;
353 case SERVICE_DISRUPTED:
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700354 notifyDelegate(new MastershipEvent(SUSPENDED, deviceId, mastershipInfo));
Jordan Haltermana1ccbc32017-12-15 17:07:52 -0800355 break;
356 case SERVICE_RESTORED:
Andrea Campanella80b296d2018-09-18 10:48:15 +0200357 notifyDelegate(new MastershipEvent(RESTORED, deviceId, mastershipInfo));
Jordan Haltermana1ccbc32017-12-15 17:07:52 -0800358 break;
359 default:
360 return;
Madan Jampani84b6b402015-02-25 17:49:54 -0800361 }
362 }
363 }
364
365 private String createDeviceMastershipTopic(DeviceId deviceId) {
Madan Jampani5756c352015-04-29 00:23:58 -0700366 return String.format("device:%s", deviceId.toString());
Madan Jampani84b6b402015-02-25 17:49:54 -0800367 }
368
369 private DeviceId extractDeviceIdFromTopic(String topic) {
370 Matcher m = DEVICE_MASTERSHIP_TOPIC_PATTERN.matcher(topic);
371 if (m.matches()) {
372 return DeviceId.deviceId(m.group(1));
373 } else {
374 throw new IllegalArgumentException("Invalid device mastership topic: " + topic);
375 }
376 }
377
378 private boolean isDeviceMastershipTopic(String topic) {
379 Matcher m = DEVICE_MASTERSHIP_TOPIC_PATTERN.matcher(topic);
380 return m.matches();
381 }
Madan Jampanidbe8a812016-01-31 21:10:46 -0800382}