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
00016 iov->loadAll();
00017
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
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
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()) ;
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()) {
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
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
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
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
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
00447
00448
00449 if(!validTime(sinceTime))
00450 reportError("cond::IOVEditor::freeInsert time not in global range",sinceTime);
00451
00452
00453
00454 if (m_iov->data->exist(sinceTime))
00455 reportError("cond::IOVEditor::freeInsert sinceTime already existing",sinceTime);
00456
00457
00458
00459
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
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 }