Skip to content

Commit 280aaa6

Browse files
committed
Fixes from codex (hangs with aod-writer waiting for inputs)
1 parent 8e64c6f commit 280aaa6

2 files changed

Lines changed: 76 additions & 13 deletions

File tree

Framework/Core/src/WorkflowHelpers.cxx

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -753,13 +753,41 @@ void WorkflowHelpers::injectAODWriter(WorkflowSpec& workflow, ConfigContext cons
753753
// create DataOutputDescriptor
754754
std::shared_ptr<DataOutputDirector> dod = AnalysisSupportHelpers::getDataOutputDirector(ctx);
755755

756+
auto hasWritableAOD = std::ranges::any_of(dec.outputsInputs, [](InputSpec const& spec) {
757+
return DataSpecUtils::partialMatch(spec, writableAODOrigins);
758+
});
759+
auto hasTFNumber = std::ranges::any_of(dec.outputsInputs, [](InputSpec const& spec) {
760+
return DataSpecUtils::partialMatch(spec, header::DataOrigin{"TFN"}) &&
761+
DataSpecUtils::partialMatch(spec, header::DataDescription{"TFNumber"});
762+
});
763+
auto hasTFFileName = std::ranges::any_of(dec.outputsInputs, [](InputSpec const& spec) {
764+
return DataSpecUtils::partialMatch(spec, header::DataOrigin{"TFF"}) &&
765+
DataSpecUtils::partialMatch(spec, header::DataDescription{"TFFilename"});
766+
});
767+
// AMD metadata is part of AODOrigins, but metadata alone is not enough to
768+
// run the AOD writer unless the same topology can provide TF bookkeeping.
769+
auto canWriteMetadataOnly = hasTFNumber && hasTFFileName;
770+
756771
// select outputs of type AOD which need to be saved
757772
dec.outputsInputsAOD.clear();
758773
for (auto ii = 0u; ii < dec.outputsInputs.size(); ii++) {
759-
if (DataSpecUtils::partialMatch(dec.outputsInputs[ii], AODOrigins)) {
760-
auto ds = dod->getDataOutputDescriptors(dec.outputsInputs[ii]);
761-
if (ds.size() > 0 || dec.isDangling[ii]) {
762-
dec.outputsInputsAOD.emplace_back(dec.outputsInputs[ii]);
774+
auto const& input = dec.outputsInputs[ii];
775+
if (!DataSpecUtils::partialMatch(input, AODOrigins)) {
776+
continue;
777+
}
778+
// Avoid injecting an AOD writer in detector-only subworkflows where the
779+
// only AOD-like output is AMD metadata from the META collector.
780+
if (DataSpecUtils::partialMatch(input, header::DataOrigin{"AMD"}) && !hasWritableAOD && !canWriteMetadataOnly) {
781+
continue;
782+
}
783+
auto ds = dod->getDataOutputDescriptors(input);
784+
if (ds.size() > 0 || dec.isDangling[ii]) {
785+
dec.outputsInputsAOD.emplace_back(input);
786+
if (DataSpecUtils::partialMatch(input, header::DataOrigin{"AMD"})) {
787+
// Metadata collected from META outputs is republished as AMD sporadic data.
788+
// Keep the AOD writer input sporadic so it can consume it together with
789+
// the timeframe AMD metadata emitted directly by AOD producers.
790+
dec.outputsInputsAOD.back().lifetime = Lifetime::Sporadic;
763791
}
764792
}
765793
}
@@ -772,15 +800,18 @@ void WorkflowHelpers::injectAODWriter(WorkflowSpec& workflow, ConfigContext cons
772800
auto fileSink = AnalysisSupportHelpers::getGlobalAODSink(ctx);
773801
workflow.push_back(fileSink);
774802

775-
auto it = std::find_if(dec.outputsInputs.begin(), dec.outputsInputs.end(), [](InputSpec const& spec) -> bool {
776-
return DataSpecUtils::partialMatch(spec, o2::header::DataOrigin("TFN"));
777-
});
778-
dec.isDangling[std::distance(dec.outputsInputs.begin(), it)] = false;
779-
780-
it = std::find_if(dec.outputsInputs.begin(), dec.outputsInputs.end(), [](InputSpec const& spec) -> bool {
781-
return DataSpecUtils::partialMatch(spec, o2::header::DataOrigin("TFF"));
782-
});
783-
dec.isDangling[std::distance(dec.outputsInputs.begin(), it)] = false;
803+
// TFN/TFF are added to the writer inputs above, but they may be absent in
804+
// metadata-only topologies. Only mark them as non-dangling when present.
805+
auto markAsMatched = [&](header::DataOrigin origin) {
806+
auto it = std::find_if(dec.outputsInputs.begin(), dec.outputsInputs.end(), [&](InputSpec const& spec) -> bool {
807+
return DataSpecUtils::partialMatch(spec, origin);
808+
});
809+
if (it != dec.outputsInputs.end()) {
810+
dec.isDangling[std::distance(dec.outputsInputs.begin(), it)] = false;
811+
}
812+
};
813+
markAsMatched(header::DataOrigin{"TFN"});
814+
markAsMatched(header::DataOrigin{"TFF"});
784815
}
785816
}
786817

Framework/Core/test/test_WorkflowHelpers.cxx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <algorithm>
2121
#include <memory>
2222
#include <list>
23+
#include <string_view>
2324

2425
using namespace o2::framework;
2526

@@ -494,6 +495,37 @@ TEST_CASE("TestExternalInput")
494495
availableForwardsInfo);
495496
}
496497

498+
TEST_CASE("TestMetadataOnlyAODWriterInjection")
499+
{
500+
auto hasProcessor = [](WorkflowSpec const& workflow, std::string_view name) {
501+
return std::ranges::any_of(workflow, [name](DataProcessorSpec const& spec) {
502+
return spec.name == name;
503+
});
504+
};
505+
506+
WorkflowSpec metadataOnlyWorkflow{
507+
{.name = "metadata-producer",
508+
.outputs = {OutputSpec{"META", "TRACKER", 0, Lifetime::Sporadic}}}};
509+
510+
auto context = makeEmptyConfigContext();
511+
WorkflowHelpers::injectServiceDevices(metadataOnlyWorkflow, *context);
512+
513+
REQUIRE(hasProcessor(metadataOnlyWorkflow, "internal-dpl-metadata-collector"));
514+
REQUIRE_FALSE(hasProcessor(metadataOnlyWorkflow, "internal-dpl-aod-writer"));
515+
516+
WorkflowSpec metadataWithTFSourceWorkflow{
517+
{.name = "metadata-producer",
518+
.outputs = {OutputSpec{"META", "TRACKER", 0, Lifetime::Sporadic}}},
519+
{.name = "tf-source",
520+
.outputs = {OutputSpec{"TFN", "TFNumber"}, OutputSpec{"TFF", "TFFilename"}}}};
521+
522+
context = makeEmptyConfigContext();
523+
WorkflowHelpers::injectServiceDevices(metadataWithTFSourceWorkflow, *context);
524+
525+
REQUIRE(hasProcessor(metadataWithTFSourceWorkflow, "internal-dpl-metadata-collector"));
526+
REQUIRE(hasProcessor(metadataWithTFSourceWorkflow, "internal-dpl-aod-writer"));
527+
}
528+
497529
TEST_CASE("DetermineDanglingOutputs")
498530
{
499531
WorkflowSpec workflow0{

0 commit comments

Comments
 (0)