Jonathan Hart
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
...@@ -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 }
......
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 -}
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;
......