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