MarlinMT  0.1.0
Application.cc
Go to the documentation of this file.
1 
2 // -- marlinmt headers
3 #include <marlinmt/Application.h>
5 #include <marlinmt/Utils.h>
7 #include <marlinmt/Processor.h>
10 #include <marlinmt/IScheduler.h>
13 #include <marlinmt/EventStore.h>
14 #include <marlinmt/RunHeader.h>
15 
16 // -- std headers
17 #include <cstring>
18 #include <filesystem>
19 
20 using namespace std::placeholders ;
21 
22 namespace marlinmt {
23 
24  int Application::main( int argc, char**argv ) {
25  // configure and run application
26  Application application ;
27  auto logger = application.logger() ;
28  try {
29  application.init( argc, argv ) ;
30  application.run() ;
31  }
32  catch ( marlinmt::Exception &e ) {
33  logger->log<ERROR>() << "MarlinMT main, caught MarlinMT exception " << e.what() << std::endl ;
34  logger->log<ERROR>() << "Exiting with status 1" << std::endl ;
35  return 1 ;
36  }
37  catch ( std::exception &e ) {
38  logger->log<ERROR>() << "MarlinMT main, caught std::exception " << e.what() << std::endl ;
39  logger->log<ERROR>() << "Exiting with status 1" << std::endl ;
40  return 1 ;
41  }
42  catch ( ... ) {
43  logger->log<ERROR>() << "MarlinMT main, caught unknown exception" << std::endl ;
44  logger->log<ERROR>() << "Exiting with status 2" << std::endl ;
45  return 2 ;
46  }
47  return 0 ;
48  }
49 
50  //--------------------------------------------------------------------------
51 
52  void Application::init( int argc, char **argv ) {
53  // Geeky MarlinMT logo
54  details::print_banner( std::cout ) ;
55 
56  // Parse command line first
57  CmdLineParser parser ;
58  _parseResult = parser.parse( argc, argv ) ;
59 
60  // Populate the configuration with command line parameters
61  auto fullCmdLine = details::convert<std::vector<std::string>>::to_string( _parseResult._arguments ) ;
62  fullCmdLine = std::string(argv[0]) + " " + fullCmdLine ;
63  auto &cmdLineSection = _configuration.createSection( "CmdLine" ) ;
64  cmdLineSection.setParameter( "Program", _parseResult._programName ) ;
65  cmdLineSection.setParameter( "Arguments", fullCmdLine ) ;
66  cmdLineSection.setParameter( "Config", _parseResult._config.value() ) ;
67  cmdLineSection.setParameter( "NThreads", _parseResult._nthreads ) ;
68  auto &argsSection = cmdLineSection.addSection( "AdditionalArgs" ) ;
69  for( auto &arg : _parseResult._additionalArgs ) {
70  argsSection.setParameter( arg.first, arg.second ) ;
71  }
72 
73  // set the main logger name a bit early for more sexy logging
74  std::filesystem::path progName = _parseResult._programName ;
75  _parseResult._programName = progName.filename().string() ;
76 
77  // load plugins
78  auto &pluginMgr = PluginManager::instance() ;
79  pluginMgr.logger()->setLevel<MESSAGE>() ;
80  auto libraries = details::split_string<std::string>( details::getenv<std::string>( "MARLINMT_DLL", "" ), ":" ) ;
81  pluginMgr.loadLibraries( libraries ) ;
82 
83  if( _parseResult._dumpExample ) {
84  _initialized = true ;
85  return ;
86  }
87 
88  // parse the config
89  ConfigHelper::readConfig( _parseResult._config.value(), _configuration ) ;
90 
91  // initialize logging
92  _loggerMgr.setup( this ) ;
93  logger()->log<MESSAGE0>() << "============ Configuration ============" << std::endl ;
94  logger()->log<MESSAGE0>() << _configuration << std::endl ;
95  logger()->log<MESSAGE0>() << "=======================================" << std::endl ;
96 
97  // initialize BookStore
98  _bookStoreManager.setup( this ) ;
99 
100  // initialize geometry
101  _geometryMgr.setup( this ) ;
102 
103  // setup scheduler
104  if( 0 == _parseResult._nthreads ) {
105  MARLINMT_THROW( "Number of threads can't be 0 !" ) ;
106  }
107  if( 1 == _parseResult._nthreads ) {
108  logger()->log<MESSAGE>() << "Running in single-thread mode" << std::endl ;
109  _scheduler = std::make_shared<SimpleScheduler>() ;
110  }
111  else {
112  logger()->log<MESSAGE>() << "Running in multi-thread mode (nthreads=" << _parseResult._nthreads << ")" << std::endl ;
113  _scheduler = std::make_shared<concurrency::PEPScheduler>() ;
114  }
115  _scheduler->setup( this ) ;
116 
117  // initialize data source
118  auto dstype = configuration().section("datasource").parameter<std::string>( "DatasourceType" ) ;
119  _dataSource = pluginMgr.create<DataSourcePlugin>( dstype ) ;
120  if( nullptr == _dataSource ) {
121  MARLINMT_THROW( "Data source of type '" + dstype + "' not found in plugins" ) ;
122  }
123  _dataSource->setup( this ) ;
124  _dataSource->onEventRead( std::bind( &Application::onEventRead, this, _1 ) ) ;
125  _dataSource->onRunHeaderRead( std::bind( &Application::onRunHeaderRead, this, _1 ) ) ;
126 
127  // store processor conditions
128  auto &execSection = _configuration.section("execute") ;
129  auto procs = execSection.parameterNames() ;
130  for( auto &proc : procs ) {
131  _conditions[ proc ] = execSection.parameter<std::string>( proc ) ;
132  }
133  _initialized = true ;
134  }
135 
136  //--------------------------------------------------------------------------
137 
138  void Application::run() {
139  if( _parseResult._dumpExample ) {
140  logger()->log<MESSAGE>() << "Dry run. Output configuration in: " << _parseResult._config.value() << std::endl ;
141  dumpExampleConfig() ;
142  return ;
143  }
144  try {
145  _dataSource->readAll() ;
146  }
147  catch( StopProcessingException &e ) {
148  logger()->log<ERROR>() << std::endl
149  << " **********************************************************" << std::endl
150  << " * *" << std::endl
151  << " * Stop of event processing requested by processor : *" << std::endl
152  << " * " << e.what() << std::endl
153  << " * will call end() method of all processors ! *" << std::endl
154  << " * *" << std::endl
155  << " **********************************************************" << std::endl
156  << std::endl ;
157  }
158  _geometryMgr.clear() ;
159  _scheduler->end() ;
160  _bookStoreManager.writeToDisk();
161  }
162 
163  //--------------------------------------------------------------------------
164 
165  const Application::CmdLineParseResult &Application::cmdLineParseResult() const {
166  return _parseResult ;
167  }
168 
169  //--------------------------------------------------------------------------
170 
171  const std::string &Application::programName() const {
172  return cmdLineParseResult()._programName ;
173  }
174 
175  //--------------------------------------------------------------------------
176 
177  bool Application::isInitialized() const {
178  return _initialized ;
179  }
180 
181  //--------------------------------------------------------------------------
182 
183  Application::Logger Application::logger() const {
184  return _loggerMgr.mainLogger() ;
185  }
186 
187  //--------------------------------------------------------------------------
188 
189  Application::Logger Application::createLogger( const std::string &name ) const {
190  if ( isInitialized() ) {
191  return _loggerMgr.createLogger( name ) ;
192  }
193  else {
194  return Logging::createLogger( name ) ;
195  }
196  }
197 
198  //--------------------------------------------------------------------------
199 
200  void Application::onEventRead( std::shared_ptr<EventStore> event ) {
201  EventList events ;
202  while( _scheduler->freeSlots() == 0 ) {
203  _scheduler->popFinishedEvents( events ) ;
204  if( not events.empty() ) {
205  processFinishedEvents( events ) ;
206  events.clear() ;
207  break;
208  }
209  std::this_thread::sleep_for( std::chrono::milliseconds(1) ) ;
210  }
211  // prepare event extensions for users
212  // random seeds extension
213  auto seeds = _randomSeedMgr.generateRandomSeeds( event.get() ) ;
214  auto randomSeedExtension = new RandomSeedExtension( std::move(seeds) ) ;
215  event->extensions().add<extensions::RandomSeed>( randomSeedExtension ) ;
216  // runtime conditions extension
217  // TODO replace this
218  auto procCondExtension = new ProcessorConditionsExtension( _conditions ) ;
219  event->extensions().add<extensions::ProcessorConditions>( procCondExtension ) ;
220  _scheduler->pushEvent( event ) ;
221  // check a second time
222  _scheduler->popFinishedEvents( events ) ;
223  if( not events.empty() ) {
224  processFinishedEvents( events ) ;
225  }
226  }
227 
228  //--------------------------------------------------------------------------
229 
230  void Application::onRunHeaderRead( std::shared_ptr<RunHeader> rhdr ) {
231  logger()->log<MESSAGE9>() << "New run header no " << rhdr->runNumber() << std::endl ;
232  _scheduler->processRunHeader( rhdr ) ;
233  }
234 
235  //--------------------------------------------------------------------------
236 
237  const GeometryManager &Application::geometryManager() const {
238  return _geometryMgr ;
239  }
240 
241  //--------------------------------------------------------------------------
242 
243  const RandomSeedManager &Application::randomSeedManager() const {
244  return _randomSeedMgr ;
245  }
246 
247  //--------------------------------------------------------------------------
248 
249  RandomSeedManager &Application::randomSeedManager() {
250  return _randomSeedMgr ;
251  }
252 
253  //--------------------------------------------------------------------------
254 
255  void Application::processFinishedEvents( const EventList &events ) const {
256  // simple printout for the time being
257  for( auto event : events ) {
258  logger()->log<MESSAGE9>()
259  << "Event uid " << event->uid()
260  << " finished" << std::endl ;
261  }
262  }
263 
264  //--------------------------------------------------------------------------
265 
266  BookStoreManager &Application::bookStoreManager() {
267  return _bookStoreManager ;
268  }
269 
270  //--------------------------------------------------------------------------
271 
272  const BookStoreManager &Application::bookStoreManager() const {
273  return _bookStoreManager ;
274  }
275 
276  //--------------------------------------------------------------------------
277 
278  const Configuration &Application::configuration() const {
279  return _configuration ;
280  }
281 
282  //--------------------------------------------------------------------------
283 
284  void Application::dumpExampleConfig() {
285  Configuration &config = _configuration ;
286  auto &pluginMgr = PluginManager::instance() ;
287 
288  auto &execSection = config.createSection("execute") ;
289  execSection.setParameter( "MyTestProcessor", true ) ;
290 
291  auto &loggingSection = config.createSection("logging") ;
292  _loggerMgr.getParameters( loggingSection ) ;
293 
294  auto &geometrySection = config.createSection("geometry") ;
295  geometrySection.setParameter<std::string>( "GeometryType", "EmptyGeometry" ) ;
296 
297  auto &datasourceSection = config.createSection("datasource") ;
298  auto lcioReader = pluginMgr.create<DataSourcePlugin>( "LCIOReader" ) ;
299  if( lcioReader ) {
300  lcioReader->getParameters( datasourceSection ) ;
301  datasourceSection.setParameter<std::string>( "DatasourceType", "LCIOReader" ) ;
302  }
303  else {
304  datasourceSection.setParameter<std::string>( "DatasourceType", "CustomSource" ) ;
305  datasourceSection.setParameter<std::string>( "InputFile", "yourinput.dat" ) ;
306  }
307 
308  auto &bookstoreSection = config.createSection("bookstore") ;
309  _bookStoreManager.getParameters( bookstoreSection ) ;
310 
311  auto &globalSection = config.createSection("global") ;
312  globalSection.setParameter( "RandomSeed", 1234567890 ) ;
313 
314  auto &procsSection = config.createSection("processors") ;
315  auto pluginNames = pluginMgr.pluginNames<Processor>() ;
316  for( auto pluginName : pluginNames ) {
317  auto processor = pluginMgr.create<Processor>( pluginName ) ;
318  processor->setName( "My" + processor->type() ) ;
319  auto &procSection = procsSection.addSection( processor->name() ) ;
320  procSection.setParameter( "ProcessorName", processor->name() ) ;
321  procSection.setParameter( "ProcessorType", processor->type() ) ;
322  auto criticalOpt = processor->runtimeOption( Processor::ERuntimeOption::eCritical ) ;
323  auto cloneOpt = processor->runtimeOption( Processor::ERuntimeOption::eClone ) ;
324  procSection.setParameter( "ProcessorCritical", criticalOpt.has_value() ? criticalOpt.value() : false ) ;
325  procSection.setParameter( "ProcessorClone", cloneOpt.has_value() ? cloneOpt.value() : false ) ;
326  processor->getParameters( procSection ) ;
327  }
328  ConfigHelper::writeConfig( _parseResult._config.value(), config ) ;
329  }
330 
331 } // namespace marlinmt
const char * what() const noexcept override
Get the full exception message.
Definition: Exceptions.cc:19
std::string _programName
The program name.
Definition: CmdLineParser.h:21
ProcessorConditionsExtension class Event extension providing access to processor runtime conditions (...
GeometryManager class.
ConfigSection & createSection(const std::string &sn)
Create a new section by name.
BookStoreManager class.
void setName(const std::string &n)
Set the component name.
Definition: Component.cc:29
RandomSeedExtension class Event extension providing access to random seeds.
ParseResult parse(int argc, char **argv)
Parse the command line.
DataSourcePlugin class Responsible for reading/getting LCEvent and LCRunHeader in the framework for f...
#define MARLINMT_THROW(message)
Definition: Exceptions.h:8
Application class Base application interface for running a Marlin application.
Definition: Application.h:25
Configuration class.
std::vector< std::shared_ptr< EventStore > > EventList
Definition: Application.h:30
ConfigSection & setParameter(const std::string &n, const T &val)
Set a parameter value.
Definition: Configuration.h:97
RandomSeedManager class.
ParseResult struct. The result of the command line parsing.
Definition: CmdLineParser.h:19
Processor class.
Definition: Processor.h:43
void getParameters(ConfigSection &section, const std::set< std::string > &exclude={}) const
Get the parameters from configurable object and populate the config section with. ...
Definition: Component.cc:139
Logging::Logger Logger
Definition: Application.h:27
void init(int argc, char **argv)
Initialize the application.
Definition: Application.cc:52
Exception class.
Definition: Exceptions.h:60
void run()
Run the application.
Definition: Application.cc:138
Logger logger() const
Get the application logger instance.
Definition: Application.cc:183
void print_banner(std::ostream &out)
Definition: Utils.h:620
CmdLineParser class Does the main command line parsing for MarlinMT.
Definition: CmdLineParser.h:14