Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:38

0001 
0002 // Copyright 2020, Jefferson Science Associates, LLC.
0003 // Subject to the terms in the LICENSE file found in the top-level directory.
0004 
0005 #pragma once
0006 
0007 #include <JANA/Components/JComponent.h>
0008 #include <JANA/Components/JHasOutputs.h>
0009 #include <JANA/JEvent.h>
0010 #include <JANA/JException.h>
0011 #include <JANA/JFactoryGenerator.h>
0012 
0013 
0014 class JFactoryGenerator;
0015 class JApplication;
0016 class JFactory;
0017 
0018 
0019 class JEventSource : public jana::components::JComponent,
0020                      public jana::components::JHasOutputs {
0021 
0022 public:
0023     /// Result describes what happened the last time a GetEvent() was attempted.
0024     /// If Emit() or GetEvent() reaches an error state, it should throw a JException instead.
0025     enum class Result { Success, FailureTryAgain, FailureFinished };
0026 
0027     /// The user is supposed to _throw_ RETURN_STATUS::kNO_MORE_EVENTS or kBUSY from GetEvent()
0028     enum class RETURN_STATUS { kSUCCESS, kNO_MORE_EVENTS, kBUSY, kTRY_AGAIN, kERROR, kUNKNOWN };
0029 
0030 
0031 private:
0032     std::string m_resource_name;
0033     std::atomic_ullong m_events_emitted {0};
0034     std::atomic_ullong m_events_finished {0};
0035     uint64_t m_nskip = 0;
0036     uint64_t m_nevents = 0;
0037     bool m_enable_finish_event = false;
0038     bool m_enable_get_objects = false;
0039     bool m_enable_preprocess = false;
0040 
0041 
0042 public:
0043     explicit JEventSource(std::string resource_name, JApplication* app = nullptr)
0044         : m_resource_name(std::move(resource_name)) {
0045             m_app = app;
0046         }
0047 
0048     JEventSource() = default;
0049     virtual ~JEventSource() = default;
0050 
0051 
0052     // `Init` is where the user requests parameters and services. If the user requests all parameters and services here,
0053     // JANA can report them back to the user without having to open the resource and run the topology.
0054 
0055     virtual void Init() {}
0056 
0057 
0058     /// `Open` is called by JANA when it is ready to accept events from this event source. The implementor should open
0059     /// file pointers or sockets here, instead of in the constructor. This is because the implementor won't know how many
0060     /// or which event sources the user will decide to activate within one job. Thus the implementor can avoid problems
0061     /// such as running out of file pointers, or multiple event sources attempting to bind to the same socket.
0062 
0063     virtual void Open() {}
0064 
0065 
0066     // `Emit` is called by JANA in order to emit a fresh event into the stream, when using CallbackStyle::ExpertMode. 
0067     // It is very similar to GetEvent(), except the user returns a Result status code instead of throwing an exception.
0068     // Exceptions are reserved for unrecoverable errors. It accepts an out parameter JEvent. If there is another 
0069     // entry in the file, or another message waiting at the socket, the user reads the data into the JEvent and returns
0070     // Result::Success, at which point JANA pushes the JEvent onto the downstream queue. If there is no data waiting yet,
0071     // the user returns Result::FailureTryAgain, at which point JANA recycles the JEvent to the pool. If there is no more
0072     // data, the user returns Result::FailureFinished, at which point JANA recycles the JEvent to the pool and calls Close().
0073 
0074     virtual Result Emit(JEvent&) { return Result::Success; };
0075 
0076 
0077     /// For work that should be done in parallel on a JEvent, but is tightly coupled to the JEventSource for some reason. 
0078     /// Called after Emit() by JEventMapArrow
0079     virtual void Preprocess(const JEvent&) const {};
0080 
0081 
0082     /// `FinishEvent` is used to notify the `JEventSource` that an event has been completely processed. This is the final
0083     /// chance to interact with the `JEvent` before it is either cleared and recycled, or deleted. Although it is
0084     /// possible to use this for freeing JObjects stored in the JEvent , this is strongly discouraged in favor of putting
0085     /// that logic on the destructor, RAII-style. Instead, this callback should be used for updating and freeing state
0086     /// owned by the JEventSource, e.g. raw data which is keyed off of run number and therefore shared among multiple
0087     /// JEvents. `FinishEvent` is also well-suited for use with `EventGroup`s, e.g. to notify someone that a batch of
0088     /// events has finished, or to implement "barrier events".
0089 
0090     virtual void FinishEvent(JEvent&) {};
0091 
0092 
0093     /// `Close` is called by JANA when it is finished accepting events from this event source. Here is where you should
0094     /// cleanly close files, sockets, etc. Although GetEvent() knows when (for instance) there are no more events in a
0095     /// file, the logic for closing needs to live here because there are other ways a computation may end besides
0096     /// running out of events in a file. For instance, the user may want to process a limited number of events using
0097     /// the `jana:nevents` parameter, or they may want to terminate the computation manually using Ctrl-C.
0098 
0099     virtual void Close() {}
0100 
0101 
0102     /// `GetEvent` is called by JANA in order to emit a fresh event into the stream. JANA manages the entire lifetime of
0103     /// the JEvent. The `JEvent` being passed in is empty and merely needs to hydrated as follows:
0104 
0105     ///  1. `SetRunNumber()`
0106     ///  2. `SetEventNumber()`
0107     ///  3. `Insert<T>()` raw data of type `T` into the `JEvent` container. Note that `T` should be a child class, such as
0108     ///     `FADC250DigiHit`, not a parent class such as `JObject` or `TObject`. Also note that `Insert` transfers
0109     ///     ownership of the data to that JEvent. If the data is shared among multiple `JEvents`, e.g. BOR data,
0110     ///     use `SetFactoryFlags(JFactory::NOT_OBJECT_OWNER)`
0111 
0112     /// Note that JEvents are usually recycled. Although all reconstruction data is cleared before `GetEvent` is called,
0113     /// the constituent `JFactories` may retain some state, e.g. statistics, or calibration data keyed off of run number.
0114 
0115     /// If an event cannot be emitted, either because the resource is not ready or because we have reached the end of
0116     /// the event stream, the implementor should throw the corresponding `RETURN_STATUS`. The user should NEVER throw
0117     /// `RETURN_STATUS SUCCESS` because this will hurt performance. Instead, they should simply return normally.
0118 
0119     virtual void GetEvent(std::shared_ptr<JEvent>) {};
0120 
0121 
0122     /// `GetObjects` was historically used for lazily unpacking data from a JEvent and putting it into a "dummy" JFactory.
0123     /// This mechanism has been replaced by `JEvent::Insert`. All lazy evaluation should happen in a (non-dummy)
0124     /// JFactory, whereas eager evaluation should happen in `JEventSource::GetEvent` via `JEvent::Insert`.
0125 
0126     virtual bool GetObjects(const std::shared_ptr<const JEvent>&, JFactory*) {
0127         return false;
0128     }
0129 
0130 
0131     // Getters
0132     
0133     std::string GetResourceName() const { return m_resource_name; }
0134 
0135     [[deprecated]]
0136     uint64_t GetEventCount() const { return m_events_emitted; };
0137     uint64_t GetEmittedEventCount() const { return m_events_emitted; };
0138     uint64_t GetFinishedEventCount() const { return m_events_finished; };
0139 
0140     [[deprecated]]
0141     virtual std::string GetType() const { return m_type_name; }
0142 
0143     [[deprecated]]
0144     std::string GetName() const { return m_resource_name; }
0145 
0146     bool IsGetObjectsEnabled() const { return m_enable_get_objects; }
0147     bool IsFinishEventEnabled() const { return m_enable_finish_event; }
0148     bool IsPreprocessEnabled() const { return m_enable_preprocess; }
0149     
0150     uint64_t GetNSkip() { return m_nskip; }
0151     uint64_t GetNEvents() { return m_nevents; }
0152 
0153     virtual std::string GetVDescription() const {
0154         return "<description unavailable>";
0155     } ///< Optional for getting description via source rather than JEventSourceGenerator
0156 
0157 
0158     // Setters
0159    
0160     void SetResourceName(std::string resource_name) { m_resource_name = resource_name; }
0161 
0162     /// EnableFinishEvent() is intended to be called by the user in the constructor in order to
0163     /// tell JANA to call the provided FinishEvent method after all JEventProcessors
0164     /// have finished with a given event. This should only be enabled when absolutely necessary
0165     /// (e.g. for backwards compatibility) because it introduces contention for the JEventSource mutex,
0166     /// which will hurt performance. Conceptually, FinishEvent isn't great, and so should be avoided when possible.
0167     void EnableFinishEvent(bool enable=true) { m_enable_finish_event = enable; }
0168     void EnableGetObjects(bool enable=true) { m_enable_get_objects = enable; }
0169     void EnablePreprocess(bool enable=true) { m_enable_preprocess = enable; }
0170 
0171     void SetNEvents(uint64_t nevents) { m_nevents = nevents; };
0172     void SetNSkip(uint64_t nskip) { m_nskip = nskip; };
0173 
0174 
0175     // Internal
0176 
0177     [[deprecated("Replaced by JEventSource::DoOpen()")]]
0178     void DoInitialize();
0179     
0180     virtual void DoInit();
0181 
0182     void DoOpen(bool with_lock=true);
0183 
0184     void DoClose(bool with_lock=true);
0185     
0186     Result DoNext(std::shared_ptr<JEvent> event);
0187 
0188     Result DoNextCompatibility(std::shared_ptr<JEvent> event);
0189 
0190     void DoFinishEvent(JEvent& event);
0191 
0192     void Summarize(JComponentSummary& summary) const override;
0193 
0194 
0195 };
0196 
0197