| # Gaudi Framework, version v22r4 |

Home |  | Generated: Fri Sep 2 2011

# CollectionCloneAlg.cpp

Go to the documentation of this file.

    00001 // $Header: /tmp/svngaudi/tmp.jEpFh25751/Gaudi/GaudiSvc/src/NTupleSvc/CollectionCloneAlg.cpp,v 1.7 2006/12/06 17:18:05 mato Exp $
    00002 //      ====================================================================
    00003 //  CollectionCloneAlg.cpp
    00004 //      --------------------------------------------------------------------
    00005 //
    00006 //      Author    : Markus Frank
    00007 //
    00008 //      ====================================================================
    00009 #include "GaudiKernel/IDataProviderSvc.h"
    00010 #include "GaudiKernel/ISelectStatement.h"
    00011 #include "GaudiKernel/IDataManagerSvc.h"
    00012 #include "GaudiKernel/GenericAddress.h"
    00013 #include "GaudiKernel/SmartDataPtr.h"
    00014 #include "GaudiKernel/AlgFactory.h"
    00015 #include "GaudiKernel/Tokenizer.h"
    00016 #include "GaudiKernel/IRegistry.h"
    00017 #include "GaudiKernel/Algorithm.h"
    00018 #include "GaudiKernel/MsgStream.h"
    00019 #include "GaudiKernel/SmartIF.h"
    00020 #include "GaudiKernel/NTuple.h"
    00021 #include <vector>
    00022
    00023 namespace {
    00024   template <class T> static long upper(const INTupleItem* item)  {
    00025     const NTuple::_Data<T>* it = dynamic_cast<const NTuple::_Data<T>*>(item);
    00026     return long(it->range().upper());
    00027   }
    00028
    00029   template<class TYP> static
    00030   StatusCode createItem (MsgStream& log,
    00031                         INTuple* tuple,
    00032                         INTupleItem* src,
    00033                         const TYP& null)
    00034   {
    00035     NTuple::_Data<TYP>* source = dynamic_cast<NTuple::_Data<TYP>*>(src);
    00036     TYP low                    = source->range().lower();
    00037     TYP high                   = source->range().upper();
    00038     long hasIdx                = source->hasIndex();
    00039     long ndim                  = source->ndim();
    00040     const std::string& name    = source->name();
    00041     std::string idxName;
    00042     long dim[4], idxLen = 0;
    00043     long dim1 = 1, dim2 = 1;
    00044     INTupleItem* it = 0;
    00045     for ( int i = 0; i < ndim; i++ )
    00046       dim[i] = source->dim(i);
    00048     if ( hasIdx )  {
    00049       const INTupleItem* index = source->indexItem();
    00050       idxName = index->name();
    00051       switch( index->type() )    {
    00052       case DataTypeInfo::UCHAR:
    00053         idxLen = upper<unsigned char>(index);
    00054         break;
    00055       case DataTypeInfo::USHORT:
    00056         idxLen = upper<unsigned short>(index);
    00057         break;
    00058       case DataTypeInfo::UINT:
    00059         idxLen = upper<unsigned int>(index);
    00060         break;
    00061       case DataTypeInfo::ULONG:
    00062         idxLen = upper<unsigned long>(index);
    00063         break;
    00064       case DataTypeInfo::CHAR:
    00065         idxLen = upper<char>(index);
    00066         break;
    00067       case DataTypeInfo::SHORT:
    00068         idxLen = upper<short>(index);
    00069         break;
    00070       case DataTypeInfo::INT:
    00071         idxLen = upper<int>(index);
    00072         break;
    00073       case DataTypeInfo::LONG:
    00074         idxLen = upper<long>(index);
    00075         break;
    00076       default:
    00077         log << MSG::ERROR << "Column " << idxName
    00078             << " is not a valid index column!" << endmsg;
    00079         return StatusCode::FAILURE;
    00080       }
    00081     }
    00082     switch( ndim )  {
    00083     case 0:
    00084       it = NTuple::_Item<TYP>::create (tuple, name, typeid(TYP), low, high, null);
    00085       break;
    00086     case 1:
    00087       dim1 = (hasIdx) ? idxLen : dim[0];
    00088       it = NTuple::_Array<TYP>::create (tuple,
    00089                                         name,
    00090                                         typeid(TYP),
    00091                                         idxName,
    00092                                         dim1,
    00093                                         low,
    00094                                         high,
    00095                                         null);
    00096       break;
    00097     case 2:
    00098       dim1 = (hasIdx) ? idxLen : dim[0];
    00099       dim2 = (hasIdx) ? dim[0] : dim[1];
    00100       it = NTuple::_Matrix<TYP>::create ( tuple,
    00101                                           name,
    00102                                           typeid(TYP),
    00103                                           idxName,
    00104                                           dim1,
    00105                                           dim2,
    00106                                           low,
    00107                                           high,
    00108                                           null);
    00109       break;
    00110     default:
    00111       return StatusCode::FAILURE;
    00112     }
    00113     return tuple->add(it);
    00114   }
    00115 }
    00116
    00127 class CollectionCloneAlg : public Algorithm {
    00129   INTupleSvc*               m_dataSvc;
    00131   std::string               m_tupleSvc;
    00133   std::string               m_output;
    00135   std::vector<std::string>  m_inputs;
    00137   std::string               m_rootName;
    00139   std::string               m_outName;
    00141   std::string               m_criteria;
    00143   std::string               m_selectorName;
    00144 public:
    00145
    00147   CollectionCloneAlg(const std::string& name, ISvcLocator* pSvcLocator)
    00148   :     Algorithm(name, pSvcLocator),  m_dataSvc(0)
    00149   {
    00150     declareProperty("EvtTupleSvc", m_tupleSvc="EvtTupleSvc");
    00151     declareProperty("Input",       m_inputs);
    00152     declareProperty("Output",      m_output);
    00153   }
    00155   virtual ~CollectionCloneAlg()     {
    00156   }
    00157
    00159   virtual StatusCode initialize()   {
    00160     MsgStream log(msgSvc(), name());
    00161     m_rootName = "";
    00162     m_outName = "";
    00163     m_criteria = "";
    00164     m_selectorName = "";
    00165     StatusCode sc = service(m_tupleSvc, m_dataSvc, true);
    00166     if ( sc.isSuccess() )  {
    00167       std::string fun;
    00168       Tokenizer tok(true);
    00169       tok.analyse(m_output, " ", "", "", "=", "'", "'");
    00170       for ( Tokenizer::Items::iterator i = tok.items().begin(); i != tok.items().end(); i++ )   {
    00171         const std::string& tag = (*i).tag();
    00172         const std::string& val = (*i).value();
    00173         switch( ::toupper(tag[0]) )    {
    00174         case 'D':
    00175           m_outName = val;
    00176           break;
    00177         case 'S':
    00178           m_criteria = val;
    00179           break;
    00180         case 'F':
    00181           fun = val;
    00182           break ;
    00183         default:
    00184           break;
    00185         }
    00186       }
    00187       if ( m_outName.empty() )  {
    00188         log << MSG::ERROR << "Failed to analyze output specs:" << m_output << endmsg;
    00189         return StatusCode::FAILURE;
    00190       }
    00191       if ( fun.length() > 0 || m_criteria.length() > 0 )   {
    00192         if ( m_criteria.length() > 0 && fun.length() == 0 ) fun = "NTuple::Selector";
    00193         m_selectorName = fun;
    00194         return StatusCode::SUCCESS;
    00195       }
    00196       return sc;
    00197     }
    00198     log << MSG::ERROR << "Failed to access service \""
    00199         << m_tupleSvc << "\"." << endmsg;
    00200     return sc;
    00201   }
    00202
    00204   virtual StatusCode finalize() {
    00205     if ( m_dataSvc ) m_dataSvc->release();
    00206     m_dataSvc = 0;
    00207     return StatusCode::SUCCESS;
    00208   }
    00209
    00211   virtual StatusCode execute()    {
    00212     StatusCode status = connect();
    00213     if ( status.isSuccess() )  {
    00214       status = mergeInputTuples();
    00215     }
    00216     return status;
    00217   }
    00218
    00220   virtual StatusCode book(const NTuple::Tuple* nt)  {
    00221     MsgStream log(msgSvc(), name());
    00222     const INTuple::ItemContainer& items = nt->items();
    00223     StatusCode status = StatusCode::SUCCESS;
    00224     INTuple::ItemContainer::const_iterator i;
    00225     NTuple::Tuple* tuple = m_dataSvc->book(m_outName, nt->clID(), nt->title());
    00226     for (i = items.begin(); i != items.end(); ++i)  {
    00227       long type = (*i)->type();
    00228       switch(type)  {
    00229       case DataTypeInfo::UCHAR:
    00230         status = createItem(log, tuple, *i, (unsigned char)0);
    00231         break;
    00232       case DataTypeInfo::USHORT:
    00233         status = createItem(log, tuple, *i, (unsigned short)0);
    00234         break;
    00235       case DataTypeInfo::UINT:
    00236         status = createItem(log, tuple, *i, (unsigned int)0);
    00237         break;
    00238       case DataTypeInfo::ULONG:
    00239         status = createItem(log, tuple, *i, (unsigned long)0);
    00240         break;
    00241       case DataTypeInfo::CHAR:
    00242         status = createItem(log, tuple, *i, char(0));
    00243         break;
    00244       case DataTypeInfo::SHORT:
    00245         status = createItem(log, tuple, *i, short(0));
    00246         break;
    00247       case DataTypeInfo::INT:
    00248         status = createItem(log, tuple, *i, int(0));
    00249         break;
    00250       case DataTypeInfo::LONG:
    00251         status = createItem(log, tuple, *i, long(0));
    00252         break;
    00253       case DataTypeInfo::BOOL:
    00254         status = createItem(log, tuple, *i, false);
    00255         break;
    00256       case DataTypeInfo::FLOAT:
    00257         status = createItem(log, tuple, *i, float(0.0));
    00258         break;
    00259       case DataTypeInfo::DOUBLE:
    00260         status = createItem(log, tuple, *i, double(0.0));
    00261         break;
    00262       case DataTypeInfo::OBJECT_ADDR:
    00263         status = createItem(log, tuple, *i, (IOpaqueAddress*)0);
    00264         break;
    00265       case DataTypeInfo::POINTER:
    00266         status = createItem(log, tuple, *i, (void*)0);
    00267         break;
    00268       case DataTypeInfo::STRING:
    00269 //        status = createItem(log, tuple, *i, (std::string*)0);
    00270 //        break;
    00271       case DataTypeInfo::NTCHAR:
    00272 //        status = createItem(log, tuple, *i, (char*)0);
    00273 //        break;
    00274       case DataTypeInfo::UNKNOWN:
    00275       default:
    00276         status = StatusCode::FAILURE;
    00277         break;
    00278       }
    00279     }
    00280     return status;
    00281   }
    00282
    00283   // Perform some basic checks
    00284   virtual StatusCode checkInput(const NTuple::Tuple* clone, const NTuple::Tuple* src)  {
    00285     MsgStream log(msgSvc(), name());
    00286     if ( 0 != clone && 0 != src )   {
    00287       const INTuple::ItemContainer& clone_items  = clone->items();
    00288       const std::string clone_id = clone->registry()->identifier();
    00289       const std::string src_id = src->registry()->identifier();
    00290
    00291       INTuple::ItemContainer::const_iterator i;
    00292       log << MSG::ERROR;
    00293       for (i = clone_items.begin(); i != clone_items.end(); ++i)  {
    00294         const INTupleItem* itm = *i;
    00295         const std::string& nam = itm->name();
    00296         const INTupleItem* src_itm = src->find(nam);
    00297         if ( !src_itm )  {
    00298           log << "Tuple item " << nam << " not present in " << src_id << endmsg;
    00299           return StatusCode::FAILURE;
    00300         }
    00301         if ( itm->type() != src_itm->type() )  {
    00302           log << "Tuple item " << nam << " are of different types in "
    00303             << src_id   << ":" << src_itm->typeName() << " <-> "
    00304             << clone_id << ":" << itm->typeName() << endmsg;
    00305           return StatusCode::FAILURE;
    00306         }
    00307         if ( itm->ndim() != src_itm->ndim() )  {
    00308           log << "Tuple item " << nam << " have different dimensions in "
    00309             << src_id   << ":" << src_itm->ndim() << " <-> "
    00310             << clone_id << ":" << itm->ndim() << endmsg;
    00311           return StatusCode::FAILURE;
    00312         }
    00313         for (int j=0; j<itm->ndim(); ++j)  {
    00314           if ( src_itm->dim(j) != itm->dim(j) )  {
    00315             log << "Tuple item " << nam << " have different dimensions in "
    00316               << src_id   << "[" << j << "]:" << src_itm->dim(j) << " <-> "
    00317               << clone_id << "[" << j << "]:" << itm->dim(j) << endmsg;
    00318             return StatusCode::FAILURE;
    00319           }
    00320         }
    00321         if ( itm->hasIndex() != src_itm->hasIndex() )  {
    00322           log << "Tuple item " << nam << " has different index colums "
    00323             << src_id   << ":" << src_itm->hasIndex() << " <-> "
    00324             << clone_id << ":" << itm->hasIndex() << endmsg;
    00325           return StatusCode::FAILURE;
    00326         }
    00327         if ( itm->hasIndex() )  {
    00328           if ( itm->index() != src_itm->index() )  {
    00329             log << "Tuple item " << nam << " has different index colums "
    00330               << src_id   << ":" << src_itm->index() << " <-> "
    00331               << clone_id << ":" << itm->index() << endmsg;
    00332             return StatusCode::FAILURE;
    00333           }
    00334         }
    00335       }
    00336       return StatusCode::SUCCESS;
    00337     }
    00338     return StatusCode::FAILURE;
    00339   }
    00340
    00342   StatusCode mergeEntries(const std::string& input)  {
    00343     MsgStream log(msgSvc(), name());
    00344     NTuplePtr out(m_dataSvc, m_outName);
    00345     if ( 0 != out )  {
    00346       const INTuple::ItemContainer& clone_items  = out->items();
    00347       std::vector<GenericAddress> addrVector(clone_items.size());
    00348       StatusCode status = StatusCode::SUCCESS;
    00349       NTuplePtr nt(m_dataSvc, input);
    00350       size_t k = 0, nentry = 0;
    00351       if ( 0 != nt ) {
    00352         const INTuple::ItemContainer& source_items = nt->items();
    00353         for (k=0; k < source_items.size(); ++k )  {
    00354           if ( source_items[k]->type() == DataTypeInfo::OBJECT_ADDR )  {
    00355             *(IOpaqueAddress**)source_items[k]->buffer() = &addrVector[k];
    00356           }
    00357         }
    00358         while ( status.isSuccess() ) {
    00359           status = m_dataSvc->readRecord(nt.ptr());
    00360           if ( status.isSuccess() )   {
    00361             INTuple::ItemContainer::const_iterator i;
    00362             nentry++;
    00363             for (k=0,i = source_items.begin(); i != source_items.end(); ++i,++k)  {
    00364               const INTupleItem* src_itm = *i;
    00365               const INTupleItem* out_itm = out->find(src_itm->name());
    00366               size_t size = 0;
    00367               switch((*i)->type())  {
    00368               case DataTypeInfo::UCHAR:
    00369                 size = sizeof(unsigned char);
    00370                 break;
    00371               case DataTypeInfo::USHORT:
    00372                 size = sizeof(unsigned short);
    00373                 break;
    00374               case DataTypeInfo::UINT:
    00375                 size = sizeof(unsigned int);
    00376                 break;
    00377               case DataTypeInfo::ULONG:
    00378                 size = sizeof(unsigned long);
    00379                 break;
    00380               case DataTypeInfo::CHAR:
    00381                 size = sizeof(char);
    00382                 break;
    00383               case DataTypeInfo::SHORT:
    00384                 size = sizeof(short);
    00385                 break;
    00386               case DataTypeInfo::INT:
    00387                 size = sizeof(int);
    00388                 break;
    00389               case DataTypeInfo::LONG:
    00390                 size = sizeof(long);
    00391                 break;
    00392               case DataTypeInfo::BOOL:
    00393                 size = sizeof(bool);
    00394                 break;
    00395               case DataTypeInfo::FLOAT:
    00396                 size = sizeof(float);
    00397                 break;
    00398               case DataTypeInfo::DOUBLE:
    00399                 size = sizeof(double);
    00400                 break;
    00401               case DataTypeInfo::STRING:
    00402                 *(std::string*)out_itm->buffer() = *(std::string*)src_itm->buffer();
    00403                 size = 0;
    00404                 break;
    00405               case DataTypeInfo::NTCHAR:
    00406                 size = ::strlen((const char*)src_itm->buffer())+1;
    00407                 break;
    00408               case DataTypeInfo::POINTER:
    00409                 {
    00410                   *(void**)out_itm->buffer() = *(void**)src_itm->buffer();
    00411                   size = 0;
    00412                 }
    00413                 break;
    00414               case DataTypeInfo::OBJECT_ADDR:
    00415                 {
    00416                 IOpaqueAddress* ppA1  = &addrVector[k];
    00417                 IOpaqueAddress** ppA2 = (IOpaqueAddress**)out_itm->buffer();
    00418                 *ppA2 = ppA1;
    00419                 size = 0;
    00420                 }
    00421                 break;
    00422               case DataTypeInfo::UNKNOWN:
    00423               default:
    00424                 size = 0;
    00425                 break;
    00426               }
    00427               if ( size > 0 )  {
    00428                 ::memcpy((void*)out_itm->buffer(), src_itm->buffer(), size*src_itm->length());
    00429               }
    00430             }
    00431             status = m_dataSvc->writeRecord(out.ptr());
    00432             if ( !status.isSuccess() )  {
    00433               log << MSG::ERROR << "Failed to write record " << nentry
    00434                   << " from " << input << " to " << m_outName << endmsg;
    00435             }
    00436           }
    00437         }
    00438         log << MSG::INFO << "End of reading tuple " << input
    00439             << " after " << nentry << " entries." << endmsg;
    00440
    00441         if ( nentry > 0 || m_selectorName != "" )  {
    00442           return StatusCode::SUCCESS;
    00443         }
    00444         return StatusCode::FAILURE;
    00445       }
    00446       log << MSG::ERROR << "Failed to access input: " << input << endmsg;
    00447     }
    00448     return StatusCode::FAILURE;
    00449   }
    00450
    00452   StatusCode connect()   {
    00453     StatusCode status = StatusCode::SUCCESS;
    00454     for (size_t i=0; i < m_inputs.size(); ++i)  {
    00455       NTuplePtr nt(m_dataSvc, m_inputs[i]);
    00456       if ( !(0 == nt) )    {
    00457         NTuplePtr out(m_dataSvc, m_outName);
    00458         if ( 0 == out )  {
    00459           status = book(nt);
    00460         }
    00461         else  {
    00462           status = checkInput(out, nt);
    00463         }
    00464         if ( !status.isSuccess() )  {
    00465           return status;
    00466         }
    00467         else if ( m_selectorName != "" )   {
    00468           SmartIF<ISelectStatement> stmt(ROOT::Reflex::PluginService::Create<IInterface*>(m_selectorName,serviceLocator()));
    00469           if ( stmt.isValid( ) )    {
    00470             if ( m_criteria.length() > 0 ) stmt->setCriteria(m_criteria);
    00471             nt->attachSelector(stmt);
    00472           }
    00473           else  {
    00474             MsgStream log(msgSvc(), name());
    00475             log << MSG::ERROR << "Failed to attach tuple selector to " << m_inputs[i] << endmsg;
    00476             return StatusCode::FAILURE;
    00477           }
    00478         }
    00479       }
    00480       else  {
    00481         MsgStream log(msgSvc(), name());
    00482         log << MSG::ERROR << "Failed to access tuple: " << m_inputs[i] << endmsg;
    00483         return StatusCode::FAILURE;
    00484       }
    00485     }
    00486     return StatusCode::SUCCESS;
    00487   }
    00488
    00490   StatusCode mergeInputTuples()  {
    00491     MsgStream log(msgSvc(), name());
    00492     for (size_t inp=0; inp < m_inputs.size(); ++inp)  {
    00493       StatusCode sc = mergeEntries(m_inputs[inp]);
    00494       if ( !sc.isSuccess() )  {
    00495         log << MSG::ERROR << "Failed to merge tuple:" << m_inputs[inp] << endmsg;
    00496         return sc;
    00497       }
    00498     }
    00499     return StatusCode::SUCCESS;
    00500   }
    00501 };
    00502 DECLARE_ALGORITHM_FACTORY(CollectionCloneAlg)

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines