From 1ecf4d3def049e8496b7d8f8382a165a7b7f931e Mon Sep 17 00:00:00 2001 From: Caner CANDAN Date: Wed, 4 Aug 2010 13:47:51 +0200 Subject: [PATCH] + feature eoSIGContinue: Continuator can catch user signals + feature eoLogger: flexible logging system for eo --- eo/src/CMakeLists.txt | 3 +- eo/src/eoSIGContinue.cpp | 38 +++++ eo/src/eoSIGContinue.h | 90 ++++++++++++ eo/src/utils/CMakeLists.txt | 4 +- eo/src/utils/eoLogger.cpp | 119 ++++++++++++++++ eo/src/utils/eoLogger.h | 236 ++++++++++++++++++++++++++++++++ eo/src/utils/eoParserLogger.cpp | 51 +++++++ eo/src/utils/eoParserLogger.h | 55 ++++++++ eo/test/CMakeLists.txt | 1 + eo/test/t-eoLogger.cpp | 43 ++++++ 10 files changed, 638 insertions(+), 2 deletions(-) create mode 100644 eo/src/eoSIGContinue.cpp create mode 100644 eo/src/eoSIGContinue.h create mode 100644 eo/src/utils/eoLogger.cpp create mode 100644 eo/src/utils/eoLogger.h create mode 100644 eo/src/utils/eoParserLogger.cpp create mode 100644 eo/src/utils/eoParserLogger.h create mode 100644 eo/test/t-eoLogger.cpp diff --git a/eo/src/CMakeLists.txt b/eo/src/CMakeLists.txt index ab4bc930..df7c8231 100644 --- a/eo/src/CMakeLists.txt +++ b/eo/src/CMakeLists.txt @@ -16,7 +16,8 @@ SET (EO_SOURCES eoFunctorStore.cpp eoPrintable.cpp eoCtrlCContinue.cpp eoParetoFitness.cpp - eoScalarFitnessAssembled.cpp) + eoScalarFitnessAssembled.cpp + eoSIGContinue.cpp) ADD_LIBRARY(eo STATIC ${EO_SOURCES}) diff --git a/eo/src/eoSIGContinue.cpp b/eo/src/eoSIGContinue.cpp new file mode 100644 index 00000000..4bc4ca24 --- /dev/null +++ b/eo/src/eoSIGContinue.cpp @@ -0,0 +1,38 @@ +// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- + +//----------------------------------------------------------------------------- +// eoSIGContinue.cpp +// (c) EEAAX 1996 - GeNeura Team, 1998 - Maarten Keijzer 2000 +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Contact: todos@geneura.ugr.es, http://geneura.ugr.es + Marc.Schoenauer@polytechnique.fr + mak@dhi.dk + Johann Dréo + Caner Candan +*/ +//----------------------------------------------------------------------------- +#ifdef _MSC_VER +// to avoid long name warnings +#pragma warning(disable:4786) +#endif + +#include +#include + +// --- Global variables - but don't know what else to do - MS --- +bool existSIGContinue = false; +bool call_func = false; diff --git a/eo/src/eoSIGContinue.h b/eo/src/eoSIGContinue.h new file mode 100644 index 00000000..2320ebd1 --- /dev/null +++ b/eo/src/eoSIGContinue.h @@ -0,0 +1,90 @@ +// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- + +//----------------------------------------------------------------------------- +// eoSIGContinue.h +// (c) EEAAX 1996 - GeNeura Team, 1998 - Maarten Keijzer 2000 +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Contact: todos@geneura.ugr.es, http://geneura.ugr.es + Marc.Schoenauer@polytechnique.fr + mak@dhi.dk + Johann Dréo + Caner Candan +*/ +//----------------------------------------------------------------------------- +// the same thing can probably be done in MS environement, but I hoave no way +// to test it so at the moment it is commented out when in MSVC + + +#ifndef eoSIGContinue_h +#define eoSIGContinue_h + +#include +#include + +extern bool existSIGContinue; +extern bool call_func; + +void set_bool(int) +{ + call_func = true; +} + +/** + Ctrl C handling: this eoContinue tells whether the user pressed Ctrl C +*/ +template< class EOT> +class eoSIGContinue: public eoContinue +{ +public: + /// Ctor : installs the signal handler + eoSIGContinue(int sig, sighandler_t fct) + : _sig(sig), _fct(fct) + { + // First checks that no other eoSIGContinue does exist + if (existSIGContinue) + throw std::runtime_error("A signal handler is already defined!\n"); + + #ifndef _WINDOWS + #ifdef SIGQUIT + ::signal( sig, set_bool ); + existSIGContinue = true; + #endif + #endif + } + + /** Returns false when the signal has been typed in reached */ + virtual bool operator() ( const eoPop& _vEO ) + { + if (call_func) + { + _fct(_sig); + call_func = false; + } + + return true; + } + + virtual std::string className(void) const { return "eoSIGContinue"; } +private: + int _sig; + sighandler_t _fct; +}; + + +#endif + + // of MSVC comment-out diff --git a/eo/src/utils/CMakeLists.txt b/eo/src/utils/CMakeLists.txt index 216693e4..2d094a08 100644 --- a/eo/src/utils/CMakeLists.txt +++ b/eo/src/utils/CMakeLists.txt @@ -25,7 +25,9 @@ SET (EOUTILS_SOURCES eoData.cpp eoStdoutMonitor.cpp eoUpdater.cpp make_help.cpp - pipecom.cpp) + pipecom.cpp + eoLogger.cpp + eoParserLogger.cpp) ADD_LIBRARY(eoutils STATIC ${EOUTILS_SOURCES}) diff --git a/eo/src/utils/eoLogger.cpp b/eo/src/utils/eoLogger.cpp new file mode 100644 index 00000000..561037b1 --- /dev/null +++ b/eo/src/utils/eoLogger.cpp @@ -0,0 +1,119 @@ +#include +#include +#include +#include // used to define EOF + +#include +#include +#include +#include +#include + +#include "eoLogger.h" + +eoLogger eo::log; + +eoLogger::eoLogger() + : std::ostream(&_obuf), + _selectedLevel(eo::progress), _contexLevel(eo::quiet), + _fd(2), _obuf(_fd, _contexLevel, _selectedLevel) +{ + _standard_io_streams[&std::cout] = 1; + _standard_io_streams[&std::clog] = 2; + _standard_io_streams[&std::cerr] = 2; + + addLevel("quiet", eo::quiet); + addLevel("errors", eo::errors); + addLevel("warnings", eo::warnings); + addLevel("progress", eo::progress); + addLevel("logging", eo::logging); + addLevel("debug", eo::debug); +} + +eoLogger::~eoLogger() +{} + +std::string eoLogger::className() const +{ + return ("eoLogger"); +} + +void eoLogger::addLevel(std::string name, eo::Levels level) +{ + _levels[name] = level; + _sortedLevels.push_back(name); +} + +void eoLogger::printLevels() const +{ + std::cout << "Available verbose levels:" << std::endl; + + for (std::vector::const_iterator it = _sortedLevels.begin(), end = _sortedLevels.end(); + it != end; ++it) + { + std::cout << "\t" << *it << std::endl; + } + + ::exit(0); +} + +eoLogger& operator<<(eoLogger& l, const eo::Levels lvl) +{ + l._contexLevel = lvl; + return l; +} + +eoLogger& operator<<(eoLogger& l, eo::file f) +{ + l._fd = ::open(f._f.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644); + return l; +} + +eoLogger& operator<<(eoLogger& l, eo::setlevel v) +{ + l._selectedLevel = (v._lvl < 0 ? l._levels[v._v] : v._lvl); + return l; +} + +eoLogger& operator<<(eoLogger& l, std::ostream& os) +{ + if (l._standard_io_streams.find(&os) != l._standard_io_streams.end()) + { + l._fd = l._standard_io_streams[&os]; + } + return l; +} + +eoLogger::outbuf::outbuf(const int& fd, + const eo::Levels& contexlvl, + const eo::Levels& selectedlvl) + : _fd(fd), _contexLevel(contexlvl), _selectedLevel(selectedlvl) +{} + +int eoLogger::outbuf::overflow(int_type c) +{ + if (_selectedLevel >= _contexLevel) + { + if (_fd >= 0 && c != EOF) + { + ssize_t num; + num = ::write(_fd, &c, 1); + } + } + return c; +} + +namespace eo +{ + file::file(const std::string f) + : _f(f) + {} + + setlevel::setlevel(const std::string v) + : _v(v), _lvl((Levels)-1) + {} + + setlevel::setlevel(const Levels lvl) + : _v(std::string("")), _lvl(lvl) + {} +} diff --git a/eo/src/utils/eoLogger.h b/eo/src/utils/eoLogger.h new file mode 100644 index 00000000..c7f8348f --- /dev/null +++ b/eo/src/utils/eoLogger.h @@ -0,0 +1,236 @@ +// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- + +//----------------------------------------------------------------------------- +// eoLogger.h +// (c) GeNeura Team, 1998 - EEAAX 1999, Maarten Keijzer 2000 +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Authors: todos@geneura.ugr.es, http://geneura.ugr.es + Marc.Schoenauer@polytechnique.fr + mak@dhi.dk + Johann Dréo + Caner Candan + */ +//----------------------------------------------------------------------------- + +/** Here's an example explaning how to use eoLogger: + + #include + #include + #include + + int main(int ac, char** av) + { + // We are declaring first an overload of eoParser class using Logger + // component. + eoParserLogger parser(ac, av); + + // This call is important to allow -v parameter to change user level. + make_verbose(parser); + + // At this time we are switching to warning message and messages + // which are going to follow it are going to be warnings message too. + // These messages can be displayed only if the user level (sets with + // eo::setlevel function) is set to eo::warnings. + eo::log << eo::warnings; + + // With the following eo::file function we are defining that + // all future logs are going to this new file resource which is + // test.txt + eo::log << eo::file("test.txt") << "In FILE" << std::endl; + + // Now we are changing again the resources destination to cout which + // is the standard output. + eo::log << std::cout << "In COUT" << std::endl; + + // Here are 2 differents examples of how to set the errors user level + // in using either a string or an identifier. + eo::log << eo::setlevel("errors"); + eo::log << eo::setlevel(eo::errors); + + // Now we are writting a quiet message. + eo::log << eo::quiet << "1) Must be in quiet mode" << std::endl; + + // And so on... + eo::log << eo::setlevel(eo::warnings) << eo::warnings << "2) Must be in warnings mode" << std::endl; + + eo::log << eo::setlevel(eo::logging); + + eo::log << eo::errors; + eo::log << "3) Must be in errors mode"; + eo::log << std::endl; + + eo::log << eo::debug << 4 << ')' + << " Must be in debug mode\n"; + + return 0; + } + + */ + +#ifndef eoLogger_h +# define eoLogger_h + +# include +# include +# include +# include + +# include "eoObject.h" + +//----------------------------------------------------------------------------- + +namespace eo +{ + /** + * Levels contents all the available levels in eoLogger + */ + enum Levels {quiet = 0, + errors, + warnings, + progress, + logging, + debug}; + + /** + * file + * this structure combined with the friend operator<< below is an easy way to select a file like output. + */ + struct file + { + file(const std::string f); + const std::string _f; + }; + + /** + * setlevel + * this structure combined with the friend operator<< below is an easy way to set a verbose level. + */ + struct setlevel + { + setlevel(const std::string v); + setlevel(const Levels lvl); + const std::string _v; + const Levels _lvl; + }; +} + +/** + * eoLogger + * Class providing a verbose management through EO + * Use of a global variable eo::log to easily use the logger like std::cout + */ +class eoLogger : public eoObject, + public std::ostream +{ +public: + eoLogger(); + ~eoLogger(); + + virtual std::string className() const; + + void addLevel(std::string name, eo::Levels level); + void printLevels() const; + +private: + /** + * outbuf + * this class is inherits of std::streambuf which is used by eoLogger to write the buffer in an output. + */ + class outbuf : public std::streambuf + { + public: + outbuf(const int& fd, + const eo::Levels& contexlvl, + const eo::Levels& selectedlvl); + protected: + virtual int overflow(int_type c); + private: + const int& _fd; + const eo::Levels& _contexLevel; + const eo::Levels& _selectedLevel; + }; + +private: + /** + * MapLevel is the type used by the map member _levels. + */ + typedef std::map MapLevel; + +public: + /** + * operator<< used there to set a verbose mode. + */ + friend eoLogger& operator<<(eoLogger&, const eo::Levels); + + /** + * operator<< used there to set a filename through the class file. + */ + friend eoLogger& operator<<(eoLogger&, eo::file); + + /** + * operator<< used there to set a verbose level through the class setlevel. + */ + friend eoLogger& operator<<(eoLogger&, eo::setlevel); + + /** + * operator<< used there to be able to use std::cout to say that we wish to redirect back the buffer to the standard output. + */ + friend eoLogger& operator<<(eoLogger&, std::ostream&); + +private: + /** + * _selectedLevel is the member storing verbose level setted by the user thanks to operator() + */ + eo::Levels _selectedLevel; + eo::Levels _contexLevel; + + /** + * _fd in storing the file descriptor at this place we can disable easily the buffer in + * changing the value at -1. It is used by operator <<. + */ + int _fd; + + /** + * _obuf std::ostream mandates to use a buffer. _obuf is a outbuf inheriting of std::streambuf. + */ + outbuf _obuf; + + /** + * _levels contains all the existing level order by position + */ + MapLevel _levels; + + /** + * _levelsOrder is just a list to keep the order of levels + */ + std::vector _sortedLevels; + + /** + * _standard_io_streams + */ + std::map< std::ostream*, int > _standard_io_streams; +}; + +namespace eo +{ + /** + * log is an external global variable defined to easily use a same way than std::cout to write a log. + */ + extern eoLogger log; +} + +#endif // !eoLogger_h diff --git a/eo/src/utils/eoParserLogger.cpp b/eo/src/utils/eoParserLogger.cpp new file mode 100644 index 00000000..4864f1da --- /dev/null +++ b/eo/src/utils/eoParserLogger.cpp @@ -0,0 +1,51 @@ +/* (c) Marc Schoenauer, Maarten Keijzer and GeNeura Team, 2000 + +This library is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your option) any +later version. + +This library is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this library; if not, write to the Free Software Foundation, Inc., 59 +Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Contact: http://eodev.sourceforge.net + todos@geneura.ugr.es, http://geneura.ugr.es + Marc.Schoenauer@polytechnique.fr + mkeijzer@dhi.dk + Johann Dreo + Caner Candan +*/ + +#include "eoParserLogger.h" + +eoParserLogger::eoParserLogger(unsigned _argc, char** _argv, + std::string _programDescription /*= ""*/ + , + std::string _lFileParamName /*= "param-file"*/, + char _shortHand /*= 'p'*/) + : eoParser(_argc, _argv, _programDescription, _lFileParamName, _shortHand), + _verbose("quiet", "verbose", "Set the verbose level", 'v'), + _printVerboseLevels(false, "print-verbose-levels", "Print verbose levels", 'l') +{ + processParam(_verbose); + processParam(_printVerboseLevels); + + if (!_printVerboseLevels.value()) + return; + + eo::log.printLevels(); +} + +eoParserLogger::~eoParserLogger() +{} + +//! make_verbose gets level of verbose and sets it in eoLogger +void make_verbose(eoParserLogger& _parser) +{ + eo::log << eo::setlevel(_parser._verbose.value()); +} diff --git a/eo/src/utils/eoParserLogger.h b/eo/src/utils/eoParserLogger.h new file mode 100644 index 00000000..9ac85bbe --- /dev/null +++ b/eo/src/utils/eoParserLogger.h @@ -0,0 +1,55 @@ +/* (c) Marc Schoenauer, Maarten Keijzer and GeNeura Team, 2000 + +This library is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your option) any +later version. + +This library is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this library; if not, write to the Free Software Foundation, Inc., 59 +Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Contact: http://eodev.sourceforge.net + todos@geneura.ugr.es, http://geneura.ugr.es + Marc.Schoenauer@polytechnique.fr + mkeijzer@dhi.dk + Johann Dreo + Caner Candan +*/ + +#ifndef EO_PARSER_LOGGER_H +#define EO_PARSER_LOGGER_H + +#include "eoParser.h" +#include "eoLogger.h" + +class eoParserLogger : public eoParser +{ +public: + eoParserLogger(unsigned _argc, char** _argv, + std::string _programDescription = "", + std::string _lFileParamName = "param-file", + char _shortHand = 'p'); + ~eoParserLogger(); + +private: + friend void make_verbose(eoParserLogger&); + eoValueParam _verbose; + eoValueParam _printVerboseLevels; +}; + +void make_verbose(eoParserLogger&); + +#endif // !EO_PARSER_LOGGER_H + +// Local Variables: +// coding: iso-8859-1 +// mode: C++ +// c-file-offsets: ((c . 0)) +// c-file-style: "Stroustrup" +// fill-column: 80 +// End: diff --git a/eo/test/CMakeLists.txt b/eo/test/CMakeLists.txt index b8d5b75a..e9ecce70 100644 --- a/eo/test/CMakeLists.txt +++ b/eo/test/CMakeLists.txt @@ -67,6 +67,7 @@ SET (TEST_LIST t-eoParetoFitness t-eoExtendedVelocity # t-eoFrontSorter # t-eoEpsMOEA + t-eoLogger ) FOREACH (test ${TEST_LIST}) diff --git a/eo/test/t-eoLogger.cpp b/eo/test/t-eoLogger.cpp new file mode 100644 index 00000000..cea44166 --- /dev/null +++ b/eo/test/t-eoLogger.cpp @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// t-eoLogger.cpp +//----------------------------------------------------------------------------- + +#include +#include +#include + +//----------------------------------------------------------------------------- + +int main(int ac, char** av) +{ + eoParserLogger parser(ac, av); + + make_verbose(parser); + + eo::log << eo::setlevel(eo::debug); + + eo::log << eo::warnings; + + eo::log << eo::file("test.txt") << "In FILE" << std::endl; + eo::log << std::cout << "In COUT" << std::endl; + + eo::log << eo::setlevel("errors"); + eo::log << eo::setlevel(eo::errors); + + eo::log << eo::quiet << "1) Must be in quiet mode" << std::endl; + + eo::log << eo::setlevel(eo::warnings) << eo::warnings << "2) Must be in warnings mode" << std::endl; + + eo::log << eo::setlevel(eo::logging); + + eo::log << eo::errors; + eo::log << "3) Must be in errors mode"; + eo::log << std::endl; + + eo::log << eo::debug << 4 << ')' + << " Must be in debug mode\n"; + + return 0; +} + +//-----------------------------------------------------------------------------