| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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/Tokenizer.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() ) {
51 case DataTypeInfo::UCHAR:
52 idxLen = upper<unsigned char>(index);
53 break;
54 case DataTypeInfo::USHORT:
55 idxLen = upper<unsigned short>(index);
56 break;
57 case DataTypeInfo::UINT:
58 idxLen = upper<unsigned int>(index);
59 break;
60 case DataTypeInfo::ULONG:
61 idxLen = upper<unsigned long>(index);
62 break;
63 case DataTypeInfo::CHAR:
64 idxLen = upper<char>(index);
65 break;
66 case DataTypeInfo::SHORT:
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
126 class CollectionCloneAlg : public Algorithm {
128 INTupleSvc* m_dataSvc;
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 }
154 virtual ~CollectionCloneAlg() {
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 Tokenizer tok(true);
168 tok.analyse(m_output, " ", "", "", "=", "'", "'");
169 for ( Tokenizer::Items::iterator i = tok.items().begin(); i != tok.items().end(); i++ ) {
170 const std::string& tag = (*i).tag();
171 const std::string& val = (*i).value();
172 switch( ::toupper(tag[0]) ) {
173 case 'D':
174 m_outName = val;
175 break;
176 case 'S':
177 m_criteria = val;
178 break;
179 case 'F':
180 fun = val;
181 break ;
182 default:
183 break;
184 }
185 }
186 if ( m_outName.empty() ) {
187 log << MSG::ERROR << "Failed to analyze output specs:" << m_output << endmsg;
188 return StatusCode::FAILURE;
189 }
190 if ( fun.length() > 0 || m_criteria.length() > 0 ) {
191 if ( m_criteria.length() > 0 && fun.length() == 0 ) fun = "NTuple::Selector";
192 m_selectorName = fun;
193 return StatusCode::SUCCESS;
194 }
195 return sc;
196 }
197 log << MSG::ERROR << "Failed to access service \""
198 << m_tupleSvc << "\"." << endmsg;
199 return sc;
200 }
201
203 virtual StatusCode finalize() {
204 if ( m_dataSvc ) m_dataSvc->release();
205 m_dataSvc = 0;
206 return StatusCode::SUCCESS;
207 }
208
210 virtual StatusCode execute() {
211 StatusCode status = connect();
212 if ( status.isSuccess() ) {
213 status = mergeInputTuples();
214 }
215 return status;
216 }
217
219 virtual StatusCode book(const NTuple::Tuple* nt) {
220 MsgStream log(msgSvc(), name());
221 const INTuple::ItemContainer& items = nt->items();
222 StatusCode status = StatusCode::SUCCESS;
223 INTuple::ItemContainer::const_iterator i;
224 NTuple::Tuple* tuple = m_dataSvc->book(m_outName, nt->clID(), nt->title());
225 for (i = items.begin(); i != items.end(); ++i) {
226 long type = (*i)->type();
227 switch(type) {
228 case DataTypeInfo::UCHAR:
229 status = createItem(log, tuple, *i, (unsigned char)0);
230 break;
231 case DataTypeInfo::USHORT:
232 status = createItem(log, tuple, *i, (unsigned short)0);
233 break;
234 case DataTypeInfo::UINT:
235 status = createItem(log, tuple, *i, (unsigned int)0);
236 break;
237 case DataTypeInfo::ULONG:
238 status = createItem(log, tuple, *i, (unsigned long)0);
239 break;
240 case DataTypeInfo::CHAR:
241 status = createItem(log, tuple, *i, char(0));
242 break;
243 case DataTypeInfo::SHORT:
244 status = createItem(log, tuple, *i, short(0));
245 break;
246 case DataTypeInfo::INT:
247 status = createItem(log, tuple, *i, int(0));
248 break;
249 case DataTypeInfo::LONG:
250 status = createItem(log, tuple, *i, long(0));
251 break;
252 case DataTypeInfo::BOOL:
253 status = createItem(log, tuple, *i, false);
254 break;
255 case DataTypeInfo::FLOAT:
256 status = createItem(log, tuple, *i, float(0.0));
257 break;
258 case DataTypeInfo::DOUBLE:
259 status = createItem(log, tuple, *i, double(0.0));
260 break;
261 case DataTypeInfo::OBJECT_ADDR:
262 status = createItem(log, tuple, *i, (IOpaqueAddress*)0);
263 break;
264 case DataTypeInfo::POINTER:
265 status = createItem(log, tuple, *i, (void*)0);
266 break;
267 case DataTypeInfo::STRING:
268 // status = createItem(log, tuple, *i, (std::string*)0);
269 // break;
270 case DataTypeInfo::NTCHAR:
271 // status = createItem(log, tuple, *i, (char*)0);
272 // break;
273 case DataTypeInfo::UNKNOWN:
274 default:
275 status = StatusCode::FAILURE;
276 break;
277 }
278 }
279 return status;
280 }
281
282 // Perform some basic checks
283 virtual StatusCode checkInput(const NTuple::Tuple* clone, const NTuple::Tuple* src) {
284 MsgStream log(msgSvc(), name());
285 if ( 0 != clone && 0 != src ) {
286 const INTuple::ItemContainer& clone_items = clone->items();
287 const std::string clone_id = clone->registry()->identifier();
288 const std::string src_id = src->registry()->identifier();
289
290 INTuple::ItemContainer::const_iterator i;
291 log << MSG::ERROR;
292 for (i = clone_items.begin(); i != clone_items.end(); ++i) {
293 const INTupleItem* itm = *i;
294 const std::string& nam = itm->name();
295 const INTupleItem* src_itm = src->find(nam);
296 if ( !src_itm ) {
297 log << "Tuple item " << nam << " not present in " << src_id << endmsg;
298 return StatusCode::FAILURE;
299 }
300 if ( itm->type() != src_itm->type() ) {
301 log << "Tuple item " << nam << " are of different types in "
302 << src_id << ":" << src_itm->typeName() << " <-> "
303 << clone_id << ":" << itm->typeName() << endmsg;
304 return StatusCode::FAILURE;
305 }
306 if ( itm->ndim() != src_itm->ndim() ) {
307 log << "Tuple item " << nam << " have different dimensions in "
308 << src_id << ":" << src_itm->ndim() << " <-> "
309 << clone_id << ":" << itm->ndim() << endmsg;
310 return StatusCode::FAILURE;
311 }
312 for (int j=0; j<itm->ndim(); ++j) {
313 if ( src_itm->dim(j) != itm->dim(j) ) {
314 log << "Tuple item " << nam << " have different dimensions in "
315 << src_id << "[" << j << "]:" << src_itm->dim(j) << " <-> "
316 << clone_id << "[" << j << "]:" << itm->dim(j) << endmsg;
317 return StatusCode::FAILURE;
318 }
319 }
320 if ( itm->hasIndex() != src_itm->hasIndex() ) {
321 log << "Tuple item " << nam << " has different index colums "
322 << src_id << ":" << src_itm->hasIndex() << " <-> "
323 << clone_id << ":" << itm->hasIndex() << endmsg;
324 return StatusCode::FAILURE;
325 }
326 if ( itm->hasIndex() ) {
327 if ( itm->index() != src_itm->index() ) {
328 log << "Tuple item " << nam << " has different index colums "
329 << src_id << ":" << src_itm->index() << " <-> "
330 << clone_id << ":" << itm->index() << endmsg;
331 return StatusCode::FAILURE;
332 }
333 }
334 }
335 return StatusCode::SUCCESS;
336 }
337 return StatusCode::FAILURE;
338 }
339
341 StatusCode mergeEntries(const std::string& input) {
342 MsgStream log(msgSvc(), name());
343 NTuplePtr out(m_dataSvc, m_outName);
344 if ( 0 != out ) {
345 const INTuple::ItemContainer& clone_items = out->items();
346 std::vector<GenericAddress> addrVector(clone_items.size());
347 StatusCode status = StatusCode::SUCCESS;
348 NTuplePtr nt(m_dataSvc, input);
349 size_t k = 0, nentry = 0;
350 if ( 0 != nt ) {
351 const INTuple::ItemContainer& source_items = nt->items();
352 for (k=0; k < source_items.size(); ++k ) {
353 if ( source_items[k]->type() == DataTypeInfo::OBJECT_ADDR ) {
354 *(IOpaqueAddress**)source_items[k]->buffer() = &addrVector[k];
355 }
356 }
357 while ( status.isSuccess() ) {
358 status = m_dataSvc->readRecord(nt.ptr());
359 if ( status.isSuccess() ) {
360 INTuple::ItemContainer::const_iterator i;
361 nentry++;
362 for (k=0,i = source_items.begin(); i != source_items.end(); ++i,++k) {
363 const INTupleItem* src_itm = *i;
364 const INTupleItem* out_itm = out->find(src_itm->name());
365 size_t size = 0;
366 switch((*i)->type()) {
367 case DataTypeInfo::UCHAR:
368 size = sizeof(unsigned char);
369 break;
370 case DataTypeInfo::USHORT:
371 size = sizeof(unsigned short);
372 break;
373 case DataTypeInfo::UINT:
374 size = sizeof(unsigned int);
375 break;
376 case DataTypeInfo::ULONG:
377 size = sizeof(unsigned long);
378 break;
379 case DataTypeInfo::CHAR:
380 size = sizeof(char);
381 break;
382 case DataTypeInfo::SHORT:
383 size = sizeof(short);
384 break;
385 case DataTypeInfo::INT:
386 size = sizeof(int);
387 break;
388 case DataTypeInfo::LONG:
389 size = sizeof(long);
390 break;
391 case DataTypeInfo::BOOL:
392 size = sizeof(bool);
393 break;
394 case DataTypeInfo::FLOAT:
395 size = sizeof(float);
396 break;
397 case DataTypeInfo::DOUBLE:
398 size = sizeof(double);
399 break;
400 case DataTypeInfo::STRING:
401 *(std::string*)out_itm->buffer() = *(std::string*)src_itm->buffer();
402 size = 0;
403 break;
404 case DataTypeInfo::NTCHAR:
405 size = ::strlen((const char*)src_itm->buffer())+1;
406 break;
407 case DataTypeInfo::POINTER:
408 {
409 *(void**)out_itm->buffer() = *(void**)src_itm->buffer();
410 size = 0;
411 }
412 break;
413 case DataTypeInfo::OBJECT_ADDR:
414 {
415 IOpaqueAddress* ppA1 = &addrVector[k];
416 IOpaqueAddress** ppA2 = (IOpaqueAddress**)out_itm->buffer();
417 *ppA2 = ppA1;
418 size = 0;
419 }
420 break;
421 case DataTypeInfo::UNKNOWN:
422 default:
423 size = 0;
424 break;
425 }
426 if ( size > 0 ) {
427 ::memcpy((void*)out_itm->buffer(), src_itm->buffer(), size*src_itm->length());
428 }
429 }
430 status = m_dataSvc->writeRecord(out.ptr());
431 if ( !status.isSuccess() ) {
432 log << MSG::ERROR << "Failed to write record " << nentry
433 << " from " << input << " to " << m_outName << endmsg;
434 }
435 }
436 }
437 log << MSG::INFO << "End of reading tuple " << input
438 << " after " << nentry << " entries." << endmsg;
439
440 if ( nentry > 0 || m_selectorName != "" ) {
441 return StatusCode::SUCCESS;
442 }
443 return StatusCode::FAILURE;
444 }
445 log << MSG::ERROR << "Failed to access input: " << input << endmsg;
446 }
447 return StatusCode::FAILURE;
448 }
449
451 StatusCode connect() {
452 StatusCode status = StatusCode::SUCCESS;
453 for (size_t i=0; i < m_inputs.size(); ++i) {
454 NTuplePtr nt(m_dataSvc, m_inputs[i]);
455 if ( !(0 == nt) ) {
456 NTuplePtr out(m_dataSvc, m_outName);
457 if ( 0 == out ) {
458 status = book(nt);
459 }
460 else {
461 status = checkInput(out, nt);
462 }
463 if ( !status.isSuccess() ) {
464 return status;
465 }
466 else if ( m_selectorName != "" ) {
467 SmartIF<ISelectStatement> stmt(ObjFactory::create(m_selectorName, serviceLocator()));
468 if ( stmt.isValid( ) ) {
469 if ( m_criteria.length() > 0 ) stmt->setCriteria(m_criteria);
470 nt->attachSelector(stmt);
471 }
472 else {
473 MsgStream log(msgSvc(), name());
474 log << MSG::ERROR << "Failed to attach tuple selector to " << m_inputs[i] << endmsg;
475 return StatusCode::FAILURE;
476 }
477 }
478 }
479 else {
480 MsgStream log(msgSvc(), name());
481 log << MSG::ERROR << "Failed to access tuple: " << m_inputs[i] << endmsg;
482 return StatusCode::FAILURE;
483 }
484 }
485 return StatusCode::SUCCESS;
486 }
487
489 StatusCode mergeInputTuples() {
490 MsgStream log(msgSvc(), name());
491 for (size_t inp=0; inp < m_inputs.size(); ++inp) {
492 StatusCode sc = mergeEntries(m_inputs[inp]);
493 if ( !sc.isSuccess() ) {
494 log << MSG::ERROR << "Failed to merge tuple:" << m_inputs[inp] << endmsg;
495 return sc;
496 }
497 }
498 return StatusCode::SUCCESS;
499 }
500 };
501 DECLARE_COMPONENT(CollectionCloneAlg)