Sierra Toolkit  Version of the Day
stk_util/stk_util/diag/Trace.cpp
1 
10 #include <string>
11 #include <cstring>
12 #include <sstream>
13 #include <list>
14 #include <exception>
15 
16 #include <stk_util/diag/Trace.hpp>
17 #include <stk_util/diag/Writer.hpp>
18 #include <stk_util/environment/FormatTime.hpp>
19 #include <stk_util/diag/Platform.hpp>
20 
21 namespace stk_classic {
22 namespace diag {
23 
25 Trace::s_extra = 0;
26 
27 Trace::TraceList
28 Trace::s_traceList;
29 
30 bool
31 Trace::s_traceListExists = false;
32 
34 Traceback::s_top = s_stack;
35 
37 Traceback::s_storedTop = s_storedStack;
38 
40 Traceback::s_stack;
41 
43 Traceback::s_storedStack;
44 
46 Traceback::s_tracebackState = Traceback::RUNNING;
47 
48 int
49 Traceback::s_tracebackPreserve = 0;
50 
51 int
52 Traceback::s_tracebackDisplay = 0;
53 
54 bool
55 Traceback::s_coverageEnabled = false;
56 
58 Traceback::s_coverage;
59 
60 namespace {
61 
62 bool
63 prefix_compare(
64  const char * prefix,
65  const char * name)
66 {
67  for (; *prefix != 0 && *prefix == *name; ++prefix, ++name)
68  ;
69  return *prefix == 0;
70 }
71 
72 
73 bool
74 prefix_find(
75  const Trace::TraceList & trace_list,
76  const char * s)
77 {
78  for (Trace::TraceList::const_iterator it = trace_list.begin(); it != trace_list.end(); ++it)
79  if (prefix_compare((*it), s))
80  return true;;
81  return false;
82 }
83 
84 
85 size_t
86 get_heap_used()
87 {
89 }
90 
91 std::string::const_iterator
92 find_next_char(
93  std::string::const_iterator p,
94  std::string::const_iterator end,
95  char c)
96 {
97  while (p != end && *p != c)
98  p++;
99  return p;
100 }
101 
102 std::string::const_iterator
103 find_prev_char(
104  std::string::const_iterator begin,
105  std::string::const_iterator p,
106  char c)
107 {
108  while (p != begin && *p != c)
109  p--;
110  return p;
111 }
112 
113 std::string::const_iterator
114 find_prev_double_colon(
115  std::string::const_iterator begin,
116  std::string::const_iterator p)
117 {
118  std::string::const_iterator it = p - 1;
119 
120  while ((it = find_prev_char(begin, it, ':')) != begin) {
121  if (*(it - 1) == ':')
122  return it + 1;
123  --it;
124  }
125 
126  return it;
127 }
128 
129 
130 inline std::string::const_iterator find_next_open_paren(std::string::const_iterator p, std::string::const_iterator end) {
131  return find_next_char(p, end, '(');
132 }
133 
155 void
156 get_function_spec_parts(
157  const std::string & spec,
158  std::string & namespace_name,
159  std::string & class_name,
160  std::string & function_name,
161  std::vector<std::string> & arglist)
162 {
163  namespace_name.erase(namespace_name.begin(), namespace_name.end());
164  class_name.erase(class_name.begin(), class_name.end());
165  function_name.erase(function_name.begin(), function_name.end());
166  arglist.erase(arglist.begin(), arglist.end());
167 
168  std::string::const_iterator it_paren = find_next_open_paren(spec.begin(), spec.end());
169  std::string::const_iterator it_func_name = find_prev_double_colon(spec.begin(), it_paren);
170  function_name = std::string(it_func_name, it_paren);
171  if (it_func_name != spec.begin()) {
172  it_func_name -= 2;
173  std::string::const_iterator it_class_name = find_prev_double_colon(spec.begin(), it_func_name);
174  class_name = std::string(it_class_name, it_func_name);
175  if (it_class_name != spec.begin()) {
176  it_class_name -= 2;
177  namespace_name = std::string(spec.begin(), it_class_name);
178  }
179  }
180 }
181 
182 std::string
183 format_memory(
184  int size)
185 {
186  static const char *suffix[] = {" B", " KB", " MB", " GB"};
187 
188  char sign = size < 0 ? '-' : '+';
189 
190  size = size > 0 ? size : -size;
191 
192  int s = size/10240;
193 
194  unsigned int i;
195  for (i = 0; i < sizeof(suffix); i++) {
196  if (s == 0)
197  break;
198  size /= 1024;
199  s /= 1024;
200  }
201 
202  std::stringstream strout;
203 
204  strout << sign << size << suffix[i];
205 
206  return strout.str();
207 }
208 
209 } // namespace
210 
211 
212 std::string
214 {
215  std::string namespace_name;
216  std::string class_name;
217  std::string function_name;
218  std::vector<std::string> arglist;
219 
220  get_function_spec_parts(m_functionSpec, namespace_name, class_name, function_name, arglist);
221 
222  return namespace_name;
223 }
224 
225 
226 std::string
228 {
229  std::string namespace_name;
230  std::string class_name;
231  std::string function_name;
232  std::vector<std::string> arglist;
233 
234  get_function_spec_parts(m_functionSpec, namespace_name, class_name, function_name, arglist);
235 
236  return namespace_name + "::" + class_name;
237 }
238 
239 
240 std::string
242 {
243  std::string namespace_name;
244  std::string class_name;
245  std::string function_name;
246  std::vector<std::string> arglist;
247 
248  get_function_spec_parts(m_functionSpec, namespace_name, class_name, function_name, arglist);
249 
250  return class_name;
251 }
252 
253 
254 std::string
256 {
257  std::string namespace_name;
258  std::string class_name;
259  std::string function_name;
260  std::vector<std::string> arglist;
261 
262  get_function_spec_parts(m_functionSpec, namespace_name, class_name, function_name, arglist);
263 
264  return namespace_name + "::" + class_name + "::" + function_name;
265 }
266 
267 
268 std::string
270 {
271  std::string namespace_name;
272  std::string class_name;
273  std::string function_name;
274  std::vector<std::string> arglist;
275 
276  get_function_spec_parts(m_functionSpec, namespace_name, class_name, function_name, arglist);
277 
278  return function_name;
279 }
280 
281 
282 struct CoverageValueSort
283 {
284  int operator()(const std::pair<const char *, int> &s1, const std::pair<const char *, int> &s2) {
285  return std::strcmp(s1.first, s2.first) < 0;
286  }
287 };
288 
290  Writer &dout,
291  const char *function_name,
292  int line_mask,
293  bool do_trace)
294  : Traceback(function_name),
295  m_diagWriter(dout),
296  m_startCpuTime(0.0),
297  m_startMemAlloc(0),
298  m_lineMask(line_mask),
299  m_do_trace(do_trace),
300  m_flags((dout.isTracing()
301  || (dout.shouldTrace(m_lineMask)
302  && (s_traceListExists && (s_traceList.empty() || prefix_find(s_traceList, m_functionSpec))))) ? IN_TRACE_LIST : 0)
303 {
304  if (m_do_trace && (m_flags & IN_TRACE_LIST)) {
305  m_diagWriter.incTraceDepth();
306 
307  m_diagWriter.m(m_lineMask) << m_functionSpec
308  << (std::uncaught_exception() ? " (throw unwinding) " : "")
309  << push << dendl;
310 
311  if (dout.shouldPrint(LOG_TRACE_STATS)) {
312  m_startCpuTime = sierra::Env::cpu_now();
313  m_startMemAlloc = get_heap_used();
314  }
315  }
316 }
317 
318 
320 {
321  if (m_do_trace && (m_flags & IN_TRACE_LIST)) {
322  if (m_diagWriter.shouldPrint(LOG_TRACE_STATS)) {
323  m_startCpuTime = sierra::Env::cpu_now() - m_startCpuTime;
324  m_startMemAlloc = get_heap_used() - m_startMemAlloc;
325  }
326 
327  if (m_diagWriter.shouldPrint(LOG_TRACE_STATS)) {
328  m_diagWriter.m(m_lineMask) << "[" << stk_classic::formatTime(m_startCpuTime)
329  << "s, " << format_memory(m_startMemAlloc) << "]" << dendl;
330  }
331 
332  m_diagWriter.m(m_lineMask) << (std::uncaught_exception() ? " (throw unwinding) " : "")
333  << pop << dendl;
334 
335  m_diagWriter.decTraceDepth();
336  }
337 }
338 
339 
340 Writer &
342  Writer & dout) const
343 {
344  dout << "Trace, " << m_functionSpec;
345  return dout;
346 }
347 
348 
349 TracebackStack
350 Traceback::snapshot()
351 {
352  TracebackStack traceback_stack;
353  traceback_stack.reserve(s_top - s_stack);
354 
355  if (Traceback::getTracebackState() == Traceback::RUNNING)
356  for (const_stack_iterator it = s_top - 1; it >= s_stack; --it)
357  traceback_stack.push_back(*it);
358  else
359  for (const_stack_iterator it = s_storedTop - 1; it >= s_storedStack; --it)
360  traceback_stack.push_back(*it);
361 
362  return traceback_stack;
363 }
364 
365 
366 std::string
368  const TracebackStack & traceback_stack)
369 {
370  std::ostringstream s;
371  if (traceback_stack.empty())
372  s << " traceback not available" << std::endl;
373  else {
374  for (TracebackStack::const_iterator it = traceback_stack.begin(); it != traceback_stack.end(); ++it)
375  s << " from " << (*it) << std::endl;
376  }
377 
378  return s.str();
379 }
380 
381 std::ostream &
383  std::ostream & os)
384 {
385  std::vector<std::pair<const char *, int> > sorted_list;
386  sorted_list.reserve(s_coverage.size());
387 
388  for (Coverage::const_iterator it = s_coverage.begin(); it != s_coverage.end(); ++it)
389  sorted_list.push_back(std::pair<const char *, int>((*it).first, (*it).second));
390 
391  std::sort(sorted_list.begin(), sorted_list.end(), CoverageValueSort());
392 
393  for (std::vector<std::pair<const char *, int> >::const_iterator it = sorted_list.begin(); it != sorted_list.end(); ++it)
394  os << "<FUNCTION specification=\"" << (*it).first << "\" count=\"" << (*it).second << "\"/>" << std::endl;
395 
396  return os;
397 }
398 
399 
400 } // namespace diag
401 } // namespace stk_classic
double cpu_now()
Member function cpu_now returns the accumlated cpu time for the process as a double precision value i...
Definition: Platform.cpp:271
int incTraceDepth()
Member function incTraceDepth increments the tracing count.
Definition: Writer.hpp:468
static TracebackState getTracebackState()
Member function getTracebackState returns the value of the traceback state.
Trace(Writer &dout, const char *function_name, int print_mask=LOG_TRACE, bool do_trace=true)
Creates a new Trace instance, resulting in the printing of the member function name and pushing the d...
static std::string printTraceback(const TracebackStack &traceback_stack)
Member function printTraceback writes the traceback stack function specifications to the output strea...
Writer & verbose_print(Writer &dout) const
Member function dump writes the trace to the specified Writer.
std::string getFunctionName() const
Member function getFunctionName returns the function&#39;s name.
static PrintCoverage printCoverage()
Member function printCoverage creates a PrintCoverage type holder class which enables operator<< to p...
const char * m_functionSpec
The member function specification.
size_t get_heap_usage()
Function get_heap_usage returns the number of bytes used by the heap.
Definition: Platform.hpp:152
std::map< const char *, int > Coverage
Typedef Coverage declares the function usage coverage data type.
Class Traceback is a stack of char constant pointers to function specifications which have been encou...
bool shouldPrint()
Member function shouldPrint returns true if the line should print.
Definition: Writer.hpp:369
Writer & dendl(Writer &dout)
Writer function dendl calls the Writer::dendl manipulator.
Definition: Writer.hpp:520
const char * Stack[STACK_SIZE]
Stack type.
Sierra Toolkit.
Class Writer implements a runtime selectable diagnostic output writer to aid in the development and d...
Definition: Writer.hpp:49
const char *const * const_stack_iterator
const iterator thru stack
Writer &(* ExtraFuncPtr)(Writer &)
Typedef ExtraFuncPtr declares the extra function pointer signature.
Writer & m(PrintMask line_mask)
Member function m sets the line mask of this line.
Definition: Writer.hpp:294
int decTraceDepth()
Member function decTraceDepth decrements the tracing count.
Definition: Writer.hpp:477
std::string getFunctionShortName() const
Member function getFunctionName returns the function&#39;s name.
std::string getFunctionClass() const
Member function getFunctionName returns the function&#39;s name.
std::string getFunctionNamespace() const
Member function getFunctionName returns the function&#39;s name.
TracebackState
Enumeration TracebackState lists the traceback execution states.
std::string getFunctionShortClass() const
Member function getFunctionName returns the function&#39;s name.
~Trace()
Destroys a Trace instance, resulting in the printing of the member function name and popping the diag...
const char ** stack_iterator
iterator thru stack