9656644c68273386406033177bd52dec71548009
[u/mrichter/AliRoot.git] / RAW / AliRawReader.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, 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 ///////////////////////////////////////////////////////////////////////////////
19 ///
20 /// This is the base class for reading raw data.
21 ///
22 /// The derived classes, which operate on concrete raw data formats,
23 /// should implement
24 /// - ReadHeader to read the next (data/equipment) header
25 /// - ReadNextData to read the next raw data block (=1 DDL)
26 /// - ReadNext to read a given number of bytes
27 /// - several getters like GetType
28 ///
29 /// Sequential access to the raw data is provided by the methods
30 /// ReadHeader, ReadNextData, ReadNextInt, ReadNextShort, ReadNextChar
31 ///
32 /// If only data from a specific detector (and a given range of DDL numbers)
33 /// should be read, this can be achieved by the Select method.
34 /// Several getters provide information about the current event and the
35 /// current type of raw data.
36 ///
37 ///////////////////////////////////////////////////////////////////////////////
38
39 #include <TClass.h>
40 #include <TPluginManager.h>
41 #include <TROOT.h>
42
43 #include <Riostream.h>
44 #include "AliRawReader.h"
45 #include "AliRawReaderFile.h"
46 #include "AliRawReaderDate.h"
47 #include "AliRawReaderRoot.h"
48 #include "AliDAQ.h"
49 #include "AliLog.h"
50
51 ClassImp(AliRawReader)
52
53
54 AliRawReader::AliRawReader() :
55   fEquipmentIdsIn(NULL),
56   fEquipmentIdsOut(NULL),
57   fRequireHeader(kTRUE),
58   fHeader(NULL),
59   fCount(0),
60   fSelectEquipmentType(-1),
61   fSelectMinEquipmentId(-1),
62   fSelectMaxEquipmentId(-1),
63   fSkipInvalid(kFALSE),
64   fSelectEventType(-1),
65   fSelectTriggerMask(0),
66   fErrorCode(0),
67   fEventNumber(-1),
68   fErrorLogs("AliRawDataErrorLog",100),
69   fHeaderSwapped(NULL)
70 {
71 // default constructor: initialize data members
72 // Allocate the swapped header in case of Mac
73 #ifndef R__BYTESWAP
74   fHeaderSwapped=new AliRawDataHeader();
75 #endif
76 }
77
78 Bool_t AliRawReader::LoadEquipmentIdsMap(const char *fileName)
79 {
80   // Open the mapping file
81   // and load the mapping data
82   ifstream input(fileName);
83   if (input.is_open()) {
84     Warning("AliRawReader","Equipment ID mapping file is found !");
85     const Int_t kMaxDDL = 256;
86     fEquipmentIdsIn = new TArrayI(kMaxDDL);
87     fEquipmentIdsOut = new TArrayI(kMaxDDL);
88     Int_t equipIn, equipOut;
89     Int_t nIds = 0;
90     while (input >> equipIn >> equipOut) {
91       if (nIds >= kMaxDDL) {
92         Error("AliRawReader","Too many equipment Id mappings found ! Truncating the list !");
93         break;
94       }
95       fEquipmentIdsIn->AddAt(equipIn,nIds); 
96       fEquipmentIdsOut->AddAt(equipOut,nIds);
97       nIds++;
98     }
99     fEquipmentIdsIn->Set(nIds);
100     fEquipmentIdsOut->Set(nIds);
101     input.close();
102     return kTRUE;
103   }
104   else {
105     Error("AliRawReader","equipment id map file is not found ! Skipping the mapping !");
106     return kFALSE;
107   }
108 }
109
110 AliRawReader::AliRawReader(const AliRawReader& rawReader) :
111   TObject(rawReader),
112   fEquipmentIdsIn(rawReader.fEquipmentIdsIn),
113   fEquipmentIdsOut(rawReader.fEquipmentIdsOut),
114   fRequireHeader(rawReader.fRequireHeader),
115   fHeader(rawReader.fHeader),
116   fCount(rawReader.fCount),
117   fSelectEquipmentType(rawReader.fSelectEquipmentType),
118   fSelectMinEquipmentId(rawReader.fSelectMinEquipmentId),
119   fSelectMaxEquipmentId(rawReader.fSelectMaxEquipmentId),
120   fSkipInvalid(rawReader.fSkipInvalid),
121   fSelectEventType(rawReader.fSelectEventType),
122   fSelectTriggerMask(rawReader.fSelectTriggerMask),
123   fErrorCode(0),
124   fEventNumber(-1),
125   fErrorLogs("AliRawDataErrorLog",100),
126   fHeaderSwapped(NULL)
127 {
128 // copy constructor
129 // Allocate the swapped header in case of Mac
130 #ifndef R__BYTESWAP
131   fHeaderSwapped=new AliRawDataHeader(*rawReader.fHeaderSwapped);
132 #endif
133 }
134
135 AliRawReader& AliRawReader::operator = (const AliRawReader& rawReader)
136 {
137 // assignment operator
138   fEquipmentIdsIn = rawReader.fEquipmentIdsIn;
139   fEquipmentIdsOut = rawReader.fEquipmentIdsOut;
140
141   fHeader = rawReader.fHeader;
142   fCount = rawReader.fCount;
143
144   fSelectEquipmentType = rawReader.fSelectEquipmentType;
145   fSelectMinEquipmentId = rawReader.fSelectMinEquipmentId;
146   fSelectMaxEquipmentId = rawReader.fSelectMaxEquipmentId;
147   fSkipInvalid = rawReader.fSkipInvalid;
148   fSelectEventType = rawReader.fSelectEventType;
149   fSelectTriggerMask = rawReader.fSelectTriggerMask;
150
151   fErrorCode = rawReader.fErrorCode;
152
153   fEventNumber = rawReader.fEventNumber;
154   fErrorLogs = *((TClonesArray*)rawReader.fErrorLogs.Clone());
155
156   return *this;
157 }
158
159 AliRawReader::~AliRawReader()
160 {
161   // destructor
162   // delete the mapping arrays if
163   // initialized
164   if (fEquipmentIdsIn) delete fEquipmentIdsIn;
165   if (fEquipmentIdsOut) delete fEquipmentIdsOut;
166   fErrorLogs.Delete();
167   if (fHeaderSwapped) delete fHeaderSwapped;
168 }
169
170 AliRawReader* AliRawReader::Create(const char *uri)
171 {
172   // RawReader's factory
173   // It instantiate corresponding raw-reader implementation class object
174   // depending on the URI provided
175   // Normal URIs point to files, while the URI starting with
176   // 'mem://:' or 'mem://<filename>' will create
177   // AliRawReaderDateOnline object which is supposed to be used
178   // in the online reconstruction
179
180   TString strURI = uri;
181
182   if (strURI.IsNull()) {
183     AliWarningClass("No raw-reader created");
184     return NULL;
185   }
186
187   AliRawReader *rawReader = NULL;
188   if (!strURI.BeginsWith("mem://")) {
189     AliInfoClass(Form("Creating raw-reader in order to read raw-data file: %s",strURI.Data()));
190     if (strURI.EndsWith("/")) {
191       rawReader = new AliRawReaderFile(strURI);
192     } else if (strURI.EndsWith(".root")) {
193       rawReader = new AliRawReaderRoot(strURI);
194     } else {
195       rawReader = new AliRawReaderDate(strURI);
196     }
197   }
198   else {
199     strURI.ReplaceAll("mem://","");
200     AliInfoClass(Form("Creating raw-reader in order to read events in shared memory (option=%s)",strURI.Data()));
201
202     TPluginManager* pluginManager = gROOT->GetPluginManager();
203     TString rawReaderName = "AliRawReaderDateOnline";
204     TPluginHandler* pluginHandler = pluginManager->FindHandler("AliRawReader", "online");
205     // if not, add a plugin for it
206     if (!pluginHandler) {
207       pluginManager->AddHandler("AliRawReader", "online", 
208                                 "AliRawReaderDateOnline", "RAWDatarecOnline", "AliRawReaderDateOnline(const char*)");
209       pluginHandler = pluginManager->FindHandler("AliRawReader", "online");
210     }
211     if (pluginHandler && (pluginHandler->LoadPlugin() == 0)) {
212       rawReader = (AliRawReader*)pluginHandler->ExecPlugin(1,strURI.Data());
213     }
214     else {
215       return NULL;
216     }
217   }
218
219   return rawReader;
220 }
221
222 Int_t AliRawReader::GetMappedEquipmentId() const
223 {
224   if (!fEquipmentIdsIn || !fEquipmentIdsOut) {
225     Error("AliRawReader","equipment Ids mapping is not initialized !");
226     return GetEquipmentId();
227   }
228   Int_t equipmentId = GetEquipmentId();
229   for(Int_t iId = 0; iId < fEquipmentIdsIn->GetSize(); iId++) {
230     if (equipmentId == fEquipmentIdsIn->At(iId)) {
231       equipmentId = fEquipmentIdsOut->At(iId);
232       break;
233     }
234   }
235   return equipmentId;
236 }
237
238 Int_t AliRawReader::GetDetectorID() const
239 {
240   // Get the detector ID
241   // The list of detector IDs
242   // can be found in AliDAQ.h
243   Int_t equipmentId;
244   if (fEquipmentIdsIn && fEquipmentIdsIn)
245     equipmentId = GetMappedEquipmentId();
246   else
247     equipmentId = GetEquipmentId();
248
249   if (equipmentId >= 0) {
250     Int_t ddlIndex;
251     return AliDAQ::DetectorIDFromDdlID(equipmentId,ddlIndex);
252   }
253   else
254     return -1;
255 }
256
257 Int_t AliRawReader::GetDDLID() const
258 {
259   // Get the DDL ID (within one sub-detector)
260   // The list of detector IDs
261   // can be found in AliDAQ.h
262   Int_t equipmentId;
263   if (fEquipmentIdsIn && fEquipmentIdsIn)
264     equipmentId = GetMappedEquipmentId();
265   else
266     equipmentId = GetEquipmentId();
267
268   if (equipmentId >= 0) {
269     Int_t ddlIndex;
270     AliDAQ::DetectorIDFromDdlID(equipmentId,ddlIndex);
271     return ddlIndex;
272   }
273   else
274     return -1;
275 }
276
277 void AliRawReader::Select(const char *detectorName, Int_t minDDLID, Int_t maxDDLID)
278 {
279 // read only data of the detector with the given name and in the given
280 // range of DDLs (minDDLID <= DDLID <= maxDDLID).
281 // no selection is applied if a value < 0 is used.
282   Int_t detectorID = AliDAQ::DetectorID(detectorName);
283   if(detectorID >= 0)
284     Select(detectorID,minDDLID,maxDDLID);
285 }
286
287 void AliRawReader::Select(Int_t detectorID, Int_t minDDLID, Int_t maxDDLID)
288 {
289 // read only data of the detector with the given ID and in the given
290 // range of DDLs (minDDLID <= DDLID <= maxDDLID).
291 // no selection is applied if a value < 0 is used.
292
293   fSelectEquipmentType = -1;
294
295   if (minDDLID < 0)
296     fSelectMinEquipmentId = AliDAQ::DdlIDOffset(detectorID);
297   else
298     fSelectMinEquipmentId = AliDAQ::DdlID(detectorID,minDDLID);
299
300   if (maxDDLID < 0)
301     fSelectMaxEquipmentId = AliDAQ::DdlID(detectorID,AliDAQ::NumberOfDdls(detectorID)-1);
302   else
303     fSelectMaxEquipmentId = AliDAQ::DdlID(detectorID,maxDDLID);
304 }
305
306 void AliRawReader::SelectEquipment(Int_t equipmentType, 
307                                    Int_t minEquipmentId, Int_t maxEquipmentId)
308 {
309 // read only data of the equipment with the given type and in the given
310 // range of IDs (minEquipmentId <= EquipmentId <= maxEquipmentId).
311 // no selection is applied if a value < 0 is used.
312
313   fSelectEquipmentType = equipmentType;
314   fSelectMinEquipmentId = minEquipmentId;
315   fSelectMaxEquipmentId = maxEquipmentId;
316 }
317
318 void AliRawReader::SelectEvents(Int_t type, ULong64_t triggerMask)
319 {
320 // read only events with the given type and optionally
321 // trigger mask.
322 // no selection is applied if a value < 0 is used.
323
324   fSelectEventType = type;
325   fSelectTriggerMask = triggerMask;
326 }
327
328 Bool_t AliRawReader::IsSelected() const
329 {
330 // apply the selection (if any)
331
332   if (fSkipInvalid && !IsValid()) return kFALSE;
333
334   if (fSelectEquipmentType >= 0)
335     if (GetEquipmentType() != fSelectEquipmentType) return kFALSE;
336
337   Int_t equipmentId;
338   if (fEquipmentIdsIn && fEquipmentIdsIn)
339     equipmentId = GetMappedEquipmentId();
340   else
341     equipmentId = GetEquipmentId();
342
343   if ((fSelectMinEquipmentId >= 0) && 
344       (equipmentId < fSelectMinEquipmentId))
345     return kFALSE;
346   if ((fSelectMaxEquipmentId >= 0) && 
347       (equipmentId > fSelectMaxEquipmentId))
348     return kFALSE;
349
350   return kTRUE;
351 }
352
353 Bool_t AliRawReader::IsEventSelected() const
354 {
355   // apply the event selection (if any)
356
357   // First check the event type
358   if (fSelectEventType >= 0) {
359     if (GetType() != (UInt_t) fSelectEventType) return kFALSE;
360   }
361
362   // Then check the trigger pattern and compared it
363   // to the required trigger mask
364   if (fSelectTriggerMask != 0) {
365     if ((GetClassMask() & fSelectTriggerMask) != fSelectTriggerMask) return kFALSE;
366   }
367
368   return kTRUE;
369 }
370
371 UInt_t AliRawReader::SwapWord(UInt_t x) const
372 {
373    // Swap the endianess of the integer value 'x'
374
375    return (((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) <<  8) |
376            ((x & 0x00ff0000U) >>  8) | ((x & 0xff000000U) >> 24));
377 }
378
379 UShort_t AliRawReader::SwapShort(UShort_t x) const
380 {
381    // Swap the endianess of the short value 'x'
382
383    return (((x & 0x00ffU) <<  8) | ((x & 0xff00U) >>  8)) ;
384 }
385
386 Bool_t AliRawReader::ReadNextInt(UInt_t& data)
387 {
388 // reads the next 4 bytes at the current position
389 // returns kFALSE if the data could not be read
390
391   while (fCount == 0) {
392     if (!ReadHeader()) return kFALSE;
393   }
394   if (fCount < (Int_t) sizeof(data)) {
395     Error("ReadNextInt", 
396           "too few data left (%d bytes) to read an UInt_t!", fCount);
397     return kFALSE;
398   }
399   if (!ReadNext((UChar_t*) &data, sizeof(data))) {
400     Error("ReadNextInt", "could not read data!");
401     return kFALSE;
402   }
403 #ifndef R__BYTESWAP
404   data=SwapWord(data);
405 #endif
406   return kTRUE;
407 }
408
409 Bool_t AliRawReader::ReadNextShort(UShort_t& data)
410 {
411 // reads the next 2 bytes at the current position
412 // returns kFALSE if the data could not be read
413
414   while (fCount == 0) {
415     if (!ReadHeader()) return kFALSE;
416   }
417   if (fCount < (Int_t) sizeof(data)) {
418     Error("ReadNextShort", 
419           "too few data left (%d bytes) to read an UShort_t!", fCount);
420     return kFALSE;
421   }
422   if (!ReadNext((UChar_t*) &data, sizeof(data))) {
423     Error("ReadNextShort", "could not read data!");
424     return kFALSE;
425   }
426 #ifndef R__BYTESWAP
427   data=SwapShort(data);
428 #endif
429   return kTRUE;
430 }
431
432 Bool_t AliRawReader::ReadNextChar(UChar_t& data)
433 {
434 // reads the next 1 byte at the current stream position
435 // returns kFALSE if the data could not be read
436
437   while (fCount == 0) {
438     if (!ReadHeader()) return kFALSE;
439   }
440   if (!ReadNext((UChar_t*) &data, sizeof(data))) {
441     Error("ReadNextChar", "could not read data!");
442     return kFALSE;
443   }
444   return kTRUE;
445 }
446
447
448 Int_t AliRawReader::CheckData() const
449 {
450 // check the consistency of the data
451 // derived classes should overwrite the default method which returns 0 (no err)
452
453   return 0;
454 }
455
456
457 void AliRawReader::DumpData(Int_t limit)
458 {
459 // print the raw data
460 // if limit is not negative, only the first and last "limit" lines of raw data
461 // are printed
462
463   Reset();
464   if (!ReadHeader()) {
465     Error("DumpData", "no header");
466     return;
467   }
468   printf("header:\n"
469          " type = %d  run = %d  ", GetType(), GetRunNumber());
470   if (GetEventId()) {
471     printf("event = %8.8x %8.8x\n", GetEventId()[1], GetEventId()[0]);
472   } else {
473     printf("event = -------- --------\n");
474   }
475   if (GetTriggerPattern()) {
476     printf(" trigger = %8.8x %8.8x  ",
477            GetTriggerPattern()[1], GetTriggerPattern()[0]);
478   } else {
479     printf(" trigger = -------- --------  ");
480   }
481   if (GetDetectorPattern()) {
482     printf("detector = %8.8x\n", GetDetectorPattern()[0]);
483   } else {
484     printf("detector = --------\n");
485   }
486   if (GetAttributes()) {
487     printf(" attributes = %8.8x %8.8x %8.8x  ",
488            GetAttributes()[2], GetAttributes()[1], GetAttributes()[0]);
489   } else {
490     printf(" attributes = -------- -------- --------  ");
491   }
492   printf("GDC = %d\n", GetGDCId());
493   printf("\n");
494
495   do {
496     printf("-------------------------------------------------------------------------------\n");
497     printf("LDC = %d\n", GetLDCId());
498
499     printf("equipment:\n"
500            " size = %d  type = %d  id = %d\n",
501            GetEquipmentSize(), GetEquipmentType(), GetEquipmentId());
502     if (GetEquipmentAttributes()) {
503       printf(" attributes = %8.8x %8.8x %8.8x  ", GetEquipmentAttributes()[2],
504              GetEquipmentAttributes()[1], GetEquipmentAttributes()[0]);
505     } else {
506       printf(" attributes = -------- -------- --------  ");
507     }
508     printf("element size = %d\n", GetEquipmentElementSize());
509
510     printf("data header:\n"
511            " size = %d  version = %d  valid = %d  compression = %d\n",
512            GetDataSize(), GetVersion(), IsValid(), IsCompressed());
513
514     printf("\n");
515     if (limit == 0) continue;
516
517     Int_t size = GetDataSize();
518     char line[70];
519     for (Int_t i = 0; i < 70; i++) line[i] = ' ';
520     line[69] = '\0';
521     Int_t pos = 0;
522     Int_t max = 16;
523     UChar_t byte;
524
525     for (Int_t n = 0; n < size; n++) {
526       if (!ReadNextChar(byte)) {
527         Error("DumpData", "couldn't read byte number %d\n", n);
528         break;
529       }
530       if (pos >= max) {
531         printf("%8.8x  %s\n", n-pos, line);
532         for (Int_t i = 0; i < 70; i++) line[i] = ' ';
533         line[69] = '\0';
534         pos = 0;
535         if ((limit > 0) && (n/max == limit)) {
536           Int_t nContinue = ((size-1)/max+1-limit) * max;
537           if (nContinue > n) {
538             printf(" [skipping %d bytes]\n", nContinue-n);
539             n = nContinue-1;
540             continue;
541           }
542         }
543       }
544       Int_t offset = pos/4;
545       if ((byte > 0x20) && (byte < 0x7f)) {
546         line[pos+offset] = byte;
547       } else {
548         line[pos+offset] = '.';
549       }
550       char hex[3];
551       sprintf(hex, "%2.2x", byte);
552       line[max+max/4+3+2*pos+offset] = hex[0];
553       line[max+max/4+4+2*pos+offset] = hex[1];
554       pos++;
555     }
556
557     if (pos > 0) printf("%8.8x  %s\n", size-pos, line);
558     printf("\n");
559            
560   } while (ReadHeader());
561 }
562
563 void AliRawReader::AddErrorLog(AliRawDataErrorLog::ERawDataErrorLevel level,
564                                Int_t code,
565                                const char *message)
566 {
567   // Add a raw data error message to the list
568   // of raw-data decoding errors
569   if (fEventNumber < 0) {
570     return;
571   }
572   Int_t ddlId = GetEquipmentId();
573   if (ddlId < 0) {
574     AliError("No ddl raw data have been read so far! Impossible to add a raw data error log!");
575     return;
576   }
577
578   Int_t prevEventNumber = -1;
579   Int_t prevDdlId = -1;
580   Int_t prevErrorCode = -1;
581   AliRawDataErrorLog *prevLog = (AliRawDataErrorLog *)fErrorLogs.Last();
582   if (prevLog) {
583     prevEventNumber = prevLog->GetEventNumber();
584     prevDdlId       = prevLog->GetDdlID();
585     prevErrorCode   = prevLog->GetErrorCode();
586   }
587
588   if ((prevEventNumber != fEventNumber) ||
589       (prevDdlId != ddlId) ||
590       (prevErrorCode != code)) {
591     new (fErrorLogs[fErrorLogs.GetEntriesFast()])
592       AliRawDataErrorLog(fEventNumber,
593                          ddlId,
594                          level,
595                          code,
596                          message);
597   }
598   else
599     if (prevLog) prevLog->AddCount();
600
601 }