mana-core-athenaservices / src / FPEAuditor.cxx

The default branch has multiple heads

///////////////////////// -*- C++ -*- /////////////////////////////
// FPEAuditor.cxx 
// Implementation file for class FPEAuditor
// Author: S.Binet<binet@cern.ch>
/////////////////////////////////////////////////////////////////// 


// STL includes
#include <stdexcept>

// FrameWork includes
#include "GaudiKernel/AudFactory.h"
#include "GaudiKernel/INamedInterface.h"

// AthenaServices includes
#include "FPEAuditor.h"

// C includes
#include <fenv.h>

/////////////////////////////////////////////////////////////////// 
// Public methods: 
/////////////////////////////////////////////////////////////////// 

// Constructors
////////////////
FPEAuditor::FPEAuditor( const std::string& name, 
			ISvcLocator* pSvcLocator ) : 
  Auditor     ( name, pSvcLocator  ),
  AthMessaging(msgSvc(), name),
  m_fpe_stack()
{
  //
  // Property declaration
  // 
  //declareProperty( "Property", m_nProperty, "descr" );

  // for AuditorHandle ? someday ?
  //declareInterface<IAuditor>(this);
}

// Destructor
///////////////
FPEAuditor::~FPEAuditor()
{ 
  //m_msg << MSG::DEBUG << "Calling destructor" << endreq;
}

StatusCode FPEAuditor::initialize()
{
  //ATH_MSG_INFO("==> initialize");
  // add a fake node here because we may come alive while the AuditorSvc is
  // still initializing (so one edge is left orphaned)
  add_fpe_node();
  return StatusCode::SUCCESS;
}

/////////////////////////////////////////////////////////////////// 
// Const methods: 
///////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////// 
// Non-const methods: 
/////////////////////////////////////////////////////////////////// 

void FPEAuditor::beforeInitialize(INamedInterface* /*comp*/)
{
  add_fpe_node();
}

void FPEAuditor::afterInitialize(INamedInterface* comp)
{
  //ATH_MSG_INFO("<== ini [" << comp->name() << "]");
  static const std::string step = "initialize";
  report_fpe(step, comp->name());
  pop_fpe_node();
}

void FPEAuditor::beforeReinitialize(INamedInterface* /*comp*/)
{
  add_fpe_node();
}

void FPEAuditor::afterReinitialize( INamedInterface* comp)
{
  static const std::string step = "reinitialize";
  report_fpe(step, comp->name());
  pop_fpe_node();
}

void FPEAuditor::beforeExecute(INamedInterface* /*comp*/)
{
  add_fpe_node();
}

void FPEAuditor::afterExecute( INamedInterface* comp, 
			       const StatusCode& ) 
{
  static const std::string step = "execute";
  report_fpe(step, comp->name());
  pop_fpe_node();
}

void FPEAuditor::beforeBeginRun(INamedInterface* /*comp*/)
{
  add_fpe_node();
}

void FPEAuditor::afterBeginRun(INamedInterface* comp)
{
  static const std::string step = "beginrun";
  report_fpe(step, comp->name());
  pop_fpe_node();
}

void FPEAuditor::beforeEndRun(INamedInterface* /*comp*/)
{
  add_fpe_node();
}

void FPEAuditor::afterEndRun(INamedInterface* comp)
{
  static const std::string step = "endrun";
  report_fpe(step, comp->name());
  pop_fpe_node();
}

void FPEAuditor::beforeFinalize(INamedInterface* /*comp*/)
{
  add_fpe_node();
}

void FPEAuditor::afterFinalize(INamedInterface* comp)
{
  static const std::string step = "finalize";
  report_fpe(step, comp->name());
  pop_fpe_node();
}

void FPEAuditor::before(CustomEventTypeRef /*evt*/, 
			const std::string& /*caller*/)
{
  add_fpe_node();
}

void FPEAuditor::after(CustomEventTypeRef evt, 
		       const std::string& caller,
		       const StatusCode&)
{
  report_fpe(evt, caller);
  pop_fpe_node();
}

/////////////////////////////////////////////////////////////////// 
// Protected methods: 
/////////////////////////////////////////////////////////////////// 

/////////////////////////////////////////////////////////////////// 
// Const methods: 
///////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////// 
// Non-const methods: 
/////////////////////////////////////////////////////////////////// 

/** report fpes which happened during step 'step' on behalf of 'caller'
 */
void
FPEAuditor::report_fpe(const std::string& step, 
		       const std::string& caller)
{
  // store current list of FPE flags which were raised before
  int raised = fetestexcept(FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
  if (raised) {
    if (raised & FE_OVERFLOW) {
      ATH_MSG_WARNING("FPE OVERFLOW in [" << step << "] of [" << caller << "]");
    }
    if (raised & FE_INVALID) {
      ATH_MSG_WARNING("FPE INVALID in [" << step << "] of [" << caller << "]");
    }
    if (raised & FE_DIVBYZERO) {
      ATH_MSG_WARNING("FPE DIVBYZERO in [" << step << " of [" << caller << "]");
    }
  }
}

void
FPEAuditor::add_fpe_node()
{
  // get current list of FPE flags so far
  int raised = fetestexcept(FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
  m_fpe_stack.push_back(std::make_pair(raised, 0));

  // clear FPE status word
  feclearexcept(FE_ALL_EXCEPT);
}

void
FPEAuditor::pop_fpe_node()
{
  if (m_fpe_stack.empty()) {
    ATH_MSG_ERROR("inconsistent fpe-stack !");
    throw std::runtime_error("inconsistent fpe-stack");
  }

  // restore fpe stack info
  int raised = m_fpe_stack.back().first;
  m_fpe_stack.pop_back();
  
  // consolidate
  if (!m_fpe_stack.empty()) {
    m_fpe_stack.back().second |= raised;
  }
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.