2 * Copyright (c) 2019 Orange. All rights reserved.
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
8 package org.opendaylight.graph.impl;
10 import static com.google.common.base.Preconditions.checkArgument;
12 import java.nio.ByteBuffer;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.opendaylight.graph.ConnectedEdge;
18 import org.opendaylight.graph.ConnectedGraph;
19 import org.opendaylight.graph.ConnectedVertex;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.Graph;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.Edge;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.EdgeKey;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.Prefix;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.Vertex;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.VertexKey;
31 import org.opendaylight.yangtools.yang.common.Uint32;
32 import org.opendaylight.yangtools.yang.common.Uint64;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
37 * This Class implements the Connected Graph for path computation algorithms.
39 * @author Olivier Dugeon
40 * @author Philippe Niger
42 public class ConnectedGraphImpl implements ConnectedGraph {
43 private static final Logger LOG = LoggerFactory.getLogger(ConnectedGraphImpl.class);
45 /* List of Connected Vertics that composed this Connected Graph */
46 private final HashMap<Long, ConnectedVertexImpl> vertices = new HashMap<>();
48 /* List of Connected Edges that composed this Connected Graph */
49 private final HashMap<Long, ConnectedEdgeImpl> edges = new HashMap<>();
51 /* List of IP prefix attached to Vertices */
52 private final HashMap<IpPrefix, Prefix> prefixes = new HashMap<>();
54 /* Reference to the non connected Graph stored in DataStore */
57 /* Reference to Graph Model Server to store corresponding graph in DataStore */
58 private final ConnectedGraphServer connectedGraphServer;
60 public ConnectedGraphImpl(final Graph newGraph, final ConnectedGraphServer server) {
61 this.graph = newGraph;
62 createConnectedGraph();
63 this.connectedGraphServer = server;
67 * Transform the associated Graph in a Connected Graph. This method will automatically create associated Connected
68 * Vertices, from the Graph Vertices, Connected Edges, from the Graph Edges and Prefix from the Graph Prefix.
71 private void createConnectedGraph() {
72 if (this.graph == null) {
75 /* Add all vertices */
76 for (Vertex vertex : this.graph.nonnullVertex().values()) {
77 ConnectedVertexImpl cvertex = new ConnectedVertexImpl(vertex);
78 vertices.put(cvertex.getKey(), cvertex);
81 for (Edge edge : this.graph.nonnullEdge().values()) {
82 ConnectedEdgeImpl cedge = new ConnectedEdgeImpl(edge);
83 edges.put(cedge.getKey(), cedge);
85 /* Add all prefixes */
86 for (Prefix prefix : this.graph.nonnullPrefix().values()) {
87 ConnectedVertexImpl cvertex = vertices.get(prefix.getVertexId().longValue());
88 if (cvertex != null) {
89 cvertex.addPrefix(prefix);
91 prefixes.putIfAbsent(prefix.getPrefix(), prefix);
96 * Return Connected Vertex if it exists or create a new one.
98 * @param key Unique Vertex Key identifier
99 * @return new or existing Connected Vertex
101 private ConnectedVertexImpl updateConnectedVertex(final @NonNull Long key) {
102 checkArgument(key != 0, "Provided Vertex Key must not be equal to 0");
103 ConnectedVertexImpl vertex = vertices.get(key);
104 if (vertex == null) {
105 vertex = new ConnectedVertexImpl(key);
106 vertices.put(key, vertex);
112 * Return Connected Edge if it exist or create a new one.
114 * @param key Unique Edge Key identifier
115 * @return new or existing Connected Edge
117 private ConnectedEdgeImpl updateConnectedEdge(final @NonNull Long key) {
118 checkArgument(key != 0, "Provided Edge Key must not be equal to 0");
119 ConnectedEdgeImpl edge = edges.get(key);
121 edge = new ConnectedEdgeImpl(key);
122 edges.put(edge.getKey(), edge);
128 * Connect source and destination Connected Vertices with the given Connected Edge.
130 * @param srcVertex Source Connected Vertex
131 * @param dstVertex Destination Connected Vertex
132 * @param edge Connected Edge
134 private static void connectVertices(final ConnectedVertexImpl srcVertex, final ConnectedVertexImpl dstVertex,
135 final ConnectedEdgeImpl edge) {
137 edge.setSource(srcVertex);
138 edge.setDestination(dstVertex);
140 if (srcVertex != null) {
141 srcVertex.addOutput(edge);
143 if (dstVertex != null) {
144 dstVertex.addInput(edge);
149 public Graph getGraph() {
154 public List<ConnectedVertex> getVertices() {
155 return new ArrayList<>(this.vertices.values());
159 public ConnectedVertex getConnectedVertex(final Long key) {
160 return vertices.get(key);
164 public ConnectedVertex getConnectedVertex(final IpAddress address) {
165 IpPrefix prefix = null;
166 if (address.getIpv4Address() != null) {
167 prefix = new IpPrefix(new Ipv4Prefix(address.getIpv4Address().getValue() + "/32"));
169 if (address.getIpv6Address() != null) {
170 prefix = new IpPrefix(new Ipv6Prefix(address.getIpv6Address().getValue() + "/128"));
172 if (prefix != null && prefixes.containsKey(prefix)) {
173 long key = prefixes.get(prefix).getVertexId().longValue();
174 return vertices.get(key);
181 public int getVerticesSize() {
182 return vertices.size();
186 public List<ConnectedEdge> getEdges() {
187 return new ArrayList<>(this.edges.values());
191 public ConnectedEdge getConnectedEdge(final Long key) {
192 return edges.get(key);
196 public ConnectedEdge getConnectedEdge(final IpAddress address) {
198 if (address.getIpv4Address() != null) {
199 key = Uint32.fromIntBits(IetfInetUtil.INSTANCE.ipv4AddressBits(address.getIpv4Address())).toUint64();
200 return getConnectedEdge(key.longValue());
202 if (address.getIpv6Address() != null) {
203 final byte[] ip = IetfInetUtil.INSTANCE.ipv6AddressBytes(address.getIpv6Address());
204 key = Uint64.fromLongBits(ByteBuffer.wrap(ip, Long.BYTES, Long.BYTES).getLong());
205 return getConnectedEdge(key.longValue());
211 public int getEdgesSize() {
216 public List<Prefix> getPrefixes() {
217 return new ArrayList<>(this.prefixes.values());
221 public Prefix getPrefix(final IpPrefix prefix) {
222 return this.prefixes.get(prefix);
226 public ConnectedVertex addVertex(final Vertex vertex) {
227 checkArgument(vertex != null, "Provided Vertex is a null object");
228 ConnectedVertexImpl cvertex = updateConnectedVertex(vertex.getVertexId().longValue());
229 Vertex old = cvertex.getVertex();
230 this.connectedGraphServer.addVertex(this.graph, vertex, old);
231 cvertex.setVertex(vertex);
236 public void deleteVertex(final VertexKey key) {
237 checkArgument(key != null, "Provided Vertex Key is a null object");
238 ConnectedVertexImpl cvertex = vertices.get(key.getVertexId().longValue());
239 if (cvertex != null) {
240 cvertex.disconnect();
241 vertices.remove(cvertex.getKey());
242 this.connectedGraphServer.deleteVertex(this.graph, cvertex.getVertex());
243 cvertex.setVertex(null);
248 public ConnectedEdge addEdge(final Edge edge) {
249 checkArgument(edge != null, "Provided Edge is a null object");
250 ConnectedEdgeImpl cedge = updateConnectedEdge(edge.getEdgeId().longValue());
251 Edge old = cedge.getEdge();
253 ConnectedVertexImpl source = null;
254 ConnectedVertexImpl destination = null;
255 if (edge.getLocalVertexId() != null) {
256 source = updateConnectedVertex(edge.getLocalVertexId().longValue());
258 if (edge.getRemoteVertexId() != null) {
259 destination = updateConnectedVertex(edge.getRemoteVertexId().longValue());
261 connectVertices(source, destination, cedge);
263 this.connectedGraphServer.addEdge(this.graph, edge, old);
269 * Connected Edge is kept in the edges Hash Map in order to memorize the total Bandwidth reserved by
270 * Constrained Paths that belong to this Edge. Connected Edges are removed when the Connected Graph is cleared.
273 public void deleteEdge(final EdgeKey key) {
274 checkArgument(key != null, "Provided Edge Key is a null object");
275 ConnectedEdgeImpl cedge = edges.get(key.getEdgeId().longValue());
277 this.connectedGraphServer.deleteEdge(this.graph, cedge.getEdge());
284 public void addPrefix(final Prefix prefix) {
285 checkArgument(prefix != null, "Provided Prefix is a null object");
286 ConnectedVertexImpl cvertex = updateConnectedVertex(prefix.getVertexId().longValue());
287 cvertex.addPrefix(prefix);
288 prefixes.putIfAbsent(prefix.getPrefix(), prefix);
289 this.connectedGraphServer.addPrefix(this.graph, prefix);
293 public void deletePrefix(final IpPrefix ippfx) {
294 checkArgument(ippfx != null, "Provided Prefix is a null object");
295 Prefix prefix = prefixes.get(ippfx);
296 if (prefix != null) {
297 ConnectedVertexImpl cvertex = vertices.get(prefix.getVertexId().longValue());
298 if (cvertex != null) {
299 cvertex.removePrefix(prefix);
301 prefixes.remove(prefix.getPrefix());
302 this.connectedGraphServer.deletePrefix(this.graph, prefix);
307 public void clear() {
308 LOG.info("Reset Connected Graph({})", graph.getName());
309 this.vertices.clear();
311 this.prefixes.clear();
312 this.connectedGraphServer.clearGraph(this.graph);
317 public String getSummary() {
318 return vertices.size() + "/" + edges.size() + "/" + prefixes.size();
322 * Returns the name of the associated Graph.
327 public String toString() {
328 return this.graph.getName();