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