5b9177651dc66db1abd5a800c6f199a79a38b1cc
[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 "AliLog.h"
37 #include "AliDAQ.h"            // RAW, for detector names and equipment ids
38 #include "TObjString.h"
39 #include <cassert>
40
41 /** ROOT macro for the implementation of ROOT specific class methods */
42 ClassImp(AliRawReaderHLT)
43
44 AliRawReaderHLT::AliRawReaderHLT(AliRawReader* pRawreader, const char* options)
45   :
46   AliRawReader(),
47   fpParentReader(pRawreader),
48   fOptions(),
49   fpData(NULL),
50   fDataSize(0),
51   fOffset(0),
52   fEquipmentId(-1),
53   fbHaveHLTData(false),
54   fDetectors(),
55   fpHLTOUT(NULL),
56   fpDataHandler(NULL)
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   if (fpHLTOUT) {
71     if (fpDataHandler) fpDataHandler->ReleaseProcessedData(fpData, fDataSize);
72     else fpHLTOUT->ReleaseDataBuffer(fpData);
73     fpDataHandler=NULL;
74     delete fpHLTOUT;
75     fpHLTOUT=NULL;
76   }
77 }
78
79 UInt_t AliRawReaderHLT::GetType() const
80 {
81   // see header file for class documentation
82   return fpParentReader->GetType();
83 }
84
85 UInt_t AliRawReaderHLT::GetRunNumber() const
86 {
87   // see header file for class documentation
88   return fpParentReader->GetRunNumber();
89 }
90
91 const UInt_t* AliRawReaderHLT::GetEventId() const
92 {
93   // see header file for class documentation
94   return fpParentReader->GetEventId();
95 }
96
97 const UInt_t* AliRawReaderHLT::GetTriggerPattern() const
98 {
99   // see header file for class documentation
100   return fpParentReader->GetTriggerPattern();
101 }
102
103 const UInt_t* AliRawReaderHLT::GetDetectorPattern() const
104 {
105   // see header file for class documentation
106   return fpParentReader->GetDetectorPattern();
107 }
108
109 const UInt_t* AliRawReaderHLT::GetAttributes() const
110 {
111   // see header file for class documentation
112   return fpParentReader->GetAttributes();
113 }
114
115 const UInt_t* AliRawReaderHLT::GetSubEventAttributes() const
116 {
117   // see header file for class documentation
118   return fpParentReader->GetSubEventAttributes();
119 }
120
121 UInt_t AliRawReaderHLT::GetLDCId() const
122 {
123   // see header file for class documentation
124   return fpParentReader->GetLDCId();
125 }
126
127 UInt_t AliRawReaderHLT::GetGDCId() const
128 {
129   // see header file for class documentation
130   return fpParentReader->GetGDCId();
131 }
132
133 UInt_t AliRawReaderHLT::GetTimestamp() const
134 {
135   // see header file for class documentation
136   return fpParentReader->GetTimestamp();
137 }
138
139 const UInt_t* AliRawReaderHLT::GetEquipmentAttributes() const
140 {
141   // see header file for class documentation
142   return fpParentReader->GetEquipmentAttributes();
143 }
144
145 Int_t    AliRawReaderHLT::GetEquipmentElementSize() const
146 {
147   // see header file for class documentation
148   // don't know what it really means, bu the AliRawReaderFile
149   // just sets it to 0
150   // do the same if we have a valid equipment data set from
151   // the HLT stream
152   if (fEquipmentId>=0) return 0;
153   return fpParentReader->GetEquipmentElementSize();
154 }
155
156 Int_t    AliRawReaderHLT::GetEquipmentHeaderSize() const
157 {
158   // see header file for class documentation
159
160   // equipment header means the additional data header?
161   // if we have a valid equipment data set from the HLT stream
162   // there is no additional header
163   if (fEquipmentId>=0) return 0;
164   return fpParentReader->GetEquipmentHeaderSize();
165 }
166
167 Int_t    AliRawReaderHLT::GetEquipmentSize() const
168 {
169   // see header file for class documentation
170   if (fEquipmentId>=0) return fDataSize+sizeof(AliRawDataHeader);
171   return fpParentReader->GetEquipmentSize();
172 }
173
174 Int_t    AliRawReaderHLT::GetEquipmentType() const
175 {
176   // see header file for class documentation
177   return fpParentReader->GetEquipmentType();
178 }
179
180 Int_t    AliRawReaderHLT::GetEquipmentId() const
181 {
182   // see header file for class documentation
183   Int_t id=-1;
184   if (fEquipmentId>=0) id=fEquipmentId;
185   else id=fpParentReader->GetEquipmentId();
186   return id;
187 }
188
189 Bool_t   AliRawReaderHLT::ReadHeader()
190 {
191   // see header file for class documentation
192   Bool_t result=fpParentReader->ReadHeader();
193   fHeader=const_cast<AliRawDataHeader*>(fpParentReader->GetDataHeader());
194   return result;
195 }
196
197 Bool_t   AliRawReaderHLT::ReadNextData(UChar_t*& data)
198 {
199   // see header file for class documentation
200
201   // this function is the backbone of the ReadNext functions, it gets the
202   // whole data block either from the HLT stream or the parent raw reader.
203   // Each call of ReadNextData directly jumps to the next data set.
204   Bool_t result=kFALSE;
205   if (fbHaveHLTData&=ReadNextHLTData()) {
206     // all internal data variables set
207     assert(fpData!=NULL);
208     data=const_cast<AliHLTUInt8_t*>(fpData);
209     result=kTRUE;
210   }
211   if (!result) {
212     // no data in the HLT stream, read real data
213     //AliInfo(Form("read from parent reader: min=%d max=%d", fSelectMinEquipmentId, fSelectMaxEquipmentId));
214
215     // first set the selection back to the original one
216     fpParentReader->SelectEquipment(fSelectEquipmentType, fSelectMinEquipmentId, fSelectMaxEquipmentId);
217
218     // read data
219     while (result=fpParentReader->ReadNextData(data)) {
220       // continue if the Equipment Id is supposed to be replaced by the HLT stream
221       // in that case we do not want to read it from the parent raw reader
222       if (!IsHLTInput(fpParentReader->GetEquipmentId())) break;
223     }
224
225     // set the header of this reader from the parent reader.
226     // This is necessary because of a few base class methods working directly
227     // on the header
228     fHeader=const_cast<AliRawDataHeader*>(fpParentReader->GetDataHeader());
229     if (result) {
230       fpData=data;
231       fDataSize=fpParentReader->GetDataSize();
232     } else {
233       fpData=NULL;
234       fDataSize=0;
235     }
236     fOffset=0;
237     fEquipmentId=-1;
238   }
239   return result;
240 }
241
242 Bool_t   AliRawReaderHLT::ReadNextInt(UInt_t& data)
243 {
244   // see header file for class documentation
245   int iCopy=sizeof(UInt_t);
246   UChar_t* dummy=NULL;
247   do {
248     if (fpData && (fDataSize-fOffset)>=iCopy) {
249       data=*reinterpret_cast<const UInt_t*>(fpData+fOffset);
250       fOffset+=iCopy;
251       return kTRUE;
252     }
253   } while (ReadNextData(dummy));
254   return kFALSE;
255 }
256
257 Bool_t   AliRawReaderHLT::ReadNextShort(UShort_t& data)
258 {
259   // see header file for class documentation
260   int iCopy=sizeof(UShort_t);
261   UChar_t* dummy=NULL;
262   do {
263     if (fpData && (fDataSize-fOffset)>=iCopy) {
264       data=*reinterpret_cast<const UShort_t*>(fpData+fOffset);
265       fOffset+=iCopy;
266       return kTRUE;
267     }
268   } while (ReadNextData(dummy));
269   return kFALSE;
270 }
271
272 Bool_t   AliRawReaderHLT::ReadNextChar(UChar_t& data)
273 {
274   // see header file for class documentation
275   int iCopy=sizeof(UChar_t);
276   UChar_t* dummy=NULL;
277   do {
278     if (fpData && (fDataSize-fOffset)>=iCopy) {
279       data=*reinterpret_cast<const UChar_t*>(fpData+fOffset);
280       fOffset+=iCopy;
281       return kTRUE;
282     }
283   } while (ReadNextData(dummy));
284   return kFALSE;
285 }
286
287 Bool_t   AliRawReaderHLT::ReadNext(UChar_t* data, Int_t size)
288 {
289   // see header file for class documentation
290   UChar_t* dummy=NULL;
291   do {
292     if (fpData && (fDataSize-fOffset)>=size) {
293       // copy remaining data
294       int iCopy=fDataSize-fOffset;
295       if (iCopy>size) iCopy=size;
296       memcpy(data, fpData+fOffset, iCopy);
297       fOffset+=iCopy;
298       return kTRUE;
299     }
300   } while (ReadNextData(dummy));
301   return kFALSE;
302 }
303
304 Bool_t   AliRawReaderHLT::Reset()
305 {
306   // see header file for class documentation
307   Bool_t result=fpParentReader->Reset();
308   fpData=NULL;
309   fDataSize=0;
310   fOffset=0;
311   fEquipmentId=-1;
312   if (fbHaveHLTData=(fDetectors.size()>0)) {
313     vector<int>::iterator detector=fDetectors.begin();
314     for (; detector!=fDetectors.end(); detector++) {
315       int ddlOffset=AliDAQ::DdlIDOffset(*detector);
316       int nofDDLs=AliDAQ::NumberOfDdls(*detector);
317       if ((fSelectMinEquipmentId>=0 && fSelectMinEquipmentId>ddlOffset+nofDDLs) ||
318           (fSelectMinEquipmentId>=0 && fSelectMaxEquipmentId<ddlOffset))
319         continue;
320       break;
321     }
322     fbHaveHLTData=detector!=fDetectors.end();
323   }
324
325   if (fpHLTOUT) {
326     if (fpDataHandler) fpDataHandler->ReleaseProcessedData(fpData, fDataSize);
327     else fpHLTOUT->ReleaseDataBuffer(fpData);
328     fpDataHandler=NULL;
329     delete fpHLTOUT;
330     fpHLTOUT=NULL;
331   }
332
333   return result;
334 }
335
336 Bool_t   AliRawReaderHLT::NextEvent()
337 {
338   // see header file for class documentation
339   Bool_t result=fpParentReader->NextEvent();
340   if (result) {
341     fEventNumber++;
342     Reset();
343   }
344   return result;
345 }
346
347 Bool_t   AliRawReaderHLT::RewindEvents()
348 {
349   // see header file for class documentation
350   fEventNumber=-1;
351   Reset();
352   return fpParentReader->RewindEvents();
353 }
354
355 void AliRawReaderHLT::Select(Int_t detectorID, Int_t minDDLID, Int_t maxDDLID)
356 {
357   // see header file for class documentation
358   AliRawReader::Select(detectorID, minDDLID, maxDDLID);
359   fpParentReader->Select(detectorID, minDDLID, maxDDLID);
360 }
361
362 // most likely we do not need this method since the base class directly forwards
363 // to this method
364 // void AliRawReaderHLT::Select(const char *detectorName, Int_t minDDLID, Int_t maxDDLID)
365 // {
366 //   AliInfo(Form("detectorName=%s, minDDLID=%d, maxDDLID=%d", detectorName, minDDLID, maxDDLID));
367 //   AliRawReader::Select(detectorName, minDDLID, maxDDLID);
368 //   fpParentReader->Select(detectorName, minDDLID, maxDDLID);
369 // }
370
371 void AliRawReaderHLT::SelectEquipment(Int_t equipmentType, Int_t minEquipmentId, Int_t maxEquipmentId)
372 {
373   // see header file for class documentation
374
375   //AliInfo(Form("equipmentType=%d, minEquipmentId=%d, maxEquipmentId=%d", equipmentType, minEquipmentId, maxEquipmentId));
376   AliRawReader::Select(equipmentType, minEquipmentId, maxEquipmentId);
377   fpParentReader->Select(equipmentType, minEquipmentId, maxEquipmentId);
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       }
417     }
418     delete pTokens;
419   }
420
421   return iResult;
422 }
423
424 Bool_t   AliRawReaderHLT::ReadNextHLTData()
425 {
426   // see header file for class documentation
427   bool result=kTRUE;
428   if (!fpHLTOUT) {
429     fpHLTOUT=new AliHLTOUTRawReader(fpParentReader);
430     if (result=(fpHLTOUT!=NULL)) {
431       if (result=(fpHLTOUT->Init()>=0)) {
432         result=fpHLTOUT->SelectFirstDataBlock(kAliHLTAnyDataType, kAliHLTVoidDataSpec,
433                                               AliHLTModuleAgent::kRawReader)>=0;
434       }
435     }
436   } else {
437     // first release the data buffer
438     if (fpDataHandler) fpDataHandler->ReleaseProcessedData(fpData, fDataSize);
439     else fpHLTOUT->ReleaseDataBuffer(fpData);
440     fpDataHandler=NULL;
441     if (!(result=fpHLTOUT->SelectNextDataBlock()>=0)) {
442       delete fpHLTOUT;
443       fpHLTOUT=NULL;
444     }
445   }
446   if (result) {
447     AliHLTComponentDataType dt=kAliHLTVoidDataType;
448     AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
449     fpHLTOUT->GetDataBlockDescription(dt, spec);
450     AliHLTUInt32_t size=0;
451     AliHLTOUTHandler* pHandler=fpHLTOUT->GetHandler();
452     if (pHandler) {
453       if (dynamic_cast<AliHLTOUTHandlerEquId*>(pHandler)!=NULL) {
454         AliHLTOUT::AliHLTOUTLockGuard g(fpHLTOUT);
455         fEquipmentId=pHandler->ProcessData(fpHLTOUT);
456         fpData=NULL;
457         fDataSize=pHandler->GetProcessedData(fpData);
458         if (!fpData) {
459           result=fpHLTOUT->GetDataBuffer(fpData, size)>=0;
460           AliDebug(AliLog::kDebug, Form("forward data block from HLTOUT stream to equipment %d", fEquipmentId));
461           fDataSize=(int)size;
462         } else {
463           // remember the current handler in order to properly release the data buffer
464           fpDataHandler=pHandler;
465           AliDebug(AliLog::kDebug, Form("forward decoded data block provided by handler to equipment %d", fEquipmentId));
466         }
467       } else {
468         AliError(Form("handler is not of type AliHLTOUTHandlerEquId for block %x data type %s spec %#x; data block skipped",
469                       fpHLTOUT->GetDataBlockIndex(), AliHLTComponent::DataType2Text(dt).c_str(), spec));
470       }
471     } else {
472       AliWarning(Form("no data handler found for block %x data type %s spec %#x; data block skipped",
473                       fpHLTOUT->GetDataBlockIndex(), AliHLTComponent::DataType2Text(dt).c_str(), spec));
474     }
475   } else {
476     fpData=NULL;
477     fDataSize=0;
478     fOffset=0;
479     fEquipmentId=-1;
480   }
481   return false;
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 AliRawReader* AliRawReaderHLTCreateInstance(AliRawReader* pParentReader, const char* options)
498 {
499   // see header file for class documentation
500   if (!pParentReader) return NULL;
501   return new AliRawReaderHLT(pParentReader, options);
502 }