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