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); | ... | ... |
core/net/src/test/java/org/onlab/onos/net/intent/impl/TestMultiPointToSinglePointIntentCompiler.java
... | @@ -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))); | ... | ... |
core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleIntentBatchQueue.java
0 → 100644
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 | } | ... | ... |
-
Please register or login to post a comment