The Gaudi Framework  v36r0 (4abb4d13)
JobOptionsSvc.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2021 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 // ============================================================================
12 // Local:
13 // ============================================================================
14 
15 #include "JobOptionsSvc.h"
16 
17 #include "Analyzer.h"
18 #include "Catalog.h"
19 #include "Messages.h"
20 #include "Node.h"
21 #include "PragmaOptions.h"
22 #include "PythonConfig.h"
23 #include "Units.h"
24 // ============================================================================
25 // Gaudi:
26 // ============================================================================
27 #include "GaudiKernel/MsgStream.h"
28 #include "GaudiKernel/System.h"
29 #include <Gaudi/Parsers/Factory.h>
30 
31 #include <algorithm>
32 #include <cctype>
33 
34 #if __cplusplus >= 201703
35 # include <string_view>
36 #else
37 # include <experimental/string_view>
38 namespace std {
39  using experimental::string_view;
40 }
41 #endif
42 
43 namespace {
44 #if __cplusplus >= 202000
45  inline bool starts_with( std::string_view s, std::string_view prefix ) { return s.starts_with( prefix ); }
46 #else
47  inline bool starts_with( const std::string_view s, const std::string& prefix ) {
48  return s.substr( 0, prefix.size() ) == prefix;
49  }
50 #endif
51 
52 } // namespace
53 
54 // ============================================================================
56 // ============================================================================
57 // Namespace aliases:
58 // ============================================================================
59 namespace gp = Gaudi::Parsers;
60 // ============================================================================
62  if ( System::isEnvSet( "JOBOPTSEARCHPATH" ) ) m_dir_search_path = System::getEnv( "JOBOPTSEARCHPATH" );
63  if ( System::isEnvSet( "JOBOPTSDUMPFILE" ) ) m_dump = System::getEnv( "JOBOPTSDUMPFILE" );
64 
68  for ( const auto& p : m_globalDefaultsProp ) { m_globalDefaults.emplace_back( p.first, p.second ); }
69  } );
70 }
71 // ============================================================================
73  // Call base class initializer
75  // Read the job options if needed
76  if ( sc ) {
77  if ( m_source_type == "NONE" ) {
78  return sc;
79  } else if ( m_source_type == "PYTHON" ) {
80  PythonConfig conf( this );
81  return conf.evaluateConfig( m_source_path, m_pythonParams, m_pythonAction );
82  } else {
84  }
85  }
86  return sc;
87 }
89  if ( m_reportUnused ) {
91  unused.reserve( m_options.size() );
92 
93  for ( const auto& p : m_options ) {
94  if ( !p.second.isBound() ) unused.emplace_back( p.first );
95  }
96 
97  if ( !unused.empty() ) {
98  std::sort( unused.begin(), unused.end() );
99  auto& log = warning();
100  log << unused.size() << " unused properties:";
101  for ( const auto& k : unused ) log << "\n - " << k;
102  log << endmsg;
103  }
104  }
105  return Service::stop();
106 }
107 
108 // ============================================================================
110  if ( !m_dump.empty() ) { dump( m_dump ); }
111  return StatusCode::SUCCESS;
112 }
113 
114 void JobOptionsSvc::dump( const std::string& file, const gp::Catalog& catalog ) const {
115  std::ofstream out( file, std::ios_base::out | std::ios_base::trunc );
116  if ( !out ) {
117  error() << "Unable to open dump-file \"" + file + "\"" << endmsg;
118  return; // RETURN
119  }
120  info() << "Properties are dumped into \"" + file + "\"" << endmsg;
121  // perform the actual dump:
122  out << catalog;
123 }
124 
125 void JobOptionsSvc::dump( const std::string& file ) const {
126  std::ofstream out( file, std::ios_base::out | std::ios_base::trunc );
127  if ( !out ) {
128  error() << "Unable to open dump-file \"" + file + "\"" << endmsg;
129  } else {
130  info() << "Properties are dumped into \"" + file + "\"" << endmsg;
131  for ( const auto& [key, value] : items() ) {
132  out << key << " = " << value << ';';
133  if ( !m_options.find( key )->second.isBound() ) out << " // unused";
134  out << '\n';
135  }
136  }
137 }
138 
140  for ( const auto& client : catalog ) {
141  for ( const auto& current : client.second ) {
142  set( client.first + '.' + current.NameInClient(), current.ValueAsString() );
143  }
144  }
145 }
146 
147 StatusCode JobOptionsSvc::readOptions( std::string_view file, std::string_view path ) {
148  std::string search_path = std::string{path};
149  if ( search_path.empty() && !m_dir_search_path.empty() ) { search_path = m_dir_search_path; }
150  //
151  if ( msgLevel( MSG::DEBUG ) )
152  debug() << "Reading options from the file "
153  << "'" << file << "'" << endmsg;
154  gp::Messages messages( msgStream() );
155  gp::Catalog catalog;
156  gp::Units units;
157  gp::PragmaOptions pragma;
158  gp::Node ast;
159  StatusCode sc = gp::ReadOptions( file, path, &messages, &catalog, &units, &pragma, &ast ) ? StatusCode::SUCCESS
161 
162  // --------------------------------------------------------------------------
163  if ( sc.isSuccess() ) {
164  if ( pragma.IsPrintOptions() ) { info() << "Print options" << std::endl << catalog << endmsg; }
165  if ( pragma.IsPrintTree() ) { info() << "Print tree:" << std::endl << ast.ToString() << endmsg; }
166  if ( pragma.HasDumpFile() ) dump( pragma.dumpFile(), catalog );
167  info() << "Job options successfully read in from " << file << endmsg;
168  fillServiceCatalog( catalog );
169  } else {
170  fatal() << "Job options errors." << endmsg;
171  }
172  // ----------------------------------------------------------------------------
173  return sc;
174 }
175 
177  const std::string key = prefix + '.' + property->name();
178 
179  std::tuple<bool, std::string_view> defaultValue{false, ""};
180  if ( !has( key ) && !m_globalDefaults.empty() ) { // look for a global default only if it was not set
181  std::smatch match;
182  for ( const auto& p : m_globalDefaults ) {
183  if ( regex_match( key, match, p.first ) ) { defaultValue = {true, p.second}; }
184  }
185  }
186 
187  m_options[key] = *property;
188 
189  // at this point the property is bound, so we can set the default if needed
190  if ( std::get<0>( defaultValue ) ) set( key, std::string{std::get<1>( defaultValue )} );
191 }
192 
193 void JobOptionsSvc::broadcast( const std::regex& filter, const std::string& value, OnlyDefaults defaults_only ) {
194  std::smatch match;
195  for ( auto& p : m_options ) {
196  if ( !defaults_only || !p.second.isSet() ) {
197  if ( regex_match( p.first, match, filter ) ) { p.second = value; }
198  }
199  }
200 }
MSG::DEBUG
@ DEBUG
Definition: IMessageSvc.h:25
Gaudi::Details::PropertyBase
PropertyBase base class allowing PropertyBase* collections to be "homogeneous".
Definition: PropertyBase.h:35
Service::initialize
StatusCode initialize() override
Definition: Service.cpp:118
std::string
STL class.
Gaudi.Configuration.log
log
Definition: Configuration.py:24
JobOptionsSvc::m_reportUnused
Gaudi::Property< bool > m_reportUnused
Definition: JobOptionsSvc.h:111
StatusCode::isSuccess
bool isSuccess() const
Definition: StatusCode.h:355
Gaudi::Parsers::Units
Definition: Units.h:28
System.h
std::vector::reserve
T reserve(T... args)
Gaudi::Details::WeakPropertyRef::isBound
bool isBound() const
Definition: PropertyBase.h:208
gaudirun.s
string s
Definition: gaudirun.py:328
System::getEnv
GAUDI_API std::string getEnv(const char *var)
get a particular environment variable (returning "UNKNOWN" if not set)
Definition: System.cpp:379
std::vector
STL class.
std::unordered_map::find
T find(T... args)
std::unordered_map::size
T size(T... args)
ISvcLocator
Definition: ISvcLocator.h:46
JobOptionsSvc::m_pythonAction
Gaudi::Property< std::string > m_pythonAction
Definition: JobOptionsSvc.h:105
JobOptionsSvc::m_source_path
Gaudi::Property< std::string > m_source_path
Definition: JobOptionsSvc.h:102
JobOptionsSvc::set
void set(const std::string &key, const std::string &value) override
Definition: JobOptionsSvc.h:44
JobOptionsSvc::bind
void bind(const std::string &prefix, Gaudi::Details::PropertyBase *property) override
Definition: JobOptionsSvc.cpp:176
std::tuple
gaudirun.prefix
string prefix
Definition: gaudirun.py:343
Gaudi::Parsers::Node
Definition: Node.h:35
JobOptionsSvc::m_options
StorageType m_options
Definition: JobOptionsSvc.h:37
JobOptionsSvc::m_pythonParams
Gaudi::Property< std::string > m_pythonParams
Definition: JobOptionsSvc.h:106
std::sort
T sort(T... args)
CommonMessaging< implements< IService, IProperty, IStateful > >::msgLevel
MSG::Level msgLevel() const
get the cached level (originally extracted from the embedded MsgStream)
Definition: CommonMessaging.h:148
std::vector::clear
T clear(T... args)
PropertyHolder< CommonMessaging< implements< IService, IProperty, IStateful > > >::property
Gaudi::Details::PropertyBase * property(std::string_view name) const
\fixme property and bindPropertiesTo should be protected
Definition: PropertyHolder.h:238
JobOptionsSvc::broadcast
void broadcast(const std::regex &filter, const std::string &value, OnlyDefaults defaults_only) override
Definition: JobOptionsSvc.cpp:193
JobOptionsSvc::start
StatusCode start() override
Definition: JobOptionsSvc.cpp:109
Gaudi::Parsers::PragmaOptions
Definition: PragmaOptions.h:33
TimingHistograms.name
name
Definition: TimingHistograms.py:23
StatusCode
Definition: StatusCode.h:65
Gaudi::Parsers::Node::ToString
std::string ToString(int indent=0) const
Definition: Node.cpp:63
JobOptionsSvc::m_dump
Gaudi::Property< std::string > m_dump
Definition: JobOptionsSvc.h:104
JobOptionsSvc::stop
StatusCode stop() override
Definition: JobOptionsSvc.cpp:88
std::ofstream
STL class.
JobOptionsSvc::m_globalDefaultsProp
Gaudi::Property< std::vector< std::pair< std::string, std::string > > > m_globalDefaultsProp
Definition: JobOptionsSvc.h:108
CommonMessaging
Definition: CommonMessaging.h:66
Gaudi::Parsers::Messages
Definition: Messages.h:31
Gaudi::Property::declareUpdateHandler
Details::PropertyBase & declareUpdateHandler(std::function< void(Details::PropertyBase &)> fun) override
set new callback for update
Definition: Property.h:146
GaudiPython.HistoUtils.path
path
Definition: HistoUtils.py:943
JobOptionsSvc::readOptions
StatusCode readOptions(std::string_view file, std::string_view path="") override
look for file 'file' into search path 'path' and read it to update existing JobOptionsCatalogue
Definition: JobOptionsSvc.cpp:147
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202
System::isEnvSet
GAUDI_API bool isEnvSet(const char *var)
Check if an environment variable is set or not.
Definition: System.cpp:399
std::regex
Units.h
Gaudi::Parsers::ReadOptions
bool ReadOptions(std::string_view filename, std::string_view search_path, Messages *messages, Catalog *catalog, Units *units, PragmaOptions *pragma, Node *root)
Parse and analyze filename, save all messages and properties.
Definition: Analyzer.cpp:379
JobOptionsSvc::dump
void dump(const std::string &file, const Gaudi::Parsers::Catalog &catalog) const
dump properties catalog to file
Definition: JobOptionsSvc.cpp:114
Messages.h
JobOptionsSvc::m_dir_search_path
Gaudi::Property< std::string > m_dir_search_path
Definition: JobOptionsSvc.h:103
JobOptionsSvc.h
PythonConfig.h
Factory.h
std::vector::emplace_back
T emplace_back(T... args)
Node.h
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
std::endl
T endl(T... args)
Service::stop
StatusCode stop() override
Definition: Service.cpp:181
JobOptionsSvc::initialize
StatusCode initialize() override
Definition: JobOptionsSvc.cpp:72
JobOptionsSvc::m_source_type
Gaudi::Property< std::string > m_source_type
Definition: JobOptionsSvc.h:101
Gaudi::Parsers::PragmaOptions::IsPrintOptions
bool IsPrintOptions()
Definition: PragmaOptions.h:49
JobOptionsSvc
Definition: JobOptionsSvc.h:30
std::vector::begin
T begin(T... args)
std
STL namespace.
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
std::vector::empty
T empty(T... args)
Gaudi::Parsers::PragmaOptions::HasDumpFile
bool HasDumpFile()
Definition: PragmaOptions.h:51
Gaudi::Parsers
Definition: DODBasicMapper.cpp:17
std::smatch
std::vector::end
T end(T... args)
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
Catalog.h
JobOptionsSvc::fillServiceCatalog
void fillServiceCatalog(const Gaudi::Parsers::Catalog &catalog)
Definition: JobOptionsSvc.cpp:139
ProduceConsume.key
key
Definition: ProduceConsume.py:52
JobOptionsSvc::items
std::vector< std::tuple< std::string, std::string > > items() const override
Definition: JobOptionsSvc.h:60
Gaudi::Parsers::PragmaOptions::IsPrintTree
bool IsPrintTree()
Definition: PragmaOptions.h:50
Gaudi::Parsers::PragmaOptions::dumpFile
const std::string & dumpFile() const
Definition: PragmaOptions.h:46
JobOptionsSvc::has
bool has(const std::string &key) const override
Definition: JobOptionsSvc.h:59
conf
Definition: conf.py:1
JobOptionsSvc::m_globalDefaults
std::vector< std::pair< std::regex, std::string > > m_globalDefaults
Definition: JobOptionsSvc.h:113
JobOptionsSvc::JobOptionsSvc
JobOptionsSvc(const std::string &name, ISvcLocator *svc)
Definition: JobOptionsSvc.cpp:61
Gaudi::Parsers::Catalog
Definition: Catalog.h:39
MsgStream.h
PythonConfig
Definition: PythonConfig.h:33
PrepareBase.out
out
Definition: PrepareBase.py:20
Analyzer.h
PragmaOptions.h