Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
JEventSource_EVIOpp.h
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: JEventSource_EVIOpp.h
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 #ifndef _JEventSource_EVIOpp_
9 #define _JEventSource_EVIOpp_
10 
11 #include <atomic>
12 #include <chrono>
13 #include <cinttypes>
14 
15 #include <JANA/jerror.h>
16 #include <JANA/JApplication.h>
17 #include <JANA/JEventSource.h>
18 #include <JANA/JEvent.h>
19 #include <JANA/JFactory.h>
20 #include <JANA/JStreamLog.h>
21 
22 #include <DAQ/HDEVIO.h>
23 #include <DAQ/HDET.h>
24 #include <DAQ/DEVIOWorkerThread.h>
25 #include <DAQ/DParsedEvent.h>
26 #include <DAQ/DBORptrs.h>
29 
30 #include <DANA/DStatusBits.h>
31 
32 /// How this Event Source Works
33 /// ===================================================================
34 ///
35 /// Overview
36 /// -------------------
37 /// This event source represents a complete rewrite of the original
38 /// JEventSource_EVIO class. It is highly optimized and while it
39 /// gets rid of some of the complexities that developed in the
40 /// original over time, in some ways it replaced them with complexities
41 /// of its own.
42 ///
43 /// In a nut shell, this source launches a minimum of 2 dedicated
44 /// threads for reading in and parsing the events. These are in
45 /// addition to any threads the JANA framework creates. There is
46 /// a single "dispatcher" thread that reads in the events and
47 /// assigns them to one of a group of "worker" threads.
48 ///
49 /// JANA itself has a similar structure in that there is a single
50 /// "EventBufferThread" that grabs fully parsed events from this
51 /// class via its GetEvent method, and then hands them to one of
52 /// a group of "processing" threads where the actual analysis begins.
53 ///
54 /// One benefit of this design is that it allows certain objects,
55 /// methods, or member data to be modified by only a single thread
56 /// throughout its life. This avoids the use of locks which introduce
57 /// inefficiency in a multi-threaded application.
58 ///
59 ///
60 /// BORconfig objects
61 /// --------------------
62 /// Typically, BOR events only occur at the begining of a file and
63 /// a given job will see only one. However, we must support the
64 /// possibility of multiple BOR events in case we are reading from
65 /// an ET system or file of merged events.
66 ///
67 /// BOR objects are applicable to all events in the stream until
68 /// another BOR event is encountered. We therefore need every event
69 /// to get a copy of the BOR config object pointers. Thus, they must be
70 /// kept in a place that all worker threads see. This is the borptrs_list
71 /// object in the JEventSource_EVIOpp class.
72 ///
73 /// Here's the sequence for how the BOR event is handled:
74 /// 1. When a BOR event is parsed it creates a DBORptrs object which
75 /// holds a complete set of BOR objects. The pointer to this
76 /// DBORptrs object is left in the DParsedEvent object which
77 /// would otherwise be NULL.
78 ///
79 /// 2. When JEventSource_EVIOpp::GetEvent() is called, it will see the
80 /// non-NULL borptrs pointer in DParsedEvent. At this point it will
81 /// copy it to the front of borptrs_list, effectively giving ownership
82 /// to JEventSource_EVIOpp. Note that aside from the destructor,
83 /// borptrs_list is only accessed here which is only called from the
84 /// event reader thread. This means we don't have to use a lock.
85 ///
86 /// 3. If the borptrs pointer is NULL, then JEventSource_EVIOpp::GetEvent
87 /// will copy the front pointer from borptrs_list into the
88 /// DParsedEvent. We rely on the events being in istream order here
89 /// to only apply the BORconfig objects to events after the BOR
90 /// event itself.
91 ///
92 /// 4. When GetObjects is called, it calls DParsedEvent::CopyToFactories
93 /// where the BOR objects are copied into the appropriate factories.
94 /// It then calls JEventSource_EVIOpp::LinkBORassociations to add
95 /// the BORConfig objects as associated objects to various hit objects.
96 ///
97 /// 5. Only when the JEventSource_EVIOpp object is destroyed are any
98 /// BORConfig objects deleted. We don't implement a mechansim to
99 /// keep track of which DBORptrs objects are still in use so we can't
100 /// delete them sooner. This shouldn't be a problem though since BOR
101 /// events are rare.
102 ///
103 
104 class JEventSource_EVIOpp: public jana::JEventSource{
105  public:
106 
111  };
112 
117  };
118 
119 
120  JEventSource_EVIOpp(const char* source_name);
121  virtual ~JEventSource_EVIOpp();
122  virtual const char* className(void){return static_className();}
123  static const char* static_className(void){return "JEventSource_EVIOpp";}
124 
125  void Dispatcher(void);
126 
127  jerror_t GetEvent(jana::JEvent &event);
128  void FreeEvent(jana::JEvent &event);
129  jerror_t GetObjects(jana::JEvent &event, jana::JFactory_base *factory);
130 
132  uint64_t SearchFileForRunNumber(void);
135  void AddToCallStack(DParsedEvent *pe, JEventLoop *loop);
136  void AddSourceObjectsToCallStack(JEventLoop *loop, string className);
137  void AddEmulatedObjectsToCallStack(JEventLoop *loop, string caller, string callee);
138  void AddROCIDtoParseList(uint32_t rocid){ ROCIDS_TO_PARSE.insert(rocid); }
139  set<uint32_t> GetROCIDParseList(uint32_t rocid){ return ROCIDS_TO_PARSE; }
140 
141 
142  bool DONE;
144  std::chrono::high_resolution_clock::time_point tstart;
145  std::chrono::high_resolution_clock::time_point tend;
146 
149  condition_variable PARSED_EVENTS_CV;
150  list<DParsedEvent*> parsed_events;
151 
152  std::atomic<uint_fast64_t> NEVENTS_PROCESSED;
153  std::atomic<uint_fast64_t> NDISPATCHER_STALLED;
154  std::atomic<uint_fast64_t> NPARSER_STALLED;
155  std::atomic<uint_fast64_t> NEVENTBUFF_STALLED;
156 
159 
164 
165  vector<DEVIOWorkerThread*> worker_threads;
167 
168  JStreamLog evioout;
169 
170  uint32_t F250_EMULATION_MODE; // (EmulationModeType)
171  uint32_t F125_EMULATION_MODE; // (EmulationModeType)
175 
177  set<uint32_t> ROCIDS_TO_PARSE;
178 
179  list<DBORptrs*> borptrs_list;
180 
181  bool PARSE;
187  bool PARSE_BOR;
191  bool PARSE_SSP;
196  uint32_t USER_RUN_NUMBER;
197  int VERBOSE;
199  float TIMEOUT;
200  uint32_t NTHREADS;
202  bool SWAP;
203  bool LINK;
210 
211  uint32_t jobtype;
212  bool IS_CDAQ_FILE = false;
213 };
214 
215 #endif // _JEventSourceGenerator_EVIOpp_
216 
jerror_t GetObjects(jana::JEvent &event, jana::JFactory_base *factory)
Df125EmulatorAlgorithm * f125Emulator
void AddToCallStack(DParsedEvent *pe, JEventLoop *loop)
virtual const char * className(void)
void LinkBORassociations(DParsedEvent *pe)
set< uint32_t > GetROCIDParseList(uint32_t rocid)
set< uint32_t > ROCIDS_TO_PARSE
std::atomic< uint_fast64_t > NEVENTBUFF_STALLED
uint64_t SearchFileForRunNumber(void)
void AddROCIDtoParseList(uint32_t rocid)
vector< DEVIOWorkerThread * > worker_threads
JEventSource_EVIOpp(const char *source_name)
How this Event Source Works
list< DParsedEvent * > parsed_events
list< DBORptrs * > borptrs_list
Definition: HDEVIO.h:45
void FreeEvent(jana::JEvent &event)
void EmulateDf125Firmware(DParsedEvent *pe)
Df250EmulatorAlgorithm * f250Emulator
EVIOSourceType source_type
std::chrono::high_resolution_clock::time_point tend
void EmulateDf250Firmware(DParsedEvent *pe)
static const char * static_className(void)
jerror_t GetEvent(jana::JEvent &event)
Definition: HDET.h:25
std::chrono::high_resolution_clock::time_point tstart
std::atomic< uint_fast64_t > NPARSER_STALLED
void AddSourceObjectsToCallStack(JEventLoop *loop, string className)
void AddEmulatedObjectsToCallStack(JEventLoop *loop, string caller, string callee)
condition_variable PARSED_EVENTS_CV
std::atomic< uint_fast64_t > NDISPATCHER_STALLED
std::atomic< uint_fast64_t > NEVENTS_PROCESSED