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 m_localElement.clear();
00042 m_recordId.clear();
00043
00044 m_recordId.push_back(0);
00045
00046 RelationalStreamerFactory streamerFactory( m_schema );
00047
00048
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
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
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
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
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
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
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 ) {
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
00191 iteratorHandler->increment();
00192 }
00193
00194
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
00250 m_recordId.push_back(0);
00251
00252 RelationalStreamerFactory streamerFactory( m_schema );
00253
00254
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
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
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
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
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
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 ) {
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 }