![]() |
|
|
Generated: 8 Jan 2009 |
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!" << endreq; 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 default: 00183 break; 00184 } 00185 } 00186 if ( m_outName.empty() ) { 00187 log << MSG::ERROR << "Failed to analyze output specs:" << m_output << endmsg; 00188 return StatusCode::FAILURE; 00189 } 00190 if ( fun.length() > 0 || m_criteria.length() > 0 ) { 00191 if ( m_criteria.length() > 0 && fun.length() == 0 ) fun = "NTuple::Selector"; 00192 m_selectorName = fun; 00193 return StatusCode::SUCCESS; 00194 } 00195 return sc; 00196 } 00197 log << MSG::ERROR << "Failed to access service \"" 00198 << m_tupleSvc << "\"." << endmsg; 00199 return sc; 00200 } 00201 00203 virtual StatusCode finalize() { 00204 if ( m_dataSvc ) m_dataSvc->release(); 00205 m_dataSvc = 0; 00206 return StatusCode::SUCCESS; 00207 } 00208 00210 virtual StatusCode execute() { 00211 StatusCode status = connect(); 00212 if ( status.isSuccess() ) { 00213 status = mergeInputTuples(); 00214 } 00215 return status; 00216 } 00217 00219 virtual StatusCode book(const NTuple::Tuple* nt) { 00220 MsgStream log(msgSvc(), name()); 00221 const INTuple::ItemContainer& items = nt->items(); 00222 StatusCode status = StatusCode::SUCCESS; 00223 INTuple::ItemContainer::const_iterator i; 00224 NTuple::Tuple* tuple = m_dataSvc->book(m_outName, nt->clID(), nt->title()); 00225 for (i = items.begin(); i != items.end(); ++i) { 00226 long type = (*i)->type(); 00227 switch(type) { 00228 case DataTypeInfo::UCHAR: 00229 status = createItem(log, tuple, *i, (unsigned char)0); 00230 break; 00231 case DataTypeInfo::USHORT: 00232 status = createItem(log, tuple, *i, (unsigned short)0); 00233 break; 00234 case DataTypeInfo::UINT: 00235 status = createItem(log, tuple, *i, (unsigned int)0); 00236 break; 00237 case DataTypeInfo::ULONG: 00238 status = createItem(log, tuple, *i, (unsigned long)0); 00239 break; 00240 case DataTypeInfo::CHAR: 00241 status = createItem(log, tuple, *i, char(0)); 00242 break; 00243 case DataTypeInfo::SHORT: 00244 status = createItem(log, tuple, *i, short(0)); 00245 break; 00246 case DataTypeInfo::INT: 00247 status = createItem(log, tuple, *i, int(0)); 00248 break; 00249 case DataTypeInfo::LONG: 00250 status = createItem(log, tuple, *i, long(0)); 00251 break; 00252 case DataTypeInfo::BOOL: 00253 status = createItem(log, tuple, *i, false); 00254 break; 00255 case DataTypeInfo::FLOAT: 00256 status = createItem(log, tuple, *i, float(0.0)); 00257 break; 00258 case DataTypeInfo::DOUBLE: 00259 status = createItem(log, tuple, *i, double(0.0)); 00260 break; 00261 case DataTypeInfo::OBJECT_ADDR: 00262 status = createItem(log, tuple, *i, (IOpaqueAddress*)0); 00263 break; 00264 case DataTypeInfo::POINTER: 00265 status = createItem(log, tuple, *i, (void*)0); 00266 break; 00267 case DataTypeInfo::STRING: 00268 // status = createItem(log, tuple, *i, (std::string*)0); 00269 // break; 00270 case DataTypeInfo::NTCHAR: 00271 // status = createItem(log, tuple, *i, (char*)0); 00272 // break; 00273 case DataTypeInfo::UNKNOWN: 00274 default: 00275 status = StatusCode::FAILURE; 00276 break; 00277 } 00278 } 00279 return status; 00280 } 00281 00282 // Perform some basic checks 00283 virtual StatusCode checkInput(const NTuple::Tuple* clone, const NTuple::Tuple* src) { 00284 MsgStream log(msgSvc(), name()); 00285 if ( 0 != clone && 0 != src ) { 00286 const INTuple::ItemContainer& clone_items = clone->items(); 00287 const std::string clone_id = clone->registry()->identifier(); 00288 const std::string src_id = src->registry()->identifier(); 00289 00290 INTuple::ItemContainer::const_iterator i; 00291 log << MSG::ERROR; 00292 for (i = clone_items.begin(); i != clone_items.end(); ++i) { 00293 const INTupleItem* itm = *i; 00294 const std::string& nam = itm->name(); 00295 const INTupleItem* src_itm = src->find(nam); 00296 if ( !src_itm ) { 00297 log << "Tuple item " << nam << " not present in " << src_id << endmsg; 00298 return StatusCode::FAILURE; 00299 } 00300 if ( itm->type() != src_itm->type() ) { 00301 log << "Tuple item " << nam << " are of different types in " 00302 << src_id << ":" << src_itm->typeName() << " <-> " 00303 << clone_id << ":" << itm->typeName() << endmsg; 00304 return StatusCode::FAILURE; 00305 } 00306 if ( itm->ndim() != src_itm->ndim() ) { 00307 log << "Tuple item " << nam << " have different dimensions in " 00308 << src_id << ":" << src_itm->ndim() << " <-> " 00309 << clone_id << ":" << itm->ndim() << endmsg; 00310 return StatusCode::FAILURE; 00311 } 00312 for (int j=0; j<itm->ndim(); ++j) { 00313 if ( src_itm->dim(j) != itm->dim(j) ) { 00314 log << "Tuple item " << nam << " have different dimensions in " 00315 << src_id << "[" << j << "]:" << src_itm->dim(j) << " <-> " 00316 << clone_id << "[" << j << "]:" << itm->dim(j) << endmsg; 00317 return StatusCode::FAILURE; 00318 } 00319 } 00320 if ( itm->hasIndex() != src_itm->hasIndex() ) { 00321 log << "Tuple item " << nam << " has different index colums " 00322 << src_id << ":" << src_itm->hasIndex() << " <-> " 00323 << clone_id << ":" << itm->hasIndex() << endmsg; 00324 return StatusCode::FAILURE; 00325 } 00326 if ( itm->hasIndex() ) { 00327 if ( itm->index() != src_itm->index() ) { 00328 log << "Tuple item " << nam << " has different index colums " 00329 << src_id << ":" << src_itm->index() << " <-> " 00330 << clone_id << ":" << itm->index() << endmsg; 00331 return StatusCode::FAILURE; 00332 } 00333 } 00334 } 00335 return StatusCode::SUCCESS; 00336 } 00337 return StatusCode::FAILURE; 00338 } 00339 00341 StatusCode mergeEntries(const std::string& input) { 00342 MsgStream log(msgSvc(), name()); 00343 NTuplePtr out(m_dataSvc, m_outName); 00344 if ( 0 != out ) { 00345 const INTuple::ItemContainer& clone_items = out->items(); 00346 std::vector<GenericAddress> addrVector(clone_items.size()); 00347 StatusCode status = StatusCode::SUCCESS; 00348 NTuplePtr nt(m_dataSvc, input); 00349 size_t k = 0, nentry = 0; 00350 if ( 0 != nt ) { 00351 const INTuple::ItemContainer& source_items = nt->items(); 00352 for (k=0; k < source_items.size(); ++k ) { 00353 if ( source_items[k]->type() == DataTypeInfo::OBJECT_ADDR ) { 00354 *(IOpaqueAddress**)source_items[k]->buffer() = &addrVector[k]; 00355 } 00356 } 00357 while ( status.isSuccess() ) { 00358 status = m_dataSvc->readRecord(nt.ptr()); 00359 if ( status.isSuccess() ) { 00360 INTuple::ItemContainer::const_iterator i; 00361 nentry++; 00362 for (k=0,i = source_items.begin(); i != source_items.end(); ++i,++k) { 00363 const INTupleItem* src_itm = *i; 00364 const INTupleItem* out_itm = out->find(src_itm->name()); 00365 size_t size = 0; 00366 switch((*i)->type()) { 00367 case DataTypeInfo::UCHAR: 00368 size = sizeof(unsigned char); 00369 break; 00370 case DataTypeInfo::USHORT: 00371 size = sizeof(unsigned short); 00372 break; 00373 case DataTypeInfo::UINT: 00374 size = sizeof(unsigned int); 00375 break; 00376 case DataTypeInfo::ULONG: 00377 size = sizeof(unsigned long); 00378 break; 00379 case DataTypeInfo::CHAR: 00380 size = sizeof(char); 00381 break; 00382 case DataTypeInfo::SHORT: 00383 size = sizeof(short); 00384 break; 00385 case DataTypeInfo::INT: 00386 size = sizeof(int); 00387 break; 00388 case DataTypeInfo::LONG: 00389 size = sizeof(long); 00390 break; 00391 case DataTypeInfo::BOOL: 00392 size = sizeof(bool); 00393 break; 00394 case DataTypeInfo::FLOAT: 00395 size = sizeof(float); 00396 break; 00397 case DataTypeInfo::DOUBLE: 00398 size = sizeof(double); 00399 break; 00400 case DataTypeInfo::STRING: 00401 *(std::string*)out_itm->buffer() = *(std::string*)src_itm->buffer(); 00402 size = 0; 00403 break; 00404 case DataTypeInfo::NTCHAR: 00405 size = ::strlen((const char*)src_itm->buffer())+1; 00406 break; 00407 case DataTypeInfo::POINTER: 00408 { 00409 *(void**)out_itm->buffer() = *(void**)src_itm->buffer(); 00410 size = 0; 00411 } 00412 break; 00413 case DataTypeInfo::OBJECT_ADDR: 00414 { 00415 IOpaqueAddress* ppA1 = &addrVector[k]; 00416 IOpaqueAddress** ppA2 = (IOpaqueAddress**)out_itm->buffer(); 00417 *ppA2 = ppA1; 00418 size = 0; 00419 } 00420 break; 00421 case DataTypeInfo::UNKNOWN: 00422 default: 00423 size = 0; 00424 break; 00425 } 00426 if ( size > 0 ) { 00427 ::memcpy((void*)out_itm->buffer(), src_itm->buffer(), size*src_itm->length()); 00428 } 00429 } 00430 status = m_dataSvc->writeRecord(out.ptr()); 00431 if ( !status.isSuccess() ) { 00432 log << MSG::ERROR << "Failed to write record " << nentry 00433 << " from " << input << " to " << m_outName << endmsg; 00434 } 00435 } 00436 } 00437 log << MSG::INFO << "End of reading tuple " << input 00438 << " after " << nentry << " entries." << endmsg; 00439 00440 if ( nentry > 0 || m_selectorName != "" ) { 00441 return StatusCode::SUCCESS; 00442 } 00443 return StatusCode::FAILURE; 00444 } 00445 log << MSG::ERROR << "Failed to access input: " << input << endmsg; 00446 } 00447 return StatusCode::FAILURE; 00448 } 00449 00451 StatusCode connect() { 00452 StatusCode status = StatusCode::SUCCESS; 00453 for (size_t i=0; i < m_inputs.size(); ++i) { 00454 NTuplePtr nt(m_dataSvc, m_inputs[i]); 00455 if ( !(0 == nt) ) { 00456 NTuplePtr out(m_dataSvc, m_outName); 00457 if ( 0 == out ) { 00458 status = book(nt); 00459 } 00460 else { 00461 status = checkInput(out, nt); 00462 } 00463 if ( !status.isSuccess() ) { 00464 return status; 00465 } 00466 else if ( m_selectorName != "" ) { 00467 SmartIF<ISelectStatement> stmt(ROOT::Reflex::PluginService::Create<IInterface*>(m_selectorName,serviceLocator())); 00468 if ( stmt.isValid( ) ) { 00469 if ( m_criteria.length() > 0 ) stmt->setCriteria(m_criteria); 00470 nt->attachSelector(stmt); 00471 } 00472 else { 00473 MsgStream log(msgSvc(), name()); 00474 log << MSG::ERROR << "Failed to attach tuple selector to " << m_inputs[i] << endmsg; 00475 return StatusCode::FAILURE; 00476 } 00477 } 00478 } 00479 else { 00480 MsgStream log(msgSvc(), name()); 00481 log << MSG::ERROR << "Failed to access tuple: " << m_inputs[i] << endmsg; 00482 return StatusCode::FAILURE; 00483 } 00484 } 00485 return StatusCode::SUCCESS; 00486 } 00487 00489 StatusCode mergeInputTuples() { 00490 MsgStream log(msgSvc(), name()); 00491 for (size_t inp=0; inp < m_inputs.size(); ++inp) { 00492 StatusCode sc = mergeEntries(m_inputs[inp]); 00493 if ( !sc.isSuccess() ) { 00494 log << MSG::ERROR << "Failed to merge tuple:" << m_inputs[inp] << endmsg; 00495 return sc; 00496 } 00497 } 00498 return StatusCode::SUCCESS; 00499 } 00500 }; 00501 DECLARE_ALGORITHM_FACTORY(CollectionCloneAlg)