* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-
package org.opendaylight.graph.impl;
import static com.google.common.base.Preconditions.checkArgument;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.graph.ConnectedEdge;
+import org.opendaylight.graph.ConnectedEdgeTrigger;
import org.opendaylight.graph.ConnectedGraph;
+import org.opendaylight.graph.ConnectedGraphTrigger;
import org.opendaylight.graph.ConnectedVertex;
+import org.opendaylight.graph.ConnectedVertexTrigger;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.Graph;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.Edge;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.EdgeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.Prefix;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.Vertex;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev191125.graph.topology.graph.VertexKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.Graph;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.Edge;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.EdgeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.Vertex;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.VertexKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* @author Olivier Dugeon
* @author Philippe Niger
*/
-
-
public class ConnectedGraphImpl implements ConnectedGraph {
-
private static final Logger LOG = LoggerFactory.getLogger(ConnectedGraphImpl.class);
- /* List of Connected Vertics that composed this Connected Graph */
+ /* List of Connected Vertices that composed this Connected Graph */
private final HashMap<Long, ConnectedVertexImpl> vertices = new HashMap<>();
/* List of Connected Edges that composed this Connected Graph */
/* List of IP prefix attached to Vertices */
private final HashMap<IpPrefix, Prefix> prefixes = new HashMap<>();
+ /* List of Triggers attached to the Connected Graph */
+ private final ConcurrentHashMap<TopologyKey, ConnectedGraphTrigger> graphTriggers = new ConcurrentHashMap<>();
+ private final ListeningExecutorService exec = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
+
/* Reference to the non connected Graph stored in DataStore */
private Graph graph;
/* Reference to Graph Model Server to store corresponding graph in DataStore */
private final ConnectedGraphServer connectedGraphServer;
- public ConnectedGraphImpl(Graph newGraph, ConnectedGraphServer server) {
+ public ConnectedGraphImpl(final Graph newGraph, final ConnectedGraphServer server) {
this.graph = newGraph;
createConnectedGraph();
this.connectedGraphServer = server;
return;
}
/* Add all vertices */
- if (this.graph.getVertex() != null) {
- for (Vertex vertex : this.graph.getVertex()) {
- ConnectedVertexImpl cvertex = new ConnectedVertexImpl(vertex);
- vertices.put(cvertex.getKey(), cvertex);
- }
+ for (Vertex vertex : this.graph.nonnullVertex().values()) {
+ ConnectedVertexImpl cvertex = new ConnectedVertexImpl(vertex);
+ vertices.put(cvertex.getKey(), cvertex);
}
/* Add all edges */
- if (this.graph.getEdge() != null) {
- for (Edge edge : this.graph.getEdge()) {
- ConnectedEdgeImpl cedge = new ConnectedEdgeImpl(edge);
- edges.put(cedge.getKey(), cedge);
- }
+ for (Edge edge : this.graph.nonnullEdge().values()) {
+ ConnectedEdgeImpl cedge = new ConnectedEdgeImpl(edge);
+ edges.put(cedge.getKey(), cedge);
}
/* Add all prefixes */
- if (this.graph.getPrefix() != null) {
- for (Prefix prefix : this.graph.getPrefix()) {
- ConnectedVertexImpl cvertex = vertices.get(prefix.getVertexId().longValue());
- if (cvertex != null) {
- cvertex.addPrefix(prefix);
- }
- prefixes.putIfAbsent(prefix.getPrefix(), prefix);
+ for (Prefix prefix : this.graph.nonnullPrefix().values()) {
+ ConnectedVertexImpl cvertex = vertices.get(prefix.getVertexId().longValue());
+ if (cvertex != null) {
+ cvertex.addPrefix(prefix);
}
+ prefixes.putIfAbsent(prefix.getPrefix(), prefix);
}
}
* @param key Unique Vertex Key identifier
* @return new or existing Connected Vertex
*/
- private ConnectedVertexImpl updateConnectedVertex(@NonNull Long key) {
+ private ConnectedVertexImpl updateConnectedVertex(final @NonNull Long key) {
checkArgument(key != 0, "Provided Vertex Key must not be equal to 0");
ConnectedVertexImpl vertex = vertices.get(key);
if (vertex == null) {
* @param key Unique Edge Key identifier
* @return new or existing Connected Edge
*/
- private ConnectedEdgeImpl updateConnectedEdge(@NonNull Long key) {
+ private ConnectedEdgeImpl updateConnectedEdge(final @NonNull Long key) {
checkArgument(key != 0, "Provided Edge Key must not be equal to 0");
ConnectedEdgeImpl edge = edges.get(key);
if (edge == null) {
* @param dstVertex Destination Connected Vertex
* @param edge Connected Edge
*/
- private void connectVertices(ConnectedVertexImpl srcVertex, ConnectedVertexImpl dstVertex, ConnectedEdgeImpl edge) {
+ private static void connectVertices(final ConnectedVertexImpl srcVertex, final ConnectedVertexImpl dstVertex,
+ final ConnectedEdgeImpl edge) {
if (edge != null) {
edge.setSource(srcVertex);
edge.setDestination(dstVertex);
@Override
public List<ConnectedVertex> getVertices() {
- return new ArrayList<ConnectedVertex>(this.vertices.values());
+ return new ArrayList<>(this.vertices.values());
}
@Override
- public ConnectedVertex getConnectedVertex(@NonNull Long key) {
+ public ConnectedVertex getConnectedVertex(final Long key) {
return vertices.get(key);
}
@Override
- public ConnectedVertex getConnectedVertex(IpAddress address) {
+ public ConnectedVertex getConnectedVertex(final IpAddress address) {
+ if (address == null) {
+ return null;
+ }
IpPrefix prefix = null;
if (address.getIpv4Address() != null) {
prefix = new IpPrefix(new Ipv4Prefix(address.getIpv4Address().getValue() + "/32"));
@Override
public List<ConnectedEdge> getEdges() {
- return new ArrayList<ConnectedEdge>(this.edges.values());
+ return new ArrayList<>(this.edges.values());
}
@Override
- public ConnectedEdge getConnectedEdge(@NonNull Long key) {
+ public ConnectedEdge getConnectedEdge(final Long key) {
return edges.get(key);
}
@Override
- public ConnectedEdge getConnectedEdge(IpAddress address) {
- for (ConnectedEdge cedge : edges.values()) {
- if (cedge.getEdge() == null) {
- continue;
- }
- if (cedge.getEdge().getEdgeAttributes().getLocalAddress().equals(address)) {
- return cedge;
- }
+ public ConnectedEdge getConnectedEdge(final IpAddress address) {
+ if (address == null) {
+ return null;
+ }
+ if (address.getIpv4Address() != null) {
+ return getConnectedEdge(address.getIpv4Address());
+ }
+ if (address.getIpv6Address() != null) {
+ return getConnectedEdge(address.getIpv6Address());
}
return null;
}
+ @Override
+ public ConnectedEdge getConnectedEdge(final Ipv4Address address) {
+ if (address == null) {
+ return null;
+ }
+ final Uint64 key = Uint32.fromIntBits(IetfInetUtil.INSTANCE.ipv4AddressBits(address)).toUint64();
+ return getConnectedEdge(key.longValue());
+ }
+
+ @Override
+ public ConnectedEdge getConnectedEdge(final Ipv6Address address) {
+ if (address == null) {
+ return null;
+ }
+ final byte[] ip = IetfInetUtil.INSTANCE.ipv6AddressBytes(address);
+ final Uint64 key = Uint64.fromLongBits(ByteBuffer.wrap(ip, Long.BYTES, Long.BYTES).getLong());
+ return getConnectedEdge(key.longValue());
+ }
+
@Override
public int getEdgesSize() {
return edges.size();
@Override
public List<Prefix> getPrefixes() {
- return new ArrayList<Prefix>(this.prefixes.values());
+ return new ArrayList<>(this.prefixes.values());
}
@Override
- public Prefix getPrefix(IpPrefix prefix) {
+ public Prefix getPrefix(final IpPrefix prefix) {
return this.prefixes.get(prefix);
}
+ private void callVertexTrigger(ConnectedVertexImpl cvertex, Vertex vertex) {
+ List<ConnectedVertexTrigger> vertexTriggers = cvertex.getTriggers();
+ if (vertexTriggers == null || vertexTriggers.isEmpty()) {
+ return;
+ }
+ for (ConnectedGraphTrigger trigger : graphTriggers.values()) {
+ this.exec.submit(() -> trigger.verifyVertex(vertexTriggers, cvertex, vertex));
+ }
+ }
+
@Override
- public ConnectedVertex addVertex(Vertex vertex) {
+ public ConnectedVertex addVertex(final Vertex vertex) {
checkArgument(vertex != null, "Provided Vertex is a null object");
ConnectedVertexImpl cvertex = updateConnectedVertex(vertex.getVertexId().longValue());
Vertex old = cvertex.getVertex();
this.connectedGraphServer.addVertex(this.graph, vertex, old);
cvertex.setVertex(vertex);
+ if (old != null) {
+ callVertexTrigger(cvertex, old);
+ }
return cvertex;
}
@Override
- public void deleteVertex(VertexKey key) {
+ public void deleteVertex(final VertexKey key) {
checkArgument(key != null, "Provided Vertex Key is a null object");
ConnectedVertexImpl cvertex = vertices.get(key.getVertexId().longValue());
if (cvertex != null) {
vertices.remove(cvertex.getKey());
this.connectedGraphServer.deleteVertex(this.graph, cvertex.getVertex());
cvertex.setVertex(null);
+ callVertexTrigger(cvertex, null);
+ }
+ }
+
+ private void callEdgeTrigger(ConnectedEdgeImpl cedge, Edge edge) {
+ List<ConnectedEdgeTrigger> edgeTriggers = cedge.getTriggers();
+ if (edgeTriggers == null || edgeTriggers.isEmpty()) {
+ return;
+ }
+ for (ConnectedGraphTrigger trigger : graphTriggers.values()) {
+ this.exec.submit(() -> trigger.verifyEdge(edgeTriggers, cedge, edge));
}
}
@Override
- public ConnectedEdge addEdge(Edge edge) {
+ public ConnectedEdge addEdge(final Edge edge) {
checkArgument(edge != null, "Provided Edge is a null object");
ConnectedEdgeImpl cedge = updateConnectedEdge(edge.getEdgeId().longValue());
Edge old = cedge.getEdge();
}
this.connectedGraphServer.addEdge(this.graph, edge, old);
cedge.setEdge(edge);
+ callEdgeTrigger(cedge, old);
return cedge;
}
+ /**
+ * Connected Edge is kept in the edges Hash Map in order to memorize the total Bandwidth reserved by
+ * Constrained Paths that belong to this Edge. Connected Edges are removed when the Connected Graph is cleared.
+ */
@Override
- public void deleteEdge(EdgeKey key) {
+ public void deleteEdge(final EdgeKey key) {
checkArgument(key != null, "Provided Edge Key is a null object");
ConnectedEdgeImpl cedge = edges.get(key.getEdgeId().longValue());
if (cedge != null) {
this.connectedGraphServer.deleteEdge(this.graph, cedge.getEdge());
cedge.disconnect();
- edges.remove(cedge.getKey());
cedge.setEdge(null);
+ callEdgeTrigger(cedge, null);
}
}
@Override
- public void addPrefix(Prefix prefix) {
+ public void addPrefix(final Prefix prefix) {
checkArgument(prefix != null, "Provided Prefix is a null object");
ConnectedVertexImpl cvertex = updateConnectedVertex(prefix.getVertexId().longValue());
cvertex.addPrefix(prefix);
}
@Override
- public void deletePrefix(IpPrefix ippfx) {
+ public void deletePrefix(final IpPrefix ippfx) {
checkArgument(ippfx != null, "Provided Prefix is a null object");
Prefix prefix = prefixes.get(ippfx);
if (prefix != null) {
return vertices.size() + "/" + edges.size() + "/" + prefixes.size();
}
+ @Override
+ public boolean registerTrigger(ConnectedGraphTrigger trigger, TopologyKey key) {
+ return graphTriggers.putIfAbsent(key, trigger) == null;
+ }
+
+ @Override
+ public boolean unRegisterTrigger(ConnectedGraphTrigger trigger, TopologyKey key) {
+ return graphTriggers.remove(key, trigger);
+ }
+
/**
* Returns the name of the associated Graph.
*