New flat raw-data event format. The details can be found at: http://indico.cern.ch...
[u/mrichter/AliRoot.git] / RAW / AliRawEventHeaderBase.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 // Author: Cvetan Cheshkov  10/10/2005
19
20 //////////////////////////////////////////////////////////////////////////
21 //                                                                      //
22 // AliRawEventHeaderBase                                                //
23 // This a new versioning scheme for raw data root-ification and reading //
24 // For details look at offline weekly meeting 20/10/2005                //
25 //                                                                      //
26 //////////////////////////////////////////////////////////////////////////
27
28 #include <unistd.h>
29
30 #include <Bytes.h>
31 #include <TClass.h>
32 #include <TDataMember.h>
33 #include <TList.h>
34 #include <TMethodCall.h>
35
36 #include "AliLog.h"
37 #include "AliRawEventHeaderBase.h"
38
39 #include <Riostream.h>
40
41 ClassImp(AliRawEventHeaderBase)
42
43 //______________________________________________________________________________
44 AliRawEventHeaderBase::AliRawEventHeaderBase():
45 fSize(0),
46 fMagic(0),
47 fHeadSize(0),
48 fVersion(0),
49 fExtendedDataSize(0),
50 fExtendedAllocSize(0),
51 fExtendedData(NULL),
52 fIsSwapped(kFALSE),
53 fHeaderSize(0),
54 fHeaderBegin(NULL),
55 fFirstEqIndex(-1),
56 fLastEqIndex(-1)
57 {
58   // Default constructor
59 }
60
61 //______________________________________________________________________________
62 void *AliRawEventHeaderBase::HeaderBegin() const
63 {
64   // Returns the pointer to the first data member
65   // beyond the base class data members
66
67   if (fHeaderBegin) return fHeaderBegin;
68
69   TList *datalist = IsA()->GetListOfDataMembers();
70   TIter next(datalist);                           
71   TDataMember *member = (TDataMember *)next();
72
73   if(!strcmp(member->GetTypeName(),"TClass"))
74     member = (TDataMember *)next();
75
76   void *ptr = (void *)((char *)this+member->GetOffset());
77   const_cast<AliRawEventHeaderBase*>(this)->fHeaderBegin = ptr;
78
79   return ptr;
80 }
81
82 //______________________________________________________________________________
83 Int_t AliRawEventHeaderBase::HeaderSize() const
84 {
85   // Returns the size of the data members list
86   // beyond the base class data members
87
88   if (fHeaderSize) return fHeaderSize;
89
90   Int_t size = 0;
91
92   TList *datalist = IsA()->GetListOfDataMembers();
93   TIter next(datalist);                           
94   TDataMember *member;
95   while ((member=(TDataMember *)next()) != 0x0) {
96     if (!strcmp(member->GetTypeName(),"TClass")) continue;
97     UInt_t unitsize = member->GetUnitSize();
98     UInt_t ndim = member->GetArrayDim();
99     if (ndim == 0)
100       size += unitsize;
101     else
102       for(UInt_t i=0;i<ndim;i++) size += member->GetMaxIndex(i)*unitsize;
103   }
104
105   const_cast<AliRawEventHeaderBase*>(this)->fHeaderSize = size;
106
107   return size;
108 }
109
110 //______________________________________________________________________________
111 UInt_t AliRawEventHeaderBase::SwapWord(UInt_t x) const
112 {
113    // Swap the endianess of the integer value 'x'
114
115    return (((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) <<  8) |
116            ((x & 0x00ff0000U) >>  8) | ((x & 0xff000000U) >> 24));
117 }
118
119 void AliRawEventHeaderBase::Swap()
120 {
121    // Swap base header data.
122    // Update the fIsSwapped flag which
123    // is then use to copy in an appropriate way
124    // the rest of the header data from the raw data stream
125
126    if (IsSwapped()) {
127       fIsSwapped    = kTRUE;
128       fSize         = SwapWord(fSize);
129       fMagic        = SwapWord(fMagic);
130       fHeadSize     = SwapWord(fHeadSize);
131       fVersion      = SwapWord(fVersion);
132    }
133 }
134
135 //______________________________________________________________________________
136 const char *AliRawEventHeaderBase::GetTypeName() const
137 {
138    // Get event type as a string.
139    // Will fail in case data header
140    // does not contain eventType field
141    UInt_t eventType = Get("Type");
142
143    return GetTypeName(eventType);
144 }
145
146 //______________________________________________________________________________
147 const char *AliRawEventHeaderBase::GetTypeName(UInt_t eventType)
148 {
149   // Get event type as a string.
150   // Static method that could be used
151   // from everywhere inside aliroot
152
153    switch (eventType) {
154       case kStartOfRun:
155          return "START_OF_RUN";
156          break;
157       case kEndOfRun:
158          return "END_OF_RUN";
159          break;
160       case kStartOfRunFiles:
161          return "START_OF_RUN_FILES";
162          break;
163       case kEndOfRunFiles:
164          return "END_OF_RUN_FILES";
165          break;
166       case kStartOfBurst:
167          return "START_OF_BURST";
168          break;
169       case kEndOfBurst:
170          return "END_OF_BURST";
171          break;
172       case kPhysicsEvent:
173          return "PHYSICS_EVENT";
174          break;
175       case kCalibrationEvent:
176          return "CALIBRATION_EVENT";
177          break;
178       case kFormatError:
179          return "EVENT_FORMAT_ERROR";
180          break;
181       case kStartOfData:
182          return "START_OF_DATA";
183          break;
184       case kEndOfData:
185          return "END_OF_DATA";
186          break;
187       case kSystemSoftwareTriggerEvent:
188          return "SYSTEM_SOFTWARE_TRIGGER_EVENT";
189          break;
190       case kDetectorSoftwareTriggerEvent:
191          return "DETECTOR_SOFTWARE_TRIGGER_EVENT";
192          break;
193       default:
194          return "UNKNOWN EVENT TYPE NUMBER";
195          break;
196    }
197 }
198
199 //______________________________________________________________________________
200 AliRawEventHeaderBase* AliRawEventHeaderBase::Create(char*& data)
201 {
202   // Static method to create AliRawEventHeaderVX object
203   // The actual header class version is taken from the
204   // raw data
205
206   // First create AlirawEVentHeaderBase class object
207   AliRawEventHeaderBase header;
208
209   // Copy the first common part of the raw data header
210   memcpy(header.HeaderBaseBegin(), data, header.HeaderBaseSize());
211  
212     // Swap header data if needed
213   if (header.IsSwapped())
214     header.Swap();
215
216   // Is header valid...
217   if (!header.IsValid()) {
218     AliFatalClass("Invalid header format!");
219     // try recovery... how?
220     return 0x0;
221   }
222
223   if (header.GetEventSize() < (UInt_t)header.HeaderBaseSize()) {
224     AliFatalClass("Invalid header base size!");
225     // try recovery... how?
226     return 0x0;
227   }
228
229   // Now check the DATE version and create the corresponding header
230   // class object
231   UInt_t version = header.GetVersion();
232   UInt_t majorversion = (version>>16)&0x0000ffff;
233   UInt_t minorversion = version&0x0000ffff;
234   TString classname;
235   classname.Form("AliRawEventHeaderV%d_%d",majorversion,minorversion);
236     
237   TClass *tcl = TClass::GetClass(classname.Data());
238   if (!tcl) {
239     AliFatalClass(Form("Unknown header version (%s)!",classname.Data()));
240     return 0x0;
241   }
242
243   //  header.Dump(); tcl->Dump();
244
245   AliRawEventHeaderBase *hdr = (AliRawEventHeaderBase *)tcl->New();
246   if (!hdr) {
247     AliFatalClass(Form("Can not create object of class %s",classname.Data()));
248     return 0x0;
249   }
250
251   // Copy the base header data members and initialize other data members
252   memcpy(hdr->HeaderBaseBegin(),header.HeaderBaseBegin(), header.HeaderBaseSize());
253   memset(hdr->HeaderBegin(),0, hdr->HeaderSize());
254   hdr->fIsSwapped = header.fIsSwapped;
255
256   // Consistency check
257   if (hdr->GetEventSize() < ((UInt_t)hdr->HeaderBaseSize() + (UInt_t)hdr->HeaderSize())) {
258     AliFatalClass(Form("Invalid header size (%d < %d +%d)!",
259                        hdr->GetEventSize(),hdr->HeaderBaseSize(),hdr->HeaderSize()));
260     // try recovery... how?
261     return 0x0;
262   }
263
264   // Check for the presence of header extension and its size
265   Int_t extsize = (Int_t)hdr->GetHeadSize() - (hdr->HeaderBaseSize() + hdr->HeaderSize());
266   if (extsize < 0) {
267     AliFatalClass(Form("Invalid header size (%d < %d +%d)!",
268                        hdr->GetHeadSize(),hdr->HeaderBaseSize(),hdr->HeaderSize()));
269     // try recovery... how?
270     return 0x0;
271   }
272   else {
273     if (extsize > 0) {
274       hdr->AllocateExtendedData(extsize);
275     }
276   }
277
278   return hdr;
279 }
280
281 void AliRawEventHeaderBase::SwapData(const void* inbuf, const void* outbuf, UInt_t size) {
282   // The method swaps the contents of the
283   // raw-data event header
284   UInt_t  intCount = size/sizeof(UInt_t);
285
286   UInt_t* buf = (UInt_t*) inbuf;    // temporary integers buffer
287   for (UInt_t i=0; i<intCount; i++, buf++) {
288       UInt_t value = SwapWord(*buf);
289       memcpy((UInt_t*)outbuf+i, &value, sizeof(UInt_t)); 
290   }
291 }
292
293 //______________________________________________________________________________
294 Int_t AliRawEventHeaderBase::ReadHeader(char*& data)
295 {
296   // Read header info from DATE data stream.
297   // Returns bytes read
298
299   Long_t start = (Long_t)data;
300   // Swap header data if needed
301   if (DataIsSwapped()) {
302     SwapData(data, HeaderBaseBegin(), HeaderBaseSize());
303     data += HeaderBaseSize();
304     SwapData(data, HeaderBegin(), HeaderSize());
305     data += HeaderSize();
306   }
307   else {
308     memcpy(HeaderBaseBegin(), data, HeaderBaseSize());
309     data += HeaderBaseSize();
310     memcpy(HeaderBegin(), data, HeaderSize());
311     data += HeaderSize();
312   }
313   data += ReadExtendedData(data);
314
315   return (Int_t)((Long_t)data - start);
316 }
317
318 //______________________________________________________________________________
319 void AliRawEventHeaderBase::AllocateExtendedData(Int_t extsize)
320 {
321   // Allocate the space for the header
322   // extended data
323   if (fExtendedData) delete [] fExtendedData;
324   
325   fExtendedDataSize = fExtendedAllocSize = extsize;
326   fExtendedData = new char[fExtendedAllocSize];
327   memset(fExtendedData,0,fExtendedAllocSize);
328 }
329
330 //______________________________________________________________________________
331 Int_t AliRawEventHeaderBase::ReadExtendedData(char*& data)
332 {
333   // Read extended header data
334   // Reallocates memory if the present
335   // buffer is insufficient
336   Int_t extsize = (Int_t)GetHeadSize() - (HeaderBaseSize() + HeaderSize());
337
338   if (extsize == 0) {
339     fExtendedDataSize = 0;
340     return 0;
341   }
342
343   if (extsize < 0) {
344     AliFatal(Form("Invalid header size (%d < %d +%d)!",
345                   GetHeadSize(),HeaderBaseSize(),HeaderSize()));
346     // try recovery... how?
347     return 0;
348   }
349
350   fExtendedDataSize = extsize;
351   if (fExtendedDataSize > fExtendedAllocSize)
352     AllocateExtendedData(fExtendedDataSize);
353
354   if (DataIsSwapped())
355     SwapData(data, fExtendedData, fExtendedDataSize);
356   else
357     memcpy(fExtendedData, data, fExtendedDataSize);
358
359   return fExtendedDataSize;
360 }
361
362 //______________________________________________________________________________
363 UInt_t AliRawEventHeaderBase::Get(const char *datamember) const
364 {
365   // The method to get a data member from the header object
366   // Except for the data members of the base class, all the
367   // other header data should be retrieved ONLY by this method
368   // The name of the data member should be supplied without "f"
369   // in front
370
371   char buf[256] = "f";
372   strcat(buf,datamember);
373
374   TDataMember *member = IsA()->GetDataMember(buf);
375   if (!member) {
376     AliFatal(Form("No data member %s is found! Check the raw data version!",buf));
377     return 0;
378   }
379
380   if (member->GetArrayDim() != 0) {
381     AliFatal(Form("Member %s is an array! Use the GetP() method!",buf));
382     return 0;
383   }
384
385   if (strcmp(member->GetTypeName(),"UInt_t") != 0) {
386     AliFatal(Form("Member %s is not of type UInt_t!",buf));
387     return 0;
388   }
389
390   const void *pointer = (char *)this+member->GetOffset();
391
392   return *((UInt_t *)pointer);
393 }
394
395 //______________________________________________________________________________
396 const UInt_t* AliRawEventHeaderBase::GetP(const char *datamember) const
397 {
398   // The method to get a data member from the header object
399   // Except for the data members of the base class, all the
400   // other header data should be retrieved ONLY by this method
401   // The name of the data member should be supplied without "f"
402   // in front
403
404   char buf[256] = "f";
405   strcat(buf,datamember);
406
407   TDataMember *member = IsA()->GetDataMember(buf);
408   if (!member) {
409     AliFatal(Form("No data member %s is found! Check the raw data version!",buf));
410     return 0;
411   }
412
413   //  if (member->GetArrayDim() == 0) {
414   //    AliFatal(Form("Member %s is not an array! Use the Get() method!",buf));
415   //    return 0;
416   //  }
417
418   if (strcmp(member->GetTypeName(),"UInt_t") != 0) {
419     AliFatal(Form("Member %s is not of type UInt_t*!",buf));
420     return 0;
421   }
422
423   const void *pointer = (char *)this+member->GetOffset();
424
425   return (const UInt_t*)pointer;
426 }
427
428 //_____________________________________________________________________________
429 void AliRawEventHeaderBase::Print( const Option_t* opt ) const
430 {
431   // Dumps the event or sub-event
432   // header fields
433
434   cout << opt << "  Event size: " << GetEventSize() << endl;
435   cout << opt << "  Event header size: " << GetHeadSize() << endl;
436   cout << opt << "  Event header version: " << GetMajorVersion() << "." << GetMinorVersion() << endl;
437   cout << opt << "  Event type: " << Get("Type") << "( " << GetTypeName() << " )" << endl;
438   cout << opt << "  Run Number: " << Get("RunNb") << endl;
439   const UInt_t *id = GetP("Id");
440   cout << opt << "  Period: " << (((id)[0]>>4)&0x0fffffff) << " Orbit: " << ((((id)[0]<<20)&0xf00000)|(((id)[1]>>12)&0xfffff)) << " Bunch-crossing: " << ((id)[1]&0x00000fff) << endl;
441   cout << opt << "  Trigger pattern: " << GetP("TriggerPattern")[0] << "-" << GetP("TriggerPattern")[1] << endl;
442   cout << opt << "  Detector pattern: " << Get("DetectorPattern") << endl;
443   cout << opt << "  Type attribute: " << GetP("TypeAttribute")[0] << "-" << GetP("TypeAttribute")[1] << "-" << GetP("TypeAttribute")[2] << endl;
444   cout << opt << "  GDC: " << Get("GdcId") << " LDC: " << Get("LdcId") << endl;
445 }
446
447 //_____________________________________________________________________________
448 void AliRawEventHeaderBase::AddEqIndex(Int_t index)
449 {
450   // Adds an equipment by changing properly
451   // the first and last equipment indexes
452   if (fFirstEqIndex < 0) fFirstEqIndex = index; 
453   if (index > fLastEqIndex) fLastEqIndex = index;
454 }
455
456 //_____________________________________________________________________________
457 void AliRawEventHeaderBase::Reset()
458 {
459   fFirstEqIndex = fLastEqIndex = -1;
460 }
461
462 //______________________________________________________________________________
463 void AliRawEventHeaderBase::Streamer(TBuffer &R__b)
464 {
465    // Stream an object of class AliRawEventHeaderBase.
466
467    if (R__b.IsReading()) {
468       UInt_t R__s, R__c;
469       Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
470       if (R__v > 3) {
471         R__b.ReadClassBuffer(AliRawEventHeaderBase::Class(),this,R__v,R__s,R__c);
472         return;
473       }
474       TObject::Streamer(R__b);
475       R__b >> fSize;
476       R__b >> fMagic;
477       R__b >> fHeadSize;
478       R__b >> fVersion;
479       R__b >> fExtendedDataSize;
480       delete [] fExtendedData;
481       fExtendedData = new char[fExtendedDataSize];
482       R__b.ReadFastArray(fExtendedData,fExtendedDataSize);
483       R__b >> fIsSwapped;
484       R__b.CheckByteCount(R__s, R__c, AliRawEventHeaderBase::IsA());
485    } else {
486       R__b.WriteClassBuffer(AliRawEventHeaderBase::Class(),this);
487    }
488 }