Minor fix to avoid compilation problems with DATE installed
[u/mrichter/AliRoot.git] / RAW / AliMDC.cxx
1 // @(#)alimdc:$Name$:$Id$
2 // Author: Fons Rademakers  26/11/99
3 // Updated: Dario Favretto  15/04/2003
4
5 /**************************************************************************
6  * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
7  *                                                                        *
8  * Author: The ALICE Off-line Project.                                    *
9  * Contributors are mentioned in the code where appropriate.              *
10  *                                                                        *
11  * Permission to use, copy, modify and distribute this software and its   *
12  * documentation strictly for non-commercial purposes is hereby granted   *
13  * without fee, provided that the above copyright notice appears in all   *
14  * copies and that both the copyright notice and this permission notice   *
15  * appear in the supporting documentation. The authors make no claims     *
16  * about the suitability of this software for any purpose. It is          *
17  * provided "as is" without express or implied warranty.                  *
18  **************************************************************************/
19
20 /* $Id$ */
21
22 //////////////////////////////////////////////////////////////////////////
23 //                                                                      //
24 // AliMDC                                                               //
25 //                                                                      //
26 // Set of classes defining the ALICE RAW event format. The AliRawEvent  //
27 // class defines a RAW event. It consists of an AliEventHeader object   //
28 // an AliEquipmentHeader object, an AliRawData object and an array of   //
29 // sub-events, themselves also being AliRawEvents. The number of        //
30 // sub-events depends on the number of DATE LDC's.                      //
31 // The AliRawEvent objects are written to a ROOT file using different   //
32 // technologies, i.e. to local disk via AliRawDB or via rfiod using     //
33 // AliRawRFIODB or via rootd using AliRawRootdDB or to CASTOR via       //
34 // rootd using AliRawCastorDB (and for performance testing there is     //
35 // also AliRawNullDB).                                                  //
36 // The AliRunDB class provides the interface to the run and file        //
37 // catalogues (AliEn or plain MySQL).                                   //
38 // The AliStats class provides statics information that is added as     //
39 // a single keyed object to each raw file.                              //
40 // The AliTagDB provides an interface to a TAG database.                //
41 // The AliMDC class is usid by the "alimdc" stand-alone program         //
42 // that reads data directly from DATE.                                  //
43 //                                                                      //
44 //////////////////////////////////////////////////////////////////////////
45
46 #include <sys/types.h>
47 #include <sys/stat.h>
48
49 #include <errno.h>
50
51 #include <TSystem.h>
52 #include <TError.h>
53 #include <TStopwatch.h>
54
55 #ifdef ALI_DATE
56 #include "event.h"
57 #endif
58 #ifdef USE_EB
59 #include "libDateEb.h"
60 #endif
61
62 #ifdef USE_HLT
63 #include <AliL3StandardIncludes.h>
64 #ifndef use_logging
65 #include "AliL3Logging.h"
66 #endif
67 #include <AliL3Transform.h>
68 #include "AliRawReaderRoot.h"
69 #include <AliL3Hough.h>
70 #include <AliESD.h>
71 #endif
72
73 #include "AliRawEvent.h"
74 #include "AliRawEventHeader.h"
75 #include "AliRawEquipment.h"
76 #include "AliRawEquipmentHeader.h"
77 #include "AliRawData.h"
78 #include "AliStats.h"
79 #include "AliRawDB.h"
80 #include "AliRawRFIODB.h"
81 #include "AliRawCastorDB.h"
82 #include "AliRawRootdDB.h"
83 #include "AliRawNullDB.h"
84 #include "AliTagDB.h"
85
86 #include "AliMDC.h"
87
88
89 ClassImp(AliMDC)
90
91
92 #define ALIDEBUG(level) \
93    if (AliMDC::Instance() && (AliMDC::Instance()->GetDebugLevel() >= (level)))
94
95
96 // Fixed file system locations for the different DB's
97 #ifdef USE_RDM
98 const char* const AliMDC::fgkFifo       = "/tmp/alimdc.fifo";
99 const char* const AliMDC::fgkRawDBFS[2] = { "/tmp/mdc1", "/tmp/mdc2" };
100 const char* const AliMDC::fgkTagDBFS    = "/tmp/mdc1/tags";
101 const char* const AliMDC::fgkRunDBFS    = "/tmp/mdc1/meta";
102 const char* const AliMDC::fgkRFIOFS     = "rfio:/castor/cern.ch/user/r/rdm";
103 const char* const AliMDC::fgkCastorFS   = "castor:/castor/cern.ch/user/r/rdm";
104 const char* const AliMDC::fgkRootdFS    = "root://localhost//tmp/mdc1";
105 const char* const AliMDC::fgkAlienHost  = "alien://aliens7.cern.ch:15000/?direct";
106 const char* const AliMDC::fgkAlienDir   = "/alice_mdc/DC";
107 #else
108 const char* const AliMDC::fgkFifo       = "/tmp/alimdc.fifo";
109 const char* const AliMDC::fgkRawDBFS[2] = { "/data1/mdc", "/data2/mdc" };
110 const char* const AliMDC::fgkTagDBFS    = "/data1/mdc/tags";
111 const char* const AliMDC::fgkRunDBFS    = "/data1/mdc/meta";
112 const char* const AliMDC::fgkRFIOFS     = "rfio:/castor/cern.ch/lcg/dc5";
113 const char* const AliMDC::fgkCastorFS   = "castor:/castor/cern.ch/lcg/dc5";
114 const char* const AliMDC::fgkRootdFS    = "root://localhost//tmp/mdc1";
115 const char* const AliMDC::fgkAlienHost  = "alien://aliens7.cern.ch:15000/?direct";
116 const char* const AliMDC::fgkAlienDir   = "/alice_mdc/DC";
117 #endif
118
119 // Maximum size of tag db files
120 const Double_t AliMDC::fgkMaxTagFileSize = 2.5e8;    // 250MB
121
122 Bool_t AliMDC::fgDeleteFiles = kFALSE;
123 AliMDC* AliMDC::fgInstance = NULL;
124
125
126 //______________________________________________________________________________
127 AliMDC::AliMDC(Int_t fd, Int_t compress, Double_t maxFileSize, Bool_t useFilter,
128                EWriteMode mode, Bool_t useLoop, Bool_t delFiles)
129 {
130    // Create MDC processor object.
131
132    fFd           = fd;
133    fCompress     = compress;
134    fMaxFileSize  = maxFileSize;
135    fUseFilter    = useFilter;
136    fWriteMode    = mode;
137    fUseLoop      = useLoop;
138    fUseFifo      = kFALSE;
139    fUseEb        = kFALSE;
140    fStopLoop     = kFALSE;
141    fNumEvents    = 0;
142    fDebugLevel   = 0;
143    fgDeleteFiles = delFiles;
144
145    if (fFd == -1) {
146 #ifdef USE_EB
147      if (!ebRegister()) {
148         Error("AliMDC", "cannot register with the event builder (%s)",
149               ebGetLastError());
150         return;
151      }
152      fUseEb = kTRUE;
153 #else
154      if ((mkfifo(fgkFifo, 0644) < 0) && (errno != EEXIST)) {
155          Error("AliMDC", "cannot create fifo %s", fgkFifo);
156          return;
157       }
158       if ((chmod(fgkFifo, 0666) == -1) && (errno != EPERM)) {
159          Error("AliMDC", "cannot change permission of fifo %s", fgkFifo);
160          return;
161       }
162       if ((fFd = open(fgkFifo, O_RDONLY)) == -1) {
163          Error("AliMDC", "cannot open input file %s", fgkFifo);
164          return;
165       }
166       fUseFifo = kTRUE;
167 #endif
168       fUseLoop = kFALSE;
169    }
170
171    printf("<AliMDC::AliMDC>: input = %s, rawdb size = %f, filter = %s, "
172           "looping = %s, compression = %d, delete files = %s",
173           fUseFifo ? "fifo" : (fUseEb ? "eb" : "file"), fMaxFileSize,
174           fUseFilter ? "on" : "off", fUseLoop ? "yes" : "no", fCompress,
175           fgDeleteFiles ? "yes" : "no");
176    if (fWriteMode == kRFIO)
177       printf(", use RFIO\n");
178    else if (fWriteMode == kROOTD)
179       printf(", use rootd\n");
180    else if (fWriteMode == kCASTOR)
181       printf(", use CASTOR/rootd\n");
182    else if (fWriteMode == kDEVNULL)
183       printf(", write raw data to /dev/null\n");
184    else
185       printf("\n");
186
187    // install SIGUSR1 handler to allow clean interrupts
188    gSystem->AddSignalHandler(new AliMDCInterruptHandler(this));
189
190    fgInstance = this;
191 }
192
193 //______________________________________________________________________________
194 AliMDC::AliMDC(const AliMDC& mdc): TObject(mdc)
195 {
196 // copy constructor
197
198   Fatal("AliMDC", "copy constructor not implemented");
199 }
200
201 //______________________________________________________________________________
202 AliMDC& AliMDC::operator = (const AliMDC& /*mdc*/)
203 {
204 // assignment operator
205
206   Fatal("operator =", "assignment operator not implemented");
207   return *this;
208 }
209
210 //______________________________________________________________________________
211 Int_t AliMDC::Run()
212 {
213    // Run the MDC processor. Read from the input stream and only return
214    // when the input gave and EOF or a fatal error occured. On success 0
215    // is returned, 1 in case of a fatality.
216
217    TStopwatch timer;
218    Int_t status;
219
220    // Make sure needed directories exist
221    const char *dirs[4];
222    dirs[0] = fgkRawDBFS[0];
223    dirs[1] = fgkRawDBFS[1];
224    dirs[2] = fgkTagDBFS;
225    dirs[3] = fgkRunDBFS;
226    for (int idir = 0; idir < 4; idir++) {
227       gSystem->ResetErrno();
228       gSystem->MakeDirectory(dirs[idir]);
229       if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
230          SysError("Run", "mkdir %s", dirs[idir]);
231          return 1;
232       }
233    }
234
235    // Used for statistics
236    timer.Start();
237    Double_t told = 0, tnew = 0;
238    Float_t  chunkSize = fMaxFileSize/100, nextChunk = chunkSize;
239
240    // Event object used to store event data.
241    AliRawEvent *event = new AliRawEvent;
242 #ifdef USE_HLT
243    //Init HLT
244 #ifndef use_logging
245    AliL3Log::fgLevel=AliL3Log::kError;
246    ALIDEBUG(1)
247      AliL3Log::fgLevel=AliL3Log::kWarning;
248    ALIDEBUG(2)
249      AliL3Log::fgLevel=AliL3Log::kWarning;
250    ALIDEBUG(3)
251      AliL3Log::fgLevel=AliL3Log::kNone;
252 #endif
253    if (!AliL3Transform::Init("./", kFALSE)) {
254      Error("Run","HLT initialization failed!");
255      return 1;
256    }
257
258    AliESD *esd = new AliESD;
259 #endif
260
261    // Create new raw DB.
262    AliRawDB *rawdb;
263    if (fWriteMode == kRFIO)
264       rawdb = new AliRawRFIODB(event, esd, fMaxFileSize, fCompress);
265    else if (fWriteMode == kROOTD)
266       rawdb = new AliRawRootdDB(event, esd, fMaxFileSize, fCompress);
267    else if (fWriteMode == kCASTOR)
268       rawdb = new AliRawCastorDB(event, esd, fMaxFileSize, fCompress);
269    else if (fWriteMode == kDEVNULL)
270       rawdb = new AliRawNullDB(event, esd, fMaxFileSize, fCompress);
271    else
272       rawdb = new AliRawDB(event, esd, fMaxFileSize, fCompress);
273
274    if (rawdb->IsZombie()) return 1;
275    printf("Filling raw DB %s\n", rawdb->GetDBName());
276
277    // Create new tag DB.
278    AliTagDB *tagdb = 0;
279 #if 0
280    // no tagdb for the time being to get maximum speed
281    if (fWriteMode == fgkDEVNULL)
282       tagdb = new AliTagNullDB(event->GetHeader(), fgkMaxTagFileSize);
283    else
284       tagdb = new AliTagDB(event->GetHeader(), fgkMaxTagFileSize);
285    if (tagdb->IsZombie())
286       tagdb = 0;
287    else
288       printf("Filling tag DB %s\n", tagdb->GetDBName());
289 #endif
290
291    // Create AliStats object
292    AliStats *stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter);
293
294    // Shortcut for easy header access
295    AliRawEventHeader &header = *event->GetHeader();
296
297    // Process input stream
298 #ifdef USE_EB
299    Int_t eorFlag = 0;
300    while (!(eorFlag = ebEor())) {
301       struct iovec *ebvec;
302       if ((ebvec = ebGetNextEvent()) == (void *)-1) {
303          Error("Run", "error getting next event (%s)", ebGetLastError());
304          break;
305       }
306       if (ebvec == 0) {
307          // no event, sleep for 1 second and try again
308          gSystem->Sleep(1000);
309          continue;
310       }
311       char *ebdata = (char *) ebvec[0].iov_base;
312 #else
313    while (1) {
314       char *ebdata = 0;
315 #endif
316
317       // Read event header
318       if ((status = ReadHeader(header, ebdata)) != header.HeaderSize()) {
319          if (status == 0) {
320             if (fUseLoop) {
321 #ifndef USE_EB
322                ::lseek(fFd, 0, SEEK_SET);
323 #endif
324                continue;
325             }
326             printf("<AliMDC::Run>: EOF, processed %d events\n", fNumEvents);
327             break;
328          }
329          return 1;
330       }
331       ALIDEBUG(3)
332          header.Dump();
333
334       // If we were in looping mode stop directly after a SIGUSR1 signal
335       if (StopLoop()) {
336          Info("Run", "Stopping loop, processed %d events", fNumEvents);
337          break;
338       }
339
340       // Check if event has any hard track flagged
341       Bool_t callFilter = kFALSE;
342       if (fUseFilter)
343         callFilter = kTRUE;
344
345       // Check event type and skip "Start of Run", "End of Run",
346       // "Start of Run Files" and "End of Run Files"
347       switch (header.GetType()) {
348          case AliRawEventHeader::kStartOfRun:
349          case AliRawEventHeader::kEndOfRun:
350          case AliRawEventHeader::kStartOfRunFiles:
351          case AliRawEventHeader::kEndOfRunFiles:
352             {
353                Int_t skip = header.GetEventSize() - header.HeaderSize();
354 #ifndef USE_EB
355                ::lseek(fFd, skip, SEEK_CUR);
356 #endif
357                ALIDEBUG(1)
358                   Info("Run", "Skipping %s (%d bytes)", header.GetTypeName(), skip);
359                continue;
360             }
361          default:
362             ALIDEBUG(1) {
363                Int_t s = header.GetEventSize() - header.HeaderSize();
364                Info("Run", "Processing %s (%d bytes)", header.GetTypeName(), s);
365             }
366       }
367
368       // Amount of data left to read for this event
369       Int_t toRead = header.GetEventSize() - header.HeaderSize();
370
371       // If there is less data for this event than the next sub-event
372       // header, something is wrong. Skip to next event...
373       if (toRead < header.HeaderSize()) {
374          ALIDEBUG(1) {
375             Warning("Run",
376                     "header size (%d) exceeds number of bytes to read (%d)\n",
377                     header.HeaderSize(), toRead);
378             header.Dump();
379          }
380          if ((status = DumpEvent(toRead)) != toRead) {
381             if (status == 0)
382                break;
383             return 1;
384          }
385          Error("Run", "discarding event %d (too little data for header)", fNumEvents);
386          continue;
387       }
388
389       // Loop over all sub-events... (LDCs)
390       Int_t nsub = 1;
391       while (toRead > 0) {
392 #ifdef USE_EB
393          ebdata = (char *)ebvec[nsub].iov_base;
394 #endif
395
396          ALIDEBUG(1)
397             Info("Run", "reading LDC %d", nsub);
398
399          AliRawEvent *subEvent = event->NextSubEvent();
400
401          // Read sub-event header
402          AliRawEventHeader &subHeader = *subEvent->GetHeader();
403          if ((status = ReadHeader(subHeader, ebdata)) != subHeader.HeaderSize()) {
404             if (status == 0) {
405                Error("Run", "unexpected EOF reading sub-event header");
406                break;
407             }
408             return 1;
409          }
410
411          ALIDEBUG(3)
412             subHeader.Dump();
413
414          toRead -= subHeader.HeaderSize();
415
416 #ifdef USE_EB
417          ebdata = (char *)(ebvec[nsub].iov_base) + subHeader.HeaderSize();
418 #endif
419
420          Int_t rawSize = subHeader.GetEventSize() - subHeader.HeaderSize();
421
422          // Make sure raw data less than left over bytes for current event
423          if (rawSize > toRead) {
424             ALIDEBUG(1) {
425                Warning("Run", "raw data size (%d) exceeds number of "
426                        "bytes to read (%d)\n", rawSize, toRead);
427                subHeader.Dump();
428             }
429             if ((status = DumpEvent(toRead)) != toRead) {
430                if (status == 0)
431                   break;
432                return 1;
433             }
434             Error("Run", "discarding event %d (too much data)", fNumEvents);
435             continue;
436          }
437
438          // Read Equipment Headers (in case of physics or calibration event)
439          if (header.GetType() == AliRawEventHeader::kPhysicsEvent ||
440              header.GetType() == AliRawEventHeader::kCalibrationEvent) {
441             while (rawSize > 0) {
442                AliRawEquipment &equipment = *subEvent->NextEquipment();
443                AliRawEquipmentHeader &equipmentHeader = 
444                   *equipment.GetEquipmentHeader();
445                Int_t equipHeaderSize = equipmentHeader.HeaderSize();
446                if ((status = ReadEquipmentHeader(equipmentHeader, header.DataIsSwapped(),
447                                                  ebdata)) != equipHeaderSize) {
448                   if (status == 0) {
449                      Error("Run", "unexpected EOF reading equipment-header");
450                      break;
451                   }
452                   return 1;
453                }
454                toRead  -= equipHeaderSize;
455                rawSize -= equipHeaderSize;
456 #ifdef USE_EB
457                ebdata = (char *)(ebvec[nsub].iov_base) +
458                         subHeader.HeaderSize() + equipHeaderSize;
459 #endif
460
461                // Read equipment raw data
462                AliRawData &subRaw = *equipment.GetRawData();
463
464                Int_t eqSize = equipmentHeader.GetEquipmentSize() -
465                                equipHeaderSize;
466                if ((status = ReadRawData(subRaw, eqSize, ebdata)) != eqSize) {
467                   if (status == 0) {
468                      Error("Run", "unexpected EOF reading sub-event raw data");
469                      break;
470                   }
471                   return 1;
472                }
473                toRead  -= eqSize;
474                rawSize -= eqSize;
475
476             }
477
478          } else {  // Read only raw data but no equipment header
479             AliRawEquipment &equipment = *subEvent->NextEquipment();
480             AliRawData &subRaw = *equipment.GetRawData();
481             if ((status = ReadRawData(subRaw, rawSize, ebdata)) != rawSize) {
482                if (status == 0) {
483                   Error("Run", "unexpected EOF reading sub-event raw data");
484                   break;
485                }
486                return 1;
487             }
488             toRead  -= rawSize;
489
490          }
491
492          nsub++;
493       }
494
495       //HLT
496       if (callFilter) {
497 #ifdef ALI_DATE
498         if(header.GetType() == AliRawEventHeader::kPhysicsEvent ||
499            header.GetType() == AliRawEventHeader::kCalibrationEvent)
500           Filter(
501 #ifdef USE_HLT
502                  event,esd
503 #endif
504                  );
505 #endif
506       }
507
508       // Set stat info for first event of this file
509       if (rawdb->GetEvents() == 0)
510          stats->SetFirstId(header.GetRunNumber(), header.GetEventInRun());
511
512       // Store raw event in tree
513       rawdb->Fill();
514
515       // Store header in tree
516       if (tagdb) tagdb->Fill();
517
518       fNumEvents++;
519
520       if (!(fNumEvents%10))
521          printf("Processed event %d (%d)\n", fNumEvents, rawdb->GetEvents());
522
523       // Filling time statistics
524       if (rawdb->GetBytesWritten() > nextChunk) {
525          tnew = timer.RealTime();
526          stats->Fill(tnew-told);
527          told = tnew;
528          timer.Continue();
529          nextChunk += chunkSize;
530       }
531
532       // Check size of raw db. If bigger than maxFileSize, close file
533       // and continue with new file.
534       if (rawdb->FileFull()) {
535
536          printf("Written raw DB at a rate of %.1f MB/s\n",
537                 rawdb->GetBytesWritten() / timer.RealTime() / 1000000.);
538
539          // Write stats object to raw db, run db, MySQL and AliEn
540          stats->WriteToDB(rawdb);
541          delete stats;
542
543          if (!rawdb->NextFile()) {
544             Error("Run", "error opening next raw data file");
545             return 1;
546          }
547
548          printf("Filling raw DB %s\n", rawdb->GetDBName());
549          stats = new AliStats(rawdb->GetDBName(), fCompress, fUseFilter);
550
551          timer.Start();
552          told = 0, tnew = 0;
553          nextChunk = chunkSize;
554       }
555
556       // Check size of tag db
557       if (tagdb && tagdb->FileFull()) {
558          if (!tagdb->NextFile())
559             tagdb = 0;
560          else
561             printf("Filling tag DB %s\n", tagdb->GetDBName());
562       }
563
564       // Make top event object ready for next event data
565       //printf("Event %d has %d sub-events\n", fNumEvents, event->GetNSubEvents());
566       event->Reset();
567 #ifdef USE_HLT
568       // Clean up HLT ESD for the next event
569       // Probably we could add esd->Reset() method to AliESD?
570       esd->Reset();
571 #endif
572 #ifdef USE_EB
573       if (!ebReleaseEvent(ebvec)) {
574          Error("Run", "problem releasing event (%s)", ebGetLastError());
575          break;
576       }
577 #endif
578    }
579
580    printf("Written raw DB at a rate of %.1f MB/s\n",
581           rawdb->GetBytesWritten() / timer.RealTime() / 1000000.);
582
583    // Write stats to raw db and run db and delete stats object
584    stats->WriteToDB(rawdb);
585    delete stats;
586
587    // Close the raw DB
588    delete rawdb;
589
590    // Close the tag DB
591    delete tagdb;
592
593    // Close input source
594    close(fFd);
595
596 #if 0
597    // Cleanup fifo
598    if (fUseFifo && ::unlink(fgkFifo) == -1) {
599       SysError("Run", "unlink");
600       return 1;
601    }
602 #endif
603
604 #ifdef USE_EB
605    // Print eor flag
606    if (eorFlag) {
607       Info("Run", "event builder reported end of run (%d)", eorFlag);
608    }
609 #endif
610
611    return 0;
612 }
613
614 //______________________________________________________________________________
615 Int_t AliMDC::Read(void *buffer, Int_t length)
616 {
617    // Read exactly length bytes into buffer. Returns number of bytes
618    // received, returns -1 in case of error and 0 for EOF.
619
620    errno = 0;
621
622    if (fFd < 0) return -1;
623
624    Int_t n, nrecv = 0;
625    char *buf = (char *)buffer;
626
627    for (n = 0; n < length; n += nrecv) {
628       if ((nrecv = read(fFd, buf+n, length-n)) <= 0) {
629          if (nrecv == 0)
630             break;        // EOF
631          if (errno != EINTR)
632             SysError("Read", "read");
633          return -1;
634       }
635    }
636    return n;
637 }
638
639 //______________________________________________________________________________
640 Int_t AliMDC::ReadHeader(AliRawEventHeader &header, void *eb)
641 {
642    // Read header info from DATE data stream. Returns bytes read (i.e.
643    // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
644
645    Int_t nrecv;
646
647    if (eb) {
648       // read from event builder memory area
649       memcpy(header.HeaderBegin(), eb, header.HeaderSize());
650       nrecv = header.HeaderSize();
651    } else {
652       // read from fifo or file
653       if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) !=
654            header.HeaderSize()) {
655          if (nrecv == 0)
656             return 0;
657          return -1;
658       }
659    }
660
661    // Swap header data if needed
662    if (header.IsSwapped())
663       header.Swap();
664
665    // Is header valid...
666    if (!header.IsValid()) {
667       Error("ReadHeader", "invalid header format");
668       // try recovery... how?
669       return -1;
670    }
671    if (header.GetEventSize() < (UInt_t)header.HeaderSize()) {
672       Error("ReadHeader", "invalid header size");
673       // try recovery... how?
674       return -1;
675    }
676
677    return nrecv;
678 }
679
680 //______________________________________________________________________________
681 Int_t AliMDC::ReadEquipmentHeader(AliRawEquipmentHeader &header,
682                                   Bool_t isSwapped, void *eb)
683 {
684    // Read equipment header info from DATE data stream. Returns bytes read
685    // (i.e. AliRawEquipmentHeader::HeaderSize()), -1 in case of error and
686    // 0 for EOF. If isSwapped is kTRUE the event data is byte swapped
687    // and we will swap the header to host format.
688
689    Int_t nrecv;
690
691    if (eb) {
692       // read from event builder memory area
693       memcpy(header.HeaderBegin(), eb, header.HeaderSize());
694       nrecv = header.HeaderSize();
695    } else {
696       // read from fifo or file
697       if ((nrecv = Read(header.HeaderBegin(), header.HeaderSize())) !=
698            header.HeaderSize()) {
699          if (nrecv == 0)
700             return 0;
701          return -1;
702       }
703    }
704
705    // Swap equipment header data if needed
706    if (isSwapped)
707       header.Swap();
708
709    if (header.GetEquipmentSize() < (UInt_t)header.HeaderSize()) {
710       Error("ReadEquipmentHeader", "invalid equipment header size");
711       // try recovery... how?
712       return -1;
713    }
714
715    return nrecv;
716 }
717
718 //______________________________________________________________________________
719 Int_t AliMDC::ReadRawData(AliRawData &raw, Int_t size, void *eb)
720 {
721    // Read raw data from DATE data stream. Returns bytes read (i.e.
722    // AliRawEventHeader::HeaderSize()), -1 in case of error and 0 for EOF.
723
724    Int_t nrecv;
725
726    if (eb) {
727       // read from event builder memory area
728       raw.SetBuffer(eb, size);
729       nrecv = size;
730    } else {
731       // read from fifo or file
732       raw.SetSize(size);
733       if ((nrecv = Read(raw.GetBuffer(), size)) != size) {
734          if (nrecv == 0) {
735             Error("ReadRawData", "unexpected EOF");
736             return 0;
737          }
738          return -1;
739       }
740    }
741
742    return nrecv;
743 }
744
745 //______________________________________________________________________________
746 Int_t AliMDC::DumpEvent(Int_t toRead)
747 {
748    // This case should not happen, but if it does try to handle it
749    // gracefully by reading the rest of the event and discarding it.
750    // Returns bytes read, -1 in case of fatal error and 0 for EOF.
751
752    Error("DumpEvent", "dumping %d bytes of event %d", toRead, fNumEvents);
753
754    Int_t nrecv;
755    char *tbuf = new char[toRead];
756    if ((nrecv = Read(tbuf, toRead)) != toRead) {
757       if (nrecv == 0) {
758          Error("DumpEvent", "unexpected EOF");
759          return 0;
760       }
761       return -1;
762    }
763    delete [] tbuf;
764
765    return nrecv;
766 }
767
768 //______________________________________________________________________________
769 Int_t AliMDC::Filter(
770 #ifdef USE_HLT
771                      AliRawEvent *event,AliESD *esd
772 #endif
773                      )
774 {
775   // Call 3rd level filter for this raw data event.
776
777 #ifdef USE_HLT
778
779   // Run the HLT code
780   {
781     TStopwatch timer;
782     timer.Start();
783
784     AliL3Hough *hough1 = new AliL3Hough();
785     
786     hough1->SetThreshold(4);
787     hough1->SetTransformerParams(76,140,0.4,-1);
788     hough1->SetPeakThreshold(70,-1);
789     // Attention Z of the vertex to be taken from the event head!
790     // So far for debug purposes it is fixed by hand...
791     hough1->Init(100,4,event,3.82147);
792     hough1->SetAddHistograms();
793
794     AliL3Hough *hough2 = new AliL3Hough();
795
796     hough2->SetThreshold(4);
797     hough2->SetTransformerParams(76,140,0.4,-1);
798     hough2->SetPeakThreshold(70,-1);
799     hough2->Init(100,4,event,3.82147);
800     hough2->SetAddHistograms();
801
802     Int_t nglobaltracks = 0;
803     /* In case we run HLT code in 2 threads */
804     hough1->StartProcessInThread(0,17);
805     hough2->StartProcessInThread(18,35);
806
807     if(hough1->WaitForThreadFinish())
808       ::Fatal("AliL3Hough::WaitForThreadFinish"," Can not join the required thread! ");
809     if(hough2->WaitForThreadFinish())
810       ::Fatal("AliL3Hough::WaitForThreadFinish"," Can not join the required thread! ");
811
812     /* In case we run HLT code in the main thread
813     for(Int_t slice=0; slice<=17; slice++)
814       {
815         hough1->ReadData(slice,0);
816         hough1->Transform();
817         hough1->AddAllHistogramsRows();
818         hough1->FindTrackCandidatesRow();
819         hough1->AddTracks();
820       }
821     for(Int_t slice=18; slice<=35; slice++)
822       {
823         hough2->ReadData(slice,0);
824         hough2->Transform();
825         hough2->AddAllHistogramsRows();
826         hough2->FindTrackCandidatesRow();
827         hough2->AddTracks();
828       }
829     */
830
831     nglobaltracks += hough1->FillESD(esd);
832     nglobaltracks += hough2->FillESD(esd);
833
834     /* In case we want to debug the ESD
835     gSystem->MakeDirectory("hough1");
836     hough1->WriteTracks("./hough1");
837     gSystem->MakeDirectory("hough2");
838     hough2->WriteTracks("./hough2");
839     */
840
841     delete hough1;
842     delete hough2;
843
844     printf("Filter called for event %d\n", fNumEvents);
845     printf("Filter has found %d TPC tracks in %f seconds\n", nglobaltracks,timer.RealTime());
846   }
847
848 #else
849
850   printf("Filter called for event %d\n", fNumEvents);
851
852 #endif
853
854   return 0;
855 }
856
857 //______________________________________________________________________________
858 AliMDC::AliMDCInterruptHandler::AliMDCInterruptHandler(const 
859                                                        AliMDCInterruptHandler&
860                                                        handler): 
861   TSignalHandler(handler) 
862 {
863 // copy constructor
864
865   Fatal("AliMDCInterruptHandler", "copy constructor not implemented");
866 }
867
868 //______________________________________________________________________________
869 AliMDC::AliMDCInterruptHandler& 
870   AliMDC::AliMDCInterruptHandler::operator = (const AliMDCInterruptHandler& 
871                                               /*handler*/)
872 {
873 // assignment operator
874
875   Fatal("operator =", "assignment operator not implemented");
876   return *this;
877 }