CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_1/src/CondCore/IOVService/src/IOVEditor.cc

Go to the documentation of this file.
00001 #include "CondCore/IOVService/interface/IOVEditor.h"
00002 #include "CondCore/IOVService/interface/IOVSchemaUtility.h"
00003 #include "CondCore/IOVService/interface/IOVNames.h"
00004 #include "CondCore/DBCommon/interface/Exception.h"
00005 #include "CondCore/DBCommon/interface/IOVInfo.h"
00006 
00007 namespace cond {
00008 
00009   boost::shared_ptr<cond::IOVSequence> loadIOV( cond::DbSession& dbSess, 
00010                                                 const std::string& iovToken ){
00011     if( iovToken.empty()){
00012       throw cond::Exception("IOVEditor::loadIOV Error: token is empty.");
00013     } 
00014     boost::shared_ptr<cond::IOVSequence> iov = dbSess.getTypedObject<cond::IOVSequence>( iovToken );
00015     // loading the lazy-loading Queryable vector...
00016     iov->loadAll();
00017     //**** temporary for the schema transition
00018     if( dbSess.isOldSchema() ){
00019       PoolTokenParser parser(  dbSess.storage() ); 
00020       iov->swapTokens( parser );
00021     }
00022     //****
00023     return iov;
00024   }
00025   
00026   std::string insertIOV( cond::DbSession& dbSess, 
00027                          const boost::shared_ptr<IOVSequence>& data,
00028                          bool swapOIds=false ){
00029     // ***** TEMPORARY FOR TRANSITION PHASE
00030     if( swapOIds && dbSess.isOldSchema() ){
00031       PoolTokenWriter writer( dbSess.storage() );
00032       data->swapOIds( writer );
00033     }
00034     // *****
00035     return dbSess.storeObject( data.get(), cond::IOVNames::container());
00036   }
00037 
00038   void updateIOV( cond::DbSession& dbSess, 
00039                   const boost::shared_ptr<IOVSequence>& data,
00040                   const std::string& token ){
00041     // ***** TEMPORARY FOR TRANSITION PHASE
00042     if( dbSess.isOldSchema() ){
00043       PoolTokenWriter writer( dbSess.storage() );
00044       data->swapOIds( writer );
00045     }
00046     // *****
00047     dbSess.updateObject( data.get(), token );
00048   }
00049 
00050   IOVImportIterator::IOVImportIterator( boost::shared_ptr<cond::IOVProxyData>& destIov ):
00051     m_sourceIov(),
00052     m_destIov( destIov ),
00053     m_lastSince( 0 ),
00054     m_bulkSize( 0 ),
00055     m_cursor(),
00056     m_till()
00057   {
00058   }
00059   
00060   IOVImportIterator::~IOVImportIterator(){
00061   }
00062 
00063   void IOVImportIterator::setUp( cond::IOVProxy& sourceIov,
00064                                  cond::Time_t since,
00065                                  cond::Time_t till,
00066                                  bool outOfOrder,
00067                                  size_t bulkSize ){  
00068     m_sourceIov = sourceIov;
00069     const IOVSequence& siov = m_sourceIov.iov();
00070     cond::Time_t dsince = std::max(since, siov.firstSince());
00071     IOVSequence::const_iterator ifirstTill = siov.find(dsince);
00072     IOVSequence::const_iterator isecondTill = siov.find(till);
00073     if( isecondTill != siov.iovs().end() ) isecondTill++;
00074     
00075     if (ifirstTill==isecondTill) 
00076       throw cond::Exception("IOVImportIterator::setUp Error: empty input range");
00077     
00078     IOVSequence& diov = *m_destIov->data;
00079     if ( diov.iovs().empty()) ; // do not waist time
00080     else if (outOfOrder) {
00081       for( IOVSequence::const_iterator it=ifirstTill;
00082            it!=isecondTill; ++it)
00083         if (diov.exist(it->sinceTime()))
00084           throw cond::Exception("IOVImportIterator::setUp Error: since time already exists");
00085     } else if (dsince <= diov.iovs().back().sinceTime())
00086       throw cond::Exception("IOVImportIterator::setUp Error: since time out of range, below last since");
00087     
00088     m_lastSince = dsince;
00089     m_cursor = ifirstTill;
00090     m_till = isecondTill;
00091     m_bulkSize = bulkSize;
00092  }
00093 
00094   void IOVImportIterator::setUp( cond::DbSession& sourceSess,
00095                                  const std::string& sourceIovToken,
00096                                  cond::Time_t since,
00097                                  cond::Time_t till,
00098                                  bool outOfOrder,
00099                                  size_t bulkSize ){
00100     IOVProxy sourceIov( sourceSess, sourceIovToken );
00101     setUp( sourceIov, since, till, outOfOrder, bulkSize );
00102   }
00103 
00104   void IOVImportIterator::setUp( cond::IOVProxy& sourceIov,
00105                                  size_t bulkSize ){ 
00106 
00107     m_sourceIov = sourceIov;
00108     const IOVSequence& siov = m_sourceIov.iov();
00109     cond::Time_t dsince = siov.firstSince();
00110 
00111     IOVSequence::const_iterator ifirstTill = siov.iovs().begin();
00112     IOVSequence::const_iterator isecondTill = siov.iovs().end();
00113     
00114     IOVSequence& diov = *m_destIov->data;
00115     if (!diov.iovs().empty()) { // do not waist time
00116       if (dsince <= diov.iovs().back().sinceTime())
00117         throw cond::Exception("IOVImportIterator::setUp Error: since time out of range, below last since");
00118     }
00119 
00120     m_lastSince = dsince;
00121     m_cursor = ifirstTill;
00122     m_till = isecondTill;
00123     m_bulkSize = bulkSize;
00124   }
00125 
00126   void IOVImportIterator::setUp( cond::DbSession& sourceSess,
00127                                  const std::string& sourceIovToken,
00128                                  size_t bulkSize ){
00129     IOVProxy sourceIov( sourceSess, sourceIovToken );
00130     setUp( sourceIov, bulkSize );
00131   }
00132 
00133   bool IOVImportIterator::hasMoreElements(){
00134     return m_cursor != m_till;
00135   }
00136 
00137   size_t IOVImportIterator::importMoreElements(){
00138     size_t i = 0;    
00139     boost::shared_ptr<IOVSequence>& diov = m_destIov->data;
00140     for( ; i<m_bulkSize && m_cursor != m_till; ++i, ++m_cursor, m_lastSince=m_cursor->sinceTime() ){
00141       std::string newPtoken = m_destIov->dbSession.importObject( m_sourceIov.db(),m_cursor->token());
00142       ora::OId poid;
00143       poid.fromString( newPtoken );
00144       ora::Container cont = m_destIov->dbSession.storage().containerHandle( poid.containerId() );
00145       diov->add(m_lastSince, newPtoken, cont.className());
00146     }
00147     if( m_cursor == m_till ) diov->stamp(cond::userInfo(),false);
00148     updateIOV( m_destIov->dbSession, diov, m_destIov->token );
00149     return i;
00150   }
00151 
00152   size_t IOVImportIterator::importAll(){
00153     size_t total = 0;
00154     while( hasMoreElements() ){
00155       total += importMoreElements();
00156     }
00157     return total;
00158   }
00159     
00160   IOVEditor::~IOVEditor(){}
00161 
00162   IOVEditor::IOVEditor( cond::DbSession& dbSess):
00163     m_isLoaded(false),
00164     m_iov( new IOVProxyData( dbSess ) ){
00165   }
00166 
00167   IOVEditor::IOVEditor( cond::DbSession& dbSess,
00168                         const std::string& token ):
00169     m_isLoaded(false),
00170     m_iov( new IOVProxyData( dbSess, token )){
00171   }
00172   
00173   void IOVEditor::reload(){
00174     m_iov->refresh();
00175     m_isLoaded = true;
00176   }
00177 
00178   void IOVEditor::load( const std::string& token ){
00179     m_iov->token = token;
00180     m_iov->refresh();
00181     m_isLoaded = true;
00182   }
00183 
00184   void IOVEditor::debugInfo(std::ostream & co) const {
00185     boost::shared_ptr<IOVSequence>& iov = m_iov->data;
00186     co << "IOVEditor: ";
00187     co << "db " << m_iov->dbSession.connectionString();
00188     if(m_iov->token.empty()) {
00189       co << " no token"; return;
00190     }
00191     if (!m_iov->data.get() )  {
00192       co << " no iov for token " << m_iov->token;
00193       return;
00194     }
00195     co << " iov token " << m_iov->token;
00196     co << "\nStamp: " <<  iov->comment()
00197        << "; time " <<  iov->timestamp()
00198        << "; revision " <<  iov->revision();
00199     co <<". TimeType " << cond::timeTypeSpecs[ iov->timeType()].name;
00200     if(  iov->iovs().empty() ) 
00201       co << ". empty";
00202     else
00203       co << ". size " <<  iov->iovs().size() 
00204          << "; last since " << iov->iovs().back().sinceTime();
00205   }
00206 
00207   void IOVEditor::reportError(std::string message) const {
00208     std::ostringstream out;
00209     out << "Error in ";
00210     debugInfo(out);
00211     out  << "\n" << message;
00212     throw cond::Exception(out.str());
00213   }
00214 
00215   void IOVEditor::reportError( std::string message, 
00216                                cond::Time_t time) const {
00217     std::ostringstream out;
00218     out << "Error in";
00219     debugInfo(out);
00220     out << "\n" <<  message << " for time:  " << time;
00221     throw cond::Exception(out.str());
00222   }
00223 
00224 
00225   bool IOVEditor::createIOVContainerIfNecessary(){
00226     bool ret = false;
00227     cond::IOVSchemaUtility schemaUtil( m_iov->dbSession );
00228     if( !schemaUtil.existsIOVContainer() ){
00229       schemaUtil.createIOVContainer();
00230       ret = true;
00231     }
00232     return ret;
00233   }
00234 
00235   // create empty default sequence
00236   std::string IOVEditor::create( cond::TimeType timetype ) {
00237     m_iov->data.reset( new cond::IOVSequence(timetype) );
00238     m_iov->token = insertIOV( m_iov->dbSession, m_iov->data );
00239     m_isLoaded=true;
00240     return m_iov->token;
00241   }
00242 
00243   std::string IOVEditor::create(  cond::TimeType timetype,
00244                                   cond::Time_t lastTill,
00245                                   const std::string& metadata ) {
00246     m_iov->data.reset( new cond::IOVSequence((int)timetype,lastTill, metadata) );
00247     m_iov->token = insertIOV( m_iov->dbSession, m_iov->data );
00248     m_isLoaded=true;
00249     return m_iov->token;
00250   }
00251    
00252      // ####### TO BE REOMOVED ONLY USED IN TESTS
00253   std::string IOVEditor::create(cond::TimeType timetype, cond::Time_t lastTill ){
00254     m_iov->data.reset( new cond::IOVSequence((int)timetype,lastTill, std::string(" ")) );
00255     m_iov->token = insertIOV( m_iov->dbSession, m_iov->data );
00256     m_isLoaded=true;
00257     return m_iov->token;
00258   }
00259 
00260   bool IOVEditor::validTime( cond::Time_t time, 
00261                              cond::TimeType timetype) const {
00262     return time>=timeTypeSpecs[timetype].beginValue && time<=timeTypeSpecs[timetype].endValue;   
00263     
00264   }
00265   
00266   bool IOVEditor::validTime(cond::Time_t time) const {
00267     return validTime(time,m_iov->data->timeType());
00268   }
00269   
00270   
00271   
00272   unsigned int
00273   IOVEditor::insert( cond::Time_t tillTime,
00274                      const std::string& payloadToken ){
00275     if( !m_isLoaded ){
00276       reload();
00277     }
00278     boost::shared_ptr<IOVSequence>& iov = m_iov->data;
00279     if( iov->iovs().empty() ) 
00280       reportError("cond::IOVEditor::insert cannot inser into empty IOV sequence",tillTime);
00281     
00282     if(!validTime(tillTime))
00283       reportError("cond::IOVEditor::insert time not in global range",tillTime);
00284     
00285     if(tillTime<=iov->lastTill() )
00286       reportError("cond::IOVEditor::insert IOV not in range",tillTime);
00287     
00288     cond::Time_t newSince=iov->lastTill()+1;
00289     std::string payloadClassName = m_iov->dbSession.classNameForItem( payloadToken );
00290     unsigned int ret = iov->add(newSince, payloadToken, payloadClassName);
00291     iov->updateLastTill(tillTime);
00292     updateIOV( m_iov->dbSession, iov, m_iov->token );
00293     return ret;
00294   }
00295   
00296   void 
00297   IOVEditor::bulkAppend(std::vector< std::pair<cond::Time_t, std::string > >& values){
00298     if (values.empty()) return;
00299     if( !m_isLoaded ){
00300       reload();
00301     }
00302     boost::shared_ptr<IOVSequence>& iov = m_iov->data;
00303     cond::Time_t firstTime = values.front().first;
00304     cond::Time_t  lastTime = values.back().first;
00305     if(!validTime(firstTime))
00306       reportError("cond::IOVEditor::bulkInsert first time not in global range",firstTime);
00307 
00308     if(!validTime(lastTime))
00309       reportError("cond::IOVEditor::bulkInsert last time not in global range",lastTime);
00310 
00311     if(lastTime>= iov->lastTill() ||
00312       ( !iov->iovs().empty() && firstTime<=iov->iovs().back().sinceTime()) 
00313        )    
00314      reportError("cond::IOVEditor::bulkInsert IOV not in range",firstTime);
00315 
00316    for(std::vector< std::pair<cond::Time_t,std::string> >::const_iterator it=values.begin(); it!=values.end(); ++it){
00317      std::string payloadClassName = m_iov->dbSession.classNameForItem( it->second );    
00318      iov->add(it->first,it->second,payloadClassName );
00319    }
00320    updateIOV( m_iov->dbSession, iov, m_iov->token );
00321   }
00322 
00323   void 
00324   IOVEditor::bulkAppend(std::vector< cond::IOVElement >& values){
00325     if (values.empty()) return;
00326     if( !m_isLoaded ){
00327       reload();
00328     }
00329     boost::shared_ptr<IOVSequence>& iov = m_iov->data;
00330     cond::Time_t firstTime = values.front().sinceTime();
00331     cond::Time_t   lastTime = values.back().sinceTime();
00332     if(!validTime(firstTime))
00333       reportError("cond::IOVEditor::bulkInsert first time not in global range",firstTime);
00334 
00335     if(!validTime(lastTime))
00336       reportError("cond::IOVEditor::bulkInsert last time not in global range",lastTime);
00337 
00338    if(lastTime>=iov->lastTill() ||
00339       ( !iov->iovs().empty() && firstTime<=iov->iovs().back().sinceTime()) 
00340       )    reportError("cond::IOVEditor::bulkInsert IOV not in range",firstTime);
00341 
00342    for(std::vector< cond::IOVElement >::const_iterator it=values.begin(); it!=values.end(); ++it){
00343      std::string payloadClassName = m_iov->dbSession.classNameForItem( it->token() );     
00344      iov->add(it->sinceTime(),it->token(),payloadClassName );
00345    }
00346 
00347    updateIOV( m_iov->dbSession, iov, m_iov->token );
00348   }
00349 
00350   void 
00351   IOVEditor::stamp( std::string const & icomment, 
00352                     bool append) {
00353     if( !m_isLoaded ){
00354       reload();
00355     }
00356     boost::shared_ptr<IOVSequence>& iov = m_iov->data;
00357     iov->stamp(icomment, append);
00358     updateIOV( m_iov->dbSession, iov, m_iov->token );
00359   }
00360 
00361   void IOVEditor::editMetadata( std::string const & metadata, 
00362                                 bool append ){
00363     if( !m_isLoaded ){
00364       reload();
00365     }
00366     boost::shared_ptr<IOVSequence>& iov = m_iov->data;
00367     iov->updateMetadata( metadata, append);
00368     updateIOV( m_iov->dbSession, iov, m_iov->token );
00369   }
00370 
00371   void IOVEditor::setScope( cond::IOVSequence::ScopeType scope ){
00372     if( !m_isLoaded ){
00373       reload();
00374     }
00375     boost::shared_ptr<IOVSequence>& iov = m_iov->data;
00376     iov->setScope( scope );
00377     updateIOV( m_iov->dbSession, iov, m_iov->token );
00378   }
00379 
00380   void 
00381   IOVEditor::updateClosure( cond::Time_t newtillTime ){
00382     if( m_iov->token.empty() ) reportError("cond::IOVEditor::updateClosure cannot change non-existing IOV index");
00383     if( !m_isLoaded ){
00384       reload();
00385     }
00386     boost::shared_ptr<IOVSequence>& iov = m_iov->data;
00387     iov->updateLastTill(newtillTime);
00388     updateIOV( m_iov->dbSession, iov, m_iov->token );
00389   }
00390   
00391   unsigned int 
00392   IOVEditor::append( cond::Time_t sinceTime,
00393                      const std::string& payloadToken ){
00394     if( m_iov->token.empty() ) {
00395       reportError("cond::IOVEditor::appendIOV cannot append to non-existing IOV index");
00396     }
00397     
00398     if( !m_isLoaded ){
00399       reload();
00400     }
00401     boost::shared_ptr<IOVSequence>& iov = m_iov->data;
00402 
00403     if(!validTime(sinceTime))
00404       reportError("cond::IOVEditor::append time not in global range",sinceTime);  
00405     
00406     if(  !iov->iovs().empty() ){
00407       //range check in case 
00408       cond::Time_t lastValidSince=iov->iovs().back().sinceTime();
00409       if( sinceTime<= lastValidSince){
00410         reportError("IOVEditor::append Error: since time out of range: below last since",sinceTime);
00411       }
00412     }
00413 
00414     // does it make sense? (in case of mixed till and since insertions...)
00415     if (iov->lastTill()<=sinceTime) iov->updateLastTill( timeTypeSpecs[iov->timeType()].endValue );
00416     std::string payloadClassName = m_iov->dbSession.classNameForItem( payloadToken );   
00417     unsigned int ret = iov->add(sinceTime,payloadToken, payloadClassName );
00418     updateIOV( m_iov->dbSession, iov, m_iov->token );
00419     return ret;
00420   }
00421 
00422  
00423   unsigned int 
00424  IOVEditor::freeInsert( cond::Time_t sinceTime ,
00425                         const std::string& payloadToken ){
00426     if( m_iov->token.empty() ) {
00427       reportError("cond::IOVEditor::freeInsert cannot append to non-existing IOV index");
00428     }
00429     
00430     if( !m_isLoaded ){
00431       reload();
00432     }
00433     boost::shared_ptr<IOVSequence>& iov = m_iov->data;
00434     
00435     //   if( m_iov->data->iov.empty() ) reportError("cond::IOVEditor::freeInsert cannot insert  to empty IOV index");
00436     
00437 
00438    if(!validTime(sinceTime))
00439      reportError("cond::IOVEditor::freeInsert time not in global range",sinceTime);
00440 
00441    
00442    // we do not support multiple iov with identical since...
00443    if (m_iov->data->exist(sinceTime))
00444      reportError("cond::IOVEditor::freeInsert sinceTime already existing",sinceTime);
00445 
00446 
00447 
00448      // does it make sense? (in case of mixed till and since insertions...)
00449    if (iov->lastTill()<sinceTime) iov->updateLastTill( timeTypeSpecs[iov->timeType()].endValue );
00450    std::string payloadClassName = m_iov->dbSession.classNameForItem( payloadToken );   
00451    unsigned int ret = iov->add(sinceTime,payloadToken, payloadClassName );
00452    updateIOV( m_iov->dbSession, iov, m_iov->token );
00453    return ret;
00454   }
00455 
00456 
00457   // remove last entry
00458   unsigned int IOVEditor::truncate(bool withPayload) {
00459     if( m_iov->token.empty() ) reportError("cond::IOVEditor::truncate cannot delete to non-existing IOV sequence");
00460     if( !m_isLoaded ){
00461       reload();
00462     }
00463     boost::shared_ptr<IOVSequence>& iov = m_iov->data;
00464     if (iov->piovs().empty()) return 0;
00465     if(withPayload){
00466       std::string tokenStr = iov->piovs().back().token();
00467       m_iov->dbSession.deleteObject( tokenStr );
00468     }
00469     unsigned int ret = iov->truncate();
00470     updateIOV( m_iov->dbSession, iov, m_iov->token );
00471     return ret;
00472     
00473   }
00474 
00475 
00476   void 
00477   IOVEditor::deleteEntries(bool withPayload){
00478     if( m_iov->token.empty() ) reportError("cond::IOVEditor::deleteEntries cannot delete to non-existing IOV sequence");
00479     if( !m_isLoaded ){
00480       reload();
00481     }
00482     boost::shared_ptr<IOVSequence>& iov = m_iov->data;
00483     if(withPayload){
00484       std::string tokenStr;
00485       IOVSequence::const_iterator payloadIt;
00486       IOVSequence::const_iterator payloadItEnd=iov->piovs().end();
00487       for(payloadIt=iov->piovs().begin();payloadIt!=payloadItEnd;++payloadIt){
00488         tokenStr=payloadIt->token();
00489         m_iov->dbSession.deleteObject( tokenStr );
00490       }
00491     }
00492     m_iov->dbSession.deleteObject( m_iov->token );
00493     iov->piovs().clear();
00494   }
00495 
00496   size_t IOVEditor::import( cond::DbSession& sourceSess, 
00497                             const std::string& sourceIovToken ){
00498     boost::shared_ptr<IOVImportIterator> importer = importIterator();
00499     importer->setUp( sourceSess, sourceIovToken );
00500     return importer->importAll();
00501   }
00502     
00503   boost::shared_ptr<IOVImportIterator> 
00504   IOVEditor::importIterator(){
00505     if( !m_isLoaded ){
00506       reload();
00507     }
00508     return boost::shared_ptr<IOVImportIterator>( new IOVImportIterator( m_iov ));                                                
00509   }
00510 
00511   TimeType IOVEditor::timetype() const {
00512     return m_iov->data->timeType();
00513   }
00514 
00515   std::string const & IOVEditor::token() const {
00516     return m_iov->token;
00517   }
00518 
00519   IOVProxy IOVEditor::proxy(){
00520     return IOVProxy( m_iov );
00521   }
00522 
00523 }