Bump upstreams
[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 package org.opendaylight.bgpcep.bgp.topology.provider.config;
9
10 import static java.util.Objects.requireNonNull;
11
12 import java.util.HashSet;
13 import java.util.List;
14 import java.util.Set;
15 import java.util.stream.Collectors;
16 import javax.annotation.PreDestroy;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.checkerframework.checker.lock.qual.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.mdsal.binding.api.ClusteredDataTreeChangeListener;
24 import org.opendaylight.mdsal.binding.api.DataBroker;
25 import org.opendaylight.mdsal.binding.api.DataObjectModification;
26 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
27 import org.opendaylight.mdsal.binding.api.DataTreeModification;
28 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
29 import org.opendaylight.mdsal.singleton.api.ClusterSingletonServiceProvider;
30 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
31 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
32 import org.opendaylight.yangtools.concepts.AbstractRegistration;
33 import org.opendaylight.yangtools.concepts.Registration;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.osgi.service.component.annotations.Activate;
36 import org.osgi.service.component.annotations.Component;
37 import org.osgi.service.component.annotations.Deactivate;
38 import org.osgi.service.component.annotations.Reference;
39 import org.osgi.service.component.annotations.RequireServiceComponentRuntime;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 @Singleton
44 @Component(service = BgpTopologyDeployer.class, immediate = true)
45 @RequireServiceComponentRuntime
46 public final class BgpTopologyDeployerImpl implements BgpTopologyDeployer, AutoCloseable,
47         ClusteredDataTreeChangeListener<Topology> {
48
49     private static final Logger LOG = LoggerFactory.getLogger(BgpTopologyDeployerImpl.class);
50     private static final InstanceIdentifier<Topology> TOPOLOGY_IID =
51             InstanceIdentifier.create(NetworkTopology.class).child(Topology.class);
52
53     @GuardedBy("this")
54     private final Set<BgpTopologyProvider> topologyProviders = new HashSet<>();
55     @GuardedBy("this")
56     private final Set<Topology> topologies = new HashSet<>();
57     private final DataBroker dataBroker;
58     private final ClusterSingletonServiceProvider singletonProvider;
59     private Registration registration;
60     @GuardedBy("this")
61     private boolean closed;
62
63     @Inject
64     @Activate
65     public BgpTopologyDeployerImpl(@Reference final DataBroker dataBroker,
66             @Reference final ClusterSingletonServiceProvider singletonProvider) {
67         this.dataBroker = requireNonNull(dataBroker);
68         this.singletonProvider = requireNonNull(singletonProvider);
69         registration = dataBroker.registerDataTreeChangeListener(
70             DataTreeIdentifier.create(LogicalDatastoreType.CONFIGURATION, TOPOLOGY_IID), this);
71         LOG.info("BGP topology deployer started.");
72     }
73
74     @Override
75     public synchronized void onDataTreeChanged(final List<DataTreeModification<Topology>> changes) {
76         if (closed) {
77             LOG.trace("BGP Topology Provider Deployer was already closed, skipping changes.");
78             return;
79         }
80         for (final DataTreeModification<Topology> change : changes) {
81             final DataObjectModification<Topology> rootNode = change.getRootNode();
82             final Topology dataBefore = rootNode.getDataBefore();
83             final Topology dataAfter = rootNode.getDataAfter();
84             LOG.trace("BGP topology deployer configuration changed: modification type: [{}],"
85                     + " data before:[{}], data after: [{}]", rootNode.getModificationType(), dataBefore, dataAfter);
86             switch (rootNode.getModificationType()) {
87                 case DELETE:
88                     filterTopologyBuilders(dataBefore)
89                             .forEach(provider -> provider.onTopologyBuilderRemoved(dataBefore));
90                     topologies.remove(dataBefore);
91                     break;
92                 case SUBTREE_MODIFIED:
93                     filterTopologyBuilders(dataBefore).forEach(provider
94                         -> provider.onTopologyBuilderRemoved(dataBefore));
95                     topologies.remove(dataBefore);
96                     filterTopologyBuilders(dataAfter).forEach(provider
97                         -> provider.onTopologyBuilderCreated(dataAfter));
98                     topologies.add(dataAfter);
99                     break;
100                 case WRITE:
101                     filterTopologyBuilders(dataAfter).forEach(provider
102                         -> provider.onTopologyBuilderCreated(dataAfter));
103                     topologies.add(dataAfter);
104                     break;
105                 default:
106                     break;
107             }
108         }
109     }
110
111     @Override
112     public synchronized AbstractRegistration registerTopologyProvider(final BgpTopologyProvider topologyBuilder) {
113         filterTopologies(topologyBuilder).forEach(topology -> topologyBuilder.onTopologyBuilderCreated(topology));
114         topologyProviders.add(topologyBuilder);
115         return new AbstractRegistration() {
116             @Override
117             protected void removeRegistration() {
118                 synchronized (BgpTopologyDeployerImpl.this) {
119                     filterTopologies(topologyBuilder)
120                             .forEach(topology -> topologyBuilder.onTopologyBuilderRemoved(topology));
121                     topologyProviders.remove(topologyBuilder);
122                 }
123             }
124         };
125     }
126
127     @Override
128     public DataBroker getDataBroker() {
129         return dataBroker;
130     }
131
132     @Override
133     public Registration registerService(final TopologyReferenceSingletonService topologyProviderService) {
134         return singletonProvider.registerClusterSingletonService(topologyProviderService);
135     }
136
137     @Deactivate
138     @PreDestroy
139     @Override
140     public synchronized void close() {
141         if (registration != null) {
142             registration.close();
143             registration = null;
144         }
145
146         LOG.info("BGP topology deployer stopped.");
147         closed = true;
148     }
149
150     private Iterable<BgpTopologyProvider> filterTopologyBuilders(final Topology topology) {
151         return topologyProviders.stream().filter(input -> input.topologyTypeFilter(topology))
152                 .collect(Collectors.toList());
153     }
154
155     private Iterable<Topology> filterTopologies(final BgpTopologyProvider topologyBuilder) {
156         return topologies.stream().filter(topology -> topologyBuilder.topologyTypeFilter(topology))
157                 .collect(Collectors.toList());
158     }
159 }