2 * Copyright (c) 2015, 2017 China Telecom Beijing Research Institute and others. All rights reserved.
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
9 package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
11 import org.apache.commons.lang3.tuple.Pair;
12 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
13 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
14 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
17 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
18 import org.opendaylight.yangtools.yang.binding.DataObject;
19 import org.opendaylight.yangtools.yang.binding.Identifiable;
20 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.HashMap;
27 import java.util.List;
29 import java.util.Objects;
31 public class TransactCommandAggregator implements TransactCommand {
33 private static final Logger LOG = LoggerFactory.getLogger(TransactCommandAggregator.class);
35 private List<TransactCommand> commands = new ArrayList<TransactCommand>();
36 private final HwvtepOperationalState operationalState;
37 /* stores the modified and deleted data for each child type of each node id
38 Map<nodeid , Pair < updated, deleted >
39 each updated/ deleted contains Map < child type, List<ChildData>>
40 child type is the child of hwvtep Global augmentation
42 private final Map<InstanceIdentifier<Node>,
43 Pair<Map<Class<? extends Identifiable>, List<Identifiable>>,
44 Map<Class<? extends Identifiable>, List<Identifiable>>>> modifiedData = new HashMap<>();
47 public TransactCommandAggregator(HwvtepOperationalState state, Collection<DataTreeModification<Node>> changes) {
48 this.operationalState = state;
49 onDataTreeChanged(changes);
50 commands.add(new PhysicalSwitchUpdateCommand(state,changes));
51 commands.add(new PhysicalSwitchRemoveCommand(state,changes));
52 commands.add(new LogicalSwitchUpdateCommand(state,changes));
53 commands.add(new LogicalSwitchRemoveCommand(state,changes));
54 commands.add(new PhysicalPortUpdateCommand(state,changes));
55 commands.add(new PhysicalPortRemoveCommand(state,changes));
56 commands.add(new McastMacsRemoteUpdateCommand(state,changes));
57 commands.add(new McastMacsRemoteRemoveCommand(state,changes));
58 commands.add(new McastMacsLocalUpdateCommand(state,changes));
59 commands.add(new McastMacsLocalRemoveCommand(state,changes));
60 commands.add(new UcastMacsRemoteUpdateCommand(state,changes));
61 commands.add(new UcastMacsRemoteRemoveCommand(state,changes));
62 commands.add(new UcastMacsLocalUpdateCommand(state,changes));
63 commands.add(new UcastMacsLocalRemoveCommand(state,changes));
64 commands.add(new TunnelUpdateCommand(state,changes));
65 commands.add(new TunnelRemoveCommand(state,changes));
69 public void execute(TransactionBuilder transaction) {
70 for (TransactCommand command:commands) {
71 command.execute(transaction);
76 public void onConfigUpdate(TransactionBuilder transaction, InstanceIdentifier nodeIid, Identifiable data,
77 InstanceIdentifier key,
78 Object... extraData) {
82 public void doDeviceTransaction(TransactionBuilder transaction, InstanceIdentifier nodeIid, Identifiable data,
83 InstanceIdentifier key,
84 Object... extraData) {
87 private void onDataTreeChanged(final Collection<DataTreeModification<Node>> changes) {
88 for (DataTreeModification<Node> change : changes) {
89 final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
90 final DataObjectModification<Node> mod = change.getRootNode();
91 final Map<Class<? extends Identifiable>, List<Identifiable>> updatedData = new HashMap<>();
92 final Map<Class<? extends Identifiable>, List<Identifiable>> deletedData = new HashMap<>();
93 extractDataChanged(key, mod, updatedData, deletedData);
94 modifiedData.put(key, Pair.of(updatedData, deletedData));
95 operationalState.setModifiedData(modifiedData);
99 private void extractDataChanged(final InstanceIdentifier<Node> key,
100 final DataObjectModification<Node> mod,
101 final Map<Class<? extends Identifiable>, List<Identifiable>> updatedData,
102 final Map<Class<? extends Identifiable>, List<Identifiable>> deletedData) {
104 extractDataChanged(mod.getModifiedChildren(), updatedData, deletedData);
105 DataObjectModification<HwvtepGlobalAugmentation> aug = mod.getModifiedAugmentation(
106 HwvtepGlobalAugmentation.class);
107 if (aug != null && getModificationType(aug) != null) {
108 extractDataChanged(aug.getModifiedChildren(), updatedData, deletedData);
110 DataObjectModification<PhysicalSwitchAugmentation> psAug = mod.getModifiedAugmentation(
111 PhysicalSwitchAugmentation.class);
112 if (psAug != null && getModificationType(psAug) != null) {
113 extractDataChanged(psAug.getModifiedChildren(), updatedData, deletedData);
117 private void extractDataChanged(final Collection<DataObjectModification<? extends DataObject>> children,
118 final Map<Class<? extends Identifiable>, List<Identifiable>> updatedData,
119 final Map<Class<? extends Identifiable>, List<Identifiable>> deletedData) {
120 if (children == null) {
123 for (DataObjectModification<? extends DataObject> child : children) {
124 DataObjectModification.ModificationType type = getModificationType(child);
128 InstanceIdentifier instanceIdentifier = null;
129 Class<? extends Identifiable> childClass = (Class<? extends Identifiable>) child.getDataType();
130 InstanceIdentifier.PathArgument pathArgument = child.getIdentifier();
133 case SUBTREE_MODIFIED:
134 DataObject dataAfter = child.getDataAfter();
135 if (!(dataAfter instanceof Identifiable)) {
138 DataObject before = child.getDataBefore();
139 if (Objects.equals(dataAfter, before)) {
141 in cluster reboot scenarios,
142 application rewrites the data tx.put( logicalswitchiid, logicalswitch )
143 that time it fires the update again ignoring such updates here
147 Identifiable identifiable = (Identifiable) dataAfter;
148 addToUpdatedData(updatedData, childClass, identifiable);
151 DataObject dataBefore = child.getDataBefore();
152 if (!(dataBefore instanceof Identifiable)) {
155 addToUpdatedData(deletedData, childClass, (Identifiable)dataBefore);
161 private void addToUpdatedData(Map<Class<? extends Identifiable>, List<Identifiable>> updatedData,
162 Class<? extends Identifiable> childClass, Identifiable identifiable) {
163 updatedData.computeIfAbsent(childClass, (cls) -> new ArrayList<>());
164 updatedData.get(childClass).add(identifiable);
167 private DataObjectModification.ModificationType getModificationType(
168 DataObjectModification<? extends DataObject> mod) {
170 return mod.getModificationType();
171 } catch (IllegalStateException e) {
172 //not sure why this getter throws this exception, could be some mdsal bug
173 LOG.warn("Failed to get the modification type for mod {}", mod);