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