summaryrefslogtreecommitdiff
path: root/src/base/stats
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/stats')
-rw-r--r--src/base/stats/events.cc131
-rw-r--r--src/base/stats/events.hh10
-rw-r--r--src/base/stats/mysql.cc253
-rw-r--r--src/base/stats/mysql.hh60
-rw-r--r--src/base/stats/output.cc70
-rw-r--r--src/base/stats/output.hh1
-rw-r--r--src/base/stats/text.cc22
-rw-r--r--src/base/stats/text.hh6
8 files changed, 354 insertions, 199 deletions
diff --git a/src/base/stats/events.cc b/src/base/stats/events.cc
index 6ecc5434c..dc56fe75f 100644
--- a/src/base/stats/events.cc
+++ b/src/base/stats/events.cc
@@ -31,20 +31,8 @@
#include <vector>
#include "base/stats/events.hh"
-
-#if USE_MYSQL
-#include "base/cprintf.hh"
-#include "base/misc.hh"
-#include "base/mysql.hh"
-#include "base/stats/mysql.hh"
-#include "base/stats/mysql_run.hh"
-#include "base/str.hh"
-#endif
-
-#include "base/match.hh"
+#include "base/stats/output.hh"
#include "sim/host.hh"
-#include "sim/sim_object.hh"
-#include "sim/root.hh"
using namespace std;
@@ -52,118 +40,21 @@ namespace Stats {
Tick EventStart = ULL(0x7fffffffffffffff);
-ObjectMatch event_ignore;
+extern list<Output *> OutputList;
#if USE_MYSQL
-class InsertEvent
-{
- private:
- char *query;
- int size;
- bool first;
- static const int maxsize = 1024*1024;
-
- typedef map<string, uint32_t> event_map_t;
- event_map_t events;
-
- MySQL::Connection &mysql;
- uint16_t run;
-
- public:
- InsertEvent()
- : mysql(MySqlDB.conn()), run(MySqlDB.run())
- {
- query = new char[maxsize + 1];
- size = 0;
- first = true;
- flush();
- }
- ~InsertEvent()
- {
- flush();
- }
-
- void flush();
- void insert(const string &stat);
-};
-
void
-InsertEvent::insert(const string &stat)
+__event(const string &event)
{
- assert(mysql.connected());
-
- event_map_t::iterator i = events.find(stat);
- uint32_t event;
- if (i == events.end()) {
- mysql.query(
- csprintf("SELECT en_id "
- "from event_names "
- "where en_name=\"%s\"",
- stat));
-
- MySQL::Result result = mysql.store_result();
- if (!result)
- panic("could not get a run\n%s\n", mysql.error);
-
- assert(result.num_fields() == 1);
- MySQL::Row row = result.fetch_row();
- if (row) {
- if (!to_number(row[0], event))
- panic("invalid event id: %s\n", row[0]);
- } else {
- mysql.query(
- csprintf("INSERT INTO "
- "event_names(en_name)"
- "values(\"%s\")",
- stat));
-
- if (mysql.error)
- panic("could not get a run\n%s\n", mysql.error);
-
- event = mysql.insert_id();
- }
- } else {
- event = (*i).second;
+ list<Output *>::iterator i = OutputList.begin();
+ list<Output *>::iterator end = OutputList.end();
+ for (; i != end; ++i) {
+ Output *output = *i;
+ if (!output->valid())
+ continue;
+
+ output->event(event);
}
-
- if (size + 1024 > maxsize)
- flush();
-
- if (!first) {
- query[size++] = ',';
- query[size] = '\0';
- }
-
- first = false;
-
- size += sprintf(query + size, "(%u,%u,%llu)",
- event, run, (unsigned long long)curTick);
-}
-
-void
-InsertEvent::flush()
-{
- static const char query_header[] = "INSERT INTO "
- "events(ev_event, ev_run, ev_tick)"
- "values";
-
- if (size) {
- MySQL::Connection &mysql = MySqlDB.conn();
- assert(mysql.connected());
- mysql.query(query);
- }
-
- query[0] = '\0';
- size = sizeof(query_header);
- first = true;
- memcpy(query, query_header, size);
-}
-
-void
-__event(const string &stat)
-{
- static InsertEvent event;
- event.insert(stat);
}
#endif
diff --git a/src/base/stats/events.hh b/src/base/stats/events.hh
index b09b91c7c..8ba9cece5 100644
--- a/src/base/stats/events.hh
+++ b/src/base/stats/events.hh
@@ -42,11 +42,10 @@ extern Tick EventStart;
#if USE_MYSQL
void __event(const std::string &stat);
-bool MySqlConnected();
+#else
+inline void __event(const std::string &stat) {}
#endif
-bool ignoreEvent(const std::string &name);
-
inline void
recordEvent(const std::string &stat)
{
@@ -55,12 +54,7 @@ recordEvent(const std::string &stat)
DPRINTF(StatEvents, "Statistics Event: %s\n", stat);
-#if USE_MYSQL
- if (!MySqlConnected())
- return;
-
__event(stat);
-#endif
}
/* namespace Stats */ }
diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc
index 0fb31f4ce..39a687fff 100644
--- a/src/base/stats/mysql.cc
+++ b/src/base/stats/mysql.cc
@@ -43,20 +43,13 @@
#include "base/stats/statdb.hh"
#include "base/stats/types.hh"
#include "base/str.hh"
+#include "base/userinfo.hh"
#include "sim/host.hh"
using namespace std;
namespace Stats {
-MySqlRun MySqlDB;
-
-bool
-MySqlConnected()
-{
- return MySqlDB.connected();
-}
-
void
MySqlRun::connect(const string &host, const string &user, const string &passwd,
const string &db, const string &name, const string &sample,
@@ -196,9 +189,9 @@ SetupStat::init()
}
unsigned
-SetupStat::setup()
+SetupStat::setup(MySqlRun *run)
{
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
stringstream insert;
ccprintf(insert,
@@ -301,7 +294,8 @@ SetupStat::setup()
return statid;
}
-InsertData::InsertData()
+InsertData::InsertData(MySqlRun *_run)
+ : run(_run)
{
query = new char[maxsize + 1];
size = 0;
@@ -317,7 +311,7 @@ void
InsertData::flush()
{
if (size) {
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
assert(mysql.connected());
mysql.query(query);
if (mysql.error)
@@ -349,10 +343,97 @@ InsertData::insert()
first = false;
size += sprintf(query + size, "(%u,%d,%d,%u,%llu,\"%f\")",
- stat, x, y, MySqlDB.run(), (unsigned long long)tick,
+ stat, x, y, run->run(), (unsigned long long)tick,
data);
}
+InsertEvent::InsertEvent(MySqlRun *_run)
+ : run(_run)
+{
+ query = new char[maxsize + 1];
+ size = 0;
+ first = true;
+ flush();
+}
+
+InsertEvent::~InsertEvent()
+{
+ flush();
+}
+
+void
+InsertEvent::insert(const string &stat)
+{
+ MySQL::Connection &mysql = run->conn();
+ assert(mysql.connected());
+
+ event_map_t::iterator i = events.find(stat);
+ uint32_t event;
+ if (i == events.end()) {
+ mysql.query(
+ csprintf("SELECT en_id "
+ "from event_names "
+ "where en_name=\"%s\"",
+ stat));
+
+ MySQL::Result result = mysql.store_result();
+ if (!result)
+ panic("could not get a run\n%s\n", mysql.error);
+
+ assert(result.num_fields() == 1);
+ MySQL::Row row = result.fetch_row();
+ if (row) {
+ if (!to_number(row[0], event))
+ panic("invalid event id: %s\n", row[0]);
+ } else {
+ mysql.query(
+ csprintf("INSERT INTO "
+ "event_names(en_name)"
+ "values(\"%s\")",
+ stat));
+
+ if (mysql.error)
+ panic("could not get a run\n%s\n", mysql.error);
+
+ event = mysql.insert_id();
+ }
+ } else {
+ event = (*i).second;
+ }
+
+ if (size + 1024 > maxsize)
+ flush();
+
+ if (!first) {
+ query[size++] = ',';
+ query[size] = '\0';
+ }
+
+ first = false;
+
+ size += sprintf(query + size, "(%u,%u,%llu)",
+ event, run->run(), (unsigned long long)curTick);
+}
+
+void
+InsertEvent::flush()
+{
+ static const char query_header[] = "INSERT INTO "
+ "events(ev_event, ev_run, ev_tick)"
+ "values";
+
+ MySQL::Connection &mysql = run->conn();
+ assert(mysql.connected());
+
+ if (size)
+ mysql.query(query);
+
+ query[0] = '\0';
+ size = sizeof(query_header);
+ first = true;
+ memcpy(query, query_header, size);
+}
+
struct InsertSubData
{
uint16_t stat;
@@ -361,13 +442,13 @@ struct InsertSubData
string name;
string descr;
- void setup();
+ void setup(MySqlRun *run);
};
void
-InsertSubData::setup()
+InsertSubData::setup(MySqlRun *run)
{
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
assert(mysql.connected());
stringstream insert;
ccprintf(insert,
@@ -383,47 +464,27 @@ InsertSubData::setup()
panic("could not commit transaction\n%s\n", mysql.error);
}
-void
-InsertFormula(uint16_t stat, const string &formula)
-{
- MySQL::Connection &mysql = MySqlDB.conn();
- assert(mysql.connected());
- stringstream insert_formula;
- ccprintf(insert_formula,
- "INSERT INTO formulas(fm_stat,fm_formula) values(%d, \"%s\")",
- stat, formula);
+MySql::MySql()
+ : run(new MySqlRun), newdata(run), newevent(run)
+{}
- mysql.query(insert_formula);
-// if (mysql.error)
-// panic("could not insert formula\n%s\n", mysql.error);
-
- stringstream insert_ref;
- ccprintf(insert_ref,
- "INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)",
- stat, MySqlDB.run());
-
- mysql.query(insert_ref);
-// if (mysql.error)
-// panic("could not insert formula reference\n%s\n", mysql.error);
-
- if (mysql.commit())
- panic("could not commit transaction\n%s\n", mysql.error);
+MySql::~MySql()
+{
+ delete run;
}
void
-UpdatePrereq(uint16_t stat, uint16_t prereq)
+MySql::connect(const string &host, const string &user, const string &passwd,
+ const string &db, const string &name, const string &sample,
+ const string &project)
{
- MySQL::Connection &mysql = MySqlDB.conn();
- assert(mysql.connected());
- stringstream update;
- ccprintf(update, "UPDATE stats SET st_prereq=%d WHERE st_id=%d",
- prereq, stat);
- mysql.query(update);
- if (mysql.error)
- panic("could not update prereq\n%s\n", mysql.error);
+ run->connect(host, user, passwd, db, name, sample, project);
+}
- if (mysql.commit())
- panic("could not commit transaction\n%s\n", mysql.error);
+bool
+MySql::connected() const
+{
+ return run->connected();
}
void
@@ -434,7 +495,7 @@ MySql::configure()
*/
using namespace Database;
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
stat_list_t::const_iterator i, end = stats().end();
for (i = stats().begin(); i != end; ++i) {
@@ -444,11 +505,20 @@ MySql::configure()
for (i = stats().begin(); i != end; ++i) {
StatData *data = *i;
if (data->prereq) {
+ // update the prerequisite
uint16_t stat_id = find(data->id);
uint16_t prereq_id = find(data->prereq->id);
assert(stat_id && prereq_id);
- UpdatePrereq(stat_id, prereq_id);
+ stringstream update;
+ ccprintf(update, "UPDATE stats SET st_prereq=%d WHERE st_id=%d",
+ prereq_id, stat_id);
+ mysql.query(update);
+ if (mysql.error)
+ panic("could not update prereq\n%s\n", mysql.error);
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
}
}
@@ -483,7 +553,7 @@ MySql::configure(const ScalarData &data)
if (!configure(data, "SCALAR"))
return;
- insert(data.id, stat.setup());
+ insert(data.id, stat.setup(run));
}
void
@@ -492,7 +562,7 @@ MySql::configure(const VectorData &data)
if (!configure(data, "VECTOR"))
return;
- uint16_t statid = stat.setup();
+ uint16_t statid = stat.setup(run);
if (!data.subnames.empty()) {
InsertSubData subdata;
@@ -504,7 +574,7 @@ MySql::configure(const VectorData &data)
subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
if (!subdata.name.empty() || !subdata.descr.empty())
- subdata.setup();
+ subdata.setup(run);
}
}
@@ -523,7 +593,7 @@ MySql::configure(const DistData &data)
stat.max = data.data.max;
stat.bktsize = data.data.bucket_size;
}
- insert(data.id, stat.setup());
+ insert(data.id, stat.setup(run));
}
void
@@ -539,7 +609,7 @@ MySql::configure(const VectorDistData &data)
stat.bktsize = data.data[0].bucket_size;
}
- uint16_t statid = stat.setup();
+ uint16_t statid = stat.setup(run);
if (!data.subnames.empty()) {
InsertSubData subdata;
@@ -550,7 +620,7 @@ MySql::configure(const VectorDistData &data)
subdata.name = data.subnames[i];
subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
if (!subdata.name.empty() || !subdata.descr.empty())
- subdata.setup();
+ subdata.setup(run);
}
}
@@ -563,7 +633,7 @@ MySql::configure(const Vector2dData &data)
if (!configure(data, "VECTOR2D"))
return;
- uint16_t statid = stat.setup();
+ uint16_t statid = stat.setup(run);
if (!data.subnames.empty()) {
InsertSubData subdata;
@@ -574,7 +644,7 @@ MySql::configure(const Vector2dData &data)
subdata.name = data.subnames[i];
subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
if (!subdata.name.empty() || !subdata.descr.empty())
- subdata.setup();
+ subdata.setup(run);
}
}
@@ -587,7 +657,7 @@ MySql::configure(const Vector2dData &data)
subdata.y = i;
subdata.name = data.y_subnames[i];
if (!subdata.name.empty())
- subdata.setup();
+ subdata.setup(run);
}
}
@@ -597,15 +667,41 @@ MySql::configure(const Vector2dData &data)
void
MySql::configure(const FormulaData &data)
{
+ MySQL::Connection &mysql = run->conn();
+ assert(mysql.connected());
+
configure(data, "FORMULA");
- insert(data.id, stat.setup());
- InsertFormula(find(data.id), data.str());
+ insert(data.id, stat.setup(run));
+
+ uint16_t stat = find(data.id);
+ string formula = data.str();
+
+ stringstream insert_formula;
+ ccprintf(insert_formula,
+ "INSERT INTO formulas(fm_stat,fm_formula) values(%d, \"%s\")",
+ stat, formula);
+
+ mysql.query(insert_formula);
+// if (mysql.error)
+// panic("could not insert formula\n%s\n", mysql.error);
+
+ stringstream insert_ref;
+ ccprintf(insert_ref,
+ "INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)",
+ stat, run->run());
+
+ mysql.query(insert_ref);
+// if (mysql.error)
+// panic("could not insert formula reference\n%s\n", mysql.error);
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
}
bool
MySql::valid() const
{
- return MySqlDB.connected();
+ return run->connected();
}
void
@@ -620,7 +716,7 @@ MySql::output()
// store sample #
newdata.tick = curTick;
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
Database::stat_list_t::const_iterator i, end = Database::stats().end();
for (i = Database::stats().begin(); i != end; ++i) {
@@ -634,6 +730,13 @@ MySql::output()
}
void
+MySql::event(const std::string &event)
+{
+ newevent.insert(event);
+}
+
+
+void
MySql::output(const ScalarData &data)
{
if (!(data.flags & print))
@@ -825,4 +928,20 @@ MySql::visit(const FormulaData &data)
output(data);
}
-/* namespace Stats */ }
+bool
+initMySQL(string host, string user, string password, string database,
+ string project, string name, string sample)
+{
+ extern list<Output *> OutputList;
+ static MySql mysql;
+
+ if (mysql.connected())
+ return false;
+
+ mysql.connect(host, user, password, database, name, sample, project);
+ OutputList.push_back(&mysql);
+
+ return true;
+}
+
+/* end namespace Stats */ }
diff --git a/src/base/stats/mysql.hh b/src/base/stats/mysql.hh
index 50f7d9e97..0ce381c2f 100644
--- a/src/base/stats/mysql.hh
+++ b/src/base/stats/mysql.hh
@@ -35,14 +35,13 @@
#include <string>
#include "base/stats/output.hh"
+#include "config/use_mysql.hh"
namespace MySQL { class Connection; }
namespace Stats {
class DistDataData;
class MySqlRun;
-bool MySqlConnected();
-extern MySqlRun MySqlDB;
struct SetupStat
{
@@ -63,7 +62,7 @@ struct SetupStat
uint16_t size;
void init();
- unsigned setup();
+ unsigned setup(MySqlRun *run);
};
class InsertData
@@ -85,18 +84,43 @@ class InsertData
int16_t y;
public:
- InsertData();
+ InsertData(MySqlRun *_run);
~InsertData();
void flush();
void insert();
};
+class InsertEvent
+{
+ private:
+ char *query;
+ int size;
+ bool first;
+ static const int maxsize = 1024*1024;
+
+ typedef std::map<std::string, uint32_t> event_map_t;
+ event_map_t events;
+
+ MySqlRun *run;
+
+ public:
+ InsertEvent(MySqlRun *_run);
+ ~InsertEvent();
+
+ void flush();
+ void insert(const std::string &stat);
+};
+
class MySql : public Output
{
protected:
+ MySqlRun *run; /* Hide the implementation so we don't have a
+ #include mess */
+
SetupStat stat;
InsertData newdata;
+ InsertEvent newevent;
std::list<FormulaData *> formulas;
bool configured;
@@ -116,6 +140,17 @@ class MySql : public Output
assert(i != idmap.end());
return (*i).second;
}
+
+ public:
+ MySql();
+ ~MySql();
+
+ void connect(const std::string &host, const std::string &user,
+ const std::string &passwd, const std::string &db,
+ const std::string &name, const std::string &sample,
+ const std::string &project);
+ bool connected() const;
+
public:
// Implement Visit
virtual void visit(const ScalarData &data);
@@ -129,6 +164,9 @@ class MySql : public Output
virtual bool valid() const;
virtual void output();
+ // Implement Event Output
+ virtual void event(const std::string &event);
+
protected:
// Output helper
void output(const DistDataData &data);
@@ -149,6 +187,20 @@ class MySql : public Output
void configure(const FormulaData &data);
};
+bool initMySQL(std::string host, std::string database, std::string user,
+ std::string passwd, std::string project, std::string name,
+ std::string sample);
+
+#if !USE_MYSQL
+inline bool
+initMySQL(std::string host, std::string user, std::string password,
+ std::string database, std::string project, std::string name,
+ std::string sample)
+{
+ return false;
+}
+#endif
+
/* namespace Stats */ }
#endif // __BASE_STATS_MYSQL_HH__
diff --git a/src/base/stats/output.cc b/src/base/stats/output.cc
new file mode 100644
index 000000000..9f2b91c77
--- /dev/null
+++ b/src/base/stats/output.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * 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;
+ * neither the name of the copyright holders 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 COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#include <list>
+
+#include "base/stats/output.hh"
+#include "sim/eventq.hh"
+#include "sim/host.hh"
+
+using namespace std;
+
+namespace Stats {
+
+Tick lastDump(0);
+list<Output *> OutputList;
+
+void
+dump()
+{
+ assert(lastDump <= curTick);
+ if (lastDump == curTick)
+ return;
+ lastDump = curTick;
+
+ list<Output *>::iterator i = OutputList.begin();
+ list<Output *>::iterator end = OutputList.end();
+ for (; i != end; ++i) {
+ Output *output = *i;
+ if (!output->valid())
+ continue;
+
+ output->output();
+ }
+}
+
+/* namespace Stats */ }
+
+void
+debugDumpStats()
+{
+ Stats::dump();
+}
+
diff --git a/src/base/stats/output.hh b/src/base/stats/output.hh
index 4fe93791f..c7ffcaade 100644
--- a/src/base/stats/output.hh
+++ b/src/base/stats/output.hh
@@ -42,6 +42,7 @@ struct Output : public Visit
inline void operator()() { output(); }
virtual void output() = 0;
virtual bool valid() const = 0;
+ virtual void event(const std::string &event) = 0;
};
/* namespace Stats */ }
diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc
index ae0d65537..a018c4837 100644
--- a/src/base/stats/text.cc
+++ b/src/base/stats/text.cc
@@ -251,6 +251,7 @@ VectorPrint::operator()(std::ostream &stream) const
ScalarPrint print;
print.name = name;
print.desc = desc;
+ print.compat = compat;
print.precision = precision;
print.descriptions = descriptions;
print.flags = flags;
@@ -725,4 +726,25 @@ Text::visit(const FormulaData &data)
visit((const VectorData &)data);
}
+bool
+initText(const string &filename, bool desc, bool compat)
+{
+ static Text text;
+ static bool connected = false;
+
+ if (connected)
+ return false;
+
+ extern list<Output *> OutputList;
+
+ text.open(*simout.find(filename));
+ text.descriptions = desc;
+ text.compat = compat;
+ OutputList.push_back(&text);
+ connected = true;
+
+ return true;
+}
+
+
/* namespace Stats */ }
diff --git a/src/base/stats/text.hh b/src/base/stats/text.hh
index b3faf5ad5..781d1083d 100644
--- a/src/base/stats/text.hh
+++ b/src/base/stats/text.hh
@@ -34,6 +34,7 @@
#include <iosfwd>
#include <string>
+#include "base/output.hh"
#include "base/stats/output.hh"
namespace Stats {
@@ -71,8 +72,13 @@ class Text : public Output
// Implement Output
virtual bool valid() const;
virtual void output();
+
+ // Implement Event Output
+ virtual void event(const std::string &event) {}
};
+bool initText(const std::string &filename, bool desc=true, bool compat=true);
+
/* namespace Stats */ }
#endif // __BASE_STATS_TEXT_HH__