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