CMS 3D CMS Logo

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