VirtualBox

Ignore:
Timestamp:
Jan 12, 2024 2:09:25 PM (11 months ago)
Author:
vboxsync
Message:

FE/Qt: bugref:10501. Fixes for the iterrupted data series.

Location:
trunk/src/VBox/Frontends/VirtualBox/src/activity/vmactivity
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/activity/vmactivity/UIVMActivityMonitor.cpp

    r102810 r102858  
    7070const int g_iMetricSetupCount = 1;
    7171const int g_iDecimalCount = 2;
    72 
    7372const int g_iBackgroundTint = 104;
    74 
     73const quint64 uInvalidValueSentinel = ~0U;
    7574
    7675/*********************************************************************************************************************************
     
    523522    {
    524523        QHelpEvent *pToolTipEvent = static_cast<QHelpEvent *>(pEvent);
    525         // if (m_iDataIndexUnderCursor == -1)
    526         //     QToolTip::hideText();
    527         // else
    528         //     QToolTip::showText(pToolTipEvent->globalPos(), toolTipText(), this, m_lineChartRect);
    529524        if (m_pMouseOverLabel)
    530525        {
    531             if (m_iDataIndexUnderCursor == -1)
     526            if (m_iDataIndexUnderCursor < 0)
    532527                m_pMouseOverLabel->setVisible(false);
    533528            else
    534529            {
    535                 m_pMouseOverLabel->setText(toolTipText());
    536 
    537                 //m_pMouseOverLabel->resize(m_pMouseOverLabel->fontMetrics().size(Qt::TextSingleLine, m_pMouseOverLabel->text()));
    538                 m_pMouseOverLabel->move(QPoint(pToolTipEvent->pos().x(), pToolTipEvent->pos().y() - m_pMouseOverLabel->height()));
    539                 m_pMouseOverLabel->setVisible(true);
     530                QString strToolTip = toolTipText();
     531                if (!strToolTip.isEmpty())
     532                {
     533                    m_pMouseOverLabel->setText(strToolTip);
     534                    m_pMouseOverLabel->move(QPoint(pToolTipEvent->pos().x(), pToolTipEvent->pos().y() - m_pMouseOverLabel->height()));
     535                    m_pMouseOverLabel->setVisible(true);
     536                }
     537                else
     538                    m_pMouseOverLabel->setVisible(false);
    540539            }
    541540        }
     
    676675            {
    677676                int j = i + 1;
     677                if (data->at(i) == uInvalidValueSentinel || data->at(j) == uInvalidValueSentinel)
     678                    continue;
     679
    678680                float fHeight = fH * data->at(i);
    679681                float fX = (width() - m_iMarginRight) - ((data->size() - i - 1) * fBarWidth);
     
    687689            for (int i = 0; i < data->size(); ++i)
    688690            {
     691                if (data->at(i) == uInvalidValueSentinel)
     692                    continue;
    689693                float fHeight = fH * data->at(i);
    690694                float fX = (width() - m_iMarginRight) - ((data->size() - i - 1) * fBarWidth);
     
    726730QString UIChart::YAxisValueLabel(quint64 iValue) const
    727731{
     732    if (iValue == uInvalidValueSentinel)
     733        return QString();
    728734    if (m_pMetric->unit().compare("%", Qt::CaseInsensitive) == 0)
    729735        return QString::number(iValue).append("%");
     
    838844QString UIChart::toolTipText() const
    839845{
    840     if (m_iDataIndexUnderCursor == -1)
     846    if (m_iDataIndexUnderCursor < 0)
    841847        return QString();
    842848
     
    844850        return QString();
    845851    QString strToolTip;
    846     if (m_pMetric->data(1) &&  !m_pMetric->data(1)->isEmpty())
     852    QString strData0;
     853    if (m_iDataIndexUnderCursor < m_pMetric->data(0)->size())
     854        strData0 = YAxisValueLabel(m_pMetric->data(0)->at(m_iDataIndexUnderCursor));
     855    QString strData1;
     856    if (m_iDataIndexUnderCursor < m_pMetric->data(1)->size())
     857        strData1 = YAxisValueLabel(m_pMetric->data(1)->at(m_iDataIndexUnderCursor));
     858    if (!strData0.isEmpty() && !strData1.isEmpty())
    847859    {
    848860        strToolTip = QString("<font color=\"%1\">%2</font> / <font color=\"%3\">%4</font>")
    849             .arg(m_dataSeriesColor[0].name(QColor::HexRgb)).arg(YAxisValueLabel(m_pMetric->data(0)->at(m_iDataIndexUnderCursor)))
    850             .arg(m_dataSeriesColor[1].name(QColor::HexRgb)).arg(YAxisValueLabel(m_pMetric->data(1)->at(m_iDataIndexUnderCursor)));
    851     }
    852     else
     861            .arg(m_dataSeriesColor[0].name(QColor::HexRgb)).arg(strData0)
     862            .arg(m_dataSeriesColor[1].name(QColor::HexRgb)).arg(strData1);
     863    }
     864    else if (!strData0.isEmpty())
    853865    {
    854866        strToolTip = QString("<font color=\"%1\">%2</font>")
    855             .arg(m_dataSeriesColor[0].name(QColor::HexRgb)).arg(YAxisValueLabel(m_pMetric->data(0)->at(m_iDataIndexUnderCursor)));
     867            .arg(m_dataSeriesColor[0].name(QColor::HexRgb)).arg(strData0);
     868    }
     869    else if (!strData1.isEmpty())
     870    {
     871        strToolTip = QString("<font color=\"%1\">%2</font>")
     872            .arg(m_dataSeriesColor[1].name(QColor::HexRgb)).arg(strData1);
    856873    }
    857874    return strToolTip;
    858     //m_dataSeriesColor[iDataIndex]);
    859     // return pChart->dataSeriesColor(iDataIndex).name(QColor::HexRgb);
    860     // QColor dataSeriesColor(int iDataSeriesIndex, int iDark = 0);
    861     //QString strInfo = QString("<b>%1</b></b><br/> <font color=\"%2\">%3: %4</font><br/> <font color=\"%5\">%6: %7</font>")
    862 
    863     // QStringList toolTipStrings;
    864     // for (int k = 0; k < DATA_SERIES_SIZE; ++k)
    865     // {
    866     //     const QQueue<quint64> *data = m_pMetric->data(k);
    867     //     if (data && data->size() > 0 && m_iDataIndexUnderCursor < data->size())
    868     //         toolTipStrings << YAxisValueLabel(data->at(m_iDataIndexUnderCursor));
    869     // }
    870     // return toolTipStrings.join(" / ");
    871     //QString strInfo = QString("<b>%1</b></b><br/> <font color=\"%2\">%3: %4</font><br/> <font color=\"%5\">%6: %7</font>")
    872875}
    873876
     
    10251028    if (iDataSeriesIndex >= DATA_SERIES_SIZE)
    10261029        return;
     1030
    10271031    m_data[iDataSeriesIndex].enqueue(iData);
    1028     if (m_fAutoUpdateMaximum)
    1029         m_iMaximum = qMax(m_iMaximum, iData);
    10301032
    10311033    /* dequeue if needed and update the maximum value: */
    10321034    if (m_data[iDataSeriesIndex].size() > m_iMaximumQueueSize)
    1033     {
    1034         bool fSearchMax = false;
    1035         /* Check if the dequeued value is the Max value. In which case we will scan and find a new Max: */
    1036         if (m_fAutoUpdateMaximum && m_data[iDataSeriesIndex].head() >= m_iMaximum)
    1037             fSearchMax = true;
    10381035        m_data[iDataSeriesIndex].dequeue();
    1039         if (fSearchMax)
     1036
     1037    updateMax();
     1038}
     1039
     1040void UIMetric::updateMax()
     1041{
     1042    if (!m_fAutoUpdateMaximum)
     1043        return;
     1044    m_iMaximum = 0;
     1045    for (int k = 0; k < DATA_SERIES_SIZE; ++k)
     1046    {
     1047        for (int i = 0; i < m_data[k].size(); ++i)
    10401048        {
    1041             m_iMaximum = 0;
    1042             foreach (quint64 iVal, m_data[iDataSeriesIndex])
    1043                 m_iMaximum = qMax(m_iMaximum, iVal);
     1049            if (m_data[k].at(i) != uInvalidValueSentinel)
     1050                m_iMaximum = qMax(m_iMaximum, m_data[k].at(i));
    10441051        }
    10451052    }
     
    17641771}
    17651772
    1766 void UIVMActivityMonitorLocal::updateCPUChart(ULONG iExecutingPercentage, ULONG iOtherPercentage)
     1773void UIVMActivityMonitorLocal::updateCPUChart(quint64 iExecutingPercentage, ULONG iOtherPercentage)
    17671774{
    17681775    UIMetric &CPUMetric = m_metrics[m_strCPUMetricName];
     
    20652072    if (data.size() != timeStamps.size())
    20662073        return;
     2074    /* Hack alert!! I am told that time series' interval is `guaranteed` to be 1 min. although it is clearly
     2075     * parametrized in OCI API. I would much prefer to have some way of deermining the said interval via our API
     2076     * but it looks like Christmas is over: */
     2077    const int iInterval = 60;
    20672078    QVector<QString> newTimeStamps;
    2068     foreach (const QString &strTimeStamp, timeStamps)
    2069     {
    2070         if (strTimeStamp.isEmpty())
     2079    QVector<quint64> newData;
     2080    for (int i = 0; i < timeStamps.size() - 1; ++i)
     2081    {
     2082        if (timeStamps[i].isEmpty())
    20712083            continue;
    2072         QDateTime dateTime = QDateTime::fromString(strTimeStamp, Qt::RFC2822Date);
    2073         if (!dateTime.isValid())
     2084        QTime time = QDateTime::fromString(timeStamps[i], Qt::RFC2822Date).time();
     2085        if (!time.isValid())
    20742086            continue;
    2075         newTimeStamps << dateTime.time().toString("hh:mm");
    2076     }
    2077 
    2078     for (int i = 0; i < data.size(); ++i)
     2087        newTimeStamps << time.toString("hh:mm");
     2088        /* It looks like in some cases OCI sends us negative values: */
     2089        if (data[i].toFloat() < 0)
     2090            newData << 0U;
     2091        else
     2092            newData << (quint64)data[i].toFloat();
     2093
     2094        QTime nextTime = QDateTime::fromString(timeStamps[i + 1], Qt::RFC2822Date).time();
     2095        while(time.secsTo(nextTime) > iInterval)
     2096        {
     2097            time = time.addSecs(iInterval);
     2098            newTimeStamps << time.toString("hh:mm");
     2099            newData << uInvalidValueSentinel;
     2100        }
     2101    }
     2102    if (!data.isEmpty())
     2103    {
     2104        if (!timeStamps.last().isEmpty())
     2105            newTimeStamps << QDateTime::fromString(timeStamps.last(), Qt::RFC2822Date).time().toString("hh:mm");
     2106        newData << (quint64)data.last().toFloat();
     2107    }
     2108    AssertReturnVoid(newData.size() == newTimeStamps.size());
     2109
     2110    if (enmMetricType == KMetricType_NetworksBytesIn)
     2111    {
     2112        m_networkReceiveCache.clear();
     2113        m_metrics[m_strNetworkMetricName].reset();
     2114    }
     2115    else if (enmMetricType == KMetricType_NetworksBytesOut)
     2116    {
     2117        m_networkTransmitCache.clear();
     2118        m_metrics[m_strNetworkMetricName].reset();
     2119    }
     2120    else if (enmMetricType == KMetricType_DiskBytesRead)
     2121    {
     2122        m_diskReadCache.clear();
     2123        m_metrics[m_strDiskIOMetricName].reset();
     2124    }
     2125    else if (enmMetricType == KMetricType_DiskBytesWritten)
     2126    {
     2127        m_diskWriteCache.clear();
     2128        m_metrics[m_strDiskIOMetricName].reset();
     2129
     2130    }
     2131    else if (enmMetricType == KMetricType_CpuUtilization)
     2132        m_metrics[m_strCPUMetricName].reset();
     2133    else if (enmMetricType == KMetricType_MemoryUtilization)
     2134        m_metrics[m_strRAMMetricName].reset();
     2135
     2136
     2137    for (int i = 0; i < newData.size(); ++i)
    20792138    {
    20802139        if (enmMetricType == KMetricType_CpuUtilization)
    20812140        {
    2082             float fValue = data[i].toFloat();
    2083             updateCPUChart((ULONG) fValue, newTimeStamps[i]);
     2141            updateCPUChart(newData[i], newTimeStamps[i]);
    20842142        }
    20852143        else if (enmMetricType == KMetricType_NetworksBytesOut)
    2086             cacheNetworkTransmit(newTimeStamps[i], (int)data[i].toFloat());
     2144            cacheNetworkTransmit(newTimeStamps[i], newData[i]);
    20872145        else if (enmMetricType == KMetricType_NetworksBytesIn)
    2088             cacheNetworkReceive(newTimeStamps[i], (int)data[i].toFloat());
     2146            cacheNetworkReceive(newTimeStamps[i], newData[i]);
    20892147        else if (enmMetricType == KMetricType_DiskBytesRead)
    2090             cacheDiskRead(newTimeStamps[i], (int)data[i].toFloat());
     2148            cacheDiskRead(newTimeStamps[i], newData[i]);
    20912149        else if (enmMetricType == KMetricType_DiskBytesWritten)
    2092             cacheDiskWrite(newTimeStamps[i], (int)data[i].toFloat());
     2150            cacheDiskWrite(newTimeStamps[i], newData[i]);
    20932151        else if (enmMetricType == KMetricType_MemoryUtilization)
    20942152        {
     
    20962154            {
    20972155                /* calculate used RAM amount in kb: */
    2098                 quint64 iUsedRAM = data[i].toFloat() * (m_iTotalRAM / 100.f);
    2099                 updateRAMChart(iUsedRAM, newTimeStamps[i]);
     2156                if (newData[i] != uInvalidValueSentinel)
     2157                {
     2158                    quint64 iUsedRAM = newData[i] * (m_iTotalRAM / 100.f);
     2159                    updateRAMChart(iUsedRAM, newTimeStamps[i]);
     2160                }
     2161                else
     2162                    updateRAMChart(newData[i], newTimeStamps[i]);
    21002163            }
    21012164        }
     
    21372200        if (iDataSeriesIndex >= DATA_SERIES_SIZE)
    21382201            continue;
     2202#if 0
    21392203        int iDataSize = 1;
    21402204        if (metric.dataSize(iDataSeriesIndex) == 0)
    21412205            iDataSize = 60;
    2142 
     2206#endif
     2207        /* Request the whole time series (all 60 values) at each iteration to detect time points with no
     2208         * data (due to stop and restart). We sanitize the data when we receive it and mark time points
     2209         * with no data with sentinel value: */
     2210        int iDataSize = 60;
    21432211        UIProgressTaskReadCloudMachineMetricData *pTask = new UIProgressTaskReadCloudMachineMetricData(this, m_comMachine,
    21442212                                                                                                       enmMetricType, iDataSize);
     
    21912259}
    21922260
    2193 void UIVMActivityMonitorCloud::updateCPUChart(ULONG iLoadPercentage, const QString &strLabel)
     2261void UIVMActivityMonitorCloud::updateCPUChart(quint64 iLoadPercentage, const QString &strLabel)
    21942262{
    21952263    UIMetric &CPUMetric = m_metrics[m_strCPUMetricName];
     
    23672435}
    23682436
    2369 void UIVMActivityMonitorCloud::cacheDiskWrite(const QString &strTimeStamp, int iValue)
     2437void UIVMActivityMonitorCloud::cacheDiskWrite(const QString &strTimeStamp, quint64 iValue)
    23702438{
    23712439    /* Make sure this is the first time we receieve write for this time stap: */
     
    23812449}
    23822450
    2383 void UIVMActivityMonitorCloud::cacheDiskRead(const QString &strTimeStamp, int iValue)
     2451void UIVMActivityMonitorCloud::cacheDiskRead(const QString &strTimeStamp, quint64 iValue)
    23842452{
    23852453    /* Make sure this is the first time we receieve read for this time stap: */
     
    23952463}
    23962464
    2397 void UIVMActivityMonitorCloud::cacheNetworkReceive(const QString &strTimeStamp, int iValue)
     2465void UIVMActivityMonitorCloud::cacheNetworkReceive(const QString &strTimeStamp, quint64 iValue)
    23982466{
    23992467    AssertReturnVoid(!m_networkReceiveCache.contains(strTimeStamp));
     
    24092477
    24102478
    2411 void UIVMActivityMonitorCloud::cacheNetworkTransmit(const QString &strTimeStamp, int iValue)
     2479void UIVMActivityMonitorCloud::cacheNetworkTransmit(const QString &strTimeStamp, quint64 iValue)
    24122480{
    24132481    AssertReturnVoid(!m_networkTransmitCache.contains(strTimeStamp));
  • trunk/src/VBox/Frontends/VirtualBox/src/activity/vmactivity/UIVMActivityMonitor.h

    r102810 r102858  
    115115
    116116private:
     117    void updateMax();
    117118
    118119    QString m_strName;
     
    287288    bool guestAdditionsAvailable(const char *pszMinimumVersion);
    288289    void enableDisableGuestAdditionDependedWidgets(bool fEnable);
    289     void updateCPUChart(ULONG iLoadPercentage, ULONG iOtherPercentage);
     290    void updateCPUChart(quint64 iLoadPercentage, ULONG iOtherPercentage);
    290291    void updateRAMGraphsAndMetric(quint64 iTotalRAM, quint64 iFreeRAM);
    291292    void updateNetworkChart(quint64 uReceiveTotal, quint64 uTransmitTotal);
     
    340341    /** @name The following functions update corresponding metric charts and labels with new values
    341342      * @{ */
    342         void updateCPUChart(ULONG iLoadPercentage, const QString &strLabel);
     343        void updateCPUChart(quint64 iLoadPercentage, const QString &strLabel);
    343344        void updateNetworkChart(quint64 uReceive, quint64 uTransmit, const QString &strLabel);
    344345        void updateDiskIOChart(quint64 uWriteRate, quint64 uReadRate, const QString &strLabel);
     
    351352    /* Since we have a single UIMetric instance for disk IO we cache write and/or read until the other value arrives. Then update
    352353     * the corresponding chart. */
    353     void cacheDiskWrite(const QString &strTimeStamp, int iValue);
    354     void cacheDiskRead(const QString &strTimeStamp, int iValue);
    355 
    356     void cacheNetworkReceive(const QString &strTimeStamp, int iValue);
    357     void cacheNetworkTransmit(const QString &strTimeStamp, int iValue);
     354    void cacheDiskWrite(const QString &strTimeStamp, quint64 iValue);
     355    void cacheDiskRead(const QString &strTimeStamp, quint64 iValue);
     356
     357    void cacheNetworkReceive(const QString &strTimeStamp, quint64 iValue);
     358    void cacheNetworkTransmit(const QString &strTimeStamp, quint64 iValue);
    358359
    359360    bool findMetric(KMetricType enmMetricType, UIMetric &metric, int &iDataSeriesIndex) const;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette