Path Computation Server
[bgpcep.git] / pcep / topology / topology-provider / src / main / java / org / opendaylight / bgpcep / pcep / topology / provider / config / PCEPTopologyProviderBean.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
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.FluentFuture;
14 import java.util.Dictionary;
15 import java.util.Hashtable;
16 import java.util.List;
17 import org.checkerframework.checker.lock.qual.GuardedBy;
18 import org.opendaylight.bgpcep.pcep.server.PceServerProvider;
19 import org.opendaylight.bgpcep.pcep.topology.provider.PCEPTopologyProvider;
20 import org.opendaylight.bgpcep.pcep.topology.provider.TopologySessionListenerFactory;
21 import org.opendaylight.bgpcep.pcep.topology.spi.stats.TopologySessionStatsRegistry;
22 import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
23 import org.opendaylight.bgpcep.topology.DefaultTopologyReference;
24 import org.opendaylight.mdsal.binding.api.DataBroker;
25 import org.opendaylight.mdsal.binding.api.RpcProviderService;
26 import org.opendaylight.mdsal.common.api.CommitInfo;
27 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
28 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
29 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
30 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
31 import org.opendaylight.protocol.pcep.PCEPCapability;
32 import org.opendaylight.protocol.pcep.PCEPDispatcher;
33 import org.osgi.framework.BundleContext;
34 import org.osgi.framework.ServiceRegistration;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 public final class PCEPTopologyProviderBean implements PCEPTopologyProviderDependencies, AutoCloseable {
39     private static final Logger LOG = LoggerFactory.getLogger(PCEPTopologyProviderBean.class);
40
41     private static final String STATEFUL_NOT_DEFINED =
42             "Stateful capability not defined, aborting PCEP Topology Deployer instantiation";
43     private final PCEPDispatcher pcepDispatcher;
44     private final DataBroker dataBroker;
45     private final TopologySessionListenerFactory sessionListenerFactory;
46     private final RpcProviderService rpcProviderRegistry;
47     private final BundleContext bundleContext;
48     private final ClusterSingletonServiceProvider cssp;
49     private final TopologySessionStatsRegistry stateRegistry;
50     private final PceServerProvider pceServerProvider;
51     @GuardedBy("this")
52     private PCEPTopologyProviderBeanCSS pcepTopoProviderCSS;
53
54     public PCEPTopologyProviderBean(
55             final ClusterSingletonServiceProvider cssp,
56             final BundleContext bundleContext,
57             final DataBroker dataBroker,
58             final PCEPDispatcher pcepDispatcher,
59             final RpcProviderService rpcProviderRegistry,
60             final TopologySessionListenerFactory sessionListenerFactory,
61             final TopologySessionStatsRegistry stateRegistry,
62             final PceServerProvider pceServerProvider) {
63         this.cssp = requireNonNull(cssp);
64         this.bundleContext = requireNonNull(bundleContext);
65         this.pcepDispatcher = requireNonNull(pcepDispatcher);
66         this.dataBroker = requireNonNull(dataBroker);
67         this.sessionListenerFactory = requireNonNull(sessionListenerFactory);
68         this.rpcProviderRegistry = requireNonNull(rpcProviderRegistry);
69         this.stateRegistry = requireNonNull(stateRegistry);
70         this.pceServerProvider = requireNonNull(pceServerProvider);
71         final List<PCEPCapability> capabilities = this.pcepDispatcher.getPCEPSessionNegotiatorFactory()
72                 .getPCEPSessionProposalFactory().getCapabilities();
73         final boolean statefulCapability = capabilities.stream().anyMatch(PCEPCapability::isStateful);
74         if (!statefulCapability) {
75             throw new IllegalStateException(STATEFUL_NOT_DEFINED);
76         }
77     }
78
79     synchronized FluentFuture<? extends CommitInfo> closeServiceInstance() {
80         if (this.pcepTopoProviderCSS != null) {
81             return this.pcepTopoProviderCSS.closeServiceInstance();
82         }
83         return CommitInfo.emptyFluentFuture();
84     }
85
86     @Override
87     public synchronized void close() throws Exception {
88         if (this.pcepTopoProviderCSS != null) {
89             this.pcepTopoProviderCSS.close();
90             this.pcepTopoProviderCSS = null;
91         }
92     }
93
94     @SuppressWarnings("checkstyle:IllegalCatch")
95     synchronized void start(final PCEPTopologyConfiguration configDependencies,
96             final InstructionScheduler instructionScheduler) {
97         Preconditions.checkState(this.pcepTopoProviderCSS == null,
98                 "Previous instance %s was not closed.", this);
99         try {
100             this.pcepTopoProviderCSS = new PCEPTopologyProviderBeanCSS(configDependencies,
101                     instructionScheduler, this);
102         } catch (final Exception e) {
103             LOG.debug("Failed to create PCEPTopologyProvider {}", configDependencies.getTopologyId().getValue(), e);
104         }
105     }
106
107     @Override
108     public PCEPDispatcher getPCEPDispatcher() {
109         return this.pcepDispatcher;
110     }
111
112     @Override
113     public RpcProviderService getRpcProviderRegistry() {
114         return this.rpcProviderRegistry;
115     }
116
117     @Override
118     public DataBroker getDataBroker() {
119         return this.dataBroker;
120     }
121
122     @Override
123     public TopologySessionListenerFactory getTopologySessionListenerFactory() {
124         return this.sessionListenerFactory;
125     }
126
127     @Override
128     public TopologySessionStatsRegistry getStateRegistry() {
129         return this.stateRegistry;
130     }
131
132     @Override
133     public PceServerProvider getPceServerProvider() {
134         return this.pceServerProvider;
135     }
136
137     private static class PCEPTopologyProviderBeanCSS implements ClusterSingletonService, AutoCloseable {
138         private final ServiceGroupIdentifier sgi;
139         private final PCEPTopologyProvider pcepTopoProvider;
140         private final InstructionScheduler scheduler;
141         private ServiceRegistration<?> serviceRegistration;
142         private ClusterSingletonServiceRegistration cssRegistration;
143         @GuardedBy("this")
144         private boolean serviceInstantiated;
145
146         PCEPTopologyProviderBeanCSS(final PCEPTopologyConfiguration configDependencies,
147                 final InstructionScheduler instructionScheduler, final PCEPTopologyProviderBean bean) {
148             this.scheduler = instructionScheduler;
149             this.sgi = this.scheduler.getIdentifier();
150             this.pcepTopoProvider = PCEPTopologyProvider.create(bean, this.scheduler, configDependencies);
151
152             final Dictionary<String, String> properties = new Hashtable<>();
153             properties.put(PCEPTopologyProvider.class.getName(), configDependencies.getTopologyId().getValue());
154             this.serviceRegistration = bean.bundleContext
155                     .registerService(DefaultTopologyReference.class.getName(), this.pcepTopoProvider, properties);
156             LOG.info("PCEP Topology Provider service {} registered", getIdentifier().getName());
157             this.cssRegistration = bean.cssp.registerClusterSingletonService(this);
158         }
159
160         @Override
161         @SuppressWarnings("checkstyle:IllegalCatch")
162         public synchronized void instantiateServiceInstance() {
163             LOG.info("PCEP Topology Provider Singleton Service {} instantiated", getIdentifier().getName());
164             try {
165                 this.pcepTopoProvider.instantiateServiceInstance();
166             } catch (final Exception e) {
167                 LOG.error("Failed to instantiate PCEP Topology provider", e);
168             }
169             this.serviceInstantiated = true;
170         }
171
172         @Override
173         public synchronized FluentFuture<? extends CommitInfo> closeServiceInstance() {
174             LOG.info("Close PCEP Topology Provider Singleton Service {}", getIdentifier().getName());
175             if (this.serviceInstantiated) {
176                 this.serviceInstantiated = false;
177                 return this.pcepTopoProvider.closeServiceInstance();
178             }
179             return CommitInfo.emptyFluentFuture();
180         }
181
182         @Override
183         public ServiceGroupIdentifier getIdentifier() {
184             return this.sgi;
185         }
186
187         @Override
188         public synchronized void close() throws Exception {
189             if (this.cssRegistration != null) {
190                 this.cssRegistration.close();
191                 this.cssRegistration = null;
192             }
193             if (this.serviceRegistration != null) {
194                 this.serviceRegistration.unregister();
195                 this.serviceRegistration = null;
196             }
197             this.scheduler.close();
198         }
199     }
200 }