CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_1/src/CondCore/ESSources/plugins/CondDBESSource.cc

Go to the documentation of this file.
00001 //
00002 // Package:     CondCore/ESSources
00003 // Module:      CondDBESSource
00004 //
00005 // Description: <one line class summary>
00006 //
00007 // Implementation:
00008 //     <Notes on implementation>
00009 //
00010 // Author:      Zhen Xie
00011 //
00012 #include "CondDBESSource.h"
00013 
00014 #include "boost/shared_ptr.hpp"
00015 #include "CondCore/DBCommon/interface/Exception.h"
00016 #include "CondCore/DBCommon/interface/Auth.h"
00017 #include "CondFormats/Common/interface/Time.h"
00018 #include "CondCore/DBCommon/interface/DbTransaction.h"
00019 #include "CondCore/DBCommon/interface/ConvertIOVSyncValue.h"
00020 
00021 #include "CondCore/ESSources/interface/ProxyFactory.h"
00022 #include "CondCore/ESSources/interface/DataProxy.h"
00023 
00024 #include "CondCore/IOVService/interface/PayloadProxy.h"
00025 #include "CondCore/MetaDataService/interface/MetaData.h"
00026 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00027 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00028 #include "CondCore/TagCollection/interface/TagCollectionRetriever.h"
00029 #include <exception>
00030 //#include <cstdlib>
00031 //#include <iostream>
00032 
00033 
00034 #include "CondFormats/Common/interface/TimeConversions.h"
00035 #include <iomanip>
00036 
00037 namespace {
00038   /* utility ot build the name of the plugin corresponding to a given record
00039      se ESSources
00040    */
00041   std::string
00042   buildName( const std::string& iRecordName) {
00043     return iRecordName+"@NewProxy";
00044   }
00045 
00046 
00047   /* utility class to return a IOVs associated to a given "name"
00048      This implementation return the IOV associated to a record...
00049      It is essentialy a workaround to get the full IOV out of the tag colector
00050      that is not accessible as hidden in the ESSource
00051      FIXME: need to support label??
00052    */
00053   class CondGetterFromESSource : public cond::CondGetter {
00054   public:
00055     CondGetterFromESSource(CondDBESSource::ProxyMap const & ip) : m_proxies(ip){}
00056     virtual ~CondGetterFromESSource(){}
00057 
00058     cond::IOVProxy get(std::string name) const {
00059       CondDBESSource::ProxyMap::const_iterator p = m_proxies.find(name);
00060       if ( p != m_proxies.end())
00061         return (*p).second->proxy()->iov();
00062       return cond::IOVProxy();
00063     }
00064 
00065     CondDBESSource::ProxyMap const & m_proxies;
00066   };
00067 
00068   // dump the state of a DataProxy
00069   void dumpInfo(std::ostream & out, std::string const & recName, cond::DataProxyWrapperBase const & proxy) {
00070     cond::SequenceState state(proxy.proxy()->iov().state());
00071     out << recName << " / " << proxy.label() << ": " 
00072         << proxy.connString() << ", " << proxy.tag()   << "\n  "
00073         << state.size() << ", " << state.revision()  << ", "
00074         << cond::time::to_boost(state.timestamp())     << "\n  "
00075         << state.comment()
00076         << "\n  "
00077         << "refresh " << proxy.proxy()->stats.nRefresh
00078         << "/" << proxy.proxy()->stats.nArefresh
00079         << ", make " << proxy.proxy()->stats.nMake
00080         << ", load " << proxy.proxy()->stats.nLoad
00081       ;
00082     if ( proxy.proxy()->stats.nLoad>0) {
00083       out << "\n oids,sinces:";
00084       cond::BasePayloadProxy::ObjIds const & ids =  proxy.proxy()->stats.ids;
00085       for (cond::BasePayloadProxy::ObjIds::const_iterator id=ids.begin(); id!=ids.end(); ++id)
00086         out << " "
00087             // << std::ios::hex 
00088             << (*id).oid1 <<"-"<< (*id).oid2 <<"," 
00089             // << std::ios::dec 
00090             <<  (*id).since;
00091     }
00092   }
00093 
00094 }
00095 
00096 
00097 /*
00098  *  config Param
00099  *  RefreshEachRun: if true will refresh the IOV at each new run (or lumiSection)
00100  *  DumpStat: if true dump the statistics of all DataProxy (currently on cout)
00101  *  DBParameters: configuration set of the connection
00102  *  globaltag: The GlobalTag
00103  *  toGet: list of record label tag connection-string to add/overwrite the content of the global-tag
00104  */
00105 CondDBESSource::CondDBESSource( const edm::ParameterSet& iConfig ) :
00106   m_connection(), 
00107   lastRun(0),  // for the stat
00108   lastLumi(0),  // for the stat
00109   doRefresh(iConfig.getUntrackedParameter<bool>("RefreshEachRun",false)),
00110   doDump(iConfig.getUntrackedParameter<bool>("DumpStat",false))
00111 {
00112   Stats s = {0,0,0,0,0,0};
00113   stats=s;      
00114   //std::cout<<"CondDBESSource::CondDBESSource"<<std::endl;
00115   /*parameter set parsing and pool environment setting
00116    */
00117   
00118   // default connection string
00119   // inproduction used for the global tag
00120   std::string userconnect= iConfig.getParameter<std::string>("connect");
00121   
00122 
00123   // connection configuration
00124   edm::ParameterSet connectionPset = iConfig.getParameter<edm::ParameterSet>("DBParameters");
00125   m_connection.configuration().setParameters( connectionPset );
00126   m_connection.configure();
00127   
00128 
00129   // load additional record/tag info it will overwrite the global tag
00130   std::map<std::string,cond::TagMetadata> replacement;
00131   if( iConfig.exists("toGet") ){
00132     typedef std::vector< edm::ParameterSet > Parameters;
00133     Parameters toGet = iConfig.getParameter<Parameters>("toGet");
00134     for(Parameters::iterator itToGet = toGet.begin(); itToGet != toGet.end(); ++itToGet ) {
00135       cond::TagMetadata nm;
00136       nm.recordname=itToGet->getParameter<std::string>("record");
00137       nm.labelname=itToGet->getUntrackedParameter<std::string>("label","");
00138       nm.tag=itToGet->getParameter<std::string>("tag");
00139       nm.pfn=itToGet->getUntrackedParameter<std::string>("connect",userconnect);
00140       //        nm.objectname=itFound->second;
00141       std::string k=nm.recordname+"@"+nm.labelname;
00142       replacement.insert(std::pair<std::string,cond::TagMetadata>(k,nm));
00143     }
00144   }
00145   
00146   // get the global tag, merge with "replacement" store in "tagCollection"
00147   std::string globaltag;
00148   if( iConfig.exists("globaltag")) globaltag=iConfig.getParameter<std::string>("globaltag");
00149   
00150   fillTagCollectionFromDB(userconnect,
00151                           iConfig.getUntrackedParameter<std::string>("pfnPrefix",""),
00152                           iConfig.getUntrackedParameter<std::string>("pfnPostfix",""),
00153                           globaltag,
00154                           replacement);
00155   
00156   
00157   TagCollection::iterator it;
00158   TagCollection::iterator itBeg=m_tagCollection.begin();
00159   TagCollection::iterator itEnd=m_tagCollection.end();
00160  
00161   typedef std::map<std::string, cond::DbSession> Sessions;
00162   Sessions sessions;
00163 
00164   /* load DataProxy Plugin (it is strongly typed due to EventSetup ideosyncrasis)
00165    * construct proxy
00166    * contrary to EventSetup the "object-name" is not used as identifier: multiple entries in a record are
00167    * dinstinguished only by their label...
00168    * done in two step: first create ProxyWrapper loading ALL required dictionaries
00169    * this will allow to initialize POOL in one go for each "database"
00170    * The real initialization of the Data-Proxies is done in the second loop 
00171    */
00172   std::vector<cond::DataProxyWrapperBase *> proxyWrappers(m_tagCollection.size());
00173   size_t ipb=0;
00174   for(it=itBeg;it!=itEnd;++it){
00175     proxyWrappers[ipb++] =  
00176       cond::ProxyFactory::get()->create(buildName(it->recordname));
00177   }
00178   // now all required libraries have been loaded
00179   // init sessions and DataProxies
00180   ipb=0;
00181   for(it=itBeg;it!=itEnd;++it){
00182     Sessions::iterator p = sessions.find( it->pfn);
00183     cond::DbSession nsess;
00184     if (p==sessions.end()) {
00185       //open db get tag info (i.e. the IOV token...)
00186       nsess = m_connection.createSession();
00187       nsess.open( it->pfn, cond::Auth::COND_READER_ROLE, true );
00188       sessions.insert(std::make_pair(it->pfn,nsess));
00189     } else nsess = (*p).second;
00190     //cond::MetaData metadata(nsess);
00191     //nsess.transaction().start(true);
00192     //std::string iovtoken = metadata.getToken(it->tag);
00193     // owenship...
00194     ProxyP proxy(proxyWrappers[ipb++]);
00195    //  instert in the map
00196     m_proxies.insert(std::make_pair(it->recordname, proxy));
00197     // initialize
00198     //proxy->lateInit(nsess,iovtoken, 
00199     //              it->labelname, it->pfn, it->tag
00200     //      );
00201     proxy->lateInit(nsess,it->tag, 
00202                     it->labelname, it->pfn);
00203     //nsess.transaction().commit();
00204   }
00205 
00206   // one loaded expose all other tags to the Proxy! 
00207   CondGetterFromESSource visitor(m_proxies);
00208   ProxyMap::iterator b= m_proxies.begin();
00209   ProxyMap::iterator e= m_proxies.end();
00210   for (;b!=e;b++) {
00211     (*b).second->proxy()->loadMore(visitor);
00212 
00214     edm::eventsetup::EventSetupRecordKey recordKey(edm::eventsetup::EventSetupRecordKey::TypeTag::findType( (*b).first ) );
00215     if( recordKey.type() != edm::eventsetup::EventSetupRecordKey::TypeTag() ) {
00216       findingRecordWithKey( recordKey );
00217       usingRecordWithKey( recordKey );
00218     }
00219   }
00220 
00221   stats.nData=m_proxies.size();
00222 }
00223 
00224 
00225 CondDBESSource::~CondDBESSource() {
00226   //dump info FIXME: find a more suitable place...
00227   if (doDump) {
00228     std::cout << "CondDBESSource Statistics" << std::endl
00229               << "DataProxy " << stats.nData
00230               <<" setInterval " << stats.nSet
00231               <<" Runs " << stats.nRun
00232               <<" Lumis " << stats.nLumi
00233               <<" Refresh " << stats.nRefresh
00234               <<" Actual Refresh " << stats.nActualRefresh;
00235     std::cout << std::endl;
00236     std::cout << "Global Proxy Statistics" << std::endl
00237               << "proxy " << cond::BasePayloadProxy::gstats.nProxy
00238               << " make " << cond::BasePayloadProxy::gstats.nMake
00239               << " load " << cond::BasePayloadProxy::gstats.nLoad;
00240     std::cout << std::endl;
00241 
00242 
00243     ProxyMap::iterator b= m_proxies.begin();
00244     ProxyMap::iterator e= m_proxies.end();
00245     for (;b!=e;b++) {
00246       dumpInfo(std::cout,(*b).first,*(*b).second);
00247       std::cout << "\n" << std::endl;
00248     }
00249 
00250     // FIXME
00251     // We shall eventually close transaction and session...
00252   }
00253 }
00254 
00255 
00256 //
00257 // invoked by EventSetUp: for a given record return the smallest IOV for which iTime is valid
00258 // limit to next run/lumisection of Refresh is required
00259 //
00260 void 
00261 CondDBESSource::setIntervalFor( const edm::eventsetup::EventSetupRecordKey& iKey, const edm::IOVSyncValue& iTime, edm::ValidityInterval& oInterval ){
00262 
00263   stats.nSet++;
00264   {
00265     // not really required, keep here for the time being
00266     if(iTime.eventID().run()!=lastRun) {
00267       lastRun=iTime.eventID().run();
00268       stats.nRun++;
00269     }
00270     if(iTime.luminosityBlockNumber()!=lastLumi) {
00271       lastLumi=iTime.luminosityBlockNumber();
00272       stats.nLumi++;
00273     }
00274   }
00275  
00276 
00277   std::string recordname=iKey.name();
00278   oInterval = edm::ValidityInterval::invalidInterval();
00279   
00280   //FIXME use equal_range
00281   ProxyMap::const_iterator b = m_proxies.lower_bound(recordname);
00282   ProxyMap::const_iterator e = m_proxies.upper_bound(recordname);
00283   if ( b == e) {
00284     LogDebug ("CondDBESSource")<<"no DataProxy (Pluging) found for record "<<recordname;
00285     return;
00286   }
00287 
00288   // compute the smallest interval (assume all objects have the same timetype....)
00289   cond::ValidityInterval recordValidity(1,cond::TIMELIMIT);
00290   cond::TimeType timetype;
00291   bool userTime=true;
00292   for (ProxyMap::const_iterator p=b;p!=e;++p) {
00293 
00294     timetype = (*p).second->proxy()->timetype();
00295     
00296     cond::Time_t abtime = cond::fromIOVSyncValue(iTime,timetype);
00297     userTime = (0==abtime);
00298     
00299     //std::cout<<"abtime "<<abtime<<std::endl;
00300 
00301     if (userTime) return; //  oInterval invalid to avoid that make is called...
00302     /*
00303       // make oInterval valid For Ever
00304     {
00305      oInterval = edm::ValidityInterval(cond::toIOVSyncValue(recordValidity.first,  cond::runnumber, true), 
00306                                        cond::toIOVSyncValue(recordValidity.second, cond::runnumber, false));
00307      return;
00308     }    
00309     */
00310 
00311 
00312     // refresh if required...
00313     if (doRefresh)  {
00314       LogDebug ("CondDBESSource") << "Refresh " << recordname << " " << iTime.eventID() << std::endl; 
00315       stats.nActualRefresh += (*p).second->proxy()->refresh(); 
00316       stats.nRefresh++;
00317     }
00318     
00319    
00320     
00321 
00322 
00323     //query the IOVSequence
00324     cond::ValidityInterval validity = (*p).second->proxy()->setIntervalFor(abtime);
00325     
00326     recordValidity.first = std::max(recordValidity.first,validity.first);
00327     recordValidity.second = std::min(recordValidity.second,validity.second);
00328  
00329     LogDebug ("CondDBESSource") <<"setting validity " << recordname << " "
00330                                 <<recordValidity.first<<" "<<recordValidity.second<<" for ibtime "<<abtime<< std::endl;
00331  
00332   }      
00333    
00334   // to force refresh we set end-value to the minimum such an IOV can exend to: current run or lumiblock
00335     
00336   if ( (!userTime) && recordValidity.second!=0) {
00337     edm::IOVSyncValue start = cond::toIOVSyncValue(recordValidity.first, timetype, true);
00338     edm::IOVSyncValue stop = doRefresh ? cond::limitedIOVSyncValue (iTime, timetype)
00339       : cond::toIOVSyncValue(recordValidity.second, timetype, false);
00340        
00341     oInterval = edm::ValidityInterval( start, stop );
00342    }
00343 }
00344   
00345 
00346 //required by EventSetup System
00347 void 
00348 CondDBESSource::registerProxies(const edm::eventsetup::EventSetupRecordKey& iRecordKey , KeyedProxies& aProxyList) {
00349   std::string recordname=iRecordKey.name();
00350 
00351   ProxyMap::const_iterator b = m_proxies.lower_bound(recordname);
00352   ProxyMap::const_iterator e = m_proxies.upper_bound(recordname);
00353   if ( b == e) {
00354     LogDebug ("CondDBESSource")<<"no DataProxy (Pluging) found for record "<<recordname;
00355     return;
00356   }
00357 
00358   for (ProxyMap::const_iterator p=b;p!=e;++p) {  
00359     if(0 != (*p).second.get()) {
00360       edm::eventsetup::TypeTag type =  (*p).second->type(); 
00361       edm::eventsetup::DataKey key( type, edm::eventsetup::IdTags((*p).second->label().c_str()) );
00362       aProxyList.push_back(KeyedProxies::value_type(key,(*p).second->edmProxy()));
00363     }
00364   }
00365 }
00366 
00367 // required by the EventSetup System
00368 void 
00369 CondDBESSource::newInterval(const edm::eventsetup::EventSetupRecordKey& iRecordType,
00370                             const edm::ValidityInterval&) 
00371 {
00372   //LogDebug ("CondDBESSource")<<"newInterval";
00373   invalidateProxies(iRecordType);
00374 }
00375 
00376 
00377 // fills tagcollection merging with replacement
00378 void 
00379 CondDBESSource::fillTagCollectionFromDB( const std::string & coraldb, 
00380                                          const std::string & prefix,
00381                                          const std::string & postfix,
00382                                          const std::string & roottag,
00383                                          std::map<std::string,cond::TagMetadata>& replacement){
00384   //  std::cout<<"fillTagCollectionFromDB"<<std::endl;
00385 
00386 
00387   std::set< cond::TagMetadata > tagcoll;
00388  
00389  if (!roottag.empty()) {
00390    if (coraldb.empty()) 
00391      throw cond::Exception(std::string("ESSource: requested global tag ")+roottag+" but not connection string given");
00392    cond::DbSession session = m_connection.createSession();
00393    session.open( coraldb, cond::Auth::COND_READER_ROLE, true );
00394    session.transaction().start(true);
00395    cond::TagCollectionRetriever tagRetriever( session, prefix, postfix );
00396    tagRetriever.getTagCollection(roottag,tagcoll);
00397    session.transaction().commit();
00398   } 
00399 
00400   std::set<cond::TagMetadata>::iterator it;
00401   std::set<cond::TagMetadata>::iterator itBeg=tagcoll.begin();
00402   std::set<cond::TagMetadata>::iterator itEnd=tagcoll.end();
00403 
00404   // FIXME the logic is a bit perverse: can be surely linearized (at least simplified!) ....
00405   for(it=itBeg; it!=itEnd; ++it){
00406     std::string k=it->recordname+"@"+it->labelname;
00407     std::map<std::string,cond::TagMetadata>::iterator fid=replacement.find(k);
00408     if(fid != replacement.end()){
00409       cond::TagMetadata m;
00410       m.recordname=it->recordname;
00411       m.labelname=it->labelname;
00412       m.pfn=fid->second.pfn;
00413       m.tag=fid->second.tag;
00414       m.objectname=it->objectname;
00415       m_tagCollection.insert(m);
00416       replacement.erase(fid);
00417     }else{
00418       m_tagCollection.insert(*it);
00419     }
00420   }
00421   std::map<std::string,cond::TagMetadata>::iterator itrep;
00422   std::map<std::string,cond::TagMetadata>::iterator itrepBeg=replacement.begin();
00423   std::map<std::string,cond::TagMetadata>::iterator itrepEnd=replacement.end();
00424   for(itrep=itrepBeg; itrep!=itrepEnd; ++itrep){
00425     //std::cout<<"appending"<<std::endl;
00426     //std::cout<<"pfn "<<itrep->second.pfn<<std::endl;
00427     //std::cout<<"objectname "<<itrep->second.objectname<<std::endl;
00428     //std::cout<<"tag "<<itrep->second.tag<<std::endl;
00429     //std::cout<<"recordname "<<itrep->second.recordname<<std::endl;
00430     m_tagCollection.insert(itrep->second);
00431   }
00432 }
00433 
00434 
00435 // backward compatibility for configuration files
00436 class PoolDBESSource : public CondDBESSource {
00437 public:
00438   explicit  PoolDBESSource( const edm::ParameterSet& ps) :
00439     CondDBESSource(ps){}
00440 };
00441 
00442 #include "FWCore/Framework/interface/SourceFactory.h"
00443 //define this as a plug-in
00444 DEFINE_FWK_EVENTSETUP_SOURCE(PoolDBESSource);
00445