gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-252-gf9a3f78
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  if (verbose) std::cout<<"Logger was never initialised! Creating default log messenger..."<<std::endl;
153  StdLogger* deflogger = new StdLogger(Utils::runtime_scratch() + "default.log");
154  std::set<int> deftag;
155  deftag.insert(def);
156  loggers[deftag] = deflogger;
157  loggers_readyQ = true;
158  if (verbose) std::cout<<"Log messages will be delivered to '" << Utils::runtime_scratch() << "default.log'"<<std::endl;
159  }
160  // Dump buffered messages
161  empty_backlog();
162  }
163  }
164  }
165 
166  // Destructor
168  {
169  // See signal_handling.cpp for why we should not bail out in this situation
170  // // LogMaster should not be destructed from within a parallel block. This check helps detect such a bug.
171  // if(omp_get_level()!=0)
172  // {
173  // // Raising an error from within the loggers within a parallel block probably will not end well, just use cout.
174  // #pragma omp critical(logmaster_destructor)
175  // {
176  // 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;
177  // exit(EXIT_FAILURE);
178  // }
179  // }
180 
181  if(not silenced)
182  {
183  // Check if there is anything in the output stream that has not been sent, and send it if there is
184  // (these messages will get backlogged because they are sent (ended) from a parallel block, but we are
185  // about to empty the backlogs anyway so that is no problem).
186  if (stream != NULL and streamtags!= NULL)
187  {
188  #pragma omp parallel
189  {
190  int i = omp_get_thread_num();
191  if (not stream[i].str().empty() or not streamtags[i].empty())
192  {
193  *this <<"#### NO EOM RECEIVED FOR MESSAGE FROM THREAD ("<<i<<"): MESSAGE MAY BE INCOMPLETE ####"<<warn<<EOM;
194  }
195  }
196  }
197 
198  // Output the message backlogs if needed
199  emit_backlog(true);
200 
201  }
202 
203  // Delete logger objects
204  for(std::map<std::set<int>,BaseLogger*>::iterator keyvalue = loggers.begin(); keyvalue != loggers.end(); ++keyvalue)
205  {
206  // Ensure their filestreams have been flushed before we delete them.
207  // (not sure if this is really needed, I think the message is in the operating systems domain by this point)
208  // Edit: I think I have decided that this is unnecessary
209  //(keyvalue->second)->flush();
210  delete (keyvalue->second);
211  }
212 
213  // Delete the thread variables
214  if (stream != NULL) delete [] stream;
215  if (streamtags != NULL) delete [] streamtags;
216  if (backlog != NULL) delete [] backlog;
217  if (current_module !=NULL) delete [] current_module;
218  if (current_backend !=NULL) delete [] current_backend;
219  }
220 
222  // 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.
223  void LogMaster::initialise(std::vector<std::pair< std::set<std::string>, std::string >>& loggerinfo)
224  {
225  // Fix up the MPI variables
226  #ifdef WITH_MPI
227  if(GMPI::Is_initialized())
228  {
229  GMPI::Comm COMM_WORLD;
230  MPIsize = COMM_WORLD.Get_size();
231  MPIrank = COMM_WORLD.Get_rank();
232  }
233  #endif
234 
235  // Check options and inform user what they are
236  if (MPIrank == 0) std::cout << "Initialising logger...";
237  // NOTE! Option to merge log files no longer exists. Concurrent write access is a nightmare. Log messages were
238  // being lost due to different processes overwriting each others data, and using the FileLock system doesn't
239  // help because the issue is the file pointer location. To fix that, files have to be closed and reopened
240  // constantly, which creates a lot of overhead. On top of this, it is very hard to overwrite old log files at the
241  // beginning of the run since we have to coordinate who creates the file at the beginning of the run, would have
242  // to add a bunch of message passing. Overall it just isn't worth it.
243  // #ifdef WITH_MPI
244  // std::cout << std::endl << " separate_file_per_process = ";
245  // 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)"; }
246  // 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)";}
247  // #endif
248  std::ostringstream logmsg;
249  logmsg << " log_debug_messages = ";
250  if(log_debug_messages) logmsg << "true; log messages tagged as 'Debug' WILL be logged. " << endl << "WARNING: This may lead to very large log files!";
251  else
252  {
253  // Add "Debug" tag to the global ignore list
254  ignore.insert(LogTag::debug);
255  logmsg << "false; log messages tagged as 'Debug' will NOT be logged";
256  }
257 
258  if (MPIrank == 0) std::cout << logmsg.str() << std::endl;
259  *this << LogTag::logs << LogTag::debug << logmsg.str() << EOM;
260 
261  // Iterate through map and build the logger objects
262  for(std::vector<std::pair< std::set<std::string>, std::string >>::iterator infopair = loggerinfo.begin();
263  infopair != loggerinfo.end(); ++infopair)
264  {
265  std::set<std::string> yamltags = infopair->first;
266  std::string filename = infopair->second;
267  std::set<int> tags;
268 
270  and filename!="stdout" and filename!="stderr")
271  {
272  std::ostringstream unique_filename;
273  unique_filename << filename << "_" << MPIrank;
274  filename = unique_filename.str();
275  }
276 
277  // Log the loggers being created :)
278  // (will be put into a preliminary buffer until loggers are all constructed)
279  *this << LogTag::logs << LogTag::debug << std::endl << "Creating logger for tags [";
280 
281  // Iterate through string tags and convert them to the corresponding index
282  for(std::set<std::string>::iterator stag = yamltags.begin();
283  stag != yamltags.end(); ++stag)
284  {
285  // Finding the tag index from the tag string is kind of a drag, have to do a brute search
286  int newtag = str2tag(*stag);
287  // Check that valid tag was found (returns -1 if no tag found)
288  if(newtag==-1)
289  {
290  // If we didn't find the tag, raise an exception (probably means there was an error in the yaml file)
291  std::ostringstream errormsg;
292  errormsg << "If you have an entry something like this:"<< endl
293  << " Logger:" << endl
294  << " redirection:" << endl
295  << " [" << *stag << "] : \"blah.log\"" << endl
296  << "in your yaml file, then you probably should remove the last line. The LogTag" << endl
297  << "\"" << *stag << "\" is not recognised by the logger system. This commonly happens" << endl
298  << "if you try to redirect log output for a module that either doesn't exist, or was" << endl
299  << "ditched at cmake time." << endl;
300  logging_error().raise(LOCAL_INFO,errormsg.str());
301  }
302  *this << *stag <<", ";
303  tags.insert(newtag);
304  }
305  // Build the logger object
306  StdLogger* newlogger;
307  if(filename=="stdout")
308  {
309  newlogger = new StdLogger(std::cout);
310  }
311  else if(filename=="stderr")
312  {
313  newlogger = new StdLogger(std::cerr);
314  }
315  else
316  {
317  newlogger = new StdLogger(filename);
318  }
319  *this << "]; output is \"" << filename << "\"";
320  loggers[tags] = newlogger;
321  }
322  *this << EOM; // End message about loggers.
323  // Set logger objects ready for use and dump any buffered messages
324  loggers_readyQ = true;
325  empty_backlog();
326  }
327 
328  // Overload for initialise to allow input of logging instructions via maps
329  void LogMaster::initialise(std::map<std::set<std::string>, std::string>& loggerinfo)
330  {
331  std::vector<std::pair< std::set<std::string>, std::string >> loggerinfo_vec;
332  // Iterate through map and convert it to a vector of pairs
333  for(std::map<std::set<std::string>, std::string>::iterator infopair = loggerinfo.begin();
334  infopair != loggerinfo.end(); ++infopair)
335  {
336  loggerinfo_vec.push_back(std::make_pair(infopair->first,infopair->second));
337  }
338  // Run the 'normal' initialise function
339  initialise(loggerinfo_vec);
340  }
341 
342  // Overload for initialise, to make it easier to manually initialise the logger in standalone modules
343  void LogMaster::initialise(std::map<std::string, std::string>& loggerinfo)
344  {
345  std::map<std::set<std::string>, std::string> loggerinfo_set;
346  // Translate the string containing the tags into (map of) a set of tags
347  for(std::map<std::string, std::string>::iterator infopair = loggerinfo.begin();
348  infopair != loggerinfo.end(); ++infopair)
349  {
350  std::vector<std::string> tags_vec(Utils::delimiterSplit(infopair->first, ","));
351  std::set<std::string> tags_set(tags_vec.begin(), tags_vec.end());
352  loggerinfo_set[tags_set] = infopair->second;
353  }
354  // Run the 'normal' initialise function
355  initialise(loggerinfo_set);
356  }
357 
358  // Function to completely silence all log messages
360  {
361  loggers_readyQ = true;
362  silenced = true;
363  }
364 
365  // Turn logs back on
367  {
368  silenced = false;
369  }
370 
371  // Function to check if all log messages are silenced
373  {
374  return silenced;
375  }
376 
377  // Dump the backlog buffer to the 'finalsend' function
379  {
380  // See signal_handling.cpp for why we should not bail out in this situation
381  //if(omp_get_level()!=0)
382  //{
383  // // Raising an error from within the loggers within a parallel block probably will not end well, just use cout.
384  // #pragma omp critical(logmaster_empty_backlog)
385  // {
386  // 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;
387  // exit(EXIT_FAILURE);
388  // }
389  //}
390 
391  for(int i=0; i<globlMaxThreads; i++)
392  {
393  for(size_t j=0; j<backlog[i].size(); j++)
394  {
395  finalsend(backlog[i].front());
396  backlog[i].pop_front();
397  }
398  }
399  }
400 
402  // Need a bunch of overloads of this to deal with
403  void LogMaster::send(const std::string& message)
404  {
405  std::set<LogTag> tags;
406  send(message,tags);
407  }
408 
409  void LogMaster::send(const std::string& message, LogTag tag1)
410  {
411  std::set<LogTag> tags;
412  tags.insert(tag1);
413  send(message,tags);
414  }
415 
416  void LogMaster::send(const std::string& message, LogTag tag1, LogTag tag2)
417  {
418  std::set<LogTag> tags;
419  tags.insert(tag1);
420  tags.insert(tag2);
421  send(message,tags);
422  }
423 
424  void LogMaster::send(const std::string& message, LogTag tag1, LogTag tag2, LogTag tag3)
425  {
426  std::set<LogTag> tags;
427  tags.insert(tag1);
428  tags.insert(tag2);
429  tags.insert(tag3);
430  send(message,tags);
431  }
432 
433  void LogMaster::send(const std::string& message, LogTag tag1, LogTag tag2, LogTag tag3, LogTag tag4)
434  {
435  std::set<LogTag> tags;
436  tags.insert(tag1);
437  tags.insert(tag2);
438  tags.insert(tag3);
439  tags.insert(tag4);
440  send(message,tags);
441  }
442 
443  void LogMaster::send(const std::string& message, LogTag tag1, LogTag tag2, LogTag tag3, LogTag tag4, LogTag tag5)
444  {
445  std::set<LogTag> tags;
446  tags.insert(tag1);
447  tags.insert(tag2);
448  tags.insert(tag3);
449  tags.insert(tag4);
450  tags.insert(tag5);
451  send(message,tags);
452  }
453 
454  //...add more as needed
455 
457  void LogMaster::send(const std::ostringstream& message)
458  {
459  std::set<LogTag> tags;
460  send(message.str(),tags);
461  }
462 
463  void LogMaster::send(const std::ostringstream& message, LogTag tag1)
464  {
465  std::set<LogTag> tags;
466  tags.insert(tag1);
467  send(message.str(),tags);
468  }
469 
470  void LogMaster::send(const std::ostringstream& message, LogTag tag1, LogTag tag2)
471  {
472  std::set<LogTag> tags;
473  tags.insert(tag1);
474  tags.insert(tag2);
475  send(message.str(),tags);
476  }
477 
478  void LogMaster::send(const std::ostringstream& message, LogTag tag1, LogTag tag2, LogTag tag3)
479  {
480  std::set<LogTag> tags;
481  tags.insert(tag1);
482  tags.insert(tag2);
483  tags.insert(tag3);
484  send(message.str(),tags);
485  }
486 
487  void LogMaster::send(const std::ostringstream& message, LogTag tag1, LogTag tag2, LogTag tag3, LogTag tag4)
488  {
489  std::set<LogTag> tags;
490  tags.insert(tag1);
491  tags.insert(tag2);
492  tags.insert(tag3);
493  tags.insert(tag4);
494  send(message.str(),tags);
495  }
496 
497  void LogMaster::send(const std::ostringstream& message, LogTag tag1, LogTag tag2, LogTag tag3, LogTag tag4, LogTag tag5)
498  {
499  std::set<LogTag> tags;
500  tags.insert(tag1);
501  tags.insert(tag2);
502  tags.insert(tag3);
503  tags.insert(tag4);
504  tags.insert(tag5);
505  send(message.str(),tags);
506  }
507 
508  //...add more as needed
509 
510 
511  // Overload to allow tags to be cast to ints, for delivery to the "full" send function
512  void LogMaster::send(const std::string& message, std::set<LogTag>& tags)
513  {
514  //std::set<int>& int_tags = static_cast< std::set<int> >(tags);
515  // I cannot seem to get the static cast to work, so just copying for now:
516  //std::set<int> int_tags(tags);
517  // Gah that seems not to work for the same reason, do one by one:
518  std::set<int> int_tags;
519  for(std::set<LogTag>::iterator tag = tags.begin(); tag != tags.end(); ++tag)
520  {
521  int_tags.insert(*tag); //static_cast<int>(*tag));
522  }
523  send(message, int_tags);
524  }
525 
527  // Ok this is the function that actual does things; the above are all just "syntatic sugar", as the cool kids say.
528  // In the end, this function should construct all the Message structs.
529  void LogMaster::send(const std::string& message, std::set<int>& tags)
530  {
531  // 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.
532  // 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).
533 
534  // Testing...
535  //std::cout<<"msg: "<<message<<std::endl;
536 
537  // Preliminary stuff
538 
539  // Get thread number
540  int i = omp_get_thread_num();
541 
542  // Automatically add the "def" (Default) tag so that the message definitely tries to go somewhere
543  tags.insert(def);
544 
545  // Automatically add the tags for the "current" module and backend to the tags list
546  if (current_module[i] != -1)
547  {
548  //std::cout<<"current_module="<<current_module<<"; adding tag "<<tag2str()[current_module]<<std::endl;
549  tags.insert(current_module[i]);
550  }
551  if (current_backend[i] != -1)
552  {
553  //std::cout<<"current_backend="<<current_backend<<"; adding tag "<<tag2str()[current_backend]<<std::endl;
554  tags.insert(current_backend[i]);
555  }
556 
557  // If the loggers have not yet been initialised, buffer the message
558  if(omp_get_level()!=0 or not loggers_readyQ)
559  {
560  backlog[i].emplace_back(message,tags); //time stamp automatically added NOW
561  }
562  else
563  {
564  if(omp_get_level()==0) empty_backlog();
565  finalsend(Message(message,tags)); //time stamp automatically added NOW
566  }
567  } // end LogHub::send
568 
570  void LogMaster::finalsend(const Message& mail)
571  {
572  // Check the 'ignore' set; if any of the specified tags are in this set, then do nothing more, i.e. ignore the message.
573  // (need to add extra stuff to ignore modules and backends, since these cannot be normal tags)
574  // Also ignore the message if logs have been 'silenced'.
575  if( silenced or not Utils::is_disjoint(mail.tags, ignore) )
576  {
577  //std::cout<<"Ignoring message..."<<std::endl;
578  return;
579  }
580 
581  // If the "cout" tag is seen, repeat the message to stdout
582  if(mail.tags.find(repeat_to_cout) != mail.tags.end()) std::cout << mail.message << std::endl;
583 
584  // If the "cerr" tag is seen, repeat the message to sterr
585  if(mail.tags.find(repeat_to_cerr) != mail.tags.end()) std::cerr << mail.message << std::endl;
586 
587  // Sort the tags
588  const SortedMessage sortedmsg(mail);
589 
590  // Main loop for message distribution
591 
592  // Loop through the map of loggers and see if any of them match subsets of 'key'.
593  for(std::map<std::set<int>,BaseLogger*>::iterator keyvalue = loggers.begin(); keyvalue != loggers.end(); ++keyvalue)
594  {
595  // if set1 includes set2
596  if( std::includes(mail.tags.begin(), mail.tags.end(),
597  (keyvalue->first).begin(), (keyvalue->first).end()) )
598  {
599  // Matching logger object found! Send it the sorted message object
600  (keyvalue->second)->write(sortedmsg);
601  }
602  } //end loop over loggers
603  } // end LogMaster::finalsend
604 
606  void LogMaster::send(const std::ostringstream& message, std::set<LogTag>& tags)
607  {
608  send(message.str(), tags);
609  }
610 
611  void LogMaster::send(const std::ostringstream& message, std::set<int>& tags)
612  {
613  send(message.str(), tags);
614  }
615 
617  {
618  init_memory();
619  current_module[omp_get_thread_num()] = i;
620  }
621 
623  {
624  init_memory();
625  current_module[omp_get_thread_num()] = -1;
626  leaving_backend();
627  }
628 
630  {
631  init_memory();
632  current_backend[omp_get_thread_num()] = i;
633  *this<<"Setting current_backend="<<i;
634  *this<<logs<<debug<<EOM;
635  }
637  {
638  init_memory();
639  int cb_test;
640  cb_test = current_backend[omp_get_thread_num()];
641  if (cb_test == -1) return;
642  current_backend[omp_get_thread_num()] = -1;
643  *this<<"Restoring current_backend="<<-1;
644  *this<<logs<<debug<<EOM;
645  }
646 
648  void LogMaster::input(const LogTag& tag)
649  {
650  init_memory();
651  streamtags[omp_get_thread_num()].insert(tag);
652  }
653 
656  {
657  init_memory();
658  size_t i = omp_get_thread_num();
659  // Collect the stream and tags, then send the message
660  send(stream[i].str(), streamtags[i]);
661  // Clear stream and tags for next message;
662  stream[i].str(std::string()); //TODO: check that this works properly on all compilers...
663  streamtags[i].clear();
664  }
665 
667  void LogMaster::input(const std::string& in)
668  {
669  init_memory();
670  stream[omp_get_thread_num()] << in;
671  }
672 
674  void LogMaster::input(const manip1 fp)
675  {
676  init_memory();
677  stream[omp_get_thread_num()] << fp;
678  }
679 
680  void LogMaster::input(const manip2 fp)
681  {
682  init_memory();
683  stream[omp_get_thread_num()] << fp;
684  }
685 
686  void LogMaster::input(const manip3 fp)
687  {
688  init_memory();
689  stream[omp_get_thread_num()] << fp;
690  }
691 
693 
694  } //end namespace Logging
695 } // 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:403
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:616
int str2tag(const std::string &)
Definition: logging.cpp:152
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:167
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:378
std::ostream &(* manip1)(std::ostream &)
Definition: logger.hpp:56
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:99
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:223
Header for logging classes.
Special (empty) struct for signalling end of message to LogMaster stream.
Definition: logger.hpp:43
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
EXPORT_SYMBOLS const str & runtime_scratch()
Return the path the the run-specific scratch directory.
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:667
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:59
void finalsend(const Message &)
Version of send function used by buffer dump; skips all the tag modification stuff.
Definition: logmaster.cpp:570
ios_type &(* manip2)(ios_type &)
Definition: logger.hpp:58