|
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/environment/FormatTime.hpp> 00019 #include <stk_util/diag/Platform.hpp> 00020 00021 namespace stk_classic { 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_classic::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_classic