/*
 * Copyright (C) 2017 Igalia S.L.
 * Copyright (C) 2018 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "ResourceUsageThread.h"

#if ENABLE(RESOURCE_USAGE) && OS(LINUX)

#include <JavaScriptCore/GCActivityCallback.h>
#include <JavaScriptCore/VM.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <wtf/linux/CurrentProcessMemoryStatus.h>

namespace WebCore {

static float cpuPeriod()
{
    FILE* file = fopen("/proc/stat", "r");
    if (!file)
        return 0;

    static const unsigned statMaxLineLength = 512;
    char buffer[statMaxLineLength + 1];
    char* line = fgets(buffer, statMaxLineLength, file);
    if (!line) {
        fclose(file);
        return 0;
    }

    unsigned long long userTime, niceTime, systemTime, idleTime;
    unsigned long long ioWait, irq, softIrq, steal, guest, guestnice;
    ioWait = irq = softIrq = steal = guest = guestnice = 0;
    int retVal = sscanf(buffer, "cpu  %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu",
        &userTime, &niceTime, &systemTime, &idleTime, &ioWait, &irq, &softIrq, &steal, &guest, &guestnice);
    // We expect 10 values to be matched by sscanf
    if (retVal != 10) {
        fclose(file);
        return 0;
    }


    // Keep parsing if we still don't know cpuCount.
    static unsigned cpuCount = 0;
    if (!cpuCount) {
        while ((line = fgets(buffer, statMaxLineLength, file))) {
            if (strlen(line) > 4 && line[0] == 'c' && line[1] == 'p' && line[2] == 'u')
                cpuCount++;
            else
                break;
        }
    }
    fclose(file);

    if (!cpuCount)
        return 0;

    static unsigned long long previousTotalTime = 0;
    unsigned long long totalTime = userTime + niceTime + systemTime + irq + softIrq + idleTime + ioWait + steal;
    unsigned long long period = totalTime > previousTotalTime ? totalTime - previousTotalTime : 0;
    previousTotalTime = totalTime;
    return static_cast<float>(period) / cpuCount;
}

static float cpuUsage()
{
    float period = cpuPeriod();
    if (!period)
        return -1;

    int fd = open("/proc/self/stat", O_RDONLY);
    if (fd < 0)
        return -1;

    static const ssize_t maxBufferLength = BUFSIZ - 1;
    char buffer[BUFSIZ];
    buffer[0] = '\0';

    ssize_t totalBytesRead = 0;
    while (totalBytesRead < maxBufferLength) {
        ssize_t bytesRead = read(fd, buffer + totalBytesRead, maxBufferLength - totalBytesRead);
        if (bytesRead < 0) {
            if (errno != EINTR) {
                close(fd);
                return -1;
            }
            continue;
        }

        if (!bytesRead)
            break;

        totalBytesRead += bytesRead;
    }
    close(fd);
    buffer[totalBytesRead] = '\0';

    // Skip pid and process name.
    char* position = strrchr(buffer, ')');
    if (!position)
        return -1;

    // Move after state.
    position += 4;

    // Skip ppid, pgrp, sid, tty_nr, tty_pgrp, flags, min_flt, cmin_flt, maj_flt, cmaj_flt.
    unsigned tokensToSkip = 10;
    while (tokensToSkip--) {
        while (!isASCIISpace(position[0]))
            position++;
        position++;
    }

    static unsigned long long previousUtime = 0;
    static unsigned long long previousStime = 0;
    unsigned long long utime = strtoull(position, &position, 10);
    unsigned long long stime = strtoull(position, &position, 10);
    float usage = (utime + stime - (previousUtime + previousStime)) / period * 100.0;
    previousUtime = utime;
    previousStime = stime;

    return clampTo<float>(usage, 0, 100);
}

void ResourceUsageThread::platformSaveStateBeforeStarting()
{
}

void ResourceUsageThread::platformCollectCPUData(JSC::VM*, ResourceUsageData& data)
{
    data.cpu = cpuUsage();

    // FIXME: Exclude the ResourceUsage thread.
    // FIXME: Exclude the SamplingProfiler thread.
    // FIXME: Classify usage per thread.
    data.cpuExcludingDebuggerThreads = data.cpu;
}

void ResourceUsageThread::platformCollectMemoryData(JSC::VM* vm, ResourceUsageData& data)
{
    ProcessMemoryStatus memoryStatus;
    currentProcessMemoryStatus(memoryStatus);
    data.totalDirtySize = memoryStatus.resident - memoryStatus.shared;

    size_t currentGCHeapCapacity = vm->heap.blockBytesAllocated();
    size_t currentGCOwnedExtra = vm->heap.extraMemorySize();
    size_t currentGCOwnedExternal = vm->heap.externalMemorySize();
    RELEASE_ASSERT(currentGCOwnedExternal <= currentGCOwnedExtra);

    data.categories[MemoryCategory::GCHeap].dirtySize = currentGCHeapCapacity;
    data.categories[MemoryCategory::GCOwned].dirtySize = currentGCOwnedExtra - currentGCOwnedExternal;
    data.categories[MemoryCategory::GCOwned].externalSize = currentGCOwnedExternal;

    data.totalExternalSize = currentGCOwnedExternal;

    data.timeOfNextEdenCollection = data.timestamp + vm->heap.edenActivityCallback()->timeUntilFire().valueOr(Seconds(std::numeric_limits<double>::infinity()));
    data.timeOfNextFullCollection = data.timestamp + vm->heap.fullActivityCallback()->timeUntilFire().valueOr(Seconds(std::numeric_limits<double>::infinity()));
}

} // namespace WebCore

#endif // ENABLE(RESOURCE_USAGE) && OS(LINUX)
