JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwEventBuffer.cc
Go to the documentation of this file.
1/*!
2 * \file QwEventBuffer.cc
3 * \brief Event buffer management for reading and processing CODA data files
4 */
5
6#include "QwEventBuffer.h"
7
8#include <chrono>
9#include <thread>
10
11#include "QwOptions.h"
12#include "QwEPICSEvent.h"
13#include "VQwSubsystem.h"
14#include "QwSubsystemArray.h"
15
16#include <TMath.h>
17
18#include <vector>
19#include <glob.h>
20
21#include <csignal>
24void sigint_handler(int sig)
25{
26 std::cout << "handling signal no. " << sig << " ";
27 std::cout << "(press ctrl-\\ to abort now)\n";
28 globalEXIT=1;
29}
30void sigusr_handler(int sig)
31{
32 std::cout << "handling signal no. " << sig << "\n";
33 std::cout << "Restarts the event loop in online mode." << std::endl;
34 onlineRestart = 1;
35}
36
37#include "THaCodaFile.h"
38#ifdef __CODA_ET
39#include "THaEtClient.h"
40#endif
41
42std::string QwEventBuffer::fDefaultDataDirectory = "/adaq1/data1/apar";
43std::string QwEventBuffer::fDefaultDataFileStem = "QwRun_";
45
46const Int_t QwEventBuffer::kRunNotSegmented = -20;
47const Int_t QwEventBuffer::kNoNextDataFile = -30;
49
50/// This is the ASCII character array 'NULL', and is used by the
51/// DAQ to indicate a known empty buffer.
52const UInt_t QwEventBuffer::kNullDataWord = 0x4e554c4c;
53
54
55/// Default constructor
57 : fRunListFile(nullptr),
58 fEventListFile(nullptr),
63 fEvStream(NULL),
64 fCurrentRun(-1),
66 fSingleFile(kFALSE),
67 decoder(NULL)
68{
69 // Set up the signal handler.
70 globalEXIT=0;
71 signal(SIGINT, sigint_handler);// ctrl+c
72 signal(SIGTERM, sigint_handler);// kill in shell // 15
73 // signal(SIGTSTP, sigint_handler);// ctrl+z // 20
75 signal(SIGUSR1, sigusr_handler);
76
77 fCleanParameter[0] = 0.0;
78 fCleanParameter[1] = 0.0;
79 fCleanParameter[2] = 0.0;
80}
81
82/**
83 * Defines configuration options for QwEventBuffer class using QwOptions
84 * functionality.
85 *
86 * @param options Options object
87 */
89{
90 // Define the execution options
91 options.AddDefaultOptions()
92 ("online", po::value<bool>()->default_bool_value(false),
93 "use online data stream");
94 options.AddDefaultOptions()
95 ("online.RunNumber", po::value<int>()->default_bool_value(0),
96 "Effective run number to be used by online system to find the parameter files");
97 options.AddDefaultOptions()
98 ("run,r", po::value<string>()->default_value("0:0"),
99 "run range in format #[:#]");
100 options.AddDefaultOptions()
101 ("data,d", po::value<string>()->default_value(fDefaultDataDirectory),
102 "data directory, also $QW_DATA");
103 options.AddDefaultOptions()
104 ("runlist", po::value<string>()->default_value(""),
105 "run list file name");
106 options.AddDefaultOptions()
107 ("event,e", po::value<string>()->default_value("0:"),
108 "event range in format #[:#]");
109 options.AddDefaultOptions()
110 ("segment,s", po::value<string>()->default_value("0:"),
111 "run segment range in format #[:#]");
112 options.AddDefaultOptions()
113 ("chainfiles", po::value<bool>()->default_bool_value(false),
114 "chain file segments together, do not analyze them separately");
115 options.AddDefaultOptions()
116 ("codafile-stem", po::value<string>()->default_value(fDefaultDataFileStem),
117 "stem of the input CODA filename");
118 options.AddDefaultOptions()
119 ("codafile-ext", po::value<string>()->default_value(fDefaultDataFileExtension),
120 "extension of the input CODA filename");
121 options.AddOptions()
122 ("directfile", po::value<string>(),
123 "Run over single event file");
124 // Special flag to allow sub-bank IDs less than 31
125 options.AddDefaultOptions()
126 ("allow-low-subbank-ids", po::value<bool>()->default_bool_value(false),
127 "allow the sub-bank ids to be 31 or less, when using this flag, all ROCs must be sub-banked");
128 // Options specific to the ET clients
129 options.AddOptions("ET system options")
130 ("ET.hostname", po::value<string>(),
131 "Name of the ET session's host machine --- Only used in online mode\nDefaults to the environment variable $HOSTNAME");
132 options.AddOptions("ET system options")
133 ("ET.session", po::value<string>(),
134 "ET session name --- Only used in online mode\nDefaults to the environment variable $SESSION");
135 options.AddOptions("ET system options")
136 ("ET.station", po::value<string>(),
137 "ET station name --- Only used in online mode");
138 options.AddOptions("ET system options")
139 ("ET.waitmode", po::value<int>()->default_value(0),
140 "ET system wait mode: 0 is wait-forever, 1 is timeout \"quickly\" --- Only used in online mode");
141 options.AddOptions("ET system options")
142 ("ET.exit-on-end", po::value<bool>()->default_value(false),
143 "Exit the event loop if the end event is found. JAPAN remains open and waits for the next run. --- Only used in online mode");
144 options.AddOptions("CodaVersion")
145 ("coda-version", po::value<int>()->default_value(3),
146 "Sets the Coda Version. Allowed values = {2,3}. \nThis is needed for writing and reading mock data. Mock data needs to be written and read with the same Coda Version.");
147 options.AddOptions("Event rate limiting")
148 ("max-event-rate", po::value<double>()->default_value(0.0),
149 "Maximum event write rate in Hz (0 = disabled, no rate limiting)");
150}
151
153{
154 fOnline = options.GetValue<bool>("online");
155 if (fOnline){
156 fETWaitMode = options.GetValue<int>("ET.waitmode");
157 fExitOnEnd = options.GetValue<bool>("ET.exit-on-end");
158#ifndef __CODA_ET
159 QwError << "Online mode will not work without the CODA libraries!"
160 << QwLog::endl;
161 exit(EXIT_FAILURE);
162#else
163 if (options.HasValue("online.RunNumber")) {
164 fCurrentRun = options.GetValue<int>("online.RunNumber");
165 }
166 if (options.HasValue("ET.station")) {
167 fETStationName = options.GetValue<string>("ET.station");
168 } else {
169 fETStationName = "";
170 }
171 if (options.HasValue("ET.hostname")) {
172 fETHostname = options.GetValue<string>("ET.hostname");
173 } else {
174 fETHostname = getenv("HOSTNAME");
175 }
176 if (options.HasValue("ET.session")) {
177 fETSession = options.GetValue<string>("ET.session");
178 } else {
179 fETSession = getenv("SESSION");
180 }
181 if (fETHostname.Length() == 0 || fETSession.Length() == 0) {
182 TString tmp = "";
183 if (fETHostname == NULL || fETHostname.Length() == 0)
184 tmp += " \"HOSTNAME\"";
185 if (fETSession == NULL || fETSession.Length() == 0){
186 if (tmp.Length() > 0)
187 tmp += " and";
188 tmp += " ET \"SESSION\"";
189 }
190 QwError << "The" << tmp
191 << " variable(s) is(are) not defined in your environment.\n"
192 << " This is needed to run the online analysis."
193 << QwLog::endl;
194 exit(EXIT_FAILURE);
195 }
196#endif
197 }
198 if(options.HasValue("directfile")){
199 fSingleFile = kTRUE;
200 fDataFile = options.GetValue<string>("directfile");
201 } else {
202 fSingleFile = kFALSE;
203 }
204 fDataDirectory = options.GetValue<string>("data");
205 if (fDataDirectory.Length() == 0){
206 QwError << "ERROR: Can't get the data directory in the QwEventBuffer creator."
207 << QwLog::endl;
208 } else if (! fDataDirectory.EndsWith("/")) {
209 fDataDirectory.Append("/");
210 }
211
212 fRunRange = options.GetIntValuePair("run");
213 fEventRange = options.GetIntValuePair("event");
214 fSegmentRange = options.GetIntValuePair("segment");
215 fRunListFileName = options.GetValue<string>("runlist");
216 fChainDataFiles = options.GetValue<bool>("chainfiles");
217 fDataFileStem = options.GetValue<string>("codafile-stem");
218 fDataFileExtension = options.GetValue<string>("codafile-ext");
219 fDataVersion = options.GetValue<int>("coda-version");
220
221 if(fDataVersion == 2){
223 } else if(fDataVersion == 3) {
225 } else{
226 QwError << "Invalid Coda Version. Only versions 2 and 3 are supported. "
227 << "Please set using --coda-version 2(3)" << QwLog::endl;
228 exit(EXIT_FAILURE);
229 }
230
231 decoder->SetAllowLowSubbankIDs( options.GetValue<bool>("allow-low-subbank-ids") );
232
233 // Process event rate limiting option
234 fMaxEventRate = options.GetValue<double>("max-event-rate");
235 if (fMaxEventRate > 0.0) {
237 fMinEventInterval = std::chrono::duration<double>(1.0 / fMaxEventRate);
238 QwMessage << "Event rate limiting enabled: " << fMaxEventRate << " Hz "
239 << "(minimum interval: " << (1000.0 / fMaxEventRate) << " ms)"
240 << QwLog::endl;
241 } else {
243 }
244 fLastEventTime = std::chrono::steady_clock::now();
245
246 // Open run list file
247 /* runlist file format example:
248 [5253]
249 234
250 246
251 256
252 345:456
253 567:789
254 [5259]
255 [5260]
256 0:10000
257 [5261:5270]
258 9000:10000
259 - for run 5253 it will analyze three individual events, and two event ranges
260 - for run 5259 it will analyze the entire run (all segments)
261 - for run 5260 it will analyze the first 10000 events
262 - for runs 5261 through 5270 it will analyze the events 9000 through 10000)
263 */
264 if (fRunListFileName.size() > 0) {
265 fRunListFile = std::make_unique<QwParameterFile>(fRunListFileName);
266 fEventListFile = nullptr;
267 if (! GetNextRunRange()) {
268 QwWarning << "No run range found in run list file: " << fRunListFile->GetLine() << QwLog::endl;
269 }
270 } else {
271 fRunListFile = nullptr;
272 fEventListFile = nullptr;
273 }
274}
275
277{
278 UInt_t nevents = fNumPhysicsEvents - fStartingPhysicsEvent;
279 if (nevents==0) nevents=1;
281 << "Analysis of run " << GetRunNumber() << QwLog::endl
282 << fNumPhysicsEvents << " physics events were processed"<< QwLog::endl
283 << "CPU time used: " << fRunTimer.CpuTime() << " s "
284 << "(" << 1000.0 * fRunTimer.CpuTime() / nevents << " ms per event)" << QwLog::endl
285 << "Real time used: " << fRunTimer.RealTime() << " s "
286 << "(" << 1000.0 * fRunTimer.RealTime() / nevents << " ms per event)" << QwLog::endl
287 << QwLog::endl;
288}
289
290
291
292/// Read the next requested event range, return true if success
294 // If there is an event list, open the next section
295 if (fEventListFile && !fEventListFile->IsEOF()) {
296 std::string eventrange;
297 // Find next non-whitespace, non-comment, non-empty line, before EOF
298 do {
299 fEventListFile->ReadNextLine(eventrange);
300 fEventListFile->TrimWhitespace();
301 fEventListFile->TrimComment('#');
302 } while (fEventListFile->LineIsEmpty() && !fEventListFile->IsEOF());
303 // If EOF return false; no next event range
304 if (fEventListFile->IsEOF()) return kFALSE;
305 // Parse the event range
307 QwMessage << "Next event range is " << eventrange << QwLog::endl;
308 return kTRUE;
309 }
310 return kFALSE;
311}
312
313/// Read the next requested run range, return true if success
315 // If there is a run list, open the next section
316 std::string runrange;
317 if (fRunListFile && !fRunListFile->IsEOF() &&
318 (fEventListFile = fRunListFile->ReadNextSection(runrange))) {
319 // Parse the run range
321 QwMessage << "Next run range is " << runrange << QwLog::endl;
322 // If there is no event range for this run range, set to default of 0:MAXINT
323 if (! GetNextEventRange()) {
324 QwWarning << "No valid event range in run list file: "
325 << fEventListFile->GetLine() << ". "
326 << "Assuming the full event range." << QwLog::endl;
328 }
329 return kTRUE;
330 }
331 return kFALSE;
332}
333
334/// Get the next run in the active run range, proceed to next range if needed
336 // First run
337 if (fCurrentRun == -1) {
338 fCurrentRun = fRunRange.first;
339 return kTRUE;
340 // Run is in range
341 } else if (fCurrentRun < fRunRange.second) {
342 fCurrentRun++;
343 return kTRUE;
344 // Run is not in range, get new range
345 } else if (GetNextRunRange()) {
346 fCurrentRun = fRunRange.first;
347 return kTRUE;
348 }
349 return kFALSE;
350}
351
353{
354 TString runlabel = Form("%d",fCurrentRun);
356 runlabel += Form(".%03d",*fRunSegmentIterator);
357 }
358 return runlabel;
359}
360
362{
363 Int_t status = CODA_ERROR;
364 // Reset the physics event counter
366
367 if (fOnline) {
368 // Online stream
370 } else {
371 // Offline data file
372 if (fRunIsSegmented)
373 // Segmented
374 status = OpenNextSegment();
375 else
376 // Not segmented
377 status = OpenDataFile(fCurrentRun);
378 }
379 return status;
380}
381
383{
384 Int_t status = CODA_ERROR;
385 if (globalEXIT==1) {
386 // We want to exit, so don't open the next stream.
387 status = CODA_ERROR;
388 } else if (fOnline) {
389 /* Modify the call below for your ET system, if needed.
390 OpenETStream( ET host name , $SESSION , mode)
391 mode=0: wait forever
392 mode=1: timeout quickly
393 */
394 QwMessage << "Try to open the ET station with HOSTNAME=="
395 << fETHostname
396 << ", SESSION==" << fETSession << "."
397 << QwLog::endl;
399
400 } else {
401 // Try to open the next data file for the current run,
402 // but only if we haven't hit the event limit.
403 if (fCurrentRun != -1 && !fChainDataFiles
404 && decoder->GetEvtNumber() <= fEventRange.second) {
405 status = OpenNextSegment();
406 }
407 while (status != CODA_OK && GetNextRunNumber()) {
408 status = OpenDataFile(fCurrentRun);
409 if (status == CODA_ERROR){
410 // The data file can't be opened.
411 // Get ready to process the next run.
412 QwError << "ERROR: Unable to find data files for run "
413 << fCurrentRun << ". Moving to the next run.\n"
414 << QwLog::endl;
415 }
416 }
417
418 }
419 // Grab the starting event counter
421 // Start the timers.
422 fRunTimer.Reset();
423 fRunTimer.Start();
424 fStopwatch.Start();
425 return status;
426}
427
429{
430 // Stop the timers.
431 fRunTimer.Stop();
432 fStopwatch.Stop();
433 QwWarning << "Starting CloseStream."
434 << QwLog::endl;
435 Int_t status = kFileHandleNotConfigured;
438 // The run is segmented and we are not chaining the
439 // segments together in the event loop, so close
440 // the current segment.
441 status = CloseThisSegment();
442 } else if (fEvStreamMode==fEvStreamFile) {
443 status = CloseDataFile();
444 } else if (fEvStreamMode==fEvStreamFile){
445 status = CloseETStream();
446 }
447 return status;
448}
449
450
451
453{
454 // This will return for read errors,
455 // non-physics events, and for physics
456 // events that are within the event range.
457 Int_t status = CODA_OK;
458 do {
459 status = GetEvent();
460 if (globalEXIT == 1) {
461 // QUESTION: Should we continue to loop once we've
462 // reached the maximum event, to allow access to
463 // non-physics events?
464 // For now, mock up EOF if we've reached the maximum event.
465 status = EOF;
466 }
467 if (decoder->GetEvtNumber() > fEventRange.second) {
468 do {
469 if (GetNextEventRange()) status = CODA_OK;
470 else status = EOF;
471 } while (decoder->GetEvtNumber() < fEventRange.first);
472 }
473 // While we're in a run segment which was not requested (which
474 // should happen only when reading the zeroth segment for startup
475 // information), pretend that there's an event cut causing us to
476 // ignore events. Read configuration events only from the first
477 // part of the file.
479 fEventRange.first = decoder->GetEvtNumber() + 1;
480 if (decoder->GetEvtNumber() > 1000) status = EOF;
481 }
482 if (fOnline && fExitOnEnd && decoder->GetEndTime()>0){
483 // fExitOnEnd exits the event loop only and does not exit JAPAN.
484 // The root file gets processed and JAPAN immediately waits for the next run.
485 // We considered adding a exit-JAPAN-on-end flag that quits JAPAN but decided
486 // we didn't have a use case for it. If quitting JAPAN is desired, just set:
487 // globalEXIT = 1
488 // -- mrc (01/21/25)
489 QwMessage << "Caught End Event (end time=="<< decoder->GetEndTime()
490 << "). Exit event loop." << QwLog::endl;
491 status = EOF;
492 }
493 if (fOnline && onlineRestart){
495 status = EOF;
496 }
497 } while (status == CODA_OK &&
498 IsPhysicsEvent() &&
499 (decoder->GetEvtNumber() < fEventRange.first
500 || decoder->GetEvtNumber() > fEventRange.second)
501 );
502 if (status == CODA_OK && IsPhysicsEvent()) fNumPhysicsEvents++;
503
504 // Progress meter (this should probably produce less output in production)
505 int nevents = 10000;
506 if (IsPhysicsEvent() && decoder->GetEvtNumber() > 0 && decoder->GetEvtNumber() % nevents == 0) {
507 QwMessage << "Processing event " << decoder->GetEvtNumber() << " ";
508 fStopwatch.Stop();
509 double efficiency = 100.0 * fStopwatch.CpuTime() / fStopwatch.RealTime();
510 QwMessage << "(" << fStopwatch.CpuTime()*1e3/nevents << " ms per event with ";
511 QwMessage << efficiency << "% efficiency)";
512 fStopwatch.Reset();
513 fStopwatch.Start();
515 } else if (decoder->GetEvtNumber() > 0 && decoder->GetEvtNumber() % 100 == 0) {
516 QwVerbose << "Processing event " << decoder->GetEvtNumber() << QwLog::endl;
517 }
518
519 return status;
520}
521
522
524{
525 Int_t status = kFileHandleNotConfigured;
526 ResetFlags();
528 status = GetFileEvent();
529 } else if (fEvStreamMode==fEvStreamET){
530 status = GetEtEvent();
531 }
532 if (status == CODA_OK){
533 // Coda Data was loaded correctly
534 UInt_t* evBuffer = (UInt_t*)fEvStream->getEvBuffer();
535 if(fDataVersionVerify == 0){ // Default = 0 => Undetermined
536 VerifyCodaVersion(evBuffer);
537 }
538 decoder->DecodeEventIDBank(evBuffer);
539 }
540 return status;
541}
542
543// Tries to figure out what Coda Version the Data is
544// fDataVersionVerify =
545// 2 -- Coda Version 2
546// 3 -- Coda Version 3
547// 0 -- Default (Unknown, Could be a EPICs Event or a ROCConfiguration)
548void QwEventBuffer::VerifyCodaVersion( const UInt_t *buffer )
549{
550 if(buffer[0] == 0) return;
551 UInt_t header = buffer[1];
552 int top = (header & 0xff000000) >> 24;
553 int bot = (header & 0xff );
554 fDataVersionVerify = 0; // Default
555 if( (top == 0xff) && (bot != 0xcc) ){
556 fDataVersionVerify = 3; // Coda 3
557 } else if( (top != 0xff) && (bot == 0xcc) ){
558 fDataVersionVerify = 2; // Coda 2
559 }
560 // Validate
562 QwError << "QwEventBuffer::GetEvent: Coda Version is not recognized" << QwLog::endl;
563 QwError << "fDataVersion == " << fDataVersion
564 << ", but it looks like the data is from Coda Version "
566 << "\nTry running with --coda-version " << fDataVersionVerify
567 << "\nExiting ... " << QwLog::endl;
568 globalEXIT = 1;
569 }
570 return;
571}
572
574 Int_t status = CODA_OK;
575 // Try to get a new event. If the EOF occurs,
576 // and the run is segmented, try to open the
577 // next segment and read a new event; repeat
578 // if needed.
579 do {
580 status = fEvStream->codaRead();
581 if (fChainDataFiles && status == EOF){
583 // Crash out of the loop if we can't open the
584 // next segment!
585 if (OpenNextSegment()!=CODA_OK) break;
586 }
587 } while (fChainDataFiles && status == EOF);
588 return status;
589}
590
592 Int_t status = CODA_OK;
593 // Do we want to have any loop here to wait for a bad
594 // read to be cleared?
595 status = fEvStream->codaRead();
596 if (status != CODA_OK) {
597 globalEXIT = 1;
598 }
599 return status;
600}
601
602
604{
605 Int_t status = kFileHandleNotConfigured;
606 ResetFlags();
607
608 // Rate limiting: sleep until minimum interval has elapsed, accounting for accumulated delays
610 auto now = std::chrono::steady_clock::now();
611 auto elapsed = now - fLastEventTime;
612
613 if (elapsed < fMinEventInterval) {
614 // We're ahead of schedule - need to wait
615 auto target_sleep = fMinEventInterval - elapsed;
616
617 // Reduce sleep time by accumulated delay (time we're behind)
618 auto actual_sleep = target_sleep - fAccumulatedDelay;
619
620 if (actual_sleep > std::chrono::duration<double>(0)) {
621 // Still need to sleep after compensation
622 auto sleep_until_time = now + actual_sleep;
623 std::this_thread::sleep_until(sleep_until_time);
624
625 // We've compensated for some or all of the accumulated delay
626 fAccumulatedDelay -= (target_sleep - actual_sleep);
627 if (fAccumulatedDelay < std::chrono::duration<double>(0)) {
628 fAccumulatedDelay = std::chrono::duration<double>(0);
629 }
630 } else {
631 // Accumulated delay is larger than needed sleep - don't sleep at all
632 fAccumulatedDelay -= target_sleep;
633 }
634 } else {
635 // We're behind schedule - accumulate the delay
636 auto delay = elapsed - fMinEventInterval;
637 fAccumulatedDelay += delay;
638 }
639 fLastEventTime = std::chrono::steady_clock::now();
640 }
641
643 status = WriteFileEvent(buffer);
644 } else if (fEvStreamMode==fEvStreamET) {
645 status = WriteEtEvent(buffer);
646 }
647
648 if (globalEXIT == 1) {
649 status = CODA_ERROR;
650 }
651
652 return status;
653}
654
656{
657 Int_t status = CODA_OK;
658 // fEvStream is of inherited type THaCodaData,
659 // but codaWrite is only defined for THaCodaFile.
660 status = ((THaCodaFile*)fEvStream)->codaWrite((UInt_t*) buffer);
661 return status;
662}
663
665{
666 Int_t status = CODA_OK;
667 // fEvStream is of inherited type THaCodaData,
668 // but codaWrite for ET is defined in THaEtClient.
669#ifdef __CODA_ET
670 // Get the buffer length from the first word (CODA event header)
671 UInt_t* ubuffer = (UInt_t*)buffer;
672 UInt_t event_length = ubuffer[0]; // First word is event length in words
673
674 if( event_length == 0 || event_length > MAXEVLEN ) {
675 QwError << "WriteEtEvent: Invalid event length: " << event_length << QwLog::endl;
676 return CODA_ERROR;
677 }
678
679 status = ((THaEtClient*)fEvStream)->codaWrite(ubuffer, event_length);
680 if( status != CODA_OK ) {
681 QwError << "WriteEtEvent: codaWrite failed with status " << status << QwLog::endl;
682 }
683#else
684 QwError << "WriteEtEvent: ET support not compiled in" << QwLog::endl;
685 status = CODA_ERROR;
686#endif
687 return status;
688}
689
690
692{
693 // Encode the data in the elements of the subsystem array
694 std::vector<UInt_t> buffer;
695 std::vector<ROCID_t> ROCList;
696 subsystems.EncodeEventData(buffer);
697 subsystems.GetROCIDList(ROCList);
698 // Add CODA event header
699 std::vector<UInt_t> header = decoder->EncodePHYSEventHeader(ROCList);
700
701 // Copy the encoded event buffer into an array of integers,
702 // as expected by the CODA routines.
703 // Size of the event buffer in long words
704 int* codabuffer = new int[header.size() + buffer.size() + 1];
705 // First entry contains the buffer size
706 int k = 0;
707 codabuffer[k++] = header.size() + buffer.size();
708 for (size_t i = 0; i < header.size(); i++)
709 codabuffer[k++] = header.at(i);
710 for (size_t i = 0; i < buffer.size(); i++)
711 codabuffer[k++] = buffer.at(i);
712
713 // Now write the buffer to the stream
714 Int_t status = WriteEvent(codabuffer);
715 // delete the buffer
716 delete[] codabuffer;
717 // and report success or fail
718 return status;
719}
720
721
723{
724 decoder->ResetControlParameters();
725}
727{
728 decoder->ReportRunSummary();
729}
730
732{
733 return decoder->GetStartSQLTime();
734}
735
737{
738 return decoder->GetEndSQLTime();
739}
740
742{
743 return decoder->GetStartUnixTime();
744}
745
747{
748 return decoder->GetEndUnixTime();
749}
750
751Int_t QwEventBuffer::EncodePrestartEvent(int runnumber, int runtype)
752{
753 int buffer[5];
754 int localtime = (int)time(0);
755 decoder->EncodePrestartEventHeader(buffer, runnumber, runtype, localtime);
756 return WriteEvent(buffer);
757}
759{
760 int buffer[5];
761 int localtime = (int)time(0);
762 int eventcount = 0;
763 decoder->EncodeGoEventHeader(buffer, eventcount, localtime);
764 return WriteEvent(buffer);
765}
767{
768 int buffer[5];
769 int localtime = (int)time(0);
770 int eventcount = 0;
771 decoder->EncodePauseEventHeader(buffer, eventcount, localtime);
772 return WriteEvent(buffer);
773}
775{
776 int buffer[5];
777 int localtime = (int)time(0);
778 int eventcount = 0;
779 decoder->EncodeEndEventHeader(buffer, eventcount, localtime);
780 return WriteEvent(buffer);
781}
782
783
786
788{
789 /// Passes the data for the configuration events into each subsystem
790 /// object. Each object is responsible for recognizing the configuration
791 /// data which it ought to decode.
792 /// NOTE TO DAQ PROGRAMMERS:
793 /// The configuration event for a ROC must have the same
794 /// subbank structure as the physics events for that ROC.
795 Bool_t okay = kTRUE;
796 UInt_t rocnum = decoder->GetEvtType() - 0x90;
797 QwMessage << "QwEventBuffer::FillSubsystemConfigurationData: "
798 << "Found configuration event for ROC"
799 << rocnum
800 << QwLog::endl;
801 decoder->PrintDecoderInfo(QwMessage);
802 // Loop through the data buffer in this event.
803 UInt_t *localbuff = (UInt_t*)(fEvStream->getEvBuffer());
804 decoder->DecodeEventIDBank(localbuff);
805 while ((okay = decoder->DecodeSubbankHeader(&localbuff[decoder->GetWordsSoFar()]))){
806 // If this bank has further subbanks, restart the loop.
807 if (decoder->GetSubbankType() == 0x10) {
808 QwMessage << "This bank has further subbanks, restart the loop" << QwLog::endl;
809 continue;
810 }
811 // If this bank only contains the word 'NULL' then skip
812 // this bank.
813 if (decoder->GetFragLength()==1 && localbuff[decoder->GetWordsSoFar()]==kNullDataWord){
814 decoder->AddWordsSoFarAndFragLength();
815 QwMessage << "Skip this bank" << QwLog::endl;
816 continue;
817 }
818
819 // Subsystems may be configured to accept data in formats
820 // other than 32 bit integer (banktype==1), but the
821 // bank type is not provided. Subsystems must be able
822 // to process their data knowing only the ROC and bank tags.
823 //
824 // After trying the data in each subsystem, bump the
825 // fWordsSoFar to move to the next bank.
826
827 subsystems.ProcessConfigurationBuffer(rocnum, decoder->GetSubbankTag(),
828 &localbuff[decoder->GetWordsSoFar()],
829 decoder->GetFragLength());
830 decoder->AddWordsSoFarAndFragLength();
831 QwDebug << "QwEventBuffer::FillSubsystemConfigurationData: "
832 << "Ending loop: fWordsSoFar=="<<decoder->GetWordsSoFar()
833 <<QwLog::endl;
834 }
835
836 return okay;
837}
838
840{
841 // Initialize local flag
842 Bool_t okay = kTRUE;
843
844 // Reload the data buffer and decode the header again, this allows
845 // multiple calls to this function for different subsystem arrays.
846 UInt_t *localbuff = (UInt_t*)(fEvStream->getEvBuffer());
847
848 decoder->DecodeEventIDBank(localbuff);
849
850 // Clear the old event information from the subsystems.
851 subsystems.ClearEventData();
852
853 // Pass CODA run, segment, event number and type to the subsystem array.
854 subsystems.SetCodaRunNumber(fCurrentRun);
856 subsystems.SetCodaEventNumber(decoder->GetEvtNumber());
857 subsystems.SetCodaEventType(decoder->GetEvtType());
858
859 // If this event type is masked for the subsystem array, return right away
860 if (((0x1 << (decoder->GetEvtType() - 1)) & subsystems.GetEventTypeMask()) == 0) {
861 return kTRUE;
862 }
863
864 UInt_t offset;
865
866 // Loop through the data buffer in this event.
867 while ((okay = decoder->DecodeSubbankHeader(&localbuff[decoder->GetWordsSoFar()]))){
868
869 // If this bank has further subbanks, restart the loop.
870 if (decoder->GetSubbankType() == 0x10) continue;
871
872 // If this bank only contains the word 'NULL' then skip
873 // this bank.
874 if (decoder->GetFragLength() == 1 && localbuff[decoder->GetWordsSoFar()]==kNullDataWord) {
875 decoder->AddWordsSoFarAndFragLength();
876 continue;
877 }
878
879 // if (GetSubbankType() == 0x85) {
880 // std::cout << "ProcessEventBuffer: , SubbankTag= "<< GetSubbankTag()<<" FragLength="<<GetFragLength() <<std::endl;
881 // }
882
883// QwDebug << "QwEventBuffer::FillSubsystemData: "
884// << "Beginning loop: fWordsSoFar=="<<GetWordsSoFar()
885// <<QwLog::endl;
886
887 // Loop through the subsystems and try to store the data
888 // from this bank in each subsystem.
889 //
890 // Subsystems may be configured to accept data in formats
891 // other than 32 bit integer (banktype==1), but the
892 // bank type is not provided. Subsystems must be able
893 // to process their data knowing only the ROC and bank tags.
894 //
895 // After trying the data in each subsystem, bump the
896 // fWordsSoFar to move to the next bank.
897
898 // TODO:
899 // What is special about this subbank?
900 if( decoder->GetROC() == 0 && decoder->GetSubbankTag()==0x6101) {
901 //std::cout << "ProcessEventBuffer: ROC="<<GetROC()<<", SubbankTag="<< GetSubbankTag()<<", FragLength="<<GetFragLength() <<std::endl;
902 fCleanParameter[0]=localbuff[decoder->GetWordsSoFar()+decoder->GetFragLength()-4];//clean data
903 fCleanParameter[1]=localbuff[decoder->GetWordsSoFar()+decoder->GetFragLength()-3];//scan data 1
904 fCleanParameter[2]=localbuff[decoder->GetWordsSoFar()+decoder->GetFragLength()-2];//scan data 2
905 //std::cout << "ProcessEventBuffer: ROC="<<GetROC()<<", SubbankTag="<< GetSubbankTag()
906 // <<", FragLength="<<GetFragLength() << " " <<fCleanParameter[0]<< " " <<fCleanParameter[1]<< " " <<fCleanParameter[2]<<std::endl;
907
908 }
909
911
912 std::size_t nmarkers = CheckForMarkerWords(subsystems);
913 if (nmarkers>0) {
914 // There are markerwords for this ROC/Bank
915 for (size_t i=0; i<nmarkers; i++){
916 offset = FindMarkerWord(i,&localbuff[decoder->GetWordsSoFar()],decoder->GetFragLength());
917 BankID_t tmpbank = GetMarkerWord(i);
918 tmpbank = ((tmpbank)<<32) + decoder->GetSubbankTag();
919 offset++; // Skip the marker word
920 subsystems.ProcessEvBuffer(decoder->GetEvtType(), decoder->GetROC(), tmpbank,
921 &localbuff[decoder->GetWordsSoFar()+offset],
922 decoder->GetFragLength()-offset);
923 }
924 } else {
925 QwDebug << "QwEventBuffer::FillSubsystemData: "
926 << "fROC=="<<decoder->GetROC() << ", GetSubbankTag()==" << decoder->GetSubbankTag()
927 << QwLog::endl;
928 subsystems.ProcessEvBuffer(decoder->GetEvtType(), decoder->GetROC(), decoder->GetSubbankTag(),
929 &localbuff[decoder->GetWordsSoFar()],
930 decoder->GetFragLength());
931 }
932 decoder->AddWordsSoFarAndFragLength();
933// QwDebug << "QwEventBuffer::FillSubsystemData: "
934// << "Ending loop: fWordsSoFar=="<<GetWordsSoFar()
935// <<QwLog::endl;
936 }
937 return okay;
938}
939
940
941// added all this method for QwEPICSEvent class
943{
944 // QwVerbose << "QwEventBuffer::FillEPICSData: "
945// << Form("Length: %d; Tag: 0x%x; Bank ID num: 0x%x; ",
946// fEvtLength, fEvtTag, fIDBankNum)
947// << Form("Evt type: 0x%x; Evt number %d; Evt Class 0x%.8x; ",
948// fEvtType(), fEvtNumber, fEvtClass)
949// << Form("Status Summary: 0x%.8x; Words so far %d",
950// fStatSum, fWordsSoFar)
951// << QwLog::endl;
952
953
954 ///
955 Bool_t okay = kTRUE;
956 if (! IsEPICSEvent()){
957 okay = kFALSE;
958 return okay;
959 }
960 QwVerbose << "QwEventBuffer::FillEPICSData: "
961 << QwLog::endl;
962 // Loop through the data buffer in this event.
963 UInt_t *localbuff = (UInt_t*)(fEvStream->getEvBuffer());
964 if (decoder->GetBankDataType()==0x10){
965 while ((okay = decoder->DecodeSubbankHeader(&localbuff[decoder->GetWordsSoFar()]))){
966 // If this bank has further subbanks, restart the loop.
967 if (decoder->GetSubbankType() == 0x10) continue;
968 // If this bank only contains the word 'NULL' then skip
969 // this bank.
970 if (decoder->GetFragLength()==1 && localbuff[decoder->GetWordsSoFar()]==kNullDataWord){
971 decoder->AddWordsSoFarAndFragLength();
972 continue;
973 }
974
975 if (decoder->GetSubbankType() == 0x3){
976 // This is an ASCII string bank. Try to decode it and
977 // pass it to the EPICS class.
978 char* tmpchar = (Char_t*)&localbuff[decoder->GetWordsSoFar()];
979
980 epics.ExtractEPICSValues(string(tmpchar), GetEventNumber());
981 QwVerbose << "test for GetEventNumber =" << GetEventNumber() << QwLog::endl;// always zero, wrong.
982
983 }
984
985
986 decoder->AddWordsSoFarAndFragLength();
987
988// QwDebug << "QwEventBuffer::FillEPICSData: "
989// << "Ending loop: fWordsSoFar=="<<GetWordsSoFar()
990// <<QwLog::endl;
991// QwMessage<<"\nQwEventBuffer::FillEPICSData: fWordsSoFar = "<<GetWordsSoFar()<<QwLog::endl;
992
993
994 }
995 } else {
996 // Single bank in the event, use event headers.
997 if (decoder->GetBankDataType() == 0x3){
998 // This is an ASCII string bank. Try to decode it and
999 // pass it to the EPICS class.
1000 Char_t* tmpchar = (Char_t*)&localbuff[decoder->GetWordsSoFar()];
1001
1002 QwError << tmpchar << QwLog::endl;
1003
1004 epics.ExtractEPICSValues(string(tmpchar), GetEventNumber());
1005
1006 }
1007
1008 }
1009
1010 //std::cout<<"\nEpics data coming!! "<<GetWordsSoFar()<<std::endl;
1011 QwVerbose << "QwEventBuffer::FillEPICSData: End of routine"
1012 << QwLog::endl;
1013 return okay;
1014}
1015
1016const TString& QwEventBuffer::DataFile(const UInt_t run, const Short_t seg = -1)
1017{
1018 if(!fSingleFile){
1019 TString basename = fDataFileStem + Form("%u.",run) + fDataFileExtension;
1020 if(seg == -1){
1021 fDataFile = fDataDirectory + basename;
1022 } else {
1023 fDataFile = fDataDirectory + basename + Form(".%d",seg);
1024 }
1025 }
1026 return fDataFile;
1027}
1028
1029
1031{
1032 glob_t globbuf;
1033
1034 TString searchpath;
1035 TString scanvalue;
1036 Int_t local_segment;
1037
1038 std::vector<Int_t> tmp_segments;
1039 std::vector<Int_t> local_index;
1040
1041 /* Clear and set up the fRunSegments vector. */
1042 tmp_segments.clear();
1043 fRunSegments.clear();
1044 fRunSegments.resize(0);
1045 fRunIsSegmented = kFALSE;
1046
1047 searchpath = fDataFile;
1048 glob(searchpath.Data(), GLOB_ERR, NULL, &globbuf);
1049
1050 if(fSingleFile){
1051
1052 fRunIsSegmented = kFALSE;
1053
1054 } else if (globbuf.gl_pathc == 1){
1055 /* The base file name exists. *
1056 * Do not look for file segments. */
1057 fRunIsSegmented = kFALSE;
1058
1059 } else {
1060 /* The base file name does not exist. *
1061 * Look for file segments. */
1062 QwWarning << "File " << fDataFile << " does not exist!\n"
1063 << " Trying to find run segments for run "
1064 << fCurrentRun << "... ";
1065
1066 searchpath.Append(".[0-9]*");
1067 glob(searchpath.Data(), GLOB_ERR, NULL, &globbuf);
1068
1069 if (globbuf.gl_pathc == 0){
1070 /* There are no file segments and no base file *
1071 * Produce and error message and exit. */
1072 QwError << "\n There are no file segments either!!" << QwLog::endl;
1073
1074 // This could mean a single gzipped file!
1075 fRunIsSegmented = kFALSE;
1076
1077 } else {
1078 /* There are file segments. *
1079 * Determine the segment numbers and fill fRunSegments *
1080 * to indicate the existing file segments. */
1081
1082 QwMessage << "OK" << QwLog::endl;
1083 scanvalue = fDataFile + ".%d";
1084
1085 /* Get the list of segment numbers in file listing *
1086 * order. */
1087 for (size_t iloop=0;iloop<globbuf.gl_pathc;++iloop){
1088 /* Extract the segment numbers from the file name. */
1089 sscanf(globbuf.gl_pathv[iloop], scanvalue.Data(), &local_segment);
1090 tmp_segments.push_back(local_segment);
1091 }
1092 local_index.resize(tmp_segments.size(),0);
1093 /* Get the list of segments sorted numerically in *
1094 * increasing order. */
1095 TMath::Sort(static_cast<int>(tmp_segments.size()),&(tmp_segments[0]),&(local_index[0]),
1096 kFALSE);
1097 /* Put the segments into numerical order in fRunSegments. Add *
1098 * only those segments requested (though always add segment 0). */
1099 QwMessage << " Found the segment(s): ";
1100 size_t printed = 0;
1101 for (size_t iloop=0; iloop<tmp_segments.size(); ++iloop){
1102 local_segment = tmp_segments[local_index[iloop]];
1103 if (printed++) QwMessage << ", ";
1104 QwMessage << local_segment ;
1105 if (local_segment == 0 ||
1106 ( fSegmentRange.first <= local_segment &&
1107 local_segment <= fSegmentRange.second ) ) {
1108 fRunSegments.push_back(local_segment);
1109 } else {
1110 QwMessage << " (skipped)" ;
1111 }
1112 }
1113 QwMessage << "." << QwLog::endl;
1115
1116 fRunIsSegmented = kTRUE;
1117
1118 /* If the first requested segment hasn't been found,
1119 forget everything. */
1120 if ( local_segment < fSegmentRange.first ) {
1121 QwError << "First requested run segment "
1122 << fSegmentRange.first << " not found.\n";
1123 fRunSegments.pop_back();
1125 fRunIsSegmented = kTRUE; // well, it is true.
1126 }
1127 }
1128 }
1129 globfree(&globbuf);
1130 return fRunIsSegmented;
1131}
1132
1133//------------------------------------------------------------
1134
1136{
1137 Int_t status = kFileHandleNotConfigured;
1138 Int_t last_runsegment;
1139 if (fRunIsSegmented){
1140 last_runsegment = *fRunSegmentIterator;
1142 if (fRunSegmentIterator <= fRunSegments.end()){
1143 QwMessage << "Closing run segment " << last_runsegment <<"."
1144 << QwLog::endl;
1145 status = CloseDataFile();
1146 }
1147 } else {
1148 // Don't try to close a nonsegmented file; we will explicitly
1149 // use CloseDataFile() later.
1150 }
1151 return status;
1152}
1153
1154//------------------------------------------------------------
1155
1157{
1158 Int_t status;
1159 if (! fRunIsSegmented){
1160 /* We are processing a non-segmented run. *
1161 * We should not have entered this routine, but *
1162 * since we are here, don't do anything. */
1163 status = kRunNotSegmented;
1164
1165 } else if (fRunSegments.size()==0){
1166 /* There are actually no file segments located. *
1167 * Return "kNoNextDataFile", but don't print an *
1168 * error message. */
1169 status = kNoNextDataFile;
1170
1171 } else if (fRunSegmentIterator >= fRunSegments.begin() &&
1173 QwMessage << "Trying to open run segment " << *fRunSegmentIterator << QwLog::endl;
1175
1176 } else if (fRunSegmentIterator == fRunSegments.end() ) {
1177 /* We have reached the last run segment. */
1178 QwMessage << "There are no run segments remaining." << QwLog::endl;
1179 status = kNoNextDataFile;
1180
1181 } else {
1182 QwError << "QwEventBuffer::OpenNextSegment(): Unrecognized error" << QwLog::endl;
1183 status = CODA_ERROR;
1184 }
1185 return status;
1186}
1187
1188
1189//------------------------------------------------------------
1190//call this routine if we've selected the run segment by hand
1191Int_t QwEventBuffer::OpenDataFile(UInt_t current_run, Short_t seg)
1192{
1193 fCurrentRun = current_run;
1194
1195 fRunSegments.clear();
1196 fRunIsSegmented = kTRUE;
1197
1198 fRunSegments.push_back(seg);
1200 return OpenNextSegment();
1201}
1202
1203//------------------------------------------------------------
1204//call this routine if the run is not segmented
1205Int_t QwEventBuffer::OpenDataFile(UInt_t current_run, const TString rw)
1206{
1207 Int_t status;
1208 fCurrentRun = current_run;
1210 if (DataFileIsSegmented()){
1211 status = OpenNextSegment();
1212 } else {
1213 status = OpenDataFile(DataFile(fCurrentRun),rw);
1214 }
1215 return status;
1216}
1217
1218
1219
1220//------------------------------------------------------------
1221Int_t QwEventBuffer::OpenDataFile(const TString filename, const TString rw)
1222{
1224 QwDebug << "QwEventBuffer::OpenDataFile: File handle doesn't exist.\n"
1225 << " Try to open a new file handle!"
1226 << QwLog::endl;
1227 fEvStream = new THaCodaFile();
1229 } else if (fEvStreamMode!=fEvStreamFile){
1230 QwError << "QwEventBuffer::OpenDataFile: The stream is not configured as an input\n"
1231 << " file stream! Can't deal with this!\n"
1232 << QwLog::endl;
1233 exit(1);
1234 }
1235 fDataFile = filename;
1236
1237 if (rw.Contains("w",TString::kIgnoreCase)) {
1238 // If we open a file for write access, let's suppose
1239 // we've given the path we want to use.
1240 QwMessage << "Opening data file: " << fDataFile << QwLog::endl;
1241 } else {
1242 // Let's try to find the data file for read access.
1243 glob_t globbuf;
1244 glob(fDataFile.Data(), GLOB_ERR, NULL, &globbuf);
1245 if (globbuf.gl_pathc == 0){
1246 // Can't find the file; try in the "fDataDirectory".
1247 fDataFile = fDataDirectory + filename;
1248 glob(fDataFile.Data(), GLOB_ERR, NULL, &globbuf);
1249 }
1250 if (globbuf.gl_pathc == 0){
1251 // Can't find the file; try gzipped.
1252 fDataFile = filename + ".gz";
1253 glob(fDataFile.Data(), GLOB_ERR, NULL, &globbuf);
1254 }
1255 if (globbuf.gl_pathc == 0){
1256 // Can't find the file; try gzipped in the "fDataDirectory".
1257 fDataFile = fDataDirectory + filename + ".gz";
1258 glob(fDataFile.Data(), GLOB_ERR, NULL, &globbuf);
1259 }
1260 if (globbuf.gl_pathc == 1){
1261 QwMessage << "Opening data file: " << fDataFile << QwLog::endl;
1262 } else {
1263 fDataFile = filename;
1264 QwError << "Unable to find "
1265 << filename.Data() << " or "
1266 << (fDataDirectory + filename).Data() << QwLog::endl;
1267 }
1268 globfree(&globbuf);
1269 }
1270 return fEvStream->codaOpen(fDataFile, rw);
1271}
1272
1273
1274//------------------------------------------------------------
1276{
1277 Int_t status = kFileHandleNotConfigured;
1279 status = fEvStream->codaClose();
1280 }
1281 return status;
1282}
1283
1284//------------------------------------------------------------
1285Int_t QwEventBuffer::OpenETStream(TString computer, TString session, int mode,
1286 const TString stationname)
1287{
1288 Int_t status = CODA_OK;
1290#ifdef __CODA_ET
1291 if (stationname != ""){
1292 fEvStream = new THaEtClient(computer, session, mode, stationname.Data());
1293 } else {
1294 fEvStream = new THaEtClient(computer, session, mode);
1295 }
1297#endif
1298 }
1299 return status;
1300}
1301
1302//------------------------------------------------------------
1304{
1305 Int_t status = kFileHandleNotConfigured;
1307 status = fEvStream->codaClose();
1308 }
1309 return status;
1310}
1311
1312//------------------------------------------------------------
1314{
1315 QwDebug << "QwEventBuffer::GetMarkerWordList: start function" <<QwLog::endl;
1316 fThisRocBankLabel = decoder->GetROC();
1318 fThisRocBankLabel += decoder->GetSubbankTag();
1319 if (fMarkerList.count(fThisRocBankLabel)==0){
1320 std::vector<UInt_t> tmpvec;
1321 subsystems.GetMarkerWordList(decoder->GetROC(), decoder->GetSubbankTag(), tmpvec);
1322 fMarkerList.emplace(fThisRocBankLabel, tmpvec);
1323 fOffsetList.emplace(fThisRocBankLabel, std::vector<UInt_t>(tmpvec.size(),0));
1324 }
1325 QwDebug << "QwEventBuffer::GetMarkerWordList: fMarkerList.count(fThisRocBankLabel)=="
1327 << " fMarkerList.at(fThisRocBankLabel).size()=="
1328 << fMarkerList.at(fThisRocBankLabel).size()
1329 << QwLog::endl;
1330 return fMarkerList.at(fThisRocBankLabel).size();
1331}
1332
1333UInt_t QwEventBuffer::GetMarkerWord(UInt_t markerID){
1334 return fMarkerList.at(fThisRocBankLabel).at(markerID);
1335};
1336
1337
1338UInt_t QwEventBuffer::FindMarkerWord(UInt_t markerindex, UInt_t* buffer, UInt_t num_words){
1339 UInt_t markerpos = fOffsetList.at(fThisRocBankLabel).at(markerindex);
1340 UInt_t markerval = fMarkerList.at(fThisRocBankLabel).at(markerindex);
1341 if (markerpos < num_words && buffer[markerpos] == markerval){
1342 // The marker word is where it was last time
1343 return markerpos;
1344 } else {
1345 for (size_t i=0; i<num_words; i++){
1346 if (buffer[i] == markerval){
1347 fOffsetList.at(fThisRocBankLabel).at(markerindex) = i;
1348 markerpos = i;
1349 break;
1350 }
1351 }
1352 }
1353 return markerpos;
1354}
Definition of the pure virtual base class of all subsystems.
An options class which parses command line, config file and environment.
#define QwVerbose
Predefined log drain for verbose messages.
Definition QwLog.h:54
#define QwError
Predefined log drain for errors.
Definition QwLog.h:39
#define QwWarning
Predefined log drain for warnings.
Definition QwLog.h:44
#define QwMessage
Predefined log drain for regular messages.
Definition QwLog.h:49
#define QwDebug
Predefined log drain for debugging output.
Definition QwLog.h:59
Array container for managing multiple subsystems.
EPICS data event handling and storage.
Event buffer management for reading and processing CODA data.
ULong64_t BankID_t
Definition QwTypes.h:21
void sigint_handler(int sig)
Bool_t onlineRestart
void sigusr_handler(int sig)
Bool_t globalEXIT
CODA version 2 event decoder implementation.
CODA version 3 event decoder implementation.
EPICS slow controls data management.
void ExtractEPICSValues(const string &data, int event)
TString GetRunLabel() const
Returns a string like <run#> or <run#>.<file#>
Int_t EncodeSubsystemData(QwSubsystemArray &subsystems)
TString fETHostname
static const Int_t kRunNotSegmented
Int_t EncodeGoEvent()
TString GetEndSQLTime()
time_t GetStartUnixTime()
TString fDataDirectory
Int_t EncodePauseEvent()
UInt_t fStartingPhysicsEvent
Int_t GetEventNumber()
Int_t CloseThisSegment()
void ReportRunSummary()
static std::string fDefaultDataDirectory
Int_t EncodeEndEvent()
Bool_t fChainDataFiles
std::unordered_map< RocBankLabel_t, std::vector< UInt_t > > fMarkerList
enum QwEventBuffer::CodaStreamMode fEvStreamMode
Int_t CloseStream()
Closes a currently open event stream.
Int_t WriteEtEvent(int *buffer)
Bool_t IsEPICSEvent()
Int_t OpenETStream(TString computer, TString session, int mode, const TString stationname="")
Bool_t fRunIsSegmented
Bool_t GetNextRunRange()
Read the next requested run range, return true if success.
Int_t EncodePrestartEvent(int runnumber, int runtype=0)
QwEventBuffer()
Default constructor.
void VerifyCodaVersion(const UInt_t *buffer)
Int_t WriteFileEvent(int *buffer)
Int_t OpenNextStream()
Opens the event stream (file or ET) based on the internal flags.
static const Int_t kFileHandleNotConfigured
std::vector< Int_t >::iterator fRunSegmentIterator
std::chrono::duration< double > fAccumulatedDelay
void ProcessOptions(QwOptions &options)
Sets internal flags based on the QwOptions.
Bool_t FillSubsystemData(QwSubsystemArray &subsystems)
VEventDecoder * decoder
TStopwatch fStopwatch
Timer used for internal timing.
Int_t WriteEvent(int *buffer)
Int_t GetSegmentNumber() const
Return CODA file segment number.
std::unique_ptr< QwParameterFile > fEventListFile
void ResetControlParameters()
const TString & DataFile(const UInt_t run, const Short_t seg)
TString GetStartSQLTime()
TString fETStationName
Bool_t fEventRateLimitEnabled
static void DefineOptions(QwOptions &options)
std::unordered_map< RocBankLabel_t, std::vector< UInt_t > > fOffsetList
Double_t fCleanParameter[3]
Scan data/clean data from the green monster.
UInt_t FindMarkerWord(UInt_t markerID, UInt_t *buffer, UInt_t num_words)
TString fDataFileExtension
Int_t GetRunNumber() const
Return CODA file run number.
static const UInt_t kNullDataWord
static const Int_t kNoNextDataFile
RocBankLabel_t fThisRocBankLabel
Double_t fMaxEventRate
Bool_t GetNextEventRange()
Read the next requested event range, return true if success.
Bool_t DataFileIsSegmented()
std::pair< Int_t, Int_t > fRunRange
std::pair< UInt_t, UInt_t > fEventRange
Int_t OpenDataFile(UInt_t current_run, Short_t seg)
static std::string fDefaultDataFileExtension
std::string fRunListFileName
Int_t OpenNextSegment()
UInt_t fNumPhysicsEvents
TStopwatch fRunTimer
Timer used for runlet processing loop.
time_t GetEndUnixTime()
static std::string fDefaultDataFileStem
Bool_t GetNextRunNumber()
Get the next run in the active run range, proceed to next range if needed.
std::chrono::duration< double > fMinEventInterval
Bool_t IsPhysicsEvent()
Bool_t FillEPICSData(QwEPICSEvent &epics)
THaCodaData * fEvStream
std::pair< Int_t, Int_t > fSegmentRange
std::unique_ptr< QwParameterFile > fRunListFile
std::size_t CheckForMarkerWords(QwSubsystemArray &subsystems)
std::chrono::steady_clock::time_point fLastEventTime
std::vector< Int_t > fRunSegments
Bool_t FillSubsystemConfigurationData(QwSubsystemArray &subsystems)
TString fDataFileStem
Int_t fDataVersionVerify
UInt_t GetMarkerWord(UInt_t markerID)
static std::ostream & endl(std::ostream &)
End of the line.
Definition QwLog.cc:297
Command-line and configuration file options processor.
Definition QwOptions.h:141
std::pair< int, int > GetIntValuePair(const std::string &key)
Get a pair of integer values.
Definition QwOptions.cc:357
po::options_description_easy_init AddDefaultOptions()
Add a default option.
Definition QwOptions.h:165
T GetValue(const std::string &key)
Get a templated value.
Definition QwOptions.h:236
bool HasValue(const std::string &key)
Has this key been defined.
Definition QwOptions.h:229
po::options_description_easy_init AddOptions(const std::string &blockname="Specialized options")
Add an option to a named block or create new block.
Definition QwOptions.h:170
static std::pair< int, int > ParseIntRange(const std::string &separatorchars, const std::string &range)
Parse a range of integers as #:# where either can be missing.
Container for managing multiple subsystems with common operations.
void SetCodaRunNumber(UInt_t runnum)
Set the internal record of the CODA run number.
void SetCleanParameters(Double_t cleanparameter[3])
Set the internal record of the CODA event number.
UInt_t GetEventTypeMask() const
Get event type mask.
void GetMarkerWordList(const ROCID_t roc_id, const BankID_t bank_id, std::vector< UInt_t > &marker) const
void EncodeEventData(std::vector< UInt_t > &buffer)
Encode the data in this event.
void SetCodaSegmentNumber(UInt_t segnum)
Set the internal record of the CODA segment number.
Int_t ProcessEvBuffer(const UInt_t event_type, const ROCID_t roc_id, const BankID_t bank_id, UInt_t *buffer, UInt_t num_words)
Process the event buffer for events.
void SetCodaEventNumber(UInt_t evtnum)
Set the internal record of the CODA event number.
void SetCodaEventType(UInt_t evttype)
Set the internal record of the CODA event type.
Int_t ProcessConfigurationBuffer(const ROCID_t roc_id, const BankID_t bank_id, UInt_t *buffer, UInt_t num_words)
Process the event buffer for configuration events.
void GetROCIDList(std::vector< ROCID_t > &list)
Get the ROCID list.