diff --git a/Framework/Core/include/Framework/O2ControlLabels.h b/Framework/Core/include/Framework/O2ControlLabels.h index eb05f156cf58d..2d4ea7c66cc3a 100644 --- a/Framework/Core/include/Framework/O2ControlLabels.h +++ b/Framework/Core/include/Framework/O2ControlLabels.h @@ -31,6 +31,10 @@ const extern DataProcessorLabel uniqueProxyLabel; // Thus, AliECS will not perform host and port allocation automatically. It takes priority over `uniqueProxyLabel`. const extern DataProcessorLabel preserveRawChannelsLabel; +// This label makes AliECS templates add the property `qcConfiguration` to the tasks, allowing them +// to reconfigure in init with a freshly templated config. +const extern DataProcessorLabel qcReconfigurable; + } // namespace ecs } // namespace o2::framework diff --git a/Framework/Core/src/O2ControlHelpers.cxx b/Framework/Core/src/O2ControlHelpers.cxx index d4aeec9b169cf..e0f4858e36ed4 100644 --- a/Framework/Core/src/O2ControlHelpers.cxx +++ b/Framework/Core/src/O2ControlHelpers.cxx @@ -185,6 +185,41 @@ std::vector extractRawChannels(const DeviceSpec& spec, const DeviceE return rawChannels; } +bool isUniqueProxy(const DeviceSpec& spec) +{ + return std::find(spec.labels.begin(), spec.labels.end(), ecs::uniqueProxyLabel) != spec.labels.end(); +} + +bool shouldPreserveRawChannels(const DeviceSpec& spec) +{ + return std::find(spec.labels.begin(), spec.labels.end(), ecs::preserveRawChannelsLabel) != spec.labels.end(); +} + +bool isQcReconfigurable(const DeviceSpec& spec) +{ + return std::find(spec.labels.begin(), spec.labels.end(), ecs::qcReconfigurable) != spec.labels.end(); +} + +void dumpProperties(std::ostream& dumpOut, const DeviceExecution& execution, const DeviceSpec& spec, const std::string& indLevel) +{ + // get the argument `--config` + std::string configPath; + auto it = std::find_if(execution.args.begin(), execution.args.end(), [](char* v) { return v != nullptr && strcmp(v, "--config") == 0; }); + + // get the next argument and find `/o2/components/` in it, then take what comes after in the string. + if (it != execution.args.end()) { + std::string configParam = *(++it); + std::string prefix = "/o2/components/"; // keep only the path to the config file, i.e. stuff after "/o2/components/" + size_t pos = configParam.find(prefix); + if (pos != std::string::npos) { + configPath = configParam.substr(pos + prefix.length()); + } + } + + dumpOut << indLevel << "properties:\n"; + dumpOut << indLevel << indScheme << "qcConfiguration: " << configPath << "\n"; +} + void dumpCommand(std::ostream& dumpOut, const DeviceExecution& execution, std::string indLevel) { dumpOut << indLevel << "shell: true\n"; @@ -260,16 +295,6 @@ std::string findBinder(const std::vector& specs, const std::string& throw std::runtime_error("Could not find a device which binds the '" + channel + "' channel."); } -bool isUniqueProxy(const DeviceSpec& spec) -{ - return std::find(spec.labels.begin(), spec.labels.end(), ecs::uniqueProxyLabel) != spec.labels.end(); -} - -bool shouldPreserveRawChannels(const DeviceSpec& spec) -{ - return std::find(spec.labels.begin(), spec.labels.end(), ecs::preserveRawChannelsLabel) != spec.labels.end(); -} - void dumpRole(std::ostream& dumpOut, const std::string& taskName, const DeviceSpec& spec, const std::vector& allSpecs, const DeviceExecution& execution, const std::string indLevel) { dumpOut << indLevel << "- name: \"" << spec.id << "\"\n"; @@ -374,6 +399,10 @@ void dumpTask(std::ostream& dumpOut, const DeviceSpec& spec, const DeviceExecuti } } + if (implementation::isQcReconfigurable(spec)) { + implementation::dumpProperties(dumpOut, execution, spec, indLevel); + } + dumpOut << indLevel << "command:\n"; implementation::dumpCommand(dumpOut, execution, indLevel + indScheme); } diff --git a/Framework/Core/src/O2ControlLabels.cxx b/Framework/Core/src/O2ControlLabels.cxx index aa22d858f6e44..9c0b4dbd96d41 100644 --- a/Framework/Core/src/O2ControlLabels.cxx +++ b/Framework/Core/src/O2ControlLabels.cxx @@ -16,4 +16,5 @@ namespace o2::framework::ecs const DataProcessorLabel uniqueProxyLabel = {"ecs-unique-proxy"}; const DataProcessorLabel preserveRawChannelsLabel = {"ecs-preserve-raw-channels"}; +const DataProcessorLabel qcReconfigurable = {"qc-reconfigurable"}; } \ No newline at end of file