CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/CondCore/ORA/src/DatabaseUtilitySession.cc

Go to the documentation of this file.
00001 #include "CondCore/ORA/interface/Exception.h"
00002 #include "DatabaseUtilitySession.h"
00003 #include "DatabaseSession.h"
00004 #include "DatabaseContainer.h"
00005 #include "MappingRules.h"
00006 #include "MappingDatabase.h"
00007 #include "MappingToSchema.h"
00008 #include "IDatabaseSchema.h"
00009 #include "MappingTree.h"
00010 // externals
00011 #include "Reflex/Type.h"
00012 
00013 ora::DatabaseUtilitySession::DatabaseUtilitySession(  DatabaseSession& dbSession ):
00014   m_session( dbSession ){
00015 }
00016 
00017 ora::DatabaseUtilitySession::~DatabaseUtilitySession(){
00018 }
00019 
00020 std::set<std::string> ora::DatabaseUtilitySession::listMappingVersions( int containerId ){
00021   std::set<std::string> mappingList;
00022   m_session.mappingDatabase().getMappingVersionsForContainer( containerId, mappingList );
00023   return mappingList;
00024 }
00025 
00026 std::map<std::string,std::string> ora::DatabaseUtilitySession::listMappings( int containerId ){
00027   std::map<std::string,std::string> versionMap;
00028   m_session.mappingDatabase().getClassVersionListForContainer( containerId, versionMap );
00029   return versionMap;
00030 }
00031 
00032 bool ora::DatabaseUtilitySession::dumpMapping( const std::string& mappingVersion,
00033                                                std::ostream& outputStream ){
00034   MappingTree dest;
00035   if(m_session.mappingDatabase().getMappingByVersion( mappingVersion, dest )){
00036     dest.printXML( outputStream );
00037     return true;
00038   }
00039   return false;
00040 }
00041 
00042 ora::Handle<ora::DatabaseContainer> ora::DatabaseUtilitySession::importContainerSchema( const std::string& containerName,
00043                                                                                         DatabaseSession& sourceSession){
00044   if(!m_session.exists()){
00045     if( m_session.configuration().properties().getFlag( Configuration::automaticDatabaseCreation() )){
00046       m_session.create();
00047       m_session.open();
00048     } else {
00049       throwException( "ORA Database not found in \""+m_session.connectionString()+"\".",
00050                       "DatabaseUtilitySession::importContainerSchema");      
00051     }
00052   } else {
00053     m_session.open();
00054     if( existsContainer( containerName ) ){
00055       throwException( "A Container named \""+containerName+"\" already exists in the database.",
00056                       "DatabaseUtilitySession::importContainerSchema" );
00057     }
00058   }
00059   sourceSession.open();
00060   Sequences containerSchemaSequences( m_session.schema() );
00061   Handle<ora::DatabaseContainer> cont = sourceSession.containerHandle( containerName );
00062   // first create the container locally:
00063   Handle<ora::DatabaseContainer> newCont = m_session.addContainer( containerName, cont->className() );
00064   cont->className();
00065   MappingToSchema mapping2Schema( m_session.schema().storageSchema() );
00066   std::set<std::string> existingVersions = m_session.mappingDatabase().versions();
00067   std::set<std::string> baseVersions;
00068   // first create the cont base schema
00069   MappingTree baseMapping;
00070   if(!sourceSession.mappingDatabase().getBaseMappingForContainer( cont->className(), cont->id(), baseMapping )){
00071     throwException( "Base mapping for class \""+cont->className()+"\" has not been found in the database.",
00072                     "DatabaseUtilitySession::importContainerSchema");
00073   }
00074   std::set<std::string> classVersions;
00075   if(!sourceSession.mappingDatabase().getClassVersionListForMappingVersion( baseMapping.version(), classVersions )){
00076     throwException( "No class versions found for mapping \""+baseMapping.version()+"\".",
00077                     "DatabaseUtilitySession::importContainerSchema");
00078   }
00079   if( existingVersions.find( baseMapping.version() )!= existingVersions.end() ){
00080     throwException("Mapping version \""+baseMapping.version()+"\" for base mapping of class \""+cont->className()+"\" already exists in the database.","DatabaseUtilitySession::importContainerSchema");
00081   }
00082   if( !mapping2Schema.check( baseMapping ) ){
00083     throwException("Schema base for class \""+baseMapping.className()+"\" cannot be replicated, because some schema objects have been found with the same name.","DatabaseUtilitySession::importContainerSchema");    
00084   }
00085   baseVersions.insert( baseMapping.version() );
00086   existingVersions.insert( baseMapping.version() );
00087   m_session.mappingDatabase().storeMapping( baseMapping );
00088   bool first = true;
00089   for( std::set<std::string>::const_iterator iCv = classVersions.begin(); iCv != classVersions.end(); ++iCv ){
00090     m_session.mappingDatabase().insertClassVersion( cont->className(), *iCv , 0, newCont->id(), baseMapping.version(), first );
00091     first = false;
00092   }
00093   // ...the main container sequence...
00094   containerSchemaSequences.create( MappingRules::sequenceNameForContainer( containerName )); 
00095   // ...the main tables
00096   mapping2Schema.create( baseMapping );
00097   // second create the base dependencies if any
00098   std::set<std::string> dependentClasses;
00099   sourceSession.mappingDatabase().getDependentClassesForContainer( cont->id(), dependentClasses );
00100   for( std::set<std::string>::const_iterator iCl = dependentClasses.begin(); iCl != dependentClasses.end(); ++iCl ){
00101     MappingTree baseDepMapping;
00102     if(!sourceSession.mappingDatabase().getBaseMappingForContainer( *iCl, cont->id(), baseDepMapping )){
00103       throwException( "Base mapping for class \""+*iCl+"\" has not been found in the database.",
00104                     "DatabaseUtilitySession::importContainerSchema");      
00105     }
00106     std::set<std::string> depClassVersions;
00107     if(!sourceSession.mappingDatabase().getClassVersionListForMappingVersion( baseDepMapping.version(), depClassVersions )){
00108       throwException( "No class versions found for mapping \""+baseDepMapping.version()+"\".",
00109                       "DatabaseUtilitySession::importContainerSchema");
00110     }
00111     if( existingVersions.find( baseDepMapping.version() )!= existingVersions.end() ){
00112       throwException("Mapping version \""+baseDepMapping.version()+"\" for base mapping of class \""+*iCl+"\" already exists in the database.","DatabaseUtilitySession::importContainerSchema");
00113     }
00114     if( !mapping2Schema.check( baseDepMapping ) ){
00115       throwException("Schema base for class \""+baseDepMapping.className()+"\" cannot be replicated, because some schema objects have been found with the same name.","DatabaseUtilitySession::importContainerSchema");
00116     }
00117     baseVersions.insert( baseDepMapping.version() );
00118     existingVersions.insert( baseDepMapping.version() );
00119     m_session.mappingDatabase().storeMapping( baseDepMapping );
00120     first = true;
00121     for( std::set<std::string>::const_iterator iCv = depClassVersions.begin(); iCv != depClassVersions.end(); ++iCv ){
00122       m_session.mappingDatabase().insertClassVersion( *iCl, *iCv , 1, newCont->id(), baseDepMapping.version(), first );
00123       first = false;
00124     }
00125     // create the dep classes sequences. 
00126     containerSchemaSequences.create( MappingRules::sequenceNameForDependentClass( containerName, *iCl ));
00127     // create the dep tables
00128     mapping2Schema.create( baseDepMapping );
00129   }
00131   std::set<std::string> allVersions;
00132   if(!sourceSession.mappingDatabase().getMappingVersionsForContainer( cont->id(), allVersions )){
00133     std::stringstream mess;
00134     mess << "No mapping versions found for container id="<<cont->id();
00135     throwException( mess.str(), "DatabaseUtilitySession::importContainerSchema");
00136   }
00137   for( std::set<std::string>::const_iterator iVer = allVersions.begin(); iVer != allVersions.end(); ++iVer ){
00138     // skip the bases
00139     if( baseVersions.find( *iVer )== baseVersions.end() ){
00140       MappingTree evMapping;
00141       if(!sourceSession.mappingDatabase().getMappingByVersion( *iVer, evMapping) ){
00142         throwException("Mapping version \""+*iVer+"\" has not been found in the database.",
00143                        "DatabaseUtilitySession::importContainerSchema");
00144       }
00145       std::set<std::string> cvs;
00146       if(!sourceSession.mappingDatabase().getClassVersionListForMappingVersion( evMapping.version(), cvs )){
00147         throwException( "No class versions found for mapping \""+evMapping.version()+"\".",
00148                         "DatabaseUtilitySession::importContainerSchema");
00149       }
00150       if( existingVersions.find( *iVer )!= existingVersions.end() ){
00151         throwException("Mapping version \""+*iVer+"\" for mapping of class \""+evMapping.className()+"\" already exists in the database.","DatabaseUtilitySession::importContainerSchema");
00152       }
00153       if( !mapping2Schema.check( evMapping ) ){
00154         throwException("Evolved schema for class \""+evMapping.className()+"\" cannot be replicated, because some schema objects have been found with the same name.","DatabaseUtilitySession::importContainerSchema");
00155       }
00156       m_session.mappingDatabase().storeMapping( evMapping );
00157       existingVersions.insert( evMapping.version() );
00158       int depIndex = 0;
00159       std::string className = evMapping.className();
00160       if( evMapping.className() != baseMapping.className() ){
00161         // dependencies
00162         depIndex = 1;
00163       }
00164       for( std::set<std::string>::const_iterator iCv = cvs.begin(); iCv != cvs.end(); ++iCv ){
00165         m_session.mappingDatabase().insertClassVersion( evMapping.className(), *iCv , depIndex, newCont->id(), evMapping.version() );
00166       }
00167       // then evolve the schema
00168       mapping2Schema.alter( evMapping );
00169     }
00170   }
00171   return newCont;
00172 }
00173 
00174 void ora::DatabaseUtilitySession::importContainerSchema( const std::string& sourceConnectionString,
00175                                                          const std::string& containerName ){
00176   DatabaseSession sourceSession( m_session.connectionPool() );
00177   sourceSession.connect(sourceConnectionString, true );
00178   sourceSession.startTransaction( true );
00179   importContainerSchema(containerName, sourceSession );
00180   sourceSession.commitTransaction();
00181 }
00182 
00183 
00184 bool ora::DatabaseUtilitySession::existsContainer( const std::string& containerName ){
00185   bool found = false;
00186   for( std::map<int, Handle<DatabaseContainer> >::const_iterator iC = m_session.containers().begin();
00187        iC != m_session.containers().end(); ++iC ){
00188     if( iC->second->name() == containerName ) {
00189       found = true;
00190       break;
00191     }
00192   }
00193   return found;
00194 }
00195 
00196 void ora::DatabaseUtilitySession::importContainer( const std::string& sourceConnectionString,
00197                                                    const std::string& containerName ){
00198   DatabaseSession sourceSession( m_session.connectionPool() );
00199   sourceSession.connect(sourceConnectionString, true );
00200   sourceSession.startTransaction( true );
00201   Handle<ora::DatabaseContainer> newCont = importContainerSchema(containerName, sourceSession );
00202   Handle<ora::DatabaseContainer> cont = sourceSession.containerHandle( containerName );
00203   Handle<IteratorBuffer> iterator = cont->iteratorBuffer();
00204   std::vector<void*> objects;
00205   const Reflex::Type& contType = cont->type();
00206   while( iterator->next() ){
00207     void* data = iterator->getItem();
00208     objects.push_back( data );
00209     newCont->insertItem( data, contType );
00210   }
00211   newCont->flush();
00212   for( std::vector<void*>::const_iterator iO = objects.begin(); iO != objects.end(); iO++ ){
00213     contType.Destruct( *iO );
00214   }
00215   sourceSession.commitTransaction();
00216 }
00217 
00218 void ora::DatabaseUtilitySession::eraseMapping( const std::string& mappingVersion ){
00219   if( !m_session.exists() ){
00220     throwException( "ORA Database not found in \""+m_session.connectionString()+"\".",
00221                     "DatabaseUtilitySession::eraseMapping");      
00222 
00223   }
00224   m_session.mappingDatabase().removeMapping( mappingVersion );
00225 }
00226 
00227 ora::Handle<ora::DatabaseContainer> ora::DatabaseUtilitySession::containerHandle( const std::string& name ){
00228   if( !m_session.exists() ){
00229     throwException( "ORA Database not found in \""+m_session.connectionString()+"\".",
00230                     "DatabaseUtilitySession::containerHandle");      
00231 
00232   }
00233   m_session.open();
00234   return m_session.containerHandle( name );
00235 }
00236