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