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