diff --git a/pom.xml b/pom.xml index 769818f9a6b3305e7d74768c5bf5cd31f76e6513..2922f5c20b09e50fd17850442468033891c92467 100644 --- a/pom.xml +++ b/pom.xml @@ -112,7 +112,7 @@ simonstrator - http://dev.kom.e-technik.tu-darmstadt.de/mvn/ + https://dev.kom.e-technik.tu-darmstadt.de/mvn/ diff --git a/src/de/tud/kom/p2psim/api/topology/TopologyComponent.java b/src/de/tud/kom/p2psim/api/topology/TopologyComponent.java index fbb8b3a3fcfe9046522b1ad5212e88beb7778556..cfdefcb64ab4060ab7cbbd48738d74256c2e9be0 100644 --- a/src/de/tud/kom/p2psim/api/topology/TopologyComponent.java +++ b/src/de/tud/kom/p2psim/api/topology/TopologyComponent.java @@ -26,6 +26,8 @@ import de.tud.kom.p2psim.api.energy.EnergyComponent; import de.tud.kom.p2psim.api.topology.movement.MovementListener; import de.tud.kom.p2psim.api.topology.movement.MovementSupported; import de.tud.kom.p2psim.api.topology.views.TopologyView; +import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationSensor; +import de.tudarmstadt.maki.simonstrator.api.component.topology.UnderlayTopologyProvider; /** * One component for each host, holding the position. These are maintained @@ -36,7 +38,7 @@ import de.tud.kom.p2psim.api.topology.views.TopologyView; * @version 1.0, 21.02.2012 */ public interface TopologyComponent extends SimHostComponent, MovementSupported, - MovementListener { + MovementListener, UnderlayTopologyProvider, LocationSensor { /** * Abstract QoS-Classes for the Accuracy of the position. Implementation diff --git a/src/de/tud/kom/p2psim/api/topology/views/TopologyView.java b/src/de/tud/kom/p2psim/api/topology/views/TopologyView.java index e58f0b080c834a9b16fd2bf993b1d14583f5cbcb..4ade565fd3eccb0b0ca062f2ec7afb856d715549 100644 --- a/src/de/tud/kom/p2psim/api/topology/views/TopologyView.java +++ b/src/de/tud/kom/p2psim/api/topology/views/TopologyView.java @@ -20,6 +20,7 @@ package de.tud.kom.p2psim.api.topology.views; +import java.util.Collection; import java.util.List; import de.tud.kom.p2psim.api.common.Position; @@ -104,6 +105,12 @@ public interface TopologyView extends TopologyListener, MovementListener { * @return an unmodifiable view on the current neighbors */ public List getNeighbors(MacAddress address); + + /** + * Returns all MACs that are currently in the TopologyView. + * @return + */ + public Collection getAllMacs(); /** * Gets the real Position of the host. diff --git a/src/de/tud/kom/p2psim/impl/churn/ConstantPeerCountChurnModel.java b/src/de/tud/kom/p2psim/impl/churn/ConstantPeerCountChurnModel.java index 3ae729ae134263aa28ddddf55e2880c8a8250679..f67d31ffd9e81f1e36f49e5916ea3dff7c46a159 100644 --- a/src/de/tud/kom/p2psim/impl/churn/ConstantPeerCountChurnModel.java +++ b/src/de/tud/kom/p2psim/impl/churn/ConstantPeerCountChurnModel.java @@ -164,6 +164,7 @@ public class ConstantPeerCountChurnModel implements ChurnModel { clientSessionInfos.put(host.getHostId(), info); if (hasFlashcrowd && !flashCrowdFinished && currentJoin > flashcrowdStart) { + currentJoin = flashcrowdStart; inFlashcrowd = true; } lastJoin = currentJoin; @@ -187,6 +188,7 @@ public class ConstantPeerCountChurnModel implements ChurnModel { clientSessionInfos.put(host.getHostId(), info); if (hasFlashcrowd && !flashCrowdFinished && currentJoin > flashcrowdStart) { + currentJoin = flashcrowdStart; inFlashcrowd = true; } lastJoin = currentJoin; diff --git a/src/de/tud/kom/p2psim/impl/topology/DefaultTopologyComponent.java b/src/de/tud/kom/p2psim/impl/topology/DefaultTopologyComponent.java index d3208fc39dcaad6ca974134e88f122b8db574a88..973b0268b26230303c3e5df6b9a5a42cad6e6f38 100644 --- a/src/de/tud/kom/p2psim/impl/topology/DefaultTopologyComponent.java +++ b/src/de/tud/kom/p2psim/impl/topology/DefaultTopologyComponent.java @@ -22,6 +22,7 @@ package de.tud.kom.p2psim.impl.topology; import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; @@ -29,19 +30,32 @@ import java.util.Set; import de.tud.kom.p2psim.api.common.HostProperties; import de.tud.kom.p2psim.api.common.Position; import de.tud.kom.p2psim.api.common.SimHost; +import de.tud.kom.p2psim.api.linklayer.mac.MacAddress; +import de.tud.kom.p2psim.api.linklayer.mac.MacLayer; +import de.tud.kom.p2psim.api.linklayer.mac.PhyType; import de.tud.kom.p2psim.api.topology.Topology; import de.tud.kom.p2psim.api.topology.TopologyComponent; import de.tud.kom.p2psim.api.topology.movement.MovementListener; import de.tud.kom.p2psim.api.topology.movement.MovementSupported; import de.tud.kom.p2psim.api.topology.movement.PositionListener; import de.tud.kom.p2psim.api.topology.placement.PlacementModel; +import de.tud.kom.p2psim.api.topology.views.TopologyView; import de.tud.kom.p2psim.impl.simengine.Simulator; import de.tud.kom.p2psim.impl.topology.movement.modular.attraction.AttractionPoint; +import de.tudarmstadt.maki.simonstrator.api.Graphs; +import de.tudarmstadt.maki.simonstrator.api.Host; import de.tudarmstadt.maki.simonstrator.api.Randoms; +import de.tudarmstadt.maki.simonstrator.api.common.graph.DirectedEdge; +import de.tudarmstadt.maki.simonstrator.api.common.graph.Graph; +import de.tudarmstadt.maki.simonstrator.api.common.graph.Node; +import de.tudarmstadt.maki.simonstrator.api.component.network.NetInterface; +import de.tudarmstadt.maki.simonstrator.api.component.network.NetworkComponent.NetInterfaceName; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationListener; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationRequest; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationSensor; +import de.tudarmstadt.maki.simonstrator.api.component.topology.TopologyID; +import de.tudarmstadt.maki.simonstrator.api.component.transport.ConnectivityListener; import de.tudarmstadt.maki.simonstrator.api.operation.Operations; import de.tudarmstadt.maki.simonstrator.api.operation.PeriodicOperation; @@ -51,8 +65,8 @@ import de.tudarmstadt.maki.simonstrator.api.operation.PeriodicOperation; * @author Bjoern Richerzhagen * @version 1.0, 29.02.2012 */ -public class DefaultTopologyComponent implements TopologyComponent, - LocationSensor { +public class DefaultTopologyComponent implements TopologyComponent { + protected static Random rnd = Randoms.getRandom(AttractionPoint.class); private SimHost host; @@ -290,4 +304,242 @@ public class DefaultTopologyComponent implements TopologyComponent, } + /* + * Methods for the Graph Interface + */ + + /** + * Graph views: static, as we use global knowledge and maintain one shared + * graph (potentially with partitions!) + */ + private final static LinkedHashMap graphViews = new LinkedHashMap<>(); + + @Override + public TopologyID getTopologyID(NetInterfaceName netName, boolean onlyOnline) { + TopologyID id = TopologyID.getIdentifier(netName.toString() + + (onlyOnline ? "-online" : "-all"), + DefaultTopologyComponent.class); + if (!this.graphViews.containsKey(id)) { + this.graphViews.put(id, new LocalGraphView(netName, onlyOnline)); + } + return id; + } + + @Override + public TopologyID getTopologyID(NetInterfaceName netName, + boolean onlyOnline, double range) { + TopologyID id = TopologyID.getIdentifier(netName.toString() + + (onlyOnline ? "-online" : "-all") + String.valueOf(range), + DefaultTopologyComponent.class); + if (!this.graphViews.containsKey(id)) { + this.graphViews.put(id, new LocalGraphView(netName, onlyOnline, + range)); + } + return id; + } + + @Override + public Node getNode(TopologyID identifier) { + assert graphViews.containsKey(identifier); + return graphViews.get(identifier).getOwnNode(host); + } + + @Override + public Set getNeighbors(TopologyID topologyIdentifier) { + assert graphViews.containsKey(topologyIdentifier); + return graphViews.get(topologyIdentifier).getNeighbors(host); + } + + @Override + public Graph getLocalView(TopologyID topologyIdentifier) { + assert graphViews.containsKey(topologyIdentifier); + return graphViews.get(topologyIdentifier).getLocalView(); + } + + @Override + public Iterable getTopologyIdentifiers() { + return graphViews.keySet(); + } + + /** + * This is calculated based on global knowledge. It only registers as + * {@link MovementListener}, if a range is specified by the Provider. + * + * @author Bjoern Richerzhagen + * @version 1.0, May 13, 2015 + */ + private class LocalGraphView implements MovementListener, + ConnectivityListener { + + /** + * Marker: has there been any movement since the graph view was last + * requested? If so: recalculate! Otherwise, we ignore this object to + * not perform calculations if no one is interested... + */ + private final double distance; + + private final boolean isDistanceBased; + + private final NetInterfaceName medium; + + private final TopologyView topoView; + + private final boolean onlyOnline; + + private Graph currentView; + + private boolean isInvalid = true; + + private final PhyType phy; + + public LocalGraphView(NetInterfaceName medium, boolean onlyOnline) { + this(medium, onlyOnline, -1); + } + + public LocalGraphView(NetInterfaceName medium, boolean onlyOnline, + double distance) { + this.medium = medium; + PhyType localPhy = null; + for (PhyType currPhy : PhyType.values()) { + if (currPhy.getNetInterfaceName() == medium) { + localPhy = currPhy; + break; + } + } + phy = localPhy; + assert localPhy != null; + this.topoView = getTopology().getTopologyView(localPhy); + this.distance = distance; + this.onlyOnline = onlyOnline; + this.isDistanceBased = (distance > 0); + assert !isDistanceBased || phy.isBroadcastMedium(); + if (phy.isBroadcastMedium()) { + // register as listener for movement + addMovementListener(LocalGraphView.this); + } + // register as listener for online/offline events + if (onlyOnline) { + getHost().getNetworkComponent().getByName(medium) + .addConnectivityListener(LocalGraphView.this); + } + } + + private void recalculateLocalView() { + if (!isInvalid) { + /* + * Graphs are invalidated (i) based on movement, IFF a range was + * specified, (ii) based on online/offline events, IFF only + * online hosts are to be considered. + */ + return; + } + /* + * Calculate a complete global connectivity graph + */ + + // Create new, empty graph + currentView = Graphs.createGraph(); + + // Add all (online?) nodes + for (MacLayer mac : topoView.getAllMacs()) { + if (!onlyOnline || mac.isOnline()) { + currentView.createAndAddNode(mac.getHost().getHostId()); + } + } + + if (isDistanceBased) { + // Build neighbors solely based on an assumed range + for (MacLayer mac : topoView.getAllMacs()) { + // Add neighbors + Node currentNode = currentView.createNode(mac + .getMacAddress()); + // Consider all nodes as potential neighbors + for (MacLayer neighborMac : topoView.getAllMacs()) { + // create, but do NOT add the node object + Node neighbor = currentView.createNode(neighborMac + .getMacAddress()); + // only online nodes (already in graph) + if (!onlyOnline || currentView.contains(neighbor)) { + // Distance? + if (topoView.getDistance(mac.getMacAddress(), + neighborMac.getMacAddress()) <= distance) { + currentView.createAndAddEdge(currentNode, + neighbor); + } + } + } + } + } else { + // Build neighborhoods based on underlay neighbors (1-hop) + for (MacLayer mac : topoView.getAllMacs()) { + // Add neighbors + Node currentNode = currentView.createNode(mac + .getMacAddress()); + // Rely on underlay for neighbors + List neighbors = topoView.getNeighbors(mac + .getMacAddress()); + for (MacAddress neighborMac : neighbors) { + // create, but do NOT add the node object + Node neighbor = currentView.createNode(neighborMac); + // only online nodes (already in graph) + if (!onlyOnline || currentView.contains(neighbor)) { + currentView.createAndAddEdge(currentNode, neighbor); + } + } + } + } + + isInvalid = false; + } + + public Node getOwnNode(SimHost ownHost) { + MacLayer mac = ownHost.getLinkLayer().getMac(phy); + if (!onlyOnline || mac.isOnline()) { + return currentView.createNode(ownHost.getLinkLayer() + .getMac(phy).getMacAddress()); + } + return null; + } + + public Set getNeighbors(SimHost ownHost) { + recalculateLocalView(); + Node ownNode = getOwnNode(ownHost); + return currentView.getOutgoingEdges(ownNode); + } + + /** + * This is the global view, therefore we do not distinguish between + * hosts. + * + * @return + */ + public Graph getLocalView() { + recalculateLocalView(); + return currentView; + } + + @Override + public void afterComponentsMoved() { + this.isInvalid = true; + } + + @Override + public void afterComponentMoved(MovementSupported comp) { + // don't care, we calculate based on global knowledge. + } + + @Override + public void wentOnline(Host host, NetInterface netInterface) { + assert netInterface.getName() == medium; + this.isInvalid = true; + } + + @Override + public void wentOffline(Host host, NetInterface netInterface) { + assert netInterface.getName() == medium; + this.isInvalid = true; + } + + } + } diff --git a/src/de/tud/kom/p2psim/impl/topology/views/AbstractTopologyView.java b/src/de/tud/kom/p2psim/impl/topology/views/AbstractTopologyView.java index fae2092dddbc2098fccdd920575da973c1d4596d..560a3450e9fe717e8b49798ebae5782bd9d4443e 100644 --- a/src/de/tud/kom/p2psim/impl/topology/views/AbstractTopologyView.java +++ b/src/de/tud/kom/p2psim/impl/topology/views/AbstractTopologyView.java @@ -20,6 +20,7 @@ package de.tud.kom.p2psim.impl.topology.views; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -306,6 +307,11 @@ public abstract class AbstractTopologyView implements public MacLayer getMac(MacAddress address) { return macs.get(address); } + + @Override + public Collection getAllMacs() { + return macs.values(); + } @Override public void afterComponentsMoved() { diff --git a/src/de/tud/kom/p2psim/impl/topology/views/VisualizationTopologyView.java b/src/de/tud/kom/p2psim/impl/topology/views/VisualizationTopologyView.java index a96a2f560b13864b4b37cc690c680bf93ee9a08d..91f1c79bd84c8d5ccd8be378732648e0017cac98 100644 --- a/src/de/tud/kom/p2psim/impl/topology/views/VisualizationTopologyView.java +++ b/src/de/tud/kom/p2psim/impl/topology/views/VisualizationTopologyView.java @@ -36,6 +36,7 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -285,6 +286,11 @@ public class VisualizationTopologyView extends JFrame implements TopologyView, throw new UnsupportedOperationException(); } + @Override + public Collection getAllMacs() { + throw new UnsupportedOperationException(); + } + @Override public List getNeighbors(MacAddress address) { throw new UnsupportedOperationException(); diff --git a/src/de/tud/kom/p2psim/impl/util/oracle/GlobalOracle.java b/src/de/tud/kom/p2psim/impl/util/oracle/GlobalOracle.java index 629530624313ebae7dc3dc206d4a88d2eb263118..48608824f1f9238e474235554df6dbe92113fd57 100644 --- a/src/de/tud/kom/p2psim/impl/util/oracle/GlobalOracle.java +++ b/src/de/tud/kom/p2psim/impl/util/oracle/GlobalOracle.java @@ -22,16 +22,26 @@ package de.tud.kom.p2psim.impl.util.oracle; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; +import java.util.Set; import de.tud.kom.p2psim.api.common.SimHost; +import de.tudarmstadt.maki.simonstrator.api.Graphs; import de.tudarmstadt.maki.simonstrator.api.Host; import de.tudarmstadt.maki.simonstrator.api.Randoms; +import de.tudarmstadt.maki.simonstrator.api.common.graph.DirectedEdge; +import de.tudarmstadt.maki.simonstrator.api.common.graph.Graph; +import de.tudarmstadt.maki.simonstrator.api.common.graph.Node; +import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException; import de.tudarmstadt.maki.simonstrator.api.component.core.OracleComponent; import de.tudarmstadt.maki.simonstrator.api.component.network.NetID; import de.tudarmstadt.maki.simonstrator.api.component.network.NetInterface; +import de.tudarmstadt.maki.simonstrator.api.component.topology.TopologyID; +import de.tudarmstadt.maki.simonstrator.api.component.topology.TopologyProvider; /** * This class gives access to the hosts of the scenario. To work, it has to be @@ -172,6 +182,92 @@ public class GlobalOracle implements OracleComponent { public boolean isSimulation() { return true; } + + /** + * Returns a global view of the topology for the specified mechanism. The + * mechanism must be a HostComponent that is registered at the local host. + * Otherwise, this method will not be able to find the local mechanism + * objects. + * + * @param component + * @param identifier + * @return + */ + public static Graph getTopology( + Class component, TopologyID identifier) { + + HashSet edges = new LinkedHashSet<>(); + HashSet nodes = new LinkedHashSet(); + + LinkedList allProviders = new LinkedList<>(); + + for (SimHost host : getHosts()) { + try { + TopologyProvider topologyProvider = host + .getComponent(component); + + Node providerNode = topologyProvider.getNode(identifier); + + nodes.add(providerNode); + + allProviders.add(topologyProvider); + + } catch (ComponentNotAvailableException e) { + // if the component is not available on the host, we can't do + // anything about it + // no reason to crash the simulation as this might be the case + // in various scenarios + } + } + + for (TopologyProvider topologyProvider : allProviders) { + Set neighbors = topologyProvider + .getNeighbors(identifier); + edges.addAll(neighbors); + } + + Graph graph = Graphs.createGraph(); + for(Node node : nodes){ + graph.add(node); + } + for(DirectedEdge edge : edges) { + graph.add(edge); + } + + return graph; + } + + /** + * Returns available topology identifiers for the given component. Throws an + * {@link ComponentNotAvailableException} if the component is not available + * on any node in the network. Assumes that all instances of a given + * component class provide the same topology identifiers. + * + * @throws ComponentNotAvailableException + */ + public static Iterable getTopologyIdentifiers( + Class component) throws ComponentNotAvailableException { + + // iterate over all the hosts, find one host that contains the given + // component class and ask this component about available topologies + for (SimHost host : getHosts()) { + try { + TopologyProvider topologyProvider = host + .getComponent(component); + return topologyProvider.getTopologyIdentifiers(); + + } catch (ComponentNotAvailableException e) { + // if the component is not available on the host, we can't do + // anything about it + // no reason to crash the simulation as this might be the case + // in various scenarios + } + } + + throw new ComponentNotAvailableException(); + } + + /** * Checks whether the host with the given NetID is online using a global