Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:12:44

0001 #include "FWCore/MessageLogger/interface/ErrorSummaryEntry.h"
0002 #include "FWCore/MessageLogger/interface/MessageSender.h"
0003 #include "FWCore/MessageLogger/interface/MessageLoggerQ.h"
0004 #include "FWCore/MessageLogger/interface/MessageDrop.h"
0005 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0006 
0007 #include <algorithm>
0008 #include <cassert>
0009 #include <vector>
0010 #include <limits>
0011 #include <atomic>
0012 
0013 #include <functional>
0014 #include "oneapi/tbb/concurrent_unordered_map.h"
0015 
0016 #define TRACE_DROP
0017 #ifdef TRACE_DROP
0018 #include <iostream>
0019 #endif
0020 
0021 // Change log
0022 //
0023 //  1  mf 8/25/08   keeping the error summary information for
0024 //          LoggedErrorsSummary()
0025 //
0026 // 2  mf 11/2/10    Use new moduleContext method of MessageDrop:
0027 //          see MessageServer/src/MessageLogger.cc change 17.
0028 //
0029 
0030 using namespace edm;
0031 using namespace edm::messagelogger;
0032 
0033 namespace {
0034   //Helper class used as 'key' to the thread safe map storing the
0035   // per event log error and log warning messages
0036   struct ErrorSummaryMapKey {
0037     std::string category;
0038     std::string module;
0039     ELseverityLevel severity;
0040 
0041     bool operator<(ErrorSummaryMapKey const& iOther) const {
0042       int comp = severity.getLevel() - iOther.severity.getLevel();
0043       if (0 == comp) {
0044         comp = category.compare(iOther.category);
0045         if (comp == 0) {
0046           comp = module.compare(iOther.module);
0047         }
0048       }
0049       return comp < 0;
0050     }
0051 
0052     bool operator==(ErrorSummaryMapKey const& iOther) const {
0053       return ((iOther.category == category) and (iOther.module == module) and
0054               (severity.getLevel() == iOther.severity.getLevel()));
0055     }
0056     size_t smallHash() const {
0057       std::hash<std::string> h;
0058 
0059       return h(category + module + severity.getSymbol());
0060     }
0061 
0062     struct key_hash {
0063       std::size_t operator()(ErrorSummaryMapKey const& iKey) const { return iKey.smallHash(); }
0064     };
0065   };
0066 
0067   class AtomicUnsignedInt {
0068   public:
0069     AtomicUnsignedInt() : value_(0) {}
0070     AtomicUnsignedInt(AtomicUnsignedInt const& r) : value_(r.value_.load(std::memory_order_acquire)) {}
0071     std::atomic<unsigned int>& value() { return value_; }
0072     std::atomic<unsigned int> const& value() const { return value_; }
0073 
0074   private:
0075     std::atomic<unsigned int> value_;
0076   };
0077 
0078 }  // namespace
0079 
0080 CMS_THREAD_SAFE static std::atomic<bool> errorSummaryIsBeingKept{false};
0081 //Each item in the vector is reserved for a different Stream
0082 CMS_THREAD_SAFE static std::vector<
0083     oneapi::tbb::concurrent_unordered_map<ErrorSummaryMapKey, AtomicUnsignedInt, ErrorSummaryMapKey::key_hash>>
0084     errorSummaryMaps;
0085 
0086 MessageSender::MessageSender(ELseverityLevel const& sev, std::string_view id, bool verbatim, bool suppressed)
0087     : errorobj_p(suppressed ? nullptr : new ErrorObj(sev, id, verbatim), ErrorObjDeleter()) {
0088   //std::cout << "MessageSender ctor; new ErrorObj at: " << errorobj_p << '\n';
0089 }
0090 
0091 // This destructor must not be permitted to throw. A
0092 // boost::thread_resoruce_error is thrown at static destruction time,
0093 // if the MessageLogger library is loaded -- even if it is not used.
0094 void MessageSender::ErrorObjDeleter::operator()(ErrorObj* errorObjPtr) {
0095   if (errorObjPtr == nullptr) {
0096     return;
0097   }
0098   try {
0099     //std::cout << "MessageSender dtor; ErrorObj at: " << errorobj_p << '\n';
0100 
0101     // surrender ownership of our ErrorObj, transferring ownership
0102     // (via the intermediate MessageLoggerQ) to the MessageLoggerScribe
0103     // that will (a) route the message text to its destination(s)
0104     // and will then (b) dispose of the ErrorObj
0105 
0106     MessageDrop* drop = MessageDrop::instance();
0107     if (drop) {
0108       errorObjPtr->setModule(drop->moduleContext());  // change log
0109       errorObjPtr->setContext(drop->runEvent);
0110     }
0111 #ifdef TRACE_DROP
0112     if (!drop)
0113       std::cerr << "MessageSender::~MessageSender() - Null drop pointer \n";
0114 #endif
0115     // change log 1
0116     if (errorSummaryIsBeingKept.load(std::memory_order_acquire) && errorObjPtr->xid().severity >= ELwarning && drop &&
0117         drop->streamID < std::numeric_limits<unsigned int>::max()) {
0118       auto& errorSummaryMap = errorSummaryMaps[drop->streamID];
0119 
0120       ELextendedID const& xid = errorObjPtr->xid();
0121       ErrorSummaryMapKey key{xid.id, xid.module, xid.severity};
0122       auto i = errorSummaryMap.find(key);
0123       if (i != errorSummaryMap.end()) {
0124         i->second.value().fetch_add(1, std::memory_order_acq_rel);  // same as ++errorSummaryMap[key]
0125       } else {
0126         errorSummaryMap[key].value().store(1, std::memory_order_release);
0127       }
0128     }
0129 
0130     MessageLoggerQ::MLqLOG(errorObjPtr);
0131   } catch (...) {
0132     // nothing to do
0133 
0134     // for test that removal of thread-involved static works,
0135     // simply throw here, then run in trivial_main in totalview
0136     // and Next or Step so that the exception would be detected.
0137     // That test has been done 12/14/07.
0138   }
0139 }
0140 MessageSender::~MessageSender() {}
0141 
0142 //The following functions are declared here rather than in
0143 // LoggedErrorsSummary.cc because only  MessageSender and these
0144 // functions interact with the statics errorSummaryIsBeingKept and
0145 // errorSummaryMaps. By putting them into the same .cc file the
0146 // statics can be file scoped rather than class scoped and therefore
0147 // better encapsulated.
0148 namespace edm {
0149   using namespace messagelogger;
0150 
0151   bool EnableLoggedErrorsSummary() {
0152     bool ret = errorSummaryIsBeingKept.exchange(true, std::memory_order_acq_rel);
0153     return ret;
0154   }
0155 
0156   bool DisableLoggedErrorsSummary() {
0157     bool ret = errorSummaryIsBeingKept.exchange(false, std::memory_order_acq_rel);
0158     return ret;
0159   }
0160 
0161   bool FreshErrorsExist(unsigned int iStreamID) {
0162     assert(iStreamID < errorSummaryMaps.size());
0163     return !errorSummaryMaps[iStreamID].empty();
0164   }
0165 
0166   std::vector<ErrorSummaryEntry> LoggedErrorsSummary(unsigned int iStreamID) {
0167     assert(iStreamID < errorSummaryMaps.size());
0168     auto const& errorSummaryMap = errorSummaryMaps[iStreamID];
0169     std::vector<ErrorSummaryEntry> v;
0170     auto end = errorSummaryMap.end();
0171     for (auto i = errorSummaryMap.begin(); i != end; ++i) {
0172       auto const& key = i->first;
0173       ErrorSummaryEntry e{key.category, key.module, key.severity};
0174 
0175       e.count = i->second.value().load(std::memory_order_acquire);
0176       v.push_back(e);
0177     }
0178     std::sort(v.begin(), v.end());
0179     return v;
0180   }
0181 
0182   void clearLoggedErrorsSummary(unsigned int iStreamID) {
0183     assert(iStreamID < errorSummaryMaps.size());
0184     errorSummaryMaps[iStreamID].clear();
0185   }
0186 
0187   void setMaxLoggedErrorsSummaryIndicies(unsigned int iMax) { errorSummaryMaps.resize(iMax); }
0188 
0189   std::vector<ErrorSummaryEntry> LoggedErrorsOnlySummary(unsigned int iStreamID) {  //  ChangeLog 2
0190     std::vector<ErrorSummaryEntry> v;
0191     assert(iStreamID < errorSummaryMaps.size());
0192     auto const& errorSummaryMap = errorSummaryMaps[iStreamID];
0193     auto end = errorSummaryMap.end();
0194     for (auto i = errorSummaryMap.begin(); i != end; ++i) {
0195       auto const& key = i->first;
0196       if (key.severity >= edm::ELerror) {
0197         ErrorSummaryEntry e{key.category, key.module, key.severity};
0198         e.count = i->second.value().load(std::memory_order_acquire);
0199         v.push_back(e);
0200       }
0201     }
0202     std::sort(v.begin(), v.end());
0203     return v;
0204   }
0205 
0206 }  // end namespace edm