Bump versions to 0.21.7-SNAPSHOT
[bgpcep.git] / pcep / tunnel / tunnel-provider / src / main / java / org / opendaylight / bgpcep / pcep / tunnel / provider / PCEPTunnelClusterSingletonService.java
1 /*
2  * Copyright (c) 2017 AT&T Intellectual Property. 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.tunnel.provider;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.util.Map;
15 import java.util.concurrent.TimeUnit;
16 import org.checkerframework.checker.lock.qual.GuardedBy;
17 import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
18 import org.opendaylight.bgpcep.topology.DefaultTopologyReference;
19 import org.opendaylight.mdsal.common.api.CommitInfo;
20 import org.opendaylight.mdsal.singleton.api.ClusterSingletonService;
21 import org.opendaylight.mdsal.singleton.api.ServiceGroupIdentifier;
22 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
23 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
24 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
25 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
26 import org.opendaylight.yangtools.concepts.Registration;
27 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
28 import org.osgi.framework.BundleContext;
29 import org.osgi.framework.Constants;
30 import org.osgi.framework.FrameworkUtil;
31 import org.osgi.framework.InvalidSyntaxException;
32 import org.osgi.framework.ServiceRegistration;
33 import org.osgi.util.tracker.ServiceTracker;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 public final class PCEPTunnelClusterSingletonService implements ClusterSingletonService, AutoCloseable {
38     private static final Logger LOG = LoggerFactory.getLogger(PCEPTunnelClusterSingletonService.class);
39
40     private final PCEPTunnelTopologyProvider ttp;
41     private final TunnelProgramming tp;
42     private final ServiceGroupIdentifier sgi;
43     private final TopologyId tunnelTopologyId;
44
45     @GuardedBy("this")
46     private ServiceRegistration<?> serviceRegistration;
47     @GuardedBy("this")
48     private Registration pcepTunnelCssReg;
49     @GuardedBy("this")
50     private Registration reg;
51
52     public PCEPTunnelClusterSingletonService(
53             final TunnelProviderDependencies dependencies,
54             final InstanceIdentifier<Topology> pcepTopology,
55             final TopologyId tunnelTopologyId
56     ) {
57         this.tunnelTopologyId = requireNonNull(tunnelTopologyId);
58         final TopologyId pcepTopologyId = pcepTopology.firstKeyOf(Topology.class).getTopologyId();
59         final BundleContext bundleContext = dependencies.getBundleContext();
60
61         final InstructionScheduler scheduler;
62         ServiceTracker<InstructionScheduler, ?> tracker = null;
63         try {
64             tracker = new ServiceTracker<>(bundleContext,
65                 bundleContext.createFilter("(&(%s=%s)%s)".formatted(
66                     Constants.OBJECTCLASS, InstructionScheduler.class.getName(),
67                     "(" + InstructionScheduler.class.getName() + "=" + pcepTopologyId.getValue() + ")")),
68                 null);
69             tracker.open();
70             scheduler = (InstructionScheduler) tracker.waitForService(
71                     TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES));
72             Preconditions.checkState(scheduler != null, "InstructionScheduler service not found");
73         } catch (InvalidSyntaxException | InterruptedException e) {
74             throw new IllegalStateException("Error retrieving InstructionScheduler service", e);
75         } finally {
76             if (tracker != null) {
77                 tracker.close();
78             }
79         }
80
81         final InstanceIdentifier<Topology> tunnelTopology = InstanceIdentifier.builder(NetworkTopology.class)
82                 .child(Topology.class, new TopologyKey(tunnelTopologyId)).build();
83         ttp = new PCEPTunnelTopologyProvider(dependencies.getDataBroker(), pcepTopology, pcepTopologyId,
84                 tunnelTopology, tunnelTopologyId);
85
86
87         sgi = scheduler.getIdentifier();
88         tp = new TunnelProgramming(scheduler, dependencies);
89
90
91         serviceRegistration = bundleContext.registerService(DefaultTopologyReference.class, ttp,
92             FrameworkUtil.asDictionary(Map.of(
93                 PCEPTunnelTopologyProvider.class.getName(), tunnelTopologyId.getValue())));
94
95         LOG.info("PCEP Tunnel Cluster Singleton service {} registered", getIdentifier().value());
96         pcepTunnelCssReg = dependencies.getCssp().registerClusterSingletonService(this);
97     }
98
99     @Override
100     public synchronized void instantiateServiceInstance() {
101         LOG.info("Instantiate PCEP Tunnel Topology Provider Singleton Service {}", getIdentifier().value());
102
103         reg = tp.register(InstanceIdentifier.builder(NetworkTopology.class)
104             .child(Topology.class, new TopologyKey(tunnelTopologyId))
105             .build());
106         ttp.init();
107     }
108
109     @Override
110     public synchronized ListenableFuture<? extends CommitInfo> closeServiceInstance() {
111         LOG.info("Close Service Instance PCEP Tunnel Topology Provider Singleton Service {}", getIdentifier().value());
112         reg.close();
113         tp.close();
114         ttp.close();
115         return CommitInfo.emptyFluentFuture();
116     }
117
118     @Override
119     public ServiceGroupIdentifier getIdentifier() {
120         return sgi;
121     }
122
123     @Override
124     @SuppressWarnings("checkstyle:IllegalCatch")
125     public synchronized void close() {
126         LOG.info("Close PCEP Tunnel Topology Provider Singleton Service {}", getIdentifier().value());
127
128         if (pcepTunnelCssReg != null) {
129             try {
130                 pcepTunnelCssReg.close();
131             } catch (final Exception e) {
132                 LOG.debug("Failed to close PCEP Tunnel Topology service {}", sgi.value(), e);
133             }
134             pcepTunnelCssReg = null;
135         }
136         if (serviceRegistration != null) {
137             serviceRegistration.unregister();
138             serviceRegistration = null;
139         }
140     }
141 }