GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
* Copyright 2010, |
||
3 |
* François Bleibel, |
||
4 |
* Olivier Stasse, |
||
5 |
* |
||
6 |
* CNRS/AIST |
||
7 |
* |
||
8 |
*/ |
||
9 |
|||
10 |
/* --------------------------------------------------------------------- */ |
||
11 |
/* --- INCLUDE --------------------------------------------------------- */ |
||
12 |
/* --------------------------------------------------------------------- */ |
||
13 |
|||
14 |
/* DG */ |
||
15 |
#include <dynamic-graph/all-commands.h> |
||
16 |
#include <dynamic-graph/debug.h> |
||
17 |
#include <dynamic-graph/factory.h> |
||
18 |
#include <dynamic-graph/pool.h> |
||
19 |
#include <dynamic-graph/tracer.h> |
||
20 |
#include <dynamic-graph/value.h> |
||
21 |
|||
22 |
#include <boost/bind.hpp> |
||
23 |
|||
24 |
using namespace std; |
||
25 |
using namespace dynamicgraph; |
||
26 |
using namespace dynamicgraph::command; |
||
27 |
|||
28 |
✓✗✓✗ |
1 |
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(Tracer, "Tracer"); |
29 |
|||
30 |
/* --------------------------------------------------------------------- */ |
||
31 |
/* --- CLASS ----------------------------------------------------------- */ |
||
32 |
/* --------------------------------------------------------------------- */ |
||
33 |
|||
34 |
2 |
Tracer::Tracer(const std::string n) |
|
35 |
: Entity(n), |
||
36 |
toTraceSignals(), |
||
37 |
traceStyle(TRACE_STYLE_DEFAULT), |
||
38 |
frequency(1), |
||
39 |
basename(), |
||
40 |
suffix(".dat"), |
||
41 |
rootdir(), |
||
42 |
namesSet(false), |
||
43 |
files(), |
||
44 |
names(), |
||
45 |
play(false), |
||
46 |
timeStart(0), |
||
47 |
triger(boost::bind(&Tracer::recordTrigger, this, _1, _2), sotNOSIGNAL, |
||
48 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
2 |
"Tracer(" + n + ")::triger") { |
49 |
✓✗✓✗ |
2 |
signalRegistration(triger); |
50 |
|||
51 |
/* --- Commands --- */ |
||
52 |
{ |
||
53 |
using namespace dynamicgraph::command; |
||
54 |
2 |
std::string doc; |
|
55 |
|||
56 |
✓✗✓✗ ✓✗✓✗ |
4 |
doc = docCommandVoid2("Add a new signal to trace.", "string (signal name)", |
57 |
2 |
"string (filename, empty for default"); |
|
58 |
✓✗✓✗ |
2 |
addCommand("add", |
59 |
✓✗ | 2 |
makeCommandVoid2(*this, &Tracer::addSignalToTraceByName, doc)); |
60 |
|||
61 |
doc = |
||
62 |
✓✗✓✗ |
2 |
docCommandVoid0("Remove all signals. If necessary, close open files."); |
63 |
✓✗✓✗ |
2 |
addCommand("clear", |
64 |
✓✗ | 2 |
makeCommandVoid0(*this, &Tracer::clearSignalToTrace, doc)); |
65 |
|||
66 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
4 |
doc = docCommandVoid3( |
67 |
"Gives the args for file opening, and " |
||
68 |
"if signals have been set, open the corresponding files.", |
||
69 |
2 |
"string (dirname)", "string (prefix)", "string (suffix)"); |
|
70 |
✓✗✓✗ ✓✗ |
2 |
addCommand("open", makeCommandVoid3(*this, &Tracer::openFiles, doc)); |
71 |
|||
72 |
✓✗✓✗ |
2 |
doc = docCommandVoid0("Close all the open files."); |
73 |
✓✗✓✗ ✓✗ |
2 |
addCommand("close", makeCommandVoid0(*this, &Tracer::closeFiles, doc)); |
74 |
|||
75 |
✓✗✓✗ |
4 |
doc = docCommandVoid0( |
76 |
"If necessary, dump " |
||
77 |
2 |
"(can be done automatically for some traces type)."); |
|
78 |
✓✗✓✗ ✓✗ |
2 |
addCommand("dump", makeCommandVoid0(*this, &Tracer::trace, doc)); |
79 |
|||
80 |
✓✗✓✗ |
2 |
doc = docCommandVoid0("Start the tracing process."); |
81 |
✓✗✓✗ ✓✗ |
2 |
addCommand("start", makeCommandVoid0(*this, &Tracer::start, doc)); |
82 |
|||
83 |
✓✗✓✗ |
2 |
doc = docCommandVoid0("Stop temporarily the tracing process."); |
84 |
✓✗✓✗ ✓✗ |
2 |
addCommand("stop", makeCommandVoid0(*this, &Tracer::stop, doc)); |
85 |
|||
86 |
✓✗✓✗ |
2 |
addCommand("getTimeStart", |
87 |
✓✗ | 2 |
makeDirectGetter(*this, &timeStart, |
88 |
✓✗✓✗ ✓✗ |
4 |
docDirectGetter("timeStart", "int"))); |
89 |
✓✗✓✗ |
2 |
addCommand("setTimeStart", |
90 |
✓✗ | 2 |
makeDirectSetter(*this, &timeStart, |
91 |
✓✗✓✗ ✓✗ |
4 |
docDirectSetter("timeStart", "int"))); |
92 |
} // using namespace command |
||
93 |
2 |
} |
|
94 |
|||
95 |
/* --------------------------------------------------------------------- */ |
||
96 |
/* --------------------------------------------------------------------- */ |
||
97 |
/* --------------------------------------------------------------------- */ |
||
98 |
|||
99 |
5 |
void Tracer::addSignalToTrace(const SignalBase<int> &sig, |
|
100 |
const string &filename) { |
||
101 |
dgDEBUGIN(15); |
||
102 |
// openFile may throw so it should be called first. |
||
103 |
✓✗ | 5 |
if (namesSet) openFile(sig, filename); |
104 |
✓✗ | 4 |
toTraceSignals.push_back(&sig); |
105 |
4 |
dgDEBUGF(15, "%p", &sig); |
|
106 |
4 |
names.push_back(filename); |
|
107 |
4 |
triger.addDependency(sig); |
|
108 |
dgDEBUGOUT(15); |
||
109 |
4 |
} |
|
110 |
|||
111 |
4 |
void Tracer::addSignalToTraceByName(const string &signame, |
|
112 |
const string &filename) { |
||
113 |
dgDEBUGIN(15); |
||
114 |
✓✗ | 8 |
istringstream iss(signame); |
115 |
✓✗✓✗ |
4 |
SignalBase<int> &sig = PoolStorage::getInstance()->getSignal(iss); |
116 |
✓✓ | 4 |
addSignalToTrace(sig, filename); |
117 |
dgDEBUGOUT(15); |
||
118 |
3 |
} |
|
119 |
|||
120 |
/*! Empty the list of signals to trace. This function |
||
121 |
* does not modify the file list (it does not close |
||
122 |
* the files in particular. |
||
123 |
*/ |
||
124 |
2 |
void Tracer::clearSignalToTrace() { |
|
125 |
2 |
closeFiles(); |
|
126 |
2 |
toTraceSignals.clear(); |
|
127 |
2 |
triger.clearDependencies(); |
|
128 |
2 |
} |
|
129 |
|||
130 |
// void Tracer:: |
||
131 |
// parasite( SignalBase<int>& sig ) |
||
132 |
// { |
||
133 |
// triger.parasite(sig); |
||
134 |
// } |
||
135 |
|||
136 |
3 |
void Tracer::openFiles(const std::string &rootdir_, |
|
137 |
const std::string &basename_, |
||
138 |
const std::string &suffix_) { |
||
139 |
dgDEBUGIN(15); |
||
140 |
3 |
std::basic_string<char>::size_type n = rootdir_.length(); |
|
141 |
✓✗ | 3 |
rootdir = rootdir_; |
142 |
✓✗✓✗ ✓✗ |
3 |
if ((0 < n) & ('/' != rootdir[n - 1])) rootdir += '/'; |
143 |
|||
144 |
✓✗ | 3 |
basename = basename_; |
145 |
✓✗ | 3 |
suffix = suffix_; |
146 |
|||
147 |
✗✓✗✗ |
3 |
if (files.size()) closeFiles(); |
148 |
|||
149 |
3 |
SignalList::const_iterator iter = toTraceSignals.begin(); |
|
150 |
3 |
NameList::const_iterator iterName = names.begin(); |
|
151 |
✗✓ | 3 |
while (toTraceSignals.end() != iter) { |
152 |
dgDEBUG(15) << "Open <" << (*iter)->getName() << "> in <" << *iterName |
||
153 |
<< ">." << std::endl; |
||
154 |
openFile(**iter, *iterName); |
||
155 |
++iter; |
||
156 |
++iterName; |
||
157 |
} |
||
158 |
|||
159 |
3 |
namesSet = true; |
|
160 |
dgDEBUGOUT(15); |
||
161 |
3 |
} |
|
162 |
|||
163 |
3 |
void Tracer::openFile(const SignalBase<int> &sig, const string &givenname) { |
|
164 |
dgDEBUGIN(15); |
||
165 |
6 |
string signame; |
|
166 |
✓✗ | 3 |
if (givenname.length()) { |
167 |
✓✗ | 3 |
signame = givenname; |
168 |
} else { |
||
169 |
signame = sig.shortName(); |
||
170 |
} |
||
171 |
|||
172 |
✓✗✓✗ ✓✗ |
9 |
string filename = rootdir + basename + signame + suffix; |
173 |
|||
174 |
dgDEBUG(5) << "Sig <" << sig.getName() << ">: new file " << filename << endl; |
||
175 |
✓✗✓✗ |
3 |
std::ofstream *newfile = new std::ofstream(filename.c_str()); |
176 |
✓✗ | 3 |
files.push_back(newfile); |
177 |
dgDEBUGOUT(15); |
||
178 |
3 |
} |
|
179 |
|||
180 |
2 |
void Tracer::closeFiles() { |
|
181 |
dgDEBUGIN(15); |
||
182 |
✓✗ | 4 |
std::lock_guard<std::mutex> files_lock(files_mtx); |
183 |
|||
184 |
✓✓ | 5 |
for (FileList::iterator iter = files.begin(); files.end() != iter; ++iter) { |
185 |
3 |
std::ostream *filePtr = *iter; |
|
186 |
✓✗ | 3 |
delete filePtr; |
187 |
} |
||
188 |
2 |
files.clear(); |
|
189 |
|||
190 |
dgDEBUGOUT(15); |
||
191 |
2 |
} |
|
192 |
|||
193 |
/* --------------------------------------------------------------------- */ |
||
194 |
/* --------------------------------------------------------------------- */ |
||
195 |
/* --------------------------------------------------------------------- */ |
||
196 |
|||
197 |
2002 |
void Tracer::record() { |
|
198 |
✓✓ | 2002 |
if (!play) { |
199 |
dgDEBUGINOUT(15); |
||
200 |
2 |
return; |
|
201 |
} |
||
202 |
|||
203 |
dgDEBUGIN(15); |
||
204 |
|||
205 |
// Ensure record() never hangs. If the attempt to acquire the lock fails, |
||
206 |
// then closeFiles() is active and we shouldn't write to files anyways. |
||
207 |
2000 |
std::unique_lock<std::mutex> files_lock(files_mtx, std::try_to_lock); |
|
208 |
✗✓ | 2000 |
if (!files_lock.owns_lock()) { |
209 |
dgDEBUGOUT(15); |
||
210 |
return; |
||
211 |
} |
||
212 |
|||
213 |
✗✓ | 2000 |
if (files.size() != toTraceSignals.size()) { |
214 |
DG_THROW |
||
215 |
ExceptionTraces(ExceptionTraces::NOT_OPEN, "No files open for tracing", |
||
216 |
" (file=%d != %d=sig).", files.size(), |
||
217 |
toTraceSignals.size()); |
||
218 |
} |
||
219 |
|||
220 |
2000 |
FileList::iterator iterFile = files.begin(); |
|
221 |
2000 |
SignalList::iterator iterSig = toTraceSignals.begin(); |
|
222 |
|||
223 |
✓✓ | 6000 |
while (toTraceSignals.end() != iterSig) { |
224 |
dgDEBUG(45) << "Try..." << endl; |
||
225 |
✓✗ | 4000 |
recordSignal(**iterFile, **iterSig); |
226 |
4000 |
++iterSig; |
|
227 |
4000 |
++iterFile; |
|
228 |
} |
||
229 |
dgDEBUGOUT(15); |
||
230 |
} |
||
231 |
|||
232 |
4000 |
void Tracer::recordSignal(std::ostream &os, const SignalBase<int> &sig) { |
|
233 |
dgDEBUGIN(15); |
||
234 |
|||
235 |
try { |
||
236 |
✓✗✓✓ |
4000 |
if (sig.getTime() > timeStart) { |
237 |
✓✗✓✗ ✓✗ |
2997 |
os << sig.getTime() << "\t"; |
238 |
✓✗ | 2997 |
sig.trace(os); |
239 |
✓✗ | 2997 |
os << endl; |
240 |
} |
||
241 |
} catch (ExceptionAbstract &exc) { |
||
242 |
os << exc << std::endl; |
||
243 |
} catch (...) { |
||
244 |
os << "Unknown error occurred while reading signal." << std::endl; |
||
245 |
} |
||
246 |
|||
247 |
dgDEBUGOUT(15); |
||
248 |
4000 |
} |
|
249 |
|||
250 |
2000 |
int &Tracer::recordTrigger(int &dummy, const int &time) { |
|
251 |
dgDEBUGIN(15) << " time=" << time << endl; |
||
252 |
2000 |
record(); |
|
253 |
dgDEBUGOUT(15); |
||
254 |
2000 |
return dummy; |
|
255 |
} |
||
256 |
|||
257 |
void Tracer::trace() {} |
||
258 |
|||
259 |
/* --------------------------------------------------------------------- */ |
||
260 |
/* --------------------------------------------------------------------- */ |
||
261 |
/* --------------------------------------------------------------------- */ |
||
262 |
|||
263 |
void Tracer::display(std::ostream &os) const { |
||
264 |
os << CLASS_NAME << " " << name << " [mode=" << (play ? "play" : "pause") |
||
265 |
<< "] : " << endl |
||
266 |
<< " - Dep list: " << endl; |
||
267 |
for (SignalList::const_iterator iter = toTraceSignals.begin(); |
||
268 |
toTraceSignals.end() != iter; ++iter) { |
||
269 |
os << " -> " << (*iter)->getName() << endl; |
||
270 |
} |
||
271 |
} |
||
272 |
|||
273 |
std::ostream &operator<<(std::ostream &os, const Tracer &t) { |
||
274 |
t.display(os); |
||
275 |
return os; |
||
276 |
} |
Generated by: GCOVR (Version 4.2) |