potential memory leak fixed (Kenneth); sequential (non-bunch) reading implemented...
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTAltroChannelSelectorComponent.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   AliHLTAltroChannelSelectorComponent.cxx
20     @author Matthias Richter
21     @date   
22     @brief  A filter/selective readout component for TPC Altro data. */
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 #include <cassert>
31 #include "AliHLTAltroChannelSelectorComponent.h"
32 #include "AliHLTTPCTransform.h"
33 #include "AliHLTTPCDefinitions.h"
34 #include "AliAltroDecoder.h"
35 #include "AliAltroData.h"
36
37 /** ROOT macro for the implementation of ROOT specific class methods */
38 ClassImp(AliHLTAltroChannelSelectorComponent)
39
40 AliHLTAltroChannelSelectorComponent::AliHLTAltroChannelSelectorComponent()
41   :
42   AliHLTProcessor(),
43   fSkipCorrupted(false),
44   fTalkative(false)
45 {
46   // see header file for class documentation
47   // or
48   // refer to README to build package
49   // or
50   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
51 }
52
53 AliHLTAltroChannelSelectorComponent::~AliHLTAltroChannelSelectorComponent()
54 {
55   // see header file for class documentation
56 }
57
58 const char* AliHLTAltroChannelSelectorComponent::GetComponentID()
59 {
60   // see header file for class documentation
61   return "AltroChannelSelector";
62 }
63
64 void AliHLTAltroChannelSelectorComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list)
65 {
66   // see header file for class documentation
67   list.clear();
68   list.push_back(kAliHLTDataTypeDDLRaw|kAliHLTDataOriginTPC);
69   list.push_back(kAliHLTDataTypeHwAddr16);
70 }
71
72 AliHLTComponentDataType AliHLTAltroChannelSelectorComponent::GetOutputDataType()
73 {
74   // see header file for class documentation
75   return kAliHLTDataTypeDDLRaw|kAliHLTDataOriginTPC;
76 }
77
78 void AliHLTAltroChannelSelectorComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
79 {
80   // see header file for class documentation
81   constBase=0;
82   inputMultiplier=1.0;
83 }
84
85 AliHLTComponent* AliHLTAltroChannelSelectorComponent::Spawn()
86 {
87   // see header file for class documentation
88   return new AliHLTAltroChannelSelectorComponent;
89 }
90
91 int AliHLTAltroChannelSelectorComponent::DoInit(int argc, const char** argv)
92 {
93   // see header file for class documentation
94   int iResult=0;
95   TString argument="";
96   bool bMissingParam=0;
97   for (int i=0; i<argc && iResult>=0; i++) {
98     argument=argv[i];
99     if (argument.IsNull()) continue;
100
101     // -skip-corrupted
102     if (argument.CompareTo("-skip-corrupted")==0) {
103       fSkipCorrupted=true;
104
105     // -talkative
106     } else if (argument.CompareTo("-talkative")==0) {
107       fTalkative=true;
108     } else {
109       HLTError("unknown argument %s", argument.Data());
110       iResult=-EINVAL;
111     }
112   }
113
114   if (bMissingParam) {
115     HLTError("missing parameter for argument %s", argument.Data());
116     iResult=-EINVAL;
117   }
118
119   return iResult;
120 }
121
122 int AliHLTAltroChannelSelectorComponent::DoDeinit()
123 {
124   // see header file for class documentation
125   return 0;
126 }
127
128 int AliHLTAltroChannelSelectorComponent::DoEvent(const AliHLTComponentEventData& evtData,
129                                                  const AliHLTComponentBlockData* blocks, 
130                                                  AliHLTComponentTriggerData& /*trigData*/,
131                                                  AliHLTUInt8_t* outputPtr, 
132                                                  AliHLTUInt32_t& size,
133                                                  AliHLTComponentBlockDataList& outputBlocks )
134 {
135   // see header file for class documentation
136   int iResult=0;
137   const int cdhSize=32;
138
139   // process the DLL input
140   int blockno=0;
141   const AliHLTComponentBlockData* pDesc=NULL;
142
143   AliAltroDecoder* decoder=NULL;
144   for (pDesc=GetFirstInputBlock(kAliHLTDataTypeDDLRaw); pDesc!=NULL; pDesc=GetNextInputBlock(), blockno++) {
145     iResult=0;
146
147     // search for the active pad information
148     AliHLTUInt16_t* pActiveHwAddressArray=NULL;
149     int iArraySize=0;
150     for (int i=0; i<(int)evtData.fBlockCnt; i++ ) {
151       // search for selection data of hw address type
152       // which matches the data specification of the block
153       if (blocks[i].fDataType==kAliHLTDataTypeHwAddr16 && blocks[i].fSpecification==pDesc->fSpecification) {
154         pActiveHwAddressArray=reinterpret_cast<AliHLTUInt16_t*>(blocks[i].fPtr);
155         iArraySize=blocks[i].fSize/sizeof(AliHLTUInt16_t);
156         break;
157       }
158     }
159     if (pActiveHwAddressArray==NULL) {
160       HLTWarning("no block of type %s for specification 0x%08x available, data block unchanged", 
161                  DataType2Text(kAliHLTDataTypeHwAddr16).c_str(), 
162                  pDesc->fSpecification);
163       iResult=-EFAULT;
164     }
165
166     if (decoder) delete decoder;
167     decoder=new AliAltroDecoder;
168     if (decoder->SetMemory(reinterpret_cast<UChar_t*>(pDesc->fPtr), pDesc->fSize)<0) {
169       HLTWarning("corrupted data block: initialization of decoder failed for block: %s specification %#x size %d",
170                  DataType2Text(pDesc->fDataType).c_str(), pDesc->fSpecification, pDesc->fSize);
171       iResult=-EFAULT;
172     } else {
173       if (decoder->Decode()) {
174         HLTDebug("init decoder %p size %d", pDesc->fPtr,pDesc->fSize);
175       } else {
176         HLTWarning("corrupted data block: decoding failed for raw data block: %s specification %#x size %d",
177                    DataType2Text(pDesc->fDataType).c_str(), pDesc->fSpecification, pDesc->fSize);
178         iResult=-EFAULT;
179       }
180     }
181
182     int rcuTrailerLength=decoder->GetRCUTrailerSize();
183     if (rcuTrailerLength*sizeof(AliHLTUInt32_t)>pDesc->fSize-cdhSize) {
184       HLTWarning("corrupted data block: RCU trailer length exceeds buffer size");
185       iResult=-EFAULT;
186     }
187
188     if (iResult<0) {
189       // forward the whole block
190       outputBlocks.push_back(*pDesc);
191       continue;
192     }
193
194     int iSelected=0;
195     int iTotal=0;
196     int iCorrupted=0;
197     AliHLTUInt32_t iOutputSize=0;
198     AliHLTUInt32_t iNofAltro40=0;
199     AliHLTUInt32_t iCapacity=size;
200     AliAltroData channel;
201     while (decoder->NextChannel(&channel) && iResult>=0) {
202       iTotal++;
203
204       int hwAddress=channel.GetHadd();
205       int active=0;
206       for (active=0; active<iArraySize; active++) {
207         if (pActiveHwAddressArray[active]==(AliHLTUInt16_t)hwAddress) {
208           break;
209         }
210       }
211       if (active>=iArraySize) {
212         HLTDebug("ALTRO block %#x (%d) discarded (inactive)", hwAddress, hwAddress);
213         continue;
214       }
215
216       // no of 10 bit words is without the fill words to fill complete 40 bit words
217       // in addition, align to complete 40 bit words (the '+3')
218       // also, the 5 bytes of the Altro trailer must be added to get the full size
219       int channelSize=((channel.GetDataSize()+3)/4)*5;
220       channelSize+=5;
221       HLTDebug("ALTRO block hwAddress 0x%08x (%d) selected (active), size %d", hwAddress, hwAddress, channelSize);
222       if (iOutputSize==0) {
223         // first add the RCU trailer
224         AliHLTUInt8_t* pSrc=reinterpret_cast<AliHLTUInt8_t*>(pDesc->fPtr);
225         pSrc+=pDesc->fSize-rcuTrailerLength;
226         if ((iResult=CopyBlockToEnd(outputPtr, iCapacity, iOutputSize, pSrc, rcuTrailerLength))>=0) {
227           assert(iResult==rcuTrailerLength);
228           iOutputSize+=rcuTrailerLength;
229         } else {
230           HLTError("failed to write RCU trailer of length %d for block %d, too little space in output buffer?", rcuTrailerLength, blockno);
231           iResult=-ENOSPC;
232           break;
233         }
234       }
235
236       if ((iResult=decoder->CopyBackward(outputPtr, iCapacity-iOutputSize))>=0) {
237         if (channelSize == iResult) {
238           if (channelSize%5 == 0) {
239             iNofAltro40+=channelSize/5;
240             iOutputSize+=channelSize;
241           } else {
242             if (fTalkative) HLTWarning("corrupted ALTRO channel: incomplete 40 bit word");
243             iCorrupted++;
244             continue;
245           }
246         } else {
247           if (fTalkative) HLTWarning("internal error: failed to copy full channel: %d out of %d bytes", iResult, channelSize);
248           iCorrupted++;
249           continue;
250         }
251       } else {
252         if (fTalkative) HLTError("failed to write ALTRO channel of length %d for block %d", channelSize, blockno);
253         // corrupted channel, but keep going
254         iCorrupted++;
255         iResult=0;
256         continue;
257       }
258       iSelected++;
259     }
260     if (iResult>=0) {
261       // write the common data header
262       if ((iResult=CopyBlockToEnd(outputPtr, iCapacity, iOutputSize, pDesc->fPtr, cdhSize))>=0) {
263         assert(iResult==cdhSize);
264         iOutputSize+=cdhSize;
265
266         // set new length of the data block
267         AliHLTUInt32_t* pCdhSize=reinterpret_cast<AliHLTUInt32_t*>(outputPtr+iCapacity-iOutputSize);
268         *pCdhSize=iOutputSize;
269
270         // set number of Altro words
271         AliHLTUInt32_t* pNofAltro40=reinterpret_cast<AliHLTUInt32_t*>(outputPtr+iCapacity-rcuTrailerLength);
272         *pNofAltro40=iNofAltro40;
273
274         // insert block descriptor
275         AliHLTComponentBlockData bd;
276         FillBlockData(bd);
277         bd.fOffset=iCapacity-iOutputSize;
278         bd.fSize=iOutputSize;
279         bd.fDataType=pDesc->fDataType;
280         bd.fSpecification=pDesc->fSpecification;
281         outputBlocks.push_back(bd);
282         iCapacity-=iOutputSize;
283       } else {
284         HLTError("failed to write CDH of length %d for block %d", cdhSize, blockno);
285         break;
286       }
287     }
288     HLTInfo("data block %d (0x%08x): selected %d out of %d ALTRO channel(s), %d corrupted channels skipped", blockno, pDesc->fSpecification, iSelected, iTotal, iCorrupted);
289   }
290   if (decoder) delete decoder;
291
292   if (iResult<0) {
293     outputBlocks.clear();
294   }
295
296   // !!! do not change the size since the output buffer is filled from the end !!!
297
298   return iResult;
299 }
300
301 int AliHLTAltroChannelSelectorComponent::CopyBlockToEnd(AliHLTUInt8_t* pTgt, unsigned capacity, unsigned position, void* pSrc, unsigned size)
302 {
303   int iResult=0;
304   if (pTgt==NULL || pSrc==NULL) return -EINVAL;
305   if (capacity-position<size) return -ENOSPC;
306   
307   memcpy(pTgt+(capacity-position-size), pSrc, size);
308   iResult=size;
309   
310   return iResult;
311 }