try to restore edges loaded from old simulation configuration

This commit is contained in:
Fredrik Osterlind 2011-11-01 11:52:34 +01:00
parent ff42490e7b
commit 5cde978549

View file

@ -41,6 +41,7 @@ import org.apache.log4j.Logger;
import org.jdom.Element; import org.jdom.Element;
import se.sics.cooja.ClassDescription; import se.sics.cooja.ClassDescription;
import se.sics.cooja.Mote;
import se.sics.cooja.RadioConnection; import se.sics.cooja.RadioConnection;
import se.sics.cooja.Simulation; import se.sics.cooja.Simulation;
import se.sics.cooja.interfaces.Radio; import se.sics.cooja.interfaces.Radio;
@ -62,382 +63,402 @@ import se.sics.cooja.plugins.skins.DGRMVisualizerSkin;
*/ */
@ClassDescription("Directed Graph Radio Medium (DGRM)") @ClassDescription("Directed Graph Radio Medium (DGRM)")
public class DirectedGraphMedium extends AbstractRadioMedium { public class DirectedGraphMedium extends AbstractRadioMedium {
private static Logger logger = Logger.getLogger(DirectedGraphMedium.class); private static Logger logger = Logger.getLogger(DirectedGraphMedium.class);
private Simulation simulation; private Simulation simulation;
private Random random; private Random random;
private ArrayList<Edge> edges = new ArrayList<Edge>(); private ArrayList<Edge> edges = new ArrayList<Edge>();
private boolean edgesDirty = true; private boolean edgesDirty = true;
/* Used for optimizing lookup time */ /* Used for optimizing lookup time */
private Hashtable<Radio,DestinationRadio[]> edgesTable = new Hashtable<Radio,DestinationRadio[]>(); private Hashtable<Radio,DestinationRadio[]> edgesTable = new Hashtable<Radio,DestinationRadio[]>();
public DirectedGraphMedium() { public DirectedGraphMedium() {
/* Do not initialize radio medium: use only for hash table */ /* Do not initialize radio medium: use only for hash table */
super(null); super(null);
} Visualizer.registerVisualizerSkin(DGRMVisualizerSkin.class);
}
public DirectedGraphMedium(Simulation simulation) { public DirectedGraphMedium(Simulation simulation) {
super(simulation); super(simulation);
this.simulation = simulation; this.simulation = simulation;
random = simulation.getRandomGenerator(); random = simulation.getRandomGenerator();
requestEdgeAnalysis(); requestEdgeAnalysis();
/* Register plugin and visualizer skin */ /* Register plugin and visualizer skin */
simulation.getGUI().registerPlugin(DGRMConfigurator.class); simulation.getGUI().registerPlugin(DGRMConfigurator.class);
Visualizer.registerVisualizerSkin(DGRMVisualizerSkin.class); Visualizer.registerVisualizerSkin(DGRMVisualizerSkin.class);
} }
public void removed() {
super.removed();
/* Unregister plugin and visualizer skin */ public void removed() {
simulation.getGUI().unregisterPlugin(DGRMConfigurator.class); super.removed();
Visualizer.unregisterVisualizerSkin(DGRMVisualizerSkin.class);
}
public void addEdge(Edge e) { /* Unregister plugin and visualizer skin */
edges.add(e); simulation.getGUI().unregisterPlugin(DGRMConfigurator.class);
requestEdgeAnalysis(); Visualizer.unregisterVisualizerSkin(DGRMVisualizerSkin.class);
}
((AbstractRadioMedium.RadioMediumObservable) public void addEdge(Edge e) {
this.getRadioMediumObservable()).setRadioMediumChangedAndNotify(); edges.add(e);
} requestEdgeAnalysis();
public void removeEdge(Edge edge) { ((AbstractRadioMedium.RadioMediumObservable)
if (!edges.contains(edge)) { this.getRadioMediumObservable()).setRadioMediumChangedAndNotify();
logger.fatal("Cannot remove edge: " + edge); }
return;
}
edges.remove(edge);
requestEdgeAnalysis();
((AbstractRadioMedium.RadioMediumObservable) public void removeEdge(Edge edge) {
this.getRadioMediumObservable()).setRadioMediumChangedAndNotify(); if (!edges.contains(edge)) {
} logger.fatal("Cannot remove edge: " + edge);
return;
}
edges.remove(edge);
requestEdgeAnalysis();
public void clearEdges() { ((AbstractRadioMedium.RadioMediumObservable)
edges.clear(); this.getRadioMediumObservable()).setRadioMediumChangedAndNotify();
requestEdgeAnalysis(); }
((AbstractRadioMedium.RadioMediumObservable) public void clearEdges() {
this.getRadioMediumObservable()).setRadioMediumChangedAndNotify(); edges.clear();
} requestEdgeAnalysis();
public Edge[] getEdges() { ((AbstractRadioMedium.RadioMediumObservable)
return edges.toArray(new Edge[0]); this.getRadioMediumObservable()).setRadioMediumChangedAndNotify();
} }
/** public Edge[] getEdges() {
* Signal that the configuration changed, and needs to be re-analyzed return edges.toArray(new Edge[0]);
* before used. }
*/
public void requestEdgeAnalysis() {
edgesDirty = true;
}
public boolean needsEdgeAnalysis() { /**
return edgesDirty; * Signal that the configuration changed, and needs to be re-analyzed
} * before used.
*/
public void requestEdgeAnalysis() {
edgesDirty = true;
}
public void unregisterRadioInterface(Radio radio, Simulation sim) { public boolean needsEdgeAnalysis() {
super.unregisterRadioInterface(radio, sim); return edgesDirty;
}
for (Edge edge: getEdges()) { public void unregisterRadioInterface(Radio radio, Simulation sim) {
if (edge.source == radio || edge.superDest.radio == radio) { super.unregisterRadioInterface(radio, sim);
removeEdge(edge);
requestEdgeAnalysis();
}
}
}
public void updateSignalStrengths() { for (Edge edge: getEdges()) {
if (edge.source == radio || edge.superDest.radio == radio) {
removeEdge(edge);
requestEdgeAnalysis();
}
}
}
/* Reset signal strengths */ public void updateSignalStrengths() {
for (Radio radio : getRegisteredRadios()) {
radio.setCurrentSignalStrength(SS_NOTHING);
}
/* Set signal strengths */ /* Reset signal strengths */
RadioConnection[] conns = getActiveConnections(); for (Radio radio : getRegisteredRadios()) {
for (RadioConnection conn : conns) { radio.setCurrentSignalStrength(SS_NOTHING);
if (conn.getSource().getCurrentSignalStrength() < SS_STRONG) { }
conn.getSource().setCurrentSignalStrength(SS_STRONG);
}
for (Radio dstRadio : conn.getDestinations()) {
if (dstRadio.getCurrentSignalStrength() < SS_STRONG) {
dstRadio.setCurrentSignalStrength(SS_STRONG);
}
}
}
/* Set signal strength to weak on interfered */ /* Set signal strengths */
for (RadioConnection conn : conns) { RadioConnection[] conns = getActiveConnections();
for (Radio intfRadio : conn.getInterfered()) { for (RadioConnection conn : conns) {
if (intfRadio.getCurrentSignalStrength() < SS_STRONG) { if (conn.getSource().getCurrentSignalStrength() < SS_STRONG) {
intfRadio.setCurrentSignalStrength(SS_STRONG); conn.getSource().setCurrentSignalStrength(SS_STRONG);
} }
for (Radio dstRadio : conn.getDestinations()) {
if (dstRadio.getCurrentSignalStrength() < SS_STRONG) {
dstRadio.setCurrentSignalStrength(SS_STRONG);
}
}
}
if (!intfRadio.isInterfered()) { /* Set signal strength to weak on interfered */
/*logger.warn("Radio was not interfered");*/ for (RadioConnection conn : conns) {
intfRadio.interfereAnyReception(); for (Radio intfRadio : conn.getInterfered()) {
} if (intfRadio.getCurrentSignalStrength() < SS_STRONG) {
} intfRadio.setCurrentSignalStrength(SS_STRONG);
} }
}
if (!intfRadio.isInterfered()) {
/*logger.warn("Radio was not interfered");*/
intfRadio.interfereAnyReception();
}
}
}
}
/** /**
* Generates hash table using current edges for efficient lookup. * Generates hash table using current edges for efficient lookup.
*/ */
protected void analyzeEdges() { protected void analyzeEdges() {
Hashtable<Radio,ArrayList<DestinationRadio>> listTable = Hashtable<Radio,ArrayList<DestinationRadio>> listTable =
new Hashtable<Radio,ArrayList<DestinationRadio>>(); new Hashtable<Radio,ArrayList<DestinationRadio>>();
/* Fill edge hash table with all edges */ /* Fill edge hash table with all edges */
for (Edge edge: getEdges()) { for (Edge edge: getEdges()) {
ArrayList<DestinationRadio> destRadios; ArrayList<DestinationRadio> destRadios;
if (!listTable.containsKey(edge.source)) { if (!listTable.containsKey(edge.source)) {
destRadios = new ArrayList<DestinationRadio>(); destRadios = new ArrayList<DestinationRadio>();
} else { } else {
destRadios = listTable.get(edge.source); destRadios = listTable.get(edge.source);
} }
destRadios.add(edge.superDest); destRadios.add(edge.superDest);
listTable.put(edge.source, destRadios); listTable.put(edge.source, destRadios);
} }
/* Convert to arrays */ /* Convert to arrays */
Hashtable<Radio,DestinationRadio[]> arrTable = new Hashtable<Radio,DestinationRadio[]>(); Hashtable<Radio,DestinationRadio[]> arrTable = new Hashtable<Radio,DestinationRadio[]>();
Enumeration<Radio> sources = listTable.keys(); Enumeration<Radio> sources = listTable.keys();
while (sources.hasMoreElements()) { while (sources.hasMoreElements()) {
Radio source = sources.nextElement(); Radio source = sources.nextElement();
DestinationRadio[] arr = listTable.get(source).toArray(new DestinationRadio[0]); DestinationRadio[] arr = listTable.get(source).toArray(new DestinationRadio[0]);
arrTable.put(source, arr); arrTable.put(source, arr);
} }
this.edgesTable = arrTable; this.edgesTable = arrTable;
edgesDirty = false; edgesDirty = false;
} }
/** /**
* Returns all potential destination radios, i.e. all radios "within reach". * Returns all potential destination radios, i.e. all radios "within reach".
* Does not consider radio channels, transmission success ratios etc. * Does not consider radio channels, transmission success ratios etc.
* *
* @param source Source radio * @param source Source radio
* @return All potential destination radios * @return All potential destination radios
*/ */
public DestinationRadio[] getPotentialDestinations(Radio source) { public DestinationRadio[] getPotentialDestinations(Radio source) {
if (edgesDirty) { if (edgesDirty) {
analyzeEdges(); analyzeEdges();
} }
return edgesTable.get(source); return edgesTable.get(source);
} }
public RadioConnection createConnections(Radio source) { public RadioConnection createConnections(Radio source) {
if (edgesDirty) { if (edgesDirty) {
analyzeEdges(); analyzeEdges();
} }
if (edgesDirty) { if (edgesDirty) {
logger.fatal("Error when analyzing edges, aborting new radio connection"); logger.fatal("Error when analyzing edges, aborting new radio connection");
return new RadioConnection(source); return new RadioConnection(source);
} }
/* Create new radio connection using edge hash table */ /* Create new radio connection using edge hash table */
RadioConnection newConn = new RadioConnection(source); RadioConnection newConn = new RadioConnection(source);
DestinationRadio[] destinations = getPotentialDestinations(source); DestinationRadio[] destinations = getPotentialDestinations(source);
if (destinations == null || destinations.length == 0) { if (destinations == null || destinations.length == 0) {
/* No destinations */ /* No destinations */
/*logger.info(sendingRadio + ": No dest");*/ /*logger.info(sendingRadio + ": No dest");*/
return newConn; return newConn;
} }
/*logger.info(source + ": " + destinations.length + " potential destinations");*/ /*logger.info(source + ": " + destinations.length + " potential destinations");*/
for (DestinationRadio d: destinations) { for (DestinationRadio d: destinations) {
DGRMDestinationRadio dest = (DGRMDestinationRadio) d; DGRMDestinationRadio dest = (DGRMDestinationRadio) d;
if (dest.radio == source) { if (dest.radio == source) {
/* Fail: cannot receive our own transmission */ /* Fail: cannot receive our own transmission */
/*logger.info(source + ": Fail, receiver is sender");*/ /*logger.info(source + ": Fail, receiver is sender");*/
continue; continue;
} }
/* Fail if radios are on different (but configured) channels */ /* Fail if radios are on different (but configured) channels */
if (source.getChannel() >= 0 && if (source.getChannel() >= 0 &&
dest.radio.getChannel() >= 0 && dest.radio.getChannel() >= 0 &&
source.getChannel() != dest.radio.getChannel()) { source.getChannel() != dest.radio.getChannel()) {
continue; continue;
} }
if (!dest.radio.isReceiverOn()) { if (!dest.radio.isReceiverOn()) {
/* Fail: radio is off */ /* Fail: radio is off */
/*logger.info(source + ": Fail, off");*/ /*logger.info(source + ": Fail, off");*/
newConn.addInterfered(dest.radio); newConn.addInterfered(dest.radio);
continue; continue;
} }
if (dest.ratio < 1.0 && random.nextDouble() > dest.ratio) { if (dest.ratio < 1.0 && random.nextDouble() > dest.ratio) {
/*logger.info(source + ": Fail, randomly");*/ /*logger.info(source + ": Fail, randomly");*/
/* TODO Interfere now? */ /* TODO Interfere now? */
newConn.addInterfered(dest.radio); newConn.addInterfered(dest.radio);
dest.radio.interfereAnyReception(); dest.radio.interfereAnyReception();
RadioConnection otherConnection = null; RadioConnection otherConnection = null;
for (RadioConnection conn : getActiveConnections()) { for (RadioConnection conn : getActiveConnections()) {
for (Radio dstRadio : conn.getDestinations()) { for (Radio dstRadio : conn.getDestinations()) {
if (dstRadio == dest.radio) { if (dstRadio == dest.radio) {
otherConnection = conn; otherConnection = conn;
break; break;
} }
} }
} }
if (otherConnection != null) { if (otherConnection != null) {
otherConnection.addInterfered(dest.radio); otherConnection.addInterfered(dest.radio);
} }
continue; continue;
} }
if (dest.radio.isReceiving()) { if (dest.radio.isReceiving()) {
/* Fail: radio is already actively receiving */ /* Fail: radio is already actively receiving */
/*logger.info(source + ": Fail, receiving");*/ /*logger.info(source + ": Fail, receiving");*/
newConn.addInterfered(dest.radio); newConn.addInterfered(dest.radio);
/* We will also interfere with the other connection */ /* We will also interfere with the other connection */
dest.radio.interfereAnyReception(); dest.radio.interfereAnyReception();
RadioConnection otherConnection = null; RadioConnection otherConnection = null;
for (RadioConnection conn : getActiveConnections()) { for (RadioConnection conn : getActiveConnections()) {
for (Radio dstRadio : conn.getDestinations()) { for (Radio dstRadio : conn.getDestinations()) {
if (dstRadio == dest.radio) { if (dstRadio == dest.radio) {
otherConnection = conn; otherConnection = conn;
break; break;
} }
} }
} }
if (otherConnection != null) { if (otherConnection != null) {
otherConnection.addInterfered(dest.radio); otherConnection.addInterfered(dest.radio);
} }
continue; continue;
} }
if (dest.radio.isInterfered()) { if (dest.radio.isInterfered()) {
/* Fail: radio is interfered in another connection */ /* Fail: radio is interfered in another connection */
/*logger.info(source + ": Fail, interfered");*/ /*logger.info(source + ": Fail, interfered");*/
newConn.addInterfered(dest.radio); newConn.addInterfered(dest.radio);
continue; continue;
} }
/* Success: radio starts receiving */ /* Success: radio starts receiving */
/*logger.info(source + ": OK: " + dest.radio);*/ /*logger.info(source + ": OK: " + dest.radio);*/
newConn.addDestination(dest.radio, dest.delay); newConn.addDestination(dest.radio, dest.delay);
} }
return newConn; return newConn;
} }
public Collection<Element> getConfigXML() { public Collection<Element> getConfigXML() {
ArrayList<Element> config = new ArrayList<Element>(); ArrayList<Element> config = new ArrayList<Element>();
Element element; Element element;
for (Edge edge: getEdges()) { for (Edge edge: getEdges()) {
element = new Element("edge"); element = new Element("edge");
element.addContent(edge.getConfigXML()); element.addContent(edge.getConfigXML());
config.add(element); config.add(element);
} }
return config; return config;
} }
private Collection<Element> delayedConfiguration = null; private Collection<Element> delayedConfiguration = null;
public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) { public boolean setConfigXML(Collection<Element> configXML, boolean visAvailable) {
random = simulation.getRandomGenerator(); random = simulation.getRandomGenerator();
/* Wait until simulation has been loaded */ /* Wait until simulation has been loaded */
delayedConfiguration = configXML; delayedConfiguration = configXML;
return true; return true;
} }
public void simulationFinishedLoading() { public void simulationFinishedLoading() {
if (delayedConfiguration == null) { if (delayedConfiguration == null) {
return; return;
} }
boolean warnedOldConfig = false; boolean oldConfig = false;
for (Element element : delayedConfiguration) { for (Element element : delayedConfiguration) {
if (element.getName().equals("edge")) { if (element.getName().equals("edge")) {
Collection<Element> edgeConfig = element.getChildren(); Collection<Element> edgeConfig = element.getChildren();
Radio source = null; Radio source = null;
DestinationRadio dest = null; DestinationRadio dest = null;
for (Element edgeElement : edgeConfig) { for (Element edgeElement : edgeConfig) {
if (edgeElement.getName().equals("src")) { if (edgeElement.getName().equals("src")) {
/* Old version, ignore edge */ oldConfig = true;
if (!warnedOldConfig) {
logger.fatal("Old simulation config detected: DGRM links will not be imported");
warnedOldConfig = true;
}
return;
} else if (edgeElement.getName().equals("source")) {
source = simulation.getMoteWithID(
Integer.parseInt(edgeElement.getText())).getInterfaces().getRadio();
} else if (edgeElement.getName().equals("dest")) {
String destClassName = edgeElement.getText().trim();
if (destClassName == null || destClassName.isEmpty()) {
continue;
}
Class<? extends DestinationRadio> destClass =
simulation.getGUI().tryLoadClass(this, DestinationRadio.class, destClassName);
if (destClass == null) {
throw new RuntimeException("Could not load class: " + destClassName);
}
try {
dest = destClass.newInstance();
dest.setConfigXML(edgeElement.getChildren(), simulation);
} catch (Exception e) {
throw (RuntimeException)
new RuntimeException("Unknown class: " + destClassName).initCause(e);
}
}
}
if (source == null || dest == null) {
if (!warnedOldConfig) {
logger.fatal("Old simulation config detected: DGRM links will not be imported");
warnedOldConfig = true;
}
} else {
addEdge(new Edge(source, dest));
}
}
}
requestEdgeAnalysis();
delayedConfiguration = null;
}
public static class Edge { /* Old config: lookup source mote */
public Radio source = null; for (Mote m: simulation.getMotes()) {
public DestinationRadio superDest = null; if (m.toString().equals(edgeElement.getText())) {
logger.info("Old config: mapping '" + edgeElement.getText() + "' to node " + m.getID());
source = m.getInterfaces().getRadio();
break;
}
}
} else if (edgeElement.getName().equals("source")) {
source = simulation.getMoteWithID(
Integer.parseInt(edgeElement.getText())).getInterfaces().getRadio();
} else if (oldConfig && edgeElement.getName().equals("ratio")) {
/* Old config: parse link ratio */
double ratio = Double.parseDouble(edgeElement.getText());
((DGRMDestinationRadio)dest).ratio = ratio;
} else if (edgeElement.getName().equals("dest")) {
if (oldConfig) {
/* Old config: create simple destination link */
Radio destRadio = null;
for (Mote m: simulation.getMotes()) {
if (m.toString().equals(edgeElement.getText())) {
logger.info("Old config: mapping '" + edgeElement.getText() + "' to node " + m.getID());
destRadio = m.getInterfaces().getRadio();
break;
}
}
dest = new DGRMDestinationRadio(destRadio);
} else {
String destClassName = edgeElement.getText().trim();
if (destClassName == null || destClassName.isEmpty()) {
continue;
}
Class<? extends DestinationRadio> destClass =
simulation.getGUI().tryLoadClass(this, DestinationRadio.class, destClassName);
if (destClass == null) {
throw new RuntimeException("Could not load class: " + destClassName);
}
try {
dest = destClass.newInstance();
dest.setConfigXML(edgeElement.getChildren(), simulation);
} catch (Exception e) {
throw (RuntimeException)
new RuntimeException("Unknown class: " + destClassName).initCause(e);
}
}
}
}
if (source == null || dest == null) {
logger.fatal("Failed loading DGRM links, aborting");
return;
} else {
addEdge(new Edge(source, dest));
}
}
}
requestEdgeAnalysis();
delayedConfiguration = null;
}
public Edge(Radio source, DestinationRadio dest) { public static class Edge {
this.source = source; public Radio source = null;
this.superDest = dest; public DestinationRadio superDest = null;
}
private Collection<Element> getConfigXML() { public Edge(Radio source, DestinationRadio dest) {
ArrayList<Element> config = new ArrayList<Element>(); this.source = source;
Element element; this.superDest = dest;
}
element = new Element("source"); private Collection<Element> getConfigXML() {
element.setText("" + source.getMote().getID()); ArrayList<Element> config = new ArrayList<Element>();
config.add(element); Element element;
element = new Element("dest"); element = new Element("source");
element.setText(superDest.getClass().getName()); element.setText("" + source.getMote().getID());
Collection<Element> destConfig = superDest.getConfigXML(); config.add(element);
if (destConfig != null) {
element.addContent(destConfig);
config.add(element);
}
return config; element = new Element("dest");
} element.setText(superDest.getClass().getName());
} Collection<Element> destConfig = superDest.getConfigXML();
if (destConfig != null) {
element.addContent(destConfig);
config.add(element);
}
return config;
}
}
} }