Committed by
Gerrit Code Review
fix intent issues yuta observed
Change-Id: I7dc4a19d49a1b3fc18ecce02a4018cbc9a3043fc
Showing
13 changed files
with
208 additions
and
107 deletions
... | @@ -14,6 +14,7 @@ public interface DemoAPI { | ... | @@ -14,6 +14,7 @@ public interface DemoAPI { |
14 | /** | 14 | /** |
15 | * Installs intents based on the installation type. | 15 | * Installs intents based on the installation type. |
16 | * @param type the installation type. | 16 | * @param type the installation type. |
17 | + * @param runParams run params | ||
17 | */ | 18 | */ |
18 | void setup(InstallType type, Optional<JsonNode> runParams); | 19 | void setup(InstallType type, Optional<JsonNode> runParams); |
19 | 20 | ... | ... |
... | @@ -199,6 +199,7 @@ public class IntentPushTestCommand extends AbstractShellCommand | ... | @@ -199,6 +199,7 @@ public class IntentPushTestCommand extends AbstractShellCommand |
199 | /** | 199 | /** |
200 | * Returns application ID for the CLI. | 200 | * Returns application ID for the CLI. |
201 | * | 201 | * |
202 | + * @param id application id | ||
202 | * @return command-line application identifier | 203 | * @return command-line application identifier |
203 | */ | 204 | */ |
204 | protected ApplicationId appId(Integer id) { | 205 | protected ApplicationId appId(Integer id) { | ... | ... |
... | @@ -56,8 +56,8 @@ public interface IntentBatchService { | ... | @@ -56,8 +56,8 @@ public interface IntentBatchService { |
56 | * Return true if this instance is the local leader for batch | 56 | * Return true if this instance is the local leader for batch |
57 | * processing a given application id. | 57 | * processing a given application id. |
58 | * | 58 | * |
59 | - * @param applicationId | 59 | + * @param applicationId an application id |
60 | - * @return | 60 | + * @return true if this instance is the local leader for batch |
61 | */ | 61 | */ |
62 | boolean isLocalLeader(ApplicationId applicationId); | 62 | boolean isLocalLeader(ApplicationId applicationId); |
63 | 63 | ... | ... |
... | @@ -67,4 +67,32 @@ public class IntentEvent extends AbstractEvent<IntentEvent.Type, Intent> { | ... | @@ -67,4 +67,32 @@ public class IntentEvent extends AbstractEvent<IntentEvent.Type, Intent> { |
67 | super(type, intent); | 67 | super(type, intent); |
68 | } | 68 | } |
69 | 69 | ||
70 | + public static IntentEvent getEvent(IntentState state, Intent intent) { | ||
71 | + Type type; | ||
72 | + switch (state) { | ||
73 | + case SUBMITTED: | ||
74 | + type = Type.SUBMITTED; | ||
75 | + break; | ||
76 | + case INSTALLED: | ||
77 | + type = Type.INSTALLED; | ||
78 | + break; | ||
79 | + case WITHDRAWN: | ||
80 | + type = Type.WITHDRAWN; | ||
81 | + break; | ||
82 | + case FAILED: | ||
83 | + type = Type.FAILED; | ||
84 | + break; | ||
85 | + | ||
86 | + //fallthrough to default from here | ||
87 | + case COMPILING: | ||
88 | + case INSTALLING: | ||
89 | + case RECOMPILING: | ||
90 | + case WITHDRAWING: | ||
91 | + default: | ||
92 | + throw new IllegalArgumentException( | ||
93 | + "Intent event cannot have transient state: " + state); | ||
94 | + } | ||
95 | + return new IntentEvent(type, intent); | ||
96 | + } | ||
97 | + | ||
70 | } | 98 | } | ... | ... |
... | @@ -15,7 +15,6 @@ | ... | @@ -15,7 +15,6 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.intent; | 16 | package org.onlab.onos.net.intent; |
17 | 17 | ||
18 | -import static com.google.common.base.Preconditions.checkArgument; | ||
19 | import static com.google.common.base.Preconditions.checkNotNull; | 18 | import static com.google.common.base.Preconditions.checkNotNull; |
20 | 19 | ||
21 | import org.onlab.onos.net.intent.IntentStore.BatchWrite.Operation; | 20 | import org.onlab.onos.net.intent.IntentStore.BatchWrite.Operation; |
... | @@ -42,16 +41,16 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { | ... | @@ -42,16 +41,16 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { |
42 | * mechanism. | 41 | * mechanism. |
43 | * | 42 | * |
44 | * @param intent intent to be submitted | 43 | * @param intent intent to be submitted |
45 | - * @return event indicating the intent was submitted or null if no | ||
46 | - * change resulted, e.g. duplicate intent | ||
47 | */ | 44 | */ |
48 | - IntentEvent createIntent(Intent intent); | 45 | + @Deprecated |
46 | + void createIntent(Intent intent); | ||
49 | 47 | ||
50 | /** | 48 | /** |
51 | * Removes the specified intent from the inventory. | 49 | * Removes the specified intent from the inventory. |
52 | * | 50 | * |
53 | * @param intentId intent identification | 51 | * @param intentId intent identification |
54 | */ | 52 | */ |
53 | + @Deprecated | ||
55 | void removeIntent(IntentId intentId); | 54 | void removeIntent(IntentId intentId); |
56 | 55 | ||
57 | /** | 56 | /** |
... | @@ -89,9 +88,8 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { | ... | @@ -89,9 +88,8 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { |
89 | * | 88 | * |
90 | * @param intent intent whose state is to be changed | 89 | * @param intent intent whose state is to be changed |
91 | * @param newState new state | 90 | * @param newState new state |
92 | - * @return state transition event | ||
93 | */ | 91 | */ |
94 | - IntentEvent setState(Intent intent, IntentState newState); | 92 | + void setState(Intent intent, IntentState newState); |
95 | 93 | ||
96 | /** | 94 | /** |
97 | * Sets the installable intents which resulted from compilation of the | 95 | * Sets the installable intents which resulted from compilation of the |
... | @@ -129,64 +127,13 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { | ... | @@ -129,64 +127,13 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { |
129 | return new BatchWrite(); | 127 | return new BatchWrite(); |
130 | } | 128 | } |
131 | 129 | ||
132 | - // default implementation simply executes them sequentially. | ||
133 | - // Store implementation should override and implement actual batch write. | ||
134 | /** | 130 | /** |
135 | * Execute writes in a batch. | 131 | * Execute writes in a batch. |
136 | * | 132 | * |
137 | * @param batch BatchWrite to execute | 133 | * @param batch BatchWrite to execute |
138 | * @return failed operations | 134 | * @return failed operations |
139 | */ | 135 | */ |
140 | - default List<Operation> batchWrite(BatchWrite batch) { | 136 | + List<Operation> batchWrite(BatchWrite batch); |
141 | - List<Operation> failed = new ArrayList<>(); | ||
142 | - for (Operation op : batch.operations) { | ||
143 | - switch (op.type) { | ||
144 | - case CREATE_INTENT: | ||
145 | - checkArgument(op.args.size() == 1, | ||
146 | - "CREATE_INTENT takes 1 argument. %s", op); | ||
147 | - Intent intent = (Intent) op.args.get(0); | ||
148 | - if (createIntent(intent) == null) { | ||
149 | - failed.add(op); | ||
150 | - } | ||
151 | - break; | ||
152 | - | ||
153 | - case REMOVE_INTENT: | ||
154 | - checkArgument(op.args.size() == 1, | ||
155 | - "REMOVE_INTENT takes 1 argument. %s", op); | ||
156 | - IntentId intentId = (IntentId) op.args.get(0); | ||
157 | - removeIntent(intentId); | ||
158 | - break; | ||
159 | - | ||
160 | - case REMOVE_INSTALLED: | ||
161 | - checkArgument(op.args.size() == 1, | ||
162 | - "REMOVE_INSTALLED takes 1 argument. %s", op); | ||
163 | - intentId = (IntentId) op.args.get(0); | ||
164 | - removeInstalledIntents(intentId); | ||
165 | - break; | ||
166 | - | ||
167 | - case SET_INSTALLABLE: | ||
168 | - checkArgument(op.args.size() == 2, | ||
169 | - "SET_INSTALLABLE takes 2 arguments. %s", op); | ||
170 | - intentId = (IntentId) op.args.get(0); | ||
171 | - @SuppressWarnings("unchecked") | ||
172 | - List<Intent> installableIntents = (List<Intent>) op.args.get(1); | ||
173 | - setInstallableIntents(intentId, installableIntents); | ||
174 | - break; | ||
175 | - | ||
176 | - case SET_STATE: | ||
177 | - checkArgument(op.args.size() == 2, | ||
178 | - "SET_STATE takes 2 arguments. %s", op); | ||
179 | - intent = (Intent) op.args.get(0); | ||
180 | - IntentState newState = (IntentState) op.args.get(1); | ||
181 | - setState(intent, newState); | ||
182 | - break; | ||
183 | - | ||
184 | - default: | ||
185 | - break; | ||
186 | - } | ||
187 | - } | ||
188 | - return failed; | ||
189 | - } | ||
190 | 137 | ||
191 | public static class BatchWrite { | 138 | public static class BatchWrite { |
192 | 139 | ... | ... |
... | @@ -128,7 +128,7 @@ public class IntentManager | ... | @@ -128,7 +128,7 @@ public class IntentManager |
128 | trackerService.setDelegate(topoDelegate); | 128 | trackerService.setDelegate(topoDelegate); |
129 | batchService.setDelegate(batchDelegate); | 129 | batchService.setDelegate(batchDelegate); |
130 | eventDispatcher.addSink(IntentEvent.class, listenerRegistry); | 130 | eventDispatcher.addSink(IntentEvent.class, listenerRegistry); |
131 | - executor = newFixedThreadPool(NUM_THREADS, namedThreads("onos-intent-monitor")); | 131 | + executor = newFixedThreadPool(NUM_THREADS, namedThreads("onos-intent")); |
132 | idGenerator = coreService.getIdGenerator("intent-ids"); | 132 | idGenerator = coreService.getIdGenerator("intent-ids"); |
133 | Intent.bindIdGenerator(idGenerator); | 133 | Intent.bindIdGenerator(idGenerator); |
134 | log.info("Started"); | 134 | log.info("Started"); |
... | @@ -646,12 +646,11 @@ public class IntentManager | ... | @@ -646,12 +646,11 @@ public class IntentManager |
646 | return !isComplete() ? batches.get(currentBatch) : null; | 646 | return !isComplete() ? batches.get(currentBatch) : null; |
647 | } | 647 | } |
648 | 648 | ||
649 | - List<IntentEvent> batchSuccess(BatchWrite batchWrite) { | 649 | + void batchSuccess(BatchWrite batchWrite) { |
650 | // move on to next Batch | 650 | // move on to next Batch |
651 | if (++currentBatch == batches.size()) { | 651 | if (++currentBatch == batches.size()) { |
652 | - return finalizeStates(batchWrite); | 652 | + finalizeStates(batchWrite); |
653 | } | 653 | } |
654 | - return Collections.emptyList(); | ||
655 | } | 654 | } |
656 | 655 | ||
657 | void batchFailed() { | 656 | void batchFailed() { |
... | @@ -673,19 +672,16 @@ public class IntentManager | ... | @@ -673,19 +672,16 @@ public class IntentManager |
673 | } | 672 | } |
674 | 673 | ||
675 | // FIXME make sure this is called!!! | 674 | // FIXME make sure this is called!!! |
676 | - private List<IntentEvent> finalizeStates(BatchWrite batchWrite) { | 675 | + private void finalizeStates(BatchWrite batchWrite) { |
677 | // events to be triggered on successful write | 676 | // events to be triggered on successful write |
678 | - List<IntentEvent> events = new ArrayList<>(); | ||
679 | for (Intent intent : stateMap.keySet()) { | 677 | for (Intent intent : stateMap.keySet()) { |
680 | switch (getInflightState(intent)) { | 678 | switch (getInflightState(intent)) { |
681 | case INSTALLING: | 679 | case INSTALLING: |
682 | batchWrite.setState(intent, INSTALLED); | 680 | batchWrite.setState(intent, INSTALLED); |
683 | batchWrite.setInstallableIntents(newIntent.id(), newInstallables); | 681 | batchWrite.setInstallableIntents(newIntent.id(), newInstallables); |
684 | - events.add(new IntentEvent(Type.INSTALLED, intent)); | ||
685 | break; | 682 | break; |
686 | case WITHDRAWING: | 683 | case WITHDRAWING: |
687 | batchWrite.setState(intent, WITHDRAWN); | 684 | batchWrite.setState(intent, WITHDRAWN); |
688 | - events.add(new IntentEvent(Type.WITHDRAWN, intent)); | ||
689 | batchWrite.removeInstalledIntents(intent.id()); | 685 | batchWrite.removeInstalledIntents(intent.id()); |
690 | batchWrite.removeIntent(intent.id()); | 686 | batchWrite.removeIntent(intent.id()); |
691 | break; | 687 | break; |
... | @@ -705,7 +701,6 @@ public class IntentManager | ... | @@ -705,7 +701,6 @@ public class IntentManager |
705 | break; | 701 | break; |
706 | } | 702 | } |
707 | } | 703 | } |
708 | - return events; | ||
709 | } | 704 | } |
710 | 705 | ||
711 | List<FlowRuleBatchOperation> batches() { | 706 | List<FlowRuleBatchOperation> batches() { |
... | @@ -737,10 +732,10 @@ public class IntentManager | ... | @@ -737,10 +732,10 @@ public class IntentManager |
737 | intent.id(), oldState, newState); | 732 | intent.id(), oldState, newState); |
738 | 733 | ||
739 | stateMap.put(intent, newState); | 734 | stateMap.put(intent, newState); |
740 | - IntentEvent event = store.setState(intent, newState); | 735 | +// IntentEvent event = store.setState(intent, newState); |
741 | - if (event != null) { | 736 | +// if (event != null) { |
742 | - eventDispatcher.post(event); | 737 | +// eventDispatcher.post(event); |
743 | - } | 738 | +// } |
744 | } | 739 | } |
745 | 740 | ||
746 | Map<Intent, IntentState> stateMap() { | 741 | Map<Intent, IntentState> stateMap() { |
... | @@ -822,7 +817,7 @@ public class IntentManager | ... | @@ -822,7 +817,7 @@ public class IntentManager |
822 | BatchWrite batchWrite = store.newBatchWrite(); | 817 | BatchWrite batchWrite = store.newBatchWrite(); |
823 | List<IntentEvent> events = new ArrayList<>(); | 818 | List<IntentEvent> events = new ArrayList<>(); |
824 | for (IntentUpdate update : intentUpdates) { | 819 | for (IntentUpdate update : intentUpdates) { |
825 | - events.addAll(update.batchSuccess(batchWrite)); | 820 | + update.batchSuccess(batchWrite); |
826 | } | 821 | } |
827 | if (!batchWrite.isEmpty()) { | 822 | if (!batchWrite.isEmpty()) { |
828 | store.batchWrite(batchWrite); | 823 | store.batchWrite(batchWrite); | ... | ... |
... | @@ -5,6 +5,7 @@ import com.google.common.collect.Lists; | ... | @@ -5,6 +5,7 @@ import com.google.common.collect.Lists; |
5 | import com.google.common.collect.Maps; | 5 | import com.google.common.collect.Maps; |
6 | import com.google.common.collect.Multimap; | 6 | import com.google.common.collect.Multimap; |
7 | import com.google.common.collect.Sets; | 7 | import com.google.common.collect.Sets; |
8 | + | ||
8 | import org.hamcrest.Description; | 9 | import org.hamcrest.Description; |
9 | import org.hamcrest.Matchers; | 10 | import org.hamcrest.Matchers; |
10 | import org.hamcrest.TypeSafeMatcher; | 11 | import org.hamcrest.TypeSafeMatcher; |
... | @@ -40,6 +41,7 @@ import java.util.List; | ... | @@ -40,6 +41,7 @@ import java.util.List; |
40 | import java.util.Map; | 41 | import java.util.Map; |
41 | import java.util.Set; | 42 | import java.util.Set; |
42 | import java.util.concurrent.CountDownLatch; | 43 | import java.util.concurrent.CountDownLatch; |
44 | +import java.util.concurrent.TimeUnit; | ||
43 | import java.util.concurrent.atomic.AtomicLong; | 45 | import java.util.concurrent.atomic.AtomicLong; |
44 | 46 | ||
45 | import static org.hamcrest.Matchers.equalTo; | 47 | import static org.hamcrest.Matchers.equalTo; |
... | @@ -229,7 +231,8 @@ public class IntentManagerTest { | ... | @@ -229,7 +231,8 @@ public class IntentManagerTest { |
229 | 231 | ||
230 | public void await(IntentEvent.Type type) { | 232 | public void await(IntentEvent.Type type) { |
231 | try { | 233 | try { |
232 | - latchMap.get(type).await(); | 234 | + assertTrue("Timed out waiting for: " + type, |
235 | + latchMap.get(type).await(5, TimeUnit.SECONDS)); | ||
233 | } catch (InterruptedException e) { | 236 | } catch (InterruptedException e) { |
234 | e.printStackTrace(); | 237 | e.printStackTrace(); |
235 | } | 238 | } | ... | ... |
... | @@ -18,6 +18,7 @@ package org.onlab.onos.store.hz; | ... | @@ -18,6 +18,7 @@ package org.onlab.onos.store.hz; |
18 | import com.google.common.base.Function; | 18 | import com.google.common.base.Function; |
19 | import com.google.common.collect.FluentIterable; | 19 | import com.google.common.collect.FluentIterable; |
20 | import com.hazelcast.core.IQueue; | 20 | import com.hazelcast.core.IQueue; |
21 | +import com.hazelcast.core.ItemEvent; | ||
21 | import com.hazelcast.core.ItemListener; | 22 | import com.hazelcast.core.ItemListener; |
22 | import com.hazelcast.monitor.LocalQueueStats; | 23 | import com.hazelcast.monitor.LocalQueueStats; |
23 | 24 | ||
... | @@ -201,16 +202,39 @@ public class SQueue<T> implements IQueue<T> { | ... | @@ -201,16 +202,39 @@ public class SQueue<T> implements IQueue<T> { |
201 | return q.getLocalQueueStats(); | 202 | return q.getLocalQueueStats(); |
202 | } | 203 | } |
203 | 204 | ||
204 | - @Deprecated // not implemented yet | 205 | + |
205 | @Override | 206 | @Override |
206 | - public String addItemListener(ItemListener<T> itemListener, boolean b) { | 207 | + public String addItemListener(ItemListener<T> itemListener, boolean withValue) { |
207 | - throw new UnsupportedOperationException(); | 208 | + ItemListener<byte[]> il = new ItemListener<byte[]>() { |
209 | + @Override | ||
210 | + public void itemAdded(ItemEvent<byte[]> item) { | ||
211 | + itemListener.itemAdded(new ItemEvent<T>(getName(item), | ||
212 | + item.getEventType(), | ||
213 | + deserialize(item.getItem()), | ||
214 | + item.getMember())); | ||
215 | + } | ||
216 | + | ||
217 | + @Override | ||
218 | + public void itemRemoved(ItemEvent<byte[]> item) { | ||
219 | + itemListener.itemRemoved(new ItemEvent<T>(getName(item), | ||
220 | + item.getEventType(), | ||
221 | + deserialize(item.getItem()), | ||
222 | + item.getMember())); | ||
223 | + } | ||
224 | + | ||
225 | + private String getName(ItemEvent<byte[]> item) { | ||
226 | + return (item.getSource() instanceof String) ? | ||
227 | + (String) item.getSource() : item.getSource().toString(); | ||
228 | + | ||
229 | + } | ||
230 | + }; | ||
231 | + return q.addItemListener(il, withValue); | ||
208 | } | 232 | } |
209 | 233 | ||
210 | - @Deprecated // not implemented yet | 234 | + |
211 | @Override | 235 | @Override |
212 | - public boolean removeItemListener(String s) { | 236 | + public boolean removeItemListener(String registrationId) { |
213 | - throw new UnsupportedOperationException(); | 237 | + return q.removeItemListener(registrationId); |
214 | } | 238 | } |
215 | 239 | ||
216 | @Deprecated | 240 | @Deprecated | ... | ... |
... | @@ -23,6 +23,7 @@ import com.google.common.cache.CacheLoader; | ... | @@ -23,6 +23,7 @@ import com.google.common.cache.CacheLoader; |
23 | import com.google.common.cache.LoadingCache; | 23 | import com.google.common.cache.LoadingCache; |
24 | import com.google.common.collect.ImmutableSet; | 24 | import com.google.common.collect.ImmutableSet; |
25 | 25 | ||
26 | +import com.google.common.collect.Lists; | ||
26 | import org.apache.felix.scr.annotations.Activate; | 27 | import org.apache.felix.scr.annotations.Activate; |
27 | import org.apache.felix.scr.annotations.Component; | 28 | import org.apache.felix.scr.annotations.Component; |
28 | import org.apache.felix.scr.annotations.Deactivate; | 29 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -187,15 +188,16 @@ public class DistributedIntentStore | ... | @@ -187,15 +188,16 @@ public class DistributedIntentStore |
187 | } | 188 | } |
188 | 189 | ||
189 | @Override | 190 | @Override |
190 | - public IntentEvent createIntent(Intent intent) { | 191 | + public void createIntent(Intent intent) { |
191 | Context timer = startTimer(createIntentTimer); | 192 | Context timer = startTimer(createIntentTimer); |
192 | try { | 193 | try { |
193 | boolean absent = intents.putIfAbsent(intent.id(), intent); | 194 | boolean absent = intents.putIfAbsent(intent.id(), intent); |
194 | if (!absent) { | 195 | if (!absent) { |
195 | // duplicate, ignore | 196 | // duplicate, ignore |
196 | - return null; | 197 | + return; |
197 | } else { | 198 | } else { |
198 | - return this.setState(intent, IntentState.SUBMITTED); | 199 | + this.setState(intent, IntentState.SUBMITTED); |
200 | + return; | ||
199 | } | 201 | } |
200 | } finally { | 202 | } finally { |
201 | stopTimer(timer); | 203 | stopTimer(timer); |
... | @@ -273,7 +275,7 @@ public class DistributedIntentStore | ... | @@ -273,7 +275,7 @@ public class DistributedIntentStore |
273 | } | 275 | } |
274 | 276 | ||
275 | @Override | 277 | @Override |
276 | - public IntentEvent setState(Intent intent, IntentState state) { | 278 | + public void setState(Intent intent, IntentState state) { |
277 | Context timer = startTimer(setStateTimer); | 279 | Context timer = startTimer(setStateTimer); |
278 | try { | 280 | try { |
279 | final IntentId id = intent.id(); | 281 | final IntentId id = intent.id(); |
... | @@ -341,10 +343,10 @@ public class DistributedIntentStore | ... | @@ -341,10 +343,10 @@ public class DistributedIntentStore |
341 | log.debug("Transient State change: {} {}=>{}", id, prevTransient, state); | 343 | log.debug("Transient State change: {} {}=>{}", id, prevTransient, state); |
342 | } | 344 | } |
343 | 345 | ||
344 | - if (evtType == null) { | 346 | + if (evtType != null) { |
345 | - return null; | 347 | + notifyDelegate(new IntentEvent(evtType, intent)); |
346 | } | 348 | } |
347 | - return new IntentEvent(evtType, intent); | 349 | + return; |
348 | } finally { | 350 | } finally { |
349 | stopTimer(timer); | 351 | stopTimer(timer); |
350 | } | 352 | } |
... | @@ -417,6 +419,7 @@ public class DistributedIntentStore | ... | @@ -417,6 +419,7 @@ public class DistributedIntentStore |
417 | 419 | ||
418 | List<Operation> failed = new ArrayList<>(); | 420 | List<Operation> failed = new ArrayList<>(); |
419 | final Builder builder = BatchWriteRequest.newBuilder(); | 421 | final Builder builder = BatchWriteRequest.newBuilder(); |
422 | + List<IntentEvent> events = Lists.newArrayList(); | ||
420 | 423 | ||
421 | final Set<IntentId> transitionedToParking = new HashSet<>(); | 424 | final Set<IntentId> transitionedToParking = new HashSet<>(); |
422 | 425 | ||
... | @@ -428,6 +431,7 @@ public class DistributedIntentStore | ... | @@ -428,6 +431,7 @@ public class DistributedIntentStore |
428 | Intent intent = op.arg(0); | 431 | Intent intent = op.arg(0); |
429 | builder.putIfAbsent(INTENTS_TABLE, strIntentId(intent.id()), serializer.encode(intent)); | 432 | builder.putIfAbsent(INTENTS_TABLE, strIntentId(intent.id()), serializer.encode(intent)); |
430 | builder.putIfAbsent(STATES_TABLE, strIntentId(intent.id()), serializer.encode(SUBMITTED)); | 433 | builder.putIfAbsent(STATES_TABLE, strIntentId(intent.id()), serializer.encode(SUBMITTED)); |
434 | + events.add(IntentEvent.getEvent(SUBMITTED, intent)); | ||
431 | break; | 435 | break; |
432 | 436 | ||
433 | case REMOVE_INTENT: | 437 | case REMOVE_INTENT: |
... | @@ -450,6 +454,7 @@ public class DistributedIntentStore | ... | @@ -450,6 +454,7 @@ public class DistributedIntentStore |
450 | } else { | 454 | } else { |
451 | transitionedToParking.remove(intent.id()); | 455 | transitionedToParking.remove(intent.id()); |
452 | } | 456 | } |
457 | + events.add(IntentEvent.getEvent(newState, intent)); | ||
453 | break; | 458 | break; |
454 | 459 | ||
455 | case SET_INSTALLABLE: | 460 | case SET_INSTALLABLE: |
... | @@ -478,9 +483,11 @@ public class DistributedIntentStore | ... | @@ -478,9 +483,11 @@ public class DistributedIntentStore |
478 | if (batchWriteResult.isSuccessful()) { | 483 | if (batchWriteResult.isSuccessful()) { |
479 | // no-failure (except for invalid input) | 484 | // no-failure (except for invalid input) |
480 | transitionedToParking.forEach((intentId) -> transientStates.remove(intentId)); | 485 | transitionedToParking.forEach((intentId) -> transientStates.remove(intentId)); |
486 | + notifyDelegate(events); | ||
481 | return failed; | 487 | return failed; |
482 | } else { | 488 | } else { |
483 | // everything failed | 489 | // everything failed |
490 | + // FIXME what to do with events? | ||
484 | return batch.operations(); | 491 | return batch.operations(); |
485 | } | 492 | } |
486 | } | 493 | } | ... | ... |
... | @@ -19,6 +19,9 @@ import com.google.common.collect.Maps; | ... | @@ -19,6 +19,9 @@ import com.google.common.collect.Maps; |
19 | import com.google.common.collect.Sets; | 19 | import com.google.common.collect.Sets; |
20 | import com.hazelcast.core.HazelcastInstance; | 20 | import com.hazelcast.core.HazelcastInstance; |
21 | import com.hazelcast.core.IQueue; | 21 | import com.hazelcast.core.IQueue; |
22 | +import com.hazelcast.core.ItemEvent; | ||
23 | +import com.hazelcast.core.ItemListener; | ||
24 | + | ||
22 | import org.apache.felix.scr.annotations.Activate; | 25 | import org.apache.felix.scr.annotations.Activate; |
23 | import org.apache.felix.scr.annotations.Component; | 26 | import org.apache.felix.scr.annotations.Component; |
24 | import org.apache.felix.scr.annotations.Deactivate; | 27 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -47,7 +50,6 @@ import java.util.Collections; | ... | @@ -47,7 +50,6 @@ import java.util.Collections; |
47 | import java.util.Map; | 50 | import java.util.Map; |
48 | import java.util.Set; | 51 | import java.util.Set; |
49 | 52 | ||
50 | - | ||
51 | import static com.google.common.base.Preconditions.checkNotNull; | 53 | import static com.google.common.base.Preconditions.checkNotNull; |
52 | import static com.google.common.base.Preconditions.checkState; | 54 | import static com.google.common.base.Preconditions.checkState; |
53 | import static org.slf4j.LoggerFactory.getLogger; | 55 | import static org.slf4j.LoggerFactory.getLogger; |
... | @@ -107,6 +109,9 @@ public class HazelcastIntentBatchQueue | ... | @@ -107,6 +109,9 @@ public class HazelcastIntentBatchQueue |
107 | @Deactivate | 109 | @Deactivate |
108 | public void deactivate() { | 110 | public void deactivate() { |
109 | leadershipService.removeListener(leaderListener); | 111 | leadershipService.removeListener(leaderListener); |
112 | + for (ApplicationId appId: batchQueues.keySet()) { | ||
113 | + leadershipService.withdraw(getTopic(appId)); | ||
114 | + } | ||
110 | log.info("Stopped"); | 115 | log.info("Stopped"); |
111 | } | 116 | } |
112 | 117 | ||
... | @@ -125,12 +130,11 @@ public class HazelcastIntentBatchQueue | ... | @@ -125,12 +130,11 @@ public class HazelcastIntentBatchQueue |
125 | SQueue<IntentOperations> queue = batchQueues.get(appId); | 130 | SQueue<IntentOperations> queue = batchQueues.get(appId); |
126 | if (queue == null) { | 131 | if (queue == null) { |
127 | synchronized (this) { | 132 | synchronized (this) { |
128 | - // FIXME how will other instances find out about new queues | ||
129 | String topic = getTopic(appId); | 133 | String topic = getTopic(appId); |
130 | IQueue<byte[]> rawQueue = theInstance.getQueue(topic); | 134 | IQueue<byte[]> rawQueue = theInstance.getQueue(topic); |
131 | queue = new SQueue<>(rawQueue, serializer); | 135 | queue = new SQueue<>(rawQueue, serializer); |
136 | + queue.addItemListener(new InternalItemListener(appId), false); | ||
132 | batchQueues.putIfAbsent(appId, queue); | 137 | batchQueues.putIfAbsent(appId, queue); |
133 | - // TODO others should run for leadership when they hear about this topic | ||
134 | leadershipService.runForLeadership(topic); | 138 | leadershipService.runForLeadership(topic); |
135 | } | 139 | } |
136 | } | 140 | } |
... | @@ -209,6 +213,25 @@ public class HazelcastIntentBatchQueue | ... | @@ -209,6 +213,25 @@ public class HazelcastIntentBatchQueue |
209 | } | 213 | } |
210 | } | 214 | } |
211 | 215 | ||
216 | + private class InternalItemListener implements ItemListener<IntentOperations> { | ||
217 | + | ||
218 | + private final ApplicationId appId; | ||
219 | + | ||
220 | + public InternalItemListener(ApplicationId appId) { | ||
221 | + this.appId = appId; | ||
222 | + } | ||
223 | + | ||
224 | + @Override | ||
225 | + public void itemAdded(ItemEvent<IntentOperations> item) { | ||
226 | + dispatchNextOperation(appId); | ||
227 | + } | ||
228 | + | ||
229 | + @Override | ||
230 | + public void itemRemoved(ItemEvent<IntentOperations> item) { | ||
231 | + // no-op | ||
232 | + } | ||
233 | + } | ||
234 | + | ||
212 | private class InternalLeaderListener implements LeadershipEventListener { | 235 | private class InternalLeaderListener implements LeadershipEventListener { |
213 | @Override | 236 | @Override |
214 | public void event(LeadershipEvent event) { | 237 | public void event(LeadershipEvent event) { |
... | @@ -220,6 +243,8 @@ public class HazelcastIntentBatchQueue | ... | @@ -220,6 +243,8 @@ public class HazelcastIntentBatchQueue |
220 | return; // Not our topic: ignore | 243 | return; // Not our topic: ignore |
221 | } | 244 | } |
222 | if (!event.subject().leader().id().equals(localControllerNode.id())) { | 245 | if (!event.subject().leader().id().equals(localControllerNode.id())) { |
246 | + // run for leadership | ||
247 | + getQueue(getAppId(topic)); | ||
223 | return; // The event is not about this instance: ignore | 248 | return; // The event is not about this instance: ignore |
224 | } | 249 | } |
225 | 250 | ... | ... |
... | @@ -20,6 +20,7 @@ import com.codahale.metrics.Timer.Context; | ... | @@ -20,6 +20,7 @@ import com.codahale.metrics.Timer.Context; |
20 | import com.google.common.base.Verify; | 20 | import com.google.common.base.Verify; |
21 | import com.google.common.collect.ImmutableList; | 21 | import com.google.common.collect.ImmutableList; |
22 | import com.google.common.collect.ImmutableSet; | 22 | import com.google.common.collect.ImmutableSet; |
23 | +import com.google.common.collect.Lists; | ||
23 | import com.hazelcast.core.EntryAdapter; | 24 | import com.hazelcast.core.EntryAdapter; |
24 | import com.hazelcast.core.EntryEvent; | 25 | import com.hazelcast.core.EntryEvent; |
25 | import com.hazelcast.core.EntryListener; | 26 | import com.hazelcast.core.EntryListener; |
... | @@ -171,15 +172,16 @@ public class HazelcastIntentStore | ... | @@ -171,15 +172,16 @@ public class HazelcastIntentStore |
171 | } | 172 | } |
172 | 173 | ||
173 | @Override | 174 | @Override |
174 | - public IntentEvent createIntent(Intent intent) { | 175 | + public void createIntent(Intent intent) { |
175 | Context timer = startTimer(createIntentTimer); | 176 | Context timer = startTimer(createIntentTimer); |
176 | try { | 177 | try { |
177 | Intent existing = intents.putIfAbsent(intent.id(), intent); | 178 | Intent existing = intents.putIfAbsent(intent.id(), intent); |
178 | if (existing != null) { | 179 | if (existing != null) { |
179 | // duplicate, ignore | 180 | // duplicate, ignore |
180 | - return null; | 181 | + return; |
181 | } else { | 182 | } else { |
182 | - return this.setState(intent, IntentState.SUBMITTED); | 183 | + this.setState(intent, IntentState.SUBMITTED); |
184 | + return; | ||
183 | } | 185 | } |
184 | } finally { | 186 | } finally { |
185 | stopTimer(timer); | 187 | stopTimer(timer); |
... | @@ -256,7 +258,7 @@ public class HazelcastIntentStore | ... | @@ -256,7 +258,7 @@ public class HazelcastIntentStore |
256 | } | 258 | } |
257 | 259 | ||
258 | @Override | 260 | @Override |
259 | - public IntentEvent setState(Intent intent, IntentState state) { | 261 | + public void setState(Intent intent, IntentState state) { |
260 | Context timer = startTimer(setStateTimer); | 262 | Context timer = startTimer(setStateTimer); |
261 | try { | 263 | try { |
262 | 264 | ||
... | @@ -311,10 +313,10 @@ public class HazelcastIntentStore | ... | @@ -311,10 +313,10 @@ public class HazelcastIntentStore |
311 | final IntentState prevTransient = transientStates.put(id, state); | 313 | final IntentState prevTransient = transientStates.put(id, state); |
312 | log.debug("Transient State change: {} {}=>{}", id, prevTransient, state); | 314 | log.debug("Transient State change: {} {}=>{}", id, prevTransient, state); |
313 | 315 | ||
314 | - if (type == null) { | 316 | + if (type != null) { |
315 | - return null; | 317 | + notifyDelegate(new IntentEvent(type, intent)); |
316 | } | 318 | } |
317 | - return new IntentEvent(type, intent); | 319 | + return; |
318 | } finally { | 320 | } finally { |
319 | stopTimer(timer); | 321 | stopTimer(timer); |
320 | } | 322 | } |
... | @@ -358,6 +360,7 @@ public class HazelcastIntentStore | ... | @@ -358,6 +360,7 @@ public class HazelcastIntentStore |
358 | List<Operation> failed = new ArrayList<>(); | 360 | List<Operation> failed = new ArrayList<>(); |
359 | 361 | ||
360 | List<Pair<Operation, List<Future<?>>>> futures = new ArrayList<>(batch.operations().size()); | 362 | List<Pair<Operation, List<Future<?>>>> futures = new ArrayList<>(batch.operations().size()); |
363 | + List<IntentEvent> events = Lists.newArrayList(); | ||
361 | 364 | ||
362 | for (Operation op : batch.operations()) { | 365 | for (Operation op : batch.operations()) { |
363 | switch (op.type()) { | 366 | switch (op.type()) { |
... | @@ -434,6 +437,7 @@ public class HazelcastIntentStore | ... | @@ -434,6 +437,7 @@ public class HazelcastIntentStore |
434 | prevIntent, prevIntentState, | 437 | prevIntent, prevIntentState, |
435 | intent, newIntentState); | 438 | intent, newIntentState); |
436 | } | 439 | } |
440 | + events.add(IntentEvent.getEvent(SUBMITTED, intent)); | ||
437 | } catch (InterruptedException e) { | 441 | } catch (InterruptedException e) { |
438 | log.error("Batch write was interrupted while processing {}", op, e); | 442 | log.error("Batch write was interrupted while processing {}", op, e); |
439 | failed.add(op); | 443 | failed.add(op); |
... | @@ -487,6 +491,8 @@ public class HazelcastIntentStore | ... | @@ -487,6 +491,8 @@ public class HazelcastIntentStore |
487 | if (PARKING.contains(newState)) { | 491 | if (PARKING.contains(newState)) { |
488 | transientStates.remove(intentId); | 492 | transientStates.remove(intentId); |
489 | } | 493 | } |
494 | + events.add(IntentEvent.getEvent(newState, intent)); | ||
495 | + | ||
490 | log.trace("{} - {} -> {}", intentId, prevIntentState, newState); | 496 | log.trace("{} - {} -> {}", intentId, prevIntentState, newState); |
491 | // TODO sanity check and log? | 497 | // TODO sanity check and log? |
492 | } catch (InterruptedException e) { | 498 | } catch (InterruptedException e) { |
... | @@ -554,6 +560,9 @@ public class HazelcastIntentStore | ... | @@ -554,6 +560,9 @@ public class HazelcastIntentStore |
554 | break; | 560 | break; |
555 | } | 561 | } |
556 | } | 562 | } |
563 | + | ||
564 | + notifyDelegate(events); | ||
565 | + | ||
557 | return failed; | 566 | return failed; |
558 | } | 567 | } |
559 | 568 | ||
... | @@ -571,6 +580,8 @@ public class HazelcastIntentStore | ... | @@ -571,6 +580,8 @@ public class HazelcastIntentStore |
571 | log.debug("{} state updated remotely, removing transient state {}", | 580 | log.debug("{} state updated remotely, removing transient state {}", |
572 | intentId, oldState); | 581 | intentId, oldState); |
573 | } | 582 | } |
583 | + | ||
584 | + notifyDelegate(IntentEvent.getEvent(event.getValue(), getIntent(intentId))); | ||
574 | } | 585 | } |
575 | } | 586 | } |
576 | } | 587 | } | ... | ... |
... | @@ -16,6 +16,8 @@ | ... | @@ -16,6 +16,8 @@ |
16 | package org.onlab.onos.store.trivial.impl; | 16 | package org.onlab.onos.store.trivial.impl; |
17 | 17 | ||
18 | import com.google.common.collect.ImmutableSet; | 18 | import com.google.common.collect.ImmutableSet; |
19 | +import com.google.common.collect.Lists; | ||
20 | + | ||
19 | import org.apache.felix.scr.annotations.Activate; | 21 | import org.apache.felix.scr.annotations.Activate; |
20 | import org.apache.felix.scr.annotations.Component; | 22 | import org.apache.felix.scr.annotations.Component; |
21 | import org.apache.felix.scr.annotations.Deactivate; | 23 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -26,6 +28,7 @@ import org.onlab.onos.net.intent.IntentId; | ... | @@ -26,6 +28,7 @@ import org.onlab.onos.net.intent.IntentId; |
26 | import org.onlab.onos.net.intent.IntentState; | 28 | import org.onlab.onos.net.intent.IntentState; |
27 | import org.onlab.onos.net.intent.IntentStore; | 29 | import org.onlab.onos.net.intent.IntentStore; |
28 | import org.onlab.onos.net.intent.IntentStoreDelegate; | 30 | import org.onlab.onos.net.intent.IntentStoreDelegate; |
31 | +import org.onlab.onos.net.intent.IntentStore.BatchWrite.Operation; | ||
29 | import org.onlab.onos.store.AbstractStore; | 32 | import org.onlab.onos.store.AbstractStore; |
30 | import org.slf4j.Logger; | 33 | import org.slf4j.Logger; |
31 | 34 | ||
... | @@ -33,6 +36,7 @@ import java.util.List; | ... | @@ -33,6 +36,7 @@ import java.util.List; |
33 | import java.util.Map; | 36 | import java.util.Map; |
34 | import java.util.concurrent.ConcurrentHashMap; | 37 | import java.util.concurrent.ConcurrentHashMap; |
35 | 38 | ||
39 | +import static com.google.common.base.Preconditions.checkArgument; | ||
36 | import static com.google.common.base.Preconditions.checkState; | 40 | import static com.google.common.base.Preconditions.checkState; |
37 | import static org.onlab.onos.net.intent.IntentState.WITHDRAWN; | 41 | import static org.onlab.onos.net.intent.IntentState.WITHDRAWN; |
38 | import static org.slf4j.LoggerFactory.getLogger; | 42 | import static org.slf4j.LoggerFactory.getLogger; |
... | @@ -60,12 +64,13 @@ public class SimpleIntentStore | ... | @@ -60,12 +64,13 @@ public class SimpleIntentStore |
60 | } | 64 | } |
61 | 65 | ||
62 | @Override | 66 | @Override |
63 | - public IntentEvent createIntent(Intent intent) { | 67 | + public void createIntent(Intent intent) { |
64 | if (intents.containsKey(intent.id())) { | 68 | if (intents.containsKey(intent.id())) { |
65 | - return null; | 69 | + return; |
66 | } | 70 | } |
67 | intents.put(intent.id(), intent); | 71 | intents.put(intent.id(), intent); |
68 | - return this.setState(intent, IntentState.SUBMITTED); | 72 | + this.setState(intent, IntentState.SUBMITTED); |
73 | + return; | ||
69 | } | 74 | } |
70 | 75 | ||
71 | @Override | 76 | @Override |
... | @@ -98,7 +103,7 @@ public class SimpleIntentStore | ... | @@ -98,7 +103,7 @@ public class SimpleIntentStore |
98 | } | 103 | } |
99 | 104 | ||
100 | @Override | 105 | @Override |
101 | - public IntentEvent setState(Intent intent, IntentState state) { | 106 | + public void setState(Intent intent, IntentState state) { |
102 | IntentId id = intent.id(); | 107 | IntentId id = intent.id(); |
103 | states.put(id, state); | 108 | states.put(id, state); |
104 | IntentEvent.Type type = null; | 109 | IntentEvent.Type type = null; |
... | @@ -119,10 +124,9 @@ public class SimpleIntentStore | ... | @@ -119,10 +124,9 @@ public class SimpleIntentStore |
119 | default: | 124 | default: |
120 | break; | 125 | break; |
121 | } | 126 | } |
122 | - if (type == null) { | 127 | + if (type != null) { |
123 | - return null; | 128 | + notifyDelegate(new IntentEvent(type, intent)); |
124 | } | 129 | } |
125 | - return new IntentEvent(type, intent); | ||
126 | } | 130 | } |
127 | 131 | ||
128 | @Override | 132 | @Override |
... | @@ -139,5 +143,60 @@ public class SimpleIntentStore | ... | @@ -139,5 +143,60 @@ public class SimpleIntentStore |
139 | public void removeInstalledIntents(IntentId intentId) { | 143 | public void removeInstalledIntents(IntentId intentId) { |
140 | installable.remove(intentId); | 144 | installable.remove(intentId); |
141 | } | 145 | } |
142 | - | 146 | + /** |
147 | + * Execute writes in a batch. | ||
148 | + * | ||
149 | + * @param batch BatchWrite to execute | ||
150 | + * @return failed operations | ||
151 | + */ | ||
152 | + @Override | ||
153 | + public List<Operation> batchWrite(BatchWrite batch) { | ||
154 | + List<Operation> failed = Lists.newArrayList(); | ||
155 | + for (Operation op : batch.operations()) { | ||
156 | + switch (op.type()) { | ||
157 | + case CREATE_INTENT: | ||
158 | + checkArgument(op.args().size() == 1, | ||
159 | + "CREATE_INTENT takes 1 argument. %s", op); | ||
160 | + Intent intent = (Intent) op.args().get(0); | ||
161 | + // TODO: what if it failed? | ||
162 | + createIntent(intent); | ||
163 | + break; | ||
164 | + | ||
165 | + case REMOVE_INTENT: | ||
166 | + checkArgument(op.args().size() == 1, | ||
167 | + "REMOVE_INTENT takes 1 argument. %s", op); | ||
168 | + IntentId intentId = (IntentId) op.args().get(0); | ||
169 | + removeIntent(intentId); | ||
170 | + break; | ||
171 | + | ||
172 | + case REMOVE_INSTALLED: | ||
173 | + checkArgument(op.args().size() == 1, | ||
174 | + "REMOVE_INSTALLED takes 1 argument. %s", op); | ||
175 | + intentId = (IntentId) op.args().get(0); | ||
176 | + removeInstalledIntents(intentId); | ||
177 | + break; | ||
178 | + | ||
179 | + case SET_INSTALLABLE: | ||
180 | + checkArgument(op.args().size() == 2, | ||
181 | + "SET_INSTALLABLE takes 2 arguments. %s", op); | ||
182 | + intentId = (IntentId) op.args().get(0); | ||
183 | + @SuppressWarnings("unchecked") | ||
184 | + List<Intent> installableIntents = (List<Intent>) op.args().get(1); | ||
185 | + setInstallableIntents(intentId, installableIntents); | ||
186 | + break; | ||
187 | + | ||
188 | + case SET_STATE: | ||
189 | + checkArgument(op.args().size() == 2, | ||
190 | + "SET_STATE takes 2 arguments. %s", op); | ||
191 | + intent = (Intent) op.args().get(0); | ||
192 | + IntentState newState = (IntentState) op.args().get(1); | ||
193 | + setState(intent, newState); | ||
194 | + break; | ||
195 | + | ||
196 | + default: | ||
197 | + break; | ||
198 | + } | ||
199 | + } | ||
200 | + return failed; | ||
201 | + } | ||
143 | } | 202 | } | ... | ... |
... | @@ -19,7 +19,7 @@ import org.onlab.onos.cluster.LeadershipService; | ... | @@ -19,7 +19,7 @@ import org.onlab.onos.cluster.LeadershipService; |
19 | 19 | ||
20 | /** | 20 | /** |
21 | * A trivial implementation of the leadership service. | 21 | * A trivial implementation of the leadership service. |
22 | - * <p></p> | 22 | + * <p> |
23 | * The service is not distributed, so it can assume there's a single leadership | 23 | * The service is not distributed, so it can assume there's a single leadership |
24 | * contender. This contender is always granted leadership whenever it asks. | 24 | * contender. This contender is always granted leadership whenever it asks. |
25 | */ | 25 | */ | ... | ... |
-
Please register or login to post a comment