00001
00002
00003 #ifndef KERNEL_DATA_LOG_HPP
00004 #define KERNEL_DATA_LOG_HPP
00005
00006 #include <string>
00007 #include <sstream>
00008 #include <fstream>
00009 #include <list>
00010 #include <iomanip>
00011
00012 #include <kernel/threads.hpp>
00013
00014 namespace jafar {
00015
00016 namespace kernel {
00017
00018
00026 class Loggable
00027 {
00028 public:
00029 virtual void log() = 0;
00030 virtual ~Loggable() {}
00031 };
00032
00033
00038 class LoggerTask
00039 {
00040 private:
00041 kernel::VariableCondition<size_t> cond;
00042 std::list<Loggable*> queue;
00043 bool stopping;
00044 boost::thread *task_thread;
00045 int niceness;
00046
00047 private:
00048 void task();
00049
00050 public:
00051 LoggerTask(int niceness = 0);
00052 void push(Loggable *loggable);
00053 void stop(bool wait = true);
00054 void join();
00055 };
00056
00057
00062 class LoggableString: public Loggable
00063 {
00064 private:
00065 std::ostream &logStream;
00066 std::string content;
00067 public:
00068 LoggableString(std::ostream & logStream, std::string const & content):
00069 logStream(logStream), content(content) {}
00070 virtual void log();
00071 };
00072
00073
00078 class LoggableClose: public kernel::Loggable
00079 {
00080 private:
00081 std::fstream *logStream;
00082 std::ofstream *logoStream;
00083 public:
00084 LoggableClose(std::fstream & logStream): logStream(&logStream), logoStream(NULL) {}
00085 LoggableClose(std::ofstream & logoStream): logStream(NULL), logoStream(&logoStream) {}
00086 virtual void log() {
00087 if (logStream && logStream->is_open()) logStream->close();
00088 if (logoStream && logoStream->is_open()) logoStream->close();
00089 }
00090 };
00091
00092
00093 class DataLogger;
00094 class DataLoggable;
00095
00104 class DataLoggable {
00105
00106 private:
00107
00109 DataLogger* p_logger;
00110
00111 void setLogger(DataLogger& logger);
00112
00113 protected:
00114
00115 DataLoggable();
00116 virtual ~DataLoggable();
00117
00122 virtual void writeLogHeader(DataLogger& log) const = 0;
00123
00129 virtual void addMembersToLog(DataLogger& log) const {}
00130
00134 virtual void writeLogData(DataLogger& log) const = 0;
00135
00138 virtual void writeLogStats(DataLogger& log) const {}
00139
00140
00141 friend class DataLogger;
00142
00143 };
00144
00145
00146
00151 class DataLogger {
00152
00153 private:
00154
00155 std::ofstream logStream;
00156 std::ostringstream logHeaderLine;
00157 std::ostringstream logContent;
00158 bool logStarted;
00159
00161 char separator;
00162
00164 char commentPrefix;
00165
00166 unsigned int nbColumns;
00167
00168 LoggerTask *loggerTask;
00169
00170 typedef std::list<DataLoggable const*> LoggablesList;
00171 LoggablesList loggables;
00172
00173 typedef std::list<DataLogger*> LoggersList;
00174 LoggersList slaves;
00175
00176 void write(std::ostringstream & content);
00177
00178 public:
00179
00185 DataLogger(std::string const& logFilename_,
00186 char separator_ = '\t',
00187 char commentPrefix_ = '#');
00188
00190 void setLoggerTask(LoggerTask *loggerTask) { this->loggerTask = loggerTask; }
00191
00193 void writeComment(std::string const& comment_);
00194
00196 void writeCurrentDate();
00197
00199 void addLoggable(DataLoggable& loggable_);
00200
00202 void removeLoggable(DataLoggable const& loggable_);
00203
00207 void addSlaveLogger(DataLogger& logger_);
00208
00210 void log();
00212 void logStats();
00213
00220 void writeLegend(std::string const& legend_);
00221
00230 void writeLegendTokens(std::string const& legendTokens_, std::string const& tokenSep_ = " ");
00231
00233 template <typename T>
00234 void writeData(T const& d) {
00235 logContent << d << separator;
00236 }
00237 void writeNewLine() {
00238 logContent << std::endl;
00239 }
00240
00242 void writeNaN() {
00243 logContent << "NaN" << separator;
00244 }
00245
00247 template <class Vec>
00248 void writeDataVector(Vec const& v) {
00249 for (std::size_t i = 0 ; i < v.size() ; ++i)
00250 writeData(v[i]);
00251 }
00252
00253 };
00254
00255 }
00256 }
00257
00258 #endif // KERNEL_DATA_LOG_HPP