Brian O'Connor
Committed by Gerrit Code Review

Refactored intent framework to deal with batches.

There is still work to be done, but for now, submit, withdraw and reroute are working.

Change-Id: Ib94cf8c4be03786cc070f402d1f296f5dfa6588b
Showing 27 changed files with 806 additions and 229 deletions
...@@ -29,6 +29,7 @@ import org.onlab.onos.net.intent.Intent; ...@@ -29,6 +29,7 @@ import org.onlab.onos.net.intent.Intent;
29 import org.onlab.onos.net.intent.IntentEvent; 29 import org.onlab.onos.net.intent.IntentEvent;
30 import org.onlab.onos.net.intent.IntentEvent.Type; 30 import org.onlab.onos.net.intent.IntentEvent.Type;
31 import org.onlab.onos.net.intent.IntentListener; 31 import org.onlab.onos.net.intent.IntentListener;
32 +import org.onlab.onos.net.intent.IntentOperations;
32 import org.onlab.onos.net.intent.IntentService; 33 import org.onlab.onos.net.intent.IntentService;
33 import org.onlab.onos.net.intent.PointToPointIntent; 34 import org.onlab.onos.net.intent.PointToPointIntent;
34 import org.onlab.packet.Ethernet; 35 import org.onlab.packet.Ethernet;
...@@ -63,9 +64,6 @@ public class IntentPushTestCommand extends AbstractShellCommand ...@@ -63,9 +64,6 @@ public class IntentPushTestCommand extends AbstractShellCommand
63 required = true, multiValued = false) 64 required = true, multiValued = false)
64 String countString = null; 65 String countString = null;
65 66
66 -
67 - private static long id = 0x7870001;
68 -
69 private IntentService service; 67 private IntentService service;
70 private CountDownLatch latch; 68 private CountDownLatch latch;
71 private long start, end; 69 private long start, end;
...@@ -91,15 +89,18 @@ public class IntentPushTestCommand extends AbstractShellCommand ...@@ -91,15 +89,18 @@ public class IntentPushTestCommand extends AbstractShellCommand
91 service.addListener(this); 89 service.addListener(this);
92 latch = new CountDownLatch(count); 90 latch = new CountDownLatch(count);
93 91
94 - start = System.currentTimeMillis(); 92 + IntentOperations.Builder ops = IntentOperations.builder();
95 - for (int i = 0; i < count; i++) { 93 + for (int i = 1; i <= count; i++) {
96 TrafficSelector s = selector 94 TrafficSelector s = selector
97 .matchEthSrc(MacAddress.valueOf(i)) 95 .matchEthSrc(MacAddress.valueOf(i))
98 .build(); 96 .build();
99 Intent intent = new PointToPointIntent(appId(), s, treatment, 97 Intent intent = new PointToPointIntent(appId(), s, treatment,
100 ingress, egress); 98 ingress, egress);
101 - service.submit(intent); 99 + ops.addSubmitOperation(intent);
102 } 100 }
101 + IntentOperations operations = ops.build();
102 + start = System.currentTimeMillis();
103 + service.execute(operations);
103 try { 104 try {
104 if (latch.await(10, TimeUnit.SECONDS)) { 105 if (latch.await(10, TimeUnit.SECONDS)) {
105 printResults(count); 106 printResults(count);
......
...@@ -15,13 +15,13 @@ ...@@ -15,13 +15,13 @@
15 */ 15 */
16 package org.onlab.onos.net.flow; 16 package org.onlab.onos.net.flow;
17 17
18 -import static com.google.common.base.Preconditions.checkNotNull;
19 -
20 import java.util.Collection; 18 import java.util.Collection;
21 import java.util.Collections; 19 import java.util.Collections;
22 import java.util.LinkedList; 20 import java.util.LinkedList;
23 import java.util.List; 21 import java.util.List;
24 22
23 +import static com.google.common.base.Preconditions.checkNotNull;
24 +
25 /** 25 /**
26 * A list of BatchOperationEntry. 26 * A list of BatchOperationEntry.
27 * 27 *
...@@ -88,6 +88,16 @@ public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> { ...@@ -88,6 +88,16 @@ public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> {
88 return ops.add(entry) ? this : null; 88 return ops.add(entry) ? this : null;
89 } 89 }
90 90
91 + /**
92 + * Add all operations from another batch to this batch.
93 + *
94 + * @param another another batch
95 + * @return true if success
96 + */
97 + public boolean addAll(BatchOperation<T> another) {
98 + return ops.addAll(another.getOperations());
99 + }
100 +
91 @Override 101 @Override
92 public boolean equals(Object o) { 102 public boolean equals(Object o) {
93 if (this == o) { 103 if (this == o) {
......
...@@ -19,12 +19,20 @@ import java.util.Set; ...@@ -19,12 +19,20 @@ import java.util.Set;
19 19
20 import com.google.common.collect.ImmutableSet; 20 import com.google.common.collect.ImmutableSet;
21 21
22 +/**
23 + * Representation of a completed flow rule batch operation.
24 + */
22 public class CompletedBatchOperation implements BatchOperationResult<FlowRule> { 25 public class CompletedBatchOperation implements BatchOperationResult<FlowRule> {
23 26
24 -
25 private final boolean success; 27 private final boolean success;
26 private final Set<FlowRule> failures; 28 private final Set<FlowRule> failures;
27 29
30 + /**
31 + * Creates a new batch completion result.
32 + *
33 + * @param success indicates whether the completion is successful.
34 + * @param failures set of any failures encountered
35 + */
28 public CompletedBatchOperation(boolean success, Set<? extends FlowRule> failures) { 36 public CompletedBatchOperation(boolean success, Set<? extends FlowRule> failures) {
29 this.success = success; 37 this.success = success;
30 this.failures = ImmutableSet.copyOf(failures); 38 this.failures = ImmutableSet.copyOf(failures);
...@@ -40,5 +48,4 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> { ...@@ -40,5 +48,4 @@ public class CompletedBatchOperation implements BatchOperationResult<FlowRule> {
40 return failures; 48 return failures;
41 } 49 }
42 50
43 -
44 } 51 }
......
1 +/*
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 + */
16 +package org.onlab.onos.net.intent;
17 +
18 +/**
19 + * Facade for receiving notifications from the intent batch service.
20 + */
21 +public interface IntentBatchDelegate {
22 +
23 + /**
24 + * Submits the specified batch of intent operations for processing.
25 + *
26 + * @param operations batch of operations
27 + */
28 + void execute(IntentOperations operations);
29 +
30 + /**
31 + * Cancesl the specified batch of intent operations.
32 + *
33 + * @param operations batch of operations to be cancelled
34 + */
35 + void cancel(IntentOperations operations);
36 +}
1 +/*
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 + */
16 +package org.onlab.onos.net.intent;
17 +
18 +import java.util.Set;
19 +
20 +/**
21 + * Service for tracking and delegating batches of intent operations.
22 + */
23 +public interface IntentBatchService {
24 +
25 + /**
26 + * Submits a batch of intent operations.
27 + *
28 + * @param operations batch of operations
29 + */
30 + void addIntentOperations(IntentOperations operations);
31 +
32 + /**
33 + * Removes the specified batch of intent operations after completion.
34 + *
35 + * @param operations batch of operations
36 + */
37 + void removeIntentOperations(IntentOperations operations);
38 +
39 + /**
40 + * Returns the set of intent batches currently being tracked.
41 + * @return set of batches
42 + */
43 + Set<IntentOperations> getIntentOperations();
44 +
45 + /**
46 + * Sets the batch service delegate.
47 + *
48 + * @param delegate delegate to apply
49 + */
50 + void setDelegate(IntentBatchDelegate delegate);
51 +
52 + /**
53 + * Unsets the batch service delegate.
54 + *
55 + * @param delegate delegate to unset
56 + */
57 + void unsetDelegate(IntentBatchDelegate delegate);
58 +
59 +}
...@@ -15,7 +15,10 @@ ...@@ -15,7 +15,10 @@
15 */ 15 */
16 package org.onlab.onos.net.intent; 16 package org.onlab.onos.net.intent;
17 17
18 +import org.onlab.onos.net.resource.LinkResourceAllocations;
19 +
18 import java.util.List; 20 import java.util.List;
21 +import java.util.Set;
19 22
20 /** 23 /**
21 * Abstraction of a compiler which is capable of taking an intent 24 * Abstraction of a compiler which is capable of taking an intent
...@@ -28,8 +31,12 @@ public interface IntentCompiler<T extends Intent> { ...@@ -28,8 +31,12 @@ public interface IntentCompiler<T extends Intent> {
28 * Compiles the specified intent into other intents. 31 * Compiles the specified intent into other intents.
29 * 32 *
30 * @param intent intent to be compiled 33 * @param intent intent to be compiled
34 + * @param installable previously compilation result; optional
35 + * @param resources previously allocated resources; optional
31 * @return list of resulting intents 36 * @return list of resulting intents
32 * @throws IntentException if issues are encountered while compiling the intent 37 * @throws IntentException if issues are encountered while compiling the intent
33 */ 38 */
34 - List<Intent> compile(T intent); 39 + List<Intent> compile(T intent, List<Intent> installable,
40 + Set<LinkResourceAllocations> resources);
41 +
35 } 42 }
......
...@@ -15,10 +15,10 @@ ...@@ -15,10 +15,10 @@
15 */ 15 */
16 package org.onlab.onos.net.intent; 16 package org.onlab.onos.net.intent;
17 17
18 -import java.util.List;
19 -
20 import org.onlab.onos.net.flow.FlowRuleBatchOperation; 18 import org.onlab.onos.net.flow.FlowRuleBatchOperation;
21 19
20 +import java.util.List;
21 +
22 /** 22 /**
23 * Abstraction of entity capable of installing intents to the environment. 23 * Abstraction of entity capable of installing intents to the environment.
24 */ 24 */
...@@ -27,7 +27,7 @@ public interface IntentInstaller<T extends Intent> { ...@@ -27,7 +27,7 @@ public interface IntentInstaller<T extends Intent> {
27 * Installs the specified intent to the environment. 27 * Installs the specified intent to the environment.
28 * 28 *
29 * @param intent intent to be installed 29 * @param intent intent to be installed
30 - * @return FlowRule operations to install 30 + * @return flow rule operations to complete install
31 * @throws IntentException if issues are encountered while installing the intent 31 * @throws IntentException if issues are encountered while installing the intent
32 */ 32 */
33 List<FlowRuleBatchOperation> install(T intent); 33 List<FlowRuleBatchOperation> install(T intent);
...@@ -36,8 +36,19 @@ public interface IntentInstaller<T extends Intent> { ...@@ -36,8 +36,19 @@ public interface IntentInstaller<T extends Intent> {
36 * Uninstalls the specified intent from the environment. 36 * Uninstalls the specified intent from the environment.
37 * 37 *
38 * @param intent intent to be uninstalled 38 * @param intent intent to be uninstalled
39 - * @return FlowRule operations to uninstall 39 + * @return flow rule operations to complete uninstall
40 * @throws IntentException if issues are encountered while uninstalling the intent 40 * @throws IntentException if issues are encountered while uninstalling the intent
41 */ 41 */
42 List<FlowRuleBatchOperation> uninstall(T intent); 42 List<FlowRuleBatchOperation> uninstall(T intent);
43 +
44 + /**
45 + * Replaces the specified intent with a new one in the environment.
46 + *
47 + * @param oldIntent intent to be removed
48 + * @param newIntent intent to be installed
49 + * @return flow rule operations to complete the replace
50 + * @throws IntentException if issues are encountered while uninstalling the intent
51 + */
52 + List<FlowRuleBatchOperation> replace(T oldIntent, T newIntent);
53 +
43 } 54 }
......
...@@ -15,6 +15,11 @@ ...@@ -15,6 +15,11 @@
15 */ 15 */
16 package org.onlab.onos.net.intent; 16 package org.onlab.onos.net.intent;
17 17
18 +
19 +import java.util.Objects;
20 +
21 +import static com.google.common.base.MoreObjects.toStringHelper;
22 +
18 /** 23 /**
19 * Abstraction of an intent-related operation, e.g. add, remove, replace. 24 * Abstraction of an intent-related operation, e.g. add, remove, replace.
20 */ 25 */
...@@ -27,7 +32,7 @@ public class IntentOperation { ...@@ -27,7 +32,7 @@ public class IntentOperation {
27 /** 32 /**
28 * Operation type. 33 * Operation type.
29 */ 34 */
30 - enum Type { 35 + public enum Type {
31 /** 36 /**
32 * Indicates that an intent should be added. 37 * Indicates that an intent should be added.
33 */ 38 */
...@@ -41,7 +46,12 @@ public class IntentOperation { ...@@ -41,7 +46,12 @@ public class IntentOperation {
41 /** 46 /**
42 * Indicates that an intent should be replaced with another. 47 * Indicates that an intent should be replaced with another.
43 */ 48 */
44 - REPLACE 49 + REPLACE,
50 +
51 + /**
52 + * Indicates that an intent should be updated (i.e. recompiled/reinstalled).
53 + */
54 + UPDATE,
45 } 55 }
46 56
47 /** 57 /**
...@@ -85,4 +95,32 @@ public class IntentOperation { ...@@ -85,4 +95,32 @@ public class IntentOperation {
85 return intent; 95 return intent;
86 } 96 }
87 97
98 + @Override
99 + public int hashCode() {
100 + return Objects.hash(type, intentId, intent);
101 + }
102 +
103 + @Override
104 + public boolean equals(Object obj) {
105 + if (this == obj) {
106 + return true;
107 + }
108 + if (obj == null || getClass() != obj.getClass()) {
109 + return false;
110 + }
111 + final IntentOperation other = (IntentOperation) obj;
112 + return Objects.equals(this.type, other.type) &&
113 + Objects.equals(this.intentId, other.intentId) &&
114 + Objects.equals(this.intent, other.intent);
115 + }
116 +
117 +
118 + @Override
119 + public String toString() {
120 + return toStringHelper(this)
121 + .add("type", type)
122 + .add("intentId", intentId)
123 + .add("intent", intent)
124 + .toString();
125 + }
88 } 126 }
......
...@@ -18,11 +18,11 @@ package org.onlab.onos.net.intent; ...@@ -18,11 +18,11 @@ package org.onlab.onos.net.intent;
18 import com.google.common.collect.ImmutableList; 18 import com.google.common.collect.ImmutableList;
19 19
20 import java.util.List; 20 import java.util.List;
21 +import java.util.Objects;
21 22
23 +import static com.google.common.base.MoreObjects.toStringHelper;
22 import static com.google.common.base.Preconditions.checkNotNull; 24 import static com.google.common.base.Preconditions.checkNotNull;
23 -import static org.onlab.onos.net.intent.IntentOperation.Type.REPLACE; 25 +import static org.onlab.onos.net.intent.IntentOperation.Type.*;
24 -import static org.onlab.onos.net.intent.IntentOperation.Type.SUBMIT;
25 -import static org.onlab.onos.net.intent.IntentOperation.Type.WITHDRAW;
26 26
27 /** 27 /**
28 * Batch of intent submit/withdraw/replace operations. 28 * Batch of intent submit/withdraw/replace operations.
...@@ -58,6 +58,31 @@ public final class IntentOperations { ...@@ -58,6 +58,31 @@ public final class IntentOperations {
58 return new Builder(); 58 return new Builder();
59 } 59 }
60 60
61 +
62 + @Override
63 + public int hashCode() {
64 + return Objects.hash(operations);
65 + }
66 +
67 + @Override
68 + public boolean equals(Object obj) {
69 + if (this == obj) {
70 + return true;
71 + }
72 + if (obj == null || getClass() != obj.getClass()) {
73 + return false;
74 + }
75 + final IntentOperations other = (IntentOperations) obj;
76 + return Objects.equals(this.operations, other.operations);
77 + }
78 +
79 + @Override
80 + public String toString() {
81 + return toStringHelper(this)
82 + .add("operations", operations)
83 + .toString();
84 + }
85 +
61 /** 86 /**
62 * Builder for batches of intent operations. 87 * Builder for batches of intent operations.
63 */ 88 */
...@@ -108,6 +133,18 @@ public final class IntentOperations { ...@@ -108,6 +133,18 @@ public final class IntentOperations {
108 } 133 }
109 134
110 /** 135 /**
136 + * Adds an intent update operation.
137 + *
138 + * @param intentId identifier of the intent to be updated
139 + * @return self
140 + */
141 + public Builder addUpdateOperation(IntentId intentId) {
142 + checkNotNull(intentId, "Intent ID cannot be null");
143 + builder.add(new IntentOperation(UPDATE, intentId, null));
144 + return this;
145 + }
146 +
147 + /**
111 * Builds a batch of intent operations. 148 * Builds a batch of intent operations.
112 * 149 *
113 * @return immutable batch of intent operations 150 * @return immutable batch of intent operations
......
...@@ -17,7 +17,6 @@ package org.onlab.onos.net.intent; ...@@ -17,7 +17,6 @@ package org.onlab.onos.net.intent;
17 17
18 18
19 import java.util.List; 19 import java.util.List;
20 -import java.util.concurrent.Future;
21 20
22 /** 21 /**
23 * Service for application submitting or withdrawing their intents. 22 * Service for application submitting or withdrawing their intents.
...@@ -59,9 +58,8 @@ public interface IntentService { ...@@ -59,9 +58,8 @@ public interface IntentService {
59 * affected at later time. 58 * affected at later time.
60 * </p> 59 * </p>
61 * @param operations batch of intent operations 60 * @param operations batch of intent operations
62 - * @return Future to get execution result
63 */ 61 */
64 - Future<IntentOperations> execute(IntentOperations operations); 62 + void execute(IntentOperations operations);
65 63
66 /** 64 /**
67 * Returns an iterable of intents currently in the system. 65 * Returns an iterable of intents currently in the system.
......
...@@ -24,7 +24,6 @@ import java.util.Map; ...@@ -24,7 +24,6 @@ import java.util.Map;
24 import java.util.Set; 24 import java.util.Set;
25 import java.util.concurrent.ExecutorService; 25 import java.util.concurrent.ExecutorService;
26 import java.util.concurrent.Executors; 26 import java.util.concurrent.Executors;
27 -import java.util.concurrent.Future;
28 27
29 /** 28 /**
30 * Fake implementation of the intent service to assist in developing tests of 29 * Fake implementation of the intent service to assist in developing tests of
...@@ -104,7 +103,7 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -104,7 +103,7 @@ public class FakeIntentManager implements TestableIntentService {
104 try { 103 try {
105 // For the fake, we compile using a single level pass 104 // For the fake, we compile using a single level pass
106 List<Intent> installable = new ArrayList<>(); 105 List<Intent> installable = new ArrayList<>();
107 - for (Intent compiled : getCompiler(intent).compile(intent)) { 106 + for (Intent compiled : getCompiler(intent).compile(intent, null, null)) {
108 installable.add((Intent) compiled); 107 installable.add((Intent) compiled);
109 } 108 }
110 executeInstallingPhase(intent, installable); 109 executeInstallingPhase(intent, installable);
...@@ -192,9 +191,8 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -192,9 +191,8 @@ public class FakeIntentManager implements TestableIntentService {
192 } 191 }
193 192
194 @Override 193 @Override
195 - public Future<IntentOperations> execute(IntentOperations operations) { 194 + public void execute(IntentOperations operations) {
196 // TODO: implement later 195 // TODO: implement later
197 - return null;
198 } 196 }
199 197
200 @Override 198 @Override
......
...@@ -29,11 +29,13 @@ import java.util.Arrays; ...@@ -29,11 +29,13 @@ import java.util.Arrays;
29 import java.util.Collections; 29 import java.util.Collections;
30 import java.util.Iterator; 30 import java.util.Iterator;
31 import java.util.List; 31 import java.util.List;
32 +import java.util.Set;
32 33
33 import org.junit.After; 34 import org.junit.After;
34 import org.junit.Before; 35 import org.junit.Before;
35 import org.junit.Test; 36 import org.junit.Test;
36 import org.onlab.onos.net.flow.FlowRuleBatchOperation; 37 import org.onlab.onos.net.flow.FlowRuleBatchOperation;
38 +import org.onlab.onos.net.resource.LinkResourceAllocations;
37 39
38 /** 40 /**
39 * Suite of tests for the intent service contract. 41 * Suite of tests for the intent service contract.
...@@ -294,7 +296,8 @@ public class IntentServiceTest { ...@@ -294,7 +296,8 @@ public class IntentServiceTest {
294 } 296 }
295 297
296 @Override 298 @Override
297 - public List<Intent> compile(TestIntent intent) { 299 + public List<Intent> compile(TestIntent intent, List<Intent> installable,
300 + Set<LinkResourceAllocations> resources) {
298 if (fail) { 301 if (fail) {
299 throw new IntentException("compile failed by design"); 302 throw new IntentException("compile failed by design");
300 } 303 }
...@@ -326,6 +329,12 @@ public class IntentServiceTest { ...@@ -326,6 +329,12 @@ public class IntentServiceTest {
326 } 329 }
327 return null; 330 return null;
328 } 331 }
332 +
333 + @Override
334 + public List<FlowRuleBatchOperation> replace(TestInstallableIntent intent,
335 + TestInstallableIntent newIntent) {
336 + return null;
337 + }
329 } 338 }
330 339
331 } 340 }
......
...@@ -509,13 +509,8 @@ public class FlowRuleManager ...@@ -509,13 +509,8 @@ public class FlowRuleManager
509 boolean success = true; 509 boolean success = true;
510 Set<FlowRule> failed = Sets.newHashSet(); 510 Set<FlowRule> failed = Sets.newHashSet();
511 CompletedBatchOperation completed; 511 CompletedBatchOperation completed;
512 - long start = System.nanoTime();
513 - long end = start + unit.toNanos(timeout);
514 -
515 for (Future<CompletedBatchOperation> future : futures) { 512 for (Future<CompletedBatchOperation> future : futures) {
516 - long now = System.nanoTime(); 513 + completed = future.get(timeout, unit);
517 - long thisTimeout = end - now;
518 - completed = future.get(thisTimeout, TimeUnit.NANOSECONDS);
519 success = validateBatchOperation(failed, completed); 514 success = validateBatchOperation(failed, completed);
520 } 515 }
521 return finalizeBatchOperation(success, failed); 516 return finalizeBatchOperation(success, failed);
......
...@@ -27,9 +27,11 @@ import org.onlab.onos.net.host.HostService; ...@@ -27,9 +27,11 @@ import org.onlab.onos.net.host.HostService;
27 import org.onlab.onos.net.intent.HostToHostIntent; 27 import org.onlab.onos.net.intent.HostToHostIntent;
28 import org.onlab.onos.net.intent.Intent; 28 import org.onlab.onos.net.intent.Intent;
29 import org.onlab.onos.net.intent.PathIntent; 29 import org.onlab.onos.net.intent.PathIntent;
30 +import org.onlab.onos.net.resource.LinkResourceAllocations;
30 31
31 import java.util.Arrays; 32 import java.util.Arrays;
32 import java.util.List; 33 import java.util.List;
34 +import java.util.Set;
33 35
34 import static org.onlab.onos.net.flow.DefaultTrafficSelector.builder; 36 import static org.onlab.onos.net.flow.DefaultTrafficSelector.builder;
35 37
...@@ -54,7 +56,8 @@ public class HostToHostIntentCompiler ...@@ -54,7 +56,8 @@ public class HostToHostIntentCompiler
54 } 56 }
55 57
56 @Override 58 @Override
57 - public List<Intent> compile(HostToHostIntent intent) { 59 + public List<Intent> compile(HostToHostIntent intent, List<Intent> installable,
60 + Set<LinkResourceAllocations> resources) {
58 Path pathOne = getPath(intent, intent.one(), intent.two()); 61 Path pathOne = getPath(intent, intent.one(), intent.two());
59 Path pathTwo = getPath(intent, intent.two(), intent.one()); 62 Path pathTwo = getPath(intent, intent.two(), intent.one());
60 63
......
...@@ -15,31 +15,10 @@ ...@@ -15,31 +15,10 @@
15 */ 15 */
16 package org.onlab.onos.net.intent.impl; 16 package org.onlab.onos.net.intent.impl;
17 17
18 -import static com.google.common.base.Preconditions.checkNotNull; 18 +import com.google.common.collect.ImmutableList;
19 -import static java.util.concurrent.Executors.newSingleThreadExecutor; 19 +import com.google.common.collect.ImmutableMap;
20 -import static org.onlab.onos.net.intent.IntentState.COMPILING; 20 +import com.google.common.collect.Lists;
21 -import static org.onlab.onos.net.intent.IntentState.FAILED; 21 +import com.google.common.collect.Maps;
22 -import static org.onlab.onos.net.intent.IntentState.INSTALLED;
23 -import static org.onlab.onos.net.intent.IntentState.INSTALLING;
24 -import static org.onlab.onos.net.intent.IntentState.RECOMPILING;
25 -import static org.onlab.onos.net.intent.IntentState.WITHDRAWING;
26 -import static org.onlab.onos.net.intent.IntentState.WITHDRAWN;
27 -import static org.onlab.util.Tools.namedThreads;
28 -import static org.slf4j.LoggerFactory.getLogger;
29 -
30 -import java.util.ArrayList;
31 -import java.util.Iterator;
32 -import java.util.List;
33 -import java.util.Map;
34 -import java.util.Objects;
35 -import java.util.concurrent.ConcurrentHashMap;
36 -import java.util.concurrent.ConcurrentMap;
37 -import java.util.concurrent.ExecutionException;
38 -import java.util.concurrent.ExecutorService;
39 -import java.util.concurrent.Future;
40 -import java.util.concurrent.TimeUnit;
41 -import java.util.concurrent.TimeoutException;
42 -
43 import org.apache.felix.scr.annotations.Activate; 22 import org.apache.felix.scr.annotations.Activate;
44 import org.apache.felix.scr.annotations.Component; 23 import org.apache.felix.scr.annotations.Component;
45 import org.apache.felix.scr.annotations.Deactivate; 24 import org.apache.felix.scr.annotations.Deactivate;
...@@ -52,6 +31,8 @@ import org.onlab.onos.net.flow.CompletedBatchOperation; ...@@ -52,6 +31,8 @@ import org.onlab.onos.net.flow.CompletedBatchOperation;
52 import org.onlab.onos.net.flow.FlowRuleBatchOperation; 31 import org.onlab.onos.net.flow.FlowRuleBatchOperation;
53 import org.onlab.onos.net.flow.FlowRuleService; 32 import org.onlab.onos.net.flow.FlowRuleService;
54 import org.onlab.onos.net.intent.Intent; 33 import org.onlab.onos.net.intent.Intent;
34 +import org.onlab.onos.net.intent.IntentBatchDelegate;
35 +import org.onlab.onos.net.intent.IntentBatchService;
55 import org.onlab.onos.net.intent.IntentCompiler; 36 import org.onlab.onos.net.intent.IntentCompiler;
56 import org.onlab.onos.net.intent.IntentEvent; 37 import org.onlab.onos.net.intent.IntentEvent;
57 import org.onlab.onos.net.intent.IntentException; 38 import org.onlab.onos.net.intent.IntentException;
...@@ -59,6 +40,7 @@ import org.onlab.onos.net.intent.IntentExtensionService; ...@@ -59,6 +40,7 @@ import org.onlab.onos.net.intent.IntentExtensionService;
59 import org.onlab.onos.net.intent.IntentId; 40 import org.onlab.onos.net.intent.IntentId;
60 import org.onlab.onos.net.intent.IntentInstaller; 41 import org.onlab.onos.net.intent.IntentInstaller;
61 import org.onlab.onos.net.intent.IntentListener; 42 import org.onlab.onos.net.intent.IntentListener;
43 +import org.onlab.onos.net.intent.IntentOperation;
62 import org.onlab.onos.net.intent.IntentOperations; 44 import org.onlab.onos.net.intent.IntentOperations;
63 import org.onlab.onos.net.intent.IntentService; 45 import org.onlab.onos.net.intent.IntentService;
64 import org.onlab.onos.net.intent.IntentState; 46 import org.onlab.onos.net.intent.IntentState;
...@@ -66,9 +48,24 @@ import org.onlab.onos.net.intent.IntentStore; ...@@ -66,9 +48,24 @@ import org.onlab.onos.net.intent.IntentStore;
66 import org.onlab.onos.net.intent.IntentStoreDelegate; 48 import org.onlab.onos.net.intent.IntentStoreDelegate;
67 import org.slf4j.Logger; 49 import org.slf4j.Logger;
68 50
69 -import com.google.common.collect.ImmutableList; 51 +import java.util.ArrayList;
70 -import com.google.common.collect.ImmutableMap; 52 +import java.util.List;
71 -import com.google.common.collect.Lists; 53 +import java.util.Map;
54 +import java.util.Objects;
55 +import java.util.concurrent.ConcurrentHashMap;
56 +import java.util.concurrent.ConcurrentMap;
57 +import java.util.concurrent.ExecutionException;
58 +import java.util.concurrent.ExecutorService;
59 +import java.util.concurrent.Future;
60 +import java.util.concurrent.TimeUnit;
61 +import java.util.concurrent.TimeoutException;
62 +
63 +import static com.google.common.base.Preconditions.checkArgument;
64 +import static com.google.common.base.Preconditions.checkNotNull;
65 +import static java.util.concurrent.Executors.newSingleThreadExecutor;
66 +import static org.onlab.onos.net.intent.IntentState.*;
67 +import static org.onlab.util.Tools.namedThreads;
68 +import static org.slf4j.LoggerFactory.getLogger;
72 69
73 /** 70 /**
74 * An implementation of Intent Manager. 71 * An implementation of Intent Manager.
...@@ -96,11 +93,15 @@ public class IntentManager ...@@ -96,11 +93,15 @@ public class IntentManager
96 93
97 private final IntentStoreDelegate delegate = new InternalStoreDelegate(); 94 private final IntentStoreDelegate delegate = new InternalStoreDelegate();
98 private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate(); 95 private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate();
96 + private final IntentBatchDelegate batchDelegate = new InternalBatchDelegate();
99 97
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected IntentStore store; 99 protected IntentStore store;
102 100
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 + protected IntentBatchService batchService;
103 +
104 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 protected ObjectiveTrackerService trackerService; 105 protected ObjectiveTrackerService trackerService;
105 106
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
...@@ -113,6 +114,7 @@ public class IntentManager ...@@ -113,6 +114,7 @@ public class IntentManager
113 public void activate() { 114 public void activate() {
114 store.setDelegate(delegate); 115 store.setDelegate(delegate);
115 trackerService.setDelegate(topoDelegate); 116 trackerService.setDelegate(topoDelegate);
117 + batchService.setDelegate(batchDelegate);
116 eventDispatcher.addSink(IntentEvent.class, listenerRegistry); 118 eventDispatcher.addSink(IntentEvent.class, listenerRegistry);
117 executor = newSingleThreadExecutor(namedThreads("onos-intents")); 119 executor = newSingleThreadExecutor(namedThreads("onos-intents"));
118 monitorExecutor = newSingleThreadExecutor(namedThreads("onos-intent-monitor")); 120 monitorExecutor = newSingleThreadExecutor(namedThreads("onos-intent-monitor"));
...@@ -123,6 +125,7 @@ public class IntentManager ...@@ -123,6 +125,7 @@ public class IntentManager
123 public void deactivate() { 125 public void deactivate() {
124 store.unsetDelegate(delegate); 126 store.unsetDelegate(delegate);
125 trackerService.unsetDelegate(topoDelegate); 127 trackerService.unsetDelegate(topoDelegate);
128 + batchService.unsetDelegate(batchDelegate);
126 eventDispatcher.removeSink(IntentEvent.class); 129 eventDispatcher.removeSink(IntentEvent.class);
127 executor.shutdown(); 130 executor.shutdown();
128 monitorExecutor.shutdown(); 131 monitorExecutor.shutdown();
...@@ -132,30 +135,27 @@ public class IntentManager ...@@ -132,30 +135,27 @@ public class IntentManager
132 @Override 135 @Override
133 public void submit(Intent intent) { 136 public void submit(Intent intent) {
134 checkNotNull(intent, INTENT_NULL); 137 checkNotNull(intent, INTENT_NULL);
135 - registerSubclassCompilerIfNeeded(intent); 138 + execute(IntentOperations.builder().addSubmitOperation(intent).build());
136 - IntentEvent event = store.createIntent(intent);
137 - if (event != null) {
138 - eventDispatcher.post(event);
139 - executor.execute(new IntentTask(COMPILING, intent));
140 - }
141 } 139 }
142 140
143 @Override 141 @Override
144 public void withdraw(Intent intent) { 142 public void withdraw(Intent intent) {
145 checkNotNull(intent, INTENT_NULL); 143 checkNotNull(intent, INTENT_NULL);
146 - executor.execute(new IntentTask(WITHDRAWING, intent)); 144 + execute(IntentOperations.builder().addWithdrawOperation(intent.id()).build());
147 } 145 }
148 146
149 - // FIXME: implement this method
150 @Override 147 @Override
151 public void replace(IntentId oldIntentId, Intent newIntent) { 148 public void replace(IntentId oldIntentId, Intent newIntent) {
152 - throw new UnsupportedOperationException("execute() is not implemented yet"); 149 + checkNotNull(oldIntentId, INTENT_ID_NULL);
150 + checkNotNull(newIntent, INTENT_NULL);
151 + execute(IntentOperations.builder()
152 + .addReplaceOperation(oldIntentId, newIntent)
153 + .build());
153 } 154 }
154 155
155 - // FIXME: implement this method
156 @Override 156 @Override
157 - public Future<IntentOperations> execute(IntentOperations operations) { 157 + public void execute(IntentOperations operations) {
158 - throw new UnsupportedOperationException("execute() is not implemented yet"); 158 + batchService.addIntentOperations(operations);
159 } 159 }
160 160
161 @Override 161 @Override
...@@ -261,29 +261,25 @@ public class IntentManager ...@@ -261,29 +261,25 @@ public class IntentManager
261 /** 261 /**
262 * Compiles the specified intent. 262 * Compiles the specified intent.
263 * 263 *
264 - * @param intent intent to be compiled 264 + * @param update intent update
265 */ 265 */
266 - private void executeCompilingPhase(Intent intent) { 266 + private void executeCompilingPhase(IntentUpdate update) {
267 + Intent intent = update.newIntent();
267 // Indicate that the intent is entering the compiling phase. 268 // Indicate that the intent is entering the compiling phase.
268 - store.setState(intent, COMPILING); 269 + update.setState(intent, COMPILING);
269 270
270 try { 271 try {
271 // Compile the intent into installable derivatives. 272 // Compile the intent into installable derivatives.
272 - List<Intent> installable = compileIntent(intent); 273 + List<Intent> installables = compileIntent(intent, update);
273 274
274 // If all went well, associate the resulting list of installable 275 // If all went well, associate the resulting list of installable
275 // intents with the top-level intent and proceed to install. 276 // intents with the top-level intent and proceed to install.
276 - store.setInstallableIntents(intent.id(), installable); 277 + update.setInstallables(installables);
277 - executeInstallingPhase(intent); 278 + } catch (IntentException e) {
278 -
279 - } catch (Exception e) {
280 log.warn("Unable to compile intent {} due to:", intent.id(), e); 279 log.warn("Unable to compile intent {} due to:", intent.id(), e);
281 280
282 // If compilation failed, mark the intent as failed. 281 // If compilation failed, mark the intent as failed.
283 - IntentEvent event = store.setState(intent, FAILED); 282 + update.setState(intent, FAILED);
284 - if (event != null) {
285 - eventDispatcher.post(event);
286 - }
287 } 283 }
288 } 284 }
289 285
...@@ -293,17 +289,18 @@ public class IntentManager ...@@ -293,17 +289,18 @@ public class IntentManager
293 * @param intent intent 289 * @param intent intent
294 * @return result of compilation 290 * @return result of compilation
295 */ 291 */
296 - private List<Intent> compileIntent(Intent intent) { 292 + private List<Intent> compileIntent(Intent intent, IntentUpdate update) {
297 if (intent.isInstallable()) { 293 if (intent.isInstallable()) {
298 return ImmutableList.of(intent); 294 return ImmutableList.of(intent);
299 } 295 }
300 296
297 + registerSubclassCompilerIfNeeded(intent);
298 + List<Intent> previous = update.oldInstallables();
299 + // FIXME: get previous resources
301 List<Intent> installable = new ArrayList<>(); 300 List<Intent> installable = new ArrayList<>();
302 - // TODO do we need to registerSubclassCompiler? 301 + for (Intent compiled : getCompiler(intent).compile(intent, previous, null)) {
303 - for (Intent compiled : getCompiler(intent).compile(intent)) { 302 + installable.addAll(compileIntent(compiled, update));
304 - installable.addAll(compileIntent(compiled));
305 } 303 }
306 -
307 return installable; 304 return installable;
308 } 305 }
309 306
...@@ -311,63 +308,110 @@ public class IntentManager ...@@ -311,63 +308,110 @@ public class IntentManager
311 * Installs all installable intents associated with the specified top-level 308 * Installs all installable intents associated with the specified top-level
312 * intent. 309 * intent.
313 * 310 *
314 - * @param intent intent to be installed 311 + * @param update intent update
315 */ 312 */
316 - private void executeInstallingPhase(Intent intent) { 313 + private void executeInstallingPhase(IntentUpdate update) {
314 + if (update.newInstallables() == null) {
315 + //no failed intents allowed past this point...
316 + return;
317 + }
317 // Indicate that the intent is entering the installing phase. 318 // Indicate that the intent is entering the installing phase.
318 - store.setState(intent, INSTALLING); 319 + update.setState(update.newIntent(), INSTALLING);
319 320
320 - List<FlowRuleBatchOperation> installWork = Lists.newArrayList(); 321 + List<FlowRuleBatchOperation> batches = Lists.newArrayList();
321 - try { 322 + for (Intent installable : update.newInstallables()) {
322 - List<Intent> installables = store.getInstallableIntents(intent.id());
323 - if (installables != null) {
324 - for (Intent installable : installables) {
325 registerSubclassInstallerIfNeeded(installable); 323 registerSubclassInstallerIfNeeded(installable);
326 - trackerService.addTrackedResources(intent.id(), 324 + trackerService.addTrackedResources(update.newIntent().id(),
327 installable.resources()); 325 installable.resources());
328 - List<FlowRuleBatchOperation> batch = getInstaller(installable).install(installable); 326 + try {
329 - installWork.addAll(batch); 327 + batches.addAll(getInstaller(installable).install(installable));
328 + } catch (IntentException e) {
329 + log.warn("Unable to install intent {} due to:", update.newIntent().id(), e);
330 + //FIXME we failed... intent should be recompiled
331 + // TODO: remove resources
332 + // recompile!!!
330 } 333 }
331 } 334 }
332 - // FIXME we have to wait for the installable intents 335 + update.setBatches(batches);
333 - //eventDispatcher.post(store.setState(intent, INSTALLED)); 336 + }
334 - monitorExecutor.execute(new IntentInstallMonitor(intent, installWork, INSTALLED)); 337 +
335 - } catch (Exception e) { 338 + /**
336 - log.warn("Unable to install intent {} due to:", intent.id(), e); 339 + * Uninstalls the specified intent by uninstalling all of its associated
337 - uninstallIntent(intent, RECOMPILING); 340 + * installable derivatives.
341 + *
342 + * @param update intent update
343 + */
344 + private void executeWithdrawingPhase(IntentUpdate update) {
345 + if (!update.oldIntent().equals(update.newIntent())) {
346 + update.setState(update.oldIntent(), WITHDRAWING);
347 + } // else newIntent is FAILED
348 + uninstallIntent(update);
349 +
350 + // If all went well, disassociate the top-level intent with its
351 + // installable derivatives and mark it as withdrawn.
352 + // FIXME need to clean up
353 + //store.removeInstalledIntents(intent.id());
354 + }
338 355
339 - // If compilation failed, kick off the recompiling phase. 356 + /**
340 - // FIXME 357 + * Uninstalls all installable intents associated with the given intent.
341 - //executeRecompilingPhase(intent); 358 + *
359 + * @param update intent update
360 + */
361 + //FIXME: need to handle next state properly
362 + private void uninstallIntent(IntentUpdate update) {
363 + if (update.oldInstallables == null) {
364 + return;
365 + }
366 + List<FlowRuleBatchOperation> batches = Lists.newArrayList();
367 + for (Intent installable : update.oldInstallables()) {
368 + trackerService.removeTrackedResources(update.oldIntent().id(),
369 + installable.resources());
370 + try {
371 + batches.addAll(getInstaller(installable).uninstall(installable));
372 + } catch (IntentException e) {
373 + log.warn("Unable to uninstall intent {} due to:", update.oldIntent().id(), e);
374 + // TODO: this should never happen. but what if it does?
342 } 375 }
343 } 376 }
377 + update.setBatches(batches);
378 + // FIXME: next state for old is WITHDRAWN or FAILED
379 + }
344 380
345 /** 381 /**
346 * Recompiles the specified intent. 382 * Recompiles the specified intent.
347 * 383 *
348 - * @param intent intent to be recompiled 384 + * @param update intent update
349 */ 385 */
350 - private void executeRecompilingPhase(Intent intent) { 386 + // FIXME: update this to work
387 + private void executeRecompilingPhase(IntentUpdate update) {
388 + Intent intent = update.newIntent();
351 // Indicate that the intent is entering the recompiling phase. 389 // Indicate that the intent is entering the recompiling phase.
352 store.setState(intent, RECOMPILING); 390 store.setState(intent, RECOMPILING);
353 391
392 + List<FlowRuleBatchOperation> batches = Lists.newArrayList();
354 try { 393 try {
355 // Compile the intent into installable derivatives. 394 // Compile the intent into installable derivatives.
356 - List<Intent> installable = compileIntent(intent); 395 + List<Intent> installable = compileIntent(intent, update);
357 396
358 // If all went well, compare the existing list of installable 397 // If all went well, compare the existing list of installable
359 // intents with the newly compiled list. If they are the same, 398 // intents with the newly compiled list. If they are the same,
360 // bail, out since the previous approach was determined not to 399 // bail, out since the previous approach was determined not to
361 // be viable. 400 // be viable.
401 + // FIXME do we need this?
362 List<Intent> originalInstallable = store.getInstallableIntents(intent.id()); 402 List<Intent> originalInstallable = store.getInstallableIntents(intent.id());
363 403
404 + //FIXME let's be smarter about how we perform the update
405 + //batches.addAll(uninstallIntent(intent, null));
406 +
364 if (Objects.equals(originalInstallable, installable)) { 407 if (Objects.equals(originalInstallable, installable)) {
365 eventDispatcher.post(store.setState(intent, FAILED)); 408 eventDispatcher.post(store.setState(intent, FAILED));
366 } else { 409 } else {
367 // Otherwise, re-associate the newly compiled installable intents 410 // Otherwise, re-associate the newly compiled installable intents
368 // with the top-level intent and kick off installing phase. 411 // with the top-level intent and kick off installing phase.
369 store.setInstallableIntents(intent.id(), installable); 412 store.setInstallableIntents(intent.id(), installable);
370 - executeInstallingPhase(intent); 413 + // FIXME commented out for now
414 + //batches.addAll(executeInstallingPhase(update));
371 } 415 }
372 } catch (Exception e) { 416 } catch (Exception e) {
373 log.warn("Unable to recompile intent {} due to:", intent.id(), e); 417 log.warn("Unable to recompile intent {} due to:", intent.id(), e);
...@@ -378,45 +422,38 @@ public class IntentManager ...@@ -378,45 +422,38 @@ public class IntentManager
378 } 422 }
379 423
380 /** 424 /**
381 - * Uninstalls the specified intent by uninstalling all of its associated 425 + * Withdraws the old intent and installs the new intent as one operation.
382 - * installable derivatives.
383 * 426 *
384 - * @param intent intent to be installed 427 + * @param update intent update
385 */ 428 */
386 - private void executeWithdrawingPhase(Intent intent) { 429 + private void executeReplacementPhase(IntentUpdate update) {
387 - // Indicate that the intent is being withdrawn. 430 + checkArgument(update.oldInstallables().size() == update.newInstallables().size(),
388 - store.setState(intent, WITHDRAWING); 431 + "Old and New Intent must have equivalent installable intents.");
389 - uninstallIntent(intent, WITHDRAWN); 432 + if (!update.oldIntent().equals(update.newIntent())) {
390 - 433 + // only set the old intent's state if it is different
391 - // If all went well, disassociate the top-level intent with its 434 + update.setState(update.oldIntent(), WITHDRAWING);
392 - // installable derivatives and mark it as withdrawn. 435 + }
393 - // FIXME need to clean up 436 + update.setState(update.newIntent(), INSTALLING);
394 - //store.removeInstalledIntents(intent.id()); 437 +
395 - // FIXME 438 + List<FlowRuleBatchOperation> batches = Lists.newArrayList();
396 - //eventDispatcher.post(store.setState(intent, WITHDRAWN)); 439 + for (int i = 0; i < update.oldInstallables().size(); i++) {
397 - } 440 + Intent oldInstallable = update.oldInstallables().get(i);
398 - 441 + Intent newInstallable = update.newInstallables().get(i);
399 - /** 442 + if (oldInstallable.equals(newInstallable)) {
400 - * Uninstalls all installable intents associated with the given intent. 443 + continue;
401 - * 444 + }
402 - * @param intent intent to be uninstalled 445 + checkArgument(oldInstallable.getClass().equals(newInstallable.getClass()),
403 - */ 446 + "Installable Intent type mismatch.");
404 - private void uninstallIntent(Intent intent, IntentState nextState) { 447 + trackerService.removeTrackedResources(update.oldIntent().id(), oldInstallable.resources());
405 - List<FlowRuleBatchOperation> uninstallWork = Lists.newArrayList(); 448 + trackerService.addTrackedResources(update.newIntent().id(), newInstallable.resources());
406 try { 449 try {
407 - List<Intent> installables = store.getInstallableIntents(intent.id()); 450 + batches.addAll(getInstaller(newInstallable).replace(oldInstallable, newInstallable));
408 - if (installables != null) {
409 - for (Intent installable : installables) {
410 - trackerService.removeTrackedResources(intent.id(),
411 - installable.resources());
412 - List<FlowRuleBatchOperation> batches = getInstaller(installable).uninstall(installable);
413 - uninstallWork.addAll(batches);
414 - }
415 - }
416 - monitorExecutor.execute(new IntentInstallMonitor(intent, uninstallWork, nextState));
417 } catch (IntentException e) { 451 } catch (IntentException e) {
418 - log.warn("Unable to uninstall intent {} due to:", intent.id(), e); 452 + log.warn("Unable to update intent {} due to:", update.oldIntent().id(), e);
453 + //FIXME... we failed. need to uninstall (if same) or revert (if different)
454 + }
419 } 455 }
456 + update.setBatches(batches);
420 } 457 }
421 458
422 /** 459 /**
...@@ -474,9 +511,6 @@ public class IntentManager ...@@ -474,9 +511,6 @@ public class IntentManager
474 @Override 511 @Override
475 public void notify(IntentEvent event) { 512 public void notify(IntentEvent event) {
476 eventDispatcher.post(event); 513 eventDispatcher.post(event);
477 - if (event.type() == IntentEvent.Type.SUBMITTED) {
478 - executor.execute(new IntentTask(COMPILING, event.subject()));
479 - }
480 } 514 }
481 } 515 }
482 516
...@@ -486,131 +520,349 @@ public class IntentManager ...@@ -486,131 +520,349 @@ public class IntentManager
486 public void triggerCompile(Iterable<IntentId> intentIds, 520 public void triggerCompile(Iterable<IntentId> intentIds,
487 boolean compileAllFailed) { 521 boolean compileAllFailed) {
488 // Attempt recompilation of the specified intents first. 522 // Attempt recompilation of the specified intents first.
489 - for (IntentId intentId : intentIds) { 523 + IntentOperations.Builder builder = IntentOperations.builder();
490 - Intent intent = getIntent(intentId); 524 + for (IntentId id : intentIds) {
491 - uninstallIntent(intent, RECOMPILING); 525 + builder.addUpdateOperation(id);
492 -
493 - //FIXME
494 - //executeRecompilingPhase(intent);
495 } 526 }
496 527
497 if (compileAllFailed) { 528 if (compileAllFailed) {
498 // If required, compile all currently failed intents. 529 // If required, compile all currently failed intents.
499 for (Intent intent : getIntents()) { 530 for (Intent intent : getIntents()) {
500 if (getIntentState(intent.id()) == FAILED) { 531 if (getIntentState(intent.id()) == FAILED) {
501 - executeCompilingPhase(intent); 532 + builder.addUpdateOperation(intent.id());
533 + }
534 + }
535 + }
536 + execute(builder.build());
537 + }
538 + }
539 +
540 + /**
541 + * TODO.
542 + * @param op intent operation
543 + * @return intent update
544 + */
545 + private IntentUpdate processIntentOperation(IntentOperation op) {
546 + IntentUpdate update = new IntentUpdate(op);
547 +
548 + if (update.newIntent() != null) {
549 + executeCompilingPhase(update);
550 + }
551 +
552 + if (update.oldInstallables() != null && update.newInstallables() != null) {
553 + executeReplacementPhase(update);
554 + } else if (update.newInstallables() != null) {
555 + executeInstallingPhase(update);
556 + } else if (update.oldInstallables() != null) {
557 + executeWithdrawingPhase(update);
558 + } else {
559 + if (update.oldIntent() != null) {
560 + // TODO this shouldn't happen
561 + return update; //FIXME
562 + }
563 + if (update.newIntent() != null) {
564 + // TODO assert that next state is failed
565 + return update; //FIXME
566 + }
567 + }
568 +
569 + return update;
570 + }
571 +
572 + // TODO comments...
573 + private class IntentUpdate {
574 + private final IntentOperation op;
575 + private final Intent oldIntent;
576 + private final Intent newIntent;
577 + private final Map<Intent, IntentState> stateMap = Maps.newHashMap();
578 +
579 + private final List<Intent> oldInstallables;
580 + private List<Intent> newInstallables;
581 + private List<FlowRuleBatchOperation> batches;
582 +
583 + IntentUpdate(IntentOperation op) {
584 + this.op = op;
585 + switch (op.type()) {
586 + case SUBMIT:
587 + newIntent = op.intent();
588 + oldIntent = null;
589 + break;
590 + case WITHDRAW:
591 + newIntent = null;
592 + oldIntent = store.getIntent(op.intentId());
593 + break;
594 + case REPLACE:
595 + newIntent = op.intent();
596 + oldIntent = store.getIntent(op.intentId());
597 + break;
598 + case UPDATE:
599 + oldIntent = store.getIntent(op.intentId());
600 + newIntent = oldIntent; //InnerAssignment: Inner assignments should be avoided.
601 + break;
602 + default:
603 + oldIntent = null;
604 + newIntent = null;
605 + break;
606 + }
607 + // add new intent to store (if required)
608 + if (newIntent != null) {
609 + IntentEvent event = store.createIntent(newIntent);
610 + if (event != null) {
611 + eventDispatcher.post(event);
612 + }
613 + }
614 + // fetch the old intent's installables from the store
615 + if (oldIntent != null) {
616 + oldInstallables = store.getInstallableIntents(oldIntent.id());
617 + // TODO: remove intent from store after uninstall
618 + } else {
619 + oldInstallables = null;
620 + }
621 + }
622 +
623 + Intent oldIntent() {
624 + return oldIntent;
625 + }
626 +
627 + Intent newIntent() {
628 + return newIntent;
629 + }
630 +
631 + List<Intent> oldInstallables() {
632 + return oldInstallables;
633 + }
634 +
635 + List<Intent> newInstallables() {
636 + return newInstallables;
637 + }
638 +
639 + void setInstallables(List<Intent> installables) {
640 + newInstallables = installables;
641 + store.setInstallableIntents(newIntent.id(), installables);
642 + }
643 +
644 + List<FlowRuleBatchOperation> batches() {
645 + return batches;
646 + }
647 +
648 + void setBatches(List<FlowRuleBatchOperation> batches) {
649 + this.batches = batches;
650 + }
651 +
652 + IntentState getState(Intent intent) {
653 + return stateMap.get(intent);
654 + }
655 +
656 + void setState(Intent intent, IntentState newState) {
657 + // TODO: clean this up, or set to debug
658 + IntentState oldState = stateMap.get(intent);
659 + log.info("intent id: {}, old state: {}, new state: {}",
660 + intent.id(), oldState, newState);
661 +
662 + stateMap.put(intent, newState);
663 + IntentEvent event = store.setState(intent, newState);
664 + if (event != null) {
665 + eventDispatcher.post(event);
666 + }
667 + }
668 +
669 + Map<Intent, IntentState> stateMap() {
670 + return stateMap;
502 } 671 }
503 } 672 }
673 +
674 + private static List<FlowRuleBatchOperation> mergeBatches(Map<IntentOperation,
675 + IntentUpdate> intentUpdates) {
676 + //TODO test this.
677 + List<FlowRuleBatchOperation> batches = Lists.newArrayList();
678 + for (IntentUpdate update : intentUpdates.values()) {
679 + if (update.batches() == null) {
680 + continue;
681 + }
682 + int i = 0;
683 + for (FlowRuleBatchOperation batch : update.batches()) {
684 + if (i == batches.size()) {
685 + batches.add(batch);
686 + } else {
687 + FlowRuleBatchOperation existing = batches.get(i);
688 + existing.addAll(batch);
504 } 689 }
690 + i++;
505 } 691 }
506 } 692 }
693 + return batches;
694 + }
507 695
508 // Auxiliary runnable to perform asynchronous tasks. 696 // Auxiliary runnable to perform asynchronous tasks.
509 private class IntentTask implements Runnable { 697 private class IntentTask implements Runnable {
510 - private final IntentState state; 698 + private final IntentOperations operations;
511 - private final Intent intent;
512 699
513 - public IntentTask(IntentState state, Intent intent) { 700 + public IntentTask(IntentOperations operations) {
514 - this.state = state; 701 + this.operations = operations;
515 - this.intent = intent;
516 } 702 }
517 703
518 @Override 704 @Override
519 public void run() { 705 public void run() {
520 - if (state == COMPILING) { 706 + Map<IntentOperation, IntentUpdate> intentUpdates = Maps.newHashMap();
521 - executeCompilingPhase(intent); 707 + for (IntentOperation op : operations.operations()) {
522 - } else if (state == RECOMPILING) { 708 + intentUpdates.put(op, processIntentOperation(op));
523 - executeRecompilingPhase(intent);
524 - } else if (state == WITHDRAWING) {
525 - executeWithdrawingPhase(intent);
526 } 709 }
710 + List<FlowRuleBatchOperation> batches = mergeBatches(intentUpdates);
711 + monitorExecutor.execute(new IntentInstallMonitor(operations, intentUpdates, batches));
527 } 712 }
528 } 713 }
529 714
530 private class IntentInstallMonitor implements Runnable { 715 private class IntentInstallMonitor implements Runnable {
531 716
532 - private final Intent intent; 717 + private static final long TIMEOUT = 5000; // ms
718 + private final IntentOperations ops;
719 + private final Map<IntentOperation, IntentUpdate> intentUpdateMap;
533 private final List<FlowRuleBatchOperation> work; 720 private final List<FlowRuleBatchOperation> work;
534 - private final List<Future<CompletedBatchOperation>> futures; 721 + private Future<CompletedBatchOperation> future;
535 - private final IntentState nextState; 722 + private final long startTime = System.currentTimeMillis();
536 - 723 + private final long endTime = startTime + TIMEOUT;
537 - public IntentInstallMonitor(Intent intent, 724 +
538 - List<FlowRuleBatchOperation> work, 725 + public IntentInstallMonitor(IntentOperations ops,
539 - IntentState nextState) { 726 + Map<IntentOperation, IntentUpdate> intentUpdateMap,
540 - this.intent = intent; 727 + List<FlowRuleBatchOperation> work) {
728 + this.ops = ops;
729 + this.intentUpdateMap = intentUpdateMap;
541 this.work = work; 730 this.work = work;
542 - // TODO how many Futures can be outstanding? one? 731 + future = applyNextBatch();
543 - this.futures = Lists.newLinkedList(); 732 + }
544 - this.nextState = nextState;
545 733
546 - // TODO need to kick off the first batch sometime, why not now? 734 + /**
547 - futures.add(applyNextBatch()); 735 + * Applies the next batch, and returns the future.
736 + *
737 + * @return Future for next batch
738 + */
739 + private Future<CompletedBatchOperation> applyNextBatch() {
740 + if (work.isEmpty()) {
741 + return null;
742 + }
743 + FlowRuleBatchOperation batch = work.remove(0);
744 + return flowRuleService.applyBatch(batch);
548 } 745 }
549 746
550 /** 747 /**
551 * Update the intent store with the next status for this intent. 748 * Update the intent store with the next status for this intent.
552 */ 749 */
553 - private void updateIntent() { 750 + private void updateIntents() {
751 + // FIXME we assume everything passes for now.
752 + for (IntentUpdate update : intentUpdateMap.values()) {
753 + for (Intent intent : update.stateMap().keySet()) {
754 + switch (update.getState(intent)) {
755 + case INSTALLING:
756 + update.setState(intent, INSTALLED);
757 + break;
758 + case WITHDRAWING:
759 + update.setState(intent, WITHDRAWN);
760 + // Fall-through
761 + case FAILED:
762 + store.removeInstalledIntents(intent.id());
763 + break;
764 +
765 + case SUBMITTED:
766 + case COMPILING:
767 + case RECOMPILING:
768 + case WITHDRAWN:
769 + case INSTALLED:
770 + default:
771 + //FIXME clean this up (we shouldn't ever get here)
772 + log.warn("Bad state: {} for {}", update.getState(intent), intent);
773 + break;
774 + }
775 + }
776 + }
777 + /*
778 + for (IntentOperation op : ops.operations()) {
779 + switch (op.type()) {
780 + case SUBMIT:
781 + store.setState(op.intent(), INSTALLED);
782 + break;
783 + case WITHDRAW:
784 + Intent intent = store.getIntent(op.intentId());
785 + store.setState(intent, WITHDRAWN);
786 + break;
787 + case REPLACE:
788 + store.setState(op.intent(), INSTALLED);
789 + intent = store.getIntent(op.intentId());
790 + store.setState(intent, WITHDRAWN);
791 + break;
792 + case UPDATE:
793 + intent = store.getIntent(op.intentId());
794 + store.setState(intent, INSTALLED);
795 + break;
796 + default:
797 + break;
798 + }
799 + }
800 + */
801 + /*
554 if (nextState == RECOMPILING) { 802 if (nextState == RECOMPILING) {
555 - executor.execute(new IntentTask(nextState, intent)); 803 + eventDispatcher.post(store.setState(intent, FAILED));
804 + // FIXME try to recompile
805 +// executor.execute(new IntentTask(nextState, intent));
556 } else if (nextState == INSTALLED || nextState == WITHDRAWN) { 806 } else if (nextState == INSTALLED || nextState == WITHDRAWN) {
557 eventDispatcher.post(store.setState(intent, nextState)); 807 eventDispatcher.post(store.setState(intent, nextState));
558 } else { 808 } else {
559 log.warn("Invalid next intent state {} for intent {}", nextState, intent); 809 log.warn("Invalid next intent state {} for intent {}", nextState, intent);
560 - } 810 + }*/
561 - }
562 -
563 - /**
564 - * Applies the next batch.
565 - */
566 - private Future<CompletedBatchOperation> applyNextBatch() {
567 - if (work.isEmpty()) {
568 - return null;
569 - }
570 - FlowRuleBatchOperation batch = work.remove(0);
571 - return flowRuleService.applyBatch(batch);
572 } 811 }
573 812
574 /** 813 /**
575 * Iterate through the pending futures, and remove them when they have completed. 814 * Iterate through the pending futures, and remove them when they have completed.
576 */ 815 */
577 private void processFutures() { 816 private void processFutures() {
578 - List<Future<CompletedBatchOperation>> newFutures = Lists.newArrayList(); 817 + if (future == null) {
579 - for (Iterator<Future<CompletedBatchOperation>> i = futures.iterator(); i.hasNext();) { 818 + return; //FIXME look at this
580 - Future<CompletedBatchOperation> future = i.next(); 819 + }
581 try { 820 try {
582 - // TODO: we may want to get the future here and go back to the future.
583 CompletedBatchOperation completed = future.get(100, TimeUnit.NANOSECONDS); 821 CompletedBatchOperation completed = future.get(100, TimeUnit.NANOSECONDS);
584 if (completed.isSuccess()) { 822 if (completed.isSuccess()) {
585 - Future<CompletedBatchOperation> newFuture = applyNextBatch(); 823 + future = applyNextBatch();
586 - if (newFuture != null) {
587 - // we'll add this later so that we don't get a ConcurrentModException
588 - newFutures.add(newFuture);
589 - }
590 } else { 824 } else {
591 // TODO check if future succeeded and if not report fail items 825 // TODO check if future succeeded and if not report fail items
592 log.warn("Failed items: {}", completed.failedItems()); 826 log.warn("Failed items: {}", completed.failedItems());
593 - // TODO revert.... 827 + // FIXME revert.... by submitting a new batch
594 //uninstallIntent(intent, RECOMPILING); 828 //uninstallIntent(intent, RECOMPILING);
595 } 829 }
596 - i.remove();
597 } catch (TimeoutException | InterruptedException | ExecutionException te) { 830 } catch (TimeoutException | InterruptedException | ExecutionException te) {
598 - log.debug("Intallations of intent {} is still pending", intent); 831 + //TODO look into error message
832 + log.debug("Intallations of intent {} is still pending", ops);
599 } 833 }
600 } 834 }
601 - futures.addAll(newFutures);
602 - }
603 835
604 @Override 836 @Override
605 public void run() { 837 public void run() {
606 processFutures(); 838 processFutures();
607 - if (futures.isEmpty()) { 839 + if (future == null) {
608 // woohoo! we are done! 840 // woohoo! we are done!
609 - updateIntent(); 841 + updateIntents();
842 + batchService.removeIntentOperations(ops);
843 + } else if (endTime < System.currentTimeMillis()) {
844 + log.warn("Install request timed out");
845 +// future.cancel(true);
846 + // TODO retry and/or report the failure
610 } else { 847 } else {
611 // resubmit ourselves if we are not done yet 848 // resubmit ourselves if we are not done yet
612 monitorExecutor.submit(this); 849 monitorExecutor.submit(this);
613 } 850 }
614 } 851 }
615 } 852 }
853 +
854 + private class InternalBatchDelegate implements IntentBatchDelegate {
855 + @Override
856 + public void execute(IntentOperations operations) {
857 + log.info("Execute operations: {}", operations);
858 + //FIXME: perhaps we want to track this task so that we can cancel it.
859 + executor.execute(new IntentTask(operations));
860 + }
861 +
862 + @Override
863 + public void cancel(IntentOperations operations) {
864 + //FIXME: implement this
865 + log.warn("NOT IMPLEMENTED -- Cancel operations: {}", operations);
866 + }
867 + }
616 } 868 }
......
...@@ -111,6 +111,13 @@ public class LinkCollectionIntentInstaller implements IntentInstaller<LinkCollec ...@@ -111,6 +111,13 @@ public class LinkCollectionIntentInstaller implements IntentInstaller<LinkCollec
111 return Lists.newArrayList(new FlowRuleBatchOperation(rules)); 111 return Lists.newArrayList(new FlowRuleBatchOperation(rules));
112 } 112 }
113 113
114 + @Override
115 + public List<FlowRuleBatchOperation> replace(LinkCollectionIntent intent,
116 + LinkCollectionIntent newIntent) {
117 + // FIXME: implement
118 + return null;
119 + }
120 +
114 /** 121 /**
115 * Creates a FlowRuleBatchEntry based on the provided parameters. 122 * Creates a FlowRuleBatchEntry based on the provided parameters.
116 * 123 *
......
...@@ -29,6 +29,7 @@ import org.onlab.onos.net.intent.IntentExtensionService; ...@@ -29,6 +29,7 @@ import org.onlab.onos.net.intent.IntentExtensionService;
29 import org.onlab.onos.net.intent.LinkCollectionIntent; 29 import org.onlab.onos.net.intent.LinkCollectionIntent;
30 import org.onlab.onos.net.intent.MultiPointToSinglePointIntent; 30 import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
31 import org.onlab.onos.net.intent.PointToPointIntent; 31 import org.onlab.onos.net.intent.PointToPointIntent;
32 +import org.onlab.onos.net.resource.LinkResourceAllocations;
32 import org.onlab.onos.net.topology.PathService; 33 import org.onlab.onos.net.topology.PathService;
33 34
34 import java.util.Arrays; 35 import java.util.Arrays;
...@@ -61,7 +62,8 @@ public class MultiPointToSinglePointIntentCompiler ...@@ -61,7 +62,8 @@ public class MultiPointToSinglePointIntentCompiler
61 } 62 }
62 63
63 @Override 64 @Override
64 - public List<Intent> compile(MultiPointToSinglePointIntent intent) { 65 + public List<Intent> compile(MultiPointToSinglePointIntent intent, List<Intent> installable,
66 + Set<LinkResourceAllocations> resources) {
65 Set<Link> links = new HashSet<>(); 67 Set<Link> links = new HashSet<>();
66 68
67 for (ConnectPoint ingressPoint : intent.ingressPoints()) { 69 for (ConnectPoint ingressPoint : intent.ingressPoints()) {
......
...@@ -29,6 +29,7 @@ import org.onlab.onos.net.intent.IntentCompiler; ...@@ -29,6 +29,7 @@ import org.onlab.onos.net.intent.IntentCompiler;
29 import org.onlab.onos.net.intent.IntentExtensionService; 29 import org.onlab.onos.net.intent.IntentExtensionService;
30 import org.onlab.onos.net.intent.OpticalConnectivityIntent; 30 import org.onlab.onos.net.intent.OpticalConnectivityIntent;
31 import org.onlab.onos.net.intent.OpticalPathIntent; 31 import org.onlab.onos.net.intent.OpticalPathIntent;
32 +import org.onlab.onos.net.resource.LinkResourceAllocations;
32 import org.onlab.onos.net.topology.LinkWeight; 33 import org.onlab.onos.net.topology.LinkWeight;
33 import org.onlab.onos.net.topology.Topology; 34 import org.onlab.onos.net.topology.Topology;
34 import org.onlab.onos.net.topology.TopologyEdge; 35 import org.onlab.onos.net.topology.TopologyEdge;
...@@ -60,7 +61,9 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical ...@@ -60,7 +61,9 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
60 } 61 }
61 62
62 @Override 63 @Override
63 - public List<Intent> compile(OpticalConnectivityIntent intent) { 64 + public List<Intent> compile(OpticalConnectivityIntent intent,
65 + List<Intent> installable,
66 + Set<LinkResourceAllocations> resources) {
64 // TODO: compute multiple paths using the K-shortest path algorithm 67 // TODO: compute multiple paths using the K-shortest path algorithm
65 Path path = calculateOpticalPath(intent.getSrcConnectPoint(), intent.getDst()); 68 Path path = calculateOpticalPath(intent.getSrcConnectPoint(), intent.getDst());
66 Intent newIntent = new OpticalPathIntent(intent.appId(), 69 Intent newIntent = new OpticalPathIntent(intent.appId(),
......
...@@ -104,6 +104,13 @@ public class OpticalPathIntentInstaller implements IntentInstaller<OpticalPathIn ...@@ -104,6 +104,13 @@ public class OpticalPathIntentInstaller implements IntentInstaller<OpticalPathIn
104 return generateRules(intent, allocations, FlowRuleOperation.REMOVE); 104 return generateRules(intent, allocations, FlowRuleOperation.REMOVE);
105 } 105 }
106 106
107 + @Override
108 + public List<FlowRuleBatchOperation> replace(OpticalPathIntent intent,
109 + OpticalPathIntent newIntent) {
110 + // FIXME: implement this
111 + return null;
112 + }
113 +
107 private LinkResourceAllocations assignWavelength(OpticalPathIntent intent) { 114 private LinkResourceAllocations assignWavelength(OpticalPathIntent intent) {
108 LinkResourceRequest.Builder request = DefaultLinkResourceRequest.builder(intent.id(), 115 LinkResourceRequest.Builder request = DefaultLinkResourceRequest.builder(intent.id(),
109 intent.path().links()) 116 intent.path().links())
......
...@@ -131,6 +131,15 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { ...@@ -131,6 +131,15 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> {
131 return Lists.newArrayList(new FlowRuleBatchOperation(rules)); 131 return Lists.newArrayList(new FlowRuleBatchOperation(rules));
132 } 132 }
133 133
134 + @Override
135 + public List<FlowRuleBatchOperation> replace(PathIntent oldIntent, PathIntent newIntent) {
136 + // FIXME: implement this
137 + List<FlowRuleBatchOperation> batches = Lists.newArrayList();
138 + batches.addAll(uninstall(oldIntent));
139 + batches.addAll(install(newIntent));
140 + return batches;
141 + }
142 +
134 /** 143 /**
135 * Allocate resources required for an intent. 144 * Allocate resources required for an intent.
136 * 145 *
...@@ -147,7 +156,7 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { ...@@ -147,7 +156,7 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> {
147 return request.resources().isEmpty() ? null : resourceService.requestResources(request); 156 return request.resources().isEmpty() ? null : resourceService.requestResources(request);
148 } 157 }
149 158
150 - // TODO refactor below this line... ---------------------------- 159 + // FIXME refactor below this line... ----------------------------
151 160
152 /** 161 /**
153 * Generates the series of MatchActionOperations from the 162 * Generates the series of MatchActionOperations from the
......
...@@ -28,9 +28,11 @@ import org.onlab.onos.net.intent.Intent; ...@@ -28,9 +28,11 @@ import org.onlab.onos.net.intent.Intent;
28 import org.onlab.onos.net.intent.PathIntent; 28 import org.onlab.onos.net.intent.PathIntent;
29 import org.onlab.onos.net.intent.PointToPointIntent; 29 import org.onlab.onos.net.intent.PointToPointIntent;
30 import org.onlab.onos.net.provider.ProviderId; 30 import org.onlab.onos.net.provider.ProviderId;
31 +import org.onlab.onos.net.resource.LinkResourceAllocations;
31 32
32 import java.util.ArrayList; 33 import java.util.ArrayList;
33 import java.util.List; 34 import java.util.List;
35 +import java.util.Set;
34 36
35 import static java.util.Arrays.asList; 37 import static java.util.Arrays.asList;
36 import static org.onlab.onos.net.Link.Type.DIRECT; 38 import static org.onlab.onos.net.Link.Type.DIRECT;
...@@ -57,7 +59,9 @@ public class PointToPointIntentCompiler ...@@ -57,7 +59,9 @@ public class PointToPointIntentCompiler
57 } 59 }
58 60
59 @Override 61 @Override
60 - public List<Intent> compile(PointToPointIntent intent) { 62 + public List<Intent> compile(PointToPointIntent intent, List<Intent> installable,
63 + Set<LinkResourceAllocations> resources) {
64 +
61 ConnectPoint ingressPoint = intent.ingressPoint(); 65 ConnectPoint ingressPoint = intent.ingressPoint();
62 ConnectPoint egressPoint = intent.egressPoint(); 66 ConnectPoint egressPoint = intent.egressPoint();
63 67
......
...@@ -87,7 +87,7 @@ public class PathConstraintCalculationTest { ...@@ -87,7 +87,7 @@ public class PathConstraintCalculationTest {
87 constraints); 87 constraints);
88 final PointToPointIntentCompiler compiler = makeCompiler(resourceService); 88 final PointToPointIntentCompiler compiler = makeCompiler(resourceService);
89 89
90 - return compiler.compile(intent); 90 + return compiler.compile(intent, null, null);
91 } 91 }
92 92
93 /** 93 /**
......
...@@ -121,7 +121,7 @@ public class TestHostToHostIntentCompiler { ...@@ -121,7 +121,7 @@ public class TestHostToHostIntentCompiler {
121 HostToHostIntentCompiler compiler = makeCompiler(hops); 121 HostToHostIntentCompiler compiler = makeCompiler(hops);
122 assertThat(compiler, is(notNullValue())); 122 assertThat(compiler, is(notNullValue()));
123 123
124 - List<Intent> result = compiler.compile(intent); 124 + List<Intent> result = compiler.compile(intent, null, null);
125 assertThat(result, is(Matchers.notNullValue())); 125 assertThat(result, is(Matchers.notNullValue()));
126 assertThat(result, hasSize(2)); 126 assertThat(result, hasSize(2));
127 Intent forwardResultIntent = result.get(0); 127 Intent forwardResultIntent = result.get(0);
......
...@@ -137,7 +137,7 @@ public class TestMultiPointToSinglePointIntentCompiler { ...@@ -137,7 +137,7 @@ public class TestMultiPointToSinglePointIntentCompiler {
137 MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops); 137 MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
138 assertThat(compiler, is(notNullValue())); 138 assertThat(compiler, is(notNullValue()));
139 139
140 - List<Intent> result = compiler.compile(intent); 140 + List<Intent> result = compiler.compile(intent, null, null);
141 assertThat(result, is(Matchers.notNullValue())); 141 assertThat(result, is(Matchers.notNullValue()));
142 assertThat(result, hasSize(1)); 142 assertThat(result, hasSize(1));
143 Intent resultIntent = result.get(0); 143 Intent resultIntent = result.get(0);
...@@ -172,7 +172,7 @@ public class TestMultiPointToSinglePointIntentCompiler { ...@@ -172,7 +172,7 @@ public class TestMultiPointToSinglePointIntentCompiler {
172 MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops); 172 MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
173 assertThat(compiler, is(notNullValue())); 173 assertThat(compiler, is(notNullValue()));
174 174
175 - List<Intent> result = compiler.compile(intent); 175 + List<Intent> result = compiler.compile(intent, null, null);
176 assertThat(result, is(notNullValue())); 176 assertThat(result, is(notNullValue()));
177 assertThat(result, hasSize(1)); 177 assertThat(result, hasSize(1));
178 Intent resultIntent = result.get(0); 178 Intent resultIntent = result.get(0);
...@@ -205,7 +205,7 @@ public class TestMultiPointToSinglePointIntentCompiler { ...@@ -205,7 +205,7 @@ public class TestMultiPointToSinglePointIntentCompiler {
205 MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops); 205 MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
206 assertThat(compiler, is(notNullValue())); 206 assertThat(compiler, is(notNullValue()));
207 207
208 - List<Intent> result = compiler.compile(intent); 208 + List<Intent> result = compiler.compile(intent, null, null);
209 assertThat(result, is(notNullValue())); 209 assertThat(result, is(notNullValue()));
210 assertThat(result, hasSize(1)); 210 assertThat(result, hasSize(1));
211 Intent resultIntent = result.get(0); 211 Intent resultIntent = result.get(0);
......
...@@ -93,7 +93,7 @@ public class TestPointToPointIntentCompiler { ...@@ -93,7 +93,7 @@ public class TestPointToPointIntentCompiler {
93 PointToPointIntentCompiler compiler = makeCompiler(hops); 93 PointToPointIntentCompiler compiler = makeCompiler(hops);
94 assertThat(compiler, is(notNullValue())); 94 assertThat(compiler, is(notNullValue()));
95 95
96 - List<Intent> result = compiler.compile(intent); 96 + List<Intent> result = compiler.compile(intent, null, null);
97 assertThat(result, is(Matchers.notNullValue())); 97 assertThat(result, is(Matchers.notNullValue()));
98 assertThat(result, hasSize(1)); 98 assertThat(result, hasSize(1));
99 Intent forwardResultIntent = result.get(0); 99 Intent forwardResultIntent = result.get(0);
...@@ -126,7 +126,7 @@ public class TestPointToPointIntentCompiler { ...@@ -126,7 +126,7 @@ public class TestPointToPointIntentCompiler {
126 PointToPointIntentCompiler compiler = makeCompiler(hops); 126 PointToPointIntentCompiler compiler = makeCompiler(hops);
127 assertThat(compiler, is(notNullValue())); 127 assertThat(compiler, is(notNullValue()));
128 128
129 - List<Intent> result = compiler.compile(intent); 129 + List<Intent> result = compiler.compile(intent, null, null);
130 assertThat(result, is(Matchers.notNullValue())); 130 assertThat(result, is(Matchers.notNullValue()));
131 assertThat(result, hasSize(1)); 131 assertThat(result, hasSize(1));
132 Intent reverseResultIntent = result.get(0); 132 Intent reverseResultIntent = result.get(0);
...@@ -157,7 +157,7 @@ public class TestPointToPointIntentCompiler { ...@@ -157,7 +157,7 @@ public class TestPointToPointIntentCompiler {
157 String[] hops = {"1"}; 157 String[] hops = {"1"};
158 PointToPointIntentCompiler sut = makeCompiler(hops); 158 PointToPointIntentCompiler sut = makeCompiler(hops);
159 159
160 - List<Intent> compiled = sut.compile(intent); 160 + List<Intent> compiled = sut.compile(intent, null, null);
161 161
162 assertThat(compiled, hasSize(1)); 162 assertThat(compiled, hasSize(1));
163 assertThat(compiled.get(0), is(instanceOf(PathIntent.class))); 163 assertThat(compiled.get(0), is(instanceOf(PathIntent.class)));
......
1 +/*
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 + */
16 +package org.onlab.onos.store.trivial.impl;
17 +
18 +import com.google.common.collect.ImmutableSet;
19 +import org.apache.felix.scr.annotations.Activate;
20 +import org.apache.felix.scr.annotations.Component;
21 +import org.apache.felix.scr.annotations.Deactivate;
22 +import org.apache.felix.scr.annotations.Service;
23 +import org.onlab.onos.net.intent.IntentBatchDelegate;
24 +import org.onlab.onos.net.intent.IntentBatchService;
25 +import org.onlab.onos.net.intent.IntentOperations;
26 +import org.slf4j.Logger;
27 +
28 +import java.util.HashSet;
29 +import java.util.Set;
30 +
31 +import static com.google.common.base.Preconditions.checkNotNull;
32 +import static com.google.common.base.Preconditions.checkState;
33 +import static org.slf4j.LoggerFactory.getLogger;
34 +
35 +@Component(immediate = true)
36 +@Service
37 +public class SimpleIntentBatchQueue implements IntentBatchService {
38 +
39 + private final Logger log = getLogger(getClass());
40 + private final Set<IntentOperations> pendingBatches = new HashSet<>();
41 + private IntentBatchDelegate delegate;
42 +
43 + @Activate
44 + public void activate() {
45 + log.info("Started");
46 + }
47 +
48 + @Deactivate
49 + public void deactivate() {
50 + log.info("Stopped");
51 + }
52 +
53 + @Override
54 + public void addIntentOperations(IntentOperations operations) {
55 + checkState(delegate != null, "No delegate set");
56 + pendingBatches.add(operations);
57 + delegate.execute(operations);
58 + }
59 +
60 + @Override
61 + public void removeIntentOperations(IntentOperations operations) {
62 + pendingBatches.remove(operations);
63 + }
64 +
65 + @Override
66 + public Set<IntentOperations> getIntentOperations() {
67 + return ImmutableSet.copyOf(pendingBatches);
68 + }
69 +
70 + @Override
71 + public void setDelegate(IntentBatchDelegate delegate) {
72 + this.delegate = checkNotNull(delegate, "Delegate cannot be null");
73 + }
74 +
75 + @Override
76 + public void unsetDelegate(IntentBatchDelegate delegate) {
77 + if (this.delegate != null && this.delegate.equals(delegate)) {
78 + this.delegate = null;
79 + }
80 + }
81 +}
...@@ -33,7 +33,7 @@ import java.util.List; ...@@ -33,7 +33,7 @@ import java.util.List;
33 import java.util.Map; 33 import java.util.Map;
34 import java.util.concurrent.ConcurrentHashMap; 34 import java.util.concurrent.ConcurrentHashMap;
35 35
36 -import static org.onlab.onos.net.intent.IntentState.*; 36 +import static org.onlab.onos.net.intent.IntentState.WITHDRAWN;
37 import static org.slf4j.LoggerFactory.getLogger; 37 import static org.slf4j.LoggerFactory.getLogger;
38 38
39 @Component(immediate = true) 39 @Component(immediate = true)
...@@ -45,8 +45,8 @@ public class SimpleIntentStore ...@@ -45,8 +45,8 @@ public class SimpleIntentStore
45 private final Logger log = getLogger(getClass()); 45 private final Logger log = getLogger(getClass());
46 private final Map<IntentId, Intent> intents = new ConcurrentHashMap<>(); 46 private final Map<IntentId, Intent> intents = new ConcurrentHashMap<>();
47 private final Map<IntentId, IntentState> states = new ConcurrentHashMap<>(); 47 private final Map<IntentId, IntentState> states = new ConcurrentHashMap<>();
48 - private final Map<IntentId, List<Intent>> installable = 48 + private final Map<IntentId, List<Intent>> installable = new ConcurrentHashMap<>();
49 - new ConcurrentHashMap<>(); 49 +
50 50
51 @Activate 51 @Activate
52 public void activate() { 52 public void activate() {
...@@ -60,6 +60,9 @@ public class SimpleIntentStore ...@@ -60,6 +60,9 @@ public class SimpleIntentStore
60 60
61 @Override 61 @Override
62 public IntentEvent createIntent(Intent intent) { 62 public IntentEvent createIntent(Intent intent) {
63 + if (intents.containsKey(intent.id())) {
64 + return null;
65 + }
63 intents.put(intent.id(), intent); 66 intents.put(intent.id(), intent);
64 return this.setState(intent, IntentState.SUBMITTED); 67 return this.setState(intent, IntentState.SUBMITTED);
65 } 68 }
......