The Gaudi Framework  v30r3 (a5ef0a68)
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 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 = nullptr;
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  return status.isSuccess() ? mergeInputTuples() : status;
184  }
185 
187  virtual StatusCode book( const NTuple::Tuple* nt )
188  {
189  MsgStream log( msgSvc(), name() );
191  NTuple::Tuple* tuple = m_dataSvc->book( m_outName, nt->clID(), nt->title() );
192  for ( const auto& i : nt->items() ) {
193  switch ( i->type() ) {
194  case DataTypeInfo::UCHAR:
195  status = createItem<unsigned char>( log, tuple, i, 0 );
196  break;
198  status = createItem<unsigned short>( log, tuple, i, 0 );
199  break;
200  case DataTypeInfo::UINT:
201  status = createItem<unsigned int>( log, tuple, i, 0 );
202  break;
203  case DataTypeInfo::ULONG:
204  status = createItem<unsigned long>( log, tuple, i, 0 );
205  break;
206  case DataTypeInfo::CHAR:
207  status = createItem<char>( log, tuple, i, 0 );
208  break;
209  case DataTypeInfo::SHORT:
210  status = createItem<short>( log, tuple, i, 0 );
211  break;
212  case DataTypeInfo::INT:
213  status = createItem<int>( log, tuple, i, 0 );
214  break;
215  case DataTypeInfo::LONG:
216  status = createItem<long>( log, tuple, i, 0 );
217  break;
218  case DataTypeInfo::BOOL:
219  status = createItem( log, tuple, i, false );
220  break;
221  case DataTypeInfo::FLOAT:
222  status = createItem<float>( log, tuple, i, 0 );
223  break;
225  status = createItem<double>( log, tuple, i, 0 );
226  break;
228  status = createItem<IOpaqueAddress*>( log, tuple, i, nullptr );
229  break;
231  status = createItem<void*>( log, tuple, i, nullptr );
232  break;
234  // status = createItem(log, tuple, i, (std::string*)0);
235  // break;
237  // status = createItem(log, tuple, i, (char*)0);
238  // break;
240  default:
241  status = StatusCode::FAILURE;
242  break;
243  }
244  }
245  return status;
246  }
247 
248  // Perform some basic checks
249  virtual StatusCode checkInput( const NTuple::Tuple* clone, const NTuple::Tuple* src )
250  {
251  MsgStream log( msgSvc(), name() );
252  if ( clone && src ) {
253  const INTuple::ItemContainer& clone_items = clone->items();
254  const std::string clone_id = clone->registry()->identifier();
255  const std::string src_id = src->registry()->identifier();
256 
257  log << MSG::ERROR;
258  for ( auto i = clone_items.begin(); i != clone_items.end(); ++i ) {
259  const INTupleItem* itm = *i;
260  const std::string& nam = itm->name();
261  const INTupleItem* src_itm = src->find( nam );
262  if ( !src_itm ) {
263  log << "Tuple item " << nam << " not present in " << src_id << endmsg;
264  return StatusCode::FAILURE;
265  }
266  if ( itm->type() != src_itm->type() ) {
267  log << "Tuple item " << nam << " are of different types in " << src_id << ":" << src_itm->typeName()
268  << " <-> " << clone_id << ":" << itm->typeName() << endmsg;
269  return StatusCode::FAILURE;
270  }
271  if ( itm->ndim() != src_itm->ndim() ) {
272  log << "Tuple item " << nam << " have different dimensions in " << src_id << ":" << src_itm->ndim() << " <-> "
273  << clone_id << ":" << itm->ndim() << endmsg;
274  return StatusCode::FAILURE;
275  }
276  for ( int j = 0; j < itm->ndim(); ++j ) {
277  if ( src_itm->dim( j ) != itm->dim( j ) ) {
278  log << "Tuple item " << nam << " have different dimensions in " << src_id << "[" << j
279  << "]:" << src_itm->dim( j ) << " <-> " << clone_id << "[" << j << "]:" << itm->dim( j ) << endmsg;
280  return StatusCode::FAILURE;
281  }
282  }
283  if ( itm->hasIndex() != src_itm->hasIndex() ) {
284  log << "Tuple item " << nam << " has different index colums " << src_id << ":" << src_itm->hasIndex()
285  << " <-> " << clone_id << ":" << itm->hasIndex() << endmsg;
286  return StatusCode::FAILURE;
287  }
288  if ( itm->hasIndex() ) {
289  if ( itm->index() != src_itm->index() ) {
290  log << "Tuple item " << nam << " has different index colums " << src_id << ":" << src_itm->index()
291  << " <-> " << clone_id << ":" << itm->index() << endmsg;
292  return StatusCode::FAILURE;
293  }
294  }
295  }
296  return StatusCode::SUCCESS;
297  }
298  return StatusCode::FAILURE;
299  }
300 
303  {
304  MsgStream log( msgSvc(), name() );
305  NTuplePtr out( m_dataSvc.get(), m_outName );
306  if ( 0 != out ) {
307  const INTuple::ItemContainer& clone_items = out->items();
308  std::vector<GenericAddress> addrVector( clone_items.size() );
310  NTuplePtr nt( m_dataSvc.get(), input );
311  size_t k = 0, nentry = 0;
312  if ( 0 != nt ) {
313  const INTuple::ItemContainer& source_items = nt->items();
314  for ( k = 0; k < source_items.size(); ++k ) {
315  if ( source_items[k]->type() == DataTypeInfo::OBJECT_ADDR ) {
316  *(IOpaqueAddress**)source_items[k]->buffer() = &addrVector[k];
317  }
318  }
319  while ( status.isSuccess() ) {
320  status = m_dataSvc->readRecord( nt.ptr() );
321  if ( status.isSuccess() ) {
322  INTuple::ItemContainer::const_iterator i;
323  nentry++;
324  for ( k = 0, i = source_items.begin(); i != source_items.end(); ++i, ++k ) {
325  const INTupleItem* src_itm = *i;
326  const INTupleItem* out_itm = out->find( src_itm->name() );
327  size_t size = 0;
328  switch ( ( *i )->type() ) {
329  case DataTypeInfo::UCHAR:
330  size = sizeof( unsigned char );
331  break;
333  size = sizeof( unsigned short );
334  break;
335  case DataTypeInfo::UINT:
336  size = sizeof( unsigned int );
337  break;
338  case DataTypeInfo::ULONG:
339  size = sizeof( unsigned long );
340  break;
341  case DataTypeInfo::CHAR:
342  size = sizeof( char );
343  break;
344  case DataTypeInfo::SHORT:
345  size = sizeof( short );
346  break;
347  case DataTypeInfo::INT:
348  size = sizeof( int );
349  break;
350  case DataTypeInfo::LONG:
351  size = sizeof( long );
352  break;
353  case DataTypeInfo::BOOL:
354  size = sizeof( bool );
355  break;
356  case DataTypeInfo::FLOAT:
357  size = sizeof( float );
358  break;
360  size = sizeof( double );
361  break;
363  *(std::string*)out_itm->buffer() = *(std::string*)src_itm->buffer();
364  size = 0;
365  break;
367  size = ::strlen( (const char*)src_itm->buffer() ) + 1;
368  break;
369  case DataTypeInfo::POINTER: {
370  *(void**)out_itm->buffer() = *(void**)src_itm->buffer();
371  size = 0;
372  } break;
374  IOpaqueAddress* ppA1 = &addrVector[k];
375  IOpaqueAddress** ppA2 = (IOpaqueAddress**)( out_itm->buffer() );
376  *ppA2 = ppA1;
377  size = 0;
378  } break;
380  default:
381  size = 0;
382  break;
383  }
384  if ( size > 0 ) {
385  ::memcpy( const_cast<void*>( out_itm->buffer() ), src_itm->buffer(), size * src_itm->length() );
386  }
387  }
388  status = m_dataSvc->writeRecord( out.ptr() );
389  if ( !status.isSuccess() ) {
390  log << MSG::ERROR << "Failed to write record " << nentry << " from " << input << " to " << m_outName
391  << endmsg;
392  }
393  }
394  }
395  log << MSG::INFO << "End of reading tuple " << input << " after " << nentry << " entries." << endmsg;
396 
397  if ( nentry > 0 || m_selectorName != "" ) {
398  return StatusCode::SUCCESS;
399  }
400  return StatusCode::FAILURE;
401  }
402  log << MSG::ERROR << "Failed to access input: " << input << endmsg;
403  }
404  return StatusCode::FAILURE;
405  }
406 
409  {
411  for ( size_t i = 0; i < m_inputs.size(); ++i ) {
412  NTuplePtr nt( m_dataSvc.get(), m_inputs[i] );
413  if ( !( 0 == nt ) ) {
414  NTuplePtr out( m_dataSvc.get(), m_outName );
415  if ( 0 == out ) {
416  status = book( nt );
417  } else {
418  status = checkInput( out, nt );
419  }
420  if ( !status.isSuccess() ) {
421  return status;
422  } else if ( m_selectorName != "" ) {
423  SmartIF<ISelectStatement> stmt( ObjFactory::create( m_selectorName, serviceLocator() ).release() );
424  if ( stmt ) {
425  if ( !m_criteria.empty() ) stmt->setCriteria( m_criteria );
426  nt->attachSelector( stmt );
427  } else {
428  MsgStream log( msgSvc(), name() );
429  log << MSG::ERROR << "Failed to attach tuple selector to " << m_inputs[i] << endmsg;
430  return StatusCode::FAILURE;
431  }
432  }
433  } else {
434  MsgStream log( msgSvc(), name() );
435  log << MSG::ERROR << "Failed to access tuple: " << m_inputs[i] << endmsg;
436  return StatusCode::FAILURE;
437  }
438  }
439  return StatusCode::SUCCESS;
440  }
441 
444  {
445  MsgStream log( msgSvc(), name() );
446  for ( const auto& input : m_inputs ) {
447  StatusCode sc = mergeEntries( input );
448  if ( !sc.isSuccess() ) {
449  log << MSG::ERROR << "Failed to merge tuple:" << input << endmsg;
450  return sc;
451  }
452  }
453  return StatusCode::SUCCESS;
454  }
455 };
Parse attribute strings allowing iteration over the various attributes.
virtual const std::string & name() const =0
Access _Item name.
constexpr static const auto FAILURE
Definition: StatusCode.h:88
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:765
StatusCode execute() override
Execute procedure.
Implementation of property with value of concrete type.
Definition: Property.h:381
virtual StatusCode book(const NTuple::Tuple *nt)
Book the N-tuple according to the specification.
StatusCode initialize() override
Initialize.
bool isSuccess() const
Definition: StatusCode.h:287
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
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.
#define DECLARE_COMPONENT(type)
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:51
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:51
T move(T...args)
SmartIF< ISvcLocator > & serviceLocator() const override
The standard service locator.
Definition: Algorithm.cpp:834
std::string m_rootName
Name of the root leaf (obtained at initialize)
constexpr static const auto SUCCESS
Definition: StatusCode.h:87
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: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