summaryrefslogtreecommitdiff
path: root/src/libpcp_qmc/src/qmc_metric.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/libpcp_qmc/src/qmc_metric.h')
-rw-r--r--src/libpcp_qmc/src/qmc_metric.h336
1 files changed, 336 insertions, 0 deletions
diff --git a/src/libpcp_qmc/src/qmc_metric.h b/src/libpcp_qmc/src/qmc_metric.h
new file mode 100644
index 0000000..7bca55b
--- /dev/null
+++ b/src/libpcp_qmc/src/qmc_metric.h
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2012-2014 Red Hat, Inc.
+ * Copyright (c) 2007 Aconex. All Rights Reserved.
+ * Copyright (c) 1998-2005 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef QMC_METRIC_H
+#define QMC_METRIC_H
+
+#include "qmc.h"
+#include "qmc_desc.h"
+#include "qmc_group.h"
+#include "qmc_context.h"
+
+#include <qlist.h>
+#include <qvector.h>
+#include <qstring.h>
+#include <qtextstream.h>
+
+class QmcMetricValue;
+
+class QmcEventParameter
+{
+public:
+ QmcEventParameter() { my.pmid = PM_ID_NULL; }
+
+ void setPMID(pmID pmid) { my.pmid = pmid; }
+ void setNamePtr(QString *name) { my.name = name; }
+ void setDescPtr(QmcDesc *desc) { my.desc = desc; }
+ void setIndomPtr(QmcIndom *indom) { my.indom = indom; }
+
+ void setValueCount(int numInst);
+ QmcMetricValue *valuePtr(int inst);
+
+ int type() const;
+ double value(int inst) const;
+ QString stringValue(int inst) const;
+
+ void summary(QString &os, int instID) const;
+ void dump(QTextStream &os, int instID) const;
+
+private:
+ struct {
+ pmID pmid; // pmid for the parameter to an event
+ QString *name; // direct pointer into external cache
+ QmcDesc *desc; // direct pointer into external cache
+ QmcIndom *indom; // direct pointer into external cache
+ QVector<QmcMetricValue> values;
+ } my;
+};
+
+class QmcEventRecord
+{
+public:
+ QmcEventRecord() { my.missed = my.flags = 0; }
+
+ const struct timeval *timestamp() const { return &my.timestamp; }
+ void setTimestamp(struct timeval *tv) { my.timestamp = *tv; }
+
+ int flags() const { return my.flags; }
+ void setFlags(int flags) { my.flags = flags; }
+
+ int missed() const { return my.missed; }
+ void setMissed(int missed) { my.missed = missed; }
+
+ void setParameterCount(int numParams)
+ { my.parameters.resize(numParams); }
+ int setParameter(int n, pmID pmid, QmcContext *cp, pmValueSet const *vp);
+
+ QString parent() const;
+ QString identifier() const;
+
+ void parameterSummary(QString &os, int instID) const;
+ void dump(QTextStream &os, int instID, uint recordID) const;
+
+ static pmID eventFlags();
+ static pmID eventMissed();
+
+private:
+ QString parameterAsString(int index) const;
+
+ struct {
+ struct timeval timestamp;
+ int missed;
+ int flags;
+ QVector<QmcEventParameter> parameters;
+ } my;
+};
+
+class QmcMetricValue
+{
+public:
+ QmcMetricValue();
+ QmcMetricValue const& operator=(QmcMetricValue const& rhs);
+
+ int instance() const { return my.instance; }
+ void setInstance(int instance) { my.instance = instance; }
+
+ int error() const { return my.error; }
+ void setError(int error) { my.error = error; }
+ void setAllErrors(int error)
+ { my.error = my.currentError = my.previousError = error; }
+
+ double value() const { return my.value; }
+ void setValue(double value) { my.value = value; }
+ void divValue(double value) { my.value /= value; }
+ void addValue(double value) { my.value += value; }
+ void subValue(double value) { my.value -= value; }
+
+ QString stringValue() const { return my.stringValue; }
+ void setStringValue(const char *s) { my.stringValue = s; }
+
+ int currentError() const { return my.currentError; }
+ void setCurrentError(int error)
+ { my.currentError = error; resetCurrentValue(); }
+ double currentValue() const { return my.currentValue; }
+ void setCurrentValue(double value) { my.currentValue = value; }
+
+ int previousError() const { return my.previousError; }
+ double previousValue() const { return my.previousValue; }
+ void shiftValues() { my.previousValue = my.currentValue;
+ my.previousError = my.currentError;
+ my.currentError = 0; }
+
+ QVector<QmcEventRecord> const &eventRecords() const { return my.eventRecords; }
+ void extractEventRecords(QmcContext *context, int recordCount, pmResult **result);
+ void dumpEventRecords(QTextStream &os, int instid) const;
+
+private:
+ void resetCurrentValue()
+ { my.currentValue = 0.0; my.stringValue = QString::null; my.eventRecords.clear(); }
+
+ struct {
+ int instance;
+ int error;
+ double value;
+ double previousValue;
+ double currentValue;
+ int currentError;
+ int previousError;
+ QString stringValue;
+ QVector<QmcEventRecord> eventRecords;
+ } my;
+};
+
+class QmcMetric
+{
+ friend class QmcGroup;
+ friend class QmcContext;
+
+public:
+ QmcMetric(QmcGroup *group, const char *str, double theScale = 0.0,
+ bool active = false);
+ QmcMetric(QmcGroup *group, pmMetricSpec *theMetric, double theScale = 0.0,
+ bool active = false);
+ ~QmcMetric();
+
+ int status() const { return my.status; }
+ pmID metricID() const { return my.pmid; }
+ const QString name() const { return my.name; }
+ char *nameAscii() const { return strdup((const char *)my.name.toAscii()); }
+ QmcContext *context() const
+ { return my.group->context(my.contextIndex); }
+ const QmcDesc &desc() const
+ { return context()->desc(my.pmid); }
+ bool hasIndom() const
+ { return desc().desc().indom != PM_INDOM_NULL; }
+ bool hasInstances() const
+ { return (my.status >= 0 && my.indomIndex < UINT_MAX); }
+
+ // Were the instances explicitly listed?
+ bool explicitInsts() const { return my.explicitInst; }
+
+ // Are only active instances referenced
+ bool activeInsts() const { return my.active; }
+
+ int numInst() const
+ { return (my.status >= 0 && my.indomIndex < UINT_MAX) ?
+ my.values.size() : 0; }
+
+ // How many values does it have (will not equal number of instances
+ // if singular)
+ int numValues() const { return (my.status >= 0) ? my.values.size() : 0; }
+
+ // The metric indom
+ QmcIndom *indom() const
+ { return (my.indomIndex == UINT_MAX) ? NULL :
+ &(my.group->context(my.contextIndex)->indom(my.indomIndex)); }
+
+ // Internal instance id for instance <index>
+ int instID(int index) const
+ { return my.group->context(my.contextIndex)->indom(my.indomIndex).inst(my.values[index].instance()); }
+
+ // External instance name for instance <index>
+ const QString instName(int index) const
+ { return my.group->context(my.contextIndex)->indom(my.indomIndex).name(my.values[index].instance()); }
+
+ // Return the index for the instance in the indom list
+ int instIndex(uint index) const { return my.values[index].instance(); }
+
+ // Update the metric to include new instances
+ // Returns true if the instance list changed
+ // Metrics with implicit instances will be extended to include those
+ // new instances. The position of instances may change.
+ // If <active> is set, only those instances in the latest indom will
+ // be listed, other instances will be removed
+ bool updateIndom();
+
+ int addInst(QString const& name);
+ void removeInst(uint index);
+
+ // Scaling modifier applied to metric values
+ double scale() const { return my.scale; }
+
+ // Metric has event records (as opposed to real/string/aggregate values)
+ bool event() const { return event(desc().desc().type); }
+ static bool event(int type)
+ { return type == PM_TYPE_EVENT || type == PM_TYPE_HIGHRES_EVENT; }
+
+ bool aggregate() const { return aggregate(desc().desc().type); }
+ static void aggregateAsString(pmValue const *, char *, int);
+ static bool aggregate(int type)
+ { return type == PM_TYPE_AGGREGATE || type == PM_TYPE_AGGREGATE_STATIC; }
+
+ // Metric has real values (as opposed to event/string/aggregate values)
+ bool real() const { return real(desc().desc().type); }
+ static bool real(int type)
+ { return type > PM_TYPE_NOSUPPORT && type < PM_TYPE_STRING; }
+
+ // Current rate-converted and scaled real value
+ double value(int index) const { return my.values[index].value(); }
+
+ double realValue(int index) const // Current rate-converted value
+ { return my.values[index].value() * my.scale; }
+
+ double currentValue(int index) const // Current raw value
+ { return my.values[index].currentValue(); }
+
+ QString stringValue(int index) const // Current string value
+ { return my.values[index].stringValue(); }
+
+ QVector<QmcEventRecord> const &eventRecords(int index) const
+ { return my.values[index].eventRecords(); }
+
+ int error(int index) const // Current error code (after rate-conversion)
+ { return my.values[index].error(); }
+
+ int currentError(int index) const // Current raw error code
+ { return my.values[index].currentError(); }
+
+ void shiftValues(); // Shift values in preparation for next fetch
+
+ void setError(int sts); // Set error code for all instances
+
+ void extractValues(pmValueSet const* set); // Extract values after a fetch
+
+ uint contextIndex() const // Index for context in group list
+ { return my.contextIndex; }
+
+ // Index for metric into pmResult
+ uint idIndex() const { return my.idIndex; }
+
+ // Index for indom in context list
+ uint indomIndex() const { return my.indomIndex; }
+
+ // Set the canonical units
+ void setScaleUnits(pmUnits const& units);
+
+ // Generate a metric spec
+ QString spec(bool srcFlag = false,
+ bool instFlag = false,
+ uint instance = UINT_MAX) const;
+
+ // Dump out the metric and its current value(s)
+ void dump(QTextStream &os, bool srcFlag = false,
+ uint instance = UINT_MAX) const;
+
+ // Dump out the current value
+ void dumpValue(QTextStream &os, uint instance) const;
+
+ // Dump out the metric source
+ void dumpSource(QTextStream &os) const;
+
+ // Format a value into a fixed width format
+ static const char *formatNumber(double value);
+
+ // Determine the current errors and rate-converted scaled values
+ int update();
+
+ friend QTextStream &operator<<(QTextStream &os, const QmcMetric &metric);
+
+private:
+ struct {
+ pmID pmid;
+ int status;
+ QString name;
+ QmcGroup *group;
+ QList<QmcMetricValue> values;
+ double scale;
+
+ uint contextIndex; // Index into the context list for the group
+ uint idIndex; // Index into the pmid list for the context.
+ uint indomIndex; // Index into the indom list for the context.
+
+ bool explicitInst; // Instances explicitly specified
+ bool active; // Use only active implicit insts
+ } my;
+
+ void setup(QmcGroup *group, pmMetricSpec *theMetric);
+ void setupDesc(QmcGroup *group, pmMetricSpec *theMetric);
+ void setupIndom(pmMetricSpec *theMetric);
+ void setupValues(int num);
+
+ void extractNumericMetric(pmValueSet const *vset, pmValue const *v, QmcMetricValue &vref);
+ void extractArrayMetric(pmValueSet const *vset, pmValue const *v, QmcMetricValue &vref);
+ void extractEventMetric(pmValueSet const *vset, int index, QmcMetricValue &vref);
+
+ void setIdIndex(uint index) { my.idIndex = index; }
+
+ // Dump error messages
+ void dumpAll() const;
+ void dumpErr() const;
+ void dumpErr(const char *inst) const;
+
+ // Dump out different metric flavours and their current value(s)
+ void dumpEventMetric(QTextStream &os, bool srcFlag = false,
+ uint instance = UINT_MAX) const;
+ void dumpSampledMetric(QTextStream &os, bool srcFlag = false,
+ uint instance = UINT_MAX) const;
+};
+
+#endif // QMC_METRIC_H