blob: 7338f15618c3097301266a539ec0c4e0812c7dc7 [file] [log] [blame]
Thomas Vachuskabf916ea2015-05-20 18:24:34 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Thomas Vachuskabf916ea2015-05-20 18:24:34 -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 */
Thomas Vachuskabf916ea2015-05-20 18:24:34 -070016package org.onosproject.incubator.store.tunnel.impl;
jccd8697232015-05-05 14:42:23 +080017
Ray Milkeyd84f89b2018-08-17 14:54:17 -070018import com.google.common.base.MoreObjects;
19import com.google.common.collect.ImmutableSet;
Satish Kd8adcef2016-04-26 16:31:14 +053020import com.google.common.collect.Maps;
jccd8697232015-05-05 14:42:23 +080021import org.onlab.util.KryoNamespace;
22import org.onosproject.cluster.ClusterService;
23import org.onosproject.core.ApplicationId;
24import org.onosproject.core.CoreService;
25import org.onosproject.core.IdGenerator;
Thomas Vachuskabf916ea2015-05-20 18:24:34 -070026import org.onosproject.incubator.net.tunnel.DefaultTunnel;
27import org.onosproject.incubator.net.tunnel.Tunnel;
Avantika-Huawei4c3c9972016-04-05 14:51:46 +053028import org.onosproject.incubator.net.tunnel.Tunnel.State;
Thomas Vachuskabf916ea2015-05-20 18:24:34 -070029import org.onosproject.incubator.net.tunnel.Tunnel.Type;
30import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
31import org.onosproject.incubator.net.tunnel.TunnelEvent;
32import org.onosproject.incubator.net.tunnel.TunnelId;
33import org.onosproject.incubator.net.tunnel.TunnelName;
34import org.onosproject.incubator.net.tunnel.TunnelStore;
35import org.onosproject.incubator.net.tunnel.TunnelStoreDelegate;
36import org.onosproject.incubator.net.tunnel.TunnelSubscription;
samuel7a5691a2015-05-23 00:36:32 +080037import org.onosproject.net.Annotations;
38import org.onosproject.net.DefaultAnnotations;
39import org.onosproject.net.SparseAnnotations;
40import org.onosproject.net.provider.ProviderId;
jccd8697232015-05-05 14:42:23 +080041import org.onosproject.store.AbstractStore;
jccd8697232015-05-05 14:42:23 +080042import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
43import org.onosproject.store.serializers.KryoNamespaces;
44import org.onosproject.store.service.EventuallyConsistentMap;
Satish Kd8adcef2016-04-26 16:31:14 +053045import org.onosproject.store.service.EventuallyConsistentMapEvent;
46import org.onosproject.store.service.EventuallyConsistentMapListener;
jccd8697232015-05-05 14:42:23 +080047import org.onosproject.store.service.MultiValuedTimestamp;
48import org.onosproject.store.service.StorageService;
Madan Jampanibcf1a482015-06-24 19:05:56 -070049import org.onosproject.store.service.WallClockTimestamp;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070050import org.osgi.service.component.annotations.Activate;
51import org.osgi.service.component.annotations.Component;
52import org.osgi.service.component.annotations.Deactivate;
53import org.osgi.service.component.annotations.Reference;
54import org.osgi.service.component.annotations.ReferenceCardinality;
jccd8697232015-05-05 14:42:23 +080055import org.slf4j.Logger;
56
Ray Milkeyd84f89b2018-08-17 14:54:17 -070057import java.util.ArrayList;
58import java.util.Collection;
59import java.util.Collections;
60import java.util.HashSet;
61import java.util.List;
62import java.util.Map;
63import java.util.Objects;
64import java.util.Set;
jccd8697232015-05-05 14:42:23 +080065
Satish Kd8adcef2016-04-26 16:31:14 +053066import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT;
67import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070068import static org.slf4j.LoggerFactory.getLogger;
Satish Kd8adcef2016-04-26 16:31:14 +053069
jccd8697232015-05-05 14:42:23 +080070/**
71 * Manages inventory of tunnel in distributed data store that uses optimistic
72 * replication and gossip based techniques.
73 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070074@Component(immediate = true, service = TunnelStore.class)
jccd8697232015-05-05 14:42:23 +080075public class DistributedTunnelStore
76 extends AbstractStore<TunnelEvent, TunnelStoreDelegate>
77 implements TunnelStore {
78
79 private final Logger log = getLogger(getClass());
80
81 /**
82 * The topic used for obtaining globally unique ids.
83 */
Satish Kfc1a6312016-02-23 13:33:04 +053084 private String tunnelOpTopic = "tunnel-ops-ids";
jccd8697232015-05-05 14:42:23 +080085
Ray Milkeyd84f89b2018-08-17 14:54:17 -070086 @Reference(cardinality = ReferenceCardinality.MANDATORY)
jccd8697232015-05-05 14:42:23 +080087 protected ClusterCommunicationService clusterCommunicator;
88
Ray Milkeyd84f89b2018-08-17 14:54:17 -070089 @Reference(cardinality = ReferenceCardinality.MANDATORY)
jccd8697232015-05-05 14:42:23 +080090 protected ClusterService clusterService;
91
Ray Milkeyd84f89b2018-08-17 14:54:17 -070092 @Reference(cardinality = ReferenceCardinality.MANDATORY)
jccd8697232015-05-05 14:42:23 +080093 protected CoreService coreService;
94
Ray Milkeyd84f89b2018-08-17 14:54:17 -070095 @Reference(cardinality = ReferenceCardinality.MANDATORY)
jccd8697232015-05-05 14:42:23 +080096 protected StorageService storageService;
97
98 // tunnel identity as map key in the store.
99 private EventuallyConsistentMap<TunnelId, Tunnel> tunnelIdAsKeyStore;
jccd8697232015-05-05 14:42:23 +0800100 // maintains records that app subscribes tunnel.
101 private EventuallyConsistentMap<ApplicationId, Set<TunnelSubscription>> orderRelationship;
102
Satish Kd8adcef2016-04-26 16:31:14 +0530103 // tunnel name as map key.
104 private final Map<TunnelName, Set<TunnelId>> tunnelNameAsKeyMap = Maps.newConcurrentMap();
105 // maintains all the tunnels between source and destination.
106 private final Map<TunnelKey, Set<TunnelId>> srcAndDstKeyMap = Maps.newConcurrentMap();
107 // maintains all the tunnels by tunnel type.
108 private final Map<Tunnel.Type, Set<TunnelId>> typeKeyMap = Maps.newConcurrentMap();
109
jccd8697232015-05-05 14:42:23 +0800110 private IdGenerator idGenerator;
111
Satish Kd8adcef2016-04-26 16:31:14 +0530112 private EventuallyConsistentMapListener<TunnelId, Tunnel> tunnelUpdateListener =
113 new InternalTunnelChangeEventListener();
114
jccd8697232015-05-05 14:42:23 +0800115 @Activate
116 public void activate() {
117 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
118 .register(KryoNamespaces.API)
Madan Jampani6c02d9e2016-05-24 15:09:47 -0700119 .register(MultiValuedTimestamp.class);
jccd8697232015-05-05 14:42:23 +0800120 tunnelIdAsKeyStore = storageService
121 .<TunnelId, Tunnel>eventuallyConsistentMapBuilder()
122 .withName("all_tunnel").withSerializer(serializer)
Madan Jampanibcf1a482015-06-24 19:05:56 -0700123 .withTimestampProvider((k, v) -> new WallClockTimestamp()).build();
samuel7a5691a2015-05-23 00:36:32 +0800124 orderRelationship = storageService
125 .<ApplicationId, Set<TunnelSubscription>>eventuallyConsistentMapBuilder()
126 .withName("type_tunnel").withSerializer(serializer)
Madan Jampanibcf1a482015-06-24 19:05:56 -0700127 .withTimestampProvider((k, v) -> new WallClockTimestamp()).build();
Satish Kfc1a6312016-02-23 13:33:04 +0530128 idGenerator = coreService.getIdGenerator(tunnelOpTopic);
Satish Kd8adcef2016-04-26 16:31:14 +0530129 tunnelIdAsKeyStore.addListener(tunnelUpdateListener);
jccd8697232015-05-05 14:42:23 +0800130 log.info("Started");
131 }
132
133 @Deactivate
134 public void deactivate() {
Satish Kd8adcef2016-04-26 16:31:14 +0530135 tunnelIdAsKeyStore.removeListener(tunnelUpdateListener);
Madan Jampani632f16b2015-08-11 12:42:59 -0700136 orderRelationship.destroy();
jccd8697232015-05-05 14:42:23 +0800137 tunnelIdAsKeyStore.destroy();
Satish Kd8adcef2016-04-26 16:31:14 +0530138 srcAndDstKeyMap.clear();
139 typeKeyMap.clear();
140 tunnelNameAsKeyMap.clear();
jccd8697232015-05-05 14:42:23 +0800141 log.info("Stopped");
142 }
143
144 @Override
145 public TunnelId createOrUpdateTunnel(Tunnel tunnel) {
Avantika-Huawei4c3c9972016-04-05 14:51:46 +0530146 return handleCreateOrUpdateTunnel(tunnel, null);
147 }
148
149 @Override
150 public TunnelId createOrUpdateTunnel(Tunnel tunnel, State state) {
151 return handleCreateOrUpdateTunnel(tunnel, state);
152 }
153
154 private TunnelId handleCreateOrUpdateTunnel(Tunnel tunnel, State state) {
jccd8697232015-05-05 14:42:23 +0800155 // tunnelIdAsKeyStore.
Satish Kf1b38bc2015-11-22 17:13:51 +0530156 if (tunnel.tunnelId() != null && !"".equals(tunnel.tunnelId().toString())) {
jccd8697232015-05-05 14:42:23 +0800157 Tunnel old = tunnelIdAsKeyStore.get(tunnel.tunnelId());
158 if (old == null) {
159 log.info("This tunnel[" + tunnel.tunnelId() + "] is not available.");
160 return tunnel.tunnelId();
161 }
samuel7a5691a2015-05-23 00:36:32 +0800162 DefaultAnnotations oldAnno = (DefaultAnnotations) old.annotations();
163 SparseAnnotations newAnno = (SparseAnnotations) tunnel.annotations();
Avantika-Huawei4c3c9972016-04-05 14:51:46 +0530164 State newTunnelState = (state != null) ? state : old.state();
samuel7a5691a2015-05-23 00:36:32 +0800165 Tunnel newT = new DefaultTunnel(old.providerId(), old.src(),
166 old.dst(), old.type(),
Avantika-Huawei4c3c9972016-04-05 14:51:46 +0530167 newTunnelState, old.groupId(),
jccd8697232015-05-05 14:42:23 +0800168 old.tunnelId(),
samuel7a5691a2015-05-23 00:36:32 +0800169 old.tunnelName(),
170 old.path(),
Satish Kd70e9572016-04-28 13:58:51 +0530171 old.resource(),
samuel7a5691a2015-05-23 00:36:32 +0800172 DefaultAnnotations.merge(oldAnno, newAnno));
jccd8697232015-05-05 14:42:23 +0800173 tunnelIdAsKeyStore.put(tunnel.tunnelId(), newT);
Avantika-Huawei4c3c9972016-04-05 14:51:46 +0530174 TunnelEvent event = new TunnelEvent(TunnelEvent.Type.TUNNEL_UPDATED,
jccd8697232015-05-05 14:42:23 +0800175 tunnel);
176 notifyDelegate(event);
177 return tunnel.tunnelId();
178 } else {
Brian Stanke9a108972016-04-11 15:25:17 -0400179 TunnelId tunnelId = TunnelId.valueOf(String.valueOf(idGenerator.getNewId()));
Avantika-Huawei4c3c9972016-04-05 14:51:46 +0530180 State tunnelState = (state != null) ? state : tunnel.state();
jccd8697232015-05-05 14:42:23 +0800181 Tunnel newT = new DefaultTunnel(tunnel.providerId(), tunnel.src(),
182 tunnel.dst(), tunnel.type(),
Avantika-Huawei4c3c9972016-04-05 14:51:46 +0530183 tunnelState, tunnel.groupId(),
jccd8697232015-05-05 14:42:23 +0800184 tunnelId,
185 tunnel.tunnelName(),
samuel7a5691a2015-05-23 00:36:32 +0800186 tunnel.path(),
Satish Kd70e9572016-04-28 13:58:51 +0530187 tunnel.resource(),
jccd8697232015-05-05 14:42:23 +0800188 tunnel.annotations());
jccd8697232015-05-05 14:42:23 +0800189 tunnelIdAsKeyStore.put(tunnelId, newT);
Satish Kd8adcef2016-04-26 16:31:14 +0530190
jccd8697232015-05-05 14:42:23 +0800191 TunnelEvent event = new TunnelEvent(TunnelEvent.Type.TUNNEL_ADDED,
192 tunnel);
193 notifyDelegate(event);
194 return tunnelId;
195 }
196 }
197
198 @Override
199 public void deleteTunnel(TunnelId tunnelId) {
200 Tunnel deletedTunnel = tunnelIdAsKeyStore.get(tunnelId);
201 if (deletedTunnel == null) {
202 return;
203 }
Satish Kd8adcef2016-04-26 16:31:14 +0530204
jccd8697232015-05-05 14:42:23 +0800205 tunnelIdAsKeyStore.remove(tunnelId);
Satish Kd8adcef2016-04-26 16:31:14 +0530206
jccd8697232015-05-05 14:42:23 +0800207 TunnelEvent event = new TunnelEvent(TunnelEvent.Type.TUNNEL_REMOVED,
208 deletedTunnel);
209 notifyDelegate(event);
210 }
211
212 @Override
213 public void deleteTunnel(TunnelEndPoint src, TunnelEndPoint dst,
214 ProviderId producerName) {
215 TunnelKey key = TunnelKey.tunnelKey(src, dst);
Satish Kd8adcef2016-04-26 16:31:14 +0530216 Set<TunnelId> idSet = srcAndDstKeyMap.get(key);
jccd8697232015-05-05 14:42:23 +0800217 if (idSet == null) {
218 return;
219 }
220 Tunnel deletedTunnel = null;
221 TunnelEvent event = null;
222 List<TunnelEvent> ls = new ArrayList<TunnelEvent>();
223 for (TunnelId id : idSet) {
224 deletedTunnel = tunnelIdAsKeyStore.get(id);
Satish Kfc1a6312016-02-23 13:33:04 +0530225
Ray Milkeyfe0e0852018-01-18 11:14:05 -0800226 if (producerName == null || producerName.equals(deletedTunnel.providerId())) {
jccd8697232015-05-05 14:42:23 +0800227 tunnelIdAsKeyStore.remove(deletedTunnel.tunnelId());
Satish Kd8adcef2016-04-26 16:31:14 +0530228
Satish Kfc1a6312016-02-23 13:33:04 +0530229 event = new TunnelEvent(TunnelEvent.Type.TUNNEL_REMOVED,
230 deletedTunnel);
231 ls.add(event);
jccd8697232015-05-05 14:42:23 +0800232 }
233 }
Satish Kfc1a6312016-02-23 13:33:04 +0530234
235 if (!ls.isEmpty()) {
236 notifyDelegate(ls);
237 }
jccd8697232015-05-05 14:42:23 +0800238 }
239
240 @Override
241 public void deleteTunnel(TunnelEndPoint src, TunnelEndPoint dst, Type type,
242 ProviderId producerName) {
243 TunnelKey key = TunnelKey.tunnelKey(src, dst);
Satish Kd8adcef2016-04-26 16:31:14 +0530244 Set<TunnelId> idSet = srcAndDstKeyMap.get(key);
jccd8697232015-05-05 14:42:23 +0800245 if (idSet == null) {
246 return;
247 }
248 Tunnel deletedTunnel = null;
249 TunnelEvent event = null;
250 List<TunnelEvent> ls = new ArrayList<TunnelEvent>();
251 for (TunnelId id : idSet) {
252 deletedTunnel = tunnelIdAsKeyStore.get(id);
Satish Kfc1a6312016-02-23 13:33:04 +0530253
Ray Milkeyfe0e0852018-01-18 11:14:05 -0800254 if (type.equals(deletedTunnel.type()) && (producerName == null ||
255 producerName.equals(deletedTunnel.providerId()))) {
jccd8697232015-05-05 14:42:23 +0800256 tunnelIdAsKeyStore.remove(deletedTunnel.tunnelId());
Satish Kd8adcef2016-04-26 16:31:14 +0530257
Satish Kfc1a6312016-02-23 13:33:04 +0530258 event = new TunnelEvent(TunnelEvent.Type.TUNNEL_REMOVED,
259 deletedTunnel);
260 ls.add(event);
jccd8697232015-05-05 14:42:23 +0800261 }
262 }
Satish Kfc1a6312016-02-23 13:33:04 +0530263
264 if (!ls.isEmpty()) {
265 notifyDelegate(ls);
266 }
jccd8697232015-05-05 14:42:23 +0800267 }
268
269 @Override
270 public Tunnel borrowTunnel(ApplicationId appId, TunnelId tunnelId,
271 Annotations... annotations) {
272 Set<TunnelSubscription> orderSet = orderRelationship.get(appId);
273 if (orderSet == null) {
274 orderSet = new HashSet<TunnelSubscription>();
275 }
276 TunnelSubscription order = new TunnelSubscription(appId, null, null, tunnelId, null, null,
277 annotations);
278 Tunnel result = tunnelIdAsKeyStore.get(tunnelId);
Satish Kd9722352015-11-20 23:19:52 +0530279 if (result == null || Tunnel.State.INACTIVE.equals(result.state())) {
jccd8697232015-05-05 14:42:23 +0800280 return null;
281 }
Satish Kd9722352015-11-20 23:19:52 +0530282
jccd8697232015-05-05 14:42:23 +0800283 orderSet.add(order);
284 orderRelationship.put(appId, orderSet);
285 return result;
286 }
287
288 @Override
289 public Collection<Tunnel> borrowTunnel(ApplicationId appId,
290 TunnelEndPoint src,
291 TunnelEndPoint dst,
292 Annotations... annotations) {
293 Set<TunnelSubscription> orderSet = orderRelationship.get(appId);
294 if (orderSet == null) {
295 orderSet = new HashSet<TunnelSubscription>();
296 }
297 TunnelSubscription order = new TunnelSubscription(appId, src, dst, null, null, null, annotations);
298 boolean isExist = orderSet.contains(order);
299 if (!isExist) {
300 orderSet.add(order);
301 }
302 orderRelationship.put(appId, orderSet);
303 TunnelKey key = TunnelKey.tunnelKey(src, dst);
Satish Kd8adcef2016-04-26 16:31:14 +0530304 Set<TunnelId> idSet = srcAndDstKeyMap.get(key);
Jon Hallcbd1b392017-01-18 20:15:44 -0800305 if (idSet == null || idSet.isEmpty()) {
jccd8697232015-05-05 14:42:23 +0800306 return Collections.emptySet();
307 }
308 Collection<Tunnel> tunnelSet = new HashSet<Tunnel>();
309 for (TunnelId tunnelId : idSet) {
310 Tunnel result = tunnelIdAsKeyStore.get(tunnelId);
311 if (Tunnel.State.ACTIVE.equals(result.state())) {
312 tunnelSet.add(result);
313 }
314 }
315 return tunnelSet;
316 }
317
318 @Override
319 public Collection<Tunnel> borrowTunnel(ApplicationId appId,
320 TunnelEndPoint src,
321 TunnelEndPoint dst, Type type,
322 Annotations... annotations) {
323 Set<TunnelSubscription> orderSet = orderRelationship.get(appId);
324 if (orderSet == null) {
325 orderSet = new HashSet<TunnelSubscription>();
326 }
327 TunnelSubscription order = new TunnelSubscription(appId, src, dst, null, type, null, annotations);
328 boolean isExist = orderSet.contains(order);
329 if (!isExist) {
330 orderSet.add(order);
331 }
332 orderRelationship.put(appId, orderSet);
333 TunnelKey key = TunnelKey.tunnelKey(src, dst);
Satish Kd8adcef2016-04-26 16:31:14 +0530334 Set<TunnelId> idSet = srcAndDstKeyMap.get(key);
Jon Hallcbd1b392017-01-18 20:15:44 -0800335 if (idSet == null || idSet.isEmpty()) {
jccd8697232015-05-05 14:42:23 +0800336 return Collections.emptySet();
337 }
338 Collection<Tunnel> tunnelSet = new HashSet<Tunnel>();
339 for (TunnelId tunnelId : idSet) {
340 Tunnel result = tunnelIdAsKeyStore.get(tunnelId);
341 if (type.equals(result.type())
342 && Tunnel.State.ACTIVE.equals(result.state())) {
343 tunnelSet.add(result);
344 }
345 }
346 return tunnelSet;
347 }
348
349 @Override
350 public Collection<Tunnel> borrowTunnel(ApplicationId appId,
351 TunnelName tunnelName,
352 Annotations... annotations) {
353 Set<TunnelSubscription> orderSet = orderRelationship.get(appId);
354 if (orderSet == null) {
355 orderSet = new HashSet<TunnelSubscription>();
356 }
357 TunnelSubscription order = new TunnelSubscription(appId, null, null, null, null, tunnelName,
358 annotations);
359 boolean isExist = orderSet.contains(order);
Satish Kd8adcef2016-04-26 16:31:14 +0530360
361 Set<TunnelId> idSet = tunnelNameAsKeyMap.get(tunnelName);
Jon Hallcbd1b392017-01-18 20:15:44 -0800362 if (idSet == null || idSet.isEmpty()) {
jccd8697232015-05-05 14:42:23 +0800363 return Collections.emptySet();
364 }
365 Collection<Tunnel> tunnelSet = new HashSet<Tunnel>();
366 for (TunnelId tunnelId : idSet) {
367 Tunnel result = tunnelIdAsKeyStore.get(tunnelId);
368 if (Tunnel.State.ACTIVE.equals(result.state())) {
369 tunnelSet.add(result);
370 }
371 }
Satish Kd8adcef2016-04-26 16:31:14 +0530372
373 if (!tunnelSet.isEmpty() && !isExist) {
374 orderSet.add(order);
375 orderRelationship.put(appId, orderSet);
376 }
377
jccd8697232015-05-05 14:42:23 +0800378 return tunnelSet;
379 }
380
381 @Override
382 public boolean returnTunnel(ApplicationId appId, TunnelName tunnelName,
383 Annotations... annotations) {
384 TunnelSubscription order = new TunnelSubscription(appId, null, null, null, null, tunnelName,
385 annotations);
386 return deleteOrder(order);
387 }
388
389 @Override
390 public boolean returnTunnel(ApplicationId appId, TunnelId tunnelId,
391 Annotations... annotations) {
392 TunnelSubscription order = new TunnelSubscription(appId, null, null, tunnelId, null, null,
393 annotations);
394 return deleteOrder(order);
395 }
396
397 @Override
398 public boolean returnTunnel(ApplicationId appId, TunnelEndPoint src,
399 TunnelEndPoint dst, Type type,
400 Annotations... annotations) {
401 TunnelSubscription order = new TunnelSubscription(appId, src, dst, null, type, null, annotations);
402 return deleteOrder(order);
403 }
404
405 @Override
406 public boolean returnTunnel(ApplicationId appId, TunnelEndPoint src,
407 TunnelEndPoint dst, Annotations... annotations) {
408 TunnelSubscription order = new TunnelSubscription(appId, src, dst, null, null, null, annotations);
409 return deleteOrder(order);
410 }
411
412 private boolean deleteOrder(TunnelSubscription order) {
413 Set<TunnelSubscription> orderSet = orderRelationship.get(order.consumerId());
414 if (orderSet == null) {
415 return true;
416 }
417 if (orderSet.contains(order)) {
418 orderSet.remove(order);
419 return true;
420 }
421 return false;
422 }
423
424 @Override
425 public Tunnel queryTunnel(TunnelId tunnelId) {
426 return tunnelIdAsKeyStore.get(tunnelId);
427 }
428
429 @Override
430 public Collection<TunnelSubscription> queryTunnelSubscription(ApplicationId appId) {
431 return orderRelationship.get(appId) != null ? ImmutableSet.copyOf(orderRelationship
432 .get(appId)) : Collections.emptySet();
433 }
434
435 @Override
436 public Collection<Tunnel> queryTunnel(Type type) {
437 Collection<Tunnel> result = new HashSet<Tunnel>();
Satish Kd8adcef2016-04-26 16:31:14 +0530438 Set<TunnelId> tunnelIds = typeKeyMap.get(type);
jccd8697232015-05-05 14:42:23 +0800439 if (tunnelIds == null) {
440 return Collections.emptySet();
441 }
442 for (TunnelId id : tunnelIds) {
443 result.add(tunnelIdAsKeyStore.get(id));
444 }
Jon Hallcbd1b392017-01-18 20:15:44 -0800445 return result.isEmpty() ? Collections.emptySet() : ImmutableSet
jccd8697232015-05-05 14:42:23 +0800446 .copyOf(result);
447 }
448
449 @Override
450 public Collection<Tunnel> queryTunnel(TunnelEndPoint src, TunnelEndPoint dst) {
451 Collection<Tunnel> result = new HashSet<Tunnel>();
452 TunnelKey key = TunnelKey.tunnelKey(src, dst);
Satish Kd8adcef2016-04-26 16:31:14 +0530453 Set<TunnelId> tunnelIds = srcAndDstKeyMap.get(key);
jccd8697232015-05-05 14:42:23 +0800454 if (tunnelIds == null) {
455 return Collections.emptySet();
456 }
457 for (TunnelId id : tunnelIds) {
458 result.add(tunnelIdAsKeyStore.get(id));
459 }
Jon Hallcbd1b392017-01-18 20:15:44 -0800460 return result.isEmpty() ? Collections.emptySet() : ImmutableSet
jccd8697232015-05-05 14:42:23 +0800461 .copyOf(result);
462 }
463
464 @Override
samuel7a5691a2015-05-23 00:36:32 +0800465 public Collection<Tunnel> queryAllTunnels() {
466 return tunnelIdAsKeyStore.values();
467 }
468
469 @Override
jccd8697232015-05-05 14:42:23 +0800470 public int tunnelCount() {
471 return tunnelIdAsKeyStore.size();
472 }
473
474 /**
475 * Uses source TunnelPoint and destination TunnelPoint as map key.
476 */
477 private static final class TunnelKey {
478 private final TunnelEndPoint src;
479 private final TunnelEndPoint dst;
480
481 private TunnelKey(TunnelEndPoint src, TunnelEndPoint dst) {
482 this.src = src;
483 this.dst = dst;
484
485 }
486
487 /**
488 * create a map key.
489 *
490 * @param src
491 * @param dst
492 * @return a key using source ip and destination ip
493 */
494 static TunnelKey tunnelKey(TunnelEndPoint src, TunnelEndPoint dst) {
495 return new TunnelKey(src, dst);
496 }
497
498 @Override
499 public int hashCode() {
500 return Objects.hash(src, dst);
501 }
502
503 @Override
504 public boolean equals(Object obj) {
505 if (this == obj) {
506 return true;
507 }
508 if (obj instanceof TunnelKey) {
509 final TunnelKey other = (TunnelKey) obj;
510 return Objects.equals(this.src, other.src)
511 && Objects.equals(this.dst, other.dst);
512 }
513 return false;
514 }
515
516 @Override
517 public String toString() {
518 return MoreObjects.toStringHelper(getClass()).add("src", src)
519 .add("dst", dst).toString();
520 }
521 }
Satish Kd8adcef2016-04-26 16:31:14 +0530522
523 /**
524 * Eventually consistent map listener for tunnel change event which updated the local map based on event.
525 */
526 private class InternalTunnelChangeEventListener
527 implements EventuallyConsistentMapListener<TunnelId, Tunnel> {
528 @Override
529 public void event(EventuallyConsistentMapEvent<TunnelId, Tunnel> event) {
530 TunnelId tunnelId = event.key();
531 Tunnel tunnel = event.value();
532
533 if (event.type() == PUT) {
534
535 // Update tunnel name map
536 Set<TunnelId> tunnelNameSet = tunnelNameAsKeyMap.get(tunnel
537 .tunnelName());
538 if (tunnelNameSet == null) {
539 tunnelNameSet = new HashSet<TunnelId>();
540 }
541 tunnelNameSet.add(tunnelId);
542 tunnelNameAsKeyMap.put(tunnel.tunnelName(), tunnelNameSet);
543
544 // Update tunnel source and destination map
545 TunnelKey key = TunnelKey.tunnelKey(tunnel.src(), tunnel.dst());
546 Set<TunnelId> srcAndDstKeySet = srcAndDstKeyMap.get(key);
547 if (srcAndDstKeySet == null) {
548 srcAndDstKeySet = new HashSet<TunnelId>();
549 }
550 srcAndDstKeySet.add(tunnelId);
551 srcAndDstKeyMap.put(key, srcAndDstKeySet);
552
553 // Update tunnel type map
554 Set<TunnelId> typeKeySet = typeKeyMap.get(tunnel.type());
555 if (typeKeySet == null) {
556 typeKeySet = new HashSet<TunnelId>();
557 }
558 typeKeySet.add(tunnelId);
559 typeKeyMap.put(tunnel.type(), typeKeySet);
560 } else if (event.type() == REMOVE) {
561
562 // Update tunnel name map
563 tunnelNameAsKeyMap.get(tunnel.tunnelName()).remove(tunnelId);
564 if (tunnelNameAsKeyMap.get(tunnel.tunnelName()).isEmpty()) {
565 tunnelNameAsKeyMap.remove(tunnel.tunnelName());
566 }
567
568 // Update tunnel source and destination map
569 TunnelKey key = TunnelKey.tunnelKey(tunnel.src(), tunnel.dst());
570 srcAndDstKeyMap.get(key).remove(tunnelId);
571 if (srcAndDstKeyMap.get(key).isEmpty()) {
572 srcAndDstKeyMap.remove(key);
573 }
574
575 // Update tunnel type map
576 typeKeyMap.get(tunnel.type()).remove(tunnelId);
577 if (typeKeyMap.get(tunnel.type()).isEmpty()) {
578 typeKeyMap.remove(tunnel.type());
579 }
580 }
581 }
582 }
jccd8697232015-05-05 14:42:23 +0800583}