diff --git a/include/dynamic-graph/exception-abstract.h b/include/dynamic-graph/exception-abstract.h index 98c069667f0cce0d1f61868348ae273dc51560b9..01a8a436396f91522818585d7f59a4a3fbd76731 100644 --- a/include/dynamic-graph/exception-abstract.h +++ b/include/dynamic-graph/exception-abstract.h @@ -53,6 +53,7 @@ class DYNAMICGRAPH_EXPORT ExceptionAbstract ABSTRACT = 0 ,SIGNAL = 100 ,FACTORY = 200 + ,TRACES = 300 }; static const std::string EXCEPTION_NAME; diff --git a/include/dynamic-graph/exception-traces.h b/include/dynamic-graph/exception-traces.h new file mode 100644 index 0000000000000000000000000000000000000000..1eeecba1366cfc3ad46e3c720372dbefe9ebe4ed --- /dev/null +++ b/include/dynamic-graph/exception-traces.h @@ -0,0 +1,79 @@ +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * Copyright Projet JRL-Japan, 2007 + *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * File: ExceptionTraces.h + * Project: SOT + * Author: Nicolas Mansard + * + * Version control + * =============== + * + * $Id$ + * + * Description + * ============ + * + * + * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + +#ifndef __TRACES_EXCEPTION_H +#define __TRACES_EXCEPTION_H + +/* --------------------------------------------------------------------- */ +/* --- INCLUDE --------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + + +#include <dynamic-graph/exception-abstract.h> +#include <dynamic-graph/dynamic-graph-api.h> + +/* --------------------------------------------------------------------- */ +/* --- CLASS ----------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + +namespace dynamicgraph { + +/* \class ExceptionTraces + */ +class DYNAMICGRAPH_EXPORT ExceptionTraces +:public ExceptionAbstract + +{ + public: + enum ErrorCodeEnum + { + GENERIC = ExceptionAbstract::TRACES + + ,NOT_OPEN + }; + + static const std::string EXCEPTION_NAME; + virtual const std::string& getExceptionName( void ) const { return EXCEPTION_NAME; } + +public: + + ExceptionTraces ( const ExceptionTraces::ErrorCodeEnum& errcode, + const std::string & msg = "" ); + ExceptionTraces( const ExceptionTraces::ErrorCodeEnum& errcode, + const std::string & msg,const char* format, ... ); + virtual ~ExceptionTraces( void ){} + + +}; + + + +} //namespace dynamicgraph + + + + +#endif /* #ifndef __TRACES_EXCEPTION_H */ + +/* + * Local variables: + * c-basic-offset: 2 + * End: + */ diff --git a/include/dynamic-graph/tracer-real-time.h b/include/dynamic-graph/tracer-real-time.h new file mode 100644 index 0000000000000000000000000000000000000000..6a97d738795333dfdb72babc396a71cbb1ad24cf --- /dev/null +++ b/include/dynamic-graph/tracer-real-time.h @@ -0,0 +1,126 @@ +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * Copyright Projet JRL-Japan, 2007 + *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * File: Tracer.h + * Project: DG + * Author: Nicolas Mansard + * + * Version control + * =============== + * + * $Id$ + * + * Description + * ============ + * + * + * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + + +#ifndef __TRACER_RT_H__ +#define __TRACER_RT_H__ + +/* --------------------------------------------------------------------- */ +/* --- INCLUDE --------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + +/* STD */ +#include <sstream> + +/* DG */ +#include <dynamic-graph/tracer.h> + +/* --------------------------------------------------------------------- */ +/* --- API ------------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + +#if defined (WIN32) +# if defined (tracer_real_time_EXPORTS) +# define DGTRACERREALTIME_EXPORT __declspec(dllexport) +# else +# define DGTRACERREALTIME_EXPORT __declspec(dllimport) +# endif +#else +# define DGTRACERREALTIME_EXPORT +#endif + +/* --------------------------------------------------------------------- */ +/* --- TRACER ---------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + +namespace dynamicgraph { + +class DGTRACERREALTIME_EXPORT OutStringStream + : public std::ostringstream +{ +public: + char * buffer; + unsigned int index; + unsigned int bufferSize; + bool full; + std::string givenname; + +public: + + OutStringStream( void ); + ~OutStringStream( void ); + + void resize( const unsigned int & size ); + bool addData( const char * data, const unsigned int & size ); + void dump( std::ostream& os ); + void empty( void ); + +}; + +class DGTRACERREALTIME_EXPORT TracerRealTime +: public Tracer +{ + public: + static const std::string CLASS_NAME; + virtual const std::string& getClassName( void ) { return CLASS_NAME; } + + protected: + int bufferSize; + static const int BUFFER_SIZE_DEFAULT = 1048576; // 1Mo + typedef std::list< std::ofstream* > HardFileList; + HardFileList hardFiles; + + public: + TracerRealTime( const std::string n ); + virtual ~TracerRealTime( void ){ } + + public: + virtual void closeFiles( void ); + virtual void trace( void ); + protected: + virtual void openFile( const SignalBase<int> & sig, + const std::string& filename ); + virtual void recordSignal( std::ostream& os, + const SignalBase<int>& sig ); + void emptyBuffers( void ); + + public: + void setBufferSize( const int & SIZE ) { bufferSize=SIZE; } + const int & getBufferSize( void ) { return bufferSize; } + + public: + + /* --- DISPLAY ------------------------------------------------------------ */ + void display( std::ostream& os ) const; + DGTRACERREALTIME_EXPORT friend std::ostream& operator<< ( std::ostream& os,const TracerRealTime& t ); + + /* --- PARAMS --- */ + virtual void commandLine( const std::string& cmdLine + ,std::istringstream& cmdArgs + ,std::ostream& os ); +}; + + +} // namespace dynamicgraph + + +#endif /* #ifndef __TRACER_RT_H__ */ + + diff --git a/include/dynamic-graph/tracer.h b/include/dynamic-graph/tracer.h new file mode 100644 index 0000000000000000000000000000000000000000..6f9e60ecd203c3d0a39705fdad8aaa56f83fdd8a --- /dev/null +++ b/include/dynamic-graph/tracer.h @@ -0,0 +1,145 @@ +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * Copyright Projet JRL-Japan, 2007 + *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * File: Tracer.h + * Project: DG + * Author: Nicolas Mansard + * + * Version control + * =============== + * + * $Id$ + * + * Description + * ============ + * + * + * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + + +#ifndef __TRACER_H__ +#define __TRACER_H__ + +/* --------------------------------------------------------------------- */ +/* --- INCLUDE --------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + +/* STD */ +#include <string> +#include <list> +#include <boost/function.hpp> + +/* DG */ +#include <dynamic-graph/signal-base.h> +#include <dynamic-graph/signal-time-dependent.h> +#include <dynamic-graph/time-dependency.h> +#include <dynamic-graph/entity.h> +#include <dynamic-graph/exception-traces.h> + +/* --------------------------------------------------------------------- */ +/* --- API ------------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + +#if defined (WIN32) +# if defined (tracer_EXPORTS) +# define DGTRACER_EXPORT __declspec(dllexport) +# else +# define DGTRACER_EXPORT __declspec(dllimport) +# endif +#else +# define DGTRACER_EXPORT +#endif + +/* --------------------------------------------------------------------- */ +/* --- TRACER ---------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + +namespace dynamicgraph { + +class DGTRACER_EXPORT Tracer +: public Entity +{ + protected: + typedef std::list< const SignalBase<int>* > SignalList; + SignalList toTraceSignals; + + + public: + static const std::string CLASS_NAME; + virtual const std::string& getClassName( void ) { return CLASS_NAME; } + + public: + enum TraceStyle + { + WHEN_SAID /// Record, then trace to file only when said to. + ,EACH_TIME /// Record and trace to file immediately. + ,FREQUENTLY /// Record X time then trace (X is tuned by setFrenquence() ). + }; + TraceStyle traceStyle; + static const TraceStyle TRACE_STYLE_DEFAULT = EACH_TIME; + double frequency; + + std::string basename; + std::string suffix; + std::string rootdir; + bool namesSet; + typedef std::list< std::ostream* > FileList; + FileList files; + typedef std::list< std::string > NameList; + NameList names; + bool play; + int timeStart; + + public: + Tracer( const std::string n ); + virtual ~Tracer( void ){ closeFiles(); } + + void addSignalToTrace( const SignalBase<int>& sig, + const std::string& filename="" ); + void clearSignalToTrace( void ); + //void parasite( SignalBase<int>& sig ); + void openFiles( const std::string& rootdir, const std::string& basename, + const std::string& suffix ); + virtual void closeFiles( void ); + + protected: + virtual void openFile( const SignalBase<int> & sig, + const std::string& filename ); + + public: + void setTraceStyle( const TraceStyle& style ){ traceStyle = style; } + TraceStyle getTraceStyle( void ){ return traceStyle; } + + void setFrenquency( const double& frqu ){ frequency = frqu; } + double getFrequency( void ){ return frequency; } + + void record( void ); + virtual void recordSignal( std::ostream& os, + const SignalBase<int>& sig ); + int& recordTrigger( int& dummy, const int& time ); + + virtual void trace( void ); + + public: + //SignalTrigerer<int> triger; + SignalTimeDependent<int,int> triger; + + /* --- DISPLAY ------------------------------------------------------------ */ + DGTRACER_EXPORT friend std::ostream& operator<< ( std::ostream& os,const Tracer& t ); + + /* --- PARAMS --- */ + void display( std::ostream& os ) const; + virtual void commandLine( const std::string& cmdLine + ,std::istringstream& cmdArgs + ,std::ostream& os ); +}; + + +} // namespace dynamicgraph + + +#endif /* #ifndef __TRACER_H__ */ + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 076776c84f58e2caae1730380a6dfecbcd745ee6..9b7c3612fa44a2562094bc9b9bb95129fd9367f9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -55,6 +55,8 @@ SET(plugins_list plugins/shell-functions plugins/shell-procedure debug/contiifstream + traces/tracer + traces/tracer-real-time ) FOREACH(plugin_file ${plugins_list}) diff --git a/src/exception/exception-traces.cpp b/src/exception/exception-traces.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d40ccdff1bf4eee5fd525c2af2eab49eeb04bda0 --- /dev/null +++ b/src/exception/exception-traces.cpp @@ -0,0 +1,62 @@ +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * Copyright Projet JRL-Japan, 2007 + *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * File: ExceptionTraces.cpp + * Project: SOT + * Author: Nicolas Mansard + * + * Version control + * =============== + * + * $Id$ + * + * Description + * ============ + * + * + * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +#include <dynamic-graph/exception-traces.h> +#include <stdarg.h> +#include <cstdio> + + +using namespace dynamicgraph; +/* --------------------------------------------------------------------- */ +/* --- CLASS ----------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + +const std::string ExceptionTraces::EXCEPTION_NAME = "Traces"; + +ExceptionTraces:: +ExceptionTraces ( const ExceptionTraces::ErrorCodeEnum& errcode, + const std::string & msg ) + :ExceptionAbstract(errcode,msg) +{ +} + +ExceptionTraces:: +ExceptionTraces ( const ExceptionTraces::ErrorCodeEnum& errcode, + const std::string & msg,const char* format, ... ) + :ExceptionAbstract(errcode,msg) +{ + va_list args; + va_start(args,format); + + const unsigned int SIZE = 256; + char buffer[SIZE]; + vsnprintf(buffer,SIZE,format,args); + + message += buffer; + + va_end(args); +} + + + +/* + * Local variables: + * c-basic-offset: 2 + * End: + */ diff --git a/src/traces/tracer-real-time.cpp b/src/traces/tracer-real-time.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8c876b0676d155f54e12b21368839a49502a0654 --- /dev/null +++ b/src/traces/tracer-real-time.cpp @@ -0,0 +1,378 @@ +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * Copyright Projet JRL-Japan, 2007 + *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * File: Tracer.cpp + * Project: DG + * Author: Nicolas Mansard + * + * Version control + * =============== + * + * $Id$ + * + * Description + * ============ + * + * + * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + +/* --------------------------------------------------------------------- */ +/* --- INCLUDE --------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + +/* DG */ +#include <iomanip> +#include <boost/bind.hpp> + +#include <dynamic-graph/tracer-real-time.h> +#include <dynamic-graph/debug.h> +#include <dynamic-graph/pool.h> +#include <dynamic-graph/factory.h> + +using namespace std; +using namespace dynamicgraph; + +DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(TracerRealTime,"TracerRealTime"); + +/* --------------------------------------------------------------------- */ +/* --- DGOUTSTRINGSTREAM ---------------------------------------------- */ +/* --------------------------------------------------------------------- */ + +OutStringStream:: +OutStringStream( void ) + : std::ostringstream() + ,buffer( 0 ),index(0),bufferSize(0),full(false) +{ + dgDEBUGINOUT(15); +} + +OutStringStream:: +~OutStringStream( void ) +{ + dgDEBUGIN(15); + if( buffer ) delete [] buffer ; + dgDEBUGOUT(15); +} + +void OutStringStream:: +resize( const unsigned int & size ) +{ + dgDEBUGIN(15); + index=0; bufferSize = size; full=false; + if( 0!=buffer ) delete [] buffer; + buffer = new char [size]; + dgDEBUGOUT(15); +} + +bool OutStringStream:: +addData( const char * data, const unsigned int & size ) +{ + dgDEBUGIN(15); + unsigned int towrite = size; + if( index+towrite>bufferSize ) + { + dgDEBUGOUT(15); + full=true; + return false; + }//towrite=bufferSize-index; + memcpy( buffer+index,data,towrite ); + index+=towrite; + dgDEBUGOUT(15); + return true; + } + +void OutStringStream:: +dump( std::ostream& os ) +{ + dgDEBUGIN(15); + os.write( buffer,index ); + dgDEBUGOUT(15); +} + +void OutStringStream:: +empty( void ) +{ + dgDEBUGIN(15); + index=0; full=false; + dgDEBUGOUT(15); +} + + + +/* --------------------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + + +TracerRealTime::TracerRealTime( const std::string n ) + :Tracer(n) + ,bufferSize( BUFFER_SIZE_DEFAULT ) +{ + dgDEBUGINOUT(15); +} + +/* --------------------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + + +void TracerRealTime:: +openFile( const SignalBase<int> & sig, + const std::string& givenname ) +{ + dgDEBUGIN(15); + string signame; + if( givenname.length() ) + { signame = givenname; } else { signame = sig.shortName(); } + + string filename = rootdir + basename + signame + suffix; + dgDEBUG(5) << "Sig <"<<sig.getName() + << ">: new file "<< filename << endl; + std::ofstream * newfile = new std::ofstream( filename.c_str() ); + hardFiles.push_back( newfile ); + + //std::stringstream * newbuffer = new std::stringstream(); + OutStringStream * newbuffer = new OutStringStream(); // std::stringstream(); + newbuffer->resize( bufferSize ); + newbuffer->givenname = givenname; + files.push_back( newbuffer ); + + dgDEBUGOUT(15); +} + + +void TracerRealTime:: +closeFiles( void ) +{ + dgDEBUGIN(15); + + FileList::iterator iter = files.begin(); + HardFileList::iterator hardIter = hardFiles.begin(); + + while( files.end()!=iter ) + { + dgDEBUG(25) << "Close the files." << endl; + + std::stringstream * file = dynamic_cast< stringstream* >(*iter); + std::ofstream * hardFile = *hardIter; + + (*hardFile) <<flush; hardFile->close(); + delete file; + delete hardFile; + + ++iter; ++hardIter; + } + + dgDEBUG(25) << "Clear the lists." << endl; + files.clear(); + hardFiles.clear(); + + dgDEBUGOUT(15); +} + +void TracerRealTime:: +trace( void ) +{ + dgDEBUGIN(15); + + FileList::iterator iter = files.begin(); + HardFileList::iterator hardIter = hardFiles.begin(); + + while( files.end()!=iter ) + { + dgDEBUG(35) << "Next" << endl; + std::ostream * os = *iter; + if( NULL==os ) + { DG_THROW ExceptionTraces( ExceptionTraces::NOT_OPEN, + "The buffer is null",""); } + //std::stringstream & file = * dynamic_cast< stringstream* >(os); + OutStringStream * file = dynamic_cast< OutStringStream* >(os); // segfault + if( NULL==file ) + { DG_THROW ExceptionTraces( ExceptionTraces::NOT_OPEN, + "The buffer is not open",""); } + + std::ofstream & hardFile = **hardIter; + if(! hardFile.good() ) + { DG_THROW ExceptionTraces( ExceptionTraces::NOT_OPEN, + "The file is not open",""); } + + if( (hardFile.good())&&(NULL!=file) ) + { + +// const unsigned int SIZE = 1024*8; +// char buffer[SIZE]; +// streambuf * pbuf = file.rdbuf(); +// pbuf->pubseekpos(0); +// const unsigned int NB_BYTE = pbuf->in_avail(); +// dgDEBUG(35) << "Bytes in buffer: " << NB_BYTE << endl; +// //dgDEBUG(35) << "Copie" <<endl<<file.str()<< endl; + +// for( unsigned int index=0;index<NB_BYTE;index+=SIZE ) +// { +// pbuf->pubseekpos( index ); +// int nget = pbuf->sgetn( buffer,SIZE ); +// dgDEBUG(35) << "Copie ["<<nget<<"] " <<buffer<<endl; +// hardFile.write( buffer,nget ); +// } + //hardFile << file.str() << flush; + //file.seekp(0); + + file->dump( hardFile ); + file->empty(); + hardFile.flush(); + + //file.str(""); + } + + ++iter; ++hardIter; + } + + dgDEBUGOUT(15); +} + +void TracerRealTime:: +emptyBuffers( void ) +{ + dgDEBUGIN(15); + for( FileList::iterator iter = files.begin();files.end()!=iter;++iter ) + { + //std::stringstream & file = * dynamic_cast< stringstream* >(*iter); + try { + OutStringStream & file = * dynamic_cast< OutStringStream* >(*iter); + file.empty(); + //file.str(""); + } + catch( ... ) { DG_THROW ExceptionTraces( ExceptionTraces::NOT_OPEN, + "The buffer is not open",""); } + } + dgDEBUGOUT(15); +} + + +// void TracerRealTime:: +// emptyBuffer( std::stringstream & file ) +// { +// streambuf * pbuf = file.rdbuf(); +// pbuf->file.rdbuf() ->pubsetbuf( fileBuffer,10 ); + + + +// } +void TracerRealTime:: +recordSignal( std::ostream& os, + const SignalBase<int>& sig ) +{ + dgDEBUGIN(15); + + try { + + OutStringStream & file = dynamic_cast< OutStringStream& >(os); + file.str(""); + dgDEBUG(45) << "Empty file [" << file.tellp() + << "] <" << file.str().c_str() <<"> " <<endl; + + Tracer::recordSignal( file,sig ); + file.addData( file.str().c_str(),file.tellp() ); + dgDEBUG(35) << "Write data [" << file.tellp() + << "] <" << file.str().c_str() <<"> " <<endl; + + } catch( ExceptionAbstract & exc ) { throw exc; } + catch( ... ) { + DG_THROW ExceptionTraces( ExceptionTraces::NOT_OPEN, + "The buffer is not open",""); + } + + + dgDEBUGOUT(15); + return ; +} + + + +/* --------------------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + +void TracerRealTime:: +display( std::ostream& os ) const +{ + os << CLASS_NAME << " " << name << " [mode=" << (play?"play":"pause") + << "] : "<< endl + << " - Dep list: "<<endl; + + FileList::const_iterator iterFile = files.begin(); + for( SignalList::const_iterator iter = toTraceSignals.begin(); + toTraceSignals.end()!=iter;++iter ) + { + dgDEBUG(35) << "Next" << endl; + const OutStringStream * file = dynamic_cast< OutStringStream* >(*iterFile); + os << " -> "<<(*iter)->getName(); + if( file->givenname.length() ) os << " (in " << file->givenname << ")" ; + os << "\t"; + if( file ) + { + const std::streamsize PRECISION = os.precision(); + const unsigned int SIZE = file->index; + const unsigned int MSIZE = file->bufferSize; + unsigned int dec=0; std::string unit =""; + if( (SIZE>>30)||(MSIZE>>30) ) { dec = 30; unit="Go"; } + else if( (SIZE>>20)||(MSIZE>>20) ) { dec = 20; unit="Mo"; } + else if( (SIZE>>10)||(MSIZE>>10) ) { dec = 10; unit="Ko"; } + os << "[" << std::setw(1)<<std::setprecision(1) + << ((SIZE+0.0)/(1<<dec)) << unit << "/" + << std::setprecision(2)<<((MSIZE+0.0)/(1<<dec)) + << unit << "]\t"; + if( file->full ) os << "(FULL)"; + os.precision(PRECISION); + } + os<<endl; + iterFile++; + } + +} + + +std::ostream& operator<< ( std::ostream& os,const TracerRealTime& t ) +{ + t.display(os); + return os; +} + + +void TracerRealTime:: +commandLine( const std::string& cmdLine + ,std::istringstream& cmdArgs + ,std::ostream& os ) +{ + if( cmdLine=="help" ) + { + os << "TracerRealTime: "<<endl + << " - empty: trash the buffers." <<endl + << " - bufferSize [<size>]: get/set the buffer size." <<endl; + + Tracer::commandLine( cmdLine,cmdArgs,os ); + } + else if( cmdLine=="empty" ) + { + emptyBuffers(); + } + else if( cmdLine=="bufferSize" ) + { + cmdArgs>>ws; + if( cmdArgs.good() ) + { + int s; cmdArgs>>s; + setBufferSize( s ); + } + else os << getBufferSize() << endl; + } + + + else + Tracer::commandLine( cmdLine,cmdArgs,os ); + + + +} diff --git a/src/traces/tracer.cpp b/src/traces/tracer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4d0dfc0ab71ae2d3057a9f82f2ef9e1d60f22549 --- /dev/null +++ b/src/traces/tracer.cpp @@ -0,0 +1,321 @@ +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * Copyright Projet JRL-Japan, 2007 + *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * File: Tracer.cpp + * Project: Dynamicgraph + * Author: Nicolas Mansard + * + * Version control + * =============== + * + * $Id$ + * + * Description + * ============ + * + * + * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + +/* --------------------------------------------------------------------- */ +/* --- INCLUDE --------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + +/* DG */ +#include <dynamic-graph/tracer.h> +#include <dynamic-graph/debug.h> +#include <dynamic-graph/pool.h> +#include <dynamic-graph/factory.h> +#include <boost/bind.hpp> + +using namespace std; +using namespace dynamicgraph; + +DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(Tracer,"Tracer"); + +/* --------------------------------------------------------------------- */ +/* --- CLASS ----------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + +Tracer::Tracer( const std::string n ) + :Entity(n) + ,toTraceSignals() + ,traceStyle(TRACE_STYLE_DEFAULT) + ,frequency(1) + ,basename() + ,suffix(".dat") + ,rootdir() + ,namesSet( false ) + ,files() + ,names() + ,play(false) + ,timeStart(0) + ,triger( boost::bind(&Tracer::recordTrigger,this,_1,_2), + sotNOSIGNAL, + "Tracer("+n+")::triger" ) +{ + signalRegistration( triger ); +} + +/* --------------------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + + +void Tracer:: +addSignalToTrace( const SignalBase<int>& sig, + const string& filename ) +{ + dgDEBUGIN(15); + toTraceSignals.push_back( &sig ); dgDEBUGF(15,"%p",&sig); + names.push_back( filename ); + if( namesSet ) openFile( sig,filename ); + triger.addDependency( sig ); + dgDEBUGOUT(15); +} + +/*! Empty the list of signals to trace. This function + * does not modify the file list (it does not close + * the files in particular. + */ +void Tracer:: +clearSignalToTrace( void ) +{ + toTraceSignals.clear(); + triger.clearDependencies(); +} + + +// void Tracer:: +// parasite( SignalBase<int>& sig ) +// { +// triger.parasite(sig); +// } + +void Tracer:: +openFiles( const std::string& rootdir_, const std::string& basename_, + const std::string& suffix_ ) +{ + dgDEBUGIN(15); + int n = rootdir_.length(); + rootdir=rootdir_; + if( (0<n)&('/'!=rootdir[n-1]) ) rootdir+='/'; + + basename=basename_; + suffix=suffix_; + + if( files.size() ) closeFiles(); + + SignalList::const_iterator iter = toTraceSignals.begin(); + NameList::const_iterator iterName = names.begin(); + while( toTraceSignals.end()!=iter ) + { + dgDEBUG(15) << "Open <" << (*iter)->getName() + << "> in <" << *iterName << ">." << std::endl; + openFile( **iter,*iterName ); + ++iter; ++iterName; + } + + namesSet = true; + dgDEBUGOUT(15); +} + +void Tracer:: +openFile( const SignalBase<int> & sig, + const string& givenname ) +{ + dgDEBUGIN(15); + string signame; + if( givenname.length() ) + { signame = givenname; } else { signame = sig.shortName(); } + + string filename = rootdir + basename + signame + suffix; + + dgDEBUG(5) << "Sig <"<< sig.getName() << ">: new file "<< filename << endl; + std::ofstream * newfile = new std::ofstream( filename.c_str() ); + files.push_back( newfile ); + dgDEBUGOUT(15); +} + + +void Tracer:: +closeFiles( void ) +{ + dgDEBUGIN(15); + + for( FileList::iterator iter = files.begin();files.end()!=iter;++iter ) + { + std::ostream * filePtr = *iter; + delete filePtr; + } + files.clear(); + + dgDEBUGOUT(15); +} + +/* --------------------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + +void Tracer:: +record( void ) +{ + if(! play) { dgDEBUGINOUT(15); return;} + + dgDEBUGIN(15); + + if( files.size()!=toTraceSignals.size() ) + { DG_THROW ExceptionTraces( ExceptionTraces::NOT_OPEN, + "No files open for tracing"," (file=%d != %d=sig).", + files.size(),toTraceSignals.size()); } + + FileList::iterator iterFile = files.begin(); + SignalList::iterator iterSig = toTraceSignals.begin(); + + while( toTraceSignals.end()!=iterSig ) + { + dgDEBUG(45) << "Try..." <<endl; + recordSignal( **iterFile,**iterSig ); + ++iterSig; ++iterFile; + } + dgDEBUGOUT(15); +} + +void Tracer:: +recordSignal( std::ostream& os, + const SignalBase<int>& sig ) +{ + dgDEBUGIN(15); + + try { + if( sig.getTime()>timeStart ) + { + os<< sig.getTime() << "\t"; + sig.trace(os); os<<endl; + } + } + catch( ExceptionAbstract& exc ) { os << exc << std::endl; } + catch( ... ) { os << "Unknown error occured while reading signal." << std::endl; } + + dgDEBUGOUT(15); + +} + + +int& Tracer:: +recordTrigger( int& dummy, const int& time ) +{ + dgDEBUGIN(15) << " time="<<time <<endl; + record(); + dgDEBUGOUT(15); + return dummy; +} + + +void Tracer:: +trace( void ) +{ +} + +/* --------------------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ +/* --------------------------------------------------------------------- */ + + +void Tracer:: +display( std::ostream& os ) const +{ + os << CLASS_NAME << " " << name << " [mode=" << (play?"play":"pause") + << "] : "<< endl + << " - Dep list: "<<endl; + for( SignalList::const_iterator iter = toTraceSignals.begin(); + toTraceSignals.end()!=iter;++iter ) + { os << " -> "<<(*iter)->getName()<<endl; } +} + + +std::ostream& operator<< ( std::ostream& os,const Tracer& t ) +{ + t.display(os); + return os; +} + + +void Tracer:: +commandLine( const std::string& cmdLine + ,std::istringstream& cmdArgs + ,std::ostream& os ) +{ + if( cmdLine=="help" ) + { + os << "Tracer: "<<endl + << " - add <obj.signal> [<filename>=<signal>] "<<endl + << " - clear"<<endl + << " - open [<root> [<file> [<suffix>=.dat]]]"<<endl + << " - close "<<endl + << " - record "<<endl + << " - trace "<<endl + << " - start/stop" << endl; + // << " - parasite <obj.signal> "<<endl; + + Entity::commandLine( cmdLine,cmdArgs,os ); + } + else if( cmdLine=="add" ) + { + SignalBase<int> &sig = g_pool.getSignal(cmdArgs); + string r; cmdArgs>>ws>>r; + addSignalToTrace(sig,r); + dgDEBUG(14)<<"Add <" <<sig.getName()<<"> with nick \""<<r<<"\""<<endl; + } + else if( cmdLine=="clear" ) + { closeFiles(); toTraceSignals.clear(); } + else if( cmdLine=="open" ) + { + string n,r="",s=".dat"; + cmdArgs>>ws>>r; + if( cmdArgs.good() ) + { + cmdArgs>>ws>>n; + if( cmdArgs.good() ) + { + cmdArgs>>ws>>s; + } + } + + //>>r>>s; + dgDEBUGF( 15,"Close files."); + closeFiles(); + dgDEBUGF( 15,"Open files \"%s\" \"%s\" \"%s\".", + r.c_str(),n.c_str(),s.c_str()); + openFiles(r,n,s); + } + else if( cmdLine=="close" ) { closeFiles(); } + else if( cmdLine=="trace" ) { trace(); } + else if( cmdLine=="record" ) + { + //unsigned int t; + //cmdArgs >> ws>>t; if(! cmdArgs.good() ) t=0; + record(); + } +// else if( cmdLine=="parasite" ) +// { +// SignalBase<int> &sig = g_pool.getSignal( cmdArgs ); +// parasite(sig); +// } + else if( cmdLine == "start" ) { play=true; } + else if( cmdLine == "stop" ) { play=false; } + else if( cmdLine == "timeStart" ) + { + cmdArgs >> std::ws; if(! cmdArgs.good() ) + { os << "timeStart = " << timeStart << std::endl; } + else { cmdArgs >> timeStart; } + } + + + else //sotTaskAbstract:: + Entity::commandLine( cmdLine,cmdArgs,os ); + + + +}