The Gaudi Framework  v30r4 (9b837755)
StatusCodeSvc.cpp
Go to the documentation of this file.
1 #include "StatusCodeSvc.h"
3 
4 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5 
6 using namespace std;
7 //
9 //
10 inline void toupper( std::string& s ) { std::transform( s.begin(), s.end(), s.begin(), (int ( * )( int ))toupper ); }
11 
12 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
15 {
16 
18  if ( !sc.isSuccess() ) return sc;
19 
20  info() << "initialize" << endmsg;
21 
22  for ( const auto& itr : m_pFilter.value() ) {
23  // we need to do this if someone has gotten to regFnc before initialize
24 
25  string fnc, lib;
26  parseFilter( itr, fnc, lib );
27 
28  if ( !fnc.empty() ) {
29  filterFnc( fnc );
30  m_filterfnc.insert( fnc );
31  }
32 
33  if ( !lib.empty() ) {
34  filterLib( lib );
35  m_filterlib.insert( lib );
36  }
37  }
38 
39  return StatusCode::SUCCESS;
40 }
41 
42 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
43 
45 {
46 
47  info() << "reinitialize" << endmsg;
48 
49  return StatusCode::SUCCESS;
50 }
51 
52 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
54 {
55 
56  if ( !m_dat.empty() ) {
57 
58  info() << "listing all unchecked return codes:" << endmsg;
59 
60  list();
61 
62  } else {
63 
64  if ( msgLevel( MSG::DEBUG ) ) debug() << "all StatusCode instances where checked" << endmsg;
65  }
66 
67  return StatusCode::SUCCESS;
68 }
69 
70 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
71 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
72 
73 void StatusCodeSvc::regFnc( const std::string& fnc, const std::string& lib )
74 {
75 
76  if ( m_state == Gaudi::StateMachine::OFFLINE || m_state == Gaudi::StateMachine::CONFIGURED ) {
77  return;
78  }
79 
80  // A StatusCode instance may be create internally by ROOT dictionaries and,
81  // of course, it's not checked, so here we whitelist a few library names
82  // that are known to produce spurious reports.
83  if ( m_dict ) {
84  // ROOT's library names can end with either ".so" or ".so.x.y" with x.y the ROOT version in use
85  const auto len = lib.length();
86  if ( len >= 3 && lib.compare( len - 3, 3, ".so" ) == 0 ) {
87  if ( ( len >= 7 && ( lib.compare( len - 7, 4, "Dict" ) == 0 || lib.compare( len - 7, 4, "Core" ) == 0 ) ) ||
88  ( len >= 8 && lib.compare( len - 8, 5, "Cling" ) == 0 ) ) {
89  return;
90  }
91  } else if ( lib.rfind( "Dict.so" ) != std::string::npos || lib.rfind( "Cling.so" ) != std::string::npos ||
92  lib.rfind( "Core.so" ) != std::string::npos ) {
93  return;
94  }
95  }
96  // this appears only with gcc 4.9...
97  if ( fnc == "_PyObject_GC_Malloc" ) return;
98  // GAUDI-1036
99  if ( fnc == "PyThread_get_thread_ident" ) return;
100  if ( fnc == "local" ) return;
101 
102  {
103  const string rlib = lib.substr( lib.rfind( "/" ) + 1 );
104 
105  if ( m_filterfnc.find( fnc ) != m_filterfnc.end() || m_filterlib.find( rlib ) != m_filterlib.end() ) {
106  return;
107  }
108  }
109 
110  if ( m_abort ) {
111  fatal() << "Unchecked StatusCode in " << fnc << " from lib " << lib << endmsg;
112  abort();
113  }
114 
115  string key = fnc + lib;
116 
117  auto itr = m_dat.find( key );
118 
119  if ( itr != m_dat.end() ) {
120  itr->second.count += 1;
121  } else {
122 
123  const string rlib = lib.substr( lib.rfind( "/" ) + 1 );
124 
125  StatCodeDat dat;
126  dat.fnc = fnc;
127  dat.lib = rlib;
128  dat.count = 1;
129 
130  m_dat[key] = dat;
131  }
132 }
133 
134 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
135 
137 {
138 
140  os << "Num | Function | Source Library" << endl;
141  os << "----+--------------------------------+-------------------"
142  << "-----------------------" << endl;
143 
144  for ( const auto& itr : m_dat ) {
145  const auto& dat = itr.second;
146 
147  os.width( 3 );
148  os.setf( ios_base::right, ios_base::adjustfield );
149  os << dat.count;
150 
151  os << " | ";
152  os.width( 30 );
153  os.setf( ios_base::left, ios_base::adjustfield );
154  os << dat.fnc;
155 
156  os << " | ";
157  os.setf( ios_base::left, ios_base::adjustfield );
158  os << dat.lib;
159 
160  os << endl;
161  }
162 
163  info() << endl << os.str() << endmsg;
164 }
165 
166 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
168 {
169 
170  auto itr = std::find_if( m_dat.begin(), m_dat.end(),
171  [&]( const std::pair<std::string, StatCodeDat>& d ) { return d.second.fnc == str; } );
172  if ( itr != std::end( m_dat ) ) m_dat.erase( itr );
173 }
174 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
175 
177 {
178 
179  auto itr = std::find_if( m_dat.begin(), m_dat.end(),
180  [&]( const std::pair<std::string, StatCodeDat>& d ) { return d.second.lib == str; } );
181  if ( itr != std::end( m_dat ) ) m_dat.erase( itr );
182 }
183 
184 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
185 
186 void StatusCodeSvc::parseFilter( const string& str, string& fnc, string& lib )
187 {
188 
189  auto loc = str.find( "=" );
190  if ( loc == std::string::npos ) {
191  fnc = str;
192  lib = "";
193  } else {
194  string key = str.substr( 0, loc );
195  string val = str.substr( loc + 1 );
196 
197  toupper( key );
198 
199  if ( key == "FCN" || key == "FNC" ) {
200  fnc = val;
201  lib.clear();
202  } else if ( key == "LIB" ) {
203  fnc.clear();
204  lib = val;
205  } else {
206  fnc.clear();
207  lib.clear();
208 
209  warning() << "ignoring unknown token in Filter: " << str << endmsg;
210  }
211  }
212 }
213 
214 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
215 
T setf(T...args)
StatusCode initialize() override
Definition: Service.cpp:63
T empty(T...args)
StatusCode reinitialize() override
bool isSuccess() const
Definition: StatusCode.h:287
T rfind(T...args)
T endl(T...args)
STL namespace.
T end(T...args)
STL class.
void parseFilter(const std::string &str, std::string &fnc, std::string &lib)
#define DECLARE_COMPONENT(type)
StatusCode initialize() override
T toupper(T...args)
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:51
T width(T...args)
T clear(T...args)
STL class.
constexpr static const auto SUCCESS
Definition: StatusCode.h:87
void regFnc(const std::string &func, const std::string &lib) override
T find(T...args)
T length(T...args)
T begin(T...args)
void filterLib(const std::string &)
string s
Definition: gaudirun.py:253
T substr(T...args)
T abort(T...args)
T transform(T...args)
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:209
T compare(T...args)
void filterFnc(const std::string &)
void list() const override
StatusCode finalize() override