Sierra Toolkit Version of the Day
stk_util/stk_util/diag/Trace.cpp
00001 
00010 #include <string>
00011 #include <cstring>
00012 #include <sstream>
00013 #include <list>
00014 #include <exception>
00015 
00016 #include <stk_util/diag/Trace.hpp>
00017 #include <stk_util/diag/Writer.hpp>
00018 #include <stk_util/util/FormatTime.hpp>
00019 
00020 namespace stk {
00021 namespace diag {
00022 
00023 Trace::ExtraFuncPtr
00024 Trace::s_extra = 0;
00025 
00026 Trace::TraceList
00027 Trace::s_traceList;
00028 
00029 bool
00030 Trace::s_traceListExists = false;
00031 
00032 Traceback::stack_iterator
00033 Traceback::s_top = s_stack;
00034 
00035 Traceback::stack_iterator
00036 Traceback::s_storedTop = s_storedStack;
00037 
00038 Traceback::Stack
00039 Traceback::s_stack;
00040 
00041 Traceback::Stack
00042 Traceback::s_storedStack;
00043 
00044 Traceback::TracebackState
00045 Traceback::s_tracebackState = Traceback::RUNNING;
00046 
00047 int
00048 Traceback::s_tracebackPreserve = 0;
00049 
00050 int
00051 Traceback::s_tracebackDisplay = 0;
00052 
00053 namespace {
00054 
00055 bool
00056 prefix_compare(
00057   const char *    prefix,
00058   const char *    name)
00059 {
00060   for (; *prefix != 0 && *prefix == *name; ++prefix, ++name)
00061     ;
00062   return *prefix == 0;
00063 }
00064 
00065 
00066 bool
00067 prefix_find(
00068   const Trace::TraceList &  trace_list,
00069   const char *    s)
00070 {
00071   for (Trace::TraceList::const_iterator it = trace_list.begin(); it != trace_list.end(); ++it)
00072     if (prefix_compare((*it), s))
00073       return true;;
00074   return false;
00075 }
00076 
00077 
00078 size_t
00079 get_heap_used()
00080 {
00081   return 0;
00082 //  return Env::get_heap_usage();
00083 }
00084 
00085 double
00086 get_cpu_now()
00087 {
00088   return 0.0;
00089 //  return Env::cpu_now();
00090 }
00091 
00092 
00093 std::string::const_iterator
00094 find_next_char(
00095   std::string::const_iterator  p,
00096   std::string::const_iterator  end,
00097   char        c)
00098 {
00099   while (p != end && *p != c)
00100     p++;
00101   return p;
00102 }
00103 
00104 std::string::const_iterator
00105 find_prev_char(
00106   std::string::const_iterator  begin,
00107   std::string::const_iterator  p,
00108   char        c)
00109 {
00110   while (p != begin && *p != c)
00111     p--;
00112   return p;
00113 }
00114 
00115 std::string::const_iterator
00116 find_prev_double_colon(
00117   std::string::const_iterator  begin,
00118   std::string::const_iterator  p)
00119 {
00120   std::string::const_iterator it = p - 1;
00121 
00122   while ((it = find_prev_char(begin, it, ':')) != begin) {
00123     if (*(it - 1) == ':')
00124       return it + 1;
00125     --it;
00126   }
00127 
00128   return it;
00129 }
00130 
00131 
00132 inline std::string::const_iterator find_next_open_paren(std::string::const_iterator p, std::string::const_iterator end) {
00133   return find_next_char(p, end, '(');
00134 }
00135 
00157 void
00158 get_function_spec_parts(
00159   const std::string &    spec,
00160   std::string &      namespace_name,
00161   std::string &      class_name,
00162   std::string &      function_name,
00163   std::vector<std::string> &  arglist)
00164 {
00165   namespace_name.erase(namespace_name.begin(), namespace_name.end());
00166   class_name.erase(class_name.begin(), class_name.end());
00167   function_name.erase(function_name.begin(), function_name.end());
00168   arglist.erase(arglist.begin(), arglist.end());
00169 
00170   std::string::const_iterator it_paren = find_next_open_paren(spec.begin(), spec.end());
00171   std::string::const_iterator it_func_name = find_prev_double_colon(spec.begin(), it_paren);
00172   function_name = std::string(it_func_name, it_paren);
00173   if (it_func_name != spec.begin()) {
00174     it_func_name -= 2;
00175     std::string::const_iterator it_class_name = find_prev_double_colon(spec.begin(), it_func_name);
00176     class_name = std::string(it_class_name, it_func_name);
00177     if (it_class_name != spec.begin()) {
00178       it_class_name -= 2;
00179       namespace_name = std::string(spec.begin(), it_class_name);
00180     }
00181   }
00182 }
00183 
00184 std::string
00185 format_memory(
00186   int      size)
00187 {
00188   static const char *suffix[] = {" B", " KB", " MB", " GB"};
00189 
00190   char sign = size < 0 ? '-' : '+';
00191 
00192   size = size > 0 ? size : -size;
00193 
00194   int s = size/10240;
00195 
00196   unsigned int i;
00197   for (i = 0; i < sizeof(suffix); i++) {
00198     if (s == 0)
00199       break;
00200     size /= 1024;
00201     s /= 1024;
00202   }
00203 
00204   std::stringstream strout;
00205 
00206   strout << sign << size << suffix[i];
00207 
00208   return strout.str();
00209 }
00210 
00211 } // namespace
00212 
00213 
00214 std::string
00215 Tracespec::getFunctionNamespace() const
00216 {
00217   std::string namespace_name;
00218   std::string class_name;
00219   std::string function_name;
00220   std::vector<std::string> arglist;
00221 
00222   get_function_spec_parts(m_functionSpec, namespace_name, class_name, function_name, arglist);
00223 
00224   return namespace_name;
00225 }
00226 
00227 
00228 std::string
00229 Tracespec::getFunctionClass() const
00230 {
00231   std::string namespace_name;
00232   std::string class_name;
00233   std::string function_name;
00234   std::vector<std::string> arglist;
00235 
00236   get_function_spec_parts(m_functionSpec, namespace_name, class_name, function_name, arglist);
00237 
00238   return namespace_name + "::" + class_name;
00239 }
00240 
00241 
00242 std::string
00243 Tracespec::getFunctionShortClass() const
00244 {
00245   std::string namespace_name;
00246   std::string class_name;
00247   std::string function_name;
00248   std::vector<std::string> arglist;
00249 
00250   get_function_spec_parts(m_functionSpec, namespace_name, class_name, function_name, arglist);
00251 
00252   return class_name;
00253 }
00254 
00255 
00256 std::string
00257 Tracespec::getFunctionName() const
00258 {
00259   std::string namespace_name;
00260   std::string class_name;
00261   std::string function_name;
00262   std::vector<std::string> arglist;
00263 
00264   get_function_spec_parts(m_functionSpec, namespace_name, class_name, function_name, arglist);
00265 
00266   return namespace_name + "::" + class_name + "::" + function_name;
00267 }
00268 
00269 
00270 std::string
00271 Tracespec::getFunctionShortName() const
00272 {
00273   std::string namespace_name;
00274   std::string class_name;
00275   std::string function_name;
00276   std::vector<std::string> arglist;
00277 
00278   get_function_spec_parts(m_functionSpec, namespace_name, class_name, function_name, arglist);
00279 
00280   return function_name;
00281 }
00282 
00283 
00284 struct CoverageValueSort
00285 {
00286   int operator()(const std::pair<const char *, int> &s1, const std::pair<const char *, int> &s2) {
00287     return std::strcmp(s1.first, s2.first) < 0;
00288   }
00289 };
00290 
00291 Trace::Trace(
00292   Writer &dout,
00293   const char *function_name,
00294   int line_mask,
00295   bool do_trace)
00296   : Traceback(function_name),
00297     m_diagWriter(dout),
00298     m_startCpuTime(0.0),
00299     m_startMemAlloc(0),
00300     m_lineMask(line_mask),
00301     m_do_trace(do_trace),
00302     m_flags((dout.isTracing()
00303              || (dout.shouldTrace(m_lineMask)
00304                  && (s_traceListExists && (s_traceList.empty() || prefix_find(s_traceList, m_functionSpec))))) ? IN_TRACE_LIST : 0)
00305 {
00306   if (m_do_trace && (m_flags & IN_TRACE_LIST)) {
00307     m_diagWriter.incTraceDepth();
00308 
00309     m_diagWriter.m(m_lineMask) << m_functionSpec
00310                                << (std::uncaught_exception() ? " (throw unwinding) " : "")
00311                                << push << dendl;
00312 
00313     if (dout.shouldPrint(LOG_TRACE_STATS)) {
00314       m_startCpuTime = get_cpu_now();
00315       m_startMemAlloc = get_heap_used();
00316     }
00317   }
00318 }
00319 
00320 
00321 Trace::~Trace()
00322 {
00323   if (m_do_trace && (m_flags & IN_TRACE_LIST)) {
00324     if (m_diagWriter.shouldPrint(LOG_TRACE_STATS)) {
00325       m_startCpuTime = get_cpu_now() - m_startCpuTime;
00326       m_startMemAlloc = get_heap_used() - m_startMemAlloc;
00327     }
00328 
00329     if (m_diagWriter.shouldPrint(LOG_TRACE_STATS)) {
00330       m_diagWriter.m(m_lineMask) << "[" << stk::formatTime(m_startCpuTime)
00331                                  << "s, " << format_memory(m_startMemAlloc) << "]" << dendl;
00332     }
00333 
00334     m_diagWriter.m(m_lineMask) << (std::uncaught_exception() ? " (throw unwinding) " : "")
00335                                << pop << dendl;
00336 
00337     m_diagWriter.decTraceDepth();
00338   }
00339 }
00340 
00341 
00342 TracebackStack
00343 Traceback::snapshot()
00344 {
00345   TracebackStack traceback_stack;
00346   traceback_stack.reserve(s_top - s_stack);
00347 
00348   if (Traceback::getTracebackState() == Traceback::RUNNING)
00349     for (const_stack_iterator it = s_top - 1; it >= s_stack; --it)
00350       traceback_stack.push_back(*it);
00351   else
00352     for (const_stack_iterator it = s_storedTop - 1; it >= s_storedStack; --it)
00353       traceback_stack.push_back(*it);
00354 
00355   return traceback_stack;
00356 }
00357 
00358 
00359 std::string
00360 Traceback::printTraceback(
00361   const TracebackStack &  traceback_stack)
00362 {
00363   std::ostringstream s;
00364   if (traceback_stack.empty())
00365     s << "    traceback not available" << std::endl;
00366   else {
00367     for (TracebackStack::const_iterator it = traceback_stack.begin(); it != traceback_stack.end(); ++it)
00368       s << "    from " << (*it) << std::endl;
00369   }
00370 
00371   return s.str();
00372 }
00373 
00374 } // namespace diag
00375 } // namespace stk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends