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