added new helper components to libAliHLTUtil (EsdCollector and AliHLTOUTPublisher...
[u/mrichter/AliRoot.git] / HLT / BASE / util / AliHLTOUTPublisherComponent.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   AliHLTOUTPublisherComponent.cxx
20     @author Matthias Richter
21     @date   2008-06-11
22     @brief  A data publisher for data block out of the HLTOUT data
23 */
24
25 #include <cstdlib>
26 #include "AliHLTOUTPublisherComponent.h"
27 #include "AliHLTOUT.h"
28 #include "TString.h"
29 #include "AliRawReader.h"
30
31 /** ROOT macro for the implementation of ROOT specific class methods */
32 ClassImp(AliHLTOUTPublisherComponent)
33
34 AliHLTOUTPublisherComponent::AliHLTOUTPublisherComponent()
35   :
36   fFilterRules(),
37   fMaxSize(0)
38 {
39   // see header file for class documentation
40   // or
41   // refer to README to build package
42   // or
43   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
44 }
45
46 AliHLTOUTPublisherComponent::~AliHLTOUTPublisherComponent()
47 {
48   // see header file for class documentation
49 }
50
51 const char* AliHLTOUTPublisherComponent::GetComponentID()
52 {
53   // see header file for class documentation
54   return "AliHLTOUTPublisher";
55 }
56
57 AliHLTComponentDataType AliHLTOUTPublisherComponent::GetOutputDataType()
58 {
59   // see header file for class documentation
60   if (fFilterRules.size()==1) return fFilterRules[0].fDataType;
61   if (fFilterRules.size()==0) return kAliHLTAnyDataType;
62   return kAliHLTMultipleDataType;
63 }
64
65 int AliHLTOUTPublisherComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
66 {
67   // see header file for class documentation
68   tgtList.clear();
69   AliHLTComponentBlockDataList::iterator desc=fFilterRules.begin();
70   while (desc!=fFilterRules.end()) {
71     AliHLTComponentDataTypeList::iterator type=tgtList.begin();
72     while (type!=tgtList.end()) {
73       if (*type==(*desc).fDataType) break;
74       type++;
75     }
76     if (type==tgtList.end()) tgtList.push_back((*desc).fDataType);
77     desc++;
78   }
79   return tgtList.size();
80 }
81
82 void AliHLTOUTPublisherComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
83 {
84   // see header file for class documentation
85   constBase=fMaxSize;
86   inputMultiplier=0.0; // there is no new data, just forwarded descriptors
87 }
88
89 AliHLTComponent* AliHLTOUTPublisherComponent::Spawn()
90 {
91   // see header file for class documentation
92   return new AliHLTOUTPublisherComponent;
93 }
94
95 int AliHLTOUTPublisherComponent::DoInit( int argc, const char** argv )
96 {
97   // see header file for class documentation
98   int iResult=0;
99   TString argument="";
100   int bMissingParam=0;
101   AliHLTComponentBlockData rule;
102   FillBlockData(rule);
103   for (int i=0; i<argc && iResult>=0; i++) {
104     argument=argv[i];
105     if (argument.IsNull()) continue;
106
107     // -datatype
108     if (argument.CompareTo("-datatype")==0) {
109       if ((bMissingParam=(i+2>=argc))) break;
110
111       if (!MatchExactly(rule.fDataType,kAliHLTAnyDataType)) {
112         // the data type has already been set, add to list
113         // and reset
114         fFilterRules.push_back(rule);
115         FillBlockData(rule);
116       }
117
118       SetDataType(rule.fDataType, argv[i+1], argv[i+2]);
119       i+=2;
120
121       // -origin
122     } else if (argument.CompareTo("-origin")==0) {
123       if ((bMissingParam=(i+1>=argc))) break;
124
125       if (!MatchExactly(rule.fDataType,kAliHLTAnyDataType)) {
126         // the data type has already been set, add to list
127         // and reset
128         fFilterRules.push_back(rule);
129         FillBlockData(rule);
130       }
131
132       SetDataType(rule.fDataType, NULL, argv[i+1]);
133       i+=1;
134
135       // -typeid
136     } else if (argument.CompareTo("-typeid")==0) {
137       if ((bMissingParam=(i+1>=argc))) break;
138
139       if (!MatchExactly(rule.fDataType,kAliHLTAnyDataType)) {
140         // the data type has already been set, add to list
141         // and reset
142         fFilterRules.push_back(rule);
143         FillBlockData(rule);
144       }
145
146       SetDataType(rule.fDataType, argv[i+1], NULL);
147       i+=1;
148
149       // -dataspec
150     } else if (argument.CompareTo("-dataspec")==0) {
151       if ((bMissingParam=(++i>=argc))) break;
152
153       if (rule.fSpecification!=kAliHLTVoidDataSpec) {
154         // the specification has already been set, add to list
155         // and reset
156         fFilterRules.push_back(rule);
157         FillBlockData(rule);
158       }
159
160       TString parameter(argv[i]);
161       parameter.Remove(TString::kLeading, ' '); // remove all blanks
162       char* pRemnant=NULL;
163       rule.fSpecification=strtoul(parameter.Data(), &pRemnant, 0);
164       if (pRemnant!=NULL && pRemnant[0]!=0) {
165         HLTError("invalid parameter/remnant (%s) for argument %s, number expected", pRemnant, argument.Data());
166         iResult=-EINVAL;
167       }
168     } else {
169       HLTError("unknown argument %s", argument.Data());
170       iResult=-EINVAL;
171       break;
172     }
173   }
174   if (iResult>=0) {
175     // add the pending rule or at least the empty default rule
176     fFilterRules.push_back(rule);
177     FillBlockData(rule);
178   }
179   return iResult;
180 }
181
182 int AliHLTOUTPublisherComponent::DoDeinit()
183 {
184   // see header file for class documentation
185   int iResult=0;
186   fFilterRules.clear();
187   return iResult;
188 }
189
190 int AliHLTOUTPublisherComponent::GetEvent( const AliHLTComponentEventData& /*evtData*/,
191                                            AliHLTComponentTriggerData& /*trigData*/,
192                                            AliHLTUInt8_t* outputPtr, 
193                                            AliHLTUInt32_t& size,
194                                            AliHLTComponentBlockDataList& outputBlocks )
195 {
196   // see header file for class documentation
197   int iResult=0;
198   unsigned int offset=0;
199   AliHLTOUT* pHLTOUT=NULL;
200   AliRawReader* pRawReader=GetRawReader();
201   if (pRawReader) {
202     pRawReader->Reset();
203     pHLTOUT=AliHLTOUT::New(pRawReader);
204 //   } else {
205     // this is just a hack and work-around for the missing HLT AliLoader.
206     // Because of that the AliRoot framework does not provide the digit tree.
207     // The HLTDigits.root file is opened directly in the AliHLTOUTDigitReader.
208     // Later, the TTree digit tree object must be fetched here and passed to
209     // the HLTOUT instance.
210     // Maybe it's obsolete anyhow: 
211     // 1. AliHLT reconstruction from digit data is not supported
212     // 2. When integrated into HLTOUHandler of type kChain, most likely the
213     //    AliRawReaderMemory will be used.
214     // The functionality is tested also with the AliHLTOUTDigitReader, for the
215     // mentioned reasons I comment this branch.
216 //     pHLTOUT=AliHLTOUT::New(NULL, GetEventCount());
217   } else {
218     if (GetEventCount()==0) {
219       HLTFatal("can not get RunLoader or RawReader, event processing aborted for current and subsequent events");
220     }
221     iResult=-ENODEV;
222   }
223   if (iResult>=0 && pHLTOUT) {
224     if ((iResult=pHLTOUT->Init())>=0) {
225       for (iResult=pHLTOUT->SelectFirstDataBlock();
226            iResult>=0;
227            iResult=pHLTOUT->SelectNextDataBlock()) {
228         AliHLTComponentDataType dt=kAliHLTVoidDataType;
229         AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
230         pHLTOUT->GetDataBlockDescription(dt, spec);
231         if (fFilterRules.size()>0) {
232           // check if the block is selected
233           unsigned int rule=0;
234           for (; rule<fFilterRules.size(); rule++) {
235             if (fFilterRules[rule].fDataType!=dt) continue;
236             if (fFilterRules[rule].fSpecification!=kAliHLTVoidDataSpec &&
237                 fFilterRules[rule].fSpecification!=spec) continue;
238             break;
239           }
240           // skip the block if none of the filter rules matches
241           if (rule>=fFilterRules.size()) continue;
242         }
243         const AliHLTUInt8_t* pBuffer=NULL;
244         AliHLTUInt32_t bufferSize=0;
245         if ((iResult=pHLTOUT->GetDataBuffer(pBuffer, bufferSize))>=0) {
246           if (bufferSize+offset<=size) {
247             memcpy(outputPtr+offset, pBuffer, bufferSize);
248             AliHLTComponentBlockData bd;
249             FillBlockData( bd );
250             bd.fOffset = offset;
251             bd.fSize = bufferSize;
252             bd.fDataType = dt;
253             bd.fSpecification = spec;
254             outputBlocks.push_back( bd );
255           } else {
256             // we keep the loop going in order to collect the full size
257             fMaxSize=offset+bufferSize;
258           }
259           offset+=bufferSize;
260         }
261       }
262       // -ENOENT is not an error but the return value for 'no more data block'
263       if (iResult==-ENOENT) iResult=0;
264
265       // indicate too little space in buffer for repeated processing
266       if (offset>size) {
267         iResult=-ENOSPC;
268       }
269     } else if (GetEventCount()<5) {
270       const char* message="";
271       if (GetEventCount()==4) message=", suppressing further messages";
272       HLTError("failed initializing HLTOUT%s", message);
273     }
274     AliHLTOUT::Delete(pHLTOUT);
275     pHLTOUT=NULL;
276   } else {
277     if (GetEventCount()==0) {
278       HLTFatal("can not create HLTOUT instance, event processing aborted for current and most likely subsequent events");
279     }
280     iResult=-ENODEV;
281   }
282
283   // finally set the output size
284   size=offset;
285
286   return iResult;
287 }