Merge "Bug-607: Segment Routing TLVs parsers/serializers"
[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 java.util.ArrayList;
11 import java.util.HashMap;
12 import java.util.Map;
13 import java.util.concurrent.ExecutionException;
14 import java.util.concurrent.TimeUnit;
15
16 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
17 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
18 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
19 import org.opendaylight.protocol.framework.SessionListenerFactory;
20 import org.opendaylight.protocol.pcep.PCEPSessionListener;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspArgs;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.EnsureLspOperationalInput;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspArgs;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TopologyTypes1;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TopologyTypes1Builder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspArgs;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.topology.pcep.type.TopologyPcepBuilder;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
30 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
31 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
32 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
33 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypesBuilder;
35 import org.opendaylight.yangtools.yang.binding.DataObject;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.opendaylight.yangtools.yang.common.RpcResult;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 import com.google.common.base.Preconditions;
42 import com.google.common.util.concurrent.FutureCallback;
43 import com.google.common.util.concurrent.Futures;
44 import com.google.common.util.concurrent.JdkFutureAdapters;
45 import com.google.common.util.concurrent.ListenableFuture;
46
47 /**
48  *
49  */
50 final class ServerSessionManager implements SessionListenerFactory<PCEPSessionListener>, AutoCloseable, TopologySessionRPCs {
51         private static final Logger LOG = LoggerFactory.getLogger(ServerSessionManager.class);
52         private static final long DEFAULT_HOLD_STATE_NANOS = TimeUnit.MINUTES.toNanos(5);
53
54         private final Map<NodeId, TopologySessionListener> nodes = new HashMap<>();
55         private final Map<NodeId, TopologyNodeState> state = new HashMap<>();
56         private final TopologySessionListenerFactory listenerFactory;
57         private final InstanceIdentifier<Topology> topology;
58         private final DataProviderService dataProvider;
59
60         public ServerSessionManager(final DataProviderService dataProvider, final InstanceIdentifier<Topology> topology, final TopologySessionListenerFactory listenerFactory) {
61                 this.dataProvider = Preconditions.checkNotNull(dataProvider);
62                 this.topology = Preconditions.checkNotNull(topology);
63                 this.listenerFactory = Preconditions.checkNotNull(listenerFactory);
64
65                 // Make sure the topology does not exist
66                 final Object c = dataProvider.readOperationalData(topology);
67                 Preconditions.checkArgument(c == null, "Topology %s already exists", topology);
68
69                 // Now create the base topology
70                 final TopologyKey k = InstanceIdentifier.keyOf(topology);
71                 final DataModificationTransaction t = dataProvider.beginTransaction();
72                 t.putOperationalData(
73                                 topology,
74                                 new TopologyBuilder().setKey(k).setTopologyId(k.getTopologyId()).setTopologyTypes(
75                                                 new TopologyTypesBuilder().addAugmentation(TopologyTypes1.class,
76                                                                 new TopologyTypes1Builder().setTopologyPcep(new TopologyPcepBuilder().build()).build()).build()).setNode(
77                                                                                 new ArrayList<Node>()).build());
78
79                 Futures.addCallback(JdkFutureAdapters.listenInPoolThread(t.commit()), new FutureCallback<RpcResult<TransactionStatus>>() {
80                         @Override
81                         public void onSuccess(final RpcResult<TransactionStatus> result) {
82                                 LOG.trace("Topology {} created successfully", topology);
83                         }
84
85                         @Override
86                         public void onFailure(final Throwable t) {
87                                 LOG.error("Failed to create topology {}", topology);
88                         }
89                 });
90         }
91
92         public void releaseNodeState(final TopologyNodeState nodeState) {
93                 LOG.debug("Node {} unbound", nodeState.getNodeId());
94                 this.nodes.remove(nodeState.getNodeId());
95                 nodeState.released();
96         }
97
98         synchronized TopologyNodeState takeNodeState(final NodeId id, final TopologySessionListener sessionListener) {
99                 LOG.debug("Node {} bound to listener {}", id, sessionListener);
100
101                 TopologyNodeState ret = this.state.get(id);
102                 if (ret == null) {
103                         ret = new TopologyNodeState(id, DEFAULT_HOLD_STATE_NANOS);
104                         this.state.put(id, ret);
105                 }
106
107                 this.nodes.put(id, sessionListener);
108                 ret.taken();
109                 return ret;
110         }
111
112         @Override
113         public PCEPSessionListener getSessionListener() {
114                 return listenerFactory.createTopologySessionListener(this);
115         }
116
117         @Override
118         public synchronized ListenableFuture<OperationResult> addLsp(final AddLspArgs input) {
119                 // Get the listener corresponding to the node
120                 final TopologySessionListener l = this.nodes.get(input.getNode());
121                 if (l == null) {
122                         LOG.debug("Session for node {} not found", input.getNode());
123                         return OperationResults.UNSENT.future();
124                 }
125
126                 return l.addLsp(input);
127         }
128
129         @Override
130         public synchronized ListenableFuture<OperationResult> removeLsp(final RemoveLspArgs input) {
131                 // Get the listener corresponding to the node
132                 final TopologySessionListener l = this.nodes.get(input.getNode());
133                 if (l == null) {
134                         LOG.debug("Session for node {} not found", input.getNode());
135                         return OperationResults.UNSENT.future();
136                 }
137
138                 return l.removeLsp(input);
139         }
140
141         @Override
142         public synchronized ListenableFuture<OperationResult> updateLsp(final UpdateLspArgs input) {
143                 // Get the listener corresponding to the node
144                 final TopologySessionListener l = this.nodes.get(input.getNode());
145                 if (l == null) {
146                         LOG.debug("Session for node {} not found", input.getNode());
147                         return OperationResults.UNSENT.future();
148                 }
149
150                 return l.updateLsp(input);
151         }
152
153         @Override
154         public synchronized ListenableFuture<OperationResult> ensureLspOperational(final EnsureLspOperationalInput input) {
155                 // Get the listener corresponding to the node
156                 final TopologySessionListener l = this.nodes.get(input.getNode());
157                 if (l == null) {
158                         LOG.debug("Session for node {} not found", input.getNode());
159                         return OperationResults.UNSENT.future();
160                 }
161
162                 return l.ensureLspOperational(input);
163         }
164
165         InstanceIdentifier<Topology> getTopology() {
166                 return topology;
167         }
168
169         DataModificationTransaction beginTransaction() {
170                 return dataProvider.beginTransaction();
171         }
172
173         @SuppressWarnings("unchecked")
174         <T extends DataObject> T readOperationalData(final InstanceIdentifier<T> id) {
175                 return (T)dataProvider.readOperationalData(id);
176         }
177
178         @Override
179         public void close() throws InterruptedException, ExecutionException {
180                 final DataModificationTransaction t = this.dataProvider.beginTransaction();
181                 t.removeOperationalData(this.topology);
182                 t.commit().get();
183         }
184 }