Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New template one::EDAnalyzer for dealing with B ON/OFF transitions using EventSetup and PoolDBOutputService. #16248

Merged
merged 2 commits into from Oct 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 10 additions & 8 deletions CondTools/Ecal/plugins/BuildFile.xml
@@ -1,16 +1,18 @@
<use name="boost"/>
<use name="xerces-c"/>
<use name="CondFormats/Alignment"/>
<use name="CondFormats/DataRecord"/>
<use name="CondFormats/EcalObjects"/>
<use name="CondFormats/RunInfo"/>
<use name="CondCore/DBOutputService"/>
<use name="CondCore/PopCon"/>
<use name="CondTools/Ecal"/>
<use name="boost"/>
<use name="FWCore/PluginManager"/>
<use name="FWCore/Framework"/>
<use name="CondTools/RunInfo"/>
<use name="DataFormats/Common"/>
<use name="DataFormats/EcalDetId"/>
<use name="CondCore/DBOutputService"/>
<use name="CondFormats/EcalObjects"/>
<use name="CondFormats/DataRecord"/>
<use name="CondFormats/Alignment"/>
<use name="Utilities/General"/>
<use name="FWCore/Framework"/>
<use name="FWCore/PluginManager"/>
<use name="Utilities/General"/>
<library file="*.cc" name="CondToolsEcalPlugin">
<flags EDM_PLUGIN="1"/>
</library>
25 changes: 25 additions & 0 deletions CondTools/Ecal/plugins/EcalADCToGeVConstantBTransitionAnalyzer.cc
@@ -0,0 +1,25 @@
#include "CondFormats/EcalObjects/interface/EcalADCToGeVConstant.h"
#include "CondFormats/DataRecord/interface/EcalADCToGeVConstantRcd.h"
#include "CondTools/RunInfo/interface/BTransitionAnalyzer.h"
#include <sstream>

class EcalADCToGeVConstantBTransitionAnalyzer: public cond::BTransitionAnalyzer<EcalADCToGeVConstant, EcalADCToGeVConstantRcd> {
public:
EcalADCToGeVConstantBTransitionAnalyzer( edm::ParameterSet const & pset ):
cond::BTransitionAnalyzer<EcalADCToGeVConstant, EcalADCToGeVConstantRcd>( pset ) {}
bool equalPayloads( edm::ESHandle<EcalADCToGeVConstant> const & payloadHandle, edm::ESHandle<EcalADCToGeVConstant> const & payloadRefHandle ) {
bool areEquals = false;
std::ostringstream os;
os << "[" << "EcalADCToGeVConstantBTransitionAnalyzer::" << __func__ << "]: " << "Payload extracted starting from magnetic field value: ";
payloadHandle->print( os );
os << "\nReference payload from the target tag: ";
payloadRefHandle->print( os );
edm::LogInfo( "EcalADCToGeVConstantBTransitionAnalyzer" ) << os.str();
if( payloadHandle->getEBValue() == payloadRefHandle->getEBValue() &&
payloadHandle->getEEValue() == payloadRefHandle->getEEValue() ) areEquals = true;
return areEquals;
}
};

#include "FWCore/Framework/interface/MakerMacros.h"
DEFINE_FWK_MODULE(EcalADCToGeVConstantBTransitionAnalyzer);
107 changes: 107 additions & 0 deletions CondTools/Ecal/test/EcalADCToGeVConstantBTransitionAnalyzer_cfg.py
@@ -0,0 +1,107 @@
import socket
import time
import FWCore.ParameterSet.Config as cms
import FWCore.ParameterSet.VarParsing as VarParsing
from CondCore.CondDB.CondDB_cfi import *
from Configuration.AlCa.autoCond import autoCond

options = VarParsing.VarParsing()
options.register('connectionString',
'frontier://FrontierProd/CMS_CONDITIONS', #default value
VarParsing.VarParsing.multiplicity.singleton,
VarParsing.VarParsing.varType.string,
"GlobalTag Connection string")
options.register('globalTag',
autoCond['run2_data'], #default value
VarParsing.VarParsing.multiplicity.singleton,
VarParsing.VarParsing.varType.string,
"GlobalTag")
options.register( 'runNumber'
, 1 #default value
, VarParsing.VarParsing.multiplicity.singleton
, VarParsing.VarParsing.varType.int
, "Run number to be uploaded."
)
options.register( 'destinationConnection'
, 'sqlite_file:EcalADCToGeVConstant_EDAnalyzer_test.db' #default value
, VarParsing.VarParsing.multiplicity.singleton
, VarParsing.VarParsing.varType.string
, "Connection string to the DB where payloads will be possibly written."
)
options.register( 'tag'
, 'EcalADCToGeVConstant_EDAnalyzer_test'
, VarParsing.VarParsing.multiplicity.singleton
, VarParsing.VarParsing.varType.string
, "Tag written in destinationConnection and finally appended onto the tag in connectionString."
)
options.register( 'currentThreshold'
, 18000.
, VarParsing.VarParsing.multiplicity.singleton
, VarParsing.VarParsing.varType.float
, "The threshold on the magnet current for considering a switch of the magnetic field."
)
options.register( 'messageLevel'
, 0 #default value
, VarParsing.VarParsing.multiplicity.singleton
, VarParsing.VarParsing.varType.int
, "Message level; default to 0."
)
options.parseArguments()

CondDBConnection = CondDB.clone( connect = cms.string( options.connectionString ) )
CondDBConnection.DBParameters.messageLevel = cms.untracked.int32( options.messageLevel )
DestConnection = CondDB.clone( connect = cms.string( options.destinationConnection ) )
DestConnection.DBParameters.messageLevel = cms.untracked.int32( options.messageLevel )

process = cms.Process( "EcalADCToGeVConstantWriter" )

process.MessageLogger = cms.Service( "MessageLogger"
, destinations = cms.untracked.vstring( 'cout' )
, cout = cms.untracked.PSet( threshold = cms.untracked.string( 'INFO' ) )
)

if options.messageLevel == 3:
#enable LogDebug output: remember the USER_CXXFLAGS="-DEDM_ML_DEBUG" compilation flag!
process.MessageLogger.cout = cms.untracked.PSet( threshold = cms.untracked.string( 'DEBUG' ) )
process.MessageLogger.debugModules = cms.untracked.vstring( '*' )

process.source = cms.Source( "EmptySource",
firstRun = cms.untracked.uint32( options.runNumber ),
firstTime = cms.untracked.uint64( ( long( time.time() ) - 24 * 3600 ) << 32 ), #24 hours ago in nanoseconds
numberEventsInRun = cms.untracked.uint32( 1 ),
numberEventsInLuminosityBlock = cms.untracked.uint32( 1 )
)
process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32( 1 ) )

process.GlobalTag = cms.ESSource( "PoolDBESSource",
CondDBConnection,
globaltag = cms.string( options.globalTag ),
toGet = cms.VPSet()
)
process.GlobalTag.toGet.append( cms.PSet( record = cms.string( "EcalADCToGeVConstantRcd" ),
label = cms.untracked.string( "0T" ),
tag = cms.string( "EcalADCToGeVConstant_0T_test0" ),
connect = cms.string( "frontier://FrontierPrep/CMS_CONDITIONS" ),
)
)
process.GlobalTag.toGet.append( cms.PSet( record = cms.string( "EcalADCToGeVConstantRcd" ),
label = cms.untracked.string( "38T" ),
tag = cms.string( "EcalADCToGeVConstant_3.8T_test0" ),
connect = cms.string( "frontier://FrontierPrep/CMS_CONDITIONS" ),
)
)

process.PoolDBOutputService = cms.Service( "PoolDBOutputService"
, DestConnection
, timetype = cms.untracked.string( 'runnumber' )
, toPut = cms.VPSet( cms.PSet( record = cms.string( 'EcalADCToGeVConstantRcd' )
, tag = cms.string( options.tag )
)
)
)

process.ecalADCToGeVConstantBTransition = cms.EDAnalyzer( "EcalADCToGeVConstantBTransitionAnalyzer"
, currentThreshold = cms.untracked.double( options.currentThreshold )
)

process.p = cms.Path( process.ecalADCToGeVConstantBTransition )
1 change: 1 addition & 0 deletions CondTools/RunInfo/BuildFile.xml
Expand Up @@ -4,6 +4,7 @@
<use name="CoralBase"/>
<use name="DataFormats/Provenance"/>
<use name="FWCore/Framework"/>
<use name="FWCore/MessageLogger"/>
<use name="FWCore/ParameterSet"/>
<use name="FWCore/ServiceRegistry"/>
<use name="RelationalAccess"/>
Expand Down
72 changes: 72 additions & 0 deletions CondTools/RunInfo/interface/BTransitionAnalyzer.h
@@ -0,0 +1,72 @@
#ifndef BTRANSITIONANALYZER_H
#define BTRANSITIONANALYZER_H

#include "FWCore/Framework/interface/one/EDAnalyzer.h"
#include "FWCore/Framework/interface/ESHandle.h"
#include "FWCore/Framework/interface/EventSetup.h"
#include "FWCore/Framework/interface/Run.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/ServiceRegistry/interface/Service.h"
#include "CondCore/CondDB/interface/Utils.h"
#include "CondCore/DBOutputService/interface/PoolDBOutputService.h"
#include "CondFormats/RunInfo/interface/RunInfo.h"
#include "CondFormats/DataRecord/interface/RunSummaryRcd.h"

namespace cond {
template<class T, class R>
class BTransitionAnalyzer: public edm::one::EDAnalyzer<edm::one::WatchRuns, edm::one::SharedResources> {
public:
BTransitionAnalyzer( const edm::ParameterSet& pset ):
m_currentThreshold( pset.getUntrackedParameter<double>( "currentThreshold", 18000. ) ) {
usesResource( "PoolDBOutputService" );

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@diguida I have just one comment/question. You declare that you use the resource "PoolDBOutputService". As I understood, this is only needed, if the resource is not thread-safe. However, @Dr15Jones commented in this HN thread that it appears to be thread-safe.
Do you have reasons to declare it anyways, except that "appears to be thread-safe" might be a bit vague?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ghellwig sorry for late reply.
As discussed few minutes ago at the AlCaDB meeting, the code here was originally developed in 7.4.X, where PoolDBOutputService was not thread safe.
According to the API description

The system makes sure that only one module which has declared a usage of a specific resource will ever be run at a time. That is, the system will serialize all calls to all modules which declare that resource.

In the online context of the O2O, a cmsRun job will call only this module (apart from input sources), so, even if formally the performance penalty is introduced, operationally it should not be visible. Besides this, in that context you care more of the correctness of the database transactions than of the performance of job: if you have a fast job potentially writing wrong IOV, this is a big problem.

Anyhow, if also @Dr15Jones agrees that the usesResource is not needed, I can put a PR removing it.

HTH

P.S.: you were also saying another observation at the meeting, but I did not catch it. Feel free to post it here.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@diguida thanks for the clarification!
My other comment does not apply anymore, but I list it here for reference: You write usesResource("PoolDBOutputService");, but in general it is better practice to define a static const string in PoolDBOutputService and use this to avoid typos because the compiler checks the name of the variable which is not the case if you use a hard-coded string everytime the resource is used.

Copy link
Contributor Author

@diguida diguida Oct 31, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ghellwig you are absolutely right! This is common sense (as well as a software best practice):

  • adding a static data member using constant expression for labelling the framework service name:static constexpr auto serviceName = "PoolDBOutputService";
  • using it every time you refer to the service name in client code: usesResource( std::string( PoolDBOutputService::serviceName ) );

}
#ifdef __INTEL_COMPILER
virtual ~BTransitionAnalyzer() = default;
#endif
// implicit copy constructor
// implicit assignment operator
// implicit destructor
virtual void beginJob() final {};
virtual void beginRun(edm::Run const&, edm::EventSetup const&) final {};
virtual void analyze(edm::Event const&, edm::EventSetup const&) final {};
virtual void endRun(edm::Run const& run , edm::EventSetup const& eventSetup) final {
edm::ESHandle<RunInfo> runInfoHandle;
edm::ESHandle<T> payloadHandle, payloadRefHandle;
eventSetup.get<RunInfoRcd>().get(runInfoHandle);
double avg_current = (double)runInfoHandle->m_avg_current;
double current_default = -1;
std::string bOnLabel = std::string( "38T" );
std::string bOffLabel = std::string( "0T" );
std::string bFieldLabel = bOnLabel;
LogDebug( "BTransitionAnalyzer" ) << "Comparing value of magnet current: " << avg_current << " A for run: " << run.run()
<< " with the corresponding threshold: "<< m_currentThreshold << " A." << std::endl;
if( avg_current != current_default && avg_current <= m_currentThreshold ) bFieldLabel = bOffLabel;
edm::LogInfo( "BTransitionAnalyzer" ) << "The magnet was "
<< ( bFieldLabel == bOnLabel ? "ON" : "OFF" ) << " during run " << run.run()
<< ".\nLoading the product for the corrisponding label " << bFieldLabel << std::endl;
eventSetup.get<R>().get( bFieldLabel, payloadHandle );
eventSetup.get<R>().get( payloadRefHandle );
edm::Service<cond::service::PoolDBOutputService> mydbservice;
if( mydbservice.isAvailable() ) {
if( !equalPayloads( payloadHandle, payloadRefHandle ) ) {
edm::LogInfo( "BTransitionAnalyzer" ) << "Exporting payload corresponding to the calibrations for magnetic field "
<< ( bFieldLabel == bOnLabel ? "ON" : "OFF" )
<< " starting from run number: " << run.run() << std::endl;
mydbservice->writeOne( payloadHandle.product(), run.run(), demangledName( typeid(R) ) );
} else {
edm::LogInfo( "BTransitionAnalyzer" ) << "The payload corresponding to the calibrations for magnetic field "
<< ( bFieldLabel == bOnLabel ? "ON" : "OFF" )
<< " is still valid for run " << run.run()
<< ".\nNo transfer needed." << std::endl;
}
} else {
edm::LogError( "BTransitionAnalyzer" ) << "PoolDBOutputService unavailable";
}
}
virtual void endJob() final {};
virtual bool equalPayloads( edm::ESHandle<T> const & payloadHandle, edm::ESHandle<T> const & payloadRefHandle ) = 0;
private:
double m_currentThreshold;
};
} //namespace cond
#endif //BTRANSITIONANALYZER_H