/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * 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.
 */

#define LOG_TAG "dumpstate"

#include "DumpPool.h"

#include <array>
#include <thread>

#include <log/log.h>

#include "dumpstate.h"
#include "DumpstateInternal.h"
#include "DumpstateUtil.h"

namespace android {
namespace os {
namespace dumpstate {

const std::string DumpPool::PREFIX_TMPFILE_NAME = "dump-tmp.";


void WaitForTask(std::future<std::string> future, const std::string& title, int out_fd) {
    DurationReporter duration_reporter("Wait for " + title, true);

    std::string result = future.get();
    if (result.empty()) {
        return;
    }
    DumpFileToFd(out_fd, title, result);
    if (unlink(result.c_str())) {
        MYLOGE("Failed to unlink (%s): %s\n", result.c_str(), strerror(errno));
    }
}

DumpPool::DumpPool(const std::string& tmp_root) : tmp_root_(tmp_root), shutdown_(false),
        log_duration_(true) {
    assert(!tmp_root.empty());
    deleteTempFiles(tmp_root_);
}

DumpPool::~DumpPool() {
    std::unique_lock lock(lock_);
    if (shutdown_ || threads_.empty()) {
        return;
    }
    while (!tasks_.empty()) tasks_.pop();

    shutdown_ = true;
    condition_variable_.notify_all();
    lock.unlock();

    for (auto& thread : threads_) {
        thread.join();
    }
    threads_.clear();
    deleteTempFiles(tmp_root_);
    MYLOGI("shutdown thread pool\n");
}

void DumpPool::start(int thread_counts) {
    assert(thread_counts > 0);
    assert(threads_.empty());
    if (thread_counts > MAX_THREAD_COUNT) {
        thread_counts = MAX_THREAD_COUNT;
    }
    MYLOGI("Start thread pool:%d\n", thread_counts);
    shutdown_ = false;
    for (int i = 0; i < thread_counts; i++) {
        threads_.emplace_back(std::thread([=]() {
            setThreadName(pthread_self(), i + 1);
            loop();
        }));
    }
}

void DumpPool::deleteTempFiles() {
    deleteTempFiles(tmp_root_);
}

void DumpPool::setLogDuration(bool log_duration) {
    log_duration_ = log_duration;
}

template <>
void DumpPool::invokeTask<std::function<void()>>(std::function<void()> dump_func,
        const std::string& duration_title, int out_fd) {
    DurationReporter duration_reporter(duration_title, /*logcat_only =*/!log_duration_,
            /*verbose =*/false, out_fd);
    std::invoke(dump_func);
}

template <>
void DumpPool::invokeTask<std::function<void(int)>>(std::function<void(int)> dump_func,
        const std::string& duration_title, int out_fd) {
    DurationReporter duration_reporter(duration_title, /*logcat_only =*/!log_duration_,
            /*verbose =*/false, out_fd);
    std::invoke(dump_func, out_fd);
}

std::unique_ptr<DumpPool::TmpFile> DumpPool::createTempFile() {
    auto tmp_file_ptr = std::make_unique<TmpFile>();
    std::string file_name_format = "%s/" + PREFIX_TMPFILE_NAME + "XXXXXX";
    snprintf(tmp_file_ptr->path, sizeof(tmp_file_ptr->path), file_name_format.c_str(),
             tmp_root_.c_str());
    tmp_file_ptr->fd.reset(TEMP_FAILURE_RETRY(
            mkostemp(tmp_file_ptr->path, O_CLOEXEC)));
    if (tmp_file_ptr->fd.get() == -1) {
        MYLOGE("open(%s, %s)\n", tmp_file_ptr->path, strerror(errno));
        tmp_file_ptr = nullptr;
        return tmp_file_ptr;
    }
    return tmp_file_ptr;
}

void DumpPool::deleteTempFiles(const std::string& folder) {
    std::unique_ptr<DIR, decltype(&closedir)> dir_ptr(opendir(folder.c_str()),
            &closedir);
    if (!dir_ptr) {
        MYLOGE("Failed to opendir (%s): %s\n", folder.c_str(), strerror(errno));
        return;
    }
    int dir_fd = dirfd(dir_ptr.get());
    if (dir_fd < 0) {
        MYLOGE("Failed to get fd of dir (%s): %s\n", folder.c_str(),
               strerror(errno));
        return;
    }

    struct dirent* de;
    while ((de = readdir(dir_ptr.get()))) {
        if (de->d_type != DT_REG) {
            continue;
        }
        std::string file_name(de->d_name);
        if (file_name.find(PREFIX_TMPFILE_NAME) != 0) {
            continue;
        }
        if (unlinkat(dir_fd, file_name.c_str(), 0)) {
            MYLOGE("Failed to unlink (%s): %s\n", file_name.c_str(),
                   strerror(errno));
        }
    }
}

void DumpPool::setThreadName(const pthread_t thread, int id) {
    std::array<char, 15> name;
    snprintf(name.data(), name.size(), "dumpstate_%d", id);
    pthread_setname_np(thread, name.data());
}

void DumpPool::loop() {
    std::unique_lock lock(lock_);
    while (!shutdown_) {
        if (tasks_.empty()) {
            condition_variable_.wait(lock);
            continue;
        } else {
            std::packaged_task<std::string()> task = std::move(tasks_.front());
            tasks_.pop();
            lock.unlock();
            std::invoke(task);
            lock.lock();
        }
    }
}

}  // namespace dumpstate
}  // namespace os
}  // namespace android
