gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-2191-ga4742ac
a Global And Modular Bsm Inference Tool
logmaster.cpp
Go to the documentation of this file.
1 // GAMBIT: Global and Modular BSM Inference Tool
2 // *********************************************
20 
21 
22 // Standard libraries
23 #include <set>
24 #include <fstream>
25 #include <cstdarg>
26 #include <stdexcept>
27 #include <algorithm>
28 #include <limits>
29 #include <chrono>
30 #include <omp.h>
31 
32 // Gambit
34 #include "gambit/Logs/logging.hpp"
39 #include "gambit/cmake/cmake_variables.hpp"
40 
41 // Code!
42 namespace Gambit
43 {
44 
45  namespace Logging
46  {
47  using namespace LogTags;
48 
49  //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
51  //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52 
56  : loggers_readyQ (false)
57  , silenced (false)
58  , separate_file_per_process(true)
59  , log_debug_messages(false)
60  , MPIrank (0)
61  , MPIsize (1)
62  , globlMaxThreads(omp_get_max_threads())
63  , current_module (NULL)
64  , current_backend(NULL)
65  , stream (NULL)
66  , streamtags (NULL)
67  , backlog (NULL)
68  {
69  // Note! MPIrank and MPIsize will not be correct until initialisation occurs!
70  }
71 
73  // Mainly for testing; lets you pass in pre-built loggers and their tags
74  LogMaster::LogMaster(std::map<std::set<int>,BaseLogger*>& loggersIN)
75  : loggers (loggersIN)
76  , loggers_readyQ (true)
77  , silenced (false)
79  , log_debug_messages(false)
80  , MPIrank (0)
81  , MPIsize (1)
82  , globlMaxThreads(omp_get_max_threads())
83  , current_module (NULL)
84  , current_backend(NULL)
85  , stream (NULL)
86  , streamtags (NULL)
87  , backlog (NULL)
88  {
89  // Note! MPIrank and MPIsize will not be correct until initialisation occurs!
90  }
91 
92  // Initialise dynamic memory required for thread safety
94  {
95  int n = globlMaxThreads;
96  // Reserve enough space to hold as many variables as there are slots (threads) allowed
97  if(stream==NULL)
98  {
99  #pragma omp critical(logmaster_common_init_memory_stream)
100  {
101  if(stream==NULL) stream = new std::ostringstream[n];
102  }
103  }
104  if(streamtags==NULL)
105  {
106  #pragma omp critical(logmaster_common_init_memory_streamtags)
107  {
108  if(streamtags==NULL) streamtags = new std::set<int>[n];
109  }
110  }
111  if(backlog==NULL)
112  {
113  #pragma omp critical(logmaster_common_init_memory_backlog)
114  {
115  if(backlog==NULL) backlog = new std::deque<Message>[n];
116  }
117  }
118  if(current_module==NULL)
119  {
120  #pragma omp critical(logmaster_common_init_memory_current_module)
121  {
122  if(current_module==NULL) current_module = new int[n];
123  std::fill(current_module, current_module+n, -1);
124  }
125  }
126  if(current_backend==NULL)
127  {
128  #pragma omp critical(logmaster_common_init_memory_current_backend)
129  {
130  if(current_backend==NULL) current_backend = new int[n];
131  std::fill(current_backend, current_backend+n, -1);
132  }
133  }
134  }
135 
136  // Print the backlogs to the default log file
138  {
139  if (backlog!=NULL)
140  {
141  bool backlog_empty = true;
142  for(int i=0; i<globlMaxThreads; i++)
143  {
144  if(backlog[i].size()!=0) backlog_empty = false;
145  }
146  if (not backlog_empty)
147  {
148  if (verbose) *this<<"Logger backlog buffer not empty during LogMaster destruction; attempting to deliver unsent messages to the logs..."<<EOM;
149  // If LogMaster was never initialised, create a default log file to which the messages can be dumped.
150  if (not loggers_readyQ)
151  {
152  str log_path = Utils::construct_runtime_scratch(false) + "default.log";
153  #ifdef WITH_MPI
154  if (GMPI::Is_initialized() and not GMPI::Is_finalized())
155  log_path += ("_" + std::to_string(GMPI::Comm().Get_rank()));
156  #endif
157  if (verbose) std::cout<<std::endl<<"GAMBIT logger was never initialised. Outputting default log to "<<log_path<<std::endl;
158  StdLogger* deflogger = new StdLogger(log_path);
159  std::set<int> deftag;
160  deftag.insert(def);
161  loggers[deftag] = deflogger;
162  loggers_readyQ = true;
163  }
164  // Dump buffered messages
165  empty_backlog();
166  }
167  }
168  }
169 
170  // Destructor
172  {
173  // See signal_handling.cpp for why we should not bail out in this situation
174  // // LogMaster should not be destructed from within a parallel block. This check helps detect such a bug.
175  // if(omp_get_level()!=0)
176  // {
177  // // Raising an error from within the loggers within a parallel block probably will not end well, just use cout.
178  // #pragma omp critical(logmaster_destructor)
179  // {
180  // std::cout << "rank "<<MPIrank<<": "<< LOCAL_INFO << ": Tried to destruct LogMaster from inside an omp parallel block! This should not be allowed to happen, please file a bug report." << std::endl;
181  // exit(EXIT_FAILURE);
182  // }
183  // }
184 
185  if(not silenced)
186  {
187  // Check if there is anything in the output stream that has not been sent, and send it if there is
188  // (these messages will get backlogged because they are sent (ended) from a parallel block, but we are
189  // about to empty the backlogs anyway so that is no problem).
190  if (stream != NULL and streamtags!= NULL)
191  {
192  #pragma omp parallel
193  {
194  int i = omp_get_thread_num();
195  if (not stream[i].str().empty() or not streamtags[i].empty())
196  {
197  *this <<"#### NO EOM RECEIVED FOR MESSAGE FROM THREAD ("<<i<<"): MESSAGE MAY BE INCOMPLETE ####"<<warn<<EOM;
198  }
199  }
200  }
201 
202  // Output the message backlogs if needed
203  emit_backlog(true);
204 
205  }
206 
207  // Delete logger objects
208  for(std::map<std::set<int>,BaseLogger*>::iterator keyvalue = loggers.begin(); keyvalue != loggers.end(); ++keyvalue)
209  {
210  // Ensure their filestreams have been flushed before we delete them.
211  // (not sure if this is really needed, I think the message is in the operating systems domain by this point)
212  // Edit: I think I have decided that this is unnecessary
213  //(keyvalue->second)->flush();
214  delete (keyvalue->second);
215  }
216 
217  // Delete the thread variables
218  if (stream != NULL) delete [] stream;
219  if (streamtags != NULL) delete [] streamtags;
220  if (backlog != NULL) delete [] backlog;
221  if (current_module !=NULL) delete [] current_module;
222  if (current_backend !=NULL) delete [] current_backend;
223  }
224 
226  // This is the function that yaml_parser.hpp uses. You provide tags as a set of strings, and the filename as a string. We then construct the logger objects in here.
227  void LogMaster::initialise(std::vector<std::pair< std::set<std::string>, std::string >>& loggerinfo)
228  {
229  // Fix up the MPI variables
230  #ifdef WITH_MPI
231  if(GMPI::Is_initialized())
232  {
233  GMPI::Comm COMM_WORLD;
234  MPIsize = COMM_WORLD.Get_size();
235  MPIrank = COMM_WORLD.Get_rank();
236  }
237  #endif
238 
239  // Check options and inform user what they are
240  if (MPIrank == 0) std::cout << "Initialising logger...";
241  // NOTE! Option to merge log files no longer exists. Concurrent write access is a nightmare. Log messages were
242  // being lost due to different processes overwriting each others data, and using the FileLock system doesn't
243  // help because the issue is the file pointer location. To fix that, files have to be closed and reopened
244  // constantly, which creates a lot of overhead. On top of this, it is very hard to overwrite old log files at the
245  // beginning of the run since we have to coordinate who creates the file at the beginning of the run, would have
246  // to add a bunch of message passing. Overall it just isn't worth it.
247  // #ifdef WITH_MPI
248  // std::cout << std::endl << " separate_file_per_process = ";
249  // if(separate_file_per_process){ std::cout << "true; log messages will be stored in separate files for each MPI process (filename will be appended with underscore + MPI rank)"; }
250  // else{ std::cout << "false; log messages from separate MPI processes will be merged into one file (orchestrated by the OS; some mangling of concurrently written log messages may occur. Set this separate_file_per_process to 'True' if this mangling is a problem for you)";}
251  // #endif
252  std::ostringstream logmsg;
253  logmsg << " log_debug_messages = ";
254  if(log_debug_messages) logmsg << "true; log messages tagged as 'Debug' WILL be logged. " << endl << "WARNING: This may lead to very large log files!";
255  else
256  {
257  // Add "Debug" tag to the global ignore list
258  ignore.insert(LogTag::debug);
259  logmsg << "false; log messages tagged as 'Debug' will NOT be logged";
260  }
261 
262  if (MPIrank == 0) std::cout << logmsg.str() << std::endl;
263  *this << LogTag::logs << LogTag::debug << logmsg.str() << EOM;
264 
265  // Iterate through map and build the logger objects
266  for(std::vector<std::pair< std::set<std::string>, std::string >>::iterator infopair = loggerinfo.begin();
267  infopair != loggerinfo.end(); ++infopair)
268  {
269  std::set<std::string> yamltags = infopair->first;
270  std::string filename = infopair->second;
271  std::set<int> tags;
272 
274  and filename!="stdout" and filename!="stderr")
275  {
276  std::ostringstream unique_filename;
277  unique_filename << filename << "_" << MPIrank;
278  filename = unique_filename.str();
279  }
280 
281  // Log the loggers being created :)
282  // (will be put into a preliminary buffer until loggers are all constructed)
283  *this << LogTag::logs << LogTag::debug << std::endl << "Creating logger for tags [";
284 
285  // Iterate through string tags and convert them to the corresponding index
286  for(std::set<std::string>::iterator stag = yamltags.begin();
287  stag != yamltags.end(); ++stag)
288  {
289  // Finding the tag index from the tag string is kind of a drag, have to do a brute search
290  int newtag = str2tag(*stag);
291  // Check that valid tag was found (returns -1 if no tag found)
292  if(newtag==-1)
293  {
294  // If we didn't find the tag, raise an exception (probably means there was an error in the yaml file)
295  std::ostringstream errormsg;
296  errormsg << "If you have an entry something like this:"<< endl
297  << " Logger:" << endl
298  << " redirection:" << endl
299  << " [" << *stag << "] : \"blah.log\"" << endl
300  << "in your yaml file, then you probably should remove the last line. The LogTag" << endl
301  << "\"" << *stag << "\" is not recognised by the logger system. This commonly happens" << endl
302  << "if you try to redirect log output for a module that either doesn't exist, or was" << endl
303  << "ditched at cmake time." << endl;
304  logging_error().raise(LOCAL_INFO,errormsg.str());
305  }
306  *this << *stag <<", ";
307  tags.insert(newtag);
308  }
309  // Build the logger object
310  StdLogger* newlogger;
311  if(filename=="stdout")
312  {
313  newlogger = new StdLogger(std::cout);
314  }
315  else if(filename=="stderr")
316  {
317  newlogger = new StdLogger(std::cerr);
318  }
319  else
320  {
321  newlogger = new StdLogger(filename);
322  }
323  *this << "]; output is \"" << filename << "\"";
324  loggers[tags] = newlogger;
325  }
326  *this << EOM; // End message about loggers.
327  // Set logger objects ready for use and dump any buffered messages
328  loggers_readyQ = true;
329  empty_backlog();
330  }
331 
332  // Overload for initialise to allow input of logging instructions via maps
333  void LogMaster::initialise(std::map<std::set<std::string>, std::string>& loggerinfo)
334  {
335  std::vector<std::pair< std::set<std::string>, std::string >> loggerinfo_vec;
336  // Iterate through map and convert it to a vector of pairs
337  for(std::map<std::set<std::string>, std::string>::iterator infopair = loggerinfo.begin();
338  infopair != loggerinfo.end(); ++infopair)
339  {
340  loggerinfo_vec.push_back(std::make_pair(infopair->first,infopair->second));
341  }
342  // Run the 'normal' initialise function
343  initialise(loggerinfo_vec);
344  }
345 
346  // Overload for initialise, to make it easier to manually initialise the logger in standalone modules
347  void LogMaster::initialise(std::map<std::string, std::string>& loggerinfo)
348  {
349  std::map<std::set<std::string>, std::string> loggerinfo_set;
350  // Translate the string containing the tags into (map of) a set of tags
351  for(std::map<std::string, std::string>::iterator infopair = loggerinfo.begin();
352  infopair != loggerinfo.end(); ++infopair)
353  {
354  std::vector<std::string> tags_vec(Utils::delimiterSplit(infopair->first, ","));
355  std::set<std::string> tags_set(tags_vec.begin(), tags_vec.end());
356  loggerinfo_set[tags_set] = infopair->second;
357  }
358  // Run the 'normal' initialise function
359  initialise(loggerinfo_set);
360  }
361 
362  // Function to completely silence all log messages
364  {
365  loggers_readyQ = true;
366  silenced = true;
367  }
368 
369  // Turn logs back on
371  {
372  silenced = false;
373  }
374 
375  // Function to check if all log messages are silenced
377  {
378  return silenced;
379  }
380 
381  // Dump the backlog buffer to the 'finalsend' function
383  {
384  // See signal_handling.cpp for why we should not bail out in this situation
385  //if(omp_get_level()!=0)
386  //{
387  // // Raising an error from within the loggers within a parallel block probably will not end well, just use cout.
388  // #pragma omp critical(logmaster_empty_backlog)
389  // {
390  // std::cout << LOCAL_INFO << ": (rank "<<MPIrank<<") Tried to run empty_backlog() (in LogMaster) from inside an omp parallel block! This should not be possible, please file a bug report." << std::endl;
391  // exit(EXIT_FAILURE);
392  // }
393  //}
394 
395  for(int i=0; i<globlMaxThreads; i++)
396  {
397  for(size_t j=0; j<backlog[i].size(); j++)
398  {
399  finalsend(backlog[i].front());
400  backlog[i].pop_front();
401  }
402  }
403  }
404 
406  // Need a bunch of overloads of this to deal with
407  void LogMaster::send(const std::string& message)
408  {
409  std::set<LogTag> tags;
410  send(message,tags);
411  }
412 
413  void LogMaster::send(const std::string& message, LogTag tag1)
414  {
415  std::set<LogTag> tags;
416  tags.insert(tag1);
417  send(message,tags);
418  }
419 
420  void LogMaster::send(const std::string& message, LogTag tag1, LogTag tag2)
421  {
422  std::set<LogTag> tags;
423  tags.insert(tag1);
424  tags.insert(tag2);
425  send(message,tags);
426  }
427 
428  void LogMaster::send(const std::string& message, LogTag tag1, LogTag tag2, LogTag tag3)
429  {
430  std::set<LogTag> tags;
431  tags.insert(tag1);
432  tags.insert(tag2);
433  tags.insert(tag3);
434  send(message,tags);
435  }
436 
437  void LogMaster::send(const std::string& message, LogTag tag1, LogTag tag2, LogTag tag3, LogTag tag4)
438  {
439  std::set<LogTag> tags;
440  tags.insert(tag1);
441  tags.insert(tag2);
442  tags.insert(tag3);
443  tags.insert(tag4);
444  send(message,tags);
445  }
446 
447  void LogMaster::send(const std::string& message, LogTag tag1, LogTag tag2, LogTag tag3, LogTag tag4, LogTag tag5)
448  {
449  std::set<LogTag> tags;
450  tags.insert(tag1);
451  tags.insert(tag2);
452  tags.insert(tag3);
453  tags.insert(tag4);
454  tags.insert(tag5);
455  send(message,tags);
456  }
457 
458  //...add more as needed
459 
461  void LogMaster::send(const std::ostringstream& message)
462  {
463  std::set<LogTag> tags;
464  send(message.str(),tags);
465  }
466 
467  void LogMaster::send(const std::ostringstream& message, LogTag tag1)
468  {
469  std::set<LogTag> tags;
470  tags.insert(tag1);
471  send(message.str(),tags);
472  }
473 
474  void LogMaster::send(const std::ostringstream& message, LogTag tag1, LogTag tag2)
475  {
476  std::set<LogTag> tags;
477  tags.insert(tag1);
478  tags.insert(tag2);
479  send(message.str(),tags);
480  }
481 
482  void LogMaster::send(const std::ostringstream& message, LogTag tag1, LogTag tag2, LogTag tag3)
483  {
484  std::set<LogTag> tags;
485  tags.insert(tag1);
486  tags.insert(tag2);
487  tags.insert(tag3);
488  send(message.str(),tags);
489  }
490 
491  void LogMaster::send(const std::ostringstream& message, LogTag tag1, LogTag tag2, LogTag tag3, LogTag tag4)
492  {
493  std::set<LogTag> tags;
494  tags.insert(tag1);
495  tags.insert(tag2);
496  tags.insert(tag3);
497  tags.insert(tag4);
498  send(message.str(),tags);
499  }
500 
501  void LogMaster::send(const std::ostringstream& message, LogTag tag1, LogTag tag2, LogTag tag3, LogTag tag4, LogTag tag5)
502  {
503  std::set<LogTag> tags;
504  tags.insert(tag1);
505  tags.insert(tag2);
506  tags.insert(tag3);
507  tags.insert(tag4);
508  tags.insert(tag5);
509  send(message.str(),tags);
510  }
511 
512  //...add more as needed
513 
514 
515  // Overload to allow tags to be cast to ints, for delivery to the "full" send function
516  void LogMaster::send(const std::string& message, std::set<LogTag>& tags)
517  {
518  //std::set<int>& int_tags = static_cast< std::set<int> >(tags);
519  // I cannot seem to get the static cast to work, so just copying for now:
520  //std::set<int> int_tags(tags);
521  // Gah that seems not to work for the same reason, do one by one:
522  std::set<int> int_tags;
523  for(std::set<LogTag>::iterator tag = tags.begin(); tag != tags.end(); ++tag)
524  {
525  int_tags.insert(*tag); //static_cast<int>(*tag));
526  }
527  send(message, int_tags);
528  }
529 
531  // Ok this is the function that actual does things; the above are all just "syntatic sugar", as the cool kids say.
532  // In the end, this function should construct all the Message structs.
533  void LogMaster::send(const std::string& message, std::set<int>& tags)
534  {
535  // LogMaster keeps an internal map of all the logging objects, where the keys are sets of 'LogTag's, constructed according to the inifile. So to figure out where the message has to go, we just compare the "tags" to these keys; if any of these keys are a subset of our tags, then we send the message to that LogHub.
536  // Well almost. We have to seperate out the components first, because we can "send" a message to multiple components at once, but a direction command will never include two component tags (it is an error if it does).
537 
538  // Testing...
539  //std::cout<<"msg: "<<message<<std::endl;
540 
541  // Preliminary stuff
542 
543  // Get thread number
544  int i = omp_get_thread_num();
545 
546  // Automatically add the "def" (Default) tag so that the message definitely tries to go somewhere
547  tags.insert(def);
548 
549  // Automatically add the tags for the "current" module and backend to the tags list
550  if (current_module[i] != -1)
551  {
552  //std::cout<<"current_module="<<current_module<<"; adding tag "<<tag2str()[current_module]<<std::endl;
553  tags.insert(current_module[i]);
554  }
555  if (current_backend[i] != -1)
556  {
557  //std::cout<<"current_backend="<<current_backend<<"; adding tag "<<tag2str()[current_backend]<<std::endl;
558  tags.insert(current_backend[i]);
559  }
560 
561  // If the loggers have not yet been initialised, buffer the message
562  if(omp_get_level()!=0 or not loggers_readyQ)
563  {
564  backlog[i].emplace_back(message,tags); //time stamp automatically added NOW
565  }
566  else
567  {
568  if(omp_get_level()==0) empty_backlog();
569  finalsend(Message(message,tags)); //time stamp automatically added NOW
570  }
571  } // end LogHub::send
572 
574  void LogMaster::finalsend(const Message& mail)
575  {
576  // Check the 'ignore' set; if any of the specified tags are in this set, then do nothing more, i.e. ignore the message.
577  // (need to add extra stuff to ignore modules and backends, since these cannot be normal tags)
578  // Also ignore the message if logs have been 'silenced'.
579  if( silenced or not Utils::is_disjoint(mail.tags, ignore) )
580  {
581  //std::cout<<"Ignoring message..."<<std::endl;
582  return;
583  }
584 
585  // If the "cout" tag is seen, repeat the message to stdout
586  if(mail.tags.find(repeat_to_cout) != mail.tags.end()) std::cout << mail.message << std::endl;
587 
588  // If the "cerr" tag is seen, repeat the message to sterr
589  if(mail.tags.find(repeat_to_cerr) != mail.tags.end()) std::cerr << mail.message << std::endl;
590 
591  // Sort the tags
592  const SortedMessage sortedmsg(mail);
593 
594  // Main loop for message distribution
595 
596  // Loop through the map of loggers and see if any of them match subsets of 'key'.
597  for(std::map<std::set<int>,BaseLogger*>::iterator keyvalue = loggers.begin(); keyvalue != loggers.end(); ++keyvalue)
598  {
599  // if set1 includes set2
600  if( std::includes(mail.tags.begin(), mail.tags.end(),
601  (keyvalue->first).begin(), (keyvalue->first).end()) )
602  {
603  // Matching logger object found! Send it the sorted message object
604  (keyvalue->second)->write(sortedmsg);
605  }
606  } //end loop over loggers
607  } // end LogMaster::finalsend
608 
610  void LogMaster::send(const std::ostringstream& message, std::set<LogTag>& tags)
611  {
612  send(message.str(), tags);
613  }
614 
615  void LogMaster::send(const std::ostringstream& message, std::set<int>& tags)
616  {
617  send(message.str(), tags);
618  }
619 
621  {
622  init_memory();
623  current_module[omp_get_thread_num()] = i;
624  }
625 
627  {
628  init_memory();
629  current_module[omp_get_thread_num()] = -1;
630  leaving_backend();
631  }
632 
634  {
635  init_memory();
636  current_backend[omp_get_thread_num()] = i;
637  *this<<"Setting current_backend="<<i;
638  *this<<logs<<debug<<EOM;
639  }
641  {
642  init_memory();
643  int cb_test;
644  cb_test = current_backend[omp_get_thread_num()];
645  if (cb_test == -1) return;
646  current_backend[omp_get_thread_num()] = -1;
647  *this<<"Restoring current_backend="<<-1;
648  *this<<logs<<debug<<EOM;
649  }
650 
652  void LogMaster::input(const LogTag& tag)
653  {
654  init_memory();
655  streamtags[omp_get_thread_num()].insert(tag);
656  }
657 
660  {
661  init_memory();
662  size_t i = omp_get_thread_num();
663  // Collect the stream and tags, then send the message
664  send(stream[i].str(), streamtags[i]);
665  // Clear stream and tags for next message;
666  stream[i].str(std::string()); //TODO: check that this works properly on all compilers...
667  streamtags[i].clear();
668  }
669 
671  void LogMaster::input(const std::string& in)
672  {
673  init_memory();
674  stream[omp_get_thread_num()] << in;
675  }
676 
678  void LogMaster::input(const manip1 fp)
679  {
680  init_memory();
681  stream[omp_get_thread_num()] << fp;
682  }
683 
684  void LogMaster::input(const manip2 fp)
685  {
686  init_memory();
687  stream[omp_get_thread_num()] << fp;
688  }
689 
690  void LogMaster::input(const manip3 fp)
691  {
692  init_memory();
693  stream[omp_get_thread_num()] << fp;
694  }
695 
697 
698  } //end namespace Logging
699 } // end namespace Gambit
std::deque< Message > * backlog
Messages sent before logger objects are created will be buffered Same for messages sent while inside ...
Definition: logmaster.hpp:183
structure for storing log messages and metadata after tags are sorted
Definition: logging.hpp:89
void init_memory()
Initialise dynamic memory required for thread safety.
Definition: logmaster.cpp:93
bool log_debug_messages
Flag to ignore Debug tagged messages.
Definition: logmaster.hpp:162
bool loggers_readyQ
Flag to set whether loggers have been initialised not.
Definition: logmaster.hpp:153
void send(const std::string &)
Main logging function (user-friendly overloaded version)
Definition: logmaster.cpp:407
Header for logging classes.
std::set< int > tags
Definition: logging.hpp:77
structure for storing log messages and metadata
Definition: logging.hpp:74
Helper functions for dealing with POSIX signals.
#define LOCAL_INFO
Definition: local_info.hpp:34
Logger virtual base class.
Definition: logging.hpp:109
std::map< std::set< int >, BaseLogger * > loggers
Map to identify loggers.
Definition: logmaster.hpp:147
void entering_module(int)
Set the internal variables tracking which module and/or backend is currently running.
Definition: logmaster.cpp:620
int str2tag(const std::string &)
Definition: logging.cpp:152
EXPORT_SYMBOLS str construct_runtime_scratch(bool fail_on_mpi_uninitialised=true)
Construct the path to the run-specific scratch directory This version is safe to call from a destruct...
void emit_backlog(bool verbose)
Print the backlogs to the default log file.
Definition: logmaster.cpp:137
~LogMaster()
Destructor If errors happen before the inifile is loaded, we need to dump the log messages (that have...
Definition: logmaster.cpp:171
General small utility functions.
LogMaster()
Default constructor.
Definition: logmaster.cpp:55
void empty_backlog()
Empty the backlog buffer to the &#39;send&#39; function.
Definition: logmaster.cpp:382
std::ostream &(* manip1)(std::ostream &)
Definition: logger.hpp:57
int * current_module
Variables that need to be threadsafe.
Definition: logmaster.hpp:174
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
const bool verbose
Definition: logging.cpp:52
std::ostringstream * stream
Buffer variables needed for stream logging.
Definition: logmaster.hpp:178
bool is_disjoint(const Set1 &set1, const Set2 &set2)
Test if two sets are disjoint (works on any sorted std container I think)
Logger for &#39;standard&#39; messages.
Definition: logging.hpp:123
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
std::set< int > ignore
Global ignore set; if these tags/integers are seen, ignore messages containing them.
Definition: logmaster.hpp:150
void initialise(std::vector< std::pair< std::set< std::string >, std::string >> &)
Function to construct loggers according to blueprint.
Definition: logmaster.cpp:227
Header for logging classes.
Special (empty) struct for signalling end of message to LogMaster stream.
Definition: logger.hpp:44
bool separate_file_per_process
Flag to store log messages for different processes in separate files.
Definition: logmaster.hpp:159
int MPIrank
MPI variables.
Definition: logmaster.hpp:165
A simple C++ wrapper for the MPI C bindings.
EXPORT_SYMBOLS std::vector< str > delimiterSplit(str s, str delim)
Split a string into a vector of strings, using a delimiter, and removing any whitespace around the de...
Exception objects required for standalone compilation.
bool silenced
Flag to silence logger.
Definition: logmaster.hpp:156
error & logging_error()
Logging errors.
std::set< int > * streamtags
Definition: logmaster.hpp:179
void input(const std::string &)
Functions for stream input (actual stream operators which use these are defined in logger...
Definition: logmaster.cpp:671
int globlMaxThreads
Max number of threads that could potentially be running.
Definition: logmaster.hpp:169
TODO: see if we can use this one:
Definition: Analysis.hpp:33
std::ios_base &(* manip3)(std::ios_base &)
Definition: logger.hpp:60
void finalsend(const Message &)
Version of send function used by buffer dump; skips all the tag modification stuff.
Definition: logmaster.cpp:574
ios_type &(* manip2)(ios_type &)
Definition: logger.hpp:59