2 * Copyright (c) 2013 Cisco Systems, Inc. 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
8 package org.opendaylight.bgpcep.pcep.tunnel.provider;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.Lists;
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.MoreExecutors;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.List;
22 import java.util.Optional;
24 import java.util.concurrent.ExecutionException;
25 import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
26 import org.opendaylight.mdsal.binding.api.DataBroker;
27 import org.opendaylight.mdsal.binding.api.DataObjectModification;
28 import org.opendaylight.mdsal.binding.api.DataTreeModification;
29 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
30 import org.opendaylight.mdsal.common.api.CommitInfo;
31 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.AdministrativeStatus;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.Path1;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.identifiers.tlv.lsp.identifiers.AddressFamily;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.identifiers.tlv.lsp.identifiers.address.family.Ipv4Case;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.identifiers.tlv.lsp.identifiers.address.family.Ipv6Case;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.identifiers.tlv.lsp.identifiers.address.family.ipv4._case.Ipv4;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.lsp.identifiers.tlv.lsp.identifiers.address.family.ipv6._case.Ipv6;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.Node1;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.pcep.client.attributes.PathComputationClient;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.pcep.client.attributes.path.computation.client.ReportedLsp;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.pcep.client.attributes.path.computation.client.reported.lsp.Path;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev181109.Link1Builder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev181109.SupportingNode1Builder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev181109.tunnel.pcep.supporting.node.attributes.PathComputationClientBuilder;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.LinkId;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.DestinationBuilder;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.SourceBuilder;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkBuilder;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkKey;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
58 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
59 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
60 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
61 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
62 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
63 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNode;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNodeBuilder;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNodeKey;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.TerminationPoint1;
67 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.TerminationPoint1Builder;
68 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.termination.point.attributes.IgpTerminationPointAttributesBuilder;
69 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.termination.point.attributes.igp.termination.point.attributes.TerminationPointType;
70 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.termination.point.attributes.igp.termination.point.attributes.termination.point.type.Ip;
71 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.termination.point.attributes.igp.termination.point.attributes.termination.point.type.IpBuilder;
72 import org.opendaylight.yangtools.yang.binding.DataObject;
73 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
74 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
75 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
79 public final class NodeChangedListener implements ClusteredDataTreeChangeListener<Node> {
80 private static final Logger LOG = LoggerFactory.getLogger(NodeChangedListener.class);
81 private final InstanceIdentifier<Topology> target;
82 private final DataBroker dataProvider;
83 private final TopologyId source;
85 NodeChangedListener(final DataBroker dataProvider, final TopologyId source,
86 final InstanceIdentifier<Topology> target) {
87 this.dataProvider = requireNonNull(dataProvider);
88 this.target = requireNonNull(target);
89 this.source = requireNonNull(source);
92 private static void categorizeIdentifier(final InstanceIdentifier<?> identifier,
93 final Set<InstanceIdentifier<ReportedLsp>> changedLsps,
94 final Set<InstanceIdentifier<Node>> changedNodes) {
95 final InstanceIdentifier<ReportedLsp> li = identifier.firstIdentifierOf(ReportedLsp.class);
97 final InstanceIdentifier<Node> ni = identifier.firstIdentifierOf(Node.class);
99 LOG.warn("Ignoring uncategorized identifier {}", identifier);
101 changedNodes.add(ni);
108 private static void enumerateLsps(final InstanceIdentifier<Node> id, final Node node,
109 final Set<InstanceIdentifier<ReportedLsp>> lsps) {
111 LOG.trace("Skipping null node {}", id);
114 final Node1 pccnode = node.augmentation(Node1.class);
115 if (pccnode == null) {
116 LOG.trace("Skipping non-PCEP-enabled node {}", id);
120 for (final ReportedLsp l : pccnode.getPathComputationClient().nonnullReportedLsp().values()) {
121 lsps.add(id.builder().augmentation(Node1.class).child(PathComputationClient.class)
122 .child(ReportedLsp.class, l.key()).build());
126 private static LinkId linkIdForLsp(final InstanceIdentifier<ReportedLsp> identifier, final ReportedLsp lsp) {
127 return new LinkId(identifier.firstKeyOf(Node.class).getNodeId().getValue() + "/lsps/" + lsp.getName());
130 public static InstanceIdentifier<Link> linkIdentifier(final InstanceIdentifier<Topology> topology,
131 final NodeId node, final String name) {
132 return topology.child(Link.class, new LinkKey(new LinkId(node.getValue() + "/lsp/" + name)));
135 private InstanceIdentifier<Link> linkForLsp(final LinkId linkId) {
136 return this.target.child(Link.class, new LinkKey(linkId));
139 private SupportingNode createSupportingNode(final NodeId sni, final Boolean inControl) {
140 return new SupportingNodeBuilder()
142 .withKey(new SupportingNodeKey(sni, this.source))
143 .addAugmentation(new SupportingNode1Builder().setPathComputationClient(
144 new PathComputationClientBuilder().setControlling(inControl).build()).build())
148 private void handleSni(final InstanceIdentifier<Node> sni, final Node node, final Boolean inControl,
149 final ReadWriteTransaction trans) {
151 final NodeKey k = InstanceIdentifier.keyOf(sni);
152 boolean have = false;
154 * We may have found a termination point which has been created as a destination,
155 * so it does not have a supporting node pointer. Since we now know what it is,
158 for (final SupportingNode sn : node.nonnullSupportingNode().values()) {
159 if (sn.getNodeRef().equals(k.getNodeId())) {
165 final SupportingNode sn = createSupportingNode(k.getNodeId(), inControl);
166 trans.put(LogicalDatastoreType.OPERATIONAL, this.target.child(Node.class, node.key()).child(
167 SupportingNode.class, sn.key()), sn);
172 private InstanceIdentifier<TerminationPoint> getIpTerminationPoint(final ReadWriteTransaction trans,
173 final IpAddress addr, final InstanceIdentifier<Node> sni, final Boolean inControl)
174 throws ExecutionException, InterruptedException {
175 final Topology topo = trans.read(LogicalDatastoreType.OPERATIONAL, this.target).get().get();
176 for (final Node n : topo.nonnullNode().values()) {
177 for (final TerminationPoint tp : n.nonnullTerminationPoint().values()) {
178 final TerminationPoint1 tpa = tp.augmentation(TerminationPoint1.class);
180 final TerminationPointType tpt = tpa.getIgpTerminationPointAttributes()
181 .getTerminationPointType();
182 if (tpt instanceof Ip) {
183 for (final IpAddress address : ((Ip) tpt).getIpAddress()) {
184 if (addr.equals(address)) {
185 handleSni(sni, n, inControl, trans);
186 return this.target.builder().child(Node.class, n.key())
187 .child(TerminationPoint.class, tp.key()).build();
191 LOG.debug("Ignoring termination point type {}", tpt);
196 LOG.debug("Termination point for {} not found, creating a new one", addr);
197 return createTP(addr, sni, inControl, trans);
200 private InstanceIdentifier<TerminationPoint> createTP(final IpAddress addr, final InstanceIdentifier<Node> sni,
201 final Boolean inControl, final ReadWriteTransaction trans) {
202 final String url = "ip://" + addr.toString();
203 final TerminationPointKey tpk = new TerminationPointKey(new TpId(url));
204 final TerminationPointBuilder tpb = new TerminationPointBuilder();
205 tpb.withKey(tpk).setTpId(tpk.getTpId());
206 tpb.addAugmentation(new TerminationPoint1Builder()
207 .setIgpTerminationPointAttributes(new IgpTerminationPointAttributesBuilder()
208 .setTerminationPointType(new IpBuilder().setIpAddress(Lists.newArrayList(addr)).build())
212 final NodeKey nk = new NodeKey(new NodeId(url));
213 final NodeBuilder nb = new NodeBuilder();
214 nb.withKey(nk).setNodeId(nk.getNodeId());
215 nb.setTerminationPoint(BindingMap.of(tpb.build()));
217 nb.setSupportingNode(BindingMap.of(createSupportingNode(InstanceIdentifier.keyOf(sni).getNodeId(),
220 final InstanceIdentifier<Node> nid = this.target.child(Node.class, nb.key());
221 trans.put(LogicalDatastoreType.OPERATIONAL, nid, nb.build());
222 return nid.child(TerminationPoint.class, tpb.key());
225 private void create(final ReadWriteTransaction trans, final InstanceIdentifier<ReportedLsp> identifier,
226 final ReportedLsp value) throws ExecutionException, InterruptedException {
227 final InstanceIdentifier<Node> ni = identifier.firstIdentifierOf(Node.class);
229 final Path1 rl = value.nonnullPath().values().iterator().next().augmentation(Path1.class);
231 final AddressFamily af = rl.getLsp().getTlvs().getLspIdentifiers().getAddressFamily();
234 * We are trying to ensure we have source and destination nodes.
236 final IpAddress srcIp;
237 final IpAddress dstIp;
238 if (af instanceof Ipv4Case) {
239 final Ipv4 ipv4 = ((Ipv4Case) af).getIpv4();
240 srcIp = new IpAddress(ipv4.getIpv4TunnelSenderAddress());
241 dstIp = new IpAddress(ipv4.getIpv4TunnelEndpointAddress());
242 } else if (af instanceof Ipv6Case) {
243 final Ipv6 ipv6 = ((Ipv6Case) af).getIpv6();
244 srcIp = new IpAddress(ipv6.getIpv6TunnelSenderAddress());
245 dstIp = new IpAddress(ipv6.getIpv6TunnelSenderAddress());
247 throw new IllegalArgumentException("Unsupported address family: " + af.implementedInterface());
250 final Path path0 = value.nonnullPath().values().iterator().next();
251 final Link1Builder lab = new Link1Builder();
252 if (path0.getBandwidth() != null) {
253 lab.setBandwidth(path0.getBandwidth().getBandwidth());
255 if (path0.getClassType() != null) {
256 lab.setClassType(path0.getClassType().getClassType());
258 lab.setSymbolicPathName(value.getName());
260 final InstanceIdentifier<TerminationPoint> dst = getIpTerminationPoint(trans, dstIp, null, Boolean.FALSE);
261 final InstanceIdentifier<TerminationPoint> src = getIpTerminationPoint(trans, srcIp, ni,
262 rl.getLsp().getDelegate());
264 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720
265 .Link1Builder slab = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf
266 .stateful.rev200720.Link1Builder();
267 slab.setOperationalStatus(rl.getLsp().getOperational());
268 slab.setAdministrativeStatus(rl.getLsp().getAdministrative() ? AdministrativeStatus.Active :
269 AdministrativeStatus.Inactive);
271 final LinkId id = linkIdForLsp(identifier, value);
272 final LinkBuilder lb = new LinkBuilder();
275 lb.setSource(new SourceBuilder().setSourceNode(src.firstKeyOf(Node.class).getNodeId())
276 .setSourceTp(src.firstKeyOf(TerminationPoint.class).getTpId()).build());
277 lb.setDestination(new DestinationBuilder().setDestNode(dst.firstKeyOf(Node.class).getNodeId())
278 .setDestTp(dst.firstKeyOf(TerminationPoint.class).getTpId()).build());
279 lb.addAugmentation(lab.build());
280 lb.addAugmentation(slab.build());
282 trans.put(LogicalDatastoreType.OPERATIONAL, linkForLsp(id), lb.build());
285 private InstanceIdentifier<TerminationPoint> tpIdentifier(final NodeId node, final TpId tp) {
286 return this.target.builder().child(Node.class, new NodeKey(node)).child(TerminationPoint.class,
287 new TerminationPointKey(tp)).build();
290 private InstanceIdentifier<Node> nodeIdentifier(final NodeId node) {
291 return this.target.child(Node.class, new NodeKey(node));
294 private void remove(final ReadWriteTransaction trans, final InstanceIdentifier<ReportedLsp> identifier,
295 final ReportedLsp value) throws ExecutionException, InterruptedException {
296 final InstanceIdentifier<Link> li = linkForLsp(linkIdForLsp(identifier, value));
298 final Optional<Link> ol = trans.read(LogicalDatastoreType.OPERATIONAL, li).get();
299 if (!ol.isPresent()) {
303 final Link l = ol.get();
304 LOG.debug("Removing link {} (was {})", li, l);
305 trans.delete(LogicalDatastoreType.OPERATIONAL, li);
307 LOG.debug("Searching for orphan links/nodes");
308 final Optional<Topology> ot = trans.read(LogicalDatastoreType.OPERATIONAL, this.target).get();
309 Preconditions.checkState(ot.isPresent());
311 final Topology topology = ot.get();
312 final NodeId srcNode = l.getSource().getSourceNode();
313 final NodeId dstNode = l.getDestination().getDestNode();
314 final TpId srcTp = l.getSource().getSourceTp();
315 final TpId dstTp = l.getDestination().getDestTp();
317 boolean orphSrcNode = true;
318 boolean orphDstNode = true;
319 boolean orphDstTp = true;
320 boolean orphSrcTp = true;
321 for (final Link lw : topology.nonnullLink().values()) {
322 LOG.trace("Checking link {}", lw);
324 final NodeId sn = lw.getSource().getSourceNode();
325 final NodeId dn = lw.getDestination().getDestNode();
326 final TpId st = lw.getSource().getSourceTp();
327 final TpId dt = lw.getDestination().getDestTp();
329 // Source node checks
330 if (srcNode.equals(sn)) {
332 LOG.debug("Node {} held by source of link {}", srcNode, lw);
335 if (orphSrcTp && srcTp.equals(st)) {
336 LOG.debug("TP {} held by source of link {}", srcTp, lw);
340 if (srcNode.equals(dn)) {
342 LOG.debug("Node {} held by destination of link {}", srcNode, lw);
345 if (orphSrcTp && srcTp.equals(dt)) {
346 LOG.debug("TP {} held by destination of link {}", srcTp, lw);
351 // Destination node checks
352 if (dstNode.equals(sn)) {
354 LOG.debug("Node {} held by source of link {}", dstNode, lw);
357 if (orphDstTp && dstTp.equals(st)) {
358 LOG.debug("TP {} held by source of link {}", dstTp, lw);
362 if (dstNode.equals(dn)) {
364 LOG.debug("Node {} held by destination of link {}", dstNode, lw);
367 if (orphDstTp && dstTp.equals(dt)) {
368 LOG.debug("TP {} held by destination of link {}", dstTp, lw);
374 if (orphSrcNode && !orphSrcTp) {
375 LOG.warn("Orphan source node {} but not TP {}, retaining the node", srcNode, srcTp);
378 if (orphDstNode && !orphDstTp) {
379 LOG.warn("Orphan destination node {} but not TP {}, retaining the node", dstNode, dstTp);
384 LOG.debug("Removing orphan node {}", srcNode);
385 trans.delete(LogicalDatastoreType.OPERATIONAL, nodeIdentifier(srcNode));
386 } else if (orphSrcTp) {
387 LOG.debug("Removing orphan TP {} on node {}", srcTp, srcNode);
388 trans.delete(LogicalDatastoreType.OPERATIONAL, tpIdentifier(srcNode, srcTp));
391 LOG.debug("Removing orphan node {}", dstNode);
392 trans.delete(LogicalDatastoreType.OPERATIONAL, nodeIdentifier(dstNode));
393 } else if (orphDstTp) {
394 LOG.debug("Removing orphan TP {} on node {}", dstTp, dstNode);
395 trans.delete(LogicalDatastoreType.OPERATIONAL, tpIdentifier(dstNode, dstTp));
400 public void onDataTreeChanged(final Collection<DataTreeModification<Node>> changes) {
401 final ReadWriteTransaction trans = this.dataProvider.newReadWriteTransaction();
403 final Set<InstanceIdentifier<ReportedLsp>> lsps = new HashSet<>();
404 final Set<InstanceIdentifier<Node>> nodes = new HashSet<>();
406 final Map<InstanceIdentifier<?>, DataObject> original = new HashMap<>();
407 final Map<InstanceIdentifier<?>, DataObject> updated = new HashMap<>();
408 final Map<InstanceIdentifier<?>, DataObject> created = new HashMap<>();
410 for (final DataTreeModification<?> change : changes) {
411 final InstanceIdentifier<?> iid = change.getRootPath().getRootIdentifier();
412 final DataObjectModification<?> rootNode = change.getRootNode();
413 handleChangedNode(rootNode, iid, lsps, nodes, original, updated, created);
416 // Now walk all nodes, check for removals/additions and cascade them to LSPs
417 for (final InstanceIdentifier<Node> iid : nodes) {
418 enumerateLsps(iid, (Node) original.get(iid), lsps);
419 enumerateLsps(iid, (Node) updated.get(iid), lsps);
420 enumerateLsps(iid, (Node) created.get(iid), lsps);
423 // We now have list of all affected LSPs. Walk them create/remove them
424 updateTransaction(trans, lsps, original, updated, created);
426 trans.commit().addCallback(new FutureCallback<CommitInfo>() {
428 public void onSuccess(final CommitInfo result) {
429 LOG.trace("Topology change committed successfully");
433 public void onFailure(final Throwable throwable) {
434 LOG.error("Failed to propagate a topology change, target topology became inconsistent", throwable);
436 }, MoreExecutors.directExecutor());
439 private void handleChangedNode(final DataObjectModification<?> changedNode, final InstanceIdentifier<?> iid,
440 final Set<InstanceIdentifier<ReportedLsp>> lsps, final Set<InstanceIdentifier<Node>> nodes,
441 final Map<InstanceIdentifier<?>, DataObject> original, final Map<InstanceIdentifier<?>, DataObject> updated,
442 final Map<InstanceIdentifier<?>, DataObject> created) {
444 // Categorize reported identifiers
445 categorizeIdentifier(iid, lsps, nodes);
448 switch (changedNode.getModificationType()) {
450 original.put(iid, changedNode.getDataBefore());
452 case SUBTREE_MODIFIED:
453 original.put(iid, changedNode.getDataBefore());
454 updated.put(iid, changedNode.getDataAfter());
457 created.put(iid, changedNode.getDataAfter());
460 throw new IllegalArgumentException("Unhandled modification type " + changedNode.getModificationType());
463 for (DataObjectModification<? extends DataObject> child : changedNode.getModifiedChildren()) {
464 final List<PathArgument> pathArguments = new ArrayList<>();
465 for (PathArgument pathArgument : iid.getPathArguments()) {
466 pathArguments.add(pathArgument);
468 pathArguments.add(child.getIdentifier());
469 final InstanceIdentifier<?> childIID = InstanceIdentifier.create(pathArguments);
470 handleChangedNode(child, childIID, lsps, nodes, original, updated, created);
474 private void updateTransaction(final ReadWriteTransaction trans,
475 final Set<InstanceIdentifier<ReportedLsp>> lsps,
476 final Map<InstanceIdentifier<?>, ? extends DataObject> old,
477 final Map<InstanceIdentifier<?>, DataObject> updated,
478 final Map<InstanceIdentifier<?>, DataObject> created) {
480 for (final InstanceIdentifier<ReportedLsp> i : lsps) {
481 final ReportedLsp oldValue = (ReportedLsp) old.get(i);
482 ReportedLsp newValue = (ReportedLsp) updated.get(i);
483 if (newValue == null) {
484 newValue = (ReportedLsp) created.get(i);
487 LOG.debug("Updating lsp {} value {} -> {}", i, oldValue, newValue);
488 if (oldValue != null) {
490 remove(trans, i, oldValue);
491 } catch (final ExecutionException | InterruptedException e) {
492 LOG.warn("Failed to remove LSP {}", i, e);
495 if (newValue != null) {
497 create(trans, i, newValue);
498 } catch (final ExecutionException | InterruptedException e) {
499 LOG.warn("Failed to add LSP {}", i, e);
505 DataBroker getDataProvider() {