blob: 58249961af98db49a0e5689ce98cb07a97de2888 [file] [log] [blame]
Brian O'Connor66630c82014-10-02 21:08:19 -07001package org.onlab.onos.net.intent.impl;
2
alshabib8ca53902014-10-07 13:11:17 -07003import static com.google.common.base.Preconditions.checkNotNull;
4import static java.util.concurrent.Executors.newSingleThreadExecutor;
5import static org.onlab.onos.net.intent.IntentState.COMPILING;
6import static org.onlab.onos.net.intent.IntentState.FAILED;
7import static org.onlab.onos.net.intent.IntentState.INSTALLED;
8import static org.onlab.onos.net.intent.IntentState.INSTALLING;
9import static org.onlab.onos.net.intent.IntentState.RECOMPILING;
10import static org.onlab.onos.net.intent.IntentState.WITHDRAWING;
11import static org.onlab.onos.net.intent.IntentState.WITHDRAWN;
12import static org.onlab.util.Tools.namedThreads;
13import static org.slf4j.LoggerFactory.getLogger;
14
15import java.util.ArrayList;
Brian O'Connorcb900f42014-10-07 21:55:33 -070016import java.util.Iterator;
alshabib8ca53902014-10-07 13:11:17 -070017import java.util.List;
18import java.util.Map;
19import java.util.Objects;
20import java.util.concurrent.ConcurrentHashMap;
21import java.util.concurrent.ConcurrentMap;
alshabib26834582014-10-08 20:15:46 -070022import java.util.concurrent.ExecutionException;
alshabib8ca53902014-10-07 13:11:17 -070023import java.util.concurrent.ExecutorService;
Brian O'Connorcb900f42014-10-07 21:55:33 -070024import java.util.concurrent.Future;
alshabib26834582014-10-08 20:15:46 -070025import java.util.concurrent.TimeUnit;
26import java.util.concurrent.TimeoutException;
alshabib8ca53902014-10-07 13:11:17 -070027
Brian O'Connor66630c82014-10-02 21:08:19 -070028import org.apache.felix.scr.annotations.Activate;
29import org.apache.felix.scr.annotations.Component;
30import org.apache.felix.scr.annotations.Deactivate;
31import org.apache.felix.scr.annotations.Reference;
32import org.apache.felix.scr.annotations.ReferenceCardinality;
33import org.apache.felix.scr.annotations.Service;
34import org.onlab.onos.event.AbstractListenerRegistry;
35import org.onlab.onos.event.EventDeliveryService;
Brian O'Connorcb900f42014-10-07 21:55:33 -070036import org.onlab.onos.net.flow.CompletedBatchOperation;
Brian O'Connor66630c82014-10-02 21:08:19 -070037import org.onlab.onos.net.intent.InstallableIntent;
38import org.onlab.onos.net.intent.Intent;
39import org.onlab.onos.net.intent.IntentCompiler;
40import org.onlab.onos.net.intent.IntentEvent;
41import org.onlab.onos.net.intent.IntentException;
42import org.onlab.onos.net.intent.IntentExtensionService;
43import org.onlab.onos.net.intent.IntentId;
44import org.onlab.onos.net.intent.IntentInstaller;
45import org.onlab.onos.net.intent.IntentListener;
46import org.onlab.onos.net.intent.IntentOperations;
47import org.onlab.onos.net.intent.IntentService;
48import org.onlab.onos.net.intent.IntentState;
49import org.onlab.onos.net.intent.IntentStore;
50import org.onlab.onos.net.intent.IntentStoreDelegate;
51import org.slf4j.Logger;
52
Brian O'Connorcb900f42014-10-07 21:55:33 -070053import com.google.common.collect.ImmutableList;
alshabib8ca53902014-10-07 13:11:17 -070054import com.google.common.collect.ImmutableMap;
Brian O'Connorcb900f42014-10-07 21:55:33 -070055import com.google.common.collect.Lists;
Brian O'Connor66630c82014-10-02 21:08:19 -070056
57/**
58 * An implementation of Intent Manager.
59 */
60@Component(immediate = true)
61@Service
62public class IntentManager
63 implements IntentService, IntentExtensionService {
64 private final Logger log = getLogger(getClass());
65
66 public static final String INTENT_NULL = "Intent cannot be null";
67 public static final String INTENT_ID_NULL = "Intent ID cannot be null";
68
69 // Collections for compiler, installer, and listener are ONOS instance local
70 private final ConcurrentMap<Class<? extends Intent>,
71 IntentCompiler<? extends Intent>> compilers = new ConcurrentHashMap<>();
72 private final ConcurrentMap<Class<? extends InstallableIntent>,
73 IntentInstaller<? extends InstallableIntent>> installers = new ConcurrentHashMap<>();
Brian O'Connor66630c82014-10-02 21:08:19 -070074
75 private final AbstractListenerRegistry<IntentEvent, IntentListener>
tom95329eb2014-10-06 08:40:06 -070076 listenerRegistry = new AbstractListenerRegistry<>();
Brian O'Connor66630c82014-10-02 21:08:19 -070077
Brian O'Connorcb900f42014-10-07 21:55:33 -070078 private ExecutorService executor;
79 private ExecutorService monitorExecutor;
tom85258ee2014-10-07 00:10:02 -070080
Brian O'Connor66630c82014-10-02 21:08:19 -070081 private final IntentStoreDelegate delegate = new InternalStoreDelegate();
tom95329eb2014-10-06 08:40:06 -070082 private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate();
Brian O'Connor66630c82014-10-02 21:08:19 -070083
84 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 protected IntentStore store;
86
87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom85258ee2014-10-07 00:10:02 -070088 protected ObjectiveTrackerService trackerService;
tom95329eb2014-10-06 08:40:06 -070089
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Brian O'Connor66630c82014-10-02 21:08:19 -070091 protected EventDeliveryService eventDispatcher;
92
93 @Activate
94 public void activate() {
95 store.setDelegate(delegate);
tom95329eb2014-10-06 08:40:06 -070096 trackerService.setDelegate(topoDelegate);
Brian O'Connor66630c82014-10-02 21:08:19 -070097 eventDispatcher.addSink(IntentEvent.class, listenerRegistry);
Brian O'Connorcb900f42014-10-07 21:55:33 -070098 executor = newSingleThreadExecutor(namedThreads("onos-intents"));
99 monitorExecutor = newSingleThreadExecutor(namedThreads("onos-intent-monitor"));
Brian O'Connor66630c82014-10-02 21:08:19 -0700100 log.info("Started");
101 }
102
103 @Deactivate
104 public void deactivate() {
105 store.unsetDelegate(delegate);
tom95329eb2014-10-06 08:40:06 -0700106 trackerService.unsetDelegate(topoDelegate);
Brian O'Connor66630c82014-10-02 21:08:19 -0700107 eventDispatcher.removeSink(IntentEvent.class);
Brian O'Connorcb900f42014-10-07 21:55:33 -0700108 executor.shutdown();
109 monitorExecutor.shutdown();
Brian O'Connor66630c82014-10-02 21:08:19 -0700110 log.info("Stopped");
111 }
112
113 @Override
114 public void submit(Intent intent) {
115 checkNotNull(intent, INTENT_NULL);
116 registerSubclassCompilerIfNeeded(intent);
117 IntentEvent event = store.createIntent(intent);
tom85258ee2014-10-07 00:10:02 -0700118 if (event != null) {
119 eventDispatcher.post(event);
120 executor.execute(new IntentTask(COMPILING, intent));
121 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700122 }
123
124 @Override
125 public void withdraw(Intent intent) {
126 checkNotNull(intent, INTENT_NULL);
tom85258ee2014-10-07 00:10:02 -0700127 executor.execute(new IntentTask(WITHDRAWING, intent));
Brian O'Connor66630c82014-10-02 21:08:19 -0700128 }
129
130 // FIXME: implement this method
131 @Override
132 public void execute(IntentOperations operations) {
133 throw new UnsupportedOperationException("execute() is not implemented yet");
134 }
135
136 @Override
137 public Iterable<Intent> getIntents() {
138 return store.getIntents();
139 }
140
141 @Override
142 public long getIntentCount() {
143 return store.getIntentCount();
144 }
145
146 @Override
147 public Intent getIntent(IntentId id) {
148 checkNotNull(id, INTENT_ID_NULL);
149 return store.getIntent(id);
150 }
151
152 @Override
153 public IntentState getIntentState(IntentId id) {
154 checkNotNull(id, INTENT_ID_NULL);
155 return store.getIntentState(id);
156 }
157
158 @Override
159 public void addListener(IntentListener listener) {
160 listenerRegistry.addListener(listener);
161 }
162
163 @Override
164 public void removeListener(IntentListener listener) {
165 listenerRegistry.removeListener(listener);
166 }
167
168 @Override
169 public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) {
170 compilers.put(cls, compiler);
171 }
172
173 @Override
174 public <T extends Intent> void unregisterCompiler(Class<T> cls) {
175 compilers.remove(cls);
176 }
177
178 @Override
179 public Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers() {
180 return ImmutableMap.copyOf(compilers);
181 }
182
183 @Override
184 public <T extends InstallableIntent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer) {
185 installers.put(cls, installer);
186 }
187
188 @Override
189 public <T extends InstallableIntent> void unregisterInstaller(Class<T> cls) {
190 installers.remove(cls);
191 }
192
193 @Override
194 public Map<Class<? extends InstallableIntent>, IntentInstaller<? extends InstallableIntent>> getInstallers() {
195 return ImmutableMap.copyOf(installers);
196 }
197
198 /**
Brian O'Connor66630c82014-10-02 21:08:19 -0700199 * Returns the corresponding intent compiler to the specified intent.
200 *
201 * @param intent intent
tom95329eb2014-10-06 08:40:06 -0700202 * @param <T> the type of intent
Brian O'Connor66630c82014-10-02 21:08:19 -0700203 * @return intent compiler corresponding to the specified intent
204 */
205 private <T extends Intent> IntentCompiler<T> getCompiler(T intent) {
206 @SuppressWarnings("unchecked")
207 IntentCompiler<T> compiler = (IntentCompiler<T>) compilers.get(intent.getClass());
208 if (compiler == null) {
209 throw new IntentException("no compiler for class " + intent.getClass());
210 }
211 return compiler;
212 }
213
214 /**
215 * Returns the corresponding intent installer to the specified installable intent.
tom95329eb2014-10-06 08:40:06 -0700216 *
Brian O'Connor66630c82014-10-02 21:08:19 -0700217 * @param intent intent
tom95329eb2014-10-06 08:40:06 -0700218 * @param <T> the type of installable intent
Brian O'Connor66630c82014-10-02 21:08:19 -0700219 * @return intent installer corresponding to the specified installable intent
220 */
221 private <T extends InstallableIntent> IntentInstaller<T> getInstaller(T intent) {
222 @SuppressWarnings("unchecked")
223 IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent.getClass());
224 if (installer == null) {
225 throw new IntentException("no installer for class " + intent.getClass());
226 }
227 return installer;
228 }
229
230 /**
tom85258ee2014-10-07 00:10:02 -0700231 * Compiles the specified intent.
Brian O'Connor66630c82014-10-02 21:08:19 -0700232 *
tom85258ee2014-10-07 00:10:02 -0700233 * @param intent intent to be compiled
Brian O'Connor66630c82014-10-02 21:08:19 -0700234 */
tom85258ee2014-10-07 00:10:02 -0700235 private void executeCompilingPhase(Intent intent) {
236 // Indicate that the intent is entering the compiling phase.
237 store.setState(intent, COMPILING);
238
239 try {
240 // Compile the intent into installable derivatives.
241 List<InstallableIntent> installable = compileIntent(intent);
242
243 // If all went well, associate the resulting list of installable
244 // intents with the top-level intent and proceed to install.
245 store.addInstallableIntents(intent.id(), installable);
246 executeInstallingPhase(intent);
247
248 } catch (Exception e) {
tom53945d52014-10-07 11:01:36 -0700249 log.warn("Unable to compile intent {} due to: {}", intent.id(), e);
250
tom85258ee2014-10-07 00:10:02 -0700251 // If compilation failed, mark the intent as failed.
252 store.setState(intent, FAILED);
253 }
254 }
255
Brian O'Connorcb900f42014-10-07 21:55:33 -0700256 /**
257 * Compiles an intent recursively.
258 *
259 * @param intent intent
260 * @return result of compilation
261 */
tom85258ee2014-10-07 00:10:02 -0700262 private List<InstallableIntent> compileIntent(Intent intent) {
Brian O'Connorcb900f42014-10-07 21:55:33 -0700263 if (intent instanceof InstallableIntent) {
264 return ImmutableList.of((InstallableIntent) intent);
Brian O'Connor66630c82014-10-02 21:08:19 -0700265 }
Brian O'Connorcb900f42014-10-07 21:55:33 -0700266
267 List<InstallableIntent> installable = new ArrayList<>();
268 // TODO do we need to registerSubclassCompiler?
269 for (Intent compiled : getCompiler(intent).compile(intent)) {
270 installable.addAll(compileIntent(compiled));
271 }
272
tom85258ee2014-10-07 00:10:02 -0700273 return installable;
Brian O'Connor66630c82014-10-02 21:08:19 -0700274 }
275
276 /**
tom85258ee2014-10-07 00:10:02 -0700277 * Installs all installable intents associated with the specified top-level
278 * intent.
Brian O'Connor66630c82014-10-02 21:08:19 -0700279 *
tom85258ee2014-10-07 00:10:02 -0700280 * @param intent intent to be installed
Brian O'Connor66630c82014-10-02 21:08:19 -0700281 */
tom85258ee2014-10-07 00:10:02 -0700282 private void executeInstallingPhase(Intent intent) {
283 // Indicate that the intent is entering the installing phase.
284 store.setState(intent, INSTALLING);
285
Brian O'Connorcb900f42014-10-07 21:55:33 -0700286 List<Future<CompletedBatchOperation>> installFutures = Lists.newArrayList();
tom85258ee2014-10-07 00:10:02 -0700287 try {
288 List<InstallableIntent> installables = store.getInstallableIntents(intent.id());
289 if (installables != null) {
290 for (InstallableIntent installable : installables) {
291 registerSubclassInstallerIfNeeded(installable);
tom53945d52014-10-07 11:01:36 -0700292 trackerService.addTrackedResources(intent.id(),
293 installable.requiredLinks());
Brian O'Connorcb900f42014-10-07 21:55:33 -0700294 Future<CompletedBatchOperation> future = getInstaller(installable).install(installable);
295 installFutures.add(future);
tom85258ee2014-10-07 00:10:02 -0700296 }
tom95329eb2014-10-06 08:40:06 -0700297 }
Brian O'Connorcb900f42014-10-07 21:55:33 -0700298 // FIXME we have to wait for the installable intents
299 //eventDispatcher.post(store.setState(intent, INSTALLED));
300 monitorExecutor.execute(new IntentInstallMonitor(intent, installFutures, INSTALLED));
tom85258ee2014-10-07 00:10:02 -0700301 } catch (Exception e) {
tom53945d52014-10-07 11:01:36 -0700302 log.warn("Unable to install intent {} due to: {}", intent.id(), e);
Brian O'Connorcb900f42014-10-07 21:55:33 -0700303 uninstallIntent(intent, RECOMPILING);
tom53945d52014-10-07 11:01:36 -0700304
tom85258ee2014-10-07 00:10:02 -0700305 // If compilation failed, kick off the recompiling phase.
Brian O'Connorcb900f42014-10-07 21:55:33 -0700306 // FIXME
307 //executeRecompilingPhase(intent);
tom85258ee2014-10-07 00:10:02 -0700308 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700309 }
310
311 /**
tom85258ee2014-10-07 00:10:02 -0700312 * Recompiles the specified intent.
Brian O'Connor66630c82014-10-02 21:08:19 -0700313 *
tom85258ee2014-10-07 00:10:02 -0700314 * @param intent intent to be recompiled
Brian O'Connor66630c82014-10-02 21:08:19 -0700315 */
tom85258ee2014-10-07 00:10:02 -0700316 private void executeRecompilingPhase(Intent intent) {
317 // Indicate that the intent is entering the recompiling phase.
318 store.setState(intent, RECOMPILING);
319
320 try {
321 // Compile the intent into installable derivatives.
322 List<InstallableIntent> installable = compileIntent(intent);
323
324 // If all went well, compare the existing list of installable
325 // intents with the newly compiled list. If they are the same,
326 // bail, out since the previous approach was determined not to
327 // be viable.
328 List<InstallableIntent> originalInstallable =
329 store.getInstallableIntents(intent.id());
330
331 if (Objects.equals(originalInstallable, installable)) {
332 eventDispatcher.post(store.setState(intent, FAILED));
333 } else {
334 // Otherwise, re-associate the newly compiled installable intents
335 // with the top-level intent and kick off installing phase.
336 store.addInstallableIntents(intent.id(), installable);
337 executeInstallingPhase(intent);
338 }
339 } catch (Exception e) {
tom53945d52014-10-07 11:01:36 -0700340 log.warn("Unable to recompile intent {} due to: {}", intent.id(), e);
341
tom85258ee2014-10-07 00:10:02 -0700342 // If compilation failed, mark the intent as failed.
343 eventDispatcher.post(store.setState(intent, FAILED));
344 }
345 }
346
347 /**
348 * Uninstalls the specified intent by uninstalling all of its associated
349 * installable derivatives.
350 *
351 * @param intent intent to be installed
352 */
353 private void executeWithdrawingPhase(Intent intent) {
354 // Indicate that the intent is being withdrawn.
355 store.setState(intent, WITHDRAWING);
Brian O'Connorcb900f42014-10-07 21:55:33 -0700356 uninstallIntent(intent, WITHDRAWN);
tom85258ee2014-10-07 00:10:02 -0700357
358 // If all went well, disassociate the top-level intent with its
359 // installable derivatives and mark it as withdrawn.
Brian O'Connorcb900f42014-10-07 21:55:33 -0700360 // FIXME need to clean up
361 //store.removeInstalledIntents(intent.id());
362 // FIXME
363 //eventDispatcher.post(store.setState(intent, WITHDRAWN));
Brian O'Connor66630c82014-10-02 21:08:19 -0700364 }
365
366 /**
tom53945d52014-10-07 11:01:36 -0700367 * Uninstalls all installable intents associated with the given intent.
368 *
369 * @param intent intent to be uninstalled
370 */
Brian O'Connorcb900f42014-10-07 21:55:33 -0700371 private void uninstallIntent(Intent intent, IntentState nextState) {
372 List<Future<CompletedBatchOperation>> uninstallFutures = Lists.newArrayList();
tom53945d52014-10-07 11:01:36 -0700373 try {
374 List<InstallableIntent> installables = store.getInstallableIntents(intent.id());
375 if (installables != null) {
376 for (InstallableIntent installable : installables) {
Brian O'Connorcb900f42014-10-07 21:55:33 -0700377 Future<CompletedBatchOperation> future = getInstaller(installable).uninstall(installable);
378 uninstallFutures.add(future);
tom53945d52014-10-07 11:01:36 -0700379 }
380 }
Brian O'Connorcb900f42014-10-07 21:55:33 -0700381 monitorExecutor.execute(new IntentInstallMonitor(intent, uninstallFutures, nextState));
tom53945d52014-10-07 11:01:36 -0700382 } catch (IntentException e) {
383 log.warn("Unable to uninstall intent {} due to: {}", intent.id(), e);
384 }
385 }
386
387 /**
Brian O'Connor66630c82014-10-02 21:08:19 -0700388 * Registers an intent compiler of the specified intent if an intent compiler
389 * for the intent is not registered. This method traverses the class hierarchy of
390 * the intent. Once an intent compiler for a parent type is found, this method
391 * registers the found intent compiler.
392 *
393 * @param intent intent
394 */
395 private void registerSubclassCompilerIfNeeded(Intent intent) {
396 if (!compilers.containsKey(intent.getClass())) {
397 Class<?> cls = intent.getClass();
398 while (cls != Object.class) {
399 // As long as we're within the Intent class descendants
400 if (Intent.class.isAssignableFrom(cls)) {
401 IntentCompiler<?> compiler = compilers.get(cls);
402 if (compiler != null) {
403 compilers.put(intent.getClass(), compiler);
404 return;
405 }
406 }
407 cls = cls.getSuperclass();
408 }
409 }
410 }
411
412 /**
413 * Registers an intent installer of the specified intent if an intent installer
414 * for the intent is not registered. This method traverses the class hierarchy of
415 * the intent. Once an intent installer for a parent type is found, this method
416 * registers the found intent installer.
417 *
418 * @param intent intent
419 */
420 private void registerSubclassInstallerIfNeeded(InstallableIntent intent) {
421 if (!installers.containsKey(intent.getClass())) {
422 Class<?> cls = intent.getClass();
423 while (cls != Object.class) {
424 // As long as we're within the InstallableIntent class descendants
425 if (InstallableIntent.class.isAssignableFrom(cls)) {
426 IntentInstaller<?> installer = installers.get(cls);
427 if (installer != null) {
428 installers.put(intent.getClass(), installer);
429 return;
430 }
431 }
432 cls = cls.getSuperclass();
433 }
434 }
435 }
436
Brian O'Connor66630c82014-10-02 21:08:19 -0700437 // Store delegate to re-post events emitted from the store.
438 private class InternalStoreDelegate implements IntentStoreDelegate {
439 @Override
440 public void notify(IntentEvent event) {
tom85258ee2014-10-07 00:10:02 -0700441 eventDispatcher.post(event);
442 if (event.type() == IntentEvent.Type.SUBMITTED) {
443 executor.execute(new IntentTask(COMPILING, event.subject()));
444 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700445 }
446 }
447
tom95329eb2014-10-06 08:40:06 -0700448 // Topology change delegate
449 private class InternalTopoChangeDelegate implements TopologyChangeDelegate {
450 @Override
tom85258ee2014-10-07 00:10:02 -0700451 public void triggerCompile(Iterable<IntentId> intentIds,
452 boolean compileAllFailed) {
453 // Attempt recompilation of the specified intents first.
tom95329eb2014-10-06 08:40:06 -0700454 for (IntentId intentId : intentIds) {
tom53945d52014-10-07 11:01:36 -0700455 Intent intent = getIntent(intentId);
Brian O'Connorcb900f42014-10-07 21:55:33 -0700456 uninstallIntent(intent, RECOMPILING);
alshabib8ca53902014-10-07 13:11:17 -0700457
Brian O'Connorcb900f42014-10-07 21:55:33 -0700458 //FIXME
459 //executeRecompilingPhase(intent);
tom85258ee2014-10-07 00:10:02 -0700460 }
461
462 if (compileAllFailed) {
463 // If required, compile all currently failed intents.
464 for (Intent intent : getIntents()) {
465 if (getIntentState(intent.id()) == FAILED) {
466 executeCompilingPhase(intent);
467 }
468 }
tom95329eb2014-10-06 08:40:06 -0700469 }
470 }
tom95329eb2014-10-06 08:40:06 -0700471 }
tom85258ee2014-10-07 00:10:02 -0700472
473 // Auxiliary runnable to perform asynchronous tasks.
474 private class IntentTask implements Runnable {
475 private final IntentState state;
476 private final Intent intent;
477
478 public IntentTask(IntentState state, Intent intent) {
479 this.state = state;
480 this.intent = intent;
481 }
482
483 @Override
484 public void run() {
485 if (state == COMPILING) {
486 executeCompilingPhase(intent);
487 } else if (state == RECOMPILING) {
488 executeRecompilingPhase(intent);
489 } else if (state == WITHDRAWING) {
490 executeWithdrawingPhase(intent);
491 }
492 }
493 }
494
Brian O'Connorcb900f42014-10-07 21:55:33 -0700495 private class IntentInstallMonitor implements Runnable {
496
497 private final Intent intent;
498 private final List<Future<CompletedBatchOperation>> futures;
499 private final IntentState nextState;
500
501 public IntentInstallMonitor(Intent intent,
502 List<Future<CompletedBatchOperation>> futures, IntentState nextState) {
503 this.intent = intent;
504 this.futures = futures;
505 this.nextState = nextState;
506 }
507
508 private void updateIntent(Intent intent) {
509 if (nextState == RECOMPILING) {
510 executor.execute(new IntentTask(nextState, intent));
511 } else if (nextState == INSTALLED || nextState == WITHDRAWN) {
512 eventDispatcher.post(store.setState(intent, nextState));
513 } else {
514 log.warn("Invalid next intent state {} for intent {}", nextState, intent);
515 }
516 }
517
518 @Override
519 public void run() {
520 for (Iterator<Future<CompletedBatchOperation>> i = futures.iterator(); i.hasNext();) {
521 Future<CompletedBatchOperation> future = i.next();
alshabib26834582014-10-08 20:15:46 -0700522 try {
523 // TODO: we may want to get the future here and go back to the future.
alshabibc7e1cb62014-10-08 20:20:03 -0700524 CompletedBatchOperation completed = future.get(100, TimeUnit.NANOSECONDS);
525 // TODO check if future succeeded and if not report fail items
Brian O'Connorcb900f42014-10-07 21:55:33 -0700526 i.remove();
alshabib26834582014-10-08 20:15:46 -0700527
528 } catch (TimeoutException | InterruptedException | ExecutionException te) {
529 log.debug("Intallations of intent {} is still pending", intent);
Brian O'Connorcb900f42014-10-07 21:55:33 -0700530 }
531 }
532 if (futures.isEmpty()) {
533 updateIntent(intent);
534 } else {
535 // resubmit ourselves if we are not done yet
536 monitorExecutor.submit(this);
537 }
538 }
539 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700540}