CollectionCloneAlg.cpp
Go to the documentation of this file.
1 // ====================================================================
2 // CollectionCloneAlg.cpp
3 // --------------------------------------------------------------------
4 //
5 // Author : Markus Frank
6 //
7 // ====================================================================
8 #include "GaudiKernel/IDataProviderSvc.h"
9 #include "GaudiKernel/ISelectStatement.h"
10 #include "GaudiKernel/IDataManagerSvc.h"
11 #include "GaudiKernel/GenericAddress.h"
12 #include "GaudiKernel/SmartDataPtr.h"
13 #include "GaudiKernel/AttribStringParser.h"
14 #include "GaudiKernel/IRegistry.h"
15 #include "GaudiKernel/Algorithm.h"
16 #include "GaudiKernel/MsgStream.h"
17 #include "GaudiKernel/SmartIF.h"
18 #include "GaudiKernel/NTuple.h"
19 #include "GaudiKernel/ObjectFactory.h"
20 #include <vector>
21 
22 namespace {
23  template <class T> static long upper(const INTupleItem* item) {
24  const NTuple::_Data<T>* it = dynamic_cast<const NTuple::_Data<T>*>(item);
25  return long(it->range().upper());
26  }
27 
28  template<class TYP> static
29  StatusCode createItem (MsgStream& log,
30  INTuple* tuple,
31  INTupleItem* src,
32  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++ )
45  dim[i] = source->dim(i);
47  if ( hasIdx ) {
48  const INTupleItem* index = source->indexItem();
49  idxName = index->name();
50  switch( index->type() ) {
52  idxLen = upper<unsigned char>(index);
53  break;
55  idxLen = upper<unsigned short>(index);
56  break;
57  case DataTypeInfo::UINT:
58  idxLen = upper<unsigned int>(index);
59  break;
61  idxLen = upper<unsigned long>(index);
62  break;
63  case DataTypeInfo::CHAR:
64  idxLen = upper<char>(index);
65  break;
67  idxLen = upper<short>(index);
68  break;
69  case DataTypeInfo::INT:
70  idxLen = upper<int>(index);
71  break;
72  case DataTypeInfo::LONG:
73  idxLen = upper<long>(index);
74  break;
75  default:
76  log << MSG::ERROR << "Column " << idxName
77  << " is not a valid index column!" << endmsg;
78  return StatusCode::FAILURE;
79  }
80  }
81  switch( ndim ) {
82  case 0:
83  it = NTuple::_Item<TYP>::create (tuple, name, typeid(TYP), low, high, null);
84  break;
85  case 1:
86  dim1 = (hasIdx) ? idxLen : dim[0];
87  it = NTuple::_Array<TYP>::create (tuple,
88  name,
89  typeid(TYP),
90  idxName,
91  dim1,
92  low,
93  high,
94  null);
95  break;
96  case 2:
97  dim1 = (hasIdx) ? idxLen : dim[0];
98  dim2 = (hasIdx) ? dim[0] : dim[1];
99  it = NTuple::_Matrix<TYP>::create ( tuple,
100  name,
101  typeid(TYP),
102  idxName,
103  dim1,
104  dim2,
105  low,
106  high,
107  null);
108  break;
109  default:
110  return StatusCode::FAILURE;
111  }
112  return tuple->add(it);
113  }
114 }
115 
130  std::string m_tupleSvc;
132  std::string m_output;
134  std::vector<std::string> m_inputs;
136  std::string m_rootName;
138  std::string m_outName;
140  std::string m_criteria;
142  std::string m_selectorName;
143 public:
144 
146  CollectionCloneAlg(const std::string& name, ISvcLocator* pSvcLocator)
147  : Algorithm(name, pSvcLocator), m_dataSvc(0)
148  {
149  declareProperty("EvtTupleSvc", m_tupleSvc="EvtTupleSvc");
150  declareProperty("Input", m_inputs);
151  declareProperty("Output", m_output);
152  }
155  }
156 
158  virtual StatusCode initialize() {
159  MsgStream log(msgSvc(), name());
160  m_rootName = "";
161  m_outName = "";
162  m_criteria = "";
163  m_selectorName = "";
164  StatusCode sc = service(m_tupleSvc, m_dataSvc, true);
165  if ( sc.isSuccess() ) {
166  std::string fun;
167  using Parser = Gaudi::Utils::AttribStringParser;
168  for (auto attrib: Parser(m_output)) {
169  switch( ::toupper(attrib.tag[0]) ) {
170  case 'D':
171  m_outName = std::move(attrib.value);
172  break;
173  case 'S':
174  m_criteria = std::move(attrib.value);
175  break;
176  case 'F':
177  fun = std::move(attrib.value);
178  break ;
179  default:
180  break;
181  }
182  }
183  if ( m_outName.empty() ) {
184  log << MSG::ERROR << "Failed to analyze output specs:" << m_output << endmsg;
185  return StatusCode::FAILURE;
186  }
187  if ( fun.length() > 0 || m_criteria.length() > 0 ) {
188  if ( m_criteria.length() > 0 && fun.length() == 0 ) fun = "NTuple::Selector";
189  m_selectorName = fun;
190  return StatusCode::SUCCESS;
191  }
192  return sc;
193  }
194  log << MSG::ERROR << "Failed to access service \""
195  << m_tupleSvc << "\"." << endmsg;
196  return sc;
197  }
198 
200  virtual StatusCode finalize() {
201  if ( m_dataSvc ) m_dataSvc->release();
202  m_dataSvc = 0;
203  return StatusCode::SUCCESS;
204  }
205 
207  virtual StatusCode execute() {
208  StatusCode status = connect();
209  if ( status.isSuccess() ) {
210  status = mergeInputTuples();
211  }
212  return status;
213  }
214 
216  virtual StatusCode book(const NTuple::Tuple* nt) {
217  MsgStream log(msgSvc(), name());
218  const INTuple::ItemContainer& items = nt->items();
220  INTuple::ItemContainer::const_iterator i;
221  NTuple::Tuple* tuple = m_dataSvc->book(m_outName, nt->clID(), nt->title());
222  for (i = items.begin(); i != items.end(); ++i) {
223  long type = (*i)->type();
224  switch(type) {
225  case DataTypeInfo::UCHAR:
226  status = createItem(log, tuple, *i, (unsigned char)0);
227  break;
229  status = createItem(log, tuple, *i, (unsigned short)0);
230  break;
231  case DataTypeInfo::UINT:
232  status = createItem(log, tuple, *i, (unsigned int)0);
233  break;
234  case DataTypeInfo::ULONG:
235  status = createItem(log, tuple, *i, (unsigned long)0);
236  break;
237  case DataTypeInfo::CHAR:
238  status = createItem(log, tuple, *i, char(0));
239  break;
240  case DataTypeInfo::SHORT:
241  status = createItem(log, tuple, *i, short(0));
242  break;
243  case DataTypeInfo::INT:
244  status = createItem(log, tuple, *i, int(0));
245  break;
246  case DataTypeInfo::LONG:
247  status = createItem(log, tuple, *i, long(0));
248  break;
249  case DataTypeInfo::BOOL:
250  status = createItem(log, tuple, *i, false);
251  break;
252  case DataTypeInfo::FLOAT:
253  status = createItem(log, tuple, *i, float(0.0));
254  break;
256  status = createItem(log, tuple, *i, double(0.0));
257  break;
259  status = createItem(log, tuple, *i, (IOpaqueAddress*)0);
260  break;
262  status = createItem(log, tuple, *i, (void*)0);
263  break;
265 // status = createItem(log, tuple, *i, (std::string*)0);
266 // break;
268 // status = createItem(log, tuple, *i, (char*)0);
269 // break;
271  default:
272  status = StatusCode::FAILURE;
273  break;
274  }
275  }
276  return status;
277  }
278 
279  // Perform some basic checks
280  virtual StatusCode checkInput(const NTuple::Tuple* clone, const NTuple::Tuple* src) {
281  MsgStream log(msgSvc(), name());
282  if ( 0 != clone && 0 != src ) {
283  const INTuple::ItemContainer& clone_items = clone->items();
284  const std::string clone_id = clone->registry()->identifier();
285  const std::string src_id = src->registry()->identifier();
286 
287  INTuple::ItemContainer::const_iterator i;
288  log << MSG::ERROR;
289  for (i = clone_items.begin(); i != clone_items.end(); ++i) {
290  const INTupleItem* itm = *i;
291  const std::string& nam = itm->name();
292  const INTupleItem* src_itm = src->find(nam);
293  if ( !src_itm ) {
294  log << "Tuple item " << nam << " not present in " << src_id << endmsg;
295  return StatusCode::FAILURE;
296  }
297  if ( itm->type() != src_itm->type() ) {
298  log << "Tuple item " << nam << " are of different types in "
299  << src_id << ":" << src_itm->typeName() << " <-> "
300  << clone_id << ":" << itm->typeName() << endmsg;
301  return StatusCode::FAILURE;
302  }
303  if ( itm->ndim() != src_itm->ndim() ) {
304  log << "Tuple item " << nam << " have different dimensions in "
305  << src_id << ":" << src_itm->ndim() << " <-> "
306  << clone_id << ":" << itm->ndim() << endmsg;
307  return StatusCode::FAILURE;
308  }
309  for (int j=0; j<itm->ndim(); ++j) {
310  if ( src_itm->dim(j) != itm->dim(j) ) {
311  log << "Tuple item " << nam << " have different dimensions in "
312  << src_id << "[" << j << "]:" << src_itm->dim(j) << " <-> "
313  << clone_id << "[" << j << "]:" << itm->dim(j) << endmsg;
314  return StatusCode::FAILURE;
315  }
316  }
317  if ( itm->hasIndex() != src_itm->hasIndex() ) {
318  log << "Tuple item " << nam << " has different index colums "
319  << src_id << ":" << src_itm->hasIndex() << " <-> "
320  << clone_id << ":" << itm->hasIndex() << endmsg;
321  return StatusCode::FAILURE;
322  }
323  if ( itm->hasIndex() ) {
324  if ( itm->index() != src_itm->index() ) {
325  log << "Tuple item " << nam << " has different index colums "
326  << src_id << ":" << src_itm->index() << " <-> "
327  << clone_id << ":" << itm->index() << endmsg;
328  return StatusCode::FAILURE;
329  }
330  }
331  }
332  return StatusCode::SUCCESS;
333  }
334  return StatusCode::FAILURE;
335  }
336 
338  StatusCode mergeEntries(const std::string& input) {
339  MsgStream log(msgSvc(), name());
340  NTuplePtr out(m_dataSvc, m_outName);
341  if ( 0 != out ) {
342  const INTuple::ItemContainer& clone_items = out->items();
343  std::vector<GenericAddress> addrVector(clone_items.size());
345  NTuplePtr nt(m_dataSvc, input);
346  size_t k = 0, nentry = 0;
347  if ( 0 != nt ) {
348  const INTuple::ItemContainer& source_items = nt->items();
349  for (k=0; k < source_items.size(); ++k ) {
350  if ( source_items[k]->type() == DataTypeInfo::OBJECT_ADDR ) {
351  *(IOpaqueAddress**)source_items[k]->buffer() = &addrVector[k];
352  }
353  }
354  while ( status.isSuccess() ) {
355  status = m_dataSvc->readRecord(nt.ptr());
356  if ( status.isSuccess() ) {
357  INTuple::ItemContainer::const_iterator i;
358  nentry++;
359  for (k=0,i = source_items.begin(); i != source_items.end(); ++i,++k) {
360  const INTupleItem* src_itm = *i;
361  const INTupleItem* out_itm = out->find(src_itm->name());
362  size_t size = 0;
363  switch((*i)->type()) {
364  case DataTypeInfo::UCHAR:
365  size = sizeof(unsigned char);
366  break;
368  size = sizeof(unsigned short);
369  break;
370  case DataTypeInfo::UINT:
371  size = sizeof(unsigned int);
372  break;
373  case DataTypeInfo::ULONG:
374  size = sizeof(unsigned long);
375  break;
376  case DataTypeInfo::CHAR:
377  size = sizeof(char);
378  break;
379  case DataTypeInfo::SHORT:
380  size = sizeof(short);
381  break;
382  case DataTypeInfo::INT:
383  size = sizeof(int);
384  break;
385  case DataTypeInfo::LONG:
386  size = sizeof(long);
387  break;
388  case DataTypeInfo::BOOL:
389  size = sizeof(bool);
390  break;
391  case DataTypeInfo::FLOAT:
392  size = sizeof(float);
393  break;
395  size = sizeof(double);
396  break;
398  *(std::string*)out_itm->buffer() = *(std::string*)src_itm->buffer();
399  size = 0;
400  break;
402  size = ::strlen((const char*)src_itm->buffer())+1;
403  break;
405  {
406  *(void**)out_itm->buffer() = *(void**)src_itm->buffer();
407  size = 0;
408  }
409  break;
411  {
412  IOpaqueAddress* ppA1 = &addrVector[k];
413  IOpaqueAddress** ppA2 = (IOpaqueAddress**)out_itm->buffer();
414  *ppA2 = ppA1;
415  size = 0;
416  }
417  break;
419  default:
420  size = 0;
421  break;
422  }
423  if ( size > 0 ) {
424  ::memcpy((void*)out_itm->buffer(), src_itm->buffer(), size*src_itm->length());
425  }
426  }
427  status = m_dataSvc->writeRecord(out.ptr());
428  if ( !status.isSuccess() ) {
429  log << MSG::ERROR << "Failed to write record " << nentry
430  << " from " << input << " to " << m_outName << endmsg;
431  }
432  }
433  }
434  log << MSG::INFO << "End of reading tuple " << input
435  << " after " << nentry << " entries." << endmsg;
436 
437  if ( nentry > 0 || m_selectorName != "" ) {
438  return StatusCode::SUCCESS;
439  }
440  return StatusCode::FAILURE;
441  }
442  log << MSG::ERROR << "Failed to access input: " << input << endmsg;
443  }
444  return StatusCode::FAILURE;
445  }
446 
450  for (size_t i=0; i < m_inputs.size(); ++i) {
451  NTuplePtr nt(m_dataSvc, m_inputs[i]);
452  if ( !(0 == nt) ) {
453  NTuplePtr out(m_dataSvc, m_outName);
454  if ( 0 == out ) {
455  status = book(nt);
456  }
457  else {
458  status = checkInput(out, nt);
459  }
460  if ( !status.isSuccess() ) {
461  return status;
462  }
463  else if ( m_selectorName != "" ) {
464  SmartIF<ISelectStatement> stmt(ObjFactory::create(m_selectorName, serviceLocator()));
465  if ( stmt.isValid( ) ) {
466  if ( m_criteria.length() > 0 ) stmt->setCriteria(m_criteria);
467  nt->attachSelector(stmt);
468  }
469  else {
470  MsgStream log(msgSvc(), name());
471  log << MSG::ERROR << "Failed to attach tuple selector to " << m_inputs[i] << endmsg;
472  return StatusCode::FAILURE;
473  }
474  }
475  }
476  else {
477  MsgStream log(msgSvc(), name());
478  log << MSG::ERROR << "Failed to access tuple: " << m_inputs[i] << endmsg;
479  return StatusCode::FAILURE;
480  }
481  }
482  return StatusCode::SUCCESS;
483  }
484 
487  MsgStream log(msgSvc(), name());
488  for (size_t inp=0; inp < m_inputs.size(); ++inp) {
489  StatusCode sc = mergeEntries(m_inputs[inp]);
490  if ( !sc.isSuccess() ) {
491  log << MSG::ERROR << "Failed to merge tuple:" << m_inputs[inp] << endmsg;
492  return sc;
493  }
494  }
495  return StatusCode::SUCCESS;
496  }
497 };
std::string m_tupleSvc
Name of the data provider service.
std::string m_criteria
Selection criteria (if any)
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:24
static DataObject * find(SmartDataObjectPtr *ptr)
Static Object find method.
Small smart pointer class with automatic reference counting for IInterface.
Definition: IConverter.h:14
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:26
virtual long type() const =0
Type information of the item.
SmartIF< ISvcLocator > & serviceLocator() const
The standard service locator.
Definition: Algorithm.cpp:1091
tuple itm
Definition: ana.py:57
virtual StatusCode book(const NTuple::Tuple *nt)
Book the N-tuple according to the specification.
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:75
CollectionCloneAlg(const std::string &name, ISvcLocator *pSvcLocator)
Standard algorithm constructor.
virtual StatusCode add(INTupleItem *item)=0
Add an item row to the N tuple.
std::vector< INTupleItem * > ItemContainer
Definition: INTuple.h:86
virtual const std::string & title() const =0
Object title.
Property * declareProperty(const std::string &name, T &property, const std::string &doc="none") const
Declare the named property.
Definition: Algorithm.h:402
virtual const ItemRange & range() const =0
Access the range if specified.
virtual ~CollectionCloneAlg()
Standard Destructor.
virtual bool hasIndex() const =0
Is the tuple have an index item?
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:69
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
virtual const std::string & name() const =0
Access _Item name.
StatusCode mergeEntries(const std::string &input)
Merge the entries of a single input tuple into the output.
TYPE * ptr()
Automatic conversion to data type.
NTuple interface class definition.
Definition: INTuple.h:80
std::string m_output
Output specification.
std::vector< std::string > m_inputs
input specifications
NTuple interface class definition.
Definition: INTuple.h:27
virtual const CLID & clID() const
Retrieve reference to class definition structure.
Definition: DataObject.cpp:58
virtual INTupleItem * indexItem()=0
Pointer to index column (if present, 0 else)
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:36
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:30
virtual StatusCode writeRecord(NTuple::Tuple *tuple)=0
Write single record to N tuple.
std::string m_outName
Output tuple name.
virtual const std::string & name() const
The identifying name of the algorithm object.
Definition: Algorithm.cpp:837
StatusCode mergeInputTuples()
Merge all N-tuple entries.
virtual long dim(long i) const =0
Access individual dimensions.
INTupleSvc * m_dataSvc
Reference to data provider service.
SmartIF< IMessageSvc > & msgSvc() const
The standard message service.
Definition: Algorithm.cpp:896
Abstract class describing basic data in an Ntuple.
Definition: NTuple.h:38
virtual StatusCode checkInput(const NTuple::Tuple *clone, const NTuple::Tuple *src)
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:367
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:61
virtual StatusCode initialize()
Initialize.
virtual unsigned long release()=0
Release Interface instance.
bool isValid() const
Allow for check if smart pointer is valid.
Definition: SmartIF.h:51
virtual long ndim() const =0
Dimension.
StatusCode connect()
Connect input and output N-tuples.
virtual StatusCode execute()
Execute procedure.
virtual StatusCode finalize()
Finalize.
double fun(const std::vector< double > &x)
Definition: PFuncTest.cpp:27
Small algorithm, which allows to merge N-tuples in a generic way.
virtual StatusCode readRecord(NTuple::Tuple *tuple)=0
Read single record from N tuple.
tuple item
print s1,s2
Definition: ana.py:146
A small class used to access easily (and efficiently) data items residing in data stores...
Definition: SmartDataPtr.h:46
virtual const id_type & identifier() const =0
Full identifier (or key)
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:27
StatusCode service(const std::string &name, T *&psvc, bool createIf=true) const
Access a service by name, creating it if it doesn't already exist.
Definition: Algorithm.h:210
virtual std::string typeName() const =0
Proper type name of the object.
Opaque address interface definition.
std::string m_selectorName
Selector factory.
virtual void setCriteria(const std::string &crit)=0
Set the type.
list i
Definition: ana.py:128
void toupper(std::string &s)
virtual const INTupleItem * find(const std::string &name) const =0
Find an item row of the Ntuple (CONST)
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.
virtual const std::string & index() const =0
Access the index _Item.
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:41
string type
Definition: gaudirun.py:151
virtual long length() const =0
Access the buffer length.
virtual const void * buffer() const =0
Access data buffer (CONST)