Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
JEventSource_EVIOpp.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: JEventSource_EVIOpp.cc
4 // Created: Tue Mar 29 08:14:42 EDT 2016
5 // Creator: davidl (on Darwin harriet.jlab.org 13.4.0 i386)
6 //
7 
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <stdint.h>
11 #include <time.h>
12 
13 #include <forward_list>
14 #include <chrono>
15 #include <iostream>
16 #include <string>
17 #include <vector>
18 #include <stack>
19 #include <thread>
20 #include <mutex>
21 #include <condition_variable>
22 #include <cmath>
23 #include <algorithm>
24 
25 using namespace std;
26 using namespace std::chrono;
27 
28 
34 
35 
36 #include "JEventSource_EVIOpp.h"
37 #include "LinkAssociations.h"
38 using namespace jana;
39 
40 
41 
42 // sort Df250PulseData objects by pulse number
44  return a->pulse_number < b->pulse_number;
45 }
46 
47 //----------------
48 // Constructor
49 //----------------
50 JEventSource_EVIOpp::JEventSource_EVIOpp(const char* source_name):JEventSource(source_name)
51 {
52  DONE = false;
53  DISPATCHER_END = false;
57  NPARSER_STALLED = 0;
58 
59  // Initialize dedicated JStreamLog used for debugging messages
60  evioout.SetTag("--- EVIO ---: ");
61  evioout.SetTimestampFlag();
62  evioout.SetThreadstampFlag();
63 
64  // Define base set of status bits
66 
67  // Get configuration parameters
68  VERBOSE = 0;
69  VERBOSE_ET = 0;
70  NTHREADS = 2;
71  MAX_PARSED_EVENTS = 128;
72  MAX_EVENT_RECYCLES = 1000;
73  MAX_OBJECT_RECYCLES = 1000;
74  LOOP_FOREVER = false;
75  USER_RUN_NUMBER = 0;
76  ET_STATION_NEVENTS = 10;
78  PRINT_STATS = true;
79  SWAP = true;
80  LINK = true;
81  LINK_TRIGGERTIME = true;
82  LINK_BORCONFIG = true;
83  LINK_CONFIG = true;
84  PARSE = true;
85  PARSE_F250 = true;
86  PARSE_F125 = true;
87  PARSE_F1TDC = true;
88  PARSE_CAEN1290TDC = true;
89  PARSE_CONFIG = true;
90  PARSE_BOR = true;
91  PARSE_EPICS = true;
92  PARSE_EVENTTAG = true;
93  PARSE_TRIGGER = true;
94  PARSE_SSP = true;
96  IGNORE_EMPTY_BOR = false;
100  RECORD_CALL_STACK = false;
101  TREAT_TRUNCATED_AS_ERROR = false;
102  SYSTEMS_TO_PARSE = "";
103 
104  gPARMS->SetDefaultParameter("EVIO:VERBOSE", VERBOSE, "Set verbosity level for processing and debugging statements while parsing. 0=no debugging messages. 10=all messages");
105  gPARMS->SetDefaultParameter("ET:VERBOSE", VERBOSE_ET, "Set verbosity level for processing and debugging statements while reading from ET. 0=no debugging messages. 10=all messages");
106  gPARMS->SetDefaultParameter("EVIO:NTHREADS", NTHREADS, "Set the number of worker threads to use for parsing the EVIO data");
107  gPARMS->SetDefaultParameter("EVIO:MAX_PARSED_EVENTS", MAX_PARSED_EVENTS, "Set maximum number of events to allow in EVIO parsed events queue");
108  gPARMS->SetDefaultParameter("EVIO:MAX_EVENT_RECYCLES", MAX_EVENT_RECYCLES, "Set maximum number of EVIO (i.e. block of) events a worker thread should process before pruning excess DParsedEvent objects from its pool");
109  gPARMS->SetDefaultParameter("EVIO:MAX_OBJECT_RECYCLES", MAX_OBJECT_RECYCLES, "Set maximum number of events a DParsedEvent should be used for before pruning excess hit objects from its pools");
110  gPARMS->SetDefaultParameter("EVIO:LOOP_FOREVER", LOOP_FOREVER, "If reading from EVIO file, keep re-opening file and re-reading events forever (only useful for debugging) If reading from ET, this is ignored.");
111  gPARMS->SetDefaultParameter("EVIO:RUN_NUMBER", USER_RUN_NUMBER, "User-supplied run number. Override run number from other sources with this.(will be ignored if set to zero)");
112  gPARMS->SetDefaultParameter("EVIO:ET_STATION_NEVENTS", ET_STATION_NEVENTS, "Number of events to use if we have to create the ET station. Ignored if station already exists.");
113  gPARMS->SetDefaultParameter("EVIO:ET_STATION_CREATE_BLOCKING", ET_STATION_CREATE_BLOCKING, "Set this to 0 to create station in non-blocking mode (default is to create it in blocking mode). Ignored if station already exists.");
114  gPARMS->SetDefaultParameter("EVIO:PRINT_STATS", PRINT_STATS, "Print some additional stats from event source when it's finished processing events");
115 
116  gPARMS->SetDefaultParameter("EVIO:SWAP", SWAP, "Allow swapping automatic swapping. Turning this off should only be used for debugging.");
117  gPARMS->SetDefaultParameter("EVIO:LINK", LINK, "Link associated objects. Turning this off should only be used for debugging.");
118  gPARMS->SetDefaultParameter("EVIO:LINK_TRIGGERTIME", LINK_TRIGGERTIME, "Link D*TriggerTime associated objects. This is on by default and may be OK to turn off (but please check output if you do!)");
119  gPARMS->SetDefaultParameter("EVIO:LINK_BORCONFIG", LINK_BORCONFIG, "Link BORConfig associated objects. This is on by default. If turned off, it will break emulation (and possibly other things in the future).");
120  gPARMS->SetDefaultParameter("EVIO:LINK_CONFIG", LINK_CONFIG, "Link Config associated objects. This is on by default.");
121 
122  gPARMS->SetDefaultParameter("EVIO:PARSE", PARSE, "Set this to 0 to disable parsing of event buffers and generation of any objects (for benchmarking/debugging)");
123  gPARMS->SetDefaultParameter("EVIO:PARSE_F250", PARSE_F250, "Set this to 0 to disable parsing of data from F250 ADC modules (for benchmarking/debugging)");
124  gPARMS->SetDefaultParameter("EVIO:PARSE_F125", PARSE_F125, "Set this to 0 to disable parsing of data from F125 ADC modules (for benchmarking/debugging)");
125  gPARMS->SetDefaultParameter("EVIO:PARSE_F1TDC", PARSE_F1TDC, "Set this to 0 to disable parsing of data from F1TDC modules (for benchmarking/debugging)");
126  gPARMS->SetDefaultParameter("EVIO:PARSE_CAEN1290TDC", PARSE_CAEN1290TDC, "Set this to 0 to disable parsing of data from CAEN 1290 TDC modules (for benchmarking/debugging)");
127  gPARMS->SetDefaultParameter("EVIO:PARSE_CONFIG", PARSE_CONFIG, "Set this to 0 to disable parsing of ROC configuration data in the data stream (for benchmarking/debugging)");
128  gPARMS->SetDefaultParameter("EVIO:PARSE_BOR", PARSE_BOR, "Set this to 0 to disable parsing of BOR events from the data stream (for benchmarking/debugging)");
129  gPARMS->SetDefaultParameter("EVIO:PARSE_EPICS", PARSE_EPICS, "Set this to 0 to disable parsing of EPICS events from the data stream (for benchmarking/debugging)");
130  gPARMS->SetDefaultParameter("EVIO:PARSE_EVENTTAG", PARSE_EVENTTAG, "Set this to 0 to disable parsing of event tag data in the data stream (for benchmarking/debugging)");
131  gPARMS->SetDefaultParameter("EVIO:PARSE_TRIGGER", PARSE_TRIGGER, "Set this to 0 to disable parsing of the built trigger bank from CODA (for benchmarking/debugging)");
132  gPARMS->SetDefaultParameter("EVIO:PARSE_SSP", PARSE_SSP, "Set this to 0 to disable parsing of the SSP (DIRC data) bank from CODA (for benchmarking/debugging)");
133  gPARMS->SetDefaultParameter("EVIO:APPLY_TRANSLATION_TABLE", APPLY_TRANSLATION_TABLE, "Apply the translation table to create DigiHits (you almost always want this on)");
134  gPARMS->SetDefaultParameter("EVIO:IGNORE_EMPTY_BOR", IGNORE_EMPTY_BOR, "Set to non-zero to continue processing data even if an empty BOR event is encountered.");
135  gPARMS->SetDefaultParameter("EVIO:TREAT_TRUNCATED_AS_ERROR", TREAT_TRUNCATED_AS_ERROR, "Set to non-zero to have a truncated EVIO file the JANA return code to non-zero indicating the program errored.");
136 
137  gPARMS->SetDefaultParameter("EVIO:F250_EMULATION_MODE", F250_EMULATION_MODE, "Set f250 emulation mode. 0=no emulation, 1=always, 2=auto. Default is 2 (auto).");
138  gPARMS->SetDefaultParameter("EVIO:F125_EMULATION_MODE", F125_EMULATION_MODE, "Set f125 emulation mode. 0=no emulation, 1=always, 2=auto. Default is 2 (auto).");
139 
140  gPARMS->SetDefaultParameter("EVIO:SYSTEMS_TO_PARSE", SYSTEMS_TO_PARSE,
141  "Comma separated list of systems to parse EVIO data for. "
142  "Default is empty string which means to parse all. System "
143  "names should be what is returned by DTranslationTable::DetectorName() .");
144 
145 
146  if(gPARMS->Exists("RECORD_CALL_STACK")) gPARMS->GetParameter("RECORD_CALL_STACK", RECORD_CALL_STACK);
147 
148  // Set rocids of all systems to parse (if specified)
150 
154  if(!LINK ) LINK_BORCONFIG = false;
155 
157  hdevio = NULL;
158  hdet = NULL;
159  et_quit_next_timeout = false;
160 
161  uint64_t run_number_seed = 0;
162 
163  // Open either ET system or file
164  if(this->source_name.find("ET:") == 0){
165 
166  // Try to open ET system
167  if(VERBOSE>0) evioout << "Attempting to open \""<<this->source_name<<"\" as ET (network) source..." <<endl;
168 
169  hdet = new HDET(this->source_name, ET_STATION_NEVENTS, ET_STATION_CREATE_BLOCKING);
170  if( ! hdet->is_connected ){
171  cerr << hdet->err_mess.str() << endl;
172  throw JException("Failed to open ET system: " + this->source_name, __FILE__, __LINE__);
173  }
176 
177  }else{
178 
179  // Try to open the file.
180  if(VERBOSE>0) evioout << "Attempting to open \""<<this->source_name<<"\" as EVIO file..." <<endl;
181 
182  hdevio = new HDEVIO(this->source_name, true, VERBOSE);
183  if( ! hdevio->is_open ){
184  cerr << hdevio->err_mess.str() << endl;
185  throw JException("Failed to open EVIO file: " + this->source_name, __FILE__, __LINE__); // throw exception indicating error
186  }
189 
190  run_number_seed = SearchFileForRunNumber(); // try and dig out run number from file
191  }
192 
193  if(VERBOSE>0) evioout << "Success opening event source \"" << this->source_name << "\"!" <<endl;
194 
195  // Create dispatcher thread
197 
198  // Create worker threads
199  for(uint32_t i=0; i<NTHREADS; i++){
201  w->VERBOSE = VERBOSE;
204  w->PARSE_F250 = PARSE_F250;
205  w->PARSE_F125 = PARSE_F125;
209  w->PARSE_BOR = PARSE_BOR;
213  w->PARSE_SSP = PARSE_SSP;
216  w->run_number_seed = run_number_seed;
217  worker_threads.push_back(w);
218  }
219 
220  // Create emulator objects
221 
222  if(F250_EMULATION_VERSION == 1) {
224  } else if(F250_EMULATION_VERSION == 2) {
226  } else {
227  cerr << "loading VERSION 3" << endl;
228  if(F250_EMULATION_VERSION != 3)
229  jerr << "Invalid fADC250 firmware version specified for emulation == " << F250_EMULATION_VERSION
230  << " , Using v3 firmware as default ..." << endl;
232  }
233 
235 
236  // Record start time
237  tstart = high_resolution_clock::now();
238 
239 }
240 
241 //----------------
242 // Destructor
243 //----------------
245 {
246  // Set DONE flag to tell dispatcher thread to quit
247  // as well as anyone in a wait state
248  DONE = true;
249  PARSED_EVENTS_CV.notify_all();
250 
251  // Wait for dispatcher to complete
252  if(dispatcher_thread){
253  DISPATCHER_END = true;
254  dispatcher_thread->join();
255  delete dispatcher_thread;
256  }
257 
258  // Wait for all worker threads to end and destroy them all
259  for(auto w : worker_threads){
260  w->Finish();
261  delete w;
262  }
263 
264  // Delete emulator objects
265  if(f250Emulator) delete f250Emulator;
266  if(f125Emulator) delete f125Emulator;
267 
268  if(VERBOSE>0) evioout << "Closing hdevio event source \"" << this->source_name << "\"" <<endl;
269  if(PRINT_STATS){
270  auto tdiff = duration_cast<duration<double>>(tend - tstart);
271  double rate = (double)NEVENTS_PROCESSED/tdiff.count();
272 
273  uint32_t NTHREADS_PROC = 1;
274  if(gPARMS->Exists("NTHREADS")) gPARMS->GetParameter("NTHREADS", NTHREADS_PROC);
275 
276  // Calculate fraction of total time each stage spent
277  // idle. There was a 1ms sleep for each one of these
278  double tfrac_dis = (double)NDISPATCHER_STALLED/1000.0/tdiff.count()*100.0;
279  double tfrac_parse = (double)NPARSER_STALLED/1000.0/(double)NTHREADS/tdiff.count()*100.0;
280  double tfrac_proc = (double)NEVENTBUFF_STALLED/1000.0/tdiff.count()*100.0;
281 
282  char sdispatcher[256];
283  char sparser[256];
284  char sprocessor[256];
285  sprintf(sdispatcher, " NDISPATCHER_STALLED = %10ld (%4.1f%%)", (unsigned long)NDISPATCHER_STALLED, tfrac_dis );
286  sprintf(sparser , " NPARSER_STALLED = %10ld (%4.1f%%)", (unsigned long)NPARSER_STALLED , tfrac_parse);
287  sprintf(sprocessor , " NEVENTBUFF_STALLED = %10ld (%4.1f%%)", (unsigned long)NEVENTBUFF_STALLED , tfrac_proc );
288 
289  cout << endl;
290  cout << " EVIO Processing rate = " << rate << " Hz" << endl;
291  cout << sdispatcher << endl;
292  cout << sparser << endl;
293  cout << sprocessor << endl;
294  }
295 
296  // Delete all BOR objects
297  for(auto p : borptrs_list) delete p;
298 
299  // Delete HDEVIO and print stats
300  if(hdevio){
301  hdevio->PrintStats();
302  delete hdevio;
303  }
304 
305  // Delete HDET and print stats
306  if(hdet){
307  hdet->PrintStats();
308  delete hdet;
309  }
310 }
311 
312 //----------------
313 // Dispatcher
314 //----------------
316 {
317  /// This is run in a dedicated thread created by the constructor.
318  /// It's job is to read in events and dispatch the processing of
319  /// them to worker threads. When a worker thread is done, it adds
320  /// the event to the parsed_events list and clears its own "in_use"
321  /// flag thereby, marking itself as available for another job.
322  /// The worker threads will stall if adding the event(s) it produced
323  /// would make parsed_events contain more than MAX_PARSED_EVENTS.
324  /// This creates backpressure here by having no worker threads
325  /// available.
326 
327  bool allow_swap = false; // Defer swapping to DEVIOWorkerThread
328  uint64_t istreamorder = 0;
329  while(true){
330 
331  if(japp->GetQuittingStatus()) break;
332 
333  // Get worker thread to handle this
334  DEVIOWorkerThread *thr = NULL;
335  while( !thr){
336  for(auto t : worker_threads){
337  if(t->in_use) continue;
338  thr = t;
339  break;
340  }
341  if(!thr) {
343  this_thread::sleep_for(milliseconds(1));
344  }
345  if(DONE) break;
346  }
347  if(DONE) break;
348 
349  uint32_t* &buff = thr->buff;
350  uint32_t &buff_len = thr->buff_len;
351 
352  bool swap_needed = false;
353 
355  // ---- Read From File ----
356 // hdevio->read(buff, buff_len, allow_swap);
357 // hdevio->readSparse(buff, buff_len, allow_swap);
358  hdevio->readNoFileBuff(buff, buff_len, allow_swap);
359  thr->pos = hdevio->last_event_pos;
361  delete[] buff;
362  buff_len = hdevio->last_event_len;
363  buff = new uint32_t[buff_len];
364  continue;
365  }else if(hdevio->err_code!=HDEVIO::HDEVIO_OK){
367  if(hdevio){
368  hdevio->rewind();
369  continue;
370  }
371  }else{
372  // Some CDAQ files do not have a proper trailer at the end of the
373  // EVIO file and so get reported by HDEVIO as truncated. We do not
374  // want to treat those as an error, but DO want to treat legitimate
375  // truncations as errors. If this is a CDAQ event and there are
376  // exactly zero words left in the file then assume it is OK.
377  // n.b. the IS_CDAQ_FILE flag is set in DEVIOWorkerThread::ParseCDAQBank
378  // during the parsing of a previous event. It is possible we could
379  // reach here before that is set leading to a race condition!
381  jout << "Missing EVIO file trailer in CDAQ file (ignoring..)" << endl;
382  }else{
383  cout << hdevio->err_mess.str() << endl;
385  bool ignore_error = false;
386  if( (!TREAT_TRUNCATED_AS_ERROR) && (hdevio->err_code == HDEVIO::HDEVIO_FILE_TRUNCATED) ) ignore_error = true;
387  if(!ignore_error) japp->SetExitCode(hdevio->err_code);
388  }
389  }
390  }
391  break;
392  }else{
393  // HDEVIO_OK
394  swap_needed = hdevio->swap_needed;
395  }
396  }else{
397  // ---- Read From ET ----
398  hdet->read(buff, buff_len, allow_swap);
399  thr->pos = 0;
400  static uint64_t ntimeouts=0;
402  if(et_quit_next_timeout) break;
403  if( ++ntimeouts>=2 ){ // timeout is set to 2 seconds in HDET.cc
404  int ic = ntimeouts%4;
405  const char *c[4] = {"|","/","-","\\"};
406  if(ntimeouts==2) cout << endl;
407  cout << " ET stalled ... " << c[ic] << " \r";
408  cout.flush();
409  }
410  continue;
411  }else if(hdet->err_code != HDET::HDET_OK){
412  cout << hdet->err_mess.str() << endl;
413  break;
414  }else{
415  // HDET_OK
416  swap_needed = hdet->swap_needed;
417  if(ntimeouts>=2) cout << endl;
418  ntimeouts=0;
419  }
420  }
421 
422  uint32_t myjobtype = jobtype;
423  if(swap_needed && SWAP) myjobtype |= DEVIOWorkerThread::JOB_SWAP;
424 
425  // Wake up worker thread to handle event
426  thr->jobtype = (DEVIOWorkerThread::JOBTYPE)myjobtype;
427  thr->in_use = true;
428  thr->istreamorder = istreamorder++;
429 
430  thr->cv.notify_all();
431  }
432 
433  // If we get here then there are no more events in the source.
434  // Wait for all worker threads to become available so we know
435  // the system is drained of events. Then set the DONE flag so
436  // GetEvent will properly return NO_MORE_EVENTS_IN_SOURCE.
437  for( auto w : worker_threads ){
438  w->done = true;
439  while(w->in_use){
440  this_thread::sleep_for(milliseconds(10));
441  }
442  }
443 
444  DONE = true;
445 
446  // Free the worker threads (and their associated object pools)
447  // to reduce overall memory consumption. This JEventSource_EVIOpp
448  // object will not be deleted until just before the program exits
449  // so waiting for the destructor call will cause unneccessary
450  // memory use. (This is really for the case when more than one
451  // file is being processed). Since deleting the DEVIOWorkerThread
452  // object will also delete all of its DParsedEvents and
453  // some of those may still be in use, we must wait for all
454  // events to have their in_use flag set before deleting the
455  // worker thread object.
456  for( auto w : worker_threads ){
457 
458  while( true ){
459  bool in_use = false;
460  for( auto pe : w->parsed_event_pool ) in_use |= pe->in_use;
461  if( !in_use ) break;
462  if( DISPATCHER_END ) break;
463  this_thread::sleep_for(milliseconds(10));
464  }
465 
466  w->Finish();
467  delete w;
468  }
469  worker_threads.clear();
470 
471  tend = std::chrono::high_resolution_clock::now();
472 }
473 
474 //----------------
475 // GetEvent
476 //----------------
477 jerror_t JEventSource_EVIOpp::GetEvent(JEvent &event)
478 {
479  // Get next event from list, waiting if necessary
480  unique_lock<std::mutex> lck(PARSED_EVENTS_MUTEX);
481  while(parsed_events.empty()){
482  if(DONE){
483  done_reading = true;
484 
485  // There is a bug in JANA where an event id is inserted into
486  // the in_progress member before checking that this call
487  // succeeded. Normally, ids are removed via JEventSource::FreeEvent
488  // but this last one doesn't actually exist so we must remove
489  // it here.
490  // n.b. we check for an entry equal to Ncalls_to_GetEvent
491  // since that is what JEventSource::GetEvent stores there.
492  // In principle, if this ever gets fixed in JANA then it
493  // will not break this code.
494  pthread_mutex_lock(&in_progress_mutex);
495  auto it = in_progess_events.find(Ncalls_to_GetEvent);
496  if( it != in_progess_events.end() )in_progess_events.erase(it);
497  pthread_mutex_unlock(&in_progress_mutex);
498  return NO_MORE_EVENTS_IN_SOURCE;
499  }
501  PARSED_EVENTS_CV.wait_for(lck,std::chrono::milliseconds(1));
502  }
503 
504  DParsedEvent *pe = parsed_events.front();
505  parsed_events.pop_front();
506 
507  // Release mutex and notify workers they can use it again
508  lck.unlock();
509  PARSED_EVENTS_CV.notify_all();
510 
511  // If this is a BOR event, then take ownership of
512  // the DBORptrs object. If not, then copy a pointer
513  // to the latest DBORptrs object into the event.
514  if(pe->borptrs) borptrs_list.push_front(pe->borptrs);
515 
516  // Copy info for this parsed event into the JEvent
517  event.SetJEventSource(this);
518  event.SetEventNumber(pe->event_number);
519  event.SetRunNumber(USER_RUN_NUMBER>0 ? USER_RUN_NUMBER:pe->run_number);
520  event.SetRef(pe);
521 
522  // Set event status bits
523  event.SetStatus(pe->event_status_bits);
524  event.SetStatusBit(kSTATUS_EVIO);
525  if( source_type == kFileSource ) event.SetStatusBit(kSTATUS_FROM_FILE);
526  if( source_type == kETSource ) event.SetStatusBit(kSTATUS_FROM_ET);
527 
528  // EPICS and BOR events are barrier events
529  if(event.GetStatusBit(kSTATUS_EPICS_EVENT)) event.SetSequential();
530  if(event.GetStatusBit(kSTATUS_BOR_EVENT )) event.SetSequential();
531 
532  // Only add BOR events to physics events
533  if(pe->borptrs==NULL)
534  if(!borptrs_list.empty()) pe->borptrs = borptrs_list.front();
535 
536  return NOERROR;
537 }
538 
539 //----------------
540 // FreeEvent
541 //----------------
543 {
544  // CAUTION: This is called by the EventBufferThread in JANA which
545  // effectively serializes everything done here. (Don't delete all
546  // objects in pe which can be slow.)
547  DParsedEvent *pe = (DParsedEvent*)event.GetRef();
548  pe->in_use = false; // return pe to pool
549 
551 }
552 
553 //----------------
554 // GetObjects
555 //----------------
556 jerror_t JEventSource_EVIOpp::GetObjects(JEvent &event, JFactory_base *factory)
557 {
558  // This callback is called to extract objects of a specific type from
559  // an event and store them in the factory pointed to by JFactory_base.
560  // The data type desired can be obtained via factory->GetDataClassName()
561  // and the tag via factory->Tag().
562  //
563  // If the object is not one of a type this source can provide, then
564  // it should return OBJECT_NOT_AVAILABLE. Otherwise, it should return
565  // NOERROR;
566 
567  // When first called, the data objects will still be in the DParsedEvent
568  // object and not yet copied into their respective factories. This will
569  // do that copy of the pointers and set the "copied_to_factories" flag
570  // in DParsedEvent indicating this has been done. It will then check the
571  // name of the class being requested and return the appropriate value
572  // depending on whether we supply that class or not.
573 
574  // We must have a factory to hold the data
575  if(!factory)throw RESOURCE_UNAVAILABLE;
576 
577  // Get name of data class we're trying to extract and the factory tag
578  string dataClassName = factory->GetDataClassName();
579  string tag = factory->Tag();
580  if(tag.length()!=0) return OBJECT_NOT_AVAILABLE; // can't provide tagged factory objects
581 
582  // Get any translation tables we'll need to apply
583  JEventLoop *loop = event.GetJEventLoop();
584  vector<const DTranslationTable*> translationTables;
586  DTranslationTable_factory *ttfac = static_cast<DTranslationTable_factory*>(loop->GetFactory("DTranslationTable"));
587  if(ttfac) ttfac->Get(translationTables);
588  }
589 
590  // Copy pointers to all hits to appropriate factories.
591  // Link BORconfig objects and apply translation tables if appropriate.
592  DParsedEvent *pe = (DParsedEvent*)event.GetRef();
593  if(!pe->copied_to_factories){
594 
595  // Optionally link BOR object associations
597 
598  // Optionally emulate flash firmware
599  if(!pe->vDf250WindowRawData.empty()) EmulateDf250Firmware(pe);
600  if(!pe->vDf125WindowRawData.empty()) EmulateDf125Firmware(pe);
601 
602  // Copy all low-level hits to appropriate factories
603  pe->CopyToFactories(loop);
604 
605  // Apply translation tables to create DigiHit objects
606  for(auto tt : translationTables){
607  tt->ApplyTranslationTable(loop);
608  }
609  }
610 
611  // Optionally record call stack
612  if(RECORD_CALL_STACK) AddToCallStack(pe, loop);
613 
614  // Decide whether this is a data type the source supplies
615  // If the data type is that of some derived data that is nominally
616  // supplied by another factory, but is being stored in EVIO format
617  // for some special reason (e.g. calibration skims), then we
618  // say that we supply this data ONLY IF we actually have data
619  // of this type. Otherwise, we feign ignorance so that the
620  // data is produced by its usual factory
621  bool isSuppliedType = pe->IsParsedDataType(dataClassName)
622  && pe->IsNonEmptyDerivedDataType(dataClassName);
623  for(auto tt : translationTables){
624  if(isSuppliedType) break; // once this is set, it's set
625  isSuppliedType = tt->IsSuppliedType(dataClassName);
626  }
627 
628  // Check if this is a class we provide and return appropriate value
629  if( isSuppliedType ){
630  // We do produce this type
631  return NOERROR;
632  }else{
633  // We do not produce this type
634  return OBJECT_NOT_AVAILABLE;
635  }
636 }
637 
638 //----------------
639 // LinkBORassociations
640 //----------------
642 {
643  /// Add BORConfig objects as associated objects
644  /// to selected hit objects. Most other object associations
645  /// are made in DEVIOWorkerThread::LinkAllAssociations. The
646  /// BORConfig objects however, are not available when that
647  /// is called.
648  /// This is called from GetObjects() which is called from
649  /// one of the processing threads.
650 
651  // n.b. the values of nsamples_integral and nsamples_pedestal
652  // in the Df250PulseData objects that were copied from the
653  // config objcts will be overwritten here with values from
654  // the BOR record (if available). f125 and older f250 data
655  // doesn't do this because nped is not available there.
656  //
657  // n.b. all of the BORConfig object vectors will already
658  // be sorted by rocid, then slot when the data was parsed.
659  // The other hit objects are also already sorted (in
660  // DEVIOWorkerThread::LinkAllAssociations).
661 
662  DBORptrs *borptrs = pe->borptrs;
663 
664  LinkModule(borptrs->vDf250BORConfig, pe->vDf250WindowRawData);
665  LinkModule(borptrs->vDf250BORConfig, pe->vDf250PulseIntegral);
666  LinkModuleBORSamplesCopy(borptrs->vDf250BORConfig, pe->vDf250PulseData);
667 
668  LinkModule(borptrs->vDf125BORConfig, pe->vDf125WindowRawData);
669  LinkModule(borptrs->vDf125BORConfig, pe->vDf125PulseIntegral);
670  LinkModule(borptrs->vDf125BORConfig, pe->vDf125CDCPulse);
671  LinkModule(borptrs->vDf125BORConfig, pe->vDf125FDCPulse);
672 
673  LinkModule(borptrs->vDF1TDCBORConfig, pe->vDF1TDCHit);
674 
675  LinkModule(borptrs->vDCAEN1290TDCBORConfig, pe->vDCAEN1290TDCHit);
676 
677 }
678 
679 ////----------------
680 //// Cleanup
681 ////----------------
682 //void JEventSource_EVIOpp::Cleanup(void)
683 //{
684 // /// This is called internally by the JEventSource_EVIO class
685 // /// once all events have been read in. Its purpose is to
686 // /// free the hidden memory in all of the container class
687 // /// members of the JEventSource_EVIO class. This is needed
688 // /// for jobs that process a lot of input files and therefore
689 // /// create a lot JEventSource_EVIO objects. JANA does not delete
690 // /// these objects until the end of the job so this tends to
691 // /// act like a memory leak. The data used can be substantial
692 // /// (nearly 1GB per JEventSource_EVIO object).
693 //
694 // if(hdevio) delete hdevio;
695 // hdevio = NULL;
696 //
697 // if(hdet) delete hdet;
698 // hdet = NULL;
699 //
700 //}
701 
702 //----------------
703 // SearchFileForRunNumber
704 //----------------
706 {
707  /// This is called from the constructor when reading
708  /// from a file to seed the default run number. This
709  /// is needed because the first event is probably a BOR
710  /// event which does not contain the run number. The run
711  /// number would then be reported as "0" and incorrect
712  /// calibrations and field maps would be read in. This
713  /// will try searching past the first (BOR) event for
714  /// either a physics event, or an EPICS event that has
715  /// the run number defined in it.
716  ///
717  /// The value returned from this will be copied into each
718  /// DEVIOWorkerThread object when it is created. It will
719  /// be used to initialize the run number for each event
720  /// the worker thread processes. If the worker thread
721  /// processes a physics event containing a run number,
722  /// then that will overwrite the run number in the
723  /// DParsedEvent. Finally, if the user specified a run
724  /// number, then that will be reported to JANA in lieu of
725  /// the one in DParsedEvent.
726 
727  if(VERBOSE>2) evioout << " In JEventSource_EVIOpp::SearchFileForRunNumber() source_name=" << source_name << " ..." << endl;
728 
729  uint32_t buff_len = 4000000;
730  uint32_t *buff = new uint32_t[buff_len];
731  HDEVIO *hdevio = new HDEVIO(source_name, false, VERBOSE);
732  while(hdevio->readNoFileBuff(buff, buff_len)){
733 
734  // Assume first word is number of words in bank
735  uint32_t *iptr = buff;
736  uint32_t *iend = &iptr[*iptr - 1];
737  if(VERBOSE>2) evioout << "Checking event with header= 0x" << hex << iptr[1] << dec << endl;
738  if(*iptr > 2048) iend = &iptr[2048]; // only search the first 2kB of each event
739  bool has_timestamps = false;
740  while(iptr<iend){
741  iptr++;
742 
743  // EPICS event
744  if( (*iptr & 0xff000f) == 0x600001){
745  if(VERBOSE>2) evioout << " Found EPICS header. Looking for HD:coda:daq:run_number ..." << endl;
746  const char *cptr = (const char*)&iptr[1];
747  const char *cend = (const char*)iend;
748  const char *needle = "HD:coda:daq:run_number=";
749  while(cptr<cend){
750  if(VERBOSE>4) evioout << " \""<<cptr<<"\"" << endl;
751  if(!strncmp(cptr, needle, strlen(needle))){
752  if(VERBOSE>2) evioout << " Found it!" << endl;
753  uint64_t run_number_seed = atoi(&cptr[strlen(needle)]);
754  if(hdevio) delete hdevio;
755  if(buff) delete[] buff;
756  return run_number_seed;
757  }
758  cptr+=4; // should only start on 4-byte boundary!
759  }
760  }
761 
762  // BOR event from CODA ER
763  if( (*iptr & 0xffffffff) == 0x00700E01) continue;
764 
765  // BOR event from CDAQ ER
766  if( (*iptr & 0xffffffff) == 0x00700e34){
767  iptr++;
768  uint32_t crate_len = iptr[0];
769  uint32_t crate_header = iptr[1];
770  uint32_t *iend_crate = &iptr[crate_len];
771 
772  // Make sure crate tag is right
773  if( (crate_header>>16) == 0x71 ){
774 
775  // Loop over modules
776  iptr += 2;
777  while(iptr<iend_crate){
778  uint32_t module_header = *iptr++;
779  uint32_t module_len = module_header&0xFFFF;
780  uint32_t modType = (module_header>>20)&0x1f;
781 
782  if( modType == DModuleType::CDAQTSG){
783  uint64_t run_number_seed = iptr[0];
784  if(hdevio) delete hdevio;
785  if(buff) delete[] buff;
786  return run_number_seed;
787  }
788  iptr = &iptr[module_len];
789  }
790  iptr = iend_crate; // ensure we're pointing past this crate
791  }
792 
793  continue; // didn't find it in this CDAQ BOR. Keep looking
794  }
795 
796  // PHYSICS event
797  bool not_in_this_buffer = false;
798  switch((*iptr)>>16){
799  case 0xFF10:
800  case 0xFF11:
801  case 0xFF20:
802  case 0xFF21:
803  case 0xFF24:
804  case 0xFF25:
805  case 0xFF30:
806  not_in_this_buffer = true;
807  break;
808  case 0xFF23:
809  case 0xFF27:
810  has_timestamps = true;
811  case 0xFF22:
812  case 0xFF26:
813  break;
814  default:
815  continue;
816  }
817 
818  if(not_in_this_buffer) break; // go to next EVIO buffer
819 
820  iptr++;
821  if( ((*iptr)&0x00FF0000) != 0x000A0000) { iptr--; continue; }
822  uint32_t M = iptr[-3] & 0x000000FF; // Number of events from Physics Event header
823  if(VERBOSE>2) evioout << " ...(epic quest) Trigger bank " << (has_timestamps ? "does":"doesn't") << " have timestamps. Nevents in block M=" << M <<endl;
824  iptr++;
825  uint64_t *iptr64 = (uint64_t*)iptr;
826 
827  uint64_t event_num = *iptr64;
828  if(VERBOSE>3) evioout << " ....(epic quest) Event num: " << event_num <<endl;
829  iptr64++;
830  if(has_timestamps) iptr64 = &iptr64[M]; // advance past timestamps
831 
832  uint64_t run_number_seed = (*iptr64)>>32;
833  if(VERBOSE>1) evioout << " .. (epic quest) Found run number: " << run_number_seed <<endl;
834 
835  if(hdevio) delete hdevio;
836  if(buff) delete[] buff;
837  return run_number_seed;
838 
839  } // while(iptr<iend)
840 
841  if(hdevio->Nevents > 500){
842  if(VERBOSE>2) evioout << " more than 500 events checked and no run number seen! abondoning search" << endl;
843  break;
844  }
845 
846  } // while(hdevio->read(buff, buff_len))
847 
848  if(hdevio->err_code != HDEVIO::HDEVIO_OK) evioout << hdevio->err_mess.str() << endl;
849 
850  if(hdevio) delete hdevio;
851  if(buff) delete[] buff;
852 
853  if(VERBOSE>2) evioout << " failed to find run number. Returning 0" << endl;
854 
855  return 0;
856 }
857 
858 //----------------
859 // EmulateDf250Firmware
860 //----------------
862 {
863  /// This is called from GetObjects, but only if window raw
864  /// data objects exist. It will emulate the firmware, producing
865  /// hit objects from the sample data.
866  ///
867  /// There are some complications here worth noting regarding the
868  /// behavior of the firmware used for Spring 2016 and earlier
869  /// data. The firmware will actually look for a pulse in the
870  /// window and if found, emit pulse time and pulse pedestal
871  /// words for it. It will NOT emit a pulse integral word. Further,
872  /// it will produce those words for at most one pulse. If running
873  /// in mode 7 however, (i.e. no window raw data) it will produce
874  /// multiple pulses. Thus, to mimic the behavior of mode 7, the
875  /// emulator will produce multiple pulses.
876  ///
877  /// The exact behavior of this is determined by the F250_EMULATION_MODE
878  /// parameter which may be one of 3 values. The default is
879  /// kEmulationAuto which does the following:
880  /// 1. Produce hit objects for all pulses found in window
881  /// 2. If pulse time and pedestal objects exist from firmware
882  /// then copy the first found hit into the "*_emulated"
883  /// fields of those existing objects and discard the emulated
884  /// hit.
885  /// 3. Add the remaining emulated hits to the event.
886  ///
887  /// The end result is that the first pulse time and pulse pedestal
888  /// objects may contain some combination of emulated and firmware
889  /// generated information. All pulse integral objects will be
890  /// emulated. It may also be worth noting that this is done in such
891  /// a way that the data may contain a mixture of mode 8 data
892  /// from some boards and mode 7 from others. It will not affect
893  /// those boards producing mode 7 (e.g. won't delete their hits
894  /// even if F250_EMULATION_MODE is set to kEmulationAlways).
895 
896  if(F250_EMULATION_MODE == kEmulationNone) return;
897 
898  // The output data format of the firmware versions is different
899  // so we handle their emulation separately...
900  if(F250_EMULATION_VERSION == 1) { // pre-Fall 2016
901 
902  for(auto wrd : pe->vDf250WindowRawData){
903  const Df250PulseTime *cf250PulseTime = NULL;
904  const Df250PulsePedestal *cf250PulsePedestal = NULL;
905 
906  try{ wrd->GetSingle(cf250PulseTime); }catch(...){}
907  try{ wrd->GetSingle(cf250PulsePedestal); }catch(...){}
908 
909  Df250PulseTime *f250PulseTime = (Df250PulseTime* )cf250PulseTime;
910  Df250PulsePedestal *f250PulsePedestal = (Df250PulsePedestal*)cf250PulsePedestal;
911 
912  // Emulate firmware
913  vector<Df250PulseTime*> em_pts;
914  vector<Df250PulsePedestal*> em_pps;
915  vector<Df250PulseIntegral*> em_pis;
916  f250Emulator->EmulateFirmware(wrd, em_pts, em_pps, em_pis);
917 
918  // Spring 2016 and earlier data may have one pulse time and
919  // one pedestal object in mode 8 data. Emulation mimics mode
920  // 7 which may have more. If there are firmware generated
921  // pulse time/pedestal objects, copy the first emulated hit's
922  // info into them and then the rest of the emulated hits into
923  // appropriate lists.
924  if(!em_pts.empty() && f250PulseTime){
925  Df250PulseTime *em_pt = em_pts[0];
926  f250PulseTime->time_emulated = em_pt->time_emulated;
927  f250PulseTime->quality_factor_emulated = em_pt->quality_factor_emulated;
929  f250PulseTime->time = em_pt->time;
930  f250PulseTime->quality_factor = em_pt->quality_factor;
931  f250PulseTime->emulated = true;
932  }
933  delete em_pt;
934  em_pts.erase(em_pts.begin());
935  }
936 
937  if(!em_pps.empty() && f250PulsePedestal){
938  Df250PulsePedestal *em_pp = em_pps[0];
939  f250PulsePedestal->pedestal_emulated = em_pp->pedestal_emulated;
940  f250PulsePedestal->pulse_peak_emulated = em_pp->pulse_peak_emulated;
942  f250PulsePedestal->pedestal = em_pp->pedestal_emulated;
943  f250PulsePedestal->pulse_peak = em_pp->pulse_peak_emulated;
944  f250PulsePedestal->emulated = true;
945  }
946  delete em_pp;
947  em_pps.erase(em_pps.begin());
948  }
949 
950  pe->vDf250PulseTime.insert(pe->vDf250PulseTime.end(), em_pts.begin(), em_pts.end());
951  pe->vDf250PulsePedestal.insert(pe->vDf250PulsePedestal.end(), em_pps.begin(), em_pps.end());
952  pe->vDf250PulseIntegral.insert(pe->vDf250PulseIntegral.end(), em_pis.begin(), em_pis.end());
953  }
954 
955  } else if(F250_EMULATION_VERSION == 2) { // Fall 2016 -> ?
956 
957  for(auto wrd : pe->vDf250WindowRawData){
958  // See if we need to remake Df250PulseData objects?
959  vector<const Df250PulseData*> cpdats; // existing pulse data objects
960  try{ wrd->Get(cpdats); }catch(...){}
961 
962  vector<Df250PulseData*> pdats;
963  for(auto cpdat : cpdats)
964  pdats.push_back((Df250PulseData*)cpdat);
965 
966  // Sort the pulses since we apparently don't always get them in the right order
967  sort(pdats.begin(), pdats.end(), sortf250pulsenumbers);
968 
969  // Flag all objects as emulated and their values will be replaced with emulated quantities
971  for(auto pdat : pdats)
972  pdat->emulated = 1;
973  }
974 
975  // Emulate firmware
976  f250Emulator->EmulateFirmware(wrd, pdats);
977 
978  // Above call overwrites values with emulated values, but may also
979  // find additional pulses. Add any extra pulse data objects found
980  // to end of list
981  for(uint32_t i=cpdats.size(); i<pdats.size(); i++){
982  pe->vDf250PulseData.push_back(pdats[i]);
983  }
984  }
985 
986  } else if(F250_EMULATION_VERSION == 3) { // Fall 2019 -> ?
987 
988  for(auto wrd : pe->vDf250WindowRawData){
989  // See if we need to remake Df250PulseData objects?
990  vector<const Df250PulseData*> cpdats; // existing pulse data objects
991  try{ wrd->Get(cpdats); }catch(...){}
992 
993  vector<Df250PulseData*> pdats;
994  for(auto cpdat : cpdats)
995  pdats.push_back((Df250PulseData*)cpdat);
996 
997  // Sort the pulses since we apparently don't always get them in the right order
998  sort(pdats.begin(), pdats.end(), sortf250pulsenumbers);
999 
1000  // Flag all objects as emulated and their values will be replaced with emulated quantities
1002  for(auto pdat : pdats)
1003  pdat->emulated = 1;
1004  }
1005 
1006  // Emulate firmware
1007  f250Emulator->EmulateFirmware(wrd, pdats);
1008 
1009  // Above call overwrites values with emulated values, but may also
1010  // find additional pulses. Add any extra pulse data objects found
1011  // to end of list
1012  for(uint32_t i=cpdats.size(); i<pdats.size(); i++){
1013  pe->vDf250PulseData.push_back(pdats[i]);
1014  }
1015  }
1016 
1017  } else {
1018  stringstream ss;
1019  ss << "Invalid fADC250 firmware version specified: " << F250_EMULATION_VERSION;
1020  throw JException(ss.str());
1021  }
1022 
1023  // One last bit of nastiness here. Because the emulator creates
1024  // new objects rather than pulling them from the DParsedEvent pools,
1025  // the pools will tend to get filled with them. Delete any pool
1026  // objects for the types the emulator creates to prevent memory-
1027  // leak-like behavior.
1028  for(auto p : pe->vDf250PulseTime_pool ) delete p;
1029  for(auto p : pe->vDf250PulsePedestal_pool) delete p;
1030  for(auto p : pe->vDf250PulseIntegral_pool) delete p;
1031  pe->vDf250PulseTime_pool.clear();
1032  pe->vDf250PulsePedestal_pool.clear();
1033  pe->vDf250PulseIntegral_pool.clear();
1034 
1035 }
1036 
1037 //----------------
1038 // EmulateDf125Firmware
1039 //----------------
1041 {
1042  /// This is called from GetObjects, but only if window raw
1043  /// data objects exist. It will emulate the firmware, producing
1044  /// hit objects from the sample data.
1045 
1046  if(F125_EMULATION_MODE == kEmulationNone) return;
1047 
1048  for(auto wrd : pe->vDf125WindowRawData){
1049  const Df125CDCPulse *cf125CDCPulse = NULL;
1050  const Df125FDCPulse *cf125FDCPulse = NULL;
1051 
1052  try{ wrd->GetSingle(cf125CDCPulse); }catch(...){}
1053  try{ wrd->GetSingle(cf125FDCPulse); }catch(...){}
1054 
1055  Df125CDCPulse *f125CDCPulse = (Df125CDCPulse*)cf125CDCPulse;
1056  Df125FDCPulse *f125FDCPulse = (Df125FDCPulse*)cf125FDCPulse;
1057 
1058  // If the the pulse objects do not exist, create new ones to go with our raw data
1059  // This should rarely happen since CDC_long and FDC_long mores have the raw data
1060  // along with the calculated quantities in a pulse word. Pure raw mode would be the only time
1061  // when this would not be the case.
1062  // Since this is so infrequently used (if ever),
1063  // we add a hard coded ROCID check for CDC/FDC determination...
1064  // ROCID CDC: 25-28
1065  // ROCID FDC Cathode: 52,53,55-62
1066 
1067  if(f125CDCPulse == NULL && ( wrd->rocid < 30 ) ){
1068  f125CDCPulse = pe->NEW_Df125CDCPulse();
1069  f125CDCPulse->rocid = wrd->rocid;
1070  f125CDCPulse->slot = wrd->slot;
1071  f125CDCPulse->channel = wrd->channel;
1072  f125CDCPulse->emulated = true;
1073  f125CDCPulse->AddAssociatedObject(wrd);
1074  }
1075  else if(f125FDCPulse == NULL && ( wrd->rocid > 30 ) ){
1076  f125FDCPulse = pe->NEW_Df125FDCPulse();
1077  f125FDCPulse->rocid = wrd->rocid;
1078  f125FDCPulse->slot = wrd->slot;
1079  f125FDCPulse->channel = wrd->channel;
1080  f125FDCPulse->emulated = true;
1081  f125FDCPulse->AddAssociatedObject(wrd);
1082  }
1083 
1084  // Flag all objects as emulated and their values will be replaced with emulated quantities
1086  if(f125CDCPulse!=NULL) f125CDCPulse->emulated = 1;
1087  if(f125FDCPulse!=NULL) f125FDCPulse->emulated = 1;
1088  }
1089 
1090  // Perform the emulation
1091  f125Emulator->EmulateFirmware(wrd, f125CDCPulse, f125FDCPulse);
1092  }
1093 }
1094 
1095 //----------------
1096 // AddToCallStack
1097 //----------------
1099 {
1100  /// Add information to JANA's call stack so that the janadot
1101  /// plugin can better display the actual relationship of the
1102  /// the data objects. This only gets called if the RECORD_CALL_STACK
1103  /// config. parameter is set (which is done automatically by
1104  /// the janadot plugin)
1105 
1106  // Add all source object types as defined in DParsedEvent
1107  vector<string> sourcetypes;
1108  pe->GetParsedDataTypes(sourcetypes);
1109  for(auto t:sourcetypes) AddSourceObjectsToCallStack(loop, t);
1110 }
1111 
1112 //----------------
1113 // AddSourceObjectsToCallStack
1114 //----------------
1115 void JEventSource_EVIOpp::AddSourceObjectsToCallStack(JEventLoop *loop, string className)
1116 {
1117  /// This is used to give information to JANA regarding the origin of objects
1118  /// that *should* come from the source. We add them in explicitly because
1119  /// the file may not have any, but factories may ask for them. We want those
1120  /// links to indicate that the "0" objects in the factory came from the source
1121  /// so that janadot draws these objects correctly.
1122 
1123  JEventLoop::call_stack_t cs;
1124  cs.caller_name = "<ignore>"; // tells janadot this object wasn't actually requested by anybody
1125  cs.caller_tag = "";
1126  cs.callee_name = className;
1127  cs.callee_tag = "";
1128  cs.start_time = 0.0;
1129  cs.end_time = 0.0;
1130  cs.data_source = JEventLoop::DATA_FROM_SOURCE;
1131  loop->AddToCallStack(cs);
1132 }
1133 
1134 //----------------
1135 // AddEmulatedObjectsToCallStack
1136 //----------------
1137 void JEventSource_EVIOpp::AddEmulatedObjectsToCallStack(JEventLoop *loop, string caller, string callee)
1138 {
1139  /// This is used to give information to JANA regarding the relationship and
1140  /// origin of some of these data objects. This is really just needed so that
1141  /// the janadot program can be used to produce the correct callgraph. Because
1142  /// of how this plugin works, JANA can't record the correct call stack (at
1143  /// least not easily!) Therefore, we have to give it a little help here.
1144 
1145  JEventLoop::call_stack_t cs;
1146  cs.caller_name = caller;
1147  cs.callee_name = callee;
1148  cs.data_source = JEventLoop::DATA_FROM_SOURCE;
1149  loop->AddToCallStack(cs);
1150  cs.callee_name = cs.caller_name;
1151  cs.caller_name = "<ignore>";
1152  cs.data_source = JEventLoop::DATA_FROM_FACTORY;
1153  loop->AddToCallStack(cs);
1154 }
uint32_t pedestal_emulated
Calculated from raw data (when available)
jerror_t GetObjects(jana::JEvent &event, jana::JFactory_base *factory)
bool sortf250pulsenumbers(const Df250PulseData *a, const Df250PulseData *b)
bool IsParsedDataType(string &classname) const
Definition: DParsedEvent.h:270
uint32_t err_code
Definition: HDEVIO.h:192
Df125EmulatorAlgorithm * f125Emulator
virtual void EmulateFirmware(const Df250WindowRawData *wrd, std::vector< Df250PulseTime * > &pt_objs, std::vector< Df250PulsePedestal * > &pp_objs, std::vector< Df250PulseIntegral * > &pi_objs)=0
void AddToCallStack(DParsedEvent *pe, JEventLoop *loop)
virtual const char * className(void)
atomic< bool > in_use
streampos last_event_pos
Definition: HDEVIO.h:183
void GetParsedDataTypes(vector< string > &classnames, bool include_all=false) const
Definition: DParsedEvent.h:289
void LinkBORassociations(DParsedEvent *pe)
sprintf(text,"Post KinFit Cut")
#define c
bool is_open
Definition: HDEVIO.h:166
uint64_t event_status_bits
Definition: DParsedEvent.h:144
int event_num
set< uint32_t > ROCIDS_TO_PARSE
void rewind(void)
Definition: HDEVIO.cc:655
std::atomic< uint_fast64_t > NEVENTBUFF_STALLED
virtual void EmulateFirmware(const Df125WindowRawData *, Df125CDCPulse *, Df125FDCPulse *)=0
uint64_t SearchFileForRunNumber(void)
uint32_t pulse_peak
from Pulse Pedestal Data word
bool emulated
true if made from Window Raw Data
JApplication * japp
bool copied_to_factories
Definition: DParsedEvent.h:138
vector< DEVIOWorkerThread * > worker_threads
uint32_t err_code
Definition: HDET.h:51
uint32_t quality_factor_emulated
Calculated from raw data if available.
stringstream err_mess
Definition: HDEVIO.h:191
void PrintStats(void)
Definition: HDET.cc:454
JEventSource_EVIOpp(const char *source_name)
uint32_t last_event_len
Definition: HDEVIO.h:184
list< DParsedEvent * > parsed_events
int VERBOSE
Definition: HDET.h:67
bool swap_needed
Definition: HDET.h:68
list< DBORptrs * > borptrs_list
Definition: HDEVIO.h:45
bool readNoFileBuff(uint32_t *user_buff, uint32_t user_buff_len, bool allow_swap=true)
Definition: HDEVIO.cc:499
uint32_t quality_factor
from Pulse Time Data word
bool is_connected
Definition: HDET.h:49
stringstream err_mess
Definition: HDET.h:50
bool IsNonEmptyDerivedDataType(string &classname) const
Definition: DParsedEvent.h:281
uint64_t GetNWordsLeftInFile(void)
Definition: HDEVIO.cc:681
bool emulated
true if emulated values are copied to the main input
Definition: Df125FDCPulse.h:78
void PrintStats(void)
Definition: HDEVIO.cc:1221
void FreeEvent(jana::JEvent &event)
DBORptrs * borptrs
Definition: DParsedEvent.h:147
uint32_t time
from Pulse Time Data word
uint64_t event_number
Definition: DParsedEvent.h:143
void EmulateDf125Firmware(DParsedEvent *pe)
uint32_t time_emulated
Calculated from raw data if available.
Df250EmulatorAlgorithm * f250Emulator
bool emulated
true if made from Window Raw Data
EVIOSourceType source_type
atomic< bool > in_use
Definition: DParsedEvent.h:135
uint32_t channel
Definition: DDAQAddress.h:34
uint64_t run_number
Definition: DParsedEvent.h:142
static void SetStatusBitDescriptions(jana::JApplication *japp)
Definition: DStatusBits.h:60
uint32_t pulse_peak_emulated
Calculated from raw data (when available)
uint32_t rocid
Definition: DDAQAddress.h:32
bool IGNORE_EMPTY_BOR
Definition: HDEVIO.h:188
uint32_t pedestal
from Pulse Pedestal Data word
bool swap_needed
Definition: HDEVIO.h:181
void CopyToFactories(JEventLoop *loop)
Definition: DParsedEvent.h:247
std::chrono::high_resolution_clock::time_point tend
void EmulateDf250Firmware(DParsedEvent *pe)
bool read(uint32_t *&buff, uint32_t &buff_len, bool allow_swap)
Definition: HDET.cc:223
jerror_t GetEvent(jana::JEvent &event)
static void SetSystemsToParse(string systems, JEventSource *eventsource)
Definition: HDET.h:25
bool emulated
true if emulated values are copied to the main input
Definition: Df125CDCPulse.h:73
std::chrono::high_resolution_clock::time_point tstart
std::atomic< uint_fast64_t > NPARSER_STALLED
void AddSourceObjectsToCallStack(JEventLoop *loop, string className)
uint64_t Nevents
Definition: HDEVIO.h:195
void AddEmulatedObjectsToCallStack(JEventLoop *loop, string caller, string callee)
uint32_t pulse_number
pulse number for this channel, this event starting from 0
condition_variable PARSED_EVENTS_CV
condition_variable cv
uint64_t MAX_OBJECT_RECYCLES
std::atomic< uint_fast64_t > NDISPATCHER_STALLED
uint32_t slot
Definition: DDAQAddress.h:33
std::atomic< uint_fast64_t > NEVENTS_PROCESSED