tracer.cpp 8.78 KB
Newer Older
Thomas Moulard's avatar
Thomas Moulard committed
1
2
3
4
/*
 * Copyright 2010,
 * François Bleibel,
 * Olivier Stasse,
5
 *
Thomas Moulard's avatar
Thomas Moulard committed
6
 * CNRS/AIST
7
 *
Thomas Moulard's avatar
Thomas Moulard committed
8
 * This file is part of dynamic-graph.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 * dynamic-graph is free software:
 * 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.
 *
 * 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 HOLDER 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.
Thomas Moulard's avatar
Thomas Moulard committed
30
 */
31
32
33
34
35
36
37
38

/* --------------------------------------------------------------------- */
/* --- INCLUDE --------------------------------------------------------- */
/* --------------------------------------------------------------------- */

/* DG */
#include <dynamic-graph/tracer.h>
#include <dynamic-graph/debug.h>
Francois Keith's avatar
Francois Keith committed
39
#include <dynamic-graph/value.h>
40
41
#include <dynamic-graph/pool.h>
#include <dynamic-graph/factory.h>
42
#include <dynamic-graph/all-commands.h>
43
44
45
46
#include <boost/bind.hpp>

using namespace std;
using namespace dynamicgraph;
Francois Keith's avatar
Francois Keith committed
47
using namespace dynamicgraph::command;
48
49
50
51
52
53
54
55
56

DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(Tracer,"Tracer");

/* --------------------------------------------------------------------- */
/* --- CLASS ----------------------------------------------------------- */
/* --------------------------------------------------------------------- */

Tracer::Tracer( const std::string n )
  :Entity(n)
Thomas Moulard's avatar
Thomas Moulard committed
57
   ,toTraceSignals ()
58
59
   ,traceStyle(TRACE_STYLE_DEFAULT)
   ,frequency(1)
Thomas Moulard's avatar
Thomas Moulard committed
60
   ,basename ()
61
   ,suffix(".dat")
Thomas Moulard's avatar
Thomas Moulard committed
62
   ,rootdir ()
63
   ,namesSet( false )
Thomas Moulard's avatar
Thomas Moulard committed
64
65
   ,files ()
   ,names ()
66
67
68
69
70
71
72
   ,play(false)
   ,timeStart(0)
   ,triger( boost::bind(&Tracer::recordTrigger,this,_1,_2),
	    sotNOSIGNAL,
	   "Tracer("+n+")::triger" )
{
  signalRegistration( triger );
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118


  /* --- Commands --- */
  {
    using namespace dynamicgraph::command;
    std::string doc;

    doc = docCommandVoid2("Add a new signal to trace.",
			  "string (signal name)","string (filename, empty for default");
    addCommand("add",
	       makeCommandVoid2(*this,&Tracer::addSignalToTraceByName,doc ));

    doc = docCommandVoid0("Remove all signals. If necessary, close open files.");
    addCommand("clear",
	       makeCommandVoid0(*this,&Tracer::clearSignalToTrace,doc ));

    doc = docCommandVoid3("Gives the args for file opening, and "
			  "if signals have been set, open the corresponding files.",
			  "string (dirname)","string (prefix)","string (suffix)");
    addCommand("open",
	       makeCommandVoid3(*this,&Tracer::openFiles,doc ));

    doc = docCommandVoid0("Close all the open files.");
    addCommand("close",
	       makeCommandVoid0(*this,&Tracer::closeFiles,doc ));

    doc = docCommandVoid0("If necessary, dump "
			  "(can be done automatically for some traces type).");
    addCommand("dump",
	       makeCommandVoid0(*this,&Tracer::trace,doc ));

    doc = docCommandVoid0("Start the tracing process.");
    addCommand("start",
	       makeCommandVoid0(*this,&Tracer::start,doc ));

    doc = docCommandVoid0("Stop temporarily the tracing process.");
    addCommand("stop",
	       makeCommandVoid0(*this,&Tracer::stop,doc ));

    addCommand("getTimeStart",
	       makeDirectGetter(*this,&timeStart,
				docDirectGetter("timeStart","int")));
    addCommand("setTimeStart",
	       makeDirectSetter(*this,&timeStart,
				docDirectSetter("timeStart","int")));
  } // using namespace command
Thomas Moulard's avatar
Thomas Moulard committed
119
}
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */


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);
Thomas Moulard's avatar
Thomas Moulard committed
136
}
137

138
139
140
141
142
143
void Tracer::
addSignalToTraceByName( const string& signame,
			const string& filename )
{
  dgDEBUGIN(15);
  istringstream iss( signame );
144
  SignalBase<int> &sig = PoolStorage::getInstance()->getSignal(iss);
145
146
147
148
  addSignalToTrace(sig,filename);
  dgDEBUGOUT(15);
}

149
150
/*! Empty the list of signals to trace. This function
 * does not modify the file list (it does not close
Thomas Moulard's avatar
Thomas Moulard committed
151
 * the files in particular.
152
153
 */
void Tracer::
Thomas Moulard's avatar
Thomas Moulard committed
154
clearSignalToTrace  ()
155
{
156
  closeFiles ();
Thomas Moulard's avatar
Thomas Moulard committed
157
158
  toTraceSignals.clear ();
  triger.clearDependencies ();
159
160
161
162
163
164
165
166
167
168
169
170
171
}

// 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);
172
  std::basic_string<char>::size_type n = rootdir_.length ();
173
  rootdir = rootdir_;
174
  if( (0<n)&('/'!=rootdir[n-1]) ) rootdir+='/';
Thomas Moulard's avatar
Thomas Moulard committed
175

176
177
178
  basename=basename_;
  suffix=suffix_;

Thomas Moulard's avatar
Thomas Moulard committed
179
  if( files.size () ) closeFiles ();
180

Thomas Moulard's avatar
Thomas Moulard committed
181
182
183
  SignalList::const_iterator iter = toTraceSignals.begin ();
  NameList::const_iterator iterName = names.begin ();
  while( toTraceSignals.end ()!=iter )
184
    {
Thomas Moulard's avatar
Thomas Moulard committed
185
      dgDEBUG(15) << "Open <" << (*iter)->getName ()
186
		   << "> in <" << *iterName << ">." << std::endl;
Thomas Moulard's avatar
Thomas Moulard committed
187
      openFile( **iter,*iterName );
188
189
190
191
192
193
194
195
196
197
198
199
200
      ++iter; ++iterName;
    }

  namesSet = true;
  dgDEBUGOUT(15);
}

void Tracer::
openFile( const SignalBase<int> & sig,
	  const string& givenname )
{
  dgDEBUGIN(15);
  string signame;
Thomas Moulard's avatar
Thomas Moulard committed
201
202
  if( givenname.length () )
    { signame = givenname;  } else { signame = sig.shortName (); }
203
204
205

  string filename = rootdir + basename + signame + suffix;

Thomas Moulard's avatar
Thomas Moulard committed
206
207
  dgDEBUG(5) << "Sig <"<< sig.getName () << ">: new file "<< filename << endl;
  std::ofstream * newfile = new std::ofstream( filename.c_str () );
208
209
210
211
212
213
  files.push_back( newfile );
  dgDEBUGOUT(15);
}


void Tracer::
Thomas Moulard's avatar
Thomas Moulard committed
214
closeFiles  ()
215
216
{
  dgDEBUGIN(15);
Thomas Moulard's avatar
Thomas Moulard committed
217

Thomas Moulard's avatar
Thomas Moulard committed
218
  for( FileList::iterator iter = files.begin ();files.end ()!=iter;++iter )
219
220
221
222
    {
      std::ostream * filePtr = *iter;
      delete filePtr;
    }
Thomas Moulard's avatar
Thomas Moulard committed
223
  files.clear ();
224
225
226
227
228
229
230
231
232

  dgDEBUGOUT(15);
}

/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */

void Tracer::
Thomas Moulard's avatar
Thomas Moulard committed
233
record  ()
234
235
236
237
{
  if(! play) { dgDEBUGINOUT(15); return;}

  dgDEBUGIN(15);
Thomas Moulard's avatar
Thomas Moulard committed
238

Thomas Moulard's avatar
Thomas Moulard committed
239
  if( files.size ()!=toTraceSignals.size () )
240
241
    { DG_THROW ExceptionTraces( ExceptionTraces::NOT_OPEN,
				    "No files open for tracing"," (file=%d != %d=sig).",
Thomas Moulard's avatar
Thomas Moulard committed
242
				    files.size (),toTraceSignals.size ()); }
243

Thomas Moulard's avatar
Thomas Moulard committed
244
245
  FileList::iterator iterFile = files.begin ();
  SignalList::iterator iterSig = toTraceSignals.begin ();
246

Thomas Moulard's avatar
Thomas Moulard committed
247
  while( toTraceSignals.end ()!=iterSig )
248
249
    {
      dgDEBUG(45) << "Try..." <<endl;
Thomas Moulard's avatar
Thomas Moulard committed
250
      recordSignal( **iterFile,**iterSig );
251
252
253
254
255
256
257
258
259
260
      ++iterSig;      ++iterFile;
    }
  dgDEBUGOUT(15);
}

void Tracer::
recordSignal(  std::ostream& os,
	       const SignalBase<int>& sig )
{
  dgDEBUGIN(15);
Thomas Moulard's avatar
Thomas Moulard committed
261
262

  try {
Thomas Moulard's avatar
Thomas Moulard committed
263
    if( sig.getTime ()>timeStart )
264
      {
Thomas Moulard's avatar
Thomas Moulard committed
265
	os<< sig.getTime () << "\t";
266
267
268
269
	sig.trace(os); os<<endl;
      }
  }
  catch( ExceptionAbstract& exc ) { os << exc << std::endl; }
270
  catch( ... ) { os << "Unknown error occurred while reading signal." << std::endl; }
Thomas Moulard's avatar
Thomas Moulard committed
271

272
273
274
275
276
277
278
279
280
   dgDEBUGOUT(15);

}


int& Tracer::
recordTrigger( int& dummy, const int& time )
{
  dgDEBUGIN(15) << "    time="<<time <<endl;
Thomas Moulard's avatar
Thomas Moulard committed
281
  record ();
282
283
284
285
286
287
  dgDEBUGOUT(15);
  return dummy;
}


void Tracer::
Thomas Moulard's avatar
Thomas Moulard committed
288
trace  ()
289
290
291
292
293
294
295
296
297
298
299
{
}

/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */


void Tracer::
display( std::ostream& os ) const
{
Thomas Moulard's avatar
Thomas Moulard committed
300
  os << CLASS_NAME << " " << name << " [mode=" << (play?"play":"pause")
301
302
     << "] : "<< endl
     << "  - Dep list: "<<endl;
Thomas Moulard's avatar
Thomas Moulard committed
303
304
305
  for( SignalList::const_iterator iter = toTraceSignals.begin ();
       toTraceSignals.end ()!=iter;++iter )
    {      os << "     -> "<<(*iter)->getName ()<<endl;    }
306
307
308
309
310
311
312
313
}


std::ostream& operator<< ( std::ostream& os,const Tracer& t )
{
  t.display(os);
  return os;
}