Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-14 09:12:59

0001 
0002 // Copyright 2023, Jefferson Science Associates, LLC.
0003 // Subject to the terms in the LICENSE file found in the top-level directory.
0004 
0005 #include <JANA/JFactory.h>
0006 #include <JANA/JEvent.h>
0007 #include <JANA/JEventSource.h>
0008 #include <JANA/Utils/JTypeInfo.h>
0009 
0010 
0011 class FlagGuard {
0012     bool* m_flag;
0013 public:
0014     FlagGuard(bool* flag) : m_flag(flag) {
0015         *m_flag = true;
0016     }
0017     ~FlagGuard() {
0018         *m_flag = false;
0019     }
0020 };
0021 
0022 void JFactory::Create(const std::shared_ptr<const JEvent>& event) {
0023     Create(*event.get());
0024 }
0025 
0026 void JFactory::Create(const JEvent& event) {
0027 
0028     if (mInsideCreate && (mStatus != Status::Inserted)) {
0029         // Ideally, we disallow any calls to Create() that end up calling it right back. However, we do allow
0030         // calls that go down to GetObjects, who inserts the data, but then RETRIEVES the same data it just inserted,
0031         // so that it can subsequently calculate and insert OTHER data. Once we refactor JEventSourceEVIOpp, we can consider
0032         // removing this weird edge case.
0033         throw JException("Encountered a cycle in the factory dependency graph! Hint: Maybe this data was supposed to be inserted in the JEventSource");
0034     }
0035     FlagGuard insideCreateFlagGuard (&mInsideCreate); // No matter how we exit from Create() (particularly with exceptions) mInsideCreate will be set back to false
0036 
0037     if (m_app == nullptr && event.GetJApplication() != nullptr) {
0038         // These are usually set by JFactoryGeneratorT, but some user code has custom JFactoryGenerators which don't!
0039         // The design of JFactoryGenerator doesn't give us a better place to inject things
0040         m_app = event.GetJApplication();
0041         m_logger = m_app->GetJParameterManager()->GetLogger(GetLoggerName());
0042     }
0043 
0044     if (mStatus == Status::Uninitialized) {
0045         DoInit();
0046     }
0047 
0048     // How do we obtain our data? The priority is as follows:
0049     // 1. JFactory::Process() if REGENERATE flag is set
0050     // 2. JEvent::Insert()
0051     // 3. JEventSource::GetObjects() if source has GetObjects() enabled
0052     // 4. JFactory::Process()
0053 
0054     // ---------------------------------------------------------------------
0055     // 1. JFactory::Process() if REGENERATE flag is set
0056     // ---------------------------------------------------------------------
0057 
0058     if (mRegenerate) {
0059         if (mStatus == Status::Inserted) {
0060             // Status::Inserted indicates that the data came from either src->GetObjects() or evt->Insert()
0061             ClearData(); 
0062             // ClearData() resets mStatus to Unprocessed so that the data will be regenerated exactly once.
0063         }
0064         // After this point, control flow falls through to "4. JFactory::Process"
0065     }
0066     else {
0067 
0068         // ---------------------------------------------------------------------
0069         // 2. JEvent::Insert()
0070         // ---------------------------------------------------------------------
0071 
0072         if (mStatus == Status::Inserted) {
0073             // This may include data cached from eventsource->GetObjects().
0074             // Either way, short-circuit here, because the data is present.
0075             return;
0076         }
0077 
0078         // ---------------------------------------------------------------------
0079         // 3. JEventSource::GetObjects() if source has GetObjects() enabled
0080         // ---------------------------------------------------------------------
0081 
0082         auto src = event.GetJEventSource();
0083         if (src != nullptr && src->IsGetObjectsEnabled()) {
0084             bool found_data = false;
0085 
0086             CallWithJExceptionWrapper("JEventSource::GetObjects", [&](){ 
0087                 found_data = src->GetObjects(event.shared_from_this(), this); });
0088 
0089             if (found_data) {
0090                 mStatus = Status::Inserted;
0091                 mCreationStatus = CreationStatus::InsertedViaGetObjects;
0092                 return;
0093             }
0094         }
0095         // If neither "2. JEvent::Insert()" nor "3. JEventSource::GetObjects()" succeeded, fall through to "4. JFactory::Process()"
0096     }
0097 
0098     // ---------------------------------------------------------------------
0099     // 4. JFactory::Process()
0100     // ---------------------------------------------------------------------
0101 
0102     // If the data was Processed (instead of Inserted), it will be in cache, and we can just exit.
0103     // Otherwise we call Process() to create the data in the first place.
0104     // If we already ran Process() but it excepted, we re-run Process() to trigger the same exception, so that every consumer
0105     // is forced to handle it. Otherwise one "fault-tolerant" consumer will swallow the exception for everybody else.
0106     if (mStatus == Status::Unprocessed || mStatus == Status::Excepted) {
0107         auto run_number = event.GetRunNumber();
0108         if (mPreviousRunNumber != run_number) {
0109             if (m_callback_style == CallbackStyle::LegacyMode) {
0110                 if (mPreviousRunNumber != -1) {
0111                     CallWithJExceptionWrapper("JFactory::EndRun", [&](){ EndRun(); });
0112                 }
0113                 CallWithJExceptionWrapper("JFactory::ChangeRun", [&](){ ChangeRun(event.shared_from_this()); });
0114                 CallWithJExceptionWrapper("JFactory::BeginRun", [&](){ BeginRun(event.shared_from_this()); });
0115             }
0116             else if (m_callback_style == CallbackStyle::DeclarativeMode) {
0117                 CallWithJExceptionWrapper("JFactory::ChangeRun", [&](){ ChangeRun(event.GetRunNumber()); });
0118             }
0119             else if (m_callback_style == CallbackStyle::ExpertMode) {
0120                 CallWithJExceptionWrapper("JFactory::ChangeRun", [&](){ ChangeRun(event); });
0121             }
0122             mPreviousRunNumber = run_number;
0123         }
0124         try {
0125             for (auto* input : GetInputs()) {
0126                 input->Populate(event);
0127             }
0128             for (auto* input : GetVariadicInputs()) {
0129                 input->Populate(event);
0130             }
0131             if (m_callback_style == CallbackStyle::LegacyMode) {
0132                 CallWithJExceptionWrapper("JFactory::Process", [&](){ Process(event.shared_from_this()); });
0133             }
0134             else if (m_callback_style == CallbackStyle::DeclarativeMode) {
0135                 CallWithJExceptionWrapper("JFactory::Process", [&](){ Process(event.GetRunNumber(), event.GetEventNumber()); });
0136             }
0137             else if (m_callback_style == CallbackStyle::ExpertMode) {
0138                 CallWithJExceptionWrapper("JFactory::Process", [&](){ Process(event); });
0139             }
0140             else {
0141                 throw JException("Invalid callback style");
0142             }
0143         }
0144         catch (...) {
0145             // Save everything already created even if we throw an exception
0146             // This is so that we leave everything in a valid state just in case someone tries to catch the exception recover,
0147             // such as EICrecon. (Remember that a missing collection in the podio frame will segfault if anyone tries to write that frame)
0148             // Note that the collections themselves won't know that they exited early
0149 
0150             LOG << "Exception in JFactory::Create, prefix=" << GetPrefix();
0151             mStatus = Status::Excepted;
0152             mCreationStatus = CreationStatus::Created;
0153             for (auto* output : GetOutputs()) {
0154                 output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Excepted);
0155             }
0156             for (auto* output : GetVariadicOutputs()) {
0157                 output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Excepted);
0158             }
0159             throw;
0160         }
0161         mStatus = Status::Processed;
0162         mCreationStatus = CreationStatus::Created;
0163         for (auto* output : GetOutputs()) {
0164             output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Created);
0165         }
0166         for (auto* output : GetVariadicOutputs()) {
0167             output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Created);
0168         }
0169     }
0170 }
0171 
0172 void JFactory::DoInit() {
0173     if (mStatus != Status::Uninitialized) {
0174         return;
0175     }
0176     for (auto* parameter : m_parameters) {
0177         parameter->Init(*(m_app->GetJParameterManager()), m_prefix);
0178     }
0179     for (auto* service : m_services) {
0180         service->Fetch(m_app);
0181     }
0182     CallWithJExceptionWrapper("JFactory::Init", [&](){ Init(); });
0183     mStatus = Status::Unprocessed;
0184 }
0185 
0186 void JFactory::DoFinish() {
0187     if (mStatus == Status::Unprocessed || mStatus == Status::Processed) {
0188         if (mPreviousRunNumber != -1) {
0189             CallWithJExceptionWrapper("JFactory::EndRun", [&](){ EndRun(); });
0190         }
0191         CallWithJExceptionWrapper("JFactory::Finish", [&](){ Finish(); });
0192         mStatus = Status::Finished;
0193     }
0194 }
0195 
0196 void JFactory::Summarize(JComponentSummary& summary) const {
0197 
0198     auto fs = new JComponentSummary::Component(
0199             "Factory",
0200             GetPrefix(),
0201             GetTypeName(),
0202             GetLevel(),
0203             GetPluginName());
0204 
0205     SummarizeInputs(*fs);
0206     SummarizeOutputs(*fs);
0207     summary.Add(fs);
0208 }
0209 
0210