blob: ef1c0fd9a59a8652141bfcf86751172b42f8c621 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
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 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.intent.impl;
tom95329eb2014-10-06 08:40:06 -070017
Brian O'Connor86f6f7f2014-12-01 17:02:45 -080018import com.google.common.collect.HashMultimap;
Brian O'Connora9c18b92015-09-28 16:03:43 -070019import com.google.common.collect.ImmutableSet;
Brian O'Connor86f6f7f2014-12-01 17:02:45 -080020import com.google.common.collect.Lists;
21import com.google.common.collect.SetMultimap;
tom95329eb2014-10-06 08:40:06 -070022import org.apache.felix.scr.annotations.Activate;
23import org.apache.felix.scr.annotations.Component;
24import org.apache.felix.scr.annotations.Deactivate;
25import org.apache.felix.scr.annotations.Reference;
26import org.apache.felix.scr.annotations.ReferenceCardinality;
Brian O'Connor69d6ac72015-05-29 16:24:06 -070027import org.apache.felix.scr.annotations.ReferencePolicy;
tom95329eb2014-10-06 08:40:06 -070028import org.apache.felix.scr.annotations.Service;
Brian O'Connorabafb502014-12-02 22:26:20 -080029import org.onosproject.core.ApplicationId;
30import org.onosproject.event.Event;
Brian O'Connorb5dcc512015-03-24 17:28:00 -070031import org.onosproject.net.DeviceId;
32import org.onosproject.net.ElementId;
33import org.onosproject.net.HostId;
Brian O'Connorabafb502014-12-02 22:26:20 -080034import org.onosproject.net.Link;
35import org.onosproject.net.LinkKey;
36import org.onosproject.net.NetworkResource;
Sho SHIMIZU44f37612015-11-25 16:23:22 -080037import org.onosproject.net.PortNumber;
Brian O'Connorb5dcc512015-03-24 17:28:00 -070038import org.onosproject.net.device.DeviceEvent;
39import org.onosproject.net.device.DeviceListener;
40import org.onosproject.net.device.DeviceService;
41import org.onosproject.net.host.HostEvent;
42import org.onosproject.net.host.HostListener;
43import org.onosproject.net.host.HostService;
Brian O'Connor69d6ac72015-05-29 16:24:06 -070044import org.onosproject.net.intent.Intent;
Thomas Vachuskac46af202015-06-03 16:43:27 -070045import org.onosproject.net.intent.IntentData;
Brian O'Connorabafb502014-12-02 22:26:20 -080046import org.onosproject.net.intent.IntentService;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080047import org.onosproject.net.intent.Key;
Madan Jampani1c965102016-01-13 14:34:16 -080048import org.onosproject.net.intent.IntentPartitionEvent;
49import org.onosproject.net.intent.IntentPartitionEventListener;
50import org.onosproject.net.intent.IntentPartitionService;
Brian O'Connorabafb502014-12-02 22:26:20 -080051import org.onosproject.net.link.LinkEvent;
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -080052import org.onosproject.net.newresource.ResourceEvent;
53import org.onosproject.net.newresource.ResourceListener;
54import org.onosproject.net.newresource.ResourceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080055import org.onosproject.net.topology.TopologyEvent;
56import org.onosproject.net.topology.TopologyListener;
57import org.onosproject.net.topology.TopologyService;
tom95329eb2014-10-06 08:40:06 -070058import org.slf4j.Logger;
59
Brian O'Connor86f6f7f2014-12-01 17:02:45 -080060import java.util.Collection;
Brian O'Connorb5dcc512015-03-24 17:28:00 -070061import java.util.Collections;
Brian O'Connor86f6f7f2014-12-01 17:02:45 -080062import java.util.HashSet;
Thomas Vachuskac46af202015-06-03 16:43:27 -070063import java.util.List;
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -080064import java.util.Optional;
Brian O'Connor86f6f7f2014-12-01 17:02:45 -080065import java.util.Set;
66import java.util.concurrent.ExecutorService;
Brian O'Connor69d6ac72015-05-29 16:24:06 -070067import java.util.concurrent.Executors;
68import java.util.concurrent.ScheduledExecutorService;
69import java.util.concurrent.TimeUnit;
70import java.util.concurrent.atomic.AtomicBoolean;
tom95329eb2014-10-06 08:40:06 -070071
72import static com.google.common.base.Preconditions.checkArgument;
73import static com.google.common.base.Preconditions.checkNotNull;
74import static com.google.common.collect.Multimaps.synchronizedSetMultimap;
75import static java.util.concurrent.Executors.newSingleThreadExecutor;
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080076import static org.onlab.util.Tools.groupedThreads;
Thomas Vachuskac46af202015-06-03 16:43:27 -070077import static org.onlab.util.Tools.isNullOrEmpty;
Brian O'Connorabafb502014-12-02 22:26:20 -080078import static org.onosproject.net.LinkKey.linkKey;
Thomas Vachuskac46af202015-06-03 16:43:27 -070079import static org.onosproject.net.intent.IntentState.INSTALLED;
Brian O'Connor690fd1c2015-06-04 19:50:33 -070080import static org.onosproject.net.intent.IntentState.INSTALLING;
Brian O'Connorabafb502014-12-02 22:26:20 -080081import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED;
82import static org.onosproject.net.link.LinkEvent.Type.LINK_UPDATED;
tom95329eb2014-10-06 08:40:06 -070083import static org.slf4j.LoggerFactory.getLogger;
84
85/**
86 * Entity responsible for tracking installed flows and for monitoring topology
87 * events to determine what flows are affected by topology changes.
88 */
Ray Milkeye97ede92014-11-20 10:43:12 -080089@Component(immediate = true)
tom95329eb2014-10-06 08:40:06 -070090@Service
tom85258ee2014-10-07 00:10:02 -070091public class ObjectiveTracker implements ObjectiveTrackerService {
tom95329eb2014-10-06 08:40:06 -070092
93 private final Logger log = getLogger(getClass());
94
Ray Milkeyf9af43c2015-02-09 16:45:48 -080095 private final SetMultimap<LinkKey, Key> intentsByLink =
Brian O'Connor64a0369d2015-02-20 22:02:59 -080096 //TODO this could be slow as a point of synchronization
Ray Milkeyf9af43c2015-02-09 16:45:48 -080097 synchronizedSetMultimap(HashMultimap.<LinkKey, Key>create());
tom95329eb2014-10-06 08:40:06 -070098
Brian O'Connorb5dcc512015-03-24 17:28:00 -070099 private final SetMultimap<ElementId, Key> intentsByDevice =
100 synchronizedSetMultimap(HashMultimap.<ElementId, Key>create());
101
tom95329eb2014-10-06 08:40:06 -0700102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 protected TopologyService topologyService;
104
Ray Milkeye97ede92014-11-20 10:43:12 -0800105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800106 protected ResourceService resourceService;
Ray Milkeye97ede92014-11-20 10:43:12 -0800107
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected DeviceService deviceService;
110
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 protected HostService hostService;
113
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700114 @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY,
115 policy = ReferencePolicy.DYNAMIC)
Brian O'Connor86f6f7f2014-12-01 17:02:45 -0800116 protected IntentService intentService;
117
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Madan Jampani1c965102016-01-13 14:34:16 -0800119 protected IntentPartitionService partitionService;
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700120
tom95329eb2014-10-06 08:40:06 -0700121 private ExecutorService executorService =
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700122 newSingleThreadExecutor(groupedThreads("onos/intent", "objectivetracker"));
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700123 private ScheduledExecutorService executor = Executors
124 .newScheduledThreadPool(1);
tom95329eb2014-10-06 08:40:06 -0700125
126 private TopologyListener listener = new InternalTopologyListener();
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800127 private ResourceListener resourceListener = new InternalResourceListener();
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700128 private DeviceListener deviceListener = new InternalDeviceListener();
129 private HostListener hostListener = new InternalHostListener();
Madan Jampani1c965102016-01-13 14:34:16 -0800130 private IntentPartitionEventListener partitionListener = new InternalPartitionListener();
tom95329eb2014-10-06 08:40:06 -0700131 private TopologyChangeDelegate delegate;
132
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700133 protected final AtomicBoolean updateScheduled = new AtomicBoolean(false);
134
tom95329eb2014-10-06 08:40:06 -0700135 @Activate
136 public void activate() {
137 topologyService.addListener(listener);
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800138 resourceService.addListener(resourceListener);
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700139 deviceService.addListener(deviceListener);
140 hostService.addListener(hostListener);
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700141 partitionService.addListener(partitionListener);
tom95329eb2014-10-06 08:40:06 -0700142 log.info("Started");
143 }
144
145 @Deactivate
146 public void deactivate() {
147 topologyService.removeListener(listener);
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800148 resourceService.removeListener(resourceListener);
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700149 deviceService.removeListener(deviceListener);
150 hostService.removeListener(hostListener);
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700151 partitionService.removeListener(partitionListener);
tom95329eb2014-10-06 08:40:06 -0700152 log.info("Stopped");
153 }
154
Brian O'Connor5d55ed42014-12-01 18:27:47 -0800155 protected void bindIntentService(IntentService service) {
156 if (intentService == null) {
157 intentService = service;
158 }
159 }
160
161 protected void unbindIntentService(IntentService service) {
162 if (intentService == service) {
163 intentService = null;
164 }
165 }
166
tom95329eb2014-10-06 08:40:06 -0700167 @Override
168 public void setDelegate(TopologyChangeDelegate delegate) {
169 checkNotNull(delegate, "Delegate cannot be null");
170 checkArgument(this.delegate == null || this.delegate == delegate,
171 "Another delegate already set");
172 this.delegate = delegate;
173 }
174
175 @Override
176 public void unsetDelegate(TopologyChangeDelegate delegate) {
177 checkArgument(this.delegate == delegate, "Not the current delegate");
178 this.delegate = null;
179 }
180
181 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800182 public void addTrackedResources(Key intentKey,
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700183 Collection<NetworkResource> resources) {
184 for (NetworkResource resource : resources) {
185 if (resource instanceof Link) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800186 intentsByLink.put(linkKey((Link) resource), intentKey);
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700187 } else if (resource instanceof ElementId) {
188 intentsByDevice.put((ElementId) resource, intentKey);
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700189 }
tom95329eb2014-10-06 08:40:06 -0700190 }
191 }
192
193 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800194 public void removeTrackedResources(Key intentKey,
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700195 Collection<NetworkResource> resources) {
196 for (NetworkResource resource : resources) {
197 if (resource instanceof Link) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800198 intentsByLink.remove(linkKey((Link) resource), intentKey);
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700199 } else if (resource instanceof ElementId) {
Sho SHIMIZUd82a4e62015-09-09 14:53:46 -0700200 intentsByDevice.remove(resource, intentKey);
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700201 }
tom95329eb2014-10-06 08:40:06 -0700202 }
203 }
204
Thomas Vachuskac46af202015-06-03 16:43:27 -0700205 @Override
206 public void trackIntent(IntentData intentData) {
207
208 //NOTE: This will be called for intents that are being added to the store
209 // locally (i.e. every intent update)
210
211 Key key = intentData.key();
212 Intent intent = intentData.intent();
213 boolean isLocal = intentService.isLocal(key);
Brian O'Connor690fd1c2015-06-04 19:50:33 -0700214 boolean isInstalled = intentData.state() == INSTALLING ||
215 intentData.state() == INSTALLED;
Thomas Vachuskac46af202015-06-03 16:43:27 -0700216 List<Intent> installables = intentData.installables();
217
218 if (log.isTraceEnabled()) {
219 log.trace("intent {}, old: {}, new: {}, installableCount: {}, resourceCount: {}",
220 key,
221 intentsByDevice.values().contains(key),
Brian O'Connor690fd1c2015-06-04 19:50:33 -0700222 isLocal && isInstalled,
Thomas Vachuskac46af202015-06-03 16:43:27 -0700223 installables.size(),
224 intent.resources().size() +
225 installables.stream()
226 .mapToLong(i -> i.resources().size()).sum());
227 }
228
229 if (isNullOrEmpty(installables) && intentData.state() == INSTALLED) {
230 log.warn("Intent {} is INSTALLED with no installables", key);
231 }
232
Brian O'Connor690fd1c2015-06-04 19:50:33 -0700233 // FIXME Intents will be added 3 times (once directly using addTracked,
234 // then when installing and when installed)
235 if (isLocal && isInstalled) {
Thomas Vachuskac46af202015-06-03 16:43:27 -0700236 addTrackedResources(key, intent.resources());
237 for (Intent installable : installables) {
238 addTrackedResources(key, installable.resources());
239 }
240 // FIXME check all resources against current topo service(s); recompile if necessary
241 } else {
242 removeTrackedResources(key, intent.resources());
243 for (Intent installable : installables) {
244 removeTrackedResources(key, installable.resources());
245 }
246 }
247 }
248
tom95329eb2014-10-06 08:40:06 -0700249 // Internal re-actor to topology change events.
250 private class InternalTopologyListener implements TopologyListener {
251 @Override
252 public void event(TopologyEvent event) {
253 executorService.execute(new TopologyChangeHandler(event));
254 }
255 }
256
257 // Re-dispatcher of topology change events.
258 private class TopologyChangeHandler implements Runnable {
259
260 private final TopologyEvent event;
261
262 TopologyChangeHandler(TopologyEvent event) {
263 this.event = event;
264 }
265
266 @Override
267 public void run() {
Thomas Vachuska7b652ad2014-10-30 14:10:51 -0700268 // If there is no delegate, why bother? Just bail.
269 if (delegate == null) {
270 return;
271 }
272
Ray Milkey7c44c052014-12-05 10:34:54 -0800273 if (event.reasons() == null || event.reasons().isEmpty()) {
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700274 delegate.triggerCompile(Collections.emptySet(), true);
tom85258ee2014-10-07 00:10:02 -0700275
tom95329eb2014-10-06 08:40:06 -0700276 } else {
Jonathan Hart96c5a4a2015-07-31 14:23:33 -0700277 Set<Key> intentsToRecompile = new HashSet<>();
278 boolean dontRecompileAllFailedIntents = true;
tom85258ee2014-10-07 00:10:02 -0700279
280 // Scan through the list of reasons and keep accruing all
281 // intents that need to be recompiled.
tom95329eb2014-10-06 08:40:06 -0700282 for (Event reason : event.reasons()) {
283 if (reason instanceof LinkEvent) {
284 LinkEvent linkEvent = (LinkEvent) reason;
Jonathan Hart96c5a4a2015-07-31 14:23:33 -0700285 final LinkKey linkKey = linkKey(linkEvent.subject());
286 synchronized (intentsByLink) {
287 Set<Key> intentKeys = intentsByLink.get(linkKey);
288 log.debug("recompile triggered by LinkEvent {} ({}) for {}",
289 linkKey, linkEvent.type(), intentKeys);
290 intentsToRecompile.addAll(intentKeys);
tom85258ee2014-10-07 00:10:02 -0700291 }
Jonathan Hart96c5a4a2015-07-31 14:23:33 -0700292 dontRecompileAllFailedIntents = dontRecompileAllFailedIntents &&
Praseed Balakrishnan00dd1f92014-11-19 17:12:36 -0800293 (linkEvent.type() == LINK_REMOVED ||
294 (linkEvent.type() == LINK_UPDATED &&
295 linkEvent.subject().isDurable()));
tom95329eb2014-10-06 08:40:06 -0700296 }
297 }
Jonathan Hart96c5a4a2015-07-31 14:23:33 -0700298 delegate.triggerCompile(intentsToRecompile, !dontRecompileAllFailedIntents);
tom95329eb2014-10-06 08:40:06 -0700299 }
300 }
301 }
302
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800303 private class InternalResourceListener implements ResourceListener {
Ray Milkeye97ede92014-11-20 10:43:12 -0800304 @Override
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800305 public void event(ResourceEvent event) {
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800306 Optional<Class<?>> deviceEvent = event.subject().components().stream()
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800307 .map(Object::getClass)
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800308 .filter(x -> x == PortNumber.class)
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800309 .findFirst();
Sho SHIMIZU44f37612015-11-25 16:23:22 -0800310 if (deviceEvent.isPresent()) {
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800311 executorService.execute(() -> {
312 if (delegate == null) {
313 return;
314 }
Ray Milkeye97ede92014-11-20 10:43:12 -0800315
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800316 delegate.triggerCompile(Collections.emptySet(), true);
317 });
Ray Milkeye97ede92014-11-20 10:43:12 -0800318 }
Ray Milkeye97ede92014-11-20 10:43:12 -0800319 }
320 }
321
Brian O'Connor72a034c2014-11-26 18:24:23 -0800322 //TODO consider adding flow rule event tracking
Ray Milkeye97ede92014-11-20 10:43:12 -0800323
Brian O'Connor86f6f7f2014-12-01 17:02:45 -0800324 private void updateTrackedResources(ApplicationId appId, boolean track) {
Brian O'Connor5d55ed42014-12-01 18:27:47 -0800325 if (intentService == null) {
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700326 log.warn("Intent service is not bound yet");
Brian O'Connor5d55ed42014-12-01 18:27:47 -0800327 return;
328 }
Brian O'Connor86f6f7f2014-12-01 17:02:45 -0800329 intentService.getIntents().forEach(intent -> {
330 if (intent.appId().equals(appId)) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800331 Key key = intent.key();
Brian O'Connor86f6f7f2014-12-01 17:02:45 -0800332 Collection<NetworkResource> resources = Lists.newArrayList();
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800333 intentService.getInstallableIntents(key).stream()
Brian O'Connor86f6f7f2014-12-01 17:02:45 -0800334 .map(installable -> installable.resources())
335 .forEach(resources::addAll);
336 if (track) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800337 addTrackedResources(key, resources);
Brian O'Connor86f6f7f2014-12-01 17:02:45 -0800338 } else {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800339 removeTrackedResources(key, resources);
Brian O'Connor86f6f7f2014-12-01 17:02:45 -0800340 }
341 }
342 });
343 }
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700344
345 /*
346 * Re-dispatcher of device and host events.
347 */
348 private class DeviceAvailabilityHandler implements Runnable {
349
350 private final ElementId id;
351 private final boolean available;
352
353 DeviceAvailabilityHandler(ElementId id, boolean available) {
354 this.id = checkNotNull(id);
355 this.available = available;
356 }
357
358 @Override
359 public void run() {
360 // If there is no delegate, why bother? Just bail.
361 if (delegate == null) {
362 return;
363 }
364
365 // TODO should we recompile on available==true?
HIGUCHI Yuta99b7b342015-09-29 16:54:21 -0700366
367 final ImmutableSet<Key> snapshot;
368 synchronized (intentsByDevice) {
369 snapshot = ImmutableSet.copyOf(intentsByDevice.get(id));
370 }
371 delegate.triggerCompile(snapshot, available);
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700372 }
373 }
374
375
376 private class InternalDeviceListener implements DeviceListener {
377 @Override
378 public void event(DeviceEvent event) {
379 DeviceEvent.Type type = event.type();
Jonathan Hart94470fe2015-07-31 11:41:10 -0700380 switch (type) {
381 case DEVICE_ADDED:
382 case DEVICE_AVAILABILITY_CHANGED:
383 case DEVICE_REMOVED:
384 case DEVICE_SUSPENDED:
385 case DEVICE_UPDATED:
386 DeviceId id = event.subject().id();
387 // TODO we need to check whether AVAILABILITY_CHANGED means up or down
388 boolean available = (type == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
389 type == DeviceEvent.Type.DEVICE_ADDED ||
390 type == DeviceEvent.Type.DEVICE_UPDATED);
391 executorService.execute(new DeviceAvailabilityHandler(id, available));
392 break;
393 case PORT_ADDED:
394 case PORT_REMOVED:
395 case PORT_UPDATED:
396 case PORT_STATS_UPDATED:
397 default:
398 // Don't handle port events for now
399 break;
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700400 }
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700401 }
402 }
403
404 private class InternalHostListener implements HostListener {
405 @Override
406 public void event(HostEvent event) {
407 HostId id = event.subject().id();
Brian O'Connora9c18b92015-09-28 16:03:43 -0700408 switch (event.type()) {
409 case HOST_ADDED:
410 case HOST_MOVED:
411 case HOST_REMOVED:
412 executorService.execute(new DeviceAvailabilityHandler(id, false));
413 break;
414 case HOST_UPDATED:
415 default:
416 // DO NOTHING
417 break;
418 }
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700419 }
420 }
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700421
422 protected void doIntentUpdate() {
423 updateScheduled.set(false);
424 if (intentService == null) {
425 log.warn("Intent service is not bound yet");
426 return;
427 }
428 try {
429 //FIXME very inefficient
Thomas Vachuskac46af202015-06-03 16:43:27 -0700430 for (IntentData intentData : intentService.getIntentData()) {
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700431 try {
Thomas Vachuskac46af202015-06-03 16:43:27 -0700432 trackIntent(intentData);
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700433 } catch (NullPointerException npe) {
Thomas Vachuskac46af202015-06-03 16:43:27 -0700434 log.warn("intent error {}", intentData.key(), npe);
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700435 }
436 }
437 } catch (Exception e) {
438 log.warn("Exception caught during update task", e);
439 }
440 }
441
442 private void scheduleIntentUpdate(int afterDelaySec) {
443 if (updateScheduled.compareAndSet(false, true)) {
444 executor.schedule(this::doIntentUpdate, afterDelaySec, TimeUnit.SECONDS);
445 }
446 }
447
Madan Jampani1c965102016-01-13 14:34:16 -0800448 private final class InternalPartitionListener implements IntentPartitionEventListener {
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700449 @Override
Madan Jampani1c965102016-01-13 14:34:16 -0800450 public void event(IntentPartitionEvent event) {
Brian O'Connor3057f212015-05-29 18:22:18 -0700451 log.debug("got message {}", event.subject());
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700452 scheduleIntentUpdate(1);
453 }
454 }
tom95329eb2014-10-06 08:40:06 -0700455}