initial Distributed IntentStore using Hz
Change-Id: Iffb3f5fdfe8ba080fd039e67f8473ea18348f20d
Showing
4 changed files
with
80 additions
and
16 deletions
... | @@ -86,13 +86,13 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { | ... | @@ -86,13 +86,13 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { |
86 | IntentEvent setState(Intent intent, IntentState newState); | 86 | IntentEvent setState(Intent intent, IntentState newState); |
87 | 87 | ||
88 | /** | 88 | /** |
89 | - * Adds the installable intents which resulted from compilation of the | 89 | + * Sets the installable intents which resulted from compilation of the |
90 | * specified original intent. | 90 | * specified original intent. |
91 | * | 91 | * |
92 | * @param intentId original intent identifier | 92 | * @param intentId original intent identifier |
93 | * @param installableIntents compiled installable intents | 93 | * @param installableIntents compiled installable intents |
94 | */ | 94 | */ |
95 | - void addInstallableIntents(IntentId intentId, List<Intent> installableIntents); | 95 | + void setInstallableIntents(IntentId intentId, List<Intent> installableIntents); |
96 | 96 | ||
97 | /** | 97 | /** |
98 | * Returns the list of the installable events associated with the specified | 98 | * Returns the list of the installable events associated with the specified | ... | ... |
... | @@ -273,7 +273,7 @@ public class IntentManager | ... | @@ -273,7 +273,7 @@ public class IntentManager |
273 | 273 | ||
274 | // If all went well, associate the resulting list of installable | 274 | // If all went well, associate the resulting list of installable |
275 | // intents with the top-level intent and proceed to install. | 275 | // intents with the top-level intent and proceed to install. |
276 | - store.addInstallableIntents(intent.id(), installable); | 276 | + store.setInstallableIntents(intent.id(), installable); |
277 | executeInstallingPhase(intent); | 277 | executeInstallingPhase(intent); |
278 | 278 | ||
279 | } catch (Exception e) { | 279 | } catch (Exception e) { |
... | @@ -366,7 +366,7 @@ public class IntentManager | ... | @@ -366,7 +366,7 @@ public class IntentManager |
366 | } else { | 366 | } else { |
367 | // Otherwise, re-associate the newly compiled installable intents | 367 | // Otherwise, re-associate the newly compiled installable intents |
368 | // with the top-level intent and kick off installing phase. | 368 | // with the top-level intent and kick off installing phase. |
369 | - store.addInstallableIntents(intent.id(), installable); | 369 | + store.setInstallableIntents(intent.id(), installable); |
370 | executeInstallingPhase(intent); | 370 | executeInstallingPhase(intent); |
371 | } | 371 | } |
372 | } catch (Exception e) { | 372 | } catch (Exception e) { | ... | ... |
... | @@ -16,6 +16,8 @@ | ... | @@ -16,6 +16,8 @@ |
16 | package org.onlab.onos.store.intent.impl; | 16 | package org.onlab.onos.store.intent.impl; |
17 | 17 | ||
18 | import com.google.common.collect.ImmutableSet; | 18 | import com.google.common.collect.ImmutableSet; |
19 | +import com.hazelcast.core.IMap; | ||
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,30 +28,54 @@ import org.onlab.onos.net.intent.IntentId; | ... | @@ -26,30 +28,54 @@ 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; |
29 | -import org.onlab.onos.store.AbstractStore; | 31 | +import org.onlab.onos.store.hz.AbstractHazelcastStore; |
32 | +import org.onlab.onos.store.hz.SMap; | ||
30 | import org.slf4j.Logger; | 33 | import org.slf4j.Logger; |
31 | 34 | ||
32 | import java.util.List; | 35 | 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.Verify.verify; | ||
36 | import static org.onlab.onos.net.intent.IntentState.*; | 40 | import static org.onlab.onos.net.intent.IntentState.*; |
37 | import static org.slf4j.LoggerFactory.getLogger; | 41 | import static org.slf4j.LoggerFactory.getLogger; |
38 | 42 | ||
39 | -//FIXME: I LIE I AM NOT DISTRIBUTED | ||
40 | @Component(immediate = true) | 43 | @Component(immediate = true) |
41 | @Service | 44 | @Service |
42 | public class DistributedIntentStore | 45 | public class DistributedIntentStore |
43 | - extends AbstractStore<IntentEvent, IntentStoreDelegate> | 46 | + extends AbstractHazelcastStore<IntentEvent, IntentStoreDelegate> |
44 | implements IntentStore { | 47 | implements IntentStore { |
45 | 48 | ||
46 | private final Logger log = getLogger(getClass()); | 49 | private final Logger log = getLogger(getClass()); |
47 | - private final Map<IntentId, Intent> intents = new ConcurrentHashMap<>(); | ||
48 | - private final Map<IntentId, IntentState> states = new ConcurrentHashMap<>(); | ||
49 | - private final Map<IntentId, List<Intent>> installable = new ConcurrentHashMap<>(); | ||
50 | 50 | ||
51 | + // Assumption: IntentId will not have synonyms | ||
52 | + private SMap<IntentId, Intent> intents; | ||
53 | + private SMap<IntentId, IntentState> states; | ||
54 | + | ||
55 | + // Map to store instance local intermediate state transition | ||
56 | + private transient Map<IntentId, IntentState> transientStates = new ConcurrentHashMap<>(); | ||
57 | + | ||
58 | + private SMap<IntentId, List<Intent>> installable; | ||
59 | + | ||
60 | + @Override | ||
51 | @Activate | 61 | @Activate |
52 | public void activate() { | 62 | public void activate() { |
63 | + super.activate(); | ||
64 | + | ||
65 | + // TODO: enable near cache, allow read from backup for this IMap | ||
66 | + IMap<byte[], byte[]> rawIntents = super.theInstance.getMap("intents"); | ||
67 | + intents = new SMap<>(rawIntents , super.serializer); | ||
68 | + | ||
69 | + // TODO: disable near cache, disable read from backup for this IMap | ||
70 | + IMap<byte[], byte[]> rawStates = super.theInstance.getMap("intent-states"); | ||
71 | + states = new SMap<>(rawStates , super.serializer); | ||
72 | + | ||
73 | + transientStates.clear(); | ||
74 | + | ||
75 | + // TODO: disable near cache, disable read from backup for this IMap | ||
76 | + IMap<byte[], byte[]> rawInstallables = super.theInstance.getMap("installable-intents"); | ||
77 | + installable = new SMap<>(rawInstallables , super.serializer); | ||
78 | + | ||
53 | log.info("Started"); | 79 | log.info("Started"); |
54 | } | 80 | } |
55 | 81 | ||
... | @@ -60,16 +86,27 @@ public class DistributedIntentStore | ... | @@ -60,16 +86,27 @@ public class DistributedIntentStore |
60 | 86 | ||
61 | @Override | 87 | @Override |
62 | public IntentEvent createIntent(Intent intent) { | 88 | public IntentEvent createIntent(Intent intent) { |
63 | - intents.put(intent.id(), intent); | 89 | + Intent existing = intents.putIfAbsent(intent.id(), intent); |
64 | - return this.setState(intent, IntentState.SUBMITTED); | 90 | + if (existing != null) { |
91 | + // duplicate, ignore | ||
92 | + return null; | ||
93 | + } else { | ||
94 | + return this.setState(intent, IntentState.SUBMITTED); | ||
95 | + } | ||
65 | } | 96 | } |
66 | 97 | ||
67 | @Override | 98 | @Override |
68 | public IntentEvent removeIntent(IntentId intentId) { | 99 | public IntentEvent removeIntent(IntentId intentId) { |
69 | Intent intent = intents.remove(intentId); | 100 | Intent intent = intents.remove(intentId); |
70 | installable.remove(intentId); | 101 | installable.remove(intentId); |
102 | + if (intent == null) { | ||
103 | + // was already removed | ||
104 | + return null; | ||
105 | + } | ||
71 | IntentEvent event = this.setState(intent, WITHDRAWN); | 106 | IntentEvent event = this.setState(intent, WITHDRAWN); |
72 | states.remove(intentId); | 107 | states.remove(intentId); |
108 | + transientStates.remove(intentId); | ||
109 | + // TODO: Should we callremoveInstalledIntents if this Intent was | ||
73 | return event; | 110 | return event; |
74 | } | 111 | } |
75 | 112 | ||
... | @@ -90,31 +127,53 @@ public class DistributedIntentStore | ... | @@ -90,31 +127,53 @@ public class DistributedIntentStore |
90 | 127 | ||
91 | @Override | 128 | @Override |
92 | public IntentState getIntentState(IntentId id) { | 129 | public IntentState getIntentState(IntentId id) { |
130 | + final IntentState localState = transientStates.get(id); | ||
131 | + if (localState != null) { | ||
132 | + return localState; | ||
133 | + } | ||
93 | return states.get(id); | 134 | return states.get(id); |
94 | } | 135 | } |
95 | 136 | ||
96 | @Override | 137 | @Override |
97 | public IntentEvent setState(Intent intent, IntentState state) { | 138 | public IntentEvent setState(Intent intent, IntentState state) { |
98 | - IntentId id = intent.id(); | 139 | + final IntentId id = intent.id(); |
99 | - states.put(id, state); | ||
100 | IntentEvent.Type type = null; | 140 | IntentEvent.Type type = null; |
141 | + IntentState prev = null; | ||
142 | + boolean transientStateChangeOnly = false; | ||
101 | 143 | ||
144 | + // TODO: enable sanity checking if Debug enabled, etc. | ||
102 | switch (state) { | 145 | switch (state) { |
103 | case SUBMITTED: | 146 | case SUBMITTED: |
147 | + prev = states.putIfAbsent(id, SUBMITTED); | ||
148 | + verify(prev == null, "Illegal state transition attempted from %s to SUBMITTED", prev); | ||
104 | type = IntentEvent.Type.SUBMITTED; | 149 | type = IntentEvent.Type.SUBMITTED; |
105 | break; | 150 | break; |
106 | case INSTALLED: | 151 | case INSTALLED: |
152 | + // parking state transition | ||
153 | + prev = states.replace(id, INSTALLED); | ||
154 | + verify(prev != null, "Illegal state transition attempted from non-SUBMITTED to INSTALLED"); | ||
107 | type = IntentEvent.Type.INSTALLED; | 155 | type = IntentEvent.Type.INSTALLED; |
108 | break; | 156 | break; |
109 | case FAILED: | 157 | case FAILED: |
158 | + prev = states.replace(id, FAILED); | ||
110 | type = IntentEvent.Type.FAILED; | 159 | type = IntentEvent.Type.FAILED; |
111 | break; | 160 | break; |
112 | case WITHDRAWN: | 161 | case WITHDRAWN: |
162 | + prev = states.replace(id, WITHDRAWN); | ||
163 | + verify(prev != null, "Illegal state transition attempted from non-WITHDRAWING to WITHDRAWN"); | ||
113 | type = IntentEvent.Type.WITHDRAWN; | 164 | type = IntentEvent.Type.WITHDRAWN; |
114 | break; | 165 | break; |
115 | default: | 166 | default: |
167 | + transientStateChangeOnly = true; | ||
116 | break; | 168 | break; |
117 | } | 169 | } |
170 | + if (!transientStateChangeOnly) { | ||
171 | + log.debug("Parking State change: {} {}=>{}", id, prev, state); | ||
172 | + } | ||
173 | + // Update instance local state, which includes non-parking state transition | ||
174 | + prev = transientStates.put(id, state); | ||
175 | + log.debug("Transient State change: {} {}=>{}", id, prev, state); | ||
176 | + | ||
118 | if (type == null) { | 177 | if (type == null) { |
119 | return null; | 178 | return null; |
120 | } | 179 | } |
... | @@ -122,7 +181,7 @@ public class DistributedIntentStore | ... | @@ -122,7 +181,7 @@ public class DistributedIntentStore |
122 | } | 181 | } |
123 | 182 | ||
124 | @Override | 183 | @Override |
125 | - public void addInstallableIntents(IntentId intentId, List<Intent> result) { | 184 | + public void setInstallableIntents(IntentId intentId, List<Intent> result) { |
126 | installable.put(intentId, result); | 185 | installable.put(intentId, result); |
127 | } | 186 | } |
128 | 187 | ||
... | @@ -136,4 +195,5 @@ public class DistributedIntentStore | ... | @@ -136,4 +195,5 @@ public class DistributedIntentStore |
136 | installable.remove(intentId); | 195 | installable.remove(intentId); |
137 | } | 196 | } |
138 | 197 | ||
198 | + // FIXME add handler to react to remote event | ||
139 | } | 199 | } | ... | ... |
... | @@ -68,6 +68,10 @@ public class SimpleIntentStore | ... | @@ -68,6 +68,10 @@ public class SimpleIntentStore |
68 | public IntentEvent removeIntent(IntentId intentId) { | 68 | public IntentEvent removeIntent(IntentId intentId) { |
69 | Intent intent = intents.remove(intentId); | 69 | Intent intent = intents.remove(intentId); |
70 | installable.remove(intentId); | 70 | installable.remove(intentId); |
71 | + if (intent == null) { | ||
72 | + // was already removed | ||
73 | + return null; | ||
74 | + } | ||
71 | IntentEvent event = this.setState(intent, WITHDRAWN); | 75 | IntentEvent event = this.setState(intent, WITHDRAWN); |
72 | states.remove(intentId); | 76 | states.remove(intentId); |
73 | return event; | 77 | return event; |
... | @@ -122,7 +126,7 @@ public class SimpleIntentStore | ... | @@ -122,7 +126,7 @@ public class SimpleIntentStore |
122 | } | 126 | } |
123 | 127 | ||
124 | @Override | 128 | @Override |
125 | - public void addInstallableIntents(IntentId intentId, List<Intent> result) { | 129 | + public void setInstallableIntents(IntentId intentId, List<Intent> result) { |
126 | installable.put(intentId, result); | 130 | installable.put(intentId, result); |
127 | } | 131 | } |
128 | 132 | ... | ... |
-
Please register or login to post a comment