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
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 Handle<ora::DatabaseContainer> cont = sourceSession.containerHandle( containerName );
00061
00062 Handle<ora::DatabaseContainer> newCont = m_session.addContainer( containerName, cont->className() );
00063 cont->className();
00064 MappingToSchema mapping2Schema( m_session.schema().storageSchema() );
00065 std::set<std::string> existingVersions = m_session.mappingDatabase().versions();
00066 std::set<std::string> baseVersions;
00067
00068 MappingTree baseMapping;
00069 if(!sourceSession.mappingDatabase().getBaseMappingForContainer( cont->className(), cont->id(), baseMapping )){
00070 throwException( "Base mapping for class \""+cont->className()+"\" has not been found in the database.",
00071 "DatabaseUtilitySession::importContainerSchema");
00072 }
00073 std::set<std::string> classVersions;
00074 if(!sourceSession.mappingDatabase().getClassVersionListForMappingVersion( baseMapping.version(), classVersions )){
00075 throwException( "No class versions found for mapping \""+baseMapping.version()+"\".",
00076 "DatabaseUtilitySession::importContainerSchema");
00077 }
00078 if( existingVersions.find( baseMapping.version() )!= existingVersions.end() ){
00079 throwException("Mapping version \""+baseMapping.version()+"\" for base mapping of class \""+cont->className()+"\" already exists in the database.","DatabaseUtilitySession::importContainerSchema");
00080 }
00081 if( !mapping2Schema.check( baseMapping ) ){
00082 throwException("Schema base for class \""+baseMapping.className()+"\" cannot be replicated, because some schema objects have been found with the same name.","DatabaseUtilitySession::importContainerSchema");
00083 }
00084 baseVersions.insert( baseMapping.version() );
00085 existingVersions.insert( baseMapping.version() );
00086 m_session.mappingDatabase().storeMapping( baseMapping );
00087 bool first = true;
00088 for( std::set<std::string>::const_iterator iCv = classVersions.begin(); iCv != classVersions.end(); ++iCv ){
00089 m_session.mappingDatabase().insertClassVersion( cont->className(), *iCv , 0, newCont->id(), baseMapping.version(), first );
00090 first = false;
00091 }
00092 mapping2Schema.create( baseMapping );
00093
00094 std::set<std::string> dependentClasses;
00095 sourceSession.mappingDatabase().getDependentClassesForContainer( cont->id(), dependentClasses );
00096 for( std::set<std::string>::const_iterator iCl = dependentClasses.begin(); iCl != dependentClasses.end(); ++iCl ){
00097 MappingTree baseDepMapping;
00098 if(!sourceSession.mappingDatabase().getBaseMappingForContainer( *iCl, cont->id(), baseDepMapping )){
00099 throwException( "Base mapping for class \""+*iCl+"\" has not been found in the database.",
00100 "DatabaseUtilitySession::importContainerSchema");
00101 }
00102 std::set<std::string> depClassVersions;
00103 if(!sourceSession.mappingDatabase().getClassVersionListForMappingVersion( baseDepMapping.version(), depClassVersions )){
00104 throwException( "No class versions found for mapping \""+baseDepMapping.version()+"\".",
00105 "DatabaseUtilitySession::importContainerSchema");
00106 }
00107 if( existingVersions.find( baseDepMapping.version() )!= existingVersions.end() ){
00108 throwException("Mapping version \""+baseDepMapping.version()+"\" for base mapping of class \""+*iCl+"\" already exists in the database.","DatabaseUtilitySession::importContainerSchema");
00109 }
00110 if( !mapping2Schema.check( baseDepMapping ) ){
00111 throwException("Schema base for class \""+baseDepMapping.className()+"\" cannot be replicated, because some schema objects have been found with the same name.","DatabaseUtilitySession::importContainerSchema");
00112 }
00113 baseVersions.insert( baseDepMapping.version() );
00114 existingVersions.insert( baseDepMapping.version() );
00115 m_session.mappingDatabase().storeMapping( baseDepMapping );
00116 first = true;
00117 for( std::set<std::string>::const_iterator iCv = depClassVersions.begin(); iCv != depClassVersions.end(); ++iCv ){
00118 m_session.mappingDatabase().insertClassVersion( *iCl, *iCv , 1, newCont->id(), baseDepMapping.version(), first );
00119 first = false;
00120 }
00121 mapping2Schema.create( baseDepMapping );
00122 }
00124 std::set<std::string> allVersions;
00125 if(!sourceSession.mappingDatabase().getMappingVersionsForContainer( cont->id(), allVersions )){
00126 std::stringstream mess;
00127 mess << "No mapping versions found for container id="<<cont->id();
00128 throwException( mess.str(), "DatabaseUtilitySession::importContainerSchema");
00129 }
00130 for( std::set<std::string>::const_iterator iVer = allVersions.begin(); iVer != allVersions.end(); ++iVer ){
00131
00132 if( baseVersions.find( *iVer )== baseVersions.end() ){
00133 MappingTree evMapping;
00134 if(!sourceSession.mappingDatabase().getMappingByVersion( *iVer, evMapping) ){
00135 throwException("Mapping version \""+*iVer+"\" has not been found in the database.",
00136 "DatabaseUtilitySession::importContainerSchema");
00137 }
00138 std::set<std::string> cvs;
00139 if(!sourceSession.mappingDatabase().getClassVersionListForMappingVersion( evMapping.version(), cvs )){
00140 throwException( "No class versions found for mapping \""+evMapping.version()+"\".",
00141 "DatabaseUtilitySession::importContainerSchema");
00142 }
00143 if( existingVersions.find( *iVer )!= existingVersions.end() ){
00144 throwException("Mapping version \""+*iVer+"\" for mapping of class \""+evMapping.className()+"\" already exists in the database.","DatabaseUtilitySession::importContainerSchema");
00145 }
00146 if( !mapping2Schema.check( evMapping ) ){
00147 throwException("Evolved schema for class \""+evMapping.className()+"\" cannot be replicated, because some schema objects have been found with the same name.","DatabaseUtilitySession::importContainerSchema");
00148 }
00149 m_session.mappingDatabase().storeMapping( evMapping );
00150 existingVersions.insert( evMapping.version() );
00151 int depIndex = 0;
00152 std::string className = evMapping.className();
00153 if( evMapping.className() != baseMapping.className() ){
00154
00155 depIndex = 1;
00156 }
00157 for( std::set<std::string>::const_iterator iCv = cvs.begin(); iCv != cvs.end(); ++iCv ){
00158 m_session.mappingDatabase().insertClassVersion( evMapping.className(), *iCv , depIndex, newCont->id(), evMapping.version() );
00159 }
00160
00161 mapping2Schema.alter( evMapping );
00162 }
00163 }
00164 return newCont;
00165 }
00166
00167 void ora::DatabaseUtilitySession::importContainerSchema( const std::string& sourceConnectionString,
00168 const std::string& containerName ){
00169 DatabaseSession sourceSession( m_session.connectionPool() );
00170 sourceSession.connect(sourceConnectionString, true );
00171 sourceSession.startTransaction( true );
00172 importContainerSchema(containerName, sourceSession );
00173 sourceSession.commitTransaction();
00174 }
00175
00176
00177 bool ora::DatabaseUtilitySession::existsContainer( const std::string& containerName ){
00178 bool found = false;
00179 for( std::map<int, Handle<DatabaseContainer> >::const_iterator iC = m_session.containers().begin();
00180 iC != m_session.containers().end(); ++iC ){
00181 if( iC->second->name() == containerName ) {
00182 found = true;
00183 break;
00184 }
00185 }
00186 return found;
00187 }
00188
00189 void ora::DatabaseUtilitySession::importContainer( const std::string& sourceConnectionString,
00190 const std::string& containerName ){
00191 DatabaseSession sourceSession( m_session.connectionPool() );
00192 sourceSession.connect(sourceConnectionString, true );
00193 sourceSession.startTransaction( true );
00194 Handle<ora::DatabaseContainer> newCont = importContainerSchema(containerName, sourceSession );
00195 Handle<ora::DatabaseContainer> cont = sourceSession.containerHandle( containerName );
00196 Handle<IteratorBuffer> iterator = cont->iteratorBuffer();
00197 std::vector<void*> objects;
00198 const Reflex::Type& contType = cont->type();
00199 while( iterator->next() ){
00200 void* data = iterator->getItem();
00201 objects.push_back( data );
00202 newCont->insertItem( data, contType );
00203 }
00204 newCont->flush();
00205 for( std::vector<void*>::const_iterator iO = objects.begin(); iO != objects.end(); iO++ ){
00206 contType.Destruct( *iO );
00207 }
00208 sourceSession.commitTransaction();
00209 }
00210
00211 void ora::DatabaseUtilitySession::eraseMapping( const std::string& mappingVersion ){
00212 if( !m_session.exists() ){
00213 throwException( "ORA Database not found in \""+m_session.connectionString()+"\".",
00214 "DatabaseUtilitySession::eraseMapping");
00215
00216 }
00217 m_session.mappingDatabase().removeMapping( mappingVersion );
00218 }
00219
00220 ora::Handle<ora::DatabaseContainer> ora::DatabaseUtilitySession::containerHandle( const std::string& name ){
00221 if( !m_session.exists() ){
00222 throwException( "ORA Database not found in \""+m_session.connectionString()+"\".",
00223 "DatabaseUtilitySession::containerHandle");
00224
00225 }
00226 m_session.open();
00227 return m_session.containerHandle( name );
00228 }
00229