X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Frouting%2Fdijkstra_implementation%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Frouting%2Fdijkstra_implementation%2Finternal%2FDijkstraImplementation.java;h=07f18ff6abfaefb616371fe99d787b95e997f813;hp=64cc3fbe01045f8e2bf372fbae0ee8e360f9f908;hb=1cd3232ac46cadb97aeef5c00b93ed0a4d980c09;hpb=046c9dd2d8fef6c44e88c1bd9f6a71c687e98ec5 diff --git a/opendaylight/routing/dijkstra_implementation/src/main/java/org/opendaylight/controller/routing/dijkstra_implementation/internal/DijkstraImplementation.java b/opendaylight/routing/dijkstra_implementation/src/main/java/org/opendaylight/controller/routing/dijkstra_implementation/internal/DijkstraImplementation.java index 64cc3fbe01..07f18ff6ab 100644 --- a/opendaylight/routing/dijkstra_implementation/src/main/java/org/opendaylight/controller/routing/dijkstra_implementation/internal/DijkstraImplementation.java +++ b/opendaylight/routing/dijkstra_implementation/src/main/java/org/opendaylight/controller/routing/dijkstra_implementation/internal/DijkstraImplementation.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -17,6 +16,7 @@ */ package org.opendaylight.controller.routing.dijkstra_implementation.internal; +import org.opendaylight.controller.clustering.services.IClusterContainerServices; import org.opendaylight.controller.sal.core.Bandwidth; import org.opendaylight.controller.sal.core.ConstructionException; import org.opendaylight.controller.sal.core.Edge; @@ -25,43 +25,44 @@ import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.core.Path; import org.opendaylight.controller.sal.core.Property; import org.opendaylight.controller.sal.core.UpdateType; -import org.opendaylight.controller.sal.reader.IReadService; import org.opendaylight.controller.sal.routing.IListenRoutingUpdates; import org.opendaylight.controller.sal.routing.IRouting; +import org.opendaylight.controller.sal.topology.TopoEdgeUpdate; import org.opendaylight.controller.switchmanager.ISwitchManager; import org.opendaylight.controller.topologymanager.ITopologyManager; -import org.opendaylight.controller.topologymanager.ITopologyManagerAware; +import org.opendaylight.controller.topologymanager.ITopologyManagerClusterWideAware; import edu.uci.ics.jung.algorithms.shortestpath.DijkstraShortestPath; import edu.uci.ics.jung.graph.Graph; import edu.uci.ics.jung.graph.SparseMultigraph; import edu.uci.ics.jung.graph.util.EdgeType; -import java.lang.Exception; -import java.lang.IllegalArgumentException; + import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.ArrayList; import java.util.Set; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.commons.collections15.Transformer; -public class DijkstraImplementation implements IRouting, ITopologyManagerAware { - private static Logger log = LoggerFactory - .getLogger(DijkstraImplementation.class); +@SuppressWarnings("rawtypes") +public class DijkstraImplementation implements IRouting, ITopologyManagerClusterWideAware { + private static Logger log = LoggerFactory.getLogger(DijkstraImplementation.class); private ConcurrentMap> topologyBWAware; private ConcurrentMap> sptBWAware; - DijkstraShortestPath mtp; //Max Throughput Path + DijkstraShortestPath mtp; // Max Throughput Path private Set routingAware; private ISwitchManager switchManager; private ITopologyManager topologyManager; - private IReadService readService; private static final long DEFAULT_LINK_SPEED = Bandwidth.BW1Gbps; + private IClusterContainerServices clusterContainerService; - public void setListenRoutingUpdates(IListenRoutingUpdates i) { + public void setListenRoutingUpdates(final IListenRoutingUpdates i) { if (this.routingAware == null) { this.routingAware = new HashSet(); } @@ -71,7 +72,7 @@ public class DijkstraImplementation implements IRouting, ITopologyManagerAware { } } - public void unsetListenRoutingUpdates(IListenRoutingUpdates i) { + public void unsetListenRoutingUpdates(final IListenRoutingUpdates i) { if (this.routingAware == null) { return; } @@ -93,6 +94,7 @@ public class DijkstraImplementation implements IRouting, ITopologyManagerAware { Transformer mtTransformer = null; if (EdgeWeightMap == null) { mtTransformer = new Transformer() { + @Override public Double transform(Edge e) { if (switchManager == null) { log.error("switchManager is null"); @@ -104,36 +106,39 @@ public class DijkstraImplementation implements IRouting, ITopologyManagerAware { log.error("srcNC:{} or dstNC:{} is null", srcNC, dstNC); return (double) -1; } - Bandwidth bwSrc = (Bandwidth) switchManager - .getNodeConnectorProp(srcNC, - Bandwidth.BandwidthPropName); - Bandwidth bwDst = (Bandwidth) switchManager - .getNodeConnectorProp(dstNC, - Bandwidth.BandwidthPropName); + Bandwidth bwSrc = (Bandwidth) switchManager.getNodeConnectorProp(srcNC, + Bandwidth.BandwidthPropName); + Bandwidth bwDst = (Bandwidth) switchManager.getNodeConnectorProp(dstNC, + Bandwidth.BandwidthPropName); long srcLinkSpeed = 0, dstLinkSpeed = 0; if ((bwSrc == null) || ((srcLinkSpeed = bwSrc.getValue()) == 0)) { - log.debug("srcNC: {} - Setting srcLinkSpeed to Default!",srcNC); - srcLinkSpeed = DEFAULT_LINK_SPEED; + log.debug("srcNC: {} - Setting srcLinkSpeed to Default!", srcNC); + srcLinkSpeed = DEFAULT_LINK_SPEED; } - + if ((bwDst == null) || ((dstLinkSpeed = bwDst.getValue()) == 0)) { - log.debug("dstNC: {} - Setting dstLinkSpeed to Default!",dstNC); + log.debug("dstNC: {} - Setting dstLinkSpeed to Default!", dstNC); dstLinkSpeed = DEFAULT_LINK_SPEED; } - long avlSrcThruPut = srcLinkSpeed - - readService.getTransmitRate(srcNC); - long avlDstThruPut = dstLinkSpeed - - readService.getTransmitRate(dstNC); - - //Use lower of the 2 available thruput as the available thruput - long avlThruPut = avlSrcThruPut < avlDstThruPut ? avlSrcThruPut - : avlDstThruPut; + // TODO: revisit the logic below with the real use case in + // mind + // For now we assume the throughput to be the speed of the + // link itself + // this kind of logic require information that should be + // polled by statistic manager and are not yet available, + // also this service at the moment is not used, so to be + // revisited later on + long avlSrcThruPut = srcLinkSpeed; + long avlDstThruPut = dstLinkSpeed; + + // Use lower of the 2 available throughput as the available + // throughput + long avlThruPut = avlSrcThruPut < avlDstThruPut ? avlSrcThruPut : avlDstThruPut; if (avlThruPut <= 0) { - log.debug("Edge {}: Available Throughput {} <= 0!", - e, avlThruPut); + log.debug("Edge {}: Available Throughput {} <= 0!", e, avlThruPut); return (double) -1; } return (double) (Bandwidth.BW1Pbps / avlThruPut); @@ -141,13 +146,14 @@ public class DijkstraImplementation implements IRouting, ITopologyManagerAware { }; } else { mtTransformer = new Transformer() { + @Override public Number transform(Edge e) { return EdgeWeightMap.get(e); } }; } Short baseBW = Short.valueOf((short) 0); - //Initialize mtp also using the default topo + // Initialize mtp also using the default topo Graph g = this.topologyBWAware.get(baseBW); if (g == null) { log.error("Default Topology Graph is null"); @@ -157,8 +163,8 @@ public class DijkstraImplementation implements IRouting, ITopologyManagerAware { } @Override - public Path getRoute(Node src, Node dst) { - if (src == null || dst == null) { + public Path getRoute(final Node src, final Node dst) { + if ((src == null) || (dst == null)) { return null; } return getRoute(src, dst, (short) 0); @@ -175,40 +181,37 @@ public class DijkstraImplementation implements IRouting, ITopologyManagerAware { try { path = mtp.getMaxThroughputPath(src, dst); } catch (IllegalArgumentException ie) { - log.debug("A vertex is yet not known between {} {}", src.toString(), - dst.toString()); + log.debug("A vertex is yet not known between {} {}", src, dst); return null; } Path res; try { res = new Path(path); } catch (ConstructionException e) { - log.debug("A vertex is yet not known between {} {}", src.toString(), - dst.toString()); + log.debug("A vertex is yet not known between {} {}", src, dst); return null; } return res; } @Override - public synchronized Path getRoute(Node src, Node dst, Short Bw) { + public synchronized Path getRoute(final Node src, final Node dst, final Short Bw) { DijkstraShortestPath spt = this.sptBWAware.get(Bw); - if (spt == null) + if (spt == null) { return null; + } List path; try { path = spt.getPath(src, dst); } catch (IllegalArgumentException ie) { - log.debug("A vertex is yet not known between {} {}", src.toString(), - dst.toString()); + log.debug("A vertex is yet not known between {} {}", src, dst); return null; } Path res; try { res = new Path(path); } catch (ConstructionException e) { - log.debug("A vertex is yet not known between {} {}", src.toString(), - dst.toString()); + log.debug("A vertex is yet not known between {} {}", src, dst); return null; } return res; @@ -229,12 +232,12 @@ public class DijkstraImplementation implements IRouting, ITopologyManagerAware { @Override public synchronized void clearMaxThroughput() { if (mtp != null) { - mtp.reset(); //reset maxthruput path + mtp.reset(); // reset max throughput path } } - @SuppressWarnings( { "rawtypes", "unchecked" }) - private synchronized boolean updateTopo(Edge edge, Short bw, boolean added) { + @SuppressWarnings({ "unchecked" }) + private synchronized boolean updateTopo(Edge edge, Short bw, UpdateType type) { Graph topo = this.topologyBWAware.get(bw); DijkstraShortestPath spt = this.sptBWAware.get(bw); boolean edgePresentInGraph = false; @@ -257,7 +260,8 @@ public class DijkstraImplementation implements IRouting, ITopologyManagerAware { this.sptBWAware.put(bw, spt); } - if (added) { + switch (type) { + case ADDED: // Make sure the vertex are there before adding the edge topo.addVertex(src.getNode()); topo.addVertex(dst.getNode()); @@ -265,38 +269,39 @@ public class DijkstraImplementation implements IRouting, ITopologyManagerAware { edgePresentInGraph = topo.containsEdge(edge); if (edgePresentInGraph == false) { try { - topo.addEdge(new Edge(src, dst), src - .getNode(), dst - .getNode(), EdgeType.DIRECTED); - } catch (ConstructionException e) { - e.printStackTrace(); + topo.addEdge(new Edge(src, dst), src.getNode(), dst.getNode(), EdgeType.DIRECTED); + } catch (final ConstructionException e) { + log.error("", e); return edgePresentInGraph; } } - } else { - //Remove the edge + case CHANGED: + // Mainly raised only on properties update, so not really useful + // in this case + break; + case REMOVED: + // Remove the edge try { topo.removeEdge(new Edge(src, dst)); - } catch (ConstructionException e) { - e.printStackTrace(); + } catch (final ConstructionException e) { + log.error("", e); return edgePresentInGraph; } // If the src and dst vertex don't have incoming or // outgoing links we can get ride of them - if (topo.containsVertex(src.getNode()) - && topo.inDegree(src.getNode()) == 0 - && topo.outDegree(src.getNode()) == 0) { + if (topo.containsVertex(src.getNode()) && (topo.inDegree(src.getNode()) == 0) + && (topo.outDegree(src.getNode()) == 0)) { log.debug("Removing vertex {}", src); topo.removeVertex(src.getNode()); } - if (topo.containsVertex(dst.getNode()) - && topo.inDegree(dst.getNode()) == 0 - && topo.outDegree(dst.getNode()) == 0) { + if (topo.containsVertex(dst.getNode()) && (topo.inDegree(dst.getNode()) == 0) + && (topo.outDegree(dst.getNode()) == 0)) { log.debug("Removing vertex {}", dst); topo.removeVertex(dst.getNode()); } + break; } spt.reset(); if (bw.equals(baseBW)) { @@ -308,55 +313,83 @@ public class DijkstraImplementation implements IRouting, ITopologyManagerAware { return edgePresentInGraph; } - @Override - public void edgeUpdate(Edge e, UpdateType type, Set props) { + private boolean edgeUpdate(Edge e, UpdateType type, Set props, boolean local) { String srcType = null; String dstType = null; - if (e == null || type == null) { + log.trace("Got an edgeUpdate: {} props: {} update type: {} local: {}", new Object[] { e, props, type, local }); + + if ((e == null) || (type == null)) { log.error("Edge or Update type are null!"); - return; + return false; } else { srcType = e.getTailNodeConnector().getType(); dstType = e.getHeadNodeConnector().getType(); if (srcType.equals(NodeConnector.NodeConnectorIDType.PRODUCTION)) { log.debug("Skip updates for {}", e); - return; + return false; } if (dstType.equals(NodeConnector.NodeConnectorIDType.PRODUCTION)) { log.debug("Skip updates for {}", e); - return; + return false; } } Bandwidth bw = new Bandwidth(0); boolean newEdge = false; - if (props != null) + if (props != null) { props.remove(bw); - - log.debug("edgeUpdate: {} bw: {}", e.toString(), bw.getValue()); + } Short baseBW = Short.valueOf((short) 0); - boolean add = (type == UpdateType.ADDED) ? true : false; // Update base topo - newEdge = !updateTopo(e, baseBW, add); + newEdge = !updateTopo(e, baseBW, type); if (newEdge == true) { if (bw.getValue() != baseBW) { // Update BW topo - updateTopo(e, (short) bw.getValue(), add); + updateTopo(e, (short) bw.getValue(), type); } - if (this.routingAware != null) { - for (IListenRoutingUpdates ra : this.routingAware) { - try { - ra.recalculateDone(); - } catch (Exception ex) { - log.error("Exception on routingAware listener call", e); - } + } + return newEdge; + } + + @Override + public void edgeUpdate(List topoedgeupdateList) { + log.trace("Start of a Bulk EdgeUpdate with " + topoedgeupdateList.size() + " elements"); + boolean callListeners = false; + for (int i = 0; i < topoedgeupdateList.size(); i++) { + Edge e = topoedgeupdateList.get(i).getEdge(); + Set p = topoedgeupdateList.get(i) + .getProperty(); + UpdateType type = topoedgeupdateList.get(i) + .getUpdateType(); + boolean isLocal = topoedgeupdateList.get(i) + .isLocal(); + if ((edgeUpdate(e, type, p, isLocal)) && (!callListeners)) { + callListeners = true; + } + } + + // The routing listeners should only be called on the coordinator, to + // avoid multiple controller cluster nodes to actually do the + // recalculation when only one need to react + boolean amICoordinator = true; + if (this.clusterContainerService != null) { + amICoordinator = this.clusterContainerService.amICoordinator(); + } + if ((callListeners) && (this.routingAware != null) && amICoordinator) { + log.trace("Calling the routing listeners"); + for (IListenRoutingUpdates ra : this.routingAware) { + try { + ra.recalculateDone(); + } catch (Exception ex) { + log.error("Exception on routingAware listener call", ex); } } } + log.trace("End of a Bulk EdgeUpdate"); } /** @@ -366,17 +399,18 @@ public class DijkstraImplementation implements IRouting, ITopologyManagerAware { */ @SuppressWarnings({ "unchecked", "rawtypes" }) public void init() { - log.debug("Routing init() is called"); - this.topologyBWAware = (ConcurrentMap>) new ConcurrentHashMap(); - this.sptBWAware = (ConcurrentMap>) new ConcurrentHashMap(); - // Now create the default topology, which doesn't consider the - // BW, also create the corresponding Dijkstra calculation - Graph g = new SparseMultigraph(); - Short sZero = Short.valueOf((short) 0); - this.topologyBWAware.put(sZero, g); - this.sptBWAware.put(sZero, new DijkstraShortestPath(g)); - // Topologies for other BW will be added on a needed base + log.debug("Routing init() is called"); + this.topologyBWAware = new ConcurrentHashMap>(); + this.sptBWAware = new ConcurrentHashMap>(); + // Now create the default topology, which doesn't consider the + // BW, also create the corresponding Dijkstra calculation + Graph g = new SparseMultigraph(); + Short sZero = Short.valueOf((short) 0); + this.topologyBWAware.put(sZero, g); + this.sptBWAware.put(sZero, new DijkstraShortestPath(g)); + // Topologies for other BW will be added on a needed base } + /** * Function called by the dependency manager when at least one dependency * become unsatisfied or when the component is shutting down because for @@ -384,30 +418,34 @@ public class DijkstraImplementation implements IRouting, ITopologyManagerAware { * */ void destroy() { - log.debug("Routing destroy() is called"); + log.debug("Routing destroy() is called"); } /** - * Function called by dependency manager after "init ()" is called - * and after the services provided by the class are registered in - * the service registry + * Function called by dependency manager after "init ()" is called and after + * the services provided by the class are registered in the service registry * */ - void start() { - log.debug("Routing start() is called"); - // build the routing database from the topology if it exists. - Map> edges = topologyManager.getEdges(); - if (edges.isEmpty()) { - return; - } - log.debug("Creating routing database from the topology"); - for (Iterator>> i = edges.entrySet().iterator(); i.hasNext();) { - Map.Entry> entry = i.next(); - Edge e = entry.getKey(); - Set props = entry.getValue(); - edgeUpdate(e, UpdateType.ADDED, props); - } - } + void start() { + log.debug("Routing start() is called"); + // build the routing database from the topology if it exists. + Map> edges = topologyManager.getEdges(); + if (edges.isEmpty()) { + return; + } + List topoedgeupdateList = new ArrayList(); + log.debug("Creating routing database from the topology"); + for (Iterator>> i = edges.entrySet() + .iterator(); i.hasNext();) { + Map.Entry> entry = i.next(); + Edge e = entry.getKey(); + Set props = entry.getValue(); + TopoEdgeUpdate topoedgeupdate = new TopoEdgeUpdate(e, props, + UpdateType.ADDED); + topoedgeupdateList.add(topoedgeupdate); + } + edgeUpdate(topoedgeupdateList); + } /** * Function called by the dependency manager before the services exported by @@ -415,20 +453,8 @@ public class DijkstraImplementation implements IRouting, ITopologyManagerAware { * calls * */ - public void stop() { - log.debug("Routing stop() is called"); - } - - @Override - public void edgeOverUtilized(Edge edge) { - // TODO Auto-generated method stub - - } - - @Override - public void edgeUtilBackToNormal(Edge edge) { - // TODO Auto-generated method stub - + public void stop() { + log.debug("Routing stop() is called"); } public void setSwitchManager(ISwitchManager switchManager) { @@ -441,23 +467,37 @@ public class DijkstraImplementation implements IRouting, ITopologyManagerAware { } } - public void setReadService(IReadService readService) { - this.readService = readService; + public void setTopologyManager(ITopologyManager tm) { + this.topologyManager = tm; } - public void unsetReadService(IReadService readService) { - if (this.readService == readService) { - this.readService = null; + public void unsetTopologyManager(ITopologyManager tm) { + if (this.topologyManager == tm) { + this.topologyManager = null; } } - - public void setTopologyManager(ITopologyManager tm) { - this.topologyManager = tm; + + void setClusterContainerService(IClusterContainerServices s) { + log.debug("Cluster Service set"); + this.clusterContainerService = s; } - - public void unsetTopologyManager(ITopologyManager tm) { - if (this.topologyManager == tm) { - this.topologyManager = null; - } + + void unsetClusterContainerService(IClusterContainerServices s) { + if (this.clusterContainerService == s) { + log.debug("Cluster Service removed!"); + this.clusterContainerService = null; + } + } + + @Override + public void edgeOverUtilized(Edge edge) { + // TODO Auto-generated method stub + + } + + @Override + public void edgeUtilBackToNormal(Edge edge) { + // TODO Auto-generated method stub + } }