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
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
00049 m_recordId.push_back(0);
00050
00051 RelationalStreamerFactory streamerFactory( m_schema );
00052
00053
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
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
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
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
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
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
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 ) {
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
00196 iteratorHandler->increment();
00197 }
00198
00199
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
00255 m_recordId.push_back(0);
00256
00257 RelationalStreamerFactory streamerFactory( m_schema );
00258
00259
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
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
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
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
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
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 ) {
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 }