File indexing completed on 2026-07-19 08:32:50
0001
0002
0003
0004
0005 #include <JANA/JException.h>
0006 #include <JANA/JLogger.h>
0007 #include <JANA/JFactory.h>
0008 #include <JANA/JEvent.h>
0009 #include <JANA/JEventSource.h>
0010 #include <JANA/Utils/JTypeInfo.h>
0011 #include <JANA/JVersion.h>
0012
0013 #if JANA2_HAVE_PERFETTO
0014 #include <JANA/Services/JPerfettoService.h>
0015
0016
0017
0018
0019
0020 static thread_local JFactory* g_current_executing_factory = nullptr;
0021 #endif
0022
0023
0024 class FlagGuard {
0025 bool* m_flag;
0026 public:
0027 FlagGuard(bool* flag) : m_flag(flag) {
0028 *m_flag = true;
0029 }
0030 ~FlagGuard() {
0031 *m_flag = false;
0032 }
0033 };
0034
0035 void JFactory::Create(const std::shared_ptr<const JEvent>& event) {
0036 Create(*event.get());
0037 }
0038
0039 void JFactory::Create(const JEvent& event) {
0040
0041 if (mInsideCreate && (mStatus != Status::Inserted)) {
0042
0043
0044
0045
0046 throw JException("Encountered a cycle in the factory dependency graph! Hint: Maybe this data was supposed to be inserted in the JEventSource");
0047 }
0048 FlagGuard insideCreateFlagGuard (&mInsideCreate);
0049
0050 if (m_app == nullptr && event.GetJApplication() != nullptr) {
0051
0052
0053 m_app = event.GetJApplication();
0054 m_logger = m_app->GetJParameterManager()->GetLogger(GetLoggerName());
0055 }
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 if (mRegenerate) {
0068 if (mStatus == Status::Inserted) {
0069
0070 ClearData();
0071
0072 }
0073
0074 }
0075 else {
0076
0077
0078
0079
0080
0081 if (mStatus == Status::Inserted) {
0082
0083
0084 return;
0085 }
0086
0087
0088
0089
0090
0091 auto src = event.GetJEventSource();
0092 if (src != nullptr && src->IsGetObjectsEnabled()) {
0093 bool found_data = false;
0094
0095 CallWithJExceptionWrapper("JEventSource::GetObjects", [&](){
0096 found_data = src->GetObjects(event.shared_from_this(), this); });
0097
0098 if (found_data) {
0099 mStatus = Status::Inserted;
0100 return;
0101 }
0102 }
0103
0104 }
0105
0106
0107
0108
0109
0110
0111 if (mInitStatus == InitStatus::InitExcepted && mStatus == Status::Empty) {
0112 for (auto* output : GetOutputs()) {
0113 output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Excepted);
0114 }
0115 for (auto* output : GetVariadicOutputs()) {
0116 output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Excepted);
0117 }
0118 mStatus = Status::Excepted;
0119 std::rethrow_exception(mException);
0120 }
0121
0122
0123
0124
0125
0126
0127 {
0128 #if JANA2_HAVE_PERFETTO
0129
0130
0131
0132 JFactory* const caller = g_current_executing_factory;
0133
0134
0135
0136 if (TRACE_EVENT_CATEGORY_ENABLED("factory") && caller != nullptr) {
0137
0138 uint64_t flow_id = 14695981039346656037ULL;
0139 flow_id = (flow_id ^ static_cast<uint64_t>(reinterpret_cast<uintptr_t>(caller))) * 1099511628211ULL;
0140 flow_id = (flow_id ^ static_cast<uint64_t>(reinterpret_cast<uintptr_t>(this))) * 1099511628211ULL;
0141 flow_id = (flow_id ^ static_cast<uint64_t>(event.GetEventNumber())) * 1099511628211ULL;
0142
0143 TRACE_EVENT_INSTANT("factory", perfetto::DynamicString{GetFactoryName()},
0144 perfetto::ThreadTrack::Current(), perfetto::Flow::Global(flow_id));
0145
0146 TRACE_EVENT_BEGIN("factory", perfetto::DynamicString{GetFactoryName()},
0147 perfetto::TerminatingFlow::Global(flow_id),
0148 "tag", GetTag(), "event_nr", event.GetEventNumber());
0149 } else {
0150 TRACE_EVENT_BEGIN("factory", perfetto::DynamicString{GetFactoryName()},
0151 "tag", GetTag(), "event_nr", event.GetEventNumber());
0152 }
0153
0154 struct SpanGuard { ~SpanGuard() { TRACE_EVENT_END("factory"); } } span_guard;
0155
0156
0157
0158 struct CallerGuard {
0159 JFactory** slot; JFactory* saved;
0160 ~CallerGuard() { *slot = saved; }
0161 } caller_guard{&g_current_executing_factory, caller};
0162 g_current_executing_factory = this;
0163 #endif
0164
0165
0166 try {
0167 DoInit();
0168 }
0169 catch(...) {
0170
0171 mStatus = Status::Excepted;
0172 for (auto* output : GetOutputs()) {
0173 output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Excepted);
0174 }
0175 for (auto* output : GetVariadicOutputs()) {
0176 output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Excepted);
0177 }
0178 std::rethrow_exception(mException);
0179 }
0180
0181
0182
0183 if (mStatus == Status::Excepted) {
0184
0185 std::rethrow_exception(mException);
0186 }
0187 else if (mStatus == Status::Empty) {
0188
0189 try {
0190 auto run_number = event.GetRunNumber();
0191 if (mPreviousRunNumber != run_number) {
0192 if (m_callback_style == CallbackStyle::LegacyMode) {
0193 if (mPreviousRunNumber != -1) {
0194 {
0195 #if JANA2_HAVE_PERFETTO
0196 TRACE_EVENT("factory_end_run", perfetto::DynamicString{GetFactoryName()},
0197 "tag", GetTag(), "run_nr", mPreviousRunNumber);
0198 #endif
0199 CallWithJExceptionWrapper("JFactory::EndRun", [&](){ EndRun(); });
0200 }
0201 }
0202 {
0203 #if JANA2_HAVE_PERFETTO
0204 TRACE_EVENT("factory_change_run", perfetto::DynamicString{GetFactoryName()},
0205 "tag", GetTag(), "run_nr", run_number);
0206 #endif
0207 CallWithJExceptionWrapper("JFactory::ChangeRun", [&](){ ChangeRun(event.shared_from_this()); });
0208 }
0209 {
0210 #if JANA2_HAVE_PERFETTO
0211 TRACE_EVENT("factory_begin_run", perfetto::DynamicString{GetFactoryName()},
0212 "tag", GetTag(), "run_nr", run_number);
0213 #endif
0214 CallWithJExceptionWrapper("JFactory::BeginRun", [&](){ BeginRun(event.shared_from_this()); });
0215 }
0216 }
0217 else if (m_callback_style == CallbackStyle::ExpertMode) {
0218 {
0219 #if JANA2_HAVE_PERFETTO
0220 TRACE_EVENT("factory_change_run", perfetto::DynamicString{GetFactoryName()},
0221 "tag", GetTag(), "run_nr", run_number);
0222 #endif
0223 CallWithJExceptionWrapper("JFactory::ChangeRun", [&](){ ChangeRun(event); });
0224 }
0225 }
0226 mPreviousRunNumber = run_number;
0227 }
0228 for (auto* input : GetInputs()) {
0229 input->Populate(event);
0230 }
0231 for (auto* input : GetVariadicInputs()) {
0232 input->Populate(event);
0233 }
0234
0235 if (m_callback_style == CallbackStyle::LegacyMode) {
0236 CallWithJExceptionWrapper("JFactory::Process", [&](){ Process(event.shared_from_this()); });
0237 }
0238 else if (m_callback_style == CallbackStyle::ExpertMode) {
0239 CallWithJExceptionWrapper("JFactory::Process", [&](){ Process(event); });
0240 }
0241 else {
0242 throw JException("Invalid callback style");
0243 }
0244 }
0245 catch (JException& ex) {
0246
0247
0248
0249
0250
0251 LOG_DEBUG(GetLogger()) << "Exception in JFactory::Create, prefix=" << GetPrefix()
0252 << ", message=" << ex.GetMessage();
0253 mStatus = Status::Excepted;
0254 mException = std::current_exception();
0255 for (auto* output : GetOutputs()) {
0256 output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Excepted);
0257 }
0258 for (auto* output : GetVariadicOutputs()) {
0259 output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Excepted);
0260 }
0261 throw;
0262 }
0263 catch (...) {
0264
0265
0266
0267
0268
0269 LOG_DEBUG(GetLogger()) << "Exception in JFactory::Create, prefix=" << GetPrefix();
0270 mStatus = Status::Excepted;
0271 mException = std::current_exception();
0272 for (auto* output : GetOutputs()) {
0273 output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Excepted);
0274 }
0275 for (auto* output : GetVariadicOutputs()) {
0276 output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Excepted);
0277 }
0278 throw;
0279 }
0280
0281
0282 mStatus = Status::Processed;
0283 for (auto* output : GetOutputs()) {
0284 output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Created);
0285 }
0286 for (auto* output : GetVariadicOutputs()) {
0287 output->LagrangianStore(*event.GetFactorySet(), JDatabundle::Status::Created);
0288 }
0289 }
0290 }
0291 }
0292
0293 void JFactory::DoInit() {
0294 if (mInitStatus != InitStatus::InitNotRun) {
0295 return;
0296 }
0297 for (auto* parameter : m_parameters) {
0298 parameter->Init(*(m_app->GetJParameterManager()), m_prefix);
0299 }
0300 for (auto* service : m_services) {
0301 service->Fetch(m_app);
0302 }
0303 try {
0304 {
0305 #if JANA2_HAVE_PERFETTO
0306 TRACE_EVENT("factory_init", perfetto::DynamicString{GetFactoryName()},
0307 "tag", GetTag());
0308 #endif
0309 CallWithJExceptionWrapper("JFactory::Init", [&](){ Init(); });
0310 }
0311 mInitStatus = InitStatus::InitRun;
0312 }
0313 catch (...) {
0314 mInitStatus = InitStatus::InitExcepted;
0315 mException = std::current_exception();
0316 throw;
0317 }
0318 }
0319
0320 void JFactory::DoFinish() {
0321 if (mInitStatus == InitStatus::InitRun) {
0322 if (mPreviousRunNumber != -1) {
0323 CallWithJExceptionWrapper("JFactory::EndRun", [&](){ EndRun(); });
0324 }
0325 CallWithJExceptionWrapper("JFactory::Finish", [&](){ Finish(); });
0326 }
0327 }
0328
0329 void JFactory::Summarize(JComponentSummary& summary) const {
0330
0331 auto fs = new JComponentSummary::Component(
0332 "Factory",
0333 GetPrefix(),
0334 GetTypeName(),
0335 GetLevel(),
0336 GetPluginName());
0337
0338 SummarizeInputs(*fs);
0339 SummarizeOutputs(*fs);
0340 summary.Add(fs);
0341 }
0342
0343