Modified GossipIntentStore to use EventuallyConsistentMaps.
All IntentStore operations are now implemented. ONOS-858 Change-Id: I5081805b61c7e25e28707b90093cae12b5a4374b
Showing
4 changed files
with
80 additions
and
284 deletions
... | @@ -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 | ... | ... |
-
Please register or login to post a comment