The Gaudi Framework  v29r0 (ff2e7097)
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 
132  ~CollectionCloneAlg() override = default;
133 
136  {
137  MsgStream log( msgSvc(), name() );
138  m_rootName = "";
139  m_outName = "";
140  m_criteria = "";
141  m_selectorName = "";
142  m_dataSvc = service( m_tupleSvc, true );
143  if ( !m_dataSvc ) {
144  log << MSG::ERROR << "Failed to access service \"" << m_tupleSvc << "\"." << endmsg;
145  return StatusCode::FAILURE;
146  }
148  using Parser = Gaudi::Utils::AttribStringParser;
149  for ( auto attrib : Parser( m_output ) ) {
150  switch (::toupper( attrib.tag[0] ) ) {
151  case 'D':
152  m_outName = std::move( attrib.value );
153  break;
154  case 'S':
155  m_criteria = std::move( attrib.value );
156  break;
157  case 'F':
158  fun = std::move( attrib.value );
159  break;
160  default:
161  break;
162  }
163  }
164  if ( m_outName.empty() ) {
165  log << MSG::ERROR << "Failed to analyze output specs:" << m_output << endmsg;
166  return StatusCode::FAILURE;
167  }
168  if ( !fun.empty() || !m_criteria.empty() ) {
169  if ( !m_criteria.empty() && fun.empty() ) fun = "NTuple::Selector";
170  m_selectorName = fun;
171  }
172  return StatusCode::SUCCESS;
173  }
174 
176  StatusCode finalize() override
177  {
178  m_dataSvc.reset();
179  return StatusCode::SUCCESS;
180  }
181 
183  StatusCode execute() override
184  {
185  StatusCode status = connect();
186  if ( status.isSuccess() ) {
187  status = mergeInputTuples();
188  }
189  return status;
190  }
191 
193  virtual StatusCode book( const NTuple::Tuple* nt )
194  {
195  MsgStream log( msgSvc(), name() );
196  const INTuple::ItemContainer& items = nt->items();
198  INTuple::ItemContainer::const_iterator i;
199  NTuple::Tuple* tuple = m_dataSvc->book( m_outName, nt->clID(), nt->title() );
200  for ( i = items.begin(); i != items.end(); ++i ) {
201  long type = ( *i )->type();
202  switch ( type ) {
203  case DataTypeInfo::UCHAR:
204  status = createItem( log, tuple, *i, (unsigned char)0 );
205  break;
207  status = createItem( log, tuple, *i, (unsigned short)0 );
208  break;
209  case DataTypeInfo::UINT:
210  status = createItem( log, tuple, *i, (unsigned int)0 );
211  break;
212  case DataTypeInfo::ULONG:
213  status = createItem( log, tuple, *i, (unsigned long)0 );
214  break;
215  case DataTypeInfo::CHAR:
216  status = createItem( log, tuple, *i, char( 0 ) );
217  break;
218  case DataTypeInfo::SHORT:
219  status = createItem( log, tuple, *i, short( 0 ) );
220  break;
221  case DataTypeInfo::INT:
222  status = createItem( log, tuple, *i, int( 0 ) );
223  break;
224  case DataTypeInfo::LONG:
225  status = createItem( log, tuple, *i, long( 0 ) );
226  break;
227  case DataTypeInfo::BOOL:
228  status = createItem( log, tuple, *i, false );
229  break;
230  case DataTypeInfo::FLOAT:
231  status = createItem( log, tuple, *i, float( 0.0 ) );
232  break;
234  status = createItem( log, tuple, *i, double( 0.0 ) );
235  break;
237  status = createItem( log, tuple, *i, (IOpaqueAddress*)0 );
238  break;
240  status = createItem( log, tuple, *i, (void*)0 );
241  break;
243  // status = createItem(log, tuple, *i, (std::string*)0);
244  // break;
246  // status = createItem(log, tuple, *i, (char*)0);
247  // break;
249  default:
250  status = StatusCode::FAILURE;
251  break;
252  }
253  }
254  return status;
255  }
256 
257  // Perform some basic checks
258  virtual StatusCode checkInput( const NTuple::Tuple* clone, const NTuple::Tuple* src )
259  {
260  MsgStream log( msgSvc(), name() );
261  if ( 0 != clone && 0 != src ) {
262  const INTuple::ItemContainer& clone_items = clone->items();
263  const std::string clone_id = clone->registry()->identifier();
264  const std::string src_id = src->registry()->identifier();
265 
266  INTuple::ItemContainer::const_iterator i;
267  log << MSG::ERROR;
268  for ( i = clone_items.begin(); i != clone_items.end(); ++i ) {
269  const INTupleItem* itm = *i;
270  const std::string& nam = itm->name();
271  const INTupleItem* src_itm = src->find( nam );
272  if ( !src_itm ) {
273  log << "Tuple item " << nam << " not present in " << src_id << endmsg;
274  return StatusCode::FAILURE;
275  }
276  if ( itm->type() != src_itm->type() ) {
277  log << "Tuple item " << nam << " are of different types in " << src_id << ":" << src_itm->typeName()
278  << " <-> " << clone_id << ":" << itm->typeName() << endmsg;
279  return StatusCode::FAILURE;
280  }
281  if ( itm->ndim() != src_itm->ndim() ) {
282  log << "Tuple item " << nam << " have different dimensions in " << src_id << ":" << src_itm->ndim() << " <-> "
283  << clone_id << ":" << itm->ndim() << endmsg;
284  return StatusCode::FAILURE;
285  }
286  for ( int j = 0; j < itm->ndim(); ++j ) {
287  if ( src_itm->dim( j ) != itm->dim( j ) ) {
288  log << "Tuple item " << nam << " have different dimensions in " << src_id << "[" << j
289  << "]:" << src_itm->dim( j ) << " <-> " << clone_id << "[" << j << "]:" << itm->dim( j ) << endmsg;
290  return StatusCode::FAILURE;
291  }
292  }
293  if ( itm->hasIndex() != src_itm->hasIndex() ) {
294  log << "Tuple item " << nam << " has different index colums " << src_id << ":" << src_itm->hasIndex()
295  << " <-> " << clone_id << ":" << itm->hasIndex() << endmsg;
296  return StatusCode::FAILURE;
297  }
298  if ( itm->hasIndex() ) {
299  if ( itm->index() != src_itm->index() ) {
300  log << "Tuple item " << nam << " has different index colums " << src_id << ":" << src_itm->index()
301  << " <-> " << clone_id << ":" << itm->index() << endmsg;
302  return StatusCode::FAILURE;
303  }
304  }
305  }
306  return StatusCode::SUCCESS;
307  }
308  return StatusCode::FAILURE;
309  }
310 
313  {
314  MsgStream log( msgSvc(), name() );
315  NTuplePtr out( m_dataSvc.get(), m_outName );
316  if ( 0 != out ) {
317  const INTuple::ItemContainer& clone_items = out->items();
318  std::vector<GenericAddress> addrVector( clone_items.size() );
320  NTuplePtr nt( m_dataSvc.get(), input );
321  size_t k = 0, nentry = 0;
322  if ( 0 != nt ) {
323  const INTuple::ItemContainer& source_items = nt->items();
324  for ( k = 0; k < source_items.size(); ++k ) {
325  if ( source_items[k]->type() == DataTypeInfo::OBJECT_ADDR ) {
326  *(IOpaqueAddress**)source_items[k]->buffer() = &addrVector[k];
327  }
328  }
329  while ( status.isSuccess() ) {
330  status = m_dataSvc->readRecord( nt.ptr() );
331  if ( status.isSuccess() ) {
332  INTuple::ItemContainer::const_iterator i;
333  nentry++;
334  for ( k = 0, i = source_items.begin(); i != source_items.end(); ++i, ++k ) {
335  const INTupleItem* src_itm = *i;
336  const INTupleItem* out_itm = out->find( src_itm->name() );
337  size_t size = 0;
338  switch ( ( *i )->type() ) {
339  case DataTypeInfo::UCHAR:
340  size = sizeof( unsigned char );
341  break;
343  size = sizeof( unsigned short );
344  break;
345  case DataTypeInfo::UINT:
346  size = sizeof( unsigned int );
347  break;
348  case DataTypeInfo::ULONG:
349  size = sizeof( unsigned long );
350  break;
351  case DataTypeInfo::CHAR:
352  size = sizeof( char );
353  break;
354  case DataTypeInfo::SHORT:
355  size = sizeof( short );
356  break;
357  case DataTypeInfo::INT:
358  size = sizeof( int );
359  break;
360  case DataTypeInfo::LONG:
361  size = sizeof( long );
362  break;
363  case DataTypeInfo::BOOL:
364  size = sizeof( bool );
365  break;
366  case DataTypeInfo::FLOAT:
367  size = sizeof( float );
368  break;
370  size = sizeof( double );
371  break;
373  *(std::string*)out_itm->buffer() = *(std::string*)src_itm->buffer();
374  size = 0;
375  break;
377  size = ::strlen( (const char*)src_itm->buffer() ) + 1;
378  break;
379  case DataTypeInfo::POINTER: {
380  *(void**)out_itm->buffer() = *(void**)src_itm->buffer();
381  size = 0;
382  } break;
384  IOpaqueAddress* ppA1 = &addrVector[k];
385  IOpaqueAddress** ppA2 = (IOpaqueAddress**)out_itm->buffer();
386  *ppA2 = ppA1;
387  size = 0;
388  } break;
390  default:
391  size = 0;
392  break;
393  }
394  if ( size > 0 ) {
395  ::memcpy( (void*)out_itm->buffer(), src_itm->buffer(), size * src_itm->length() );
396  }
397  }
398  status = m_dataSvc->writeRecord( out.ptr() );
399  if ( !status.isSuccess() ) {
400  log << MSG::ERROR << "Failed to write record " << nentry << " from " << input << " to " << m_outName
401  << endmsg;
402  }
403  }
404  }
405  log << MSG::INFO << "End of reading tuple " << input << " after " << nentry << " entries." << endmsg;
406 
407  if ( nentry > 0 || m_selectorName != "" ) {
408  return StatusCode::SUCCESS;
409  }
410  return StatusCode::FAILURE;
411  }
412  log << MSG::ERROR << "Failed to access input: " << input << endmsg;
413  }
414  return StatusCode::FAILURE;
415  }
416 
419  {
421  for ( size_t i = 0; i < m_inputs.size(); ++i ) {
422  NTuplePtr nt( m_dataSvc.get(), m_inputs[i] );
423  if ( !( 0 == nt ) ) {
424  NTuplePtr out( m_dataSvc.get(), m_outName );
425  if ( 0 == out ) {
426  status = book( nt );
427  } else {
428  status = checkInput( out, nt );
429  }
430  if ( !status.isSuccess() ) {
431  return status;
432  } else if ( m_selectorName != "" ) {
433  SmartIF<ISelectStatement> stmt( ObjFactory::create( m_selectorName, serviceLocator() ) );
434  if ( stmt ) {
435  if ( !m_criteria.empty() ) stmt->setCriteria( m_criteria );
436  nt->attachSelector( stmt );
437  } else {
438  MsgStream log( msgSvc(), name() );
439  log << MSG::ERROR << "Failed to attach tuple selector to " << m_inputs[i] << endmsg;
440  return StatusCode::FAILURE;
441  }
442  }
443  } else {
444  MsgStream log( msgSvc(), name() );
445  log << MSG::ERROR << "Failed to access tuple: " << m_inputs[i] << endmsg;
446  return StatusCode::FAILURE;
447  }
448  }
449  return StatusCode::SUCCESS;
450  }
451 
454  {
455  MsgStream log( msgSvc(), name() );
456  for ( const auto& input : m_inputs ) {
457  StatusCode sc = mergeEntries( input );
458  if ( !sc.isSuccess() ) {
459  log << MSG::ERROR << "Failed to merge tuple:" << input << endmsg;
460  return sc;
461  }
462  }
463  return StatusCode::SUCCESS;
464  }
465 };
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:731
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:75
virtual StatusCode add(INTupleItem *item)=0
Add an item row to the N tuple.
~CollectionCloneAlg() override=default
Standard Destructor.
T end(T...args)
Gaudi::Property< std::vector< std::string > > m_inputs
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:72
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:28
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.
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:809
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:412
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
SmartIF< IMessageSvc > & msgSvc() const
The standard message service.
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:231
Opaque address interface definition.
const std::string & type() const override
The type of the algorithm object.
Definition: Algorithm.h:166
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