enhanced functionality (sub dirs, file name format specifiers)
[u/mrichter/AliRoot.git] / HLT / BASE / util / AliHLTFileWriter.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   AliHLTFileWriter.cxx
20     @author Matthias Richter
21     @date   
22     @brief  HLT file writer component implementation. */
23
24 #if __GNUC__>= 3
25 using namespace std;
26 #endif
27
28 #include "AliHLTFileWriter.h"
29 #include <TObjArray.h>
30 #include <TObjString.h>
31 #include <TSystem.h>
32 //#include <TMath.h>
33 //#include <TFile.h>
34
35 /** the global object for component registration */
36 AliHLTFileWriter gAliHLTFileWriter;
37
38 /** ROOT macro for the implementation of ROOT specific class methods */
39 ClassImp(AliHLTFileWriter)
40
41 AliHLTFileWriter::AliHLTFileWriter()
42   :
43   AliHLTDataSink(),
44   fBaseName(""),
45   fExtension(""),
46   fDirectory(""),
47   fSubDirFormat(""),
48   fIdFormat(""),
49   fSpecFormat(""),
50   fBlcknoFormat(""),
51   fCurrentFileName(""),
52   fMode(0)
53 {
54   // see header file for class documentation
55   // or
56   // refer to README to build package
57   // or
58   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
59 }
60
61 AliHLTFileWriter::~AliHLTFileWriter()
62 {
63   // see header file for class documentation
64
65   // file list and file name list are owner of their objects and
66   // delete all the objects
67 }
68
69 const char* AliHLTFileWriter::GetComponentID()
70 {
71   // see header file for class documentation
72   return "FileWriter";
73 }
74
75 void AliHLTFileWriter::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
76 {
77   // see header file for class documentation
78   list.clear();
79   list.push_back(kAliHLTAnyDataType);
80 }
81
82 AliHLTComponent* AliHLTFileWriter::Spawn()
83 {
84   // see header file for class documentation
85   return new AliHLTFileWriter;
86 }
87
88 int AliHLTFileWriter::DoInit( int argc, const char** argv )
89 {
90   // see header file for class documentation
91   int iResult=0;
92   TString argument="";
93   int bMissingParam=0;
94   for (int i=0; i<argc && iResult>=0; i++) {
95     argument=argv[i];
96     if (argument.IsNull()) continue;
97
98     // -basename
99     if (argument.CompareTo("-datafile")==0) {
100       if ((bMissingParam=(++i>=argc))) break;
101       fBaseName=argv[i];
102       TObjArray* pTokens=fBaseName.Tokenize(".");
103       if (pTokens) {
104         int iEntries=pTokens->GetEntries();
105         if (iEntries>1) {
106           int i=0;
107           fBaseName=((TObjString*)pTokens->At(i++))->GetString();
108           while (i<iEntries-1) {
109             fBaseName+="." + ((TObjString*)pTokens->At(i++))->GetString();
110           }
111           fExtension=((TObjString*)pTokens->At(i))->GetString();
112         }
113         delete pTokens;
114       }
115
116       // -directory
117     } else if (argument.CompareTo("-directory")==0) {
118       if ((bMissingParam=(++i>=argc))) break;
119       fDirectory=argv[i];
120
121       // -subdir
122     } else if (argument.BeginsWith("-subdir")) {
123       argument.ReplaceAll("-subdir", "");
124       if (argument.BeginsWith("=")) {
125         fSubDirFormat=argument.Replace(0,1,"");
126       } else {
127         fSubDirFormat="event%03d";
128       }
129
130       // -idfmt
131     } else if (argument.BeginsWith("-idfmt")) {
132       argument.ReplaceAll("-idfmt", "");
133       if (argument.BeginsWith("=")) {
134         fIdFormat=argument.Replace(0,1,"");
135       }
136
137       // -specfmt
138     } else if (argument.BeginsWith("-specfmt")) {
139       argument.ReplaceAll("-specfmt", "");
140       if (argument.BeginsWith("=")) {
141         fSpecFormat=argument.Replace(0,1,"");
142       } else {
143         fSpecFormat="_0x%08x";
144       }
145
146       // -blcknofmt
147     } else if (argument.BeginsWith("-blcknofmt")) {
148       argument.ReplaceAll("-blcknofmt", "");
149       if (argument.BeginsWith("=")) {
150         fBlcknoFormat=argument.Replace(0,1,"");
151       } else {
152         fBlcknoFormat="_0x%02x";
153       }
154
155       // -enumeration
156     } else if (argument.CompareTo("-enumerate")==0) {
157       SetMode(kEnumerate);
158
159       // -concatenate-blocks
160     } else if (argument.CompareTo("-concatenate-blocks")==0) {
161       SetMode(kConcatenateBlocks);
162
163       // -concatenate-events
164     } else if (argument.CompareTo("-concatenate-events")==0) {
165       SetMode(kConcatenateEvents);
166
167     } else {
168       if ((iResult=ScanArgument(argc-i, &argv[i]))==-EINVAL) {
169         HLTError("unknown argument %s", argument.Data());
170         break;
171       } else if (iResult==-EPROTO) {
172         bMissingParam=1;
173         break;
174       } else if (iResult>=0) {
175         i+=iResult;
176         iResult=0;
177       }
178     }
179   }
180   if (bMissingParam) {
181     HLTError("missing parameter for argument %s", argument.Data());
182     iResult=-EINVAL;
183   }
184   if (iResult>=0) {
185     if (fIdFormat.IsNull() && fSubDirFormat.IsNull()) {
186       // set the default format string for the id if it is not set and
187       // no sub dirs set (the sub dir than contains the id)
188       fIdFormat="_0x%08x";
189     }
190     iResult=InitWriter();
191   }
192
193   return iResult;
194 }
195
196 int AliHLTFileWriter::InitWriter()
197 {
198   // see header file for class documentation
199   
200   // fCurrentFileName is used in dump event, just touched her to avoid
201   // coding convention violation RC11. The function can not be declared
202   // const since it is just the default implementation, overloaded
203   // virtual function might not be const
204   fCurrentFileName="";
205   return 0; // note: this doesn't mean 'error'
206 }
207
208 int AliHLTFileWriter::ScanArgument(int argc, const char** argv)
209 {
210   // see header file for class documentation
211
212   // there are no other arguments than the standard ones
213   if (argc==0 && argv==NULL) {
214     // this is just to get rid of the warning "unused parameter"
215   }
216   // fCurrentFileName is used in dump event, just touched her to avoid
217   // coding convention violation RC11. The function can not be declared
218   // const since it is just the default implementation, overloaded
219   // virtual function might not be const
220   fCurrentFileName="";
221   return -EINVAL;
222 }
223
224 int AliHLTFileWriter::DoDeinit()
225 {
226   // see header file for class documentation
227   int iResult=CloseWriter();
228   ClearMode(kEnumerate);
229   return iResult;
230 }
231
232 int AliHLTFileWriter::CloseWriter()
233 {
234   // see header file for class documentation
235
236   // fCurrentFileName is used in dump event, just touched her to avoid
237   // coding convention violation RC11. The function can not be declared
238   // const since it is just the default implementation, overloaded
239   // virtual function might not be const
240   fCurrentFileName="";
241   return 0; // note: this doesn't mean 'error'
242 }
243
244 int AliHLTFileWriter::DumpEvent( const AliHLTComponentEventData& evtData,
245                          const AliHLTComponentBlockData* blocks, 
246                          AliHLTComponentTriggerData& trigData )
247 {
248   // see header file for class documentation
249   int iResult=0;
250   if (CheckMode(kConcatenateEvents)==0) {
251     // reset the current file name in order to open a new file
252     // for the first block. If events are concatenated, the current
253     // file name stays in order to be opended in append mode.
254     fCurrentFileName="";
255   }
256   for (int n=0; n<(int)evtData.fBlockCnt; n++ ) {
257     //HLTDebug("block %d out of %d", n, evtData.fBlockCnt);
258     TString filename;
259     HLTDebug("dataspec 0x%x", blocks[n].fSpecification);
260     iResult=BuildFileName(evtData.fEventID, n, blocks[n].fDataType, blocks[n].fSpecification, filename);
261     ios::openmode filemode=(ios::openmode)0;
262     if (fCurrentFileName.CompareTo(filename)==0) {
263       // append to the file
264       filemode=ios::app;
265     } else {
266       // store the file for the next block
267       fCurrentFileName=filename;
268     }
269     if (iResult>=0) {
270       ofstream dump(filename.Data(), filemode);
271       if (dump.good()) {
272         dump.write((static_cast<const char*>(blocks[n].fPtr))+blocks[n].fOffset, blocks[n].fSize);
273         HLTDebug("wrote %d byte(s) to file %s", blocks[n].fSize, filename.Data());
274       } else {
275         HLTError("can not open file %s for writing", filename.Data());
276         iResult=-EBADF;
277       }
278       dump.close();
279     }
280   }
281   if (trigData.fStructSize==0) {
282     // this is just to get rid of the warning "unused parameter"
283   }
284   return iResult;
285 }
286
287 int AliHLTFileWriter::BuildFileName(const AliHLTEventID_t eventID, const int blockID,
288                                     const AliHLTComponentDataType& dataType,
289                                     const AliHLTUInt32_t specification,
290                                     TString& filename)
291 {
292   // see header file for class documentation
293   int iResult=0;
294   //HLTDebug("build file name for event %d block %d", eventID, blockID);
295   filename="";
296   if (!fDirectory.IsNull()) {
297     filename+=fDirectory;
298     if (!filename.EndsWith("/"))
299       filename+="/";
300   }
301   if (!fSubDirFormat.IsNull()) {
302     filename+=Form(fSubDirFormat, eventID);
303     if (!filename.EndsWith("/"))
304       filename+="/";
305   }
306   if (filename.EndsWith("/")) {
307     gSystem->mkdir(filename);
308   }
309   if (!fBaseName.IsNull())
310     filename+=fBaseName;
311   else
312     filename+="event";
313   if (!CheckMode(kConcatenateEvents)) {
314     if (!CheckMode(kEnumerate)) {
315       if (eventID!=kAliHLTVoidEventID && !fIdFormat.IsNull()) {
316         filename+=Form(fIdFormat, eventID);
317       }
318     } else {
319       filename+=Form("_%d", GetEventCount());
320     }
321   }
322   if (blockID>=0 && !CheckMode(kConcatenateBlocks)) {
323     if (!fBlcknoFormat.IsNull())
324       filename+=Form(fBlcknoFormat, blockID);
325     if (dataType!=kAliHLTVoidDataType) {
326       filename+="_";
327       filename+=AliHLTComponent::DataType2Text(dataType).data();
328     }
329     if (!fSpecFormat.IsNull())
330       filename+=Form(fSpecFormat, specification);
331   }
332   if (!fExtension.IsNull())
333     filename+="." + fExtension;
334   filename.ReplaceAll(" ", "");
335   return iResult;
336 }
337
338 int AliHLTFileWriter::SetMode(Short_t mode) 
339 {
340   // see header file for class documentation
341   fMode|=mode;
342   //HLTDebug("mode set to 0x%x", fMode);
343   return fMode;
344 }
345
346 int AliHLTFileWriter::ClearMode(Short_t mode)
347 {
348   // see header file for class documentation
349   fMode&=~mode;
350   //HLTDebug("mode set to 0x%x", fMode);
351   return fMode;
352 }
353
354 int AliHLTFileWriter::CheckMode(Short_t mode) const
355 {
356   // see header file for class documentation
357
358   //HLTDebug("check mode 0x%x for flag 0x%x: %d", fMode, mode, (fMode&mode)!=0);
359   return (fMode&mode)!=0;
360 }