From 8b4d057a7eb7340a40b0456a67746ea547332e5f Mon Sep 17 00:00:00 2001 From: nifi Date: Tue, 27 Oct 2009 08:41:01 +0000 Subject: [PATCH] Changed file redirection in CLI to be more similar to normal shell. ">file" will overwrite file and ">>file" will append to file. Closing a file will stop all attached commands git-svn-id: https://mspsim.svn.sourceforge.net/svnroot/mspsim/mspsim@638 23d1a52b-0c3c-0410-b72d-8f29ab48fe35 --- scripts/autorun.sc | 5 +- se/sics/mspsim/cli/FileCommands.java | 32 +++-- se/sics/mspsim/cli/FileTarget.java | 159 +++++++++++++++++----- se/sics/mspsim/cli/FileTargetCommand.java | 43 +++--- 4 files changed, 176 insertions(+), 63 deletions(-) diff --git a/scripts/autorun.sc b/scripts/autorun.sc index de1450c..396a6a0 100644 --- a/scripts/autorun.sc +++ b/scripts/autorun.sc @@ -1,8 +1,7 @@ # autorun script for MSPSim # - all commands will run after loaded firmware into MSPSim -#exec rm log.txt #log CC2420 >log.txt -#printcalls >log.txt +#printcalls >>log.txt # Install and activate the plugin 'ContikiChecker' # install ContikiChecker @@ -12,5 +11,5 @@ service controlgui start service nodegui start #service stackchart start -rflistener output CC2420 > rfdata.txt +#rflistener output CC2420 >> rfdata.txt start diff --git a/se/sics/mspsim/cli/FileCommands.java b/se/sics/mspsim/cli/FileCommands.java index 4db9eb0..e460c0d 100644 --- a/se/sics/mspsim/cli/FileCommands.java +++ b/se/sics/mspsim/cli/FileCommands.java @@ -1,21 +1,24 @@ package se.sics.mspsim.cli; import java.util.Hashtable; -import java.util.Iterator; import se.sics.mspsim.util.ComponentRegistry; public class FileCommands implements CommandBundle { - private Hashtable fileTargets = new Hashtable(); + private final Hashtable fileTargets = new Hashtable(); public void setupCommands(final ComponentRegistry registry, CommandHandler handler) { // TODO: this should also be "registered" as a "sink". // probably this should be handled using ">" instead! handler.registerCommand(">", new FileTargetCommand(fileTargets, - null, "", false)); + null, "", false, false)); + + handler.registerCommand(">>", new FileTargetCommand(fileTargets, + null, "", false, true)); + handler.registerCommand("tee", new FileTargetCommand(fileTargets, - "redirect to file and std-out", "", true)); + "redirect to file and standard out", "", true, true)); handler.registerCommand("fclose", new BasicCommand("close the specified file", "") { public int executeCommand(CommandContext context) { @@ -23,21 +26,28 @@ public class FileCommands implements CommandBundle { FileTarget ft = fileTargets.get(name); if (ft != null) { context.out.println("Closing file " + name); - fileTargets.remove(name); ft.close(); return 0; - } else { - context.err.println("Could not find the open file " + name); - return 1; } + context.err.println("Could not find the open file " + name); + return 1; } }); handler.registerCommand("files", new BasicCommand("list open files", "") { public int executeCommand(CommandContext context) { - for (Iterator iterator = fileTargets.values().iterator(); iterator.hasNext();) { - FileTarget type = iterator.next(); - context.out.println(type.getName()); + FileTarget[] files = null; + synchronized (fileTargets) { + if (fileTargets.size() > 0) { + files = fileTargets.values().toArray(new FileTarget[fileTargets.size()]); + } + } + if (files == null) { + context.out.println("There are no open files."); + } else { + for (FileTarget type : files) { + context.out.println(type.getStatus()); + } } return 0; } diff --git a/se/sics/mspsim/cli/FileTarget.java b/se/sics/mspsim/cli/FileTarget.java index 0448425..9dccd9f 100644 --- a/se/sics/mspsim/cli/FileTarget.java +++ b/se/sics/mspsim/cli/FileTarget.java @@ -42,48 +42,141 @@ package se.sics.mspsim.cli; import java.io.FileWriter; import java.io.IOException; +import java.util.ArrayList; +import java.util.Hashtable; /** * @author joakim - * */ -public class FileTarget implements LineListener { +public class FileTarget { - private final FileWriter out; - private final String name; + private static final boolean DEBUG = false; - public FileTarget(String name) throws IOException { - this.out = new FileWriter(name); - this.name = name; - } + private final Hashtable fileTargets; + private final String name; + private final FileWriter out; + private ArrayList contexts = new ArrayList(); - public String getName() { - return name; - } - - /* (non-Javadoc) - * @see se.sics.mspsim.cli.LineListener#lineRead(java.lang.String) - */ - public void lineRead(String line) { - if (line == null) { - close(); - } else { - try { - out.write(line); - out.write('\n'); - out.flush(); - } catch (IOException e) { - e.printStackTrace(); - }; + public FileTarget(Hashtable fileTargets, String name, + boolean append) throws IOException { + this.fileTargets = fileTargets; + this.out = new FileWriter(name, append); + this.name = name; + fileTargets.put(name, this); } - } - public void close() { - try { - out.close(); - } catch (IOException e) { - e.printStackTrace(); + public String getName() { + return name; + } + + public String getStatus() { + StringBuilder sb = new StringBuilder(); + sb.append(name); + synchronized (fileTargets) { + if (contexts != null) { + sb.append(" \tPIDs: ["); + for (int i = 0, n = contexts.size(); i < n; i++) { + int pid = contexts.get(i).getPID(); + if (i > 0) { + sb.append(','); + } + if (pid < 0) { + sb.append('?'); + } else { + sb.append(pid); + } + } + sb.append(']'); + } + } + return sb.toString(); + } + + public void lineRead(CommandContext context, String line) { + if (line == null) { + removeContext(context); + } else { + try { + out.write(line); + out.write('\n'); + out.flush(); + } catch (IOException e) { + e.printStackTrace(context.err); + } + } + } + + public void addContext(CommandContext context) { + boolean added = false; + synchronized (fileTargets) { + if (contexts != null) { + contexts.add(context); + added = true; + if (DEBUG) { + System.out.println("FileTarget: new writer to " + name + + " (" + contexts.size() + ')'); + } + } + } + if (!added) { + context.kill(); + } + } + + public void removeContext(CommandContext context) { + boolean close = false; + synchronized (fileTargets) { + if (contexts != null && contexts.remove(context)) { + if (DEBUG) { + System.out.println("FileTarget: removed writer from " + + name + " (" + contexts.size() + ')'); + } + if (contexts.size() == 0) { + close = true; + } + } + } + if (close) { + close(false); + } + } + + public void close() { + close(true); + } + + private void close(boolean forceClose) { + ArrayList list; + synchronized (fileTargets) { + if (contexts == null) { + // Already closed + return; + } + if (contexts.size() > 0 && !forceClose) { + // File still has connected writers. + return; + } + list = contexts; + contexts = null; + if (fileTargets.get(name) == this) { + fileTargets.remove(name); + if (DEBUG) { + System.out.println("FileTarget: closed file " + name); + } + } + } + + if (list != null) { + // Close any connected writers + for (CommandContext context : list) { + context.kill(); + } + } + try { + out.close(); + } catch (IOException e) { + // Ignore close errors + } } - } } diff --git a/se/sics/mspsim/cli/FileTargetCommand.java b/se/sics/mspsim/cli/FileTargetCommand.java index 6edf92b..a949930 100644 --- a/se/sics/mspsim/cli/FileTargetCommand.java +++ b/se/sics/mspsim/cli/FileTargetCommand.java @@ -4,39 +4,50 @@ import java.io.IOException; import java.util.Hashtable; public class FileTargetCommand extends BasicLineCommand { - FileTarget ft; - Hashtable fileTargets; - private boolean print; + private final Hashtable fileTargets; + private final boolean print; + private final boolean append; + + private FileTarget ft; private CommandContext context; public FileTargetCommand(Hashtable fileTargets, - String name, String desc, boolean print) { + String name, String desc, boolean print, boolean append) { super(name, desc); this.fileTargets = fileTargets; this.print = print; + this.append = append; } + public int executeCommand(CommandContext context) { this.context = context; String fileName = context.getArgument(0); - ft = fileTargets.get(fileName); - if (ft == null) { - try { - ft = new FileTarget(fileName); - fileTargets.put(fileName, ft); - } catch (IOException e) { - e.printStackTrace(); + synchronized (fileTargets) { + ft = fileTargets.get(fileName); + if (ft == null) { + try { + ft = new FileTarget(fileTargets, fileName, append); + } catch (IOException e) { + e.printStackTrace(context.err); + return -1; + } + } else if (!append) { + context.err.println("File already opened: can not overwrite"); + return -1; } + ft.addContext(context); } return 0; } - + public void lineRead(String line) { - ft.lineRead(line); if (print) context.out.println(line); + ft.lineRead(context, line); } - + public void stopCommand(CommandContext context) { - // Should this do anything? - // Probably depending on the ft's config + if (ft != null) { + ft.removeContext(context); + } } }