blob: 50e86bd16913e7f1e689eb248ce6acea0a4402cc [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
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;
Brian O'Connor66630c82014-10-02 21:08:19 -070017
Brian O'Connor64a0369d2015-02-20 22:02:59 -080018import com.google.common.collect.ImmutableList;
Brian O'Connor66630c82014-10-02 21:08:19 -070019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.apache.felix.scr.annotations.Service;
Brian O'Connorabafb502014-12-02 22:26:20 -080025import org.onosproject.core.CoreService;
26import org.onosproject.core.IdGenerator;
27import org.onosproject.event.AbstractListenerRegistry;
28import org.onosproject.event.EventDeliveryService;
Brian O'Connor0e271dc2015-02-04 18:20:25 -080029import org.onosproject.net.flow.FlowRuleOperations;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.net.flow.FlowRuleService;
31import org.onosproject.net.intent.Intent;
32import org.onosproject.net.intent.IntentBatchDelegate;
Brian O'Connorabafb502014-12-02 22:26:20 -080033import org.onosproject.net.intent.IntentCompiler;
Brian O'Connorcff03322015-02-03 15:28:59 -080034import org.onosproject.net.intent.IntentData;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.net.intent.IntentEvent;
Brian O'Connorabafb502014-12-02 22:26:20 -080036import org.onosproject.net.intent.IntentExtensionService;
Brian O'Connorabafb502014-12-02 22:26:20 -080037import org.onosproject.net.intent.IntentInstaller;
38import org.onosproject.net.intent.IntentListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080039import org.onosproject.net.intent.IntentService;
40import org.onosproject.net.intent.IntentState;
41import org.onosproject.net.intent.IntentStore;
Brian O'Connorabafb502014-12-02 22:26:20 -080042import org.onosproject.net.intent.IntentStoreDelegate;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080043import org.onosproject.net.intent.Key;
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -080044import org.onosproject.net.intent.impl.phase.CompilingFailed;
45import org.onosproject.net.intent.impl.phase.FinalIntentProcessPhase;
46import org.onosproject.net.intent.impl.phase.InstallRequest;
47import org.onosproject.net.intent.impl.phase.IntentProcessPhase;
48import org.onosproject.net.intent.impl.phase.WithdrawRequest;
49import org.onosproject.net.intent.impl.phase.Withdrawn;
Brian O'Connor66630c82014-10-02 21:08:19 -070050import org.slf4j.Logger;
51
Brian O'Connor64a0369d2015-02-20 22:02:59 -080052import java.util.Collection;
Brian O'Connor64a0369d2015-02-20 22:02:59 -080053import java.util.EnumSet;
Brian O'Connor64a0369d2015-02-20 22:02:59 -080054import java.util.List;
55import java.util.Map;
56import java.util.Optional;
57import java.util.concurrent.Callable;
Brian O'Connor64a0369d2015-02-20 22:02:59 -080058import java.util.concurrent.ExecutionException;
59import java.util.concurrent.ExecutorService;
60import java.util.concurrent.Future;
61import java.util.stream.Collectors;
Brian O'Connorfa81eae2014-10-30 13:20:05 -070062
Brian O'Connorfa81eae2014-10-30 13:20:05 -070063import static com.google.common.base.Preconditions.checkNotNull;
Yuta HIGUCHIc2bf3d82014-11-28 18:50:41 -080064import static java.util.concurrent.Executors.newFixedThreadPool;
Brian O'Connordb15b042015-02-04 14:59:28 -080065import static java.util.concurrent.Executors.newSingleThreadExecutor;
Brian O'Connorbdc7f002015-02-18 20:49:41 -080066import static org.onlab.util.Tools.groupedThreads;
Brian O'Connore2eac102015-02-12 18:30:22 -080067import static org.onlab.util.Tools.isNullOrEmpty;
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -080068import static org.onosproject.net.intent.IntentState.FAILED;
69import static org.onosproject.net.intent.IntentState.INSTALL_REQ;
70import static org.onosproject.net.intent.IntentState.WITHDRAWN;
71import static org.onosproject.net.intent.IntentState.WITHDRAW_REQ;
Brian O'Connorfa81eae2014-10-30 13:20:05 -070072import static org.slf4j.LoggerFactory.getLogger;
Brian O'Connor66630c82014-10-02 21:08:19 -070073
74/**
75 * An implementation of Intent Manager.
76 */
77@Component(immediate = true)
78@Service
79public class IntentManager
80 implements IntentService, IntentExtensionService {
Sho SHIMIZU8b5051d2014-11-05 11:24:13 -080081 private static final Logger log = getLogger(IntentManager.class);
Brian O'Connor66630c82014-10-02 21:08:19 -070082
83 public static final String INTENT_NULL = "Intent cannot be null";
Ray Milkeyf9af43c2015-02-09 16:45:48 -080084 public static final String INTENT_ID_NULL = "Intent key cannot be null";
Brian O'Connor66630c82014-10-02 21:08:19 -070085
Yuta HIGUCHIc2bf3d82014-11-28 18:50:41 -080086 private static final int NUM_THREADS = 12;
87
Brian O'Connor7a71d5d2014-12-02 00:12:27 -080088 private static final EnumSet<IntentState> RECOMPILE
89 = EnumSet.of(INSTALL_REQ, FAILED, WITHDRAW_REQ);
Brian O'Connor7a71d5d2014-12-02 00:12:27 -080090
Brian O'Connor66630c82014-10-02 21:08:19 -070091 private final AbstractListenerRegistry<IntentEvent, IntentListener>
tom95329eb2014-10-06 08:40:06 -070092 listenerRegistry = new AbstractListenerRegistry<>();
Brian O'Connor66630c82014-10-02 21:08:19 -070093
Brian O'Connor520c0522014-11-23 23:50:47 -080094 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected CoreService coreService;
Brian O'Connor66630c82014-10-02 21:08:19 -070096
97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
98 protected IntentStore store;
99
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom85258ee2014-10-07 00:10:02 -0700101 protected ObjectiveTrackerService trackerService;
tom95329eb2014-10-06 08:40:06 -0700102
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Brian O'Connor66630c82014-10-02 21:08:19 -0700104 protected EventDeliveryService eventDispatcher;
105
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800106 // TODO: make this protected due to short term hack for ONOS-1051
Brian O'Connorf2dbde52014-10-10 16:20:24 -0700107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800108 public FlowRuleService flowRuleService;
Brian O'Connorf2dbde52014-10-10 16:20:24 -0700109
Brian O'Connor520c0522014-11-23 23:50:47 -0800110
Brian O'Connordb15b042015-02-04 14:59:28 -0800111 private ExecutorService batchExecutor;
112 private ExecutorService workerExecutor;
Brian O'Connor520c0522014-11-23 23:50:47 -0800113
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800114 private final CompilerRegistry compilerRegistry = new CompilerRegistry();
115 private final InstallerRegistry installerRegistry = new InstallerRegistry();
116 private final InternalIntentProcessor processor = new InternalIntentProcessor();
Brian O'Connor520c0522014-11-23 23:50:47 -0800117 private final IntentStoreDelegate delegate = new InternalStoreDelegate();
118 private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate();
119 private final IntentBatchDelegate batchDelegate = new InternalBatchDelegate();
120 private IdGenerator idGenerator;
121
Brian O'Connorb499b352015-02-03 16:46:15 -0800122 private final IntentAccumulator accumulator = new IntentAccumulator(batchDelegate);
Brian O'Connorcff03322015-02-03 15:28:59 -0800123
Brian O'Connor66630c82014-10-02 21:08:19 -0700124 @Activate
125 public void activate() {
126 store.setDelegate(delegate);
tom95329eb2014-10-06 08:40:06 -0700127 trackerService.setDelegate(topoDelegate);
Brian O'Connor66630c82014-10-02 21:08:19 -0700128 eventDispatcher.addSink(IntentEvent.class, listenerRegistry);
Brian O'Connorbdc7f002015-02-18 20:49:41 -0800129 batchExecutor = newSingleThreadExecutor(groupedThreads("onos/intent", "batch"));
130 workerExecutor = newFixedThreadPool(NUM_THREADS, groupedThreads("onos/intent", "worker-%d"));
Brian O'Connor520c0522014-11-23 23:50:47 -0800131 idGenerator = coreService.getIdGenerator("intent-ids");
132 Intent.bindIdGenerator(idGenerator);
Brian O'Connor66630c82014-10-02 21:08:19 -0700133 log.info("Started");
134 }
135
136 @Deactivate
137 public void deactivate() {
138 store.unsetDelegate(delegate);
tom95329eb2014-10-06 08:40:06 -0700139 trackerService.unsetDelegate(topoDelegate);
Brian O'Connor66630c82014-10-02 21:08:19 -0700140 eventDispatcher.removeSink(IntentEvent.class);
Brian O'Connordb15b042015-02-04 14:59:28 -0800141 batchExecutor.shutdown();
Brian O'Connor520c0522014-11-23 23:50:47 -0800142 Intent.unbindIdGenerator(idGenerator);
Brian O'Connor66630c82014-10-02 21:08:19 -0700143 log.info("Stopped");
144 }
145
146 @Override
147 public void submit(Intent intent) {
148 checkNotNull(intent, INTENT_NULL);
Brian O'Connorcff03322015-02-03 15:28:59 -0800149 IntentData data = new IntentData(intent, IntentState.INSTALL_REQ, null);
Brian O'Connorcff03322015-02-03 15:28:59 -0800150 store.addPending(data);
Brian O'Connor66630c82014-10-02 21:08:19 -0700151 }
152
153 @Override
154 public void withdraw(Intent intent) {
155 checkNotNull(intent, INTENT_NULL);
Brian O'Connorcff03322015-02-03 15:28:59 -0800156 IntentData data = new IntentData(intent, IntentState.WITHDRAW_REQ, null);
Brian O'Connorcff03322015-02-03 15:28:59 -0800157 store.addPending(data);
Brian O'Connor66630c82014-10-02 21:08:19 -0700158 }
159
Brian O'Connor66630c82014-10-02 21:08:19 -0700160 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800161 public Intent getIntent(Key key) {
162 return store.getIntent(key);
163 }
164
165 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700166 public Iterable<Intent> getIntents() {
167 return store.getIntents();
168 }
169
170 @Override
171 public long getIntentCount() {
172 return store.getIntentCount();
173 }
174
175 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800176 public IntentState getIntentState(Key intentKey) {
177 checkNotNull(intentKey, INTENT_ID_NULL);
178 return store.getIntentState(intentKey);
Brian O'Connor66630c82014-10-02 21:08:19 -0700179 }
180
181 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800182 public List<Intent> getInstallableIntents(Key intentKey) {
183 checkNotNull(intentKey, INTENT_ID_NULL);
184 return store.getInstallableIntents(intentKey);
Thomas Vachuska10d4abc2014-10-21 12:47:26 -0700185 }
186
187 @Override
Brian O'Connorbe28a872015-02-19 21:44:37 -0800188 public boolean isLocal(Key intentKey) {
189 return store.isMaster(intentKey);
190 }
191
192 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700193 public void addListener(IntentListener listener) {
194 listenerRegistry.addListener(listener);
195 }
196
197 @Override
198 public void removeListener(IntentListener listener) {
199 listenerRegistry.removeListener(listener);
200 }
201
202 @Override
203 public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800204 compilerRegistry.registerCompiler(cls, compiler);
Brian O'Connor66630c82014-10-02 21:08:19 -0700205 }
206
207 @Override
208 public <T extends Intent> void unregisterCompiler(Class<T> cls) {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800209 compilerRegistry.unregisterCompiler(cls);
Brian O'Connor66630c82014-10-02 21:08:19 -0700210 }
211
212 @Override
213 public Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers() {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800214 return compilerRegistry.getCompilers();
Brian O'Connor66630c82014-10-02 21:08:19 -0700215 }
216
217 @Override
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700218 public <T extends Intent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer) {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800219 installerRegistry.registerInstaller(cls, installer);
Brian O'Connor66630c82014-10-02 21:08:19 -0700220 }
221
222 @Override
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700223 public <T extends Intent> void unregisterInstaller(Class<T> cls) {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800224 installerRegistry.unregisterInstaller(cls);
Brian O'Connor66630c82014-10-02 21:08:19 -0700225 }
226
227 @Override
Thomas Vachuskab97cf282014-10-20 23:31:12 -0700228 public Map<Class<? extends Intent>, IntentInstaller<? extends Intent>> getInstallers() {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800229 return installerRegistry.getInstallers();
Brian O'Connor66630c82014-10-02 21:08:19 -0700230 }
231
Brian O'Connor66630c82014-10-02 21:08:19 -0700232 // Store delegate to re-post events emitted from the store.
233 private class InternalStoreDelegate implements IntentStoreDelegate {
234 @Override
235 public void notify(IntentEvent event) {
tom85258ee2014-10-07 00:10:02 -0700236 eventDispatcher.post(event);
Brian O'Connor66630c82014-10-02 21:08:19 -0700237 }
Brian O'Connorea4d7d12015-01-28 16:37:46 -0800238
239 @Override
Brian O'Connorcff03322015-02-03 15:28:59 -0800240 public void process(IntentData data) {
241 accumulator.add(data);
Brian O'Connorea4d7d12015-01-28 16:37:46 -0800242 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700243 }
244
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800245 private void buildAndSubmitBatches(Iterable<Key> intentKeys,
Brian O'Connor72a034c2014-11-26 18:24:23 -0800246 boolean compileAllFailed) {
Brian O'Connor72a034c2014-11-26 18:24:23 -0800247 // Attempt recompilation of the specified intents first.
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800248 for (Key key : intentKeys) {
249 Intent intent = store.getIntent(key);
Brian O'Connor72a034c2014-11-26 18:24:23 -0800250 if (intent == null) {
251 continue;
252 }
Brian O'Connor03406a42015-02-03 17:28:57 -0800253 submit(intent);
Brian O'Connor72a034c2014-11-26 18:24:23 -0800254 }
255
256 if (compileAllFailed) {
257 // If required, compile all currently failed intents.
258 for (Intent intent : getIntents()) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800259 IntentState state = getIntentState(intent.key());
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800260 if (RECOMPILE.contains(state)) {
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800261 if (state == WITHDRAW_REQ) {
Brian O'Connor03406a42015-02-03 17:28:57 -0800262 withdraw(intent);
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800263 } else {
Brian O'Connor03406a42015-02-03 17:28:57 -0800264 submit(intent);
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800265 }
Brian O'Connor72a034c2014-11-26 18:24:23 -0800266 }
267 }
268 }
269
Brian O'Connorb499b352015-02-03 16:46:15 -0800270 //FIXME
271// for (ApplicationId appId : batches.keySet()) {
272// if (batchService.isLocalLeader(appId)) {
273// execute(batches.get(appId).build());
274// }
275// }
Brian O'Connor72a034c2014-11-26 18:24:23 -0800276 }
277
tom95329eb2014-10-06 08:40:06 -0700278 // Topology change delegate
279 private class InternalTopoChangeDelegate implements TopologyChangeDelegate {
280 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800281 public void triggerCompile(Iterable<Key> intentKeys,
tom85258ee2014-10-07 00:10:02 -0700282 boolean compileAllFailed) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800283 buildAndSubmitBatches(intentKeys, compileAllFailed);
tom95329eb2014-10-06 08:40:06 -0700284 }
tom95329eb2014-10-06 08:40:06 -0700285 }
tom85258ee2014-10-07 00:10:02 -0700286
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800287 private Future<FinalIntentProcessPhase> submitIntentData(IntentData data) {
Sho SHIMIZU0cb6fe62015-02-23 16:39:57 -0800288 IntentData current = store.getIntentData(data.key());
289 return workerExecutor.submit(new IntentWorker(data, current));
Sho SHIMIZU8d9d1362015-02-04 12:28:15 -0800290 }
291
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800292 private class IntentBatchPreprocess implements Runnable {
293
294 // TODO make this configurable
295 private static final int TIMEOUT_PER_OP = 500; // ms
296 protected static final int MAX_ATTEMPTS = 3;
297
Sho SHIMIZU5f281a42015-02-04 15:29:11 -0800298 protected final Collection<IntentData> data;
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800299
300 // future holding current FlowRuleBatch installation result
301 protected final long startTime = System.currentTimeMillis();
302 protected final long endTime;
303
Sho SHIMIZU5f281a42015-02-04 15:29:11 -0800304 private IntentBatchPreprocess(Collection<IntentData> data, long endTime) {
305 this.data = checkNotNull(data);
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800306 this.endTime = endTime;
307 }
308
Sho SHIMIZU5f281a42015-02-04 15:29:11 -0800309 public IntentBatchPreprocess(Collection<IntentData> data) {
310 this(data, System.currentTimeMillis() + data.size() * TIMEOUT_PER_OP);
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800311 }
312
313 // FIXME compute reasonable timeouts
314 protected long calculateTimeoutLimit() {
Sho SHIMIZU5f281a42015-02-04 15:29:11 -0800315 return System.currentTimeMillis() + data.size() * TIMEOUT_PER_OP;
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800316 }
317
318 @Override
319 public void run() {
320 try {
Brian O'Connor0e271dc2015-02-04 18:20:25 -0800321 /*
322 1. wrap each intentdata in a runnable and submit
323 2. wait for completion of all the work
324 3. accumulate results and submit batch write of IntentData to store
325 (we can also try to update these individually)
326 */
327 submitUpdates(waitForFutures(createIntentUpdates()));
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800328 } catch (Exception e) {
329 log.error("Error submitting batches:", e);
330 // FIXME incomplete Intents should be cleaned up
331 // (transition to FAILED, etc.)
332
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800333 // the batch has failed
334 // TODO: maybe we should do more?
335 log.error("Walk the plank, matey...");
Brian O'Connorb499b352015-02-03 16:46:15 -0800336 //FIXME
Sho SHIMIZU5f281a42015-02-04 15:29:11 -0800337// batchService.removeIntentOperations(data);
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800338 }
339 }
340
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800341 private List<Future<FinalIntentProcessPhase>> createIntentUpdates() {
Sho SHIMIZU5f281a42015-02-04 15:29:11 -0800342 return data.stream()
Brian O'Connor0e271dc2015-02-04 18:20:25 -0800343 .map(IntentManager.this::submitIntentData)
344 .collect(Collectors.toList());
345 }
346
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800347 private List<FinalIntentProcessPhase> waitForFutures(List<Future<FinalIntentProcessPhase>> futures) {
348 ImmutableList.Builder<FinalIntentProcessPhase> updateBuilder = ImmutableList.builder();
349 for (Future<FinalIntentProcessPhase> future : futures) {
Brian O'Connor0e271dc2015-02-04 18:20:25 -0800350 try {
351 updateBuilder.add(future.get());
352 } catch (InterruptedException | ExecutionException e) {
353 //FIXME
354 log.warn("Future failed: {}", e);
355 }
356 }
357 return updateBuilder.build();
358 }
359
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800360 private void submitUpdates(List<FinalIntentProcessPhase> updates) {
Brian O'Connor0e271dc2015-02-04 18:20:25 -0800361 store.batchWrite(updates.stream()
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800362 .map(FinalIntentProcessPhase::data)
Brian O'Connor0e271dc2015-02-04 18:20:25 -0800363 .collect(Collectors.toList()));
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800364 }
Sho SHIMIZUadf8c482014-12-12 18:23:29 -0800365 }
Yuta HIGUCHIc2bf3d82014-11-28 18:50:41 -0800366
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800367 private final class IntentWorker implements Callable<FinalIntentProcessPhase> {
Brian O'Connordb15b042015-02-04 14:59:28 -0800368
369 private final IntentData data;
Sho SHIMIZU0cb6fe62015-02-23 16:39:57 -0800370 private final IntentData current;
Brian O'Connordb15b042015-02-04 14:59:28 -0800371
Sho SHIMIZU0cb6fe62015-02-23 16:39:57 -0800372 private IntentWorker(IntentData data, IntentData current) {
373 this.data = checkNotNull(data);
374 this.current = current;
Brian O'Connordb15b042015-02-04 14:59:28 -0800375 }
376
377 @Override
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800378 public FinalIntentProcessPhase call() throws Exception {
Sho SHIMIZU0cb6fe62015-02-23 16:39:57 -0800379 IntentProcessPhase update = createIntentUpdate();
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800380 Optional<IntentProcessPhase> currentPhase = Optional.of(update);
381 IntentProcessPhase previousPhase = update;
Brian O'Connordb15b042015-02-04 14:59:28 -0800382
383 while (currentPhase.isPresent()) {
384 previousPhase = currentPhase.get();
385 currentPhase = previousPhase.execute();
386 }
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -0800387 return (FinalIntentProcessPhase) previousPhase;
Brian O'Connor427a1762014-11-19 18:40:32 -0800388 }
Sho SHIMIZUb413be82015-02-23 16:25:48 -0800389
Sho SHIMIZU0cb6fe62015-02-23 16:39:57 -0800390 private IntentProcessPhase createIntentUpdate() {
391 switch (data.state()) {
Sho SHIMIZUb413be82015-02-23 16:25:48 -0800392 case INSTALL_REQ:
Sho SHIMIZU0cb6fe62015-02-23 16:39:57 -0800393 return new InstallRequest(processor, data, Optional.ofNullable(current));
Sho SHIMIZUb413be82015-02-23 16:25:48 -0800394 case WITHDRAW_REQ:
395 if (current == null || isNullOrEmpty(current.installables())) {
Sho SHIMIZU0cb6fe62015-02-23 16:39:57 -0800396 return new Withdrawn(data, WITHDRAWN);
Sho SHIMIZUb413be82015-02-23 16:25:48 -0800397 } else {
Sho SHIMIZU0cb6fe62015-02-23 16:39:57 -0800398 return new WithdrawRequest(processor, data, current);
Sho SHIMIZUb413be82015-02-23 16:25:48 -0800399 }
400 default:
401 // illegal state
Sho SHIMIZU0cb6fe62015-02-23 16:39:57 -0800402 return new CompilingFailed(data);
Sho SHIMIZUb413be82015-02-23 16:25:48 -0800403 }
404 }
Brian O'Connorcb900f42014-10-07 21:55:33 -0700405 }
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700406
407 private class InternalBatchDelegate implements IntentBatchDelegate {
408 @Override
Brian O'Connorb499b352015-02-03 16:46:15 -0800409 public void execute(Collection<IntentData> operations) {
Brian O'Connorab8ef822015-02-17 18:08:54 -0800410 log.debug("Execute {} operation(s).", operations.size());
411 log.trace("Execute operations: {}", operations);
Brian O'Connordb15b042015-02-04 14:59:28 -0800412 batchExecutor.execute(new IntentBatchPreprocess(operations));
413 // TODO ensure that only one batch is in flight at a time
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700414 }
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700415 }
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800416
417 private class InternalIntentProcessor implements IntentProcessor {
418 @Override
419 public List<Intent> compile(Intent intent, List<Intent> previousInstallables) {
420 return compilerRegistry.compile(intent, previousInstallables);
421 }
422
423 @Override
424 public FlowRuleOperations coordinate(IntentData current, IntentData pending) {
425 return installerRegistry.coordinate(current, pending, store, trackerService);
426 }
427
428 @Override
429 public FlowRuleOperations uninstallCoordinate(IntentData current, IntentData pending) {
430 return installerRegistry.uninstallCoordinate(current, pending, store, trackerService);
431 }
432
433 @Override
434 public void applyFlowRules(FlowRuleOperations flowRules) {
435 flowRuleService.apply(flowRules);
436 }
437 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700438}