06af6f0c648af629c062820decaf55fd004bd887
[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 <cerrno>
29 #include <cassert>
30 #include <list>
31
32 /** ROOT macro for the implementation of ROOT specific class methods */
33 ClassImp(AliHLTRawReaderPublisherComponent)
34
35 AliHLTRawReaderPublisherComponent::AliHLTRawReaderPublisherComponent()
36   :
37   fMaxSize(5000000),
38   fDetector(),
39   fMinEquId(-1),
40   fMaxEquId(-1),
41   fVerbosity(0),
42   fDataType(kAliHLTVoidDataType),
43   fSpecification(kAliHLTVoidDataSpec),
44   fSkipEmpty(kFALSE)
45 {
46   // constructor
47 }
48
49 AliHLTRawReaderPublisherComponent::~AliHLTRawReaderPublisherComponent()
50 {
51   // destructor
52 }
53
54 const char* AliHLTRawReaderPublisherComponent::GetComponentID()
55 {
56   /// inherited from AliHLTComponent: id of the component
57   return "AliRawReaderPublisher";
58 }
59
60 AliHLTComponentDataType AliHLTRawReaderPublisherComponent::GetOutputDataType()
61 {
62   /// inherited from AliHLTComponent: output data type of the component.
63   return fDataType;
64 }
65
66 void AliHLTRawReaderPublisherComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
67 {
68   /// inherited from AliHLTComponent: output data size estimator
69   constBase=fMaxSize;
70   inputMultiplier=1;
71 }
72
73 AliHLTComponent* AliHLTRawReaderPublisherComponent::Spawn()
74 {
75   /// inherited from AliHLTComponent: spawn function.
76   return new AliHLTRawReaderPublisherComponent;
77 }
78
79 int AliHLTRawReaderPublisherComponent::DoInit( int argc, const char** argv )
80 {
81   /// inherited from AliHLTComponent: component initialisation and argument scan.
82   int iResult=0;
83
84   // scan arguments
85   if (argc && (iResult = ConfigureFromArgumentString(argc, argv)) < 0)
86     return iResult;
87
88   if (!fDetector.IsNull()) {
89     int ddloffset=-1;
90     int ddlcount=-1;
91     if ((ddloffset=AliDAQ::DdlIDOffset(fDetector))<0 || 
92         (ddlcount=AliDAQ::NumberOfDdls(fDetector))<0) {
93       return -EINVAL;
94     }
95     if (fMinEquId<0) fMinEquId=ddloffset;
96     else fMinEquId+=ddloffset;
97
98     if (fMaxEquId<0 || fMaxEquId>ddlcount) fMaxEquId=ddloffset+ddlcount-1;
99     else fMaxEquId+=ddloffset;
100   }
101
102   if (fMinEquId>fMaxEquId) fMaxEquId=fMinEquId;
103
104   if (fMinEquId<0) {
105     AliErrorStream() << "equipment id required, use \'-equipmentid\' or \'-detector\' option" << endl;
106     return -EINVAL;
107   }
108
109   AliHLTUInt32_t dummy;
110   if (fMinEquId!=fMaxEquId && GetSpecificationFromEquipmentId(0, dummy)==-ENOSYS) {
111     AliWarningStream() << "publication of multiple equipment ids needs implementation of a child and function GetSpecificationFromEquipmentId to set correct specifications" << endl;
112     //return -EINVAL;
113   }
114
115   if (GetRawReader()!=NULL) {
116   } else {
117     AliErrorStream() << "RawReader instance needed" << endl;
118     return -EINVAL;
119   }
120
121   return iResult;
122 }
123
124 int AliHLTRawReaderPublisherComponent::DoDeinit()
125 {
126   /// inherited from AliHLTComponent: component cleanup
127   int iResult=0;
128   return iResult;
129 }
130
131 int AliHLTRawReaderPublisherComponent::ScanConfigurationArgument(int argc, const char** argv)
132 {
133   /// inherited from AliHLTComponent: argument scan
134   if (argc<1) return 0;
135   int bMissingParam=0;
136   int i=0;
137   TString argument=argv[i];
138
139   do {
140     // -detector
141     if (argument.CompareTo("-detector")==0) {
142       if ((bMissingParam=(++i>=argc))) break;
143       fDetector=argv[i];
144       return 2;
145
146       // -equipmentid, -minid
147     } else if (argument.CompareTo("-equipmentid")==0 ||
148                argument.CompareTo("-minid")==0) {
149       if ((bMissingParam=(++i>=argc))) break;
150       TString parameter(argv[i]);
151       parameter.Remove(TString::kLeading, ' '); // remove all blanks
152       if (parameter.IsDigit()) {
153         fMinEquId=(AliHLTUInt32_t)parameter.Atoi();
154         return 2;
155       } else {
156         HLTError("wrong parameter for argument %s, number expected", argument.Data());
157         return -EINVAL;
158       }
159
160       // -maxid
161     } else if (argument.CompareTo("-maxid")==0) {
162       if ((bMissingParam=(++i>=argc))) break;
163       TString parameter(argv[i]);
164       parameter.Remove(TString::kLeading, ' '); // remove all blanks
165       if (parameter.IsDigit()) {
166         fMaxEquId=(AliHLTUInt32_t)parameter.Atoi();
167         return 2;
168       } else {
169         HLTError("wrong parameter for argument %s, number expected", argument.Data());
170         return -EINVAL;
171       }
172
173       // -verbose
174     } else if (argument.CompareTo("-verbose")==0) {
175       fVerbosity++;
176       return 1;
177
178       // -silent
179     } else if (argument.CompareTo("-silent")==0) {
180       fVerbosity=0;
181       return 1;
182
183       // -skipempty
184     } else if (argument.CompareTo("-skipempty")==0) {
185       fSkipEmpty=kTRUE;
186       return 1;
187
188       // -datatype
189     } else if (argument.CompareTo("-datatype")==0) {
190       if ((bMissingParam=(++i>=argc))) break;
191       memcpy(&fDataType.fID, argv[i], TMath::Min(kAliHLTComponentDataTypefIDsize, (Int_t)strlen(argv[i])));
192       if ((bMissingParam=(++i>=argc))) break;
193       memcpy(&fDataType.fOrigin, argv[i], TMath::Min(kAliHLTComponentDataTypefOriginSize, (Int_t)strlen(argv[i])));
194       return 3;
195
196       // -dataspec
197     } else if (argument.CompareTo("-dataspec")==0) {
198       if ((bMissingParam=(++i>=argc))) break;
199       TString parameter(argv[i]);
200       parameter.Remove(TString::kLeading, ' '); // remove all blanks
201       if (parameter.IsDigit()) {
202         fSpecification=(AliHLTUInt32_t)parameter.Atoi();
203       } else if (parameter.BeginsWith("0x") &&
204                  parameter.Replace(0,2,"",0).IsHex()) {
205         sscanf(parameter.Data(),"%x", &fSpecification);
206       } else {
207         HLTError("wrong parameter for argument %s, number expected", argument.Data());
208         return -EINVAL;
209       }
210       return 2;
211     }
212   } while (0); // using do-while only to have break available
213   if (bMissingParam) {
214     HLTError("missing parameter for argument %s", argument.Data());
215     return -EINVAL;
216   }
217
218   return -EPROTO;
219 }
220
221 int AliHLTRawReaderPublisherComponent::GetEvent(const AliHLTComponentEventData& /*evtData*/, 
222                                                 AliHLTComponentTriggerData& /*trigData*/, 
223                                                 AliHLTUInt8_t* outputPtr, 
224                                                 AliHLTUInt32_t& size, 
225                                                 vector<AliHLTComponentBlockData>& outputBlocks)
226 {
227   /// inherited from AliHLTDataSource: get the event
228   int iResult=0;
229   AliHLTUInt32_t capacity=size;
230   size=0;
231
232   // process data events only
233   if (!IsDataEvent()) return 0;
234
235   unsigned int offset=0;
236   assert(outputPtr!=NULL || size==0);
237   AliRawReader* pRawReader=GetRawReader();
238   if (pRawReader) {
239     pRawReader->Reset();
240     pRawReader->SelectEquipment(-1, fMinEquId, fMaxEquId);
241     if (fVerbosity>1) {
242       AliInfo(Form("get event from RawReader %p equipment id range [%d,%d]", pRawReader, fMinEquId, fMaxEquId));
243     } else {
244       AliDebug(0, Form("get event from RawReader %p equipment id range [%d,%d]", pRawReader, fMinEquId, fMaxEquId));
245     }
246     list<int> processedIds;
247     while (pRawReader->ReadHeader() && (iResult>=0 || iResult==-ENOSPC)) {
248       const AliRawDataHeader* pHeader=pRawReader->GetDataHeader();
249       if (pHeader==NULL) {
250         HLTError("can not get data header from RawReader, skipping data block ...");
251         continue;
252       }
253       unsigned int readSize=pRawReader->GetDataSize()+sizeof(AliRawDataHeader);
254       int id=pRawReader->GetEquipmentId();
255       if (fMinEquId>id || fMaxEquId<id) {
256         AliError(Form("id %d returned from RawReader is outside range [%d,%d]", id, fMinEquId, fMaxEquId));
257         continue;
258       }
259       processedIds.push_back(id);
260       bool isSelected=IsSelected(id);
261       if (fVerbosity>0) {
262         AliInfo(Form("got header for id %d, size %d, %s", id, readSize, isSelected?"selected":"discarded"));
263       } else {
264         AliDebug(0, Form("got header for id %d, size %d", id, readSize));
265       }
266       if (!isSelected) continue;
267       if (readSize+offset<=capacity) {
268         memcpy(outputPtr+offset, pHeader, sizeof(AliRawDataHeader));
269         if (readSize>sizeof(AliRawDataHeader)) {
270           if (!pRawReader->ReadNext(outputPtr+offset+sizeof(AliRawDataHeader), readSize-sizeof(AliRawDataHeader))) {
271             AliError(Form("error reading %ld bytes from RawReader %p", readSize-sizeof(AliRawDataHeader), pRawReader));
272             iResult=-ENODATA;
273             break;
274           }
275         }
276         AliHLTComponentBlockData bd;
277         FillBlockData( bd );
278         bd.fOffset = offset;
279         bd.fSize = readSize;
280         bd.fDataType = fDataType;
281         if (fSpecification == kAliHLTVoidDataSpec) {
282           GetSpecificationFromEquipmentId(id, bd.fSpecification);
283         } else {
284           bd.fSpecification=fSpecification;
285         }
286         outputBlocks.push_back( bd );
287       } else {
288         // we keep the loop going in order to collect the full size
289         fMaxSize=offset+readSize;
290         iResult=-ENOSPC;
291       }
292       offset+=readSize;
293     }
294     if (!fSkipEmpty && processedIds.size()!=size_t(fMaxEquId-fMinEquId+1)) {
295       // add further empty data blocks
296       AliRawDataHeader header;
297       header.fSize=sizeof(AliRawDataHeader);
298       const UInt_t* triggermask=pRawReader->GetTriggerPattern();
299       if (triggermask) {
300         header.fTriggerClassLow=triggermask[0];
301         header.fROILowTriggerClassHigh=triggermask[1];
302       }
303       processedIds.sort();
304       list<int>::iterator curr=processedIds.begin();
305       for (int id=fMinEquId; id<=fMaxEquId; id++) {
306         if (curr!=processedIds.end() && *curr<=id) {
307           curr++;
308         } else {
309           if (sizeof(AliRawDataHeader)<=capacity-offset) {
310             HLTInfo("add empty data block for equipment id %d", id);
311             memcpy(outputPtr+offset, &header, sizeof(AliRawDataHeader));
312             AliHLTComponentBlockData bd;
313             FillBlockData( bd );
314             bd.fOffset = offset;
315             bd.fSize = sizeof(AliRawDataHeader);
316             bd.fDataType = fDataType;
317             if (fSpecification == kAliHLTVoidDataSpec) {
318               GetSpecificationFromEquipmentId(id, bd.fSpecification);
319             } else {
320               bd.fSpecification=fSpecification;
321             }
322             outputBlocks.push_back( bd );
323           } else {
324             // we keep the loop going in order to collect the full size
325             fMaxSize=offset+sizeof(AliRawDataHeader);
326             iResult=-ENOSPC;
327           }
328           offset+=sizeof(AliRawDataHeader);
329         }
330       }
331     }
332     if (offset<=capacity) {
333       size=offset;
334     } else {
335       outputBlocks.clear();
336     }
337   } else {
338     AliErrorStream() << "RawReader uninitialized" << endl;
339     iResult=-EFAULT;
340   }
341   return iResult;
342 }
343
344 int AliHLTRawReaderPublisherComponent::GetSpecificationFromEquipmentId(int id, AliHLTUInt32_t& specification) const {
345   /// get the data specification from the equipment id
346   /// default method just returns the equipment id
347   return specification=id;
348 }