]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/util/AliHLTFilePublisher.cxx
d317c77319848884ffbb796aee41647f3a74f5e6
[u/mrichter/AliRoot.git] / HLT / BASE / util / AliHLTFilePublisher.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   AliHLTFilePublisher.cxx
20     @author Matthias Richter
21     @date   
22     @brief  HLT file publisher component implementation. */
23
24 // see header file for class documentation
25 // or
26 // refer to README to build package
27 // or
28 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
29
30 #if __GNUC__>= 3
31 using namespace std;
32 #endif
33
34 #include "AliHLTFilePublisher.h"
35 #include "AliLog.h"
36 //#include <TObjString.h>
37 #include <TMath.h>
38 #include <TFile.h>
39
40
41 /** ROOT macro for the implementation of ROOT specific class methods */
42 ClassImp(AliHLTFilePublisher)
43
44 AliHLTFilePublisher::AliHLTFilePublisher()
45   :
46   AliHLTDataSource(),
47   fpCurrent(NULL),
48   fEvents(),
49   fMaxSize(0),
50   fOpenFilesAtStart(false),
51   fOutputDataTypes()
52 {
53   // see header file for class documentation
54   // or
55   // refer to README to build package
56   // or
57   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
58
59   // make the lists owners of their objects in order to automatically
60   // de-allocate the objects
61   fEvents.SetOwner();
62 }
63
64 AliHLTFilePublisher::~AliHLTFilePublisher()
65 {
66   // see header file for class documentation
67
68   // file list and file name list are owner of their objects and
69   // delete all the objects
70 }
71
72 const char* AliHLTFilePublisher::GetComponentID()
73 {
74   // see header file for class documentation
75   return "FilePublisher";
76 }
77
78 AliHLTComponentDataType AliHLTFilePublisher::GetOutputDataType()
79 {
80   // see header file for class documentation
81   if (fOutputDataTypes.size()==0) return kAliHLTVoidDataType;
82   else if (fOutputDataTypes.size()==1) return fOutputDataTypes[0];
83   return kAliHLTMultipleDataType;
84 }
85
86 int AliHLTFilePublisher::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
87 {
88   // see header file for class documentation
89   tgtList.assign(fOutputDataTypes.begin(), fOutputDataTypes.end());
90   HLTInfo("%s %p provides %d output data types", GetComponentID(), this, fOutputDataTypes.size());
91   return fOutputDataTypes.size();
92 }
93
94 void AliHLTFilePublisher::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
95 {
96   // see header file for class documentation
97   constBase=fMaxSize;
98   inputMultiplier=1.0;
99 }
100
101 AliHLTComponent* AliHLTFilePublisher::Spawn()
102 {
103   // see header file for class documentation
104   return new AliHLTFilePublisher;
105 }
106
107 int AliHLTFilePublisher::DoInit( int argc, const char** argv )
108 {
109   // see header file for class documentation
110
111   //HLTDebug("%d %s", argc, argv[0]);
112   int iResult=0;
113   TString argument="";
114   int bMissingParam=0;
115   int bHaveDatatype=0;
116   int bHaveSpecification=0;
117   fOpenFilesAtStart = false;
118   AliHLTComponentDataType currDataType=kAliHLTVoidDataType;
119   AliHLTUInt32_t          currSpecification=kAliHLTVoidDataSpec;
120   EventFiles*             pCurrEvent=NULL;
121   for (int i=0; i<argc && iResult>=0; i++) {
122     argument=argv[i];
123     if (argument.IsNull()) continue;
124
125     // -datafile
126     if (argument.CompareTo("-datafile")==0) {
127       if ((bMissingParam=(++i>=argc))) break;
128       if (!bHaveDatatype) {
129         HLTWarning("no data type available so far, please set data type and specification before the file name. The first available data type will be set for all files preceding it");
130       }
131       FileDesc* pDesc=new FileDesc(argv[i], currDataType, currSpecification);
132       if (pDesc) {
133         iResult=InsertFile(pCurrEvent, pDesc);
134       } else {
135         iResult=-ENOMEM;
136       }
137
138       // -datafilelist
139     } else if (argument.CompareTo("-datafilelist")==0) {
140       if ((bMissingParam=(++i>=argc))) break;
141       HLTWarning("-datafilelist option not yet implemented");
142
143       // -datatype
144     } else if (argument.CompareTo("-datatype")==0) {
145       currDataType=kAliHLTVoidDataType;
146       if ((bMissingParam=(++i>=argc))) break;
147       memcpy(&currDataType.fID, argv[i], TMath::Min(kAliHLTComponentDataTypefIDsize, (Int_t)strlen(argv[i])));
148       if ((bMissingParam=(++i>=argc))) break;
149       memcpy(&currDataType.fOrigin, argv[i], TMath::Min(kAliHLTComponentDataTypefOriginSize, (Int_t)strlen(argv[i])));
150
151       // add all different data types to the list
152       AliHLTComponentDataTypeList::iterator element=fOutputDataTypes.begin();
153       while (element!=fOutputDataTypes.end() && *element!=currDataType) element++;
154       if (element==fOutputDataTypes.end()) fOutputDataTypes.push_back(currDataType);
155
156       if (bHaveDatatype==0 && pCurrEvent && iResult>=0) {
157         // this is a workaround to make old tutorials working which contain
158         // the arguments in the wrong sequence
159         TList& files=*pCurrEvent; // type conversion operator defined
160         TObjLink *flnk=files.FirstLink();
161         while (flnk) {
162           FileDesc* pFileDesc=dynamic_cast<FileDesc*>(flnk->GetObject());
163           if (pFileDesc) {
164             pFileDesc->SetDataType(currDataType);
165           }
166           flnk=flnk->Next();
167         }
168       }
169       bHaveDatatype=1;
170
171       // -dataspec
172     } else if (argument.CompareTo("-dataspec")==0) {
173       if ((bMissingParam=(++i>=argc))) break;
174       TString parameter(argv[i]);
175       parameter.Remove(TString::kLeading, ' '); // remove all blanks
176       if (parameter.IsDigit()) {
177         currSpecification=(AliHLTUInt32_t)parameter.Atoi();
178       } else if (parameter.BeginsWith("0x") &&
179                  parameter.Replace(0,2,"",0).IsHex()) {
180         sscanf(parameter.Data(),"%x", &currSpecification);
181       } else {
182         HLTError("wrong parameter for argument %s, number expected", argument.Data());
183         iResult=-EINVAL;
184       }
185       if (bHaveSpecification==0 && pCurrEvent && iResult>=0) {
186         // this is a workaround to make old tutorials working which contain
187         // the arguments in the wrong sequence
188         TList& files=*pCurrEvent; // type conversion operator defined
189         TObjLink *flnk=files.FirstLink();
190         while (flnk) {
191           FileDesc* pFileDesc=dynamic_cast<FileDesc*>(flnk->GetObject());
192           if (pFileDesc) {
193             pFileDesc->SetSpecification(currSpecification);
194           }
195           flnk=flnk->Next();
196         }
197       }
198       bHaveSpecification=1;
199       // -nextevent
200     } else if (argument.CompareTo("-nextevent")==0) {
201       InsertEvent(pCurrEvent);
202     } else if (argument.CompareTo("-open_files_at_start")==0) {
203       fOpenFilesAtStart = true;
204     } else {
205       if ((iResult=ScanArgument(argc-i, &argv[i]))==-EINVAL) {
206         HLTError("unknown argument %s", argument.Data());
207         break;
208       } else if (iResult==-EPROTO) {
209         bMissingParam=1;
210         break;
211       } else if (iResult>=0) {
212         i+=iResult;
213         iResult=0;
214       }
215     }
216   }
217   InsertEvent(pCurrEvent);
218
219   if (bMissingParam) {
220     HLTError("missing parameter for argument %s", argument.Data());
221     iResult=-EINVAL;
222   }
223   if (fEvents.GetSize()==0) {
224     HLTError("the publisher needs at least one file argument");
225     iResult=-EINVAL;
226   }
227   if (iResult>=0) iResult=OpenFiles(fOpenFilesAtStart);
228   if (iResult<0) {
229     fEvents.Clear();
230   }
231   return iResult;
232 }
233
234 int AliHLTFilePublisher::InsertFile(EventFiles* &pCurrEvent, FileDesc* pDesc)
235 {
236   // see header file for class documentation
237   int iResult=0;
238   if (pDesc) {
239     if (pCurrEvent==NULL) {
240       pCurrEvent=new EventFiles;
241       if (pCurrEvent!=NULL) {
242       } else {
243         iResult=-ENOMEM;
244       }
245     }
246     if (iResult>=0 && pCurrEvent!=NULL) {
247       HLTDebug("Insert file %p to event %p", pDesc, pCurrEvent);
248       pCurrEvent->Add(pDesc);
249     }
250   } else {
251     iResult=-EINVAL;
252   }
253   return iResult;
254 }
255
256 int AliHLTFilePublisher::InsertEvent(EventFiles* &pEvent)
257 {
258   // see header file for class documentation
259   int iResult=0;
260   if (pEvent) {
261     HLTDebug("Inserted event %p", pEvent);
262     fEvents.Add(pEvent);
263     pEvent=NULL;
264   }
265   return iResult;
266 }
267
268 int AliHLTFilePublisher::ScanArgument(int argc, const char** argv)
269 {
270   // see header file for class documentation
271
272   // there are no other arguments than the standard ones
273   if (argc==0 && argv==NULL) {
274     // this is just to get rid of the warning "unused parameter"
275   }
276   return -EINVAL;
277 }
278
279 int AliHLTFilePublisher::OpenFiles(bool keepOpen)
280 {
281   // see header file for class documentation
282   int iResult=0;
283   TObjLink *lnk=fEvents.FirstLink();
284   while (lnk && iResult>=0) {
285     EventFiles* pEventDesc=dynamic_cast<EventFiles*>(lnk->GetObject());
286     if (pEventDesc) {
287       HLTDebug("open files for event %p", pEventDesc);
288       TList& files=*pEventDesc; // type conversion operator defined
289       TObjLink *flnk=files.FirstLink();
290       int eventSize=0;
291       while (flnk && iResult>=0) {
292         FileDesc* pFileDesc=dynamic_cast<FileDesc*>(flnk->GetObject());
293         if (pFileDesc) {
294           int size=pFileDesc->OpenFile();
295           if (not keepOpen) pFileDesc->CloseFile();
296           if (size<0) {
297             iResult=size;
298             HLTError("can not open file %s", pFileDesc->GetName());
299           } else {
300             eventSize+=size;
301           }
302         }
303         flnk=flnk->Next();
304       }
305       HLTDebug("event %p size %d", pEventDesc, eventSize);
306       if (fMaxSize<eventSize) fMaxSize=eventSize;
307     } else {
308       HLTError("can not get event descriptor for TObjLink");
309     }
310     lnk = lnk->Next();
311   }
312
313   return iResult;
314 }
315
316 int AliHLTFilePublisher::DoDeinit()
317 {
318   // see header file for class documentation
319   int iResult=0;
320   fEvents.Clear();
321   return iResult;
322 }
323
324 int AliHLTFilePublisher::GetEvent( const AliHLTComponentEventData& /*evtData*/,
325                                    AliHLTComponentTriggerData& /*trigData*/,
326                                    AliHLTUInt8_t* outputPtr, 
327                                    AliHLTUInt32_t& size,
328                                    AliHLTComponentBlockDataList& outputBlocks )
329 {
330   // see header file for class documentation
331
332   // process data events only
333   if (!IsDataEvent()) return 0;
334   AliHLTUInt32_t capacity=size;
335   size=0;
336
337   int iResult=0;
338   TObjLink *lnk=fpCurrent;
339   if (lnk==NULL) lnk=fEvents.FirstLink();
340   fpCurrent=lnk;
341   if (lnk) {
342     EventFiles* pEventDesc=dynamic_cast<EventFiles*>(lnk->GetObject());
343     if (pEventDesc) {
344       HLTDebug("publishing files for event %p", pEventDesc);
345       TList& files=*pEventDesc; // type conversion operator defined
346       TObjLink *flnk=files.FirstLink();
347       int iTotalSize=0;
348       while (flnk && iResult>=0) {
349         FileDesc* pFileDesc=dynamic_cast<FileDesc*>(flnk->GetObject());
350         if (not fOpenFilesAtStart) pFileDesc->OpenFile();
351         TFile* pFile=NULL;
352         if (pFileDesc && (pFile=*pFileDesc)!=NULL) {
353           int iCopy=pFile->GetSize();
354           pFile->Seek(0);
355           if (iCopy+iTotalSize<=(int)capacity) {
356             if (pFile->ReadBuffer((char*)outputPtr+iTotalSize, iCopy)!=0) {
357               // ReadBuffer returns 1 in case of failure and 0 in case of success
358               iResult=-EIO;
359             } else {
360               AliHLTComponentBlockData bd;
361               FillBlockData(bd);
362               bd.fPtr=outputPtr;
363               bd.fOffset=iTotalSize;
364               bd.fSize=iCopy;
365               bd.fDataType=*pFileDesc;      // type conversion operator defined
366               bd.fSpecification=*pFileDesc; // type conversion operator defined
367               outputBlocks.push_back(bd);
368               iTotalSize+=iCopy;
369 //            TString msg;
370 //            msg.Form("get file %s ", pFile->GetName());
371 //            msg+="data type \'%s\'";
372 //            PrintDataTypeContent(bd.fDataType, msg.Data());
373             }
374           } else {
375             // output buffer too small, update GetOutputDataSize for the second trial
376             fMaxSize=iCopy;
377             iResult=-ENOSPC;
378           }
379           if (not fOpenFilesAtStart) pFileDesc->CloseFile();
380         } else {
381           HLTError("no file available");
382           iResult=-EFAULT;
383         }
384         flnk=flnk->Next();
385       }
386       size=iTotalSize;
387     } else {
388       HLTError("can not get event descriptor from list link");
389       iResult=-EFAULT;
390     }
391   } else {
392     iResult=-ENOENT;
393   }
394   if (iResult>=0 && fpCurrent) fpCurrent=fpCurrent->Next();
395
396   return iResult;
397 }
398
399 // AliHLTComponentDataType AliHLTFilePublisher::GetCurrentDataType() const
400 // {
401 //   return kAliHLTVoidDataType;
402 // }
403
404 // AliHLTUInt32_t          AliHLTFilePublisher::GetCurrentSpecification() const
405 // {
406 //   return 0;
407 // }
408
409 AliHLTFilePublisher::FileDesc::FileDesc(const char* name, AliHLTComponentDataType dt, AliHLTUInt32_t spec)
410   :
411   TObject(),
412   fName(name),
413   fpInstance(NULL),
414   fDataType(dt),
415   fSpecification(spec)
416 {
417   // see header file for class documentation
418   // or
419   // refer to README to build package
420   // or
421   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
422 }
423
424 AliHLTFilePublisher::FileDesc::~FileDesc()
425 {
426   // see header file for class documentation
427   CloseFile();
428 }
429
430 void AliHLTFilePublisher::FileDesc::CloseFile()
431 {
432   // see header file for class documentation
433   if (fpInstance)
434   {
435     // Unfortunately had to use AliLog mechanisms rather that AliHLTLogging because
436     // AliHLTFilePublisher::FileDesc does not derive from AliHLTLogging. It would
437     // become a rather heavy class if it did.
438 #ifdef __DEBUG
439     AliDebugGeneral("AliHLTFilePublisher::FileDesc",
440       2, Form("File %s has been closed.", fName.Data())
441     );
442 #endif
443     delete fpInstance;
444   }
445   fpInstance=NULL;
446 }
447
448 int AliHLTFilePublisher::FileDesc::OpenFile()
449 {
450   // see header file for class documentation
451   int iResult=0;
452   TString fullFN= fName + "?filetype=raw";
453   fpInstance = new TFile(fullFN);
454   if (fpInstance) {
455     if (fpInstance->IsZombie()==0) {
456       iResult=fpInstance->GetSize();
457 #ifdef __DEBUG
458       AliDebugGeneral("AliHLTFilePublisher::FileDesc",
459         2, Form("File %s has been opened.", fName.Data())
460       );
461 #endif
462     } else {
463       iResult=-ENOENT;
464     }
465   }
466   return iResult;
467 }