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