Get rid of JSR305 annotations
[bgpcep.git] / pcep / topology / topology-provider / src / main / java / org / opendaylight / bgpcep / pcep / topology / provider / config / PCEPTopologyDeployerImpl.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.pcep.topology.provider.config;
9
10 import static java.util.Objects.requireNonNull;
11 import static org.opendaylight.bgpcep.pcep.topology.provider.config.PCEPTopologyProviderUtil.filterPcepTopologies;
12 import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;
13
14 import java.util.Collection;
15 import java.util.HashMap;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.concurrent.TimeUnit;
19 import java.util.stream.Collectors;
20 import org.checkerframework.checker.lock.qual.GuardedBy;
21 import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
22 import org.opendaylight.bgpcep.programming.spi.InstructionSchedulerFactory;
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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.config.rev171025.pcep.config.SessionConfig;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.config.rev181109.PcepTopologyTypeConfig;
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.TopologyId;
32 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
33 import org.opendaylight.yangtools.concepts.ListenerRegistration;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.osgi.service.blueprint.container.BlueprintContainer;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 public class PCEPTopologyDeployerImpl implements ClusteredDataTreeChangeListener<Topology>, AutoCloseable {
40
41     private static final Logger LOG = LoggerFactory.getLogger(PCEPTopologyDeployerImpl.class);
42
43     private static final long TIMEOUT_NS = TimeUnit.SECONDS.toNanos(5);
44     private final BlueprintContainer container;
45     private final InstanceIdentifier<NetworkTopology> networTopology;
46     private final DataBroker dataBroker;
47     private final InstructionSchedulerFactory instructionSchedulerFactory;
48     @GuardedBy("this")
49     private final Map<TopologyId, PCEPTopologyProviderBean> pcepTopologyServices = new HashMap<>();
50     private ListenerRegistration<PCEPTopologyDeployerImpl> listenerRegistration;
51
52     public PCEPTopologyDeployerImpl(final BlueprintContainer container,
53             final DataBroker dataBroker, final InstructionSchedulerFactory instructionSchedulerFactory) {
54         this.container = requireNonNull(container);
55         this.dataBroker = requireNonNull(dataBroker);
56         this.instructionSchedulerFactory = requireNonNull(instructionSchedulerFactory);
57         this.networTopology = InstanceIdentifier.builder(NetworkTopology.class).build();
58     }
59
60     public synchronized void init() {
61         LOG.info("PCEP Topology Deployer initialized");
62         this.listenerRegistration = this.dataBroker.registerDataTreeChangeListener(
63                 DataTreeIdentifier.create(CONFIGURATION, this.networTopology.child(Topology.class)), this);
64     }
65
66     @Override
67     public synchronized void onDataTreeChanged(final Collection<DataTreeModification<Topology>> changes) {
68         final List<DataObjectModification<Topology>> topoChanges = changes.stream()
69                 .map(DataTreeModification::getRootNode)
70                 .collect(Collectors.toList());
71         topoChanges.stream().iterator().forEachRemaining(topo -> {
72             switch (topo.getModificationType()) {
73                 case SUBTREE_MODIFIED:
74                 case WRITE:
75                     updateTopologyProvider(topo.getDataAfter());
76                     break;
77                 case DELETE:
78                     removeTopologyProvider(topo.getDataBefore());
79                     break;
80                 default:
81             }
82         });
83     }
84
85     private synchronized void updateTopologyProvider(final Topology topology) {
86         if (!filterPcepTopologies(topology.getTopologyTypes())) {
87             return;
88         }
89         final TopologyId topologyId = topology.getTopologyId();
90         LOG.info("Updating Topology {}", topologyId);
91         final PCEPTopologyProviderBean previous = this.pcepTopologyServices.remove(topology.getTopologyId());
92         closeTopology(previous, topologyId);
93         createTopologyProvider(topology);
94     }
95
96     private synchronized void createTopologyProvider(final Topology topology) {
97         if (!filterPcepTopologies(topology.getTopologyTypes())) {
98             return;
99         }
100         final TopologyId topologyId = topology.getTopologyId();
101         if (this.pcepTopologyServices.containsKey(topology.getTopologyId())) {
102             LOG.warn("Topology Provider {} already exist. New instance won't be created", topologyId);
103             return;
104         }
105         LOG.info("Creating Topology {}", topologyId);
106         LOG.trace("Topology {}.", topology);
107
108         final SessionConfig config = topology.augmentation(PcepTopologyTypeConfig.class).getSessionConfig();
109         final InstructionScheduler instructionScheduler = this.instructionSchedulerFactory
110                 .createInstructionScheduler(topologyId.getValue());
111
112         final PCEPTopologyConfiguration dependencies = new PCEPTopologyConfiguration(config, topology);
113
114         final PCEPTopologyProviderBean pcepTopologyProviderBean = (PCEPTopologyProviderBean) this.container
115                 .getComponentInstance(PCEPTopologyProviderBean.class.getSimpleName());
116         this.pcepTopologyServices.put(topologyId, pcepTopologyProviderBean);
117         pcepTopologyProviderBean.start(dependencies, instructionScheduler);
118     }
119
120     private synchronized void removeTopologyProvider(final Topology topology) {
121         if (!filterPcepTopologies(topology.getTopologyTypes())) {
122             return;
123         }
124         final TopologyId topologyId = topology.getTopologyId();
125         closeTopology(this.pcepTopologyServices.remove(topologyId), topologyId);
126     }
127
128     @Override
129     public synchronized void close() {
130         LOG.info("PCEP Topology Deployer closing");
131         if (this.listenerRegistration != null) {
132             this.listenerRegistration.close();
133             this.listenerRegistration = null;
134         }
135         for (Map.Entry<TopologyId, PCEPTopologyProviderBean> entry:this.pcepTopologyServices.entrySet()) {
136             closeTopology(entry.getValue(), entry.getKey());
137         }
138         this.pcepTopologyServices.clear();
139         LOG.info("PCEP Topology Deployer closed");
140     }
141
142
143     @SuppressWarnings("checkstyle:IllegalCatch")
144     private synchronized void closeTopology(final PCEPTopologyProviderBean topology, final TopologyId topologyId) {
145         if (topology == null) {
146             return;
147         }
148         LOG.info("Removing Topology {}", topologyId);
149         try {
150             topology.closeServiceInstance().get(TIMEOUT_NS, TimeUnit.NANOSECONDS);
151             topology.close();
152         } catch (final Exception e) {
153             LOG.error("Topology {} instance failed to close service instance", topologyId, e);
154         }
155     }
156 }