blob: ea9468635cc1244b9e8d09edc2f927ef1a0fd3cd [file] [log] [blame]
Madan Jampanibad538c2015-08-19 17:35:27 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Madan Jampanibad538c2015-08-19 17:35:27 -07003 *
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 */
16package org.onosproject.store.link.impl;
17
Madan Jampanibad538c2015-08-19 17:35:27 -070018import java.util.Collection;
19import java.util.Map;
20import java.util.Objects;
21import java.util.Set;
22import java.util.concurrent.atomic.AtomicReference;
23import java.util.function.Predicate;
24import java.util.stream.Collectors;
25
26import org.apache.felix.scr.annotations.Activate;
27import org.apache.felix.scr.annotations.Component;
28import org.apache.felix.scr.annotations.Deactivate;
29import org.apache.felix.scr.annotations.Reference;
30import org.apache.felix.scr.annotations.ReferenceCardinality;
31import org.apache.felix.scr.annotations.Service;
32import org.onlab.util.KryoNamespace;
33import org.onlab.util.SharedExecutors;
34import org.onosproject.cluster.ClusterService;
35import org.onosproject.cluster.NodeId;
Ray Milkeyb7f0f642016-01-22 16:08:14 -080036import org.onosproject.core.ApplicationId;
37import org.onosproject.core.CoreService;
Madan Jampanibad538c2015-08-19 17:35:27 -070038import org.onosproject.mastership.MastershipService;
39import org.onosproject.net.AnnotationKeys;
40import org.onosproject.net.AnnotationsUtil;
41import org.onosproject.net.ConnectPoint;
42import org.onosproject.net.DefaultAnnotations;
43import org.onosproject.net.DefaultLink;
44import org.onosproject.net.DeviceId;
45import org.onosproject.net.Link;
Madan Jampanibad538c2015-08-19 17:35:27 -070046import org.onosproject.net.Link.Type;
Ray Milkeyb7f0f642016-01-22 16:08:14 -080047import org.onosproject.net.LinkKey;
48import org.onosproject.net.config.ConfigFactory;
49import org.onosproject.net.config.NetworkConfigEvent;
50import org.onosproject.net.config.NetworkConfigListener;
51import org.onosproject.net.config.NetworkConfigRegistry;
Madan Jampanibad538c2015-08-19 17:35:27 -070052import org.onosproject.net.device.DeviceClockService;
53import org.onosproject.net.link.DefaultLinkDescription;
54import org.onosproject.net.link.LinkDescription;
55import org.onosproject.net.link.LinkEvent;
56import org.onosproject.net.link.LinkStore;
57import org.onosproject.net.link.LinkStoreDelegate;
58import org.onosproject.net.provider.ProviderId;
59import org.onosproject.store.AbstractStore;
60import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
61import org.onosproject.store.cluster.messaging.MessageSubject;
62import org.onosproject.store.impl.MastershipBasedTimestamp;
63import org.onosproject.store.serializers.KryoNamespaces;
HIGUCHI Yutae7290652016-05-18 11:29:01 -070064import org.onosproject.store.serializers.StoreSerializer;
Madan Jampanibad538c2015-08-19 17:35:27 -070065import org.onosproject.store.serializers.custom.DistributedStoreSerializers;
66import org.onosproject.store.service.EventuallyConsistentMap;
67import org.onosproject.store.service.EventuallyConsistentMapEvent;
68import org.onosproject.store.service.EventuallyConsistentMapListener;
69import org.onosproject.store.service.StorageService;
70import org.slf4j.Logger;
71
72import com.google.common.collect.Iterables;
73import com.google.common.collect.Maps;
kircaali28d67682016-04-11 15:08:14 +000074import com.google.common.collect.Sets;
Madan Jampanibad538c2015-08-19 17:35:27 -070075import com.google.common.util.concurrent.Futures;
76
Ray Milkeyb7f0f642016-01-22 16:08:14 -080077import static com.google.common.base.Preconditions.checkNotNull;
78import static org.onosproject.net.DefaultAnnotations.merge;
79import static org.onosproject.net.DefaultAnnotations.union;
80import static org.onosproject.net.Link.State.ACTIVE;
81import static org.onosproject.net.Link.State.INACTIVE;
82import static org.onosproject.net.Link.Type.DIRECT;
83import static org.onosproject.net.Link.Type.INDIRECT;
84import static org.onosproject.net.LinkKey.linkKey;
85import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
86import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
87import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED;
88import static org.onosproject.net.link.LinkEvent.Type.LINK_UPDATED;
89import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT;
90import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE;
91import static org.slf4j.LoggerFactory.getLogger;
92
Madan Jampanibad538c2015-08-19 17:35:27 -070093/**
94 * Manages the inventory of links using a {@code EventuallyConsistentMap}.
95 */
Madan Jampani8856ee12015-08-21 09:24:27 -070096@Component(immediate = true, enabled = true)
Madan Jampanibad538c2015-08-19 17:35:27 -070097@Service
98public class ECLinkStore
kircaali28d67682016-04-11 15:08:14 +000099 extends AbstractStore<LinkEvent, LinkStoreDelegate>
100 implements LinkStore {
Madan Jampanibad538c2015-08-19 17:35:27 -0700101
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800102 /**
103 * Modes for dealing with newly discovered links.
104 */
105 protected enum LinkDiscoveryMode {
106 /**
107 * Permissive mode - all newly discovered links are valid.
108 */
109 PERMISSIVE,
110
111 /**
112 * Strict mode - all newly discovered links must be defined in
113 * the network config.
114 */
115 STRICT
116 }
117
Madan Jampanibad538c2015-08-19 17:35:27 -0700118 private final Logger log = getLogger(getClass());
119
120 private final Map<LinkKey, Link> links = Maps.newConcurrentMap();
kircaali28d67682016-04-11 15:08:14 +0000121 private final Map<LinkKey, Set<ProviderId>> linkProviders = Maps.newConcurrentMap();
Madan Jampanibad538c2015-08-19 17:35:27 -0700122 private EventuallyConsistentMap<Provided<LinkKey>, LinkDescription> linkDescriptions;
123
kircaali28d67682016-04-11 15:08:14 +0000124
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800125 private ApplicationId appId;
126
Madan Jampanibad538c2015-08-19 17:35:27 -0700127 private static final MessageSubject LINK_INJECT_MESSAGE = new MessageSubject("inject-link-request");
128
129 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
130 protected StorageService storageService;
131
132 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
133 protected MastershipService mastershipService;
134
135 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
136 protected DeviceClockService deviceClockService;
137
138 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
139 protected ClusterCommunicationService clusterCommunicator;
140
141 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
142 protected ClusterService clusterService;
143
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800144 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
145 protected NetworkConfigRegistry netCfgService;
146
147 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
148 protected CoreService coreService;
149
Madan Jampanibad538c2015-08-19 17:35:27 -0700150 private EventuallyConsistentMapListener<Provided<LinkKey>, LinkDescription> linkTracker =
151 new InternalLinkTracker();
152
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800153 // Listener for config changes
154 private final InternalConfigListener cfgListener = new InternalConfigListener();
155
156 protected LinkDiscoveryMode linkDiscoveryMode = LinkDiscoveryMode.STRICT;
157
HIGUCHI Yutae7290652016-05-18 11:29:01 -0700158 protected static final StoreSerializer SERIALIZER = StoreSerializer.using(
159 KryoNamespace.newBuilder()
Madan Jampanibad538c2015-08-19 17:35:27 -0700160 .register(DistributedStoreSerializers.STORE_COMMON)
161 .nextId(DistributedStoreSerializers.STORE_CUSTOM_BEGIN)
162 .register(Provided.class)
HIGUCHI Yutae7290652016-05-18 11:29:01 -0700163 .build("ECLink"));
Madan Jampanibad538c2015-08-19 17:35:27 -0700164
165 @Activate
166 public void activate() {
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800167 appId = coreService.registerApplication("org.onosproject.core");
168 netCfgService.registerConfigFactory(factory);
169 netCfgService.addListener(cfgListener);
170
171 cfgListener.reconfigure(netCfgService.getConfig(appId, CoreConfig.class));
172
Madan Jampanibad538c2015-08-19 17:35:27 -0700173 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
174 .register(KryoNamespaces.API)
175 .register(MastershipBasedTimestamp.class)
176 .register(Provided.class);
177
178 linkDescriptions = storageService.<Provided<LinkKey>, LinkDescription>eventuallyConsistentMapBuilder()
179 .withName("onos-link-descriptions")
180 .withSerializer(serializer)
181 .withTimestampProvider((k, v) -> {
182 try {
183 return v == null ? null : deviceClockService.getTimestamp(v.dst().deviceId());
184 } catch (IllegalStateException e) {
185 return null;
186 }
187 }).build();
188
189 clusterCommunicator.addSubscriber(LINK_INJECT_MESSAGE,
kircaali28d67682016-04-11 15:08:14 +0000190 SERIALIZER::decode,
191 this::injectLink,
192 SERIALIZER::encode,
193 SharedExecutors.getPoolThreadExecutor());
Madan Jampanibad538c2015-08-19 17:35:27 -0700194
195 linkDescriptions.addListener(linkTracker);
196
197 log.info("Started");
198 }
199
200 @Deactivate
201 public void deactivate() {
202 linkDescriptions.removeListener(linkTracker);
203 linkDescriptions.destroy();
kircaali28d67682016-04-11 15:08:14 +0000204 linkProviders.clear();
Madan Jampanibad538c2015-08-19 17:35:27 -0700205 links.clear();
206 clusterCommunicator.removeSubscriber(LINK_INJECT_MESSAGE);
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800207 netCfgService.removeListener(cfgListener);
208 netCfgService.unregisterConfigFactory(factory);
Madan Jampanibad538c2015-08-19 17:35:27 -0700209
210 log.info("Stopped");
211 }
212
213 @Override
214 public int getLinkCount() {
215 return links.size();
216 }
217
218 @Override
219 public Iterable<Link> getLinks() {
220 return links.values();
221 }
222
223 @Override
224 public Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
225 return filter(links.values(), link -> deviceId.equals(link.src().deviceId()));
226 }
227
228 @Override
229 public Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
230 return filter(links.values(), link -> deviceId.equals(link.dst().deviceId()));
231 }
232
233 @Override
234 public Link getLink(ConnectPoint src, ConnectPoint dst) {
235 return links.get(linkKey(src, dst));
236 }
237
238 @Override
239 public Set<Link> getEgressLinks(ConnectPoint src) {
240 return filter(links.values(), link -> src.equals(link.src()));
241 }
242
243 @Override
244 public Set<Link> getIngressLinks(ConnectPoint dst) {
245 return filter(links.values(), link -> dst.equals(link.dst()));
246 }
247
248 @Override
249 public LinkEvent createOrUpdateLink(ProviderId providerId,
250 LinkDescription linkDescription) {
251 final DeviceId dstDeviceId = linkDescription.dst().deviceId();
252 final NodeId dstNodeId = mastershipService.getMasterFor(dstDeviceId);
253
254 // Process link update only if we're the master of the destination node,
255 // otherwise signal the actual master.
256 if (clusterService.getLocalNode().id().equals(dstNodeId)) {
257 LinkKey linkKey = linkKey(linkDescription.src(), linkDescription.dst());
Ayaka Koshibe2c59acf2015-09-08 15:37:47 -0700258 Provided<LinkKey> internalLinkKey = getProvided(linkKey, providerId);
259 if (internalLinkKey == null) {
260 return null;
261 }
Jian Li68c4fc42016-01-11 16:07:03 -0800262 linkDescriptions.compute(internalLinkKey, (k, v) -> createOrUpdateLinkInternal(v, linkDescription));
Madan Jampanibad538c2015-08-19 17:35:27 -0700263 return refreshLinkCache(linkKey);
264 } else {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800265 // Only forward for ConfigProvider
266 // Forwarding was added as a workaround for ONOS-490
HIGUCHI Yuta4ea4e422016-01-13 16:40:34 -0800267 if (!providerId.scheme().equals("cfg")) {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800268 return null;
269 }
270 // Temporary hack for NPE (ONOS-1171).
271 // Proper fix is to implement forwarding to master on ConfigProvider
Madan Jampanibad538c2015-08-19 17:35:27 -0700272 if (dstNodeId == null) {
273 return null;
274 }
275 return Futures.getUnchecked(clusterCommunicator.sendAndReceive(new Provided<>(linkDescription, providerId),
kircaali28d67682016-04-11 15:08:14 +0000276 LINK_INJECT_MESSAGE,
277 SERIALIZER::encode,
278 SERIALIZER::decode,
279 dstNodeId));
Madan Jampanibad538c2015-08-19 17:35:27 -0700280 }
281 }
282
Ayaka Koshibe2c59acf2015-09-08 15:37:47 -0700283 private Provided<LinkKey> getProvided(LinkKey linkKey, ProviderId provId) {
284 ProviderId bpid = getBaseProviderId(linkKey);
285 if (provId == null) {
286 // The LinkService didn't know who this LinkKey belongs to.
287 // A fix is to either modify the getProvider() in LinkService classes
288 // or expose the contents of linkDescriptions to the LinkService.
289 return (bpid == null) ? null : new Provided<>(linkKey, bpid);
290 } else {
291 return new Provided<>(linkKey, provId);
292 }
293 }
294
Madan Jampanibad538c2015-08-19 17:35:27 -0700295 private LinkDescription createOrUpdateLinkInternal(LinkDescription current, LinkDescription updated) {
296 if (current != null) {
297 // we only allow transition from INDIRECT -> DIRECT
kircaali28d67682016-04-11 15:08:14 +0000298 return new DefaultLinkDescription(
299 current.src(),
300 current.dst(),
301 current.type() == DIRECT ? DIRECT : updated.type(),
302 current.isExpected(),
303 union(current.annotations(), updated.annotations()));
Madan Jampanibad538c2015-08-19 17:35:27 -0700304 }
305 return updated;
306 }
307
kircaali28d67682016-04-11 15:08:14 +0000308 private Set<ProviderId> createOrUpdateLinkProviders(Set<ProviderId> current, ProviderId providerId) {
309 if (current == null) {
310 current = Sets.newConcurrentHashSet();
311 }
312 current.add(providerId);
313 return current;
314 }
315
Madan Jampanibad538c2015-08-19 17:35:27 -0700316 private LinkEvent refreshLinkCache(LinkKey linkKey) {
317 AtomicReference<LinkEvent.Type> eventType = new AtomicReference<>();
318 Link link = links.compute(linkKey, (key, existingLink) -> {
319 Link newLink = composeLink(linkKey);
Madan Jampani11591862016-06-27 13:58:07 -0700320 if (newLink == null) {
321 return null;
322 }
Madan Jampanibad538c2015-08-19 17:35:27 -0700323 if (existingLink == null) {
324 eventType.set(LINK_ADDED);
325 return newLink;
326 } else if (existingLink.state() != newLink.state() ||
kircaali28d67682016-04-11 15:08:14 +0000327 existingLink.isExpected() != newLink.isExpected() ||
328 (existingLink.type() == INDIRECT && newLink.type() == DIRECT) ||
329 !AnnotationsUtil.isEqual(existingLink.annotations(), newLink.annotations())) {
330 eventType.set(LINK_UPDATED);
331 return newLink;
Madan Jampanibad538c2015-08-19 17:35:27 -0700332 } else {
333 return existingLink;
334 }
335 });
336 return eventType.get() != null ? new LinkEvent(eventType.get(), link) : null;
337 }
338
339 private Set<ProviderId> getAllProviders(LinkKey linkKey) {
kircaali28d67682016-04-11 15:08:14 +0000340 return linkProviders.getOrDefault(linkKey, Sets.newConcurrentHashSet());
Madan Jampanibad538c2015-08-19 17:35:27 -0700341 }
342
343 private ProviderId getBaseProviderId(LinkKey linkKey) {
344 Set<ProviderId> allProviders = getAllProviders(linkKey);
345 if (allProviders.size() > 0) {
346 return allProviders.stream()
kircaali28d67682016-04-11 15:08:14 +0000347 .filter(p -> !p.isAncillary())
348 .findFirst()
349 .orElse(Iterables.getFirst(allProviders, null));
Madan Jampanibad538c2015-08-19 17:35:27 -0700350 }
351 return null;
352 }
353
354 private Link composeLink(LinkKey linkKey) {
355
356 ProviderId baseProviderId = checkNotNull(getBaseProviderId(linkKey));
357 LinkDescription base = linkDescriptions.get(new Provided<>(linkKey, baseProviderId));
Madan Jampani11591862016-06-27 13:58:07 -0700358 // short circuit if link description no longer exists
359 if (base == null) {
360 return null;
361 }
Madan Jampanibad538c2015-08-19 17:35:27 -0700362 ConnectPoint src = base.src();
363 ConnectPoint dst = base.dst();
364 Type type = base.type();
365 AtomicReference<DefaultAnnotations> annotations = new AtomicReference<>(DefaultAnnotations.builder().build());
366 annotations.set(merge(annotations.get(), base.annotations()));
367
368 getAllProviders(linkKey).stream()
kircaali28d67682016-04-11 15:08:14 +0000369 .map(p -> new Provided<>(linkKey, p))
370 .forEach(key -> {
371 LinkDescription linkDescription = linkDescriptions.get(key);
372 if (linkDescription != null) {
373 annotations.set(merge(annotations.get(),
374 linkDescription.annotations()));
375 }
376 });
Madan Jampanibad538c2015-08-19 17:35:27 -0700377
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800378 Link.State initialLinkState;
379
380 boolean isExpected;
381 if (linkDiscoveryMode == LinkDiscoveryMode.PERMISSIVE) {
382 initialLinkState = ACTIVE;
383 isExpected =
384 Objects.equals(annotations.get().value(AnnotationKeys.DURABLE), "true");
385 } else {
386 initialLinkState = base.isExpected() ? ACTIVE : INACTIVE;
387 isExpected = base.isExpected();
388 }
389
390
Ray Milkey2693bda2016-01-22 16:08:14 -0800391 return DefaultLink.builder()
392 .providerId(baseProviderId)
393 .src(src)
394 .dst(dst)
395 .type(type)
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800396 .state(initialLinkState)
397 .isExpected(isExpected)
Ray Milkey2693bda2016-01-22 16:08:14 -0800398 .annotations(annotations.get())
399 .build();
Madan Jampanibad538c2015-08-19 17:35:27 -0700400 }
401
402 // Updates, if necessary the specified link and returns the appropriate event.
403 // Guarded by linkDescs value (=locking each Link)
404 private LinkEvent updateLink(LinkKey key, Link oldLink, Link newLink) {
405 // Note: INDIRECT -> DIRECT transition only
406 // so that BDDP discovered Link will not overwrite LDDP Link
407 if (oldLink.state() != newLink.state() ||
kircaali28d67682016-04-11 15:08:14 +0000408 (oldLink.type() == INDIRECT && newLink.type() == DIRECT) ||
409 !AnnotationsUtil.isEqual(oldLink.annotations(), newLink.annotations())) {
Madan Jampanibad538c2015-08-19 17:35:27 -0700410
411 links.put(key, newLink);
412 return new LinkEvent(LINK_UPDATED, newLink);
413 }
414 return null;
415 }
416
417 @Override
418 public LinkEvent removeOrDownLink(ConnectPoint src, ConnectPoint dst) {
419 Link link = getLink(src, dst);
420 if (link == null) {
421 return null;
422 }
423
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800424 if (linkDiscoveryMode == LinkDiscoveryMode.PERMISSIVE && link.isExpected()) {
Madan Jampanibad538c2015-08-19 17:35:27 -0700425 // FIXME: this will not sync link state!!!
426 return link.state() == INACTIVE ? null :
427 updateLink(linkKey(link.src(), link.dst()), link,
Ray Milkey2693bda2016-01-22 16:08:14 -0800428 DefaultLink.builder()
429 .providerId(link.providerId())
430 .src(link.src())
431 .dst(link.dst())
432 .type(link.type())
433 .state(INACTIVE)
434 .isExpected(link.isExpected())
435 .annotations(link.annotations())
436 .build());
Madan Jampanibad538c2015-08-19 17:35:27 -0700437 }
438 return removeLink(src, dst);
439 }
440
441 @Override
442 public LinkEvent removeLink(ConnectPoint src, ConnectPoint dst) {
443 final LinkKey linkKey = LinkKey.linkKey(src, dst);
Madan Jampani5d4396f2015-09-02 16:04:20 -0700444 ProviderId primaryProviderId = getBaseProviderId(linkKey);
445 // Stop if there is no base provider.
446 if (primaryProviderId == null) {
447 return null;
448 }
Madan Jampanibad538c2015-08-19 17:35:27 -0700449 LinkDescription removedLinkDescription =
Madan Jampani5d4396f2015-09-02 16:04:20 -0700450 linkDescriptions.remove(new Provided<>(linkKey, primaryProviderId));
Madan Jampanibad538c2015-08-19 17:35:27 -0700451 if (removedLinkDescription != null) {
452 return purgeLinkCache(linkKey);
453 }
454 return null;
455 }
456
457 private LinkEvent purgeLinkCache(LinkKey linkKey) {
458 Link removedLink = links.remove(linkKey);
459 if (removedLink != null) {
460 getAllProviders(linkKey).forEach(p -> linkDescriptions.remove(new Provided<>(linkKey, p)));
kircaali28d67682016-04-11 15:08:14 +0000461 linkProviders.remove(linkKey);
Madan Jampanibad538c2015-08-19 17:35:27 -0700462 return new LinkEvent(LINK_REMOVED, removedLink);
463 }
464 return null;
465 }
466
467 private Set<Link> filter(Collection<Link> links, Predicate<Link> predicate) {
468 return links.stream().filter(predicate).collect(Collectors.toSet());
469 }
470
471 private LinkEvent injectLink(Provided<LinkDescription> linkInjectRequest) {
472 log.trace("Received request to inject link {}", linkInjectRequest);
473
474 ProviderId providerId = linkInjectRequest.providerId();
475 LinkDescription linkDescription = linkInjectRequest.key();
476
477 final DeviceId deviceId = linkDescription.dst().deviceId();
478 if (!deviceClockService.isTimestampAvailable(deviceId)) {
479 // workaround for ONOS-1208
480 log.warn("Not ready to accept update. Dropping {}", linkInjectRequest);
481 return null;
482 }
483 return createOrUpdateLink(providerId, linkDescription);
484 }
485
486 private class InternalLinkTracker implements EventuallyConsistentMapListener<Provided<LinkKey>, LinkDescription> {
487 @Override
488 public void event(EventuallyConsistentMapEvent<Provided<LinkKey>, LinkDescription> event) {
489 if (event.type() == PUT) {
kircaali28d67682016-04-11 15:08:14 +0000490 linkProviders.compute(event.key().key(), (k, v) ->
491 createOrUpdateLinkProviders(v, event.key().providerId()));
Madan Jampanibad538c2015-08-19 17:35:27 -0700492 notifyDelegate(refreshLinkCache(event.key().key()));
493 } else if (event.type() == REMOVE) {
494 notifyDelegate(purgeLinkCache(event.key().key()));
kircaali28d67682016-04-11 15:08:14 +0000495 linkProviders.remove(event.key().key());
Madan Jampanibad538c2015-08-19 17:35:27 -0700496 }
497 }
498 }
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800499
500 private class InternalConfigListener implements NetworkConfigListener {
501
502 void reconfigure(CoreConfig coreConfig) {
503 if (coreConfig == null) {
504 linkDiscoveryMode = LinkDiscoveryMode.PERMISSIVE;
505 } else {
506 linkDiscoveryMode = coreConfig.linkDiscoveryMode();
507 }
508 if (linkDiscoveryMode == LinkDiscoveryMode.STRICT) {
509 // Remove any previous links to force them to go through the strict
510 // discovery process
Ray Milkey15551272016-02-10 16:22:02 -0800511 if (linkDescriptions != null) {
512 linkDescriptions.clear();
513 }
514 if (links != null) {
515 links.clear();
516 }
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800517 }
518 log.debug("config set link discovery mode to {}",
519 linkDiscoveryMode.name());
520 }
521
522 @Override
523 public void event(NetworkConfigEvent event) {
524
525 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
526 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
527 event.configClass().equals(CoreConfig.class)) {
528
529 CoreConfig cfg = netCfgService.getConfig(appId, CoreConfig.class);
530 reconfigure(cfg);
531 log.info("Reconfigured");
532 }
533 }
534 }
535
536 // Configuration properties factory
537 private final ConfigFactory factory =
538 new ConfigFactory<ApplicationId, CoreConfig>(APP_SUBJECT_FACTORY,
kircaali28d67682016-04-11 15:08:14 +0000539 CoreConfig.class,
540 "core") {
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800541 @Override
542 public CoreConfig createConfig() {
543 return new CoreConfig();
544 }
545 };
Ray Milkeyd0dd1352016-01-19 10:58:41 -0800546}