CMS 3D CMS Logo

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