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
268 fReader = reader;
269
271 printf("Lz4Reader::ctor!\n");
272
273 if (fReader->fError) {
274 // if reader is in an error state, we should go into the same error state
277 }
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 (fReader->fError) {
341 // if reader is in an error state, we should go into the same error state
344 }
345
346 if (clen > 0)
347 return clen;
348 else
349 return rd;
350 } else if (rd == 0) {
351 return clen;
352 }
353
354 fSrcBufHave += rd;
355
356 //printf("Lz4Reader::ReadMore: rd %d, srcbuf start %d, have %d\n", rd, fSrcBufStart, fSrcBufHave);
357 }
358
359 MLZ4F_decompressOptions_t* dOptPtr = NULL;
360
361 char* dst = cptr;
362 size_t dst_size = more;
363 size_t src_size = fSrcBufHave;
364
365 size_t status = MLZ4F_decompress(fContext, dst, &dst_size, fSrcBuf + fSrcBufStart, &src_size, dOptPtr);
366
367 if (MLZ4F_isError(status)) {
368 fError = true;
369 fErrorString = "MLZ4F_decompress() error ";
370 fErrorString += Lz4Error(status);
371 return -1;
372 }
373
374 //printf("LZ4Reader::Decompress: status %d, dst_size %d -> %d, src_size %d -> %d\n", (int)status, more, (int)dst_size, fSrcBufHave, (int)src_size);
375
376 assert(dst_size!=0 || src_size!=0); // make sure we make progress
377
378 clen += dst_size;
379 cptr += dst_size;
380
381 fSrcBufStart += src_size;
382 fSrcBufHave -= src_size;
383
384 if (fSrcBufHave == 0)
385 fSrcBufStart = 0;
386 }
387
388 //printf("Lz4Reader::Read %d bytes, returning %d bytes!\n", count, clen);
389 return clen;
390 }
391
392 int Close()
393 {
395 printf("Lz4Reader::Close!\n");
396 return fReader->Close();
397 }
398
399 void AllocSrcBuf(int size)
400 {
401 //printf("Lz4Reader::AllocSrcBuffer %d -> %d bytes!\n", fSrcBufSize, size);
402 fSrcBuf = (char*) realloc(fSrcBuf, size);
403 assert(fSrcBuf != NULL);
404 fSrcBufSize = size;
405 }
406
409
410 int fSrcBufSize = 0;
412 int fSrcBufHave = 0;
413 char* fSrcBuf = NULL;
414};
415
417{
418 public:
419 FileWriter(const char* filename)
420 {
421 fFilename = filename;
422 fFp = fopen(filename, "w");
423 assert(fFp != NULL); // FIXME: check for error
424 }
425
426 int Write(const void* buf, int count)
427 {
428 assert(fFp != NULL);
429 return fwrite(buf, 1, count, fFp);
430 }
431
432 int Close()
433 {
434 assert(fFp != NULL);
435 fclose(fFp);
436 fFp = NULL;
437 return 0;
438 }
439
440 std::string fFilename;
441 FILE* fFp;
442};
443
444static int hasSuffix(const char*name,const char*suffix)
445{
446 const char* s = strstr(name,suffix);
447 if (s == NULL)
448 return 0;
449
450 return (s-name)+strlen(suffix) == strlen(name);
451}
452
454{
455#ifdef SIGPIPE
456 signal(SIGPIPE, SIG_IGN); // crash if reading from closed pipe
457#endif
458#ifdef SIGXFSZ
459 signal(SIGXFSZ, SIG_IGN); // crash if reading from file >2GB without O_LARGEFILE
460#endif
461
462 if (0)
463 {
464 }
465 else if (strncmp(source, "ssh://", 6) == 0)
466 {
467 const char* name = source + 6;
468 const char* s = strstr(name, "/");
469
470 if (s == NULL) {
472 e->fError = true;
473 e->fErrorString = "TMidasFile::Open: Invalid ssh:// URI. Should be: ssh://user@host/file/path/...";
474 return e;
475 }
476
477 const char* remoteFile = s + 1;
478
479 std::string remoteHost;
480 for (s=name; *s != '/'; s++)
481 remoteHost += *s;
482
483 std::string pipe;
484
485 pipe = "ssh -e none -T -x -n ";
486 pipe += remoteHost;
487 pipe += " dd if=";
488 pipe += remoteFile;
489 pipe += " bs=1024k";
490
491 if (hasSuffix(remoteFile,".gz"))
492 pipe += " | gzip -dc";
493 else if (hasSuffix(remoteFile,".bz2"))
494 pipe += " | bzip2 -dc";
495 else if (hasSuffix(remoteFile,".lz4"))
496 pipe += " | lz4 -d";
497
498 return new PipeReader(pipe.c_str());
499 }
500 else if (strncmp(source, "dccp://", 7) == 0)
501 {
502 const char* name = source + 7;
503
504 std::string pipe;
505
506 pipe = "dccp ";
507 pipe += name;
508 pipe += " /dev/fd/1";
509
510 if (hasSuffix(source,".gz"))
511 pipe += " | gzip -dc";
512 else if (hasSuffix(source,".bz2"))
513 pipe += " | bzip2 -dc";
514 else if (hasSuffix(source,".lz4"))
515 pipe += " | lz4 -d";
516
517 return new PipeReader(pipe.c_str());
518 }
519 else if (strncmp(source, "pipein://", 9) == 0)
520 {
521 std::string pipe = source + 9;
522 return new PipeReader(pipe.c_str());
523 }
524#if 0 // read compressed files using the zlib library
525 else if (hasSuffix(source, ".gz"))
526 {
527 pipe = "gzip -dc ";
528 pipe += source;
529 }
530#endif
531 else if (hasSuffix(source, ".gz"))
532 {
533 return new ZlibReader(source);
534 }
535 else if (hasSuffix(source, ".bz2"))
536 {
537 return new PipeReader((std::string("bzip2 -dc ") + source).c_str());
538 }
539 else if (hasSuffix(source, ".lz4"))
540 {
541 return new Lz4Reader(new FileReader(source));
542 }
543 else
544 {
545 return new FileReader(source);
546 }
547}
548
549TMWriterInterface* TMNewWriter(const char* destination)
550{
551 if (0) {
552#if 0
553 } else if (hasSuffix(source, ".gz")) {
554 return new ZlibReader(source);
555 } else if (hasSuffix(source, ".bz2")) {
556 return new PipeReader((std::string("bzip2 -dc ") + source).c_str());
557 } else if (hasSuffix(source, ".lz4")) {
558 return new Lz4Reader(new FileReader(source));
559#endif
560 } else {
561 return new FileWriter(destination);
562 }
563}
564
565static uint16_t GetU16(const void*ptr)
566{
567 return *(uint16_t*)ptr;
568}
569
570static uint32_t GetU32(const void*ptr)
571{
572 return *(uint32_t*)ptr;
573}
574
575static void PutU16(char* ptr, uint16_t v)
576{
577 *(uint16_t*)ptr = v;
578}
579
580static void PutU32(char* ptr, uint32_t v)
581{
582 *(uint32_t*)ptr = v;
583}
584
585static size_t Align8(size_t size)
586{
587 // align to 8 bytes (uint64_t)
588 return (size + 7) & ~7;
589}
590
592{
593 bool gOnce = true;
594 if (gOnce) {
595 gOnce = false;
596 assert(sizeof(char)==1);
597 assert(sizeof(uint16_t)==2);
598 assert(sizeof(uint32_t)==4);
599 }
600
601 TMEvent* e = new TMEvent;
602
603 e->Reset();
604
605 const int event_header_size = 4*4;
606 char event_header[event_header_size];
607
608 int rd = reader->Read(event_header, event_header_size);
609
610 if (rd < 0) { // read error
611 delete e;
612 return NULL;
613 } else if (rd == 0) { // end of file
614 delete e;
615 return NULL;
616 } else if (rd != event_header_size) { // truncated data in file
617 fprintf(stderr, "TMReadEvent: error: read %d shorter than event header size %d\n", (int)rd, (int)event_header_size);
618 e->error = true;
619 return e;
620 }
621
622 e->event_id = GetU16(event_header+0);
623 e->trigger_mask = GetU16(event_header+2);
624 e->serial_number = GetU32(event_header+4);
625 e->time_stamp = GetU32(event_header+8);
626 e->data_size = GetU32(event_header+12);
627
628 e->event_header_size = event_header_size;
629
630 e->bank_header_flags = 0;
631
632 //if (!e->old_event.IsGoodSize()) { // invalid event size
633 // e->error = true;
634 // return e;
635 //}
636
637 size_t to_read = e->data_size;
638
639 e->data.resize(event_header_size + to_read);
640
641 memcpy(&e->data[0], event_header, event_header_size);
642
643 rd = reader->Read(&e->data[event_header_size], to_read);
644
645 if (rd < 0) { // read error
646 delete e;
647 return NULL;
648 } else if (rd != (int)to_read) { // truncated data in file
649 fprintf(stderr, "TMReadEvent: error: short read %d instead of %d\n", (int)rd, (int)to_read);
650 e->error = true;
651 return e;
652 }
653
654 return e;
655}
656
657void TMWriteEvent(TMWriterInterface* writer, const TMEvent* event)
658{
659 writer->Write(&(event->data[0]), event->data.size());
660}
661
662std::string TMEvent::HeaderToString() const
663{
664 char buf[1024];
665 snprintf(buf, sizeof(buf), "event: id %d, mask 0x%04x, serial %d, time %d, size %d, error %d, banks %d", event_id, trigger_mask, serial_number, time_stamp, data_size, error, (int)banks.size());
666 return buf;
667}
668
669std::string TMEvent::BankListToString() const
670{
671 std::string s;
672 for (unsigned i=0; i<banks.size(); i++) {
673 if (i>0)
674 s += ",";
675 s += banks[i].name;
676 }
677 return s;
678}
679
680std::string TMEvent::BankToString(const TMBank*b) const
681{
682 char buf[1024];
683 snprintf(buf, sizeof(buf), "name \"%s\", type %d, size %d, offset %d\n", b->name.c_str(), b->type, b->data_size, (int)b->data_offset);
684 return buf;
685}
686
688{
689 Reset();
690}
691
693{
694 error = false;
695
696 event_id = 0;
697 trigger_mask = 0;
698 serial_number = 0;
699 time_stamp = 0;
700 data_size = 0;
701
704
705 banks.clear();
706 data.clear();
707
708 found_all_banks = false;
710}
711
713{
714 ParseHeader(data.data(), data.size());
715
716 if (data.size() != event_header_size + data_size) {
717 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));
718 error = true;
719 }
720}
721
722void TMEvent::ParseHeader(const void* buf, size_t buf_size)
723{
724 event_header_size = 4*4;
725
726 const char* event_header = (const char*)buf;
727
728 if (buf_size < event_header_size) {
729 fprintf(stderr, "TMEvent::ctor: error: buffer size %d is smaller than event header size %d\n", (int)buf_size, (int)event_header_size);
730 error = true;
731 return;
732 }
733
734 event_id = GetU16(event_header+0);
735 trigger_mask = GetU16(event_header+2);
736 serial_number = GetU32(event_header+4);
737 time_stamp = GetU32(event_header+8);
738 data_size = GetU32(event_header+12);
739
741
742 //if (!e->old_event.IsGoodSize()) { // invalid event size
743 // e->error = true;
744 // return e;
745 //}
746}
747
748TMEvent::TMEvent(const void* buf, size_t buf_size)
749{
750 bool gOnce = true;
751 if (gOnce) {
752 gOnce = false;
753 assert(sizeof(char)==1);
754 assert(sizeof(uint16_t)==2);
755 assert(sizeof(uint32_t)==4);
756 }
757
758 Reset();
759 ParseHeader(buf, buf_size);
760
761 if (error) {
762 return;
763 }
764
765 size_t zdata_size = data_size;
766 size_t zevent_size = zdata_size + event_header_size;
767
768 if (zevent_size != buf_size) {
769 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);
770 error = true;
771 return;
772 }
773
774 //data.resize(event_header_size + to_read);
775 //memcpy(&data[0], xdata, event_header_size + to_read);
776
777 const char* cptr = (const char*)buf;
778
779 data.assign(cptr, cptr + zevent_size);
780
781 assert(data.size() == zevent_size);
782}
783
784void TMEvent::Init(uint16_t xevent_id, uint16_t xtrigger_mask, uint32_t xserial_number, uint32_t xtime_stamp, size_t capacity)
785{
786 Reset();
787
788 event_header_size = 4*4;
789
790 event_id = xevent_id;
791 trigger_mask = xtrigger_mask;
792 serial_number = xserial_number;
793 if (xtime_stamp) {
794 time_stamp = xtime_stamp;
795 } else {
796 time_stamp = time(NULL);
797 }
798
799 data_size = 8; // data size: 2 words of bank header, 0 words of data banks
800 bank_header_flags = 0x00000031; // bank header flags, bk_init32a() format
801
802 // bank list is empty
803
805 found_all_banks = false;
806
807 // allocate event buffer
808
809 if (capacity < 1024)
810 capacity = 1024;
811
812 data.reserve(capacity);
813
814 // create event data
815
817
818 char* event_header = data.data();
819
820 PutU16(event_header+0, event_id);
821 PutU16(event_header+2, trigger_mask);
822 PutU32(event_header+4, serial_number);
823 PutU32(event_header+8, time_stamp);
824 PutU32(event_header+12, data_size);
825 PutU32(event_header+16, 0); // bank header data size
826 PutU32(event_header+20, bank_header_flags); // bank header flags
827}
828
829void TMEvent::AddBank(const char* bank_name, int tid, const char* buf, size_t size)
830{
831 assert(data.size() > 0); // must call Init() before calling AddBank()
832
833 size_t bank_size = event_header_size + Align8(size);
834
835 size_t end_of_event_offset = data.size();
836
837 data.resize(end_of_event_offset + bank_size);
838
839 char* pbank = data.data() + end_of_event_offset;
840
841 //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);
842
843 pbank[0] = bank_name[0];
844 pbank[1] = bank_name[1];
845 pbank[2] = bank_name[2];
846 pbank[3] = bank_name[3];
847 PutU32(pbank+1*4, tid);
848 PutU32(pbank+2*4, size);
849 PutU32(pbank+3*4, 0); // bk_init32a() extra padding/reserved word
850
851 memcpy(pbank+4*4, buf, size);
852
853 // adjust event header
854
855 data_size += bank_size;
856
857 char* event_header = data.data();
858 PutU32(event_header + 12, data_size); // event header
859 PutU32(event_header + 16, data_size - 8); // bank header
860
861 // add a bank record
862
863 if (found_all_banks) {
864 TMBank b;
865 b.name = bank_name;
866 b.type = tid;
867 b.data_size = size;
868 b.data_offset = end_of_event_offset + 4*4;
869 banks.push_back(b);
870 }
871}
872
873static size_t FindFirstBank(TMEvent* e)
874{
875 if (e->error)
876 return 0;
877
878 size_t off = e->event_header_size;
879
880 if (e->data.size() < off + 8) {
881 fprintf(stderr, "TMEvent::FindFirstBank: error: data size %d is too small\n", (int)e->data.size());
882 e->error = true;
883 return 0;
884 }
885
886 uint32_t bank_header_data_size = GetU32(&e->data[off]);
887 uint32_t bank_header_flags = GetU32(&e->data[off+4]);
888
889 //printf("bank header: data size %d, flags 0x%08x\n", bank_header_data_size, bank_header_flags);
890
891 if (bank_header_data_size + 8 != e->data_size) {
892 fprintf(stderr, "TMEvent::FindFirstBank: error: bank header size %d mismatch against data size %d\n", (int)bank_header_data_size, (int)e->data_size);
893 e->error = true;
894 return 0;
895 }
896
897 e->bank_header_flags = bank_header_flags;
898
899 return off+8;
900}
901
902#if 0
903static char xchar(char c)
904{
905 if (c>='0' && c<='9')
906 return c;
907 if (c>='a' && c<='z')
908 return c;
909 if (c>='A' && c<='Z')
910 return c;
911 return '$';
912}
913#endif
914
915static size_t FindNextBank(TMEvent* e, size_t pos, TMBank** pb)
916{
917 if (e->error)
918 return 0;
919
920 size_t remaining = e->data.size() - pos;
921
922 //printf("pos %d, event data_size %d, size %d, remaining %d\n", pos, e->data_size, (int)e->data.size(), remaining);
923
924 if (remaining == 0) {
925 // end of data, no more banks to find
926 e->found_all_banks = true;
927 return 0;
928 }
929
930 if (remaining < 8) {
931 fprintf(stderr, "TMEvent::FindNextBank: error: too few bytes %d remaining at the end of event\n", (int)remaining);
932 e->error = true;
933 e->found_all_banks = true; // no more banks will be found after this error
934 return 0;
935 }
936
937 size_t ibank = e->banks.size();
938 e->banks.resize(ibank+1);
939
940 TMBank* b = &e->banks[ibank];
941
942 b->name.resize(4);
943 b->name[0] = e->data[pos+0];
944 b->name[1] = e->data[pos+1];
945 b->name[2] = e->data[pos+2];
946 b->name[3] = e->data[pos+3];
947 b->name[4] = 0;
948
949 size_t data_offset = 0;
950
951 //printf("bank header flags: 0x%08x\n", e->bank_header_flags);
952
953 if (e->bank_header_flags & (1<<5)) {
954 // bk_init32a format
955 b->type = GetU32(&e->data[pos+4+0]);
956 b->data_size = GetU32(&e->data[pos+4+4]);
957 data_offset = pos+4+4+4+4;
958 } else if (e->bank_header_flags & (1<<4)) {
959 // bk_init32 format
960 b->type = GetU32(&e->data[pos+4+0]);
961 b->data_size = GetU32(&e->data[pos+4+4]);
962 data_offset = pos+4+4+4;
963 } else {
964 // bk_init format
965 b->type = GetU16(&e->data[pos+4+0]);
966 b->data_size = GetU16(&e->data[pos+4+2]);
967 data_offset = pos+4+2+2;
968 }
969
970 b->data_offset = data_offset;
971
972 //printf("found bank at pos %d: %s\n", pos, e->BankToString(b).c_str());
973
974 if (b->type < 1 || b->type >= TID_LAST) {
975 fprintf(stderr, "TMEvent::FindNextBank: error: invalid tid %d\n", b->type);
976 e->error = true;
977 return 0;
978 }
979
980 size_t aligned_data_size = Align8(b->data_size);
981
982 //printf("data_size %d, alignemnt: %d %d, aligned %d\n", b->data_size, align, b->data_size%align, aligned_data_size);
983
984 size_t npos = data_offset + aligned_data_size;
985
986 //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]));
987
988 if (npos > e->data.size()) {
989 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());
990 e->error = true;
991 return 0;
992 }
993
994 if (pb)
995 *pb = b;
996
997 return npos;
998}
999
1001{
1002 if (error)
1003 return NULL;
1004 if (event_header_size == 0)
1005 return NULL;
1006 if (event_header_size > data.size())
1007 return NULL;
1008 if (event_header_size + data_size > data.size())
1009 return NULL;
1010 return &data[event_header_size];
1011}
1012
1013const char* TMEvent::GetEventData() const
1014{
1015 if (error)
1016 return NULL;
1017 if (event_header_size == 0)
1018 return NULL;
1019 if (event_header_size > data.size())
1020 return NULL;
1021 if (event_header_size + data_size > data.size())
1022 return NULL;
1023 return &data[event_header_size];
1024}
1025
1027{
1028 if (error)
1029 return NULL;
1030 if (!b)
1031 return NULL;
1032 if (b->data_offset >= data.size())
1033 return NULL;
1034 if (b->data_offset + b->data_size > data.size())
1035 return NULL;
1036 return &data[b->data_offset];
1037}
1038
1039const char* TMEvent::GetBankData(const TMBank* b) const
1040{
1041 if (error)
1042 return NULL;
1043 if (!b)
1044 return NULL;
1045 if (b->data_offset >= data.size())
1046 return NULL;
1047 if (b->data_offset + b->data_size > data.size())
1048 return NULL;
1049 return &data[b->data_offset];
1050}
1051
1052TMBank* TMEvent::FindBank(const char* bank_name)
1053{
1054 if (error)
1055 return NULL;
1056
1057 // if we already found this bank, return it
1058
1059 if (bank_name)
1060 for (unsigned i=0; i<banks.size(); i++) {
1061 if (banks[i].name == bank_name)
1062 return &banks[i];
1063 }
1064
1065 //printf("found_all_banks %d\n", found_all_banks);
1066
1067 if (found_all_banks)
1068 return NULL;
1069
1070 size_t pos = bank_scan_position;
1071
1072 if (pos == 0)
1073 pos = FindFirstBank(this);
1074
1075 //printf("pos %d\n", pos);
1076
1077 while (pos > 0) {
1078 TMBank* b = NULL;
1079 pos = FindNextBank(this, pos, &b);
1080 bank_scan_position = pos;
1081 //printf("pos %d, b %p\n", pos, b);
1082 if (pos>0 && b && bank_name) {
1083 if (b->name == bank_name)
1084 return b;
1085 }
1086 }
1087
1088 found_all_banks = true;
1089
1090 return NULL;
1091}
1092
1094{
1095 if (found_all_banks)
1096 return;
1097
1098 FindBank(NULL);
1099
1100 assert(found_all_banks);
1101}
1102
1104{
1105 printf("Event: id 0x%04x, mask 0x%04x, serial 0x%08x, time 0x%08x, data size %d, vector size %d, capacity %d\n",
1106 event_id,
1109 time_stamp,
1110 data_size,
1111 (int)data.size(),
1112 (int)data.capacity()
1113 );
1114}
1115
1116void TMEvent::PrintBanks(int level)
1117{
1118 FindAllBanks();
1119
1120 printf("%d banks:", (int)banks.size());
1121 for (size_t i=0; i<banks.size(); i++) {
1122 printf(" %s", banks[i].name.c_str());
1123 }
1124 printf("\n");
1125
1126 if (level > 0) {
1127 for (size_t i=0; i<banks.size(); i++) {
1128 printf("bank %3d: name \"%s\", tid %2d, data_size %8d\n",
1129 (int)i,
1130 banks[i].name.c_str(),
1131 banks[i].type,
1132 banks[i].data_size);
1133 if (level > 1) {
1134 const char* p = GetBankData(&banks[i]);
1135 if (p) {
1136 for (size_t j=0; j<banks[i].data_size; j+=4) {
1137 printf("%11d: 0x%08x\n", (int)j, *(uint32_t*)(p+j));
1138 }
1139 }
1140 }
1141 }
1142 }
1143}
1144
1146{
1147 const char* p = data.data();
1148
1149 // event header
1150 printf(" 0: 0x%08x\n", GetU32(p+0*4));
1151 printf(" 1: 0x%08x\n", GetU32(p+1*4));
1152 printf(" 2: 0x%08x\n", GetU32(p+2*4));
1153 printf(" 3: 0x%08x (0x%08x and 0x%08x-0x10)\n", GetU32(p+3*4), data_size, (int)data.size());
1154
1155 // bank header
1156 printf(" 4: 0x%08x\n", GetU32(p+4*4));
1157 printf(" 5: 0x%08x (0x%08x)\n", GetU32(p+5*4), bank_header_flags);
1158}
1159
1160/* emacs
1161 * Local Variables:
1162 * tab-width: 8
1163 * c-basic-offset: 3
1164 * indent-tabs-mode: nil
1165 * End:
1166 */
1167
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:441
int Close()
Definition midasio.cxx:432
int Write(const void *buf, int count)
Definition midasio.cxx:426
FileWriter(const char *filename)
Definition midasio.cxx:419
std::string fFilename
Definition midasio.cxx:440
int fSrcBufHave
Definition midasio.cxx:412
int Close()
Definition midasio.cxx:392
Lz4Reader(TMReaderInterface *reader)
Definition midasio.cxx:264
MLZ4F_decompressionContext_t fContext
Definition midasio.cxx:408
TMReaderInterface * fReader
Definition midasio.cxx:407
void AllocSrcBuf(int size)
Definition midasio.cxx:399
int fSrcBufStart
Definition midasio.cxx:411
int fSrcBufSize
Definition midasio.cxx:410
char * fSrcBuf
Definition midasio.cxx:413
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:669
void PrintHeader() const
Definition midasio.cxx:1103
void FindAllBanks()
scan the MIDAS event, find all data banks
Definition midasio.cxx:1093
std::string HeaderToString() const
print the MIDAS event header
Definition midasio.cxx:662
TMBank * FindBank(const char *bank_name)
scan the MIDAS event
Definition midasio.cxx:1052
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:692
void PrintBanks(int level=0)
Definition midasio.cxx:1116
void AddBank(const char *bank_name, int tid, const char *buf, size_t size)
add new MIDAS bank
Definition midasio.cxx:829
char * GetEventData()
get pointer to MIDAS event data
Definition midasio.cxx:1000
void DumpHeader() const
Definition midasio.cxx:1145
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:784
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:722
void ParseEvent()
parse event data
Definition midasio.cxx:712
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:1026
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:680
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:873
static int ReadPipe(FILE *fp, char *buf, int length)
Definition midasio.cxx:47
void TMWriteEvent(TMWriterInterface *writer, const TMEvent *event)
Definition midasio.cxx:657
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:580
static uint32_t GetU32(const void *ptr)
Definition midasio.cxx:570
static size_t FindNextBank(TMEvent *e, size_t pos, TMBank **pb)
Definition midasio.cxx:915
static void PutU16(char *ptr, uint16_t v)
Definition midasio.cxx:575
TMWriterInterface * TMNewWriter(const char *destination)
Definition midasio.cxx:549
static std::string Errno(const char *s)
Definition midasio.cxx:35
static int hasSuffix(const char *name, const char *suffix)
Definition midasio.cxx:444
TMEvent * TMReadEvent(TMReaderInterface *reader)
Definition midasio.cxx:591
static uint16_t GetU16(const void *ptr)
Definition midasio.cxx:565
TMReaderInterface * TMNewReader(const char *source)
Definition midasio.cxx:453
static size_t Align8(size_t size)
Definition midasio.cxx:585