CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch13/src/CondCore/ORA/src/DatabaseContainer.cc

Go to the documentation of this file.
00001 #include "CondCore/ORA/interface/Exception.h"
00002 #include "DatabaseContainer.h"
00003 #include "DatabaseSession.h"
00004 #include "ContainerSchema.h"
00005 #include "IRelationalStreamer.h"
00006 #include "RelationalBuffer.h"
00007 #include "RelationalOperation.h"
00008 #include "DataElement.h"
00009 #include "RelationalDeleter.h"
00010 #include "RelationalStreamerFactory.h"
00011 #include "IDatabaseSchema.h"
00012 #include "ClassUtils.h"
00013 #include "MappingRules.h"
00014 // externals
00015 #include "CoralBase/Attribute.h"
00016 
00017 namespace ora {
00018 
00019   class WriteBuffer {
00020     public:
00021       explicit WriteBuffer( ContainerSchema& contSchema ):
00022         m_buffer(),
00023         m_operationBuffer( contSchema.storageSchema() ),
00024         m_topLevelElement(),
00025         m_writer(),
00026         m_topLevelInsert( 0 ){
00027 
00028         MappingElement& topLevelMapping = contSchema.mapping( true ).topElement();
00029         m_topLevelInsert = &m_operationBuffer.newInsert( topLevelMapping.tableName() );
00030         m_topLevelInsert->addId(  topLevelMapping.columnNames()[ 0 ] );
00031         const Reflex::Type& type = contSchema.type();
00032         MappingElement::iterator iMap = topLevelMapping.find( type.Name(Reflex::SCOPED) );
00033         // the first inner mapping is the relevant...
00034         if( iMap == topLevelMapping.end()){
00035           throwException("Could not find a mapping element for class \""+
00036                          type.Name(Reflex::SCOPED)+"\"",
00037                          "WriteBuffer::WriteBuffer");
00038         }
00039         MappingElement& mapping = iMap->second;
00040         RelationalStreamerFactory streamerFactory( contSchema );
00041         m_writer.reset( streamerFactory.newWriter( type, mapping ) );
00042         m_writer->build( m_topLevelElement, *m_topLevelInsert, m_operationBuffer );
00043       }
00044       
00045 
00046       ~WriteBuffer(){
00047       }
00048 
00049       void registerForWrite( int oid, const void* data ){
00050         m_buffer.push_back( std::make_pair(oid, data ) );
00051       }
00052       
00053       size_t flush(){
00054         size_t nobj = 0;
00055         for( std::vector<std::pair<int, const void*> >::const_iterator iW = m_buffer.begin();
00056              iW != m_buffer.end(); ++iW ){
00057           write( iW->first, iW->second );
00058           if( m_operationBuffer.flush() ) nobj++;
00059         }
00060         m_buffer.clear();
00061         return nobj;
00062       }
00063 
00064     private:
00065       void write( int oid, const void* data ){
00066         coral::AttributeList& dataBuff = m_topLevelInsert->data();
00067         dataBuff.begin()->data<int>() = oid;
00068         m_writer->write( oid, data );
00069       }      
00070 
00071     private:
00072       std::vector<std::pair<int, const void*> > m_buffer;
00073       RelationalBuffer m_operationBuffer;
00074       DataElement m_topLevelElement;
00075       std::auto_ptr<IRelationalWriter> m_writer;
00076       InsertOperation* m_topLevelInsert;
00077   };
00078 
00079   class UpdateBuffer {
00080     public:
00081       explicit UpdateBuffer( ContainerSchema& contSchema ):
00082         m_buffer(),
00083         m_operationBuffer( contSchema.storageSchema() ),
00084         m_topLevelElement(),
00085         m_depDeleter(),
00086         m_updater(),
00087         m_topLevelUpdate( 0 ){
00088 
00089         std::vector<MappingElement> dependentMappings;
00090         contSchema.mappingForDependentClasses( dependentMappings );
00091         m_depDeleter.reset( new RelationalDeleter( dependentMappings ) );
00092         m_depDeleter->build( m_operationBuffer );
00093         dependentMappings.clear();
00094 
00095         MappingElement& topLevelMapping = contSchema.mapping( true ).topElement();
00096         m_topLevelUpdate = &m_operationBuffer.newUpdate( topLevelMapping.tableName(), true );
00097         m_topLevelUpdate->addId(  topLevelMapping.columnNames()[ 0 ] );
00098         m_topLevelUpdate->addWhereId(  topLevelMapping.columnNames()[ 0 ] );
00099         const Reflex::Type& type = contSchema.type();
00100         MappingElement::iterator iMap = topLevelMapping.find( type.Name(Reflex::SCOPED) );
00101         // the first inner mapping is the relevant...
00102         if( iMap == topLevelMapping.end()){
00103           throwException("Could not find a mapping element for class \""+
00104                          type.Name(Reflex::SCOPED)+"\"",
00105                          "UpdateBuffer::UpdateBuffer");
00106         }
00107         MappingElement& mapping = iMap->second;
00108         RelationalStreamerFactory streamerFactory( contSchema );
00109         m_updater.reset( streamerFactory.newUpdater( type, mapping ));
00110         m_updater->build( m_topLevelElement, *m_topLevelUpdate, m_operationBuffer );
00111       }
00112       
00113       ~UpdateBuffer(){
00114       }
00115       
00116 
00117       void registerForUpdate( int oid, const void* data ){
00118         m_buffer.push_back( std::make_pair( oid, data ));
00119       }
00120       
00121 
00122       size_t flush(){
00123         size_t nobj = 0;
00124         for( std::vector<std::pair<int, const void*> >::const_iterator iU = m_buffer.begin();
00125              iU != m_buffer.end(); ++iU ){
00126           update( iU->first, iU->second );
00127           if( m_operationBuffer.flush()) nobj++;
00128         }
00129         m_buffer.clear();
00130         return nobj;
00131       }
00132       
00133 
00134     private:
00135       void update( int oid, const void* data ){
00136         // erase the dependencies (cannot be updated...)
00137         m_depDeleter->erase( oid );
00138         coral::AttributeList& dataBuff = m_topLevelUpdate->data();
00139         dataBuff.begin()->data<int>() = oid;
00140         coral::AttributeList& whereDataBuff = m_topLevelUpdate->whereData();
00141         whereDataBuff.begin()->data<int>() = oid;
00142         m_updater->update( oid, data );
00143       }
00144       
00145 
00146     private:
00147       std::vector<std::pair<int, const void*> > m_buffer;
00148       RelationalBuffer m_operationBuffer;
00149       DataElement m_topLevelElement;
00150       std::auto_ptr<RelationalDeleter> m_depDeleter;
00151       std::auto_ptr<IRelationalUpdater> m_updater;
00152       UpdateOperation* m_topLevelUpdate;
00153   };
00154 
00155   class ReadBuffer {
00156     public:
00157       explicit ReadBuffer( ContainerSchema& contSchema ):
00158         m_topLevelElement(),
00159         m_type( contSchema.type() ),
00160         m_reader(),
00161         m_topLevelQuery( contSchema.mapping().topElement().tableName(), contSchema.storageSchema() ){
00162 
00163         MappingElement& topLevelMapping = contSchema.mapping().topElement();
00164         m_topLevelQuery.addWhereId(  topLevelMapping.columnNames()[ 0 ] );
00165         MappingElement::iterator iMap = topLevelMapping.find( m_type.Name(Reflex::SCOPED) );
00166         // the first inner mapping is the good one ...
00167         if( iMap == topLevelMapping.end()){
00168           throwException("Could not find a mapping element for class \""+
00169                          m_type.Name(Reflex::SCOPED)+"\"",
00170                          "ReadBuffer::ReadBuffer");
00171         }
00172         MappingElement& mapping = iMap->second;
00173         RelationalStreamerFactory streamerFactory( contSchema );
00174         m_reader.reset( streamerFactory.newReader( m_type, mapping )) ;
00175         m_reader->build( m_topLevelElement , m_topLevelQuery );
00176       }
00177 
00178       ~ReadBuffer(){
00179       }
00180       
00181       void* read( int oid ){
00182         coral::AttributeList& dataBuff = m_topLevelQuery.whereData();
00183         dataBuff.begin()->data<int>() = oid;
00184         m_topLevelQuery.execute();
00185         m_reader->select( oid );
00186         void* destination = 0;
00187         if( m_topLevelQuery.nextCursorRow() ){
00188           destination = ClassUtils::constructObject( m_type );
00189           m_reader->read( destination );
00190         }
00191         m_reader->clear();
00192         m_topLevelQuery.clear();
00193         return destination;
00194       }
00195 
00196       const Reflex::Type& type(){
00197         return m_type;
00198       }
00199       
00200     private:
00201       DataElement m_topLevelElement;
00202       const Reflex::Type& m_type;
00203       std::auto_ptr<IRelationalReader> m_reader;
00204       SelectOperation m_topLevelQuery;
00205   };
00206 
00207   class DeleteBuffer {
00208     public:
00209       explicit DeleteBuffer( ContainerSchema& contSchema ):
00210         m_buffer(),
00211         m_operationBuffer( contSchema.storageSchema() ),
00212         m_mainDeleter(),
00213         m_depDeleter(){
00214         m_mainDeleter.reset( new RelationalDeleter( contSchema.mapping().topElement() ));
00215         m_mainDeleter->build( m_operationBuffer );
00216         
00217         std::vector<MappingElement> dependentMappings;
00218         contSchema.mappingForDependentClasses( dependentMappings );
00219         m_depDeleter.reset( new RelationalDeleter( dependentMappings ) );
00220         m_depDeleter->build( m_operationBuffer );
00221         dependentMappings.clear();                             
00222       }
00223       
00224       ~DeleteBuffer(){
00225       }
00226       
00227 
00228       void registerForDelete( int oid ){
00229         m_buffer.push_back( oid );
00230       }
00231 
00232       size_t flush(){
00233         size_t nobj = 0;
00234         for( std::vector<int>::const_iterator iD = m_buffer.begin();
00235              iD != m_buffer.end(); ++iD ){
00236           m_depDeleter->erase( *iD );
00237           m_mainDeleter->erase( *iD );
00238           if( m_operationBuffer.flush() ) nobj++;
00239         }
00240         m_buffer.clear();
00241         return nobj;
00242       }
00243       
00244     private:
00245       std::vector<int> m_buffer;
00246       RelationalBuffer m_operationBuffer;
00247       std::auto_ptr<RelationalDeleter> m_mainDeleter;
00248       std::auto_ptr<RelationalDeleter> m_depDeleter;
00249   };
00250   
00251 }
00252 
00253 ora::IteratorBuffer::IteratorBuffer( ContainerSchema& schema,
00254                                      ReadBuffer& buffer ):
00255   m_query( schema.mapping().topElement().tableName(), schema.storageSchema() ),
00256   m_itemId( -1 ),
00257   m_readBuffer( buffer ){
00258   const std::string& idCol = schema.mapping().topElement().columnNames()[0];
00259   m_query.addId( idCol );
00260   m_query.addOrderId( idCol );
00261 }
00262 
00263 ora::IteratorBuffer::~IteratorBuffer(){
00264 }
00265 
00266 void ora::IteratorBuffer::reset(){
00267   m_query.execute();
00268 }
00269 
00270 bool ora::IteratorBuffer::next(){
00271   bool prevValid = (m_itemId != -1);
00272   bool currValid = false;
00273   m_itemId = -1;
00274   if( m_query.nextCursorRow() ){
00275     coral::AttributeList& row = m_query.data();
00276     m_itemId = row.begin()->data<int>();
00277     currValid = true;
00278   }
00279   
00280   if( !currValid && prevValid ) m_query.clear();
00281   return currValid;
00282 }
00283 
00284 void* ora::IteratorBuffer::getItem(){
00285   void* ret = 0;
00286   if( m_itemId != -1 ){
00287     ret =  m_readBuffer.read( m_itemId );
00288   }
00289   return ret;
00290 }
00291 
00292 void* ora::IteratorBuffer::getItemAsType( const Reflex::Type& asType ){
00293   if( !ClassUtils::isType( type(), asType ) ){
00294     throwException("Provided output object type \""+asType.Name(Reflex::SCOPED)+"\" does not match with the container type \""+
00295                    type().Name(Reflex::SCOPED)+"\"","IteratorBuffer::getItemAsType");
00296   } 
00297   return getItem();
00298 }
00299 
00300 int ora::IteratorBuffer::itemId(){
00301   return m_itemId;
00302 }
00303 
00304 const Reflex::Type& ora::IteratorBuffer::type(){
00305   return m_readBuffer.type();
00306 }
00307       
00308 ora::DatabaseContainer::DatabaseContainer( int contId,
00309                                            const std::string& containerName,
00310                                            const std::string& className,
00311                                            unsigned int containerSize,
00312                                            DatabaseSession& session ):
00313   m_schema( new ContainerSchema(contId, containerName, className, session) ),
00314   m_writeBuffer(),
00315   m_updateBuffer(),
00316   m_readBuffer(),
00317   m_deleteBuffer(),
00318   m_iteratorBuffer(),
00319   m_size( containerSize ),
00320   m_containerUpdateTable( session.containerUpdateTable() ){
00321 }
00322 
00323 ora::DatabaseContainer::DatabaseContainer( int contId,
00324                                            const std::string& containerName,
00325                                            const Reflex::Type& containerType,
00326                                            DatabaseSession& session ):
00327   m_schema( new ContainerSchema(contId, containerName, containerType, session) ),
00328   m_writeBuffer(),
00329   m_updateBuffer(),
00330   m_readBuffer(),
00331   m_deleteBuffer(),
00332   m_iteratorBuffer(),
00333   m_size(0),
00334   m_containerUpdateTable( session.containerUpdateTable() ){
00335 }
00336 
00337 ora::DatabaseContainer::~DatabaseContainer(){
00338   m_iteratorBuffer.clear();
00339 }
00340 
00341 int ora::DatabaseContainer::id(){
00342   return m_schema->containerId();
00343 }
00344 
00345 const std::string& ora::DatabaseContainer::name(){
00346   return m_schema->containerName();
00347 }
00348 
00349 const std::string& ora::DatabaseContainer::className(){
00350   return m_schema->className();
00351 }
00352 
00353 const Reflex::Type& ora::DatabaseContainer::type(){
00354   return m_schema->type();
00355 }
00356 
00357 const std::string& ora::DatabaseContainer::mappingVersion(){
00358   return m_schema->mappingVersion();
00359 }
00360 
00361 size_t ora::DatabaseContainer::size(){
00362   return m_size;
00363 }
00364 
00365 ora::Handle<ora::IteratorBuffer> ora::DatabaseContainer::iteratorBuffer(){
00366   if(!m_readBuffer.get()){
00367     m_readBuffer.reset( new ReadBuffer( *m_schema ) );
00368   }
00369   if( !m_iteratorBuffer ){
00370     m_iteratorBuffer.reset( new IteratorBuffer(*m_schema, *m_readBuffer ) );
00371     m_iteratorBuffer->reset();
00372   }
00373   return m_iteratorBuffer;
00374 }
00375 
00376 void ora::DatabaseContainer::create(){
00377   m_schema->create();
00378 }
00379 
00380 void ora::DatabaseContainer::drop(){
00381   m_schema->drop();
00382 }
00383 
00384 void ora::DatabaseContainer::extendSchema( const Reflex::Type& dependentType ){
00385   m_schema->extendIfRequired( dependentType );
00386 }
00387 
00388 void* ora::DatabaseContainer::fetchItem(int itemId){
00389 
00390   if(!m_readBuffer.get()){
00391     m_readBuffer.reset( new ReadBuffer( *m_schema ) );
00392   }
00393   return m_readBuffer->read( itemId );
00394 }
00395 
00396 void* ora::DatabaseContainer::fetchItemAsType(int itemId,
00397                                               const Reflex::Type& asType){
00398   if(!m_readBuffer.get()){
00399     m_readBuffer.reset( new ReadBuffer( *m_schema ) );
00400   }
00401   if( !ClassUtils::isType( type(), asType ) ){
00402     throwException("Provided output object type \""+asType.Name(Reflex::SCOPED)+"\" does not match with the container type \""+
00403                    type().Name(Reflex::SCOPED)+"\"","DatabaseContainer::fetchItemAsType");
00404   } 
00405   return m_readBuffer->read( itemId );
00406 }
00407 
00408 int ora::DatabaseContainer::insertItem( const void* data,
00409                                         const Reflex::Type& dataType ){
00410   if(!m_writeBuffer.get()){
00411     m_writeBuffer.reset( new WriteBuffer( *m_schema ) );
00412   }
00413   Reflex::Type inputResType = ClassUtils::resolvedType( dataType );
00414   Reflex::Type contType = ClassUtils::resolvedType(m_schema->type());
00415   if( inputResType.Name()!= contType.Name() && !inputResType.HasBase( contType ) ){
00416     throwException( "Provided input object type=\""+inputResType.Name()+
00417                     "\" does not match with the container type=\""+contType.Name()+"\"",
00418                     "DatabaseContainer::insertItem" );
00419   }
00420 
00421   int newId = m_schema->containerSequences().getNextId( MappingRules::sequenceNameForContainer( m_schema->containerName()) );
00422   m_writeBuffer->registerForWrite( newId, data );
00423   return newId;
00424 }
00425 
00426 void ora::DatabaseContainer::updateItem( int itemId,
00427                                          const void* data,
00428                                          const Reflex::Type& dataType ){
00429   if(!m_updateBuffer.get()){
00430     m_updateBuffer.reset( new UpdateBuffer( *m_schema ) );
00431   }
00432   Reflex::Type inputResType = ClassUtils::resolvedType( dataType );
00433   Reflex::Type contType = ClassUtils::resolvedType(m_schema->type());
00434   if( inputResType.Name()!= contType.Name() && !inputResType.HasBase( contType ) ){
00435     throwException( "Provided input object type=\""+inputResType.Name()+"\" does not match with the container type=\""+
00436                     contType.Name()+"\".",
00437                     "DatabaseContainer::updateItem" );
00438   }
00439 
00440   m_updateBuffer->registerForUpdate( itemId, data );
00441 }
00442 
00443 void ora::DatabaseContainer::erase( int itemId ){
00444   if(!m_deleteBuffer.get()){
00445     m_deleteBuffer.reset( new DeleteBuffer( *m_schema ) );
00446   }
00447   m_deleteBuffer->registerForDelete( itemId );
00448 }
00449 
00450 void ora::DatabaseContainer::flush(){
00451   size_t prevSize = m_size;
00452   if(m_writeBuffer.get()) m_size += m_writeBuffer->flush(); 
00453   if(m_updateBuffer.get()) m_updateBuffer->flush();
00454   if(m_deleteBuffer.get()) m_size -= m_deleteBuffer->flush();
00455   m_schema->containerSequences().sinchronizeAll();
00456   if( prevSize != m_size ){
00457     m_containerUpdateTable.takeNote( id(), m_size );
00458   }
00459 }
00460 
00461 void ora::DatabaseContainer::setItemName( const std::string& name, 
00462                                           int itemId ){
00463   m_schema->dbSession().setObjectName( name, m_schema->containerId(), itemId );
00464 }
00465 
00466 bool ora::DatabaseContainer::getNames( std::vector<std::string>& destination ){
00467   return m_schema->dbSession().getNamesForContainer( m_schema->containerId(), destination );
00468 }
00469 
00470