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