ROOTANA
Loading...
Searching...
No Matches
midasio.cxx
Go to the documentation of this file.
1// midasio.cxx
2
3#include "midasio.h"
4
5#include <stdio.h>
6#include <assert.h>
7#include <stdlib.h> // malloc()
8#include <string.h> // memcpy()
9#include <errno.h> // errno
10#include <signal.h> // signal()
11#include <ctime> // time()
12
13#include <string>
14
15#undef NDEBUG // working assert() is required by this program. K.O.
16
19
21{
23 printf("TMReaderInterface::ctor!\n");
24 fError = false;
25 fErrorString = "";
26}
27
28static std::string to_string(int v)
29{
30 char buf[256];
31 snprintf(buf, sizeof(buf), "%d", v);
32 return buf;
33}
34
35static std::string Errno(const char* s)
36{
37 std::string r;
38 r += s;
39 r += " failed: errno: ";
40 r += to_string(errno);
41 r += " (";
42 r += strerror(errno);
43 r += ")";
44 return r;
45}
46
47static int ReadPipe(FILE *fp, char* buf, int length)
48{
49 int count = 0;
50 while (length > 0) {
51 int rd = fread(buf, 1, length, fp);
52 if (rd < 0)
53 return rd;
54 if (rd == 0)
55 return count;
56
57 buf += rd;
58 length -= rd;
59 count += rd;
60 }
61 return count;
62}
63
64
66{
67 public:
68 ErrorReader(const char* filename)
69 {
71 printf("ErrorReader::ctor!\n");
72 fError = true;
73 fErrorString = "The ErrorReader always returns an error";
74 }
75
76 ~ErrorReader() // dtor
77 {
79 printf("ErrorReader::dtor!\n");
80 }
81
82 int Read(void* buf, int count)
83 {
84 return -1;
85 }
86
87 int Close()
88 {
89 // an exception, no error on close.
90 return 0;
91 }
92};
93
95{
96 public:
97 FileReader(const char* filename)
98 {
100 printf("FileReader::ctor!\n");
101 fFilename = filename;
102 fFp = fopen(filename, "r");
103 if (!fFp) {
104 fError = true;
105 fErrorString = Errno((std::string("fopen(\"")+filename+"\")").c_str());
106 }
107 }
108
109 ~FileReader() // dtor
110 {
112 printf("FileReader::dtor!\n");
113 if (fFp)
114 Close();
115 }
116
117 int Read(void* buf, int count)
118 {
119 if (fError)
120 return -1;
121 assert(fFp != NULL);
122 int rd = ReadPipe(fFp, (char*)buf, count);
123 if (rd < 0) {
124 fError = true;
125 fErrorString = Errno((std::string("fread(\"")+fFilename+"\")").c_str());
126 }
127 return rd;
128 }
129
130 int Close()
131 {
133 printf("FileReader::Close!\n");
134 if (fFp) {
135 fclose(fFp);
136 fFp = NULL;
137 }
138 return 0;
139 }
140
141 std::string fFilename;
142 FILE* fFp;
143};
144
146{
147 public:
148 PipeReader(const char* pipename)
149 {
151 printf("PipeReader::ctor!\n");
152 fPipename = pipename;
153 fPipe = popen(pipename, "r");
154 if (!fPipe) {
155 fError = true;
156 fErrorString = Errno((std::string("popen(\"")+pipename+"\")").c_str());
157 }
158 }
159
160 ~PipeReader() // dtor
161 {
163 printf("PipeReader::dtor!\n");
164 if (fPipe)
165 Close();
166 }
167
168 int Read(void* buf, int count)
169 {
170 if (fError)
171 return -1;
172 assert(fPipe != NULL);
173 int rd = ReadPipe(fPipe, (char*)buf, count);
174 if (rd < 0) {
175 fError = true;
176 fErrorString = Errno((std::string("fread(\"")+fPipename+"\")").c_str());
177 }
178 return rd;
179 }
180
181 int Close()
182 {
184 printf("PipeReader::Close!\n");
185 if (fPipe) {
186 pclose(fPipe); // FIXME: check error // only need to check error if writing to pipe
187 fPipe = NULL;
188 }
189 return 0;
190 }
191
192 std::string fPipename;
193 FILE* fPipe;
194};
195
196#include <zlib.h>
197
199{
200 public:
201 ZlibReader(const char* filename)
202 {
204 printf("ZlibReader::ctor!\n");
205 fFilename = filename;
206 fGzFile = gzopen(filename, "rb");
207 if (!fGzFile) {
208 fError = true;
209 fErrorString = Errno((std::string("gzopen(\"")+fFilename+"\")").c_str());
210 }
211 }
212
213 ~ZlibReader() // dtor
214 {
216 printf("PipeReader::dtor!\n");
217 if (fGzFile)
218 Close();
219 }
220
221 int Read(void* buf, int count)
222 {
223 if (fError)
224 return -1;
225 assert(fGzFile != NULL);
226 int rd = gzread(fGzFile, buf, count);
227 if (rd < 0) {
228 fError = true;
229 fErrorString = Errno((std::string("gzread(\"")+fFilename+"\")").c_str());
230 }
231 return rd;
232 }
233
234 int Close()
235 {
237 printf("ZlibReader::Close!\n");
238 if (fGzFile) {
239 gzclose(fGzFile); // FIXME: must check error on write, ok no check on read
240 fGzFile = NULL;
241 }
242 return 0;
243 }
244
245 std::string fFilename;
246 gzFile fGzFile;
247};
248
249#include "mlz4frame.h"
250
251static std::string Lz4Error(int errorCode)
252{
253 std::string s;
254 s += to_string(errorCode);
255 s += " (";
256 s += MLZ4F_getErrorName(errorCode);
257 s += ")";
258 return s;
259}
260
262{
263public:
265 {
266 assert(reader);
267 // If there is an error opening the file, the decompression will
268 // not do anything (not even report an error)
269 if (reader->fError)
270 {
271 fError = reader->fError;
272 fErrorString = reader->fErrorString;
273 }
274 fReader = reader;
275
277 printf("Lz4Reader::ctor!\n");
278
280 if (MLZ4F_isError(errorCode)) {
281 fError = true;
282 fErrorString = "MLZ4F_createDecompressionContext() error ";
283 fErrorString += Lz4Error(errorCode);
284 }
285
286 fSrcBuf = NULL;
287 fSrcBufSize = 0;
288 fSrcBufStart = 0;
289 fSrcBufHave = 0;
290
291 AllocSrcBuf(1024*1024);
292 }
293
296 printf("Lz4Reader::dtor!\n");
297
298 if (fSrcBuf) {
299 free(fSrcBuf);
300 fSrcBuf = NULL;
301 }
302
304 if (MLZ4F_isError(errorCode)) {
305 fError = true;
306 fErrorString = "MLZ4F_freeDecompressionContext() error ";
307 fErrorString += Lz4Error(errorCode);
308 // NB: this error cannot be reported: we are in the destructor, fErrorString
309 // is immediately destroyed...
310 }
311
312 if (fReader) {
313 delete fReader;
314 fReader = NULL;
315 }
316 }
317
318
319 int Read(void* buf, int count)
320 {
321 if (fError)
322 return -1;
323
324 //printf("Lz4Reader::Read %d bytes!\n", count);
325
326 char* cptr = (char*)buf;
327 int clen = 0;
328
329 while (clen < count) {
330 int more = count - clen;
331
332 if (fSrcBufHave == 0) {
333 assert(fSrcBufStart == 0);
334
335 int rd = fReader->Read(fSrcBuf, fSrcBufSize);
336
337 //printf("read asked %d, got %d\n", to_read, rd);
338
339 if (rd < 0) {
340 if (clen > 0)
341 return clen;
342 else
343 return rd;
344 } else if (rd == 0) {
345 return clen;
346 }
347
348 fSrcBufHave += rd;
349
350 //printf("Lz4Reader::ReadMore: rd %d, srcbuf start %d, have %d\n", rd, fSrcBufStart, fSrcBufHave);
351 }
352
353 MLZ4F_decompressOptions_t* dOptPtr = NULL;
354
355 char* dst = cptr;
356 size_t dst_size = more;
357 size_t src_size = fSrcBufHave;
358
359 size_t status = MLZ4F_decompress(fContext, dst, &dst_size, fSrcBuf + fSrcBufStart, &src_size, dOptPtr);
360
361 if (MLZ4F_isError(status)) {
362 fError = true;
363 fErrorString = "MLZ4F_decompress() error ";
364 fErrorString += Lz4Error(status);
365 return -1;
366 }
367
368 //printf("LZ4Reader::Decompress: status %d, dst_size %d -> %d, src_size %d -> %d\n", (int)status, more, (int)dst_size, fSrcBufHave, (int)src_size);
369
370 assert(dst_size!=0 || src_size!=0); // make sure we make progress
371
372 clen += dst_size;
373 cptr += dst_size;
374
375 fSrcBufStart += src_size;
376 fSrcBufHave -= src_size;
377
378 if (fSrcBufHave == 0)
379 fSrcBufStart = 0;
380 }
381
382 //printf("Lz4Reader::Read %d bytes, returning %d bytes!\n", count, clen);
383 return clen;
384 }
385
386 int Close()
387 {
389 printf("Lz4Reader::Close!\n");
390 return fReader->Close();
391 }
392
393 void AllocSrcBuf(int size)
394 {
395 //printf("Lz4Reader::AllocSrcBuffer %d -> %d bytes!\n", fSrcBufSize, size);
396 fSrcBuf = (char*) realloc(fSrcBuf, size);
397 assert(fSrcBuf != NULL);
398 fSrcBufSize = size;
399 }
400
403
407 char* fSrcBuf;
408};
409
411{
412 public:
413 FileWriter(const char* filename)
414 {
415 fFilename = filename;
416 fFp = fopen(filename, "w");
417 assert(fFp != NULL); // FIXME: check for error
418 }
419
420 int Write(const void* buf, int count)
421 {
422 assert(fFp != NULL);
423 return fwrite(buf, 1, count, fFp);
424 }
425
426 int Close()
427 {
428 assert(fFp != NULL);
429 fclose(fFp);
430 fFp = NULL;
431 return 0;
432 }
433
434 std::string fFilename;
435 FILE* fFp;
436};
437
438static int hasSuffix(const char*name,const char*suffix)
439{
440 const char* s = strstr(name,suffix);
441 if (s == NULL)
442 return 0;
443
444 return (s-name)+strlen(suffix) == strlen(name);
445}
446
448{
449#ifdef SIGPIPE
450 signal(SIGPIPE, SIG_IGN); // crash if reading from closed pipe
451#endif
452#ifdef SIGXFSZ
453 signal(SIGXFSZ, SIG_IGN); // crash if reading from file >2GB without O_LARGEFILE
454#endif
455
456 if (0)
457 {
458 }
459 else if (strncmp(source, "ssh://", 6) == 0)
460 {
461 const char* name = source + 6;
462 const char* s = strstr(name, "/");
463
464 if (s == NULL) {
466 e->fError = true;
467 e->fErrorString = "TMidasFile::Open: Invalid ssh:// URI. Should be: ssh://user@host/file/path/...";
468 return e;
469 }
470
471 const char* remoteFile = s + 1;
472
473 std::string remoteHost;
474 for (s=name; *s != '/'; s++)
475 remoteHost += *s;
476
477 std::string pipe;
478
479 pipe = "ssh -e none -T -x -n ";
480 pipe += remoteHost;
481 pipe += " dd if=";
482 pipe += remoteFile;
483 pipe += " bs=1024k";
484
485 if (hasSuffix(remoteFile,".gz"))
486 pipe += " | gzip -dc";
487 else if (hasSuffix(remoteFile,".bz2"))
488 pipe += " | bzip2 -dc";
489 else if (hasSuffix(remoteFile,".lz4"))
490 pipe += " | lz4 -d";
491
492 return new PipeReader(pipe.c_str());
493 }
494 else if (strncmp(source, "dccp://", 7) == 0)
495 {
496 const char* name = source + 7;
497
498 std::string pipe;
499
500 pipe = "dccp ";
501 pipe += name;
502 pipe += " /dev/fd/1";
503
504 if (hasSuffix(source,".gz"))
505 pipe += " | gzip -dc";
506 else if (hasSuffix(source,".bz2"))
507 pipe += " | bzip2 -dc";
508 else if (hasSuffix(source,".lz4"))
509 pipe += " | lz4 -d";
510
511 return new PipeReader(pipe.c_str());
512 }
513 else if (strncmp(source, "pipein://", 9) == 0)
514 {
515 std::string pipe = source + 9;
516 return new PipeReader(pipe.c_str());
517 }
518#if 0 // read compressed files using the zlib library
519 else if (hasSuffix(source, ".gz"))
520 {
521 pipe = "gzip -dc ";
522 pipe += source;
523 }
524#endif
525 else if (hasSuffix(source, ".gz"))
526 {
527 return new ZlibReader(source);
528 }
529 else if (hasSuffix(source, ".bz2"))
530 {
531 return new PipeReader((std::string("bzip2 -dc ") + source).c_str());
532 }
533 else if (hasSuffix(source, ".lz4"))
534 {
535 return new Lz4Reader(new FileReader(source));
536 }
537 else
538 {
539 return new FileReader(source);
540 }
541}
542
543TMWriterInterface* TMNewWriter(const char* destination)
544{
545 if (0) {
546#if 0
547 } else if (hasSuffix(source, ".gz")) {
548 return new ZlibReader(source);
549 } else if (hasSuffix(source, ".bz2")) {
550 return new PipeReader((std::string("bzip2 -dc ") + source).c_str());
551 } else if (hasSuffix(source, ".lz4")) {
552 return new Lz4Reader(new FileReader(source));
553#endif
554 } else {
555 return new FileWriter(destination);
556 }
557}
558
559static uint16_t GetU16(const void*ptr)
560{
561 return *(uint16_t*)ptr;
562}
563
564static uint32_t GetU32(const void*ptr)
565{
566 return *(uint32_t*)ptr;
567}
568
569static void PutU16(char* ptr, uint16_t v)
570{
571 *(uint16_t*)ptr = v;
572}
573
574static void PutU32(char* ptr, uint32_t v)
575{
576 *(uint32_t*)ptr = v;
577}
578
579static size_t Align8(size_t size)
580{
581 // align to 8 bytes (uint64_t)
582 return (size + 7) & ~7;
583}
584
586{
587 bool gOnce = true;
588 if (gOnce) {
589 gOnce = false;
590 assert(sizeof(char)==1);
591 assert(sizeof(uint16_t)==2);
592 assert(sizeof(uint32_t)==4);
593 }
594
595 TMEvent* e = new TMEvent;
596
597 e->Reset();
598
599 const int event_header_size = 4*4;
600 char event_header[event_header_size];
601
602 int rd = reader->Read(event_header, event_header_size);
603
604 if (rd < 0) { // read error
605 delete e;
606 return NULL;
607 } else if (rd == 0) { // end of file
608 delete e;
609 return NULL;
610 } else if (rd != event_header_size) { // truncated data in file
611 fprintf(stderr, "TMReadEvent: error: read %d shorter than event header size %d\n", (int)rd, (int)event_header_size);
612 e->error = true;
613 return e;
614 }
615
616 e->event_id = GetU16(event_header+0);
617 e->trigger_mask = GetU16(event_header+2);
618 e->serial_number = GetU32(event_header+4);
619 e->time_stamp = GetU32(event_header+8);
620 e->data_size = GetU32(event_header+12);
621
622 e->event_header_size = event_header_size;
623
624 e->bank_header_flags = 0;
625
626 //if (!e->old_event.IsGoodSize()) { // invalid event size
627 // e->error = true;
628 // return e;
629 //}
630
631 size_t to_read = e->data_size;
632
633 e->data.resize(event_header_size + to_read);
634
635 memcpy(&e->data[0], event_header, event_header_size);
636
637 rd = reader->Read(&e->data[event_header_size], to_read);
638
639 if (rd < 0) { // read error
640 delete e;
641 return NULL;
642 } else if (rd != (int)to_read) { // truncated data in file
643 fprintf(stderr, "TMReadEvent: error: short read %d instead of %d\n", (int)rd, (int)to_read);
644 e->error = true;
645 return e;
646 }
647
648 return e;
649}
650
651void TMWriteEvent(TMWriterInterface* writer, const TMEvent* event)
652{
653 writer->Write(&(event->data[0]), event->data.size());
654}
655
656std::string TMEvent::HeaderToString() const
657{
658 char buf[1024];
659 snprintf(buf, sizeof(buf), "event: id %d, mask 0x%04x, serial %d, time %d, size %d, error %d, banks %d",
661 return buf;
662}
663
664std::string TMEvent::BankListToString() const
665{
666 std::string s;
667 for (unsigned i=0; i<banks.size(); i++) {
668 if (i>0)
669 s += ",";
670 s += banks[i].name;
671 }
672 return s;
673}
674
675std::string TMEvent::BankToString(const TMBank*b) const
676{
677 char buf[1024];
678 snprintf(buf, sizeof(buf), "name \"%s\", type %d, size %d, offset %d\n",
679 b->name.c_str(), b->type, b->data_size, (int)b->data_offset);
680 return buf;
681}
682
684{
685 Reset();
686}
687
689{
690 error = false;
691
692 event_id = 0;
693 trigger_mask = 0;
694 serial_number = 0;
695 time_stamp = 0;
696 data_size = 0;
697
700
701 banks.clear();
702 data.clear();
703
704 found_all_banks = false;
706}
707
709{
710 ParseHeader(data.data(), data.size());
711
712 if (data.size() != event_header_size + data_size) {
713 fprintf(stderr, "TMEvent::ParseEvent: error: vector size %d mismatch against event size in event header: data_size %d, event_size %d\n", (int)data.size(), (int)data_size, (int)(event_header_size + data_size));
714 error = true;
715 }
716}
717
718void TMEvent::ParseHeader(const void* buf, size_t buf_size)
719{
720 event_header_size = 4*4;
721
722 const char* event_header = (const char*)buf;
723
724 if (buf_size < event_header_size) {
725 fprintf(stderr, "TMEvent::ctor: error: buffer size %d is smaller than event header size %d\n", (int)buf_size, (int)event_header_size);
726 error = true;
727 return;
728 }
729
730 event_id = GetU16(event_header+0);
731 trigger_mask = GetU16(event_header+2);
732 serial_number = GetU32(event_header+4);
733 time_stamp = GetU32(event_header+8);
734 data_size = GetU32(event_header+12);
735
737
738 //if (!e->old_event.IsGoodSize()) { // invalid event size
739 // e->error = true;
740 // return e;
741 //}
742}
743
744TMEvent::TMEvent(const void* buf, size_t buf_size)
745{
746 bool gOnce = true;
747 if (gOnce) {
748 gOnce = false;
749 assert(sizeof(char)==1);
750 assert(sizeof(uint16_t)==2);
751 assert(sizeof(uint32_t)==4);
752 }
753
754 Reset();
755 ParseHeader(buf, buf_size);
756
757 if (error) {
758 return;
759 }
760
761 size_t zdata_size = data_size;
762 size_t zevent_size = zdata_size + event_header_size;
763
764 if (zevent_size != buf_size) {
765 fprintf(stderr, "TMEvent::ctor: error: buffer size %d mismatch against event size in event header: data_size %d, event_size %d\n", (int)buf_size, (int)zdata_size, (int)zevent_size);
766 error = true;
767 return;
768 }
769
770 //data.resize(event_header_size + to_read);
771 //memcpy(&data[0], xdata, event_header_size + to_read);
772
773 const char* cptr = (const char*)buf;
774
775 data.assign(cptr, cptr + zevent_size);
776
777 assert(data.size() == zevent_size);
778}
779
780void TMEvent::Init(uint16_t xevent_id, uint16_t xtrigger_mask, uint32_t xserial_number, uint32_t xtime_stamp, size_t capacity)
781{
782 Reset();
783
784 event_header_size = 4*4;
785
786 event_id = xevent_id;
787 trigger_mask = xtrigger_mask;
788 serial_number = xserial_number;
789 if (xtime_stamp) {
790 time_stamp = xtime_stamp;
791 } else {
792 time_stamp = time(NULL);
793 }
794
795 data_size = 8; // data size: 2 words of bank header, 0 words of data banks
796 bank_header_flags = 0x00000031; // bank header flags, bk_init32a() format
797
798 // bank list is empty
799
801 found_all_banks = false;
802
803 // allocate event buffer
804
805 if (capacity < 1024)
806 capacity = 1024;
807
808 data.reserve(capacity);
809
810 // create event data
811
813
814 char* event_header = data.data();
815
816 PutU16(event_header+0, event_id);
817 PutU16(event_header+2, trigger_mask);
818 PutU32(event_header+4, serial_number);
819 PutU32(event_header+8, time_stamp);
820 PutU32(event_header+12, data_size);
821 PutU32(event_header+16, 0); // bank header data size
822 PutU32(event_header+20, bank_header_flags); // bank header flags
823}
824
825void TMEvent::AddBank(const char* bank_name, int tid, const char* buf, size_t size)
826{
827 assert(data.size() > 0); // must call Init() before calling AddBank()
828
829 size_t bank_size = event_header_size + Align8(size);
830
831 size_t end_of_event_offset = data.size();
832
833 data.resize(end_of_event_offset + bank_size);
834
835 char* pbank = data.data() + end_of_event_offset;
836
837 //printf("AddBank: buf %p size %d, bank size %d, data.size %d, data.data %p, pbank %p, memcpy %p\n", buf, (int)size, (int)bank_size, (int)data.size(), data.data(), pbank, pbank+4*4);
838
839 pbank[0] = bank_name[0];
840 pbank[1] = bank_name[1];
841 pbank[2] = bank_name[2];
842 pbank[3] = bank_name[3];
843 PutU32(pbank+1*4, tid);
844 PutU32(pbank+2*4, size);
845 PutU32(pbank+3*4, 0); // bk_init32a() extra padding/reserved word
846
847 memcpy(pbank+4*4, buf, size);
848
849 // adjust event header
850
851 data_size += bank_size;
852
853 char* event_header = data.data();
854 PutU32(event_header + 12, data_size); // event header
855 PutU32(event_header + 16, data_size - 8); // bank header
856
857 // add a bank record
858
859 if (found_all_banks) {
860 TMBank b;
861 b.name = bank_name;
862 b.type = tid;
863 b.data_size = size;
864 b.data_offset = end_of_event_offset + 4*4;
865 banks.push_back(b);
866 }
867}
868
869static size_t FindFirstBank(TMEvent* e)
870{
871 if (e->error)
872 return 0;
873
874 size_t off = e->event_header_size;
875
876 if (e->data.size() < off + 8) {
877 fprintf(stderr, "TMEvent::FindFirstBank: error: data size %d is too small\n", (int)e->data.size());
878 e->error = true;
879 return 0;
880 }
881
882 uint32_t bank_header_data_size = GetU32(&e->data[off]);
883 uint32_t bank_header_flags = GetU32(&e->data[off+4]);
884
885 //printf("bank header: data size %d, flags 0x%08x\n", bank_header_data_size, bank_header_flags);
886
887 if (bank_header_data_size + 8 != e->data_size) {
888 fprintf(stderr, "TMEvent::FindFirstBank: error: bank header size %d mismatch against data size %d\n", (int)bank_header_data_size, (int)e->data_size);
889 e->error = true;
890 return 0;
891 }
892
893 e->bank_header_flags = bank_header_flags;
894
895 return off+8;
896}
897
898#if 0
899static char xchar(char c)
900{
901 if (c>='0' && c<='9')
902 return c;
903 if (c>='a' && c<='z')
904 return c;
905 if (c>='A' && c<='Z')
906 return c;
907 return '$';
908}
909#endif
910
911static size_t FindNextBank(TMEvent* e, size_t pos, TMBank** pb)
912{
913 if (e->error)
914 return 0;
915
916 size_t remaining = e->data.size() - pos;
917
918 //printf("pos %d, event data_size %d, size %d, remaining %d\n", pos, e->data_size, (int)e->data.size(), remaining);
919
920 if (remaining == 0) {
921 // end of data, no more banks to find
922 e->found_all_banks = true;
923 return 0;
924 }
925
926 if (remaining < 8) {
927 fprintf(stderr, "TMEvent::FindNextBank: error: too few bytes %d remaining at the end of event\n", (int)remaining);
928 e->error = true;
929 e->found_all_banks = true; // no more banks will be found after this error
930 return 0;
931 }
932
933 size_t ibank = e->banks.size();
934 e->banks.resize(ibank+1);
935
936 TMBank* b = &e->banks[ibank];
937
938 b->name.resize(4);
939 b->name[0] = e->data[pos+0];
940 b->name[1] = e->data[pos+1];
941 b->name[2] = e->data[pos+2];
942 b->name[3] = e->data[pos+3];
943 b->name[4] = 0;
944
945 size_t data_offset = 0;
946
947 //printf("bank header flags: 0x%08x\n", e->bank_header_flags);
948
949 if (e->bank_header_flags & (1<<5)) {
950 // bk_init32a format
951 b->type = GetU32(&e->data[pos+4+0]);
952 b->data_size = GetU32(&e->data[pos+4+4]);
953 data_offset = pos+4+4+4+4;
954 } else if (e->bank_header_flags & (1<<4)) {
955 // bk_init32 format
956 b->type = GetU32(&e->data[pos+4+0]);
957 b->data_size = GetU32(&e->data[pos+4+4]);
958 data_offset = pos+4+4+4;
959 } else {
960 // bk_init format
961 b->type = GetU16(&e->data[pos+4+0]);
962 b->data_size = GetU16(&e->data[pos+4+2]);
963 data_offset = pos+4+2+2;
964 }
965
966 b->data_offset = data_offset;
967
968 //printf("found bank at pos %d: %s\n", pos, e->BankToString(b).c_str());
969
970 if (b->type < 1 || b->type >= TID_LAST) {
971 fprintf(stderr, "TMEvent::FindNextBank: error: invalid tid %d\n", b->type);
972 e->error = true;
973 return 0;
974 }
975
976 size_t aligned_data_size = Align8(b->data_size);
977
978 //printf("data_size %d, alignemnt: %d %d, aligned %d\n", b->data_size, align, b->data_size%align, aligned_data_size);
979
980 size_t npos = data_offset + aligned_data_size;
981
982 //printf("pos %d, next bank at %d: [%c%c%c%c]\n", pos, npos, xchar(e->data[npos+0]), xchar(e->data[npos+1]), xchar(e->data[npos+2]), xchar(e->data[npos+3]));
983
984 if (npos > e->data.size()) {
985 fprintf(stderr, "TMEvent::FindNextBank: error: invalid bank data size %d: aligned %d, npos %d, end of event %d\n", b->data_size, (int)aligned_data_size, (int)npos, (int)e->data.size());
986 e->error = true;
987 return 0;
988 }
989
990 if (pb)
991 *pb = b;
992
993 return npos;
994}
995
997{
998 if (error)
999 return NULL;
1000 if (event_header_size == 0)
1001 return NULL;
1002 if (event_header_size > data.size())
1003 return NULL;
1004 if (event_header_size + data_size > data.size())
1005 return NULL;
1006 return &data[event_header_size];
1007}
1008
1009const char* TMEvent::GetEventData() const
1010{
1011 if (error)
1012 return NULL;
1013 if (event_header_size == 0)
1014 return NULL;
1015 if (event_header_size > data.size())
1016 return NULL;
1017 if (event_header_size + data_size > data.size())
1018 return NULL;
1019 return &data[event_header_size];
1020}
1021
1023{
1024 if (error)
1025 return NULL;
1026 if (!b)
1027 return NULL;
1028 if (b->data_offset >= data.size())
1029 return NULL;
1030 if (b->data_offset + b->data_size > data.size())
1031 return NULL;
1032 return &data[b->data_offset];
1033}
1034
1035const char* TMEvent::GetBankData(const TMBank* b) const
1036{
1037 if (error)
1038 return NULL;
1039 if (!b)
1040 return NULL;
1041 if (b->data_offset >= data.size())
1042 return NULL;
1043 if (b->data_offset + b->data_size > data.size())
1044 return NULL;
1045 return &data[b->data_offset];
1046}
1047
1048TMBank* TMEvent::FindBank(const char* bank_name)
1049{
1050 if (error)
1051 return NULL;
1052
1053 // if we already found this bank, return it
1054
1055 if (bank_name)
1056 for (unsigned i=0; i<banks.size(); i++) {
1057 if (banks[i].name == bank_name)
1058 return &banks[i];
1059 }
1060
1061 //printf("found_all_banks %d\n", found_all_banks);
1062
1063 if (found_all_banks)
1064 return NULL;
1065
1066 size_t pos = bank_scan_position;
1067
1068 if (pos == 0)
1069 pos = FindFirstBank(this);
1070
1071 //printf("pos %d\n", pos);
1072
1073 while (pos > 0) {
1074 TMBank* b = NULL;
1075 pos = FindNextBank(this, pos, &b);
1076 bank_scan_position = pos;
1077 //printf("pos %d, b %p\n", pos, b);
1078 if (pos>0 && b && bank_name) {
1079 if (b->name == bank_name)
1080 return b;
1081 }
1082 }
1083
1084 found_all_banks = true;
1085
1086 return NULL;
1087}
1088
1090{
1091 if (found_all_banks)
1092 return;
1093
1094 FindBank(NULL);
1095
1096 assert(found_all_banks);
1097}
1098
1100{
1101 printf("Event: id 0x%04x, mask 0x%04x, serial 0x%08x, time 0x%08x, data size %d, vector size %d, capacity %d\n",
1102 event_id,
1105 time_stamp,
1106 data_size,
1107 (int)data.size(),
1108 (int)data.capacity()
1109 );
1110}
1111
1112void TMEvent::PrintBanks(int level)
1113{
1114 FindAllBanks();
1115
1116 printf("%d banks:", (int)banks.size());
1117 for (size_t i=0; i<banks.size(); i++) {
1118 printf(" %s", banks[i].name.c_str());
1119 }
1120 printf("\n");
1121
1122 if (level > 0) {
1123 for (size_t i=0; i<banks.size(); i++) {
1124 printf("bank %3d: name \"%s\", tid %2d, data_size %8d\n",
1125 (int)i,
1126 banks[i].name.c_str(),
1127 banks[i].type,
1128 banks[i].data_size);
1129 if (level > 1) {
1130 const char* p = GetBankData(&banks[i]);
1131 if (p) {
1132 for (size_t j=0; j<banks[i].data_size; j+=4) {
1133 printf("%11d: 0x%08x\n", (int)j, *(uint32_t*)(p+j));
1134 }
1135 }
1136 }
1137 }
1138 }
1139}
1140
1142{
1143 const char* p = data.data();
1144
1145 // event header
1146 printf(" 0: 0x%08x\n", GetU32(p+0*4));
1147 printf(" 1: 0x%08x\n", GetU32(p+1*4));
1148 printf(" 2: 0x%08x\n", GetU32(p+2*4));
1149 printf(" 3: 0x%08x (0x%08x and 0x%08x-0x10)\n", GetU32(p+3*4), data_size, (int)data.size());
1150
1151 // bank header
1152 printf(" 4: 0x%08x\n", GetU32(p+4*4));
1153 printf(" 5: 0x%08x (0x%08x)\n", GetU32(p+5*4), bank_header_flags);
1154}
1155
1156/* emacs
1157 * Local Variables:
1158 * tab-width: 8
1159 * c-basic-offset: 3
1160 * indent-tabs-mode: nil
1161 * End:
1162 */
1163
ErrorReader(const char *filename)
Definition midasio.cxx:68
int Read(void *buf, int count)
Definition midasio.cxx:82
int Close()
Definition midasio.cxx:87
FileReader(const char *filename)
Definition midasio.cxx:97
int Close()
Definition midasio.cxx:130
FILE * fFp
Definition midasio.cxx:142
int Read(void *buf, int count)
Definition midasio.cxx:117
std::string fFilename
Definition midasio.cxx:141
FILE * fFp
Definition midasio.cxx:435
int Close()
Definition midasio.cxx:426
int Write(const void *buf, int count)
Definition midasio.cxx:420
FileWriter(const char *filename)
Definition midasio.cxx:413
std::string fFilename
Definition midasio.cxx:434
int fSrcBufHave
Definition midasio.cxx:406
int Close()
Definition midasio.cxx:386
Lz4Reader(TMReaderInterface *reader)
Definition midasio.cxx:264
MLZ4F_decompressionContext_t fContext
Definition midasio.cxx:402
TMReaderInterface * fReader
Definition midasio.cxx:401
void AllocSrcBuf(int size)
Definition midasio.cxx:393
int fSrcBufStart
Definition midasio.cxx:405
int fSrcBufSize
Definition midasio.cxx:404
char * fSrcBuf
Definition midasio.cxx:407
int Read(void *buf, int count)
Definition midasio.cxx:319
std::string fPipename
Definition midasio.cxx:192
int Close()
Definition midasio.cxx:181
FILE * fPipe
Definition midasio.cxx:193
int Read(void *buf, int count)
Definition midasio.cxx:168
PipeReader(const char *pipename)
Definition midasio.cxx:148
uint32_t type
type of bank data, enum of TID_xxx
Definition midasio.h:47
uint32_t data_size
size of bank data in bytes
Definition midasio.h:48
size_t data_offset
offset of data for this bank in the event data[] container
Definition midasio.h:49
std::string name
bank name, 4 characters max
Definition midasio.h:46
std::string BankListToString() const
print the list of MIDAS banks
Definition midasio.cxx:664
void PrintHeader() const
Definition midasio.cxx:1099
void FindAllBanks()
scan the MIDAS event, find all data banks
Definition midasio.cxx:1089
std::string HeaderToString() const
print the MIDAS event header
Definition midasio.cxx:656
TMBank * FindBank(const char *bank_name)
scan the MIDAS event
Definition midasio.cxx:1048
bool found_all_banks
all the banks in the event data have been discovered
Definition midasio.h:71
std::vector< TMBank > banks
list of MIDAS banks, fill using FindAllBanks()
Definition midasio.h:66
void Reset()
reset everything
Definition midasio.cxx:688
void PrintBanks(int level=0)
Definition midasio.cxx:1112
void AddBank(const char *bank_name, int tid, const char *buf, size_t size)
add new MIDAS bank
Definition midasio.cxx:825
char * GetEventData()
get pointer to MIDAS event data
Definition midasio.cxx:996
void DumpHeader() const
Definition midasio.cxx:1141
void Init(uint16_t event_id, uint16_t trigger_mask=0, uint32_t serial_number=0, uint32_t time_stamp=0, size_t capacity=0)
Definition midasio.cxx:780
uint32_t time_stamp
MIDAS event time stamp (unix time in sec)
Definition midasio.h:60
size_t bank_scan_position
location where scan for MIDAS banks was last stopped
Definition midasio.h:72
uint32_t bank_header_flags
flags from the MIDAS event bank header
Definition midasio.h:64
void ParseHeader(const void *buf, size_t buf_size)
parse event header
Definition midasio.cxx:718
void ParseEvent()
parse event data
Definition midasio.cxx:708
std::vector< char > data
MIDAS event bytes.
Definition midasio.h:67
size_t event_header_size
size of MIDAS event header
Definition midasio.h:63
uint32_t serial_number
MIDAS event serial number.
Definition midasio.h:59
uint32_t data_size
MIDAS event data size.
Definition midasio.h:61
uint16_t trigger_mask
MIDAS trigger mask.
Definition midasio.h:58
uint16_t event_id
MIDAS event ID.
Definition midasio.h:57
char * GetBankData(const TMBank *)
get pointer to MIDAS data bank
Definition midasio.cxx:1022
bool error
event has an error - incomplete, truncated, inconsistent or corrupted
Definition midasio.h:55
std::string BankToString(const TMBank *) const
print definition of one MIDAS bank
Definition midasio.cxx:675
virtual int Read(void *buf, int count)=0
virtual int Close()=0
std::string fErrorString
Definition midasio.h:116
static bool fgTrace
Definition midasio.h:117
virtual int Write(const void *buf, int count)=0
static bool fgTrace
Definition midasio.h:127
int Read(void *buf, int count)
Definition midasio.cxx:221
gzFile fGzFile
Definition midasio.cxx:246
int Close()
Definition midasio.cxx:234
std::string fFilename
Definition midasio.cxx:245
ZlibReader(const char *filename)
Definition midasio.cxx:201
#define TID_LAST
Definition midasio.h:40
char * dst
Definition mlz4.h:354
MLZ4F_errorCode_t MLZ4F_freeDecompressionContext(MLZ4F_decompressionContext_t dctx)
Definition lz4frame.cxx:772
const char * MLZ4F_getErrorName(MLZ4F_errorCode_t code)
Definition lz4frame.cxx:165
size_t MLZ4F_decompress(MLZ4F_decompressionContext_t dctx, void *dstBuffer, size_t *dstSizePtr, const void *srcBuffer, size_t *srcSizePtr, const MLZ4F_decompressOptions_t *dOptPtr)
size_t MLZ4F_errorCode_t
Definition mlz4frame.h:56
unsigned MLZ4F_isError(MLZ4F_errorCode_t code)
Definition lz4frame.cxx:160
#define MLZ4F_VERSION
Definition mlz4frame.h:158
MLZ4F_errorCode_t MLZ4F_createDecompressionContext(MLZ4F_decompressionContext_t *dctxPtr, unsigned version)
Definition lz4frame.cxx:760
const char * source
Definition mlz4hc.h:181
static size_t FindFirstBank(TMEvent *e)
Definition midasio.cxx:869
static int ReadPipe(FILE *fp, char *buf, int length)
Definition midasio.cxx:47
void TMWriteEvent(TMWriterInterface *writer, const TMEvent *event)
Definition midasio.cxx:651
static std::string to_string(int v)
Definition midasio.cxx:28
static std::string Lz4Error(int errorCode)
Definition midasio.cxx:251
static void PutU32(char *ptr, uint32_t v)
Definition midasio.cxx:574
static uint32_t GetU32(const void *ptr)
Definition midasio.cxx:564
static size_t FindNextBank(TMEvent *e, size_t pos, TMBank **pb)
Definition midasio.cxx:911
static void PutU16(char *ptr, uint16_t v)
Definition midasio.cxx:569
TMWriterInterface * TMNewWriter(const char *destination)
Definition midasio.cxx:543
static std::string Errno(const char *s)
Definition midasio.cxx:35
static int hasSuffix(const char *name, const char *suffix)
Definition midasio.cxx:438
TMEvent * TMReadEvent(TMReaderInterface *reader)
Definition midasio.cxx:585
static uint16_t GetU16(const void *ptr)
Definition midasio.cxx:559
TMReaderInterface * TMNewReader(const char *source)
Definition midasio.cxx:447
static size_t Align8(size_t size)
Definition midasio.cxx:579