CMS 3D CMS Logo

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

Go to the documentation of this file.
00001 #include "CondCore/ORA/interface/Exception.h"
00002 #include "STLContainerStreamer.h"
00003 #include "ClassUtils.h"
00004 #include "MappingElement.h"
00005 #include "DataElement.h"
00006 #include "ContainerSchema.h"
00007 #include "RelationalBuffer.h"
00008 #include "MultiRecordInsertOperation.h"
00009 #include "MultiRecordSelectOperation.h"
00010 #include "RelationalStreamerFactory.h"
00011 #include "ArrayHandlerFactory.h"
00012 #include "IArrayHandler.h"
00013 #include "ArrayCommonImpl.h"
00014 // externals
00015 #include "CoralBase/Attribute.h"
00016 #include "RelationalAccess/IBulkOperation.h"
00017 #include "Reflex/Member.h"
00018 
00019 ora::STLContainerWriter::STLContainerWriter( const Reflex::Type& objectType,
00020                                              MappingElement& mapping,
00021                                              ContainerSchema& contSchema ):
00022   m_objectType( objectType ),
00023   m_mappingElement( mapping ),
00024   m_schema( contSchema ),
00025   m_recordId(),
00026   m_localElement(),
00027   m_associative( ClassUtils::isTypeAssociativeContainer( objectType ) ),
00028   m_offset( 0 ),
00029   m_insertOperation( 0 ),
00030   m_arrayHandler(),
00031   m_keyWriter(),
00032   m_dataWriter(){
00033 }
00034 
00035 ora::STLContainerWriter::~STLContainerWriter(){
00036 }
00037 
00038 bool ora::STLContainerWriter::build( DataElement& offset,
00039                                      IRelationalData&,
00040                                      RelationalBuffer& operationBuffer ){
00041   m_localElement.clear();
00042   m_recordId.clear();
00043   // allocate for the index...
00044   m_recordId.push_back(0);
00045     
00046   RelationalStreamerFactory streamerFactory( m_schema );
00047   
00048   // first open the insert on the extra table...
00049   m_insertOperation = &operationBuffer.newMultiRecordInsert( m_mappingElement.tableName() );
00050   const std::vector<std::string>& columns = m_mappingElement.columnNames();
00051   if( !columns.size() ){
00052     throwException( "Id columns not found in the mapping.",
00053                     "STLContainerWriter::build");    
00054   }
00055   for( size_t i=0; i<columns.size(); i++ ){
00056     m_insertOperation->addId( columns[ i ] );
00057   }
00058 
00059   m_offset = &offset;
00060 
00061   m_arrayHandler.reset( ArrayHandlerFactory::newArrayHandler( m_objectType ) );
00062   
00063   Reflex::Type valueType;
00064   if ( m_associative ){
00065     
00066     Reflex::Type keyType = ClassUtils::containerKeyType(m_objectType);
00067     Reflex::Type keyResolvedType = ClassUtils::resolvedType(keyType);
00068     if ( ! keyType || !keyResolvedType ) {
00069       throwException( "Missing dictionary information for the key type of the container \"" +
00070                       m_objectType.Name(Reflex::SCOPED) + "\"",
00071                       "STLContainerWriter::build" );
00072     }
00073     std::string keyName = keyType.Name();
00074     // Retrieve the relevant mapping element
00075     MappingElement::iterator iMe = m_mappingElement.find( keyName );
00076     if ( iMe == m_mappingElement.end() ) {
00077       throwException( "Item for \"" + keyName + "\" not found in the mapping element",
00078                       "STLContainerWriter::build" );
00079     }
00080 
00081     m_keyWriter.reset( streamerFactory.newWriter( keyResolvedType, iMe->second ) );
00082     m_keyWriter->build( m_localElement, *m_insertOperation, operationBuffer );
00083     valueType = ClassUtils::containerDataType(m_objectType);
00084   } else {
00085     valueType = ClassUtils::containerValueType(m_objectType);
00086   }
00087 
00088   Reflex::Type valueResolvedType = ClassUtils::resolvedType(valueType);
00089   // Check the component type
00090   if ( ! valueType || !valueResolvedType ) {
00091     throwException( "Missing dictionary information for the content type of the container \"" +
00092                     m_objectType.Name(Reflex::SCOPED) + "\"",
00093                     "STLContainerWriter::build" );
00094   }
00095   
00096   std::string valueName = valueType.Name();
00097   // Retrieve the relevant mapping element
00098   MappingElement::iterator iMe = m_mappingElement.find( valueName );
00099   if ( iMe == m_mappingElement.end() ) {
00100     throwException( "Item for \"" + valueName + "\" not found in the mapping element",
00101                     "STLContainerWriter::build" );
00102   }
00103 
00104   m_dataWriter.reset( streamerFactory.newWriter( valueResolvedType, iMe->second ) );
00105   m_dataWriter->build( m_localElement, *m_insertOperation, operationBuffer );
00106   //operationBuffer.addToExecutionBuffer( *m_insertOperation );
00107   return true;
00108 }
00109 
00110 void ora::STLContainerWriter::setRecordId( const std::vector<int>& identity ){
00111   m_recordId.clear();
00112   for(size_t i=0;i<identity.size();i++) {
00113     m_recordId.push_back( identity[i] );
00114   }
00115   m_recordId.push_back( 0 );
00116 }
00117       
00118 void ora::STLContainerWriter::write( int oid,
00119                                      const void* inputData ){
00120 
00121   if(!m_offset){
00122     throwException("The streamer has not been built.",
00123                    "STLContainerWriter::write");
00124   }
00125 
00126   const std::vector<std::string>& columns = m_mappingElement.columnNames();
00127   if( columns.size() != m_recordId.size()+1){
00128     throwException( "Object id elements provided are not matching with the mapped id columns.",
00129                     "STLContainerWriter::write");
00130   }
00131 
00132   const Reflex::Type& iteratorReturnType = m_arrayHandler->iteratorReturnType();
00133   // Retrieve the container type
00134   Reflex::Type keyType;
00135   if ( m_associative ) keyType = m_objectType.TemplateArgumentAt(0);
00136   Reflex::Member firstMember;
00137   Reflex::Member secondMember;
00138   if( keyType ){
00139     firstMember = iteratorReturnType.MemberByName( "first" );
00140     if ( ! firstMember ) {
00141       throwException( "Could not find the data member \"first\" for the class \"" +
00142                       iteratorReturnType.Name(Reflex::SCOPED) + "\"",
00143                       "STLContainerWriter::write" );
00144     }
00145     secondMember = iteratorReturnType.MemberByName( "second" );
00146     if ( ! secondMember ) {
00147       throwException( "Could not retrieve the data member \"second\" for the class \"" +
00148                       iteratorReturnType.Name(Reflex::SCOPED) + "\"",
00149                       "STLContainerWriter::write" );
00150     }
00151   }
00152   
00153   void* data = m_offset->address( inputData );
00154   
00155   // Use the iterator to loop over the elements of the container.
00156   size_t containerSize = m_arrayHandler->size( data  );
00157   
00158   if ( containerSize == 0 ) return;
00159 
00160   size_t startElementIndex = m_arrayHandler->startElementIndex( data );
00161   std::auto_ptr<IArrayIteratorHandler> iteratorHandler( m_arrayHandler->iterate( data ) );
00162 
00163   InsertCache& bulkInsert = m_insertOperation->setUp( containerSize-startElementIndex+1 );
00164 
00165   for ( size_t iIndex = startElementIndex; iIndex < containerSize; ++iIndex ) {
00166 
00167     m_recordId[m_recordId.size()-1] = iIndex;
00168     coral::AttributeList& dataBuff = m_insertOperation->data();
00169 
00170     dataBuff[ columns[0] ].data<int>() = oid;
00171     for( size_t i = 1;i < columns.size(); i++ ){
00172       dataBuff[ columns[i] ].data<int>() = m_recordId[i-1];
00173     }
00174 
00175     void* objectReference = iteratorHandler->object();
00176     void* componentData = objectReference;
00177 
00178     if ( keyType ) { // treat the key object first
00179       void* keyData = static_cast< char* >( objectReference ) + firstMember.Offset();
00180       m_keyWriter->setRecordId( m_recordId );
00181       m_keyWriter->write( oid, keyData );
00182 
00183       componentData = static_cast< char* >( objectReference ) + secondMember.Offset();
00184     }
00185     m_dataWriter->setRecordId( m_recordId );
00186 
00187     m_dataWriter->write( oid, componentData );
00188     bulkInsert.processNextIteration();
00189    
00190     // Increment the iterator
00191     iteratorHandler->increment();
00192   }
00193 
00194   // execute the insert...
00195   m_arrayHandler->finalize( const_cast<void*>( data ) );
00196 
00197 }
00198 
00199 ora::STLContainerUpdater::STLContainerUpdater(const Reflex::Type& objectType,
00200                                               MappingElement& mapping,
00201                                               ContainerSchema& contSchema ):
00202   m_deleter( mapping ),
00203   m_writer( objectType, mapping, contSchema ){
00204 }
00205 
00206 ora::STLContainerUpdater::~STLContainerUpdater(){
00207 }
00208 
00209 bool ora::STLContainerUpdater::build( DataElement& offset,
00210                                       IRelationalData& relationalData,
00211                                       RelationalBuffer& operationBuffer){
00212   m_deleter.build( operationBuffer );
00213   m_writer.build( offset, relationalData, operationBuffer );
00214   return true;
00215 }
00216 
00217 void ora::STLContainerUpdater::setRecordId( const std::vector<int>& identity ){
00218   m_writer.setRecordId( identity );
00219 }
00220 
00221 void ora::STLContainerUpdater::update( int oid,
00222                                        const void* data ){
00223   m_deleter.erase( oid );
00224   m_writer.write( oid, data );
00225 }
00226 
00227 ora::STLContainerReader::STLContainerReader(const Reflex::Type& objectType,
00228                                             MappingElement& mapping,
00229                                             ContainerSchema& contSchema ):
00230   m_objectType( objectType ),
00231   m_mappingElement( mapping ),
00232   m_schema( contSchema ),
00233   m_recordId(),
00234   m_localElement(),
00235   m_associative( ClassUtils::isTypeAssociativeContainer( objectType ) ),
00236   m_offset(0 ),
00237   m_query(),
00238   m_arrayHandler(),
00239   m_keyReader(),
00240   m_dataReader(){
00241 }
00242 
00243 ora::STLContainerReader::~STLContainerReader(){
00244 }
00245 
00246 bool ora::STLContainerReader::build( DataElement& offset, IRelationalData& ){
00247   m_localElement.clear();
00248   m_recordId.clear();
00249   // allocate for the index...
00250   m_recordId.push_back(0);
00251 
00252   RelationalStreamerFactory streamerFactory( m_schema );
00253   
00254   // first open the insert on the extra table...
00255   m_query.reset( new MultiRecordSelectOperation( m_mappingElement.tableName(), m_schema.storageSchema() ));
00256 
00257   m_query->addWhereId( m_mappingElement.pkColumn() );
00258   std::vector<std::string> recIdCols = m_mappingElement.recordIdColumns();
00259   for( size_t i=0; i<recIdCols.size(); i++ ){
00260     m_query->addId( recIdCols[ i ] );
00261     m_query->addOrderId( recIdCols[ i ] );
00262   }
00263   
00264   m_offset = &offset;
00265 
00266   m_arrayHandler.reset( ArrayHandlerFactory::newArrayHandler( m_objectType ) );
00267 
00268   Reflex::Type valueType;
00269   if ( m_associative ){
00270 
00271     Reflex::Type keyType = ClassUtils::containerKeyType( m_objectType );
00272     Reflex::Type keyResolvedType = ClassUtils::resolvedType(keyType);
00273 
00274     if ( ! keyType ||!keyResolvedType ) {
00275       throwException( "Missing dictionary information for the key type of the container \"" +
00276                       m_objectType.Name(Reflex::SCOPED) + "\"",
00277                       "STLContainerReader::build" );
00278     }
00279 
00280     std::string keyName = keyType.Name();
00281     // Retrieve the relevant mapping element
00282     MappingElement::iterator iMe = m_mappingElement.find( keyName );
00283     if ( iMe == m_mappingElement.end() ) {
00284       throwException( "Item for \"" + keyName + "\" not found in the mapping element",
00285                       "STLContainerReader::build" );
00286     }
00287 
00288     m_keyReader.reset( streamerFactory.newReader( keyResolvedType, iMe->second ) );
00289     m_keyReader->build( m_localElement, *m_query );
00290     
00291     valueType = ClassUtils::containerDataType(m_objectType);
00292   } else {
00293     valueType = ClassUtils::containerValueType(m_objectType);
00294   }
00295 
00296   Reflex::Type valueResolvedType = ClassUtils::resolvedType(valueType);
00297   // Check the component type
00298   if ( ! valueType ||!valueResolvedType ) {
00299     throwException( "Missing dictionary information for the content type of the container \"" +
00300                     m_objectType.Name(Reflex::SCOPED) + "\"",
00301                     "STLContainerReader::build" );
00302   }
00303   
00304   std::string valueName = valueType.Name();
00305   // Retrieve the relevant mapping element
00306   MappingElement::iterator iMe = m_mappingElement.find( valueName );
00307   if ( iMe == m_mappingElement.end() ) {
00308     throwException( "Item for \"" + valueName + "\" not found in the mapping element",
00309                     "STLContainerReader::build" );
00310   }
00311 
00312   m_dataReader.reset( streamerFactory.newReader( valueResolvedType, iMe->second ) );
00313   m_dataReader->build( m_localElement, *m_query );
00314   return true;
00315 }
00316 
00317 void ora::STLContainerReader::select( int oid ){
00318   if(!m_query.get()){
00319     throwException("The streamer has not been built.",
00320                    "STLContainerReader::read");
00321   }
00322   coral::AttributeList& whereData = m_query->whereData();
00323   whereData[ m_mappingElement.pkColumn() ].data<int>() = oid;
00324   m_query->execute();
00325   if(m_keyReader.get()) m_keyReader->select( oid );
00326   m_dataReader->select( oid );
00327 }
00328 
00329 void ora::STLContainerReader::setRecordId( const std::vector<int>& identity ){
00330   m_recordId.clear();
00331   for(size_t i=0;i<identity.size();i++) {
00332     m_recordId.push_back( identity[i] );
00333   }
00334   // allocate the element for the index...
00335   m_recordId.push_back( 0 );
00336 }
00337 
00338 void ora::STLContainerReader::read( void* destinationData ) {
00339 
00340   if(!m_offset){
00341     throwException("The streamer has not been built.",
00342                    "STLContainerReader::read");
00343   }
00344 
00345   void* address = m_offset->address( destinationData );
00346 
00347   const Reflex::Type& iteratorReturnType = m_arrayHandler->iteratorReturnType();
00348   U_Primitives primitiveStub;
00349   
00350   Reflex::Type keyType;
00351   Reflex::Member firstMember;
00352   Reflex::Member secondMember;
00353   if ( m_associative ) {
00354     keyType = m_objectType.TemplateArgumentAt(0);
00355     firstMember = iteratorReturnType.MemberByName( "first" );
00356     if ( ! firstMember ) {
00357       throwException("Could not retrieve the data member \"first\" of the class \"" +
00358                      iteratorReturnType.Name(Reflex::SCOPED) + "\"",
00359                      "STLContainerReader::read" );
00360     }
00361     secondMember = iteratorReturnType.MemberByName( "second" );
00362     if ( ! secondMember ) {
00363       throwException( "Could not retrieve the data member \"second\" of the class \"" +
00364                       iteratorReturnType.Name(Reflex::SCOPED) + "\"",
00365                       "STLContainerReader::read" );
00366     }
00367   }
00368   
00369   bool isElementFundamental = iteratorReturnType.IsFundamental();
00370   
00371   m_arrayHandler->clear( address );
00372 
00373   size_t cursorSize = m_query->selectionSize(m_recordId, m_recordId.size()-1);
00374   unsigned int i=0;
00375   while ( i< cursorSize ){
00376 
00377     m_recordId[m_recordId.size()-1] = (int)i;
00378     m_query->selectRow( m_recordId );
00379 
00380     // Create a new element for the array
00381     void* objectData = 0;
00382     if(isElementFundamental){
00383       objectData = &primitiveStub;
00384     } else {
00385       objectData = iteratorReturnType.Construct().Address();
00386     }
00387 
00388     void* componentData = objectData;
00389     void* keyData = 0;
00390 
00391     if ( keyType ) { // treat the key object first
00392       keyData = static_cast< char* >( objectData ) + firstMember.Offset();
00393       m_keyReader->setRecordId( m_recordId );
00394       m_keyReader->read( keyData );
00395       
00396       componentData = static_cast< char* >( objectData ) + secondMember.Offset();
00397     }
00398     m_dataReader->setRecordId( m_recordId );
00399     m_dataReader->read( componentData );
00400 
00401     size_t prevSize = m_arrayHandler->size( address );
00402     m_arrayHandler->appendNewElement( address, objectData );
00403     bool inserted = m_arrayHandler->size( address )>prevSize;
00404     if ( ! ( iteratorReturnType.IsFundamental() ) ) {
00405       iteratorReturnType.Destruct( objectData );
00406     }
00407     if ( !inserted ) {
00408       throwException( "Could not insert a new element in the array type \"" +
00409                       m_objectType.Name(Reflex::SCOPED) + "\"",
00410                       "STLContainerReader::read" );
00411     }
00412     ++i;
00413   }
00414 
00415   m_arrayHandler->finalize( address );
00416 
00417 }
00418 
00419 void ora::STLContainerReader::clear(){
00420   if(m_query.get()) m_query->clear();
00421   if(m_keyReader.get()) m_keyReader->clear();
00422   if(m_dataReader.get()) m_dataReader->clear();
00423 }
00424 
00425 ora::STLContainerStreamer::STLContainerStreamer( const Reflex::Type& objectType,
00426                                                  MappingElement& mapping,
00427                                                  ContainerSchema& contSchema ):
00428   m_objectType( objectType ),
00429   m_mapping( mapping ),
00430   m_schema( contSchema ){
00431 }
00432 
00433 ora::STLContainerStreamer::~STLContainerStreamer(){
00434 }
00435 
00436 ora::IRelationalWriter* ora::STLContainerStreamer::newWriter(){
00437   return new STLContainerWriter( m_objectType, m_mapping, m_schema );
00438 }
00439 
00440 ora::IRelationalUpdater* ora::STLContainerStreamer::newUpdater(){
00441   return new STLContainerUpdater( m_objectType, m_mapping, m_schema );
00442 }
00443 
00444 ora::IRelationalReader* ora::STLContainerStreamer::newReader(){
00445   return new STLContainerReader( m_objectType, m_mapping, m_schema );
00446 }