From 0e78bc67f95e84011a6fa25020dca61f1c9388e0 Mon Sep 17 00:00:00 2001 From: Enrico Joerns Date: Wed, 11 Jun 2014 00:27:33 +0200 Subject: [PATCH 1/8] [cooja] skins/TrafficVisualizerSkin: Added @Override annotations and added some final modifiers --- .../plugins/skins/TrafficVisualizerSkin.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java index d632ae094..d9a009023 100644 --- a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java +++ b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java @@ -60,7 +60,7 @@ import org.contikios.cooja.radiomediums.AbstractRadioMedium; @ClassDescription("Radio traffic") @SupportedArguments(radioMediums = {AbstractRadioMedium.class}) public class TrafficVisualizerSkin implements VisualizerSkin { - private static Logger logger = Logger.getLogger(TrafficVisualizerSkin.class); + private static final Logger logger = Logger.getLogger(TrafficVisualizerSkin.class); private final int MAX_HISTORY_SIZE = 200; @@ -73,6 +73,7 @@ public class TrafficVisualizerSkin implements VisualizerSkin { private RadioConnectionArrow[] history = null; private Observer radioMediumObserver = new Observer() { + @Override public void update(Observable obs, Object obj) { RadioConnection last = radioMedium.getLastConnection(); if (last != null && historyList.size() < MAX_HISTORY_SIZE) { @@ -82,7 +83,8 @@ public class TrafficVisualizerSkin implements VisualizerSkin { } } }; - private TimeEvent ageArrowsTimeEvent = new TimeEvent(0) { + private final TimeEvent ageArrowsTimeEvent = new TimeEvent(0) { + @Override public void execute(long t) { if (!active) { return; @@ -118,6 +120,7 @@ public class TrafficVisualizerSkin implements VisualizerSkin { } }; + @Override public void setActive(final Simulation simulation, Visualizer vis) { this.radioMedium = (AbstractRadioMedium) simulation.getRadioMedium(); this.simulation = simulation; @@ -125,6 +128,7 @@ public class TrafficVisualizerSkin implements VisualizerSkin { this.active = true; simulation.invokeSimulationThread(new Runnable() { + @Override public void run() { historyList.clear(); history = null; @@ -138,6 +142,7 @@ public class TrafficVisualizerSkin implements VisualizerSkin { }); } + @Override public void setInactive() { this.active = false; if (simulation == null) { @@ -149,11 +154,12 @@ public class TrafficVisualizerSkin implements VisualizerSkin { radioMedium.deleteRadioMediumObserver(radioMediumObserver); } + @Override public Color[] getColorOf(Mote mote) { return null; } - private Polygon arrowPoly = new Polygon(); + private final Polygon arrowPoly = new Polygon(); private void drawArrow(Graphics g, int xSource, int ySource, int xDest, int yDest, int delta) { double dx = xSource - xDest; double dy = ySource - yDest; @@ -183,6 +189,7 @@ public class TrafficVisualizerSkin implements VisualizerSkin { return (int)(0.5 + len * Math.sin(dir)); } + @Override public void paintBeforeMotes(Graphics g) { RadioConnectionArrow[] historyCopy = history; if (historyCopy == null) { @@ -201,15 +208,17 @@ public class TrafficVisualizerSkin implements VisualizerSkin { } } + @Override public void paintAfterMotes(Graphics g) { } + @Override public Visualizer getVisualizer() { return visualizer; } private static class RadioConnectionArrow { - private RadioConnection conn; + private final RadioConnection conn; private int age; private static final int MAX_AGE = 10; RadioConnectionArrow(RadioConnection conn) { From c92f83c0488112ac0a33f56d6965c6651c39ab1b Mon Sep 17 00:00:00 2001 From: Enrico Joerns Date: Wed, 11 Jun 2014 00:29:26 +0200 Subject: [PATCH 2/8] [cooja] skins/TrafficVisualizerSkin: Indicate sent but unreceived messages by a red double circle around mote --- .../cooja/plugins/skins/TrafficVisualizerSkin.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java index d9a009023..b1ab3633f 100644 --- a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java +++ b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java @@ -200,6 +200,13 @@ public class TrafficVisualizerSkin implements VisualizerSkin { g.setColor(new Color(colorHistoryIndex, colorHistoryIndex, 1.0f)); Radio source = connArrow.getConnection().getSource(); Point sourcePoint = visualizer.transformPositionToPixel(source.getPosition()); + /* If there is no destination, paint red circles to indicate untransmitted message */ + if (connArrow.getConnection().getDestinations().length == 0) { + g.setColor(new Color(1.0f, colorHistoryIndex, colorHistoryIndex)); + g.drawOval(sourcePoint.x - 20, sourcePoint.y - 20, 40, 40); + g.drawOval(sourcePoint.x - 30, sourcePoint.y - 30, 60, 60); + continue; + } for (Radio destRadio : connArrow.getConnection().getDestinations()) { Position destPos = destRadio.getPosition(); Point destPoint = visualizer.transformPositionToPixel(destPos); From ea80fd92571a7e84e397bab38cb1024811d0426b Mon Sep 17 00:00:00 2001 From: Enrico Joerns Date: Wed, 11 Jun 2014 00:31:31 +0200 Subject: [PATCH 3/8] [cooja] skins/TrafficVisualizerSkin: Use LinkedList instead of ArrayList to increase add and remove performance --- .../contikios/cooja/plugins/skins/TrafficVisualizerSkin.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java index b1ab3633f..ee60bd367 100644 --- a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java +++ b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java @@ -33,7 +33,8 @@ import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.Polygon; -import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; import java.util.Observable; import java.util.Observer; @@ -69,7 +70,7 @@ public class TrafficVisualizerSkin implements VisualizerSkin { private Visualizer visualizer = null; private AbstractRadioMedium radioMedium = null; - private ArrayList historyList = new ArrayList(); + private List historyList = new LinkedList<>(); private RadioConnectionArrow[] history = null; private Observer radioMediumObserver = new Observer() { From 468d533c415ba5323bbab3695887521123e49ef5 Mon Sep 17 00:00:00 2001 From: Enrico Joerns Date: Wed, 11 Jun 2014 00:47:34 +0200 Subject: [PATCH 4/8] [cooja] skins/TrafficVisualizerSkin: Removed unnecessary 'historyCopy' --- .../cooja/plugins/skins/TrafficVisualizerSkin.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java index ee60bd367..bc82492c5 100644 --- a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java +++ b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java @@ -192,11 +192,7 @@ public class TrafficVisualizerSkin implements VisualizerSkin { @Override public void paintBeforeMotes(Graphics g) { - RadioConnectionArrow[] historyCopy = history; - if (historyCopy == null) { - return; - } - for (RadioConnectionArrow connArrow : historyCopy) { + for (RadioConnectionArrow connArrow : historyList) { float colorHistoryIndex = (float)connArrow.getAge() / (float)connArrow.getMaxAge(); g.setColor(new Color(colorHistoryIndex, colorHistoryIndex, 1.0f)); Radio source = connArrow.getConnection().getSource(); From 7c80213c3a9329fd2decf5622a38670770214c82 Mon Sep 17 00:00:00 2001 From: Enrico Joerns Date: Wed, 11 Jun 2014 00:49:25 +0200 Subject: [PATCH 5/8] [cooja] skins/TrafficVisualizerSkin: Reduce array copy and iteration overhead --- .../plugins/skins/TrafficVisualizerSkin.java | 28 ++++++------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java index bc82492c5..7ee1c46c7 100644 --- a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java +++ b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java @@ -33,6 +33,7 @@ import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.Polygon; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Observable; @@ -71,7 +72,6 @@ public class TrafficVisualizerSkin implements VisualizerSkin { private AbstractRadioMedium radioMedium = null; private List historyList = new LinkedList<>(); - private RadioConnectionArrow[] history = null; private Observer radioMediumObserver = new Observer() { @Override @@ -79,7 +79,6 @@ public class TrafficVisualizerSkin implements VisualizerSkin { RadioConnection last = radioMedium.getLastConnection(); if (last != null && historyList.size() < MAX_HISTORY_SIZE) { historyList.add(new RadioConnectionArrow(last)); - history = historyList.toArray(new RadioConnectionArrow[0]); visualizer.repaint(500); } } @@ -92,27 +91,17 @@ public class TrafficVisualizerSkin implements VisualizerSkin { } if (historyList.size() > 0) { - boolean hasOld = false; - /* Increase age */ - for (RadioConnectionArrow connArrow : historyList) { - connArrow.increaseAge(); - if(connArrow.getAge() >= connArrow.getMaxAge()) { - hasOld = true; + /* Increase age and remove too old arrows */ + Iterator iter = historyList.iterator(); + while (iter.hasNext()) { + RadioConnectionArrow rca = iter.next(); + rca.increaseAge(); + if(rca.getAge() >= rca.getMaxAge()) { + iter.remove(); } } - /* Remove too old arrows */ - if (hasOld) { - RadioConnectionArrow[] historyArr = historyList.toArray(new RadioConnectionArrow[0]); - for (RadioConnectionArrow connArrow : historyArr) { - if(connArrow.getAge() >= connArrow.getMaxAge()) { - historyList.remove(connArrow); - } - } - historyArr = historyList.toArray(new RadioConnectionArrow[0]); - } - visualizer.repaint(500); } @@ -132,7 +121,6 @@ public class TrafficVisualizerSkin implements VisualizerSkin { @Override public void run() { historyList.clear(); - history = null; /* Start observing radio medium for transmissions */ radioMedium.addRadioMediumObserver(radioMediumObserver); From 449046669f40d2ae4b9cabef5a7f090f59ea2801 Mon Sep 17 00:00:00 2001 From: Enrico Joerns Date: Wed, 11 Jun 2014 11:11:45 +0200 Subject: [PATCH 6/8] [cooja] skins/TrafficVisualizerSkin: Age handling moved to RadioConnectionArrow class which also got some lines of function documentation --- .../plugins/skins/TrafficVisualizerSkin.java | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java index 7ee1c46c7..a57bac447 100644 --- a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java +++ b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java @@ -96,8 +96,8 @@ public class TrafficVisualizerSkin implements VisualizerSkin { Iterator iter = historyList.iterator(); while (iter.hasNext()) { RadioConnectionArrow rca = iter.next(); - rca.increaseAge(); - if(rca.getAge() >= rca.getMaxAge()) { + /* Try to increase age and remove if max age was reached */ + if (!rca.increaseAge()) { iter.remove(); } } @@ -181,7 +181,7 @@ public class TrafficVisualizerSkin implements VisualizerSkin { @Override public void paintBeforeMotes(Graphics g) { for (RadioConnectionArrow connArrow : historyList) { - float colorHistoryIndex = (float)connArrow.getAge() / (float)connArrow.getMaxAge(); + float colorHistoryIndex = connArrow.getAge(); g.setColor(new Color(colorHistoryIndex, colorHistoryIndex, 1.0f)); Radio source = connArrow.getConnection().getSource(); Point sourcePoint = visualizer.transformPositionToPixel(source.getPosition()); @@ -210,26 +210,47 @@ public class TrafficVisualizerSkin implements VisualizerSkin { } private static class RadioConnectionArrow { + + private static final int MAX_AGE = 10; private final RadioConnection conn; private int age; - private static final int MAX_AGE = 10; + RadioConnectionArrow(RadioConnection conn) { this.conn = conn; this.age = 0; } - public void increaseAge() { + + /** + * Increases age of radio connection if possible or indicates max age. + * + * @return true if max age was not reached yet, false, if max age was + * reached + */ + public boolean increaseAge() { if (age < MAX_AGE) { age++; + return true; + } else { + return false; } } - public int getAge() { - return age; + + /** + * Returns relative age of radio connection + * + * @return Relative age (0.0 - 1.0) + */ + public float getAge() { + return (float) age / (float) MAX_AGE; } + + /** + * Returns radio connection + * + * @return radio connection + */ public RadioConnection getConnection() { return conn; } - public int getMaxAge() { - return MAX_AGE; - } } } From cd9164d5e285bafba539caece4c4d1c315a8988f Mon Sep 17 00:00:00 2001 From: Enrico Joerns Date: Wed, 11 Jun 2014 11:21:39 +0200 Subject: [PATCH 7/8] [cooja] skins/TrafficVisualizerSkin: Use alpha value to fade out arrow color an potentially allow to configure colors --- .../cooja/plugins/skins/TrafficVisualizerSkin.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java index a57bac447..cf0649bd8 100644 --- a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java +++ b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java @@ -65,6 +65,8 @@ public class TrafficVisualizerSkin implements VisualizerSkin { private static final Logger logger = Logger.getLogger(TrafficVisualizerSkin.class); private final int MAX_HISTORY_SIZE = 200; + private final float TRANSMITTED_COLOR_RGB[] = Color.BLUE.getRGBColorComponents(null); + private final float UNTRANSMITTED_COLOR_RGB[] = Color.RED.getRGBColorComponents(null); private boolean active = false; private Simulation simulation = null; @@ -181,17 +183,17 @@ public class TrafficVisualizerSkin implements VisualizerSkin { @Override public void paintBeforeMotes(Graphics g) { for (RadioConnectionArrow connArrow : historyList) { - float colorHistoryIndex = connArrow.getAge(); - g.setColor(new Color(colorHistoryIndex, colorHistoryIndex, 1.0f)); + float colorHistoryIndex = 1.0f - connArrow.getAge(); Radio source = connArrow.getConnection().getSource(); Point sourcePoint = visualizer.transformPositionToPixel(source.getPosition()); /* If there is no destination, paint red circles to indicate untransmitted message */ if (connArrow.getConnection().getDestinations().length == 0) { - g.setColor(new Color(1.0f, colorHistoryIndex, colorHistoryIndex)); + g.setColor(new Color(UNTRANSMITTED_COLOR_RGB[0], UNTRANSMITTED_COLOR_RGB[1], UNTRANSMITTED_COLOR_RGB[2], colorHistoryIndex)); g.drawOval(sourcePoint.x - 20, sourcePoint.y - 20, 40, 40); g.drawOval(sourcePoint.x - 30, sourcePoint.y - 30, 60, 60); continue; } + g.setColor(new Color(TRANSMITTED_COLOR_RGB[0], TRANSMITTED_COLOR_RGB[1], TRANSMITTED_COLOR_RGB[2], colorHistoryIndex)); for (Radio destRadio : connArrow.getConnection().getDestinations()) { Position destPos = destRadio.getPosition(); Point destPoint = visualizer.transformPositionToPixel(destPos); From d4f7cf6a8375714718687a37cd1c24638f196f58 Mon Sep 17 00:00:00 2001 From: Enrico Joerns Date: Wed, 25 Jun 2014 17:02:01 +0200 Subject: [PATCH 8/8] [cooja] plugins/sinks/TrafficVisualizerSkin: Synchronized to avoid ConcurrentModificationExcpetions --- .../plugins/skins/TrafficVisualizerSkin.java | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java index cf0649bd8..0cd05c319 100644 --- a/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java +++ b/tools/cooja/java/org/contikios/cooja/plugins/skins/TrafficVisualizerSkin.java @@ -73,18 +73,21 @@ public class TrafficVisualizerSkin implements VisualizerSkin { private Visualizer visualizer = null; private AbstractRadioMedium radioMedium = null; - private List historyList = new LinkedList<>(); + private final List historyList = new LinkedList<>(); private Observer radioMediumObserver = new Observer() { @Override public void update(Observable obs, Object obj) { RadioConnection last = radioMedium.getLastConnection(); if (last != null && historyList.size() < MAX_HISTORY_SIZE) { - historyList.add(new RadioConnectionArrow(last)); - visualizer.repaint(500); + synchronized(historyList) { + historyList.add(new RadioConnectionArrow(last)); + visualizer.repaint(500); + } } } }; + private final TimeEvent ageArrowsTimeEvent = new TimeEvent(0) { @Override public void execute(long t) { @@ -94,13 +97,15 @@ public class TrafficVisualizerSkin implements VisualizerSkin { if (historyList.size() > 0) { - /* Increase age and remove too old arrows */ - Iterator iter = historyList.iterator(); - while (iter.hasNext()) { - RadioConnectionArrow rca = iter.next(); - /* Try to increase age and remove if max age was reached */ - if (!rca.increaseAge()) { - iter.remove(); + synchronized (historyList) { + /* Increase age and remove too old arrows */ + Iterator iter = historyList.iterator(); + while (iter.hasNext()) { + RadioConnectionArrow rca = iter.next(); + /* Try to increase age and remove if max age was reached */ + if (!rca.increaseAge()) { + iter.remove(); + } } } @@ -182,22 +187,24 @@ public class TrafficVisualizerSkin implements VisualizerSkin { @Override public void paintBeforeMotes(Graphics g) { - for (RadioConnectionArrow connArrow : historyList) { - float colorHistoryIndex = 1.0f - connArrow.getAge(); - Radio source = connArrow.getConnection().getSource(); - Point sourcePoint = visualizer.transformPositionToPixel(source.getPosition()); - /* If there is no destination, paint red circles to indicate untransmitted message */ - if (connArrow.getConnection().getDestinations().length == 0) { - g.setColor(new Color(UNTRANSMITTED_COLOR_RGB[0], UNTRANSMITTED_COLOR_RGB[1], UNTRANSMITTED_COLOR_RGB[2], colorHistoryIndex)); - g.drawOval(sourcePoint.x - 20, sourcePoint.y - 20, 40, 40); - g.drawOval(sourcePoint.x - 30, sourcePoint.y - 30, 60, 60); - continue; - } - g.setColor(new Color(TRANSMITTED_COLOR_RGB[0], TRANSMITTED_COLOR_RGB[1], TRANSMITTED_COLOR_RGB[2], colorHistoryIndex)); - for (Radio destRadio : connArrow.getConnection().getDestinations()) { - Position destPos = destRadio.getPosition(); - Point destPoint = visualizer.transformPositionToPixel(destPos); - drawArrow(g, sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y, 8); + synchronized (historyList) { + for (RadioConnectionArrow connArrow : historyList) { + float colorHistoryIndex = 1.0f - connArrow.getAge(); + Radio source = connArrow.getConnection().getSource(); + Point sourcePoint = visualizer.transformPositionToPixel(source.getPosition()); + /* If there is no destination, paint red circles to indicate untransmitted message */ + if (connArrow.getConnection().getDestinations().length == 0) { + g.setColor(new Color(UNTRANSMITTED_COLOR_RGB[0], UNTRANSMITTED_COLOR_RGB[1], UNTRANSMITTED_COLOR_RGB[2], colorHistoryIndex)); + g.drawOval(sourcePoint.x - 20, sourcePoint.y - 20, 40, 40); + g.drawOval(sourcePoint.x - 30, sourcePoint.y - 30, 60, 60); + continue; + } + g.setColor(new Color(TRANSMITTED_COLOR_RGB[0], TRANSMITTED_COLOR_RGB[1], TRANSMITTED_COLOR_RGB[2], colorHistoryIndex)); + for (Radio destRadio : connArrow.getConnection().getDestinations()) { + Position destPos = destRadio.getPosition(); + Point destPoint = visualizer.transformPositionToPixel(destPos); + drawArrow(g, sourcePoint.x, sourcePoint.y, destPoint.x, destPoint.y, 8); + } } } }