]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/sim/AliHLTOUTComponent.cxx
bugfix: dynamic_cast caused undefined symbol; sequence of writers written to raw...
[u/mrichter/AliRoot.git] / HLT / sim / AliHLTOUTComponent.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   AliHLTOUTComponent.cxx
20     @author Matthias Richter
21     @date   
22     @brief  The HLTOUT data sink component similar to HLTOUT nodes */
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 <cassert>
35 #include <iostream>
36 #include "AliHLTOUTComponent.h"
37 #include "AliHLTOUT.h"
38 #include "AliHLTHOMERWriter.h"
39 #include "AliDAQ.h" // equipment Ids
40 #include "AliRawDataHeader.h" // Common Data Header 
41 #include <TDatime.h> // seed for TRandom
42 #include <TRandom.h> // random int generation for DDL no
43
44 /** ROOT macro for the implementation of ROOT specific class methods */
45 ClassImp(AliHLTOUTComponent)
46
47 AliHLTOUTComponent::AliHLTOUTComponent()
48   :
49   AliHLTOfflineDataSink(),
50   fWriters(),
51   fNofDDLs(10),
52   fIdFirstDDL(4864), // 0x13<<8
53   fWriteDigits(kTRUE),
54   fWriteRaw(kTRUE),
55   fBuffer(),
56   fpLibManager(NULL)
57 {
58   // see header file for class documentation
59   // or
60   // refer to README to build package
61   // or
62   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
63
64   // I guess DDL definitions should never change any more
65   assert(fNofDDLs==AliDAQ::NumberOfDdls("HLT"));
66   fNofDDLs=AliDAQ::NumberOfDdls("HLT");
67   assert(fIdFirstDDL==AliDAQ::DdlIDOffset("HLT"));
68   fIdFirstDDL=AliDAQ::DdlIDOffset("HLT");
69 }
70
71 AliHLTOUTComponent::~AliHLTOUTComponent()
72 {
73   // see header file for class documentation
74   if (fpLibManager) delete fpLibManager;
75   fpLibManager=NULL;
76 }
77
78 const char* AliHLTOUTComponent::GetComponentID()
79 {
80   // see header file for class documentation
81   return "HLTOUT";
82 }
83
84 void AliHLTOUTComponent::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
85 {
86   // see header file for class documentation
87   list.clear();
88   list.push_back(kAliHLTAnyDataType);
89 }
90
91 AliHLTComponent* AliHLTOUTComponent::Spawn()
92 {
93   // see header file for class documentation
94   return new AliHLTOUTComponent;
95 }
96
97 int AliHLTOUTComponent::DoInit( int argc, const char** argv )
98 {
99   // see header file for class documentation
100   int iResult=0;
101   TString argument="";
102   int bMissingParam=0;
103   for (int i=0; i<argc && iResult>=0; i++) {
104     argument=argv[i];
105     if (argument.IsNull()) continue;
106
107     {
108       HLTError("unknown argument %s", argument.Data());
109       break;
110     }
111   }
112   if (bMissingParam) {
113     HLTError("missing parameter for argument %s", argument.Data());
114     iResult=-EINVAL;
115   }
116   if (iResult>=0) {
117   }
118
119   fpLibManager=new AliHLTHOMERLibManager;
120   if (fpLibManager) {
121     int writerNo=0;
122     for (writerNo=0; writerNo<fNofDDLs; writerNo++) {
123       AliHLTMonitoringWriter* pWriter=fpLibManager->OpenWriter();
124       if (pWriter) {
125         fWriters.push_back(pWriter);
126       } else {
127         iResult=-ENOMEM;
128         break;
129       }
130     }
131   } else {
132     iResult=-ENOMEM;
133   }
134
135   return iResult;
136 }
137
138 int AliHLTOUTComponent::DoDeinit()
139 {
140   // see header file for class documentation
141   int iResult=0;
142
143   if (fpLibManager) {
144     AliHLTMonitoringWriterPVector::iterator element=fWriters.begin();
145     while (element!= fWriters.end()) {
146       assert(*element);
147       // wanted to have a dynamic_cast<AliHLTHOMERWriter*> here, but this results into
148       // undefined symbol when loading the library
149       if (*element!=NULL) fpLibManager->DeleteWriter((AliHLTHOMERWriter*)(*element));
150       element=fWriters.erase(element);
151     }
152   }
153   
154   return iResult;
155 }
156
157 int AliHLTOUTComponent::DumpEvent( const AliHLTComponentEventData& evtData,
158                          const AliHLTComponentBlockData* blocks, 
159                          AliHLTComponentTriggerData& /*trigData*/ )
160 {
161   // see header file for class documentation
162   int iResult=0;
163   HLTInfo("write %d output blocks", evtData.fBlockCnt);
164   fWriters.clear();
165   if (iResult>=0) {
166     homer_uint64 homerHeader[kCount_64b_Words];
167     HOMERBlockDescriptor homerDescriptor(homerHeader);
168     for (int n=0; n<(int)evtData.fBlockCnt; n++ ) {
169       memset( homerHeader, 0, sizeof(homer_uint64)*kCount_64b_Words );
170       homerDescriptor.Initialize();
171       homerDescriptor.SetType(reinterpret_cast<homer_uint64>(blocks[n].fDataType.fID));
172       homerDescriptor.SetSubType1(reinterpret_cast<homer_uint64>(blocks[n].fDataType.fOrigin));
173       homerDescriptor.SetSubType2(static_cast<homer_uint64>(blocks[n].fSpecification));
174       int writerNo=ShuffleWriters(fWriters, blocks[n].fSize);
175       assert(writerNo>=0 && writerNo<fWriters.size());
176       fWriters[writerNo]->AddBlock(&homerDescriptor, blocks[n].fPtr);
177     }
178   }
179
180   return iResult;
181 }
182
183 int AliHLTOUTComponent::FillESD(int eventNo, AliRunLoader* runLoader, AliESDEvent* /*esd*/)
184 {
185   // see header file for class documentation
186   int iResult=0;
187   if (fWriters.size()==0) return 0;
188   
189   // search for the writer with the biggest data volume in order to allocate the
190   // output buffer of sufficient size
191   vector<int> sorted;
192   for (int i=0; i<fWriters.size(); i++) {
193     assert(fWriters[i]);
194     if (fWriters[i]) {
195       if (sorted.size()>=0 && fWriters[i]->GetTotalMemorySize()>fWriters[sorted[0]]->GetTotalMemorySize()) {
196         sorted.insert(sorted.begin(), i);
197       } else {
198         sorted.push_back(i);
199       }
200     }
201   }
202
203   vector<int>::iterator ddlno=sorted.begin();
204   while (ddlno!=sorted.end()) {
205     const AliHLTUInt8_t* pBuffer=NULL;
206     int bufferSize=0;
207     
208     if ((bufferSize=FillOutputBuffer(eventNo, fWriters[*ddlno], pBuffer))>0) {
209       if (fWriteDigits) WriteDigits(eventNo, runLoader, *ddlno, pBuffer, bufferSize);
210       if (fWriteRaw) WriteRawFile(eventNo, runLoader, *ddlno, pBuffer, bufferSize);
211     }
212     ddlno++;
213   }
214   return iResult;
215 }
216
217 int AliHLTOUTComponent::ShuffleWriters(AliHLTMonitoringWriterPVector &list, AliHLTUInt32_t size)
218 {
219   // see header file for class documentation
220   int iResult=-ENOENT;
221   assert(list.size()>0);
222   if (list.size()==0) return iResult;
223   vector<int> writers;
224   int i=0;
225   for (i=0; i<list.size(); i++) {
226     if (list[i]->GetTotalMemorySize()==0)
227       writers.push_back(i);
228     else if (iResult<0 ||
229              list[i]->GetTotalMemorySize()<list[iResult]->GetTotalMemorySize())
230       iResult=i;
231       
232   }
233   if (writers.size()>0) {
234     iResult=writers[0];
235     if (writers.size()>0) {
236       // shuffle among the empty writers
237       TDatime dt;
238       TRandom rand;
239       rand.SetSeed(dt.Get()*(iResult+1));
240       i=rand.Integer(writers.size()-1);
241       assert(i>0 && i<writers.size()-1);
242       iResult=writers[i];
243     }
244   } else {
245     // take the writer with the least data volume
246     assert(iResult>=0);
247   }
248   return iResult;
249 }
250
251 int AliHLTOUTComponent::FillOutputBuffer(int eventNo, AliHLTMonitoringWriter* pWriter, const AliHLTUInt8_t* &pBuffer)
252 {
253   // see header file for class documentation
254   int iResult=0;
255   int bufferSize=0;
256
257   // space for common data header
258   bufferSize+=sizeof(AliRawDataHeader);
259   assert(sizeof(AliRawDataHeader)==24);
260
261   // space for HLT event header
262   bufferSize+=sizeof(AliHLTOUT::AliHLTOUTEventHeader);
263
264   // space for payload from the writer
265   if (pWriter) bufferSize+=pWriter->GetTotalMemorySize();
266
267   if (bufferSize>fBuffer.size())
268     fBuffer.resize(bufferSize);
269
270   if (bufferSize<=fBuffer.size()) {
271     AliRawDataHeader* pCDH=reinterpret_cast<AliRawDataHeader*>(&fBuffer[0]);
272     AliHLTOUT::AliHLTOUTEventHeader* pHLTH=reinterpret_cast<AliHLTOUT::AliHLTOUTEventHeader*>(&fBuffer[sizeof(AliRawDataHeader)]);
273     memset(pCDH, 0, sizeof(AliRawDataHeader));
274     memset(pHLTH, 0, sizeof(AliHLTOUT::AliHLTOUTEventHeader));
275     pHLTH->fVersion=1;
276     if (pWriter) {
277       // copy payload
278       pWriter->Copy(&fBuffer[sizeof(AliRawDataHeader)+sizeof(AliHLTOUT::AliHLTOUTEventHeader)], 0, 0, 0, 0);
279       pHLTH->fLength=pWriter->GetTotalMemorySize();
280       // set status bit to indicate HLT payload
281       pCDH->fStatusMiniEventID|=0x1<<(AliHLTOUT::fgkCDHStatusFlagsOffset+AliHLTOUT::fgkCDHFlagsHLTPayload);
282     }
283     pHLTH->fLength+=sizeof(AliHLTOUT::AliHLTOUTEventHeader);
284     pHLTH->fEventID=eventNo;
285
286     pCDH->fSize=sizeof(AliRawDataHeader)+pHLTH->fLength;
287     
288     pBuffer=&fBuffer[0];
289   } else {
290     pBuffer=NULL;
291     iResult=-ENOMEM;
292   }
293
294   return iResult;
295 }
296
297 int AliHLTOUTComponent::WriteDigits(int eventNo, AliRunLoader* runLoader, int hltddl, const AliHLTUInt8_t* pBuffer, int bufferSize)
298 {
299   // see header file for class documentation
300   int iResult=0;
301   return iResult;
302 }
303
304 int AliHLTOUTComponent::WriteRawFile(int eventNo, AliRunLoader* runLoader, int hltddl, const AliHLTUInt8_t* pBuffer, int bufferSize)
305 {
306   // see header file for class documentation
307   int iResult=0;
308   const char* fileName=AliDAQ::DdlFileName("HLT", hltddl);
309   assert(fileName!=NULL);
310   TString filePath(fileName);
311   if (fileName) {
312     ios::openmode filemode=(ios::openmode)0;
313     ofstream rawfile(filePath.Data(), filemode);
314     if (rawfile.good()) {
315       if (pBuffer && bufferSize>0) {
316         rawfile.write(reinterpret_cast<const char*>(pBuffer), bufferSize);
317       } else {
318         HLTWarning("writing zero length raw data file %s");
319       }
320       HLTDebug("wrote %d byte(s) to file %s", bufferSize, filePath.Data());
321     } else {
322       HLTError("can not open file %s for writing", filePath.Data());
323       iResult=-EBADF;
324     }
325     rawfile.close();
326   }
327   return iResult;
328 }