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