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
162 additions
and
315 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
This diff is collapsed. Click to expand it.
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,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; | ... | ... |
-
Please register or login to post a comment