b7b8d4f85b6ca3545d5f007cb5efb5178040cc18
[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 "TMath.h"
35 #include "TObjArray.h"
36 #include "TObjectTable.h"
37 #include "TClass.h"
38 #include "TStopwatch.h"
39 #include "AliHLTMemoryFile.h"
40 #include "AliHLTMisc.h"
41 #include <cassert>
42 #include <stdint.h>
43
44 /**
45  * default compression level for ROOT objects
46  */
47 #define ALIHLTCOMPONENT_DEFAULT_OBJECT_COMPRESSION 5
48 #define ALIHLTCOMPONENT_STATTIME_SCALER 1000000
49
50 /** ROOT macro for the implementation of ROOT specific class methods */
51 ClassImp(AliHLTComponent);
52
53 /** stopwatch macro using the stopwatch guard */
54 #define ALIHLTCOMPONENT_STOPWATCH(type) AliHLTStopwatchGuard swguard(fpStopwatches!=NULL?reinterpret_cast<TStopwatch*>(fpStopwatches->At((int)type)):NULL)
55 //#define ALIHLTCOMPONENT_STOPWATCH(type) 
56
57 /** stopwatch macro for operations of the base class */
58 #define ALIHLTCOMPONENT_BASE_STOPWATCH() ALIHLTCOMPONENT_STOPWATCH(kSWBase)
59 /** stopwatch macro for operations of the detector algorithm (DA) */
60 #define ALIHLTCOMPONENT_DA_STOPWATCH() ALIHLTCOMPONENT_STOPWATCH(kSWDA)
61
62 AliHLTComponent::AliHLTComponent()
63   :
64   fEnvironment(),
65   fCurrentEvent(0),
66   fEventCount(-1),
67   fFailedEvents(0),
68   fCurrentEventData(),
69   fpInputBlocks(NULL),
70   fCurrentInputBlock(-1),
71   fSearchDataType(kAliHLTVoidDataType),
72   fClassName(),
73   fpInputObjects(NULL),
74   fpOutputBuffer(NULL),
75   fOutputBufferSize(0),
76   fOutputBufferFilled(0),
77   fOutputBlocks(),
78   fpStopwatches(new TObjArray(kSWTypeCount)),
79   fMemFiles(),
80   fpRunDesc(NULL),
81   fpDDLList(NULL),
82   fCDBSetRunNoFunc(false),
83   fChainId(),
84   fChainIdCrc(0),
85   fpBenchmark(NULL),
86   fRequireSteeringBlocks(false),
87   fEventType(gkAliEventTypeUnknown),
88   fComponentArgs(),
89   fEventDoneData(NULL),
90   fEventDoneDataSize(0),
91   fCompressionLevel(ALIHLTCOMPONENT_DEFAULT_OBJECT_COMPRESSION)
92   , fLastObjectSize(0)
93 {
94   // see header file for class documentation
95   // or
96   // refer to README to build package
97   // or
98   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
99   memset(&fEnvironment, 0, sizeof(AliHLTAnalysisEnvironment));
100   if (fgpComponentHandler)
101     fgpComponentHandler->ScheduleRegister(this);
102   //SetLocalLoggingLevel(kHLTLogDefault);
103 }
104
105 AliHLTComponent::~AliHLTComponent()
106 {
107   // see header file for function documentation
108   if (fpBenchmark) delete fpBenchmark;
109   fpBenchmark=NULL;
110
111   CleanupInputObjects();
112   if (fpStopwatches!=NULL) delete fpStopwatches;
113   fpStopwatches=NULL;
114   AliHLTMemoryFilePList::iterator element=fMemFiles.begin();
115   while (element!=fMemFiles.end()) {
116     if (*element) {
117       if ((*element)->IsClosed()==0) {
118         HLTWarning("memory file has not been closed, possible data loss or incomplete buffer");
119         // close but do not flush as we dont know whether the buffer is still valid
120         (*element)->CloseMemoryFile(0);
121       }
122       delete *element;
123       *element=NULL;
124     }
125     element++;
126   }
127   if (fpRunDesc) {
128     delete fpRunDesc;
129     fpRunDesc=NULL;
130   }
131   if (fEventDoneData)
132     delete [] reinterpret_cast<AliHLTUInt8_t*>( fEventDoneData );
133 }
134
135 AliHLTComponentHandler* AliHLTComponent::fgpComponentHandler=NULL;
136
137 int AliHLTComponent::SetGlobalComponentHandler(AliHLTComponentHandler* pCH, int bOverwrite) 
138 {
139   // see header file for function documentation
140   int iResult=0;
141   if (fgpComponentHandler==NULL || bOverwrite!=0)
142     fgpComponentHandler=pCH;
143   else
144     iResult=-EPERM;
145   return iResult;
146 }
147
148 int AliHLTComponent::UnsetGlobalComponentHandler() 
149 {
150   // see header file for function documentation
151   return SetGlobalComponentHandler(NULL,1);
152 }
153
154 int AliHLTComponent::Init(const AliHLTAnalysisEnvironment* comenv, void* environParam, int argc, const char** argv )
155 {
156   // see header file for function documentation
157   HLTLogKeyword(fChainId.c_str());
158   int iResult=0;
159   if (comenv) {
160     memset(&fEnvironment, 0, sizeof(AliHLTAnalysisEnvironment));
161     memcpy(&fEnvironment, comenv, comenv->fStructSize<sizeof(AliHLTAnalysisEnvironment)?comenv->fStructSize:sizeof(AliHLTAnalysisEnvironment));
162     fEnvironment.fStructSize=sizeof(AliHLTAnalysisEnvironment);
163     fEnvironment.fParam=environParam;
164   }
165   fComponentArgs="";
166   const char** pArguments=NULL;
167   int iNofChildArgs=0;
168   TString argument="";
169   int bMissingParam=0;
170   if (argc>0) {
171     pArguments=new const char*[argc];
172     if (pArguments) {
173       for (int i=0; i<argc && iResult>=0; i++) {
174         if (fComponentArgs.size()>0) fComponentArgs+=" ";
175         fComponentArgs+=argv[i];
176         argument=argv[i];
177         if (argument.IsNull()) continue;
178
179         // benchmark
180         if (argument.CompareTo("-benchmark")==0) {
181
182           // -loglevel=
183         } else if (argument.BeginsWith("-loglevel=")) {
184           TString parameter=argument.ReplaceAll("-loglevel=", "");
185           parameter.Remove(TString::kLeading, ' '); // remove all blanks
186           if (parameter.BeginsWith("0x") &&
187               parameter.Replace(0,2,"",0).IsHex()) {
188             unsigned int loglevel=kHLTLogNone;
189             sscanf(parameter.Data(),"%x", &loglevel);
190             SetLocalLoggingLevel((AliHLTComponentLogSeverity)loglevel);
191           } else {
192             HLTError("wrong parameter for argument %s, hex number expected", argument.Data());
193             iResult=-EINVAL;
194           }
195           // -object-compression=
196         } else if (argument.BeginsWith("-object-compression=")) {
197           argument.ReplaceAll("-object-compression=", "");
198           if (argument.IsDigit()) {
199             fCompressionLevel=argument.Atoi();
200             if (fCompressionLevel<0 || fCompressionLevel>9) {
201               HLTWarning("invalid compression level %d, setting to default %d", fCompressionLevel, ALIHLTCOMPONENT_DEFAULT_OBJECT_COMPRESSION);
202               fCompressionLevel=ALIHLTCOMPONENT_DEFAULT_OBJECT_COMPRESSION;
203             }
204           } else {
205             HLTError("wrong parameter for argument -object-compression, number expected");
206           }
207         } else {
208           pArguments[iNofChildArgs++]=argv[i];
209         }
210       }
211     } else {
212       iResult=-ENOMEM;
213     }
214   }
215   if (bMissingParam) {
216     HLTError("missing parameter for argument %s", argument.Data());
217     iResult=-EINVAL;
218   }
219   if (iResult>=0) {
220     iResult=DoInit(iNofChildArgs, pArguments);
221   }
222   if (iResult>=0) {
223     fEventCount=0;
224
225     // find out if the component wants to get the steering events
226     // explicitly
227     AliHLTComponentDataTypeList inputDt;
228     GetInputDataTypes(inputDt);
229     for (AliHLTComponentDataTypeList::iterator dt=inputDt.begin();
230          dt!=inputDt.end() && !fRequireSteeringBlocks;
231          dt++) {
232       fRequireSteeringBlocks|=MatchExactly(*dt,kAliHLTDataTypeSOR);
233       fRequireSteeringBlocks|=MatchExactly(*dt,kAliHLTDataTypeRunType);
234       fRequireSteeringBlocks|=MatchExactly(*dt,kAliHLTDataTypeEOR);
235       fRequireSteeringBlocks|=MatchExactly(*dt,kAliHLTDataTypeDDL);
236       fRequireSteeringBlocks|=MatchExactly(*dt,kAliHLTDataTypeComponentStatistics);
237     }
238   }
239   if (pArguments) delete [] pArguments;
240
241 #if defined(__DEBUG) || defined(HLT_COMPONENT_STATISTICS)
242   // benchmarking stopwatch for the component statistics
243   fpBenchmark=new TStopwatch;
244 #endif
245
246   return iResult;
247 }
248
249 int AliHLTComponent::Deinit()
250 {
251   // see header file for function documentation
252   HLTLogKeyword(fChainId.c_str());
253   int iResult=0;
254   iResult=DoDeinit();
255   if (fpRunDesc) {
256     HLTWarning("did not receive EOR for run %d", fpRunDesc->fRunNo);
257     AliHLTRunDesc* pRunDesc=fpRunDesc;
258     fpRunDesc=NULL;
259     delete pRunDesc;
260   }
261   fEventCount=0;
262   return iResult;
263 }
264
265 int AliHLTComponent::InitCDB(const char* cdbPath, AliHLTComponentHandler* pHandler)
266 {
267   // see header file for function documentation
268   int iResult=0;
269   if (pHandler) {
270   // I have to think about separating the library handling from the
271   // component handler. Requiring the component hanlder here is not
272   // the cleanest solution.
273   // We presume the library already to be loaded
274   // find the symbol
275   AliHLTMiscInitCDB_t pFunc=(AliHLTMiscInitCDB_t)pHandler->FindSymbol(ALIHLTMISC_LIBRARY, ALIHLTMISC_INIT_CDB);
276   if (pFunc) {
277     TString path;
278     if (cdbPath && cdbPath[0]!=0) {
279       path=cdbPath;
280       // very temporary fix, have to check for other formats
281       if (!path.BeginsWith("local://")) {
282         path="local://";
283         path+=cdbPath;
284       }
285     }
286     if ((iResult=(*pFunc)(path.Data()))>=0) {
287       if (!(fCDBSetRunNoFunc=pHandler->FindSymbol(ALIHLTMISC_LIBRARY, ALIHLTMISC_SET_CDB_RUNNO))) {
288         Message(NULL, kHLTLogWarning, "AliHLTComponent::InitCDB", "init CDB",
289                 "can not find function to set CDB run no");
290       }
291     }
292   } else {
293     Message(NULL, kHLTLogError, "AliHLTComponent::InitCDB", "init CDB",
294             "can not find initialization function");
295     iResult=-ENOSYS;
296   }
297   } else {
298     iResult=-EINVAL;
299   }
300   return iResult;
301 }
302
303 int AliHLTComponent::SetCDBRunNo(int runNo)
304 {
305   // see header file for function documentation
306   if (!fCDBSetRunNoFunc) return 0;
307   return (*((AliHLTMiscSetCDBRunNo_t)fCDBSetRunNoFunc))(runNo);
308 }
309
310 int AliHLTComponent::SetRunDescription(const AliHLTRunDesc* desc, const char* /*runType*/)
311 {
312   // see header file for function documentation
313   if (!desc) return -EINVAL;
314   if (desc->fStructSize!=sizeof(AliHLTRunDesc)) {
315     HLTError("invalid size of RunDesc struct (%ul)", desc->fStructSize);
316     return -EINVAL;
317   }
318
319   if (!fpRunDesc) {
320     fpRunDesc=new AliHLTRunDesc;
321     if (!fpRunDesc) return -ENOMEM;
322     *fpRunDesc=kAliHLTVoidRunDesc;
323   }
324
325   if (fpRunDesc->fRunNo!=kAliHLTVoidRunNo && fpRunDesc->fRunNo!=desc->fRunNo) {
326     HLTWarning("Run description has already been set");
327   }
328   *fpRunDesc=*desc;
329   SetCDBRunNo(fpRunDesc->fRunNo);
330   // TODO: we have to decide about the runType
331   return 0;
332 }
333
334 int AliHLTComponent::SetComponentDescription(const char* desc)
335 {
336   // see header file for function documentation
337   int iResult=0;
338   if (!desc) return 0;
339
340   TString descriptor=desc;
341   TObjArray* pTokens=descriptor.Tokenize(" ");
342   if (pTokens) {
343     for (int i=0; i<pTokens->GetEntries() && iResult>=0; i++) {
344       TString argument=((TObjString*)pTokens->At(i++))->GetString();
345       if (!argument || argument.IsNull()) continue;
346
347       // chainid
348       if (argument.BeginsWith("chainid")) {
349         argument.ReplaceAll("chainid", "");
350         if (argument.BeginsWith("=")) {
351           fChainId=argument.Replace(0,1,"");
352           fChainIdCrc=CalculateChecksum((const AliHLTUInt8_t*)fChainId.c_str(), fChainId.length());
353           HLTDebug("setting component description: chain id %s crc 0x%8x", fChainId.c_str(), fChainIdCrc);
354         } else {
355           fChainId="";
356         }
357       } else {
358         HLTWarning("unknown component description %s", argument.Data());
359       }
360     }
361   }
362   
363   return iResult;
364 }
365
366 int AliHLTComponent::DoInit( int /*argc*/, const char** /*argv*/)
367 {
368   // default implementation, childs can overload
369   HLTLogKeyword("dummy");
370   return 0;
371 }
372
373 int AliHLTComponent::DoDeinit()
374 {
375   // default implementation, childs can overload
376   HLTLogKeyword("dummy");
377   return 0;
378 }
379
380 int AliHLTComponent::Reconfigure(const char* /*cdbEntry*/, const char* /*chainId*/)
381 {
382   // default implementation, childs can overload
383   HLTLogKeyword("dummy");
384   return 0;
385 }
386
387 int AliHLTComponent::ReadPreprocessorValues(const char* /*modules*/)
388 {
389   // default implementation, childs can overload
390   HLTLogKeyword("dummy");
391   return 0;
392 }
393
394 int AliHLTComponent::StartOfRun()
395 {
396   // default implementation, childs can overload
397   HLTLogKeyword("dummy");
398   return 0;
399 }
400
401 int AliHLTComponent::EndOfRun()
402 {
403   // default implementation, childs can overload
404   HLTLogKeyword("dummy");
405   return 0;
406 }
407
408
409 int AliHLTComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& /*tgtList*/)
410 {
411   // default implementation, childs can overload
412   HLTLogKeyword("dummy");
413   return 0;
414 }
415
416 void AliHLTComponent::DataType2Text( const AliHLTComponentDataType& type, char output[kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2] ) const
417 {
418   // see header file for function documentation
419   memset( output, 0, kAliHLTComponentDataTypefIDsize+kAliHLTComponentDataTypefOriginSize+2 );
420   strncat( output, type.fOrigin, kAliHLTComponentDataTypefOriginSize );
421   strcat( output, ":" );
422   strncat( output, type.fID, kAliHLTComponentDataTypefIDsize );
423 }
424
425 string AliHLTComponent::DataType2Text( const AliHLTComponentDataType& type, int mode)
426 {
427   // see header file for function documentation
428   string out("");
429
430   if (mode==2) {
431     int i=0;
432     char tmp[8];
433     for (i=0; i<kAliHLTComponentDataTypefOriginSize; i++) {
434       sprintf(tmp, "'%d", type.fOrigin[i]);
435       out+=tmp;
436     }
437     out+="':'";
438     for (i=0; i<kAliHLTComponentDataTypefIDsize; i++) {
439       sprintf(tmp, "%d'", type.fID[i]);
440       out+=tmp;
441     }
442     return out;
443   }
444
445   if (mode==1) {
446     int i=0;
447     char tmp[8];
448     for (i=0; i<kAliHLTComponentDataTypefOriginSize; i++) {
449       unsigned char* puc=(unsigned char*)type.fOrigin;
450       if ((puc[i])<32)
451         sprintf(tmp, "'\\%x", type.fOrigin[i]);
452       else
453         sprintf(tmp, "'%c", type.fOrigin[i]);
454       out+=tmp;
455     }
456     out+="':'";
457     for (i=0; i<kAliHLTComponentDataTypefIDsize; i++) {
458       unsigned char* puc=(unsigned char*)type.fID;
459       if (puc[i]<32)
460         sprintf(tmp, "\\%x'", type.fID[i]);
461       else
462         sprintf(tmp, "%c'", type.fID[i]);
463       out+=tmp;
464     }
465     return out;
466   }
467
468   if (type==kAliHLTVoidDataType) {
469     out="VOID:VOID";
470   } else {
471     // some gymnastics in order to avoid a '0' which is part of either or both
472     // ID and origin terminating the whole string. Unfortunately, string doesn't
473     // stop appending at the '0' if the number of elements to append was 
474     // explicitely specified
475     string tmp("");
476     tmp.append(type.fOrigin, kAliHLTComponentDataTypefOriginSize);
477     out.append(tmp.c_str());
478     out.append(":");
479     tmp="";
480     tmp.append(type.fID, kAliHLTComponentDataTypefIDsize);
481     out.append(tmp.c_str());
482   }
483   return out;
484 }
485
486
487 void* AliHLTComponent::AllocMemory( unsigned long size ) 
488 {
489   // see header file for function documentation
490   if (fEnvironment.fAllocMemoryFunc)
491     return (*fEnvironment.fAllocMemoryFunc)(fEnvironment.fParam, size );
492   HLTFatal("no memory allocation handler registered");
493   return NULL;
494 }
495
496 int AliHLTComponent::MakeOutputDataBlockList( const AliHLTComponentBlockDataList& blocks, AliHLTUInt32_t* blockCount,
497                                               AliHLTComponentBlockData** outputBlocks ) 
498 {
499   // see header file for function documentation
500     if ( blockCount==NULL || outputBlocks==NULL )
501         return -EFAULT;
502     AliHLTUInt32_t count = blocks.size();
503     if ( !count )
504         {
505         *blockCount = 0;
506         *outputBlocks = NULL;
507         return 0;
508         }
509     *outputBlocks = reinterpret_cast<AliHLTComponentBlockData*>( AllocMemory( sizeof(AliHLTComponentBlockData)*count ) );
510     if ( !*outputBlocks )
511         return -ENOMEM;
512     for ( unsigned long i = 0; i < count; i++ ) {
513         (*outputBlocks)[i] = blocks[i];
514         if (MatchExactly(blocks[i].fDataType, kAliHLTAnyDataType)) {
515           (*outputBlocks)[i].fDataType=GetOutputDataType();
516           /* data type was set to the output data type by the PubSub AliRoot
517              Wrapper component, if data type of the block was ********:****.
518              Now handled by the component base class in order to have same
519              behavior when running embedded in AliRoot
520           memset((*outputBlocks)[i].fDataType.fID, '*', kAliHLTComponentDataTypefIDsize);
521           memset((*outputBlocks)[i].fDataType.fOrigin, '*', kAliHLTComponentDataTypefOriginSize);
522           */
523         }
524     }
525     *blockCount = count;
526     return 0;
527
528 }
529
530 int AliHLTComponent::GetEventDoneData( unsigned long size, AliHLTComponentEventDoneData** edd ) 
531 {
532   // see header file for function documentation
533   if (fEnvironment.fGetEventDoneDataFunc)
534     return (*fEnvironment.fGetEventDoneDataFunc)(fEnvironment.fParam, fCurrentEvent, size, edd );
535   return -ENOSYS;
536 }
537
538 int AliHLTComponent::ReserveEventDoneData( unsigned long size )
539 {
540   // see header file for function documentation
541   int iResult=0;
542
543   
544   if (size>fEventDoneDataSize) {
545     AliHLTComponentEventDoneData* newEDD = reinterpret_cast<AliHLTComponentEventDoneData*>( new AliHLTUInt8_t[ sizeof(AliHLTComponentEventDoneData)+size ] );
546     if (!newEDD)
547       return -ENOMEM;
548     newEDD->fStructSize = sizeof(AliHLTComponentEventDoneData);
549     newEDD->fDataSize = 0;
550     newEDD->fData = reinterpret_cast<AliHLTUInt8_t*>(newEDD)+newEDD->fStructSize;
551     if (fEventDoneData) {
552       memcpy( newEDD->fData, fEventDoneData->fData, fEventDoneData->fDataSize );
553       newEDD->fDataSize = fEventDoneData->fDataSize;
554       delete [] reinterpret_cast<AliHLTUInt8_t*>( fEventDoneData );
555     }
556     fEventDoneData = newEDD;
557     fEventDoneDataSize = size;
558   }
559   return iResult;
560
561 }
562
563 int AliHLTComponent::PushEventDoneData( AliHLTUInt32_t eddDataWord )
564 {
565   if (!fEventDoneData)
566     return -ENOMEM;
567   if (fEventDoneData->fDataSize+sizeof(AliHLTUInt32_t)>fEventDoneDataSize)
568     return -ENOSPC;
569   *reinterpret_cast<AliHLTUInt32_t*>((reinterpret_cast<AliHLTUInt8_t*>(fEventDoneData->fData)+fEventDoneData->fDataSize)) = eddDataWord;
570   fEventDoneData->fDataSize += sizeof(AliHLTUInt32_t);
571   return 0;
572 }
573
574 void AliHLTComponent::ReleaseEventDoneData()
575 {
576   if (fEventDoneData)
577     delete [] reinterpret_cast<AliHLTUInt8_t*>( fEventDoneData );
578   fEventDoneData = NULL;
579   fEventDoneDataSize = 0;
580 }
581
582
583 int AliHLTComponent::FindMatchingDataTypes(AliHLTComponent* pConsumer, AliHLTComponentDataTypeList* tgtList) 
584 {
585   // see header file for function documentation
586   int iResult=0;
587   if (pConsumer) {
588     AliHLTComponentDataTypeList itypes;
589     AliHLTComponentDataTypeList otypes;
590     otypes.push_back(GetOutputDataType());
591     if (otypes[0]==kAliHLTMultipleDataType) {
592       otypes.clear();
593       int count=0;
594       if ((count=GetOutputDataTypes(otypes))>0) {
595       } else if (GetComponentType()!=kSink) {
596         HLTWarning("component %s indicates multiple output data types but GetOutputDataTypes returns %d", GetComponentID(), count);
597       }
598     }
599     ((AliHLTComponent*)pConsumer)->GetInputDataTypes(itypes);
600     AliHLTComponentDataTypeList::iterator otype=otypes.begin();
601     for (;otype!=otypes.end();otype++) {
602       //PrintDataTypeContent((*otype), "publisher \'%s\'");
603       if ((*otype)==(kAliHLTAnyDataType|kAliHLTDataOriginPrivate)) {
604         if (tgtList) tgtList->push_back(*otype);
605         iResult++;
606         continue;
607       }
608       
609       AliHLTComponentDataTypeList::iterator itype=itypes.begin();
610       for ( ; itype!=itypes.end() && (*itype)!=(*otype) ; itype++) {/* empty body */};
611       //if (itype!=itypes.end()) PrintDataTypeContent(*itype, "consumer \'%s\'");
612       if (itype!=itypes.end()) {
613         if (tgtList) tgtList->push_back(*otype);
614         iResult++;
615       }
616     }
617   } else {
618     iResult=-EINVAL;
619   }
620   return iResult;
621 }
622
623 void AliHLTComponent::PrintDataTypeContent(AliHLTComponentDataType& dt, const char* format)
624 {
625   // see header file for function documentation
626   const char* fmt="\'%s\'";
627   if (format) fmt=format;
628   AliHLTLogging::Message(NULL, kHLTLogNone, NULL , NULL, Form(fmt, (DataType2Text(dt)).c_str()));
629   AliHLTLogging::Message(NULL, kHLTLogNone, NULL , NULL, 
630                          Form("%x %x %x %x %x %x %x %x : %x %x %x %x", 
631                               dt.fID[0],
632                               dt.fID[1],
633                               dt.fID[2],
634                               dt.fID[3],
635                               dt.fID[4],
636                               dt.fID[5],
637                               dt.fID[6],
638                               dt.fID[7],
639                               dt.fOrigin[0],
640                               dt.fOrigin[1],
641                               dt.fOrigin[2],
642                               dt.fOrigin[3]));
643 }
644
645 void AliHLTComponent::FillBlockData( AliHLTComponentBlockData& blockData )
646 {
647   // see header file for function documentation
648   blockData.fStructSize = sizeof(blockData);
649   FillShmData( blockData.fShmKey );
650   blockData.fOffset = ~(AliHLTUInt32_t)0;
651   blockData.fPtr = NULL;
652   blockData.fSize = 0;
653   FillDataType( blockData.fDataType );
654   blockData.fSpecification = kAliHLTVoidDataSpec;
655 }
656
657 void AliHLTComponent::FillShmData( AliHLTComponentShmData& shmData )
658 {
659   // see header file for function documentation
660   shmData.fStructSize = sizeof(shmData);
661   shmData.fShmType = gkAliHLTComponentInvalidShmType;
662   shmData.fShmID = gkAliHLTComponentInvalidShmID;
663 }
664
665 void AliHLTComponent::FillDataType( AliHLTComponentDataType& dataType )
666 {
667   // see header file for function documentation
668   dataType=kAliHLTAnyDataType;
669 }
670
671 void AliHLTComponent::CopyDataType(AliHLTComponentDataType& tgtdt, const AliHLTComponentDataType& srcdt) 
672 {
673   // see header file for function documentation
674   memcpy(&tgtdt.fID[0], &srcdt.fID[0], kAliHLTComponentDataTypefIDsize);
675   memcpy(&tgtdt.fOrigin[0], &srcdt.fOrigin[0], kAliHLTComponentDataTypefOriginSize);
676 }
677
678 void AliHLTComponent::SetDataType(AliHLTComponentDataType& tgtdt, const char* id, const char* origin) 
679 {
680   // see header file for function documentation
681   tgtdt.fStructSize=sizeof(AliHLTComponentDataType);
682   if (id) {
683     memset(&tgtdt.fID[0], 0, kAliHLTComponentDataTypefIDsize);
684     strncpy(&tgtdt.fID[0], id, strlen(id)<(size_t)kAliHLTComponentDataTypefIDsize?strlen(id):kAliHLTComponentDataTypefIDsize);
685   }
686   if (origin) {
687     memset(&tgtdt.fOrigin[0], 0, kAliHLTComponentDataTypefOriginSize);
688     strncpy(&tgtdt.fOrigin[0], origin, strlen(origin)<(size_t)kAliHLTComponentDataTypefOriginSize?strlen(origin):kAliHLTComponentDataTypefOriginSize);
689   }
690 }
691
692 void AliHLTComponent::SetDataType(AliHLTComponentDataType& dt, AliHLTUInt64_t id, AliHLTUInt32_t origin)
693 {
694   // see header file for function documentation
695   dt.fStructSize=sizeof(AliHLTComponentDataType);
696   assert(kAliHLTComponentDataTypefIDsize==sizeof(id));
697   assert(kAliHLTComponentDataTypefOriginSize==sizeof(origin));
698   memcpy(&dt.fID, &id, kAliHLTComponentDataTypefIDsize);
699   memcpy(&dt.fOrigin, &origin, kAliHLTComponentDataTypefOriginSize);
700 }
701
702 void AliHLTComponent::FillEventData(AliHLTComponentEventData& evtData)
703 {
704   // see header file for function documentation
705   memset(&evtData, 0, sizeof(AliHLTComponentEventData));
706   evtData.fStructSize=sizeof(AliHLTComponentEventData);
707   evtData.fEventID=kAliHLTVoidEventID;
708 }
709
710 void AliHLTComponent::PrintComponentDataTypeInfo(const AliHLTComponentDataType& dt) 
711 {
712   // see header file for function documentation
713   TString msg;
714   msg.Form("AliHLTComponentDataType(%d): ID=\"", dt.fStructSize);
715   for ( int i = 0; i < kAliHLTComponentDataTypefIDsize; i++ ) {
716    if (dt.fID[i]!=0) msg+=dt.fID[i];
717    else msg+="\\0";
718   }
719   msg+="\" Origin=\"";
720   for ( int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++ ) {
721    if (dt.fOrigin[i]!=0) msg+=dt.fOrigin[i];
722    else msg+="\\0";
723   }
724   msg+="\"";
725   AliHLTLogging::Message(NULL, kHLTLogNone, NULL , NULL, msg.Data());
726 }
727
728 int AliHLTComponent::GetEventCount() const
729 {
730   // see header file for function documentation
731   return fEventCount;
732 }
733
734 int AliHLTComponent::IncrementEventCounter()
735 {
736   // see header file for function documentation
737   if (fEventCount>=0) fEventCount++;
738   return fEventCount;
739 }
740
741 int AliHLTComponent::GetNumberOfInputBlocks() const
742 {
743   // see header file for function documentation
744   if (fpInputBlocks!=NULL) {
745     return fCurrentEventData.fBlockCnt;
746   }
747   return 0;
748 }
749
750 AliHLTEventID_t AliHLTComponent::GetEventId() const
751 {
752   // see header file for function documentation
753   if (fpInputBlocks!=NULL) {
754     return fCurrentEventData.fEventID;
755   }
756   return 0;
757 }
758
759 const TObject* AliHLTComponent::GetFirstInputObject(const AliHLTComponentDataType& dt,
760                                                     const char* classname,
761                                                     int bForce)
762 {
763   // see header file for function documentation
764   ALIHLTCOMPONENT_BASE_STOPWATCH();
765   fSearchDataType=dt;
766   if (classname) fClassName=classname;
767   else fClassName.clear();
768   int idx=FindInputBlock(fSearchDataType, 0, 1);
769   TObject* pObj=NULL;
770   if (idx>=0) {
771     HLTDebug("found block %d when searching for data type %s", idx, DataType2Text(dt).c_str());
772     if ((pObj=GetInputObject(idx, fClassName.c_str(), bForce))!=NULL) {
773       fCurrentInputBlock=idx;
774     } else {
775     }
776   }
777   return pObj;
778 }
779
780 const TObject* AliHLTComponent::GetFirstInputObject(const char* dtID, 
781                                                     const char* dtOrigin,
782                                                     const char* classname,
783                                                     int         bForce)
784 {
785   // see header file for function documentation
786   ALIHLTCOMPONENT_BASE_STOPWATCH();
787   AliHLTComponentDataType dt;
788   SetDataType(dt, dtID, dtOrigin);
789   return GetFirstInputObject(dt, classname, bForce);
790 }
791
792 const TObject* AliHLTComponent::GetNextInputObject(int bForce)
793 {
794   // see header file for function documentation
795   ALIHLTCOMPONENT_BASE_STOPWATCH();
796   int idx=FindInputBlock(fSearchDataType, fCurrentInputBlock+1, 1);
797   //HLTDebug("found block %d when searching for data type %s", idx, DataType2Text(fSearchDataType).c_str());
798   TObject* pObj=NULL;
799   if (idx>=0) {
800     if ((pObj=GetInputObject(idx, fClassName.c_str(), bForce))!=NULL) {
801       fCurrentInputBlock=idx;
802     }
803   }
804   return pObj;
805 }
806
807 int AliHLTComponent::FindInputBlock(const AliHLTComponentDataType& dt, int startIdx, int bObject) const
808 {
809   // see header file for function documentation
810   int iResult=-ENOENT;
811   if (fpInputBlocks!=NULL) {
812     int idx=startIdx<0?0:startIdx;
813     for ( ; (UInt_t)idx<fCurrentEventData.fBlockCnt && iResult==-ENOENT; idx++) {
814       if (dt!=fpInputBlocks[idx].fDataType) continue;
815
816       if (bObject!=0) {
817         if (fpInputBlocks[idx].fPtr==NULL) continue;
818         AliHLTUInt32_t firstWord=*((AliHLTUInt32_t*)fpInputBlocks[idx].fPtr);
819         if (firstWord!=fpInputBlocks[idx].fSize-sizeof(AliHLTUInt32_t)) continue;
820       }
821       iResult=idx;
822     }
823   }
824   return iResult;
825 }
826
827 TObject* AliHLTComponent::CreateInputObject(int idx, int bForce)
828 {
829   // see header file for function documentation
830   TObject* pObj=NULL;
831   if (fpInputBlocks!=NULL) {
832     if ((UInt_t)idx<fCurrentEventData.fBlockCnt) {
833       if (fpInputBlocks[idx].fPtr) {
834         AliHLTUInt32_t firstWord=*((AliHLTUInt32_t*)fpInputBlocks[idx].fPtr);
835         if (firstWord==fpInputBlocks[idx].fSize-sizeof(AliHLTUInt32_t)) {
836           HLTDebug("create object from block %d size %d", idx, fpInputBlocks[idx].fSize);
837           AliHLTMessage msg(fpInputBlocks[idx].fPtr, fpInputBlocks[idx].fSize);
838           TClass* objclass=msg.GetClass();
839           pObj=msg.ReadObject(objclass);
840           if (pObj && objclass) {
841             HLTDebug("object %p type %s created", pObj, objclass->GetName());
842           } else {
843           }
844           //} else {
845         } else if (bForce!=0) {
846           HLTError("size mismatch: block size %d, indicated %d", fpInputBlocks[idx].fSize, firstWord+sizeof(AliHLTUInt32_t));
847         }
848       } else {
849         HLTFatal("block descriptor empty");
850       }
851     } else {
852       HLTError("index %d out of range %d", idx, fCurrentEventData.fBlockCnt);
853     }
854   } else {
855     HLTError("no input blocks available");
856   }
857   
858   return pObj;
859 }
860
861 TObject* AliHLTComponent::GetInputObject(int idx, const char* /*classname*/, int bForce)
862 {
863   // see header file for function documentation
864   if (fpInputObjects==NULL) {
865     fpInputObjects=new TObjArray(fCurrentEventData.fBlockCnt);
866   }
867   TObject* pObj=NULL;
868   if (fpInputObjects) {
869     pObj=fpInputObjects->At(idx);
870     if (pObj==NULL) {
871       pObj=CreateInputObject(idx, bForce);
872       if (pObj) {
873         fpInputObjects->AddAt(pObj, idx);
874       }
875     }
876   } else {
877     HLTFatal("memory allocation failed: TObjArray of size %d", fCurrentEventData.fBlockCnt);
878   }
879   return pObj;
880 }
881
882 int AliHLTComponent::CleanupInputObjects()
883 {
884   // see header file for function documentation
885   if (!fpInputObjects) return 0;
886   TObjArray* array=fpInputObjects;
887   fpInputObjects=NULL;
888   for (int i=0; i<array->GetEntries(); i++) {
889     TObject* pObj=array->At(i);
890     // grrr, garbage collection strikes back: When read via AliHLTMessage
891     // (CreateInputObject), and written to a TFile afterwards, the
892     // TFile::Close calls ROOOT's garbage collection. No clue why the
893     // object ended up in the key list and needs to be deleted
894     //
895     // Matthias 09.11.2008 follow up
896     // This approach doesn't actually work in all cases: the object table
897     // can be switched off globally, the flag needs to be checked here as
898     // well in order to avoid memory leaks.
899     // This means we have to find another solution for the problem if it
900     // pops up again.
901     if (pObj &&
902         (!TObject::GetObjectStat() || gObjectTable->PtrIsValid(pObj))) {
903       delete pObj;
904     }
905   }
906   delete array;
907   return 0;
908 }
909
910 AliHLTComponentDataType AliHLTComponent::GetDataType(const TObject* pObject)
911 {
912   // see header file for function documentation
913   ALIHLTCOMPONENT_BASE_STOPWATCH();
914   AliHLTComponentDataType dt=kAliHLTVoidDataType;
915   int idx=fCurrentInputBlock;
916   if (pObject) {
917     if (fpInputObjects==NULL || (idx=fpInputObjects->IndexOf(pObject))>=0) {
918     } else {
919       HLTError("unknown object %p", pObject);
920     }
921   }
922   if (idx>=0) {
923     if ((UInt_t)idx<fCurrentEventData.fBlockCnt) {
924       dt=fpInputBlocks[idx].fDataType;
925     } else {
926       HLTFatal("severe internal error, index out of range");
927     }
928   }
929   return dt;
930 }
931
932 AliHLTUInt32_t AliHLTComponent::GetSpecification(const TObject* pObject)
933 {
934   // see header file for function documentation
935   ALIHLTCOMPONENT_BASE_STOPWATCH();
936   AliHLTUInt32_t iSpec=kAliHLTVoidDataSpec;
937   int idx=fCurrentInputBlock;
938   if (pObject) {
939     if (fpInputObjects==NULL || (idx=fpInputObjects->IndexOf(pObject))>=0) {
940     } else {
941       HLTError("unknown object %p", pObject);
942     }
943   }
944   if (idx>=0) {
945     if ((UInt_t)idx<fCurrentEventData.fBlockCnt) {
946       iSpec=fpInputBlocks[idx].fSpecification;
947     } else {
948       HLTFatal("severe internal error, index out of range");
949     }
950   }
951   return iSpec;
952 }
953
954 int AliHLTComponent::Forward(const TObject* pObject)
955 {
956   // see header file for function documentation
957   int iResult=0;
958   int idx=fCurrentInputBlock;
959   if (pObject) {
960     if (fpInputObjects==NULL || (idx=fpInputObjects->IndexOf(pObject))>=0) {
961     } else {
962       HLTError("unknown object %p", pObject);
963       iResult=-ENOENT;
964     }
965   }
966   if (idx>=0) {
967     fOutputBlocks.push_back(fpInputBlocks[idx]);
968   }
969   return iResult;
970 }
971
972 int AliHLTComponent::Forward(const AliHLTComponentBlockData* pBlock)
973 {
974   // see header file for function documentation
975   int iResult=0;
976   int idx=fCurrentInputBlock;
977   if (pBlock) {
978     if (fpInputObjects==NULL || (idx=FindInputBlock(pBlock))>=0) {
979     } else {
980       HLTError("unknown Block %p", pBlock);
981       iResult=-ENOENT;      
982     }
983   }
984   if (idx>=0) {
985     // check for fpInputBlocks pointer done in FindInputBlock
986     fOutputBlocks.push_back(fpInputBlocks[idx]);
987   }
988   return iResult;
989 }
990
991 const AliHLTComponentBlockData* AliHLTComponent::GetFirstInputBlock(const AliHLTComponentDataType& dt)
992 {
993   // see header file for function documentation
994   ALIHLTCOMPONENT_BASE_STOPWATCH();
995   fSearchDataType=dt;
996   fClassName.clear();
997   int idx=FindInputBlock(fSearchDataType, 0);
998   const AliHLTComponentBlockData* pBlock=NULL;
999   if (idx>=0) {
1000     // check for fpInputBlocks pointer done in FindInputBlock
1001     pBlock=&fpInputBlocks[idx];
1002     fCurrentInputBlock=idx;
1003   }
1004   return pBlock;
1005 }
1006
1007 const AliHLTComponentBlockData* AliHLTComponent::GetFirstInputBlock(const char* dtID, 
1008                                                                     const char* dtOrigin)
1009 {
1010   // see header file for function documentation
1011   ALIHLTCOMPONENT_BASE_STOPWATCH();
1012   AliHLTComponentDataType dt;
1013   SetDataType(dt, dtID, dtOrigin);
1014   return GetFirstInputBlock(dt);
1015 }
1016
1017 const AliHLTComponentBlockData* AliHLTComponent::GetInputBlock(int index) const
1018 {
1019   // see header file for function documentation
1020   ALIHLTCOMPONENT_BASE_STOPWATCH();
1021   assert( 0 <= index and index < (int)fCurrentEventData.fBlockCnt );
1022   return &fpInputBlocks[index];
1023 }
1024
1025 const AliHLTComponentBlockData* AliHLTComponent::GetNextInputBlock()
1026 {
1027   // see header file for function documentation
1028   ALIHLTCOMPONENT_BASE_STOPWATCH();
1029   int idx=FindInputBlock(fSearchDataType, fCurrentInputBlock+1);
1030   const AliHLTComponentBlockData* pBlock=NULL;
1031   if (idx>=0) {
1032     // check for fpInputBlocks pointer done in FindInputBlock
1033     pBlock=&fpInputBlocks[idx];
1034     fCurrentInputBlock=idx;
1035   }
1036   return pBlock;
1037 }
1038
1039 int AliHLTComponent::FindInputBlock(const AliHLTComponentBlockData* pBlock) const
1040 {
1041   // see header file for function documentation
1042   int iResult=-ENOENT;
1043   if (fpInputBlocks!=NULL) {
1044     if (pBlock) {
1045       if (pBlock>=fpInputBlocks && pBlock<fpInputBlocks+fCurrentEventData.fBlockCnt) {
1046         iResult=(int)(pBlock-fpInputBlocks);
1047       }
1048     } else {
1049       iResult=-EINVAL;
1050     }
1051   }
1052   return iResult;
1053 }
1054
1055 AliHLTUInt32_t AliHLTComponent::GetSpecification(const AliHLTComponentBlockData* pBlock)
1056 {
1057   // see header file for function documentation
1058   ALIHLTCOMPONENT_BASE_STOPWATCH();
1059   AliHLTUInt32_t iSpec=kAliHLTVoidDataSpec;
1060   int idx=fCurrentInputBlock;
1061   if (pBlock) {
1062     if (fpInputObjects==NULL || (idx=FindInputBlock(pBlock))>=0) {
1063     } else {
1064       HLTError("unknown Block %p", pBlock);
1065     }
1066   }
1067   if (idx>=0) {
1068     // check for fpInputBlocks pointer done in FindInputBlock
1069     iSpec=fpInputBlocks[idx].fSpecification;
1070   }
1071   return iSpec;
1072 }
1073
1074 int AliHLTComponent::PushBack(TObject* pObject, const AliHLTComponentDataType& dt, AliHLTUInt32_t spec, 
1075                               void* pHeader, int headerSize)
1076 {
1077   // see header file for function documentation
1078   ALIHLTCOMPONENT_BASE_STOPWATCH();
1079   int iResult=0;
1080   fLastObjectSize=0;
1081   if (pObject) {
1082     AliHLTMessage msg(kMESS_OBJECT);
1083     msg.SetCompressionLevel(fCompressionLevel);
1084     msg.WriteObject(pObject);
1085     Int_t iMsgLength=msg.Length();
1086     if (iMsgLength>0) {
1087       // Matthias Sep 2008
1088       // NOTE: AliHLTMessage does implement it's own SetLength method
1089       // which is not architecture independent. The original SetLength
1090       // stores the size always in network byte order.
1091       // I'm trying to remember the rational for that, might be that
1092       // it was just some lack of knowledge. Want to change this, but
1093       // has to be done carefullt to be backward compatible.
1094       msg.SetLength(); // sets the length to the first (reserved) word
1095
1096       // does nothing if the level is 0
1097       msg.Compress();
1098
1099       char *mbuf = msg.Buffer();
1100       if (msg.CompBuffer()) {
1101         msg.SetLength(); // set once more to have to byte order
1102         mbuf = msg.CompBuffer();
1103         iMsgLength = msg.CompLength();
1104       }
1105       assert(mbuf!=NULL);
1106       iResult=InsertOutputBlock(mbuf, iMsgLength, dt, spec, pHeader, headerSize);
1107       if (iResult>=0) {
1108         HLTDebug("object %s (%p) size %d compression %d inserted to output", pObject->ClassName(), pObject, iMsgLength, msg.GetCompressionLevel());
1109       }
1110       fLastObjectSize=iMsgLength;
1111     } else {
1112       HLTError("object serialization failed for object %p", pObject);
1113       iResult=-ENOMSG;
1114     }
1115   } else {
1116     iResult=-EINVAL;
1117   }
1118   return iResult;
1119 }
1120
1121 int AliHLTComponent::PushBack(TObject* pObject, const char* dtID, const char* dtOrigin, AliHLTUInt32_t spec,
1122                               void* pHeader, int headerSize)
1123 {
1124   // see header file for function documentation
1125   ALIHLTCOMPONENT_BASE_STOPWATCH();
1126   AliHLTComponentDataType dt;
1127   SetDataType(dt, dtID, dtOrigin);
1128   return PushBack(pObject, dt, spec, pHeader, headerSize);
1129 }
1130
1131 int AliHLTComponent::PushBack(const void* pBuffer, int iSize, const AliHLTComponentDataType& dt, AliHLTUInt32_t spec,
1132                               const void* pHeader, int headerSize)
1133 {
1134   // see header file for function documentation
1135   ALIHLTCOMPONENT_BASE_STOPWATCH();
1136   return InsertOutputBlock(pBuffer, iSize, dt, spec, pHeader, headerSize);
1137 }
1138
1139 int AliHLTComponent::PushBack(const void* pBuffer, int iSize, const char* dtID, const char* dtOrigin, AliHLTUInt32_t spec,
1140                               const void* pHeader, int headerSize)
1141 {
1142   // see header file for function documentation
1143   ALIHLTCOMPONENT_BASE_STOPWATCH();
1144   AliHLTComponentDataType dt;
1145   SetDataType(dt, dtID, dtOrigin);
1146   return PushBack(pBuffer, iSize, dt, spec, pHeader, headerSize);
1147 }
1148
1149 int AliHLTComponent::InsertOutputBlock(const void* pBuffer, int iBufferSize, const AliHLTComponentDataType& dt, AliHLTUInt32_t spec,
1150                                        const void* pHeader, int iHeaderSize)
1151 {
1152   // see header file for function documentation
1153   int iResult=0;
1154   int iBlkSize = iBufferSize + iHeaderSize;
1155
1156   if ((pBuffer!=NULL && iBufferSize>0) || (pHeader!=NULL && iHeaderSize>0)) {
1157     if (fpOutputBuffer && iBlkSize<=(int)(fOutputBufferSize-fOutputBufferFilled)) {
1158       AliHLTUInt8_t* pTgt=fpOutputBuffer+fOutputBufferFilled;
1159
1160       // copy header if provided but skip if the header is the target location
1161       // in that case it has already been copied
1162       if (pHeader!=NULL && pHeader!=pTgt) {
1163         memcpy(pTgt, pHeader, iHeaderSize);
1164       }
1165
1166       pTgt += (AliHLTUInt8_t) iHeaderSize;
1167
1168       // copy buffer if provided but skip if buffer is the target location
1169       // in that case it has already been copied
1170       if (pBuffer!=NULL && pBuffer!=pTgt) {
1171         memcpy(pTgt, pBuffer, iBufferSize);
1172         
1173         //AliHLTUInt32_t firstWord=*((AliHLTUInt32_t*)pBuffer); 
1174         //HLTDebug("copy %d bytes from %p to output buffer %p, first word %#x", iBufferSize, pBuffer, pTgt, firstWord);
1175       }
1176       //HLTDebug("buffer inserted to output: size %d data type %s spec %#x", iBlkSize, DataType2Text(dt).c_str(), spec);
1177     } else {
1178       if (fpOutputBuffer) {
1179         HLTError("too little space in output buffer: %d of %d, required %d", fOutputBufferSize-fOutputBufferFilled, fOutputBufferSize, iBlkSize);
1180       } else {
1181         HLTError("output buffer not available");
1182       }
1183       iResult=-ENOSPC;
1184     }
1185   }
1186   if (iResult>=0) {
1187     AliHLTComponentBlockData bd;
1188     FillBlockData( bd );
1189     bd.fOffset        = fOutputBufferFilled;
1190     bd.fSize          = iBlkSize;
1191     bd.fDataType      = dt;
1192     bd.fSpecification = spec;
1193     fOutputBlocks.push_back( bd );
1194     fOutputBufferFilled+=bd.fSize;
1195   }
1196
1197   return iResult;
1198 }
1199
1200 int AliHLTComponent::EstimateObjectSize(TObject* pObject) const
1201 {
1202   // see header file for function documentation
1203   if (!pObject) return -EINVAL;
1204     AliHLTMessage msg(kMESS_OBJECT);
1205     msg.WriteObject(pObject);
1206     return msg.Length();  
1207 }
1208
1209 AliHLTMemoryFile* AliHLTComponent::CreateMemoryFile(int capacity, const char* dtID,
1210                                                     const char* dtOrigin,
1211                                                     AliHLTUInt32_t spec)
1212 {
1213   // see header file for function documentation
1214   ALIHLTCOMPONENT_BASE_STOPWATCH();
1215   AliHLTComponentDataType dt;
1216   SetDataType(dt, dtID, dtOrigin);
1217   return CreateMemoryFile(capacity, dt, spec);
1218 }
1219
1220 AliHLTMemoryFile* AliHLTComponent::CreateMemoryFile(int capacity,
1221                                                     const AliHLTComponentDataType& dt,
1222                                                     AliHLTUInt32_t spec)
1223 {
1224   // see header file for function documentation
1225   ALIHLTCOMPONENT_BASE_STOPWATCH();
1226   AliHLTMemoryFile* pFile=NULL;
1227   if (capacity>=0 && static_cast<unsigned int>(capacity)<=fOutputBufferSize-fOutputBufferFilled){
1228     AliHLTUInt8_t* pTgt=fpOutputBuffer+fOutputBufferFilled;
1229     pFile=new AliHLTMemoryFile((char*)pTgt, capacity);
1230     if (pFile) {
1231       unsigned int nofBlocks=fOutputBlocks.size();
1232       if (nofBlocks+1>fMemFiles.size()) {
1233         fMemFiles.resize(nofBlocks+1, NULL);
1234       }
1235       if (nofBlocks<fMemFiles.size()) {
1236         fMemFiles[nofBlocks]=pFile;
1237         AliHLTComponentBlockData bd;
1238         FillBlockData( bd );
1239         bd.fOffset        = fOutputBufferFilled;
1240         bd.fSize          = capacity;
1241         bd.fDataType      = dt;
1242         bd.fSpecification = spec;
1243         fOutputBufferFilled+=bd.fSize;
1244         fOutputBlocks.push_back( bd );
1245       } else {
1246         HLTError("can not allocate/grow object array");
1247         pFile->CloseMemoryFile(0);
1248         delete pFile;
1249         pFile=NULL;
1250       }
1251     }
1252   } else {
1253     HLTError("can not create memory file of size %d (%d available)", capacity, fOutputBufferSize-fOutputBufferFilled);
1254   }
1255   return pFile;
1256 }
1257
1258 AliHLTMemoryFile* AliHLTComponent::CreateMemoryFile(const char* dtID,
1259                                                     const char* dtOrigin,
1260                                                     AliHLTUInt32_t spec,
1261                                                     float capacity)
1262 {
1263   // see header file for function documentation
1264   ALIHLTCOMPONENT_BASE_STOPWATCH();
1265   AliHLTComponentDataType dt;
1266   SetDataType(dt, dtID, dtOrigin);
1267   int size=fOutputBufferSize-fOutputBufferFilled;
1268   if (capacity<0 || capacity>1.0) {
1269     HLTError("invalid parameter: capacity %f", capacity);
1270     return NULL;
1271   }
1272   size=(int)(size*capacity);
1273   return CreateMemoryFile(size, dt, spec);
1274 }
1275
1276 AliHLTMemoryFile* AliHLTComponent::CreateMemoryFile(const AliHLTComponentDataType& dt,
1277                                                     AliHLTUInt32_t spec,
1278                                                     float capacity)
1279 {
1280   // see header file for function documentation
1281   ALIHLTCOMPONENT_BASE_STOPWATCH();
1282   int size=fOutputBufferSize-fOutputBufferFilled;
1283   if (capacity<0 || capacity>1.0) {
1284     HLTError("invalid parameter: capacity %f", capacity);
1285     return NULL;
1286   }
1287   size=(int)(size*capacity);
1288   return CreateMemoryFile(size, dt, spec);
1289 }
1290
1291 int AliHLTComponent::Write(AliHLTMemoryFile* pFile, const TObject* pObject,
1292                            const char* key, int option)
1293 {
1294   // see header file for function documentation
1295   int iResult=0;
1296   if (pFile && pObject) {
1297     pFile->cd();
1298     iResult=pObject->Write(key, option);
1299     if (iResult>0) {
1300       // success
1301     } else {
1302       iResult=-pFile->GetErrno();
1303       if (iResult==-ENOSPC) {
1304         HLTError("error writing memory file, buffer too small");
1305       }
1306     }
1307   } else {
1308     iResult=-EINVAL;
1309   }
1310   return iResult;
1311 }
1312
1313 int AliHLTComponent::CloseMemoryFile(AliHLTMemoryFile* pFile)
1314 {
1315   // see header file for function documentation
1316   int iResult=0;
1317   if (pFile) {
1318     AliHLTMemoryFilePList::iterator element=fMemFiles.begin();
1319     int i=0;
1320     while (element!=fMemFiles.end() && iResult>=0) {
1321       if (*element && *element==pFile) {
1322         iResult=pFile->CloseMemoryFile();
1323         
1324         // sync memory files and descriptors
1325         if (iResult>=0) {
1326           fOutputBlocks[i].fSize=(*element)->GetSize()+(*element)->GetHeaderSize();
1327         }
1328         delete *element;
1329         *element=NULL;
1330         return iResult;
1331       }
1332       element++; i++;
1333     }
1334     HLTError("can not find memory file %p", pFile);
1335     iResult=-ENOENT;
1336   } else {
1337     iResult=-EINVAL;
1338   }
1339   return iResult;
1340 }
1341
1342 int AliHLTComponent::CreateEventDoneData(AliHLTComponentEventDoneData edd)
1343 {
1344   // see header file for function documentation
1345   int iResult=0;
1346
1347   AliHLTComponentEventDoneData* newEDD = NULL;
1348   
1349   unsigned long newSize=edd.fDataSize;
1350   if (fEventDoneData)
1351     newSize += fEventDoneData->fDataSize;
1352
1353   if (newSize>fEventDoneDataSize) {
1354     newEDD = reinterpret_cast<AliHLTComponentEventDoneData*>( new AliHLTUInt8_t[ sizeof(AliHLTComponentEventDoneData)+newSize ] );
1355     if (!newEDD)
1356       return -ENOMEM;
1357     newEDD->fStructSize = sizeof(AliHLTComponentEventDoneData);
1358     newEDD->fDataSize = newSize;
1359     newEDD->fData = reinterpret_cast<AliHLTUInt8_t*>(newEDD)+newEDD->fStructSize;
1360     unsigned long long offset = 0;
1361     if (fEventDoneData) {
1362       memcpy( newEDD->fData, fEventDoneData->fData, fEventDoneData->fDataSize );
1363       offset += fEventDoneData->fDataSize;
1364     }
1365     memcpy( reinterpret_cast<AliHLTUInt8_t*>(newEDD->fData)+offset, edd.fData, edd.fDataSize );
1366     if (fEventDoneData)
1367       delete [] reinterpret_cast<AliHLTUInt8_t*>( fEventDoneData );
1368     fEventDoneData = newEDD;
1369     fEventDoneDataSize = newSize;
1370   }
1371   else {
1372     memcpy( reinterpret_cast<AliHLTUInt8_t*>(fEventDoneData->fData)+fEventDoneData->fDataSize, edd.fData, edd.fDataSize );
1373     fEventDoneData->fDataSize += edd.fDataSize;
1374   }
1375   return iResult;
1376 }
1377
1378 int AliHLTComponent::ProcessEvent( const AliHLTComponentEventData& evtData,
1379                                    const AliHLTComponentBlockData* blocks, 
1380                                    AliHLTComponentTriggerData& trigData,
1381                                    AliHLTUInt8_t* outputPtr, 
1382                                    AliHLTUInt32_t& size,
1383                                    AliHLTUInt32_t& outputBlockCnt, 
1384                                    AliHLTComponentBlockData*& outputBlocks,
1385                                    AliHLTComponentEventDoneData*& edd )
1386 {
1387   // see header file for function documentation
1388   HLTLogKeyword(fChainId.c_str());
1389   ALIHLTCOMPONENT_BASE_STOPWATCH();
1390   int iResult=0;
1391   fCurrentEvent=evtData.fEventID;
1392   fCurrentEventData=evtData;
1393   fpInputBlocks=blocks;
1394   fCurrentInputBlock=-1;
1395   fSearchDataType=kAliHLTAnyDataType;
1396   fpOutputBuffer=outputPtr;
1397   fOutputBufferSize=size;
1398   fOutputBufferFilled=0;
1399   fOutputBlocks.clear();
1400   outputBlockCnt=0;
1401   outputBlocks=NULL;
1402
1403   AliHLTComponentBlockDataList forwardedBlocks;
1404
1405   // optional component statistics
1406   AliHLTComponentStatisticsList compStats;
1407   bool bAddComponentTableEntry=false;
1408   vector<AliHLTUInt32_t> parentComponentTables;
1409 #if defined(__DEBUG) || defined(HLT_COMPONENT_STATISTICS)
1410   AliHLTComponentStatistics outputStat;
1411   memset(&outputStat, 0, sizeof(AliHLTComponentStatistics));
1412   outputStat.fStructSize=sizeof(AliHLTComponentStatistics);
1413   outputStat.fId=fChainIdCrc;
1414   if (fpBenchmark) {
1415     fpBenchmark->Stop();
1416     outputStat.fComponentCycleTime=(AliHLTUInt32_t)(fpBenchmark->RealTime()*ALIHLTCOMPONENT_STATTIME_SCALER);
1417     fpBenchmark->Reset();
1418     fpBenchmark->Start();
1419   }
1420   compStats.push_back(outputStat);
1421 #endif
1422
1423   // data processing is skipped
1424   // -  if there are only steering events in the block list.
1425   //    For the sake of data source components data processing
1426   //    is not skipped if there is no block list at all or if it
1427   //    just contains the eventType block
1428   // - always skipped if the event is of type
1429   //   - gkAliEventTypeConfiguration
1430   //   - gkAliEventTypeReadPreprocessor
1431   const unsigned int skipModeDefault=0x1;
1432   const unsigned int skipModeForce=0x2;
1433   unsigned int bSkipDataProcessing=skipModeDefault;
1434
1435   // find special events
1436   if (fpInputBlocks && evtData.fBlockCnt>0) {
1437     // first look for all special events and execute in the appropriate
1438     // sequence afterwords
1439     int indexComConfEvent=-1;
1440     int indexUpdtDCSEvent=-1;
1441     int indexSOREvent=-1;
1442     int indexEOREvent=-1;
1443     for (unsigned int i=0; i<evtData.fBlockCnt && iResult>=0; i++) {
1444       if (fpInputBlocks[i].fDataType==kAliHLTDataTypeSOR) {
1445         indexSOREvent=i;
1446         // the AliHLTCalibrationProcessor relies on the SOR and EOR events
1447         bSkipDataProcessing&=~skipModeDefault;
1448       } else if (fpInputBlocks[i].fDataType==kAliHLTDataTypeRunType) {
1449         // run type string
1450         // handling is not clear yet
1451         if (fpInputBlocks[i].fPtr) {
1452           HLTDebug("got run type \"%s\"\n", fpInputBlocks[i].fPtr);
1453         }
1454       } else if (fpInputBlocks[i].fDataType==kAliHLTDataTypeEOR) {
1455         indexEOREvent=i;
1456         // the calibration processor relies on the SOR and EOR events
1457         bSkipDataProcessing&=~skipModeDefault;
1458       } else if (fpInputBlocks[i].fDataType==kAliHLTDataTypeDDL) {
1459         // DDL list
1460         // this event is most likely deprecated
1461       } else if (fpInputBlocks[i].fDataType==kAliHLTDataTypeComConf) {
1462         indexComConfEvent=i;
1463       } else if (fpInputBlocks[i].fDataType==kAliHLTDataTypeUpdtDCS) {
1464         indexUpdtDCSEvent=i;
1465       } else if (fpInputBlocks[i].fDataType==kAliHLTDataTypeEvent) {
1466         fEventType=fpInputBlocks[i].fSpecification;
1467
1468         // skip always in case of gkAliEventTypeConfiguration
1469         if (fpInputBlocks[i].fSpecification==gkAliEventTypeConfiguration) bSkipDataProcessing|=skipModeForce;
1470
1471         // skip always in case of gkAliEventTypeReadPreprocessor
1472         if (fpInputBlocks[i].fSpecification==gkAliEventTypeReadPreprocessor) bSkipDataProcessing|=skipModeForce;
1473
1474         // never skip if the event type block is the only block
1475         if (evtData.fBlockCnt==1) bSkipDataProcessing&=~skipModeDefault;
1476
1477       } else if (fpInputBlocks[i].fDataType==kAliHLTDataTypeComponentStatistics) {
1478         if (compStats.size()>0) {
1479           AliHLTUInt8_t* pData=reinterpret_cast<AliHLTUInt8_t*>(fpInputBlocks[i].fPtr);
1480           for (AliHLTUInt32_t offset=0;
1481                offset+sizeof(AliHLTComponentStatistics)<=fpInputBlocks[i].fSize;
1482                offset+=sizeof(AliHLTComponentStatistics)) {
1483             AliHLTComponentStatistics* pStat=reinterpret_cast<AliHLTComponentStatistics*>(pData+offset);
1484             if (pStat && compStats[0].fLevel<=pStat->fLevel) {
1485               compStats[0].fLevel=pStat->fLevel+1;
1486             }
1487             compStats.push_back(*pStat);
1488           }
1489         }
1490       } else if (fpInputBlocks[i].fDataType==kAliHLTDataTypeComponentTable) {
1491         forwardedBlocks.push_back(fpInputBlocks[i]);
1492         parentComponentTables.push_back(fpInputBlocks[i].fSpecification);
1493       } else {
1494         // the processing function is called if there is at least one
1495         // non-steering data block. Steering blocks are not filtered out
1496         // for sake of performance 
1497         bSkipDataProcessing&=~skipModeDefault;
1498         if (compStats.size()>0) {
1499           compStats[0].fInputBlockCount++;
1500           compStats[0].fTotalInputSize+=fpInputBlocks[i].fSize;
1501         }
1502       }
1503     }
1504
1505     if (indexSOREvent>=0) {
1506       // start of run
1507       bAddComponentTableEntry=true;
1508       if (fpRunDesc==NULL) {
1509         fpRunDesc=new AliHLTRunDesc;
1510         if (fpRunDesc) *fpRunDesc=kAliHLTVoidRunDesc;
1511       }
1512       if (fpRunDesc) {
1513         AliHLTRunDesc rundesc;
1514         if ((iResult=CopyStruct(&rundesc, sizeof(AliHLTRunDesc), indexSOREvent, "AliHLTRunDesc", "SOR"))>0) {
1515           if (fpRunDesc->fRunNo==kAliHLTVoidRunNo) {
1516             *fpRunDesc=rundesc;
1517             HLTDebug("set run decriptor, run no %d", fpRunDesc->fRunNo);
1518             SetCDBRunNo(fpRunDesc->fRunNo);
1519           } else if (fpRunDesc->fRunNo!=rundesc.fRunNo) {
1520             HLTWarning("already set run properties run no %d, ignoring SOR with run no %d", fpRunDesc->fRunNo, rundesc.fRunNo);
1521           }
1522         }
1523       } else {
1524         iResult=-ENOMEM;
1525       }
1526     }
1527     if (indexEOREvent>=0) {
1528       bAddComponentTableEntry=true;
1529       if (fpRunDesc!=NULL) {
1530         if (fpRunDesc) {
1531           AliHLTRunDesc rundesc;
1532           if ((iResult=CopyStruct(&rundesc, sizeof(AliHLTRunDesc), indexEOREvent, "AliHLTRunDesc", "SOR"))>0) {
1533             if (fpRunDesc->fRunNo!=rundesc.fRunNo) {
1534               HLTWarning("run no mismatch: SOR %d, EOR %d", fpRunDesc->fRunNo, rundesc.fRunNo);
1535             } else {
1536               HLTDebug("EOR run no %d", fpRunDesc->fRunNo);
1537             }
1538           }
1539           AliHLTRunDesc* pRunDesc=fpRunDesc;
1540           fpRunDesc=NULL;
1541           delete pRunDesc;
1542         }
1543       } else {
1544         HLTWarning("did not receive SOR, ignoring EOR");
1545       }
1546     }
1547     if (indexComConfEvent>=0 || fEventType==gkAliEventTypeConfiguration) {
1548       TString cdbEntry;
1549       if (indexComConfEvent>=0 && fpInputBlocks[indexComConfEvent].fPtr!=NULL && fpInputBlocks[indexComConfEvent].fSize>0) {
1550         cdbEntry.Append(reinterpret_cast<const char*>(fpInputBlocks[indexComConfEvent].fPtr), fpInputBlocks[indexComConfEvent].fSize);
1551       }
1552       HLTDebug("received component configuration command: entry %s", cdbEntry.IsNull()?"none":cdbEntry.Data());
1553       int tmpResult=Reconfigure(cdbEntry[0]==0?NULL:cdbEntry.Data(), fChainId.c_str());
1554       if (tmpResult<0) {
1555         HLTWarning("reconfiguration of component %p (%s) failed with error code %d", this, GetComponentID(), tmpResult);
1556       }
1557     }
1558     if (indexUpdtDCSEvent>=0 || fEventType==gkAliEventTypeReadPreprocessor) {
1559       TString modules;
1560       if (fpInputBlocks[indexUpdtDCSEvent].fPtr!=NULL && fpInputBlocks[indexUpdtDCSEvent].fSize>0) {
1561         modules.Append(reinterpret_cast<const char*>(fpInputBlocks[indexUpdtDCSEvent].fPtr), fpInputBlocks[indexUpdtDCSEvent].fSize);
1562       }
1563       HLTDebug("received preprocessor update command: detectors %s", modules.IsNull()?"ALL":modules.Data());
1564       int tmpResult=ReadPreprocessorValues(modules[0]==0?"ALL":modules.Data());
1565       if (tmpResult<0) {
1566         HLTWarning("preprocessor update of component %p (%s) failed with error code %d", this, GetComponentID(), tmpResult);
1567       }
1568     }
1569   } else {
1570     // processing function needs to be called if there are no input data
1571     // blocks in order to make data source components working.
1572     bSkipDataProcessing&=~skipModeDefault;
1573   }
1574
1575   // data processing is not skipped if the component explicitly asks
1576   // for the private blocks
1577   if (fRequireSteeringBlocks) bSkipDataProcessing=0;
1578
1579   AliHLTComponentBlockDataList blockData;
1580   if (iResult>=0 && !bSkipDataProcessing)
1581   { // dont delete, sets the scope for the stopwatch guard
1582     // do not use ALIHLTCOMPONENT_DA_STOPWATCH(); macro
1583     // in order to avoid 'shadowed variable' warning
1584     AliHLTStopwatchGuard swguard2(fpStopwatches!=NULL?reinterpret_cast<TStopwatch*>(fpStopwatches->At((int)kSWDA)):NULL);
1585     iResult=DoProcessing(evtData, blocks, trigData, outputPtr, size, blockData, edd);
1586   } // end of the scope of the stopwatch guard
1587   if (iResult>=0 && !bSkipDataProcessing) {
1588     if (fOutputBlocks.size()>0) {
1589       // High Level interface
1590
1591       //HLTDebug("got %d block(s) via high level interface", fOutputBlocks.size());      
1592       // sync memory files and descriptors
1593       AliHLTMemoryFilePList::iterator element=fMemFiles.begin();
1594       int i=0;
1595       while (element!=fMemFiles.end() && iResult>=0) {
1596         if (*element) {
1597           if ((*element)->IsClosed()==0) {
1598             HLTWarning("memory file has not been closed, force flush");
1599             iResult=CloseMemoryFile(*element);
1600           }
1601         }
1602         element++; i++;
1603       }
1604
1605       if (iResult>=0) {
1606         // create the descriptor list
1607         if (blockData.size()>0) {
1608           HLTError("low level and high interface must not be mixed; use PushBack methods to insert data blocks");
1609           iResult=-EFAULT;
1610         } else {
1611           if (compStats.size()>0 && IsDataEvent()) {
1612             int offset=AddComponentStatistics(fOutputBlocks, fpOutputBuffer, fOutputBufferSize, fOutputBufferFilled, compStats);
1613             if (offset>0) fOutputBufferFilled+=offset;
1614           }
1615           if (bAddComponentTableEntry) {
1616             int offset=AddComponentTableEntry(fOutputBlocks, fpOutputBuffer, fOutputBufferSize, fOutputBufferFilled, parentComponentTables);
1617             if (offset>0) size+=offset;
1618           }
1619           if (forwardedBlocks.size()>0) {
1620             fOutputBlocks.insert(fOutputBlocks.end(), forwardedBlocks.begin(), forwardedBlocks.end());
1621           }
1622           iResult=MakeOutputDataBlockList(fOutputBlocks, &outputBlockCnt, &outputBlocks);
1623           size=fOutputBufferFilled;
1624         }
1625       }
1626     } else {
1627       // Low Level interface
1628       if (compStats.size()>0) {
1629         int offset=AddComponentStatistics(blockData, fpOutputBuffer, fOutputBufferSize, size, compStats);
1630         if (offset>0) size+=offset;
1631       }
1632       if (bAddComponentTableEntry) {
1633         int offset=AddComponentTableEntry(blockData, fpOutputBuffer, fOutputBufferSize, size, parentComponentTables);
1634         if (offset>0) size+=offset;
1635       }
1636       if (forwardedBlocks.size()>0) {
1637         blockData.insert(blockData.end(), forwardedBlocks.begin(), forwardedBlocks.end());
1638       }
1639       iResult=MakeOutputDataBlockList(blockData, &outputBlockCnt, &outputBlocks);
1640     }
1641     if (iResult<0) {
1642       HLTFatal("component %s (%p): can not convert output block descriptor list", GetComponentID(), this);
1643     }
1644   }
1645   if (iResult<0 || bSkipDataProcessing) {
1646     outputBlockCnt=0;
1647     outputBlocks=NULL;
1648   }
1649   CleanupInputObjects();
1650   if (iResult>=0 && IsDataEvent()) {
1651     IncrementEventCounter();
1652   }
1653   if (outputBlockCnt==0) {
1654     // no output blocks, set size to 0
1655     size=0;
1656   }
1657   FillEventData(fCurrentEventData);
1658   return iResult;
1659 }
1660
1661 int  AliHLTComponent::AddComponentStatistics(AliHLTComponentBlockDataList& blocks, 
1662                                              AliHLTUInt8_t* buffer,
1663                                              AliHLTUInt32_t bufferSize,
1664                                              AliHLTUInt32_t offset,
1665                                              AliHLTComponentStatisticsList& stats) const
1666 {
1667   // see header file for function documentation
1668   int iResult=0;
1669 #if defined(__DEBUG) || defined(HLT_COMPONENT_STATISTICS)
1670   if (stats.size()==0) return -ENOENT;
1671   // check if there is space for at least one entry
1672   if (offset+sizeof(AliHLTComponentStatistics)>bufferSize) return 0;
1673   stats[0].fTotalOutputSize=offset;
1674   stats[0].fOutputBlockCount=blocks.size();
1675   if (fpBenchmark) {
1676     fpBenchmark->Stop();
1677     stats[0].fTime=(AliHLTUInt32_t)(fpBenchmark->RealTime()*ALIHLTCOMPONENT_STATTIME_SCALER);
1678     stats[0].fCTime=(AliHLTUInt32_t)(fpBenchmark->CpuTime()*ALIHLTCOMPONENT_STATTIME_SCALER);
1679     fpBenchmark->Continue();
1680   }
1681   if (offset+stats.size()*sizeof(AliHLTComponentStatistics)>bufferSize) {
1682     AliHLTUInt32_t removedLevel=0;
1683     do {
1684       // remove all entries of the level of the last entry
1685       removedLevel=stats.back().fLevel;
1686       AliHLTComponentStatisticsList::iterator element=stats.begin();
1687       element++;
1688       while (element!=stats.end()) {
1689         if (element->fLevel<=removedLevel) {
1690           element=stats.erase(element);
1691         } else {
1692           element++;
1693         }
1694       }
1695     } while (stats.size()>1 && 
1696              (offset+stats.size()*sizeof(AliHLTComponentStatistics)>bufferSize));
1697   }
1698   assert(stats.size()>0);
1699   if (stats.size()==0) return 0;
1700
1701   if (offset+stats.size()*sizeof(AliHLTComponentStatistics)<=bufferSize) {
1702     AliHLTComponentBlockData bd;
1703     FillBlockData( bd );
1704     bd.fOffset        = offset;
1705     bd.fSize          = stats.size()*sizeof(AliHLTComponentStatistics);
1706     bd.fDataType      = kAliHLTDataTypeComponentStatistics;
1707     bd.fSpecification = kAliHLTVoidDataSpec;
1708     unsigned int master=0;
1709     for (unsigned int i=1; i<blocks.size(); i++) {
1710       if (blocks[i].fSize>blocks[master].fSize && 
1711           !MatchExactly(blocks[i].fDataType, kAliHLTVoidDataType|kAliHLTDataOriginPrivate))
1712         master=i;
1713     }
1714     if (blocks.size()>0 && !MatchExactly(blocks[master].fDataType, kAliHLTVoidDataType|kAliHLTDataOriginPrivate)) {
1715       // take the data origin of the biggest block as specification
1716       // this is similar to the treatment in the HOMER interface. For traditional
1717       // reasons, the bytes are swapped there on a little endian architecture, so
1718       // we do it as well.
1719       memcpy(&bd.fSpecification, &blocks[master].fDataType.fOrigin, sizeof(bd.fSpecification));
1720 #ifdef R__BYTESWAP // set on little endian architectures
1721       bd.fSpecification=((bd.fSpecification & 0xFFULL) << 24) | 
1722         ((bd.fSpecification & 0xFF00ULL) << 8) | 
1723         ((bd.fSpecification & 0xFF0000ULL) >> 8) | 
1724         ((bd.fSpecification & 0xFF000000ULL) >> 24);
1725 #endif
1726     }
1727     memcpy(buffer+offset, &(stats[0]), bd.fSize);
1728     blocks.push_back(bd);
1729     iResult=bd.fSize;
1730   }
1731 #else
1732   if (blocks.size() && buffer && bufferSize && offset && stats.size()) {
1733     // get rid of warning
1734   }
1735 #endif
1736   return iResult;
1737 }
1738
1739 int  AliHLTComponent::AddComponentTableEntry(AliHLTComponentBlockDataList& blocks, 
1740                                              AliHLTUInt8_t* buffer,
1741                                              AliHLTUInt32_t bufferSize,
1742                                              AliHLTUInt32_t offset,
1743                                              const vector<AliHLTUInt32_t>& parents) const
1744 {
1745   // see header file for function documentation
1746   int iResult=0;
1747 #if defined(__DEBUG) || defined(HLT_COMPONENT_STATISTICS)
1748   // the payload consists of the AliHLTComponentTableEntry struct,
1749   // followed by a an array of 32bit crc chain ids and the component
1750   // description string
1751   unsigned int payloadSize=sizeof(AliHLTComponentTableEntry);
1752   payloadSize+=parents.size()*sizeof(AliHLTUInt32_t);
1753
1754   // the component description has the following format:
1755   // chain-id{component-id:arguments}
1756   const char* componentId=const_cast<AliHLTComponent*>(this)->GetComponentID();
1757   unsigned int descriptionSize=fChainId.size()+1;
1758   descriptionSize+=2; // the '{}' around the component id
1759   descriptionSize+=strlen(componentId);
1760   descriptionSize+=1; // the ':' between component id and arguments
1761   descriptionSize+=fComponentArgs.size();
1762
1763   payloadSize+=descriptionSize;
1764   if (buffer && (offset+payloadSize<=bufferSize)) {
1765     AliHLTUInt8_t* pTgt=buffer+offset;
1766     memset(pTgt, 0, payloadSize);
1767
1768     // write entry
1769     AliHLTComponentTableEntry* pEntry=reinterpret_cast<AliHLTComponentTableEntry*>(pTgt);
1770     pEntry->fStructSize=sizeof(AliHLTComponentTableEntry);
1771     pEntry->fNofParents=parents.size();
1772     pEntry->fSizeDescription=descriptionSize;
1773     pTgt=pEntry->fBuffer;
1774
1775     // write array of parents
1776     if (parents.size()>0) {
1777       unsigned int copy=parents.size()*sizeof(vector<AliHLTUInt32_t>::value_type);
1778       memcpy(pTgt, &parents[0], parents.size()*sizeof(vector<AliHLTUInt32_t>::value_type));
1779       pTgt+=copy;
1780     }
1781
1782     // write component description
1783     memcpy(pTgt, fChainId.c_str(), fChainId.size());
1784     pTgt+=fChainId.size();
1785     *pTgt++='{';
1786     memcpy(pTgt, componentId, strlen(componentId));
1787     pTgt+=strlen(componentId);
1788     *pTgt++=':';
1789     memcpy(pTgt, fComponentArgs.c_str(), fComponentArgs.size());
1790     pTgt+=fComponentArgs.size();
1791     *pTgt++='}';
1792     *pTgt++=0;
1793
1794     AliHLTComponentBlockData bd;
1795     FillBlockData( bd );
1796     bd.fOffset        = offset;
1797     bd.fSize          = payloadSize;
1798     bd.fDataType      = kAliHLTDataTypeComponentTable;
1799     bd.fSpecification = fChainIdCrc;
1800     blocks.push_back(bd);
1801     iResult=bd.fSize;
1802   }
1803 #else
1804   if (blocks.size() && buffer && bufferSize && offset && parents.size()) {
1805     // get rid of warning
1806   }
1807  #endif
1808   return iResult;
1809 }
1810
1811 AliHLTComponent::AliHLTStopwatchGuard::AliHLTStopwatchGuard()
1812   :
1813   fpStopwatch(NULL),
1814   fpPrec(NULL)
1815 {
1816   // standard constructor (not for use)
1817 }
1818
1819 AliHLTComponent::AliHLTStopwatchGuard::AliHLTStopwatchGuard(TStopwatch* pStopwatch)
1820   :
1821   fpStopwatch(pStopwatch),
1822   fpPrec(NULL)
1823 {
1824   // constructor
1825
1826   // check for already existing guard
1827   if (fgpCurrent) fpPrec=fgpCurrent;
1828   fgpCurrent=this;
1829
1830   // stop the preceeding guard if it controls a different stopwatch
1831   int bStart=1;
1832   if (fpPrec && fpPrec!=this) bStart=fpPrec->Hold(fpStopwatch);
1833
1834   // start the stopwatch if the current guard controls a different one
1835   if (fpStopwatch && bStart==1) fpStopwatch->Start(kFALSE);
1836 }
1837
1838 AliHLTComponent::AliHLTStopwatchGuard::AliHLTStopwatchGuard(const AliHLTStopwatchGuard&)
1839   :
1840   fpStopwatch(NULL),
1841   fpPrec(NULL)
1842 {
1843   //
1844   // copy constructor not for use
1845   //
1846 }
1847
1848 AliHLTComponent::AliHLTStopwatchGuard& AliHLTComponent::AliHLTStopwatchGuard::operator=(const AliHLTStopwatchGuard&)
1849 {
1850   //
1851   // assignment operator not for use
1852   //
1853   fpStopwatch=NULL;
1854   fpPrec=NULL;
1855   return *this;
1856 }
1857
1858 AliHLTComponent::AliHLTStopwatchGuard* AliHLTComponent::AliHLTStopwatchGuard::fgpCurrent=NULL;
1859
1860 AliHLTComponent::AliHLTStopwatchGuard::~AliHLTStopwatchGuard()
1861 {
1862   // destructor
1863
1864   // resume the preceeding guard if it controls a different stopwatch
1865   int bStop=1;
1866   if (fpPrec && fpPrec!=this) bStop=fpPrec->Resume(fpStopwatch);
1867
1868   // stop the stopwatch if the current guard controls a different one
1869   if (fpStopwatch && bStop==1) fpStopwatch->Stop();
1870
1871   // resume to the preceeding guard
1872   fgpCurrent=fpPrec;
1873 }
1874
1875 int AliHLTComponent::AliHLTStopwatchGuard::Hold(TStopwatch* pSucc)
1876 {
1877   // see header file for function documentation
1878   if (fpStopwatch!=NULL && fpStopwatch!=pSucc) fpStopwatch->Stop();
1879   return fpStopwatch!=pSucc?1:0;
1880 }
1881
1882 int AliHLTComponent::AliHLTStopwatchGuard::Resume(TStopwatch* pSucc)
1883 {
1884   // see header file for function documentation
1885   if (fpStopwatch!=NULL && fpStopwatch!=pSucc) fpStopwatch->Start(kFALSE);
1886   return fpStopwatch!=pSucc?1:0;
1887 }
1888
1889 int AliHLTComponent::SetStopwatch(TObject* pSW, AliHLTStopwatchType type) 
1890 {
1891   // see header file for function documentation
1892   int iResult=0;
1893   if (pSW!=NULL && type<kSWTypeCount) {
1894     if (fpStopwatches) {
1895       TObject* pObj=fpStopwatches->At((int)type);
1896       if (pSW==NULL        // explicit reset
1897           || pObj==NULL) { // explicit set
1898         fpStopwatches->AddAt(pSW, (int)type);
1899       } else if (pObj!=pSW) {
1900         HLTWarning("stopwatch %d already set, reset first", (int)type);
1901         iResult=-EBUSY;
1902       }
1903     }
1904   } else {
1905     iResult=-EINVAL;
1906   }
1907   return iResult;
1908 }
1909
1910 int AliHLTComponent::SetStopwatches(TObjArray* pStopwatches)
1911 {
1912   // see header file for function documentation
1913   if (pStopwatches==NULL) return -EINVAL;
1914
1915   int iResult=0;
1916   for (int i=0 ; i<(int)kSWTypeCount && pStopwatches->GetEntries(); i++)
1917     SetStopwatch(pStopwatches->At(i), (AliHLTStopwatchType)i);
1918   return iResult;
1919 }
1920
1921 AliHLTUInt32_t AliHLTComponent::GetRunNo() const
1922 {
1923   // see header file for function documentation
1924   if (fpRunDesc==NULL) return kAliHLTVoidRunNo;
1925   return fpRunDesc->fRunNo;
1926 }
1927
1928 AliHLTUInt32_t AliHLTComponent::GetRunType() const
1929 {
1930   // see header file for function documentation
1931   if (fpRunDesc==NULL) return kAliHLTVoidRunType;
1932   return fpRunDesc->fRunType;
1933 }
1934
1935 bool AliHLTComponent::IsDataEvent(AliHLTUInt32_t* pTgt)
1936 {
1937   // see header file for function documentation
1938   if (pTgt) *pTgt=fEventType;
1939   return (fEventType==gkAliEventTypeData ||
1940           fEventType==gkAliEventTypeDataReplay ||
1941           fEventType==gkAliEventTypeCalibration);
1942 }
1943
1944 int AliHLTComponent::CopyStruct(void* pStruct, unsigned int iStructSize, unsigned int iBlockNo,
1945                                 const char* structname, const char* eventname)
1946 {
1947   // see header file for function documentation
1948   int iResult=0;
1949   if (pStruct!=NULL && iStructSize>sizeof(AliHLTUInt32_t)) {
1950     if (fpInputBlocks!=NULL && iBlockNo<fCurrentEventData.fBlockCnt) {
1951       AliHLTUInt32_t* pTgt=(AliHLTUInt32_t*)pStruct;
1952       if (fpInputBlocks[iBlockNo].fPtr && fpInputBlocks[iBlockNo].fSize) {
1953         AliHLTUInt32_t copy=*((AliHLTUInt32_t*)fpInputBlocks[iBlockNo].fPtr);
1954         if (fpInputBlocks[iBlockNo].fSize!=copy) {
1955           HLTWarning("%s event: mismatch of block size (%d) and structure size (%d)", eventname, fpInputBlocks[iBlockNo].fSize, copy);
1956           if (copy>fpInputBlocks[iBlockNo].fSize) copy=fpInputBlocks[iBlockNo].fSize;
1957         }
1958         if (copy!=iStructSize) {
1959           HLTWarning("%s event: mismatch in %s version (data type version %d)", eventname, structname, ALIHLT_DATA_TYPES_VERSION);
1960           if (copy>iStructSize) {
1961             copy=iStructSize;
1962           } else {
1963             memset(pTgt, 0, iStructSize);
1964           }
1965         }
1966         memcpy(pTgt, fpInputBlocks[iBlockNo].fPtr, copy);
1967         *pTgt=iStructSize;
1968         iResult=copy;
1969       } else {
1970         HLTWarning("%s event: missing data block", eventname);
1971       }
1972     } else {
1973       iResult=-ENODATA;
1974     }
1975   } else {
1976     HLTError("invalid struct");
1977     iResult=-EINVAL;
1978   }
1979   return iResult;
1980 }
1981
1982 void AliHLTComponent::SetDDLBit(AliHLTEventDDL &list, Int_t ddlId, Bool_t state ) const
1983 {
1984   // see header file for function documentation
1985   
1986   // -- Detector offset
1987   Int_t ddlIdBase =  TMath::FloorNint( (Double_t) ddlId / 256.0 );
1988   
1989   // -- Word Base = 1. word of detector ( TPC has 8 words, TOF 3 ) 
1990   Int_t wordBase = 0;
1991
1992   if ( ddlIdBase <= 3 )
1993     wordBase = ddlIdBase;
1994   else if ( ddlIdBase > 3 && ddlIdBase < 5 )
1995     wordBase = ddlIdBase + 7;
1996   else 
1997     wordBase = ddlIdBase + 9;
1998
1999   // -- Bit index in Word
2000   Int_t bitIdx = ddlId % 32;
2001
2002   // -- Index of word
2003   Int_t wordIdx = wordBase;
2004
2005   // -- if TPC (3) or TOD (5) add word idx
2006   if ( ( ddlIdBase == 3 ) || ( ddlIdBase == 5 ) ) {
2007     wordIdx += TMath::FloorNint( (Double_t) ( ddlId - ( ddlIdBase * 256 ) ) / 32.0 );
2008   }
2009
2010   // -- Set -- 'OR' word with bit mask;
2011   if ( state )
2012     list.fList[wordIdx] |= ( 0x00000001 << bitIdx );
2013   // -- Unset -- 'AND' word with bit mask;
2014   else
2015     list.fList[wordIdx] &= ( 0xFFFFFFFF ^ ( 0x00000001 << bitIdx ) );
2016 }
2017
2018 Int_t AliHLTComponent::GetFirstUsedDDLWord(AliHLTEventDDL &list) const
2019 {
2020   // see header file for function documentation
2021
2022   Int_t iResult = -1;
2023
2024   for ( Int_t wordNdx = 0 ; wordNdx < gkAliHLTDDLListSize ; wordNdx++ ) {
2025
2026     if ( list.fList[wordNdx] != 0 && iResult == -1 ) {
2027       // check for special cases TPC and TOF
2028       if ( wordNdx > 3 && wordNdx <= 10 ) {
2029         wordNdx = 10;
2030         iResult = 3;
2031       }
2032       else if ( wordNdx > 12 && wordNdx <= 14 ) {
2033         wordNdx = 14;
2034         iResult = 12;
2035       }
2036       else
2037         iResult = wordNdx;
2038     }
2039     else if ( list.fList[wordNdx] != 0 && iResult >= 0 ) {
2040       HLTError( "DDLIDs for minimum of TWO detectors ( %d, %d ) set, this function works only for ONE detector.", iResult, wordNdx );
2041       iResult = -1;
2042       break;
2043     }
2044   }
2045
2046   return iResult;
2047 }
2048
2049 AliHLTUInt32_t AliHLTComponent::CalculateChecksum(const AliHLTUInt8_t* buffer, int size)
2050 {
2051   // see header file for function documentation
2052   AliHLTUInt32_t  remainder = 0; 
2053   const AliHLTUInt8_t crcwidth=(8*sizeof(AliHLTUInt32_t));
2054   const AliHLTUInt32_t topbit=1 << (crcwidth-1);
2055   const AliHLTUInt32_t polynomial=0xD8;  /* 11011 followed by 0's */
2056
2057   // code from
2058   // http://www.netrino.com/Embedded-Systems/How-To/CRC-Calculation-C-Code
2059
2060   /*
2061    * Perform modulo-2 division, a byte at a time.
2062    */
2063   for (int byte = 0; byte < size; ++byte)
2064     {
2065       /*
2066        * Bring the next byte into the remainder.
2067        */
2068       remainder ^= (buffer[byte] << (crcwidth - 8));
2069
2070       /*
2071        * Perform modulo-2 division, a bit at a time.
2072        */
2073       for (uint8_t bit = 8; bit > 0; --bit)
2074         {
2075           /*
2076            * Try to divide the current data bit.
2077            */
2078           if (remainder & topbit)
2079             {
2080               remainder = (remainder << 1) ^ polynomial;
2081             }
2082           else
2083             {
2084               remainder = (remainder << 1);
2085             }
2086         }
2087     }
2088
2089   /*
2090    * The final remainder is the CRC result.
2091    */
2092   return (remainder);
2093 }
2094
2095 int AliHLTComponent::ExtractComponentTableEntry(const AliHLTUInt8_t* pBuffer, AliHLTUInt32_t size,
2096                                                 string& retChainId, string& retCompId, string& retCompArgs,
2097                                                 vector<AliHLTUInt32_t>& parents)
2098 {
2099   // see header file for function documentation
2100   retChainId.clear();
2101   retCompId.clear();
2102   retCompArgs.clear();
2103   parents.clear();
2104   if (!pBuffer || size==0) return 0;
2105
2106   const AliHLTComponentTableEntry* pEntry=reinterpret_cast<const AliHLTComponentTableEntry*>(pBuffer);
2107   if (size<8/* the initial size of the structure*/ ||
2108       pEntry==NULL || pEntry->fStructSize<8) return -ENOMSG;
2109   const AliHLTUInt32_t* pParents=reinterpret_cast<const AliHLTUInt32_t*>(pEntry->fBuffer);
2110   const AliHLTUInt8_t* pEnd=pBuffer+size;
2111
2112   if (pParents+pEntry->fNofParents>=reinterpret_cast<const AliHLTUInt32_t*>(pEnd)) return -ENODEV;
2113   for (unsigned int i=0; i<pEntry->fNofParents; i++, pParents++) {
2114     parents.push_back(*pParents);
2115   }
2116
2117   const char* pDescription=reinterpret_cast<const char*>(pParents);
2118   if (pDescription+pEntry->fSizeDescription>=reinterpret_cast<const char*>(pEnd) ||
2119       *(pDescription+pEntry->fSizeDescription)!=0) {
2120     return -EBADF;
2121   }
2122
2123   TString descriptor=reinterpret_cast<const char*>(pDescription);
2124   TString chainId;
2125   TString compId;
2126   TString compArgs;
2127   TObjArray* pTokens=descriptor.Tokenize("{");
2128   if (pTokens) {
2129     int n=0;
2130     if (pTokens->GetEntries()>n) {
2131       retChainId=((TObjString*)pTokens->At(n++))->GetString();
2132     }
2133     if (pTokens->GetEntries()>n) {
2134       compId=((TObjString*)pTokens->At(n++))->GetString();
2135     }
2136     delete pTokens;
2137   }
2138   if (!compId.IsNull() && (pTokens=compId.Tokenize(":"))!=NULL) {
2139     int n=0;
2140     if (pTokens->GetEntries()>n) {
2141       compId=((TObjString*)pTokens->At(n++))->GetString();
2142     }
2143     if (pTokens->GetEntries()>n) {
2144       compArgs=((TObjString*)pTokens->At(n++))->GetString();
2145     }
2146     delete pTokens;
2147   }
2148   compId.ReplaceAll("}", "");
2149   compArgs.ReplaceAll("}", "");
2150
2151   retCompId=compId;
2152   retCompArgs=compArgs;
2153
2154   if (retChainId.size()==0) return -ENODATA;
2155
2156   return 1;
2157 }
2158
2159 int AliHLTComponent::LoggingVarargs(AliHLTComponentLogSeverity severity, 
2160                                     const char* originClass, const char* originFunc,
2161                                     const char* file, int line, ... ) const
2162 {
2163   // see header file for function documentation
2164   int iResult=0;
2165
2166   va_list args;
2167   va_start(args, line);
2168
2169   // logging function needs to be const in order to be called from const member functions
2170   // without problems. But at this point we face the problem with virtual members which
2171   // are not necessarily const.
2172   AliHLTComponent* nonconst=const_cast<AliHLTComponent*>(this);
2173   AliHLTLogging::SetLogString("%s (%s, %p): ", 
2174                               fChainId[0]!=0?fChainId.c_str():nonconst->GetComponentID(),
2175                               nonconst->GetComponentID(), this);
2176   iResult=SendMessage(severity, originClass, originFunc, file, line, AliHLTLogging::BuildLogString(NULL, args, true /*append*/));
2177   va_end(args);
2178
2179   return iResult;
2180 }