activating individual HLT simulations from digits and raw data
[u/mrichter/AliRoot.git] / HLT / rec / AliRawReaderHLT.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  *                  for The ALICE HLT Project.                            *
9  *                                                                        *
10  * Permission to use, copy, modify and distribute this software and its   *
11  * documentation strictly for non-commercial purposes is hereby granted   *
12  * without fee, provided that the above copyright notice appears in all   *
13  * copies and that both the copyright notice and this permission notice   *
14  * appear in the supporting documentation. The authors make no claims     *
15  * about the suitability of this software for any purpose. It is          *
16  * provided "as is" without express or implied warranty.                  *
17  **************************************************************************/
18
19 /** @file   AliRawReaderHLT.cxx
20     @author Matthias Richter
21     @date   
22     @brief  AliRawReader implementation which replaces original input of
23             detectors with the appropriate HLT output.                    */
24
25 // see header file for class documentation
26 // or
27 // refer to README to build package
28 // or
29 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
30
31 #include "AliRawReaderHLT.h"
32 #include "AliHLTOUTRawReader.h"
33 #include "AliHLTModuleAgent.h"
34 #include "AliHLTOUTHandler.h"
35 #include "AliHLTOUTHandlerEquId.h"
36 #include "AliHLTSystem.h"
37 #include "AliHLTPluginBase.h"
38 #include "AliLog.h"
39 #include "AliDAQ.h"            // RAW, for detector names and equipment ids
40 #include "TObjString.h"
41 #include <cassert>
42
43 /** ROOT macro for the implementation of ROOT specific class methods */
44 ClassImp(AliRawReaderHLT)
45
46 AliRawReaderHLT::AliRawReaderHLT(AliRawReader* pRawreader, const char* options)
47   :
48   AliRawReader(),
49   fpParentReader(pRawreader),
50   fOptions(),
51   fSystemOptions(),
52   fpData(NULL),
53   fDataSize(0),
54   fOffset(0),
55   fPosition(0),
56   fEquipmentId(-1),
57   fbHaveHLTData(false),
58   fDetectors(),
59   fpHLTOUT(NULL),
60   fbReadFirst(true),
61   fpDataHandler(NULL),
62   fpPluginBase(new AliHLTPluginBase)
63 {
64   // see header file for class documentation
65   // or
66   // refer to README to build package
67   // or
68   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
69   fOptions=options;
70   ScanOptions(options);
71 }
72
73 AliRawReaderHLT::~AliRawReaderHLT()
74 {
75   // see header file for class documentation
76   ReleaseHLTData();
77   if (fpPluginBase) delete fpPluginBase;
78   fpPluginBase=NULL;
79 }
80
81 UInt_t AliRawReaderHLT::GetType() const
82 {
83   // see header file for class documentation
84   return fpParentReader->GetType();
85 }
86
87 UInt_t AliRawReaderHLT::GetRunNumber() const
88 {
89   // see header file for class documentation
90   return fpParentReader->GetRunNumber();
91 }
92
93 const UInt_t* AliRawReaderHLT::GetEventId() const
94 {
95   // see header file for class documentation
96   return fpParentReader->GetEventId();
97 }
98
99 const UInt_t* AliRawReaderHLT::GetTriggerPattern() const
100 {
101   // see header file for class documentation
102   return fpParentReader->GetTriggerPattern();
103 }
104
105 const UInt_t* AliRawReaderHLT::GetDetectorPattern() const
106 {
107   // see header file for class documentation
108   return fpParentReader->GetDetectorPattern();
109 }
110
111 const UInt_t* AliRawReaderHLT::GetAttributes() const
112 {
113   // see header file for class documentation
114   return fpParentReader->GetAttributes();
115 }
116
117 const UInt_t* AliRawReaderHLT::GetSubEventAttributes() const
118 {
119   // see header file for class documentation
120   return fpParentReader->GetSubEventAttributes();
121 }
122
123 UInt_t AliRawReaderHLT::GetLDCId() const
124 {
125   // see header file for class documentation
126   return fpParentReader->GetLDCId();
127 }
128
129 UInt_t AliRawReaderHLT::GetGDCId() const
130 {
131   // see header file for class documentation
132   return fpParentReader->GetGDCId();
133 }
134
135 UInt_t AliRawReaderHLT::GetTimestamp() const
136 {
137   // see header file for class documentation
138   return fpParentReader->GetTimestamp();
139 }
140
141 const UInt_t* AliRawReaderHLT::GetEquipmentAttributes() const
142 {
143   // see header file for class documentation
144   return fpParentReader->GetEquipmentAttributes();
145 }
146
147 Int_t    AliRawReaderHLT::GetEquipmentElementSize() const
148 {
149   // see header file for class documentation
150   // don't know what it really means, bu the AliRawReaderFile
151   // just sets it to 0
152   // do the same if we have a valid equipment data set from
153   // the HLT stream
154   if (fEquipmentId>=0) return 0;
155   return fpParentReader->GetEquipmentElementSize();
156 }
157
158 Int_t    AliRawReaderHLT::GetEquipmentHeaderSize() const
159 {
160   // see header file for class documentation
161
162   // equipment header means the additional data header?
163   // if we have a valid equipment data set from the HLT stream
164   // there is no additional header
165   if (fEquipmentId>=0) return 0;
166   return fpParentReader->GetEquipmentHeaderSize();
167 }
168
169 Int_t    AliRawReaderHLT::GetEquipmentSize() const
170 {
171   // see header file for class documentation
172   if (fEquipmentId>=0) return fDataSize+sizeof(AliRawDataHeader);
173   return fpParentReader->GetEquipmentSize();
174 }
175
176 Int_t    AliRawReaderHLT::GetEquipmentType() const
177 {
178   // see header file for class documentation
179   return fpParentReader->GetEquipmentType();
180 }
181
182 Int_t    AliRawReaderHLT::GetEquipmentId() const
183 {
184   // see header file for class documentation
185   Int_t id=-1;
186   if (fEquipmentId>=0) id=fEquipmentId;
187   else id=fpParentReader->GetEquipmentId();
188   return id;
189 }
190
191 Bool_t   AliRawReaderHLT::ReadHeader()
192 {
193   // see header file for class documentation
194   Bool_t result=kFALSE;
195   Bool_t firstParentCycle=fbHaveHLTData;
196   while ((fbHaveHLTData=(fbHaveHLTData && ReadNextHLTData()))) {
197     // all internal data variables set
198     assert(fpData!=NULL);
199     fHeader=reinterpret_cast<AliRawDataHeader*>(const_cast<AliHLTUInt8_t*>(fpData));
200     fOffset=sizeof(AliRawDataHeader);
201     fPosition=fOffset;
202     if ((result=IsSelected())) break;
203   }
204   firstParentCycle&=!fbHaveHLTData; // true if it just changed from true to false
205   while (!result) {
206     if (firstParentCycle) {
207       firstParentCycle=kFALSE;
208       // reset and set the selection back to the original one
209       fpParentReader->Reset();
210       fpParentReader->SelectEquipment(fSelectEquipmentType, fSelectMinEquipmentId, fSelectMaxEquipmentId);
211     }
212
213     if (!(result=fpParentReader->ReadHeader())) {
214       fHeader=NULL;
215       break;
216     }
217     fHeader=const_cast<AliRawDataHeader*>(fpParentReader->GetDataHeader());
218     fDataSize=fpParentReader->GetDataSize();
219     fPosition=0;
220     fpData=NULL;
221
222     // filter out all equipment ids which should be taken from the HLT stream
223     int id=fpParentReader->GetEquipmentId();
224     if ((result=!IsHLTInput(id))) break;
225   }
226   return result;
227 }
228
229 Bool_t   AliRawReaderHLT::ReadNextData(UChar_t*& data)
230 {
231   // see header file for class documentation
232   return ReadNextData(data, kTRUE);
233 }
234
235 Bool_t   AliRawReaderHLT::ReadNextData(UChar_t*& data, Bool_t readHeader)
236 {
237   // see header file for class documentation
238
239   // this function is the backbone of the ReadNext functions, it gets the
240   // whole data block either from the HLT stream or the parent raw reader.
241   // Each call of ReadNextData directly jumps to the next data set.
242   Bool_t result=kTRUE;
243
244   // read new header if data already read
245   if (fPosition<fDataSize || (result=(readHeader && ReadHeader()))) {
246     if (fbHaveHLTData && fpHLTOUT!=NULL) {
247       // all internal data variables set
248       result=kTRUE;
249       data=const_cast<AliHLTUInt8_t*>(fpData+sizeof(AliRawDataHeader));
250       // fpData includes the CDH, set offset behind CDH
251       fOffset=sizeof(AliRawDataHeader);
252     } else {
253       // no data in the HLT stream, read real data
254       //AliInfo(Form("read from parent reader: min=%d max=%d", fSelectMinEquipmentId, fSelectMaxEquipmentId));
255
256       // read data
257       result=fpParentReader->ReadNextData(data);
258       if (result) {
259         fpData=data;
260         fDataSize=fpParentReader->GetDataSize();
261         // fpData is without CDH
262         fOffset=0;
263       } else {
264         fpData=NULL;
265         fDataSize=0;
266       }
267
268       fEquipmentId=-1;
269     }
270     fPosition=fDataSize;
271   }
272   return result;
273 }
274
275 Bool_t   AliRawReaderHLT::ReadNextInt(UInt_t& data)
276 {
277   // see header file for class documentation
278   int iCopy=sizeof(UInt_t);
279   UChar_t* dummy=NULL;
280   do {
281     if (fpData && (fDataSize-fOffset)>=iCopy) {
282       data=*reinterpret_cast<const UInt_t*>(fpData+fOffset);
283       fOffset+=iCopy;
284       return kTRUE;
285     }
286   } while (ReadNextData(dummy, kTRUE));
287   return kFALSE;
288 }
289
290 Bool_t   AliRawReaderHLT::ReadNextShort(UShort_t& data)
291 {
292   // see header file for class documentation
293   int iCopy=sizeof(UShort_t);
294   UChar_t* dummy=NULL;
295   do {
296     if (fpData && (fDataSize-fOffset)>=iCopy) {
297       data=*reinterpret_cast<const UShort_t*>(fpData+fOffset);
298       fOffset+=iCopy;
299       return kTRUE;
300     }
301   } while (ReadNextData(dummy, kTRUE));
302   return kFALSE;
303 }
304
305 Bool_t   AliRawReaderHLT::ReadNextChar(UChar_t& data)
306 {
307   // see header file for class documentation
308   int iCopy=sizeof(UChar_t);
309   UChar_t* dummy=NULL;
310   do {
311     if (fpData && (fDataSize-fOffset)>=iCopy) {
312       data=*reinterpret_cast<const UChar_t*>(fpData+fOffset);
313       fOffset+=iCopy;
314       return kTRUE;
315     }
316   } while (ReadNextData(dummy, kTRUE));
317   return kFALSE;
318 }
319
320 Bool_t   AliRawReaderHLT::ReadNext(UChar_t* data, Int_t size)
321 {
322   // see header file for class documentation
323   UChar_t* dummy=NULL;
324   do {
325     if (fpData && (fDataSize-fOffset)>=size) {
326       // copy remaining data
327       int iCopy=fDataSize-fOffset;
328       if (iCopy>size) iCopy=size;
329       memcpy(data, fpData+fOffset, iCopy);
330       fOffset+=iCopy;
331       return kTRUE;
332     }
333     // By convention, the ReadNextData function stays in the
334     // current block and does not switch to the next one
335     // automatically -> kFALSE
336   } while (ReadNextData(dummy, kFALSE));
337   return kFALSE;
338 }
339
340 Bool_t   AliRawReaderHLT::Reset()
341 {
342   // see header file for class documentation
343   ReleaseHLTData(false/* keep HLTOUT instance */);
344   Bool_t result=fpParentReader->Reset();
345   fEquipmentId=-1;
346
347   // check if redirection is enabled for at least one detector in the selected range
348   fbHaveHLTData=EvaluateSelection();
349
350   // start reading HLTOUT data blocks from the beginning
351   fbReadFirst=true;
352
353   return result;
354 }
355
356 Bool_t   AliRawReaderHLT::NextEvent()
357 {
358   // see header file for class documentation
359
360   ReleaseHLTData();
361
362   Bool_t result=fpParentReader->NextEvent();
363   if (result) {
364     fEventNumber++;
365     Reset();
366   }
367   return result;
368 }
369
370 Bool_t   AliRawReaderHLT::RewindEvents()
371 {
372   // see header file for class documentation
373   fEventNumber=-1;
374   Reset();
375   return fpParentReader->RewindEvents();
376 }
377
378 void AliRawReaderHLT::Select(Int_t detectorID, Int_t minDDLID, Int_t maxDDLID)
379 {
380   // see header file for class documentation
381   AliRawReader::Select(detectorID, minDDLID, maxDDLID);
382   fpParentReader->Select(detectorID, minDDLID, maxDDLID);
383   fbHaveHLTData=EvaluateSelection();
384 }
385
386 // most likely we do not need this method since the base class directly forwards
387 // to this method
388 // void AliRawReaderHLT::Select(const char *detectorName, Int_t minDDLID, Int_t maxDDLID)
389 // {
390 //   AliInfo(Form("detectorName=%s, minDDLID=%d, maxDDLID=%d", detectorName, minDDLID, maxDDLID));
391 //   AliRawReader::Select(detectorName, minDDLID, maxDDLID);
392 //   fpParentReader->Select(detectorName, minDDLID, maxDDLID);
393 // }
394
395 void AliRawReaderHLT::SelectEquipment(Int_t equipmentType, Int_t minEquipmentId, Int_t maxEquipmentId)
396 {
397   // see header file for class documentation
398
399   //AliInfo(Form("equipmentType=%d, minEquipmentId=%d, maxEquipmentId=%d", equipmentType, minEquipmentId, maxEquipmentId));
400   AliRawReader::SelectEquipment(equipmentType, minEquipmentId, maxEquipmentId);
401   fpParentReader->SelectEquipment(equipmentType, minEquipmentId, maxEquipmentId);
402   fbHaveHLTData=EvaluateSelection();
403 }
404
405 void AliRawReaderHLT::SkipInvalid(Bool_t skip)
406 {
407   // see header file for class documentation
408
409   AliRawReader::SkipInvalid(skip);
410   fpParentReader->SkipInvalid(skip);
411 }
412
413 /*
414 void AliRawReaderHLT::SelectEvents(Int_t type)
415 {
416   // see header file for class documentation
417
418   //AliInfo(Form("type=%d", type));
419   AliRawReader::SelectEvents(type);
420   fpParentReader->SelectEvents(type);
421 }
422 */
423
424 int AliRawReaderHLT::ScanOptions(const char* options)
425 {
426   // see header file for class documentation
427   int iResult=0;
428   TString optString(options);
429   TString argument;
430   TString parameter;
431   TString detectors;
432   TObjArray* pTokens=optString.Tokenize(" ");
433   if (pTokens) {
434     int iEntries=pTokens->GetEntries();
435     for (int i =0; i<iEntries; i++) {
436       argument=((TObjString*)pTokens->At(i))->GetString();
437       // first scan all the other options
438       // no other options for the moment
439
440       // it must be a detector name
441       int detId=AliDAQ::DetectorID(argument.Data());
442       if (detId>=0) {
443         fDetectors.push_back(detId);
444         if (!detectors.IsNull()) detectors+=" ";
445         detectors+=argument;
446       } else {
447         if (!fSystemOptions.IsNull()) fSystemOptions+=" ";
448         fSystemOptions+=argument;
449       }
450     }
451     delete pTokens;
452   }
453
454   if (iResult>=0 && !detectors.IsNull()) {
455     AliInfo(Form("running reconstruction from HLT data: %s", detectors.Data()));
456   }
457   return iResult;
458 }
459
460 Bool_t   AliRawReaderHLT::ReadNextHLTData()
461 {
462   // see header file for class documentation
463   bool result=kTRUE;
464   if (fbReadFirst || !fpHLTOUT) {
465     if (!fpHLTOUT) {
466     fpHLTOUT=new AliHLTOUTRawReader(fpParentReader);
467     if ((result=(fpHLTOUT!=NULL))) {
468       if (!fpPluginBase) {
469         AliFatal("internal data error: can not get AliHLTSystem instance from plugin");
470         return false;
471       }
472       AliHLTSystem* pSystem=fpPluginBase->GetInstance();
473       if (pSystem) {
474         pSystem->ScanOptions(fSystemOptions.Data());
475       }
476       if ((result=(fpHLTOUT->Init())>=0)) {
477       }
478     }
479     }
480     if (result) {
481       result=fpHLTOUT->SelectFirstDataBlock(kAliHLTAnyDataType, kAliHLTVoidDataSpec,
482                                             AliHLTModuleAgent::kRawReader)>=0;
483     }
484     fbReadFirst=false;
485   } else {
486     // first release the data buffer
487     ReleaseHLTData(false /* keep HLTOUT instance */);
488     result=fpHLTOUT->SelectNextDataBlock()>=0;
489   }
490   if (result) {
491     AliHLTComponentDataType dt=kAliHLTVoidDataType;
492     AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
493     fpHLTOUT->GetDataBlockDescription(dt, spec);
494     AliHLTUInt32_t size=0;
495     AliHLTOUTHandler* pHandler=fpHLTOUT->GetHandler();
496     if (pHandler) {
497       if (dynamic_cast<AliHLTOUTHandlerEquId*>(pHandler)!=NULL) {
498         AliHLTOUT::AliHLTOUTSelectionGuard g(fpHLTOUT);
499         fEquipmentId=pHandler->ProcessData(fpHLTOUT);
500         fpData=NULL;
501         fDataSize=pHandler->GetProcessedData(fpData);
502         if (!fpData) {
503           result=fpHLTOUT->GetDataBuffer(fpData, size)>=0;
504           fpDataHandler=NULL;
505           AliDebug(AliLog::kDebug, Form("forward data block from HLTOUT stream to equipment %d", fEquipmentId));
506           fDataSize=(int)size;
507         } else {
508           // remember the current handler in order to properly release the data buffer
509           fpDataHandler=pHandler;
510           AliDebug(AliLog::kDebug, Form("forward decoded data block provided by handler to equipment %d", fEquipmentId));
511         }
512         return kTRUE;
513       } else {
514         AliError(Form("handler is not of type AliHLTOUTHandlerEquId for block %x data type %s spec %#x; data block skipped",
515                       fpHLTOUT->GetDataBlockIndex(), AliHLTComponent::DataType2Text(dt).c_str(), spec));
516       }
517     } else {
518       AliWarning(Form("no data handler found for block %x data type %s spec %#x; data block skipped",
519                       fpHLTOUT->GetDataBlockIndex(), AliHLTComponent::DataType2Text(dt).c_str(), spec));
520     }
521   } else {
522     ReleaseHLTData(false /* keep HLTOUT instance */);
523   }
524   return kFALSE;
525 }
526
527 Bool_t AliRawReaderHLT::IsHLTInput(int ddlid)
528 {
529   // see header file for class documentation
530   vector<int>::iterator detector=fDetectors.begin();
531   for (; detector!=fDetectors.end(); detector++) {
532     int ddlOffset=AliDAQ::DdlIDOffset(*detector);
533     int nofDDLs=AliDAQ::NumberOfDdls(*detector);
534     if (ddlid>=ddlOffset && ddlid<ddlOffset+nofDDLs)
535       return kTRUE;
536   }
537   return kFALSE;
538 }
539
540 int AliRawReaderHLT::ReleaseHLTData(bool bReleaseHLTOUT)
541 {
542   // see header file for class documentation
543   if (fpHLTOUT) {
544     if (fpDataHandler) fpDataHandler->ReleaseProcessedData(fpData, fDataSize);
545     else fpHLTOUT->ReleaseDataBuffer(fpData);
546     fpDataHandler=NULL;
547     if (bReleaseHLTOUT) {
548       delete fpHLTOUT;
549       fpHLTOUT=NULL;
550     }
551   }
552
553   fpData=NULL;
554   fDataSize=0;
555   fOffset=0;
556   fPosition=0;
557   fEquipmentId=-1;
558
559   return 0;
560 }
561
562 Bool_t AliRawReaderHLT::EvaluateSelection()
563 {
564   // see header file for class documentation
565   Bool_t bHaveHLTData=kFALSE;
566   if ((bHaveHLTData=(fDetectors.size())>0)) {
567     vector<int>::iterator detector=fDetectors.begin();
568     for (; detector!=fDetectors.end(); detector++) {
569       int ddlOffset=AliDAQ::DdlIDOffset(*detector);
570       int nofDDLs=AliDAQ::NumberOfDdls(*detector);
571       if ((fSelectMinEquipmentId<0 || fSelectMinEquipmentId<ddlOffset+nofDDLs) &&
572           (fSelectMaxEquipmentId<0 || fSelectMaxEquipmentId>=ddlOffset))
573         break;
574     }
575     bHaveHLTData=detector!=fDetectors.end();
576   }
577   return bHaveHLTData;
578 }
579
580 AliRawReader* AliRawReaderHLTCreateInstance(AliRawReader* pParentReader, const char* options)
581 {
582   // see header file for class documentation
583   if (!pParentReader) return NULL;
584   return new AliRawReaderHLT(pParentReader, options);
585 }