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 Sequences containerSchemaSequences( m_session.schema() );
00061 Handle<ora::DatabaseContainer> cont = sourceSession.containerHandle( containerName );
00062
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
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
00094 containerSchemaSequences.create( MappingRules::sequenceNameForContainer( containerName ));
00095
00096 mapping2Schema.create( baseMapping );
00097
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
00126 containerSchemaSequences.create( MappingRules::sequenceNameForDependentClass( containerName, *iCl ));
00127
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
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
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
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