Committed by
Gerrit Code Review
Cleaned up IntentStores.
* Removed HazelcastIntentStore * Moved SimpleIntentStore back to trivial bundle (and removed older version that was already in the trivial bundle) * Removed default methods from IntentStore interface ONOS-1056 Change-Id: Id5e15f44e287f51cca3e0b12a85d49cb4a07a9d3
Showing
7 changed files
with
165 additions
and
878 deletions
... | @@ -17,7 +17,6 @@ package org.onosproject.net.intent; | ... | @@ -17,7 +17,6 @@ package org.onosproject.net.intent; |
17 | 17 | ||
18 | import org.onosproject.store.Store; | 18 | import org.onosproject.store.Store; |
19 | 19 | ||
20 | -import java.util.Collections; | ||
21 | import java.util.List; | 20 | import java.util.List; |
22 | 21 | ||
23 | /** | 22 | /** |
... | @@ -45,27 +44,23 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { | ... | @@ -45,27 +44,23 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { |
45 | * @param intentKey intent identification | 44 | * @param intentKey intent identification |
46 | * @return current intent state | 45 | * @return current intent state |
47 | */ | 46 | */ |
48 | - default IntentState getIntentState(Key intentKey) { | 47 | + IntentState getIntentState(Key intentKey); |
49 | - return null; | ||
50 | - } | ||
51 | 48 | ||
52 | /** | 49 | /** |
53 | * Returns the list of the installable events associated with the specified | 50 | * Returns the list of the installable events associated with the specified |
54 | * original intent. | 51 | * original intent. |
55 | * | 52 | * |
56 | * @param intentKey original intent identifier | 53 | * @param intentKey original intent identifier |
57 | - * @return compiled installable intents | 54 | + * @return compiled installable intents, or null if no installables exist |
58 | */ | 55 | */ |
59 | - default List<Intent> getInstallableIntents(Key intentKey) { | 56 | + List<Intent> getInstallableIntents(Key intentKey); |
60 | - throw new UnsupportedOperationException("getInstallableIntents()"); | ||
61 | - } | ||
62 | 57 | ||
63 | /** | 58 | /** |
64 | * Writes an IntentData object to the store. | 59 | * Writes an IntentData object to the store. |
65 | * | 60 | * |
66 | * @param newData new intent data to write | 61 | * @param newData new intent data to write |
67 | */ | 62 | */ |
68 | - default void write(IntentData newData) {} | 63 | + void write(IntentData newData); |
69 | 64 | ||
70 | /** | 65 | /** |
71 | * Writes a batch of IntentData objects to the store. A batch has no | 66 | * Writes a batch of IntentData objects to the store. A batch has no |
... | @@ -73,7 +68,7 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { | ... | @@ -73,7 +68,7 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { |
73 | * | 68 | * |
74 | * @param updates collection of intent data objects to write | 69 | * @param updates collection of intent data objects to write |
75 | */ | 70 | */ |
76 | - default void batchWrite(Iterable<IntentData> updates) {} | 71 | + void batchWrite(Iterable<IntentData> updates); |
77 | 72 | ||
78 | /** | 73 | /** |
79 | * Returns the intent with the specified identifier. | 74 | * Returns the intent with the specified identifier. |
... | @@ -81,10 +76,7 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { | ... | @@ -81,10 +76,7 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { |
81 | * @param key key | 76 | * @param key key |
82 | * @return intent or null if not found | 77 | * @return intent or null if not found |
83 | */ | 78 | */ |
84 | - default Intent getIntent(Key key) { | 79 | + Intent getIntent(Key key); |
85 | - // FIXME remove this default implementation when all stores have implemented it | ||
86 | - return null; | ||
87 | - } | ||
88 | 80 | ||
89 | /** | 81 | /** |
90 | * Returns the intent data object associated with the specified key. | 82 | * Returns the intent data object associated with the specified key. |
... | @@ -92,16 +84,14 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { | ... | @@ -92,16 +84,14 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { |
92 | * @param key key to look up | 84 | * @param key key to look up |
93 | * @return intent data object | 85 | * @return intent data object |
94 | */ | 86 | */ |
95 | - default IntentData getIntentData(Key key) { //FIXME remove when impl. | 87 | + IntentData getIntentData(Key key); |
96 | - return null; | ||
97 | - } | ||
98 | 88 | ||
99 | /** | 89 | /** |
100 | * Adds a new operation, which should be persisted and delegated. | 90 | * Adds a new operation, which should be persisted and delegated. |
101 | * | 91 | * |
102 | * @param intent operation | 92 | * @param intent operation |
103 | */ | 93 | */ |
104 | - default void addPending(IntentData intent) {} //FIXME remove when impl. | 94 | + void addPending(IntentData intent); |
105 | 95 | ||
106 | /** | 96 | /** |
107 | * Checks to see whether the calling instance is the master for processing | 97 | * Checks to see whether the calling instance is the master for processing |
... | @@ -111,17 +101,12 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { | ... | @@ -111,17 +101,12 @@ public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> { |
111 | * @return true if master; false, otherwise | 101 | * @return true if master; false, otherwise |
112 | */ | 102 | */ |
113 | //TODO better name | 103 | //TODO better name |
114 | - default boolean isMaster(Key intentKey) { //FIXME remove default when impl. | 104 | + boolean isMaster(Key intentKey); |
115 | - return true; | ||
116 | - } | ||
117 | 105 | ||
118 | /** | 106 | /** |
119 | * Returns the intent requests pending processing. | 107 | * Returns the intent requests pending processing. |
120 | * | 108 | * |
121 | * @return pending intents | 109 | * @return pending intents |
122 | */ | 110 | */ |
123 | - // FIXME remove default | 111 | + Iterable<Intent> getPending(); |
124 | - default Iterable<Intent> getPending() { | ||
125 | - return Collections.emptyList(); | ||
126 | - } | ||
127 | } | 112 | } | ... | ... |
... | @@ -48,7 +48,7 @@ import org.onosproject.net.intent.IntentService; | ... | @@ -48,7 +48,7 @@ import org.onosproject.net.intent.IntentService; |
48 | import org.onosproject.net.intent.IntentState; | 48 | import org.onosproject.net.intent.IntentState; |
49 | import org.onosproject.net.intent.Key; | 49 | import org.onosproject.net.intent.Key; |
50 | import org.onosproject.net.resource.LinkResourceAllocations; | 50 | import org.onosproject.net.resource.LinkResourceAllocations; |
51 | -import org.onosproject.store.intent.impl.SimpleIntentStore; | 51 | +import org.onosproject.store.trivial.impl.SimpleIntentStore; |
52 | 52 | ||
53 | import com.google.common.collect.HashMultimap; | 53 | import com.google.common.collect.HashMultimap; |
54 | import com.google.common.collect.ImmutableSet; | 54 | import com.google.common.collect.ImmutableSet; | ... | ... |
... | @@ -37,7 +37,7 @@ import org.onosproject.store.ecmap.EventuallyConsistentMapEvent; | ... | @@ -37,7 +37,7 @@ import org.onosproject.store.ecmap.EventuallyConsistentMapEvent; |
37 | import org.onosproject.store.ecmap.EventuallyConsistentMapImpl; | 37 | import org.onosproject.store.ecmap.EventuallyConsistentMapImpl; |
38 | import org.onosproject.store.ecmap.EventuallyConsistentMapListener; | 38 | import org.onosproject.store.ecmap.EventuallyConsistentMapListener; |
39 | import org.onosproject.store.impl.MultiValuedTimestamp; | 39 | import org.onosproject.store.impl.MultiValuedTimestamp; |
40 | -import org.onosproject.store.impl.SystemClockTimestamp; | 40 | +import org.onosproject.store.impl.WallClockTimestamp; |
41 | import org.onosproject.store.serializers.KryoNamespaces; | 41 | import org.onosproject.store.serializers.KryoNamespaces; |
42 | import org.slf4j.Logger; | 42 | import org.slf4j.Logger; |
43 | 43 | ||
... | @@ -80,7 +80,7 @@ public class GossipIntentStore | ... | @@ -80,7 +80,7 @@ public class GossipIntentStore |
80 | .register(KryoNamespaces.API) | 80 | .register(KryoNamespaces.API) |
81 | .register(IntentData.class) | 81 | .register(IntentData.class) |
82 | .register(MultiValuedTimestamp.class) | 82 | .register(MultiValuedTimestamp.class) |
83 | - .register(SystemClockTimestamp.class); | 83 | + .register(WallClockTimestamp.class); |
84 | 84 | ||
85 | currentMap = new EventuallyConsistentMapImpl<>("intent-current", | 85 | currentMap = new EventuallyConsistentMapImpl<>("intent-current", |
86 | clusterService, | 86 | clusterService, |
... | @@ -225,8 +225,6 @@ public class GossipIntentStore | ... | @@ -225,8 +225,6 @@ public class GossipIntentStore |
225 | 225 | ||
226 | @Override | 226 | @Override |
227 | public void write(IntentData newData) { | 227 | public void write(IntentData newData) { |
228 | - //log.debug("writing intent {}", newData); | ||
229 | - | ||
230 | IntentData currentData = currentMap.get(newData.key()); | 228 | IntentData currentData = currentMap.get(newData.key()); |
231 | 229 | ||
232 | if (isUpdateAcceptable(currentData, newData)) { | 230 | if (isUpdateAcceptable(currentData, newData)) { |
... | @@ -239,12 +237,6 @@ public class GossipIntentStore | ... | @@ -239,12 +237,6 @@ public class GossipIntentStore |
239 | } else { | 237 | } else { |
240 | log.debug("not writing update: current {}, new {}", currentData, newData); | 238 | log.debug("not writing update: current {}, new {}", currentData, newData); |
241 | } | 239 | } |
242 | - /*try { | ||
243 | - notifyDelegate(IntentEvent.getEvent(newData)); | ||
244 | - } catch (IllegalArgumentException e) { | ||
245 | - //no-op | ||
246 | - log.trace("ignore this exception: {}", e); | ||
247 | - }*/ | ||
248 | } | 240 | } |
249 | 241 | ||
250 | @Override | 242 | @Override |
... | @@ -268,9 +260,8 @@ public class GossipIntentStore | ... | @@ -268,9 +260,8 @@ public class GossipIntentStore |
268 | 260 | ||
269 | @Override | 261 | @Override |
270 | public void addPending(IntentData data) { | 262 | public void addPending(IntentData data) { |
271 | - log.debug("new pending {} {} {}", data.key(), data.state(), data.version()); | ||
272 | if (data.version() == null) { | 263 | if (data.version() == null) { |
273 | - data.setVersion(new SystemClockTimestamp()); | 264 | + data.setVersion(new WallClockTimestamp()); |
274 | } | 265 | } |
275 | pendingMap.put(data.key(), copyData(data)); | 266 | pendingMap.put(data.key(), copyData(data)); |
276 | } | 267 | } | ... | ... |
core/store/dist/src/main/java/org/onosproject/store/intent/impl/HazelcastIntentStore.java
deleted
100644 → 0
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.onosproject.store.intent.impl; | ||
17 | - | ||
18 | -import com.codahale.metrics.Timer; | ||
19 | -import com.codahale.metrics.Timer.Context; | ||
20 | -import com.google.common.base.Verify; | ||
21 | -import com.google.common.collect.ImmutableList; | ||
22 | -import com.google.common.collect.ImmutableSet; | ||
23 | -import com.hazelcast.config.Config; | ||
24 | -import com.hazelcast.config.MapConfig; | ||
25 | -import com.hazelcast.core.EntryAdapter; | ||
26 | -import com.hazelcast.core.EntryEvent; | ||
27 | -import com.hazelcast.core.EntryListener; | ||
28 | -import com.hazelcast.core.IMap; | ||
29 | -import com.hazelcast.core.Member; | ||
30 | -import org.apache.commons.lang3.tuple.Pair; | ||
31 | -import org.apache.felix.scr.annotations.Activate; | ||
32 | -import org.apache.felix.scr.annotations.Component; | ||
33 | -import org.apache.felix.scr.annotations.Deactivate; | ||
34 | -import org.apache.felix.scr.annotations.Reference; | ||
35 | -import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
36 | -import org.apache.felix.scr.annotations.Service; | ||
37 | -import org.onlab.metrics.MetricsService; | ||
38 | -import org.onlab.util.KryoNamespace; | ||
39 | -import org.onosproject.core.MetricsHelper; | ||
40 | -import org.onosproject.net.intent.BatchWrite; | ||
41 | -import org.onosproject.net.intent.BatchWrite.Operation; | ||
42 | -import org.onosproject.net.intent.Intent; | ||
43 | -import org.onosproject.net.intent.IntentEvent; | ||
44 | -import org.onosproject.net.intent.IntentId; | ||
45 | -import org.onosproject.net.intent.IntentState; | ||
46 | -import org.onosproject.net.intent.IntentStore; | ||
47 | -import org.onosproject.net.intent.IntentStoreDelegate; | ||
48 | -import org.onosproject.net.intent.Key; | ||
49 | -import org.onosproject.store.hz.AbstractHazelcastStore; | ||
50 | -import org.onosproject.store.hz.SMap; | ||
51 | -import org.onosproject.store.serializers.KryoNamespaces; | ||
52 | -import org.onosproject.store.serializers.KryoSerializer; | ||
53 | -import org.slf4j.Logger; | ||
54 | - | ||
55 | -import java.util.EnumSet; | ||
56 | -import java.util.List; | ||
57 | -import java.util.Map; | ||
58 | -import java.util.Set; | ||
59 | -import java.util.concurrent.ConcurrentHashMap; | ||
60 | -import java.util.concurrent.ExecutionException; | ||
61 | -import java.util.concurrent.Future; | ||
62 | - | ||
63 | -import static com.google.common.base.Preconditions.checkArgument; | ||
64 | -import static org.onlab.metrics.MetricsUtil.startTimer; | ||
65 | -import static org.onlab.metrics.MetricsUtil.stopTimer; | ||
66 | -import static org.onosproject.net.intent.IntentState.FAILED; | ||
67 | -import static org.onosproject.net.intent.IntentState.INSTALLED; | ||
68 | -import static org.onosproject.net.intent.IntentState.INSTALL_REQ; | ||
69 | -import static org.onosproject.net.intent.IntentState.WITHDRAWN; | ||
70 | -import static org.slf4j.LoggerFactory.getLogger; | ||
71 | - | ||
72 | -//TODO Note: this store will be removed | ||
73 | - | ||
74 | -@Component(immediate = true, enabled = false) | ||
75 | -@Service | ||
76 | -public class HazelcastIntentStore | ||
77 | - extends AbstractHazelcastStore<IntentEvent, IntentStoreDelegate> | ||
78 | - implements IntentStore, MetricsHelper { | ||
79 | - | ||
80 | - /** Valid parking state, which can transition to INSTALLED. */ | ||
81 | - private static final Set<IntentState> PRE_INSTALLED = EnumSet.of(INSTALL_REQ, INSTALLED, FAILED); | ||
82 | - | ||
83 | - /** Valid parking state, which can transition to WITHDRAWN. */ | ||
84 | - private static final Set<IntentState> PRE_WITHDRAWN = EnumSet.of(INSTALLED, FAILED); | ||
85 | - | ||
86 | - private static final Set<IntentState> PARKING = EnumSet.of(INSTALL_REQ, INSTALLED, WITHDRAWN, FAILED); | ||
87 | - | ||
88 | - private final Logger log = getLogger(getClass()); | ||
89 | - | ||
90 | - // Assumption: IntentId will not have synonyms | ||
91 | - private static final String INTENTS_MAP_NAME = "intents"; | ||
92 | - private SMap<IntentId, Intent> intents; | ||
93 | - private static final String INTENT_STATES_MAP_NAME = "intent-states"; | ||
94 | - private SMap<IntentId, IntentState> states; | ||
95 | - | ||
96 | - // Map to store instance local intermediate state transition | ||
97 | - private transient Map<IntentId, IntentState> transientStates = new ConcurrentHashMap<>(); | ||
98 | - | ||
99 | - private static final String INSTALLABLE_INTENTS_MAP_NAME = "installable-intents"; | ||
100 | - private SMap<IntentId, List<Intent>> installable; | ||
101 | - | ||
102 | - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
103 | - protected MetricsService metricsService; | ||
104 | - | ||
105 | - private boolean onlyLogTransitionError = true; | ||
106 | - | ||
107 | - private Timer getInstallableIntentsTimer; | ||
108 | - private Timer getIntentCountTimer; | ||
109 | - private Timer getIntentsTimer; | ||
110 | - private Timer getIntentTimer; | ||
111 | - private Timer getIntentStateTimer; | ||
112 | - | ||
113 | - // manual near cache of Intent | ||
114 | - // (Note: IntentId -> Intent is expected to be immutable) | ||
115 | - // entry will be evicted, when state for that IntentId is removed. | ||
116 | - private Map<IntentId, Intent> localIntents; | ||
117 | - | ||
118 | - private String stateListenerId; | ||
119 | - | ||
120 | - private String intentsListenerId; | ||
121 | - | ||
122 | - private Timer createResponseTimer(String methodName) { | ||
123 | - return createTimer("IntentStore", methodName, "responseTime"); | ||
124 | - } | ||
125 | - | ||
126 | - @Override | ||
127 | - @Activate | ||
128 | - public void activate() { | ||
129 | - localIntents = new ConcurrentHashMap<>(); | ||
130 | - | ||
131 | - getInstallableIntentsTimer = createResponseTimer("getInstallableIntents"); | ||
132 | - getIntentCountTimer = createResponseTimer("getIntentCount"); | ||
133 | - getIntentsTimer = createResponseTimer("getIntents"); | ||
134 | - getIntentTimer = createResponseTimer("getIntent"); | ||
135 | - getIntentStateTimer = createResponseTimer("getIntentState"); | ||
136 | - | ||
137 | - // We need a way to add serializer for intents which has been plugged-in. | ||
138 | - // As a short term workaround, relax Kryo config to | ||
139 | - // registrationRequired=false | ||
140 | - super.activate(); | ||
141 | - super.serializer = new KryoSerializer() { | ||
142 | - | ||
143 | - @Override | ||
144 | - protected void setupKryoPool() { | ||
145 | - serializerPool = KryoNamespace.newBuilder() | ||
146 | - .setRegistrationRequired(false) | ||
147 | - .register(KryoNamespaces.API) | ||
148 | - .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID) | ||
149 | - .build(); | ||
150 | - } | ||
151 | - | ||
152 | - }; | ||
153 | - | ||
154 | - final Config config = theInstance.getConfig(); | ||
155 | - | ||
156 | - MapConfig intentsCfg = config.getMapConfig(INTENTS_MAP_NAME); | ||
157 | - intentsCfg.setAsyncBackupCount(MapConfig.MAX_BACKUP_COUNT - intentsCfg.getBackupCount()); | ||
158 | - | ||
159 | - IMap<byte[], byte[]> rawIntents = super.theInstance.getMap(INTENTS_MAP_NAME); | ||
160 | - intents = new SMap<>(rawIntents , super.serializer); | ||
161 | - intentsListenerId = intents.addEntryListener(new RemoteIntentsListener(), true); | ||
162 | - | ||
163 | - MapConfig statesCfg = config.getMapConfig(INTENT_STATES_MAP_NAME); | ||
164 | - statesCfg.setAsyncBackupCount(MapConfig.MAX_BACKUP_COUNT - statesCfg.getBackupCount()); | ||
165 | - | ||
166 | - IMap<byte[], byte[]> rawStates = super.theInstance.getMap(INTENT_STATES_MAP_NAME); | ||
167 | - states = new SMap<>(rawStates , super.serializer); | ||
168 | - EntryListener<IntentId, IntentState> listener = new RemoteIntentStateListener(); | ||
169 | - stateListenerId = states.addEntryListener(listener, true); | ||
170 | - | ||
171 | - transientStates.clear(); | ||
172 | - | ||
173 | - MapConfig installableCfg = config.getMapConfig(INSTALLABLE_INTENTS_MAP_NAME); | ||
174 | - installableCfg.setAsyncBackupCount(MapConfig.MAX_BACKUP_COUNT - installableCfg.getBackupCount()); | ||
175 | - | ||
176 | - IMap<byte[], byte[]> rawInstallables = super.theInstance.getMap(INSTALLABLE_INTENTS_MAP_NAME); | ||
177 | - installable = new SMap<>(rawInstallables , super.serializer); | ||
178 | - | ||
179 | - log.info("Started"); | ||
180 | - } | ||
181 | - | ||
182 | - @Deactivate | ||
183 | - public void deactivate() { | ||
184 | - intents.removeEntryListener(intentsListenerId); | ||
185 | - states.removeEntryListener(stateListenerId); | ||
186 | - log.info("Stopped"); | ||
187 | - } | ||
188 | - | ||
189 | - @Override | ||
190 | - public MetricsService metricsService() { | ||
191 | - return metricsService; | ||
192 | - } | ||
193 | - | ||
194 | - @Override | ||
195 | - public long getIntentCount() { | ||
196 | - Context timer = startTimer(getIntentCountTimer); | ||
197 | - try { | ||
198 | - return intents.size(); | ||
199 | - } finally { | ||
200 | - stopTimer(timer); | ||
201 | - } | ||
202 | - } | ||
203 | - | ||
204 | - @Override | ||
205 | - public Iterable<Intent> getIntents() { | ||
206 | - Context timer = startTimer(getIntentsTimer); | ||
207 | - try { | ||
208 | - return ImmutableSet.copyOf(intents.values()); | ||
209 | - } finally { | ||
210 | - stopTimer(timer); | ||
211 | - } | ||
212 | - } | ||
213 | - | ||
214 | - @Override | ||
215 | - public Intent getIntent(Key intentKey) { | ||
216 | - return null; | ||
217 | - } | ||
218 | - | ||
219 | - | ||
220 | - public Intent getIntent(IntentId intentId) { | ||
221 | - Context timer = startTimer(getIntentTimer); | ||
222 | - try { | ||
223 | - Intent intent = localIntents.get(intentId); | ||
224 | - if (intent != null) { | ||
225 | - return intent; | ||
226 | - } | ||
227 | - intent = intents.get(intentId); | ||
228 | - if (intent != null) { | ||
229 | - localIntents.put(intentId, intent); | ||
230 | - } | ||
231 | - return intent; | ||
232 | - } finally { | ||
233 | - stopTimer(timer); | ||
234 | - } | ||
235 | - } | ||
236 | - | ||
237 | - @Override | ||
238 | - public IntentState getIntentState(Key key) { | ||
239 | - // TODO: either implement this or remove this class | ||
240 | - return IntentState.FAILED; | ||
241 | - /* | ||
242 | - Context timer = startTimer(getIntentStateTimer); | ||
243 | - try { | ||
244 | - final IntentState localState = transientStates.get(id); | ||
245 | - if (localState != null) { | ||
246 | - return localState; | ||
247 | - } | ||
248 | - return states.get(id); | ||
249 | - } finally { | ||
250 | - stopTimer(timer); | ||
251 | - } | ||
252 | - */ | ||
253 | - } | ||
254 | - | ||
255 | - private void verify(boolean expression, String errorMessageTemplate, Object... errorMessageArgs) { | ||
256 | - if (onlyLogTransitionError) { | ||
257 | - if (!expression) { | ||
258 | - log.error(errorMessageTemplate.replace("%s", "{}"), errorMessageArgs); | ||
259 | - } | ||
260 | - } else { | ||
261 | - Verify.verify(expression, errorMessageTemplate, errorMessageArgs); | ||
262 | - } | ||
263 | - } | ||
264 | - | ||
265 | - @Override | ||
266 | - public List<Intent> getInstallableIntents(Key intentKey) { | ||
267 | - // TODO: implement this or delete class | ||
268 | - return null; | ||
269 | - | ||
270 | - /* | ||
271 | - Context timer = startTimer(getInstallableIntentsTimer); | ||
272 | - try { | ||
273 | - return installable.get(intentId); | ||
274 | - } finally { | ||
275 | - stopTimer(timer); | ||
276 | - } | ||
277 | - */ | ||
278 | - } | ||
279 | - | ||
280 | - /*@Override | ||
281 | - public List<Operation> batchWrite(BatchWrite batch) { | ||
282 | - if (batch.isEmpty()) { | ||
283 | - return Collections.emptyList(); | ||
284 | - } | ||
285 | - | ||
286 | - // Hazelcast version will never fail for conditional failure now. | ||
287 | - List<Operation> failed = new ArrayList<>(); | ||
288 | - | ||
289 | - List<Pair<Operation, List<Future<?>>>> futures = new ArrayList<>(batch.operations().size()); | ||
290 | - List<IntentEvent> events = Lists.newArrayList(); | ||
291 | - | ||
292 | - batchWriteAsync(batch, failed, futures); | ||
293 | - | ||
294 | - // verify result | ||
295 | - verifyAsyncWrites(futures, failed, events); | ||
296 | - | ||
297 | - notifyDelegate(events); | ||
298 | - | ||
299 | - return failed; | ||
300 | - }*/ | ||
301 | - | ||
302 | - private void batchWriteAsync(BatchWrite batch, List<Operation> failed, | ||
303 | - List<Pair<Operation, List<Future<?>>>> futures) { | ||
304 | - for (Operation op : batch.operations()) { | ||
305 | - switch (op.type()) { | ||
306 | - case CREATE_INTENT: | ||
307 | - checkArgument(op.args().size() == 1, | ||
308 | - "CREATE_INTENT takes 1 argument. %s", op); | ||
309 | - Intent intent = op.arg(0); | ||
310 | - futures.add(Pair.of(op, | ||
311 | - ImmutableList.of(intents.putAsync(intent.id(), intent), | ||
312 | - states.putAsync(intent.id(), INSTALL_REQ)))); | ||
313 | - break; | ||
314 | - | ||
315 | - case REMOVE_INTENT: | ||
316 | - checkArgument(op.args().size() == 1, | ||
317 | - "REMOVE_INTENT takes 1 argument. %s", op); | ||
318 | - IntentId intentId = (IntentId) op.arg(0); | ||
319 | - futures.add(Pair.of(op, | ||
320 | - ImmutableList.of(intents.removeAsync(intentId), | ||
321 | - states.removeAsync(intentId), | ||
322 | - installable.removeAsync(intentId)))); | ||
323 | - break; | ||
324 | - | ||
325 | - case SET_STATE: | ||
326 | - checkArgument(op.args().size() == 2, | ||
327 | - "SET_STATE takes 2 arguments. %s", op); | ||
328 | - intent = op.arg(0); | ||
329 | - IntentState newState = op.arg(1); | ||
330 | - futures.add(Pair.of(op, | ||
331 | - ImmutableList.of(states.putAsync(intent.id(), newState)))); | ||
332 | - break; | ||
333 | - | ||
334 | - case SET_INSTALLABLE: | ||
335 | - checkArgument(op.args().size() == 2, | ||
336 | - "SET_INSTALLABLE takes 2 arguments. %s", op); | ||
337 | - intentId = op.arg(0); | ||
338 | - List<Intent> installableIntents = op.arg(1); | ||
339 | - futures.add(Pair.of(op, | ||
340 | - ImmutableList.of(installable.putAsync(intentId, installableIntents)))); | ||
341 | - break; | ||
342 | - | ||
343 | - case REMOVE_INSTALLED: | ||
344 | - checkArgument(op.args().size() == 1, | ||
345 | - "REMOVE_INSTALLED takes 1 argument. %s", op); | ||
346 | - intentId = op.arg(0); | ||
347 | - futures.add(Pair.of(op, | ||
348 | - ImmutableList.of(installable.removeAsync(intentId)))); | ||
349 | - break; | ||
350 | - | ||
351 | - default: | ||
352 | - log.warn("Unknown Operation encountered: {}", op); | ||
353 | - failed.add(op); | ||
354 | - break; | ||
355 | - } | ||
356 | - } | ||
357 | - } | ||
358 | - | ||
359 | - /** | ||
360 | - * Checks the async write result Futures and prepare Events to post. | ||
361 | - * | ||
362 | - * @param futures async write Futures | ||
363 | - * @param failed list to output failed batch write operations | ||
364 | - * @param events list to output events to post as result of writes | ||
365 | - */ | ||
366 | - private void verifyAsyncWrites(List<Pair<Operation, List<Future<?>>>> futures, | ||
367 | - List<Operation> failed, | ||
368 | - List<IntentEvent> events) { | ||
369 | - for (Pair<Operation, List<Future<?>>> future : futures) { | ||
370 | - final Operation op = future.getLeft(); | ||
371 | - final List<Future<?>> subops = future.getRight(); | ||
372 | - | ||
373 | - switch (op.type()) { | ||
374 | - | ||
375 | - case CREATE_INTENT: | ||
376 | - { | ||
377 | - Intent intent = op.arg(0); | ||
378 | - IntentState newIntentState = INSTALL_REQ; | ||
379 | - | ||
380 | - try { | ||
381 | - Intent prevIntent = (Intent) subops.get(0).get(); | ||
382 | - IntentState prevIntentState = (IntentState) subops.get(1).get(); | ||
383 | - | ||
384 | - if (prevIntent != null || prevIntentState != null) { | ||
385 | - log.warn("Overwriting existing Intent: {}@{} with {}@{}", | ||
386 | - prevIntent, prevIntentState, | ||
387 | - intent, newIntentState); | ||
388 | - } | ||
389 | - events.add(IntentEvent.getEvent(INSTALL_REQ, intent)); | ||
390 | - } catch (InterruptedException e) { | ||
391 | - log.error("Batch write was interrupted while processing {}", op, e); | ||
392 | - failed.add(op); | ||
393 | - Thread.currentThread().interrupt(); | ||
394 | - } catch (ExecutionException e) { | ||
395 | - log.error("Batch write failed processing {}", op, e); | ||
396 | - failed.add(op); | ||
397 | - } | ||
398 | - break; | ||
399 | - } | ||
400 | - | ||
401 | - case REMOVE_INTENT: | ||
402 | - { | ||
403 | - IntentId intentId = op.arg(0); | ||
404 | - | ||
405 | - try { | ||
406 | - Intent prevIntent = (Intent) subops.get(0).get(); | ||
407 | - IntentState prevIntentState = (IntentState) subops.get(1).get(); | ||
408 | - @SuppressWarnings("unchecked") | ||
409 | - List<Intent> prevInstallable = (List<Intent>) subops.get(2).get(); | ||
410 | - | ||
411 | - if (prevIntent == null) { | ||
412 | - log.warn("Intent {} was already removed.", intentId); | ||
413 | - } | ||
414 | - if (prevIntentState == null) { | ||
415 | - log.warn("Intent {} state was already removed", intentId); | ||
416 | - } | ||
417 | - if (prevInstallable != null) { | ||
418 | - log.warn("Intent {} removed installable still found", intentId); | ||
419 | - } | ||
420 | - } catch (InterruptedException e) { | ||
421 | - log.error("Batch write was interrupted while processing {}", op, e); | ||
422 | - failed.add(op); | ||
423 | - Thread.currentThread().interrupt(); | ||
424 | - } catch (ExecutionException e) { | ||
425 | - log.error("Batch write failed processing {}", op, e); | ||
426 | - failed.add(op); | ||
427 | - } | ||
428 | - break; | ||
429 | - } | ||
430 | - | ||
431 | - case SET_STATE: | ||
432 | - { | ||
433 | - Intent intent = op.arg(0); | ||
434 | - IntentId intentId = intent.id(); | ||
435 | - IntentState newState = op.arg(1); | ||
436 | - | ||
437 | - try { | ||
438 | - IntentState prevIntentState = (IntentState) subops.get(0).get(); | ||
439 | - | ||
440 | - if (PARKING.contains(newState)) { | ||
441 | - transientStates.remove(intentId); | ||
442 | - events.add(IntentEvent.getEvent(newState, intent)); | ||
443 | - } | ||
444 | - | ||
445 | - log.trace("{} - {} -> {}", intentId, prevIntentState, newState); | ||
446 | - } catch (InterruptedException e) { | ||
447 | - log.error("Batch write was interrupted while processing {}", op, e); | ||
448 | - failed.add(op); | ||
449 | - Thread.currentThread().interrupt(); | ||
450 | - } catch (ExecutionException e) { | ||
451 | - log.error("Batch write failed processing {}", op, e); | ||
452 | - failed.add(op); | ||
453 | - } | ||
454 | - break; | ||
455 | - } | ||
456 | - | ||
457 | - case SET_INSTALLABLE: | ||
458 | - { | ||
459 | - IntentId intentId = op.arg(0); | ||
460 | - List<Intent> installableIntents = op.arg(1); | ||
461 | - | ||
462 | - try { | ||
463 | - @SuppressWarnings("unchecked") | ||
464 | - List<Intent> prevInstallable = (List<Intent>) subops.get(0).get(); | ||
465 | - | ||
466 | - if (prevInstallable != null) { | ||
467 | - log.warn("Overwriting Intent {} installable {} -> {}", | ||
468 | - intentId, prevInstallable, installableIntents); | ||
469 | - } | ||
470 | - } catch (InterruptedException e) { | ||
471 | - log.error("Batch write was interrupted while processing {}", op, e); | ||
472 | - failed.add(op); | ||
473 | - Thread.currentThread().interrupt(); | ||
474 | - } catch (ExecutionException e) { | ||
475 | - log.error("Batch write failed processing {}", op, e); | ||
476 | - failed.add(op); | ||
477 | - } | ||
478 | - break; | ||
479 | - } | ||
480 | - | ||
481 | - case REMOVE_INSTALLED: | ||
482 | - { | ||
483 | - IntentId intentId = op.arg(0); | ||
484 | - | ||
485 | - try { | ||
486 | - @SuppressWarnings("unchecked") | ||
487 | - List<Intent> prevInstallable = (List<Intent>) subops.get(0).get(); | ||
488 | - | ||
489 | - if (prevInstallable == null) { | ||
490 | - log.warn("Intent {} installable was already removed", intentId); | ||
491 | - } | ||
492 | - } catch (InterruptedException e) { | ||
493 | - log.error("Batch write was interrupted while processing {}", op, e); | ||
494 | - failed.add(op); | ||
495 | - Thread.currentThread().interrupt(); | ||
496 | - } catch (ExecutionException e) { | ||
497 | - log.error("Batch write failed processing {}", op, e); | ||
498 | - failed.add(op); | ||
499 | - } | ||
500 | - break; | ||
501 | - } | ||
502 | - | ||
503 | - default: | ||
504 | - log.warn("Unknown Operation encountered: {}", op); | ||
505 | - if (!failed.contains(op)) { | ||
506 | - failed.add(op); | ||
507 | - } | ||
508 | - break; | ||
509 | - } | ||
510 | - } | ||
511 | - } | ||
512 | - | ||
513 | - public final class RemoteIntentsListener extends EntryAdapter<IntentId, Intent> { | ||
514 | - | ||
515 | - @Override | ||
516 | - public void entryAdded(EntryEvent<IntentId, Intent> event) { | ||
517 | - localIntents.put(event.getKey(), event.getValue()); | ||
518 | - } | ||
519 | - | ||
520 | - @Override | ||
521 | - public void entryUpdated(EntryEvent<IntentId, Intent> event) { | ||
522 | - entryAdded(event); | ||
523 | - } | ||
524 | - } | ||
525 | - | ||
526 | - public final class RemoteIntentStateListener extends EntryAdapter<IntentId, IntentState> { | ||
527 | - | ||
528 | - @Override | ||
529 | - public void onEntryEvent(EntryEvent<IntentId, IntentState> event) { | ||
530 | - final IntentId intentId = event.getKey(); | ||
531 | - final Member myself = theInstance.getCluster().getLocalMember(); | ||
532 | - if (!myself.equals(event.getMember())) { | ||
533 | - // When Intent state was modified by remote node, | ||
534 | - // clear local transient state. | ||
535 | - IntentState oldState = transientStates.remove(intentId); | ||
536 | - if (oldState != null) { | ||
537 | - log.debug("{} state updated remotely, removing transient state {}", | ||
538 | - intentId, oldState); | ||
539 | - } | ||
540 | - | ||
541 | - if (event.getValue() != null) { | ||
542 | - // notify if this is not entry removed event | ||
543 | - | ||
544 | - final Intent intent = getIntent(intentId); | ||
545 | - if (intent == null) { | ||
546 | - log.warn("no Intent found for {} on Event {}", intentId, event); | ||
547 | - return; | ||
548 | - } | ||
549 | - notifyDelegate(IntentEvent.getEvent(event.getValue(), intent)); | ||
550 | - // remove IntentCache | ||
551 | - localIntents.remove(intentId, intent); | ||
552 | - } | ||
553 | - } | ||
554 | - | ||
555 | - // populate manual near cache, to prepare for | ||
556 | - // transition event to WITHDRAWN | ||
557 | - getIntent(intentId); | ||
558 | - } | ||
559 | - } | ||
560 | -} |
core/store/dist/src/main/java/org/onosproject/store/intent/impl/SimpleIntentStore.java
deleted
100644 → 0
1 | -/* | ||
2 | - * Copyright 2015 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.onosproject.store.intent.impl; | ||
17 | - | ||
18 | -import com.google.common.collect.Maps; | ||
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.onosproject.net.intent.Intent; | ||
24 | -import org.onosproject.net.intent.IntentData; | ||
25 | -import org.onosproject.net.intent.IntentEvent; | ||
26 | -import org.onosproject.net.intent.IntentState; | ||
27 | -import org.onosproject.net.intent.IntentStore; | ||
28 | -import org.onosproject.net.intent.IntentStoreDelegate; | ||
29 | -import org.onosproject.net.intent.Key; | ||
30 | -import org.onosproject.store.AbstractStore; | ||
31 | -import org.onosproject.store.impl.SystemClockTimestamp; | ||
32 | -import org.slf4j.Logger; | ||
33 | - | ||
34 | -import java.util.List; | ||
35 | -import java.util.Map; | ||
36 | -import java.util.stream.Collectors; | ||
37 | - | ||
38 | -import static com.google.common.base.Preconditions.checkNotNull; | ||
39 | -import static org.onosproject.net.intent.IntentState.*; | ||
40 | -import static org.slf4j.LoggerFactory.getLogger; | ||
41 | - | ||
42 | -//TODO Note: this store will be removed once the GossipIntentStore is stable | ||
43 | - | ||
44 | -@Component(immediate = true, enabled = false) | ||
45 | -@Service | ||
46 | -//FIXME remove this | ||
47 | -public class SimpleIntentStore | ||
48 | - extends AbstractStore<IntentEvent, IntentStoreDelegate> | ||
49 | - implements IntentStore { | ||
50 | - | ||
51 | - private final Logger log = getLogger(getClass()); | ||
52 | - | ||
53 | - private final Map<Key, IntentData> current = Maps.newConcurrentMap(); | ||
54 | - private final Map<Key, IntentData> pending = Maps.newConcurrentMap(); | ||
55 | - | ||
56 | - private IntentData copyData(IntentData original) { | ||
57 | - if (original == null) { | ||
58 | - return null; | ||
59 | - } | ||
60 | - IntentData result = | ||
61 | - new IntentData(original.intent(), original.state(), original.version()); | ||
62 | - | ||
63 | - if (original.installables() != null) { | ||
64 | - result.setInstallables(original.installables()); | ||
65 | - } | ||
66 | - return result; | ||
67 | - } | ||
68 | - | ||
69 | - @Activate | ||
70 | - public void activate() { | ||
71 | - log.info("Started"); | ||
72 | - } | ||
73 | - | ||
74 | - @Deactivate | ||
75 | - public void deactivate() { | ||
76 | - log.info("Stopped"); | ||
77 | - } | ||
78 | - | ||
79 | - @Override | ||
80 | - public long getIntentCount() { | ||
81 | - return current.size(); | ||
82 | - } | ||
83 | - | ||
84 | - @Override | ||
85 | - public Iterable<Intent> getIntents() { | ||
86 | - return current.values().stream() | ||
87 | - .map(IntentData::intent) | ||
88 | - .collect(Collectors.toList()); | ||
89 | - } | ||
90 | - | ||
91 | - @Override | ||
92 | - public IntentState getIntentState(Key intentKey) { | ||
93 | - IntentData data = current.get(intentKey); | ||
94 | - return (data != null) ? data.state() : null; | ||
95 | - } | ||
96 | - | ||
97 | - @Override | ||
98 | - public List<Intent> getInstallableIntents(Key intentKey) { | ||
99 | - // TODO: implement this or delete class | ||
100 | - return null; | ||
101 | - /* | ||
102 | - for (IntentData data : current.values()) { | ||
103 | - if (Objects.equals(data.intent().id(), intentId)) { | ||
104 | - return data.installables(); | ||
105 | - } | ||
106 | - } | ||
107 | - return null; | ||
108 | - */ | ||
109 | - } | ||
110 | - | ||
111 | - | ||
112 | - /** | ||
113 | - * Determines whether an intent data update is allowed. The update must | ||
114 | - * either have a higher version than the current data, or the state | ||
115 | - * transition between two updates of the same version must be sane. | ||
116 | - * | ||
117 | - * @param currentData existing intent data in the store | ||
118 | - * @param newData new intent data update proposal | ||
119 | - * @return true if we can apply the update, otherwise false | ||
120 | - */ | ||
121 | - private boolean isUpdateAcceptable(IntentData currentData, IntentData newData) { | ||
122 | - | ||
123 | - if (currentData == null) { | ||
124 | - return true; | ||
125 | - } else if (currentData.version().compareTo(newData.version()) < 0) { | ||
126 | - return true; | ||
127 | - } else if (currentData.version().compareTo(newData.version()) > 0) { | ||
128 | - return false; | ||
129 | - } | ||
130 | - | ||
131 | - // current and new data versions are the same | ||
132 | - IntentState currentState = currentData.state(); | ||
133 | - IntentState newState = newData.state(); | ||
134 | - | ||
135 | - switch (newState) { | ||
136 | - case INSTALLING: | ||
137 | - if (currentState == INSTALLING) { | ||
138 | - return false; | ||
139 | - } | ||
140 | - // FALLTHROUGH | ||
141 | - case INSTALLED: | ||
142 | - if (currentState == INSTALLED) { | ||
143 | - return false; | ||
144 | - } else if (currentState == WITHDRAWING || currentState == WITHDRAWN) { | ||
145 | - log.warn("Invalid state transition from {} to {} for intent {}", | ||
146 | - currentState, newState, newData.key()); | ||
147 | - return false; | ||
148 | - } | ||
149 | - return true; | ||
150 | - | ||
151 | - case WITHDRAWING: | ||
152 | - if (currentState == WITHDRAWING) { | ||
153 | - return false; | ||
154 | - } | ||
155 | - // FALLTHOUGH | ||
156 | - case WITHDRAWN: | ||
157 | - if (currentState == WITHDRAWN) { | ||
158 | - return false; | ||
159 | - } else if (currentState == INSTALLING || currentState == INSTALLED) { | ||
160 | - log.warn("Invalid state transition from {} to {} for intent {}", | ||
161 | - currentState, newState, newData.key()); | ||
162 | - return false; | ||
163 | - } | ||
164 | - return true; | ||
165 | - | ||
166 | - | ||
167 | - case FAILED: | ||
168 | - if (currentState == FAILED) { | ||
169 | - return false; | ||
170 | - } | ||
171 | - return true; | ||
172 | - | ||
173 | - | ||
174 | - case COMPILING: | ||
175 | - case RECOMPILING: | ||
176 | - case INSTALL_REQ: | ||
177 | - case WITHDRAW_REQ: | ||
178 | - default: | ||
179 | - log.warn("Invalid state {} for intent {}", newState, newData.key()); | ||
180 | - return false; | ||
181 | - } | ||
182 | - } | ||
183 | - | ||
184 | - @Override | ||
185 | - public void write(IntentData newData) { | ||
186 | - synchronized (this) { | ||
187 | - // TODO this could be refactored/cleaned up | ||
188 | - IntentData currentData = current.get(newData.key()); | ||
189 | - IntentData pendingData = pending.get(newData.key()); | ||
190 | - | ||
191 | - if (isUpdateAcceptable(currentData, newData)) { | ||
192 | - current.put(newData.key(), copyData(newData)); | ||
193 | - | ||
194 | - if (pendingData != null | ||
195 | - // pendingData version is less than or equal to newData's | ||
196 | - // Note: a new update for this key could be pending (it's version will be greater) | ||
197 | - && pendingData.version().compareTo(newData.version()) <= 0) { | ||
198 | - pending.remove(newData.key()); | ||
199 | - } | ||
200 | - | ||
201 | - notifyDelegateIfNotNull(IntentEvent.getEvent(newData)); | ||
202 | - } | ||
203 | - } | ||
204 | - } | ||
205 | - | ||
206 | - private void notifyDelegateIfNotNull(IntentEvent event) { | ||
207 | - if (event != null) { | ||
208 | - notifyDelegate(event); | ||
209 | - } | ||
210 | - } | ||
211 | - | ||
212 | - @Override | ||
213 | - public void batchWrite(Iterable<IntentData> updates) { | ||
214 | - for (IntentData data : updates) { | ||
215 | - write(data); | ||
216 | - } | ||
217 | - } | ||
218 | - | ||
219 | - @Override | ||
220 | - public Intent getIntent(Key key) { | ||
221 | - IntentData data = current.get(key); | ||
222 | - return (data != null) ? data.intent() : null; | ||
223 | - } | ||
224 | - | ||
225 | - @Override | ||
226 | - public IntentData getIntentData(Key key) { | ||
227 | - return copyData(current.get(key)); | ||
228 | - } | ||
229 | - | ||
230 | - @Override | ||
231 | - public void addPending(IntentData data) { | ||
232 | - if (data.version() == null) { // recompiled intents will already have a version | ||
233 | - data.setVersion(new SystemClockTimestamp()); | ||
234 | - } | ||
235 | - synchronized (this) { | ||
236 | - IntentData existingData = pending.get(data.key()); | ||
237 | - if (existingData == null || | ||
238 | - // existing version is strictly less than data's version | ||
239 | - // Note: if they are equal, we already have the update | ||
240 | - // TODO maybe we should still make this <= to be safe? | ||
241 | - existingData.version().compareTo(data.version()) < 0) { | ||
242 | - pending.put(data.key(), data); | ||
243 | - checkNotNull(delegate, "Store delegate is not set") | ||
244 | - .process(data); | ||
245 | - notifyDelegateIfNotNull(IntentEvent.getEvent(data)); | ||
246 | - } else { | ||
247 | - log.debug("IntentData {} is older than existing: {}", | ||
248 | - data, existingData); | ||
249 | - } | ||
250 | - //TODO consider also checking the current map at this point | ||
251 | - } | ||
252 | - } | ||
253 | - | ||
254 | - @Override | ||
255 | - public boolean isMaster(Key intentKey) { | ||
256 | - return true; | ||
257 | - } | ||
258 | -} |
1 | /* | 1 | /* |
2 | - * Copyright 2014 Open Networking Laboratory | 2 | + * Copyright 2015 Open Networking Laboratory |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
... | @@ -35,10 +35,9 @@ import java.util.Map; | ... | @@ -35,10 +35,9 @@ import java.util.Map; |
35 | import java.util.stream.Collectors; | 35 | import java.util.stream.Collectors; |
36 | 36 | ||
37 | import static com.google.common.base.Preconditions.checkNotNull; | 37 | import static com.google.common.base.Preconditions.checkNotNull; |
38 | +import static org.onosproject.net.intent.IntentState.*; | ||
38 | import static org.slf4j.LoggerFactory.getLogger; | 39 | import static org.slf4j.LoggerFactory.getLogger; |
39 | 40 | ||
40 | -//TODO Note: this store will be removed | ||
41 | - | ||
42 | @Component(immediate = true) | 41 | @Component(immediate = true) |
43 | @Service | 42 | @Service |
44 | public class SimpleIntentStore | 43 | public class SimpleIntentStore |
... | @@ -47,9 +46,21 @@ public class SimpleIntentStore | ... | @@ -47,9 +46,21 @@ public class SimpleIntentStore |
47 | 46 | ||
48 | private final Logger log = getLogger(getClass()); | 47 | private final Logger log = getLogger(getClass()); |
49 | 48 | ||
50 | - // current state maps FIXME.. make this a IntentData map | ||
51 | private final Map<Key, IntentData> current = Maps.newConcurrentMap(); | 49 | private final Map<Key, IntentData> current = Maps.newConcurrentMap(); |
52 | - private final Map<Key, IntentData> pending = Maps.newConcurrentMap(); //String is "key" | 50 | + private final Map<Key, IntentData> pending = Maps.newConcurrentMap(); |
51 | + | ||
52 | + private IntentData copyData(IntentData original) { | ||
53 | + if (original == null) { | ||
54 | + return null; | ||
55 | + } | ||
56 | + IntentData result = | ||
57 | + new IntentData(original.intent(), original.state(), original.version()); | ||
58 | + | ||
59 | + if (original.installables() != null) { | ||
60 | + result.setInstallables(original.installables()); | ||
61 | + } | ||
62 | + return result; | ||
63 | + } | ||
53 | 64 | ||
54 | @Activate | 65 | @Activate |
55 | public void activate() { | 66 | public void activate() { |
... | @@ -82,22 +93,110 @@ public class SimpleIntentStore | ... | @@ -82,22 +93,110 @@ public class SimpleIntentStore |
82 | @Override | 93 | @Override |
83 | public List<Intent> getInstallableIntents(Key intentKey) { | 94 | public List<Intent> getInstallableIntents(Key intentKey) { |
84 | IntentData data = current.get(intentKey); | 95 | IntentData data = current.get(intentKey); |
85 | - return (data != null) ? data.installables() : null; | 96 | + if (data != null) { |
97 | + return data.installables(); | ||
98 | + } | ||
99 | + return null; | ||
100 | + } | ||
101 | + | ||
102 | + | ||
103 | + /** | ||
104 | + * Determines whether an intent data update is allowed. The update must | ||
105 | + * either have a higher version than the current data, or the state | ||
106 | + * transition between two updates of the same version must be sane. | ||
107 | + * | ||
108 | + * @param currentData existing intent data in the store | ||
109 | + * @param newData new intent data update proposal | ||
110 | + * @return true if we can apply the update, otherwise false | ||
111 | + */ | ||
112 | + private boolean isUpdateAcceptable(IntentData currentData, IntentData newData) { | ||
113 | + | ||
114 | + if (currentData == null) { | ||
115 | + return true; | ||
116 | + } else if (currentData.version().compareTo(newData.version()) < 0) { | ||
117 | + return true; | ||
118 | + } else if (currentData.version().compareTo(newData.version()) > 0) { | ||
119 | + return false; | ||
120 | + } | ||
121 | + | ||
122 | + // current and new data versions are the same | ||
123 | + IntentState currentState = currentData.state(); | ||
124 | + IntentState newState = newData.state(); | ||
125 | + | ||
126 | + switch (newState) { | ||
127 | + case INSTALLING: | ||
128 | + if (currentState == INSTALLING) { | ||
129 | + return false; | ||
130 | + } | ||
131 | + // FALLTHROUGH | ||
132 | + case INSTALLED: | ||
133 | + if (currentState == INSTALLED) { | ||
134 | + return false; | ||
135 | + } else if (currentState == WITHDRAWING || currentState == WITHDRAWN) { | ||
136 | + log.warn("Invalid state transition from {} to {} for intent {}", | ||
137 | + currentState, newState, newData.key()); | ||
138 | + return false; | ||
139 | + } | ||
140 | + return true; | ||
141 | + | ||
142 | + case WITHDRAWING: | ||
143 | + if (currentState == WITHDRAWING) { | ||
144 | + return false; | ||
145 | + } | ||
146 | + // FALLTHOUGH | ||
147 | + case WITHDRAWN: | ||
148 | + if (currentState == WITHDRAWN) { | ||
149 | + return false; | ||
150 | + } else if (currentState == INSTALLING || currentState == INSTALLED) { | ||
151 | + log.warn("Invalid state transition from {} to {} for intent {}", | ||
152 | + currentState, newState, newData.key()); | ||
153 | + return false; | ||
154 | + } | ||
155 | + return true; | ||
156 | + | ||
157 | + | ||
158 | + case FAILED: | ||
159 | + if (currentState == FAILED) { | ||
160 | + return false; | ||
161 | + } | ||
162 | + return true; | ||
163 | + | ||
164 | + | ||
165 | + case COMPILING: | ||
166 | + case RECOMPILING: | ||
167 | + case INSTALL_REQ: | ||
168 | + case WITHDRAW_REQ: | ||
169 | + default: | ||
170 | + log.warn("Invalid state {} for intent {}", newState, newData.key()); | ||
171 | + return false; | ||
172 | + } | ||
86 | } | 173 | } |
87 | 174 | ||
88 | @Override | 175 | @Override |
89 | public void write(IntentData newData) { | 176 | public void write(IntentData newData) { |
90 | - //FIXME need to compare the versions | 177 | + synchronized (this) { |
91 | - current.put(newData.key(), newData); | 178 | + // TODO this could be refactored/cleaned up |
92 | - try { | 179 | + IntentData currentData = current.get(newData.key()); |
93 | - notifyDelegate(IntentEvent.getEvent(newData)); | 180 | + IntentData pendingData = pending.get(newData.key()); |
94 | - } catch (IllegalArgumentException e) { | 181 | + |
95 | - //no-op | 182 | + if (isUpdateAcceptable(currentData, newData)) { |
96 | - log.trace("ignore this exception: {}", e); | 183 | + current.put(newData.key(), copyData(newData)); |
184 | + | ||
185 | + if (pendingData != null | ||
186 | + // pendingData version is less than or equal to newData's | ||
187 | + // Note: a new update for this key could be pending (it's version will be greater) | ||
188 | + && pendingData.version().compareTo(newData.version()) <= 0) { | ||
189 | + pending.remove(newData.key()); | ||
190 | + } | ||
191 | + | ||
192 | + notifyDelegateIfNotNull(IntentEvent.getEvent(newData)); | ||
193 | + } | ||
97 | } | 194 | } |
98 | - IntentData old = pending.get(newData.key()); | 195 | + } |
99 | - if (old != null /* && FIXME version check */) { | 196 | + |
100 | - pending.remove(newData.key()); | 197 | + private void notifyDelegateIfNotNull(IntentEvent event) { |
198 | + if (event != null) { | ||
199 | + notifyDelegate(event); | ||
101 | } | 200 | } |
102 | } | 201 | } |
103 | 202 | ||
... | @@ -114,14 +213,44 @@ public class SimpleIntentStore | ... | @@ -114,14 +213,44 @@ public class SimpleIntentStore |
114 | return (data != null) ? data.intent() : null; | 213 | return (data != null) ? data.intent() : null; |
115 | } | 214 | } |
116 | 215 | ||
216 | + @Override | ||
217 | + public IntentData getIntentData(Key key) { | ||
218 | + return copyData(current.get(key)); | ||
219 | + } | ||
117 | 220 | ||
118 | @Override | 221 | @Override |
119 | public void addPending(IntentData data) { | 222 | public void addPending(IntentData data) { |
120 | - //FIXME need to compare versions | 223 | + if (data.version() == null) { // recompiled intents will already have a version |
121 | - pending.put(data.key(), data); | 224 | + data.setVersion(new SystemClockTimestamp()); |
122 | - checkNotNull(delegate, "Store delegate is not set") | 225 | + } |
123 | - .process(data); | 226 | + synchronized (this) { |
124 | - notifyDelegate(IntentEvent.getEvent(data)); | 227 | + IntentData existingData = pending.get(data.key()); |
228 | + if (existingData == null || | ||
229 | + // existing version is strictly less than data's version | ||
230 | + // Note: if they are equal, we already have the update | ||
231 | + // TODO maybe we should still make this <= to be safe? | ||
232 | + existingData.version().compareTo(data.version()) < 0) { | ||
233 | + pending.put(data.key(), data); | ||
234 | + checkNotNull(delegate, "Store delegate is not set") | ||
235 | + .process(data); | ||
236 | + notifyDelegateIfNotNull(IntentEvent.getEvent(data)); | ||
237 | + } else { | ||
238 | + log.debug("IntentData {} is older than existing: {}", | ||
239 | + data, existingData); | ||
240 | + } | ||
241 | + //TODO consider also checking the current map at this point | ||
242 | + } | ||
243 | + } | ||
244 | + | ||
245 | + @Override | ||
246 | + public boolean isMaster(Key intentKey) { | ||
247 | + return true; | ||
125 | } | 248 | } |
126 | 249 | ||
250 | + @Override | ||
251 | + public Iterable<Intent> getPending() { | ||
252 | + return pending.values().stream() | ||
253 | + .map(IntentData::intent) | ||
254 | + .collect(Collectors.toList()); | ||
255 | + } | ||
127 | } | 256 | } | ... | ... |
... | @@ -13,7 +13,7 @@ | ... | @@ -13,7 +13,7 @@ |
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | -package org.onosproject.store.impl; | 16 | +package org.onosproject.store.trivial.impl; |
17 | 17 | ||
18 | import com.google.common.base.MoreObjects; | 18 | import com.google.common.base.MoreObjects; |
19 | import com.google.common.collect.ComparisonChain; | 19 | import com.google.common.collect.ComparisonChain; | ... | ... |
-
Please register or login to post a comment