CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ThreadSafeLogMessageLoggerScribe.cc
Go to the documentation of this file.
1 // ----------------------------------------------------------------------
2 //
3 // ThreadSafeLogMessageLoggerScribe.cc
4 //
5 // NOTE: This was originally copied from MessageLoggerScribe but removed
6 // the potential use of the ThreadQueue. MessageLoggerScribe was not
7 // modified since it was decided we might have to keep the old behaviour
8 // around for 'legacy' reasons.
9 //
10 // ----------------------------------------------------------------------
11 
18 
22 #include "FWCore/MessageLogger/interface/MessageDrop.h" // change log 37
23 #include "FWCore/MessageLogger/interface/ELseverityLevel.h" // change log 37
24 
27 
28 #include <algorithm>
29 #include <cassert>
30 #include <fstream>
31 #include <string>
32 #include <signal.h>
33 
34 using std::cerr;
35 
36 namespace edm {
37  namespace service {
38 
39 
41  : admin_p ( new ELadministrator() )
42  , early_dest( admin_p->attach(ELoutput(std::cerr, false)) )
43  , file_ps ( )
44  , job_pset_p( )
45  , extern_dests( )
46  , clean_slate_configuration( true )
47  , active( true )
48  , purge_mode (false) // changeLog 32
49  , count (false) // changeLog 32
50  , m_messageBeingSent(false)
51  {
52  }
53 
55  {
56  //if there are any waiting message, finish them off
57  ErrorObj* errorobj_p=nullptr;
58  std::vector<std::string> categories;
59  while(m_waitingMessages.try_pop(errorobj_p)) {
60  if(not purge_mode) {
61  categories.clear();
62  parseCategories(errorobj_p->xid().id, categories);
63  for (unsigned int icat = 0; icat < categories.size(); ++icat) {
64  errorobj_p->setID(categories[icat]);
65  admin_p->log( *errorobj_p ); // route the message text
66  }
67  }
68  delete errorobj_p;
69  }
70 
71  admin_p->finish();
72  assert( extern_dests.empty() ); // nothing to do
73  }
74 
75  void
78  void * operand)
79  {
80  switch(opcode) { // interpret the work item
81  default: {
82  assert(false); // can't happen (we certainly hope!)
83  break;
84  }
86  break;
87  }
89  ErrorObj * errorobj_p = static_cast<ErrorObj *>(operand);
90  try {
91  if(active && !purge_mode){
92  log (errorobj_p);
93  }
94  }
95  catch(cms::Exception& e)
96  {
97  ++count;
98  std::cerr << "ThreadSafeLogMessageLoggerScribe caught " << count
99  << " cms::Exceptions, text = \n"
100  << e.what() << "\n";
101 
102  if(count > 25)
103  {
104  cerr << "MessageLogger will no longer be processing "
105  << "messages due to errors (entering purge mode).\n";
106  purge_mode = true;
107  }
108  }
109  catch(...)
110  {
111  std::cerr << "ThreadSafeLogMessageLoggerScribe caught an unknown exception and "
112  << "will no longer be processing "
113  << "messages. (entering purge mode)\n";
114  purge_mode = true;
115  }
116  break;
117  }
118  case MessageLoggerQ::CONFIGURE: { // changelog 17
119  job_pset_p = std::shared_ptr<PSet>(static_cast<PSet*>(operand)); // propagate_const<T> has no reset() function
121  break;
122  }
124  try {
125  extern_dests.push_back( static_cast<NamedDestination *>(operand) );
127  }
128  catch(cms::Exception& e) // change log 21
129  {
130  std::cerr << "ThreadSafeLogMessageLoggerScribe caught a cms::Exception "
131  << "during extern dest configuration:\n"
132  << e.what() << "\n"
133  << "This is a serious problem, and the extern dest "
134  << "will not be produced.\n"
135  << "However, the rest of the logger continues to run.\n";
136  }
137  catch(...) // change log 21
138  {
139  std::cerr << "ThreadSafeLogMessageLoggerScribe caught unkonwn exception type\n"
140  << "during extern dest configuration. "
141  << "This is a serious problem, and the extern dest "
142  << "will not be produced.\n"
143  << "The rest of the logger will attempt to continue to run.\n";
144  }
145  break;
146  }
148  assert( operand == 0 );
149  try {
151  }
152  catch(cms::Exception& e)
153  {
154  std::cerr << "ThreadSafeLogMessageLoggerScribe caught exception "
155  << "during summarize:\n"
156  << e.what() << "\n";
157  }
158  catch(...)
159  {
160  std::cerr << "ThreadSafeLogMessageLoggerScribe caught unkonwn exception type "
161  << "during summarize. (Ignored)\n";
162  }
163  break;
164  }
165  case MessageLoggerQ::JOBMODE: { // change log 24
166  std::string* jobMode_p =
167  static_cast<std::string*>(operand);
168  JobMode jm = MessageLoggerDefaults::mode(*jobMode_p);
171  // Note - since messageLoggerDefaults is a value_ptr,
172  // there is no concern about deleting here.
173  delete jobMode_p; // dispose of the message text
174  // which will have been new-ed
175  // in MessageLogger.cc (service version)
176  break;
177  }
179  assert( operand == 0 );
180  active = false;
181  break;
182  }
183  case MessageLoggerQ::FLUSH_LOG_Q: { // changelog 26
184  break;
185  }
186  case MessageLoggerQ::GROUP_STATS: { // change log 27
187  std::string* cat_p =
188  static_cast<std::string*>(operand);
190  delete cat_p; // dispose of the message text
191  break;
192  }
193  case MessageLoggerQ::FJR_SUMMARY: { // changelog 29
194  std::map<std::string, double> * smp =
195  static_cast<std::map<std::string, double> *>(operand);
197  break;
198  }
199  } // switch
200 
201  } // ThreadSafeLogMessageLoggerScribe::runCommand(opcode, operand)
202 
204  bool expected = false;
205  std::unique_ptr<ErrorObj> obj(errorobj_p);
206  if(m_messageBeingSent.compare_exchange_strong(expected,true)) {
207  std::vector<std::string> categories;
208  parseCategories(errorobj_p->xid().id, categories);
209  for (unsigned int icat = 0; icat < categories.size(); ++icat) {
210  errorobj_p->setID(categories[icat]);
211  admin_p->log( *errorobj_p ); // route the message text
212  }
213  //process any waiting messages
214  errorobj_p=nullptr;
215  while(not purge_mode and m_waitingMessages.try_pop(errorobj_p)) {
216  obj.reset(errorobj_p);
217  categories.clear();
218  parseCategories(errorobj_p->xid().id, categories);
219  for (unsigned int icat = 0; icat < categories.size(); ++icat) {
220  errorobj_p->setID(categories[icat]);
221  admin_p->log( *errorobj_p ); // route the message text
222  }
223  }
224  m_messageBeingSent.store(false);
225  } else {
226  obj.release();
227  m_waitingMessages.push(errorobj_p);
228  }
229  }
230 
231  void
233  {
234  vString empty_vString;
235  String empty_String;
236  PSet empty_PSet;
237 
238  // The following is present to test pre-configuration message handling:
239  String preconfiguration_message
240  = getAparameter<String>
241  (*job_pset_p, "generate_preconfiguration_message", empty_String);
242  if (preconfiguration_message != empty_String) {
243  // To test a preconfiguration message without first going thru the
244  // configuration we are about to do, we issue the message (so it sits
245  // on the queue), then copy the processing that the LOG_A_MESSAGE case
246  // does. We suppress the timestamp to allow for automated unit testing.
248  LogError ("preconfiguration") << preconfiguration_message;
249  }
250 
251  if ( !stream_ps.empty() ) {
252  LogWarning ("multiLogConfig")
253  << "The message logger has been configured multiple times";
254  clean_slate_configuration = false; // Change Log 22
255  }
256  configure_ordinary_destinations(); // Change Log 16
257  configure_statistics(); // Change Log 16
258 
260 
261  } // ThreadSafeLogMessageLoggerScribe::configure_errorlog()
262 
263 
264 
265 
266  void
268  , String const & filename
269  )
270  {
271  static const int NO_VALUE_SET = -45654; // change log 2
272  vString empty_vString;
273  PSet empty_PSet;
274  String empty_String;
275 
276  // Defaults: // change log 3a
277  const std::string COMMON_DEFAULT_THRESHOLD = "INFO";
278  const int COMMON_DEFAULT_LIMIT = NO_VALUE_SET;
279  const int COMMON_DEFAULT_INTERVAL = NO_VALUE_SET; // change log 6
280  const int COMMON_DEFAULT_TIMESPAN = NO_VALUE_SET;
281 
282  char const* severity_array[] = {"WARNING", "INFO", "ERROR", "DEBUG"};
283  vString const severities(severity_array+0, severity_array+4);
284 
285  // grab list of categories
287  = getAparameter<vString>(*job_pset_p, "categories", empty_vString);
288 
289  // grab list of messageIDs -- these are a synonym for categories
290  // Note -- the use of messageIDs is deprecated in favor of categories
291  {
292  vString messageIDs
293  = getAparameter<vString>(*job_pset_p, "messageIDs", empty_vString);
294 
295  // combine the lists, not caring about possible duplicates (for now)
296  copy_all( messageIDs, std::back_inserter(categories) );
297  } // no longer need messageIDs
298 
299  // grab list of hardwired categories (hardcats) -- these are to be added
300  // to the list of categories -- change log 24
301  {
302  std::vector<std::string> hardcats = messageLoggerDefaults->categories;
303  // combine the lists, not caring about possible duplicates (for now)
304  copy_all( hardcats, std::back_inserter(categories) );
305  } // no longer need hardcats
306 
307  // grab default threshold common to all destinations
308  String default_threshold
309  = getAparameter<String>(*job_pset_p, "threshold", empty_String);
310  // change log 3a
311  // change log 24
312 
313  // grab default limit/interval/timespan common to all destinations/categories:
314  PSet default_pset
315  = getAparameter<PSet>(*job_pset_p, "default", empty_PSet);
316  int default_limit
317  = getAparameter<int>(default_pset, "limit", COMMON_DEFAULT_LIMIT);
318  int default_interval
319  = getAparameter<int>(default_pset, "reportEvery", COMMON_DEFAULT_INTERVAL);
320  // change log 6, 10
321  int default_timespan
322  = getAparameter<int>(default_pset, "timespan", COMMON_DEFAULT_TIMESPAN);
323  // change log 2a
324  // change log 3a
325  String default_pset_threshold
326  = getAparameter<String>(default_pset, "threshold", default_threshold);
327  // change log 34
328 
329  // grab all of this destination's parameters:
330  PSet dest_pset = getAparameter<PSet>(*job_pset_p, filename, empty_PSet);
331 
332  // See if this is just a placeholder // change log 9
333  bool is_placeholder
334  = getAparameter<bool>(dest_pset, "placeholder", false);
335  if (is_placeholder) return;
336 
337  // grab this destination's default limit/interval/timespan:
338  PSet dest_default_pset
339  = getAparameter<PSet>(dest_pset, "default", empty_PSet);
340  int dest_default_limit
341  = getAparameter<int>(dest_default_pset, "limit", default_limit);
342  int dest_default_interval
343  = getAparameter<int>(dest_default_pset, "reportEvery", default_interval);
344  // change log 6
345  int dest_default_timespan
346  = getAparameter<int>(dest_default_pset, "timespan", default_timespan);
347  // change log 1a
348  if ( dest_default_limit != NO_VALUE_SET ) {
349  if ( dest_default_limit < 0 ) dest_default_limit = 2000000000;
350  dest_ctrl.setLimit("*", dest_default_limit );
351  } // change log 1b, 2a, 2b
352  if ( dest_default_interval != NO_VALUE_SET ) { // change log 6
353  dest_ctrl.setInterval("*", dest_default_interval );
354  }
355  if ( dest_default_timespan != NO_VALUE_SET ) {
356  if ( dest_default_timespan < 0 ) dest_default_timespan = 2000000000;
357  dest_ctrl.setTimespan("*", dest_default_timespan );
358  } // change log 1b, 2a, 2b
359 
360  // establish this destination's threshold:
361  String dest_threshold
362  = getAparameter<String>(dest_pset, "threshold", default_threshold);
363  if (dest_threshold == empty_String) {
364  dest_threshold = default_threshold;
365  }
366  if (dest_threshold == empty_String) { // change log 34
367  dest_threshold = default_pset_threshold;
368  }
369  if (dest_threshold == empty_String) {
370  dest_threshold = messageLoggerDefaults->threshold(filename);
371  }
372  if (dest_threshold == empty_String) dest_threshold = COMMON_DEFAULT_THRESHOLD;
373  ELseverityLevel threshold_sev(dest_threshold);
374  dest_ctrl.setThreshold(threshold_sev);
375  // change log 37
376  if (threshold_sev <= ELseverityLevel::ELsev_success)
378  if (threshold_sev <= ELseverityLevel::ELsev_info)
380  if (threshold_sev <= ELseverityLevel::ELsev_warning)
382 
383  // establish this destination's limit/interval/timespan for each category:
384  for( vString::const_iterator id_it = categories.begin()
385  ; id_it != categories.end()
386  ; ++id_it
387  )
388  {
389  String msgID = *id_it;
390  PSet default_category_pset
391  = getAparameter<PSet>(default_pset, msgID, empty_PSet); // change log 5
392  PSet category_pset
393  = getAparameter<PSet>(dest_pset, msgID, default_category_pset);
394 
395  int category_default_limit
396  = getAparameter<int>(default_category_pset, "limit", NO_VALUE_SET);
397  int limit
398  = getAparameter<int>(category_pset, "limit", category_default_limit);
399  if (limit == NO_VALUE_SET) limit = dest_default_limit;
400  // change log 7
401  int category_default_interval
402  = getAparameter<int>(default_category_pset, "reportEvery", NO_VALUE_SET);
403  int interval
404  = getAparameter<int>(category_pset, "reportEvery",category_default_interval);
405  if (interval == NO_VALUE_SET) interval = dest_default_interval;
406  // change log 6 and then 7
407  int category_default_timespan
408  = getAparameter<int>(default_category_pset, "timespan", NO_VALUE_SET);
409  int timespan
410  = getAparameter<int>(category_pset, "timespan", category_default_timespan);
411  if (timespan == NO_VALUE_SET) timespan = dest_default_timespan;
412  // change log 7
413 
414  std::string category = msgID;
415  if ( limit == NO_VALUE_SET ) { // change log 24
416  limit = messageLoggerDefaults->limit(filename,category);
417  }
418  if ( interval == NO_VALUE_SET ) { // change log 24
419  interval = messageLoggerDefaults->reportEvery(filename,category);
420  }
421  if ( timespan == NO_VALUE_SET ) { // change log 24
422  timespan = messageLoggerDefaults->timespan(filename,category);
423  }
424 
425  if( limit != NO_VALUE_SET ) {
426  if ( limit < 0 ) limit = 2000000000;
427  dest_ctrl.setLimit(msgID, limit);
428  } // change log 2a, 2b
429  if( interval != NO_VALUE_SET ) {
430  dest_ctrl.setInterval(msgID, interval);
431  } // change log 6
432  if( timespan != NO_VALUE_SET ) {
433  if ( timespan < 0 ) timespan = 2000000000;
434  dest_ctrl.setTimespan(msgID, timespan);
435  } // change log 2a, 2b
436 
437  } // for
438 
439  // establish this destination's limit for each severity:
440  for( vString::const_iterator sev_it = severities.begin()
441  ; sev_it != severities.end()
442  ; ++sev_it
443  )
444  {
445  String sevID = *sev_it;
446  ELseverityLevel severity(sevID);
447  PSet default_sev_pset
448  = getAparameter<PSet>(default_pset, sevID, empty_PSet);
449  PSet sev_pset
450  = getAparameter<PSet>(dest_pset, sevID, default_sev_pset);
451  // change log 5
452  int limit = getAparameter<int>(sev_pset, "limit", NO_VALUE_SET);
453  if ( limit == NO_VALUE_SET ) { // change log 24
454  limit = messageLoggerDefaults->sev_limit(filename,sevID);
455  }
456  if( limit != NO_VALUE_SET ) {
457  if (limit < 0) limit = 2000000000; // change log 38
458  dest_ctrl.setLimit(severity, limit );
459  }
460  int interval = getAparameter<int>(sev_pset, "reportEvery", NO_VALUE_SET);
461  if ( interval == NO_VALUE_SET ) { // change log 24
462  interval = messageLoggerDefaults->sev_reportEvery(filename,sevID);
463  }
464  if( interval != NO_VALUE_SET ) dest_ctrl.setInterval(severity, interval);
465  // change log 2
466  int timespan = getAparameter<int>(sev_pset, "timespan", NO_VALUE_SET);
467  if ( timespan == NO_VALUE_SET ) { // change log 24
468  timespan = messageLoggerDefaults->sev_timespan(filename,sevID);
469  }
470  if( timespan != NO_VALUE_SET ) {
471  if (timespan < 0) timespan = 2000000000; // change log 38
472  dest_ctrl.setTimespan(severity, timespan );
473  }
474  } // for
475 
476  // establish this destination's linebreak policy:
477  bool noLineBreaks_default
478  = getAparameter<bool> (default_pset, "noLineBreaks", false);
479  // change log 5
480  bool noLineBreaks
481  = getAparameter<bool> (dest_pset, "noLineBreaks", noLineBreaks_default);
482  if (noLineBreaks) {
483  dest_ctrl.setLineLength(32000);
484  }
485  else {
486  int lenDef = 80;
487  int lineLen_default
488  = getAparameter<int> (default_pset, "lineLength", lenDef);
489  // change log 5
490  int lineLen = getAparameter<int> (dest_pset, "lineLength", lineLen_default);
491  if (lineLen != lenDef) {
492  dest_ctrl.setLineLength(lineLen);
493  }
494  }
495 
496  // if indicated, suppress time stamps in this destination's output
497  bool suppressTime_default
498  = getAparameter<bool> (default_pset, "noTimeStamps", false);
499  bool suppressTime
500  = getAparameter<bool> (dest_pset, "noTimeStamps", suppressTime_default);
501  if (suppressTime) {
502  dest_ctrl.suppressTime();
503  }
504 
505  } // ThreadSafeLogMessageLoggerScribe::configure_dest()
506 
507  void
509  {
510  vString empty_vString;
511  String empty_String;
512  PSet empty_PSet;
513 
514  // Initialize unversal suppression variables
515  MessageDrop::debugAlwaysSuppressed=true; // change log 37
516  MessageDrop::infoAlwaysSuppressed=true; // change log 37
517  MessageDrop::warningAlwaysSuppressed=true; // change log 37
518 
519  // grab list of destinations:
521  = getAparameter<vString>(*job_pset_p, "destinations", empty_vString);
522 
523  // Use the default list of destinations if and only if the grabbed list is
524  // empty // change log 24
525  if (destinations.empty()) {
526  destinations = messageLoggerDefaults->destinations;
527  }
528 
529  // dial down the early destination if other dest's are supplied:
530  if( ! destinations.empty() )
532 
533  // establish each destination:
534  for( vString::const_iterator it = destinations.begin()
535  ; it != destinations.end()
536  ; ++it
537  )
538  {
539  String filename = *it;
540  String psetname = filename;
541 
542  // check that this destination is not just a placeholder // change log 11
543  PSet dest_pset = getAparameter<PSet>(*job_pset_p, psetname, empty_PSet);
544  bool is_placeholder
545  = getAparameter<bool>(dest_pset, "placeholder", false);
546  if (is_placeholder) continue;
547 
548  // Modify the file name if extension or name is explicitly specified
549  // change log 14
550 
551  // Although for an ordinary destination there is no output attribute
552  // for the cfg (you can use filename instead) we provide output() for
553  // uniformity with the statistics destinations. The "right way" to
554  // work this would have been to provide a filename() method, along with
555  // an extension() method. We recognize the potential name confusion here
556  // (filename(filename))!
557 
558  // Determine the destination file name to use if no explicit filename is
559  // supplied in the cfg.
560  String filename_default
561  = getAparameter<String>(dest_pset, "output", empty_String);
562  if ( filename_default == empty_String ) {
563  filename_default = messageLoggerDefaults->output(psetname); // change log 31
564  if (filename_default == empty_String) {
565  filename_default = filename;
566  }
567  }
568 
569  String explicit_filename
570  = getAparameter<String>(dest_pset, "filename", filename_default);
571  if (explicit_filename != empty_String) filename = explicit_filename;
572  String explicit_extension
573  = getAparameter<String>(dest_pset, "extension", empty_String);
574  if (explicit_extension != empty_String) {
575  if (explicit_extension[0] == '.') {
576  filename += explicit_extension;
577  } else {
578  filename = filename + "." + explicit_extension;
579  }
580  }
581 
582  // Attach a default extension of .log if there is no extension on a file
583  // change log 18 - this had been done in concert with attaching destination
584 
585  std::string actual_filename = filename; // change log 4
586  if ( (filename != "cout") && (filename != "cerr") ) {
587  const std::string::size_type npos = std::string::npos;
588  if ( filename.find('.') == npos ) {
589  actual_filename += ".log";
590  }
591  }
592 
593  // Check that this is not a duplicate name // change log 18
594  if ( stream_ps.find(actual_filename)!=stream_ps.end() ) {
595  if (clean_slate_configuration) { // change log 22
596  // throw edm::Exception ( edm::errors::Configuration )
597  LogError("duplicateDestination") // change log 35
598  <<"Duplicate name for a MessageLogger Destination: "
599  << actual_filename
600  << "\n" << "Only the first configuration instructions are used";
601  continue;
602  } else {
603  LogWarning("duplicateDestination")
604  <<"Duplicate name for a MessageLogger Destination: "
605  << actual_filename
606  << "\n" << "Only original configuration instructions are used";
607  continue;
608  }
609  }
610 
611  ordinary_destination_filenames.push_back(actual_filename);
612 
613  // attach the current destination, keeping a control handle to it:
614  ELdestControl dest_ctrl;
615  if( actual_filename == "cout" ) {
616  dest_ctrl = admin_p->attach( ELoutput(std::cout) );
617  stream_ps["cout"] = &std::cout;
618  }
619  else if( actual_filename == "cerr" ) {
621  dest_ctrl = early_dest;
622  stream_ps["cerr"] = &std::cerr;
623  }
624  else {
625  auto os_sp = std::make_shared<std::ofstream>(actual_filename.c_str());
626  file_ps.push_back(os_sp);
627  dest_ctrl = admin_p->attach( ELoutput(*os_sp) );
628  stream_ps[actual_filename] = os_sp.get();
629  }
630 
631  // now configure this destination:
632  configure_dest(dest_ctrl, psetname);
633 
634  } // for [it = destinations.begin() to end()]
635 
636  } // configure_ordinary_destinations
637 
638 
639  void
641  {
642  vString empty_vString;
643  String empty_String;
644  PSet empty_PSet;
645 
646  // grab list of statistics destinations:
648  = getAparameter<vString>(*job_pset_p, "statistics", empty_vString);
649 
650  bool no_statistics_configured = statistics.empty(); // change log 24
651 
652  if ( no_statistics_configured ) {
653  // Read the list of staistics destinations from hardwired defaults,
654  // but only if there is also no list of ordinary destinations.
655  // (If a cfg specifies destinations, and no statistics, assume that
656  // is what the user wants.)
658  = getAparameter<vString>(*job_pset_p, "destinations", empty_vString);
659  if (destinations.empty()) {
660  statistics = messageLoggerDefaults->statistics;
661  no_statistics_configured = statistics.empty();
662  }
663  }
664 
665  // establish each statistics destination:
666  for( vString::const_iterator it = statistics.begin()
667  ; it != statistics.end()
668  ; ++it
669  )
670  {
671  String statname = *it;
672  String psetname = statname;
673 
674  // check that this destination is not just a placeholder // change log 20
675  PSet stat_pset = getAparameter<PSet>(*job_pset_p, psetname, empty_PSet);
676  bool is_placeholder
677  = getAparameter<bool>(stat_pset, "placeholder", false);
678  if (is_placeholder) continue;
679 
680  // Determine the destination file name
682  = getAparameter<String>(stat_pset, "output", empty_String);
683  if ( filename == empty_String ) {
684  filename = messageLoggerDefaults->output(psetname); // change log 31
685  if (filename == empty_String) {
686  filename = statname;
687  }
688  }
689 
690  // Modify the file name if extension or name is explicitly specified
691  // change log 14 -- probably suspenders and a belt, because ouput option
692  // is present, but uniformity is nice.
693 
694  String explicit_filename
695  = getAparameter<String>(stat_pset, "filename", filename);
696  if (explicit_filename != empty_String) filename = explicit_filename;
697  String explicit_extension
698  = getAparameter<String>(stat_pset, "extension", empty_String);
699  if (explicit_extension != empty_String) {
700  if (explicit_extension[0] == '.') {
701  filename += explicit_extension;
702  } else {
703  filename = filename + "." + explicit_extension;
704  }
705  }
706 
707  // Attach a default extension of .log if there is no extension on a file
708  // change log 18 - this had been done in concert with attaching destination
709 
710  std::string actual_filename = filename; // change log 4
711  if ( (filename != "cout") && (filename != "cerr") ) { // change log 23
712  const std::string::size_type npos = std::string::npos;
713  if ( filename.find('.') == npos ) {
714  actual_filename += ".log";
715  }
716  }
717 
718  // Check that this is not a duplicate name -
719  // unless it is an ordinary destination (which stats can share)
720  if ( !search_all(ordinary_destination_filenames, actual_filename) ) {
721  if ( stream_ps.find(actual_filename)!=stream_ps.end() ) {
722  if (clean_slate_configuration) { // change log 22
724  <<"Duplicate name for a MessageLogger Statistics Destination: "
725  << actual_filename
726  << "\n";
727  } else {
728  LogWarning("duplicateDestination")
729  <<"Duplicate name for a MessageLogger Statistics Destination: "
730  << actual_filename
731  << "\n" << "Only original configuration instructions are used";
732  continue;
733  }
734  }
735  }
736 
737  // create (if statistics file does not match any destination file name)
738  // or note (if statistics file matches a destination file name) the ostream.
739  // But if no statistics destinations were provided in the config, do not
740  // create a new destination for this hardwired statistics - only act if
741  // it is matches a destination. (shange log 24)
742  bool statistics_destination_is_real = !no_statistics_configured;
743  std::ostream* os_p;
744  if ( stream_ps.find(actual_filename) == stream_ps.end() ) {
745  if ( actual_filename == "cout" ) {
746  os_p = &std::cout;
747  } else if ( actual_filename == "cerr" ) {
748  os_p = &std::cerr;
749  } else {
750  auto os_sp = std::make_shared<std::ofstream>(actual_filename.c_str());
751  file_ps.push_back(os_sp);
752  os_p = os_sp.get();
753  }
754  stream_ps[actual_filename] = os_p;
755  } else {
756  statistics_destination_is_real = true; // change log 24
757  os_p = stream_ps[actual_filename];
758  }
759 
760  if (statistics_destination_is_real) { // change log 24
761  // attach the statistics destination, keeping a control handle to it:
762  ELdestControl dest_ctrl;
763  dest_ctrl = admin_p->attach( ELstatistics(*os_p) );
764  statisticsDestControls.push_back(dest_ctrl);
765  bool reset = getAparameter<bool>(stat_pset, "reset", false);
766  statisticsResets.push_back(reset);
767 
768  // now configure this destination:
769  configure_dest(dest_ctrl, psetname);
770 
771  // and suppress the desire to do an extra termination summary just because
772  // of end-of-job info messages
773  dest_ctrl.noTerminationSummary();
774  }
775 
776  } // for [it = statistics.begin() to end()]
777 
778  } // configure_statistics
779 
780  void
782  {
783  if( ! job_pset_p )
784  {
785  // extern_dests.clear();
786  // change log 12, removed by change log 13
787  return;
788  }
789 
790  for( auto& dest : extern_dests)
791  {
792  ELdestination * dest_p = dest->dest_p().get();
793  ELdestControl dest_ctrl = admin_p->attach( *dest_p );
794 
795  // configure the newly-attached destination:
796  configure_dest( dest_ctrl, dest->name() );
797  delete dest; // dispose of our (copy of the) NamedDestination
798  }
799  extern_dests.clear();
800 
801  } // ThreadSafeLogMessageLoggerScribe::configure_external_dests
802 
803  void
805  std::vector<std::string> & cats)
806  {
807  const std::string::size_type npos = std::string::npos;
809  while ( i != npos ) {
810  std::string::size_type j = s.find('|',i);
811  cats.push_back (s.substr(i,j-i));
812  i = j;
813  while ( (i != npos) && (s[i] == '|') ) ++i;
814  // the above handles cases of || and also | at end of string
815  }
816  // Note: This algorithm assigns, as desired, one null category if it
817  // encounters an empty categories string
818  }
819 
820  void
823  for (unsigned int i = 0; i != statisticsDestControls.size(); ++i) {
824  statisticsDestControls[i].summary( );
826  }
827  }
828 
829  void
831  triggerFJRmessageSummary(std::map<std::string, double> & sm) // ChangeLog 29
832  {
833  if (statisticsDestControls.empty()) {
834  sm["NoStatisticsDestinationsConfigured"] = 0.0;
835  } else {
836  statisticsDestControls[0].summaryForJobReport(sm);
837  }
838  }
839 
840 
841 
842  } // end of namespace service
843 } // end of namespace edm
844 
virtual char const * what() const
Definition: Exception.cc:141
int i
Definition: DBlmapReader.cc:9
ELdestControl & setLimit(const ELstring &s, int n)
virtual void clear()
Definition: ErrorObj.cc:256
ELdestControl & setThreshold(const ELseverityLevel &sv)
tuple interval
Definition: MergeJob_cfg.py:20
assert(m_qm.get())
std::vector< edm::propagate_const< std::shared_ptr< std::ofstream > > > file_ps
virtual void runCommand(MessageLoggerQ::OpCode opcode, void *operand)
void configure_dest(ELdestControl &dest_ctrl, String const &filename)
ELdestControl & setTimespan(const ELstring &s, int n)
ELslProxy< ELhighestSeverityGen > const ELhighestSeverity
uint16_t size_type
void triggerFJRmessageSummary(std::map< std::string, double > &sm)
static bool debugAlwaysSuppressed
Definition: MessageDrop.h:112
const ELextendedID & xid() const
Definition: ErrorObj.cc:147
ELslProxy< ELzeroSeverityGen > const ELzeroSeverity
ThreadSafeLogMessageLoggerScribe()
— If queue is NULL, this sets singleThread true
int j
Definition: DBlmapReader.cc:9
std::map< String, edm::propagate_const< std::ostream * > > stream_ps
edm::propagate_const< std::shared_ptr< PSet > > job_pset_p
static void noteGroupedCategory(std::string const &cat)
static bool warningAlwaysSuppressed
Definition: MessageDrop.h:114
virtual void setID(const ELstring &ID)
Definition: ErrorObj.cc:182
bool search_all(ForwardSequence const &s, Datum const &d)
Definition: Algorithms.h:46
static edm::JobMode mode(std::string const &jm)
edm::propagate_const< std::shared_ptr< ELadministrator > > admin_p
ELdestControl & setInterval(const ELstring &s, int interval)
JobMode
Definition: JobMode.h:15
Func copy_all(ForwardSequence &s, Func f)
wrappers for copy
Definition: Algorithms.h:24
tuple filename
Definition: lut2db_cfg.py:20
tuple destinations
Definition: gather_cfg.py:144
void parseCategories(std::string const &s, std::vector< std::string > &cats)
tuple cout
Definition: gather_cfg.py:145
volatile std::atomic< bool > shutdown_flag false
static bool infoAlwaysSuppressed
Definition: MessageDrop.h:113
void reset(double vett[256])
Definition: TPedValues.cc:11