// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "metric.hpp"

#include "metricblob.pb.n.h"

#include "util.hpp"

#include <pb_encode.h>
#include <sys/statvfs.h>

#include <phosphor-logging/log.hpp>

#include <cstdint>
#include <filesystem>
#include <sstream>
#include <string>
#include <string_view>

namespace metric_blob
{

using phosphor::logging::entry;
using phosphor::logging::log;
using level = phosphor::logging::level;

BmcHealthSnapshot::BmcHealthSnapshot() :
    done(false), stringId(0), ticksPerSec(0)
{}

template <typename T>
static constexpr auto pbEncodeStr =
    [](pb_ostream_t* stream, const pb_field_iter_t* field,
       void* const* arg) noexcept {
        static_assert(sizeof(*std::declval<T>().data()) == sizeof(pb_byte_t));
        const auto& s = *reinterpret_cast<const T*>(*arg);
        return pb_encode_tag_for_field(stream, field) &&
               pb_encode_string(stream,
                                reinterpret_cast<const pb_byte_t*>(s.data()),
                                s.size());
    };

template <typename T>
static pb_callback_t pbStrEncoder(const T& t) noexcept
{
    return {{.encode = pbEncodeStr<T>}, const_cast<T*>(&t)};
}

template <auto fields, typename T>
static constexpr auto pbEncodeSubs =
    [](pb_ostream_t* stream, const pb_field_iter_t* field,
       void* const* arg) noexcept {
        for (const auto& sub : *reinterpret_cast<const std::vector<T>*>(*arg))
        {
            if (!pb_encode_tag_for_field(stream, field) ||
                !pb_encode_submessage(stream, fields, &sub))
            {
                return false;
            }
        }
        return true;
    };

template <auto fields, typename T>
static pb_callback_t pbSubsEncoder(const std::vector<T>& t)
{
    return {{.encode = pbEncodeSubs<fields, T>},
            const_cast<std::vector<T>*>(&t)};
}

struct ProcStatEntry
{
    std::string cmdline;
    std::string tcomm;
    float utime;
    float stime;

    // Processes with the longest utime + stime are ranked first.
    // Tie breaking is done with cmdline then tcomm.
    bool operator<(const ProcStatEntry& other) const
    {
        const float negTime = -(utime + stime);
        const float negOtherTime = -(other.utime + other.stime);
        return std::tie(negTime, cmdline, tcomm) <
               std::tie(negOtherTime, other.cmdline, other.tcomm);
    }
};

static bmcmetrics_metricproto_BmcProcStatMetric getProcStatMetric(
    BmcHealthSnapshot& obj, long ticksPerSec,
    std::vector<bmcmetrics_metricproto_BmcProcStatMetric_BmcProcStat>& procs,
    bool& use) noexcept
{
    if (ticksPerSec == 0)
    {
        return {};
    }
    constexpr std::string_view procPath = "/proc/";

    std::vector<ProcStatEntry> entries;

    for (const auto& procEntry : std::filesystem::directory_iterator(procPath))
    {
        const std::string& path = procEntry.path();
        int pid = -1;
        if (isNumericPath(path, pid))
        {
            ProcStatEntry entry;

            try
            {
                entry.cmdline = getCmdLine(pid);
                TcommUtimeStime t = getTcommUtimeStime(pid, ticksPerSec);
                entry.tcomm = t.tcomm;
                entry.utime = t.utime;
                entry.stime = t.stime;

                entries.push_back(entry);
            }
            catch (const std::exception& e)
            {
                log<level::ERR>("Could not obtain process stats");
            }
        }
    }

    std::sort(entries.begin(), entries.end());

    bool isOthers = false;
    ProcStatEntry others;
    others.cmdline = "(Others)";
    others.utime = others.stime = 0;

    // Only show this many processes and aggregate all remaining ones into
    // "others" in order to keep the size of the snapshot reasonably small.
    // With 10 process stat entries and 10 FD count entries, the size of the
    // snapshot reaches around 1.5KiB. This is non-trivial, and we have to set
    // the collection interval long enough so as not to over-stress the IPMI
    // interface and the data collection service. The value of 10 is chosen
    // empirically, it might be subject to adjustments when the system is
    // launched later.
    constexpr int topN = 10;

    for (size_t i = 0; i < entries.size(); ++i)
    {
        if (i >= topN)
        {
            isOthers = true;
        }

        const ProcStatEntry& entry = entries[i];

        if (isOthers)
        {
            others.utime += entry.utime;
            others.stime += entry.stime;
        }
        else
        {
            std::string fullCmdline = entry.cmdline;
            if (entry.tcomm.size() > 0)
            {
                fullCmdline += " ";
                fullCmdline += entry.tcomm;
            }
            procs.emplace_back(
                bmcmetrics_metricproto_BmcProcStatMetric_BmcProcStat{
                    .sidx_cmdline = obj.getStringID(fullCmdline),
                    .utime = entry.utime,
                    .stime = entry.stime,
                });
        }
    }

    if (isOthers)
    {
        procs.emplace_back(bmcmetrics_metricproto_BmcProcStatMetric_BmcProcStat{
            .sidx_cmdline = obj.getStringID(others.cmdline),
            .utime = others.utime,
            .stime = others.stime,

        });
    }

    use = true;
    return bmcmetrics_metricproto_BmcProcStatMetric{
        .stats = pbSubsEncoder<
            bmcmetrics_metricproto_BmcProcStatMetric_BmcProcStat_fields>(procs),
    };
}

int getFdCount(int pid)
{
    const std::string& fdPath = "/proc/" + std::to_string(pid) + "/fd";
    return std::distance(std::filesystem::directory_iterator(fdPath),
                         std::filesystem::directory_iterator{});
}

struct FdStatEntry
{
    int fdCount;
    std::string cmdline;
    std::string tcomm;

    // Processes with the largest fdCount goes first.
    // Tie-breaking using cmdline then tcomm.
    bool operator<(const FdStatEntry& other) const
    {
        const int negFdCount = -fdCount;
        const int negOtherFdCount = -other.fdCount;
        return std::tie(negFdCount, cmdline, tcomm) <
               std::tie(negOtherFdCount, other.cmdline, other.tcomm);
    }
};

static bmcmetrics_metricproto_BmcFdStatMetric getFdStatMetric(
    BmcHealthSnapshot& obj, long ticksPerSec,
    std::vector<bmcmetrics_metricproto_BmcFdStatMetric_BmcFdStat>& fds,
    bool& use) noexcept
{
    if (ticksPerSec == 0)
    {
        return {};
    }

    // Sort by fd count, no tie-breaking
    std::vector<FdStatEntry> entries;

    const std::string_view procPath = "/proc/";
    for (const auto& procEntry : std::filesystem::directory_iterator(procPath))
    {
        const std::string& path = procEntry.path();
        int pid = 0;
        FdStatEntry entry;
        if (isNumericPath(path, pid))
        {
            try
            {
                entry.fdCount = getFdCount(pid);
                TcommUtimeStime t = getTcommUtimeStime(pid, ticksPerSec);
                entry.cmdline = getCmdLine(pid);
                entry.tcomm = t.tcomm;
                entries.push_back(entry);
            }
            catch (const std::exception& e)
            {
                log<level::ERR>("Could not get file descriptor stats");
            }
        }
    }

    std::sort(entries.begin(), entries.end());

    bool isOthers = false;

    // Only report the detailed fd count and cmdline for the top 10 entries,
    // and collapse all others into "others".
    constexpr int topN = 10;

    FdStatEntry others;
    others.cmdline = "(Others)";
    others.fdCount = 0;

    for (size_t i = 0; i < entries.size(); ++i)
    {
        if (i >= topN)
        {
            isOthers = true;
        }

        const FdStatEntry& entry = entries[i];
        if (isOthers)
        {
            others.fdCount += entry.fdCount;
        }
        else
        {
            std::string fullCmdline = entry.cmdline;
            if (entry.tcomm.size() > 0)
            {
                fullCmdline += " ";
                fullCmdline += entry.tcomm;
            }
            fds.emplace_back(bmcmetrics_metricproto_BmcFdStatMetric_BmcFdStat{
                .sidx_cmdline = obj.getStringID(fullCmdline),
                .fd_count = entry.fdCount,
            });
        }
    }

    if (isOthers)
    {
        fds.emplace_back(bmcmetrics_metricproto_BmcFdStatMetric_BmcFdStat{
            .sidx_cmdline = obj.getStringID(others.cmdline),
            .fd_count = others.fdCount,
        });
    }

    use = true;
    return bmcmetrics_metricproto_BmcFdStatMetric{
        .stats = pbSubsEncoder<
            bmcmetrics_metricproto_BmcFdStatMetric_BmcFdStat_fields>(fds),
    };
}

static bmcmetrics_metricproto_BmcECCMetric getECCMetric(bool& use) noexcept
{
    EccCounts eccCounts;
    use = getECCErrorCounts(eccCounts);
    if (!use)
    {
        return {};
    }
    return bmcmetrics_metricproto_BmcECCMetric{
        .correctable_error_count = eccCounts.correctableErrCount,
        .uncorrectable_error_count = eccCounts.uncorrectableErrCount,
    };
}

static bmcmetrics_metricproto_BmcMemoryMetric getMemMetric() noexcept
{
    bmcmetrics_metricproto_BmcMemoryMetric ret = {};
    auto data = readFileThenGrepIntoString("/proc/meminfo");
    int value;
    if (parseMeminfoValue(data, "MemAvailable:", value))
    {
        ret.mem_available = value;
    }
    if (parseMeminfoValue(data, "Slab:", value))
    {
        ret.slab = value;
    }

    if (parseMeminfoValue(data, "KernelStack:", value))
    {
        ret.kernel_stack = value;
    }
    return ret;
}

static bmcmetrics_metricproto_BmcUptimeMetric
    getUptimeMetric(bool& use) noexcept
{
    bmcmetrics_metricproto_BmcUptimeMetric ret = {};

    double uptime = 0;
    {
        auto data = readFileThenGrepIntoString("/proc/uptime");
        double idleProcessTime = 0;
        if (!parseProcUptime(data, uptime, idleProcessTime))
        {
            log<level::ERR>("Error parsing /proc/uptime");
            return ret;
        }
        ret.uptime = uptime;
        ret.idle_process_time = idleProcessTime;
    }

    BootTimesMonotonic btm;
    if (!getBootTimesMonotonic(btm))
    {
        log<level::ERR>("Could not get boot time");
        return ret;
    }
    if (btm.firmwareTime == 0 && btm.powerOnSecCounterTime != 0)
    {
        ret.firmware_boot_time_sec =
            static_cast<double>(btm.powerOnSecCounterTime) - uptime;
    }
    else
    {
        ret.firmware_boot_time_sec =
            static_cast<double>(btm.firmwareTime - btm.loaderTime) / 1e6;
    }
    ret.loader_boot_time_sec = static_cast<double>(btm.loaderTime) / 1e6;
    if (btm.initrdTime != 0)
    {
        ret.kernel_boot_time_sec = static_cast<double>(btm.initrdTime) / 1e6;
        ret.initrd_boot_time_sec =
            static_cast<double>(btm.userspaceTime - btm.initrdTime) / 1e6;
        ret.userspace_boot_time_sec =
            static_cast<double>(btm.finishTime - btm.userspaceTime) / 1e6;
    }
    else
    {
        ret.kernel_boot_time_sec = static_cast<double>(btm.userspaceTime) / 1e6;
        ret.initrd_boot_time_sec = 0;
        ret.userspace_boot_time_sec =
            static_cast<double>(btm.finishTime - btm.userspaceTime) / 1e6;
    }

    use = true;
    return ret;
}

static bmcmetrics_metricproto_BmcDiskSpaceMetric
    getStorageMetric(bool& use) noexcept
{
    bmcmetrics_metricproto_BmcDiskSpaceMetric ret = {};
    struct statvfs rwFiData, tmpFiData;
    if (statvfs("/", &rwFiData) < 0)
    {
        log<level::ERR>("Could not call statvfs");
    }
    else
    {
        ret.rwfs_kib_available = (rwFiData.f_bsize * rwFiData.f_bfree) / 1024;
        use = true;
    }
    if (statvfs("/tmp", &tmpFiData) < 0)
    {
        log<level::ERR>("Could not call statvfs");
    }
    else
    {
        ret.tmpfs_kib_available =
            (tmpFiData.f_bsize * tmpFiData.f_bfree) / 1024;
        use = true;
    }
    return ret;
}

void BmcHealthSnapshot::doWork()
{
    // The next metrics require a sane ticks_per_sec value, typically 100 on
    // the BMC. In the very rare circumstance when it's 0, exit early and return
    // a partially complete snapshot (no process).
    ticksPerSec = getTicksPerSec();

    static constexpr auto stcb = [](pb_ostream_t* stream,
                                    const pb_field_t* field,
                                    void* const* arg) noexcept {
        auto& self = *reinterpret_cast<BmcHealthSnapshot*>(*arg);
        std::vector<std::string_view> strs(self.stringTable.size());
        for (const auto& [str, i] : self.stringTable)
        {
            strs[i] = str;
        }
        for (auto& str : strs)
        {
            bmcmetrics_metricproto_BmcStringTable_StringEntry msg = {
                .value = pbStrEncoder(str),
            };
            if (!pb_encode_tag_for_field(stream, field) ||
                !pb_encode_submessage(
                    stream,
                    bmcmetrics_metricproto_BmcStringTable_StringEntry_fields,
                    &msg))
            {
                return false;
            }
        }
        return true;
    };
    std::vector<bmcmetrics_metricproto_BmcProcStatMetric_BmcProcStat> procs;
    std::vector<bmcmetrics_metricproto_BmcFdStatMetric_BmcFdStat> fds;
    bmcmetrics_metricproto_BmcMetricSnapshot snapshot = {
        .has_string_table = true,
        .string_table =
            {
                .entries = {{.encode = stcb}, this},
            },
        .has_memory_metric = true,
        .memory_metric = getMemMetric(),
        .has_uptime_metric = false,
        .uptime_metric = getUptimeMetric(snapshot.has_uptime_metric),
        .has_storage_space_metric = false,
        .storage_space_metric =
            getStorageMetric(snapshot.has_storage_space_metric),
        .has_procstat_metric = false,
        .procstat_metric = getProcStatMetric(*this, ticksPerSec, procs,
                                             snapshot.has_procstat_metric),
        .has_fdstat_metric = false,
        .fdstat_metric = getFdStatMetric(*this, ticksPerSec, fds,
                                         snapshot.has_fdstat_metric),
        .has_ecc_metric = false,
        .ecc_metric = getECCMetric(snapshot.has_ecc_metric),
    };
    pb_ostream_t nost = {};
    if (!pb_encode(&nost, bmcmetrics_metricproto_BmcMetricSnapshot_fields,
                   &snapshot))
    {
        auto msg = std::format("Getting pb size: {}", PB_GET_ERROR(&nost));
        log<level::ERR>(msg.c_str());
        return;
    }
    pbDump.resize(nost.bytes_written);
    auto ost = pb_ostream_from_buffer(
        reinterpret_cast<pb_byte_t*>(pbDump.data()), pbDump.size());
    if (!pb_encode(&ost, bmcmetrics_metricproto_BmcMetricSnapshot_fields,
                   &snapshot))
    {
        auto msg = std::format("Writing pb msg: {}", PB_GET_ERROR(&ost));
        log<level::ERR>(msg.c_str());
        return;
    }
    done = true;
}

// BmcBlobSessionStat (9) but passing meta as reference instead of pointer,
// since the metadata must not be null at this point.
bool BmcHealthSnapshot::stat(blobs::BlobMeta& meta)
{
    if (!done)
    {
        // Bits 8~15 are blob-specific state flags.
        // For this blob, bit 8 is set when metric collection is still in
        // progress.
        meta.blobState |= (1 << 8);
    }
    else
    {
        meta.blobState = 0;
        meta.blobState = blobs::StateFlags::open_read;
        meta.size = pbDump.size();
    }
    return true;
}

std::string_view BmcHealthSnapshot::read(uint32_t offset,
                                         uint32_t requestedSize)
{
    uint32_t size = static_cast<uint32_t>(pbDump.size());
    if (offset >= size)
    {
        return {};
    }
    return std::string_view(pbDump.data() + offset,
                            std::min(requestedSize, size - offset));
}

int BmcHealthSnapshot::getStringID(const std::string_view s)
{
    int ret = 0;
    auto itr = stringTable.find(s.data());
    if (itr == stringTable.end())
    {
        stringTable[s.data()] = stringId;
        ret = stringId;
        ++stringId;
    }
    else
    {
        ret = itr->second;
    }
    return ret;
}

} // namespace metric_blob
