Jonathan Hart

Modified GossipIntentStore to use EventuallyConsistentMaps.

All IntentStore operations are now implemented.

ONOS-858

Change-Id: I5081805b61c7e25e28707b90093cae12b5a4374b
...@@ -151,7 +151,7 @@ public interface EventuallyConsistentMap<K, V> { ...@@ -151,7 +151,7 @@ public interface EventuallyConsistentMap<K, V> {
151 * 151 *
152 * @param listener listener to register for events 152 * @param listener listener to register for events
153 */ 153 */
154 - public void addListener(EventuallyConsistentMapListener listener); 154 + public void addListener(EventuallyConsistentMapListener<K, V> listener);
155 155
156 /** 156 /**
157 * Removes the specified listener from the map such that it will no longer 157 * Removes the specified listener from the map such that it will no longer
...@@ -159,7 +159,7 @@ public interface EventuallyConsistentMap<K, V> { ...@@ -159,7 +159,7 @@ public interface EventuallyConsistentMap<K, V> {
159 * 159 *
160 * @param listener listener to deregister for events 160 * @param listener listener to deregister for events
161 */ 161 */
162 - public void removeListener(EventuallyConsistentMapListener listener); 162 + public void removeListener(EventuallyConsistentMapListener<K, V> listener);
163 163
164 /** 164 /**
165 * Shuts down the map and breaks communication between different instances. 165 * Shuts down the map and breaks communication between different instances.
......
...@@ -78,7 +78,7 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -78,7 +78,7 @@ public class EventuallyConsistentMapImpl<K, V>
78 private final ScheduledExecutorService backgroundExecutor; 78 private final ScheduledExecutorService backgroundExecutor;
79 79
80 private volatile boolean destroyed = false; 80 private volatile boolean destroyed = false;
81 - private static final String ERROR_DESTROYED = " is already destroyed"; 81 + private static final String ERROR_DESTROYED = " map is already destroyed";
82 82
83 // TODO: Make these anti-entropy params configurable 83 // TODO: Make these anti-entropy params configurable
84 private long initialDelaySec = 5; 84 private long initialDelaySec = 5;
...@@ -154,6 +154,7 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -154,6 +154,7 @@ public class EventuallyConsistentMapImpl<K, V>
154 serializerPool = builder 154 serializerPool = builder
155 .register(WallClockTimestamp.class) 155 .register(WallClockTimestamp.class)
156 .register(PutEntry.class) 156 .register(PutEntry.class)
157 + .register(RemoveEntry.class)
157 .register(ArrayList.class) 158 .register(ArrayList.class)
158 .register(InternalPutEvent.class) 159 .register(InternalPutEvent.class)
159 .register(InternalRemoveEvent.class) 160 .register(InternalRemoveEvent.class)
...@@ -166,25 +167,25 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -166,25 +167,25 @@ public class EventuallyConsistentMapImpl<K, V>
166 167
167 @Override 168 @Override
168 public int size() { 169 public int size() {
169 - checkState(destroyed, mapName + ERROR_DESTROYED); 170 + checkState(!destroyed, mapName + ERROR_DESTROYED);
170 return items.size(); 171 return items.size();
171 } 172 }
172 173
173 @Override 174 @Override
174 public boolean isEmpty() { 175 public boolean isEmpty() {
175 - checkState(destroyed, mapName + ERROR_DESTROYED); 176 + checkState(!destroyed, mapName + ERROR_DESTROYED);
176 return items.isEmpty(); 177 return items.isEmpty();
177 } 178 }
178 179
179 @Override 180 @Override
180 public boolean containsKey(K key) { 181 public boolean containsKey(K key) {
181 - checkState(destroyed, mapName + ERROR_DESTROYED); 182 + checkState(!destroyed, mapName + ERROR_DESTROYED);
182 return items.containsKey(key); 183 return items.containsKey(key);
183 } 184 }
184 185
185 @Override 186 @Override
186 public boolean containsValue(V value) { 187 public boolean containsValue(V value) {
187 - checkState(destroyed, mapName + ERROR_DESTROYED); 188 + checkState(!destroyed, mapName + ERROR_DESTROYED);
188 189
189 return items.values().stream() 190 return items.values().stream()
190 .anyMatch(timestamped -> timestamped.value().equals(value)); 191 .anyMatch(timestamped -> timestamped.value().equals(value));
...@@ -192,7 +193,7 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -192,7 +193,7 @@ public class EventuallyConsistentMapImpl<K, V>
192 193
193 @Override 194 @Override
194 public V get(K key) { 195 public V get(K key) {
195 - checkState(destroyed, mapName + ERROR_DESTROYED); 196 + checkState(!destroyed, mapName + ERROR_DESTROYED);
196 197
197 Timestamped<V> value = items.get(key); 198 Timestamped<V> value = items.get(key);
198 if (value != null) { 199 if (value != null) {
...@@ -203,7 +204,7 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -203,7 +204,7 @@ public class EventuallyConsistentMapImpl<K, V>
203 204
204 @Override 205 @Override
205 public void put(K key, V value) { 206 public void put(K key, V value) {
206 - checkState(destroyed, mapName + ERROR_DESTROYED); 207 + checkState(!destroyed, mapName + ERROR_DESTROYED);
207 208
208 Timestamp timestamp = clockService.getTimestamp(key); 209 Timestamp timestamp = clockService.getTimestamp(key);
209 if (putInternal(key, value, timestamp)) { 210 if (putInternal(key, value, timestamp)) {
...@@ -235,7 +236,7 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -235,7 +236,7 @@ public class EventuallyConsistentMapImpl<K, V>
235 236
236 @Override 237 @Override
237 public void remove(K key) { 238 public void remove(K key) {
238 - checkState(destroyed, mapName + ERROR_DESTROYED); 239 + checkState(!destroyed, mapName + ERROR_DESTROYED);
239 240
240 Timestamp timestamp = clockService.getTimestamp(key); 241 Timestamp timestamp = clockService.getTimestamp(key);
241 if (removeInternal(key, timestamp)) { 242 if (removeInternal(key, timestamp)) {
...@@ -261,7 +262,7 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -261,7 +262,7 @@ public class EventuallyConsistentMapImpl<K, V>
261 262
262 @Override 263 @Override
263 public void putAll(Map<? extends K, ? extends V> m) { 264 public void putAll(Map<? extends K, ? extends V> m) {
264 - checkState(destroyed, mapName + ERROR_DESTROYED); 265 + checkState(!destroyed, mapName + ERROR_DESTROYED);
265 266
266 List<PutEntry<K, V>> updates = new ArrayList<>(m.size()); 267 List<PutEntry<K, V>> updates = new ArrayList<>(m.size());
267 268
...@@ -287,7 +288,7 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -287,7 +288,7 @@ public class EventuallyConsistentMapImpl<K, V>
287 288
288 @Override 289 @Override
289 public void clear() { 290 public void clear() {
290 - checkState(destroyed, mapName + ERROR_DESTROYED); 291 + checkState(!destroyed, mapName + ERROR_DESTROYED);
291 292
292 List<RemoveEntry<K>> removed = new ArrayList<>(items.size()); 293 List<RemoveEntry<K>> removed = new ArrayList<>(items.size());
293 294
...@@ -311,14 +312,14 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -311,14 +312,14 @@ public class EventuallyConsistentMapImpl<K, V>
311 312
312 @Override 313 @Override
313 public Set<K> keySet() { 314 public Set<K> keySet() {
314 - checkState(destroyed, mapName + ERROR_DESTROYED); 315 + checkState(!destroyed, mapName + ERROR_DESTROYED);
315 316
316 return items.keySet(); 317 return items.keySet();
317 } 318 }
318 319
319 @Override 320 @Override
320 public Collection<V> values() { 321 public Collection<V> values() {
321 - checkState(destroyed, mapName + ERROR_DESTROYED); 322 + checkState(!destroyed, mapName + ERROR_DESTROYED);
322 323
323 return items.values().stream() 324 return items.values().stream()
324 .map(Timestamped::value) 325 .map(Timestamped::value)
...@@ -327,7 +328,7 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -327,7 +328,7 @@ public class EventuallyConsistentMapImpl<K, V>
327 328
328 @Override 329 @Override
329 public Set<Map.Entry<K, V>> entrySet() { 330 public Set<Map.Entry<K, V>> entrySet() {
330 - checkState(destroyed, mapName + ERROR_DESTROYED); 331 + checkState(!destroyed, mapName + ERROR_DESTROYED);
331 332
332 return items.entrySet().stream() 333 return items.entrySet().stream()
333 .map(e -> new Entry(e.getKey(), e.getValue().value())) 334 .map(e -> new Entry(e.getKey(), e.getValue().value()))
...@@ -335,15 +336,15 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -335,15 +336,15 @@ public class EventuallyConsistentMapImpl<K, V>
335 } 336 }
336 337
337 @Override 338 @Override
338 - public void addListener(EventuallyConsistentMapListener listener) { 339 + public void addListener(EventuallyConsistentMapListener<K, V> listener) {
339 - checkState(destroyed, mapName + ERROR_DESTROYED); 340 + checkState(!destroyed, mapName + ERROR_DESTROYED);
340 341
341 listeners.add(checkNotNull(listener)); 342 listeners.add(checkNotNull(listener));
342 } 343 }
343 344
344 @Override 345 @Override
345 - public void removeListener(EventuallyConsistentMapListener listener) { 346 + public void removeListener(EventuallyConsistentMapListener<K, V> listener) {
346 - checkState(destroyed, mapName + ERROR_DESTROYED); 347 + checkState(!destroyed, mapName + ERROR_DESTROYED);
347 348
348 listeners.remove(checkNotNull(listener)); 349 listeners.remove(checkNotNull(listener));
349 } 350 }
......
...@@ -19,12 +19,12 @@ package org.onosproject.store.impl; ...@@ -19,12 +19,12 @@ package org.onosproject.store.impl;
19 * Listener interested in receiving modification events for an 19 * Listener interested in receiving modification events for an
20 * EventuallyConsistentMap. 20 * EventuallyConsistentMap.
21 */ 21 */
22 -public interface EventuallyConsistentMapListener { 22 +public interface EventuallyConsistentMapListener<K, V> {
23 23
24 /** 24 /**
25 * Reacts to the specified event. 25 * Reacts to the specified event.
26 * 26 *
27 * @param event the event 27 * @param event the event
28 */ 28 */
29 - public void event(EventuallyConsistentMapEvent event); 29 + public void event(EventuallyConsistentMapEvent<K, V> event);
30 } 30 }
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
16 package org.onosproject.store.intent.impl; 16 package org.onosproject.store.intent.impl;
17 17
18 import com.google.common.collect.ImmutableList; 18 import com.google.common.collect.ImmutableList;
19 -import com.google.common.collect.Lists;
20 -import com.google.common.collect.Sets;
21 import org.apache.felix.scr.annotations.Activate; 19 import org.apache.felix.scr.annotations.Activate;
22 import org.apache.felix.scr.annotations.Component; 20 import org.apache.felix.scr.annotations.Component;
23 import org.apache.felix.scr.annotations.Deactivate; 21 import org.apache.felix.scr.annotations.Deactivate;
...@@ -26,46 +24,29 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -26,46 +24,29 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
26 import org.apache.felix.scr.annotations.Service; 24 import org.apache.felix.scr.annotations.Service;
27 import org.onlab.util.KryoNamespace; 25 import org.onlab.util.KryoNamespace;
28 import org.onosproject.cluster.ClusterService; 26 import org.onosproject.cluster.ClusterService;
29 -import org.onosproject.cluster.NodeId;
30 import org.onosproject.net.intent.BatchWrite; 27 import org.onosproject.net.intent.BatchWrite;
31 import org.onosproject.net.intent.Intent; 28 import org.onosproject.net.intent.Intent;
32 -import org.onosproject.net.intent.IntentClockService;
33 import org.onosproject.net.intent.IntentEvent; 29 import org.onosproject.net.intent.IntentEvent;
34 import org.onosproject.net.intent.IntentId; 30 import org.onosproject.net.intent.IntentId;
35 import org.onosproject.net.intent.IntentState; 31 import org.onosproject.net.intent.IntentState;
36 import org.onosproject.net.intent.IntentStore; 32 import org.onosproject.net.intent.IntentStore;
37 import org.onosproject.net.intent.IntentStoreDelegate; 33 import org.onosproject.net.intent.IntentStoreDelegate;
38 import org.onosproject.store.AbstractStore; 34 import org.onosproject.store.AbstractStore;
39 -import org.onosproject.store.Timestamp;
40 import org.onosproject.store.cluster.messaging.ClusterCommunicationService; 35 import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
41 -import org.onosproject.store.cluster.messaging.ClusterMessage; 36 +import org.onosproject.store.impl.EventuallyConsistentMap;
42 -import org.onosproject.store.cluster.messaging.ClusterMessageHandler; 37 +import org.onosproject.store.impl.EventuallyConsistentMapEvent;
43 -import org.onosproject.store.cluster.messaging.MessageSubject; 38 +import org.onosproject.store.impl.EventuallyConsistentMapImpl;
44 -import org.onosproject.store.impl.Timestamped; 39 +import org.onosproject.store.impl.EventuallyConsistentMapListener;
45 -import org.onosproject.store.serializers.KryoSerializer; 40 +import org.onosproject.store.impl.WallclockClockManager;
46 -import org.onosproject.store.serializers.impl.DistributedStoreSerializers; 41 +import org.onosproject.store.serializers.KryoNamespaces;
47 import org.slf4j.Logger; 42 import org.slf4j.Logger;
48 43
49 -import java.io.IOException;
50 import java.util.ArrayList; 44 import java.util.ArrayList;
51 import java.util.Collections; 45 import java.util.Collections;
52 import java.util.List; 46 import java.util.List;
53 -import java.util.Set;
54 -import java.util.concurrent.ConcurrentHashMap;
55 -import java.util.concurrent.ConcurrentMap;
56 -import java.util.concurrent.ExecutorService;
57 -import java.util.concurrent.Executors;
58 -import java.util.concurrent.ScheduledExecutorService;
59 -import java.util.concurrent.TimeUnit;
60 47
61 import static com.google.common.base.Preconditions.checkArgument; 48 import static com.google.common.base.Preconditions.checkArgument;
62 -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
63 -import static org.onlab.util.Tools.minPriority;
64 -import static org.onlab.util.Tools.namedThreads;
65 import static org.onosproject.net.intent.IntentState.INSTALL_REQ; 49 import static org.onosproject.net.intent.IntentState.INSTALL_REQ;
66 -import static org.onosproject.store.intent.impl.GossipIntentStoreMessageSubjects.INTENT_ANTI_ENTROPY_ADVERTISEMENT;
67 -import static org.onosproject.store.intent.impl.GossipIntentStoreMessageSubjects.INTENT_SET_INSTALLABLES_MSG;
68 -import static org.onosproject.store.intent.impl.GossipIntentStoreMessageSubjects.INTENT_UPDATED_MSG;
69 import static org.slf4j.LoggerFactory.getLogger; 50 import static org.slf4j.LoggerFactory.getLogger;
70 51
71 /** 52 /**
...@@ -80,20 +61,11 @@ public class GossipIntentStore ...@@ -80,20 +61,11 @@ public class GossipIntentStore
80 61
81 private final Logger log = getLogger(getClass()); 62 private final Logger log = getLogger(getClass());
82 63
83 - private final ConcurrentMap<IntentId, Intent> intents = 64 + private EventuallyConsistentMap<IntentId, Intent> intents;
84 - new ConcurrentHashMap<>();
85 65
86 - private final ConcurrentMap<IntentId, Timestamped<IntentState>> intentStates 66 + private EventuallyConsistentMap<IntentId, IntentState> intentStates;
87 - = new ConcurrentHashMap<>();
88 67
89 - private final Set<IntentId> withdrawRequestedIntents 68 + private EventuallyConsistentMap<IntentId, List<Intent>> installables;
90 - = Sets.newConcurrentHashSet();
91 -
92 - private ConcurrentMap<IntentId, Timestamped<List<Intent>>> installables
93 - = new ConcurrentHashMap<>();
94 -
95 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 - protected IntentClockService intentClockService;
97 69
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected ClusterCommunicationService clusterCommunicator; 71 protected ClusterCommunicationService clusterCommunicator;
...@@ -101,64 +73,39 @@ public class GossipIntentStore ...@@ -101,64 +73,39 @@ public class GossipIntentStore
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected ClusterService clusterService; 74 protected ClusterService clusterService;
103 75
104 - private static final KryoSerializer SERIALIZER = new KryoSerializer() {
105 - @Override
106 - protected void setupKryoPool() {
107 - serializerPool = KryoNamespace.newBuilder()
108 - .register(DistributedStoreSerializers.STORE_COMMON)
109 - .nextId(DistributedStoreSerializers.STORE_CUSTOM_BEGIN)
110 - .register(InternalIntentEvent.class)
111 - .register(InternalSetInstallablesEvent.class)
112 - .register(Collections.emptyList().getClass())
113 - //.register(InternalIntentAntiEntropyEvent.class)
114 - //.register(IntentAntiEntropyAdvertisement.class)
115 - .build();
116 - }
117 - };
118 -
119 - private ExecutorService executor;
120 -
121 - private ScheduledExecutorService backgroundExecutor;
122 -
123 - // TODO: Make these anti-entropy params configurable
124 - private long initialDelaySec = 5;
125 - private long periodSec = 5;
126 -
127 @Activate 76 @Activate
128 public void activate() { 77 public void activate() {
129 - clusterCommunicator.addSubscriber(INTENT_UPDATED_MSG, 78 + KryoNamespace.Builder intentSerializer = KryoNamespace.newBuilder()
130 - new InternalIntentCreateOrUpdateEventListener()); 79 + .register(KryoNamespaces.API)
131 - clusterCommunicator.addSubscriber(INTENT_SET_INSTALLABLES_MSG, 80 + // TODO this should be in BASIC namespace
132 - new InternalIntentSetInstallablesListener()); 81 + .register(Collections.emptyList().getClass());
133 - clusterCommunicator.addSubscriber( 82 + intents = new EventuallyConsistentMapImpl<>("intents", clusterService,
134 - INTENT_ANTI_ENTROPY_ADVERTISEMENT, 83 + clusterCommunicator,
135 - new InternalIntentAntiEntropyAdvertisementListener()); 84 + intentSerializer,
136 - 85 + new WallclockClockManager<>());
137 - executor = Executors.newCachedThreadPool(namedThreads("onos-intent-fg-%d")); 86 +
138 - 87 + intentStates = new EventuallyConsistentMapImpl<>("intent-states",
139 - backgroundExecutor = 88 + clusterService,
140 - newSingleThreadScheduledExecutor(minPriority(namedThreads("onos-intent-bg-%d"))); 89 + clusterCommunicator,
141 - 90 + intentSerializer,
142 - // start anti-entropy thread 91 + new WallclockClockManager<>());
143 - //backgroundExecutor.scheduleAtFixedRate(new SendAdvertisementTask(), 92 +
144 - //initialDelaySec, periodSec, TimeUnit.SECONDS); 93 + installables = new EventuallyConsistentMapImpl<>("intent-installables",
94 + clusterService,
95 + clusterCommunicator,
96 + intentSerializer,
97 + new WallclockClockManager<>());
98 +
99 + intentStates.addListener(new InternalIntentStatesListener());
145 100
146 log.info("Started"); 101 log.info("Started");
147 } 102 }
148 103
149 @Deactivate 104 @Deactivate
150 public void deactivate() { 105 public void deactivate() {
151 - executor.shutdownNow(); 106 + intents.destroy();
152 - backgroundExecutor.shutdownNow(); 107 + intentStates.destroy();
153 - try { 108 + installables.destroy();
154 - if (!backgroundExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
155 - log.error("Timeout during executor shutdown");
156 - }
157 - } catch (InterruptedException e) {
158 - log.error("Error during executor shutdown", e);
159 - }
160 -
161 - intents.clear();
162 109
163 log.info("Stopped"); 110 log.info("Stopped");
164 } 111 }
...@@ -181,76 +128,19 @@ public class GossipIntentStore ...@@ -181,76 +128,19 @@ public class GossipIntentStore
181 128
182 @Override 129 @Override
183 public IntentState getIntentState(IntentId intentId) { 130 public IntentState getIntentState(IntentId intentId) {
184 - Timestamped<IntentState> state = intentStates.get(intentId); 131 + return intentStates.get(intentId);
185 - if (state != null) {
186 - return state.value();
187 - }
188 - return null;
189 - }
190 -
191 - private IntentEvent setStateInternal(IntentId intentId, IntentState newState, Timestamp timestamp) {
192 - switch (newState) {
193 - case WITHDRAW_REQ:
194 - withdrawRequestedIntents.add(intentId);
195 - break;
196 - case INSTALL_REQ:
197 - case COMPILING:
198 - case INSTALLING:
199 - case INSTALLED:
200 - case RECOMPILING:
201 - case WITHDRAWING:
202 - case WITHDRAWN:
203 - case FAILED:
204 - synchronized (intentStates) {
205 - Timestamped<IntentState> existing = intentStates.get(intentId);
206 - if (existing == null || !existing.isNewer(timestamp)) {
207 - intentStates.put(intentId, new Timestamped<>(newState, timestamp));
208 - }
209 - }
210 - break;
211 - default:
212 - log.warn("Unknown intent state {}", newState);
213 - break;
214 - }
215 -
216 - try {
217 - // TODO make sure it's OK if the intent is null
218 - return IntentEvent.getEvent(newState, intents.get(intentId));
219 - } catch (IllegalArgumentException e) {
220 - // Transient states can't be used for events, so don't send one
221 - return null;
222 - }
223 - }
224 -
225 - private void setInstallableIntentsInternal(IntentId intentId,
226 - List<Intent> installableIntents,
227 - Timestamp timestamp) {
228 - synchronized (installables) {
229 - Timestamped<List<Intent>> existing = installables.get(intentId);
230 - if (existing == null || !existing.isNewer(timestamp)) {
231 - installables.put(intentId,
232 - new Timestamped<>(installableIntents, timestamp));
233 - }
234 - }
235 } 132 }
236 133
237 @Override 134 @Override
238 public List<Intent> getInstallableIntents(IntentId intentId) { 135 public List<Intent> getInstallableIntents(IntentId intentId) {
239 - Timestamped<List<Intent>> tInstallables = installables.get(intentId); 136 + return installables.get(intentId);
240 - if (tInstallables != null) {
241 - return tInstallables.value();
242 - }
243 - return null;
244 } 137 }
245 138
246 @Override 139 @Override
247 public List<BatchWrite.Operation> batchWrite(BatchWrite batch) { 140 public List<BatchWrite.Operation> batchWrite(BatchWrite batch) {
248 141
249 - List<IntentEvent> events = Lists.newArrayList();
250 List<BatchWrite.Operation> failed = new ArrayList<>(); 142 List<BatchWrite.Operation> failed = new ArrayList<>();
251 143
252 - Timestamp timestamp = null;
253 -
254 for (BatchWrite.Operation op : batch.operations()) { 144 for (BatchWrite.Operation op : batch.operations()) {
255 switch (op.type()) { 145 switch (op.type()) {
256 case CREATE_INTENT: 146 case CREATE_INTENT:
...@@ -258,19 +148,18 @@ public class GossipIntentStore ...@@ -258,19 +148,18 @@ public class GossipIntentStore
258 "CREATE_INTENT takes 1 argument. %s", op); 148 "CREATE_INTENT takes 1 argument. %s", op);
259 Intent intent = op.arg(0); 149 Intent intent = op.arg(0);
260 150
261 - timestamp = intentClockService.getTimestamp(intent.id()); 151 + intents.put(intent.id(), intent);
262 - if (createIntentInternal(intent)) { 152 + intentStates.put(intent.id(), INSTALL_REQ);
263 - events.add(setStateInternal(intent.id(), INSTALL_REQ, timestamp));
264 - notifyPeers(new InternalIntentEvent(intent.id(), intent,
265 - INSTALL_REQ, timestamp));
266 - }
267 153
268 break; 154 break;
269 case REMOVE_INTENT: 155 case REMOVE_INTENT:
270 checkArgument(op.args().size() == 1, 156 checkArgument(op.args().size() == 1,
271 "REMOVE_INTENT takes 1 argument. %s", op); 157 "REMOVE_INTENT takes 1 argument. %s", op);
272 - IntentId intentId = (IntentId) op.arg(0); 158 + IntentId intentId = op.arg(0);
273 - // TODO implement 159 +
160 + intents.remove(intentId);
161 + intentStates.remove(intentId);
162 + installables.remove(intentId);
274 163
275 break; 164 break;
276 case SET_STATE: 165 case SET_STATE:
...@@ -279,10 +168,7 @@ public class GossipIntentStore ...@@ -279,10 +168,7 @@ public class GossipIntentStore
279 intent = op.arg(0); 168 intent = op.arg(0);
280 IntentState newState = op.arg(1); 169 IntentState newState = op.arg(1);
281 170
282 - timestamp = intentClockService.getTimestamp(intent.id()); 171 + intentStates.put(intent.id(), newState);
283 - IntentEvent externalEvent = setStateInternal(intent.id(), newState, timestamp);
284 - events.add(externalEvent);
285 - notifyPeers(new InternalIntentEvent(intent.id(), null, newState, timestamp));
286 172
287 break; 173 break;
288 case SET_INSTALLABLE: 174 case SET_INSTALLABLE:
...@@ -291,18 +177,14 @@ public class GossipIntentStore ...@@ -291,18 +177,14 @@ public class GossipIntentStore
291 intentId = op.arg(0); 177 intentId = op.arg(0);
292 List<Intent> installableIntents = op.arg(1); 178 List<Intent> installableIntents = op.arg(1);
293 179
294 - timestamp = intentClockService.getTimestamp(intentId); 180 + installables.put(intentId, installableIntents);
295 - setInstallableIntentsInternal(
296 - intentId, installableIntents, timestamp);
297 -
298 - notifyPeers(new InternalSetInstallablesEvent(intentId, installableIntents, timestamp));
299 181
300 break; 182 break;
301 case REMOVE_INSTALLED: 183 case REMOVE_INSTALLED:
302 checkArgument(op.args().size() == 1, 184 checkArgument(op.args().size() == 1,
303 "REMOVE_INSTALLED takes 1 argument. %s", op); 185 "REMOVE_INSTALLED takes 1 argument. %s", op);
304 intentId = op.arg(0); 186 intentId = op.arg(0);
305 - // TODO implement 187 + installables.remove(intentId);
306 break; 188 break;
307 default: 189 default:
308 log.warn("Unknown Operation encountered: {}", op); 190 log.warn("Unknown Operation encountered: {}", op);
...@@ -311,121 +193,34 @@ public class GossipIntentStore ...@@ -311,121 +193,34 @@ public class GossipIntentStore
311 } 193 }
312 } 194 }
313 195
314 - notifyDelegate(events);
315 return failed; 196 return failed;
316 } 197 }
317 198
318 - private boolean createIntentInternal(Intent intent) {
319 - Intent oldValue = intents.putIfAbsent(intent.id(), intent);
320 - if (oldValue == null) {
321 - return true;
322 - }
323 -
324 - log.warn("Intent ID {} already in store, throwing new update away",
325 - intent.id());
326 - return false;
327 - }
328 -
329 - private void notifyPeers(InternalIntentEvent event) {
330 - broadcastMessage(INTENT_UPDATED_MSG, event);
331 - }
332 -
333 - private void notifyPeers(InternalSetInstallablesEvent event) {
334 - broadcastMessage(INTENT_SET_INSTALLABLES_MSG, event);
335 - }
336 -
337 - private void broadcastMessage(MessageSubject subject, Object event) {
338 - ClusterMessage message = new ClusterMessage(
339 - clusterService.getLocalNode().id(),
340 - subject,
341 - SERIALIZER.encode(event));
342 - clusterCommunicator.broadcast(message);
343 - }
344 -
345 - private void unicastMessage(NodeId peer,
346 - MessageSubject subject,
347 - Object event) throws IOException {
348 - ClusterMessage message = new ClusterMessage(
349 - clusterService.getLocalNode().id(),
350 - subject,
351 - SERIALIZER.encode(event));
352 - clusterCommunicator.unicast(message, peer);
353 - }
354 -
355 private void notifyDelegateIfNotNull(IntentEvent event) { 199 private void notifyDelegateIfNotNull(IntentEvent event) {
356 if (event != null) { 200 if (event != null) {
357 notifyDelegate(event); 201 notifyDelegate(event);
358 } 202 }
359 } 203 }
360 204
361 - private final class InternalIntentCreateOrUpdateEventListener 205 + private final class InternalIntentStatesListener implements
362 - implements ClusterMessageHandler { 206 + EventuallyConsistentMapListener<IntentId, IntentState> {
363 @Override 207 @Override
364 - public void handle(ClusterMessage message) { 208 + public void event(
365 - 209 + EventuallyConsistentMapEvent<IntentId, IntentState> event) {
366 - log.debug("Received intent update event from peer: {}", message.sender()); 210 + if (event.type() == EventuallyConsistentMapEvent.Type.PUT) {
367 - InternalIntentEvent event = SERIALIZER.decode(message.payload()); 211 + IntentEvent externalEvent;
212 + Intent intent = intents.get(event.key()); // TODO OK if this is null?
368 213
369 - IntentId intentId = event.intentId();
370 - Intent intent = event.intent();
371 - IntentState state = event.state();
372 - Timestamp timestamp = event.timestamp();
373 -
374 - executor.submit(() -> {
375 try { 214 try {
376 - switch (state) { 215 + externalEvent = IntentEvent.getEvent(event.value(), intent);
377 - case INSTALL_REQ: 216 + } catch (IllegalArgumentException e) {
378 - createIntentInternal(intent); 217 + externalEvent = null;
379 - // Fallthrough to setStateInternal for INSTALL_REQ
380 - default:
381 - notifyDelegateIfNotNull(setStateInternal(intentId, state, timestamp));
382 - break;
383 - }
384 - } catch (Exception e) {
385 - log.warn("Exception thrown handling intent create or update", e);
386 } 218 }
387 - });
388 - }
389 - }
390 -
391 - private final class InternalIntentSetInstallablesListener
392 - implements ClusterMessageHandler {
393 - @Override
394 - public void handle(ClusterMessage message) {
395 - log.debug("Received intent set installables event from peer: {}", message.sender());
396 - InternalSetInstallablesEvent event = SERIALIZER.decode(message.payload());
397 -
398 - IntentId intentId = event.intentId();
399 - List<Intent> installables = event.installables();
400 - Timestamp timestamp = event.timestamp();
401 219
402 - executor.submit(() -> { 220 + notifyDelegateIfNotNull(externalEvent);
403 - try { 221 + }
404 - setInstallableIntentsInternal(intentId, installables, timestamp);
405 - } catch (Exception e) {
406 - log.warn("Exception thrown handling intent set installables", e);
407 - }
408 - });
409 } 222 }
410 } 223 }
411 224
412 - private final class InternalIntentAntiEntropyAdvertisementListener
413 - implements ClusterMessageHandler {
414 -
415 - @Override
416 - public void handle(ClusterMessage message) {
417 - log.trace("Received intent Anti-Entropy advertisement from peer: {}", message.sender());
418 - // TODO implement
419 - //IntentAntiEntropyAdvertisement advertisement = SERIALIZER.decode(message.payload());
420 - backgroundExecutor.submit(() -> {
421 - try {
422 - log.debug("something");
423 - //handleAntiEntropyAdvertisement(advertisement);
424 - } catch (Exception e) {
425 - log.warn("Exception thrown handling intent advertisements", e);
426 - }
427 - });
428 - }
429 - }
430 } 225 }
431 226
......