CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/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 addFromTableHierarchy( const std::string& tableName,
00036                               std::map<std::string, std::set<std::string> >& tableList,
00037                               std::vector<std::string>& orderedList ){
00038     orderedList.push_back( tableName );
00039     std::map<std::string, std::set<std::string> >::const_iterator iDeps = tableList.find( tableName );
00040     if(iDeps != tableList.end() ){
00041       for( std::set<std::string>::const_iterator iDt = iDeps->second.begin();
00042            iDt != iDeps->second.end(); iDt++ ){
00043         addFromTableHierarchy( *iDt, tableList, orderedList );
00044       }
00045     }
00046   }
00047 
00048 }
00049 
00050 ora::ContainerSchema::ContainerSchema( int containerId,
00051                                        const std::string& containerName,
00052                                        const Reflex::Type& containerType,
00053                                        DatabaseSession& session ):
00054   m_containerId( containerId ),
00055   m_containerName( containerName ),
00056   m_className( containerType.Name( Reflex::SCOPED ) ),
00057   m_classDict( containerType ),
00058   m_session( session ),
00059   m_loaded( false ),
00060   m_containerSchemaSequences( session.schema() ),
00061   m_mapping(),
00062   m_dependentMappings(){
00063 }
00064 
00065 ora::ContainerSchema::ContainerSchema( int containerId,
00066                                        const std::string& containerName,
00067                                        const std::string& className,
00068                                        DatabaseSession& session ):
00069   m_containerId( containerId ),
00070   m_containerName( containerName ),
00071   m_className( className ),
00072   m_classDict(),
00073   m_session( session ),
00074   m_loaded( false ),
00075   m_containerSchemaSequences( session.schema() ),
00076   m_mapping(),
00077   m_dependentMappings(){
00078 }
00079 
00080 ora::ContainerSchema::~ContainerSchema(){
00081   for( std::map<std::string,MappingTree*>::iterator iDep = m_dependentMappings.begin();
00082        iDep != m_dependentMappings.end(); ++iDep ){
00083     delete iDep->second;
00084   }
00085 }
00086 
00087 void ora::ContainerSchema::initClassDict(){
00088   if( !m_classDict ) m_classDict = ClassUtils::lookupDictionary( m_className, false );
00089   if( !m_classDict ) throwException("Container class \""+m_className+"\" has not been found in the dictionary.",
00090                                     "ContainerSchema::initClassDict");
00091 }
00092 
00093 void ora::ContainerSchema::create(){
00094 
00095   initClassDict();
00096   // adding the new entry in the container table
00097   m_session.schema().containerHeaderTable().addContainer( m_containerId, m_containerName, m_className );
00098  
00099   // creating and storing the mapping
00100   std::string newMappingVersion = m_session.mappingDatabase().newMappingVersionForContainer( m_containerName );
00101   MappingGenerator mapGen( m_session.schema().storageSchema() );
00102   mapGen.createNewMapping( m_containerName, m_classDict, m_mapping );
00103   m_mapping.setVersion( newMappingVersion );
00104   m_session.mappingDatabase().storeMapping( m_mapping );
00105   m_session.mappingDatabase().insertClassVersion( m_classDict, 0, m_containerId, newMappingVersion, true );
00106   //m_mapping.tables();
00107   // creating the sequences...
00108   m_containerSchemaSequences.create( MappingRules::sequenceNameForContainer( m_containerName ) );
00109   for( std::map<std::string,MappingTree*>::iterator iDep = m_dependentMappings.begin();
00110        iDep != m_dependentMappings.end(); ++iDep ){
00111     m_containerSchemaSequences.create( MappingRules::sequenceNameForDependentClass( m_containerName, iDep->first ));
00112   }
00113   // finally create the tables... 
00114   MappingToSchema mapping2Schema( m_session.schema().storageSchema() );
00115   mapping2Schema.create(  m_mapping );
00116   m_loaded = true;
00117 }
00118 
00119 void ora::ContainerSchema::getTableHierarchy( const std::set<std::string>& containerMappingVersions, std::vector<std::string>& destination ){
00120   // building the table hierarchy
00121   std::map< std::string, std::set<std::string> > tableHierarchy;
00122   std::set<std::string> topLevelTables; // should be strictly only one!
00123   for( std::set<std::string>::const_iterator iV = containerMappingVersions.begin();
00124        iV!= containerMappingVersions.end(); ++iV ){
00125      MappingTree mapping;
00126      if( m_session.mappingDatabase().getMappingByVersion( *iV, mapping ) ){
00127         topLevelTables.insert( mapping.topElement().tableName() );
00128         getTableHierarchyFromMappingElement( mapping.topElement(), tableHierarchy );
00129      }
00130   }
00131   for(std::set<std::string>::const_iterator iMainT = topLevelTables.begin();
00132       iMainT != topLevelTables.end(); ++iMainT ){
00133     addFromTableHierarchy( *iMainT, tableHierarchy, destination );
00134   }
00135 }
00136 
00137 void ora::ContainerSchema::drop(){
00138 
00139   std::set<std::string> containerMappingVersions;
00140   m_session.mappingDatabase().getMappingVersionsForContainer( m_containerId, containerMappingVersions );
00141   std::vector<std::string> orderedTableList;
00142   getTableHierarchy( containerMappingVersions, orderedTableList );
00143 
00144   // getting the dependent class list...
00145   std::set<std::string> depClasses;
00146   m_session.mappingDatabase().getDependentClassesForContainer( m_containerId, depClasses );
00147 
00148   // now the mappings can be removed    
00149   for( std::set<std::string>::const_iterator iM = containerMappingVersions.begin();
00150        iM != containerMappingVersions.end(); ++iM ){
00151     m_session.mappingDatabase().removeMapping( *iM );
00152   }
00153   // removing the sequences
00154   m_containerSchemaSequences.erase( MappingRules::sequenceNameForContainer( m_containerName ));
00155   for(std::set<std::string>::const_iterator iDepCl = depClasses.begin();
00156       iDepCl != depClasses.end(); iDepCl++){
00157     m_containerSchemaSequences.erase( MappingRules::sequenceNameForDependentClass( m_containerName, *iDepCl ) );
00158   }
00159 
00160   // removing the entry in the containers table
00161   m_session.schema().containerHeaderTable().removeContainer( m_containerId );
00162 
00163   // finally drop the container tables following the hierarchy
00164   for(std::vector<std::string>::reverse_iterator iTable = orderedTableList.rbegin();
00165       iTable != orderedTableList.rend(); iTable++ ){
00166     m_session.schema().storageSchema().dropIfExistsTable( *iTable );
00167   } 
00168       
00169 }
00170 
00171 void ora::ContainerSchema::evolve(){
00172   MappingGenerator mapGen( m_session.schema().storageSchema() );
00173   // retrieve the base mapping
00174   MappingTree baseMapping;
00175   if( !m_session.mappingDatabase().getBaseMappingForContainer( m_classDict.Name(Reflex::SCOPED), m_containerId, baseMapping )){
00176     throwException("Base mapping has not been found in the database.",
00177                    "ContainerSchema::evolve");
00178   }
00179   mapGen.createNewMapping( m_containerName, m_classDict, baseMapping,  m_mapping );
00180   std::string newMappingVersion = m_session.mappingDatabase().newMappingVersionForContainer( m_containerName );
00181   m_mapping.setVersion( newMappingVersion );
00182   m_session.mappingDatabase().storeMapping( m_mapping );
00183   m_session.mappingDatabase().insertClassVersion( m_classDict, 0, m_containerId, newMappingVersion );
00184   MappingToSchema mapping2Schema( m_session.schema().storageSchema() );
00185   mapping2Schema.alter(  m_mapping  );
00186   m_loaded = true;
00187 }
00188 
00189 void ora::ContainerSchema::evolve( const Reflex::Type& dependentClass, MappingTree& baseMapping ){
00190   std::string className = dependentClass.Name(Reflex::SCOPED);
00191   MappingGenerator mapGen( m_session.schema().storageSchema() );
00192   std::map<std::string,MappingTree*>::iterator iDep =
00193     m_dependentMappings.insert( std::make_pair( className, new MappingTree ) ).first;
00194   if( baseMapping.className() != dependentClass.Name(Reflex::SCOPED) ){
00195     throwException("Provided base mapping does not map class \""+dependentClass.Name(Reflex::SCOPED)+"\".",
00196                    "ContainerSchema::evolve");    
00197   }
00198   mapGen.createNewDependentMapping( dependentClass, m_mapping, baseMapping, *iDep->second );
00199   std::string newMappingVersion = m_session.mappingDatabase().newMappingVersionForContainer( m_containerName );
00200   iDep->second->setVersion( newMappingVersion );
00201   m_session.mappingDatabase().storeMapping( *iDep->second );
00202   m_session.mappingDatabase().insertClassVersion( dependentClass, 1, m_containerId, newMappingVersion, false );
00203 }
00204 
00205 void ora::ContainerSchema::setAccessPermission( const std::string& principal, 
00206                                                 bool forWrite ){
00207   std::set<std::string> containerMappingVersions;
00208   m_session.mappingDatabase().getMappingVersionsForContainer( m_containerId, containerMappingVersions );
00209   std::vector<std::string> orderedTableList;
00210   getTableHierarchy( containerMappingVersions, orderedTableList );
00211   for( std::vector<std::string>::const_iterator iT = orderedTableList.begin();
00212        iT != orderedTableList.end(); iT++ ){
00213     setTableAccessPermission( m_session.schema().storageSchema().tableHandle( *iT ), principal, forWrite );
00214   }
00215 }
00216 
00217 const Reflex::Type& ora::ContainerSchema::type(){
00218   initClassDict();
00219   return m_classDict;
00220 }
00221 
00222 ora::MappingTree& ora::ContainerSchema::mapping( bool writeEnabled ){
00223   initClassDict();
00224   if(!m_loaded ){
00225     std::string classVersion = MappingDatabase::versionOfClass( m_classDict );
00226     if( !m_session.mappingDatabase().getMappingForContainer( m_className, classVersion, m_containerId, m_mapping ) ){
00227       // if enabled, invoke the evolution
00228       if( writeEnabled && m_session.configuration().properties().getFlag( Configuration::automaticSchemaEvolution() )){
00229         evolve();
00230       } else {
00231         std::string msg( "No mapping available for the class=\""+m_className+"\"  version=\""+classVersion+"\"." );
00232         throwException( msg,
00233                         "ContainerSchema::mapping");
00234       }
00235     } else {
00236       m_loaded = true;
00237     }
00238     
00239   }
00240   if( m_mapping.topElement().find( m_className )==m_mapping.topElement().end() ){
00241     throwException( "Mapping for container class \""+m_className+"\" could not be loaded.",
00242                     "ContainerSchema::mapping");
00243   }
00244   return m_mapping;
00245 }
00246 
00247 bool ora::ContainerSchema::loadMappingForDependentClass( const Reflex::Type& dependentClassDict ){
00248   if( !dependentClassDict ) throwException("The dependent class has not been found in the dictionary.",
00249                                            "ContainerSchema::loadMappingForDependentClass");
00250   std::string className = dependentClassDict.Name(Reflex::SCOPED);
00251   std::map<std::string,MappingTree*>::iterator iDep = m_dependentMappings.find( className );
00252   if( iDep ==  m_dependentMappings.end() ){
00253     // not in cache, search the database...
00254     iDep = m_dependentMappings.insert( std::make_pair( className, new MappingTree ) ).first;
00255     if( ! m_session.mappingDatabase().getMappingForContainer( className, 
00256                                                               MappingDatabase::versionOfClass( dependentClassDict ), 
00257                                                               m_containerId, 
00258                                                               *iDep->second ) ){
00259       m_dependentMappings.erase( className );
00260       return false;
00261     }
00262   }
00263   return true;  
00264 }
00265 
00266 void ora::ContainerSchema::create( const Reflex::Type& dependentClassDict ){
00267   std::string className = dependentClassDict.Name(Reflex::SCOPED);
00268   std::map<std::string,MappingTree*>::iterator iDep =
00269     m_dependentMappings.insert( std::make_pair( className, new MappingTree ) ).first;
00270   MappingGenerator mapGen( m_session.schema().storageSchema() );
00271   MappingToSchema mapping2Schema( m_session.schema().storageSchema() );
00272   mapGen.createNewDependentMapping( dependentClassDict, m_mapping, *iDep->second );
00273   mapping2Schema.create(  *iDep->second  );
00274   std::string newMappingVersion = m_session.mappingDatabase().newMappingVersionForContainer( m_containerName );
00275   iDep->second->setVersion( newMappingVersion );
00276   m_session.mappingDatabase().storeMapping( *iDep->second );
00277   m_session.mappingDatabase().insertClassVersion( dependentClassDict, 1, m_containerId, newMappingVersion, true );
00278   m_containerSchemaSequences.create( MappingRules::sequenceNameForDependentClass( m_containerName, className ));
00279 }
00280 
00281 void ora::ContainerSchema::extend( const Reflex::Type& dependentClassDict ){
00282   std::string className = dependentClassDict.Name(Reflex::SCOPED);
00283   MappingTree baseMapping;
00284   if( !m_session.mappingDatabase().getBaseMappingForContainer( className,
00285                                                                m_containerId, baseMapping ) ){
00286     create( dependentClassDict );
00287   } else {
00288     evolve( dependentClassDict, baseMapping );
00289   }
00290 }
00291 
00292 bool ora::ContainerSchema::extendIfRequired( const Reflex::Type& dependentClassDict ){
00293   bool ret = false;
00294   if( ! loadMappingForDependentClass( dependentClassDict ) ){
00295     extend( dependentClassDict );
00296     ret = true;
00297   }
00298   return ret;
00299 }
00300 
00301 ora::MappingElement& ora::ContainerSchema::mappingForDependentClass( const Reflex::Type& dependentClassDict,
00302                                                                      bool writeEnabled ){
00303   std::string className = dependentClassDict.Name(Reflex::SCOPED);
00304   if( ! loadMappingForDependentClass( dependentClassDict ) ){
00305     if( writeEnabled ){
00306       // check if a base is available:
00307       MappingTree baseMapping;
00308       if( !m_session.mappingDatabase().getBaseMappingForContainer( className,
00309                                                                    m_containerId, baseMapping ) ){
00310         // mapping has to be generated from scratch
00311         if( m_session.configuration().properties().getFlag( Configuration::automaticDatabaseCreation()) ||
00312             m_session.configuration().properties().getFlag( Configuration::automaticContainerCreation() ) ){
00313           create( dependentClassDict );
00314         }
00315       } else {
00316         // evolve if allowed
00317         if( m_session.configuration().properties().getFlag( Configuration::automaticSchemaEvolution() )){
00318           evolve( dependentClassDict, baseMapping );
00319         }
00320       }
00321     }
00322   }
00323   std::map<std::string,MappingTree*>::iterator iDep = m_dependentMappings.find( className );
00324   if( iDep ==  m_dependentMappings.end() ){
00325     throwException( "Mapping for class \""+ className + "\" is not available in the database.",
00326                     "ContainerSchema::mappingForDependentClass");
00327   }
00328   return iDep->second->topElement();
00329 }
00330 
00331 bool ora::ContainerSchema::mappingForDependentClasses( std::vector<ora::MappingElement>& destination ){
00332   return m_session.mappingDatabase().getDependentMappingsForContainer( m_containerId, destination );
00333 }
00334 
00335 ora::Sequences& ora::ContainerSchema::containerSequences(){
00336   return m_containerSchemaSequences;
00337 }
00338 
00339 ora::IBlobStreamingService* ora::ContainerSchema::blobStreamingService(){
00340   return m_session.configuration().blobStreamingService();
00341 }
00342 
00343 ora::IReferenceHandler* ora::ContainerSchema::referenceHandler(){
00344   return m_session.configuration().referenceHandler();
00345 }
00346   
00347 const std::string& ora::ContainerSchema::mappingVersion(){
00348   return m_mapping.version();
00349 }
00350 
00351 int ora::ContainerSchema::containerId(){
00352   return m_containerId;
00353 }
00354 
00355 const std::string&  ora::ContainerSchema::containerName(){
00356   return m_containerName;
00357 }
00358 
00359 const std::string&  ora::ContainerSchema::className(){
00360   return m_className;
00361 }
00362 
00363 coral::ISchema& ora::ContainerSchema::storageSchema(){
00364   return m_session.schema().storageSchema();
00365 }
00366 
00367 ora::DatabaseSession& ora::ContainerSchema::dbSession(){
00368   return m_session;
00369 }
00370 
00371 
00372