bug 7599 performance improvement for ucast macs
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / transact / HwvtepOperationalState.java
1 /*
2  * Copyright (c) 2015, 2017 China Telecom Beijing Research Institute 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.ovsdb.hwvtepsouthbound.transact;
10
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.Maps;
14 import org.apache.commons.lang3.tuple.Pair;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
17 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
18 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepConnectionInstance;
19 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
20 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundUtil;
21 import org.opendaylight.ovsdb.lib.notation.UUID;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeBase;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalPortAugmentation;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalMcastMacs;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalMcastMacsKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacsKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitchesKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacsKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Switches;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.Tunnels;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelsKey;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
44 import org.opendaylight.yangtools.yang.binding.Identifiable;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 import java.util.Collection;
50 import java.util.Collections;
51 import java.util.HashMap;
52 import java.util.List;
53 import java.util.Map;
54 import java.util.Map.Entry;
55 import java.util.Set;
56 import java.util.concurrent.ConcurrentHashMap;
57
58 //TODO: need to be optimized, get entry by iid not name
59 public class HwvtepOperationalState {
60
61     private static final Logger LOG = LoggerFactory.getLogger(HwvtepOperationalState.class);
62
63     private Map<InstanceIdentifier<Node>, Node> operationalNodes = new HashMap<>();
64     private ReadWriteTransaction transaction;
65     HashMap<InstanceIdentifier<TerminationPoint>, UUID> inflightLocators = Maps.newHashMap();
66     private HwvtepDeviceInfo deviceInfo;
67     private HwvtepConnectionInstance connectionInstance;
68     private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, UUID>> currentTxUUIDs = new ConcurrentHashMap<>();
69     private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, Boolean>> currentTxDeletedKeys = new ConcurrentHashMap<>();
70
71     /* stores the modified and deleted data for each child type of each node id
72        Map<nodeid , Pair < updated, deleted >
73        each updated/ deleted contains Map < child type, List<ChildData>>
74        child type is the child of hwvtep Global augmentation
75      */
76     private Map<InstanceIdentifier<Node>,
77             Pair<Map<Class<? extends Identifiable>, List<Identifiable>>,
78                     Map<Class<? extends Identifiable>, List<Identifiable>>>> modifiedData = new HashMap<>();
79     private boolean inReconciliation = false;
80
81     public HwvtepOperationalState(DataBroker db, HwvtepConnectionInstance connectionInstance,
82                                   Collection<DataTreeModification<Node>> changes) {
83         this.connectionInstance = connectionInstance;
84         this.deviceInfo = connectionInstance.getDeviceInfo();
85         Map<InstanceIdentifier<Node>, Node> nodeCreateOrUpdate =
86             TransactUtils.extractCreatedOrUpdatedOrRemoved(changes, Node.class);
87         if (nodeCreateOrUpdate != null) {
88             transaction = db.newReadWriteTransaction();
89             for (Entry<InstanceIdentifier<Node>, Node> entry: nodeCreateOrUpdate.entrySet()) {
90                 Optional<Node> readNode = HwvtepSouthboundUtil.readNode(transaction, entry.getKey());
91                 //add related globalNode or physicalSwitchNode to operationalNodes map
92                 //for example, when creating physical port, logical switch is needed
93                 //but logical switch is in HwvtepGlobalAugmentation rather than PhysicalSwitchAugmentation
94                 if (readNode.isPresent()) {
95                     operationalNodes.put(entry.getKey(), readNode.get());
96                     HwvtepGlobalAugmentation hgAugmentation = readNode.get().getAugmentation(HwvtepGlobalAugmentation.class);
97                     PhysicalSwitchAugmentation psAugmentation = readNode.get().getAugmentation(PhysicalSwitchAugmentation.class);
98                     if (hgAugmentation != null && hgAugmentation.getSwitches() != null) {
99                         for (Switches pswitch : hgAugmentation.getSwitches()) {
100                             @SuppressWarnings("unchecked")
101                             InstanceIdentifier<Node> psNodeIid = (InstanceIdentifier<Node>) pswitch.getSwitchRef().getValue();
102                             Optional<Node> psNode = HwvtepSouthboundUtil.readNode(transaction, psNodeIid);
103                             if (psNode.isPresent()) {
104                                 operationalNodes.put(psNodeIid, psNode.get());
105                             }
106                         }
107                     }
108                     if (psAugmentation != null) {
109                         @SuppressWarnings("unchecked")
110                         InstanceIdentifier<Node> hgNodeIid = (InstanceIdentifier<Node>) psAugmentation.getManagedBy().getValue();
111                         Optional<Node> hgNode = HwvtepSouthboundUtil.readNode(transaction, hgNodeIid);
112                         if (hgNode.isPresent()) {
113                             operationalNodes.put(hgNodeIid, hgNode.get());
114                         }
115                     }
116                 }
117             }
118         }
119     }
120
121     public HwvtepOperationalState(HwvtepConnectionInstance connectionInstance) {
122         this.connectionInstance = connectionInstance;
123         this.deviceInfo = connectionInstance.getDeviceInfo();
124         transaction = connectionInstance.getDataBroker().newReadWriteTransaction();
125         Optional<Node> readNode = HwvtepSouthboundUtil.readNode(transaction, connectionInstance.getInstanceIdentifier());
126         if (readNode.isPresent()) {
127             operationalNodes.put(connectionInstance.getInstanceIdentifier(), readNode.get());
128         }
129     }
130
131     public Optional<Node> getGlobalNode(InstanceIdentifier<?> iid) {
132         InstanceIdentifier<Node> nodeIid = iid.firstIdentifierOf(Node.class);
133         return Optional.fromNullable(operationalNodes.get(nodeIid));
134     }
135
136     public Optional<HwvtepGlobalAugmentation> getHwvtepGlobalAugmentation(InstanceIdentifier<?> iid) {
137         Preconditions.checkNotNull(iid);
138         Optional<Node> nodeOptional = getGlobalNode(iid);
139         if (nodeOptional.isPresent()) {
140             return Optional.fromNullable(nodeOptional.get().getAugmentation(HwvtepGlobalAugmentation.class));
141         }
142         return Optional.absent();
143     }
144
145     public Optional<PhysicalSwitchAugmentation> getPhysicalSwitchAugmentation(InstanceIdentifier<?> iid) {
146         Preconditions.checkNotNull(iid);
147         Optional<Node> nodeOptional = getGlobalNode(iid);
148         if (nodeOptional.isPresent()) {
149             return Optional.fromNullable(nodeOptional.get().getAugmentation(PhysicalSwitchAugmentation.class));
150         }
151         return Optional.absent();
152     }
153
154     public Optional<List<TerminationPoint>> getTerminationPointList(InstanceIdentifier<?> iid) {
155         Preconditions.checkNotNull(iid);
156         Optional<Node> nodeOptional = getGlobalNode(iid);
157         if (nodeOptional.isPresent() && nodeOptional.get().getTerminationPoint() != null) {
158             return Optional.fromNullable(nodeOptional.get().getTerminationPoint());
159         }
160         return Optional.absent();
161     }
162
163     public Optional<LogicalSwitches> getLogicalSwitches(InstanceIdentifier<?> iid, LogicalSwitchesKey logicalSwitchesKey) {
164         Preconditions.checkNotNull(iid);
165         Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(iid);
166         if (nodeOptional.isPresent()) {
167             HwvtepGlobalAugmentation hgAugmentation = nodeOptional.get();
168             List<LogicalSwitches> lswitchList = null;
169             if (hgAugmentation != null) {
170                 lswitchList = hgAugmentation.getLogicalSwitches();
171             }
172             if (lswitchList != null) {
173                 for (LogicalSwitches lswitch: lswitchList) {
174                     if (lswitch.getKey().equals(logicalSwitchesKey)) {
175                         return Optional.fromNullable(lswitch);
176                     }
177                 }
178             }
179         }
180         return Optional.absent();
181     }
182
183     public Optional<Tunnels> getTunnels(InstanceIdentifier<?> iid, TunnelsKey tunnelsKey) {
184         Preconditions.checkNotNull(iid);
185         Optional<PhysicalSwitchAugmentation> psOptional = getPhysicalSwitchAugmentation(iid);
186         if (psOptional.isPresent()) {
187             PhysicalSwitchAugmentation psAugmentation = psOptional.get();
188             List<Tunnels> tunnelList = null;
189             if (psAugmentation != null) {
190                 tunnelList = psAugmentation.getTunnels();
191             }
192             if (tunnelList != null) {
193                 for (Tunnels tunnel: tunnelList) {
194                     if (tunnel.getKey().equals(tunnelsKey)) {
195                         return Optional.fromNullable(tunnel);
196                     }
197                 }
198             }
199         }
200         return Optional.absent();
201     }
202
203     public Optional<HwvtepPhysicalPortAugmentation> getPhysicalPortAugmentation(InstanceIdentifier<?> iid,
204             HwvtepNodeName hwvtepNodeName) {
205         Preconditions.checkNotNull(iid);
206         Optional<List<TerminationPoint>> nodeOptional = getTerminationPointList(iid);
207         if (nodeOptional.isPresent()) {
208             List<TerminationPoint> tpList = nodeOptional.get();
209             for (TerminationPoint tp : tpList) {
210                 HwvtepPhysicalPortAugmentation hppAugmentation = tp.getAugmentation(HwvtepPhysicalPortAugmentation.class);
211                 if (hppAugmentation != null && hppAugmentation.getHwvtepNodeName().equals(hwvtepNodeName)) {
212                     return Optional.fromNullable(hppAugmentation);
213                 }
214             }
215         }
216         return Optional.absent();
217     }
218
219     public Optional<HwvtepPhysicalLocatorAugmentation> getPhysicalLocatorAugmentation(InstanceIdentifier<?> iid,
220             IpAddress dstIp, Class<? extends EncapsulationTypeBase> encapType) {
221         Preconditions.checkNotNull(iid);
222         Optional<List<TerminationPoint>> nodeOptional = getTerminationPointList(iid);
223         if (nodeOptional.isPresent()) {
224             List<TerminationPoint> tpList = nodeOptional.get();
225             for (TerminationPoint tp : tpList) {
226                 HwvtepPhysicalLocatorAugmentation hppAugmentation = tp.getAugmentation(HwvtepPhysicalLocatorAugmentation.class);
227                 if (hppAugmentation != null && hppAugmentation.getDstIp().equals(dstIp)
228                         && hppAugmentation.getEncapsulationType().equals(encapType)) {
229                     return Optional.fromNullable(hppAugmentation);
230                 }
231             }
232         }
233         return Optional.absent();
234     }
235
236     public Optional<LocalMcastMacs> getLocalMcastMacs(InstanceIdentifier<?> iid, LocalMcastMacsKey key) {
237         Preconditions.checkNotNull(iid);
238         Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(iid);
239         if (nodeOptional.isPresent()) {
240             HwvtepGlobalAugmentation hgAugmentation = nodeOptional.get();
241             List<LocalMcastMacs> macList = null;
242             if (hgAugmentation != null) {
243                 macList = hgAugmentation.getLocalMcastMacs();
244             }
245             if (macList != null) {
246                 for (LocalMcastMacs mac: macList) {
247                     if (mac.getKey().equals(key)) {
248                         return Optional.fromNullable(mac);
249                     }
250                 }
251             }
252         }
253         return Optional.absent();
254     }
255
256     public Optional<RemoteMcastMacs> getRemoteMcastMacs(InstanceIdentifier<?> iid, RemoteMcastMacsKey key) {
257         Preconditions.checkNotNull(iid);
258         Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(iid);
259         if (nodeOptional.isPresent()) {
260             HwvtepGlobalAugmentation hgAugmentation = nodeOptional.get();
261             List<RemoteMcastMacs> macList = null;
262             if (hgAugmentation != null) {
263                 macList = hgAugmentation.getRemoteMcastMacs();
264             }
265             if (macList != null) {
266                 for (RemoteMcastMacs mac: macList) {
267                     if (mac.getKey().equals(key)) {
268                         return Optional.fromNullable(mac);
269                     }
270                 }
271             }
272         }
273         return Optional.absent();
274     }
275
276     public Optional<LocalUcastMacs> getLocalUcastMacs(InstanceIdentifier<?> iid, LocalUcastMacsKey key) {
277         Preconditions.checkNotNull(iid);
278         Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(iid);
279         if (nodeOptional.isPresent()) {
280             HwvtepGlobalAugmentation hgAugmentation = nodeOptional.get();
281             List<LocalUcastMacs> macList = null;
282             if (hgAugmentation != null) {
283                 macList = hgAugmentation.getLocalUcastMacs();
284             }
285             if (macList != null) {
286                 for (LocalUcastMacs mac: macList) {
287                     if (mac.getKey().equals(key)) {
288                         return Optional.fromNullable(mac);
289                     }
290                 }
291             }
292         }
293         return Optional.absent();
294     }
295
296     public Optional<RemoteUcastMacs> getRemoteUcastMacs(InstanceIdentifier<?> iid, RemoteUcastMacsKey key) {
297         Preconditions.checkNotNull(iid);
298         Optional<HwvtepGlobalAugmentation> nodeOptional = getHwvtepGlobalAugmentation(iid);
299         if (nodeOptional.isPresent()) {
300             HwvtepGlobalAugmentation hgAugmentation = nodeOptional.get();
301             List<RemoteUcastMacs> macList = null;
302             if (hgAugmentation != null) {
303                 macList = hgAugmentation.getRemoteUcastMacs();
304             }
305             if (macList != null) {
306                 for (RemoteUcastMacs mac: macList) {
307                     if (mac.getKey().equals(key)) {
308                         return Optional.fromNullable(mac);
309                     }
310                 }
311             }
312         }
313         return Optional.absent();
314     }
315
316     public Optional<HwvtepPhysicalLocatorAugmentation> getPhysicalLocatorAugmentation(InstanceIdentifier<TerminationPoint> iid) {
317         Optional<TerminationPoint> tp = HwvtepSouthboundUtil.readNode(transaction, iid);
318         if (tp.isPresent()) {
319             return Optional.fromNullable(tp.get().getAugmentation(HwvtepPhysicalLocatorAugmentation.class));
320         }
321         return Optional.absent();
322     }
323
324     public Optional<LogicalSwitches> getLogicalSwitches(InstanceIdentifier<LogicalSwitches> iid) {
325         Optional<LogicalSwitches> lswitch = HwvtepSouthboundUtil.readNode(transaction, iid);
326         return lswitch;
327     }
328
329     public Optional<Tunnels> getTunnels(InstanceIdentifier<Tunnels> iid) {
330         Optional<Tunnels> tunnels = HwvtepSouthboundUtil.readNode(transaction, iid);
331         return tunnels;
332     }
333
334     public ReadWriteTransaction getReadWriteTransaction() {
335         return transaction;
336     }
337
338     public void setPhysicalLocatorInFlight(InstanceIdentifier<TerminationPoint> iid,
339                                            UUID uuid) {
340         inflightLocators.put(iid, uuid);
341     }
342
343     public UUID getPhysicalLocatorInFlight(InstanceIdentifier<TerminationPoint> iid) {
344         return inflightLocators.get(iid);
345     }
346
347     public HwvtepConnectionInstance getConnectionInstance() {
348         return connectionInstance;
349     }
350
351     public HwvtepDeviceInfo getDeviceInfo() {
352         return deviceInfo;
353     }
354
355     public void updateCurrentTxData(Class<? extends Identifiable> cls, InstanceIdentifier key, UUID uuid) {
356         HwvtepSouthboundUtil.updateData(currentTxUUIDs, cls, key, uuid);
357     }
358
359     public void updateCurrentTxDeleteData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
360         HwvtepSouthboundUtil.updateData(currentTxDeletedKeys, cls, key, Boolean.TRUE);
361     }
362
363     public UUID getUUIDFromCurrentTx(Class<? extends Identifiable> cls, InstanceIdentifier key) {
364         return HwvtepSouthboundUtil.getData(currentTxUUIDs, cls, key);
365     }
366
367     public boolean isKeyPartOfCurrentTx(Class<? extends Identifiable> cls, InstanceIdentifier key) {
368         return HwvtepSouthboundUtil.containsKey(currentTxUUIDs, cls, key);
369     }
370
371     public Set<InstanceIdentifier> getDeletedKeysInCurrentTx(Class<? extends Identifiable> cls) {
372         if (currentTxDeletedKeys.containsKey(cls)) {
373             return currentTxDeletedKeys.get(cls).keySet();
374         }
375         return Collections.EMPTY_SET;
376     }
377
378     public List<? extends Identifiable> getUpdatedData(final InstanceIdentifier<Node> key,
379                                                        final Class<? extends Identifiable> cls) {
380         List<Identifiable> result = null;
381         if (modifiedData.get(key) != null && modifiedData.get(key).getLeft() != null) {
382             result = modifiedData.get(key).getLeft().get(cls);
383         }
384         if (result == null) {
385             result = Collections.EMPTY_LIST;
386         }
387         return result;
388     }
389
390     public List<? extends Identifiable> getDeletedData(final InstanceIdentifier<Node> key,
391                                                        final Class<? extends Identifiable> cls) {
392         List<Identifiable> result = null;
393         if (modifiedData.get(key) != null && modifiedData.get(key).getRight() != null) {
394             result = modifiedData.get(key).getRight().get(cls);
395         }
396         if (result == null) {
397             result = Collections.EMPTY_LIST;
398         }
399         return result;
400     }
401
402     public void setModifiedData(final Map<InstanceIdentifier<Node>,
403             Pair<Map<Class<? extends Identifiable>, List<Identifiable>>,
404                     Map<Class<? extends Identifiable>, List<Identifiable>>>> modifiedData) {
405         this.modifiedData = modifiedData;
406     }
407
408     public boolean isInReconciliation() {
409         return inReconciliation;
410     }
411
412     public void setInReconciliation(boolean inReconciliation) {
413         this.inReconciliation = inReconciliation;
414     }
415 }