2 * Copyright (c) 2016 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
9 package org.opendaylight.bgpcep.bgp.topology.provider.config;
11 import static java.util.Objects.requireNonNull;
13 import java.util.Collection;
14 import java.util.Dictionary;
15 import java.util.HashSet;
16 import java.util.Hashtable;
18 import java.util.stream.Collectors;
19 import javax.annotation.concurrent.GuardedBy;
20 import org.opendaylight.bgpcep.bgp.topology.provider.spi.BgpTopologyDeployer;
21 import org.opendaylight.bgpcep.bgp.topology.provider.spi.BgpTopologyProvider;
22 import org.opendaylight.bgpcep.bgp.topology.provider.spi.TopologyReferenceSingletonService;
23 import org.opendaylight.bgpcep.topology.TopologyReference;
24 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
27 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
28 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
29 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
30 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
31 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
32 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
33 import org.opendaylight.protocol.bgp.rib.spi.util.ClusterSingletonServiceRegistrationHelper;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
36 import org.opendaylight.yangtools.concepts.AbstractRegistration;
37 import org.opendaylight.yangtools.concepts.ListenerRegistration;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.osgi.framework.BundleContext;
40 import org.osgi.framework.ServiceRegistration;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
44 public final class BgpTopologyDeployerImpl implements BgpTopologyDeployer, AutoCloseable,
45 ClusteredDataTreeChangeListener<Topology> {
47 private static final Logger LOG = LoggerFactory.getLogger(BgpTopologyDeployerImpl.class);
48 private static final InstanceIdentifier<Topology> TOPOLOGY_IID =
49 InstanceIdentifier.create(NetworkTopology.class).child(Topology.class);
52 private final Set<BgpTopologyProvider> topologyProviders = new HashSet<>();
53 private final DataBroker dataBroker;
54 private final BundleContext context;
55 private final ClusterSingletonServiceProvider singletonProvider;
56 private ListenerRegistration<BgpTopologyDeployerImpl> registration;
58 private boolean closed;
60 public BgpTopologyDeployerImpl(final BundleContext context, final DataBroker dataBroker,
61 final ClusterSingletonServiceProvider singletonProvider) {
62 this.context = requireNonNull(context);
63 this.dataBroker = requireNonNull(dataBroker);
64 this.singletonProvider = requireNonNull(singletonProvider);
68 this.registration = this.dataBroker.registerDataTreeChangeListener(
69 new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, TOPOLOGY_IID), this);
70 LOG.info("BGP topology deployer started.");
74 public synchronized void onDataTreeChanged(final Collection<DataTreeModification<Topology>> changes) {
76 LOG.trace("BGP Topology Provider Deployer was already closed, skipping changes.");
79 for (final DataTreeModification<Topology> change : changes) {
80 final DataObjectModification<Topology> rootNode = change.getRootNode();
81 final Topology dataBefore = rootNode.getDataBefore();
82 final Topology dataAfter = rootNode.getDataAfter();
83 LOG.trace("BGP topology deployer configuration changed: modification type: [{}]," +
84 " data before:[{}], data after: [{}]", rootNode.getModificationType(), dataBefore, dataAfter);
85 switch (rootNode.getModificationType()) {
87 filterTopologyBuilders(dataBefore)
88 .forEach(provider -> provider.onTopologyBuilderRemoved(dataBefore));
90 case SUBTREE_MODIFIED:
91 filterTopologyBuilders(dataBefore).forEach(provider
92 -> provider.onTopologyBuilderRemoved(dataBefore));
93 filterTopologyBuilders(dataAfter).forEach(provider
94 -> provider.onTopologyBuilderCreated(dataAfter));
97 filterTopologyBuilders(dataAfter).forEach(provider
98 -> provider.onTopologyBuilderCreated(dataAfter));
107 public synchronized AbstractRegistration registerTopologyProvider(final BgpTopologyProvider topologyBuilder) {
108 this.topologyProviders.add(topologyBuilder);
109 return new AbstractRegistration() {
111 protected void removeRegistration() {
112 synchronized (BgpTopologyDeployerImpl.this) {
113 BgpTopologyDeployerImpl.this.topologyProviders.remove(topologyBuilder);
120 public DataBroker getDataBroker() {
121 return this.dataBroker;
125 public AbstractRegistration registerService(final TopologyReferenceSingletonService topologyProviderService) {
126 final Dictionary<String, String> properties = new Hashtable<>();
127 properties.put("topology-id", topologyProviderService.getInstanceIdentifier()
128 .firstKeyOf(Topology.class).getTopologyId().getValue());
129 final ServiceRegistration<?> registerService = this.context
130 .registerService(new String[]{TopologyReference.class.getName()},
131 topologyProviderService, properties);
132 final ClusterSingletonServiceRegistration registerClusterSingletonService =
133 registerSingletonService(topologyProviderService);
134 return new AbstractRegistration() {
136 protected void removeRegistration() {
138 registerClusterSingletonService.close();
139 } catch (final Exception e) {
140 LOG.warn("Failed to close ClusterSingletonServiceRegistration {} for TopologyBuilder {}",
141 registerClusterSingletonService, topologyProviderService.getInstanceIdentifier(), e);
143 registerService.unregister();
149 public synchronized void close() {
150 if (this.registration != null) {
151 this.registration.close();
152 this.registration = null;
155 LOG.info("BGP topology deployer stopped.");
159 private Iterable<BgpTopologyProvider> filterTopologyBuilders(final Topology topology) {
160 return this.topologyProviders.stream().filter(input -> input.topologyTypeFilter(topology))
161 .collect(Collectors.toList());
164 private ClusterSingletonServiceRegistration registerSingletonService(
165 final ClusterSingletonService clusterSingletonService) {
166 return ClusterSingletonServiceRegistrationHelper
167 .registerSingletonService(this.singletonProvider, clusterSingletonService);