Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix: JFactory::Finish #377

Merged
merged 17 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions docs/howto/other-howtos.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,15 @@ The following configuration options are used most commonly:
| nthreads | int | Size of thread team (Defaults to the number of cores on your machine) |
| plugins | string | Comma-separated list of plugin filenames. JANA will look for these on the `$JANA_PLUGIN_PATH` |
| plugins_to_ignore | string | This removes plugins which had been specified in `plugins`. |
| event_source_type | string | Manually override JANA's decision about which JEventSource to use |
| event_source_type | string | Manually specify which JEventSource to use |
| jana:nevents | int | Limit the number of events each source may emit |
| jana:nskip | int | Skip processing the first n events from each event source |
| jana:extended_report | bool | The amount of status information to show while running |
| jana:status_fname | string | Named pipe for retrieving status information remotely |
| jana:loglevel | string | Set the log level (trace,debug,info,warn,error,fatal,off) for loggers internal to JANA |
| jana:global_loglevel | string | Set the default log level (trace,debug,info,warn,error,fatal,off) for all loggers |
| jana:show_ticker | bool | Controls whether the status ticker is shown |
| jana:ticker_interval | int | Controls how often the status ticker updates (in ms) |
| jana:extended_report | bool | Controls whether to show extra details in the status ticker and final report |

JANA automatically provides each component with its own logger. You can control the logging verbosity of individual components
just like any other parameter. For instance, if your component prefixes its parameters with `BCAL:tracking`,
Expand Down
2 changes: 2 additions & 0 deletions src/libraries/JANA/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
set(JANA2_SOURCES

JApplication.cc
JEvent.cc
JEventSource.cc
JFactory.cc
JFactorySet.cc
JMultifactory.cc
JService.cc
JVersion.cc
JEvent.cc

Engine/JArrowProcessingController.cc
Engine/JScheduler.cc
Expand Down
9 changes: 9 additions & 0 deletions src/libraries/JANA/Engine/JScheduler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,15 @@ void JScheduler::finish_topology() {
std::lock_guard<std::mutex> lock(m_mutex);
// This finalizes all arrows. Once this happens, we cannot restart the topology.
// assert(m_topology_state.current_topology_status == TopologyStatus::Inactive);

// We ensure that JFactory::EndRun() and JFactory::Finish() are called _before_
// JApplication::Run() exits. This leaves the topology in an unrunnable state,
// but it won't be resumable anyway once it reaches Status::Finished.
for (JEventPool* pool : m_topology->pools) {
pool->finalize();
}

// Next we finalize all remaining components (particularly JEventProcessors)
for (ArrowState& as : m_topology_state.arrow_states) {

if (as.status != ArrowStatus::Finalized) {
Expand Down
1 change: 1 addition & 0 deletions src/libraries/JANA/JApplication.cc
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ void JApplication::Initialize() {
m_desired_nthreads = JCpuInfo::GetNumCpus();
}

m_params->SetDefaultParameter("jana:show_ticker", m_ticker_on, "Controls whether the ticker is visible");
m_params->SetDefaultParameter("jana:ticker_interval", m_ticker_interval_ms, "Controls the ticker interval (in ms)");
m_params->SetDefaultParameter("jana:extended_report", m_extended_report, "Controls whether the ticker shows simple vs detailed performance metrics");

Expand Down
125 changes: 125 additions & 0 deletions src/libraries/JANA/JEvent.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@

#include <JANA/JEvent.h>
#include <JANA/Services/JComponentManager.h>


JEvent::JEvent() : mInspector(this){
mFactorySet = new JFactorySet();
}

JEvent::JEvent(JApplication* app) : mInspector(this) {
// Furnish the JEvent with the parameter values and factory generators provided to the JApplication
app->Initialize();
app->GetService<JComponentManager>()->configure_event(*this);
}

JEvent::~JEvent() {
if (mFactorySet != nullptr) {
// Prevent memory leaks of factory contents
mFactorySet->Clear();
// We mustn't call EndRun() or Finish() here because that would give us an excepting destructor
}
delete mFactorySet;
}

void JEvent::SetFactorySet(JFactorySet* factorySet) {
delete mFactorySet;
mFactorySet = factorySet;
#if JANA2_HAVE_PODIO
// Maintain the index of PODIO factories
for (JFactory* factory : mFactorySet->GetAllFactories()) {
if (dynamic_cast<JFactoryPodio*>(factory) != nullptr) {
auto tag = factory->GetTag();
auto it = mPodioFactories.find(tag);
if (it != mPodioFactories.end()) {
throw JException("SetFactorySet failed because PODIO factory tag '%s' is not unique", tag.c_str());
}
mPodioFactories[tag] = factory;
}
}
#endif
}


/// GetFactory() should be used with extreme care because it subverts the JEvent abstraction.
/// Most historical uses of GetFactory are far better served by JMultifactory
JFactory* JEvent::GetFactory(const std::string& object_name, const std::string& tag) const {
return mFactorySet->GetFactory(object_name, tag);
}

/// GetAllFactories() should be used with extreme care because it subverts the JEvent abstraction.
/// Most historical uses of GetFactory are far better served by JMultifactory
std::vector<JFactory*> JEvent::GetAllFactories() const {
return mFactorySet->GetAllFactories();
}

bool JEvent::HasParent(JEventLevel level) const {
for (const auto& pair : mParents) {
if (pair.first == level) return true;
}
return false;
}

const JEvent& JEvent::GetParent(JEventLevel level) const {
for (const auto& pair : mParents) {
if (pair.first == level) return *(*(pair.second));
}
throw JException("Unable to find parent at level %s",
toString(level).c_str());
}

void JEvent::SetParent(std::shared_ptr<JEvent>* parent) {
JEventLevel level = parent->get()->GetLevel();
for (const auto& pair : mParents) {
if (pair.first == level) throw JException("Event already has a parent at level %s",
toString(parent->get()->GetLevel()).c_str());
}
mParents.push_back({level, parent});
parent->get()->mReferenceCount.fetch_add(1);
}

std::shared_ptr<JEvent>* JEvent::ReleaseParent(JEventLevel level) {
if (mParents.size() == 0) {
throw JException("ReleaseParent failed: child has no parents!");
}
auto pair = mParents.back();
if (pair.first != level) {
throw JException("JEvent::ReleaseParent called out of level order: Caller expected %s, but parent was actually %s",
toString(level).c_str(), toString(pair.first).c_str());
}
mParents.pop_back();
auto remaining_refs = pair.second->get()->mReferenceCount.fetch_sub(1);
if (remaining_refs < 1) { // Remember, this was fetched _before_ the last subtraction
throw JException("Parent refcount has gone negative!");
}
if (remaining_refs == 1) {
return pair.second;
// Parent is no longer shared. Transfer back to arrow
}
else {
return nullptr; // Parent is still shared by other children
}
}

void JEvent::Release() {
auto remaining_refs = mReferenceCount.fetch_sub(1);
if (remaining_refs < 0) {
throw JException("JEvent's own refcount has gone negative!");
}
}

void JEvent::Clear() {
if (mEventSource != nullptr) {
mEventSource->DoFinishEvent(*this);
}
mFactorySet->Clear();
mInspector.Reset();
mCallGraph.Reset();
mReferenceCount = 1;
}

void JEvent::Finish() {
mFactorySet->Finish();
}


Loading
Loading