CMS 3D CMS Logo

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