a86458bb7b7ddee4ddcf58561b33198531aa0d61
[bgpcep.git] / pcep / topology-provider / src / main / java / org / opendaylight / bgpcep / pcep / topology / provider / ServerSessionManager.java
1 /*
2  * Copyright (c) 2013 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.pcep.topology.provider;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.Map;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.TimeUnit;
21
22 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
25 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
30 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
31 import org.opendaylight.protocol.framework.SessionListenerFactory;
32 import org.opendaylight.protocol.pcep.PCEPSessionListener;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspArgs;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.EnsureLspOperationalInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspArgs;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TopologyTypes1;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TopologyTypes1Builder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspArgs;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.topology.pcep.type.TopologyPcepBuilder;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypesBuilder;
49 import org.opendaylight.yangtools.yang.binding.DataObject;
50 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 /**
55  *
56  */
57 final class ServerSessionManager implements SessionListenerFactory<PCEPSessionListener>, AutoCloseable, TopologySessionRPCs, TransactionChainListener {
58     private static final Logger LOG = LoggerFactory.getLogger(ServerSessionManager.class);
59     private static final long DEFAULT_HOLD_STATE_NANOS = TimeUnit.MINUTES.toNanos(5);
60
61     private final Map<NodeId, TopologySessionListener> nodes = new HashMap<>();
62     private final Map<NodeId, TopologyNodeState> state = new HashMap<>();
63     private final TopologySessionListenerFactory listenerFactory;
64     private final InstanceIdentifier<Topology> topology;
65     private final BindingTransactionChain chain;
66
67     public ServerSessionManager(final DataBroker dataProvider, final InstanceIdentifier<Topology> topology,
68             final TopologySessionListenerFactory listenerFactory) {
69         this.chain = dataProvider.createTransactionChain(this);
70         this.topology = Preconditions.checkNotNull(topology);
71         this.listenerFactory = Preconditions.checkNotNull(listenerFactory);
72
73         // FIXME: should migrated to transaction chain
74         final ReadWriteTransaction tx = chain.newReadWriteTransaction();
75
76         // Make sure the topology does not exist
77         final Optional<?> c;
78         try {
79             c = tx.read(LogicalDatastoreType.OPERATIONAL, topology).get();
80         } catch (InterruptedException | ExecutionException e) {
81             throw new IllegalStateException("Failed to ensure topology presence", e);
82         }
83         Preconditions.checkArgument(!c.isPresent(), "Topology %s already exists", topology);
84
85         // create empty network-topology is not exists
86         tx.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(NetworkTopology.class).build(), new NetworkTopologyBuilder().build());
87         // Now create the base topology
88         final TopologyKey k = InstanceIdentifier.keyOf(topology);
89         tx.put(LogicalDatastoreType.OPERATIONAL, topology, new TopologyBuilder().setKey(k).setTopologyId(k.getTopologyId()).setTopologyTypes(
90                 new TopologyTypesBuilder().addAugmentation(TopologyTypes1.class,
91                         new TopologyTypes1Builder().setTopologyPcep(new TopologyPcepBuilder().build()).build()).build()).setNode(
92                                 new ArrayList<Node>()).build());
93
94         Futures.addCallback(tx.submit(), new FutureCallback<Void>() {
95             @Override
96             public void onSuccess(final Void result) {
97                 LOG.trace("Topology {} created successfully", topology);
98             }
99
100             @Override
101             public void onFailure(final Throwable t) {
102                 LOG.error("Failed to create topology {}", topology, t);
103             }
104         });
105     }
106
107     public void releaseNodeState(final TopologyNodeState nodeState) {
108         LOG.debug("Node {} unbound", nodeState.getNodeId());
109         this.nodes.remove(nodeState.getNodeId());
110         nodeState.released();
111     }
112
113     synchronized TopologyNodeState takeNodeState(final NodeId id, final TopologySessionListener sessionListener) {
114         LOG.debug("Node {} bound to listener {}", id, sessionListener);
115
116         TopologyNodeState ret = this.state.get(id);
117         if (ret == null) {
118             ret = new TopologyNodeState(id, DEFAULT_HOLD_STATE_NANOS);
119             this.state.put(id, ret);
120         }
121
122         this.nodes.put(id, sessionListener);
123         ret.taken();
124         return ret;
125     }
126
127     @Override
128     public PCEPSessionListener getSessionListener() {
129         return listenerFactory.createTopologySessionListener(this);
130     }
131
132     @Override
133     public synchronized ListenableFuture<OperationResult> addLsp(final AddLspArgs input) {
134         // Get the listener corresponding to the node
135         final TopologySessionListener l = this.nodes.get(input.getNode());
136         if (l == null) {
137             LOG.debug("Session for node {} not found", input.getNode());
138             return OperationResults.UNSENT.future();
139         }
140
141         return l.addLsp(input);
142     }
143
144     @Override
145     public synchronized ListenableFuture<OperationResult> removeLsp(final RemoveLspArgs input) {
146         // Get the listener corresponding to the node
147         final TopologySessionListener l = this.nodes.get(input.getNode());
148         if (l == null) {
149             LOG.debug("Session for node {} not found", input.getNode());
150             return OperationResults.UNSENT.future();
151         }
152
153         return l.removeLsp(input);
154     }
155
156     @Override
157     public synchronized ListenableFuture<OperationResult> updateLsp(final UpdateLspArgs input) {
158         // Get the listener corresponding to the node
159         final TopologySessionListener l = this.nodes.get(input.getNode());
160         if (l == null) {
161             LOG.debug("Session for node {} not found", input.getNode());
162             return OperationResults.UNSENT.future();
163         }
164
165         return l.updateLsp(input);
166     }
167
168     @Override
169     public synchronized ListenableFuture<OperationResult> ensureLspOperational(final EnsureLspOperationalInput input) {
170         // Get the listener corresponding to the node
171         final TopologySessionListener l = this.nodes.get(input.getNode());
172         if (l == null) {
173             LOG.debug("Session for node {} not found", input.getNode());
174             return OperationResults.UNSENT.future();
175         }
176
177         return l.ensureLspOperational(input);
178     }
179
180     InstanceIdentifier<Topology> getTopology() {
181         return topology;
182     }
183
184     WriteTransaction beginTransaction() {
185         return chain.newWriteOnlyTransaction();
186     }
187
188     ReadWriteTransaction rwTransaction() {
189         return chain.newReadWriteTransaction();
190     }
191
192     <T extends DataObject> ListenableFuture<Optional<T>> readOperationalData(final InstanceIdentifier<T> id) {
193         final ReadTransaction t = chain.newReadOnlyTransaction();
194         return t.read(LogicalDatastoreType.OPERATIONAL, id);
195     }
196
197     @Override
198     public void close() throws InterruptedException, ExecutionException {
199         final WriteTransaction t = this.chain.newWriteOnlyTransaction();
200         t.delete(LogicalDatastoreType.OPERATIONAL, this.topology);
201         t.submit().get();
202         chain.close();
203     }
204
205     @Override
206     public void onTransactionChainFailed(final TransactionChain<?, ?> chain, final AsyncTransaction<?, ?> transaction, final Throwable cause) {
207         LOG.error("Unexpected transaction failure in topology {} transaction {}", getTopology(), transaction.getIdentifier(), cause);
208     }
209
210     @Override
211     public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
212         LOG.info("Topology {} shutdown successfully", getTopology());
213     }
214 }