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