Changing the way the tag files are produced during reco: there is just a call to...
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTComponent.cxx
1 // $Id$
2
3 /**************************************************************************
4  * This file is property of and copyright by the ALICE HLT Project        * 
5  * ALICE Experiment at CERN, All rights reserved.                         *
6  *                                                                        *
7  * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8  *                  Timm Steinbeck <timm@kip.uni-heidelberg.de>           *
9  *                  for The ALICE HLT Project.                            *
10  *                                                                        *
11  * Permission to use, copy, modify and distribute this software and its   *
12  * documentation strictly for non-commercial purposes is hereby granted   *
13  * without fee, provided that the above copyright notice appears in all   *
14  * copies and that both the copyright notice and this permission notice   *
15  * appear in the supporting documentation. The authors make no claims     *
16  * about the suitability of this software for any purpose. It is          *
17  * provided "as is" without express or implied warranty.                  *
18  **************************************************************************/
19
20 /** @file   AliHLTComponent.cxx
21     @author Matthias Richter, Timm Steinbeck
22     @date   
23     @brief  Base class implementation for HLT components. */
24
25 #if __GNUC__>= 3
26 using namespace std;
27 #endif
28
29 //#include "AliHLTStdIncludes.h"
30 #include "AliHLTComponent.h"
31 #include "AliHLTComponentHandler.h"
32 #include "AliHLTMessage.h"
33 #include "TString.h"
34 #include "TObjArray.h"
35 #include "TObjectTable.h"
36 #include "TClass.h"
37 #include "TStopwatch.h"
38 #include "AliHLTMemoryFile.h"
39
40 /** ROOT macro for the implementation of ROOT specific class methods */
41 ClassImp(AliHLTComponent);
42
43 /** stopwatch macro using the stopwatch guard */
44 #define ALIHLTCOMPONENT_STOPWATCH(type) AliHLTStopwatchGuard swguard(fpStopwatches!=NULL?reinterpret_cast<TStopwatch*>(fpStopwatches->At((int)type)):NULL)
45 //#define ALIHLTCOMPONENT_STOPWATCH(type) 
46
47 /** stopwatch macro for operations of the base class */
48 #define ALIHLTCOMPONENT_BASE_STOPWATCH() ALIHLTCOMPONENT_STOPWATCH(kSWBase)
49 /** stopwatch macro for operations of the detector algorithm (DA) */
50 #define ALIHLTCOMPONENT_DA_STOPWATCH() ALIHLTCOMPONENT_STOPWATCH(kSWDA)
51
52 AliHLTComponent::AliHLTComponent()
53   :
54   fEnvironment(),
55   fCurrentEvent(0),
56   fEventCount(-1),
57   fFailedEvents(0),
58   fCurrentEventData(),
59   fpInputBlocks(NULL),
60   fCurrentInputBlock(-1),
61   fSearchDataType(kAliHLTVoidDataType),
62   fClassName(),
63   fpInputObjects(NULL),
64   fpOutputBuffer(NULL),
65   fOutputBufferSize(0),
66   fOutputBufferFilled(0),
67   fOutputBlocks(),
68   fpStopwatches(new TObjArray(kSWTypeCount)),
69   fMemFiles()
70 {
71   // see header file for class documentation
72   // or
73   // refer to README to build package
74   // or
75   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
76   memset(&fEnvironment, 0, sizeof(AliHLTComponentEnvironment));
77   if (fgpComponentHandler)
78     fgpComponentHandler->ScheduleRegister(this);
79   //SetLocalLoggingLevel(kHLTLogDefault);
80 }
81
82 AliHLTComponent::AliHLTComponent(const AliHLTComponent&)
83   :
84   AliHLTLogging(),
85   fEnvironment(),
86   fCurrentEvent(0),
87   fEventCount(-1),
88   fFailedEvents(0),
89   fCurrentEventData(),
90   fpInputBlocks(NULL),
91   fCurrentInputBlock(-1),
92   fSearchDataType(kAliHLTVoidDataType),
93   fClassName(),
94   fpInputObjects(NULL),
95   fpOutputBuffer(NULL),
96   fOutputBufferSize(0),
97   fOutputBufferFilled(0),
98   fOutputBlocks(),
99   fpStopwatches(NULL),
100   fMemFiles()
101 {
102   // see header file for class documentation
103 }
104
105 AliHLTComponent& AliHLTComponent::operator=(const AliHLTComponent&)
106
107   // see header file for class documentation
108   return *this;
109 }
110
111 AliHLTComponent::~AliHLTComponent()
112 {
113   // see header file for function documentation
114   CleanupInputObjects();
115   if (fpStopwatches!=NULL) delete fpStopwatches;
116   fpStopwatches=NULL;
117   vector<AliHLTMemoryFile*>::iterator element=fMemFiles.begin();
118   while (element!=fMemFiles.end()) {
119     if (*element) {
120       if ((*element)->IsClosed()==0) {
121         HLTWarning("memory file has not been closed, possible data loss or incomplete buffer");
122         // close but do not flush as we dont know whether the buffer is still valid
123         (*element)->Close(0);
124       }
125       delete *element;
126       *element=NULL;
127     }
128     element++;
129   }
130 }
131
132 AliHLTComponentHandler* AliHLTComponent::fgpComponentHandler=NULL;
133
134 int AliHLTComponent::SetGlobalComponentHandler(AliHLTComponentHandler* pCH, int bOverwrite) 
135 {
136   // see header file for function documentation
137   int iResult=0;
138   if (fgpComponentHandler==NULL || bOverwrite!=0)
139     fgpComponentHandler=pCH;
140   else
141     iResult=-EPERM;
142   return iResult;
143 }
144
145 int AliHLTComponent::UnsetGlobalComponentHandler() 
146 {
147   // see header file for function documentation
148   return SetGlobalComponentHandler(NULL,1);
149 }
150
151 int AliHLTComponent::Init( AliHLTComponentEnvironment* environ, void* environParam, int argc, const char** argv )
152 {
153   // see header file for function documentation
154   int iResult=0;
155   if (environ) {
156     memcpy(&fEnvironment, environ, sizeof(AliHLTComponentEnvironment));
157     fEnvironment.fParam=environParam;
158   }
159   const char** pArguments=NULL;
160   int iNofChildArgs=0;
161   TString argument="";
162   int bMissingParam=0;
163   if (argc>0) {
164     pArguments=new const char*[argc];
165     if (pArguments) {
166       for (int i=0; i<argc && iResult>=0; i++) {
167         argument=argv[i];
168         if (argument.IsNull()) continue;
169
170         // benchmark
171         if (argument.CompareTo("benchmark")==0) {
172
173           // loglevel
174         } else if (argument.CompareTo("loglevel")==0) {
175           if ((bMissingParam=(++i>=argc))) break;
176           TString parameter(argv[i]);
177           parameter.Remove(TString::kLeading, ' '); // remove all blanks
178           if (parameter.BeginsWith("0x") &&
179               parameter.Replace(0,2,"",0).IsHex()) {
180             AliHLTComponentLogSeverity loglevel=kHLTLogNone;
181             sscanf(parameter.Data(),"%x", (unsigned int*)&loglevel);
182             SetLocalLoggingLevel(loglevel);
183           } else {
184             HLTError("wrong parameter for argument %s, hex number expected", argument.Data());
185             iResult=-EINVAL;
186           }
187         } else {
188           pArguments[iNofChildArgs++]=argv[i];
189         }
190       }
191     } else {
192       iResult=-ENOMEM;
193     }
194   }
195   if (bMissingParam) {
196     HLTError("missing parameter for argument %s", argument.Data());
197     iResult=-EINVAL;
198   }
199   if (iResult>=0) {
200     iResult=DoInit(iNofChildArgs, pArguments);
201   }
202   if (iResult>=0) fEventCount=0;
203   if (pArguments) delete [] pArguments;
204   return iResult;
205 }
206
207 int AliHLTComponent::Deinit()
208 {
209   // see header file for function documentation
210   int iResult=0;
211   iResult=DoDeinit();
212   return iResult;
213 }
214
215 int AliHLTComponent::DoInit( int argc, const char** argv )
216 {
217   // see header file for function documentation
218   if (argc==0 && argv==NULL) {
219     // this is currently just to get rid of the warning "unused parameter"
220   }
221   fEventCount=0;
222   return 0;
223 }
224
225 int AliHLTComponent::DoDeinit()
226 {
227   // see header file for function documentation
228   fEventCount=0;
229   return 0;
230 }
231
232 void AliHLTComponent::DataType2Text( const AliHLTComponentDataType& type, char output[kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2] ) const
233 {
234   // see header file for function documentation
235   memset( output, 0, kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2 );
236   strncat( output, type.fOrigin, kAliHLTComponentDataTypefOriginSize );
237   strcat( output, ":" );
238   strncat( output, type.fID, kAliHLTComponentDataTypefIDsize );
239 }
240
241 string AliHLTComponent::DataType2Text( const AliHLTComponentDataType& type )
242 {
243   // see header file for function documentation
244   string out("");
245   
246   if (type==kAliHLTVoidDataType) {
247     out="VOID:VOID";
248   } else {
249     // some gymnastics in order to avoid a '0' which is part of either or both
250     // ID and origin terminating the whole string. Unfortunately, string doesn't
251     // stop appending at the '0' if the number of elements to append was 
252     // explicitely specified
253     string tmp("");
254     tmp.append(type.fOrigin, kAliHLTComponentDataTypefOriginSize);
255     out.append(tmp.c_str());
256     out.append(":");
257     tmp="";
258     tmp.append(type.fID, kAliHLTComponentDataTypefIDsize);
259     out.append(tmp.c_str());
260   }
261   return out;
262 }
263
264
265 void* AliHLTComponent::AllocMemory( unsigned long size ) 
266 {
267   // see header file for function documentation
268   if (fEnvironment.fAllocMemoryFunc)
269     return (*fEnvironment.fAllocMemoryFunc)(fEnvironment.fParam, size );
270   HLTFatal("no memory allocation handler registered");
271   return NULL;
272 }
273
274 int AliHLTComponent::MakeOutputDataBlockList( const vector<AliHLTComponentBlockData>& blocks, AliHLTUInt32_t* blockCount,
275                                               AliHLTComponentBlockData** outputBlocks ) 
276 {
277   // see header file for function documentation
278     if ( blockCount==NULL || outputBlocks==NULL )
279         return -EFAULT;
280     AliHLTUInt32_t count = blocks.size();
281     if ( !count )
282         {
283         *blockCount = 0;
284         *outputBlocks = NULL;
285         return 0;
286         }
287     *outputBlocks = reinterpret_cast<AliHLTComponentBlockData*>( AllocMemory( sizeof(AliHLTComponentBlockData)*count ) );
288     if ( !*outputBlocks )
289         return -ENOMEM;
290     for ( unsigned long i = 0; i < count; i++ ) {
291         (*outputBlocks)[i] = blocks[i];
292         if (blocks[i].fDataType==kAliHLTAnyDataType) {
293           (*outputBlocks)[i].fDataType=GetOutputDataType();
294           /* data type was set to the output data type by the PubSub AliRoot
295              Wrapper component, if data type of the block was ********:****.
296              Now handled by the component base class in order to have same
297              behavior when running embedded in AliRoot
298           memset((*outputBlocks)[i].fDataType.fID, '*', kAliHLTComponentDataTypefIDsize);
299           memset((*outputBlocks)[i].fDataType.fOrigin, '*', kAliHLTComponentDataTypefOriginSize);
300           */
301         }
302     }
303     *blockCount = count;
304     return 0;
305
306 }
307
308 int AliHLTComponent::GetEventDoneData( unsigned long size, AliHLTComponentEventDoneData** edd ) 
309 {
310   // see header file for function documentation
311   if (fEnvironment.fGetEventDoneDataFunc)
312     return (*fEnvironment.fGetEventDoneDataFunc)(fEnvironment.fParam, fCurrentEvent, size, edd );
313   return -ENOSYS;
314 }
315
316 int AliHLTComponent::FindMatchingDataTypes(AliHLTComponent* pConsumer, vector<AliHLTComponentDataType>* tgtList) 
317 {
318   // see header file for function documentation
319   int iResult=0;
320   if (pConsumer) {
321     vector<AliHLTComponentDataType> ctlist;
322     ((AliHLTComponent*)pConsumer)->GetInputDataTypes(ctlist);
323     vector<AliHLTComponentDataType>::iterator type=ctlist.begin();
324     //AliHLTComponentDataType ouptdt=GetOutputDataType();
325     //PrintDataTypeContent(ouptdt, "publisher \'%s\'");
326     while (type!=ctlist.end() && iResult==0) {
327       //PrintDataTypeContent((*type), "consumer \'%s\'");
328       if ((*type)==GetOutputDataType() ||
329           (*type)==kAliHLTAnyDataType) {
330         if (tgtList) tgtList->push_back(*type);
331         iResult++;
332         // this loop has to be changed in case of multiple output types
333         break;
334       }
335       type++;
336     }
337   } else {
338     iResult=-EINVAL;
339   }
340   return iResult;
341 }
342
343 void AliHLTComponent::PrintDataTypeContent(AliHLTComponentDataType& dt, const char* format) const
344 {
345   // see header file for function documentation
346   const char* fmt="publisher \'%s\'";
347   if (format) fmt=format;
348   HLTMessage(fmt, (DataType2Text(dt)).c_str());
349   HLTMessage("%x %x %x %x %x %x %x %x : %x %x %x %x", 
350              dt.fID[0],
351              dt.fID[1],
352              dt.fID[2],
353              dt.fID[3],
354              dt.fID[4],
355              dt.fID[5],
356              dt.fID[6],
357              dt.fID[7],
358              dt.fOrigin[0],
359              dt.fOrigin[1],
360              dt.fOrigin[2],
361              dt.fOrigin[3]);
362 }
363
364 void AliHLTComponent::FillBlockData( AliHLTComponentBlockData& blockData ) const
365 {
366   // see header file for function documentation
367   blockData.fStructSize = sizeof(blockData);
368   FillShmData( blockData.fShmKey );
369   blockData.fOffset = ~(AliHLTUInt32_t)0;
370   blockData.fPtr = NULL;
371   blockData.fSize = 0;
372   FillDataType( blockData.fDataType );
373   blockData.fSpecification = kAliHLTVoidDataSpec;
374 }
375
376 void AliHLTComponent::FillShmData( AliHLTComponentShmData& shmData ) const
377 {
378   // see header file for function documentation
379   shmData.fStructSize = sizeof(shmData);
380   shmData.fShmType = gkAliHLTComponentInvalidShmType;
381   shmData.fShmID = gkAliHLTComponentInvalidShmID;
382 }
383
384 void AliHLTComponent::FillDataType( AliHLTComponentDataType& dataType ) const
385 {
386   // see header file for function documentation
387   dataType=kAliHLTAnyDataType;
388 }
389
390 void AliHLTComponent::CopyDataType(AliHLTComponentDataType& tgtdt, const AliHLTComponentDataType& srcdt) 
391 {
392   // see header file for function documentation
393   memcpy(&tgtdt.fID[0], &srcdt.fID[0], kAliHLTComponentDataTypefIDsize);
394   memcpy(&tgtdt.fOrigin[0], &srcdt.fOrigin[0], kAliHLTComponentDataTypefOriginSize);
395 }
396
397 void AliHLTComponent::SetDataType(AliHLTComponentDataType& tgtdt, const char* id, const char* origin) 
398 {
399   // see header file for function documentation
400   tgtdt.fStructSize = sizeof(AliHLTComponentDataType);
401   memset(&tgtdt.fID[0], 0, kAliHLTComponentDataTypefIDsize);
402   memset(&tgtdt.fOrigin[0], 0, kAliHLTComponentDataTypefOriginSize);
403
404   if ((int)strlen(id)>kAliHLTComponentDataTypefIDsize) {
405     HLTWarning("data type id %s is too long, truncated to %d", id, kAliHLTComponentDataTypefIDsize);
406   }
407   strncpy(&tgtdt.fID[0], id, kAliHLTComponentDataTypefIDsize);
408
409   if ((int)strlen(origin)>kAliHLTComponentDataTypefOriginSize) {
410     HLTWarning("data type origin %s is too long, truncated to %d", origin, kAliHLTComponentDataTypefOriginSize);
411   }
412   strncpy(&tgtdt.fOrigin[0], origin, kAliHLTComponentDataTypefOriginSize);
413 }
414
415 void AliHLTComponent::FillEventData(AliHLTComponentEventData& evtData)
416 {
417   // see header file for function documentation
418   memset(&evtData, 0, sizeof(AliHLTComponentEventData));
419   evtData.fStructSize=sizeof(AliHLTComponentEventData);
420 }
421
422 void AliHLTComponent::PrintComponentDataTypeInfo(const AliHLTComponentDataType& dt) 
423 {
424   // see header file for function documentation
425   TString msg;
426   msg.Form("AliHLTComponentDataType(%d): ID=\"", dt.fStructSize);
427   for ( int i = 0; i < kAliHLTComponentDataTypefIDsize; i++ ) {
428    if (dt.fID[i]!=0) msg+=dt.fID[i];
429    else msg+="\\0";
430   }
431   msg+="\" Origin=\"";
432   for ( int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++ ) {
433    if (dt.fOrigin[i]!=0) msg+=dt.fOrigin[i];
434    else msg+="\\0";
435   }
436   msg+="\"";
437   AliHLTLogging::Message(NULL, kHLTLogNone, NULL , NULL, msg.Data());
438 }
439
440 int AliHLTComponent::GetEventCount() const
441 {
442   // see header file for function documentation
443   return fEventCount;
444 }
445
446 int AliHLTComponent::IncrementEventCounter()
447 {
448   // see header file for function documentation
449   if (fEventCount>=0) fEventCount++;
450   return fEventCount;
451 }
452
453 int AliHLTComponent::GetNumberOfInputBlocks() const
454 {
455   // see header file for function documentation
456   if (fpInputBlocks!=NULL) {
457     return fCurrentEventData.fBlockCnt;
458   }
459   return 0;
460 }
461
462 const TObject* AliHLTComponent::GetFirstInputObject(const AliHLTComponentDataType& dt,
463                                                     const char* classname,
464                                                     int bForce)
465 {
466   // see header file for function documentation
467   ALIHLTCOMPONENT_BASE_STOPWATCH();
468   fSearchDataType=dt;
469   if (classname) fClassName=classname;
470   else fClassName.clear();
471   int idx=FindInputBlock(fSearchDataType, 0, 1);
472   TObject* pObj=NULL;
473   if (idx>=0) {
474     HLTDebug("found block %d when searching for data type %s", idx, DataType2Text(dt).c_str());
475     if ((pObj=GetInputObject(idx, fClassName.c_str(), bForce))!=NULL) {
476       fCurrentInputBlock=idx;
477     } else {
478     }
479   }
480   return pObj;
481 }
482
483 const TObject* AliHLTComponent::GetFirstInputObject(const char* dtID, 
484                                                     const char* dtOrigin,
485                                                     const char* classname,
486                                                     int         bForce)
487 {
488   // see header file for function documentation
489   ALIHLTCOMPONENT_BASE_STOPWATCH();
490   AliHLTComponentDataType dt;
491   SetDataType(dt, dtID, dtOrigin);
492   return GetFirstInputObject(dt, classname, bForce);
493 }
494
495 const TObject* AliHLTComponent::GetNextInputObject(int bForce)
496 {
497   // see header file for function documentation
498   ALIHLTCOMPONENT_BASE_STOPWATCH();
499   int idx=FindInputBlock(fSearchDataType, fCurrentInputBlock+1, 1);
500   //HLTDebug("found block %d when searching for data type %s", idx, DataType2Text(fSearchDataType).c_str());
501   TObject* pObj=NULL;
502   if (idx>=0) {
503     if ((pObj=GetInputObject(idx, fClassName.c_str(), bForce))!=NULL) {
504       fCurrentInputBlock=idx;
505     }
506   }
507   return pObj;
508 }
509
510 int AliHLTComponent::FindInputBlock(const AliHLTComponentDataType& dt, int startIdx, int bObject) const
511 {
512   // see header file for function documentation
513   int iResult=-ENOENT;
514   if (fpInputBlocks!=NULL) {
515     int idx=startIdx<0?0:startIdx;
516     for ( ; (UInt_t)idx<fCurrentEventData.fBlockCnt && iResult==-ENOENT; idx++) {
517       if (bObject!=0) {
518         if (fpInputBlocks[idx].fPtr==NULL) continue;
519         AliHLTUInt32_t firstWord=*((AliHLTUInt32_t*)fpInputBlocks[idx].fPtr);
520         if (firstWord!=fpInputBlocks[idx].fSize-sizeof(AliHLTUInt32_t)) continue;
521       }
522       if (dt == kAliHLTAnyDataType || fpInputBlocks[idx].fDataType == dt) {
523         iResult=idx;
524       }
525     }
526   }
527   return iResult;
528 }
529
530 TObject* AliHLTComponent::CreateInputObject(int idx, int bForce)
531 {
532   // see header file for function documentation
533   TObject* pObj=NULL;
534   if (fpInputBlocks!=NULL) {
535     if ((UInt_t)idx<fCurrentEventData.fBlockCnt) {
536       if (fpInputBlocks[idx].fPtr) {
537         AliHLTUInt32_t firstWord=*((AliHLTUInt32_t*)fpInputBlocks[idx].fPtr);
538         if (firstWord==fpInputBlocks[idx].fSize-sizeof(AliHLTUInt32_t)) {
539           HLTDebug("create object from block %d size %d", idx, fpInputBlocks[idx].fSize);
540           AliHLTMessage msg(fpInputBlocks[idx].fPtr, fpInputBlocks[idx].fSize);
541           TClass* objclass=msg.GetClass();
542           pObj=msg.ReadObject(objclass);
543           if (pObj && objclass) {
544             HLTDebug("object %p type %s created", pObj, objclass->GetName());
545           } else {
546           }
547           //} else {
548         } else if (bForce!=0) {
549           HLTError("size missmatch: block size %d, indicated %d", fpInputBlocks[idx].fSize, firstWord+sizeof(AliHLTUInt32_t));
550         }
551       } else {
552         HLTFatal("block descriptor empty");
553       }
554     } else {
555       HLTError("index %d out of range %d", idx, fCurrentEventData.fBlockCnt);
556     }
557   } else {
558     HLTError("no input blocks available");
559   }
560   
561   return pObj;
562 }
563
564 TObject* AliHLTComponent::GetInputObject(int idx, const char* classname, int bForce)
565 {
566   // see header file for function documentation
567   if (fpInputObjects==NULL) {
568     fpInputObjects=new TObjArray(fCurrentEventData.fBlockCnt);
569   }
570   TObject* pObj=NULL;
571   if (fpInputObjects) {
572     pObj=fpInputObjects->At(idx);
573     if (pObj==NULL) {
574       pObj=CreateInputObject(idx, bForce);
575       if (pObj) {
576         fpInputObjects->AddAt(pObj, idx);
577       }
578     }
579   } else {
580     HLTFatal("memory allocation failed: TObjArray of size %d", fCurrentEventData.fBlockCnt);
581   }
582   return pObj;
583 }
584
585 int AliHLTComponent::CleanupInputObjects()
586 {
587   // see header file for function documentation
588   if (!fpInputObjects) return 0;
589   TObjArray* array=fpInputObjects;
590   fpInputObjects=NULL;
591   for (int i=0; i<array->GetEntries(); i++) {
592     TObject* pObj=array->At(i);
593     // grrr, garbage collection strikes back: When read via AliHLTMessage
594     // (CreateInputObject), and written to a TFile afterwards, the
595     // TFile::Close calls ROOOT's garbage collection. No clue why the
596     // object ended up in the key list and needs to be deleted
597     if (pObj && gObjectTable->PtrIsValid(pObj)) delete pObj;
598   }
599   delete array;
600   return 0;
601 }
602
603 AliHLTComponentDataType AliHLTComponent::GetDataType(const TObject* pObject)
604 {
605   // see header file for function documentation
606   ALIHLTCOMPONENT_BASE_STOPWATCH();
607   AliHLTComponentDataType dt=kAliHLTVoidDataType;
608   int idx=fCurrentInputBlock;
609   if (pObject) {
610     if (fpInputObjects==NULL || (idx=fpInputObjects->IndexOf(pObject))>=0) {
611     } else {
612       HLTError("unknown object %p", pObject);
613     }
614   }
615   if (idx>=0) {
616     if ((UInt_t)idx<fCurrentEventData.fBlockCnt) {
617       dt=fpInputBlocks[idx].fDataType;
618     } else {
619       HLTFatal("severe internal error, index out of range");
620     }
621   }
622   return dt;
623 }
624
625 AliHLTUInt32_t AliHLTComponent::GetSpecification(const TObject* pObject)
626 {
627   // see header file for function documentation
628   ALIHLTCOMPONENT_BASE_STOPWATCH();
629   AliHLTUInt32_t iSpec=kAliHLTVoidDataSpec;
630   int idx=fCurrentInputBlock;
631   if (pObject) {
632     if (fpInputObjects==NULL || (idx=fpInputObjects->IndexOf(pObject))>=0) {
633     } else {
634       HLTError("unknown object %p", pObject);
635     }
636   }
637   if (idx>=0) {
638     if ((UInt_t)idx<fCurrentEventData.fBlockCnt) {
639       iSpec=fpInputBlocks[idx].fSpecification;
640     } else {
641       HLTFatal("severe internal error, index out of range");
642     }
643   }
644   return iSpec;
645 }
646
647 const AliHLTComponentBlockData* AliHLTComponent::GetFirstInputBlock(const AliHLTComponentDataType& dt)
648 {
649   // see header file for function documentation
650   ALIHLTCOMPONENT_BASE_STOPWATCH();
651   fSearchDataType=dt;
652   fClassName.clear();
653   int idx=FindInputBlock(fSearchDataType, 0);
654   const AliHLTComponentBlockData* pBlock=NULL;
655   if (idx>=0) {
656     // check for fpInputBlocks pointer done in FindInputBlock
657     pBlock=&fpInputBlocks[idx];
658     fCurrentInputBlock=idx;
659   }
660   return pBlock;
661 }
662
663 const AliHLTComponentBlockData* AliHLTComponent::GetFirstInputBlock(const char* dtID, 
664                                                                     const char* dtOrigin)
665 {
666   // see header file for function documentation
667   ALIHLTCOMPONENT_BASE_STOPWATCH();
668   AliHLTComponentDataType dt;
669   SetDataType(dt, dtID, dtOrigin);
670   return GetFirstInputBlock(dt);
671 }
672
673 const AliHLTComponentBlockData* AliHLTComponent::GetNextInputBlock()
674 {
675   // see header file for function documentation
676   ALIHLTCOMPONENT_BASE_STOPWATCH();
677   int idx=FindInputBlock(fSearchDataType, fCurrentInputBlock+1);
678   const AliHLTComponentBlockData* pBlock=NULL;
679   if (idx>=0) {
680     // check for fpInputBlocks pointer done in FindInputBlock
681     pBlock=&fpInputBlocks[idx];
682     fCurrentInputBlock=idx;
683   }
684   return pBlock;
685 }
686
687 int AliHLTComponent::FindInputBlock(const AliHLTComponentBlockData* pBlock) const
688 {
689   // see header file for function documentation
690   int iResult=-ENOENT;
691   if (fpInputBlocks!=NULL) {
692     if (pBlock) {
693       if (pBlock>=fpInputBlocks && pBlock<fpInputBlocks+fCurrentEventData.fBlockCnt) {
694         iResult=(int)(pBlock-fpInputBlocks);
695       }
696     } else {
697       iResult=-EINVAL;
698     }
699   }
700   return iResult;
701 }
702
703 AliHLTUInt32_t AliHLTComponent::GetSpecification(const AliHLTComponentBlockData* pBlock)
704 {
705   // see header file for function documentation
706   ALIHLTCOMPONENT_BASE_STOPWATCH();
707   AliHLTUInt32_t iSpec=kAliHLTVoidDataSpec;
708   int idx=fCurrentInputBlock;
709   if (pBlock) {
710     if (fpInputObjects==NULL || (idx=FindInputBlock(pBlock))>=0) {
711     } else {
712       HLTError("unknown Block %p", pBlock);
713     }
714   }
715   if (idx>=0) {
716     // check for fpInputBlocks pointer done in FindInputBlock
717     iSpec=fpInputBlocks[idx].fSpecification;
718   }
719   return iSpec;
720 }
721
722 int AliHLTComponent::PushBack(TObject* pObject, const AliHLTComponentDataType& dt, AliHLTUInt32_t spec, 
723                               void* pHeader, int headerSize)
724 {
725   // see header file for function documentation
726   ALIHLTCOMPONENT_BASE_STOPWATCH();
727   int iResult=0;
728   if (pObject) {
729     AliHLTMessage msg(kMESS_OBJECT);
730     msg.WriteObject(pObject);
731     Int_t iMsgLength=msg.Length();
732     if (iMsgLength>0) {
733       msg.SetLength(); // sets the length to the first (reserved) word
734       iResult=InsertOutputBlock(msg.Buffer(), iMsgLength, dt, spec, pHeader, headerSize);
735       if (iResult>=0) {
736         HLTDebug("object %s (%p) size %d inserted to output", pObject->ClassName(), pObject, iMsgLength);
737       }
738     } else {
739       HLTError("object serialization failed for object %p", pObject);
740       iResult=-ENOMSG;
741     }
742   } else {
743     iResult=-EINVAL;
744   }
745   return iResult;
746 }
747
748 int AliHLTComponent::PushBack(TObject* pObject, const char* dtID, const char* dtOrigin, AliHLTUInt32_t spec,
749                               void* pHeader, int headerSize)
750 {
751   // see header file for function documentation
752   ALIHLTCOMPONENT_BASE_STOPWATCH();
753   AliHLTComponentDataType dt;
754   SetDataType(dt, dtID, dtOrigin);
755   return PushBack(pObject, dt, spec, pHeader, headerSize);
756 }
757
758 int AliHLTComponent::PushBack(void* pBuffer, int iSize, const AliHLTComponentDataType& dt, AliHLTUInt32_t spec)
759 {
760   // see header file for function documentation
761   ALIHLTCOMPONENT_BASE_STOPWATCH();
762   return InsertOutputBlock(pBuffer, iSize, dt, spec);
763 }
764
765 int AliHLTComponent::PushBack(void* pBuffer, int iSize, const char* dtID, const char* dtOrigin, AliHLTUInt32_t spec)
766 {
767   // see header file for function documentation
768   ALIHLTCOMPONENT_BASE_STOPWATCH();
769   AliHLTComponentDataType dt;
770   SetDataType(dt, dtID, dtOrigin);
771   return PushBack(pBuffer, iSize, dt, spec);
772 }
773
774 int AliHLTComponent::InsertOutputBlock(void* pBuffer, int iBufferSize, const AliHLTComponentDataType& dt, AliHLTUInt32_t spec,
775                               void* pHeader, int iHeaderSize)
776 {
777   // see header file for function documentation
778   int iResult=0;
779   int iBlkSize = iBufferSize + iHeaderSize;
780   if (pBuffer) {
781     if (fpOutputBuffer && iBlkSize<=(int)(fOutputBufferSize-fOutputBufferFilled)) {
782       AliHLTUInt8_t* pTgt=fpOutputBuffer+fOutputBufferFilled;
783       AliHLTComponentBlockData bd;
784       FillBlockData( bd );
785       bd.fOffset        = fOutputBufferFilled;
786       bd.fPtr           = pTgt;
787       bd.fSize          = iBlkSize;
788       bd.fDataType      = dt;
789       bd.fSpecification = spec;
790       if (pHeader!=NULL && pHeader!=pTgt) {
791         memcpy(pTgt, pHeader, iHeaderSize);
792       }
793
794       pTgt += (AliHLTUInt8_t) iHeaderSize;
795
796       if (pBuffer!=NULL && pBuffer!=pTgt) {
797         memcpy(pTgt, pBuffer, iBufferSize);
798         
799         //AliHLTUInt32_t firstWord=*((AliHLTUInt32_t*)pBuffer); 
800         //HLTDebug("copy %d bytes from %p to output buffer %p, first word %#x", iBufferSize, pBuffer, pTgt, firstWord);
801       }
802       fOutputBufferFilled+=bd.fSize;
803       fOutputBlocks.push_back( bd );
804       //HLTDebug("buffer inserted to output: size %d data type %s spec %#x", iBlkSize, DataType2Text(dt).c_str(), spec);
805     } else {
806       if (fpOutputBuffer) {
807         HLTError("too little space in output buffer: %d, required %d", fOutputBufferSize-fOutputBufferFilled, iBlkSize);
808       } else {
809         HLTError("output buffer not available");
810       }
811       iResult=-ENOSPC;
812     }
813   } else {
814     iResult=-EINVAL;
815   }
816   return iResult;
817 }
818
819 int AliHLTComponent::EstimateObjectSize(TObject* pObject) const
820 {
821   // see header file for function documentation
822   if (!pObject) return -EINVAL;
823     AliHLTMessage msg(kMESS_OBJECT);
824     msg.WriteObject(pObject);
825     return msg.Length();  
826 }
827
828 AliHLTMemoryFile* AliHLTComponent::CreateMemoryFile(int capacity, const char* dtID,
829                                                     const char* dtOrigin,
830                                                     AliHLTUInt32_t spec)
831 {
832   // see header file for function documentation
833   ALIHLTCOMPONENT_BASE_STOPWATCH();
834   AliHLTComponentDataType dt;
835   SetDataType(dt, dtID, dtOrigin);
836   return CreateMemoryFile(capacity, dt, spec);
837 }
838
839 AliHLTMemoryFile* AliHLTComponent::CreateMemoryFile(int capacity,
840                                                     const AliHLTComponentDataType& dt,
841                                                     AliHLTUInt32_t spec)
842 {
843   // see header file for function documentation
844   ALIHLTCOMPONENT_BASE_STOPWATCH();
845   AliHLTMemoryFile* pFile=NULL;
846   if (capacity>=0 && capacity<=fOutputBufferSize-fOutputBufferFilled){
847     AliHLTUInt8_t* pTgt=fpOutputBuffer+fOutputBufferFilled;
848     pFile=new AliHLTMemoryFile((char*)pTgt, capacity);
849     if (pFile) {
850       int nofBlocks=fOutputBlocks.size();
851       if (nofBlocks+1>fMemFiles.size()) {
852         fMemFiles.resize(nofBlocks+1, NULL);
853       }
854       if (nofBlocks<fMemFiles.size()) {
855         fMemFiles[nofBlocks]=pFile;
856         AliHLTComponentBlockData bd;
857         FillBlockData( bd );
858         bd.fOffset        = fOutputBufferFilled;
859         bd.fPtr           = pTgt;
860         bd.fSize          = capacity;
861         bd.fDataType      = dt;
862         bd.fSpecification = spec;
863         fOutputBufferFilled+=bd.fSize;
864         fOutputBlocks.push_back( bd );
865       } else {
866         HLTError("can not allocate/grow object array");
867         pFile->Close(0);
868         delete pFile;
869         pFile=NULL;
870       }
871     }
872   } else {
873     HLTError("can not create memory file of size %d (%d available)", capacity, fOutputBufferSize-fOutputBufferFilled);
874   }
875   return pFile;
876 }
877
878 AliHLTMemoryFile* AliHLTComponent::CreateMemoryFile(const char* dtID,
879                                                     const char* dtOrigin,
880                                                     AliHLTUInt32_t spec,
881                                                     float capacity)
882 {
883   // see header file for function documentation
884   ALIHLTCOMPONENT_BASE_STOPWATCH();
885   AliHLTComponentDataType dt;
886   SetDataType(dt, dtID, dtOrigin);
887   int size=fOutputBufferSize-fOutputBufferFilled;
888   if (capacity<0 || capacity>1.0) {
889     HLTError("invalid parameter: capacity %f", capacity);
890     return NULL;
891   }
892   size=(int)(size*capacity);
893   return CreateMemoryFile(size, dt, spec);
894 }
895
896 AliHLTMemoryFile* AliHLTComponent::CreateMemoryFile(const AliHLTComponentDataType& dt,
897                                                     AliHLTUInt32_t spec,
898                                                     float capacity)
899 {
900   // see header file for function documentation
901   ALIHLTCOMPONENT_BASE_STOPWATCH();
902   int size=fOutputBufferSize-fOutputBufferFilled;
903   if (capacity<0 || capacity>1.0) {
904     HLTError("invalid parameter: capacity %f", capacity);
905     return NULL;
906   }
907   size=(int)(size*capacity);
908   return CreateMemoryFile(size, dt, spec);
909 }
910
911 int AliHLTComponent::Write(AliHLTMemoryFile* pFile, const TObject* pObject,
912                            const char* key, int option)
913 {
914   int iResult=0;
915   if (pFile && pObject) {
916     pFile->cd();
917     iResult=pObject->Write(key, option);
918     if (iResult>0) {
919       // success
920     } else {
921       iResult=-pFile->GetErrno();
922       if (iResult==-ENOSPC) {
923         HLTError("error writing memory file, buffer too small");
924       }
925     }
926   } else {
927     iResult=-EINVAL;
928   }
929   return iResult;
930 }
931
932 int AliHLTComponent::CloseMemoryFile(AliHLTMemoryFile* pFile)
933 {
934   int iResult=0;
935   if (pFile) {
936     vector<AliHLTMemoryFile*>::iterator element=fMemFiles.begin();
937     int i=0;
938     while (element!=fMemFiles.end() && iResult>=0) {
939       if (*element && *element==pFile) {
940         iResult=pFile->Close();
941         
942         // sync memory files and descriptors
943         if (iResult>=0) {
944           fOutputBlocks[i].fSize=(*element)->GetSize()+(*element)->GetHeaderSize();
945         }
946         delete *element;
947         *element=NULL;
948         return iResult;
949       }
950       element++; i++;
951     }
952     HLTError("can not find memory file %p", pFile);
953     iResult=-ENOENT;
954   } else {
955     iResult=-EINVAL;
956   }
957   return iResult;
958 }
959
960 int AliHLTComponent::CreateEventDoneData(AliHLTComponentEventDoneData edd)
961 {
962   // see header file for function documentation
963   int iResult=-ENOSYS;
964   //#warning  function not yet implemented
965   HLTWarning("function not yet implemented");
966   return iResult;
967 }
968
969 int AliHLTComponent::ProcessEvent( const AliHLTComponentEventData& evtData,
970                                    const AliHLTComponentBlockData* blocks, 
971                                    AliHLTComponentTriggerData& trigData,
972                                    AliHLTUInt8_t* outputPtr, 
973                                    AliHLTUInt32_t& size,
974                                    AliHLTUInt32_t& outputBlockCnt, 
975                                    AliHLTComponentBlockData*& outputBlocks,
976                                    AliHLTComponentEventDoneData*& edd )
977 {
978   // see header file for function documentation
979   ALIHLTCOMPONENT_BASE_STOPWATCH();
980   int iResult=0;
981   fCurrentEvent=evtData.fEventID;
982   fCurrentEventData=evtData;
983   fpInputBlocks=blocks;
984   fCurrentInputBlock=-1;
985   fSearchDataType=kAliHLTAnyDataType;
986   fpOutputBuffer=outputPtr;
987   fOutputBufferSize=size;
988   fOutputBufferFilled=0;
989   fOutputBlocks.clear();
990   
991   vector<AliHLTComponentBlockData> blockData;
992   { // dont delete, sets the scope for the stopwatch guard
993     ALIHLTCOMPONENT_DA_STOPWATCH();
994     iResult=DoProcessing(evtData, blocks, trigData, outputPtr, size, blockData, edd);
995   } // end of the scope of the stopwatch guard
996   if (iResult>=0) {
997     if (fOutputBlocks.size()>0) {
998       //HLTDebug("got %d block(s) via high level interface", fOutputBlocks.size());
999       
1000       // sync memory files and descriptors
1001       vector<AliHLTMemoryFile*>::iterator element=fMemFiles.begin();
1002       int i=0;
1003       while (element!=fMemFiles.end() && iResult>=0) {
1004         if (*element) {
1005           if ((*element)->IsClosed()==0) {
1006             HLTWarning("memory file has not been closed, force flush");
1007             iResult=CloseMemoryFile(*element);
1008           }
1009         }
1010         element++; i++;
1011       }
1012
1013       if (iResult>=0) {
1014         // create the descriptor list
1015         if (blockData.size()>0) {
1016           HLTError("low level and high interface must not be mixed; use PushBack methods to insert data blocks");
1017           iResult=-EFAULT;
1018         } else {
1019           iResult=MakeOutputDataBlockList(fOutputBlocks, &outputBlockCnt, &outputBlocks);
1020           size=fOutputBufferFilled;
1021         }
1022       }
1023     } else {
1024       iResult=MakeOutputDataBlockList(blockData, &outputBlockCnt, &outputBlocks);
1025     }
1026     if (iResult<0) {
1027       HLTFatal("component %s (%p): can not convert output block descriptor list", GetComponentID(), this);
1028     }
1029   }
1030   if (iResult<0) {
1031     outputBlockCnt=0;
1032     outputBlocks=NULL;
1033   }
1034   CleanupInputObjects();
1035   IncrementEventCounter();
1036   return iResult;
1037 }
1038
1039 AliHLTComponent::AliHLTStopwatchGuard::AliHLTStopwatchGuard()
1040   :
1041   fpStopwatch(NULL),
1042   fpPrec(NULL)
1043 {
1044   // standard constructor (not for use)
1045 }
1046
1047 AliHLTComponent::AliHLTStopwatchGuard::AliHLTStopwatchGuard(TStopwatch* pStopwatch)
1048   :
1049   fpStopwatch(pStopwatch),
1050   fpPrec(NULL)
1051 {
1052   // constructor
1053
1054   // check for already existing guard
1055   if (fgpCurrent) fpPrec=fgpCurrent;
1056   fgpCurrent=this;
1057
1058   // stop the preceeding guard if it controls a different stopwatch
1059   int bStart=1;
1060   if (fpPrec && fpPrec!=this) bStart=fpPrec->Hold(fpStopwatch);
1061
1062   // start the stopwatch if the current guard controls a different one
1063   if (fpStopwatch && bStart==1) fpStopwatch->Start(kFALSE);
1064 }
1065
1066 AliHLTComponent::AliHLTStopwatchGuard::AliHLTStopwatchGuard(const AliHLTStopwatchGuard&)
1067   :
1068   fpStopwatch(NULL),
1069   fpPrec(NULL)
1070 {
1071   //
1072   // copy constructor not for use
1073   //
1074 }
1075
1076 AliHLTComponent::AliHLTStopwatchGuard& AliHLTComponent::AliHLTStopwatchGuard::operator=(const AliHLTStopwatchGuard&)
1077 {
1078   //
1079   // assignment operator not for use
1080   //
1081   fpStopwatch=NULL;
1082   fpPrec=NULL;
1083   return *this;
1084 }
1085
1086 AliHLTComponent::AliHLTStopwatchGuard* AliHLTComponent::AliHLTStopwatchGuard::fgpCurrent=NULL;
1087
1088 AliHLTComponent::AliHLTStopwatchGuard::~AliHLTStopwatchGuard()
1089 {
1090   // destructor
1091
1092   // resume the preceeding guard if it controls a different stopwatch
1093   int bStop=1;
1094   if (fpPrec && fpPrec!=this) bStop=fpPrec->Resume(fpStopwatch);
1095
1096   // stop the stopwatch if the current guard controls a different one
1097   if (fpStopwatch && bStop==1) fpStopwatch->Stop();
1098
1099   // resume to the preceeding guard
1100   fgpCurrent=fpPrec;
1101 }
1102
1103 int AliHLTComponent::AliHLTStopwatchGuard::Hold(TStopwatch* pSucc)
1104 {
1105   // see header file for function documentation
1106   if (fpStopwatch!=NULL && fpStopwatch!=pSucc) fpStopwatch->Stop();
1107   return fpStopwatch!=pSucc?1:0;
1108 }
1109
1110 int AliHLTComponent::AliHLTStopwatchGuard::Resume(TStopwatch* pSucc)
1111 {
1112   // see header file for function documentation
1113   if (fpStopwatch!=NULL && fpStopwatch!=pSucc) fpStopwatch->Start(kFALSE);
1114   return fpStopwatch!=pSucc?1:0;
1115 }
1116
1117 int AliHLTComponent::SetStopwatch(TObject* pSW, AliHLTStopwatchType type) 
1118 {
1119   // see header file for function documentation
1120   int iResult=0;
1121   if (pSW!=NULL && type<kSWTypeCount) {
1122     if (fpStopwatches) {
1123       TObject* pObj=fpStopwatches->At((int)type);
1124       if (pSW==NULL        // explicit reset
1125           || pObj==NULL) { // explicit set
1126         fpStopwatches->AddAt(pSW, (int)type);
1127       } else if (pObj!=pSW) {
1128         HLTWarning("stopwatch %d already set, reset first", (int)type);
1129         iResult=-EBUSY;
1130       }
1131     }
1132   } else {
1133     iResult=-EINVAL;
1134   }
1135   return iResult;
1136 }
1137
1138 int AliHLTComponent::SetStopwatches(TObjArray* pStopwatches)
1139 {
1140   // see header file for function documentation
1141   if (pStopwatches==NULL) return -EINVAL;
1142
1143   int iResult=0;
1144   for (int i=0 ; i<(int)kSWTypeCount && pStopwatches->GetEntries(); i++)
1145     SetStopwatch(pStopwatches->At(i), (AliHLTStopwatchType)i);
1146   return iResult;
1147 }