CMS 3D CMS Logo

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