9897ba3f4289c928f4a4d2d6d67b62a2f9871a1f
[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.ListenableFuture;
13 import java.net.InetAddress;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.Map;
17 import java.util.concurrent.TimeUnit;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
20 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
23 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
24 import org.opendaylight.protocol.framework.SessionListenerFactory;
25 import org.opendaylight.protocol.pcep.PCEPSessionListener;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.AddLspArgs;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.EnsureLspOperationalInput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.OperationResult;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.RemoveLspArgs;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TopologyTypes1;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.TopologyTypes1Builder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.UpdateLspArgs;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.topology.pcep.type.TopologyPcepBuilder;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypesBuilder;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 /**
47  *
48  */
49 final class ServerSessionManager implements SessionListenerFactory<PCEPSessionListener>, AutoCloseable, TopologySessionRPCs {
50     private static final Logger LOG = LoggerFactory.getLogger(ServerSessionManager.class);
51     private static final long DEFAULT_HOLD_STATE_NANOS = TimeUnit.MINUTES.toNanos(5);
52
53     private final Map<NodeId, TopologySessionListener> nodes = new HashMap<>();
54     private final Map<NodeId, TopologyNodeState> state = new HashMap<>();
55     private final TopologySessionListenerFactory listenerFactory;
56     private final InstanceIdentifier<Topology> topology;
57     private final DataBroker broker;
58
59     public ServerSessionManager(final DataBroker broker, final InstanceIdentifier<Topology> topology,
60             final TopologySessionListenerFactory listenerFactory) throws ReadFailedException, TransactionCommitFailedException {
61         this.broker = Preconditions.checkNotNull(broker);
62         this.topology = Preconditions.checkNotNull(topology);
63         this.listenerFactory = Preconditions.checkNotNull(listenerFactory);
64
65
66         // Make sure the topology does not exist
67         final ReadWriteTransaction tx = broker.newReadWriteTransaction();
68         final Optional<?> c = tx.read(LogicalDatastoreType.OPERATIONAL, topology).checkedGet();
69         Preconditions.checkArgument(!c.isPresent(), "Topology %s already exists", topology);
70
71         // create empty network-topology if not exists
72         tx.merge(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(NetworkTopology.class).build(), new NetworkTopologyBuilder().build());
73         // Now create the base topology
74         final TopologyKey k = InstanceIdentifier.keyOf(topology);
75         tx.put(LogicalDatastoreType.OPERATIONAL, topology, new TopologyBuilder().setKey(k).setTopologyId(k.getTopologyId()).setTopologyTypes(
76                 new TopologyTypesBuilder().addAugmentation(TopologyTypes1.class,
77                         new TopologyTypes1Builder().setTopologyPcep(new TopologyPcepBuilder().build()).build()).build()).setNode(
78                                 new ArrayList<Node>()).build());
79
80         tx.submit().checkedGet();
81     }
82
83     private static NodeId createNodeId(final InetAddress addr) {
84         return new NodeId("pcc://" + addr.getHostAddress());
85     }
86
87     synchronized void releaseNodeState(final TopologyNodeState nodeState) {
88         LOG.debug("Node {} unbound", nodeState.getNodeId());
89         this.nodes.remove(nodeState.getNodeId());
90         nodeState.released();
91     }
92
93     synchronized TopologyNodeState takeNodeState(final InetAddress address, final TopologySessionListener sessionListener) {
94         final NodeId id = createNodeId(address);
95
96         LOG.debug("Node {} requested by listener {}", id, sessionListener);
97         TopologyNodeState ret = this.state.get(id);
98
99         if (ret == null) {
100             ret = new TopologyNodeState(broker, topology, id, DEFAULT_HOLD_STATE_NANOS);
101             LOG.debug("Created topology node {} for id {} at {}", ret, id, ret.getNodeId());
102             this.state.put(id, ret);
103         } else {
104             // FIXME: check for conflicting session
105         }
106
107         ret.taken();
108         this.nodes.put(id, sessionListener);
109         LOG.debug("Node {} bound to listener {}", id, sessionListener);
110         return ret;
111     }
112
113     @Override
114     public PCEPSessionListener getSessionListener() {
115         return listenerFactory.createTopologySessionListener(this);
116     }
117
118     @Override
119     public synchronized ListenableFuture<OperationResult> addLsp(final AddLspArgs input) {
120         // Get the listener corresponding to the node
121         final TopologySessionListener l = this.nodes.get(input.getNode());
122         if (l == null) {
123             LOG.debug("Session for node {} not found", input.getNode());
124             return OperationResults.UNSENT.future();
125         }
126
127         return l.addLsp(input);
128     }
129
130     @Override
131     public synchronized ListenableFuture<OperationResult> removeLsp(final RemoveLspArgs input) {
132         // Get the listener corresponding to the node
133         final TopologySessionListener l = this.nodes.get(input.getNode());
134         if (l == null) {
135             LOG.debug("Session for node {} not found", input.getNode());
136             return OperationResults.UNSENT.future();
137         }
138
139         return l.removeLsp(input);
140     }
141
142     @Override
143     public synchronized ListenableFuture<OperationResult> updateLsp(final UpdateLspArgs input) {
144         // Get the listener corresponding to the node
145         final TopologySessionListener l = this.nodes.get(input.getNode());
146         if (l == null) {
147             LOG.debug("Session for node {} not found", input.getNode());
148             return OperationResults.UNSENT.future();
149         }
150
151         return l.updateLsp(input);
152     }
153
154     @Override
155     public synchronized ListenableFuture<OperationResult> ensureLspOperational(final EnsureLspOperationalInput input) {
156         // Get the listener corresponding to the node
157         final TopologySessionListener l = this.nodes.get(input.getNode());
158         if (l == null) {
159             LOG.debug("Session for node {} not found", input.getNode());
160             return OperationResults.UNSENT.future();
161         }
162
163         return l.ensureLspOperational(input);
164     }
165
166     @Override
167     public void close() throws TransactionCommitFailedException {
168         for (final TopologySessionListener sessionListener : nodes.values()) {
169             sessionListener.close();
170         }
171         for (final TopologyNodeState nodeState : state.values()) {
172             nodeState.close();
173         }
174         final WriteTransaction t = this.broker.newWriteOnlyTransaction();
175         t.delete(LogicalDatastoreType.OPERATIONAL, this.topology);
176         t.submit().checkedGet();
177     }
178 }