From 739e21caafb946a11546b974688b84ec8be022ed Mon Sep 17 00:00:00 2001 From: fros4943 Date: Fri, 3 Jul 2009 13:37:40 +0000 Subject: [PATCH] + support for configurable buffer sizes (currently only for log output events) --- tools/cooja/java/se/sics/cooja/GUI.java | 21 ++- .../java/se/sics/cooja/SimEventCentral.java | 76 ++++++++- .../cooja/java/se/sics/cooja/Simulation.java | 20 ++- .../se/sics/cooja/dialogs/BufferSettings.java | 160 ++++++++++++++++++ .../se/sics/cooja/plugins/LogListener.java | 18 +- 5 files changed, 283 insertions(+), 12 deletions(-) create mode 100644 tools/cooja/java/se/sics/cooja/dialogs/BufferSettings.java diff --git a/tools/cooja/java/se/sics/cooja/GUI.java b/tools/cooja/java/se/sics/cooja/GUI.java index 7bdc2cbbc..87d23c0e1 100644 --- a/tools/cooja/java/se/sics/cooja/GUI.java +++ b/tools/cooja/java/se/sics/cooja/GUI.java @@ -24,7 +24,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: GUI.java,v 1.141 2009/06/30 13:31:42 nifi Exp $ + * $Id: GUI.java,v 1.142 2009/07/03 13:37:40 fros4943 Exp $ */ package se.sics.cooja; @@ -122,6 +122,7 @@ import se.sics.cooja.MoteType.MoteTypeCreationException; import se.sics.cooja.VisPlugin.PluginRequiresVisualizationException; import se.sics.cooja.contikimote.ContikiMoteType; import se.sics.cooja.dialogs.AddMoteDialog; +import se.sics.cooja.dialogs.BufferSettings; import se.sics.cooja.dialogs.ConfigurationWizard; import se.sics.cooja.dialogs.CreateSimDialog; import se.sics.cooja.dialogs.ExternalToolsDialog; @@ -631,7 +632,8 @@ public class GUI extends Observable { guiActions.add(exitCoojaAction); guiActions.add(startStopSimulationAction); guiActions.add(removeAllMotesAction); - + guiActions.add(showBufferSettingsAction); + /* File menu */ menu = new JMenu("File"); menu.addMenuListener(new MenuListener() { @@ -903,6 +905,8 @@ public class GUI extends Observable { menuItem.setToolTipText("Not available in applet version"); } + menu.add(new JMenuItem(showBufferSettingsAction)); + menu.addSeparator(); menuItem = new JMenuItem("Java version: " @@ -4141,5 +4145,16 @@ public class GUI extends Observable { return true; } }; - + GUIAction showBufferSettingsAction = new GUIAction("Buffer sizes") { + public void actionPerformed(ActionEvent e) { + if (mySimulation == null) { + return; + } + BufferSettings.showDialog(myDesktopPane, mySimulation); + } + public boolean shouldBeEnabled() { + return mySimulation != null; + } + }; + } diff --git a/tools/cooja/java/se/sics/cooja/SimEventCentral.java b/tools/cooja/java/se/sics/cooja/SimEventCentral.java index 3a1e28990..c572d0c65 100644 --- a/tools/cooja/java/se/sics/cooja/SimEventCentral.java +++ b/tools/cooja/java/se/sics/cooja/SimEventCentral.java @@ -24,17 +24,23 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: SimEventCentral.java,v 1.1 2009/07/02 12:03:09 fros4943 Exp $ + * $Id: SimEventCentral.java,v 1.2 2009/07/03 13:37:41 fros4943 Exp $ */ package se.sics.cooja; +import java.io.File; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Collection; import java.util.Observable; import java.util.Observer; +import java.util.Vector; import org.apache.log4j.Logger; +import org.jdom.Element; +import se.sics.cooja.MoteType.MoteTypeCreationException; import se.sics.cooja.interfaces.Log; import se.sics.cooja.util.ArrayUtils; @@ -55,6 +61,10 @@ public class SimEventCentral { public SimEventCentral(Simulation simulation) { this.simulation = simulation; + /* Default buffer sizes */ + logOutputBufferSize = Integer.parseInt(GUI.getExternalToolsSetting("BUFFERSIZE_LOGOUTPUT", "" + 40000)); + + moteObservations = new ArrayList(); /* Mote count: notifications */ @@ -62,7 +72,7 @@ public class SimEventCentral { /* Log output: notifications and history */ logOutputListeners = new LogOutputListener[0]; - logOutputEvents = new ArrayList(); + logOutputEvents = new ArrayDeque(); } @@ -86,6 +96,10 @@ public class SimEventCentral { public long getTime() { return time; } + + public String toString() { + return "" + ID; + } } /** Help class for maintaining mote-specific observations */ private static class MoteObservation { @@ -183,8 +197,10 @@ public class SimEventCentral { return msg; } } - private ArrayList logOutputEvents; + private int logOutputBufferSize; + private ArrayDeque logOutputEvents; public interface LogOutputListener extends MoteCountListener { + public void removedLogOutput(LogOutputEvent ev); public void newLogOutput(LogOutputEvent ev); } private LogOutputListener[] logOutputListeners; @@ -199,6 +215,17 @@ public class SimEventCentral { msg = msg.substring(0, msg.length() - 1); } + /* We may have to remove some events now */ + while (logOutputEvents.size() > logOutputBufferSize-1) { + LogOutputEvent removed = logOutputEvents.pollFirst(); + if (removed == null) { + break; + } + for (LogOutputListener l: logOutputListeners) { + l.removedLogOutput(removed); + } + } + /* Store log output, and notify listeners */ LogOutputEvent ev = new LogOutputEvent(mote, simulation.getSimulationTime(), msg); @@ -244,6 +271,23 @@ public class SimEventCentral { public LogOutputEvent[] getLogOutputHistory() { return logOutputEvents.toArray(new LogOutputEvent[0]); } + public int getLogOutputBufferSize() { + return logOutputBufferSize; + } + public void setLogOutputBufferSize(int size) { + logOutputBufferSize = size; + + /* We may have to remove some events now */ + while (logOutputEvents.size() > logOutputBufferSize) { + LogOutputEvent removed = logOutputEvents.pollFirst(); + if (removed == null) { + break; + } + for (LogOutputListener l: logOutputListeners) { + l.removedLogOutput(removed); + } + } + } public int getLogOutputObservationsCount() { int count=0; MoteObservation[] observations = moteObservations.toArray(new MoteObservation[0]); @@ -289,4 +333,30 @@ public class SimEventCentral { "\nLog output history: " + logOutputEvents.size() ; } + + + public Collection getConfigXML() { + ArrayList config = new ArrayList(); + Element element; + + /* Log output buffer size */ + element = new Element("logoutput"); + element.setText("" + logOutputBufferSize); + config.add(element); + + return config; + } + + public boolean setConfigXML(Simulation simulation, + Collection configXML, boolean visAvailable) + throws MoteTypeCreationException { + for (Element element : configXML) { + String name = element.getName(); + if (name.equals("logoutput")) { + logOutputBufferSize = Integer.parseInt(element.getText()); + } + } + return true; + } + } diff --git a/tools/cooja/java/se/sics/cooja/Simulation.java b/tools/cooja/java/se/sics/cooja/Simulation.java index ca2c30e50..5f37a57ae 100644 --- a/tools/cooja/java/se/sics/cooja/Simulation.java +++ b/tools/cooja/java/se/sics/cooja/Simulation.java @@ -24,7 +24,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: Simulation.java,v 1.49 2009/07/02 12:04:28 fros4943 Exp $ + * $Id: Simulation.java,v 1.50 2009/07/03 13:37:41 fros4943 Exp $ */ package se.sics.cooja; @@ -413,7 +413,7 @@ public class Simulation extends Observable implements Runnable { * @return Current simulation config */ public Collection getConfigXML() { - Vector config = new Vector(); + ArrayList config = new ArrayList(); Element element; @@ -445,18 +445,23 @@ public class Simulation extends Observable implements Runnable { element = new Element("radiomedium"); element.setText(currentRadioMedium.getClass().getName()); - Collection radioMediumXML = currentRadioMedium.getConfigXML(); + Collection radioMediumXML = currentRadioMedium.getConfigXML(); if (radioMediumXML != null) { element.addContent(radioMediumXML); } config.add(element); + /* Event central */ + element = new Element("events"); + element.addContent(eventCentral.getConfigXML()); + config.add(element); + // Mote types for (MoteType moteType : getMoteTypes()) { element = new Element("motetype"); element.setText(moteType.getClass().getName()); - Collection moteTypeXML = moteType.getConfigXML(); + Collection moteTypeXML = moteType.getConfigXML(); if (moteTypeXML != null) { element.addContent(moteTypeXML); } @@ -468,7 +473,7 @@ public class Simulation extends Observable implements Runnable { element = new Element("mote"); element.setText(mote.getClass().getName()); - Collection moteXML = mote.getConfigXML(); + Collection moteXML = mote.getConfigXML(); if (moteXML != null) { element.addContent(moteXML); } @@ -560,6 +565,11 @@ public class Simulation extends Observable implements Runnable { } } + /* Event central */ + if (element.getName().equals("events")) { + eventCentral.setConfigXML(this, element.getChildren(), visAvailable); + } + // Mote type if (element.getName().equals("motetype")) { String moteTypeClassName = element.getText().trim(); diff --git a/tools/cooja/java/se/sics/cooja/dialogs/BufferSettings.java b/tools/cooja/java/se/sics/cooja/dialogs/BufferSettings.java new file mode 100644 index 000000000..d9c33f31c --- /dev/null +++ b/tools/cooja/java/se/sics/cooja/dialogs/BufferSettings.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2009, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: BufferSettings.java,v 1.1 2009/07/03 13:37:41 fros4943 Exp $ + */ + +package se.sics.cooja.dialogs; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.text.NumberFormat; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.InputMap; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDesktopPane; +import javax.swing.JDialog; +import javax.swing.JFormattedTextField; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.KeyStroke; + +import org.apache.log4j.Logger; + +import se.sics.cooja.GUI; +import se.sics.cooja.SimEventCentral; +import se.sics.cooja.Simulation; + +public class BufferSettings extends JDialog { + private static final long serialVersionUID = 7086171115472941104L; + private static Logger logger = Logger.getLogger(BufferSettings.class); + private final static Dimension LABEL_SIZE = new Dimension(150, 25); + + private SimEventCentral central; + + public static void showDialog(JDesktopPane parent, Simulation simulation) { + if (GUI.isVisualizedInApplet()) { + return; + } + + BufferSettings dialog = new BufferSettings(simulation); + dialog.setLocationRelativeTo(parent); + dialog.setVisible(true); + } + + private BufferSettings(Simulation simulation) { + setTitle("Event buffer settings"); + setResizable(false); + setModal(true); + + central = simulation.getEventCentral(); + + /* Escape key */ + InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "dispose"); + getRootPane().getActionMap().put("dispose", disposeAction); + + Box main = Box.createVerticalBox(); + JButton okButton = new JButton(disposeAction); + getRootPane().setDefaultButton(okButton); + + JFormattedTextField value = addEntry(main, "Log output messages"); + value.setValue(central.getLogOutputBufferSize()); + value.addPropertyChangeListener("value", new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + int newVal = ((Number)evt.getNewValue()).intValue(); + if (newVal < 1) { + newVal = 1; + ((JFormattedTextField)evt.getSource()).setValue(newVal); + } + central.setLogOutputBufferSize(newVal); + } + }); + + main.add(Box.createVerticalStrut(10)); + + Box line = Box.createHorizontalBox(); + line.add(Box.createHorizontalGlue()); + line.add(new JButton(setDefaultAction)); + line.add(okButton); + main.add(line); + + main.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + getContentPane().add(main); + pack(); + } + + private JFormattedTextField addEntry(JComponent container, String desc) { + Box box; + box = Box.createHorizontalBox(); + JLabel label = new JLabel(desc); + label.setPreferredSize(LABEL_SIZE); + box.add(label); + box.add(Box.createHorizontalGlue()); + JFormattedTextField value = new JFormattedTextField(NumberFormat.getIntegerInstance()); + value.setPreferredSize(LABEL_SIZE); + box.add(value); + + container.add(box); + return value; + } + + private Action setDefaultAction = new AbstractAction("Set default") { + public void actionPerformed(ActionEvent e) { + logger.debug("DEFAULT"); + Object[] options = { "Ok", "Cancel" }; + + String question = "Use current settings as default for future simulations?"; + String title = "Set default?"; + int answer = JOptionPane.showOptionDialog(BufferSettings.this, question, title, + JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, + options, options[0]); + + if (answer != JOptionPane.YES_OPTION) { + return; + } + + GUI.setExternalToolsSetting("BUFFERSIZE_LOGOUTPUT", "" + central.getLogOutputBufferSize()); + } + }; + + private Action disposeAction = new AbstractAction("OK") { + public void actionPerformed(ActionEvent e) { + dispose(); + } + }; + +} diff --git a/tools/cooja/java/se/sics/cooja/plugins/LogListener.java b/tools/cooja/java/se/sics/cooja/plugins/LogListener.java index 5df4993ce..d97a7f95c 100644 --- a/tools/cooja/java/se/sics/cooja/plugins/LogListener.java +++ b/tools/cooja/java/se/sics/cooja/plugins/LogListener.java @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: LogListener.java,v 1.17 2009/07/02 12:07:18 fros4943 Exp $ + * $Id: LogListener.java,v 1.18 2009/07/03 13:37:41 fros4943 Exp $ */ package se.sics.cooja.plugins; @@ -247,6 +247,22 @@ public class LogListener extends VisPlugin { } }); } + public void removedLogOutput(final LogOutputEvent ev) { + java.awt.EventQueue.invokeLater(new Runnable() { + public void run() { + LogData toRemove = null; + for (LogData data: logs) { + if (data.ev == ev) { + toRemove = data; + break; + } + } + if (toRemove != null) { + logs.remove(toRemove); + } + } + }); + } }); /* UI components */