Skip to content

Commit

Permalink
Merge pull request #377 from JeffersonLab/nbrei_jfactory_finish
Browse files Browse the repository at this point in the history
Bugfix: JFactory::Finish
  • Loading branch information
nathanwbrei authored Oct 23, 2024
2 parents 7b51136 + 5f63b12 commit ba511e3
Show file tree
Hide file tree
Showing 29 changed files with 907 additions and 402 deletions.
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

0 comments on commit ba511e3

Please sign in to comment.