Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 14:32:09

0001 
0002 #include <iostream>
0003 
0004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0005 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0006 
0007 #include "QualityMetric.h"
0008 
0009 #ifdef __MACH__
0010 #include <mach/clock.h>
0011 #include <mach/mach.h>
0012 #define GET_CLOCK_MONOTONIC(ts)                                      \
0013   {                                                                  \
0014     clock_serv_t cclock;                                             \
0015     mach_timespec_t mts;                                             \
0016     host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); \
0017     clock_get_time(cclock, &mts);                                    \
0018     mach_port_deallocate(mach_task_self(), cclock);                  \
0019     ts.tv_sec = mts.tv_sec;                                          \
0020     ts.tv_nsec = mts.tv_nsec;                                        \
0021   }
0022 #else
0023 #define GET_CLOCK_MONOTONIC(ts) clock_gettime(CLOCK_MONOTONIC, &ts);
0024 #endif
0025 
0026 using namespace XrdAdaptor;
0027 
0028 QualityMetricWatch::QualityMetricWatch(QualityMetric *parent1, QualityMetric *parent2)
0029     : m_parent1(parent1), m_parent2(parent2) {
0030   // TODO: just assuming success.
0031   GET_CLOCK_MONOTONIC(m_start);
0032 }
0033 
0034 QualityMetricWatch::~QualityMetricWatch() {
0035   if (m_parent1 && m_parent2) {
0036     timespec stop;
0037     GET_CLOCK_MONOTONIC(stop);
0038 
0039     int ms = 1000 * (stop.tv_sec - m_start.tv_sec) + (stop.tv_nsec - m_start.tv_nsec) / 1e6;
0040     edm::LogVerbatim("XrdAdaptorInternal") << "Finished timer after " << ms << std::endl;
0041     m_parent1->finishWatch(stop, ms);
0042     m_parent2->finishWatch(stop, ms);
0043   }
0044 }
0045 
0046 QualityMetricWatch::QualityMetricWatch(QualityMetricWatch &&that) {
0047   m_parent1 = that.m_parent1;
0048   m_parent2 = that.m_parent2;
0049   m_start = that.m_start;
0050   that.m_parent1 = nullptr;
0051   that.m_parent2 = nullptr;
0052   that.m_start = {0, 0};
0053 }
0054 
0055 void QualityMetricWatch::swap(QualityMetricWatch &that) {
0056   QualityMetric *tmp;
0057   tmp = that.m_parent1;
0058   that.m_parent1 = m_parent1;
0059   m_parent1 = tmp;
0060   tmp = that.m_parent2;
0061   that.m_parent2 = m_parent2;
0062   m_parent2 = tmp;
0063   timespec tmp2;
0064   tmp2 = that.m_start;
0065   that.m_start = m_start;
0066   m_start = tmp2;
0067 }
0068 
0069 QualityMetric::QualityMetric(timespec now, int default_value)
0070     : m_value(default_value),
0071       m_interval0_n(0),
0072       m_interval0_val(-1),
0073       m_interval0_start(now.tv_sec),
0074       m_interval1_val(-1),
0075       m_interval2_val(-1),
0076       m_interval3_val(-1),
0077       m_interval4_val(-1) {}
0078 
0079 void QualityMetric::finishWatch(timespec stop, int ms) {
0080   std::unique_lock<std::mutex> sentry(m_mutex);
0081 
0082   m_value = -1;
0083   if (stop.tv_sec > m_interval0_start + interval_length) {
0084     m_interval4_val = m_interval3_val;
0085     m_interval3_val = m_interval2_val;
0086     m_interval2_val = m_interval1_val;
0087     m_interval1_val = m_interval0_val;
0088     m_interval0_n = 1;
0089     m_interval0_val = ms;
0090     m_interval0_start = stop.tv_sec;
0091   } else {
0092     int num = m_interval0_val * m_interval0_n + ms;
0093     m_interval0_n++;
0094     m_interval0_val = num / m_interval0_n;
0095   }
0096 }
0097 
0098 unsigned QualityMetric::get() {
0099   std::unique_lock<std::mutex> sentry(m_mutex);
0100 
0101   if (m_value == -1) {
0102     unsigned den = 0;
0103     m_value = 0;
0104     if (m_interval0_val >= 0) {
0105       den += 16;
0106       m_value = 16 * m_interval0_val;
0107     }
0108     if (m_interval1_val >= 0) {
0109       den += 8;
0110       m_value += 8 * m_interval1_val;
0111     }
0112     if (m_interval2_val >= 0) {
0113       den += 4;
0114       m_value += 4 * m_interval2_val;
0115     }
0116     if (m_interval3_val >= 0) {
0117       den += 2;
0118       m_value += 2 * m_interval3_val;
0119     }
0120     if (m_interval4_val >= 0) {
0121       den += 1;
0122       m_value += m_interval4_val;
0123     }
0124     if (den)
0125       m_value /= den;
0126     else
0127       m_value = 260;
0128   }
0129   return m_value;
0130 }
0131 
0132 CMS_THREAD_SAFE QualityMetricFactory QualityMetricFactory::m_instance;
0133 
0134 std::unique_ptr<QualityMetricSource> QualityMetricFactory::get(timespec now, const std::string &id) {
0135   auto itFound = m_instance.m_sources.find(id);
0136   if (itFound == m_instance.m_sources.end()) {
0137     // try to make a new one
0138     std::unique_ptr<QualityMetricUniqueSource> source(new QualityMetricUniqueSource(now));
0139     auto insertResult = m_instance.m_sources.insert(std::make_pair(id, source.get()));
0140     itFound = insertResult.first;
0141     if (insertResult.second) {  // Insert was successful; release our reference.
0142       source.release();
0143     }  // Otherwise, we raced with a different thread and they won; we will delete our new QM source.
0144   }
0145   return itFound->second->newSource(now);
0146 }
0147 
0148 QualityMetricSource::QualityMetricSource(QualityMetricUniqueSource &parent, timespec now, int default_value)
0149     : QualityMetric(now, default_value), m_parent(parent) {}
0150 
0151 void QualityMetricSource::startWatch(QualityMetricWatch &watch) {
0152   QualityMetricWatch tmp(&m_parent, this);
0153   watch.swap(tmp);
0154 }
0155 
0156 QualityMetricUniqueSource::QualityMetricUniqueSource(timespec now) : QualityMetric(now) {}
0157 
0158 std::unique_ptr<QualityMetricSource> QualityMetricUniqueSource::newSource(timespec now) {
0159   std::unique_ptr<QualityMetricSource> child(new QualityMetricSource(*this, now, get()));
0160   return child;
0161 }