|
Sierra Toolkit
Version of the Day
|
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