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