File: | libraries/DAQ/HDEVIO.cc |
Location: | line 377, column 12 |
Description: | Value stored to 'type' during its initialization is never read |
1 | // $Id$ |
2 | // |
3 | // File: HDEVIO.cc |
4 | // Created: Wed Dec 10 07:22:00 EST 2014 |
5 | // Creator: davidl (on Darwin harriet 13.4.0 i386) |
6 | // |
7 | |
8 | #include <stdlib.h> |
9 | #include <string.h> |
10 | |
11 | #include "HDEVIO.h" |
12 | |
13 | //--------------------------------- |
14 | // HDEVIO (Constructor) |
15 | //--------------------------------- |
16 | HDEVIO::HDEVIO(string filename):filename(filename) |
17 | { |
18 | // These must be initialized in case we return early |
19 | // so they aren't deleted in the destructor if they |
20 | // were never allocated. |
21 | fbuff = NULL__null; |
22 | buff = NULL__null; |
23 | |
24 | is_open = false; |
25 | ifs.open(filename.c_str()); |
26 | if(!ifs.is_open()){ |
27 | ClearErrorMessage(); |
28 | err_mess << "Unable to open EVIO file: " << filename; |
29 | return; |
30 | } |
31 | |
32 | fbuff_size = 10000000; // 40MB input buffer |
33 | fbuff = new uint32_t[fbuff_size];; |
34 | fnext = fbuff; |
35 | fbuff_end = fbuff; |
36 | fbuff_len = 0; |
37 | _gcount = 0; |
38 | |
39 | buff_limit = 5000000; // Don't allow us to allocate more than 5M words for read buffer |
40 | buff_size = 1024; // initialize with 4kB buffer |
41 | buff_len = 0; |
42 | buff = new uint32_t[buff_size]; |
43 | next = buff; // needed so initial calculation of left is 0 |
44 | last_event_pos = 0; |
45 | last_event_len = 0; |
46 | err_code = HDEVIO_OK; |
47 | |
48 | Nblocks = 0; |
49 | Nevents = 0; |
50 | Nerrors = 0; |
51 | Nbad_blocks = 0; |
52 | Nbad_events = 0; |
53 | |
54 | event_type_mask = 0xFFFF; // default to accepting all types |
55 | is_mapped = false; |
56 | |
57 | NB_next_pos = 0; |
58 | |
59 | ifs.seekg(0, ios_base::end); |
60 | total_size_bytes = ifs.tellg(); |
61 | ifs.seekg(0, ios_base::beg); |
62 | |
63 | is_open = true; |
64 | } |
65 | |
66 | //--------------------------------- |
67 | // ~HDEVIO (Destructor) |
68 | //--------------------------------- |
69 | HDEVIO::~HDEVIO() |
70 | { |
71 | if(ifs.is_open()) ifs.close(); |
72 | if(buff ) delete[] buff; |
73 | if(fbuff) delete[] fbuff; |
74 | } |
75 | |
76 | //--------------------------------- |
77 | // buff_read |
78 | //--------------------------------- |
79 | void HDEVIO::buff_read(char* s, streamsize nwords) |
80 | { |
81 | /// Read n bytes into the specified buffer. |
82 | /// This will read from the file if needed, or simply copy |
83 | /// the bytes from the existing fbuff. It is purposely meant |
84 | /// as a drop-in replacement for ifstream::read so that we |
85 | /// can make actual reads from the file in larger chunks and |
86 | /// avoid backwards seeks on the actual file. This is needed |
87 | /// because the Lustre filesystem is optimized for large data |
88 | /// reads but smaller reads with backwards seeks tend to cripple |
89 | /// its performance. The main difference between this and |
90 | /// ifstream::read is that this does not return an istream& |
91 | /// reference. |
92 | |
93 | // Number of words left in fbuff |
94 | uint64_t left = ((uint64_t)fbuff_end - (uint64_t)fnext)/sizeof(uint32_t); |
95 | |
96 | // First, copy what's already in fbuff |
97 | uint64_t Ncopied = nwords<(int64_t)left ? (uint64_t)nwords:left; |
98 | _gcount = Ncopied*sizeof(uint32_t); |
99 | if(_gcount>0) memcpy((char*)s, (char*)fnext, _gcount); |
100 | left -= Ncopied; |
101 | fnext += Ncopied; |
102 | s += _gcount; // advance pointer to user buff in case we need to write more |
103 | |
104 | // If needed, read in another chunk from the file. |
105 | // Try and keep last 8 words so if a seekg is called to back |
106 | // us up that amount, we don't have to call seekg on the file. |
107 | if( (int64_t)Ncopied < nwords ){ |
108 | |
109 | // Initialize to start of buffer |
110 | uint32_t *myfbuff = fbuff; |
111 | uint32_t myfbuff_size = fbuff_size; |
112 | fbuff_len = 0; |
113 | |
114 | // If at least 8 words exist in fbuff, then copy last |
115 | // 8 words into front of fbuff. |
116 | if( fbuff_len >= 8 ){ |
117 | memcpy((char*)fbuff, (char*)&fbuff[fbuff_len-8], 8*sizeof(uint32_t)); |
118 | myfbuff = &fbuff[8]; |
119 | myfbuff_size -= 8; |
120 | fbuff_len += 8; |
121 | } |
122 | |
123 | // Read in chunk from file |
124 | ifs.read((char*)myfbuff, myfbuff_size*sizeof(uint32_t)); |
125 | fbuff_len += (uint64_t)(ifs.gcount()/sizeof(uint32_t)); |
126 | fnext = myfbuff; |
127 | fbuff_end = &fbuff[fbuff_len]; |
128 | |
129 | // Copy remainder of request |
130 | uint64_t myleft = ((uint64_t)fbuff_end - (uint64_t)fnext)/sizeof(uint32_t); |
131 | |
132 | uint64_t mynwords = nwords - Ncopied; |
133 | uint64_t myNcopied = mynwords<myleft ? mynwords:myleft; |
134 | uint64_t mygcount = myNcopied*sizeof(uint32_t); |
135 | if(mygcount>0) memcpy((char*)s, (char*)fnext, mygcount); |
136 | fnext += myNcopied; |
137 | _gcount += myNcopied*sizeof(uint32_t); |
138 | } |
139 | } |
140 | |
141 | //--------------------------------- |
142 | // buff_seekg |
143 | //--------------------------------- |
144 | void HDEVIO::buff_seekg (streamoff off, ios_base::seekdir way) |
145 | { |
146 | // Convert offset from bytes to words |
147 | int64_t off_words = (int64_t)off/(int64_t)sizeof(uint32_t); |
148 | |
149 | // find current position relative to start of buffer in words |
150 | int64_t fpos = (int64_t)((uint64_t)fnext - (uint64_t)fbuff)/sizeof(uint32_t); |
151 | |
152 | // Seek depending on what user has requested |
153 | if( way == ios_base::cur ){ |
154 | |
155 | // Add requested offset |
156 | fpos += off_words; // desired position relative to start of fbuff |
157 | |
158 | if(fpos>=0 && fpos<(int64_t)fbuff_len){ |
159 | // Request is to a point inside current buffer |
160 | fnext = &fbuff[fpos]; |
161 | _gcount = 0; |
162 | }else if(fpos<0){ |
163 | // Seek point is outside of buffer. Move file pointer |
164 | // and indicate buffer is now empty so next buff_read() |
165 | // call will force a read. |
166 | |
167 | // Current file position should be just after end of fbuff |
168 | // Subtract fbuff_len to move it back to start of fbuff. |
169 | // fpos is position relative to start of fbuff. |
170 | off = (streamoff)fpos - (streamoff)fbuff_len; // offset relative to actual current file position |
171 | |
172 | ifs.seekg(off); |
173 | |
174 | // Set fbuff parameters to indicate no valid data |
175 | fnext = fbuff; |
176 | fbuff_end = fbuff; |
177 | fbuff_len = 0; |
178 | _gcount = 0; |
179 | |
180 | } |
181 | |
182 | }else{ |
183 | _DBG_cout<<"libraries/DAQ/HDEVIO.cc"<<":"<<183<< " "<<"buff_seekg called with something other than ios_base::cur is unsupported!" << endl; |
184 | exit(-1); |
185 | } |
186 | } |
187 | |
188 | //--------------------------------- |
189 | // ReadBlock |
190 | //--------------------------------- |
191 | bool HDEVIO::ReadBlock(void) |
192 | { |
193 | /// Read in the next EVIO block. Return true if successful |
194 | /// and false otherwise. |
195 | |
196 | err_code = HDEVIO_OK; |
197 | next = NULL__null; |
198 | |
199 | buff_read((char*)buff, 8); |
200 | uint32_t valid_words = buff_gcount()/sizeof(uint32_t); |
201 | if(valid_words != 8){ |
202 | SetErrorMessage("Could not read in 8 word EVIO block header!"); |
203 | err_code = HDEVIO_FILE_TRUNCATED; |
204 | Nerrors++; |
205 | return false; |
206 | } |
207 | |
208 | // Check endianess |
209 | if(buff[7]!=0xc0da0100 && buff[7]!=0x0001dac0){ |
210 | ClearErrorMessage(); |
211 | err_mess << "Magic word not valid!: " << HexStr(buff[7]) << endl; |
212 | err_code = HDEVIO_BAD_BLOCK_HEADER; |
213 | Nerrors++; |
214 | Nbad_blocks++; |
215 | return false; |
216 | } |
217 | swap_needed = (buff[7]==0x0001dac0); |
218 | |
219 | // Swap header (if needed) |
220 | if(swap_needed) swap_block(buff, 8, buff); |
221 | |
222 | // Re-allocate buffer if needed so we can read in entire block |
223 | uint32_t block_length = buff[0]; |
224 | if(buff_size < block_length){ |
225 | if(block_length > buff_limit){ |
226 | ClearErrorMessage(); |
227 | err_mess << "ERROR: EVIO block length greater than allocation limit (" << block_length <<" > " << block_length << " words)" << endl; |
228 | err_code = HDEVIO_BLOCKSIZE_GREATER_THAN_LIMIT; |
229 | Nerrors++; |
230 | return false; |
231 | } |
232 | if(buff) delete[] buff; |
233 | buff_size = block_length; |
234 | buff = new uint32_t[buff_size]; |
235 | if(buff == NULL__null){ |
236 | ClearErrorMessage(); |
237 | err_mess << "ERROR: unable to allocate " << block_length <<" words" << endl; |
238 | err_code = HDEVIO_MEMORY_ALLOCATION_ERROR; |
239 | return false; |
240 | } |
241 | |
242 | // Re-read in the block header |
243 | buff_seekg(-8*sizeof(uint32_t), ifs.cur); |
244 | buff_read((char*)buff, 8); |
245 | if(swap_needed) swap_block(buff, 8, buff); |
246 | } |
247 | |
248 | if(block_length == 8){ |
249 | // block_length =8 indicates end of file. |
250 | SetErrorMessage("end of file"); |
251 | err_code = HDEVIO_EOF; |
252 | return false; |
253 | } |
254 | |
255 | // Read payload of block |
256 | buff_read((char*)&buff[8], (block_length-8)); |
257 | valid_words = 8 + buff_gcount()/sizeof(uint32_t); |
258 | if(valid_words < block_length){ |
259 | ClearErrorMessage(); |
260 | err_mess << "Error reading in EVIO entire block! (block number: " << buff[1] << ")" << endl; |
261 | err_mess << "valid_words="<<valid_words << " block_length=" << block_length; |
262 | err_code = HDEVIO_FILE_TRUNCATED; |
263 | Nerrors++; |
264 | return false; |
265 | } |
266 | |
267 | // Set pointers |
268 | buff_len = valid_words; |
269 | buff_end = &buff[valid_words]; |
270 | next = &buff[8]; |
271 | bh = (BLOCKHEADER_t*)buff; |
272 | |
273 | Nblocks++; |
274 | return true; |
275 | } |
276 | |
277 | //--------------------------------- |
278 | // read |
279 | //--------------------------------- |
280 | bool HDEVIO::read(uint32_t *user_buff, uint32_t user_buff_len, bool allow_swap) |
281 | { |
282 | /// Read the next EVIO event into the user supplied buffer. |
283 | /// Return true if successful and false otherwise. Details of |
284 | /// the error will be in err_mess. |
285 | |
286 | // If only certain event types are requested then |
287 | // defer to the sparse reader |
288 | if(event_type_mask != 0xFFFF){ |
289 | return readSparse(user_buff, user_buff_len, allow_swap); |
290 | } |
291 | |
292 | err_code = HDEVIO_OK; |
293 | |
294 | // calculate remaining valid words in buffer |
295 | uint32_t left = buff_len - (uint32_t)(((unsigned long)next - (unsigned long)buff)/sizeof(uint32_t)); |
296 | |
297 | // Read in another event block if necessary |
298 | if(left < 1 || next==NULL__null){ |
299 | bool isgood = ReadBlock(); |
300 | if(!isgood) return false; |
301 | left = buff_len - 8; |
302 | } |
303 | |
304 | if(next == NULL__null){ |
305 | SetErrorMessage("No valid events in buffer"); |
306 | err_code = HDEVIO_NO_EVENTS_IN_BUFFER; |
307 | return false; |
308 | } |
309 | |
310 | // Check if next event will fit into user supplied buffer |
311 | uint32_t event_len = next[0]; |
312 | if(swap_needed) swap_block(&event_len, 1, &event_len); |
313 | event_len++; // include length word for EVIO bank |
314 | last_event_len = event_len; |
315 | |
316 | // Check that event isn't claiming to be larger than EVIO block |
317 | if( event_len > left ){ |
318 | ClearErrorMessage(); |
319 | err_mess << "WARNING: EVIO bank indicates a bigger size than block header (" << event_len << " > " << left << ")"; |
320 | next = &buff[buff_len]; // setup so subsequent call will read in another block |
321 | err_code = HDEVIO_EVENT_BIGGER_THAN_BLOCK; |
322 | Nerrors++; |
323 | Nbad_blocks++; |
324 | return false; |
325 | } |
326 | |
327 | // Check if user buffer is big enough to hold this |
328 | if(event_len > user_buff_len){ |
329 | ClearErrorMessage(); |
330 | err_mess << "user buffer too small for event (" << user_buff_len << " < " << event_len << ")"; |
331 | err_code = HDEVIO_USER_BUFFER_TOO_SMALL; |
332 | return false; |
333 | } |
334 | |
335 | // Copy entire event into user buffer, swapping if needed during copy |
336 | bool isgood = true; |
337 | if(swap_needed && allow_swap){ |
338 | uint32_t Nswapped = swap_bank(user_buff, next, event_len); |
339 | isgood = (Nswapped == event_len); |
340 | }else{ |
341 | memcpy(user_buff, next, event_len*sizeof(uint32_t)); |
342 | } |
343 | |
344 | // Advance next pointer to next EVIO event or past end of buffer. |
345 | next = &next[event_len]; |
346 | |
347 | if(isgood) Nevents++; |
348 | |
349 | return isgood; |
350 | } |
351 | |
352 | //--------------------------------- |
353 | // readSparse |
354 | //--------------------------------- |
355 | bool HDEVIO::readSparse(uint32_t *user_buff, uint32_t user_buff_len, bool allow_swap) |
356 | { |
357 | /// This is an alternative to the read(...) method above that |
358 | /// is used when the user has specified that only certain |
359 | /// event types are desired. This really only makes sense |
360 | /// for EPICS and SYNC events. This method does not use the |
361 | /// fbuff system and instead reads directly from the file |
362 | /// after seeking to the desired location determined from |
363 | /// a previously generated map. |
364 | |
365 | err_code = HDEVIO_OK; |
366 | ClearErrorMessage(); |
367 | |
368 | // Make sure we've mapped this file |
369 | if(!is_mapped) MapBlocks(); |
370 | |
371 | // Loop over all events of all blocks looking for the next |
372 | // event matching the currently set type mask. |
373 | for(; sparse_block_iter!=evio_blocks.end(); sparse_block_iter++, sparse_event_idx = 0){ |
374 | |
375 | // Filter out blocks of the wrong type |
376 | EVIOBlockRecord &br = *sparse_block_iter; |
377 | uint32_t type = (1 << br.block_type); |
Value stored to 'type' during its initialization is never read | |
378 | |
379 | for(; sparse_event_idx < br.evio_events.size(); sparse_event_idx++){ |
380 | EVIOEventRecord &er = sparse_block_iter->evio_events[sparse_event_idx]; |
381 | |
382 | uint32_t etype = (1 << er.event_type); |
383 | if( etype & event_type_mask ) break; |
384 | } |
385 | if(sparse_event_idx >= br.evio_events.size()) continue; |
386 | |
387 | EVIOEventRecord &er = sparse_block_iter->evio_events[sparse_event_idx]; |
388 | |
389 | uint32_t event_len = er.event_len; |
390 | last_event_len = event_len; |
391 | |
392 | // Check if user buffer is big enough to hold block |
393 | if( event_len > user_buff_len ){ |
394 | ClearErrorMessage(); |
395 | err_mess << "user buffer too small for event (" << user_buff_len << " < " << event_len << ")"; |
396 | err_code = HDEVIO_USER_BUFFER_TOO_SMALL; |
397 | return false; |
398 | } |
399 | |
400 | // At this point we're committed to reading this event so go |
401 | // ahead and increment pointer to next event so no matter |
402 | // what happens below, we don't try reading it again. |
403 | sparse_event_idx++; |
404 | |
405 | // Set file pointer to start of EVIO event (NOT block header!) |
406 | last_event_pos = er.pos; |
407 | ifs.seekg(last_event_pos, ios_base::beg); |
408 | |
409 | // Read data directly into user buffer |
410 | ifs.read((char*)user_buff, event_len*sizeof(uint32_t)); |
411 | |
412 | // Swap entire bank if needed |
413 | swap_needed = br.swap_needed; // set flag in HDEVIO |
414 | bool isgood = true; |
415 | if(br.swap_needed && allow_swap){ |
416 | uint32_t Nswapped = swap_bank(user_buff, user_buff, event_len); |
417 | isgood = (Nswapped == event_len); |
418 | } |
419 | |
420 | // Double check that event length matches EVIO block header |
421 | // but only if we either don't need to swap or need to and |
422 | // were allowed to (otherwise, the test will almost certainly |
423 | // fail!) |
424 | if( (!br.swap_needed) || (br.swap_needed && allow_swap) ){ |
425 | if( (user_buff[0]+1) != event_len ){ |
426 | ClearErrorMessage(); |
427 | err_mess << "WARNING: EVIO bank indicates a different size than block header (" << event_len << " != " << (user_buff[0]+1) << ")"; |
428 | err_code = HDEVIO_EVENT_BIGGER_THAN_BLOCK; |
429 | Nerrors++; |
430 | Nbad_blocks++; |
431 | return false; |
432 | } |
433 | } |
434 | |
435 | if(isgood) Nevents++; |
436 | |
437 | return isgood; |
438 | } |
439 | |
440 | // If we got here then we did not find an event of interest |
441 | // above. Report that there are no more events in the file. |
442 | SetErrorMessage("No more events"); |
443 | err_code = HDEVIO_EOF; |
444 | return false; // isgood=false |
445 | } |
446 | |
447 | //--------------------------------- |
448 | // readNoFileBuff |
449 | //--------------------------------- |
450 | bool HDEVIO::readNoFileBuff(uint32_t *user_buff, uint32_t user_buff_len, bool allow_swap) |
451 | { |
452 | /// This is an alternative to the read(...) method above that |
453 | /// does not use a large primary file buffer. A single EVIO |
454 | /// header is read in at a time and the events within the block |
455 | /// mapped just like when using readSparse. The difference is |
456 | /// that here, only a single block is mapped at a time rather |
457 | /// than trying to map the entire file before starting. This |
458 | /// gives a faster start up. This may be quicker for most |
459 | /// desktop filesystems but may be slower for Lustre file systems |
460 | /// that are configured for large volume data transfers and show |
461 | /// perfomance degredation with small reads. |
462 | |
463 | err_code = HDEVIO_OK; |
464 | ClearErrorMessage(); |
465 | |
466 | // Check if we need to read in a block header using the |
467 | // current file position |
468 | EVIOBlockRecord &br = NB_block_record; |
469 | if(br.evio_events.empty()){ |
470 | |
471 | // read EVIO block header |
472 | BLOCKHEADER_t bh; |
473 | ifs.seekg( NB_next_pos, ios_base::beg); |
474 | ifs.read((char*)&bh, sizeof(bh)); |
475 | if(!ifs.good()){ |
476 | err_code = HDEVIO_FILE_TRUNCATED; |
477 | return false; |
478 | } |
479 | |
480 | // Check if we need to byte swap and simultaneously |
481 | // verify header is good by checking magic word |
482 | bool swap_needed = false; |
483 | if(bh.magic==0x0001dac0){ |
484 | swap_needed = true; |
485 | }else{ |
486 | if(bh.magic!=0xc0da0100){ |
487 | err_mess.str() = "Bad magic word"; |
488 | err_code = HDEVIO_BAD_BLOCK_HEADER; |
489 | return false; |
490 | } |
491 | } |
492 | |
493 | if(swap_needed)swap_block((uint32_t*)&bh, sizeof(bh)>>2, (uint32_t*)&bh); |
494 | |
495 | Nblocks++; |
496 | streampos pos = ifs.tellg() - (streampos)sizeof(bh); |
497 | |
498 | if( (uint64_t)(pos+(streampos)bh.length) > total_size_bytes ){ |
499 | err_mess << "EVIO block extends past end of file!"; |
500 | err_code = HDEVIO_FILE_TRUNCATED; |
501 | return false; |
502 | } |
503 | |
504 | br.pos = pos; |
505 | br.block_len = bh.length; |
506 | br.swap_needed = swap_needed; |
507 | br.first_event = 0; |
508 | br.last_event = 0; |
509 | |
510 | MapEvents(bh, br); |
511 | |
512 | NB_next_pos = pos + (streampos)(bh.length<<2); |
513 | } |
514 | |
515 | // Check if we did not find an event of interest above. |
516 | // If not, report that there are no more events in the file. |
517 | if(br.evio_events.empty() || !ifs.good()){ |
518 | SetErrorMessage("No more events"); |
519 | err_code = HDEVIO_EOF; |
520 | return false; // isgood=false |
521 | } |
522 | |
523 | // Grab next event record |
524 | EVIOEventRecord &er = br.evio_events.front(); |
525 | |
526 | uint32_t event_len = er.event_len; |
527 | last_event_len = event_len; |
528 | |
529 | // Check if user buffer is big enough to hold block |
530 | if( event_len > user_buff_len ){ |
531 | ClearErrorMessage(); |
532 | err_mess << "user buffer too small for event (" << user_buff_len << " < " << event_len << ")"; |
533 | err_code = HDEVIO_USER_BUFFER_TOO_SMALL; |
534 | return false; |
535 | } |
536 | |
537 | // Set file pointer to start of EVIO event (NOT block header!) |
538 | last_event_pos = er.pos; |
539 | ifs.seekg(last_event_pos, ios_base::beg); |
540 | |
541 | // Read data directly into user buffer |
542 | ifs.read((char*)user_buff, event_len*sizeof(uint32_t)); |
543 | if(!ifs.good()){ |
544 | SetErrorMessage("No more events"); |
545 | err_code = HDEVIO_EOF; |
546 | return false; // isgood=false |
547 | } |
548 | |
549 | // Remove EVIO Event record, effectively advancing to |
550 | // next event for the next time we're called |
551 | br.evio_events.erase(NB_block_record.evio_events.begin()); |
552 | |
553 | // Swap entire bank if needed |
554 | swap_needed = br.swap_needed; // set flag in HDEVIO |
555 | bool isgood = true; |
556 | if(br.swap_needed && allow_swap){ |
557 | uint32_t Nswapped = swap_bank(user_buff, user_buff, event_len); |
558 | isgood = (Nswapped == event_len); |
559 | } |
560 | |
561 | // Double check that event length matches EVIO block header |
562 | // but only if we either don't need to swap or need to and |
563 | // were allowed to (otherwise, the test will almost certainly |
564 | // fail!) |
565 | if( (!br.swap_needed) || (br.swap_needed && allow_swap) ){ |
566 | if( (user_buff[0]+1) != event_len ){ |
567 | ClearErrorMessage(); |
568 | err_mess << "WARNING: EVIO bank indicates a different size than block header (" << event_len << " != " << (user_buff[0]+1) << ")"; |
569 | err_code = HDEVIO_EVENT_BIGGER_THAN_BLOCK; |
570 | Nerrors++; |
571 | Nbad_blocks++; |
572 | return false; |
573 | } |
574 | } |
575 | |
576 | if(isgood) Nevents++; |
577 | |
578 | return isgood; |
579 | } |
580 | |
581 | //------------------------ |
582 | // rewind |
583 | //------------------------ |
584 | void HDEVIO::rewind(void) |
585 | { |
586 | /// This can be used whe reading from a file to |
587 | /// reset the file pointer and other position holders |
588 | /// to the begining of the file. This is done when |
589 | /// the "LOOP_FOREVER" option is used in the event source |
590 | /// to continuously re-read a file, essesntially making |
591 | /// it an infinite stream of events that can be used for |
592 | /// testing. |
593 | |
594 | ifs.seekg(0, ios_base::beg); |
595 | ifs.clear(); |
596 | |
597 | sparse_block_iter = evio_blocks.begin(); |
598 | sparse_event_idx = 0; |
599 | |
600 | NB_block_record.evio_events.clear(); |
601 | NB_next_pos = 0; |
602 | |
603 | ClearErrorMessage(); |
604 | err_code = HDEVIO_OK; |
605 | } |
606 | |
607 | //------------------------ |
608 | // SetEventMask |
609 | //------------------------ |
610 | uint32_t HDEVIO::SetEventMask(uint32_t mask) |
611 | { |
612 | uint32_t prev_mask = event_type_mask; |
613 | event_type_mask = mask; |
614 | |
615 | return prev_mask; |
616 | } |
617 | |
618 | //------------------------ |
619 | // SetEventMask |
620 | //------------------------ |
621 | uint32_t HDEVIO::SetEventMask(string types_str) |
622 | { |
623 | uint32_t prev_mask = event_type_mask; |
624 | |
625 | event_type_mask = 0; |
626 | if(types_str.find("BOR" ) != string::npos) event_type_mask |= (1<<kBT_BOR); |
627 | if(types_str.find("EPICS" ) != string::npos) event_type_mask |= (1<<kBT_EPICS); |
628 | if(types_str.find("PHYSICS") != string::npos) event_type_mask |= (1<<kBT_PHYSICS); |
629 | |
630 | return prev_mask; |
631 | } |
632 | |
633 | //------------------------ |
634 | // AddToEventMask |
635 | //------------------------ |
636 | uint32_t HDEVIO::AddToEventMask(string type_str) |
637 | { |
638 | return 0; |
639 | } |
640 | |
641 | //------------------------ |
642 | // GetEVIOBlockRecords |
643 | //------------------------ |
644 | vector<HDEVIO::EVIOBlockRecord>& HDEVIO::GetEVIOBlockRecords(void) |
645 | { |
646 | if(!is_mapped) MapBlocks(); |
647 | |
648 | return evio_blocks; |
649 | } |
650 | |
651 | //------------------------ |
652 | // MapBlocks |
653 | //------------------------ |
654 | void HDEVIO::MapBlocks(bool print_ticker) |
655 | { |
656 | if(!is_open){ |
657 | err_mess.str() = "File is not open"; |
658 | err_code = HDEVIO_FILE_NOT_OPEN; |
659 | return; |
660 | } |
661 | |
662 | // Remember current file pos so we can restore it. |
663 | streampos start_pos = ifs.tellg(); |
664 | |
665 | if(print_ticker) cout << "Mapping EVIO file ..." << endl; |
666 | |
667 | // Rewind to beginning of file and loop over all blocks |
668 | ifs.seekg(0, ios_base::beg); |
669 | BLOCKHEADER_t bh; |
670 | uint64_t Nblocks = 0; |
671 | while(ifs.good()){ |
672 | ifs.read((char*)&bh, sizeof(bh)); |
673 | if(!ifs.good()) break; |
674 | |
675 | // Check if we need to byte swap and simultaneously |
676 | // verify header is good by checking magic word |
677 | bool swap_needed = false; |
678 | if(bh.magic==0x0001dac0){ |
679 | swap_needed = true; |
680 | }else{ |
681 | if(bh.magic!=0xc0da0100){ |
682 | err_mess.str() = "Bad magic word"; |
683 | err_code = HDEVIO_BAD_BLOCK_HEADER; |
684 | break; |
685 | } |
686 | } |
687 | |
688 | if(swap_needed)swap_block((uint32_t*)&bh, sizeof(bh)>>2, (uint32_t*)&bh); |
689 | |
690 | Nblocks++; |
691 | streampos block_len_bytes = (bh.length<<2)-sizeof(bh); // <<2 is for *4 |
692 | streampos pos = ifs.tellg() - (streampos)sizeof(bh); |
693 | |
694 | EVIOBlockRecord br; |
695 | br.pos = pos; |
696 | br.block_len = bh.length; |
697 | br.swap_needed = swap_needed; |
698 | br.first_event = 0; |
699 | br.last_event = 0; |
700 | |
701 | // Categorize this block |
702 | uint32_t tag = bh.header>>16; |
703 | uint32_t M = bh.header&0xFF; |
704 | |
705 | switch(tag){ |
706 | case 0xFFD0: br.block_type = kBT_SYNC; break; |
707 | case 0xFFD1: br.block_type = kBT_PRESTART; break; |
708 | case 0xFFD2: br.block_type = kBT_GO; break; |
709 | case 0xFFD3: br.block_type = kBT_PAUSE; break; |
710 | case 0xFFD4: br.block_type = kBT_END; break; |
711 | case 0x0060: br.block_type = kBT_EPICS; break; |
712 | case 0x0070: br.block_type = kBT_BOR; break; |
713 | case 0xFF50: |
714 | case 0xFF51: |
715 | case 0xFF70: |
716 | br.block_type = kBT_PHYSICS; |
717 | br.first_event = bh.physics.first_event_lo; |
718 | br.first_event += ((uint64_t)bh.physics.first_event_hi)<<32; |
719 | br.last_event = br.first_event + (uint64_t)M - 1; |
720 | break; |
721 | default: |
722 | _DBG_cout<<"libraries/DAQ/HDEVIO.cc"<<":"<<722<< " " << "Uknown tag: " << hex << tag << dec << endl; |
723 | } |
724 | |
725 | // Scan through and map all events within this block |
726 | MapEvents(bh, br); |
727 | |
728 | // Add block to list |
729 | evio_blocks.push_back(br); |
730 | |
731 | // Update ticker |
732 | if(print_ticker){ |
733 | if((Nblocks%500) == 0){ |
734 | uint64_t total_MB = total_size_bytes>>20; |
735 | uint64_t read_MB = ifs.tellg()>>20; |
736 | if(Nblocks==0) cout << endl; |
737 | cout << Nblocks << " blocks scanned (" << read_MB << "/" << total_MB << " MB " << (100*read_MB/total_MB) << "%) \r"; |
738 | cout.flush(); |
739 | } |
740 | } |
741 | |
742 | // Advance file pointer to start of next EVIO block header |
743 | ifs.seekg(block_len_bytes, ios_base::cur); |
744 | } |
745 | |
746 | if(print_ticker) cout << endl; |
747 | |
748 | // Setup iterators for sparse reading |
749 | sparse_block_iter = evio_blocks.begin(); |
750 | sparse_event_idx = 0; |
751 | |
752 | // Restore file pos and set flag that file has been mapped |
753 | ifs.clear(); |
754 | ifs.seekg(start_pos, ios_base::beg); |
755 | is_mapped = true; |
756 | } |
757 | |
758 | //--------------------------------- |
759 | // MapEvents |
760 | //--------------------------------- |
761 | void HDEVIO::MapEvents(BLOCKHEADER_t &bh, EVIOBlockRecord &br) |
762 | { |
763 | /// This is called if the EVIO block header indicates that |
764 | /// it contains more than one top-level event. The position |
765 | /// and event length of the first top-level event are passed |
766 | /// in as starting parameters. |
767 | |
768 | // Record stream position upon entry so we can restore it at end |
769 | streampos start_pos = ifs.tellg(); |
770 | |
771 | // Calculate stream position of EVIO event |
772 | streampos pos = start_pos -(streampos)sizeof(BLOCKHEADER_t) + (streampos)(8<<2); // (8<<2) is 8 word EVIO block header times 4bytes/word |
773 | ifs.seekg(pos, ios_base::beg); |
774 | |
775 | EVENTHEADER_t myeh; |
776 | for(uint32_t i=0; i<bh.eventcnt; i++){ |
777 | |
778 | // For the first iteration through this loop, |
779 | // we use the event header that has already been |
780 | // read in as part of the block header. |
781 | EVENTHEADER_t *eh = (EVENTHEADER_t*)&bh.event_len; |
782 | if(i!=0){ |
783 | // Read in first few words of event |
784 | eh = &myeh; |
785 | ifs.read((char*)eh, sizeof(EVENTHEADER_t)); |
786 | if(!ifs.good()) break; |
787 | if(br.swap_needed)swap_block((uint32_t*)eh, sizeof(EVENTHEADER_t)>>2, (uint32_t*)eh); |
788 | }else{ |
789 | ifs.seekg(sizeof(EVENTHEADER_t), ios_base::cur); |
790 | } |
791 | |
792 | EVIOEventRecord er; |
793 | er.pos = pos; |
794 | er.event_len = eh->event_len + 1; // +1 to include length word |
795 | er.event_type = kBT_UNKNOWN; |
796 | er.first_event = 0; |
797 | er.last_event = 0; |
798 | |
799 | uint32_t tag = eh->header>>16; |
800 | uint32_t M = eh->header&0xFF; |
801 | |
802 | switch(tag){ |
803 | case 0xFFD0: er.event_type = kBT_SYNC; break; |
804 | case 0xFFD1: er.event_type = kBT_PRESTART; break; |
805 | case 0xFFD2: er.event_type = kBT_GO; break; |
806 | case 0xFFD3: er.event_type = kBT_PAUSE; break; |
807 | case 0xFFD4: er.event_type = kBT_END; break; |
808 | case 0x0060: er.event_type = kBT_EPICS; break; |
809 | case 0x0070: er.event_type = kBT_BOR; break; |
810 | case 0xFF50: |
811 | case 0xFF51: |
812 | case 0xFF70: |
813 | er.event_type = kBT_PHYSICS; |
814 | er.first_event = eh->physics.first_event_lo; |
815 | er.first_event += ((uint64_t)eh->physics.first_event_hi)<<32; |
816 | er.last_event = er.first_event + (uint64_t)M - 1; |
817 | if(er.first_event < br.first_event) br.first_event = er.first_event; |
818 | if(er.last_event > br.last_event ) br.last_event = er.last_event; |
819 | break; |
820 | default: |
821 | _DBG_cout<<"libraries/DAQ/HDEVIO.cc"<<":"<<821<< " " << "Uknown tag: " << hex << tag << dec << endl; |
822 | } |
823 | |
824 | br.evio_events.push_back(er); |
825 | |
826 | // Move file position to start of next event |
827 | streampos delta = (streampos)((eh->event_len+1)<<2) - (streampos)sizeof(EVENTHEADER_t); |
828 | ifs.seekg(delta, ios_base::cur); |
829 | pos += (streampos)((eh->event_len+1)<<2); |
830 | } |
831 | |
832 | ifs.seekg(start_pos, ios_base::beg); |
833 | } |
834 | |
835 | //--------------------------------- |
836 | // swap_bank |
837 | //--------------------------------- |
838 | uint32_t HDEVIO::swap_bank(uint32_t *outbuff, uint32_t *inbuff, uint32_t len) |
839 | { |
840 | /// Swap an EVIO bank. If the bank contains data, it is automatically |
841 | /// swapped according to it's type. If the bank is a container of other |
842 | /// containers, then this repeatedly calls the swapper methods for the |
843 | /// appropriate container type (bank, tagsegment, segment). This means |
844 | /// that this method will be recursive in the cases where it is a bank |
845 | /// of banks. |
846 | |
847 | if(len < 2){ |
848 | SetErrorMessage("Attempt to swap bank with len<2"); |
849 | err_code = HDEVIO_BANK_TRUNCATED; |
850 | Nerrors++; |
851 | Nbad_events++; |
852 | return 0; |
853 | } |
854 | |
855 | // Swap length and header words |
856 | swap_block(inbuff, 2, outbuff); |
857 | uint32_t bank_len = outbuff[0]; |
858 | if((bank_len+1) > len){ |
859 | ClearErrorMessage(); |
860 | err_mess << "WARNING: Bank length word exceeds valid words in buffer (" << bank_len+1 << " > " << len << ")"; |
861 | err_code = HDEVIO_BANK_TRUNCATED; |
862 | Nerrors++; |
863 | Nbad_events++; |
864 | return 0; |
865 | } |
866 | |
867 | uint32_t type = (outbuff[1]>>8) & 0xFF; |
868 | uint32_t Nwords = bank_len - 1; |
869 | uint32_t Nswapped = 2; |
870 | switch(type){ |
871 | case 0x0a: // 64 bit unsigned int |
872 | case 0x08: // 64 bit double |
873 | case 0x09: // 64 bit signed int |
874 | swap_block((uint64_t*)&inbuff[2], Nwords/2, (uint64_t*)&outbuff[2]); |
875 | Nswapped += Nwords; |
876 | break; |
877 | case 0x01: // 32 bit unsigned int |
878 | case 0x02: // 32 bit float |
879 | case 0x0b: // 32 bit signed int |
880 | swap_block(&inbuff[2], Nwords, &outbuff[2]); |
881 | Nswapped += Nwords; |
882 | break; |
883 | case 0x05: // 16 bit unsigned int |
884 | case 0x04: // 16 bit signed int |
885 | swap_block((uint16_t*)&inbuff[2], Nwords*2, (uint16_t*)&outbuff[2]); |
886 | Nswapped += Nwords; |
887 | break; |
888 | case 0x00: // 32 bit unknown (not swapped) |
889 | case 0x07: // 8 bit unsigned int |
890 | case 0x06: // 8 bit signed int |
891 | memcpy((uint8_t*)&outbuff[2], (uint8_t*)&inbuff[2], Nwords*sizeof(uint32_t)); |
892 | Nswapped += Nwords; |
893 | break; |
894 | case 0x0c: |
895 | while(Nswapped < (Nwords+2)){ |
896 | uint32_t N = swap_tagsegment(&outbuff[Nswapped], &inbuff[Nswapped], (Nwords+2)-Nswapped); |
897 | if(N == 0) return Nswapped; |
898 | Nswapped += N; |
899 | } |
900 | break; |
901 | case 0x0d: |
902 | case 0x20: |
903 | while(Nswapped < (Nwords+2)){ |
904 | uint32_t N = swap_segment(&outbuff[Nswapped], &inbuff[Nswapped], (Nwords+2)-Nswapped); |
905 | if(N == 0) return Nswapped; |
906 | Nswapped += N; |
907 | } |
908 | break; |
909 | case 0x0e: |
910 | case 0x10: |
911 | while(Nswapped < (Nwords+2)){ |
912 | uint32_t N = swap_bank(&outbuff[Nswapped], &inbuff[Nswapped], (Nwords+2)-Nswapped); |
913 | if(N == 0) return Nswapped; |
914 | Nswapped += N; |
915 | } |
916 | break; |
917 | default: |
918 | ClearErrorMessage(); |
919 | err_mess << "WARNING: unknown bank type (0x" << hex << type << dec << ")"; |
920 | err_code = HDEVIO_UNKNOWN_BANK_TYPE; |
921 | Nerrors++; |
922 | Nbad_events++; |
923 | return 0; |
924 | break; |
925 | } |
926 | |
927 | return Nswapped; |
928 | } |
929 | |
930 | //--------------------------------- |
931 | // swap_tagsegment |
932 | //--------------------------------- |
933 | uint32_t HDEVIO::swap_tagsegment(uint32_t *outbuff, uint32_t *inbuff, uint32_t len) |
934 | { |
935 | /// Swap an EVIO tagsegment. |
936 | |
937 | if(len < 1){ |
938 | SetErrorMessage("Attempt to swap segment with len<1"); |
939 | err_code = HDEVIO_BANK_TRUNCATED; |
940 | Nerrors++; |
941 | Nbad_events++; |
942 | return 0; |
943 | } |
944 | |
945 | // Swap header/length word |
946 | swap_block(inbuff, 1, outbuff); |
947 | uint32_t bank_len = outbuff[0] & 0xFFFF; |
948 | if((bank_len) > len){ |
949 | ClearErrorMessage(); |
950 | err_mess << "Segment length word exceeds valid words in buffer (" << bank_len << " > " << len << ")"; |
951 | err_code = HDEVIO_BANK_TRUNCATED; |
952 | Nerrors++; |
953 | Nbad_events++; |
954 | return 0; |
955 | } |
956 | |
957 | uint32_t type = (outbuff[0]>>16) & 0x0F; |
958 | uint32_t Nwords = bank_len; |
959 | uint32_t Nswapped = 1; |
960 | switch(type){ |
961 | case 0x0a: // 64 bit unsigned int |
962 | case 0x08: // 64 bit double |
963 | case 0x09: // 64 bit signed int |
964 | swap_block((uint64_t*)&inbuff[1], Nwords/2, (uint64_t*)&outbuff[1]); |
965 | Nswapped += Nwords; |
966 | break; |
967 | case 0x01: // 32 bit unsigned int |
968 | case 0x02: // 32 bit float |
969 | case 0x0b: // 32 bit signed int |
970 | swap_block(&inbuff[1], Nwords, &outbuff[1]); |
971 | Nswapped += Nwords; |
972 | break; |
973 | case 0x05: // 16 bit unsigned int |
974 | case 0x04: // 16 bit signed int |
975 | swap_block((uint16_t*)&inbuff[1], Nwords*2, (uint16_t*)&outbuff[1]); |
976 | Nswapped += Nwords; |
977 | break; |
978 | case 0x00: // 32 bit unknown (not swapped) |
979 | case 0x07: // 8 bit unsigned int |
980 | case 0x06: // 8 bit signed int |
981 | memcpy((uint8_t*)&outbuff[1], (uint8_t*)&inbuff[1], Nwords*sizeof(uint32_t)); |
982 | Nswapped += Nwords; |
983 | break; |
984 | } |
985 | |
986 | return Nswapped; |
987 | } |
988 | |
989 | //--------------------------------- |
990 | // swap_segment |
991 | //--------------------------------- |
992 | uint32_t HDEVIO::swap_segment(uint32_t *outbuff, uint32_t *inbuff, uint32_t len) |
993 | { |
994 | /// Swap an EVIO segment. |
995 | |
996 | if(len < 1){ |
997 | SetErrorMessage("Attempt to swap segment with len<1"); |
998 | err_code = HDEVIO_BANK_TRUNCATED; |
999 | Nerrors++; |
1000 | Nbad_events++; |
1001 | return 0; |
1002 | } |
1003 | |
1004 | // Swap header/length word |
1005 | swap_block(inbuff, 1, outbuff); |
1006 | uint32_t bank_len = outbuff[0] & 0xFFFF; |
1007 | if((bank_len) > len){ |
1008 | ClearErrorMessage(); |
1009 | err_mess << "Segment length word exceeds valid words in buffer (" << bank_len << " > " << len << ")"; |
1010 | err_code = HDEVIO_BANK_TRUNCATED; |
1011 | Nerrors++; |
1012 | Nbad_events++; |
1013 | return 0; |
1014 | } |
1015 | |
1016 | uint32_t type = (outbuff[0]>>16) & 0x3F; |
1017 | uint32_t Nwords = bank_len; |
1018 | uint32_t Nswapped = 1; |
1019 | switch(type){ |
1020 | case 0x0a: // 64 bit unsigned int |
1021 | case 0x08: // 64 bit double |
1022 | case 0x09: // 64 bit signed int |
1023 | swap_block((uint64_t*)&inbuff[1], Nwords/2, (uint64_t*)&outbuff[1]); |
1024 | Nswapped += Nwords; |
1025 | break; |
1026 | case 0x01: // 32 bit unsigned int |
1027 | case 0x02: // 32 bit float |
1028 | case 0x0b: // 32 bit signed int |
1029 | swap_block(&inbuff[1], Nwords, &outbuff[1]); |
1030 | Nswapped += Nwords; |
1031 | break; |
1032 | case 0x05: // 16 bit unsigned int |
1033 | case 0x04: // 16 bit signed int |
1034 | swap_block((uint16_t*)&inbuff[1], Nwords*2, (uint16_t*)&outbuff[1]); |
1035 | Nswapped += Nwords; |
1036 | break; |
1037 | case 0x00: // 32 bit unknown (not swapped) |
1038 | case 0x07: // 8 bit unsigned int |
1039 | case 0x06: // 8 bit signed int |
1040 | memcpy((uint8_t*)&outbuff[1], (uint8_t*)&inbuff[1], Nwords*sizeof(uint32_t)); |
1041 | Nswapped += Nwords; |
1042 | break; |
1043 | } |
1044 | |
1045 | return Nswapped; |
1046 | } |
1047 | |
1048 | //------------------------ |
1049 | // Print_fbuff |
1050 | //------------------------ |
1051 | void HDEVIO::Print_fbuff(void) |
1052 | { |
1053 | cout << endl; |
1054 | cout << " fbuff: " << hex << (uint64_t)fbuff << dec << endl; |
1055 | cout << " fnext: " << hex << (uint64_t)fnext << dec << endl; |
1056 | cout << " fbuff_end: " << hex << (uint64_t)fbuff_end << dec << endl; |
1057 | cout << " fbuff_size: " << fbuff_size << endl; |
1058 | cout << " fbuff_len: " << fbuff_len << endl; |
1059 | cout << " _gcount: " << _gcount << endl; |
1060 | } |
1061 | |
1062 | //------------------------ |
1063 | // PrintEVIOBlockHeader |
1064 | //------------------------ |
1065 | void HDEVIO::PrintEVIOBlockHeader(void) |
1066 | { |
1067 | |
1068 | cout << endl; |
1069 | cout << "EVIO Block Header:" << endl; |
1070 | cout << "------------------------" << endl; |
1071 | cout << " Block Length: " << HexStr(buff[0]) << " (" << buff[0] << " words = " << (buff[0]>>(10-2)) << " kB)" << endl; |
1072 | cout << " Block Number: " << HexStr(buff[1]) << endl; |
1073 | cout << "Header Length: " << HexStr(buff[2]) << " (should be 8)" << endl; |
1074 | cout << " Event Count: " << HexStr(buff[3]) << endl; |
1075 | cout << " Reserved 1: " << HexStr(buff[4]) << endl; |
1076 | cout << " Bit Info: " << HexStr(buff[5]>>8) << endl; |
1077 | cout << " Version: " << HexStr(buff[5]&0xFF) << endl; |
1078 | cout << " Reserved 3: " << HexStr(buff[6]) << endl; |
1079 | cout << " Magic word: " << HexStr(buff[7]) << (swap_needed ? " (after swapping)":"") << endl; |
1080 | cout << "Byte swapping is" << (swap_needed ? " ":" not ") << "needed" << endl; |
1081 | } |
1082 | |
1083 | //------------------------ |
1084 | // PrintStats |
1085 | //------------------------ |
1086 | void HDEVIO::PrintStats(void) |
1087 | { |
1088 | cout << endl; |
1089 | cout << "EVIO Statistics for " << filename << " :" << endl; |
1090 | cout << "------------------------" << endl; |
1091 | cout << " Nblocks: " << Nblocks << endl; |
1092 | cout << " Nevents: " << Nevents << endl; |
1093 | cout << " Nerrors: " << Nerrors << endl; |
1094 | cout << "Nbad_blocks: " << Nbad_blocks << endl; |
1095 | cout << "Nbad_events: " << Nbad_events << endl; |
1096 | cout << endl; |
1097 | } |
1098 | |
1099 | //------------------------ |
1100 | // PrintFileSummary |
1101 | //------------------------ |
1102 | void HDEVIO::PrintFileSummary(void) |
1103 | { |
1104 | if(!is_mapped) MapBlocks(); |
1105 | |
1106 | uint32_t Nsync = 0; |
1107 | uint32_t Nprestart = 0; |
1108 | uint32_t Ngo = 0; |
1109 | uint32_t Npause = 0; |
1110 | uint32_t Nend = 0; |
1111 | uint32_t Nepics = 0; |
1112 | uint32_t Nbor = 0; |
1113 | uint32_t Nphysics = 0; |
1114 | |
1115 | uint64_t first_event = 0; |
1116 | uint64_t last_event = 0; |
1117 | |
1118 | uint32_t map_size = evio_blocks.size()*sizeof(EVIOBlockRecord); |
1119 | |
1120 | set<uint32_t> block_levels; |
1121 | set<uint32_t> events_in_block; |
1122 | |
1123 | // Loop over all EVIO block records |
1124 | for(uint32_t i=0; i<evio_blocks.size(); i++){ |
1125 | EVIOBlockRecord &br = evio_blocks[i]; |
1126 | events_in_block.insert(br.evio_events.size()); |
1127 | map_size += br.evio_events.size()*sizeof(EVIOEventRecord); |
1128 | |
1129 | for(uint32_t j=0; j<br.evio_events.size(); j++){ |
1130 | EVIOEventRecord &er = br.evio_events[j]; |
1131 | |
1132 | uint32_t block_level; |
1133 | switch(er.event_type){ |
1134 | case kBT_SYNC: Nsync++; break; |
1135 | case kBT_PRESTART: Nprestart++; break; |
1136 | case kBT_GO: Ngo++; break; |
1137 | case kBT_PAUSE: Npause++; break; |
1138 | case kBT_END: Nend++; break; |
1139 | case kBT_EPICS: Nepics++; break; |
1140 | case kBT_BOR: Nbor++; break; |
1141 | case kBT_PHYSICS: |
1142 | block_level = (uint32_t)((er.last_event - er.first_event) + 1); |
1143 | block_levels.insert(block_level); |
1144 | Nphysics += block_level; |
1145 | if(er.first_event<first_event || first_event==0) first_event = er.first_event; |
1146 | if(er.last_event>last_event) last_event = er.last_event; |
1147 | break; |
1148 | default: |
1149 | break; |
1150 | } |
1151 | |
1152 | //_DBG_ << "Block " << i << " event " << j << " " << er.last_event <<" - " << er.first_event << " = " << block_level << endl; |
1153 | } |
1154 | } |
1155 | |
1156 | // form succint string of block levels |
1157 | stringstream ss; |
1158 | set<uint32_t>::iterator it = block_levels.begin(); |
1159 | for(; it!=block_levels.end(); it++) ss << *it << ","; |
1160 | string sblock_levels = ss.str(); |
1161 | if(!sblock_levels.empty()) sblock_levels.erase(sblock_levels.length()-1); |
1162 | |
1163 | // form succint string of events per block |
1164 | ss.str(""); |
1165 | it = events_in_block.begin(); |
1166 | for(; it!=events_in_block.end(); it++){ |
1167 | uint32_t val = *it; |
1168 | ss << val; |
1169 | if(++it==events_in_block.end()) break; |
1170 | if( *it == ++val ){ |
1171 | ss << "-"; |
1172 | for(it++; it!=events_in_block.end(); it++){ |
1173 | if( *it != ++val ){ |
1174 | ss << (val-1) << ","; |
1175 | it--; |
1176 | break; |
1177 | } |
1178 | } |
1179 | }else{ |
1180 | ss << ","; |
1181 | } |
1182 | if( it==events_in_block.end() ) break; |
1183 | } |
1184 | string sevents_in_block = ss.str(); |
1185 | |
1186 | // Print results |
1187 | cout << endl; |
1188 | cout << "EVIO file size: " << (total_size_bytes>>20) << " MB" <<endl; |
1189 | cout << "EVIO block map size: " << (map_size>>10) << " kB" <<endl; |
1190 | cout << "first event: " << first_event << endl; |
1191 | cout << "last event: " << last_event << endl; |
1192 | |
1193 | cout << endl; |
1194 | cout << " Nblocks = " << evio_blocks.size() << endl; |
1195 | cout << " block levels = " << sblock_levels << endl; |
1196 | cout << "events per block = " << sevents_in_block << endl; |
1197 | cout << " Nsync = " << Nsync << endl; |
1198 | cout << " Nprestart = " << Nprestart << endl; |
1199 | cout << " Ngo = " << Ngo << endl; |
1200 | cout << " Npause = " << Npause << endl; |
1201 | cout << " Nend = " << Nend << endl; |
1202 | cout << " Nepics = " << Nepics << endl; |
1203 | cout << " Nbor = " << Nbor << endl; |
1204 | cout << " Nphysics = " << Nphysics << endl; |
1205 | cout << endl; |
1206 | } |
1207 | |
1208 |