]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/util/AliHLTRawReaderPublisherComponent.cxx
Adding warning if no data header was found in HLTRawReaderPublisher
[u/mrichter/AliRoot.git] / HLT / BASE / util / AliHLTRawReaderPublisherComponent.cxx
1 // $Id$
2
3 ///**************************************************************************
4 ///* This file is property of and copyright by the                          * 
5 ///* ALICE Experiment at CERN, All rights reserved.                         *
6 ///*                                                                        *
7 ///* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8 ///*                                                                        *
9 ///* Permission to use, copy, modify and distribute this software and its   *
10 ///* documentation strictly for non-commercial purposes is hereby granted   *
11 ///* without fee, provided that the above copyright notice appears in all   *
12 ///* copies and that both the copyright notice and this permission notice   *
13 ///* appear in the supporting documentation. The authors make no claims     *
14 ///* about the suitability of this software for any purpose. It is          *
15 ///* provided "as is" without express or implied warranty.                  *
16 ///**************************************************************************/
17
18 /// @file   AliHLTRawReaderPublisherComponent.cxx
19 /// @author Matthias Richter
20 /// @date   
21 /// @brief  Publisher component for raw data blocks through the AliRawReader
22 ///         of the offline environment
23
24 #include "AliHLTRawReaderPublisherComponent.h"
25 #include "AliRawReader.h"
26 #include "AliDAQ.h"
27 #include "AliLog.h"
28 #include "AliHLTCDHWrapper.h" 
29 #include <cerrno>
30 #include <cassert>
31 #include <list>
32
33 /** ROOT macro for the implementation of ROOT specific class methods */
34 ClassImp(AliHLTRawReaderPublisherComponent)
35
36 AliHLTRawReaderPublisherComponent::AliHLTRawReaderPublisherComponent()
37   :
38   fMaxSize(5000000),
39   fDetector(),
40   fMinEquId(-1),
41   fMaxEquId(-1),
42   fVerbosity(0),
43   fDataType(kAliHLTVoidDataType),
44   fSpecification(kAliHLTVoidDataSpec),
45   fSkipEmpty(kFALSE)
46 {
47   // constructor
48 }
49
50 AliHLTRawReaderPublisherComponent::~AliHLTRawReaderPublisherComponent()
51 {
52   // destructor
53 }
54
55 const char* AliHLTRawReaderPublisherComponent::GetComponentID()
56 {
57   /// inherited from AliHLTComponent: id of the component
58   return "AliRawReaderPublisher";
59 }
60
61 AliHLTComponentDataType AliHLTRawReaderPublisherComponent::GetOutputDataType()
62 {
63   /// inherited from AliHLTComponent: output data type of the component.
64   return fDataType;
65 }
66
67 void AliHLTRawReaderPublisherComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
68 {
69   /// inherited from AliHLTComponent: output data size estimator
70   constBase=fMaxSize;
71   inputMultiplier=1;
72 }
73
74 AliHLTComponent* AliHLTRawReaderPublisherComponent::Spawn()
75 {
76   /// inherited from AliHLTComponent: spawn function.
77   return new AliHLTRawReaderPublisherComponent;
78 }
79
80 int AliHLTRawReaderPublisherComponent::DoInit( int argc, const char** argv )
81 {
82   /// inherited from AliHLTComponent: component initialisation and argument scan.
83   int iResult=0;
84
85   // scan arguments
86   if (argc && (iResult = ConfigureFromArgumentString(argc, argv)) < 0)
87     return iResult;
88
89   if (!fDetector.IsNull()) {
90     int ddloffset=-1;
91     int ddlcount=-1;
92     if ((ddloffset=AliDAQ::DdlIDOffset(fDetector))<0 || 
93         (ddlcount=AliDAQ::NumberOfDdls(fDetector))<0) {
94       return -EINVAL;
95     }
96     if (fMinEquId<0) fMinEquId=ddloffset;
97     else fMinEquId+=ddloffset;
98
99     if (fMaxEquId<0 || fMaxEquId>ddlcount) fMaxEquId=ddloffset+ddlcount-1;
100     else fMaxEquId+=ddloffset;
101   }
102
103   if (fMinEquId>fMaxEquId) fMaxEquId=fMinEquId;
104
105   if (fMinEquId<0) {
106     AliErrorStream() << "equipment id required, use \'-equipmentid\' or \'-detector\' option" << endl;
107     return -EINVAL;
108   }
109
110   AliHLTUInt32_t dummy;
111   if (fMinEquId!=fMaxEquId && GetSpecificationFromEquipmentId(0, dummy)==-ENOSYS) {
112     AliWarningStream() << "publication of multiple equipment ids needs implementation of a child and function GetSpecificationFromEquipmentId to set correct specifications" << endl;
113     //return -EINVAL;
114   }
115
116   if (GetRawReader()!=NULL) {
117   } else {
118     AliErrorStream() << "RawReader instance needed" << endl;
119     return -EINVAL;
120   }
121
122   return iResult;
123 }
124
125 int AliHLTRawReaderPublisherComponent::DoDeinit()
126 {
127   /// inherited from AliHLTComponent: component cleanup
128   int iResult=0;
129   return iResult;
130 }
131
132 int AliHLTRawReaderPublisherComponent::ScanConfigurationArgument(int argc, const char** argv)
133 {
134   /// inherited from AliHLTComponent: argument scan
135   if (argc<1) return 0;
136   int bMissingParam=0;
137   int i=0;
138   TString argument=argv[i];
139
140   do {
141     // -detector
142     if (argument.CompareTo("-detector")==0) {
143       if ((bMissingParam=(++i>=argc))) break;
144       fDetector=argv[i];
145       return 2;
146
147       // -equipmentid, -minid
148     } else if (argument.CompareTo("-equipmentid")==0 ||
149                argument.CompareTo("-minid")==0) {
150       if ((bMissingParam=(++i>=argc))) break;
151       TString parameter(argv[i]);
152       parameter.Remove(TString::kLeading, ' '); // remove all blanks
153       if (parameter.IsDigit()) {
154         fMinEquId=(AliHLTUInt32_t)parameter.Atoi();
155         return 2;
156       } else {
157         HLTError("wrong parameter for argument %s, number expected", argument.Data());
158         return -EINVAL;
159       }
160
161       // -maxid
162     } else if (argument.CompareTo("-maxid")==0) {
163       if ((bMissingParam=(++i>=argc))) break;
164       TString parameter(argv[i]);
165       parameter.Remove(TString::kLeading, ' '); // remove all blanks
166       if (parameter.IsDigit()) {
167         fMaxEquId=(AliHLTUInt32_t)parameter.Atoi();
168         return 2;
169       } else {
170         HLTError("wrong parameter for argument %s, number expected", argument.Data());
171         return -EINVAL;
172       }
173
174       // -verbose
175     } else if (argument.CompareTo("-verbose")==0) {
176       fVerbosity++;
177       return 1;
178
179       // -silent
180     } else if (argument.CompareTo("-silent")==0) {
181       fVerbosity=0;
182       return 1;
183
184       // -skipempty
185     } else if (argument.CompareTo("-skipempty")==0) {
186       fSkipEmpty=kTRUE;
187       return 1;
188
189       // -datatype
190     } else if (argument.CompareTo("-datatype")==0) {
191       if ((bMissingParam=(++i>=argc))) break;
192       memcpy(&fDataType.fID, argv[i], TMath::Min(kAliHLTComponentDataTypefIDsize, (Int_t)strlen(argv[i])));
193       if ((bMissingParam=(++i>=argc))) break;
194       memcpy(&fDataType.fOrigin, argv[i], TMath::Min(kAliHLTComponentDataTypefOriginSize, (Int_t)strlen(argv[i])));
195       return 3;
196
197       // -dataspec
198     } else if (argument.CompareTo("-dataspec")==0) {
199       if ((bMissingParam=(++i>=argc))) break;
200       TString parameter(argv[i]);
201       parameter.Remove(TString::kLeading, ' '); // remove all blanks
202       if (parameter.IsDigit()) {
203         fSpecification=(AliHLTUInt32_t)parameter.Atoi();
204       } else if (parameter.BeginsWith("0x") &&
205                  parameter.Replace(0,2,"",0).IsHex()) {
206         sscanf(parameter.Data(),"%x", &fSpecification);
207       } else {
208         HLTError("wrong parameter for argument %s, number expected", argument.Data());
209         return -EINVAL;
210       }
211       return 2;
212     }
213   } while (0); // using do-while only to have break available
214   if (bMissingParam) {
215     HLTError("missing parameter for argument %s", argument.Data());
216     return -EINVAL;
217   }
218
219   return -EPROTO;
220 }
221
222 int AliHLTRawReaderPublisherComponent::GetEvent(const AliHLTComponentEventData& /*evtData*/, 
223                                                 AliHLTComponentTriggerData& /*trigData*/, 
224                                                 AliHLTUInt8_t* outputPtr, 
225                                                 AliHLTUInt32_t& size, 
226                                                 vector<AliHLTComponentBlockData>& outputBlocks)
227 {
228   /// inherited from AliHLTDataSource: get the event
229   int iResult=0;
230   AliHLTUInt32_t capacity=size;
231   size=0;
232
233   // process data events only
234   if (!IsDataEvent()) return 0;
235
236   unsigned int offset=0;
237   assert(outputPtr!=NULL || size==0);
238   AliRawReader* pRawReader=GetRawReader();
239   if (pRawReader) {
240     pRawReader->Reset();
241     pRawReader->SelectEquipment(-1, fMinEquId, fMaxEquId);
242     if (fVerbosity>1) {
243       AliInfo(Form("get event from RawReader %p equipment id range [%d,%d]", pRawReader, fMinEquId, fMaxEquId));
244     } else {
245       AliDebug(0, Form("get event from RawReader %p equipment id range [%d,%d]", pRawReader, fMinEquId, fMaxEquId));
246     }
247     list<int> processedIds;
248     UChar_t headerVersion=0;
249     while (pRawReader->ReadHeader() && (iResult>=0 || iResult==-ENOSPC)) {
250       const AliRawDataHeader* pHeaderV2=pRawReader->GetDataHeader();
251       const AliRawDataHeaderV3* pHeaderV3=pRawReader->GetDataHeaderV3();
252       AliHLTCDHWrapper pHeader;
253       if(pHeaderV2) {
254         pHeader=pHeaderV2;
255       } else if (pHeaderV3) {
256         pHeader=pHeaderV3;
257       } else {
258         HLTError("can not get data header from RawReader, skipping data block ...");
259         continue;
260       }
261       // store header version for empty blocks later on
262       // any found header will suffice
263       headerVersion=pHeader.GetVersion();
264       unsigned int headerSize=pHeader.GetHeaderSize();
265       unsigned int readSize=pRawReader->GetDataSize()+headerSize;
266       int id=pRawReader->GetEquipmentId();
267       if (fMinEquId>id || fMaxEquId<id) {
268         AliError(Form("id %d returned from RawReader is outside range [%d,%d]", id, fMinEquId, fMaxEquId));
269         continue;
270       }
271       processedIds.push_back(id);
272       bool isSelected=IsSelected(id);
273       if (fVerbosity>0) {
274         AliInfo(Form("got header for id %d, size %d, %s", id, readSize, isSelected?"selected":"discarded"));
275       } else {
276         AliDebug(0, Form("got header for id %d, size %d", id, readSize));
277       }
278       if (!isSelected) continue;
279       if (readSize+offset<=capacity) {
280         memcpy(outputPtr+offset, pHeader.GetHeader(), headerSize);
281         if (readSize>headerSize) {
282           if (!pRawReader->ReadNext(outputPtr+offset+headerSize, readSize-headerSize)) {
283             AliError(Form("error reading %d bytes from RawReader %p", readSize-headerSize, pRawReader));
284             iResult=-ENODATA;
285             break;
286           }
287         }
288         AliHLTComponentBlockData bd;
289         FillBlockData( bd );
290         bd.fOffset = offset;
291         bd.fSize = readSize;
292         bd.fDataType = fDataType;
293         if (fSpecification == kAliHLTVoidDataSpec) {
294           GetSpecificationFromEquipmentId(id, bd.fSpecification);
295         } else {
296           bd.fSpecification=fSpecification;
297         }
298         outputBlocks.push_back( bd );
299       } else {
300         // we keep the loop going in order to collect the full size
301         fMaxSize=offset+readSize;
302         iResult=-ENOSPC;
303       }
304       offset+=readSize;
305     }
306     if (!fSkipEmpty && processedIds.size()!=size_t(fMaxEquId-fMinEquId+1)) {
307       // add further empty data blocks
308       AliHLTCDHWrapper header;
309       AliRawDataHeader headerV2;
310       AliRawDataHeaderV3 headerV3;
311       if(headerVersion==2){
312         headerV2.fSize=sizeof(AliRawDataHeader);
313         const UInt_t* triggermask=pRawReader->GetTriggerPattern();
314         if (triggermask) {
315           headerV2.fTriggerClassLow=triggermask[0];
316           headerV2.fROILowTriggerClassHigh=triggermask[1];
317         }
318         header=&headerV2;
319       } else { //assuming V3 even if no header at all was found above
320         if(! headerVersion){
321           AliWarning("No data header found! Creating dummy header for empty blocks assuming CDH v3.");
322         }
323         headerV3.fSize=sizeof(AliRawDataHeaderV3);
324         const UInt_t* triggermask=pRawReader->GetTriggerPattern();
325         if (triggermask) {
326           headerV3.fTriggerClassLow=triggermask[0];
327           headerV3.fTriggerClassesMiddleLow=triggermask[1] & 0x3FFFF;
328           headerV3.fTriggerClassesMiddleHigh= (triggermask[1]>>18) | (triggermask[2]<<14);
329           headerV3.fROILowTriggerClassHigh=(triggermask[2]>>18) | (triggermask[3]<<14);
330         }
331         header=&headerV3;
332       }
333       unsigned int headerSize=header.GetHeaderSize();
334       processedIds.sort();
335       list<int>::iterator curr=processedIds.begin();
336       for (int id=fMinEquId; id<=fMaxEquId; id++) {
337         if (curr!=processedIds.end() && *curr<=id) {
338           curr++;
339         } else {
340           if (headerSize<=capacity-offset) {
341             HLTInfo("add empty data block for equipment id %d", id);
342             memcpy(outputPtr+offset, header.GetHeader(), headerSize);
343             AliHLTComponentBlockData bd;
344             FillBlockData( bd );
345             bd.fOffset = offset;
346             bd.fSize = headerSize;
347             bd.fDataType = fDataType;
348             if (fSpecification == kAliHLTVoidDataSpec) {
349               GetSpecificationFromEquipmentId(id, bd.fSpecification);
350             } else {
351               bd.fSpecification=fSpecification;
352             }
353             outputBlocks.push_back( bd );
354           } else {
355             // we keep the loop going in order to collect the full size
356             fMaxSize=offset+headerSize;
357             iResult=-ENOSPC;
358           }
359           offset+=headerSize;
360         }
361       }
362     }
363     if (offset<=capacity) {
364       size=offset;
365     } else {
366       outputBlocks.clear();
367     }
368   } else {
369     AliErrorStream() << "RawReader uninitialized" << endl;
370     iResult=-EFAULT;
371   }
372   return iResult;
373 }
374
375 int AliHLTRawReaderPublisherComponent::GetSpecificationFromEquipmentId(int id, AliHLTUInt32_t& specification) const {
376   /// get the data specification from the equipment id
377   /// default method just returns the equipment id
378   return specification=id;
379 }