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