File indexing completed on 2023-03-17 11:26:56
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
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
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) {
0142 source.release();
0143 }
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 }