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 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()) {
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
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
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
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
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
00436
00437
00438 if(!validTime(sinceTime))
00439 reportError("cond::IOVEditor::freeInsert time not in global range",sinceTime);
00440
00441
00442
00443 if (m_iov->data->exist(sinceTime))
00444 reportError("cond::IOVEditor::freeInsert sinceTime already existing",sinceTime);
00445
00446
00447
00448
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
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 }