Handle nullable lists in vpnmanager
[netvirt.git] / vpnmanager / impl / src / main / java / org / opendaylight / netvirt / vpnmanager / intervpnlink / InterVpnLinkCacheImpl.java
1 /*
2  * Copyright © 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netvirt.vpnmanager.intervpnlink;
10
11 import static org.opendaylight.netvirt.vpnmanager.VpnUtil.requireNonNullElse;
12
13 import com.google.common.base.Optional;
14 import com.google.common.collect.ImmutableList;
15 import java.util.Collections;
16 import java.util.List;
17 import java.util.concurrent.ConcurrentHashMap;
18 import java.util.concurrent.ConcurrentMap;
19 import javax.annotation.Nullable;
20 import javax.annotation.PostConstruct;
21 import javax.inject.Inject;
22 import javax.inject.Singleton;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.genius.mdsalutil.MDSALUtil;
26 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkCache;
27 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinkStates;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinks;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkState;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
32 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 /**
37  * Implementation of InterVpnLinkCache.
38  */
39 @Singleton
40 public class InterVpnLinkCacheImpl implements InterVpnLinkCache {
41     private static final Logger LOG = LoggerFactory.getLogger(InterVpnLinkCacheImpl.class);
42
43     // Cache that maps endpoints with their respective InterVpnLinkComposite
44     private final ConcurrentMap<String, InterVpnLinkDataComposite> endpointToInterVpnLinkCache =
45             new ConcurrentHashMap<>();
46
47     // Cache that maps Vpn UUIDs with their respective InterVpnLinkComposite
48     private final ConcurrentMap<String, InterVpnLinkDataComposite> uuidToInterVpnLinkCache =
49             new ConcurrentHashMap<>();
50
51     // Cache that maps InterVpnLink names with their corresponding InterVpnLinkComposite.
52     private final ConcurrentMap<String, InterVpnLinkDataComposite> nameToInterVpnLinkCache =
53             new ConcurrentHashMap<>();
54
55     private final DataBroker dataBroker;
56
57     @Inject
58     public InterVpnLinkCacheImpl(DataBroker dataBroker) {
59         this.dataBroker = dataBroker;
60     }
61
62     @PostConstruct
63     public void initialFeed() {
64         // Read all InterVpnLinks and InterVpnLinkStates from MD-SAL.
65         InstanceIdentifier<InterVpnLinks> interVpnLinksIid = InstanceIdentifier.builder(InterVpnLinks.class).build();
66
67         Optional<InterVpnLinks> optIVpnLinksOpData =
68                 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, interVpnLinksIid);
69
70         if (!optIVpnLinksOpData.isPresent()) {
71             return; // Nothing to be added to cache
72         }
73         InterVpnLinks interVpnLinks = optIVpnLinksOpData.get();
74         for (InterVpnLink interVpnLink : requireNonNullElse(interVpnLinks.getInterVpnLink(),
75                 Collections.<InterVpnLink>emptyList())) {
76             addInterVpnLinkToCaches(interVpnLink);
77         }
78
79         // Now the States
80         InstanceIdentifier<InterVpnLinkStates> interVpnLinkStateIid =
81                 InstanceIdentifier.builder(InterVpnLinkStates.class).build();
82
83         Optional<InterVpnLinkStates> optIVpnLinkStateOpData =
84                 MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, interVpnLinkStateIid);
85         if (!optIVpnLinkStateOpData.isPresent()) {
86             return;
87         }
88         InterVpnLinkStates interVpnLinkStates = optIVpnLinkStateOpData.get();
89         for (InterVpnLinkState interVpnLinkState : requireNonNullElse(interVpnLinkStates.getInterVpnLinkState(),
90                 Collections.<InterVpnLinkState>emptyList())) {
91             addInterVpnLinkStateToCaches(interVpnLinkState);
92         }
93     }
94
95     @Override
96     public void addInterVpnLinkToCaches(InterVpnLink interVpnLink) {
97
98         String ivlName = interVpnLink.getName();
99         LOG.debug("Adding InterVpnLink {} with vpn1=[id={} endpoint={}] and vpn2=[id={}  endpoint={}] ]",
100                   ivlName, interVpnLink.getFirstEndpoint().getVpnUuid(),
101                 interVpnLink.getFirstEndpoint().getIpAddress(), interVpnLink.getSecondEndpoint().getVpnUuid(),
102                 interVpnLink.getSecondEndpoint().getIpAddress());
103
104         InterVpnLinkDataComposite interVpnLinkDataComposite = getInterVpnLinkByName(ivlName).orNull();
105         if (interVpnLinkDataComposite != null) {
106             interVpnLinkDataComposite.setInterVpnLinkConfig(interVpnLink);
107         } else {
108             interVpnLinkDataComposite = new InterVpnLinkDataComposite(interVpnLink);
109             addToIVpnLinkNameCache(interVpnLinkDataComposite);
110         }
111
112         addToEndpointCache(interVpnLinkDataComposite);
113         addToVpnUuidCache(interVpnLinkDataComposite);
114     }
115
116     @Override
117     public void addInterVpnLinkStateToCaches(InterVpnLinkState interVpnLinkState) {
118
119         String ivlName = interVpnLinkState.getInterVpnLinkName();
120         LOG.debug("Adding InterVpnLinkState {} with vpn1=[{}]  and vpn2=[{}]",
121                   ivlName, interVpnLinkState.getFirstEndpointState(), interVpnLinkState.getSecondEndpointState());
122
123         InterVpnLinkDataComposite ivl = getInterVpnLinkByName(ivlName).orNull();
124         if (ivl != null) {
125             ivl.setInterVpnLinkState(interVpnLinkState);
126         } else {
127             ivl = new InterVpnLinkDataComposite(interVpnLinkState);
128             addToIVpnLinkNameCache(ivl);
129         }
130
131         addToEndpointCache(ivl);
132         addToVpnUuidCache(ivl);
133     }
134
135     private void addToEndpointCache(InterVpnLinkDataComposite interVpnLink) {
136         safePut(endpointToInterVpnLinkCache, interVpnLink.getFirstEndpointIpAddr().orNull(), interVpnLink);
137         safePut(endpointToInterVpnLinkCache, interVpnLink.getSecondEndpointIpAddr().orNull(), interVpnLink);
138     }
139
140     private void addToVpnUuidCache(InterVpnLinkDataComposite interVpnLink) {
141         safePut(uuidToInterVpnLinkCache, interVpnLink.getFirstEndpointVpnUuid().orNull(), interVpnLink);
142         safePut(uuidToInterVpnLinkCache, interVpnLink.getSecondEndpointVpnUuid().orNull(), interVpnLink);
143     }
144
145     private void addToIVpnLinkNameCache(InterVpnLinkDataComposite interVpnLink) {
146         safePut(nameToInterVpnLinkCache, interVpnLink.getInterVpnLinkName(), interVpnLink);
147     }
148
149     @Override
150     public void removeInterVpnLinkFromCache(InterVpnLink interVpnLink) {
151         safeRemove(endpointToInterVpnLinkCache, interVpnLink.getFirstEndpoint().getIpAddress().getValue());
152         safeRemove(endpointToInterVpnLinkCache, interVpnLink.getSecondEndpoint().getIpAddress().getValue());
153
154         safeRemove(uuidToInterVpnLinkCache, interVpnLink.getFirstEndpoint().getVpnUuid().getValue());
155         safeRemove(uuidToInterVpnLinkCache, interVpnLink.getSecondEndpoint().getVpnUuid().getValue());
156     }
157
158
159     @Override
160     public void removeInterVpnLinkStateFromCache(InterVpnLinkState interVpnLinkState) {
161         Optional<InterVpnLinkDataComposite> optIVpnLinkComposite =
162                 getInterVpnLinkByName(interVpnLinkState.getInterVpnLinkName());
163
164         if (optIVpnLinkComposite.isPresent()) {
165             InterVpnLinkDataComposite interVpnLinkComposite = optIVpnLinkComposite.get();
166             removeFromEndpointIpAddressCache(interVpnLinkComposite);
167             removeFromVpnUuidCache(interVpnLinkComposite);
168             removeFromInterVpnLinkNameCache(interVpnLinkComposite);
169         }
170     }
171
172     private void removeFromInterVpnLinkNameCache(InterVpnLinkDataComposite interVpnLinkComposite) {
173         safeRemove(nameToInterVpnLinkCache, interVpnLinkComposite.getInterVpnLinkName());
174     }
175
176
177     private void removeFromVpnUuidCache(InterVpnLinkDataComposite interVpnLinkComposite) {
178         safeRemove(uuidToInterVpnLinkCache, interVpnLinkComposite.getFirstEndpointVpnUuid().orNull());
179         safeRemove(uuidToInterVpnLinkCache, interVpnLinkComposite.getSecondEndpointVpnUuid().orNull());
180     }
181
182
183     private void removeFromEndpointIpAddressCache(InterVpnLinkDataComposite interVpnLinkComposite) {
184         safeRemove(endpointToInterVpnLinkCache, interVpnLinkComposite.getFirstEndpointIpAddr().orNull());
185         safeRemove(endpointToInterVpnLinkCache, interVpnLinkComposite.getSecondEndpointIpAddr().orNull());
186     }
187
188     @Override
189     public Optional<InterVpnLinkDataComposite> getInterVpnLinkByName(String interVpnLinkName) {
190         return Optional.fromNullable(safeGet(nameToInterVpnLinkCache, interVpnLinkName));
191     }
192
193     @Override
194     public Optional<InterVpnLinkDataComposite> getInterVpnLinkByEndpoint(String endpointIp) {
195         LOG.trace("Checking if {} is configured as an InterVpnLink endpoint", endpointIp);
196         return Optional.fromNullable(safeGet(endpointToInterVpnLinkCache, endpointIp));
197     }
198
199     @Override
200     public Optional<InterVpnLinkDataComposite> getInterVpnLinkByVpnId(String vpnId) {
201         return Optional.fromNullable(safeGet(uuidToInterVpnLinkCache, vpnId));
202     }
203
204     @Override
205     public List<InterVpnLinkDataComposite> getAllInterVpnLinks() {
206         return ImmutableList.copyOf(nameToInterVpnLinkCache.values());
207     }
208
209     private <T> void safeRemove(ConcurrentMap<T, ?> fromMap, @Nullable T key) {
210         if (key != null) {
211             fromMap.remove(key);
212         }
213     }
214
215     @Nullable
216     private <K, V> V safeGet(ConcurrentMap<K, V> fromMap, @Nullable K key) {
217         return key != null ? fromMap.get(key) : null;
218     }
219
220     private <K, V> void safePut(ConcurrentMap<K, V> toMap, @Nullable K key, V value) {
221         if (key != null) {
222             toMap.put(key, value);
223         }
224     }
225 }