+ support for configurable buffer sizes (currently only for log output events)

This commit is contained in:
fros4943 2009-07-03 13:37:40 +00:00
parent 7a228fea41
commit 739e21caaf
5 changed files with 283 additions and 12 deletions

View File

@ -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;
}
};
}

View File

@ -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<MoteObservation>();
/* Mote count: notifications */
@ -62,7 +72,7 @@ public class SimEventCentral {
/* Log output: notifications and history */
logOutputListeners = new LogOutputListener[0];
logOutputEvents = new ArrayList<LogOutputEvent>();
logOutputEvents = new ArrayDeque<LogOutputEvent>();
}
@ -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<LogOutputEvent> logOutputEvents;
private int logOutputBufferSize;
private ArrayDeque<LogOutputEvent> 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<Element> getConfigXML() {
ArrayList<Element> config = new ArrayList<Element>();
Element element;
/* Log output buffer size */
element = new Element("logoutput");
element.setText("" + logOutputBufferSize);
config.add(element);
return config;
}
public boolean setConfigXML(Simulation simulation,
Collection<Element> configXML, boolean visAvailable)
throws MoteTypeCreationException {
for (Element element : configXML) {
String name = element.getName();
if (name.equals("logoutput")) {
logOutputBufferSize = Integer.parseInt(element.getText());
}
}
return true;
}
}

View File

@ -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<Element> getConfigXML() {
Vector<Element> config = new Vector<Element>();
ArrayList<Element> config = new ArrayList<Element>();
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<Element> 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<Element> 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<Element> 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();

View File

@ -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();
}
};
}

View File

@ -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 */