blob: 16f05d6e8addc7141bd7c70332ac4cd3d23af784 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Sho SHIMIZU89925242016-01-13 14:20:34 -08002 * Copyright 2014-2016 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;
Brian O'Connor66630c82014-10-02 21:08:19 -070017
Brian O'Connor66630c82014-10-02 21:08:19 -070018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
Sho SHIMIZU4cee50f2016-02-23 16:24:42 -080021import org.apache.felix.scr.annotations.Modified;
22import org.apache.felix.scr.annotations.Property;
Brian O'Connor66630c82014-10-02 21:08:19 -070023import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.apache.felix.scr.annotations.Service;
Sho SHIMIZUe0981722016-01-14 16:02:48 -080026import org.onlab.util.Tools;
Sho SHIMIZUd5bf1062016-02-25 10:26:02 -080027import org.onosproject.cfg.ComponentConfigService;
Brian O'Connorabafb502014-12-02 22:26:20 -080028import org.onosproject.core.CoreService;
29import org.onosproject.core.IdGenerator;
Sho SHIMIZU98c0a392016-01-14 18:40:53 -080030import org.onosproject.event.AbstractListenerManager;
Brian O'Connorabafb502014-12-02 22:26:20 -080031import org.onosproject.net.flow.FlowRuleService;
Thomas Vachuskaf6ec97b2016-02-22 10:59:23 -080032import org.onosproject.net.flowobjective.FlowObjectiveService;
Brian O'Connorabafb502014-12-02 22:26:20 -080033import org.onosproject.net.intent.Intent;
34import org.onosproject.net.intent.IntentBatchDelegate;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.net.intent.IntentCompiler;
Brian O'Connorcff03322015-02-03 15:28:59 -080036import org.onosproject.net.intent.IntentData;
Brian O'Connorabafb502014-12-02 22:26:20 -080037import org.onosproject.net.intent.IntentEvent;
Brian O'Connorabafb502014-12-02 22:26:20 -080038import org.onosproject.net.intent.IntentExtensionService;
Brian O'Connorabafb502014-12-02 22:26:20 -080039import org.onosproject.net.intent.IntentListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.intent.IntentService;
41import org.onosproject.net.intent.IntentState;
42import org.onosproject.net.intent.IntentStore;
Brian O'Connorabafb502014-12-02 22:26:20 -080043import org.onosproject.net.intent.IntentStoreDelegate;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080044import org.onosproject.net.intent.Key;
Sho SHIMIZU36a8a6e2015-02-13 15:38:45 -080045import org.onosproject.net.intent.impl.phase.FinalIntentProcessPhase;
Sho SHIMIZUce49b602015-02-23 19:15:49 -080046import org.onosproject.net.intent.impl.phase.IntentProcessPhase;
Naoki Shiotabbc7ead2016-01-20 14:10:38 -080047import org.onosproject.net.newresource.ResourceService;
Sho SHIMIZU4cee50f2016-02-23 16:24:42 -080048import org.osgi.service.component.ComponentContext;
Brian O'Connor66630c82014-10-02 21:08:19 -070049import org.slf4j.Logger;
50
Brian O'Connorf0c5a052015-04-27 00:34:53 -070051import java.util.Collection;
52import java.util.EnumSet;
53import java.util.List;
54import java.util.Map;
Sho SHIMIZUab541a52016-01-13 23:29:32 -080055import java.util.Objects;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070056import java.util.Optional;
Sho SHIMIZUad8ab272016-01-13 22:08:58 -080057import java.util.concurrent.CompletableFuture;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070058import java.util.concurrent.ExecutorService;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070059import java.util.stream.Collectors;
Brian O'Connorfa81eae2014-10-30 13:20:05 -070060
Brian O'Connorfa81eae2014-10-30 13:20:05 -070061import static com.google.common.base.Preconditions.checkNotNull;
Sho SHIMIZU4cee50f2016-02-23 16:24:42 -080062import static com.google.common.base.Strings.isNullOrEmpty;
Yuta HIGUCHIc2bf3d82014-11-28 18:50:41 -080063import static java.util.concurrent.Executors.newFixedThreadPool;
Brian O'Connordb15b042015-02-04 14:59:28 -080064import static java.util.concurrent.Executors.newSingleThreadExecutor;
Brian O'Connorbdc7f002015-02-18 20:49:41 -080065import static org.onlab.util.Tools.groupedThreads;
Thomas Vachuskaf6ec97b2016-02-22 10:59:23 -080066import static org.onosproject.net.intent.IntentState.*;
Jonathan Hart96c5a4a2015-07-31 14:23:33 -070067import static org.onosproject.net.intent.constraint.PartialFailureConstraint.intentAllowsPartialFailure;
Sho SHIMIZUce49b602015-02-23 19:15:49 -080068import static org.onosproject.net.intent.impl.phase.IntentProcessPhase.newInitialPhase;
Changhoon Yoon541ef712015-05-23 17:18:34 +090069import static org.onosproject.security.AppGuard.checkPermission;
Sho SHIMIZU98c0a392016-01-14 18:40:53 -080070import static org.onosproject.security.AppPermission.Type.INTENT_READ;
71import static org.onosproject.security.AppPermission.Type.INTENT_WRITE;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070072import static org.slf4j.LoggerFactory.getLogger;
Changhoon Yoonb856b812015-08-10 03:47:19 +090073
Brian O'Connor66630c82014-10-02 21:08:19 -070074/**
Brian O'Connorce2d8b52015-07-29 16:24:13 -070075 * An implementation of intent service.
Brian O'Connor66630c82014-10-02 21:08:19 -070076 */
77@Component(immediate = true)
78@Service
79public class IntentManager
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070080 extends AbstractListenerManager<IntentEvent, IntentListener>
Brian O'Connor66630c82014-10-02 21:08:19 -070081 implements IntentService, IntentExtensionService {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070082
Sho SHIMIZU8b5051d2014-11-05 11:24:13 -080083 private static final Logger log = getLogger(IntentManager.class);
Brian O'Connor66630c82014-10-02 21:08:19 -070084
85 public static final String INTENT_NULL = "Intent cannot be null";
Ray Milkeyf9af43c2015-02-09 16:45:48 -080086 public static final String INTENT_ID_NULL = "Intent key cannot be null";
Brian O'Connor66630c82014-10-02 21:08:19 -070087
Yuta HIGUCHIc2bf3d82014-11-28 18:50:41 -080088 private static final int NUM_THREADS = 12;
89
Brian O'Connor7a71d5d2014-12-02 00:12:27 -080090 private static final EnumSet<IntentState> RECOMPILE
91 = EnumSet.of(INSTALL_REQ, FAILED, WITHDRAW_REQ);
Jonathan Hart96c5a4a2015-07-31 14:23:33 -070092 private static final EnumSet<IntentState> WITHDRAW
93 = EnumSet.of(WITHDRAW_REQ, WITHDRAWING, WITHDRAWN);
Sho SHIMIZU4cee50f2016-02-23 16:24:42 -080094 private static final boolean DEFAULT_SKIP_RELEASE_RESOURCES_ON_WITHDRAWAL = false;
95
96 @Property(name = "skipReleaseResourcesOnWithdrawal",
97 boolValue = DEFAULT_SKIP_RELEASE_RESOURCES_ON_WITHDRAWAL,
98 label = "Indicates whether skipping resource releases on withdrawal is enabled or not")
99 private boolean skipReleaseResourcesOnWithdrawal = DEFAULT_SKIP_RELEASE_RESOURCES_ON_WITHDRAWAL;
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800100
Brian O'Connor520c0522014-11-23 23:50:47 -0800101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected CoreService coreService;
Brian O'Connor66630c82014-10-02 21:08:19 -0700103
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected IntentStore store;
106
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom85258ee2014-10-07 00:10:02 -0700108 protected ObjectiveTrackerService trackerService;
tom95329eb2014-10-06 08:40:06 -0700109
110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Sho SHIMIZU214ac322015-02-23 19:30:15 -0800111 protected FlowRuleService flowRuleService;
Brian O'Connorf2dbde52014-10-10 16:20:24 -0700112
Naoki Shiotabbc7ead2016-01-20 14:10:38 -0800113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Thomas Vachuskaf6ec97b2016-02-22 10:59:23 -0800114 protected FlowObjectiveService flowObjectiveService;
115
116 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Naoki Shiotabbc7ead2016-01-20 14:10:38 -0800117 protected ResourceService resourceService;
118
Sho SHIMIZUd5bf1062016-02-25 10:26:02 -0800119 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
120 protected ComponentConfigService configService;
121
122
Brian O'Connordb15b042015-02-04 14:59:28 -0800123 private ExecutorService batchExecutor;
124 private ExecutorService workerExecutor;
Brian O'Connor520c0522014-11-23 23:50:47 -0800125
Thomas Vachuskaf6ec97b2016-02-22 10:59:23 -0800126 private final IntentInstaller intentInstaller = new IntentInstaller();
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800127 private final CompilerRegistry compilerRegistry = new CompilerRegistry();
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800128 private final InternalIntentProcessor processor = new InternalIntentProcessor();
Brian O'Connor520c0522014-11-23 23:50:47 -0800129 private final IntentStoreDelegate delegate = new InternalStoreDelegate();
Sho SHIMIZU4cee50f2016-02-23 16:24:42 -0800130 private final IntentStoreDelegate testOnlyDelegate = new TestOnlyIntentStoreDelegate();
Brian O'Connor520c0522014-11-23 23:50:47 -0800131 private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate();
132 private final IntentBatchDelegate batchDelegate = new InternalBatchDelegate();
133 private IdGenerator idGenerator;
134
Brian O'Connorb499b352015-02-03 16:46:15 -0800135 private final IntentAccumulator accumulator = new IntentAccumulator(batchDelegate);
Brian O'Connorcff03322015-02-03 15:28:59 -0800136
Brian O'Connor66630c82014-10-02 21:08:19 -0700137 @Activate
138 public void activate() {
Sho SHIMIZUd5bf1062016-02-25 10:26:02 -0800139 configService.registerProperties(getClass());
140
Thomas Vachuskaf6ec97b2016-02-22 10:59:23 -0800141 intentInstaller.init(store, trackerService, flowRuleService, flowObjectiveService);
Sho SHIMIZU4cee50f2016-02-23 16:24:42 -0800142 if (skipReleaseResourcesOnWithdrawal) {
143 store.setDelegate(testOnlyDelegate);
144 } else {
145 store.setDelegate(delegate);
146 }
tom95329eb2014-10-06 08:40:06 -0700147 trackerService.setDelegate(topoDelegate);
Brian O'Connor66630c82014-10-02 21:08:19 -0700148 eventDispatcher.addSink(IntentEvent.class, listenerRegistry);
Brian O'Connorbdc7f002015-02-18 20:49:41 -0800149 batchExecutor = newSingleThreadExecutor(groupedThreads("onos/intent", "batch"));
150 workerExecutor = newFixedThreadPool(NUM_THREADS, groupedThreads("onos/intent", "worker-%d"));
Brian O'Connor520c0522014-11-23 23:50:47 -0800151 idGenerator = coreService.getIdGenerator("intent-ids");
152 Intent.bindIdGenerator(idGenerator);
Brian O'Connor66630c82014-10-02 21:08:19 -0700153 log.info("Started");
154 }
155
156 @Deactivate
157 public void deactivate() {
Thomas Vachuskaf6ec97b2016-02-22 10:59:23 -0800158 intentInstaller.init(null, null, null, null);
Sho SHIMIZU4cee50f2016-02-23 16:24:42 -0800159 if (skipReleaseResourcesOnWithdrawal) {
160 store.unsetDelegate(testOnlyDelegate);
161 } else {
162 store.unsetDelegate(delegate);
163 }
Sho SHIMIZUd5bf1062016-02-25 10:26:02 -0800164 configService.unregisterProperties(getClass(), false);
tom95329eb2014-10-06 08:40:06 -0700165 trackerService.unsetDelegate(topoDelegate);
Brian O'Connor66630c82014-10-02 21:08:19 -0700166 eventDispatcher.removeSink(IntentEvent.class);
Brian O'Connordb15b042015-02-04 14:59:28 -0800167 batchExecutor.shutdown();
Brian O'Connor3c58e962015-04-28 23:21:51 -0700168 workerExecutor.shutdown();
Brian O'Connor520c0522014-11-23 23:50:47 -0800169 Intent.unbindIdGenerator(idGenerator);
Brian O'Connor66630c82014-10-02 21:08:19 -0700170 log.info("Stopped");
171 }
172
Sho SHIMIZU4cee50f2016-02-23 16:24:42 -0800173 @Modified
174 public void modified(ComponentContext context) {
175 if (context == null) {
176 skipReleaseResourcesOnWithdrawal = DEFAULT_SKIP_RELEASE_RESOURCES_ON_WITHDRAWAL;
177 logConfig("Default config");
178 return;
179 }
180
181 String s = Tools.get(context.getProperties(), "skipReleaseResourcesOnWithdrawal");
182 boolean newTestEnabled = isNullOrEmpty(s) ? skipReleaseResourcesOnWithdrawal : Boolean.parseBoolean(s.trim());
183 if (skipReleaseResourcesOnWithdrawal && !newTestEnabled) {
184 store.unsetDelegate(testOnlyDelegate);
185 store.setDelegate(delegate);
186 logConfig("Reconfigured");
187 } else if (!skipReleaseResourcesOnWithdrawal && newTestEnabled) {
188 store.unsetDelegate(delegate);
189 store.setDelegate(testOnlyDelegate);
190 logConfig("Reconfigured");
191 }
192 }
193
194 private void logConfig(String prefix) {
195 log.info("{} with skipReleaseResourcesOnWithdrawal = {}", prefix, skipReleaseResourcesOnWithdrawal);
196 }
197
Brian O'Connor66630c82014-10-02 21:08:19 -0700198 @Override
199 public void submit(Intent intent) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900200 checkPermission(INTENT_WRITE);
Brian O'Connor66630c82014-10-02 21:08:19 -0700201 checkNotNull(intent, INTENT_NULL);
Brian O'Connorcff03322015-02-03 15:28:59 -0800202 IntentData data = new IntentData(intent, IntentState.INSTALL_REQ, null);
Brian O'Connorcff03322015-02-03 15:28:59 -0800203 store.addPending(data);
Brian O'Connor66630c82014-10-02 21:08:19 -0700204 }
205
206 @Override
207 public void withdraw(Intent intent) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900208 checkPermission(INTENT_WRITE);
Brian O'Connor66630c82014-10-02 21:08:19 -0700209 checkNotNull(intent, INTENT_NULL);
Brian O'Connorcff03322015-02-03 15:28:59 -0800210 IntentData data = new IntentData(intent, IntentState.WITHDRAW_REQ, null);
Brian O'Connorcff03322015-02-03 15:28:59 -0800211 store.addPending(data);
Brian O'Connor66630c82014-10-02 21:08:19 -0700212 }
213
Brian O'Connor66630c82014-10-02 21:08:19 -0700214 @Override
Ray Milkey8c6d00e2015-03-13 14:14:34 -0700215 public void purge(Intent intent) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900216 checkPermission(INTENT_WRITE);
Ray Milkey8c6d00e2015-03-13 14:14:34 -0700217 checkNotNull(intent, INTENT_NULL);
218 IntentData data = new IntentData(intent, IntentState.PURGE_REQ, null);
219 store.addPending(data);
220 }
221
222 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800223 public Intent getIntent(Key key) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900224 checkPermission(INTENT_READ);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800225 return store.getIntent(key);
226 }
227
228 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700229 public Iterable<Intent> getIntents() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900230 checkPermission(INTENT_READ);
Brian O'Connor66630c82014-10-02 21:08:19 -0700231 return store.getIntents();
232 }
233
234 @Override
Thomas Vachuskac46af202015-06-03 16:43:27 -0700235 public Iterable<IntentData> getIntentData() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900236 checkPermission(INTENT_READ);
Thomas Vachuskac46af202015-06-03 16:43:27 -0700237 return store.getIntentData(false, 0);
238 }
239
240 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700241 public long getIntentCount() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900242 checkPermission(INTENT_READ);
Brian O'Connor66630c82014-10-02 21:08:19 -0700243 return store.getIntentCount();
244 }
245
246 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800247 public IntentState getIntentState(Key intentKey) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900248 checkPermission(INTENT_READ);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800249 checkNotNull(intentKey, INTENT_ID_NULL);
250 return store.getIntentState(intentKey);
Brian O'Connor66630c82014-10-02 21:08:19 -0700251 }
252
253 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800254 public List<Intent> getInstallableIntents(Key intentKey) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900255 checkPermission(INTENT_READ);
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800256 checkNotNull(intentKey, INTENT_ID_NULL);
257 return store.getInstallableIntents(intentKey);
Thomas Vachuska10d4abc2014-10-21 12:47:26 -0700258 }
259
260 @Override
Brian O'Connorbe28a872015-02-19 21:44:37 -0800261 public boolean isLocal(Key intentKey) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900262 checkPermission(INTENT_READ);
Brian O'Connorbe28a872015-02-19 21:44:37 -0800263 return store.isMaster(intentKey);
264 }
265
266 @Override
Brian O'Connor66630c82014-10-02 21:08:19 -0700267 public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800268 compilerRegistry.registerCompiler(cls, compiler);
Brian O'Connor66630c82014-10-02 21:08:19 -0700269 }
270
271 @Override
272 public <T extends Intent> void unregisterCompiler(Class<T> cls) {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800273 compilerRegistry.unregisterCompiler(cls);
Brian O'Connor66630c82014-10-02 21:08:19 -0700274 }
275
276 @Override
277 public Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers() {
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800278 return compilerRegistry.getCompilers();
Brian O'Connor66630c82014-10-02 21:08:19 -0700279 }
280
281 @Override
Jonathan Hart34f1e382015-02-24 16:52:23 -0800282 public Iterable<Intent> getPending() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900283 checkPermission(INTENT_READ);
Changhoon Yoon541ef712015-05-23 17:18:34 +0900284
Jonathan Hart34f1e382015-02-24 16:52:23 -0800285 return store.getPending();
286 }
287
Brian O'Connor66630c82014-10-02 21:08:19 -0700288 // Store delegate to re-post events emitted from the store.
289 private class InternalStoreDelegate implements IntentStoreDelegate {
290 @Override
291 public void notify(IntentEvent event) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700292 post(event);
Naoki Shiotabbc7ead2016-01-20 14:10:38 -0800293 switch (event.type()) {
294 case WITHDRAWN:
295 // release resources allocated to withdrawn intent
296 if (!resourceService.release(event.subject().id())) {
297 log.error("Failed to release resources allocated to {}", event.subject().id());
298 }
299 break;
300 default:
301 break;
302 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700303 }
Brian O'Connorea4d7d12015-01-28 16:37:46 -0800304
305 @Override
Brian O'Connorcff03322015-02-03 15:28:59 -0800306 public void process(IntentData data) {
307 accumulator.add(data);
Brian O'Connorea4d7d12015-01-28 16:37:46 -0800308 }
Thomas Vachuskac46af202015-06-03 16:43:27 -0700309
310 @Override
311 public void onUpdate(IntentData intentData) {
312 trackerService.trackIntent(intentData);
313 }
Brian O'Connor66630c82014-10-02 21:08:19 -0700314 }
315
Sho SHIMIZU4cee50f2016-02-23 16:24:42 -0800316 // Store delegate enabled only when performing intent throughput tests
317 private class TestOnlyIntentStoreDelegate implements IntentStoreDelegate {
318 @Override
319 public void process(IntentData data) {
320 accumulator.add(data);
321 }
322
323 @Override
324 public void onUpdate(IntentData data) {
325 trackerService.trackIntent(data);
326 }
327
328 @Override
329 public void notify(IntentEvent event) {
330 post(event);
331 }
332 }
333
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800334 private void buildAndSubmitBatches(Iterable<Key> intentKeys,
Brian O'Connor72a034c2014-11-26 18:24:23 -0800335 boolean compileAllFailed) {
Brian O'Connor72a034c2014-11-26 18:24:23 -0800336 // Attempt recompilation of the specified intents first.
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800337 for (Key key : intentKeys) {
338 Intent intent = store.getIntent(key);
Brian O'Connor72a034c2014-11-26 18:24:23 -0800339 if (intent == null) {
340 continue;
341 }
Brian O'Connor03406a42015-02-03 17:28:57 -0800342 submit(intent);
Brian O'Connor72a034c2014-11-26 18:24:23 -0800343 }
344
Jonathan Hart0cca3e82015-09-23 17:54:11 -0700345 if (compileAllFailed) {
346 // If required, compile all currently failed intents.
347 for (Intent intent : getIntents()) {
348 IntentState state = getIntentState(intent.key());
349 if (RECOMPILE.contains(state) || intentAllowsPartialFailure(intent)) {
350 if (WITHDRAW.contains(state)) {
351 withdraw(intent);
352 } else {
353 submit(intent);
354 }
Brian O'Connor72a034c2014-11-26 18:24:23 -0800355 }
356 }
357 }
Brian O'Connor72a034c2014-11-26 18:24:23 -0800358 }
359
tom95329eb2014-10-06 08:40:06 -0700360 // Topology change delegate
361 private class InternalTopoChangeDelegate implements TopologyChangeDelegate {
362 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800363 public void triggerCompile(Iterable<Key> intentKeys,
tom85258ee2014-10-07 00:10:02 -0700364 boolean compileAllFailed) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800365 buildAndSubmitBatches(intentKeys, compileAllFailed);
tom95329eb2014-10-06 08:40:06 -0700366 }
tom95329eb2014-10-06 08:40:06 -0700367 }
tom85258ee2014-10-07 00:10:02 -0700368
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700369 private class InternalBatchDelegate implements IntentBatchDelegate {
370 @Override
Brian O'Connorb499b352015-02-03 16:46:15 -0800371 public void execute(Collection<IntentData> operations) {
Brian O'Connorab8ef822015-02-17 18:08:54 -0800372 log.debug("Execute {} operation(s).", operations.size());
373 log.trace("Execute operations: {}", operations);
Sho SHIMIZU94b03b12015-04-10 14:53:13 -0700374
375 // batchExecutor is single-threaded, so only one batch is in flight at a time
Sho SHIMIZU489aa9b2016-01-14 17:19:32 -0800376 CompletableFuture.runAsync(() -> {
Sho SHIMIZU8f2b7772016-01-14 18:17:44 -0800377 // process intent until the phase reaches one of the final phases
378 List<CompletableFuture<IntentData>> futures = operations.stream()
379 .map(x -> CompletableFuture.completedFuture(x)
380 .thenApply(IntentManager.this::createInitialPhase)
Sho SHIMIZU4a141852016-01-14 18:55:40 -0800381 .thenApplyAsync(IntentProcessPhase::process, workerExecutor)
Sho SHIMIZU8f2b7772016-01-14 18:17:44 -0800382 .thenApply(FinalIntentProcessPhase::data)
383 .exceptionally(e -> {
384 //FIXME
385 log.warn("Future failed: {}", e);
386 return null;
387 })).collect(Collectors.toList());
Sho SHIMIZU62bbc602016-01-13 16:54:35 -0800388
Sho SHIMIZU8f2b7772016-01-14 18:17:44 -0800389 // write multiple data to store in order
390 store.batchWrite(Tools.allOf(futures).join().stream()
Thomas Vachuskaf6ec97b2016-02-22 10:59:23 -0800391 .filter(Objects::nonNull)
392 .collect(Collectors.toList()));
Sho SHIMIZU8f2b7772016-01-14 18:17:44 -0800393 }, batchExecutor).exceptionally(e -> {
394 log.error("Error submitting batches:", e);
395 // FIXME incomplete Intents should be cleaned up
396 // (transition to FAILED, etc.)
397
398 // the batch has failed
399 // TODO: maybe we should do more?
400 log.error("Walk the plank, matey...");
Sho SHIMIZU8f2b7772016-01-14 18:17:44 -0800401 return null;
402 }).thenRun(accumulator::ready);
403
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700404 }
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700405 }
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800406
Sho SHIMIZUc88b85e2016-01-14 18:45:14 -0800407 private IntentProcessPhase createInitialPhase(IntentData data) {
408 IntentData current = store.getIntentData(data.key());
409 return newInitialPhase(processor, data, current);
410 }
411
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800412 private class InternalIntentProcessor implements IntentProcessor {
413 @Override
414 public List<Intent> compile(Intent intent, List<Intent> previousInstallables) {
415 return compilerRegistry.compile(intent, previousInstallables);
416 }
417
418 @Override
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700419 public void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) {
Thomas Vachuskaf6ec97b2016-02-22 10:59:23 -0800420 intentInstaller.apply(toUninstall, toInstall);
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800421 }
Ray Milkeyfd7931d2015-03-30 13:58:38 -0700422 }
Sho SHIMIZUb0a47d42015-02-19 13:26:30 -0800423
Brian O'Connor66630c82014-10-02 21:08:19 -0700424}