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 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,23 +93,111 @@ public class SimpleIntentStore ...@@ -82,23 +93,111 @@ 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));
97 - } 184 +
98 - IntentData old = pending.get(newData.key()); 185 + if (pendingData != null
99 - if (old != null /* && FIXME version check */) { 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) {
100 pending.remove(newData.key()); 189 pending.remove(newData.key());
101 } 190 }
191 +
192 + notifyDelegateIfNotNull(IntentEvent.getEvent(newData));
193 + }
194 + }
195 + }
196 +
197 + private void notifyDelegateIfNotNull(IntentEvent event) {
198 + if (event != null) {
199 + notifyDelegate(event);
200 + }
102 } 201 }
103 202
104 @Override 203 @Override
...@@ -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
224 + data.setVersion(new SystemClockTimestamp());
225 + }
226 + synchronized (this) {
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) {
121 pending.put(data.key(), data); 233 pending.put(data.key(), data);
122 checkNotNull(delegate, "Store delegate is not set") 234 checkNotNull(delegate, "Store delegate is not set")
123 .process(data); 235 .process(data);
124 - notifyDelegate(IntentEvent.getEvent(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 + }
125 } 243 }
126 244
245 + @Override
246 + public boolean isMaster(Key intentKey) {
247 + return true;
248 + }
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;
......