c7f2ca1f2f24121cb1042b475ae5785aaca5768e
[u/mrichter/AliRoot.git] / HLT / rec / AliHLTOUTHomerCollection.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the                          * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8 //*                                                                        *
9 //* Permission to use, copy, modify and distribute this software and its   *
10 //* documentation strictly for non-commercial purposes is hereby granted   *
11 //* without fee, provided that the above copyright notice appears in all   *
12 //* copies and that both the copyright notice and this permission notice   *
13 //* appear in the supporting documentation. The authors make no claims     *
14 //* about the suitability of this software for any purpose. It is          *
15 //* provided "as is" without express or implied warranty.                  *
16 //**************************************************************************
17
18 /// @file   AliHLTOUTHomerCollection.cxx
19 /// @author Matthias Richter
20 /// @date   
21 /// @brief  General collection for HLTOUT data in DDL format.
22 ///
23
24 #include "AliHLTOUTHomerCollection.h"
25 #include "AliHLTHOMERLibManager.h"
26 #include "AliHLTHOMERReader.h"
27 #include "AliRawDataHeader.h"
28 #include "AliHLTEsdManager.h"
29 #include "AliDAQ.h"
30
31 /** ROOT macro for the implementation of ROOT specific class methods */
32 ClassImp(AliHLTOUTHomerCollection)
33
34 AliHLTOUTHomerCollection::AliHLTOUTHomerCollection(int event, AliHLTEsdManager* pEsdManager)
35   :
36   AliHLTOUTHomerBuffer(NULL, 0),
37   fEvent(event),
38   fpCurrent(NULL),
39   fpEsdManager(pEsdManager)
40 {
41   // constructor
42   //
43   // General collection for HLTOUT data in DDL format
44   // 
45   // see header file for class documentation
46 }
47
48 const int AliHLTOUTHomerCollection::fgkIdShift=16;
49
50 AliHLTOUTHomerCollection::~AliHLTOUTHomerCollection()
51 {
52   // destructor
53   if (fpManager) {
54     if (fpCurrent) fpManager->DeleteReader(fpCurrent);
55     fpCurrent=NULL;
56   }
57 }
58
59 int AliHLTOUTHomerCollection::GenerateIndex()
60 {
61   // Overloaded from AliHLTOUT
62   // step through all HLT ddls, create HOMER readers and
63   // scan data block
64   int iResult=0;
65   if (fpManager) {
66     Reset();
67     int firstLink=AliDAQ::DdlIDOffset("HLT");
68     int nofDDLs=AliDAQ::NumberOfDdls("HLT");
69     SelectEquipment(-1,firstLink, firstLink+nofDDLs);
70     UChar_t* pSrc=NULL;
71     while (ReadNextData(pSrc) && pSrc!=NULL && iResult>=0) {
72       AliHLTUInt32_t id=(GetEquipmentId());
73       unsigned int size=GetDataSize();
74
75       AliHLTHOMERReader* pReader=OpenReader(pSrc, size);
76
77       // we use the equipment id to identify the different homer blocks 
78       id<<=fgkIdShift;
79       if (pReader) {
80         iResult=ScanReader(pReader, id);
81         fpManager->DeleteReader(pReader);
82       }
83     }
84   } else {
85     iResult=-ENODEV;
86   }
87   return iResult;
88 }
89
90 int AliHLTOUTHomerCollection::GetDataBuffer(AliHLTUInt32_t index, const AliHLTUInt8_t* &pBuffer, 
91                                       AliHLTUInt32_t& size)
92 {
93   // Overloaded from AliHLTOUT: get data buffer at specified index
94   int iResult=0;
95   pBuffer=NULL;
96   size=0;
97   if (fpManager) {
98     Int_t id = Int_t(index>>fgkIdShift);
99     AliHLTUInt32_t blockNo=index&((0x1<<fgkIdShift)-1);
100
101     // block from the same ddl requested?
102     if (fpCurrent && GetEquipmentId()!=id) {
103       fpManager->DeleteReader(fpCurrent);
104       fpCurrent=NULL;
105     }
106
107     // open ddl for equipment id and create HOMER reader
108     if (!fpCurrent) {
109       Reset();
110       SelectEquipment(-1, id, id);
111       UChar_t* pSrc=NULL;
112       if (ReadNextData(pSrc) && pSrc!=NULL) {
113         int srcSize=GetDataSize();
114         fpCurrent=OpenReader(pSrc, srcSize);
115         if (fpCurrent && fpCurrent->ReadNextEvent()!=0) {
116           iResult=-ENODATA;
117         }
118       } else {
119         iResult=-ENOSYS;
120       }
121     }
122
123     // get data
124     if (fpCurrent) {
125       AliHLTMonitoringReader* pReader=fpCurrent;
126       if ((pBuffer=static_cast<const AliHLTUInt8_t*>(pReader->GetBlockData(blockNo)))!=NULL) {
127         size=pReader->GetBlockDataLength(blockNo);
128       } else {
129         iResult=-ENOENT;
130       }
131     }
132   } else {
133     iResult=-ENODEV;
134   }
135   return iResult;
136 }
137
138 AliHLTHOMERReader* AliHLTOUTHomerCollection::OpenReader(UChar_t* pSrc, unsigned int size)
139 {
140   // open HOMER reader for buffer
141   unsigned int offset=sizeof(AliHLTOUTEventHeader);
142   const AliRawDataHeader* pCDH=GetDataHeader();
143   AliHLTUInt32_t id=(GetEquipmentId());
144   AliHLTUInt32_t statusFlags=pCDH->GetStatus();
145   AliHLTOUTEventHeader* pHLTHeader=reinterpret_cast<AliHLTOUTEventHeader*>(pSrc);
146
147   // consistency check for the block size
148   if (pHLTHeader->fLength>size) {
149     HLTError("can not treat HLT data block %d: size mismatch, header %d, but buffer is %d", id, pHLTHeader->fLength, size);
150     return NULL;
151   } else if (pHLTHeader->fLength<size-3) {
152     // data payload is aligned to 32bit, so there can be a difference by at most 3 bytes
153     HLTWarning("size mismatch in HLT data block %d: header %d, but buffer is %d", id, pHLTHeader->fLength, size);
154   }
155
156   // determine the offset of the homer block
157   // the HLT header is mandatory, HLT decision and HLT
158   // payload are optional. HLT decision is always before HLT
159   // payload if existent.
160   if (statusFlags&(0x1<<kCDHFlagsHLTDecision)) {
161     // the block contains HLT decision data, this is just
162     // skipped here
163     AliHLTUInt32_t* pDecisionLen=reinterpret_cast<AliHLTUInt32_t*>(pSrc+offset);
164     if ((*pDecisionLen)*sizeof(AliHLTUInt32_t)+offset<size) {
165       // the first 32bit word specifies the number of 32bit words in the
166       // decision block -> +1 for this length word
167       offset+=((*pDecisionLen)+1)*sizeof(AliHLTUInt32_t);
168     } else {
169       HLTWarning("size mismatch: HLT decision block bigger than total block length, skipping ...");
170       return NULL;
171     }
172   }
173
174   // check if there is payload
175   if (!(statusFlags&(0x1<<kCDHFlagsHLTPayload))) return NULL;
176
177   // continue if there is no data left in the buffer
178   if (offset>=pHLTHeader->fLength) {
179     HLTWarning("no HLT payload available, but bit is set, skipping ...");
180     return NULL;
181   }
182
183   // check for the HOME descriptor type id
184   AliHLTUInt64_t* pHomerDesc=reinterpret_cast<AliHLTUInt64_t*>(pSrc+offset);
185   if (*(pHomerDesc+kID_64b_Offset) != HOMER_BLOCK_DESCRIPTOR_TYPEID && 
186       ByteSwap64(*(pHomerDesc+kID_64b_Offset)) != HOMER_BLOCK_DESCRIPTOR_TYPEID) {
187     HLTWarning("format error: can not find HOMER block descriptor typid, skipping this data block");
188     return NULL;
189   }
190
191   AliHLTUInt64_t eventId=pHLTHeader->fEventIDHigh;
192   eventId = eventId<<32;
193   eventId|=pHLTHeader->fEventIDLow;
194   SetEventId(eventId);
195   return fpManager->OpenReaderBuffer(pSrc+offset, pHLTHeader->fLength-offset);
196 }
197
198 int AliHLTOUTHomerCollection::WriteESD(const AliHLTUInt8_t* pBuffer, AliHLTUInt32_t size, AliHLTComponentDataType dt, AliESDEvent* tgtesd) const
199 {
200   // write ESD
201   if (!pBuffer && size<=0) return -EINVAL;
202   int iResult=0;
203   if (fpEsdManager) {
204     fpEsdManager->WriteESD(pBuffer, size, dt, tgtesd, GetCurrentEventNo());
205   }
206   return iResult;
207 }