Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v31r0 (aeb156f0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 #pragma GCC diagnostic push
27 #pragma GCC diagnostic ignored "-Wnull-dereference"
28  const NTuple::_Data<T>* it = dynamic_cast<const NTuple::_Data<T>*>( item );
29  assert( it != nullptr );
30  return it->range().upper();
31 #pragma GCC diagnostic pop
32  }
33 
34  template <class TYP>
35  static StatusCode createItem( MsgStream& log, INTuple* tuple, INTupleItem* src, const TYP& null ) {
36  NTuple::_Data<TYP>* source = dynamic_cast<NTuple::_Data<TYP>*>( src );
37  if ( !source ) return StatusCode::FAILURE;
38  TYP low = source->range().lower();
39  TYP high = source->range().upper();
40  long hasIdx = source->hasIndex();
41  long ndim = source->ndim();
42  const std::string& name = source->name();
43  std::string idxName;
44  long dim[4], idxLen = 0;
45  long dim1 = 1, dim2 = 1;
46  INTupleItem* it = nullptr;
47  for ( int i = 0; i < ndim; i++ ) dim[i] = source->dim( i );
49  if ( hasIdx ) {
50  const INTupleItem* index = source->indexItem();
51  idxName = index->name();
52  switch ( index->type() ) {
54  idxLen = upper<unsigned char>( index );
55  break;
57  idxLen = upper<unsigned short>( index );
58  break;
59  case DataTypeInfo::UINT:
60  idxLen = upper<unsigned int>( index );
61  break;
63  idxLen = upper<unsigned long>( index );
64  break;
65  case DataTypeInfo::CHAR:
66  idxLen = upper<char>( index );
67  break;
69  idxLen = upper<short>( index );
70  break;
71  case DataTypeInfo::INT:
72  idxLen = upper<int>( index );
73  break;
74  case DataTypeInfo::LONG:
75  idxLen = upper<long>( index );
76  break;
77  default:
78  log << MSG::ERROR << "Column " << idxName << " is not a valid index column!" << endmsg;
79  return StatusCode::FAILURE;
80  }
81  }
82  switch ( ndim ) {
83  case 0:
84  it = NTuple::_Item<TYP>::create( tuple, name, typeid( TYP ), low, high, null );
85  break;
86  case 1:
87  dim1 = ( hasIdx ) ? idxLen : dim[0];
88  it = NTuple::_Array<TYP>::create( tuple, name, typeid( TYP ), idxName, dim1, low, high, null );
89  break;
90  case 2:
91  dim1 = ( hasIdx ) ? idxLen : dim[0];
92  dim2 = ( hasIdx ) ? dim[0] : dim[1];
93  it = NTuple::_Matrix<TYP>::create( tuple, name, typeid( TYP ), idxName, dim1, dim2, low, high, null );
94  break;
95  default:
96  return StatusCode::FAILURE;
97  }
98  return tuple->add( it );
99  }
100 } // namespace
101 
113 
114  Gaudi::Property<std::string> m_tupleSvc{this, "EvtTupleSvc", "EvtTupleSvc", "name of the data provider service"};
115  Gaudi::Property<std::vector<std::string>> m_inputs{this, "Input", {}, "input specifications"};
116  Gaudi::Property<std::string> m_output{this, "Output", {}, "output specification"};
117 
128 
129 public:
131  using Algorithm::Algorithm;
132 
134  StatusCode initialize() override {
135  MsgStream log( msgSvc(), name() );
136  m_rootName = "";
137  m_outName = "";
138  m_criteria = "";
139  m_selectorName = "";
140  m_dataSvc = service( m_tupleSvc, true );
141  if ( !m_dataSvc ) {
142  log << MSG::ERROR << "Failed to access service \"" << m_tupleSvc << "\"." << endmsg;
143  return StatusCode::FAILURE;
144  }
146  using Parser = Gaudi::Utils::AttribStringParser;
147  for ( auto attrib : Parser( m_output ) ) {
148  switch ( ::toupper( attrib.tag[0] ) ) {
149  case 'D':
150  m_outName = std::move( attrib.value );
151  break;
152  case 'S':
153  m_criteria = std::move( attrib.value );
154  break;
155  case 'F':
156  fun = std::move( attrib.value );
157  break;
158  default:
159  break;
160  }
161  }
162  if ( m_outName.empty() ) {
163  log << MSG::ERROR << "Failed to analyze output specs:" << m_output << endmsg;
164  return StatusCode::FAILURE;
165  }
166  if ( !fun.empty() || !m_criteria.empty() ) {
167  if ( !m_criteria.empty() && fun.empty() ) fun = "NTuple::Selector";
168  m_selectorName = fun;
169  }
170  return StatusCode::SUCCESS;
171  }
172 
174  StatusCode finalize() override {
175  m_dataSvc.reset();
176  return StatusCode::SUCCESS;
177  }
178 
180  StatusCode execute() override {
181  StatusCode status = connect();
182  return status.isSuccess() ? mergeInputTuples() : status;
183  }
184 
186  virtual StatusCode book( const NTuple::Tuple* nt ) {
187  MsgStream log( msgSvc(), name() );
189  NTuple::Tuple* tuple = m_dataSvc->book( m_outName, nt->clID(), nt->title() );
190  for ( const auto& i : nt->items() ) {
191  switch ( i->type() ) {
192  case DataTypeInfo::UCHAR:
193  status = createItem<unsigned char>( log, tuple, i, 0 );
194  break;
196  status = createItem<unsigned short>( log, tuple, i, 0 );
197  break;
198  case DataTypeInfo::UINT:
199  status = createItem<unsigned int>( log, tuple, i, 0 );
200  break;
201  case DataTypeInfo::ULONG:
202  status = createItem<unsigned long>( log, tuple, i, 0 );
203  break;
204  case DataTypeInfo::CHAR:
205  status = createItem<char>( log, tuple, i, 0 );
206  break;
207  case DataTypeInfo::SHORT:
208  status = createItem<short>( log, tuple, i, 0 );
209  break;
210  case DataTypeInfo::INT:
211  status = createItem<int>( log, tuple, i, 0 );
212  break;
213  case DataTypeInfo::LONG:
214  status = createItem<long>( log, tuple, i, 0 );
215  break;
216  case DataTypeInfo::BOOL:
217  status = createItem( log, tuple, i, false );
218  break;
219  case DataTypeInfo::FLOAT:
220  status = createItem<float>( log, tuple, i, 0 );
221  break;
223  status = createItem<double>( log, tuple, i, 0 );
224  break;
226  status = createItem<IOpaqueAddress*>( log, tuple, i, nullptr );
227  break;
229  status = createItem<void*>( log, tuple, i, nullptr );
230  break;
232  // status = createItem(log, tuple, i, (std::string*)0);
233  // break;
235  // status = createItem(log, tuple, i, (char*)0);
236  // break;
238  default:
239  status = StatusCode::FAILURE;
240  break;
241  }
242  }
243  return status;
244  }
245 
246  // Perform some basic checks
247  virtual StatusCode checkInput( const NTuple::Tuple* clone, const NTuple::Tuple* src ) {
248  MsgStream log( msgSvc(), name() );
249  if ( clone && src ) {
250  const INTuple::ItemContainer& clone_items = clone->items();
251  const std::string clone_id = clone->registry()->identifier();
252  const std::string src_id = src->registry()->identifier();
253 
254  log << MSG::ERROR;
255  for ( auto i = clone_items.begin(); i != clone_items.end(); ++i ) {
256  const INTupleItem* itm = *i;
257  const std::string& nam = itm->name();
258  const INTupleItem* src_itm = src->find( nam );
259  if ( !src_itm ) {
260  log << "Tuple item " << nam << " not present in " << src_id << endmsg;
261  return StatusCode::FAILURE;
262  }
263  if ( itm->type() != src_itm->type() ) {
264  log << "Tuple item " << nam << " are of different types in " << src_id << ":" << src_itm->typeName()
265  << " <-> " << clone_id << ":" << itm->typeName() << endmsg;
266  return StatusCode::FAILURE;
267  }
268  if ( itm->ndim() != src_itm->ndim() ) {
269  log << "Tuple item " << nam << " have different dimensions in " << src_id << ":" << src_itm->ndim() << " <-> "
270  << clone_id << ":" << itm->ndim() << endmsg;
271  return StatusCode::FAILURE;
272  }
273  for ( int j = 0; j < itm->ndim(); ++j ) {
274  if ( src_itm->dim( j ) != itm->dim( j ) ) {
275  log << "Tuple item " << nam << " have different dimensions in " << src_id << "[" << j
276  << "]:" << src_itm->dim( j ) << " <-> " << clone_id << "[" << j << "]:" << itm->dim( j ) << endmsg;
277  return StatusCode::FAILURE;
278  }
279  }
280  if ( itm->hasIndex() != src_itm->hasIndex() ) {
281  log << "Tuple item " << nam << " has different index colums " << src_id << ":" << src_itm->hasIndex()
282  << " <-> " << clone_id << ":" << itm->hasIndex() << endmsg;
283  return StatusCode::FAILURE;
284  }
285  if ( itm->hasIndex() ) {
286  if ( itm->index() != src_itm->index() ) {
287  log << "Tuple item " << nam << " has different index colums " << src_id << ":" << src_itm->index()
288  << " <-> " << clone_id << ":" << itm->index() << endmsg;
289  return StatusCode::FAILURE;
290  }
291  }
292  }
293  return StatusCode::SUCCESS;
294  }
295  return StatusCode::FAILURE;
296  }
297 
300  MsgStream log( msgSvc(), name() );
301  NTuplePtr out( m_dataSvc.get(), m_outName );
302  if ( 0 != out ) {
303  const INTuple::ItemContainer& clone_items = out->items();
304  std::vector<GenericAddress> addrVector( clone_items.size() );
306  NTuplePtr nt( m_dataSvc.get(), input );
307  size_t k = 0, nentry = 0;
308  if ( 0 != nt ) {
309  const INTuple::ItemContainer& source_items = nt->items();
310  for ( k = 0; k < source_items.size(); ++k ) {
311  if ( source_items[k]->type() == DataTypeInfo::OBJECT_ADDR ) {
312  *(IOpaqueAddress**)source_items[k]->buffer() = &addrVector[k];
313  }
314  }
315  while ( status.isSuccess() ) {
316  status = m_dataSvc->readRecord( nt.ptr() );
317  if ( status.isSuccess() ) {
318  INTuple::ItemContainer::const_iterator i;
319  nentry++;
320  for ( k = 0, i = source_items.begin(); i != source_items.end(); ++i, ++k ) {
321  const INTupleItem* src_itm = *i;
322  const INTupleItem* out_itm = out->find( src_itm->name() );
323  size_t size = 0;
324  switch ( ( *i )->type() ) {
325  case DataTypeInfo::UCHAR:
326  size = sizeof( unsigned char );
327  break;
329  size = sizeof( unsigned short );
330  break;
331  case DataTypeInfo::UINT:
332  size = sizeof( unsigned int );
333  break;
334  case DataTypeInfo::ULONG:
335  size = sizeof( unsigned long );
336  break;
337  case DataTypeInfo::CHAR:
338  size = sizeof( char );
339  break;
340  case DataTypeInfo::SHORT:
341  size = sizeof( short );
342  break;
343  case DataTypeInfo::INT:
344  size = sizeof( int );
345  break;
346  case DataTypeInfo::LONG:
347  size = sizeof( long );
348  break;
349  case DataTypeInfo::BOOL:
350  size = sizeof( bool );
351  break;
352  case DataTypeInfo::FLOAT:
353  size = sizeof( float );
354  break;
356  size = sizeof( double );
357  break;
359  *(std::string*)out_itm->buffer() = *(std::string*)src_itm->buffer();
360  size = 0;
361  break;
363  size = ::strlen( (const char*)src_itm->buffer() ) + 1;
364  break;
365  case DataTypeInfo::POINTER: {
366  *(void**)out_itm->buffer() = *(void**)src_itm->buffer();
367  size = 0;
368  } break;
370  IOpaqueAddress* ppA1 = &addrVector[k];
371  IOpaqueAddress** ppA2 = (IOpaqueAddress**)( out_itm->buffer() );
372  *ppA2 = ppA1;
373  size = 0;
374  } break;
376  default:
377  size = 0;
378  break;
379  }
380  if ( size > 0 ) {
381  ::memcpy( const_cast<void*>( out_itm->buffer() ), src_itm->buffer(), size * src_itm->length() );
382  }
383  }
384  status = m_dataSvc->writeRecord( out.ptr() );
385  if ( !status.isSuccess() ) {
386  log << MSG::ERROR << "Failed to write record " << nentry << " from " << input << " to " << m_outName
387  << endmsg;
388  }
389  }
390  }
391  log << MSG::INFO << "End of reading tuple " << input << " after " << nentry << " entries." << endmsg;
392 
393  if ( nentry > 0 || m_selectorName != "" ) { return StatusCode::SUCCESS; }
394  return StatusCode::FAILURE;
395  }
396  log << MSG::ERROR << "Failed to access input: " << input << endmsg;
397  }
398  return StatusCode::FAILURE;
399  }
400 
404  for ( size_t i = 0; i < m_inputs.size(); ++i ) {
405  NTuplePtr nt( m_dataSvc.get(), m_inputs[i] );
406  if ( !( 0 == nt ) ) {
407  NTuplePtr out( m_dataSvc.get(), m_outName );
408  if ( 0 == out ) {
409  status = book( nt );
410  } else {
411  status = checkInput( out, nt );
412  }
413  if ( !status.isSuccess() ) {
414  return status;
415  } else if ( m_selectorName != "" ) {
416  SmartIF<ISelectStatement> stmt( ObjFactory::create( m_selectorName, serviceLocator() ).release() );
417  if ( stmt ) {
418  if ( !m_criteria.empty() ) stmt->setCriteria( m_criteria );
419  nt->attachSelector( stmt );
420  } else {
421  MsgStream log( msgSvc(), name() );
422  log << MSG::ERROR << "Failed to attach tuple selector to " << m_inputs[i] << endmsg;
423  return StatusCode::FAILURE;
424  }
425  }
426  } else {
427  MsgStream log( msgSvc(), name() );
428  log << MSG::ERROR << "Failed to access tuple: " << m_inputs[i] << endmsg;
429  return StatusCode::FAILURE;
430  }
431  }
432  return StatusCode::SUCCESS;
433  }
434 
437  MsgStream log( msgSvc(), name() );
438  for ( const auto& input : m_inputs ) {
439  StatusCode sc = mergeEntries( input );
440  if ( !sc.isSuccess() ) {
441  log << MSG::ERROR << "Failed to merge tuple:" << input << endmsg;
442  return sc;
443  }
444  }
445  return StatusCode::SUCCESS;
446  }
447 };
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)
StatusCode execute() override
Execute procedure.
Implementation of property with value of concrete type.
Definition: Property.h:352
virtual StatusCode book(const NTuple::Tuple *nt)
Book the N-tuple according to the specification.
const std::string & name() const override
The identifying name of the algorithm object.
Definition: Algorithm.cpp:635
StatusCode initialize() override
Initialize.
bool isSuccess() const
Definition: StatusCode.h:267
Algorithm(const std::string &name, ISvcLocator *svcloc, const std::string &version=PACKAGE_VERSION)
Constructor.
Definition: Algorithm.cpp:48
virtual StatusCode add(INTupleItem *item)=0
Add an item row to the N tuple.
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:215
constexpr static const auto SUCCESS
Definition: StatusCode.h:85
T end(T...args)
Gaudi::Property< std::vector< std::string > > m_inputs
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:72
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: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.
#define DECLARE_COMPONENT(type)
NTuple interface class definition.
Definition: INTuple.h:81
TYPE * get() const
Get interface pointer.
Definition: SmartIF.h:76
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:56
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:50
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:38
virtual StatusCode checkInput(const NTuple::Tuple *clone, const NTuple::Tuple *src)
virtual long type() const =0
Type information of the item.
T move(T...args)
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:375
const std::string & type() const override
The type of the algorithm object.
Definition: Algorithm.h:167
virtual const void * buffer() const =0
Access data buffer (CONST)
StatusCode finalize() override
Finalize.
Alias for backward compatibility.
Definition: Algorithm.h:56
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
constexpr static const auto FAILURE
Definition: StatusCode.h:86
SmartIF< ISvcLocator > & serviceLocator() const override
The standard service locator.
Definition: Algorithm.cpp:679
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:86
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?
Opaque address interface definition.
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:192
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:40