ATLAS Offline Software
Loading...
Searching...
No Matches
TrigConfJobOptionsSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
5#include "TrigConfSvcHelper.h"
6
7#include "GaudiKernel/IProperty.h"
8#include "Gaudi/Property.h"
9
12
13#include <nlohmann/json.hpp>
14
15#include <fstream>
16#include <format>
17
18
19namespace {
20 void trim_inplace(std::string& s) {
21 auto start = std::find_if_not(s.begin(), s.end(), ::isspace);
22 auto end = std::find_if_not(s.rbegin(), s.rend(), ::isspace).base();
23 s = (start < end) ? std::string(start, end) : "";
24 }
25}
26
27TrigConf::JobOptionsSvc::JobOptionsSvc(const std::string& name, ISvcLocator* pSvcLocator) :
28 base_class(name, pSvcLocator),
29 m_optsvc("JobOptionsSvc/TrigConfWrapped_JobOptionsSvc", name)
30{}
31
33{
34 ATH_MSG_INFO("Initializing TrigConf::JobOptionsSvc");
35
36 // Configure the wrapped JobOptionsSvc
37 ATH_CHECK(m_optsvc.retrieve());
38 m_optsvc->set( m_optsvc.name() + ".TYPE", "NONE" );
39
40 if (m_sourceType == "FILE") {
41 ATH_MSG_INFO("Reading joboptions from " << m_sourcePath.value());
43 }
44 else if (m_sourceType == "DB") {
46 ATH_MSG_INFO("Reading SMK " << m_smk << " from '" << m_server << "'");
48 }
49 else if (m_sourceType == "PYTHON") {
50 /* "PYTHON" refers to loading properties directly from Python files
51 which we do not use in ATLAS. Configuration via athena.py is of
52 course supported by the default "NONE" mode. */
53 ATH_MSG_ERROR("Not supported " << m_sourceType);
54 return StatusCode::FAILURE;
55 }
56
57 return StatusCode::SUCCESS;
58}
59
66{
67 std::string key, val;
68 std::istringstream iss(s);
69 while (std::getline(std::getline(iss, key, '='), val, ';')) {
70 trim_inplace(key);
71 trim_inplace(val);
72 if (key == "smkey")
73 m_smk = std::stoi(val);
74 else if (key == "server")
75 m_server = val;
76 else if (key == "lvl1key")
77 m_l1psk = std::stoi(val);
78 else if (key == "hltkey")
79 m_hltpsk = std::stoi(val);
80 }
81}
82
84{
85 // Dump job options to JSON file if configured (for debugging only!)
86 if (!m_dump.empty()) {
87 ATH_MSG_INFO("Writing job options to " << m_dump.value());
88 dumpOptions(m_dump).ignore();
89 }
90 return StatusCode::SUCCESS;
91}
92
93StatusCode TrigConf::JobOptionsSvc::readOptionsJson(const std::string& file)
94{
95 std::ifstream f(file);
96 if (!f) {
97 ATH_MSG_ERROR("Cannot open file " << file);
98 return StatusCode::FAILURE;
99 }
100
101 nlohmann::json json;
102 f >> json;
103
104 for (const auto& [client, props] : json["properties"].items()) {
105 for (const auto& [name, value] : props.items()) {
106 set(client + "." + name, value.get<std::string>());
107 }
108 }
109
110 return StatusCode::SUCCESS;
111}
112
113StatusCode TrigConf::JobOptionsSvc::readOptionsDB(const std::string& db_server, int smk)
114{
115 // db job options loader
116 TrigConf::TrigDBJobOptionsLoader jodbloader(db_server);
117 std::string crest_server("");
118 std::string crest_api("");
119 std::string dbname("");
120 if(isCrestConnection(db_server, crest_server, crest_api, dbname)) {
121 jodbloader.setCrestTrigDB(dbname);
122 jodbloader.setCrestConnection(crest_server, crest_api);
123 }
124
126 jodbloader.loadJobOptions( smk, jo );
127 if (jo) {
128 unsigned int nClients(0), nProps(0);
129 TrigConf::DataStructure ds = jo.getObject("properties");
130 for( const auto & client : ds.data()) {
131 nClients++;
132 for( const auto & property : client.second ) {
133 nProps++;
134 set(client.first + "." + property.first, property.second.data());
135 }
136 }
137 ATH_MSG_INFO("Loaded job options from " << nClients << " clients with " << nProps << " in total");
138 } else {
139 ATH_MSG_FATAL("Could not load job options from database " << db_server << " with SMK " << smk);
140 return StatusCode::FAILURE;
141 }
142 return StatusCode::SUCCESS;
143}
144
145
150StatusCode TrigConf::JobOptionsSvc::dumpOptions(const std::string& file)
151{
152 // JSON filetype identifier
153 nlohmann::json json_file;
154 json_file["filetype"] = "joboptions";
155
156 // Properties
157 auto& json = json_file["properties"] = {};
158 for (const auto& [name, value] : items()) {
159 const size_t idot = name.rfind('.');
160 const std::string client = name.substr(0, idot);
161 const std::string propname = name.substr(idot+1);
162 //coverity[COPY_INSTEAD_OF_MOVE]
163 json[client][propname] = value;
164 }
165
166 // Write JSON to file
167 std::ofstream o(file);
168 if (!o) {
169 ATH_MSG_ERROR("Cannot write to file " << file);
170 return StatusCode::FAILURE;
171 }
172 o << std::setw(4) << json_file << std::endl;
173
174 return StatusCode::SUCCESS;
175}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
nlohmann::json json
Loader class for Trigger configuration from the Trigger DB.
Base class for Trigger configuration data and wrapper around underlying representation.
DataStructure getObject(const std::string &pathToChild, bool ignoreIfMissing=false) const
Access to configuration object.
StatusCode readOptionsJson(const std::string &file)
virtual void set(const std::string &key, const std::string &value) override
StatusCode dumpOptions(const std::string &file)
This is mainly for debugging purposes and to compare the JobOptions as seen by the JobOptionSvc to th...
StatusCode readOptionsDB(const std::string &db_server, int smk)
int m_hltpsk
HLT prescale key.
JobOptionsSvc(const std::string &name, ISvcLocator *pSvcLocator)
Gaudi::Property< std::string > m_sourcePath
void parseDBString(const std::string &s)
Parse DB connection string and fill private members.
std::string m_server
DB connection alias.
virtual StatusCode start() override
virtual StatusCode initialize() override
Gaudi::Property< std::string > m_dump
Gaudi::Property< std::string > m_sourceType
virtual std::vector< std::tuple< std::string, std::string > > items() const override
ServiceHandle< Gaudi::Interfaces::IOptionsSvc > m_optsvc
handle to the "real" IOptionsSvc
Loader of trigger configurations from Json files.
bool loadJobOptions(unsigned int smk, boost::property_tree::ptree &jobOptions, const std::string &outFileName="") const
Load job options from the Trigger DB into a ptree for a given SuperMasterKey (SMK)
void setCrestTrigDB(const std::string &crestTrigDB)
set trigger db for the crest connection
void setCrestConnection(const std::string &server, const std::string &version="")
declare CREST as the source of the configuration An empty crest server makes it use Oracle
bool isCrestConnection(const std::string &db_connection_string, std::string &crest_server, std::string &crest_api, std::string &dbname)
Function to interpret the trigger connection string for CREST connections Format of the connections s...
TFile * file