Bug Summary

File:libraries/DAQ/HDEVIO.cc
Location:line 74, column 2
Description:Value stored to 'left' is never read

Annotated Source Code

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//---------------------------------
16HDEVIO::HDEVIO(string filename):filename(filename)
17{
18 is_open = false;
19 ifs.open(filename.c_str());
20 if(!ifs.is_open()){
21 ClearErrorMessage();
22 err_mess << "Unable to open EVIO file: " << filename;
23 return;
24 }
25
26 fbuff_size = 10000000; // 40MB input buffer
27 fbuff = new uint32_t[fbuff_size];;
28 fnext = fbuff;
29 fbuff_end = fbuff;
30 fbuff_len = 0;
31 _gcount = 0;
32
33 buff_limit = 5000000; // Don't allow us to allocate more than 5M words for read buffer
34 buff_size = 1024; // initialize with 4kB buffer
35 buff_len = 0;
36 buff = new uint32_t[buff_size];
37 next = buff; // needed so initial calculation of left is 0
38 last_event_len = 0;
39 err_code = HDEVIO_OK;
40
41 Nblocks = 0;
42 Nevents = 0;
43 Nerrors = 0;
44 Nbad_blocks = 0;
45 Nbad_events = 0;
46
47 is_open = true;
48}
49
50//---------------------------------
51// buff_read
52//---------------------------------
53void HDEVIO::buff_read(char* s, streamsize nwords)
54{
55 /// Read n bytes into the specified buffer.
56 /// This will read from the file if needed, or simply copy
57 /// the bytes from the existing fbuff. It is purposely meant
58 /// as a drop-in replacement for ifstream::read so that we
59 /// can make actual reads from the file in larger chunks and
60 /// avoid backwards seeks on the actual file. This is needed
61 /// because the Lustre filesystem is optimized for large data
62 /// reads but smaller reads with backwards seeks tend to cripple
63 /// its performance. The main difference between this and
64 /// ifstream::read is that this does not return an istream&
65 /// reference.
66
67 // Number of words left in fbuff
68 uint64_t left = ((uint64_t)fbuff_end - (uint64_t)fnext)/sizeof(uint32_t);
69
70 // First, copy what's already in fbuff
71 uint64_t Ncopied = nwords<(int64_t)left ? (uint64_t)nwords:left;
72 _gcount = Ncopied*sizeof(uint32_t);
73 if(_gcount>0) memcpy((char*)s, (char*)fnext, _gcount);
74 left -= Ncopied;
Value stored to 'left' is never read
75 fnext += Ncopied;
76 s += _gcount; // advance pointer to user buff in case we need to write more
77
78 // If needed, read in another chunk from the file.
79 // Try and keep last 8 words so if a seekg is called to back
80 // us up that amount, we don't have to call seekg on the file.
81 if( (int64_t)Ncopied < nwords ){
82
83 // Initialize to start of buffer
84 uint32_t *myfbuff = fbuff;
85 uint32_t myfbuff_size = fbuff_size;
86 fbuff_len = 0;
87
88 // If at least 8 words exist in fbuff, then copy last
89 // 8 words into front of fbuff.
90 if( fbuff_len >= 8 ){
91 memcpy((char*)fbuff, (char*)&fbuff[fbuff_len-8], 8*sizeof(uint32_t));
92 myfbuff = &fbuff[8];
93 myfbuff_size -= 8;
94 fbuff_len += 8;
95 }
96
97 // Read in chunk from file
98 ifs.read((char*)myfbuff, myfbuff_size*sizeof(uint32_t));
99 fbuff_len += (uint64_t)(ifs.gcount()/sizeof(uint32_t));
100 fnext = myfbuff;
101 fbuff_end = &fbuff[fbuff_len];
102
103 // Copy remainder of request
104 uint64_t myleft = ((uint64_t)fbuff_end - (uint64_t)fnext)/sizeof(uint32_t);
105
106 uint64_t mynwords = nwords - Ncopied;
107 uint64_t myNcopied = mynwords<myleft ? mynwords:myleft;
108 uint64_t mygcount = myNcopied*sizeof(uint32_t);
109 if(mygcount>0) memcpy((char*)s, (char*)fnext, mygcount);
110 fnext += myNcopied;
111 _gcount += myNcopied*sizeof(uint32_t);
112 }
113}
114
115//---------------------------------
116// buff_seekg
117//---------------------------------
118void HDEVIO::buff_seekg (streamoff off, ios_base::seekdir way)
119{
120 // Convert offset from bytes to words
121 int64_t off_words = (int64_t)off/(int64_t)sizeof(uint32_t);
122
123 // find current position relative to start of buffer in words
124 int64_t fpos = (int64_t)((uint64_t)fnext - (uint64_t)fbuff)/sizeof(uint32_t);
125
126 // Seek depending on what user has requested
127 if( way == ios_base::cur ){
128
129 // Add requested offset
130 fpos += off_words; // desired position relative to start of fbuff
131
132 if(fpos>=0 && fpos<(int64_t)fbuff_len){
133 // Request is to a point inside current buffer
134 fnext = &fbuff[fpos];
135 _gcount = 0;
136 }else if(fpos<0){
137 // Seek point is outside of buffer. Move file pointer
138 // and indicate buffer is now empty so next buff_read()
139 // call will force a read.
140
141 // Current file position should be just after end of fbuff
142 // Subtract fbuff_len to move it back to start of fbuff.
143 // fpos is position relative to start of fbuff.
144 off = (streamoff)fpos - (streamoff)fbuff_len; // offset relative to actual current file position
145
146 ifs.seekg(off);
147
148 // Set fbuff parameters to indicate no valid data
149 fnext = fbuff;
150 fbuff_end = fbuff;
151 fbuff_len = 0;
152 _gcount = 0;
153
154 }
155
156 }else{
157 _DBG_cout<<"libraries/DAQ/HDEVIO.cc"<<":"<<157<<
" "
<<"buff_seekg called with something other than ios_base::cur is unsupported!" << endl;
158 exit(-1);
159 }
160}
161
162//---------------------------------
163// ReadBlock
164//---------------------------------
165bool HDEVIO::ReadBlock(void)
166{
167 /// Read in the next EVIO block. Return true if successful
168 /// and false otherwise.
169
170 err_code = HDEVIO_OK;
171 next = NULL__null;
172
173 buff_read((char*)buff, 8);
174 uint32_t valid_words = buff_gcount()/sizeof(uint32_t);
175 if(valid_words != 8){
176 SetErrorMessage("Could not read in 8 word EVIO block header!");
177 err_code = HDEVIO_FILE_TRUNCATED;
178 Nerrors++;
179 return false;
180 }
181
182 // Check endianess
183 if(buff[7]!=0xc0da0100 && buff[7]!=0x0001dac0){
184 ClearErrorMessage();
185 err_mess << "Magic word not valid!: " << HexStr(buff[7]) << endl;
186 err_code = HDEVIO_BAD_BLOCK_HEADER;
187 Nerrors++;
188 Nbad_blocks++;
189 return false;
190 }
191 swap_needed = (buff[7]==0x0001dac0);
192
193 // Swap header (if needed)
194 if(swap_needed) swap_block(buff, 8, buff);
195
196 // Re-allocate buffer if needed so we can read in entire block
197 uint32_t block_length = buff[0];
198 if(buff_size < block_length){
199 if(block_length > buff_limit){
200 ClearErrorMessage();
201 err_mess << "ERROR: EVIO block length greater than allocation limit (" << block_length <<" > " << block_length << " words)" << endl;
202 err_code = HDEVIO_BLOCKSIZE_GREATER_THAN_LIMIT;
203 Nerrors++;
204 return false;
205 }
206 if(buff) delete[] buff;
207 buff_size = block_length;
208 buff = new uint32_t[buff_size];
209 if(buff == NULL__null){
210 ClearErrorMessage();
211 err_mess << "ERROR: unable to allocate " << block_length <<" words" << endl;
212 err_code = HDEVIO_MEMORY_ALLOCATION_ERROR;
213 return false;
214 }
215
216 // Re-read in the block header
217 buff_seekg(-8*sizeof(uint32_t), ifs.cur);
218 buff_read((char*)buff, 8);
219 if(swap_needed) swap_block(buff, 8, buff);
220 }
221
222 if(block_length == 8){
223 // block_length =8 indicates end of file.
224 SetErrorMessage("end of file");
225 err_code = HDEVIO_EOF;
226 return false;
227 }
228
229 // Read payload of block
230 buff_read((char*)&buff[8], (block_length-8));
231 valid_words = 8 + buff_gcount()/sizeof(uint32_t);
232 if(valid_words < block_length){
233 ClearErrorMessage();
234 err_mess << "Error reading in EVIO entire block! (block number: " << buff[1] << ")" << endl;
235 err_mess << "valid_words="<<valid_words << " block_length=" << block_length;
236 err_code = HDEVIO_FILE_TRUNCATED;
237 Nerrors++;
238 return false;
239 }
240
241 // Set pointers
242 buff_len = valid_words;
243 buff_end = &buff[valid_words];
244 next = &buff[8];
245 bh = (BLOCKHEADER_t*)buff;
246
247 Nblocks++;
248 return true;
249}
250
251//---------------------------------
252// read
253//---------------------------------
254bool HDEVIO::read(uint32_t *user_buff, uint32_t user_buff_len)
255{
256 /// Read the next EVIO event into the user supplied buffer.
257 /// Return true if successful and false otherwise. Details of
258 /// the error will be in err_mess.
259
260 err_code = HDEVIO_OK;
261
262 // calculate remaining valid words in buffer
263 uint32_t left = buff_len - (uint32_t)(((unsigned long)next - (unsigned long)buff)/sizeof(uint32_t));
264
265 // Read in another event block if necessary
266 if(left < 1 || next==NULL__null){
267 bool isgood = ReadBlock();
268 if(!isgood) return false;
269 left = buff_len - 8;
270 }
271
272 if(next == NULL__null){
273 SetErrorMessage("No valid events in buffer");
274 err_code = HDEVIO_NO_EVENTS_IN_BUFFER;
275 return false;
276 }
277
278 // Check if next event will fit into user supplied buffer
279 uint32_t event_len = next[0];
280 if(swap_needed) swap_block(&event_len, 1, &event_len);
281 event_len++; // include length word for EVIO bank
282 last_event_len = event_len;
283
284 // Check that event isn't claiming to be larger than EVIO block
285 if( event_len > left ){
286 ClearErrorMessage();
287 err_mess << "WARNING: EVIO bank indicates a bigger size than block header (" << event_len << " > " << left << ")";
288 next = &buff[buff_len]; // setup so subsequent call will read in another block
289 err_code = HDEVIO_EVENT_BIGGER_THAN_BLOCK;
290 Nerrors++;
291 Nbad_blocks++;
292 return false;
293 }
294
295 // Check if user buffer is big enough to hold this
296 if(event_len > user_buff_len){
297 ClearErrorMessage();
298 err_mess << "user buffer too small for event (" << user_buff_len << " < " << event_len << ")";
299 err_code = HDEVIO_USER_BUFFER_TOO_SMALL;
300 return false;
301 }
302
303 // Copy entire event into user buffer, swapping if needed during copy
304 bool isgood = true;
305 if(swap_needed){
306 uint32_t Nswapped = swap_bank(user_buff, next, event_len);
307 isgood = (Nswapped == event_len);
308 }else{
309 memcpy(user_buff, next, event_len*sizeof(uint32_t));
310 }
311
312 // Advance next pointer to next EVIO event or past end of buffer.
313 next = &next[event_len];
314
315 if(isgood) Nevents++;
316
317 return isgood;
318}
319
320
321//---------------------------------
322// ~HDEVIO (Destructor)
323//---------------------------------
324HDEVIO::~HDEVIO()
325{
326 if(ifs.is_open()) ifs.close();
327 if(buff) delete[] buff;
328}
329
330//---------------------------------
331// swap_bank
332//---------------------------------
333uint32_t HDEVIO::swap_bank(uint32_t *outbuff, uint32_t *inbuff, uint32_t len)
334{
335 /// Swap an EVIO bank. If the bank contains data, it is automatically
336 /// swapped according to it's type. If the bank is a container of other
337 /// containers, then this repeatedly calls the swapper methods for the
338 /// appropriate container type (bank, tagsegment, segment). This means
339 /// that this method will be recursive in the cases where it is a bank
340 /// of banks.
341
342 if(len < 2){
343 SetErrorMessage("Attempt to swap bank with len<2");
344 err_code = HDEVIO_BANK_TRUNCATED;
345 Nerrors++;
346 Nbad_events++;
347 return 0;
348 }
349
350 // Swap length and header words
351 swap_block(inbuff, 2, outbuff);
352 uint32_t bank_len = outbuff[0];
353 if((bank_len+1) > len){
354 ClearErrorMessage();
355 err_mess << "WARNING: Bank length word exceeds valid words in buffer (" << bank_len+1 << " > " << len << ")";
356 err_code = HDEVIO_BANK_TRUNCATED;
357 Nerrors++;
358 Nbad_events++;
359 return 0;
360 }
361
362 uint32_t type = (outbuff[1]>>8) & 0xFF;
363 uint32_t Nwords = bank_len - 1;
364 uint32_t Nswapped = 2;
365 switch(type){
366 case 0x0a: // 64 bit unsigned int
367 case 0x08: // 64 bit double
368 case 0x09: // 64 bit signed int
369 swap_block((uint64_t*)&inbuff[2], Nwords/2, (uint64_t*)&outbuff[2]);
370 Nswapped += Nwords;
371 break;
372 case 0x01: // 32 bit unsigned int
373 case 0x02: // 32 bit float
374 case 0x0b: // 32 bit signed int
375 swap_block(&inbuff[2], Nwords, &outbuff[2]);
376 Nswapped += Nwords;
377 break;
378 case 0x05: // 16 bit unsigned int
379 case 0x04: // 16 bit signed int
380 swap_block((uint16_t*)&inbuff[2], Nwords*2, (uint16_t*)&outbuff[2]);
381 Nswapped += Nwords;
382 break;
383 case 0x00: // 32 bit unknown (not swapped)
384 case 0x07: // 8 bit unsigned int
385 case 0x06: // 8 bit signed int
386 memcpy((uint8_t*)&outbuff[2], (uint8_t*)&inbuff[2], Nwords*sizeof(uint32_t));
387 Nswapped += Nwords;
388 break;
389 case 0x0c:
390 while(Nswapped < (Nwords+2)){
391 uint32_t N = swap_tagsegment(&outbuff[Nswapped], &inbuff[Nswapped], (Nwords+2)-Nswapped);
392 if(N == 0) return Nswapped;
393 Nswapped += N;
394 }
395 break;
396 case 0x0d:
397 case 0x20:
398 while(Nswapped < (Nwords+2)){
399 uint32_t N = swap_segment(&outbuff[Nswapped], &inbuff[Nswapped], (Nwords+2)-Nswapped);
400 if(N == 0) return Nswapped;
401 Nswapped += N;
402 }
403 break;
404 case 0x0e:
405 case 0x10:
406 while(Nswapped < (Nwords+2)){
407 uint32_t N = swap_bank(&outbuff[Nswapped], &inbuff[Nswapped], (Nwords+2)-Nswapped);
408 if(N == 0) return Nswapped;
409 Nswapped += N;
410 }
411 break;
412 default:
413 ClearErrorMessage();
414 err_mess << "WARNING: unknown bank type (0x" << hex << type << dec << ")";
415 err_code = HDEVIO_UNKNOWN_BANK_TYPE;
416 Nerrors++;
417 Nbad_events++;
418 return 0;
419 break;
420 }
421
422 return Nswapped;
423}
424
425//---------------------------------
426// swap_tagsegment
427//---------------------------------
428uint32_t HDEVIO::swap_tagsegment(uint32_t *outbuff, uint32_t *inbuff, uint32_t len)
429{
430 /// Swap an EVIO tagsegment.
431
432 if(len < 1){
433 SetErrorMessage("Attempt to swap segment with len<1");
434 err_code = HDEVIO_BANK_TRUNCATED;
435 Nerrors++;
436 Nbad_events++;
437 return 0;
438 }
439
440 // Swap header/length word
441 swap_block(inbuff, 1, outbuff);
442 uint32_t bank_len = outbuff[0] & 0xFFFF;
443 if((bank_len) > len){
444 ClearErrorMessage();
445 err_mess << "Segment length word exceeds valid words in buffer (" << bank_len << " > " << len << ")";
446 err_code = HDEVIO_BANK_TRUNCATED;
447 Nerrors++;
448 Nbad_events++;
449 return 0;
450 }
451
452 uint32_t type = (outbuff[0]>>16) & 0x0F;
453 uint32_t Nwords = bank_len;
454 uint32_t Nswapped = 1;
455 switch(type){
456 case 0x0a: // 64 bit unsigned int
457 case 0x08: // 64 bit double
458 case 0x09: // 64 bit signed int
459 swap_block((uint64_t*)&inbuff[1], Nwords/2, (uint64_t*)&outbuff[1]);
460 Nswapped += Nwords;
461 break;
462 case 0x01: // 32 bit unsigned int
463 case 0x02: // 32 bit float
464 case 0x0b: // 32 bit signed int
465 swap_block(&inbuff[1], Nwords, &outbuff[1]);
466 Nswapped += Nwords;
467 break;
468 case 0x05: // 16 bit unsigned int
469 case 0x04: // 16 bit signed int
470 swap_block((uint16_t*)&inbuff[1], Nwords*2, (uint16_t*)&outbuff[1]);
471 Nswapped += Nwords;
472 break;
473 case 0x00: // 32 bit unknown (not swapped)
474 case 0x07: // 8 bit unsigned int
475 case 0x06: // 8 bit signed int
476 memcpy((uint8_t*)&outbuff[1], (uint8_t*)&inbuff[1], Nwords*sizeof(uint32_t));
477 Nswapped += Nwords;
478 break;
479 }
480
481 return Nswapped;
482}
483
484//---------------------------------
485// swap_segment
486//---------------------------------
487uint32_t HDEVIO::swap_segment(uint32_t *outbuff, uint32_t *inbuff, uint32_t len)
488{
489 /// Swap an EVIO segment.
490
491 if(len < 1){
492 SetErrorMessage("Attempt to swap segment with len<1");
493 err_code = HDEVIO_BANK_TRUNCATED;
494 Nerrors++;
495 Nbad_events++;
496 return 0;
497 }
498
499 // Swap header/length word
500 swap_block(inbuff, 1, outbuff);
501 uint32_t bank_len = outbuff[0] & 0xFFFF;
502 if((bank_len) > len){
503 ClearErrorMessage();
504 err_mess << "Segment length word exceeds valid words in buffer (" << bank_len << " > " << len << ")";
505 err_code = HDEVIO_BANK_TRUNCATED;
506 Nerrors++;
507 Nbad_events++;
508 return 0;
509 }
510
511 uint32_t type = (outbuff[0]>>16) & 0x3F;
512 uint32_t Nwords = bank_len;
513 uint32_t Nswapped = 1;
514 switch(type){
515 case 0x0a: // 64 bit unsigned int
516 case 0x08: // 64 bit double
517 case 0x09: // 64 bit signed int
518 swap_block((uint64_t*)&inbuff[1], Nwords/2, (uint64_t*)&outbuff[1]);
519 Nswapped += Nwords;
520 break;
521 case 0x01: // 32 bit unsigned int
522 case 0x02: // 32 bit float
523 case 0x0b: // 32 bit signed int
524 swap_block(&inbuff[1], Nwords, &outbuff[1]);
525 Nswapped += Nwords;
526 break;
527 case 0x05: // 16 bit unsigned int
528 case 0x04: // 16 bit signed int
529 swap_block((uint16_t*)&inbuff[1], Nwords*2, (uint16_t*)&outbuff[1]);
530 Nswapped += Nwords;
531 break;
532 case 0x00: // 32 bit unknown (not swapped)
533 case 0x07: // 8 bit unsigned int
534 case 0x06: // 8 bit signed int
535 memcpy((uint8_t*)&outbuff[1], (uint8_t*)&inbuff[1], Nwords*sizeof(uint32_t));
536 Nswapped += Nwords;
537 break;
538 }
539
540 return Nswapped;
541}
542
543//------------------------
544// Print_fbuff
545//------------------------
546void HDEVIO::Print_fbuff(void)
547{
548 cout << endl;
549 cout << " fbuff: " << hex << (uint64_t)fbuff << dec << endl;
550 cout << " fnext: " << hex << (uint64_t)fnext << dec << endl;
551 cout << " fbuff_end: " << hex << (uint64_t)fbuff_end << dec << endl;
552 cout << " fbuff_size: " << fbuff_size << endl;
553 cout << " fbuff_len: " << fbuff_len << endl;
554 cout << " _gcount: " << _gcount << endl;
555}
556
557//------------------------
558// PrintEVIOBlockHeader
559//------------------------
560void HDEVIO::PrintEVIOBlockHeader(void)
561{
562
563 cout << endl;
564 cout << "EVIO Block Header:" << endl;
565 cout << "------------------------" << endl;
566 cout << " Block Length: " << HexStr(buff[0]) << " (" << buff[0] << " words = " << (buff[0]>>(10-2)) << " kB)" << endl;
567 cout << " Block Number: " << HexStr(buff[1]) << endl;
568 cout << "Header Length: " << HexStr(buff[2]) << " (should be 8)" << endl;
569 cout << " Event Count: " << HexStr(buff[3]) << endl;
570 cout << " Reserved 1: " << HexStr(buff[4]) << endl;
571 cout << " Bit Info: " << HexStr(buff[5]>>8) << endl;
572 cout << " Version: " << HexStr(buff[5]&0xFF) << endl;
573 cout << " Reserved 3: " << HexStr(buff[6]) << endl;
574 cout << " Magic word: " << HexStr(buff[7]) << (swap_needed ? " (after swapping)":"") << endl;
575 cout << "Byte swapping is" << (swap_needed ? " ":" not ") << "needed" << endl;
576}
577
578//------------------------
579// PrintStats
580//------------------------
581void HDEVIO::PrintStats(void)
582{
583 cout << endl;
584 cout << "EVIO Statistics for " << filename << " :" << endl;
585 cout << "------------------------" << endl;
586 cout << " Nblocks: " << Nblocks << endl;
587 cout << " Nevents: " << Nevents << endl;
588 cout << " Nerrors: " << Nerrors << endl;
589 cout << "Nbad_blocks: " << Nbad_blocks << endl;
590 cout << "Nbad_events: " << Nbad_events << endl;
591 cout << endl;
592}
593
594