The Gaudi Framework  v30r1 (5d4f4ae2)
CollectionCloneAlg.cpp
Go to the documentation of this file.
1 // ====================================================================
2 // CollectionCloneAlg.cpp
3 // --------------------------------------------------------------------
4 //
5 // Author : Markus Frank
6 //
7 // ====================================================================
13 #include "GaudiKernel/IRegistry.h"
15 #include "GaudiKernel/MsgStream.h"
16 #include "GaudiKernel/NTuple.h"
19 #include "GaudiKernel/SmartIF.h"
20 #include <vector>
21 
22 namespace
23 {
24  template <class T>
25  static long upper( const INTupleItem* item )
26  {
27  const NTuple::_Data<T>* it = dynamic_cast<const NTuple::_Data<T>*>( item );
28  return long( it->range().upper() );
29  }
30 
31  template <class TYP>
32  static StatusCode createItem( MsgStream& log, INTuple* tuple, INTupleItem* src, const TYP& null )
33  {
34  NTuple::_Data<TYP>* source = dynamic_cast<NTuple::_Data<TYP>*>( src );
35  TYP low = source->range().lower();
36  TYP high = source->range().upper();
37  long hasIdx = source->hasIndex();
38  long ndim = source->ndim();
39  const std::string& name = source->name();
40  std::string idxName;
41  long dim[4], idxLen = 0;
42  long dim1 = 1, dim2 = 1;
43  INTupleItem* it = 0;
44  for ( int i = 0; i < ndim; i++ ) dim[i] = source->dim( i );
46  if ( hasIdx ) {
47  const INTupleItem* index = source->indexItem();
48  idxName = index->name();
49  switch ( index->type() ) {
51  idxLen = upper<unsigned char>( index );
52  break;
54  idxLen = upper<unsigned short>( index );
55  break;
56  case DataTypeInfo::UINT:
57  idxLen = upper<unsigned int>( index );
58  break;
60  idxLen = upper<unsigned long>( index );
61  break;
62  case DataTypeInfo::CHAR:
63  idxLen = upper<char>( index );
64  break;
66  idxLen = upper<short>( index );
67  break;
68  case DataTypeInfo::INT:
69  idxLen = upper<int>( index );
70  break;
71  case DataTypeInfo::LONG:
72  idxLen = upper<long>( index );
73  break;
74  default:
75  log << MSG::ERROR << "Column " << idxName << " is not a valid index column!" << endmsg;
76  return StatusCode::FAILURE;
77  }
78  }
79  switch ( ndim ) {
80  case 0:
81  it = NTuple::_Item<TYP>::create( tuple, name, typeid( TYP ), low, high, null );
82  break;
83  case 1:
84  dim1 = ( hasIdx ) ? idxLen : dim[0];
85  it = NTuple::_Array<TYP>::create( tuple, name, typeid( TYP ), idxName, dim1, low, high, null );
86  break;
87  case 2:
88  dim1 = ( hasIdx ) ? idxLen : dim[0];
89  dim2 = ( hasIdx ) ? dim[0] : dim[1];
90  it = NTuple::_Matrix<TYP>::create( tuple, name, typeid( TYP ), idxName, dim1, dim2, low, high, null );
91  break;
92  default:
93  return StatusCode::FAILURE;
94  }
95  return tuple->add( it );
96  }
97 }
98 
110 {
111 
112  Gaudi::Property<std::string> m_tupleSvc{this, "EvtTupleSvc", "EvtTupleSvc", "name of the data provider service"};
113  Gaudi::Property<std::vector<std::string>> m_inputs{this, "Input", {}, "input specifications"};
114  Gaudi::Property<std::string> m_output{this, "Output", {}, "output specification"};
115 
126 
127 public:
129  using Algorithm::Algorithm;
130 
133  {
134  MsgStream log( msgSvc(), name() );
135  m_rootName = "";
136  m_outName = "";
137  m_criteria = "";
138  m_selectorName = "";
139  m_dataSvc = service( m_tupleSvc, true );
140  if ( !m_dataSvc ) {
141  log << MSG::ERROR << "Failed to access service \"" << m_tupleSvc << "\"." << endmsg;
142  return StatusCode::FAILURE;
143  }
145  using Parser = Gaudi::Utils::AttribStringParser;
146  for ( auto attrib : Parser( m_output ) ) {
147  switch (::toupper( attrib.tag[0] ) ) {
148  case 'D':
149  m_outName = std::move( attrib.value );
150  break;
151  case 'S':
152  m_criteria = std::move( attrib.value );
153  break;
154  case 'F':
155  fun = std::move( attrib.value );
156  break;
157  default:
158  break;
159  }
160  }
161  if ( m_outName.empty() ) {
162  log << MSG::ERROR << "Failed to analyze output specs:" << m_output << endmsg;
163  return StatusCode::FAILURE;
164  }
165  if ( !fun.empty() || !m_criteria.empty() ) {
166  if ( !m_criteria.empty() && fun.empty() ) fun = "NTuple::Selector";
167  m_selectorName = fun;
168  }
169  return StatusCode::SUCCESS;
170  }
171 
173  StatusCode finalize() override
174  {
175  m_dataSvc.reset();
176  return StatusCode::SUCCESS;
177  }
178 
180  StatusCode execute() override
181  {
182  StatusCode status = connect();
183  if ( status.isSuccess() ) {
184  status = mergeInputTuples();
185  }
186  return status;
187  }
188 
190  virtual StatusCode book( const NTuple::Tuple* nt )
191  {
192  MsgStream log( msgSvc(), name() );
193  const INTuple::ItemContainer& items = nt->items();
195  INTuple::ItemContainer::const_iterator i;
196  NTuple::Tuple* tuple = m_dataSvc->book( m_outName, nt->clID(), nt->title() );
197  for ( i = items.begin(); i != items.end(); ++i ) {
198  long type = ( *i )->type();
199  switch ( type ) {
200  case DataTypeInfo::UCHAR:
201  status = createItem( log, tuple, *i, (unsigned char)0 );
202  break;
204  status = createItem( log, tuple, *i, (unsigned short)0 );
205  break;
206  case DataTypeInfo::UINT:
207  status = createItem( log, tuple, *i, (unsigned int)0 );
208  break;
209  case DataTypeInfo::ULONG:
210  status = createItem( log, tuple, *i, (unsigned long)0 );
211  break;
212  case DataTypeInfo::CHAR:
213  status = createItem( log, tuple, *i, char( 0 ) );
214  break;
215  case DataTypeInfo::SHORT:
216  status = createItem( log, tuple, *i, short( 0 ) );
217  break;
218  case DataTypeInfo::INT:
219  status = createItem( log, tuple, *i, int( 0 ) );
220  break;
221  case DataTypeInfo::LONG:
222  status = createItem( log, tuple, *i, long( 0 ) );
223  break;
224  case DataTypeInfo::BOOL:
225  status = createItem( log, tuple, *i, false );
226  break;
227  case DataTypeInfo::FLOAT:
228  status = createItem( log, tuple, *i, float( 0.0 ) );
229  break;
231  status = createItem( log, tuple, *i, double( 0.0 ) );
232  break;
234  status = createItem( log, tuple, *i, (IOpaqueAddress*)0 );
235  break;
237  status = createItem( log, tuple, *i, (void*)0 );
238  break;
240  // status = createItem(log, tuple, *i, (std::string*)0);
241  // break;
243  // status = createItem(log, tuple, *i, (char*)0);
244  // break;
246  default:
247  status = StatusCode::FAILURE;
248  break;
249  }
250  }
251  return status;
252  }
253 
254  // Perform some basic checks
255  virtual StatusCode checkInput( const NTuple::Tuple* clone, const NTuple::Tuple* src )
256  {
257  MsgStream log( msgSvc(), name() );
258  if ( 0 != clone && 0 != src ) {
259  const INTuple::ItemContainer& clone_items = clone->items();
260  const std::string clone_id = clone->registry()->identifier();
261  const std::string src_id = src->registry()->identifier();
262 
263  INTuple::ItemContainer::const_iterator i;
264  log << MSG::ERROR;
265  for ( i = clone_items.begin(); i != clone_items.end(); ++i ) {
266  const INTupleItem* itm = *i;
267  const std::string& nam = itm->name();
268  const INTupleItem* src_itm = src->find( nam );
269  if ( !src_itm ) {
270  log << "Tuple item " << nam << " not present in " << src_id << endmsg;
271  return StatusCode::FAILURE;
272  }
273  if ( itm->type() != src_itm->type() ) {
274  log << "Tuple item " << nam << " are of different types in " << src_id << ":" << src_itm->typeName()
275  << " <-> " << clone_id << ":" << itm->typeName() << endmsg;
276  return StatusCode::FAILURE;
277  }
278  if ( itm->ndim() != src_itm->ndim() ) {
279  log << "Tuple item " << nam << " have different dimensions in " << src_id << ":" << src_itm->ndim() << " <-> "
280  << clone_id << ":" << itm->ndim() << endmsg;
281  return StatusCode::FAILURE;
282  }
283  for ( int j = 0; j < itm->ndim(); ++j ) {
284  if ( src_itm->dim( j ) != itm->dim( j ) ) {
285  log << "Tuple item " << nam << " have different dimensions in " << src_id << "[" << j
286  << "]:" << src_itm->dim( j ) << " <-> " << clone_id << "[" << j << "]:" << itm->dim( j ) << endmsg;
287  return StatusCode::FAILURE;
288  }
289  }
290  if ( itm->hasIndex() != src_itm->hasIndex() ) {
291  log << "Tuple item " << nam << " has different index colums " << src_id << ":" << src_itm->hasIndex()
292  << " <-> " << clone_id << ":" << itm->hasIndex() << endmsg;
293  return StatusCode::FAILURE;
294  }
295  if ( itm->hasIndex() ) {
296  if ( itm->index() != src_itm->index() ) {
297  log << "Tuple item " << nam << " has different index colums " << src_id << ":" << src_itm->index()
298  << " <-> " << clone_id << ":" << itm->index() << endmsg;
299  return StatusCode::FAILURE;
300  }
301  }
302  }
303  return StatusCode::SUCCESS;
304  }
305  return StatusCode::FAILURE;
306  }
307 
310  {
311  MsgStream log( msgSvc(), name() );
312  NTuplePtr out( m_dataSvc.get(), m_outName );
313  if ( 0 != out ) {
314  const INTuple::ItemContainer& clone_items = out->items();
315  std::vector<GenericAddress> addrVector( clone_items.size() );
317  NTuplePtr nt( m_dataSvc.get(), input );
318  size_t k = 0, nentry = 0;
319  if ( 0 != nt ) {
320  const INTuple::ItemContainer& source_items = nt->items();
321  for ( k = 0; k < source_items.size(); ++k ) {
322  if ( source_items[k]->type() == DataTypeInfo::OBJECT_ADDR ) {
323  *(IOpaqueAddress**)source_items[k]->buffer() = &addrVector[k];
324  }
325  }
326  while ( status.isSuccess() ) {
327  status = m_dataSvc->readRecord( nt.ptr() );
328  if ( status.isSuccess() ) {
329  INTuple::ItemContainer::const_iterator i;
330  nentry++;
331  for ( k = 0, i = source_items.begin(); i != source_items.end(); ++i, ++k ) {
332  const INTupleItem* src_itm = *i;
333  const INTupleItem* out_itm = out->find( src_itm->name() );
334  size_t size = 0;
335  switch ( ( *i )->type() ) {
336  case DataTypeInfo::UCHAR:
337  size = sizeof( unsigned char );
338  break;
340  size = sizeof( unsigned short );
341  break;
342  case DataTypeInfo::UINT:
343  size = sizeof( unsigned int );
344  break;
345  case DataTypeInfo::ULONG:
346  size = sizeof( unsigned long );
347  break;
348  case DataTypeInfo::CHAR:
349  size = sizeof( char );
350  break;
351  case DataTypeInfo::SHORT:
352  size = sizeof( short );
353  break;
354  case DataTypeInfo::INT:
355  size = sizeof( int );
356  break;
357  case DataTypeInfo::LONG:
358  size = sizeof( long );
359  break;
360  case DataTypeInfo::BOOL:
361  size = sizeof( bool );
362  break;
363  case DataTypeInfo::FLOAT:
364  size = sizeof( float );
365  break;
367  size = sizeof( double );
368  break;
370  *(std::string*)out_itm->buffer() = *(std::string*)src_itm->buffer();
371  size = 0;
372  break;
374  size = ::strlen( (const char*)src_itm->buffer() ) + 1;
375  break;
376  case DataTypeInfo::POINTER: {
377  *(void**)out_itm->buffer() = *(void**)src_itm->buffer();
378  size = 0;
379  } break;
381  IOpaqueAddress* ppA1 = &addrVector[k];
382  IOpaqueAddress** ppA2 = (IOpaqueAddress**)out_itm->buffer();
383  *ppA2 = ppA1;
384  size = 0;
385  } break;
387  default:
388  size = 0;
389  break;
390  }
391  if ( size > 0 ) {
392  ::memcpy( (void*)out_itm->buffer(), src_itm->buffer(), size * src_itm->length() );
393  }
394  }
395  status = m_dataSvc->writeRecord( out.ptr() );
396  if ( !status.isSuccess() ) {
397  log << MSG::ERROR << "Failed to write record " << nentry << " from " << input << " to " << m_outName
398  << endmsg;
399  }
400  }
401  }
402  log << MSG::INFO << "End of reading tuple " << input << " after " << nentry << " entries." << endmsg;
403 
404  if ( nentry > 0 || m_selectorName != "" ) {
405  return StatusCode::SUCCESS;
406  }
407  return StatusCode::FAILURE;
408  }
409  log << MSG::ERROR << "Failed to access input: " << input << endmsg;
410  }
411  return StatusCode::FAILURE;
412  }
413 
416  {
418  for ( size_t i = 0; i < m_inputs.size(); ++i ) {
419  NTuplePtr nt( m_dataSvc.get(), m_inputs[i] );
420  if ( !( 0 == nt ) ) {
421  NTuplePtr out( m_dataSvc.get(), m_outName );
422  if ( 0 == out ) {
423  status = book( nt );
424  } else {
425  status = checkInput( out, nt );
426  }
427  if ( !status.isSuccess() ) {
428  return status;
429  } else if ( m_selectorName != "" ) {
430  SmartIF<ISelectStatement> stmt( ObjFactory::create( m_selectorName, serviceLocator() ) );
431  if ( stmt ) {
432  if ( !m_criteria.empty() ) stmt->setCriteria( m_criteria );
433  nt->attachSelector( stmt );
434  } else {
435  MsgStream log( msgSvc(), name() );
436  log << MSG::ERROR << "Failed to attach tuple selector to " << m_inputs[i] << endmsg;
437  return StatusCode::FAILURE;
438  }
439  }
440  } else {
441  MsgStream log( msgSvc(), name() );
442  log << MSG::ERROR << "Failed to access tuple: " << m_inputs[i] << endmsg;
443  return StatusCode::FAILURE;
444  }
445  }
446  return StatusCode::SUCCESS;
447  }
448 
451  {
452  MsgStream log( msgSvc(), name() );
453  for ( const auto& input : m_inputs ) {
454  StatusCode sc = mergeEntries( input );
455  if ( !sc.isSuccess() ) {
456  log << MSG::ERROR << "Failed to merge tuple:" << input << endmsg;
457  return sc;
458  }
459  }
460  return StatusCode::SUCCESS;
461  }
462 };
Parse attribute strings allowing iteration over the various attributes.
virtual const std::string & name() const =0
Access _Item name.
std::string m_criteria
Selection criteria (if any)
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:24
virtual const ItemRange & range() const =0
Access the range if specified.
T empty(T...args)
const std::string & name() const override
The identifying name of the algorithm object.
Definition: Algorithm.cpp:737
StatusCode execute() override
Execute procedure.
Implementation of property with value of concrete type.
Definition: Property.h:319
virtual StatusCode book(const NTuple::Tuple *nt)
Book the N-tuple according to the specification.
StatusCode initialize() override
Initialize.
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:50
virtual StatusCode add(INTupleItem *item)=0
Add an item row to the N tuple.
T end(T...args)
Gaudi::Property< std::vector< std::string > > m_inputs
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:73
constexpr auto size(const C &c) noexcept(noexcept(c.size())) -> decltype(c.size())
static _Array * create(INTuple *tup, const std::string &name, const std::type_info &info, const std::string &index, long len, TYP min, TYP max, TYP def)
Create instance.
Definition: NTupleItems.cpp:34
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:33
SmartIF< INTupleSvc > m_dataSvc
Reference to data provider service.
STL class.
StatusCode mergeEntries(const std::string &input)
Merge the entries of a single input tuple into the output.
NTuple interface class definition.
Definition: INTuple.h:82
TYPE * get() const
Get interface pointer.
Definition: SmartIF.h:82
virtual std::string typeName() const =0
Proper type name of the object.
virtual long ndim() const =0
Dimension.
NTuple interface class definition.
Definition: INTuple.h:27
virtual const CLID & clID() const
Retrieve reference to class definition structure.
Definition: DataObject.cpp:62
virtual const id_type & identifier() const =0
Full identifier (or key)
virtual INTupleItem * indexItem()=0
Pointer to index column (if present, 0 else)
virtual long length() const =0
Access the buffer length.
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
virtual StatusCode writeRecord(NTuple::Tuple *tuple)=0
Write single record to N tuple.
std::string m_outName
Output tuple name.
StatusCode mergeInputTuples()
Merge all N-tuple entries.
const SmartIF< IMessageSvc > & msgSvc() const
The standard message service.
Abstract class describing basic data in an Ntuple.
Definition: NTuple.h:39
virtual StatusCode checkInput(const NTuple::Tuple *clone, const NTuple::Tuple *src)
virtual long type() const =0
Type information of the item.
Algorithm(const std::string &name, ISvcLocator *svcloc, const std::string &version=PACKAGE_VERSION)
Constructor.
Definition: Algorithm.cpp:47
T move(T...args)
SmartIF< ISvcLocator > & serviceLocator() const override
The standard service locator.
Definition: Algorithm.cpp:806
std::string m_rootName
Name of the root leaf (obtained at initialize)
Abstract base class which allows the user to interact with the actual N tuple implementation.
Definition: NTuple.h:407
virtual const void * buffer() const =0
Access data buffer (CONST)
StatusCode finalize() override
Finalize.
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:78
T size(T...args)
STL class.
T begin(T...args)
StatusCode connect()
Connect input and output N-tuples.
virtual const std::string & index() const =0
Access the index _Item.
double fun(const std::vector< double > &x)
Definition: PFuncTest.cpp:26
Gaudi::Property< std::string > m_output
Small algorithm, which allows to merge N-tuples in a generic way.
Gaudi::Property< std::string > m_tupleSvc
virtual StatusCode readRecord(NTuple::Tuple *tuple)=0
Read single record from N tuple.
A small class used to access easily (and efficiently) data items residing in data stores...
Definition: SmartDataPtr.h:47
virtual long dim(long i) const =0
Access individual dimensions.
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:92
virtual ItemContainer & items()=0
Access item container.
static _Item * create(INTuple *tup, const std::string &name, const std::type_info &info, TYP min, TYP max, TYP def)
Create instance.
Definition: NTupleItems.cpp:26
virtual bool hasIndex() const =0
Is the tuple have an index item?
StatusCode service(const std::string &name, T *&psvc, bool createIf=true) const
Access a service by name, creating it if it doesn&#39;t already exist.
Definition: Algorithm.h:232
Opaque address interface definition.
const std::string & type() const override
The type of the algorithm object.
Definition: Algorithm.h:167
virtual const INTupleItem * find(const std::string &name) const =0
Find an item row of the Ntuple (CONST)
std::string m_selectorName
Selector factory.
virtual void setCriteria(const std::string &crit)=0
Set the type.
virtual const std::string & title() const =0
Object title.
void toupper(std::string &s)
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:209
virtual NTuple::Tuple * book(const std::string &fullPath, const CLID &type, const std::string &title)=0
Book Ntuple and register it with the data store.
static _Matrix * create(INTuple *tup, const std::string &name, const std::type_info &info, const std::string &index, long ncol, long nrow, TYP min, TYP max, TYP def)
Create instance.
Definition: NTupleItems.cpp:42