CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/CondCore/ORA/src/ContainerSchema.cc

Go to the documentation of this file.
00001 #include "CondCore/ORA/interface/Configuration.h"
00002 #include "CondCore/ORA/interface/Exception.h"
00003 #include "ContainerSchema.h"
00004 #include "DatabaseSession.h"
00005 #include "IDatabaseSchema.h"
00006 #include "MappingToSchema.h"
00007 #include "MappingDatabase.h"
00008 #include "MappingGenerator.h"
00009 #include "MappingRules.h"
00010 #include "ClassUtils.h"
00011 // externals
00012 #include "RelationalAccess/ISchema.h"
00013 
00014 namespace ora {
00015 
00016   void getTableHierarchyFromMappingElement( const MappingElement& source,
00017                                             std::map<std::string, std::set<std::string> >& tableList ){
00018     const std::string& tableName = source.tableName();
00019     std::map<std::string, std::set<std::string> >::iterator iTab = tableList.find( tableName );
00020     if( iTab ==tableList.end() ){
00021       std::set<std::string> dependencies;
00022       tableList.insert(std::make_pair( tableName, dependencies ) );
00023     }
00024     for( MappingElement::const_iterator iElem = source.begin();
00025          iElem != source.end(); iElem++ ){
00026       std::map<std::string, std::set<std::string> >::iterator iT = tableList.find( tableName );
00027       const std::string& innerTable = iElem->second.tableName();
00028       if( innerTable != tableName ){
00029         iT->second.insert( innerTable );
00030       }
00031       getTableHierarchyFromMappingElement( iElem->second, tableList );
00032     }
00033   }
00034   
00035   //void getTableHierarchyFromMapping( const MappingTree& source,
00036   //                                   std::map<std::string,
00037   //                                   std::set<std::string> >& tableList ){
00038   //  getTableHierarchyFromMappingElement( source.element(), tableList );
00039   //  for( std::map<std::string, MappingElement >::const_iterator iDepEl = source.dependentElements().begin();
00040   //       iDepEl != source.dependentElements().end(); iDepEl++ ){
00041   //    getTableHierarchyFromMappingElement( iDepEl->second, tableList );
00042   //  }
00043   //}
00044 
00045   void addFromTableHierarchy( const std::string& tableName,
00046                               std::map<std::string, std::set<std::string> >& tableList,
00047                               std::vector<std::string>& orderedList ){
00048     orderedList.push_back( tableName );
00049     std::map<std::string, std::set<std::string> >::const_iterator iDeps = tableList.find( tableName );
00050     if(iDeps != tableList.end() ){
00051       for( std::set<std::string>::const_iterator iDt = iDeps->second.begin();
00052            iDt != iDeps->second.end(); iDt++ ){
00053         addFromTableHierarchy( *iDt, tableList, orderedList );
00054       }
00055     }
00056   }
00057 
00058 }
00059 
00060 ora::ContainerSchema::ContainerSchema( int containerId,
00061                                        const std::string& containerName,
00062                                        const Reflex::Type& containerType,
00063                                        DatabaseSession& session ):
00064   m_containerId( containerId ),
00065   m_containerName( containerName ),
00066   m_className( containerType.Name( Reflex::SCOPED ) ),
00067   m_classDict( containerType ),
00068   m_session( session ),
00069   m_loaded( false ),
00070   m_containerSchemaSequences( session.schema() ),
00071   m_mapping(),
00072   m_dependentMappings(){
00073 }
00074 
00075 ora::ContainerSchema::ContainerSchema( int containerId,
00076                                        const std::string& containerName,
00077                                        const std::string& className,
00078                                        DatabaseSession& session ):
00079   m_containerId( containerId ),
00080   m_containerName( containerName ),
00081   m_className( className ),
00082   m_classDict(),
00083   m_session( session ),
00084   m_loaded( false ),
00085   m_containerSchemaSequences( session.schema() ),
00086   m_mapping(),
00087   m_dependentMappings(){
00088 }
00089 
00090 ora::ContainerSchema::~ContainerSchema(){
00091   for( std::map<std::string,MappingTree*>::iterator iDep = m_dependentMappings.begin();
00092        iDep != m_dependentMappings.end(); ++iDep ){
00093     delete iDep->second;
00094   }
00095 }
00096 
00097 void ora::ContainerSchema::initClassDict(){
00098   if( !m_classDict ) m_classDict = ClassUtils::lookupDictionary( m_className, false );
00099   if( !m_classDict ) throwException("Container class \""+m_className+"\" has not been found in the dictionary.",
00100                                     "ContainerSchema::initClassDict");
00101 }
00102 
00103 void ora::ContainerSchema::create(){
00104 
00105   initClassDict();
00106   std::string newMappingVersion = m_session.mappingDatabase().newMappingVersionForContainer( m_containerName );
00107   MappingGenerator mapGen( m_session.schema().storageSchema() );
00108   mapGen.createNewMapping( m_containerName, m_classDict, m_mapping );
00109   //if(!mapGen.createNewMapping( m_containerName, m_classDict, m_mapping )){
00110   //  throwException("Mapping generation failed.",
00111   //                 "ContainerSchema::create");
00112   //}
00113   m_mapping.setVersion( newMappingVersion );
00114   m_session.mappingDatabase().storeMapping( m_mapping );
00115   m_session.mappingDatabase().insertClassVersion( m_classDict, 0, m_containerId, newMappingVersion, true );
00116   MappingToSchema mapping2Schema( m_session.schema().storageSchema() );
00117   m_mapping.tables();
00118   mapping2Schema.create(  m_mapping );
00119   m_loaded = true;
00120 }
00121 
00122 void ora::ContainerSchema::drop(){
00123 
00124   std::set<std::string> containerMappingVersions;
00125   if( m_session.mappingDatabase().getMappingVersionsForContainer( m_containerId, containerMappingVersions )){
00126     std::map< std::string, std::set<std::string> > tableHierarchy;
00127     std::set<std::string> topLevelTables; // should be strictly only one!
00128     for( std::set<std::string>::const_iterator iV = containerMappingVersions.begin();
00129          iV!= containerMappingVersions.end(); ++iV ){
00130       MappingTree mapping;
00131       if( m_session.mappingDatabase().getMappingByVersion( *iV, mapping ) ){
00132         topLevelTables.insert( mapping.topElement().tableName() );
00133         getTableHierarchyFromMappingElement( mapping.topElement(), tableHierarchy );
00134         m_containerSchemaSequences.erase( MappingRules::sequenceNameForDependentClass( m_containerName, mapping.className()));
00135       }
00136     }
00137 
00138     std::vector<std::string> orderedTableList;
00139     for(std::set<std::string>::const_iterator iMainT = topLevelTables.begin();
00140         iMainT != topLevelTables.end(); ++iMainT ){
00141       addFromTableHierarchy( *iMainT, tableHierarchy, orderedTableList );
00142     }
00143     for(std::vector<std::string>::reverse_iterator iTable = orderedTableList.rbegin();
00144         iTable != orderedTableList.rend(); iTable++ ){
00145       m_session.schema().storageSchema().dropIfExistsTable( *iTable );
00146     }
00147   }
00148   for( std::set<std::string>::const_iterator iM = containerMappingVersions.begin();
00149        iM != containerMappingVersions.end(); ++iM ){
00150     m_session.mappingDatabase().removeMapping( *iM );
00151   }
00152   m_containerSchemaSequences.erase( MappingRules::sequenceNameForContainer( m_containerName ));
00153 
00154 }
00155 
00156 void ora::ContainerSchema::evolve(){
00157   MappingGenerator mapGen( m_session.schema().storageSchema() );
00158   // retrieve the base mapping
00159   MappingTree baseMapping;
00160   if( !m_session.mappingDatabase().getBaseMappingForContainer( m_classDict.Name(Reflex::SCOPED), m_containerId, baseMapping )){
00161     throwException("Base mapping has not been found in the database.",
00162                    "ContainerSchema::evolve");
00163   }
00164   mapGen.createNewMapping( m_containerName, m_classDict, baseMapping,  m_mapping );
00165   std::string newMappingVersion = m_session.mappingDatabase().newMappingVersionForContainer( m_containerName );
00166   m_mapping.setVersion( newMappingVersion );
00167   m_session.mappingDatabase().storeMapping( m_mapping );
00168   m_session.mappingDatabase().insertClassVersion( m_classDict, 0, m_containerId, newMappingVersion );
00169   MappingToSchema mapping2Schema( m_session.schema().storageSchema() );
00170   mapping2Schema.alter(  m_mapping  );
00171   m_loaded = true;
00172 }
00173 
00174 void ora::ContainerSchema::evolve( const Reflex::Type& dependentClass, MappingTree& baseMapping ){
00175   std::string className = dependentClass.Name(Reflex::SCOPED);
00176   MappingGenerator mapGen( m_session.schema().storageSchema() );
00177   std::map<std::string,MappingTree*>::iterator iDep =
00178     m_dependentMappings.insert( std::make_pair( className, new MappingTree ) ).first;
00179   if( baseMapping.className() != dependentClass.Name(Reflex::SCOPED) ){
00180     throwException("Provided base mapping does not map class \""+dependentClass.Name(Reflex::SCOPED)+"\".",
00181                    "ContainerSchema::evolve");    
00182   }
00183   mapGen.createNewDependentMapping( dependentClass, m_mapping, baseMapping, *iDep->second );
00184   std::string newMappingVersion = m_session.mappingDatabase().newMappingVersionForContainer( m_containerName );
00185   iDep->second->setVersion( newMappingVersion );
00186   m_session.mappingDatabase().storeMapping( *iDep->second );
00187   m_session.mappingDatabase().insertClassVersion( dependentClass, 1, m_containerId, newMappingVersion, false );
00188 }
00189 
00190 const Reflex::Type& ora::ContainerSchema::type(){
00191   return m_classDict;
00192 }
00193 
00194 ora::MappingTree& ora::ContainerSchema::mapping( bool writeEnabled ){
00195   initClassDict();
00196   if(!m_loaded ){
00197     if( !m_session.mappingDatabase().getMappingForContainer( m_classDict, m_containerId, m_mapping ) ){
00198       // if enabled, invoke the evolution
00199       if( writeEnabled && m_session.configuration().properties().getFlag( Configuration::automaticSchemaEvolution() )){
00200         evolve();
00201       }
00202     } else {
00203       m_loaded = true;
00204     }
00205     
00206   }
00207   if( m_mapping.topElement().find( m_className )==m_mapping.topElement().end() ){
00208     throwException( "Mapping for container class \""+m_className+"\" could not be loaded.",
00209                     "ContainerSchema::mapping");
00210   }
00211   return m_mapping;
00212 }
00213 
00214 bool ora::ContainerSchema::loadMappingForDependentClass( const Reflex::Type& dependentClassDict ){
00215   if( !dependentClassDict ) throwException("The dependent class has not been found in the dictionary.",
00216                                     "ContainerSchema::loadMappingForDependentClass");
00217   std::string className = dependentClassDict.Name(Reflex::SCOPED);
00218   std::map<std::string,MappingTree*>::iterator iDep = m_dependentMappings.find( className );
00219   if( iDep ==  m_dependentMappings.end() ){
00220     // not in cache, search the database...
00221     iDep = m_dependentMappings.insert( std::make_pair( className, new MappingTree ) ).first;
00222     if( ! m_session.mappingDatabase().getMappingForContainer( dependentClassDict, m_containerId, *iDep->second ) ){
00223       m_dependentMappings.erase( className );
00224       return false;
00225     }
00226   }
00227   return true;  
00228 }
00229 
00230 void ora::ContainerSchema::create( const Reflex::Type& dependentClassDict ){
00231   std::string className = dependentClassDict.Name(Reflex::SCOPED);
00232   std::map<std::string,MappingTree*>::iterator iDep =
00233     m_dependentMappings.insert( std::make_pair( className, new MappingTree ) ).first;
00234   MappingGenerator mapGen( m_session.schema().storageSchema() );
00235   MappingToSchema mapping2Schema( m_session.schema().storageSchema() );
00236   mapGen.createNewDependentMapping( dependentClassDict, m_mapping, *iDep->second );
00237   mapping2Schema.create(  *iDep->second  );
00238   std::string newMappingVersion = m_session.mappingDatabase().newMappingVersionForContainer( m_containerName );
00239   iDep->second->setVersion( newMappingVersion );
00240   m_session.mappingDatabase().storeMapping( *iDep->second );
00241   m_session.mappingDatabase().insertClassVersion( dependentClassDict, 1, m_containerId, newMappingVersion, true );
00242 }
00243 
00244 void ora::ContainerSchema::extend( const Reflex::Type& dependentClassDict ){
00245   std::string className = dependentClassDict.Name(Reflex::SCOPED);
00246   MappingTree baseMapping;
00247   if( !m_session.mappingDatabase().getBaseMappingForContainer( className,
00248                                                                m_containerId, baseMapping ) ){
00249     create( dependentClassDict );
00250   } else {
00251     evolve( dependentClassDict, baseMapping );
00252   }
00253 }
00254 
00255 bool ora::ContainerSchema::extendIfRequired( const Reflex::Type& dependentClassDict ){
00256   bool ret = false;
00257   if( ! loadMappingForDependentClass( dependentClassDict ) ){
00258     extend( dependentClassDict );
00259     ret = true;
00260   }
00261   return ret;
00262 }
00263 
00264 ora::MappingElement& ora::ContainerSchema::mappingForDependentClass( const Reflex::Type& dependentClassDict,
00265                                                                      bool writeEnabled ){
00266   std::string className = dependentClassDict.Name(Reflex::SCOPED);
00267   if( ! loadMappingForDependentClass( dependentClassDict ) ){
00268     if( writeEnabled ){
00269       // check if a base is available:
00270       MappingTree baseMapping;
00271       if( !m_session.mappingDatabase().getBaseMappingForContainer( className,
00272                                                                    m_containerId, baseMapping ) ){
00273         // mapping has to be generated from scratch
00274         if( m_session.configuration().properties().getFlag( Configuration::automaticDatabaseCreation()) ||
00275             m_session.configuration().properties().getFlag( Configuration::automaticContainerCreation() ) ){
00276           create( dependentClassDict );
00277         }
00278       } else {
00279         // evolve if allowed
00280         if( m_session.configuration().properties().getFlag( Configuration::automaticSchemaEvolution() )){
00281           evolve( dependentClassDict, baseMapping );
00282         }
00283       }
00284     }
00285   }
00286   std::map<std::string,MappingTree*>::iterator iDep = m_dependentMappings.find( className );
00287   if( iDep ==  m_dependentMappings.end() ){
00288     throwException( "Mapping for class \""+ className + "\" is not available in the database.",
00289                     "ContainerSchema::mappingForDependentClass");
00290   }
00291   return iDep->second->topElement();
00292 }
00293 
00294 bool ora::ContainerSchema::mappingForDependentClasses( std::vector<ora::MappingElement>& destination ){
00295   return m_session.mappingDatabase().getDependentMappingsForContainer( m_containerId, destination );
00296 }
00297 
00298 ora::Sequences& ora::ContainerSchema::containerSequences(){
00299   return m_containerSchemaSequences;
00300 }
00301 
00302 ora::IBlobStreamingService* ora::ContainerSchema::blobStreamingService(){
00303   return m_session.configuration().blobStreamingService();
00304 }
00305 
00306 ora::IReferenceHandler* ora::ContainerSchema::referenceHandler(){
00307   return m_session.configuration().referenceHandler();
00308 }
00309   
00310 const std::string& ora::ContainerSchema::mappingVersion(){
00311   return m_mapping.version();
00312 }
00313 
00314 int ora::ContainerSchema::containerId(){
00315   return m_containerId;
00316 }
00317 
00318 const std::string&  ora::ContainerSchema::containerName(){
00319   return m_containerName;
00320 }
00321 
00322 const std::string&  ora::ContainerSchema::className(){
00323   return m_className;
00324 }
00325 
00326 coral::ISchema& ora::ContainerSchema::storageSchema(){
00327   return m_session.schema().storageSchema();
00328 }
00329 
00330 ora::DatabaseSession& ora::ContainerSchema::dbSession(){
00331   return m_session;
00332 }
00333 
00334 
00335