blob: eb019102cb2a110d0916edfe05c6b98b38ef1717 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-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 */
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.SetMultimap;
Brian O'Connorabafb502014-12-02 22:26:20 -080021import org.onosproject.event.Event;
Brian O'Connorb5dcc512015-03-24 17:28:00 -070022import org.onosproject.net.DeviceId;
23import org.onosproject.net.ElementId;
24import org.onosproject.net.HostId;
Brian O'Connorabafb502014-12-02 22:26:20 -080025import org.onosproject.net.Link;
26import org.onosproject.net.LinkKey;
27import org.onosproject.net.NetworkResource;
Sho SHIMIZU44f37612015-11-25 16:23:22 -080028import org.onosproject.net.PortNumber;
Brian O'Connorb5dcc512015-03-24 17:28:00 -070029import org.onosproject.net.device.DeviceEvent;
30import org.onosproject.net.device.DeviceListener;
31import org.onosproject.net.device.DeviceService;
32import org.onosproject.net.host.HostEvent;
33import org.onosproject.net.host.HostListener;
34import org.onosproject.net.host.HostService;
Brian O'Connor69d6ac72015-05-29 16:24:06 -070035import org.onosproject.net.intent.Intent;
Thomas Vachuskac46af202015-06-03 16:43:27 -070036import org.onosproject.net.intent.IntentData;
Brian O'Connorabafb502014-12-02 22:26:20 -080037import org.onosproject.net.intent.IntentService;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080038import org.onosproject.net.intent.Key;
Yi Tseng24d9be72017-05-12 11:28:13 -070039import org.onosproject.net.intent.ObjectiveTrackerService;
40import org.onosproject.net.intent.TopologyChangeDelegate;
Madan Jampani3b8101a2016-09-15 13:22:01 -070041import org.onosproject.net.intent.WorkPartitionEvent;
42import org.onosproject.net.intent.WorkPartitionEventListener;
43import org.onosproject.net.intent.WorkPartitionService;
Brian O'Connorabafb502014-12-02 22:26:20 -080044import org.onosproject.net.link.LinkEvent;
Sho SHIMIZUe18cb122016-02-22 21:04:56 -080045import org.onosproject.net.resource.ResourceEvent;
46import org.onosproject.net.resource.ResourceListener;
47import org.onosproject.net.resource.ResourceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080048import org.onosproject.net.topology.TopologyEvent;
49import org.onosproject.net.topology.TopologyListener;
50import org.onosproject.net.topology.TopologyService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070051import org.osgi.service.component.annotations.Activate;
52import org.osgi.service.component.annotations.Component;
53import org.osgi.service.component.annotations.Deactivate;
54import org.osgi.service.component.annotations.Reference;
55import org.osgi.service.component.annotations.ReferenceCardinality;
56import org.osgi.service.component.annotations.ReferencePolicy;
tom95329eb2014-10-06 08:40:06 -070057import org.slf4j.Logger;
58
Brian O'Connor86f6f7f2014-12-01 17:02:45 -080059import java.util.Collection;
Brian O'Connorb5dcc512015-03-24 17:28:00 -070060import java.util.Collections;
Brian O'Connor86f6f7f2014-12-01 17:02:45 -080061import java.util.HashSet;
Thomas Vachuskac46af202015-06-03 16:43:27 -070062import java.util.List;
Brian O'Connor86f6f7f2014-12-01 17:02:45 -080063import java.util.Set;
64import java.util.concurrent.ExecutorService;
Brian O'Connor69d6ac72015-05-29 16:24:06 -070065import java.util.concurrent.ScheduledExecutorService;
66import java.util.concurrent.TimeUnit;
67import java.util.concurrent.atomic.AtomicBoolean;
tom95329eb2014-10-06 08:40:06 -070068
69import static com.google.common.base.Preconditions.checkArgument;
70import static com.google.common.base.Preconditions.checkNotNull;
71import static com.google.common.collect.Multimaps.synchronizedSetMultimap;
Yuta HIGUCHI1624df12016-07-21 16:54:33 -070072import static java.util.concurrent.Executors.newScheduledThreadPool;
tom95329eb2014-10-06 08:40:06 -070073import static java.util.concurrent.Executors.newSingleThreadExecutor;
Thomas Vachuska6f94ded2015-02-21 14:02:38 -080074import static org.onlab.util.Tools.groupedThreads;
Thomas Vachuskac46af202015-06-03 16:43:27 -070075import static org.onlab.util.Tools.isNullOrEmpty;
Brian O'Connorabafb502014-12-02 22:26:20 -080076import static org.onosproject.net.LinkKey.linkKey;
Thomas Vachuskac46af202015-06-03 16:43:27 -070077import static org.onosproject.net.intent.IntentState.INSTALLED;
Brian O'Connor690fd1c2015-06-04 19:50:33 -070078import static org.onosproject.net.intent.IntentState.INSTALLING;
Brian O'Connorabafb502014-12-02 22:26:20 -080079import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED;
80import static org.onosproject.net.link.LinkEvent.Type.LINK_UPDATED;
tom95329eb2014-10-06 08:40:06 -070081import static org.slf4j.LoggerFactory.getLogger;
82
83/**
84 * Entity responsible for tracking installed flows and for monitoring topology
85 * events to determine what flows are affected by topology changes.
86 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070087@Component(immediate = true, service = ObjectiveTrackerService.class)
tom85258ee2014-10-07 00:10:02 -070088public class ObjectiveTracker implements ObjectiveTrackerService {
tom95329eb2014-10-06 08:40:06 -070089
90 private final Logger log = getLogger(getClass());
91
Ray Milkeyf9af43c2015-02-09 16:45:48 -080092 private final SetMultimap<LinkKey, Key> intentsByLink =
Brian O'Connor64a0369d2015-02-20 22:02:59 -080093 //TODO this could be slow as a point of synchronization
Ray Milkeyf9af43c2015-02-09 16:45:48 -080094 synchronizedSetMultimap(HashMultimap.<LinkKey, Key>create());
tom95329eb2014-10-06 08:40:06 -070095
Brian O'Connorb5dcc512015-03-24 17:28:00 -070096 private final SetMultimap<ElementId, Key> intentsByDevice =
97 synchronizedSetMultimap(HashMultimap.<ElementId, Key>create());
98
Ray Milkeyd84f89b2018-08-17 14:54:17 -070099 @Reference(cardinality = ReferenceCardinality.MANDATORY)
tom95329eb2014-10-06 08:40:06 -0700100 protected TopologyService topologyService;
101
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700102 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800103 protected ResourceService resourceService;
Ray Milkeye97ede92014-11-20 10:43:12 -0800104
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700105 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700106 protected DeviceService deviceService;
107
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700108 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700109 protected HostService hostService;
110
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700111 @Reference(cardinality = ReferenceCardinality.OPTIONAL,
jaegonkimdc8a5562018-04-05 23:14:57 +0900112 bind = "bindComponentConfigService",
113 unbind = "unbindComponentConfigService",
114 policy = ReferencePolicy.DYNAMIC)
Ray Milkey2921abc2018-12-07 13:10:55 -0800115 protected volatile IntentService intentService;
Brian O'Connor86f6f7f2014-12-01 17:02:45 -0800116
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700117 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Madan Jampani3b8101a2016-09-15 13:22:01 -0700118 protected WorkPartitionService partitionService;
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700119
tom95329eb2014-10-06 08:40:06 -0700120 private ExecutorService executorService =
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700121 newSingleThreadExecutor(groupedThreads("onos/intent", "objectivetracker", log));
Yuta HIGUCHI1624df12016-07-21 16:54:33 -0700122 private ScheduledExecutorService executor =
123 newScheduledThreadPool(1, groupedThreads("onos/intent", "scheduledIntentUpdate", log));
tom95329eb2014-10-06 08:40:06 -0700124
125 private TopologyListener listener = new InternalTopologyListener();
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800126 private ResourceListener resourceListener = new InternalResourceListener();
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700127 private DeviceListener deviceListener = new InternalDeviceListener();
128 private HostListener hostListener = new InternalHostListener();
Madan Jampani3b8101a2016-09-15 13:22:01 -0700129 private WorkPartitionEventListener partitionListener = new InternalPartitionListener();
tom95329eb2014-10-06 08:40:06 -0700130 private TopologyChangeDelegate delegate;
131
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700132 protected final AtomicBoolean updateScheduled = new AtomicBoolean(false);
133
jaegonkimdc8a5562018-04-05 23:14:57 +0900134 /**
135 * Hook for wiring up optional reference to a service.
136 *
137 * @param service service being announced
138 */
139 protected void bindComponentConfigService(IntentService service) {
140 if (intentService == null) {
141 intentService = service;
142 scheduleIntentUpdate(1);
143 }
144 }
145
146 /**
147 * Hook for unwiring optional reference to a service.
148 *
149 * @param service service being withdrawn
150 */
151 protected void unbindComponentConfigService(IntentService service) {
152 if (intentService == service) {
153 intentService = null;
154 }
155 }
156
tom95329eb2014-10-06 08:40:06 -0700157 @Activate
158 public void activate() {
159 topologyService.addListener(listener);
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800160 resourceService.addListener(resourceListener);
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700161 deviceService.addListener(deviceListener);
162 hostService.addListener(hostListener);
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700163 partitionService.addListener(partitionListener);
jaegonkimdc8a5562018-04-05 23:14:57 +0900164 scheduleIntentUpdate(1);
tom95329eb2014-10-06 08:40:06 -0700165 log.info("Started");
166 }
167
168 @Deactivate
169 public void deactivate() {
170 topologyService.removeListener(listener);
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800171 resourceService.removeListener(resourceListener);
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700172 deviceService.removeListener(deviceListener);
173 hostService.removeListener(hostListener);
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700174 partitionService.removeListener(partitionListener);
tom95329eb2014-10-06 08:40:06 -0700175 log.info("Stopped");
176 }
177
Brian O'Connor5d55ed42014-12-01 18:27:47 -0800178 protected void bindIntentService(IntentService service) {
179 if (intentService == null) {
180 intentService = service;
181 }
182 }
183
184 protected void unbindIntentService(IntentService service) {
185 if (intentService == service) {
186 intentService = null;
187 }
188 }
189
tom95329eb2014-10-06 08:40:06 -0700190 @Override
191 public void setDelegate(TopologyChangeDelegate delegate) {
192 checkNotNull(delegate, "Delegate cannot be null");
193 checkArgument(this.delegate == null || this.delegate == delegate,
194 "Another delegate already set");
195 this.delegate = delegate;
196 }
197
198 @Override
199 public void unsetDelegate(TopologyChangeDelegate delegate) {
200 checkArgument(this.delegate == delegate, "Not the current delegate");
201 this.delegate = null;
202 }
203
204 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800205 public void addTrackedResources(Key intentKey,
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700206 Collection<NetworkResource> resources) {
207 for (NetworkResource resource : resources) {
208 if (resource instanceof Link) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800209 intentsByLink.put(linkKey((Link) resource), intentKey);
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700210 } else if (resource instanceof ElementId) {
211 intentsByDevice.put((ElementId) resource, intentKey);
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700212 }
tom95329eb2014-10-06 08:40:06 -0700213 }
214 }
215
216 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800217 public void removeTrackedResources(Key intentKey,
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700218 Collection<NetworkResource> resources) {
219 for (NetworkResource resource : resources) {
220 if (resource instanceof Link) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800221 intentsByLink.remove(linkKey((Link) resource), intentKey);
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700222 } else if (resource instanceof ElementId) {
Sho SHIMIZUd82a4e62015-09-09 14:53:46 -0700223 intentsByDevice.remove(resource, intentKey);
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700224 }
tom95329eb2014-10-06 08:40:06 -0700225 }
226 }
227
Thomas Vachuskac46af202015-06-03 16:43:27 -0700228 @Override
229 public void trackIntent(IntentData intentData) {
230
231 //NOTE: This will be called for intents that are being added to the store
232 // locally (i.e. every intent update)
233
234 Key key = intentData.key();
235 Intent intent = intentData.intent();
236 boolean isLocal = intentService.isLocal(key);
Brian O'Connor690fd1c2015-06-04 19:50:33 -0700237 boolean isInstalled = intentData.state() == INSTALLING ||
238 intentData.state() == INSTALLED;
Thomas Vachuskac46af202015-06-03 16:43:27 -0700239 List<Intent> installables = intentData.installables();
240
241 if (log.isTraceEnabled()) {
242 log.trace("intent {}, old: {}, new: {}, installableCount: {}, resourceCount: {}",
243 key,
244 intentsByDevice.values().contains(key),
Brian O'Connor690fd1c2015-06-04 19:50:33 -0700245 isLocal && isInstalled,
Thomas Vachuskac46af202015-06-03 16:43:27 -0700246 installables.size(),
247 intent.resources().size() +
248 installables.stream()
249 .mapToLong(i -> i.resources().size()).sum());
250 }
251
252 if (isNullOrEmpty(installables) && intentData.state() == INSTALLED) {
253 log.warn("Intent {} is INSTALLED with no installables", key);
254 }
255
Brian O'Connor690fd1c2015-06-04 19:50:33 -0700256 // FIXME Intents will be added 3 times (once directly using addTracked,
257 // then when installing and when installed)
258 if (isLocal && isInstalled) {
Thomas Vachuskac46af202015-06-03 16:43:27 -0700259 addTrackedResources(key, intent.resources());
260 for (Intent installable : installables) {
261 addTrackedResources(key, installable.resources());
262 }
263 // FIXME check all resources against current topo service(s); recompile if necessary
264 } else {
265 removeTrackedResources(key, intent.resources());
266 for (Intent installable : installables) {
267 removeTrackedResources(key, installable.resources());
268 }
269 }
270 }
271
tom95329eb2014-10-06 08:40:06 -0700272 // Internal re-actor to topology change events.
273 private class InternalTopologyListener implements TopologyListener {
274 @Override
275 public void event(TopologyEvent event) {
276 executorService.execute(new TopologyChangeHandler(event));
277 }
278 }
279
280 // Re-dispatcher of topology change events.
281 private class TopologyChangeHandler implements Runnable {
282
283 private final TopologyEvent event;
284
285 TopologyChangeHandler(TopologyEvent event) {
286 this.event = event;
287 }
288
289 @Override
290 public void run() {
Thomas Vachuska7b652ad2014-10-30 14:10:51 -0700291 // If there is no delegate, why bother? Just bail.
292 if (delegate == null) {
293 return;
294 }
295
Ray Milkey7c44c052014-12-05 10:34:54 -0800296 if (event.reasons() == null || event.reasons().isEmpty()) {
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700297 delegate.triggerCompile(Collections.emptySet(), true);
tom85258ee2014-10-07 00:10:02 -0700298
tom95329eb2014-10-06 08:40:06 -0700299 } else {
Jonathan Hart96c5a4a2015-07-31 14:23:33 -0700300 Set<Key> intentsToRecompile = new HashSet<>();
301 boolean dontRecompileAllFailedIntents = true;
tom85258ee2014-10-07 00:10:02 -0700302
303 // Scan through the list of reasons and keep accruing all
304 // intents that need to be recompiled.
tom95329eb2014-10-06 08:40:06 -0700305 for (Event reason : event.reasons()) {
306 if (reason instanceof LinkEvent) {
307 LinkEvent linkEvent = (LinkEvent) reason;
Jonathan Hart96c5a4a2015-07-31 14:23:33 -0700308 final LinkKey linkKey = linkKey(linkEvent.subject());
309 synchronized (intentsByLink) {
310 Set<Key> intentKeys = intentsByLink.get(linkKey);
311 log.debug("recompile triggered by LinkEvent {} ({}) for {}",
312 linkKey, linkEvent.type(), intentKeys);
313 intentsToRecompile.addAll(intentKeys);
tom85258ee2014-10-07 00:10:02 -0700314 }
Jonathan Hart96c5a4a2015-07-31 14:23:33 -0700315 dontRecompileAllFailedIntents = dontRecompileAllFailedIntents &&
Praseed Balakrishnan00dd1f92014-11-19 17:12:36 -0800316 (linkEvent.type() == LINK_REMOVED ||
317 (linkEvent.type() == LINK_UPDATED &&
Ray Milkey8521f812017-05-24 09:49:26 -0700318 linkEvent.subject().isExpected()));
tom95329eb2014-10-06 08:40:06 -0700319 }
320 }
Jonathan Hart96c5a4a2015-07-31 14:23:33 -0700321 delegate.triggerCompile(intentsToRecompile, !dontRecompileAllFailedIntents);
tom95329eb2014-10-06 08:40:06 -0700322 }
323 }
324 }
325
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800326 private class InternalResourceListener implements ResourceListener {
Ray Milkeye97ede92014-11-20 10:43:12 -0800327 @Override
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800328 public void event(ResourceEvent event) {
Sho SHIMIZUb08d5862016-02-11 12:37:28 -0800329 if (event.subject().isSubTypeOf(PortNumber.class)) {
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800330 executorService.execute(() -> {
331 if (delegate == null) {
332 return;
333 }
Ray Milkeye97ede92014-11-20 10:43:12 -0800334
Sho SHIMIZU0b9c4682015-11-02 18:30:34 -0800335 delegate.triggerCompile(Collections.emptySet(), true);
336 });
Ray Milkeye97ede92014-11-20 10:43:12 -0800337 }
Ray Milkeye97ede92014-11-20 10:43:12 -0800338 }
339 }
340
Brian O'Connor72a034c2014-11-26 18:24:23 -0800341 //TODO consider adding flow rule event tracking
Ray Milkeye97ede92014-11-20 10:43:12 -0800342
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700343 /*
344 * Re-dispatcher of device and host events.
345 */
346 private class DeviceAvailabilityHandler implements Runnable {
347
348 private final ElementId id;
349 private final boolean available;
350
351 DeviceAvailabilityHandler(ElementId id, boolean available) {
352 this.id = checkNotNull(id);
353 this.available = available;
354 }
355
356 @Override
357 public void run() {
358 // If there is no delegate, why bother? Just bail.
359 if (delegate == null) {
360 return;
361 }
362
363 // TODO should we recompile on available==true?
HIGUCHI Yuta99b7b342015-09-29 16:54:21 -0700364
365 final ImmutableSet<Key> snapshot;
366 synchronized (intentsByDevice) {
367 snapshot = ImmutableSet.copyOf(intentsByDevice.get(id));
368 }
369 delegate.triggerCompile(snapshot, available);
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700370 }
371 }
372
373
374 private class InternalDeviceListener implements DeviceListener {
375 @Override
376 public void event(DeviceEvent event) {
377 DeviceEvent.Type type = event.type();
Jonathan Hart94470fe2015-07-31 11:41:10 -0700378 switch (type) {
379 case DEVICE_ADDED:
380 case DEVICE_AVAILABILITY_CHANGED:
381 case DEVICE_REMOVED:
382 case DEVICE_SUSPENDED:
383 case DEVICE_UPDATED:
384 DeviceId id = event.subject().id();
385 // TODO we need to check whether AVAILABILITY_CHANGED means up or down
386 boolean available = (type == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
387 type == DeviceEvent.Type.DEVICE_ADDED ||
388 type == DeviceEvent.Type.DEVICE_UPDATED);
389 executorService.execute(new DeviceAvailabilityHandler(id, available));
390 break;
391 case PORT_ADDED:
392 case PORT_REMOVED:
393 case PORT_UPDATED:
394 case PORT_STATS_UPDATED:
395 default:
396 // Don't handle port events for now
397 break;
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700398 }
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700399 }
400 }
401
402 private class InternalHostListener implements HostListener {
403 @Override
404 public void event(HostEvent event) {
405 HostId id = event.subject().id();
Brian O'Connora9c18b92015-09-28 16:03:43 -0700406 switch (event.type()) {
407 case HOST_ADDED:
408 case HOST_MOVED:
409 case HOST_REMOVED:
410 executorService.execute(new DeviceAvailabilityHandler(id, false));
411 break;
412 case HOST_UPDATED:
413 default:
414 // DO NOTHING
415 break;
416 }
Brian O'Connorb5dcc512015-03-24 17:28:00 -0700417 }
418 }
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700419
Sho SHIMIZU97a93dd2016-03-30 18:07:51 -0700420 private void doIntentUpdate() {
jaegonkimdc8a5562018-04-05 23:14:57 +0900421 synchronized (this) {
422 updateScheduled.set(false);
423 if (intentService == null) {
424 log.warn("Intent service is not bound yet");
425 return;
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700426 }
jaegonkimdc8a5562018-04-05 23:14:57 +0900427 try {
428 //FIXME very inefficient
429 for (IntentData intentData : intentService.getIntentData()) {
430 try {
431 trackIntent(intentData);
432 } catch (NullPointerException npe) {
433 log.warn("intent error {}", intentData.key(), npe);
434 }
435 }
436 } catch (Exception e) {
437 log.warn("Exception caught during update task", e);
438 }
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700439 }
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 Jampani3b8101a2016-09-15 13:22:01 -0700448 private final class InternalPartitionListener implements WorkPartitionEventListener {
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700449 @Override
Madan Jampani3b8101a2016-09-15 13:22:01 -0700450 public void event(WorkPartitionEvent event) {
Jon Hall274cecb2017-08-09 12:15:48 -0700451 log.debug("got message {}:{}", event.type(), event.subject());
Brian O'Connor69d6ac72015-05-29 16:24:06 -0700452 scheduleIntentUpdate(1);
453 }
454 }
tom95329eb2014-10-06 08:40:06 -0700455}