Clean up/standardize handling of various output files.
authorSteve Reinhardt <stever@eecs.umich.edu>
Wed, 20 Oct 2004 00:00:20 +0000 (20:00 -0400)
committerSteve Reinhardt <stever@eecs.umich.edu>
Wed, 20 Oct 2004 00:00:20 +0000 (20:00 -0400)
No more non-intuitive behavior shifts depending on whether
outputDirectory is set (at the expense of backwards compatibility).
outputDirectory is now always valid, defaults to ".".

dev/etherdump.cc:
    Use makeOutputStream() to create output file.
    New behavior: actually complain if dump file can't
    be opened, instead of quietly ignoring the problem.
dev/etherdump.hh:
dev/simconsole.cc:
dev/simconsole.hh:
    Use makeOutputStream() to create output file.
sim/builder.cc:
sim/builder.hh:
sim/main.cc:
    builderStream() is now *configStream.
sim/serialize.cc:
    outputDirectory is now always valid, no need to check.
sim/universe.cc:
    Clean up/standardize handling of various output files.
    No more non-intuitive behavior shifts depending on whether
    outputDirectory is set (at the expense of backwards compatibility).
    outputDirectory is now always valid, defaults to ".".
    New function makeOutputStream() does "the right thing" to
    associate a stream with a filename.

--HG--
extra : convert_revision : a03c58c547221b3906e0d6f55e4a569843f2d646

dev/etherdump.cc
dev/etherdump.hh
dev/simconsole.cc
dev/simconsole.hh
sim/builder.cc
sim/builder.hh
sim/main.cc
sim/serialize.cc
sim/universe.cc

index 27817d4569b4bef7c6e0673bb7fafb4badab0b99..485d5599cba77f946c0d6e9c399497394f895322 100644 (file)
 
 using std::string;
 
-EtherDump::EtherDump(const string &name, const string &file, int max)
-    : SimObject(name), maxlen(max)
+EtherDump::EtherDump(const string &name, std::ostream *_stream, int max)
+    : SimObject(name), stream(_stream), maxlen(max)
 {
-    if (!file.empty())
-        stream.open(file.c_str());
 }
 
 #define DLT_EN10MB             1               // Ethernet (10Mb)
@@ -74,9 +72,6 @@ struct pcap_pkthdr {
 void
 EtherDump::init()
 {
-    if (!stream.is_open())
-        return;
-
     curtime = time(NULL);
     s_freq = ticksPerSecond;
     us_freq = ticksPerSecond / ULL(1000000);
@@ -91,7 +86,7 @@ EtherDump::init()
     hdr.sigfigs = 0;
     hdr.linktype = DLT_EN10MB;
 
-    stream.write(reinterpret_cast<char *>(&hdr), sizeof(hdr));
+    stream->write(reinterpret_cast<char *>(&hdr), sizeof(hdr));
 
     /*
      * output an empty packet with the current time so that we know
@@ -103,9 +98,9 @@ EtherDump::init()
     pkthdr.microseconds = 0;
     pkthdr.caplen = 0;
     pkthdr.len = 0;
-    stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
+    stream->write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
 
-    stream.flush();
+    stream->flush();
 }
 
 void
@@ -116,9 +111,9 @@ EtherDump::dumpPacket(PacketPtr &packet)
     pkthdr.microseconds = (curTick / us_freq) % ULL(1000000);
     pkthdr.caplen = std::min(packet->length, maxlen);
     pkthdr.len = packet->length;
-    stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
-    stream.write(reinterpret_cast<char *>(packet->data), pkthdr.caplen);
-    stream.flush();
+    stream->write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
+    stream->write(reinterpret_cast<char *>(packet->data), pkthdr.caplen);
+    stream->flush();
 }
 
 BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDump)
@@ -130,28 +125,14 @@ END_DECLARE_SIM_OBJECT_PARAMS(EtherDump)
 
 BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDump)
 
-    INIT_PARAM(file, "file to dump packets to"),
+    INIT_PARAM_DFLT(file, "file to dump packets to", "etherdump"),
     INIT_PARAM_DFLT(maxlen, "max portion of packet data to dump", 96)
 
 END_INIT_SIM_OBJECT_PARAMS(EtherDump)
 
 CREATE_SIM_OBJECT(EtherDump)
 {
-    string filename;
-    if (file.isValid()) {
-        filename = file;
-
-        if (filename[0] != '/' && !outputDirectory.empty())
-            filename = outputDirectory + filename;
-    } else {
-        if (outputDirectory.empty()) {
-            filename = "etherdump";
-        } else {
-            filename = outputDirectory + "etherdump";
-        }
-    }
-
-    return new EtherDump(getInstanceName(), filename, maxlen);
+    return new EtherDump(getInstanceName(), makeOutputStream(file), maxlen);
 }
 
 REGISTER_SIM_OBJECT("EtherDump", EtherDump)
index 62364359e22f70e65cdc39ac051182426f48d7c3..b127d05e2f4a31273b084551641118e17452a2ea 100644 (file)
@@ -43,7 +43,7 @@
 class EtherDump : public SimObject
 {
   private:
-    std::ofstream stream;
+    std::ostream *stream;
     const int maxlen;
     void dumpPacket(PacketPtr &packet);
     void init();
@@ -53,9 +53,9 @@ class EtherDump : public SimObject
     Tick us_freq;
 
   public:
-    EtherDump(const std::string &name, const std::string &file, int max);
+    EtherDump(const std::string &name, std::ostream *_stream, int max);
 
-    inline void dump(PacketPtr &pkt) { if (stream.is_open()) dumpPacket(pkt); }
+    inline void dump(PacketPtr &pkt) { dumpPacket(pkt); }
 };
 
 #endif // __ETHERDUMP_H__
index a1505740239490b7385cd468b34e8ee4ce33626a..b2afb3f842ac76039950e01cb431906e9667c1ba 100644 (file)
@@ -72,27 +72,22 @@ SimConsole::Event::process(int revent)
         cons->detach();
 }
 
-SimConsole::SimConsole(const string &name, const string &file, int num)
+SimConsole::SimConsole(const string &name, std::ostream *os, int num)
     : SimObject(name), event(NULL), number(num), in_fd(-1), out_fd(-1),
-      listener(NULL), txbuf(16384), rxbuf(16384), outfile(NULL)
+      listener(NULL), txbuf(16384), rxbuf(16384), outfile(os)
 #if TRACING_ON == 1
       , linebuf(16384)
 #endif
 {
-    if (!file.empty())
-        outfile = new ofstream(file.c_str());
-
     if (outfile)
         outfile->setf(ios::unitbuf);
-
 }
 
 SimConsole::~SimConsole()
 {
     close();
-
     if (outfile)
-        delete outfile;
+        closeOutputStream(outfile);
 }
 
 void
@@ -311,7 +306,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(SimConsole)
 
     INIT_PARAM(listener, "console listener"),
     INIT_PARAM(intr_control, "interrupt controller"),
-    INIT_PARAM_DFLT(output, "file to dump output to", ""),
+    INIT_PARAM(output, "file to dump output to"),
     INIT_PARAM_DFLT(append_name, "append name() to filename", true),
     INIT_PARAM_DFLT(number, "console number", 0)
 
@@ -319,18 +314,18 @@ END_INIT_SIM_OBJECT_PARAMS(SimConsole)
 
 CREATE_SIM_OBJECT(SimConsole)
 {
-    string filename = output;
-    if (filename.empty()) {
-        if (!outputDirectory.empty())
-            filename = outputDirectory + getInstanceName();
+    string filename;
+
+    if (!output.isValid()) {
+        filename = getInstanceName();
+    } else if (append_name) {
+        filename = (string)output + "." + getInstanceName();
     } else {
-        if (append_name)
-            filename += "." + getInstanceName();
-        if (!outputDirectory.empty())
-            filename = outputDirectory + filename;
+        filename = output;
     }
 
-    SimConsole *console = new SimConsole(getInstanceName(), filename, number);
+    SimConsole *console = new SimConsole(getInstanceName(),
+                                         makeOutputStream(filename), number);
     ((ConsoleListener *)listener)->add(console);
 
     return console;
index 138e2e36acbdf272a39780faa3b409f21639cf82..c5a281834168e7f682f085aac1ed1ac5c3c1f5ba 100644 (file)
@@ -70,7 +70,7 @@ class SimConsole : public SimObject
     ConsoleListener *listener;
 
   public:
-    SimConsole(const std::string &name, const std::string &file, int num);
+    SimConsole(const std::string &name, std::ostream *os, int num);
     ~SimConsole();
 
   protected:
index 53e5cf3d82919d685caf6b9307351a773804283f..890451ec491f1d6ac6503ede3f324b05d0073cf2 100644 (file)
 
 using namespace std;
 
-
-ostream &
-builderStream()
-{
-    static ofstream file;
-    static ostream *stream = NULL;
-
-    if (!stream) {
-        if (!outputDirectory.empty()) {
-            string filename = outputDirectory + "builder.txt";
-            file.open(filename.c_str());
-            stream = &file;
-        } else {
-            stream = outputStream;
-        }
-    }
-
-    return *stream;
-}
-
 SimObjectBuilder::SimObjectBuilder(const string &_configClass,
                                    const string &_instanceName,
                                    ConfigNode *_configNode,
@@ -187,10 +167,10 @@ SimObjectClass::createObject(IniFile &configDB,
 
     // echo object parameters to stats file (for documenting the
     // config used to generate the associated stats)
-    builderStream() << "[" << object->name() << "]" << endl;
-    builderStream() << "type=" << simObjClassName << endl;
-    objectBuilder->showParams(builderStream());
-    builderStream() << endl;
+    *configStream << "[" << object->name() << "]" << endl;
+    *configStream << "type=" << simObjClassName << endl;
+    objectBuilder->showParams(*configStream);
+    *configStream << endl;
 
     // done with the SimObjectBuilder now
     delete objectBuilder;
index a85c88b764685e69306f6f819836a3cc4305591e..36e40c2a9a3698766f7c28bed88dccb240faa756 100644 (file)
@@ -38,9 +38,6 @@
 
 class SimObject;
 
-std::ostream &
-builderStream();
-
 //
 // A SimObjectBuilder serves as an evaluation context for a set of
 // parameters that describe a specific instance of a SimObject.  This
index 2a04273031837027288b4fb0341f695ae698be9e..0147ffcc3daf255b63f37d24e2a7cf642959a1c8 100644 (file)
@@ -396,7 +396,7 @@ main(int argc, char **argv)
 
     // Echo command line and all parameter settings to stats file as well.
     echoCommandLine(argc, argv, *outputStream);
-    ParamContext::showAllContexts(builderStream());
+    ParamContext::showAllContexts(*configStream);
 
     // Now process the configuration hierarchy and create the SimObjects.
     ConfigHierarchy configHierarchy(simConfigDB);
index 91548f65352337ac488fd3284e0f0355cbe881f6..2a5e3d398b45d53ad09a8194ae07819e8497a78a 100644 (file)
@@ -335,10 +335,7 @@ SerializeParamContext::checkParams()
     if (serialize_dir.isValid()) {
         checkpointDirBase = serialize_dir;
     } else {
-        if (outputDirectory.empty())
-            checkpointDirBase = "m5.%012d";
-        else
-            checkpointDirBase = outputDirectory + "cpt.%012d";
+        checkpointDirBase = outputDirectory + "cpt.%012d";
     }
 
     // guarantee that directory ends with a '/'
index 79e32098c5fa5a480303e27adba163733de00da7..ffff52104185efcf93b495c469ff4b641babf259 100644 (file)
@@ -51,12 +51,10 @@ double __ticksPerPS;
 
 string outputDirectory;
 ostream *outputStream;
+ostream *configStream;
 
 class UniverseParamContext : public ParamContext
 {
-  private:
-    ofstream outputFile;
-
   public:
     UniverseParamContext(const string &is) : ParamContext(is) {}
     void checkParams();
@@ -68,9 +66,14 @@ Param<Tick> universe_freq(&universe, "frequency", "tick frequency",
                           200000000);
 
 Param<string> universe_output_dir(&universe, "output_dir",
-                                  "directory to output data to");
+                                  "directory to output data to",
+                                  ".");
 Param<string> universe_output_file(&universe, "output_file",
-                                   "file to dump simulator output to");
+                                   "file to dump simulator output to",
+                                   "cout");
+Param<string> universe_config_output_file(&universe, "config_output_file",
+                                          "file to dump simulator config to",
+                                          "m5config.out");
 
 void
 UniverseParamContext::checkParams()
@@ -97,26 +100,49 @@ UniverseParamContext::checkParams()
         }
     }
 
-    string filename;
-    if (universe_output_file.isValid()) {
-        string f = universe_output_file;
-        if (f != "stdout" && f != "cout" && f != "stderr" && f != "cerr")
-            filename = outputDirectory + f;
-        else
-            filename = f;
-    } else {
-        if (outputDirectory.empty())
-            filename = "stdout";
-        else
-            filename = outputDirectory + "output.txt";
-    }
+    outputStream = makeOutputStream(universe_output_file);
+    configStream = universe_config_output_file.isValid()
+        ? makeOutputStream(universe_config_output_file)
+        : outputStream;
+}
 
-    if (filename == "stdout" || filename == "cout")
-        outputStream = &cout;
-    else if (filename == "stderr" || filename == "cerr")
-        outputStream = &cerr;
-    else {
-        outputFile.open(filename.c_str(), ios::trunc);
-        outputStream = &outputFile;
-    }
+
+std::ostream *
+makeOutputStream(std::string &name)
+{
+    if (name == "cerr" || name == "stderr")
+        return &std::cerr;
+
+    if (name == "cout" || name == "stdout")
+        return &std::cout;
+
+    string path = (name[0] != '/') ? outputDirectory + name : name;
+
+    // have to dynamically allocate a stream since we're going to
+    // return it... though the caller can't easily free it since it
+    // may be cerr or cout.  need GC!
+    ofstream *s = new ofstream(path.c_str(), ios::trunc);
+
+    if (!s->is_open())
+        fatal("Cannot open file %s", path);
+
+    return s;
 }
+
+
+void
+closeOutputStream(std::ostream *os)
+{
+    // can't close cerr or cout
+    if (os == &std::cerr || os == &std::cout)
+        return;
+
+    // can only close ofstreams, not generic ostreams, so try to
+    // downcast and close only if the downcast succeeds
+    std::ofstream *ofs = dynamic_cast<std::ofstream *>(os);
+    if (ofs)
+        ofs->close();
+}
+
+
+