Remove unnecesary imports
[bgpcep.git] / bgp / topology-provider / src / main / java / org / opendaylight / bgpcep / bgp / topology / provider / config / BgpTopologyDeployerImpl.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. 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.bgpcep.bgp.topology.provider.config;
10
11 import static java.util.Objects.requireNonNull;
12
13 import com.google.common.collect.Iterables;
14 import java.util.Collection;
15 import java.util.Dictionary;
16 import java.util.HashSet;
17 import java.util.Hashtable;
18 import java.util.Set;
19 import java.util.function.Function;
20 import javax.annotation.concurrent.GuardedBy;
21 import org.opendaylight.bgpcep.bgp.topology.provider.spi.BgpTopologyDeployer;
22 import org.opendaylight.bgpcep.bgp.topology.provider.spi.BgpTopologyProvider;
23 import org.opendaylight.bgpcep.bgp.topology.provider.spi.TopologyReferenceSingletonService;
24 import org.opendaylight.bgpcep.topology.TopologyReference;
25 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
26 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
27 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
28 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
29 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
30 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
31 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
32 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
33 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
34 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
35 import org.opendaylight.protocol.bgp.rib.spi.util.ClusterSingletonServiceRegistrationHelper;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
39 import org.opendaylight.yangtools.concepts.AbstractRegistration;
40 import org.opendaylight.yangtools.concepts.ListenerRegistration;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
43 import org.osgi.framework.BundleContext;
44 import org.osgi.framework.ServiceRegistration;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 public final class BgpTopologyDeployerImpl implements AutoCloseable, ClusteredDataTreeChangeListener<Topology>, BgpTopologyDeployer {
49
50     private static final Logger LOG = LoggerFactory.getLogger(BgpTopologyDeployerImpl.class);
51     private static final InstanceIdentifier<Topology> TOPOLOGY_IID = InstanceIdentifier.create(NetworkTopology.class).child(Topology.class);
52     private static final int MAX_REGISTRATION_ATTEMPTS = 10;
53     private static final int SLEEP_TIME = MAX_REGISTRATION_ATTEMPTS;
54
55     @GuardedBy("this")
56     private final Set<BgpTopologyProvider> topologyProviders = new HashSet<>();
57     private final DataBroker dataBroker;
58     private final ListenerRegistration<BgpTopologyDeployerImpl> registration;
59     private final BundleContext context;
60     private final ClusterSingletonServiceProvider singletonProvider;
61     @GuardedBy("this")
62     private boolean closed;
63
64     public BgpTopologyDeployerImpl(final BundleContext context, final DataBroker dataBroker, final ClusterSingletonServiceProvider singletonProvider) {
65         this.context = requireNonNull(context);
66         this.dataBroker = requireNonNull(dataBroker);
67         this.singletonProvider = requireNonNull(singletonProvider);
68         this.registration =
69             this.dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(NetworkTopology.class).child(Topology.class)), this);
70         LOG.info("BGP topology deployer started.");
71     }
72
73     @Override
74     public synchronized void onDataTreeChanged(final Collection<DataTreeModification<Topology>> changes) {
75         if (this.closed) {
76             LOG.trace("BGP Topology Provider Deployer was already closed, skipping changes.");
77             return;
78         }
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: [{}], data before:[{}], data after: [{}]", rootNode.getModificationType(), dataBefore, dataAfter);
84             switch (rootNode.getModificationType()) {
85             case DELETE:
86                 filterTopologyBuilders(dataBefore).forEach(provider -> provider.onTopologyBuilderRemoved(dataBefore));
87                 break;
88             case SUBTREE_MODIFIED:
89                 filterTopologyBuilders(dataBefore).forEach(provider -> provider.onTopologyBuilderRemoved(dataBefore));
90                 filterTopologyBuilders(dataAfter).forEach(provider -> provider.onTopologyBuilderCreated(dataAfter, null));
91                 break;
92             case WRITE:
93                 filterTopologyBuilders(dataAfter).forEach(provider -> provider.onTopologyBuilderCreated(dataAfter, null));
94                 break;
95             default:
96                 break;
97             }
98         }
99     }
100
101     @Override
102     public synchronized AbstractRegistration registerTopologyProvider(final BgpTopologyProvider topologyBuilder) {
103         this.topologyProviders.add(topologyBuilder);
104         return new AbstractRegistration() {
105             @Override
106             protected void removeRegistration() {
107                 synchronized (BgpTopologyDeployerImpl.this) {
108                     BgpTopologyDeployerImpl.this.topologyProviders.remove(topologyBuilder);
109                 }
110             }
111         };
112     }
113
114     @Override
115     public DataBroker getDataBroker() {
116         return this.dataBroker;
117     }
118
119     @Override
120     public AbstractRegistration registerService(final TopologyReferenceSingletonService topologyProviderService) {
121         final Dictionary<String, String> properties = new Hashtable<>();
122         properties.put("topology-id", topologyProviderService.getInstanceIdentifier().firstKeyOf(Topology.class).getTopologyId().getValue());
123         final ServiceRegistration<?> registerService = this.context.registerService(new String[]{TopologyReference.class.getName()}, topologyProviderService, properties);
124         final ClusterSingletonServiceRegistration registerClusterSingletonService = registerSingletonService(topologyProviderService);
125         return new AbstractRegistration() {
126             @Override
127             protected void removeRegistration() {
128                 try {
129                     registerClusterSingletonService.close();
130                 } catch (final Exception e) {
131                     LOG.warn("Failed to close ClusterSingletonServiceRegistration {} for TopologyBuilder {}",
132                         registerClusterSingletonService, topologyProviderService.getInstanceIdentifier(), e);
133                 }
134                 registerService.unregister();
135             }
136         };
137     }
138
139     @Override
140     public void createInstance(final Topology topology) {
141         final Function<Topology, Void> writeFunction = topology1 -> {
142             final WriteTransaction wTx = this.dataBroker.newWriteOnlyTransaction();
143             final KeyedInstanceIdentifier<Topology, TopologyKey> topologyIIdKeyed =
144                 InstanceIdentifier.create(NetworkTopology.class).child(Topology.class, topology1.getKey());
145             wTx.put(LogicalDatastoreType.CONFIGURATION, topologyIIdKeyed, topology1, true);
146             wTx.submit();
147             return null;
148         };
149
150         filterTopologyBuilders(topology).forEach(provider -> provider.onTopologyBuilderCreated(topology, writeFunction));
151     }
152
153     @Override
154     public void removeInstance(final Topology topology) {
155         filterTopologyBuilders(topology).forEach(provider -> provider.onTopologyBuilderRemoved(topology));
156     }
157
158     @Override
159     public InstanceIdentifier<Topology> getInstanceIdentifier() {
160         return TOPOLOGY_IID;
161     }
162
163     @Override
164     public synchronized void close() throws Exception {
165         this.registration.close();
166         LOG.info("BGP topology deployer stopped.");
167         this.closed = true;
168     }
169
170     private Iterable<BgpTopologyProvider> filterTopologyBuilders(final Topology topology) {
171         return Iterables.filter(this.topologyProviders, input -> input.topologyTypeFilter(topology));
172     }
173
174     private ClusterSingletonServiceRegistration registerSingletonService(final ClusterSingletonService clusterSingletonService) {
175         return ClusterSingletonServiceRegistrationHelper.registerSingletonService(this.singletonProvider, clusterSingletonService, MAX_REGISTRATION_ATTEMPTS, SLEEP_TIME);
176     }
177
178 }