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